aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-12-24 19:52:23 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2015-01-08 16:48:08 -0500
commitedccda7ca7e56b335c70ae512f89d0fdf7fb8c69 (patch)
tree472fe75d29ac7e228ffa48cd5c61f9ae60803b5d /arch/x86/kvm/emulate.c
parente2cefa746e7e2a1104931d411b6f5de159d98ec6 (diff)
KVM: x86: Access to LDT/GDT that wraparound is incorrect
When access to descriptor in LDT/GDT wraparound outside long-mode, the address of the descriptor should be truncated to 32-bit. Citing Intel SDM 2.1.1.1 "Global and Local Descriptor Tables in IA-32e Mode": "GDTR and LDTR registers are expanded to 64-bits wide in both IA-32e sub-modes (64-bit mode and compatibility mode)." So in other cases, we need to truncate. Creating new function to return a pointer to descriptor table to avoid too much code duplication. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> [Wrap 64-bit check with #ifdef CONFIG_X86_64, to avoid a "right shift count >= width of type" warning and consequent undefined behavior. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index e36e1fc5bf85..d949287ed010 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1444,10 +1444,8 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
1444 ops->get_gdt(ctxt, dt); 1444 ops->get_gdt(ctxt, dt);
1445} 1445}
1446 1446
1447/* allowed just for 8 bytes segments */ 1447static int get_descriptor_ptr(struct x86_emulate_ctxt *ctxt,
1448static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, 1448 u16 selector, ulong *desc_addr_p)
1449 u16 selector, struct desc_struct *desc,
1450 ulong *desc_addr_p)
1451{ 1449{
1452 struct desc_ptr dt; 1450 struct desc_ptr dt;
1453 u16 index = selector >> 3; 1451 u16 index = selector >> 3;
@@ -1458,8 +1456,34 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
1458 if (dt.size < index * 8 + 7) 1456 if (dt.size < index * 8 + 7)
1459 return emulate_gp(ctxt, selector & 0xfffc); 1457 return emulate_gp(ctxt, selector & 0xfffc);
1460 1458
1461 *desc_addr_p = addr = dt.address + index * 8; 1459 addr = dt.address + index * 8;
1462 return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc, 1460
1461#ifdef CONFIG_X86_64
1462 if (addr >> 32 != 0) {
1463 u64 efer = 0;
1464
1465 ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
1466 if (!(efer & EFER_LMA))
1467 addr &= (u32)-1;
1468 }
1469#endif
1470
1471 *desc_addr_p = addr;
1472 return X86EMUL_CONTINUE;
1473}
1474
1475/* allowed just for 8 bytes segments */
1476static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
1477 u16 selector, struct desc_struct *desc,
1478 ulong *desc_addr_p)
1479{
1480 int rc;
1481
1482 rc = get_descriptor_ptr(ctxt, selector, desc_addr_p);
1483 if (rc != X86EMUL_CONTINUE)
1484 return rc;
1485
1486 return ctxt->ops->read_std(ctxt, *desc_addr_p, desc, sizeof(*desc),
1463 &ctxt->exception); 1487 &ctxt->exception);
1464} 1488}
1465 1489
@@ -1467,16 +1491,13 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
1467static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt, 1491static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
1468 u16 selector, struct desc_struct *desc) 1492 u16 selector, struct desc_struct *desc)
1469{ 1493{
1470 struct desc_ptr dt; 1494 int rc;
1471 u16 index = selector >> 3;
1472 ulong addr; 1495 ulong addr;
1473 1496
1474 get_descriptor_table_ptr(ctxt, selector, &dt); 1497 rc = get_descriptor_ptr(ctxt, selector, &addr);
1475 1498 if (rc != X86EMUL_CONTINUE)
1476 if (dt.size < index * 8 + 7) 1499 return rc;
1477 return emulate_gp(ctxt, selector & 0xfffc);
1478 1500
1479 addr = dt.address + index * 8;
1480 return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc, 1501 return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc,
1481 &ctxt->exception); 1502 &ctxt->exception);
1482} 1503}