lkml.org 
[lkml]   [2011]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC 1/5] x86, perf: Implement software-activation of lwp
    Date
    From: Benjamin Block <benjamin.block@amd.com>

    Adds activation of lwp for ring3-software. With this patch and
    scheduler-support (xsave-patches done by Hans Rosenfeld) a
    userspace-application can use the lwp-instructions (llwpcb,
    slwpcb, ..) to activate lwp.

    Support for the threshold-interrupt is not given and thus the
    corresponding bits are not set. It is therefore unavailable for
    userspace-applications.

    Signed-off-by: Benjamin Block <benjamin.block@amd.com>
    Signed-off-by: Hans Rosenfeld <hans.rosenfeld@amd.com>
    ---
    arch/x86/include/asm/msr-index.h | 1 +
    arch/x86/kernel/cpu/Makefile | 2 +-
    arch/x86/kernel/cpu/perf_event_amd_lwp.c | 138 ++++++++++++++++++++++++++++++
    3 files changed, 140 insertions(+), 1 deletions(-)
    create mode 100644 arch/x86/kernel/cpu/perf_event_amd_lwp.c

    diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
    index 2d9cf3c..557a6fd 100644
    --- a/arch/x86/include/asm/msr-index.h
    +++ b/arch/x86/include/asm/msr-index.h
    @@ -136,6 +136,7 @@
    #define MSR_AMD64_IBSDCPHYSAD 0xc0011039
    #define MSR_AMD64_IBSCTL 0xc001103a
    #define MSR_AMD64_IBSBRTARGET 0xc001103b
    +#define MSR_AMD64_LWP_CFG 0xc0000105
    #define MSR_AMD64_LWP_CBADDR 0xc0000106

    /* Fam 15h MSRs */
    diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
    index 6042981..9973465 100644
    --- a/arch/x86/kernel/cpu/Makefile
    +++ b/arch/x86/kernel/cpu/Makefile
    @@ -20,7 +20,7 @@ obj-$(CONFIG_X86_32) += bugs.o
    obj-$(CONFIG_X86_64) += bugs_64.o

    obj-$(CONFIG_CPU_SUP_INTEL) += intel.o
    -obj-$(CONFIG_CPU_SUP_AMD) += amd.o
    +obj-$(CONFIG_CPU_SUP_AMD) += amd.o perf_event_amd_lwp.o
    obj-$(CONFIG_CPU_SUP_CYRIX_32) += cyrix.o
    obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o
    obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o
    diff --git a/arch/x86/kernel/cpu/perf_event_amd_lwp.c b/arch/x86/kernel/cpu/perf_event_amd_lwp.c
    new file mode 100644
    index 0000000..9aa9a91
    --- /dev/null
    +++ b/arch/x86/kernel/cpu/perf_event_amd_lwp.c
    @@ -0,0 +1,138 @@
    +#include <linux/perf_event.h>
    +#include <linux/module.h>
    +
    +#include <asm/cpufeature.h>
    +#include <asm/processor.h>
    +
    +/* masks only the events as of spec r3.08 (lwp v1) */
    +#define LWP_EVENT_MASK 0x7E
    +
    +struct lwp_capabilities {
    +#define LWP_CAPS_LWP 0
    +#define LWP_CAPS_THRESHOLD 31
    + unsigned long supported_events;
    + unsigned long available_events;
    +
    + u8 size_lwpcb;
    + u8 size_event;
    + u8 size_max_event_id;
    + u8 size_event_offset;
    +
    +#define LWP_CAPS_FILTER_BRANCH 28
    +#define LWP_CAPS_FILTER_IP 29
    +#define LWP_CAPS_FILTER_CACHE_LVL 30
    +#define LWP_CAPS_FILTER_CACHE_LAT 31
    + unsigned long features;
    +};
    +
    +union lwp_cfg_msr {
    + struct {
    + u32 allowed_events;
    + u8 core_id;
    + u8 interrupt_vector;
    + u16 reserved;
    + } cfg;
    + u64 msr_value;
    +};
    +
    +static struct lwp_capabilities lwp_caps;
    +
    +static void get_lwp_caps(struct lwp_capabilities *caps)
    +{
    + u32 sizes;
    +
    + memset(caps, 0, sizeof(*caps));
    + cpuid(0x8000001C, (u32 *) &caps->available_events, &sizes,
    + (u32 *) &caps->features,
    + (u32 *) &caps->supported_events);
    +
    + caps->size_lwpcb = (u8) sizes;
    + caps->size_event = (u8) (sizes >> 0x8);
    + caps->size_max_event_id = (u8) (sizes >> 0x10);
    + caps->size_event_offset = (u8) (sizes >> 0x18);
    +}
    +
    +static void lwp_start_cpu(void *c)
    +{
    + struct lwp_capabilities *caps = (struct lwp_capabilities *) c;
    + union lwp_cfg_msr msr;
    +
    + msr.msr_value = 0;
    + /* allow supported events of lwpv1 [1..6] */
    + msr.cfg.allowed_events |= ((u32) caps->supported_events) &
    + LWP_EVENT_MASK;
    + /*
    + * The value showing up in the core-id field of a event-record.
    + * I currently only 8 bits wide.
    + */
    + msr.cfg.core_id = (u8) smp_processor_id();
    +
    + /*
    + * We currently do not support the threshold-interrupt so
    + * bit 31 and [40..47] of msr.msr_value keep 0
    + *
    + * msr.cfg.allowed_events |= (1U << 31);
    + * msr.cfg.interrupt_vector = xxx;
    + */
    +
    + wrmsrl(MSR_AMD64_LWP_CFG, msr.msr_value);
    +}
    +
    +static int __cpuinit
    +lwp_cpu_notifier(struct notifier_block *self, unsigned long action,
    + void *hcpu)
    +{
    + switch (action & ~CPU_TASKS_FROZEN) {
    + case CPU_STARTING:
    + lwp_start_cpu(&lwp_caps);
    + break;
    + default:
    + return NOTIFY_DONE;
    + }
    +
    + return NOTIFY_OK;
    +}
    +
    +static __init int amd_lwp_init(void)
    +{
    + if (!static_cpu_has(X86_FEATURE_LWP))
    + return -ENODEV;
    +
    + /* read the _supported_ events */
    + get_lwp_caps(&lwp_caps);
    +
    + /* we currently only support lwp v1; spec r3.08 */
    + if (!test_bit(LWP_CAPS_LWP, &lwp_caps.supported_events) ||
    + (((lwp_caps.features >> 9) & 0x7F) != 1))
    + return -ENODEV;
    +
    + if (!test_bit(LWP_CAPS_THRESHOLD, &lwp_caps.supported_events))
    + return -ENODEV;
    +
    + get_online_cpus();
    +
    + barrier();
    +
    + perf_cpu_notifier(lwp_cpu_notifier);
    + smp_call_function(lwp_start_cpu, &lwp_caps, 1);
    +
    + put_online_cpus();
    +
    + /*
    + * The values returned by cpuid are corresponding to the values in
    + * MSR_AMD64_LWP_CFG and determine what events are available. As we
    + * have just changed MSR_AMD64_LWP_CFG, we have to re-read the lwp_caps.
    + */
    + get_lwp_caps(&lwp_caps);
    +
    + printk(KERN_INFO "perf: AMD LWP caps: "
    + "[%#lx],[%#hhx|%#hhx|%#hhx|%#hhx],[%#lx],[%#lx]",
    + lwp_caps.available_events, lwp_caps.size_lwpcb,
    + lwp_caps.size_event, lwp_caps.size_max_event_id,
    + lwp_caps.size_event_offset, lwp_caps.features,
    + lwp_caps.supported_events);
    +
    + return 0;
    +}
    +
    +device_initcall(amd_lwp_init);
    --
    1.7.7



    \
     
     \ /
      Last update: 2011-12-16 17:15    [W:0.031 / U:32.072 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site