From e53dc1608f9528b2db5abd8c786d46cd93a24c4d Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Aug 2010 08:31:49 +0100 Subject: [PATCH 1/5] svm: increment RIP over PAUSE instruction when emulating it Signed-off-by: Christoph Egger --- xen/arch/x86/hvm/svm/emulate.c | 4 +++- xen/arch/x86/hvm/svm/svm.c | 23 +++++++++++++++++------ xen/include/asm-x86/hvm/svm/emulate.h | 1 + 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c index 2c1693b878..2537dd2445 100644 --- a/xen/arch/x86/hvm/svm/emulate.c +++ b/xen/arch/x86/hvm/svm/emulate.c @@ -100,6 +100,7 @@ MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9); MAKE_INSTR(HLT, 1, 0xf4); MAKE_INSTR(INT3, 1, 0xcc); MAKE_INSTR(RDTSC, 2, 0x0f, 0x31); +MAKE_INSTR(PAUSE, 1, 0x90); static const u8 *opc_bytes[INSTR_MAX_COUNT] = { @@ -111,7 +112,8 @@ static const u8 *opc_bytes[INSTR_MAX_COUNT] = [INSTR_VMCALL] = OPCODE_VMCALL, [INSTR_HLT] = OPCODE_HLT, [INSTR_INT3] = OPCODE_INT3, - [INSTR_RDTSC] = OPCODE_RDTSC + [INSTR_RDTSC] = OPCODE_RDTSC, + [INSTR_PAUSE] = OPCODE_PAUSE, }; static int fetch(struct vcpu *v, u8 *buf, unsigned long addr, int len) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 1706c7fc94..7651012c40 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1261,6 +1261,22 @@ static void svm_vmexit_do_rdtsc(struct cpu_user_regs *regs) hvm_rdtsc_intercept(regs); } +static void svm_vmexit_do_pause(struct cpu_user_regs *regs) +{ + unsigned int inst_len; + + if ( (inst_len = __get_instruction_length(current, INSTR_PAUSE)) == 0 ) + return; + __update_guest_eip(regs, inst_len); + + /* + * The guest is running a contended spinlock and we've detected it. + * Do something useful, like reschedule the guest + */ + perfc_incr(pauseloop_exits); + do_sched_op_compat(SCHEDOP_yield, 0); +} + static void svm_vmexit_ud_intercept(struct cpu_user_regs *regs) { struct hvm_emulate_ctxt ctxt; @@ -1655,12 +1671,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) break; case VMEXIT_PAUSE: - /* - * The guest is running a contended spinlock and we've detected it. - * Do something useful, like reschedule the guest - */ - perfc_incr(pauseloop_exits); - do_sched_op_compat(SCHEDOP_yield, 0); + svm_vmexit_do_pause(regs); break; default: diff --git a/xen/include/asm-x86/hvm/svm/emulate.h b/xen/include/asm-x86/hvm/svm/emulate.h index 7f7a67f1db..b06f98e06f 100644 --- a/xen/include/asm-x86/hvm/svm/emulate.h +++ b/xen/include/asm-x86/hvm/svm/emulate.h @@ -31,6 +31,7 @@ enum instruction_index { INSTR_HLT, INSTR_INT3, INSTR_RDTSC, + INSTR_PAUSE, INSTR_MAX_COUNT /* Must be last - Number of instructions supported */ }; From 3a37d430ce266c8ec742a0075cd4a76e358c6a04 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Aug 2010 08:33:19 +0100 Subject: [PATCH 2/5] credit1: Make weight per-vcpu Change the meaning of credit1's "weight" parameter to be per-vcpu, rather than per-VM. At the moment, the "weight" parameter for a VM is set on a per-VM basis. This means that when cpu time is scarce, two VMs with the same weight will be given the same amount of total cpu time, no matter how many vcpus it has. I.e., if a VM has 1 vcpu, that vcpu will get x% of cpu time; if a VM has 2 vcpus, each vcpu will get (x/2)% of the cpu time. I believe this is a counter-intuitive interface. Users often choose to add vcpus; when they do so, it's with the expectation that a VM will need and use more cpu time. In my experience, however, users rarely change the weight parameter. So the normal course of events is for a user to decide a VM needs more processing power, add more cpus, but doesn't change the weight. The VM still gets the same amount of cpu time, but less efficiently allocated (because it's divided). The attached patch changes the meaning of the "weight" parameter, to be per-vcpu. Each vcpu is given the weight. So if you add an extra vcpu, your VM will get more cpu time as well. Signed-off-by: George Dunlap --- xen/common/sched_credit.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index 95384cabe0..2a7e299f11 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -555,10 +555,11 @@ __csched_vcpu_acct_start(struct csched_private *prv, struct csched_vcpu *svc) sdom->active_vcpu_count++; list_add(&svc->active_vcpu_elem, &sdom->active_vcpu); + /* Make weight per-vcpu */ + prv->weight += sdom->weight; if ( list_empty(&sdom->active_sdom_elem) ) { list_add(&sdom->active_sdom_elem, &prv->active_sdom); - prv->weight += sdom->weight; } } @@ -576,13 +577,13 @@ __csched_vcpu_acct_stop_locked(struct csched_private *prv, CSCHED_VCPU_STAT_CRANK(svc, state_idle); CSCHED_STAT_CRANK(acct_vcpu_idle); + BUG_ON( prv->weight < sdom->weight ); sdom->active_vcpu_count--; list_del_init(&svc->active_vcpu_elem); + prv->weight -= sdom->weight; if ( list_empty(&sdom->active_vcpu) ) { - BUG_ON( prv->weight < sdom->weight ); list_del_init(&sdom->active_sdom_elem); - prv->weight -= sdom->weight; } } @@ -804,8 +805,8 @@ csched_dom_cntl( { if ( !list_empty(&sdom->active_sdom_elem) ) { - prv->weight -= sdom->weight; - prv->weight += op->u.credit.weight; + prv->weight -= sdom->weight * sdom->active_vcpu_count; + prv->weight += op->u.credit.weight * sdom->active_vcpu_count; } sdom->weight = op->u.credit.weight; } @@ -976,9 +977,9 @@ csched_acct(void* dummy) BUG_ON( is_idle_domain(sdom->dom) ); BUG_ON( sdom->active_vcpu_count == 0 ); BUG_ON( sdom->weight == 0 ); - BUG_ON( sdom->weight > weight_left ); + BUG_ON( (sdom->weight * sdom->active_vcpu_count) > weight_left ); - weight_left -= sdom->weight; + weight_left -= ( sdom->weight * sdom->active_vcpu_count ); /* * A domain's fair share is computed using its weight in competition @@ -991,7 +992,9 @@ csched_acct(void* dummy) credit_peak = sdom->active_vcpu_count * CSCHED_CREDITS_PER_ACCT; if ( prv->credit_balance < 0 ) { - credit_peak += ( ( -prv->credit_balance * sdom->weight) + + credit_peak += ( ( -prv->credit_balance + * sdom->weight + * sdom->active_vcpu_count) + (weight_total - 1) ) / weight_total; } @@ -1002,11 +1005,15 @@ csched_acct(void* dummy) if ( credit_cap < credit_peak ) credit_peak = credit_cap; + /* FIXME -- set cap per-vcpu as well...? */ credit_cap = ( credit_cap + ( sdom->active_vcpu_count - 1 ) ) / sdom->active_vcpu_count; } - credit_fair = ( ( credit_total * sdom->weight) + (weight_total - 1) + credit_fair = ( ( credit_total + * sdom->weight + * sdom->active_vcpu_count ) + + (weight_total - 1) ) / weight_total; if ( credit_fair < credit_peak ) From 76ec4da93b8a101ae3e2850da771f08b311cbaae Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Aug 2010 08:38:35 +0100 Subject: [PATCH 3/5] x86: Allow dom0 pstate control to access APERF/MPERF/HWCR MSRs The current version of the powernow driver uses the APERF/MPEF and the HWCR MSRs. Add cases in traps.c to let dom0 access those MSRs. Signed-off-by: Mark Langsdorf --- xen/arch/x86/traps.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 5acf749b0d..447ce2348d 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -2228,6 +2228,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) case MSR_K8_PSTATE5: case MSR_K8_PSTATE6: case MSR_K8_PSTATE7: + case MSR_K8_HWCR: if ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) goto fail; if ( !is_cpufreq_controller(v->domain) ) @@ -2267,6 +2268,14 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) break; case MSR_IA32_MPERF: case MSR_IA32_APERF: + if (( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) && + ( boot_cpu_data.x86_vendor != X86_VENDOR_AMD ) ) + goto fail; + if ( !is_cpufreq_controller(v->domain) ) + break; + if ( wrmsr_safe(regs->ecx, msr_content ) != 0 ) + goto fail; + break; case MSR_IA32_PERF_CTL: if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ) goto fail; From b91d9efd399d353b9fa900d4b45f19f3fbdb98fd Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Aug 2010 08:39:11 +0100 Subject: [PATCH 4/5] Clean up event-channel debug-key output, and use spin_lock(). Signed-off-by: Jan Beulich --- xen/common/event_channel.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 881fac87fb..c6241d0598 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -1123,14 +1123,11 @@ static void domain_dump_evtchn_info(struct domain *d) bitmap_scnlistprintf(keyhandler_scratch, sizeof(keyhandler_scratch), d->poll_mask, d->max_vcpus); - printk("Domain %d polling vCPUs: {%s}\n", - d->domain_id, keyhandler_scratch); - - if ( !spin_trylock(&d->event_lock) ) - return; - printk("Event channel information for domain %d:\n" - " port [p/m]\n", d->domain_id); + "Polling vCPUs: {%s}\n" + " port [p/m]\n", d->domain_id, keyhandler_scratch); + + spin_lock(&d->event_lock); for ( port = 1; port < MAX_EVTCHNS(d); ++port ) { From c69440a3d7b874c90d24edc9b3aad3cb4287bff4 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 13 Aug 2010 08:46:45 +0100 Subject: [PATCH 5/5] linux buildconfig: Fix quoting error Prevent shell syntax error if $(XEN_LINUX_CONFIG) is empty. Signed-off-by: Jeremy Fitzhardinge --- buildconfigs/mk.linux-2.6-common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildconfigs/mk.linux-2.6-common b/buildconfigs/mk.linux-2.6-common index 6f203eff3a..f3680f0982 100644 --- a/buildconfigs/mk.linux-2.6-common +++ b/buildconfigs/mk.linux-2.6-common @@ -75,7 +75,7 @@ $(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src # tree. Finally attempt to use make defconfig. set -e ; \ CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p' $(LINUX_SRCDIR)/Makefile); \ - if [ ! -z "$(XEN_LINUX_CONFIG)" -a -r $(XEN_LINUX_CONFIG) ]; then \ + if [ ! -z "$(XEN_LINUX_CONFIG)" -a -r "$(XEN_LINUX_CONFIG)" ]; then \ cp $(XEN_LINUX_CONFIG) $(CONFIG_FILE); \ elif [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \ cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) $(CONFIG_FILE) ; \