diff options
author | Nadav Amit <namit@cs.technion.ac.il> | 2015-03-30 08:39:20 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-03-30 10:46:03 -0400 |
commit | 6fd8e1275709a5bb084847eda6730b983538a572 (patch) | |
tree | ac9bd3385ff16bb9b64b1abadd957bbe64b9d184 /arch/x86/kvm/emulate.c | |
parent | b91aa14d95bf4cf8ed0426bd25c0af1548519696 (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.c | 39 |
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 | ||
481 | static 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 | |||
481 | static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt) | 500 | static 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 | ||
1692 | static void write_register_operand(struct operand *op) | 1711 | static 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 | ||
1711 | static int writeback(struct x86_emulate_ctxt *ctxt, struct operand *op) | 1716 | static 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; |