static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported) { struct vcpu *v = current; struct vpmu_struct *vpmu = vcpu_vpmu(v); ASSERT(!supported); /* For all counters, enable guest only mode for HVM guest */ if ( (get_pmu_reg_type(msr) == MSR_TYPE_CTRL) && !(is_guest_mode(msr_content)) ) { set_guest_mode(msr_content); } /* check if the first counter is enabled */ if ( (get_pmu_reg_type(msr) == MSR_TYPE_CTRL) && is_pmu_enabled(msr_content) && !vpmu_is_set(vpmu, VPMU_RUNNING) ) { if ( !acquire_pmu_ownership(PMU_OWNER_HVM) ) return 1; vpmu_set(vpmu, VPMU_RUNNING); apic_write(APIC_LVTPC, PMU_APIC_VECTOR); vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR; if ( !((struct amd_vpmu_context *)vpmu->context)->msr_bitmap_set ) amd_vpmu_set_msr_bitmap(v); } /* stop saving & restore if guest stops first counter */ if ( (get_pmu_reg_type(msr) == MSR_TYPE_CTRL) && (is_pmu_enabled(msr_content) == 0) && vpmu_is_set(vpmu, VPMU_RUNNING) ) { apic_write(APIC_LVTPC, PMU_APIC_VECTOR | APIC_LVT_MASKED); vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED; vpmu_reset(vpmu, VPMU_RUNNING); if ( ((struct amd_vpmu_context *)vpmu->context)->msr_bitmap_set ) amd_vpmu_unset_msr_bitmap(v); release_pmu_ownship(PMU_OWNER_HVM); } if ( !vpmu_is_set(vpmu, VPMU_CONTEXT_LOADED) || vpmu_is_set(vpmu, VPMU_FROZEN) ) { context_load(v); vpmu_set(vpmu, VPMU_CONTEXT_LOADED); vpmu_reset(vpmu, VPMU_FROZEN); } /* Update vpmu context immediately */ context_update(msr, msr_content); /* Write to hw counters */ wrmsrl(msr, msr_content); return 1; }
static int stop_ebs(void) { int ret = 0; if (is_pmu_enabled()) { on_each_cpu(stop_pmu, NULL, 1); ret = unregister_pmu_isr(); if (ret != 0) { return ret; } ret = free_pmu(); if (ret != 0) { return ret; } unregister_hotcpu_notifier(&cpu_notifier_for_pmu); } return 0; }
static int start_ebs(bool is_start_paused) { int i; int ret; get_settings(); if (is_pmu_enabled()) { pmu_paused = is_start_paused; ret = register_hotcpu_notifier(&cpu_notifier_for_pmu); if (ret != 0) return ret; ret = allocate_pmu(); if (ret != 0) return ret; ret = register_pmu_isr(px_css_isr); if (ret != 0) return ret; for (i=0; i<COUNTER_A9_MAX_ID; i++) reg_value[i] = 0; on_each_cpu(start_pmu, &is_start_paused, 1); } return 0; }
static int resume_ebs(void) { if (is_pmu_enabled()) { pmu_paused = false; on_each_cpu(resume_pmu, NULL, 1); } return 0; }
static int pause_ebs(void) { if (is_pmu_enabled()) { pmu_paused = true; on_each_cpu(pause_pmu, NULL, 1); } return 0; }
static int resume_ebs(void) { int ret; if (is_pmu_enabled()) { if ((ret = resume_pmu()) != 0) return ret; } return 0; }
static int stop_ebs(void) { int ret; if (is_pmu_enabled()) { if ((ret = stop_pmu()) != 0) return ret; } return 0; }
static int start_ebs(bool is_start_paused) { int ret; get_settings(); if (is_pmu_enabled()) { if ((ret = start_pmu(is_start_paused)) != 0) return ret; } return 0; }