# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1251210997 -3600
# Node ID 8faef78ea759d9bea56bea4da9c2ec8d40869bb3
# Parent 9cab2b654cb4a27b77dc2ce53ab1d76514a1e9f5
Accurate accounting for credit scheduler
Rather than debit a full 10ms of credit on a scheduler tick
(probabilistic), debit credits accurately based on time stamps.
The main problem this is meant to address is an attack on the
scheduler that allows a rogue guest to avoid ever being debited
credits. The basic idea is that the rogue process checks time (using
rdtsc) periodically, and yields after 9.5ms. Using this technique, a
guest can "steal" 95% of the cpu. This is particularly an issue in
cloud environments.
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
---
xen/common/sched_credit.c | 38 ++++++++++++++++++++++++++++++++------
1 files changed, 32 insertions(+), 6 deletions(-)
diff -r 9cab2b654cb4 -r 8faef78ea759 xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Tue Aug 25 14:59:09 2009 +0100
+++ b/xen/common/sched_credit.c Tue Aug 25 15:36:37 2009 +0100
@@ -44,11 +44,12 @@
#define CSCHED_MSECS_PER_TICK 10
#define CSCHED_MSECS_PER_TSLICE \
(CSCHED_MSECS_PER_TICK * CSCHED_TICKS_PER_TSLICE)
-#define CSCHED_CREDITS_PER_TICK 100
+#define CSCHED_CREDITS_PER_MSEC 100000
#define CSCHED_CREDITS_PER_TSLICE \
- (CSCHED_CREDITS_PER_TICK * CSCHED_TICKS_PER_TSLICE)
+ (CSCHED_MSECS_PER_TSLICE * CSCHED_CREDITS_PER_MSEC)
#define CSCHED_CREDITS_PER_ACCT \
- (CSCHED_CREDITS_PER_TICK * CSCHED_TICKS_PER_ACCT)
+ (CSCHED_CREDITS_PER_MSEC * CSCHED_MSECS_PER_TSLICE)
+#define CSCHED_STIME_TO_CREDIT(_t) ((_t)*CSCHED_CREDITS_PER_MSEC/MILLISECS(1))
/*
@@ -121,6 +122,7 @@ struct csched_vcpu {
struct csched_dom *sdom;
struct vcpu *vcpu;
atomic_t credit;
+ s_time_t start_time; /* When we were scheduled (used for credit) */
uint16_t flags;
int16_t pri;
#ifdef CSCHED_STATS
@@ -209,6 +211,24 @@ __runq_remove(struct csched_vcpu *svc)
list_del_init(&svc->runq_elem);
}
+void burn_credits(struct csched_vcpu *svc, s_time_t now)
+{
+ s_time_t delta;
+
+ /* Assert svc is current */
+ ASSERT(svc==CSCHED_VCPU(per_cpu(schedule_data,
svc->vcpu->processor).curr));
+
+ if ( is_idle_vcpu(svc->vcpu) )
+ return;
+
+ delta = (now - svc->start_time);
+
+ if ( delta > 0 ) {
+ atomic_sub(CSCHED_STIME_TO_CREDIT(delta)+1, &svc->credit);
+ svc->start_time = now;
+ }
+}
+
static inline void
__runq_tickle(unsigned int cpu, struct csched_vcpu *new)
{
@@ -496,7 +516,7 @@ csched_vcpu_acct(unsigned int cpu)
/*
* Update credits
*/
- atomic_sub(CSCHED_CREDITS_PER_TICK, &svc->credit);
+ burn_credits(svc, NOW());
/*
* Put this VCPU and domain back on the active list if it was
@@ -1116,6 +1136,9 @@ csched_schedule(s_time_t now)
CSCHED_STAT_CRANK(schedule);
CSCHED_VCPU_CHECK(current);
+ /* Update credits */
+ burn_credits(scurr, now);
+
/*
* Select next runnable local VCPU (ie top of local runq)
*/
@@ -1152,6 +1175,9 @@ csched_schedule(s_time_t now)
{
cpu_clear(cpu, csched_priv.idlers);
}
+
+ if ( !is_idle_vcpu(snext->vcpu) )
+ snext->start_time = now;
/*
* Return task to run next...
@@ -1246,7 +1272,7 @@ csched_dump(void)
"\trunq_sort = %u\n"
"\tdefault-weight = %d\n"
"\tmsecs per tick = %dms\n"
- "\tcredits per tick = %d\n"
+ "\tcredits per msec = %d\n"
"\tticks per tslice = %d\n"
"\tticks per acct = %d\n"
"\tmigration delay = %uus\n",
@@ -1258,7 +1284,7 @@ csched_dump(void)
csched_priv.runq_sort,
CSCHED_DEFAULT_WEIGHT,
CSCHED_MSECS_PER_TICK,
- CSCHED_CREDITS_PER_TICK,
+ CSCHED_CREDITS_PER_MSEC,
CSCHED_TICKS_PER_TSLICE,
CSCHED_TICKS_PER_ACCT,
vcpu_migration_delay);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|