hv: Add APIs to convert x2APIC MSR accesses to LAPIC MMIO offset

This patch converts x2APIC MSR accesses to corresponding LAPIC MMIO offset to
utitlize vlapic_write/read APIs to virtualize LAPIC. Also adds support to inject
GP fault when read-only registers are attempted to be written to or vice versa.

Tracked-On: #1626
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Reviewed-by: Xu Anthony <anthony.xu@intel.com>
This commit is contained in:
Sainath Grandhi 2018-11-01 15:04:29 -07:00 committed by lijinxia
parent e9fe6efd81
commit 80b6e62735
2 changed files with 51 additions and 10 deletions

View File

@ -1996,18 +1996,34 @@ static inline bool is_x2apic_enabled(const struct acrn_vlapic *vlapic)
} }
} }
static int vlapic_x2apic_access(struct vcpu *vcpu) static inline uint32_t x2apic_msr_to_regoff(uint32_t msr)
{
return (((msr - 0x800U) & 0x3FFU) << 4U);
}
static int vlapic_x2apic_access(struct vcpu *vcpu, uint32_t msr, bool write, uint64_t *val)
{ {
struct acrn_vlapic *vlapic; struct acrn_vlapic *vlapic;
int error = 0; uint32_t offset;
int error = -1;
vlapic = vcpu_vlapic(vcpu);
if (is_x2apic_enabled(vlapic) == false) {
/* /*
* If vLAPIC is in xAPIC mode and guest tries to access x2APIC MSRs * If vLAPIC is in xAPIC mode and guest tries to access x2APIC MSRs
* inject a GP to guest * inject a GP to guest
*/ */
error = -1; vlapic = vcpu_vlapic(vcpu);
if (is_x2apic_enabled(vlapic)) {
offset = x2apic_msr_to_regoff(msr);
if (write) {
if (!is_x2apic_read_only_msr(msr)) {
error = vlapic_write(vlapic, offset, *val);
}
} else {
if (!is_x2apic_write_only_msr(msr)) {
error = vlapic_read(vlapic, offset, val);
}
}
} }
return error; return error;
@ -2033,7 +2049,7 @@ vlapic_rdmsr(struct vcpu *vcpu, uint32_t msr, uint64_t *rval)
default: default:
if (is_x2apic_msr(msr)) { if (is_x2apic_msr(msr)) {
error = vlapic_x2apic_access(vcpu); error = vlapic_x2apic_access(vcpu, msr, false, rval);
} else { } else {
error = -1; error = -1;
dev_dbg(ACRN_DBG_LAPIC, dev_dbg(ACRN_DBG_LAPIC,
@ -2064,7 +2080,7 @@ vlapic_wrmsr(struct vcpu *vcpu, uint32_t msr, uint64_t wval)
default: default:
if (is_x2apic_msr(msr)) { if (is_x2apic_msr(msr)) {
error = vlapic_x2apic_access(vcpu); error = vlapic_x2apic_access(vcpu, msr, true, &wval);
} else { } else {
error = -1; error = -1;
dev_dbg(ACRN_DBG_LAPIC, dev_dbg(ACRN_DBG_LAPIC,

View File

@ -541,6 +541,31 @@ static inline bool is_x2apic_msr(uint32_t msr)
} }
return ret; return ret;
} }
static inline bool is_x2apic_read_only_msr(uint32_t msr)
{
bool ret = false;
if ((msr == MSR_IA32_EXT_XAPICID) ||
(msr == MSR_IA32_EXT_APIC_VERSION) ||
(msr == MSR_IA32_EXT_APIC_PPR) ||
(msr == MSR_IA32_EXT_APIC_LDR) ||
((msr >= MSR_IA32_EXT_APIC_ISR0) &&
(msr <= MSR_IA32_EXT_APIC_IRR7)) ||
(msr == MSR_IA32_EXT_APIC_CUR_COUNT)) {
ret = true;
}
return ret;
}
static inline bool is_x2apic_write_only_msr(uint32_t msr)
{
bool ret = false;
if ((msr == MSR_IA32_EXT_APIC_EOI) || (msr == MSR_IA32_EXT_APIC_SELF_IPI)) {
ret = true;
}
return ret;
}
#endif /* ASSEMBLER */ #endif /* ASSEMBLER */
/* 5 high-order bits in every field are reserved */ /* 5 high-order bits in every field are reserved */