162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __KVM_X86_LAPIC_H 362306a36Sopenharmony_ci#define __KVM_X86_LAPIC_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <kvm/iodev.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/kvm_host.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "hyperv.h" 1062306a36Sopenharmony_ci#include "smm.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define KVM_APIC_INIT 0 1362306a36Sopenharmony_ci#define KVM_APIC_SIPI 1 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define APIC_SHORT_MASK 0xc0000 1662306a36Sopenharmony_ci#define APIC_DEST_NOSHORT 0x0 1762306a36Sopenharmony_ci#define APIC_DEST_MASK 0x800 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define APIC_BUS_CYCLE_NS 1 2062306a36Sopenharmony_ci#define APIC_BUS_FREQUENCY (1000000000ULL / APIC_BUS_CYCLE_NS) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define APIC_BROADCAST 0xFF 2362306a36Sopenharmony_ci#define X2APIC_BROADCAST 0xFFFFFFFFul 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cienum lapic_mode { 2662306a36Sopenharmony_ci LAPIC_MODE_DISABLED = 0, 2762306a36Sopenharmony_ci LAPIC_MODE_INVALID = X2APIC_ENABLE, 2862306a36Sopenharmony_ci LAPIC_MODE_XAPIC = MSR_IA32_APICBASE_ENABLE, 2962306a36Sopenharmony_ci LAPIC_MODE_X2APIC = MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cienum lapic_lvt_entry { 3362306a36Sopenharmony_ci LVT_TIMER, 3462306a36Sopenharmony_ci LVT_THERMAL_MONITOR, 3562306a36Sopenharmony_ci LVT_PERFORMANCE_COUNTER, 3662306a36Sopenharmony_ci LVT_LINT0, 3762306a36Sopenharmony_ci LVT_LINT1, 3862306a36Sopenharmony_ci LVT_ERROR, 3962306a36Sopenharmony_ci LVT_CMCI, 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci KVM_APIC_MAX_NR_LVT_ENTRIES, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define APIC_LVTx(x) ((x) == LVT_CMCI ? APIC_LVTCMCI : APIC_LVTT + 0x10 * (x)) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct kvm_timer { 4762306a36Sopenharmony_ci struct hrtimer timer; 4862306a36Sopenharmony_ci s64 period; /* unit: ns */ 4962306a36Sopenharmony_ci ktime_t target_expiration; 5062306a36Sopenharmony_ci u32 timer_mode; 5162306a36Sopenharmony_ci u32 timer_mode_mask; 5262306a36Sopenharmony_ci u64 tscdeadline; 5362306a36Sopenharmony_ci u64 expired_tscdeadline; 5462306a36Sopenharmony_ci u32 timer_advance_ns; 5562306a36Sopenharmony_ci atomic_t pending; /* accumulated triggered timers */ 5662306a36Sopenharmony_ci bool hv_timer_in_use; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct kvm_lapic { 6062306a36Sopenharmony_ci unsigned long base_address; 6162306a36Sopenharmony_ci struct kvm_io_device dev; 6262306a36Sopenharmony_ci struct kvm_timer lapic_timer; 6362306a36Sopenharmony_ci u32 divide_count; 6462306a36Sopenharmony_ci struct kvm_vcpu *vcpu; 6562306a36Sopenharmony_ci bool apicv_active; 6662306a36Sopenharmony_ci bool sw_enabled; 6762306a36Sopenharmony_ci bool irr_pending; 6862306a36Sopenharmony_ci bool lvt0_in_nmi_mode; 6962306a36Sopenharmony_ci /* Number of bits set in ISR. */ 7062306a36Sopenharmony_ci s16 isr_count; 7162306a36Sopenharmony_ci /* The highest vector set in ISR; if -1 - invalid, must scan ISR. */ 7262306a36Sopenharmony_ci int highest_isr_cache; 7362306a36Sopenharmony_ci /** 7462306a36Sopenharmony_ci * APIC register page. The layout matches the register layout seen by 7562306a36Sopenharmony_ci * the guest 1:1, because it is accessed by the vmx microcode. 7662306a36Sopenharmony_ci * Note: Only one register, the TPR, is used by the microcode. 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci void *regs; 7962306a36Sopenharmony_ci gpa_t vapic_addr; 8062306a36Sopenharmony_ci struct gfn_to_hva_cache vapic_cache; 8162306a36Sopenharmony_ci unsigned long pending_events; 8262306a36Sopenharmony_ci unsigned int sipi_vector; 8362306a36Sopenharmony_ci int nr_lvt_entries; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct dest_map; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciint kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns); 8962306a36Sopenharmony_civoid kvm_free_lapic(struct kvm_vcpu *vcpu); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ciint kvm_apic_has_interrupt(struct kvm_vcpu *vcpu); 9262306a36Sopenharmony_ciint kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu); 9362306a36Sopenharmony_ciint kvm_get_apic_interrupt(struct kvm_vcpu *vcpu); 9462306a36Sopenharmony_ciint kvm_apic_accept_events(struct kvm_vcpu *vcpu); 9562306a36Sopenharmony_civoid kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event); 9662306a36Sopenharmony_ciu64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu); 9762306a36Sopenharmony_civoid kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8); 9862306a36Sopenharmony_civoid kvm_lapic_set_eoi(struct kvm_vcpu *vcpu); 9962306a36Sopenharmony_civoid kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value); 10062306a36Sopenharmony_ciu64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); 10162306a36Sopenharmony_civoid kvm_recalculate_apic_map(struct kvm *kvm); 10262306a36Sopenharmony_civoid kvm_apic_set_version(struct kvm_vcpu *vcpu); 10362306a36Sopenharmony_civoid kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu); 10462306a36Sopenharmony_cibool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, 10562306a36Sopenharmony_ci int shorthand, unsigned int dest, int dest_mode); 10662306a36Sopenharmony_ciint kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2); 10762306a36Sopenharmony_civoid kvm_apic_clear_irr(struct kvm_vcpu *vcpu, int vec); 10862306a36Sopenharmony_cibool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr); 10962306a36Sopenharmony_cibool kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir, int *max_irr); 11062306a36Sopenharmony_civoid kvm_apic_update_ppr(struct kvm_vcpu *vcpu); 11162306a36Sopenharmony_ciint kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq, 11262306a36Sopenharmony_ci struct dest_map *dest_map); 11362306a36Sopenharmony_ciint kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type); 11462306a36Sopenharmony_civoid kvm_apic_update_apicv(struct kvm_vcpu *vcpu); 11562306a36Sopenharmony_ciint kvm_alloc_apic_access_page(struct kvm *kvm); 11662306a36Sopenharmony_civoid kvm_inhibit_apic_access_page(struct kvm_vcpu *vcpu); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cibool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, 11962306a36Sopenharmony_ci struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map); 12062306a36Sopenharmony_civoid kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciu64 kvm_get_apic_base(struct kvm_vcpu *vcpu); 12362306a36Sopenharmony_ciint kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info); 12462306a36Sopenharmony_ciint kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s); 12562306a36Sopenharmony_ciint kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s); 12662306a36Sopenharmony_cienum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu); 12762306a36Sopenharmony_ciint kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciu64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu); 13062306a36Sopenharmony_civoid kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_civoid kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset); 13362306a36Sopenharmony_civoid kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); 13662306a36Sopenharmony_civoid kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); 13762306a36Sopenharmony_civoid kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ciint kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data); 14062306a36Sopenharmony_ciint kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data); 14162306a36Sopenharmony_ciint kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ciint kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data); 14462306a36Sopenharmony_ciint kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciint kvm_lapic_set_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len); 14762306a36Sopenharmony_civoid kvm_lapic_exit(void); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciu64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#define VEC_POS(v) ((v) & (32 - 1)) 15262306a36Sopenharmony_ci#define REG_POS(v) (((v) >> 5) << 4) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic inline void kvm_lapic_clear_vector(int vec, void *bitmap) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic inline void kvm_lapic_set_vector(int vec, void *bitmap) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci kvm_lapic_set_vector(vec, apic->regs + APIC_IRR); 16762306a36Sopenharmony_ci /* 16862306a36Sopenharmony_ci * irr_pending must be true if any interrupt is pending; set it after 16962306a36Sopenharmony_ci * APIC_IRR to avoid race with apic_clear_irr 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ci apic->irr_pending = true; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic inline u32 __kvm_lapic_get_reg(char *regs, int reg_off) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci return *((u32 *) (regs + reg_off)); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic inline u32 kvm_lapic_get_reg(struct kvm_lapic *apic, int reg_off) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci return __kvm_lapic_get_reg(apic->regs, reg_off); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ciDECLARE_STATIC_KEY_FALSE(kvm_has_noapic_vcpu); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic inline bool lapic_in_kernel(struct kvm_vcpu *vcpu) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci if (static_branch_unlikely(&kvm_has_noapic_vcpu)) 18962306a36Sopenharmony_ci return vcpu->arch.apic; 19062306a36Sopenharmony_ci return true; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ciextern struct static_key_false_deferred apic_hw_disabled; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic inline bool kvm_apic_hw_enabled(struct kvm_lapic *apic) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci if (static_branch_unlikely(&apic_hw_disabled.key)) 19862306a36Sopenharmony_ci return apic->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE; 19962306a36Sopenharmony_ci return true; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ciextern struct static_key_false_deferred apic_sw_disabled; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline bool kvm_apic_sw_enabled(struct kvm_lapic *apic) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci if (static_branch_unlikely(&apic_sw_disabled.key)) 20762306a36Sopenharmony_ci return apic->sw_enabled; 20862306a36Sopenharmony_ci return true; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic inline bool kvm_apic_present(struct kvm_vcpu *vcpu) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci return lapic_in_kernel(vcpu) && kvm_apic_hw_enabled(vcpu->arch.apic); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic inline int kvm_lapic_enabled(struct kvm_vcpu *vcpu) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci return kvm_apic_present(vcpu) && kvm_apic_sw_enabled(vcpu->arch.apic); 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic inline int apic_x2apic_mode(struct kvm_lapic *apic) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci return apic->vcpu->arch.apic_base & X2APIC_ENABLE; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic inline bool kvm_vcpu_apicv_active(struct kvm_vcpu *vcpu) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci return lapic_in_kernel(vcpu) && vcpu->arch.apic->apicv_active; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic inline bool kvm_apic_has_pending_init_or_sipi(struct kvm_vcpu *vcpu) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci return lapic_in_kernel(vcpu) && vcpu->arch.apic->pending_events; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic inline bool kvm_apic_init_sipi_allowed(struct kvm_vcpu *vcpu) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci return !is_smm(vcpu) && 23962306a36Sopenharmony_ci !static_call(kvm_x86_apic_init_signal_blocked)(vcpu); 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic inline bool kvm_lowest_prio_delivery(struct kvm_lapic_irq *irq) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci return (irq->delivery_mode == APIC_DM_LOWEST || 24562306a36Sopenharmony_ci irq->msi_redir_hint); 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cistatic inline int kvm_lapic_latched_init(struct kvm_vcpu *vcpu) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci return lapic_in_kernel(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events); 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cibool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_civoid kvm_wait_lapic_expire(struct kvm_vcpu *vcpu); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_civoid kvm_bitmap_or_dest_vcpus(struct kvm *kvm, struct kvm_lapic_irq *irq, 25862306a36Sopenharmony_ci unsigned long *vcpu_bitmap); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cibool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq, 26162306a36Sopenharmony_ci struct kvm_vcpu **dest_vcpu); 26262306a36Sopenharmony_ciint kvm_vector_to_index(u32 vector, u32 dest_vcpus, 26362306a36Sopenharmony_ci const unsigned long *bitmap, u32 bitmap_size); 26462306a36Sopenharmony_civoid kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu); 26562306a36Sopenharmony_civoid kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu); 26662306a36Sopenharmony_civoid kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu); 26762306a36Sopenharmony_cibool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu); 26862306a36Sopenharmony_civoid kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu); 26962306a36Sopenharmony_cibool kvm_can_use_hv_timer(struct kvm_vcpu *vcpu); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic inline enum lapic_mode kvm_apic_mode(u64 apic_base) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic inline u8 kvm_xapic_id(struct kvm_lapic *apic) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci return kvm_lapic_get_reg(apic, APIC_ID) >> 24; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci#endif 282