Refactor x2apic_reg_reserved() into get_x2apic_reg_semantics() and have it provide the semantics for all registers. The full semantics will be used by the MSR test to verify KVM correctly emulates all x2APIC MSRs. No functional change intended. Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- lib/x86/apic.h | 59 ++++++++++++++++++++++++++++++++++++++----------- x86/vmx_tests.c | 6 ++--- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/lib/x86/apic.h b/lib/x86/apic.h index 6d27f047..023dff0d 100644 --- a/lib/x86/apic.h +++ b/lib/x86/apic.h @@ -1,6 +1,7 @@ #ifndef _X86_APIC_H_ #define _X86_APIC_H_ +#include <bitops.h> #include <stdint.h> #include "apic-defs.h" @@ -74,24 +75,56 @@ static inline bool apic_lvt_entry_supported(int idx) return GET_APIC_MAXLVT(apic_read(APIC_LVR)) >= idx; } -static inline bool x2apic_reg_reserved(u32 reg) +enum x2apic_reg_semantics { + X2APIC_INVALID = 0, + X2APIC_READABLE = BIT(0), + X2APIC_WRITABLE = BIT(1), + X2APIC_RO = X2APIC_READABLE, + X2APIC_WO = X2APIC_WRITABLE, + X2APIC_RW = X2APIC_READABLE | X2APIC_WRITABLE, +}; + +static inline enum x2apic_reg_semantics get_x2apic_reg_semantics(u32 reg) { + assert(!(reg & 0xf)); + switch (reg) { - case 0x000 ... 0x010: - case 0x040 ... 0x070: - case 0x090: - case 0x0c0: - case 0x0e0: - case 0x290 ... 0x2e0: - case 0x310: - case 0x3a0 ... 0x3d0: - case 0x3f0: - return true; + case APIC_ID: + case APIC_LVR: + case APIC_PROCPRI: + case APIC_LDR: + case APIC_ISR ... APIC_ISR + 0x70: + case APIC_TMR ... APIC_TMR + 0x70: + case APIC_IRR ... APIC_IRR + 0x70: + case APIC_TMCCT: + return X2APIC_RO; + case APIC_TASKPRI: + case APIC_SPIV: + case APIC_ESR: + case APIC_ICR: + case APIC_LVTT: + case APIC_LVTTHMR: + case APIC_LVTPC: + case APIC_LVT0: + case APIC_LVT1: + case APIC_LVTERR: + case APIC_TMICT: + case APIC_TDCR: + return X2APIC_RW; + case APIC_EOI: + case APIC_SELF_IPI: + return X2APIC_WO; case APIC_CMCI: - return !apic_lvt_entry_supported(6); + if (apic_lvt_entry_supported(6)) + return X2APIC_RW; + break; + case APIC_RRR: + case APIC_DFR: + case APIC_ICR2: default: - return false; + break; } + return X2APIC_INVALID; } #endif diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 7bba8165..59dfe6a5 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -6191,9 +6191,7 @@ static void virt_x2apic_mode_rd_expectation( bool apic_register_virtualization, bool virtual_interrupt_delivery, struct virt_x2apic_mode_expectation *expectation) { - bool readable = - !x2apic_reg_reserved(reg) && - reg != APIC_EOI; + enum x2apic_reg_semantics semantics = get_x2apic_reg_semantics(reg); expectation->rd_exit_reason = VMX_VMCALL; expectation->virt_fn = virt_x2apic_mode_identity; @@ -6209,7 +6207,7 @@ static void virt_x2apic_mode_rd_expectation( expectation->rd_val = MAGIC_VAL_1; expectation->virt_fn = virt_x2apic_mode_nibble1; expectation->rd_behavior = X2APIC_ACCESS_VIRTUALIZED; - } else if (!disable_x2apic && readable) { + } else if (!disable_x2apic && (semantics & X2APIC_READABLE)) { expectation->rd_val = apic_read(reg); expectation->rd_behavior = X2APIC_ACCESS_PASSED_THROUGH; } else { -- 2.39.0.314.g84b9a713c41-goog