summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-06-09 20:51:08 +0000
committerneel <neel@FreeBSD.org>2014-06-09 20:51:08 +0000
commitd4bb0b204ad21f0444db58fe460c39960212ae4e (patch)
tree4b2ec5ddd180f83cbadfe0e9e9dbd3a0aca2ac84 /sys/amd64
parentd5cc055f47fa3629f9e9e88bd625ad247cd5dfdf (diff)
downloadFreeBSD-src-d4bb0b204ad21f0444db58fe460c39960212ae4e.zip
FreeBSD-src-d4bb0b204ad21f0444db58fe460c39960212ae4e.tar.gz
Add reserved bit checking when doing %CR8 emulation and inject #GP if required.
Pointed out by: grehan Reviewed by: tychon
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/vmm/intel/vmx.c15
-rw-r--r--sys/amd64/vmm/io/vlapic.c57
-rw-r--r--sys/amd64/vmm/io/vlapic.h4
3 files changed, 51 insertions, 25 deletions
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 5c74a6b..ddda13a 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -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);
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index c4b5e21..3c93463 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -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);
-}
diff --git a/sys/amd64/vmm/io/vlapic.h b/sys/amd64/vmm/io/vlapic.h
index ba7b8d1..0e68b2f 100644
--- a/sys/amd64/vmm/io/vlapic.h
+++ b/sys/amd64/vmm/io/vlapic.h
@@ -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);
OpenPOWER on IntegriCloud