diff options
author | Avi Kivity <avi@redhat.com> | 2011-03-31 12:54:30 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:57:07 -0400 |
commit | 9fa088f4d24f045d91c37a5e55f0d2be2ef387ad (patch) | |
tree | 180438cc1847085310cd0ecadc9f6efd723153c2 /arch/x86/kvm/emulate.c | |
parent | 38503911b32186240301bbe81601cfabb37e752e (diff) |
KVM: x86 emulator: change address linearization to return an error code
Preparing to add 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 | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index c522b4e3dbb0..b46fa374d0f1 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -489,8 +489,9 @@ static unsigned seg_override(struct x86_emulate_ctxt *ctxt, | |||
489 | return c->seg_override; | 489 | return c->seg_override; |
490 | } | 490 | } |
491 | 491 | ||
492 | static ulong linear(struct x86_emulate_ctxt *ctxt, | 492 | static int linearize(struct x86_emulate_ctxt *ctxt, |
493 | struct segmented_address addr) | 493 | struct segmented_address addr, |
494 | ulong *linear) | ||
494 | { | 495 | { |
495 | struct decode_cache *c = &ctxt->decode; | 496 | struct decode_cache *c = &ctxt->decode; |
496 | ulong la; | 497 | ulong la; |
@@ -498,7 +499,8 @@ static ulong linear(struct x86_emulate_ctxt *ctxt, | |||
498 | la = seg_base(ctxt, ctxt->ops, addr.seg) + addr.ea; | 499 | la = seg_base(ctxt, ctxt->ops, addr.seg) + addr.ea; |
499 | if (c->ad_bytes != 8) | 500 | if (c->ad_bytes != 8) |
500 | la &= (u32)-1; | 501 | la &= (u32)-1; |
501 | return la; | 502 | *linear = la; |
503 | return X86EMUL_CONTINUE; | ||
502 | } | 504 | } |
503 | 505 | ||
504 | static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec, | 506 | static int emulate_exception(struct x86_emulate_ctxt *ctxt, int vec, |
@@ -545,7 +547,13 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt, | |||
545 | void *data, | 547 | void *data, |
546 | unsigned size) | 548 | unsigned size) |
547 | { | 549 | { |
548 | return ctxt->ops->read_std(linear(ctxt, addr), data, size, ctxt->vcpu, | 550 | int rc; |
551 | ulong linear; | ||
552 | |||
553 | rc = linearize(ctxt, addr, &linear); | ||
554 | if (rc != X86EMUL_CONTINUE) | ||
555 | return rc; | ||
556 | return ctxt->ops->read_std(linear, data, size, ctxt->vcpu, | ||
549 | &ctxt->exception); | 557 | &ctxt->exception); |
550 | } | 558 | } |
551 | 559 | ||
@@ -962,7 +970,13 @@ static int segmented_read(struct x86_emulate_ctxt *ctxt, | |||
962 | void *data, | 970 | void *data, |
963 | unsigned size) | 971 | unsigned size) |
964 | { | 972 | { |
965 | return read_emulated(ctxt, ctxt->ops, linear(ctxt, addr), data, size); | 973 | int rc; |
974 | ulong linear; | ||
975 | |||
976 | rc = linearize(ctxt, addr, &linear); | ||
977 | if (rc != X86EMUL_CONTINUE) | ||
978 | return rc; | ||
979 | return read_emulated(ctxt, ctxt->ops, linear, data, size); | ||
966 | } | 980 | } |
967 | 981 | ||
968 | static int segmented_write(struct x86_emulate_ctxt *ctxt, | 982 | static int segmented_write(struct x86_emulate_ctxt *ctxt, |
@@ -970,7 +984,13 @@ static int segmented_write(struct x86_emulate_ctxt *ctxt, | |||
970 | const void *data, | 984 | const void *data, |
971 | unsigned size) | 985 | unsigned size) |
972 | { | 986 | { |
973 | return ctxt->ops->write_emulated(linear(ctxt, addr), data, size, | 987 | int rc; |
988 | ulong linear; | ||
989 | |||
990 | rc = linearize(ctxt, addr, &linear); | ||
991 | if (rc != X86EMUL_CONTINUE) | ||
992 | return rc; | ||
993 | return ctxt->ops->write_emulated(linear, data, size, | ||
974 | &ctxt->exception, ctxt->vcpu); | 994 | &ctxt->exception, ctxt->vcpu); |
975 | } | 995 | } |
976 | 996 | ||
@@ -979,7 +999,13 @@ static int segmented_cmpxchg(struct x86_emulate_ctxt *ctxt, | |||
979 | const void *orig_data, const void *data, | 999 | const void *orig_data, const void *data, |
980 | unsigned size) | 1000 | unsigned size) |
981 | { | 1001 | { |
982 | return ctxt->ops->cmpxchg_emulated(linear(ctxt, addr), orig_data, data, | 1002 | int rc; |
1003 | ulong linear; | ||
1004 | |||
1005 | rc = linearize(ctxt, addr, &linear); | ||
1006 | if (rc != X86EMUL_CONTINUE) | ||
1007 | return rc; | ||
1008 | return ctxt->ops->cmpxchg_emulated(linear, orig_data, data, | ||
983 | size, &ctxt->exception, ctxt->vcpu); | 1009 | size, &ctxt->exception, ctxt->vcpu); |
984 | } | 1010 | } |
985 | 1011 | ||
@@ -2480,7 +2506,12 @@ static int em_movdqu(struct x86_emulate_ctxt *ctxt) | |||
2480 | static int em_invlpg(struct x86_emulate_ctxt *ctxt) | 2506 | static int em_invlpg(struct x86_emulate_ctxt *ctxt) |
2481 | { | 2507 | { |
2482 | struct decode_cache *c = &ctxt->decode; | 2508 | struct decode_cache *c = &ctxt->decode; |
2483 | emulate_invlpg(ctxt->vcpu, linear(ctxt, c->src.addr.mem)); | 2509 | int rc; |
2510 | ulong linear; | ||
2511 | |||
2512 | rc = linearize(ctxt, c->src.addr.mem, &linear); | ||
2513 | if (rc == X86EMUL_CONTINUE) | ||
2514 | emulate_invlpg(ctxt->vcpu, linear); | ||
2484 | /* Disable writeback. */ | 2515 | /* Disable writeback. */ |
2485 | c->dst.type = OP_NONE; | 2516 | c->dst.type = OP_NONE; |
2486 | return X86EMUL_CONTINUE; | 2517 | return X86EMUL_CONTINUE; |