/* * This runs only on the current cpu. We try to find an LVT offset and * setup the local APIC. For this we must disable preemption. On * success we initialize all nodes with this offset. This updates then * the offset in the IBS_CTL per-node msr. The per-core APIC setup of * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that * is using the new offset. */ static void force_ibs_eilvt_setup(void) { int offset; int ret; preempt_disable(); /* find the next free available EILVT entry, skip offset 0 */ for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) { if (get_eilvt(offset)) break; } preempt_enable(); if (offset == APIC_EILVT_NR_MAX) { printk(KERN_DEBUG "No EILVT entry available\n"); return; } ret = setup_ibs_ctl(offset); if (ret) goto out; if (!ibs_eilvt_valid()) goto out; pr_info("IBS: LVT offset %d assigned\n", offset); return; out: preempt_disable(); put_eilvt(offset); preempt_enable(); return; }
static __init int amd_ibs_init(void) { u32 caps; int ret = -EINVAL; caps = __get_ibs_caps(); if (!caps) return -ENODEV; /* ibs not supported by the cpu */ ibs_eilvt_setup(); if (!ibs_eilvt_valid()) goto out; perf_ibs_pm_init(); cpu_notifier_register_begin(); ibs_caps = caps; /* make ibs_caps visible to other cpus: */ smp_mb(); smp_call_function(setup_APIC_ibs, NULL, 1); __perf_cpu_notifier(perf_ibs_cpu_notifier); cpu_notifier_register_done(); ret = perf_event_ibs_init(); out: if (ret) pr_err("Failed to setup IBS, %d\n", ret); return ret; }
static __init int amd_ibs_init(void) { u32 caps; int ret = -EINVAL; caps = __get_ibs_caps(); if (!caps) return -ENODEV; /* ibs not supported by the cpu */ /* * Force LVT offset assignment for family 10h: The offsets are * not assigned by the BIOS for this family, so the OS is * responsible for doing it. If the OS assignment fails, fall * back to BIOS settings and try to setup this. */ if (boot_cpu_data.x86 == 0x10) force_ibs_eilvt_setup(); if (!ibs_eilvt_valid()) goto out; get_online_cpus(); ibs_caps = caps; /* make ibs_caps visible to other cpus: */ smp_mb(); perf_cpu_notifier(perf_ibs_cpu_notifier); smp_call_function(setup_APIC_ibs, NULL, 1); put_online_cpus(); ret = perf_event_ibs_init(); out: if (ret) pr_err("Failed to setup IBS, %d\n", ret); return ret; }