KVM: x86: Add helpers to handle 64-bit APIC MSR read/writes
Add helpers to handle 64-bit APIC read/writes via MSRs to deduplicate the x2APIC and Hyper-V code needed to service reads/writes to ICR. Future support for IPI virtualization will add yet another path where KVM must handle 64-bit APIC MSR reads/write (to ICR). Opportunistically fix the comment in the write path; ICR2 holds the destination (if there's no shorthand), not the vector. No functional change intended. Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20220204214205.3306634-9-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
7018005235
commit
5429478d03
|
@ -2774,6 +2774,30 @@ int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data)
|
||||
{
|
||||
u32 low, high = 0;
|
||||
|
||||
if (kvm_lapic_reg_read(apic, reg, 4, &low))
|
||||
return 1;
|
||||
|
||||
if (reg == APIC_ICR &&
|
||||
WARN_ON_ONCE(kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high)))
|
||||
return 1;
|
||||
|
||||
*data = (((u64)high) << 32) | low;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_lapic_msr_write(struct kvm_lapic *apic, u32 reg, u64 data)
|
||||
{
|
||||
/* For 64-bit ICR writes, set ICR2 (dest) before ICR (command). */
|
||||
if (reg == APIC_ICR)
|
||||
kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
|
||||
return kvm_lapic_reg_write(apic, reg, (u32)data);
|
||||
}
|
||||
|
||||
int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
|
@ -2785,16 +2809,13 @@ int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
|||
if (reg == APIC_ICR2)
|
||||
return 1;
|
||||
|
||||
/* if this is ICR write vector before command */
|
||||
if (reg == APIC_ICR)
|
||||
kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
|
||||
return kvm_lapic_reg_write(apic, reg, (u32)data);
|
||||
return kvm_lapic_msr_write(apic, reg, data);
|
||||
}
|
||||
|
||||
int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
u32 reg = (msr - APIC_BASE_MSR) << 4, low, high = 0;
|
||||
u32 reg = (msr - APIC_BASE_MSR) << 4;
|
||||
|
||||
if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(apic))
|
||||
return 1;
|
||||
|
@ -2802,45 +2823,23 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
|
|||
if (reg == APIC_DFR || reg == APIC_ICR2)
|
||||
return 1;
|
||||
|
||||
if (kvm_lapic_reg_read(apic, reg, 4, &low))
|
||||
return 1;
|
||||
if (reg == APIC_ICR)
|
||||
kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
|
||||
|
||||
*data = (((u64)high) << 32) | low;
|
||||
|
||||
return 0;
|
||||
return kvm_lapic_msr_read(apic, reg, data);
|
||||
}
|
||||
|
||||
int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
|
||||
if (!lapic_in_kernel(vcpu))
|
||||
return 1;
|
||||
|
||||
/* if this is ICR write vector before command */
|
||||
if (reg == APIC_ICR)
|
||||
kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
|
||||
return kvm_lapic_reg_write(apic, reg, (u32)data);
|
||||
return kvm_lapic_msr_write(vcpu->arch.apic, reg, data);
|
||||
}
|
||||
|
||||
int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
u32 low, high = 0;
|
||||
|
||||
if (!lapic_in_kernel(vcpu))
|
||||
return 1;
|
||||
|
||||
if (kvm_lapic_reg_read(apic, reg, 4, &low))
|
||||
return 1;
|
||||
if (reg == APIC_ICR)
|
||||
kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
|
||||
|
||||
*data = (((u64)high) << 32) | low;
|
||||
|
||||
return 0;
|
||||
return kvm_lapic_msr_read(vcpu->arch.apic, reg, data);
|
||||
}
|
||||
|
||||
int kvm_lapic_set_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len)
|
||||
|
|
Loading…
Reference in New Issue