diff options
-rw-r--r-- | arch/x86/kvm/emulate.c | 47 |
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 */ | 1447 | static int get_descriptor_ptr(struct x86_emulate_ctxt *ctxt, |
1448 | static 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 */ | ||
1476 | static 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, | |||
1467 | static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt, | 1491 | static 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 | } |