Restructure the x2apic access code in preparation for supporting memory mapped
access to the local apic. The vlapic code is now aware of the mode that the guest is using to access the local apic. Reviewed by: grehan@
This commit is contained in:
parent
177fd53318
commit
2d3a73ed6d
@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
#include <x86/specialreg.h>
|
||||
#include <x86/apicreg.h>
|
||||
|
||||
#include <machine/vmm.h>
|
||||
@ -86,6 +87,8 @@ static MALLOC_DEFINE(M_VLAPIC, "vlapic", "vlapic");
|
||||
#define VLAPIC_VERSION (16)
|
||||
#define VLAPIC_MAXLVT_ENTRIES (5)
|
||||
|
||||
#define x2apic(vlapic) ((vlapic)->msr_apicbase & APICBASE_X2APIC)
|
||||
|
||||
struct vlapic {
|
||||
struct vm *vm;
|
||||
int vcpuid;
|
||||
@ -107,6 +110,8 @@ struct vlapic {
|
||||
*/
|
||||
uint8_t isrvec_stk[ISRVEC_STK_SIZE];
|
||||
int isrvec_stk_top;
|
||||
|
||||
uint64_t msr_apicbase;
|
||||
};
|
||||
|
||||
static void
|
||||
@ -161,7 +166,6 @@ vlapic_op_reset(void* dev)
|
||||
struct LAPIC *lapic = &vlapic->apic;
|
||||
|
||||
memset(lapic, 0, sizeof(*lapic));
|
||||
lapic->id = vlapic->vcpuid << 24;
|
||||
lapic->apr = vlapic->vcpuid;
|
||||
vlapic_init_ipi(vlapic);
|
||||
|
||||
@ -542,7 +546,10 @@ vlapic_op_mem_read(void* dev, uint64_t gpa, opsize_t size, uint64_t *data)
|
||||
switch(offset)
|
||||
{
|
||||
case APIC_OFFSET_ID:
|
||||
*data = lapic->id;
|
||||
if (x2apic(vlapic))
|
||||
*data = vlapic->vcpuid;
|
||||
else
|
||||
*data = vlapic->vcpuid << 24;
|
||||
break;
|
||||
case APIC_OFFSET_VER:
|
||||
*data = lapic->version;
|
||||
@ -631,7 +638,6 @@ vlapic_op_mem_write(void* dev, uint64_t gpa, opsize_t size, uint64_t data)
|
||||
switch(offset)
|
||||
{
|
||||
case APIC_OFFSET_ID:
|
||||
lapic->id = data;
|
||||
break;
|
||||
case APIC_OFFSET_TPR:
|
||||
lapic->tpr = data & 0xff;
|
||||
@ -760,6 +766,14 @@ vlapic_init(struct vm *vm, int vcpuid)
|
||||
vlapic = malloc(sizeof(struct vlapic), M_VLAPIC, M_WAITOK | M_ZERO);
|
||||
vlapic->vm = vm;
|
||||
vlapic->vcpuid = vcpuid;
|
||||
|
||||
vlapic->msr_apicbase = DEFAULT_APIC_BASE |
|
||||
APICBASE_ENABLED |
|
||||
APICBASE_X2APIC;
|
||||
|
||||
if (vcpuid == 0)
|
||||
vlapic->msr_apicbase |= APICBASE_BSP;
|
||||
|
||||
vlapic->ops = &vlapic_dev_ops;
|
||||
|
||||
vlapic->mmio = vlapic_mmio + vcpuid;
|
||||
@ -782,3 +796,17 @@ vlapic_cleanup(struct vlapic *vlapic)
|
||||
vdev_unregister(vlapic);
|
||||
free(vlapic, M_VLAPIC);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
vlapic_get_apicbase(struct vlapic *vlapic)
|
||||
{
|
||||
|
||||
return (vlapic->msr_apicbase);
|
||||
}
|
||||
|
||||
void
|
||||
vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val)
|
||||
{
|
||||
|
||||
vlapic->msr_apicbase = val;
|
||||
}
|
||||
|
@ -102,4 +102,7 @@ void vlapic_intr_accepted(struct vlapic *vlapic, int vector);
|
||||
void vlapic_set_intr_ready(struct vlapic *vlapic, int vector);
|
||||
void vlapic_timer_tick(struct vlapic *vlapic);
|
||||
|
||||
uint64_t vlapic_get_apicbase(struct vlapic *vlapic);
|
||||
void vlapic_set_apicbase(struct vlapic *vlapic, uint64_t val);
|
||||
|
||||
#endif /* _VLAPIC_H_ */
|
||||
|
@ -33,20 +33,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <x86/specialreg.h>
|
||||
|
||||
#include <machine/vmm.h>
|
||||
#include "vmm_ipi.h"
|
||||
#include "vmm_lapic.h"
|
||||
#include "vlapic.h"
|
||||
|
||||
int
|
||||
lapic_write(struct vm *vm, int cpu, u_int offset, uint64_t val)
|
||||
static int
|
||||
lapic_write(struct vlapic *vlapic, u_int offset, uint64_t val)
|
||||
{
|
||||
int handled;
|
||||
|
||||
struct vlapic *vlapic;
|
||||
|
||||
vlapic = vm_lapic(vm, cpu);
|
||||
|
||||
if (vlapic_op_mem_write(vlapic, offset, DWORD, val) == 0)
|
||||
handled = 1;
|
||||
else
|
||||
@ -55,15 +53,11 @@ lapic_write(struct vm *vm, int cpu, u_int offset, uint64_t val)
|
||||
return (handled);
|
||||
}
|
||||
|
||||
int
|
||||
lapic_read(struct vm *vm, int cpu, u_int offset, uint64_t *rv)
|
||||
static int
|
||||
lapic_read(struct vlapic *vlapic, u_int offset, uint64_t *rv)
|
||||
{
|
||||
int handled;
|
||||
|
||||
struct vlapic *vlapic;
|
||||
|
||||
vlapic = vm_lapic(vm, cpu);
|
||||
|
||||
if (vlapic_op_mem_read(vlapic, offset, DWORD, rv) == 0)
|
||||
handled = 1;
|
||||
else
|
||||
@ -120,3 +114,63 @@ lapic_timer_tick(struct vm *vm, int cpu)
|
||||
|
||||
vlapic_timer_tick(vlapic);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
x2apic_msr(u_int msr)
|
||||
{
|
||||
if (msr >= 0x800 && msr <= 0xBFF)
|
||||
return (TRUE);
|
||||
else
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
x2apic_msr_to_regoff(u_int msr)
|
||||
{
|
||||
|
||||
return ((msr - 0x800) << 4);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
lapic_msr(u_int msr)
|
||||
{
|
||||
|
||||
if (x2apic_msr(msr) || (msr == MSR_APICBASE))
|
||||
return (TRUE);
|
||||
else
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
int
|
||||
lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval)
|
||||
{
|
||||
int handled;
|
||||
struct vlapic *vlapic;
|
||||
|
||||
vlapic = vm_lapic(vm, cpu);
|
||||
|
||||
if (msr == MSR_APICBASE) {
|
||||
*rval = vlapic_get_apicbase(vlapic);
|
||||
handled = 1;
|
||||
} else
|
||||
handled = lapic_read(vlapic, x2apic_msr_to_regoff(msr), rval);
|
||||
|
||||
return (handled);
|
||||
}
|
||||
|
||||
int
|
||||
lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t val)
|
||||
{
|
||||
int handled;
|
||||
struct vlapic *vlapic;
|
||||
|
||||
vlapic = vm_lapic(vm, cpu);
|
||||
|
||||
if (msr == MSR_APICBASE) {
|
||||
vlapic_set_apicbase(vlapic, val);
|
||||
handled = 1;
|
||||
} else
|
||||
handled = lapic_write(vlapic, x2apic_msr_to_regoff(msr), val);
|
||||
|
||||
return (handled);
|
||||
}
|
||||
|
@ -31,8 +31,10 @@
|
||||
|
||||
struct vm;
|
||||
|
||||
int lapic_write(struct vm *vm, int cpu, u_int offset, uint64_t val);
|
||||
int lapic_read(struct vm *vm, int cpu, u_int offset, uint64_t *retval);
|
||||
boolean_t lapic_msr(u_int num);
|
||||
int lapic_rdmsr(struct vm *vm, int cpu, u_int msr, uint64_t *rval);
|
||||
int lapic_wrmsr(struct vm *vm, int cpu, u_int msr, uint64_t wval);
|
||||
|
||||
void lapic_timer_tick(struct vm *vm, int cpu);
|
||||
|
||||
/*
|
||||
|
@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/smp.h>
|
||||
|
||||
#include <machine/specialreg.h>
|
||||
#include <x86/apicreg.h>
|
||||
|
||||
#include <machine/vmm.h>
|
||||
#include "vmm_lapic.h"
|
||||
@ -56,7 +55,6 @@ static struct vmm_msr vmm_msr[] = {
|
||||
{ MSR_STAR, 0 },
|
||||
{ MSR_SF_MASK, 0 },
|
||||
{ MSR_PAT, VMM_MSR_F_EMULATE | VMM_MSR_F_INVALID },
|
||||
{ MSR_APICBASE, VMM_MSR_F_EMULATE },
|
||||
{ MSR_BIOS_SIGN,VMM_MSR_F_EMULATE },
|
||||
{ MSR_MCG_CAP, VMM_MSR_F_EMULATE | VMM_MSR_F_READONLY },
|
||||
};
|
||||
@ -107,12 +105,6 @@ guest_msrs_init(struct vm *vm, int cpu)
|
||||
case MSR_MCG_CAP:
|
||||
guest_msrs[i] = 0;
|
||||
break;
|
||||
case MSR_APICBASE:
|
||||
guest_msrs[i] = DEFAULT_APIC_BASE | APICBASE_ENABLED |
|
||||
APICBASE_X2APIC;
|
||||
if (cpu == 0)
|
||||
guest_msrs[i] |= APICBASE_BSP;
|
||||
break;
|
||||
case MSR_PAT:
|
||||
guest_msrs[i] = PAT_VALUE(0, PAT_WRITE_BACK) |
|
||||
PAT_VALUE(1, PAT_WRITE_THROUGH) |
|
||||
@ -130,29 +122,6 @@ guest_msrs_init(struct vm *vm, int cpu)
|
||||
}
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
x2apic_msr(u_int num)
|
||||
{
|
||||
|
||||
if (num >= 0x800 && num <= 0xBFF)
|
||||
return (TRUE);
|
||||
else
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
x2apic_msr_to_regoff(u_int msr)
|
||||
{
|
||||
|
||||
return ((msr - 0x800) << 4);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
x2apic_msr_id(u_int num)
|
||||
{
|
||||
return (num == 0x802);
|
||||
}
|
||||
|
||||
static int
|
||||
msr_num_to_idx(u_int num)
|
||||
{
|
||||
@ -173,8 +142,8 @@ emulate_wrmsr(struct vm *vm, int cpu, u_int num, uint64_t val)
|
||||
|
||||
handled = 0;
|
||||
|
||||
if (x2apic_msr(num))
|
||||
return (lapic_write(vm, cpu, x2apic_msr_to_regoff(num), val));
|
||||
if (lapic_msr(num))
|
||||
return (lapic_wrmsr(vm, cpu, num, val));
|
||||
|
||||
idx = msr_num_to_idx(num);
|
||||
if (idx < 0)
|
||||
@ -208,15 +177,8 @@ emulate_rdmsr(struct vm *vm, int cpu, u_int num)
|
||||
|
||||
handled = 0;
|
||||
|
||||
if (x2apic_msr(num)) {
|
||||
handled = lapic_read(vm, cpu, x2apic_msr_to_regoff(num),
|
||||
&result);
|
||||
/*
|
||||
* The version ID needs to be massaged
|
||||
*/
|
||||
if (x2apic_msr_id(num)) {
|
||||
result = result >> 24;
|
||||
}
|
||||
if (lapic_msr(num)) {
|
||||
handled = lapic_rdmsr(vm, cpu, num, &result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user