/* * Add an event filter to a given event. This will only work for PMUv2 PMUs. */ static int armv8pmu_set_event_filter(struct hw_perf_event *event, struct perf_event_attr *attr) { unsigned long config_base = 0; if (attr->exclude_idle) return -EPERM; if (is_kernel_in_hyp_mode() && attr->exclude_kernel != attr->exclude_hv) return -EINVAL; if (attr->exclude_user) config_base |= ARMV8_PMU_EXCLUDE_EL0; if (!is_kernel_in_hyp_mode() && attr->exclude_kernel) config_base |= ARMV8_PMU_EXCLUDE_EL1; if (!attr->exclude_hv) config_base |= ARMV8_PMU_INCLUDE_EL2; /* * Install the filter into config_base as this is used to * construct the event type. */ event->config_base = config_base; return 0; }
/* * Add an event filter to a given event. This will only work for PMUv2 PMUs. */ static int armv8pmu_set_event_filter(struct hw_perf_event *event, struct perf_event_attr *attr) { unsigned long config_base = 0; if (attr->exclude_idle) return -EPERM; /* * If we're running in hyp mode, then we *are* the hypervisor. * Therefore we ignore exclude_hv in this configuration, since * there's no hypervisor to sample anyway. This is consistent * with other architectures (x86 and Power). */ if (is_kernel_in_hyp_mode()) { if (!attr->exclude_kernel) config_base |= ARMV8_PMU_INCLUDE_EL2; } else { if (attr->exclude_kernel) config_base |= ARMV8_PMU_EXCLUDE_EL1; if (!attr->exclude_hv) config_base |= ARMV8_PMU_INCLUDE_EL2; } if (attr->exclude_user) config_base |= ARMV8_PMU_EXCLUDE_EL0; /* * Install the filter into config_base as this is used to * construct the event type. */ event->config_base = config_base; return 0; }
/* * Verify that a secondary CPU is running the kernel at the same * EL as that of the boot CPU. */ void verify_cpu_run_el(void) { bool in_el2 = is_kernel_in_hyp_mode(); bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode(); if (in_el2 ^ boot_cpu_el2) { pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n", smp_processor_id(), in_el2 ? 2 : 1, boot_cpu_el2 ? 2 : 1); cpu_panic_kernel(); } }
static int __init arch_timer_init(void) { int ret; /* * If HYP mode is available, we know that the physical timer * has been configured to be accessible from PL1. Use it, so * that a guest can use the virtual timer instead. * * If no interrupt provided for virtual timer, we'll have to * stick to the physical timer. It'd better be accessible... * * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE * accesses to CNTP_*_EL1 registers are silently redirected to * their CNTHP_*_EL2 counterparts, and use a different PPI * number. */ if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { bool has_ppi; if (is_kernel_in_hyp_mode()) { arch_timer_uses_ppi = HYP_PPI; has_ppi = !!arch_timer_ppi[HYP_PPI]; } else { arch_timer_uses_ppi = PHYS_SECURE_PPI; has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] || !!arch_timer_ppi[PHYS_NONSECURE_PPI]); } if (!has_ppi) { pr_warn("arch_timer: No interrupt available, giving up\n"); return -EINVAL; } } ret = arch_timer_register(); if (ret) return ret; ret = arch_timer_common_init(); if (ret) return ret; arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; return 0; }
static inline void save_boot_cpu_run_el(void) { boot_cpu_hyp_mode = is_kernel_in_hyp_mode(); }