[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
>>> 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). Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |