Add reserved bit checking when doing %CR8 emulation and inject #GP if required.
Pointed out by: grehan Reviewed by: tychon
This commit is contained in:
parent
00c37433f4
commit
051f2bd19d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267300
@ -1602,20 +1602,23 @@ vmx_emulate_cr4_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
|
||||
static int
|
||||
vmx_emulate_cr8_access(struct vmx *vmx, int vcpu, uint64_t exitqual)
|
||||
{
|
||||
uint64_t regval;
|
||||
struct vlapic *vlapic;
|
||||
uint64_t cr8;
|
||||
int regnum;
|
||||
|
||||
/* We only handle mov %cr8 to/from a register at this time. */
|
||||
if ((exitqual & 0xe0) != 0x00) {
|
||||
return (UNHANDLED);
|
||||
}
|
||||
|
||||
vlapic = vm_lapic(vmx->vm, vcpu);
|
||||
regnum = (exitqual >> 8) & 0xf;
|
||||
if (exitqual & 0x10) {
|
||||
regval = vlapic_get_tpr(vm_lapic(vmx->vm, vcpu));
|
||||
vmx_set_guest_reg(vmx, vcpu, (exitqual >> 8) & 0xf,
|
||||
regval >> 4);
|
||||
cr8 = vlapic_get_cr8(vlapic);
|
||||
vmx_set_guest_reg(vmx, vcpu, regnum, cr8);
|
||||
} else {
|
||||
regval = vmx_get_guest_reg(vmx, vcpu, (exitqual >> 8) & 0xf);
|
||||
vlapic_set_tpr(vm_lapic(vmx->vm, vcpu), regval << 4);
|
||||
cr8 = vmx_get_guest_reg(vmx, vcpu, regnum);
|
||||
vlapic_set_cr8(vlapic, cr8);
|
||||
}
|
||||
|
||||
return (HANDLED);
|
||||
|
@ -906,6 +906,46 @@ vlapic_calcdest(struct vm *vm, cpuset_t *dmask, uint32_t dest, bool phys,
|
||||
|
||||
static VMM_STAT_ARRAY(IPIS_SENT, VM_MAXCPU, "ipis sent to vcpu");
|
||||
|
||||
static void
|
||||
vlapic_set_tpr(struct vlapic *vlapic, uint8_t val)
|
||||
{
|
||||
struct LAPIC *lapic = vlapic->apic_page;
|
||||
|
||||
lapic->tpr = val;
|
||||
vlapic_update_ppr(vlapic);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
vlapic_get_tpr(struct vlapic *vlapic)
|
||||
{
|
||||
struct LAPIC *lapic = vlapic->apic_page;
|
||||
|
||||
return (lapic->tpr);
|
||||
}
|
||||
|
||||
void
|
||||
vlapic_set_cr8(struct vlapic *vlapic, uint64_t val)
|
||||
{
|
||||
uint8_t tpr;
|
||||
|
||||
if (val & ~0xf) {
|
||||
vm_inject_gp(vlapic->vm, vlapic->vcpuid);
|
||||
return;
|
||||
}
|
||||
|
||||
tpr = val << 4;
|
||||
vlapic_set_tpr(vlapic, tpr);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
vlapic_get_cr8(struct vlapic *vlapic)
|
||||
{
|
||||
uint8_t tpr;
|
||||
|
||||
tpr = vlapic_get_tpr(vlapic);
|
||||
return (tpr >> 4);
|
||||
}
|
||||
|
||||
int
|
||||
vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
|
||||
{
|
||||
@ -1610,20 +1650,3 @@ vlapic_set_tmr_level(struct vlapic *vlapic, uint32_t dest, bool phys,
|
||||
VLAPIC_CTR1(vlapic, "vector %d set to level-triggered", vector);
|
||||
vlapic_set_tmr(vlapic, vector, true);
|
||||
}
|
||||
|
||||
void
|
||||
vlapic_set_tpr(struct vlapic *vlapic, uint8_t val)
|
||||
{
|
||||
struct LAPIC *lapic = vlapic->apic_page;
|
||||
|
||||
lapic->tpr = val;
|
||||
vlapic_update_ppr(vlapic);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
vlapic_get_tpr(struct vlapic *vlapic)
|
||||
{
|
||||
struct LAPIC *lapic = vlapic->apic_page;
|
||||
|
||||
return (lapic->tpr);
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ void vlapic_reset_tmr(struct vlapic *vlapic);
|
||||
void vlapic_set_tmr_level(struct vlapic *vlapic, uint32_t dest, bool phys,
|
||||
int delmode, int vector);
|
||||
|
||||
void vlapic_set_tpr(struct vlapic *vlapic, uint8_t val);
|
||||
uint8_t vlapic_get_tpr(struct vlapic *vlapic);
|
||||
void vlapic_set_cr8(struct vlapic *vlapic, uint64_t val);
|
||||
uint64_t vlapic_get_cr8(struct vlapic *vlapic);
|
||||
|
||||
/* APIC write handlers */
|
||||
void vlapic_id_write_handler(struct vlapic *vlapic);
|
||||
|
Loading…
Reference in New Issue
Block a user