aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2015-03-30 08:39:20 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-03-30 10:46:03 -0400
commit6fd8e1275709a5bb084847eda6730b983538a572 (patch)
treeac9bd3385ff16bb9b64b1abadd957bbe64b9d184 /arch/x86/kvm/emulate.c
parentb91aa14d95bf4cf8ed0426bd25c0af1548519696 (diff)
KVM: x86: POPA emulation may not clear bits [63:32]
POPA should assign the values to the registers as usual registers are assigned. In other words, 32-bits register assignments should clear bits [63:32] of the register. Split the code of register assignments that will be used by future changes as well. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Message-Id: <1427719163-5429-3-git-send-email-namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 62f7a395717d..4961dc5eb303 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -478,6 +478,25 @@ static void assign_masked(ulong *dest, ulong src, ulong mask)
478 *dest = (*dest & ~mask) | (src & mask); 478 *dest = (*dest & ~mask) | (src & mask);
479} 479}
480 480
481static void assign_register(unsigned long *reg, u64 val, int bytes)
482{
483 /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
484 switch (bytes) {
485 case 1:
486 *(u8 *)reg = (u8)val;
487 break;
488 case 2:
489 *(u16 *)reg = (u16)val;
490 break;
491 case 4:
492 *reg = (u32)val;
493 break; /* 64b: zero-extend */
494 case 8:
495 *reg = val;
496 break;
497 }
498}
499
481static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt) 500static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
482{ 501{
483 return (1UL << (ctxt->ad_bytes << 3)) - 1; 502 return (1UL << (ctxt->ad_bytes << 3)) - 1;
@@ -1691,21 +1710,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
1691 1710
1692static void write_register_operand(struct operand *op) 1711static void write_register_operand(struct operand *op)
1693{ 1712{
1694 /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ 1713 return assign_register(op->addr.reg, op->val, op->bytes);
1695 switch (op->bytes) {
1696 case 1:
1697 *(u8 *)op->addr.reg = (u8)op->val;
1698 break;
1699 case 2:
1700 *(u16 *)op->addr.reg = (u16)op->val;
1701 break;
1702 case 4:
1703 *op->addr.reg = (u32)op->val;
1704 break; /* 64b: zero-extend */
1705 case 8:
1706 *op->addr.reg = op->val;
1707 break;
1708 }
1709} 1714}
1710 1715
1711static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op) 1716static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op)
@@ -1926,6 +1931,7 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
1926{ 1931{
1927 int rc = X86EMUL_CONTINUE; 1932 int rc = X86EMUL_CONTINUE;
1928 int reg = VCPU_REGS_RDI; 1933 int reg = VCPU_REGS_RDI;
1934 u32 val;
1929 1935
1930 while (reg >= VCPU_REGS_RAX) { 1936 while (reg >= VCPU_REGS_RAX) {
1931 if (reg == VCPU_REGS_RSP) { 1937 if (reg == VCPU_REGS_RSP) {
@@ -1933,9 +1939,10 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
1933 --reg; 1939 --reg;
1934 } 1940 }
1935 1941
1936 rc = emulate_pop(ctxt, reg_rmw(ctxt, reg), ctxt->op_bytes); 1942 rc = emulate_pop(ctxt, &val, ctxt->op_bytes);
1937 if (rc != X86EMUL_CONTINUE) 1943 if (rc != X86EMUL_CONTINUE)
1938 break; 1944 break;
1945 assign_register(reg_rmw(ctxt, reg), val, ctxt->op_bytes);
1939 --reg; 1946 --reg;
1940 } 1947 }
1941 return rc; 1948 return rc;