debuggers.hg

changeset 21948:2c6ae364ed7b

xenoprofile: Add IBS support

Add IBS support for AMD family 10h processors. The major
implementation is derived from latest Linux. Two hypercalls are added,
which is necessary for IBS feature detection and user mode parameter
read.

Signed-off-by: Wei Wang <wei.wang2@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Aug 02 11:00:56 2010 +0100 (2010-08-02)
parents 9f49667fec71
children 668f71224241
files xen/arch/x86/oprofile/nmi_int.c xen/arch/x86/oprofile/op_counter.h xen/arch/x86/oprofile/op_model_athlon.c xen/arch/x86/oprofile/xenoprof.c xen/common/xenoprof.c xen/include/asm-x86/xenoprof.h xen/include/public/xenoprof.h
line diff
     1.1 --- a/xen/arch/x86/oprofile/nmi_int.c	Fri Jul 30 15:22:39 2010 +0100
     1.2 +++ b/xen/arch/x86/oprofile/nmi_int.c	Mon Aug 02 11:00:56 2010 +0100
     1.3 @@ -28,6 +28,7 @@
     1.4  #include "op_x86_model.h"
     1.5   
     1.6  struct op_counter_config counter_config[OP_MAX_COUNTER];
     1.7 +struct op_ibs_config ibs_config;
     1.8  
     1.9  static struct op_x86_model_spec const *__read_mostly model;
    1.10  static struct op_msrs cpu_msrs[NR_CPUS];
    1.11 @@ -430,6 +431,7 @@ static int __init nmi_init(void)
    1.12  			case 0x10:
    1.13  				model = &op_athlon_spec;
    1.14  				cpu_type = "x86-64/family10";
    1.15 +				ibs_caps = ibs_init();
    1.16  				break;
    1.17  			case 0x11:
    1.18  				model = &op_athlon_spec;
     2.1 --- a/xen/arch/x86/oprofile/op_counter.h	Fri Jul 30 15:22:39 2010 +0100
     2.2 +++ b/xen/arch/x86/oprofile/op_counter.h	Mon Aug 02 11:00:56 2010 +0100
     2.3 @@ -26,4 +26,16 @@ struct op_counter_config {
     2.4  
     2.5  extern struct op_counter_config counter_config[];
     2.6  
     2.7 +/* AMD IBS configuration */
     2.8 +struct op_ibs_config {
     2.9 +    unsigned long op_enabled;
    2.10 +    unsigned long fetch_enabled;
    2.11 +    unsigned long max_cnt_fetch;
    2.12 +    unsigned long max_cnt_op;
    2.13 +    unsigned long rand_en;
    2.14 +    unsigned long dispatched_ops;
    2.15 +};
    2.16 +
    2.17 +extern struct op_ibs_config ibs_config;
    2.18 +
    2.19  #endif /* OP_COUNTER_H */
     3.1 --- a/xen/arch/x86/oprofile/op_model_athlon.c	Fri Jul 30 15:22:39 2010 +0100
     3.2 +++ b/xen/arch/x86/oprofile/op_model_athlon.c	Mon Aug 02 11:00:56 2010 +0100
     3.3 @@ -19,6 +19,7 @@
     3.4  #include <asm/regs.h>
     3.5  #include <asm/current.h>
     3.6  #include <asm/hvm/support.h>
     3.7 +#include <xen/pci_regs.h>
     3.8   
     3.9  #include "op_x86_model.h"
    3.10  #include "op_counter.h"
    3.11 @@ -47,6 +48,116 @@ static unsigned long reset_value[NUM_COU
    3.12  
    3.13  extern char svm_stgi_label[];
    3.14  
    3.15 +u32 ibs_caps = 0;
    3.16 +static u64 ibs_op_ctl;
    3.17 +
    3.18 +/* IBS cpuid feature detection */
    3.19 +#define IBS_CPUID_FEATURES              0x8000001b
    3.20 +
    3.21 +/* IBS MSRs */
    3.22 +#define MSR_AMD64_IBSFETCHCTL           0xc0011030
    3.23 +#define MSR_AMD64_IBSFETCHLINAD         0xc0011031
    3.24 +#define MSR_AMD64_IBSFETCHPHYSAD        0xc0011032
    3.25 +#define MSR_AMD64_IBSOPCTL              0xc0011033
    3.26 +#define MSR_AMD64_IBSOPRIP              0xc0011034
    3.27 +#define MSR_AMD64_IBSOPDATA             0xc0011035
    3.28 +#define MSR_AMD64_IBSOPDATA2            0xc0011036
    3.29 +#define MSR_AMD64_IBSOPDATA3            0xc0011037
    3.30 +#define MSR_AMD64_IBSDCLINAD            0xc0011038
    3.31 +#define MSR_AMD64_IBSDCPHYSAD           0xc0011039
    3.32 +#define MSR_AMD64_IBSCTL                0xc001103a
    3.33 +
    3.34 +/*
    3.35 + * Same bit mask as for IBS cpuid feature flags (Fn8000_001B_EAX), but
    3.36 + * bit 0 is used to indicate the existence of IBS.
    3.37 + */
    3.38 +#define IBS_CAPS_AVAIL                  (1LL<<0)
    3.39 +#define IBS_CAPS_RDWROPCNT              (1LL<<3)
    3.40 +#define IBS_CAPS_OPCNT                  (1LL<<4)
    3.41 +
    3.42 +/* IBS randomization macros */
    3.43 +#define IBS_RANDOM_BITS                 12
    3.44 +#define IBS_RANDOM_MASK                 ((1ULL << IBS_RANDOM_BITS) - 1)
    3.45 +#define IBS_RANDOM_MAXCNT_OFFSET        (1ULL << (IBS_RANDOM_BITS - 5))
    3.46 +
    3.47 +/* IbsFetchCtl bits/masks */
    3.48 +#define IBS_FETCH_RAND_EN               (1ULL<<57)
    3.49 +#define IBS_FETCH_VAL                   (1ULL<<49)
    3.50 +#define IBS_FETCH_ENABLE                (1ULL<<48)
    3.51 +#define IBS_FETCH_CNT                   0xFFFF0000ULL
    3.52 +#define IBS_FETCH_MAX_CNT               0x0000FFFFULL
    3.53 +
    3.54 +/* IbsOpCtl bits */
    3.55 +#define IBS_OP_CNT_CTL                  (1ULL<<19)
    3.56 +#define IBS_OP_VAL                      (1ULL<<18)
    3.57 +#define IBS_OP_ENABLE                   (1ULL<<17)
    3.58 +#define IBS_OP_MAX_CNT                  0x0000FFFFULL
    3.59 +
    3.60 +/* IBS sample identifier */
    3.61 +#define IBS_FETCH_CODE                  13
    3.62 +#define IBS_OP_CODE                     14
    3.63 +
    3.64 +#define clamp(val, min, max) ({			\
    3.65 +	typeof(val) __val = (val);		\
    3.66 +	typeof(min) __min = (min);		\
    3.67 +	typeof(max) __max = (max);		\
    3.68 +	(void) (&__val == &__min);		\
    3.69 +	(void) (&__val == &__max);		\
    3.70 +	__val = __val < __min ? __min: __val;	\
    3.71 +	__val > __max ? __max: __val; })
    3.72 +
    3.73 +/*
    3.74 + * 16-bit Linear Feedback Shift Register (LFSR)
    3.75 + */
    3.76 +static unsigned int lfsr_random(void)
    3.77 +{
    3.78 +    static unsigned int lfsr_value = 0xF00D;
    3.79 +    unsigned int bit;
    3.80 +
    3.81 +    /* Compute next bit to shift in */
    3.82 +    bit = ((lfsr_value >> 0) ^
    3.83 +           (lfsr_value >> 2) ^
    3.84 +           (lfsr_value >> 3) ^
    3.85 +           (lfsr_value >> 5)) & 0x0001;
    3.86 +
    3.87 +    /* Advance to next register value */
    3.88 +    lfsr_value = (lfsr_value >> 1) | (bit << 15);
    3.89 +
    3.90 +    return lfsr_value;
    3.91 +}
    3.92 +
    3.93 +/*
    3.94 + * IBS software randomization
    3.95 + *
    3.96 + * The IBS periodic op counter is randomized in software. The lower 12
    3.97 + * bits of the 20 bit counter are randomized. IbsOpCurCnt is
    3.98 + * initialized with a 12 bit random value.
    3.99 + */
   3.100 +static inline u64 op_amd_randomize_ibs_op(u64 val)
   3.101 +{
   3.102 +    unsigned int random = lfsr_random();
   3.103 +
   3.104 +    if (!(ibs_caps & IBS_CAPS_RDWROPCNT))
   3.105 +        /*
   3.106 +         * Work around if the hw can not write to IbsOpCurCnt
   3.107 +         *
   3.108 +         * Randomize the lower 8 bits of the 16 bit
   3.109 +         * IbsOpMaxCnt [15:0] value in the range of -128 to
   3.110 +         * +127 by adding/subtracting an offset to the
   3.111 +         * maximum count (IbsOpMaxCnt).
   3.112 +         *
   3.113 +         * To avoid over or underflows and protect upper bits
   3.114 +         * starting at bit 16, the initial value for
   3.115 +         * IbsOpMaxCnt must fit in the range from 0x0081 to
   3.116 +         * 0xff80.
   3.117 +         */
   3.118 +        val += (s8)(random >> 4);
   3.119 +    else
   3.120 +        val |= (u64)(random & IBS_RANDOM_MASK) << 32;
   3.121 +
   3.122 +    return val;
   3.123 +}
   3.124 +
   3.125  static void athlon_fill_in_addresses(struct op_msrs * const msrs)
   3.126  {
   3.127  	msrs->counters[0].addr = MSR_K7_PERFCTR0;
   3.128 @@ -101,6 +212,78 @@ static void athlon_setup_ctrs(struct op_
   3.129  	}
   3.130  }
   3.131  
   3.132 +static inline void
   3.133 +ibs_log_event(u64 data, struct cpu_user_regs * const regs, int mode)
   3.134 +{
   3.135 +	struct vcpu *v = current;
   3.136 +	u32 temp = 0;
   3.137 +
   3.138 +	temp = data & 0xFFFFFFFF;
   3.139 +	xenoprof_log_event(v, regs, temp, mode, 0);
   3.140 +	
   3.141 +	temp = (data >> 32) & 0xFFFFFFFF;
   3.142 +	xenoprof_log_event(v, regs, temp, mode, 0);
   3.143 +	
   3.144 +}
   3.145 +
   3.146 +static inline int handle_ibs(int mode, struct cpu_user_regs * const regs)
   3.147 +{
   3.148 +	u64 val, ctl;
   3.149 +	struct vcpu *v = current;
   3.150 +
   3.151 +	if (!ibs_caps)
   3.152 +		return 1;
   3.153 +
   3.154 +	if (ibs_config.fetch_enabled) {
   3.155 +		rdmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
   3.156 +		if (ctl & IBS_FETCH_VAL) {
   3.157 +			rdmsrl(MSR_AMD64_IBSFETCHLINAD, val);
   3.158 +			xenoprof_log_event(v, regs, IBS_FETCH_CODE, mode, 0);
   3.159 +			xenoprof_log_event(v, regs, val, mode, 0);
   3.160 +
   3.161 +			ibs_log_event(val, regs, mode);
   3.162 +			ibs_log_event(ctl, regs, mode);
   3.163 +
   3.164 +			rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, val);
   3.165 +			ibs_log_event(val, regs, mode);
   3.166 +		
   3.167 +			/* reenable the IRQ */
   3.168 +			ctl &= ~(IBS_FETCH_VAL | IBS_FETCH_CNT);
   3.169 +			ctl |= IBS_FETCH_ENABLE;
   3.170 +			wrmsrl(MSR_AMD64_IBSFETCHCTL, ctl);
   3.171 +		}
   3.172 +	}
   3.173 +
   3.174 +	if (ibs_config.op_enabled) {
   3.175 +		rdmsrl(MSR_AMD64_IBSOPCTL, ctl);
   3.176 +		if (ctl & IBS_OP_VAL) {
   3.177 +
   3.178 +			rdmsrl(MSR_AMD64_IBSOPRIP, val);
   3.179 +			xenoprof_log_event(v, regs, IBS_OP_CODE, mode, 0);
   3.180 +			xenoprof_log_event(v, regs, val, mode, 0);
   3.181 +			
   3.182 +			ibs_log_event(val, regs, mode);
   3.183 +
   3.184 +			rdmsrl(MSR_AMD64_IBSOPDATA, val);
   3.185 +			ibs_log_event(val, regs, mode);
   3.186 +			rdmsrl(MSR_AMD64_IBSOPDATA2, val);
   3.187 +			ibs_log_event(val, regs, mode);
   3.188 +			rdmsrl(MSR_AMD64_IBSOPDATA3, val);
   3.189 +			ibs_log_event(val, regs, mode);
   3.190 +			rdmsrl(MSR_AMD64_IBSDCLINAD, val);
   3.191 +			ibs_log_event(val, regs, mode);
   3.192 +			rdmsrl(MSR_AMD64_IBSDCPHYSAD, val);
   3.193 +			ibs_log_event(val, regs, mode);
   3.194 +
   3.195 +			/* reenable the IRQ */
   3.196 +			ctl = op_amd_randomize_ibs_op(ibs_op_ctl);
   3.197 +			wrmsrl(MSR_AMD64_IBSOPCTL, ctl);
   3.198 +		}
   3.199 +	}
   3.200 +
   3.201 +    return 1;
   3.202 +}
   3.203 +
   3.204  static int athlon_check_ctrs(unsigned int const cpu,
   3.205  			     struct op_msrs const * const msrs,
   3.206  			     struct cpu_user_regs * const regs)
   3.207 @@ -134,10 +317,51 @@ static int athlon_check_ctrs(unsigned in
   3.208  		}
   3.209  	}
   3.210  
   3.211 +	ovf = handle_ibs(mode, regs);
   3.212  	/* See op_model_ppro.c */
   3.213  	return ovf;
   3.214  }
   3.215  
   3.216 +static inline void start_ibs(void)
   3.217 +{
   3.218 +	u64 val = 0;
   3.219 +
   3.220 +	if (!ibs_caps)
   3.221 +		return;
   3.222 +
   3.223 +	if (ibs_config.fetch_enabled) {
   3.224 +		val = (ibs_config.max_cnt_fetch >> 4) & IBS_FETCH_MAX_CNT;
   3.225 +		val |= ibs_config.rand_en ? IBS_FETCH_RAND_EN : 0;
   3.226 +		val |= IBS_FETCH_ENABLE;
   3.227 +		wrmsrl(MSR_AMD64_IBSFETCHCTL, val);
   3.228 +	}
   3.229 +
   3.230 +	if (ibs_config.op_enabled) {
   3.231 +		ibs_op_ctl = ibs_config.max_cnt_op >> 4;
   3.232 +		if (!(ibs_caps & IBS_CAPS_RDWROPCNT)) {
   3.233 +			/*
   3.234 +			 * IbsOpCurCnt not supported.  See
   3.235 +			 * op_amd_randomize_ibs_op() for details.
   3.236 +			 */
   3.237 +			ibs_op_ctl = clamp((unsigned long long)ibs_op_ctl, 
   3.238 +							0x0081ULL, 0xFF80ULL);
   3.239 +		} else {
   3.240 +			/*
   3.241 +			 * The start value is randomized with a
   3.242 +			 * positive offset, we need to compensate it
   3.243 +			 * with the half of the randomized range. Also
   3.244 +			 * avoid underflows.
   3.245 +			 */
   3.246 +		ibs_op_ctl = min(ibs_op_ctl + IBS_RANDOM_MAXCNT_OFFSET,
   3.247 +					IBS_OP_MAX_CNT);
   3.248 +		}
   3.249 +		if (ibs_caps & IBS_CAPS_OPCNT && ibs_config.dispatched_ops)
   3.250 +			ibs_op_ctl |= IBS_OP_CNT_CTL;
   3.251 +		ibs_op_ctl |= IBS_OP_ENABLE;
   3.252 +		val = op_amd_randomize_ibs_op(ibs_op_ctl);
   3.253 +		wrmsrl(MSR_AMD64_IBSOPCTL, val);
   3.254 +	}
   3.255 +}
   3.256   
   3.257  static void athlon_start(struct op_msrs const * const msrs)
   3.258  {
   3.259 @@ -150,8 +374,22 @@ static void athlon_start(struct op_msrs 
   3.260  			CTRL_WRITE(msr_content, msrs, i);
   3.261  		}
   3.262  	}
   3.263 +	start_ibs();
   3.264  }
   3.265  
   3.266 +static void stop_ibs(void)
   3.267 +{
   3.268 +	if (!ibs_caps)
   3.269 +		return;
   3.270 +
   3.271 +	if (ibs_config.fetch_enabled)
   3.272 +		/* clear max count and enable */
   3.273 +		wrmsrl(MSR_AMD64_IBSFETCHCTL, 0);
   3.274 +
   3.275 +	if (ibs_config.op_enabled)
   3.276 +		/* clear max count and enable */
   3.277 +		wrmsrl(MSR_AMD64_IBSOPCTL, 0);
   3.278 +}
   3.279  
   3.280  static void athlon_stop(struct op_msrs const * const msrs)
   3.281  {
   3.282 @@ -165,8 +403,114 @@ static void athlon_stop(struct op_msrs c
   3.283  		CTRL_SET_INACTIVE(msr_content);
   3.284  		CTRL_WRITE(msr_content, msrs, i);
   3.285  	}
   3.286 +
   3.287 +	stop_ibs();
   3.288 +}
   3.289 +
   3.290 +#define IBSCTL_LVTOFFSETVAL             (1 << 8)
   3.291 +#define APIC_EILVT_MSG_NMI              0x4
   3.292 +#define APIC_EILVT_LVTOFF_IBS           1
   3.293 +#define APIC_EILVTn(n)                  (0x500 + 0x10 * n)
   3.294 +static inline void init_ibs_nmi_per_cpu(void *arg)
   3.295 +{
   3.296 +	unsigned long reg;
   3.297 +
   3.298 +	reg = (APIC_EILVT_LVTOFF_IBS << 4) + APIC_EILVTn(0);
   3.299 +	apic_write(reg, APIC_EILVT_MSG_NMI << 8);
   3.300  }
   3.301  
   3.302 +#define PCI_VENDOR_ID_AMD               0x1022
   3.303 +#define PCI_DEVICE_ID_AMD_10H_NB_MISC   0x1203
   3.304 +#define IBSCTL                          0x1cc
   3.305 +static int init_ibs_nmi(void)
   3.306 +{
   3.307 +	int bus, dev, func;
   3.308 +	u32 id, value;
   3.309 +	u16 vendor_id, dev_id;
   3.310 +	int nodes;
   3.311 +
   3.312 +	/* per CPU setup */
   3.313 +	on_each_cpu(init_ibs_nmi_per_cpu, NULL, 1);
   3.314 +
   3.315 +	nodes = 0;
   3.316 +	for (bus = 0; bus < 256; bus++) {
   3.317 +		for (dev = 0; dev < 32; dev++) {
   3.318 +			for (func = 0; func < 8; func++) {
   3.319 +				id = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
   3.320 +
   3.321 +				if ((id == 0xffffffff) || (id == 0x00000000) ||
   3.322 +					(id == 0x0000ffff) || (id == 0xffff0000))
   3.323 +					continue;
   3.324 +
   3.325 +				vendor_id = id & 0xffff;
   3.326 +				dev_id = (id >> 16) & 0xffff;
   3.327 +
   3.328 +				if ((vendor_id == PCI_VENDOR_ID_AMD) &&
   3.329 +					(dev_id == PCI_DEVICE_ID_AMD_10H_NB_MISC)) {
   3.330 +
   3.331 +					pci_conf_write32(bus, dev, func, IBSCTL,
   3.332 +						IBSCTL_LVTOFFSETVAL | APIC_EILVT_LVTOFF_IBS);
   3.333 +
   3.334 +					value = pci_conf_read32(bus, dev, func, IBSCTL);
   3.335 +
   3.336 +					if (value != (IBSCTL_LVTOFFSETVAL |
   3.337 +						APIC_EILVT_LVTOFF_IBS)) {
   3.338 +						printk("Xenoprofile: Failed to setup IBS LVT offset, "
   3.339 +							"IBSCTL = 0x%08x", value);
   3.340 +						return 1;
   3.341 +					}
   3.342 +					nodes++;
   3.343 +				}
   3.344 +			}
   3.345 +		}
   3.346 +	}
   3.347 +
   3.348 +	if (!nodes) {
   3.349 +		printk("Xenoprofile: No CPU node configured for IBS");
   3.350 +		return 1;
   3.351 +	}
   3.352 +
   3.353 +	return 0;
   3.354 +}
   3.355 +
   3.356 +static u32 get_ibs_caps(void)
   3.357 +{
   3.358 +	unsigned int max_level;
   3.359 +
   3.360 +	if (!boot_cpu_has(X86_FEATURE_IBS))
   3.361 +		return 0;
   3.362 +
   3.363 +    /* check IBS cpuid feature flags */
   3.364 +	max_level = cpuid_eax(0x80000000);
   3.365 +	if (max_level < IBS_CPUID_FEATURES)
   3.366 +		return IBS_CAPS_AVAIL;
   3.367 +
   3.368 +	ibs_caps = cpuid_eax(IBS_CPUID_FEATURES);
   3.369 +	if (!(ibs_caps & IBS_CAPS_AVAIL))
   3.370 +		/* cpuid flags not valid */
   3.371 +		return IBS_CAPS_AVAIL;
   3.372 +
   3.373 +	return ibs_caps;
   3.374 +}
   3.375 +
   3.376 +u32 ibs_init(void)
   3.377 +{
   3.378 +	u32 ibs_caps = 0;
   3.379 +
   3.380 +	ibs_caps = get_ibs_caps();
   3.381 +
   3.382 +	if ( !ibs_caps )
   3.383 +		return 0;
   3.384 +
   3.385 +	if (init_ibs_nmi()) {
   3.386 +		ibs_caps = 0;
   3.387 +		return 0;
   3.388 +	}
   3.389 +
   3.390 +	printk("Xenoprofile: AMD IBS detected (0x%08x)\n",
   3.391 +		(unsigned)ibs_caps);
   3.392 +	return ibs_caps;
   3.393 +}
   3.394  
   3.395  struct op_x86_model_spec const op_athlon_spec = {
   3.396  	.num_counters = NUM_COUNTERS,
     4.1 --- a/xen/arch/x86/oprofile/xenoprof.c	Fri Jul 30 15:22:39 2010 +0100
     4.2 +++ b/xen/arch/x86/oprofile/xenoprof.c	Mon Aug 02 11:00:56 2010 +0100
     4.3 @@ -38,6 +38,23 @@ int xenoprof_arch_counter(XEN_GUEST_HAND
     4.4      return 0;
     4.5  }
     4.6  
     4.7 +int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg)
     4.8 +{
     4.9 +    struct xenoprof_ibs_counter ibs_counter;
    4.10 +
    4.11 +    if ( copy_from_guest(&ibs_counter, arg, 1) )
    4.12 +        return -EFAULT;
    4.13 +
    4.14 +    ibs_config.op_enabled = ibs_counter.op_enabled;
    4.15 +    ibs_config.fetch_enabled = ibs_counter.fetch_enabled;
    4.16 +    ibs_config.max_cnt_fetch = ibs_counter.max_cnt_fetch;
    4.17 +    ibs_config.max_cnt_op = ibs_counter.max_cnt_op;
    4.18 +    ibs_config.rand_en = ibs_counter.rand_en;
    4.19 +    ibs_config.dispatched_ops = ibs_counter.dispatched_ops;
    4.20 +
    4.21 +    return 0;
    4.22 +}
    4.23 +
    4.24  #ifdef CONFIG_COMPAT
    4.25  int compat_oprof_arch_counter(XEN_GUEST_HANDLE(void) arg)
    4.26  {
     5.1 --- a/xen/common/xenoprof.c	Fri Jul 30 15:22:39 2010 +0100
     5.2 +++ b/xen/common/xenoprof.c	Mon Aug 02 11:00:56 2010 +0100
     5.3 @@ -49,6 +49,9 @@ static u64 passive_samples;
     5.4  static u64 idle_samples;
     5.5  static u64 others_samples;
     5.6  
     5.7 +/* AMD IBS support */
     5.8 +extern u32 ibs_caps;
     5.9 +
    5.10  int acquire_pmu_ownership(int pmu_ownship)
    5.11  {
    5.12      spin_lock(&pmu_owner_lock);
    5.13 @@ -881,6 +884,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HAN
    5.14              ret = -EFAULT;
    5.15          break;
    5.16  
    5.17 +    case XENOPROF_ibs_counter:
    5.18 +        if ( (xenoprof_state != XENOPROF_COUNTERS_RESERVED) ||
    5.19 +             (adomains == 0) )
    5.20 +        {
    5.21 +            ret = -EPERM;
    5.22 +            break;
    5.23 +        }
    5.24 +        ret = xenoprof_arch_ibs_counter(arg);
    5.25 +        break;
    5.26 +
    5.27 +    case XENOPROF_get_ibs_caps:
    5.28 +        ret = ibs_caps;
    5.29 +        break;
    5.30 +
    5.31      default:
    5.32          ret = -ENOSYS;
    5.33      }
     6.1 --- a/xen/include/asm-x86/xenoprof.h	Fri Jul 30 15:22:39 2010 +0100
     6.2 +++ b/xen/include/asm-x86/xenoprof.h	Mon Aug 02 11:00:56 2010 +0100
     6.3 @@ -42,10 +42,15 @@ int xenoprof_arch_init(int *num_events, 
     6.4  
     6.5  int xenoprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
     6.6  int compat_oprof_arch_counter(XEN_GUEST_HANDLE(void) arg);
     6.7 +int xenoprof_arch_ibs_counter(XEN_GUEST_HANDLE(void) arg);
     6.8  
     6.9  struct vcpu;
    6.10  struct cpu_user_regs;
    6.11  
    6.12 +/* AMD IBS support */
    6.13 +u32 ibs_init(void);
    6.14 +extern u32 ibs_caps;
    6.15 +
    6.16  int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs);
    6.17  
    6.18  static inline int xenoprof_backtrace_supported(void)
     7.1 --- a/xen/include/public/xenoprof.h	Fri Jul 30 15:22:39 2010 +0100
     7.2 +++ b/xen/include/public/xenoprof.h	Mon Aug 02 11:00:56 2010 +0100
     7.3 @@ -50,7 +50,11 @@
     7.4  #define XENOPROF_shutdown           13
     7.5  #define XENOPROF_get_buffer         14
     7.6  #define XENOPROF_set_backtrace      15
     7.7 -#define XENOPROF_last_op            15
     7.8 +
     7.9 +/* AMD IBS support */
    7.10 +#define XENOPROF_get_ibs_caps       16
    7.11 +#define XENOPROF_ibs_counter        17
    7.12 +#define XENOPROF_last_op            17
    7.13  
    7.14  #define MAX_OPROF_EVENTS    32
    7.15  #define MAX_OPROF_DOMAINS   25
    7.16 @@ -124,6 +128,16 @@ typedef struct xenoprof_passive {
    7.17  } xenoprof_passive_t;
    7.18  DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
    7.19  
    7.20 +struct xenoprof_ibs_counter {
    7.21 +    uint64_t op_enabled;
    7.22 +    uint64_t fetch_enabled;
    7.23 +    uint64_t max_cnt_fetch;
    7.24 +    uint64_t max_cnt_op;
    7.25 +    uint64_t rand_en;
    7.26 +    uint64_t dispatched_ops;
    7.27 +};
    7.28 +typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
    7.29 +DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
    7.30  
    7.31  #endif /* __XEN_PUBLIC_XENOPROF_H__ */
    7.32