hv: vlapic: minor fix about vlapic write

1) In x2apic mode, when read ICR, we want to read a 64-bits value.
2) In x2apic mode, write self-IPI will trap out through MSR write when VID isn't enabled.

Tracked-On: #1842
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Li, Fei1 2019-04-11 23:43:33 +08:00 committed by wenlingz
parent fa8fa37cdf
commit 4557033a3a

View File

@ -92,6 +92,8 @@ apicv_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector);
static void apicv_post_intr(uint16_t dest_pcpu_id); static void apicv_post_intr(uint16_t dest_pcpu_id);
static void vlapic_x2apic_self_ipi_handler(struct acrn_vlapic *vlapic);
/* /*
* Post an interrupt to the vcpu running on 'hostcpu'. This will use a * Post an interrupt to the vcpu running on 'hostcpu'. This will use a
* hardware assist if available (e.g. Posted Interrupt) or fall back to * hardware assist if available (e.g. Posted Interrupt) or fall back to
@ -1530,6 +1532,9 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
break; break;
case APIC_OFFSET_ICR_LOW: case APIC_OFFSET_ICR_LOW:
*data = lapic->icr_lo.v; *data = lapic->icr_lo.v;
if (is_x2apic_enabled(vlapic)) {
*data |= ((uint64_t)lapic->icr_hi.v) << 32U;
}
break; break;
case APIC_OFFSET_ICR_HI: case APIC_OFFSET_ICR_HI:
*data = lapic->icr_hi.v; *data = lapic->icr_hi.v;
@ -1568,8 +1573,7 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
} }
} }
dev_dbg(ACRN_DBG_LAPIC, dev_dbg(ACRN_DBG_LAPIC, "vlapic read offset %#x, data %#llx", offset, *data);
"vlapic read offset %#x, data %#lx", offset, *data);
return 0; return 0;
} }
@ -1610,10 +1614,8 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
case APIC_OFFSET_ICR_LOW: case APIC_OFFSET_ICR_LOW:
if (is_x2apic_enabled(vlapic)) { if (is_x2apic_enabled(vlapic)) {
lapic->icr_hi.v = (uint32_t)(data >> 32U); lapic->icr_hi.v = (uint32_t)(data >> 32U);
lapic->icr_lo.v = data32;
} else {
lapic->icr_lo.v = data32;
} }
lapic->icr_lo.v = data32;
retval = vlapic_icrlo_write_handler(vlapic); retval = vlapic_icrlo_write_handler(vlapic);
break; break;
case APIC_OFFSET_ICR_HI: case APIC_OFFSET_ICR_HI:
@ -1643,7 +1645,6 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
lapic->dcr_timer.v = data32; lapic->dcr_timer.v = data32;
vlapic_dcr_write_handler(vlapic); vlapic_dcr_write_handler(vlapic);
break; break;
case APIC_OFFSET_ESR: case APIC_OFFSET_ESR:
vlapic_esr_write_handler(vlapic); vlapic_esr_write_handler(vlapic);
break; break;
@ -1660,7 +1661,17 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
*/ */
case APIC_OFFSET_TIMER_CCR: case APIC_OFFSET_TIMER_CCR:
break; break;
case APIC_OFFSET_SELF_IPI:
if (is_x2apic_enabled(vlapic)) {
lapic->self_ipi.v = data32;
vlapic_x2apic_self_ipi_handler(vlapic);
break;
}
/* falls through */
default: default:
retval = -EACCES;
/* Read only */ /* Read only */
break; break;
} }
@ -2344,14 +2355,13 @@ static void vlapic_x2apic_self_ipi_handler(struct acrn_vlapic *vlapic)
int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu) int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
{ {
uint64_t qual; uint64_t qual;
int32_t error, handled; int32_t err = 0;
uint32_t offset; uint32_t offset;
struct acrn_vlapic *vlapic = NULL; struct acrn_vlapic *vlapic = NULL;
qual = vcpu->arch.exit_qualification; qual = vcpu->arch.exit_qualification;
offset = (uint32_t)(qual & 0xFFFUL); offset = (uint32_t)(qual & 0xFFFUL);
handled = 1;
vcpu_retain_rip(vcpu); vcpu_retain_rip(vcpu);
vlapic = vcpu_vlapic(vcpu); vlapic = vcpu_vlapic(vcpu);
@ -2375,10 +2385,7 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
vlapic_esr_write_handler(vlapic); vlapic_esr_write_handler(vlapic);
break; break;
case APIC_OFFSET_ICR_LOW: case APIC_OFFSET_ICR_LOW:
error = vlapic_icrlo_write_handler(vlapic); err = vlapic_icrlo_write_handler(vlapic);
if (error != 0) {
handled = 0;
}
break; break;
case APIC_OFFSET_CMCI_LVT: case APIC_OFFSET_CMCI_LVT:
case APIC_OFFSET_TIMER_LVT: case APIC_OFFSET_TIMER_LVT:
@ -2398,17 +2405,18 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
case APIC_OFFSET_SELF_IPI: case APIC_OFFSET_SELF_IPI:
if (is_x2apic_enabled(vlapic)) { if (is_x2apic_enabled(vlapic)) {
vlapic_x2apic_self_ipi_handler(vlapic); vlapic_x2apic_self_ipi_handler(vlapic);
break;
} }
break; /* falls through */
default: default:
handled = 0; err = -EACCES;
pr_err("Unhandled APIC-Write, offset:0x%x", offset); pr_err("Unhandled APIC-Write, offset:0x%x", offset);
break; break;
} }
TRACE_2L(TRACE_VMEXIT_APICV_WRITE, offset, 0UL); TRACE_2L(TRACE_VMEXIT_APICV_WRITE, offset, 0UL);
return handled; return err;
} }
int32_t tpr_below_threshold_vmexit_handler(__unused struct acrn_vcpu *vcpu) int32_t tpr_below_threshold_vmexit_handler(__unused struct acrn_vcpu *vcpu)