diff options
author | Avi Kivity <avi@redhat.com> | 2011-03-31 10:52:26 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:57:06 -0400 |
commit | 3ca3ac4dae5da5af375a9e80d2316ccfa7f0c6ab (patch) | |
tree | 74ac07a23cfd88fefe1fadbb94786bfeed29c3fb /arch/x86/kvm/emulate.c | |
parent | e3e9ed3d2c443fd90a04fb7ff231ad53ef087417 (diff) |
KVM: x86 emulator: Add helpers for memory access using segmented addresses
Will help later adding proper segment checks.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 50bffb98ca82..8c38f6ca935b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -540,6 +540,15 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt) | |||
540 | return emulate_exception(ctxt, NM_VECTOR, 0, false); | 540 | return emulate_exception(ctxt, NM_VECTOR, 0, false); |
541 | } | 541 | } |
542 | 542 | ||
543 | static int segmented_read_std(struct x86_emulate_ctxt *ctxt, | ||
544 | struct segmented_address addr, | ||
545 | void *data, | ||
546 | unsigned size) | ||
547 | { | ||
548 | return ctxt->ops->read_std(linear(ctxt, addr), data, size, ctxt->vcpu, | ||
549 | &ctxt->exception); | ||
550 | } | ||
551 | |||
543 | static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, | 552 | static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, |
544 | struct x86_emulate_ops *ops, | 553 | struct x86_emulate_ops *ops, |
545 | unsigned long eip, u8 *dest) | 554 | unsigned long eip, u8 *dest) |
@@ -604,13 +613,11 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt, | |||
604 | if (op_bytes == 2) | 613 | if (op_bytes == 2) |
605 | op_bytes = 3; | 614 | op_bytes = 3; |
606 | *address = 0; | 615 | *address = 0; |
607 | rc = ops->read_std(linear(ctxt, addr), (unsigned long *)size, 2, | 616 | rc = segmented_read_std(ctxt, addr, size, 2); |
608 | ctxt->vcpu, &ctxt->exception); | ||
609 | if (rc != X86EMUL_CONTINUE) | 617 | if (rc != X86EMUL_CONTINUE) |
610 | return rc; | 618 | return rc; |
611 | addr.ea += 2; | 619 | addr.ea += 2; |
612 | rc = ops->read_std(linear(ctxt, addr), address, op_bytes, | 620 | rc = segmented_read_std(ctxt, addr, address, op_bytes); |
613 | ctxt->vcpu, &ctxt->exception); | ||
614 | return rc; | 621 | return rc; |
615 | } | 622 | } |
616 | 623 | ||
@@ -950,6 +957,32 @@ static int read_emulated(struct x86_emulate_ctxt *ctxt, | |||
950 | return X86EMUL_CONTINUE; | 957 | return X86EMUL_CONTINUE; |
951 | } | 958 | } |
952 | 959 | ||
960 | static int segmented_read(struct x86_emulate_ctxt *ctxt, | ||
961 | struct segmented_address addr, | ||
962 | void *data, | ||
963 | unsigned size) | ||
964 | { | ||
965 | return read_emulated(ctxt, ctxt->ops, linear(ctxt, addr), data, size); | ||
966 | } | ||
967 | |||
968 | static int segmented_write(struct x86_emulate_ctxt *ctxt, | ||
969 | struct segmented_address addr, | ||
970 | const void *data, | ||
971 | unsigned size) | ||
972 | { | ||
973 | return ctxt->ops->write_emulated(linear(ctxt, addr), data, size, | ||
974 | &ctxt->exception, ctxt->vcpu); | ||
975 | } | ||
976 | |||
977 | static int segmented_cmpxchg(struct x86_emulate_ctxt *ctxt, | ||
978 | struct segmented_address addr, | ||
979 | const void *orig_data, const void *data, | ||
980 | unsigned size) | ||
981 | { | ||
982 | return ctxt->ops->cmpxchg_emulated(linear(ctxt, addr), orig_data, data, | ||
983 | size, &ctxt->exception, ctxt->vcpu); | ||
984 | } | ||
985 | |||
953 | static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, | 986 | static int pio_in_emulated(struct x86_emulate_ctxt *ctxt, |
954 | struct x86_emulate_ops *ops, | 987 | struct x86_emulate_ops *ops, |
955 | unsigned int size, unsigned short port, | 988 | unsigned int size, unsigned short port, |
@@ -1197,20 +1230,16 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt, | |||
1197 | break; | 1230 | break; |
1198 | case OP_MEM: | 1231 | case OP_MEM: |
1199 | if (c->lock_prefix) | 1232 | if (c->lock_prefix) |
1200 | rc = ops->cmpxchg_emulated( | 1233 | rc = segmented_cmpxchg(ctxt, |
1201 | linear(ctxt, c->dst.addr.mem), | 1234 | c->dst.addr.mem, |
1202 | &c->dst.orig_val, | 1235 | &c->dst.orig_val, |
1203 | &c->dst.val, | 1236 | &c->dst.val, |
1204 | c->dst.bytes, | 1237 | c->dst.bytes); |
1205 | &ctxt->exception, | ||
1206 | ctxt->vcpu); | ||
1207 | else | 1238 | else |
1208 | rc = ops->write_emulated( | 1239 | rc = segmented_write(ctxt, |
1209 | linear(ctxt, c->dst.addr.mem), | 1240 | c->dst.addr.mem, |
1210 | &c->dst.val, | 1241 | &c->dst.val, |
1211 | c->dst.bytes, | 1242 | c->dst.bytes); |
1212 | &ctxt->exception, | ||
1213 | ctxt->vcpu); | ||
1214 | if (rc != X86EMUL_CONTINUE) | 1243 | if (rc != X86EMUL_CONTINUE) |
1215 | return rc; | 1244 | return rc; |
1216 | break; | 1245 | break; |
@@ -1249,7 +1278,7 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt, | |||
1249 | 1278 | ||
1250 | addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]); | 1279 | addr.ea = register_address(c, c->regs[VCPU_REGS_RSP]); |
1251 | addr.seg = VCPU_SREG_SS; | 1280 | addr.seg = VCPU_SREG_SS; |
1252 | rc = read_emulated(ctxt, ops, linear(ctxt, addr), dest, len); | 1281 | rc = segmented_read(ctxt, addr, dest, len); |
1253 | if (rc != X86EMUL_CONTINUE) | 1282 | if (rc != X86EMUL_CONTINUE) |
1254 | return rc; | 1283 | return rc; |
1255 | 1284 | ||
@@ -3440,16 +3469,16 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
3440 | } | 3469 | } |
3441 | 3470 | ||
3442 | if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) { | 3471 | if ((c->src.type == OP_MEM) && !(c->d & NoAccess)) { |
3443 | rc = read_emulated(ctxt, ops, linear(ctxt, c->src.addr.mem), | 3472 | rc = segmented_read(ctxt, c->src.addr.mem, |
3444 | c->src.valptr, c->src.bytes); | 3473 | c->src.valptr, c->src.bytes); |
3445 | if (rc != X86EMUL_CONTINUE) | 3474 | if (rc != X86EMUL_CONTINUE) |
3446 | goto done; | 3475 | goto done; |
3447 | c->src.orig_val64 = c->src.val64; | 3476 | c->src.orig_val64 = c->src.val64; |
3448 | } | 3477 | } |
3449 | 3478 | ||
3450 | if (c->src2.type == OP_MEM) { | 3479 | if (c->src2.type == OP_MEM) { |
3451 | rc = read_emulated(ctxt, ops, linear(ctxt, c->src2.addr.mem), | 3480 | rc = segmented_read(ctxt, c->src2.addr.mem, |
3452 | &c->src2.val, c->src2.bytes); | 3481 | &c->src2.val, c->src2.bytes); |
3453 | if (rc != X86EMUL_CONTINUE) | 3482 | if (rc != X86EMUL_CONTINUE) |
3454 | goto done; | 3483 | goto done; |
3455 | } | 3484 | } |
@@ -3460,7 +3489,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
3460 | 3489 | ||
3461 | if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { | 3490 | if ((c->dst.type == OP_MEM) && !(c->d & Mov)) { |
3462 | /* optimisation - avoid slow emulated read if Mov */ | 3491 | /* optimisation - avoid slow emulated read if Mov */ |
3463 | rc = read_emulated(ctxt, ops, linear(ctxt, c->dst.addr.mem), | 3492 | rc = segmented_read(ctxt, c->dst.addr.mem, |
3464 | &c->dst.val, c->dst.bytes); | 3493 | &c->dst.val, c->dst.bytes); |
3465 | if (rc != X86EMUL_CONTINUE) | 3494 | if (rc != X86EMUL_CONTINUE) |
3466 | goto done; | 3495 | goto done; |