[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v12 for-xen-4.5 11/20] x86/VPMU: Interface for setting PMU mode and flags
Am Montag 29 September 2014, 14:59:43 schrieb Jan Beulich: > >>> On 29.09.14 at 15:25, <dietmar.hahn@xxxxxxxxxxxxxx> wrote: > > Only a minor note below. > > > > Am Donnerstag 25 September 2014, 15:28:47 schrieb Boris Ostrovsky: > >> Add runtime interface for setting PMU mode and flags. Three main modes are > >> provided: > >> * XENPMU_MODE_OFF: PMU is not virtualized > >> * XENPMU_MODE_SELF: Guests can access PMU MSRs and receive PMU interrupts. > >> * XENPMU_MODE_HV: Same as XENPMU_MODE_SELF for non-proviledged guests, dom0 > >> can profile itself and the hypervisor. > >> > >> Note that PMU modes are different from what can be provided at Xen's boot > > line > >> with 'vpmu' argument. An 'off' (or '0') value is equivalent to > > XENPMU_MODE_OFF. > >> Any other value, on the other hand, will cause VPMU mode to be set to > >> XENPMU_MODE_SELF during boot. > >> > >> For feature flags only Intel's BTS is currently supported. > >> > >> Mode and flags are set via HYPERVISOR_xenpmu_op hypercall. > >> > >> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx> > >> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > >> --- > >> tools/flask/policy/policy/modules/xen/xen.te | 3 + > >> xen/arch/x86/domain.c | 6 +- > >> xen/arch/x86/hvm/svm/vpmu.c | 4 +- > >> xen/arch/x86/hvm/vmx/vpmu_core2.c | 10 +- > >> xen/arch/x86/hvm/vpmu.c | 206 > > +++++++++++++++++++++++++-- > >> xen/arch/x86/x86_64/compat/entry.S | 4 + > >> xen/arch/x86/x86_64/entry.S | 4 + > >> xen/include/Makefile | 2 + > >> xen/include/asm-x86/hvm/vpmu.h | 27 ++-- > >> xen/include/public/pmu.h | 44 ++++++ > >> xen/include/public/xen.h | 1 + > >> xen/include/xen/hypercall.h | 4 + > >> xen/include/xlat.lst | 4 + > >> xen/include/xsm/dummy.h | 15 ++ > >> xen/include/xsm/xsm.h | 6 + > >> xen/xsm/dummy.c | 1 + > >> xen/xsm/flask/hooks.c | 18 +++ > >> xen/xsm/flask/policy/access_vectors | 2 + > >> 18 files changed, 334 insertions(+), 27 deletions(-) > >> > >> diff --git a/tools/flask/policy/policy/modules/xen/xen.te > > b/tools/flask/policy/policy/modules/xen/xen.te > >> index 1937883..fb761cd 100644 > >> --- a/tools/flask/policy/policy/modules/xen/xen.te > >> +++ b/tools/flask/policy/policy/modules/xen/xen.te > >> @@ -64,6 +64,9 @@ allow dom0_t xen_t:xen { > >> getidle debug getcpuinfo heap pm_op mca_op lockprof cpupool_op tmem_op > >> tmem_control getscheduler setscheduler > >> }; > >> +allow dom0_t xen_t:xen2 { > >> + pmu_ctrl > >> +}; > >> allow dom0_t xen_t:mmu memorymap; > >> > >> # Allow dom0 to use these domctls on itself. For domctls acting on other > >> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c > >> index 7b1dfe6..6a07737 100644 > >> --- a/xen/arch/x86/domain.c > >> +++ b/xen/arch/x86/domain.c > >> @@ -1503,7 +1503,7 @@ void context_switch(struct vcpu *prev, struct vcpu > > *next) > >> if ( is_hvm_vcpu(prev) ) > >> { > >> if (prev != next) > >> - vpmu_save(prev); > >> + vpmu_switch_from(prev, next); > >> > >> if ( !list_empty(&prev->arch.hvm_vcpu.tm_list) ) > >> pt_save_timer(prev); > >> @@ -1546,9 +1546,9 @@ void context_switch(struct vcpu *prev, struct vcpu > > *next) > >> !is_hardware_domain(next->domain)); > >> } > >> > >> - if (is_hvm_vcpu(next) && (prev != next) ) > >> + if ( is_hvm_vcpu(prev) && (prev != next) ) > >> /* Must be done with interrupts enabled */ > >> - vpmu_load(next); > >> + vpmu_switch_to(prev, next); > >> > >> context_saved(prev); > >> > >> diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c > >> index 124b147..37d8228 100644 > >> --- a/xen/arch/x86/hvm/svm/vpmu.c > >> +++ b/xen/arch/x86/hvm/svm/vpmu.c > >> @@ -479,14 +479,14 @@ struct arch_vpmu_ops amd_vpmu_ops = { > >> .arch_vpmu_dump = amd_vpmu_dump > >> }; > >> > >> -int svm_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) > >> +int svm_vpmu_initialise(struct vcpu *v) > >> { > >> struct vpmu_struct *vpmu = vcpu_vpmu(v); > >> uint8_t family = current_cpu_data.x86; > >> int ret = 0; > >> > >> /* vpmu enabled? */ > >> - if ( !vpmu_flags ) > >> + if ( vpmu_mode == XENPMU_MODE_OFF ) > >> return 0; > >> > >> switch ( family ) > >> diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c > > b/xen/arch/x86/hvm/vmx/vpmu_core2.c > >> index beff5c3..c0a45cd 100644 > >> --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c > >> +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c > >> @@ -703,13 +703,13 @@ static int core2_vpmu_do_interrupt(struct > >> cpu_user_regs > > *regs) > >> return 1; > >> } > >> > >> -static int core2_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) > >> +static int core2_vpmu_initialise(struct vcpu *v) > >> { > >> struct vpmu_struct *vpmu = vcpu_vpmu(v); > >> u64 msr_content; > >> static bool_t ds_warned; > >> > >> - if ( !(vpmu_flags & VPMU_BOOT_BTS) ) > >> + if ( !(vpmu_features & XENPMU_FEATURE_INTEL_BTS) ) > >> goto func_out; > >> /* Check the 'Debug Store' feature in the CPUID.EAX[1]:EDX[21] */ > >> while ( boot_cpu_has(X86_FEATURE_DS) ) > >> @@ -824,7 +824,7 @@ struct arch_vpmu_ops core2_no_vpmu_ops = { > >> .do_cpuid = core2_no_vpmu_do_cpuid, > >> }; > >> > >> -int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags) > >> +int vmx_vpmu_initialise(struct vcpu *v) > >> { > >> struct vpmu_struct *vpmu = vcpu_vpmu(v); > >> uint8_t family = current_cpu_data.x86; > >> @@ -832,7 +832,7 @@ int vmx_vpmu_initialise(struct vcpu *v, unsigned int > > vpmu_flags) > >> int ret = 0; > >> > >> vpmu->arch_vpmu_ops = &core2_no_vpmu_ops; > >> - if ( !vpmu_flags ) > >> + if ( vpmu_mode == XENPMU_MODE_OFF ) > >> return 0; > >> > >> if ( family == 6 ) > >> @@ -875,7 +875,7 @@ int vmx_vpmu_initialise(struct vcpu *v, unsigned int > > vpmu_flags) > >> /* future: */ > >> case 0x3d: > >> case 0x4e: > >> - ret = core2_vpmu_initialise(v, vpmu_flags); > >> + ret = core2_vpmu_initialise(v); > >> if ( !ret ) > >> vpmu->arch_vpmu_ops = &core2_vpmu_ops; > >> return ret; > >> diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c > >> index 071b869..5fcee0e 100644 > >> --- a/xen/arch/x86/hvm/vpmu.c > >> +++ b/xen/arch/x86/hvm/vpmu.c > >> @@ -21,6 +21,8 @@ > >> #include <xen/config.h> > >> #include <xen/sched.h> > >> #include <xen/xenoprof.h> > >> +#include <xen/event.h> > >> +#include <xen/guest_access.h> > >> #include <asm/regs.h> > >> #include <asm/types.h> > >> #include <asm/msr.h> > >> @@ -32,13 +34,22 @@ > >> #include <asm/hvm/svm/vmcb.h> > >> #include <asm/apic.h> > >> #include <public/pmu.h> > >> +#include <xen/tasklet.h> > >> +#include <xsm/xsm.h> > >> + > >> +#include <compat/pmu.h> > >> +CHECK_pmu_params; > >> +CHECK_pmu_intel_ctxt; > >> +CHECK_pmu_amd_ctxt; > >> +CHECK_pmu_cntr_pair; > >> > >> /* > >> * "vpmu" : vpmu generally enabled > >> * "vpmu=off" : vpmu generally disabled > >> * "vpmu=bts" : vpmu enabled and Intel BTS feature switched on. > >> */ > >> -static unsigned int __read_mostly opt_vpmu_enabled; > >> +uint64_t __read_mostly vpmu_mode = XENPMU_MODE_OFF; > >> +uint64_t __read_mostly vpmu_features = 0; > >> static void parse_vpmu_param(char *s); > >> custom_param("vpmu", parse_vpmu_param); > >> > >> @@ -52,7 +63,7 @@ static void __init parse_vpmu_param(char *s) > >> break; > >> default: > >> if ( !strcmp(s, "bts") ) > >> - opt_vpmu_enabled |= VPMU_BOOT_BTS; > >> + vpmu_features |= XENPMU_FEATURE_INTEL_BTS; > >> else if ( *s ) > >> { > >> printk("VPMU: unknown flag: %s - vpmu disabled!\n", s); > >> @@ -60,7 +71,8 @@ static void __init parse_vpmu_param(char *s) > >> } > >> /* fall through */ > >> case 1: > >> - opt_vpmu_enabled |= VPMU_BOOT_ENABLED; > >> + /* Default VPMU mode */ > >> + vpmu_mode = XENPMU_MODE_SELF; > >> break; > >> } > >> } > >> @@ -77,6 +89,9 @@ int vpmu_do_wrmsr(unsigned int msr, uint64_t > >> msr_content, > > uint64_t supported) > >> { > >> struct vpmu_struct *vpmu = vcpu_vpmu(current); > >> > >> + if ( !(vpmu_mode & (XENPMU_MODE_SELF | XENPMU_MODE_HV)) ) > >> + return 0; > >> + > >> if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_wrmsr ) > >> return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content, supported); > >> return 0; > >> @@ -86,6 +101,9 @@ int vpmu_do_rdmsr(unsigned int msr, uint64_t > >> *msr_content) > >> { > >> struct vpmu_struct *vpmu = vcpu_vpmu(current); > >> > >> + if ( !(vpmu_mode & (XENPMU_MODE_SELF | XENPMU_MODE_HV)) ) > >> + return 0; > >> + > >> if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_rdmsr ) > >> return vpmu->arch_vpmu_ops->do_rdmsr(msr, msr_content); > >> return 0; > >> @@ -242,19 +260,19 @@ void vpmu_initialise(struct vcpu *v) > >> switch ( vendor ) > >> { > >> case X86_VENDOR_AMD: > >> - if ( svm_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) > >> - opt_vpmu_enabled = 0; > >> + if ( svm_vpmu_initialise(v) != 0 ) > >> + vpmu_mode = XENPMU_MODE_OFF; > >> break; > >> > >> case X86_VENDOR_INTEL: > >> - if ( vmx_vpmu_initialise(v, opt_vpmu_enabled) != 0 ) > >> - opt_vpmu_enabled = 0; > >> + if ( vmx_vpmu_initialise(v) != 0 ) > >> + vpmu_mode = XENPMU_MODE_OFF; > >> break; > >> > >> default: > >> printk("VPMU: Initialization failed. " > >> "Unknown CPU vendor %d\n", vendor); > >> - opt_vpmu_enabled = 0; > >> + vpmu_mode = XENPMU_MODE_OFF; > >> break; > >> } > >> } > >> @@ -276,3 +294,175 @@ void vpmu_dump(struct vcpu *v) > >> vpmu->arch_vpmu_ops->arch_vpmu_dump(v); > >> } > >> > >> +static atomic_t vpmu_sched_counter; > >> + > >> +static void vpmu_sched_checkin(unsigned long unused) > >> +{ > >> + atomic_inc(&vpmu_sched_counter); > >> +} > >> + > >> +static int vpmu_force_context_switch(void) > >> +{ > >> + unsigned i, j, allbutself_num, mycpu; > >> + static s_time_t start, now; > >> + struct tasklet **sync_task; > >> + struct vcpu *curr_vcpu = current; > >> + int ret = 0; > >> + > >> + allbutself_num = num_online_cpus() - 1; > >> + > >> + sync_task = xzalloc_array(struct tasklet *, allbutself_num); > >> + if ( !sync_task ) > >> + { > >> + printk(XENLOG_WARNING "vpmu_force_context_switch: out of > > memory\n"); > >> + return -ENOMEM; > >> + } > >> + > >> + for ( i = 0; i < allbutself_num; i++ ) > >> + { > >> + sync_task[i] = xmalloc(struct tasklet); > >> + if ( sync_task[i] == NULL ) > >> + { > >> + printk(XENLOG_WARNING "vpmu_force_context_switch: out of > > memory\n"); > >> + ret = -ENOMEM; > >> + goto out; > >> + } > >> + tasklet_init(sync_task[i], vpmu_sched_checkin, 0); > > > > Only a question of understanding. > > Is there a special reason not to use a single memory allocation > > except for memory fragmentation on systems with a large number of cpus? > > > > struct tasklet *sync_task; > > sync_task = xmalloc(sizeof(struct tasklet) * allbutself_num); > > Apart from this then needing to be xmalloc_array() - yes, the > reason here is to avoid non-order-zero runtime allocations. I.e. > the alternative would be to provide something vmalloc()-like to > be used here (or open code it as we do in a couple of other > places). Thank you for the hint! Dietmar. > > Jan > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > http://lists.xen.org/xen-devel > -- Company details: http://ts.fujitsu.com/imprint.html _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |