aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-07-22 11:48:54 -0400
committerAvi Kivity <avi@qumranet.com>2007-07-25 07:29:17 -0400
commitb0fcd903e6f3f47189baddf3fe085bdf78c9644c (patch)
treec3c0e098b25d158973a7262865e74ae790a66772
parent0de085bb474f64e4fdb2f1ff3268590792648c7b (diff)
KVM: Correctly handle writes crossing a page boundary
Writes that are contiguous in virtual memory may not be contiguous in physical memory; so split writes that straddle a page boundary. Thanks to Aurelien for reporting the bug, patient testing, and a fix to this very patch. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/kvm_main.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index bcbe6835beb4..a0a3fddba815 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1078,10 +1078,10 @@ static int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
1078 return 1; 1078 return 1;
1079} 1079}
1080 1080
1081static int emulator_write_emulated(unsigned long addr, 1081static int emulator_write_emulated_onepage(unsigned long addr,
1082 const void *val, 1082 const void *val,
1083 unsigned int bytes, 1083 unsigned int bytes,
1084 struct x86_emulate_ctxt *ctxt) 1084 struct x86_emulate_ctxt *ctxt)
1085{ 1085{
1086 struct kvm_vcpu *vcpu = ctxt->vcpu; 1086 struct kvm_vcpu *vcpu = ctxt->vcpu;
1087 struct kvm_io_device *mmio_dev; 1087 struct kvm_io_device *mmio_dev;
@@ -1113,6 +1113,26 @@ static int emulator_write_emulated(unsigned long addr,
1113 return X86EMUL_CONTINUE; 1113 return X86EMUL_CONTINUE;
1114} 1114}
1115 1115
1116static int emulator_write_emulated(unsigned long addr,
1117 const void *val,
1118 unsigned int bytes,
1119 struct x86_emulate_ctxt *ctxt)
1120{
1121 /* Crossing a page boundary? */
1122 if (((addr + bytes - 1) ^ addr) & PAGE_MASK) {
1123 int rc, now;
1124
1125 now = -addr & ~PAGE_MASK;
1126 rc = emulator_write_emulated_onepage(addr, val, now, ctxt);
1127 if (rc != X86EMUL_CONTINUE)
1128 return rc;
1129 addr += now;
1130 val += now;
1131 bytes -= now;
1132 }
1133 return emulator_write_emulated_onepage(addr, val, bytes, ctxt);
1134}
1135
1116static int emulator_cmpxchg_emulated(unsigned long addr, 1136static int emulator_cmpxchg_emulated(unsigned long addr,
1117 const void *old, 1137 const void *old,
1118 const void *new, 1138 const void *new,