aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2011-07-13 02:32:31 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:17:17 -0400
commit22388a3c8ce2a2a004ce764194cce8a2f9b13d66 (patch)
tree73d190bd75bcd7ff264d1c665cc7b1b2c59fdc30
parent77d197b2ca37b33b0461ab1e2dbe40cbe4a6fd6a (diff)
KVM: x86: cleanup the code of read/write emulation
Using the read/write operation to remove the same code Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/kvm/x86.c146
1 files changed, 45 insertions, 101 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f5c60a84fcf5..2b76ae3cb501 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4045,85 +4045,6 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
4045 return 0; 4045 return 0;
4046} 4046}
4047 4047
4048static int emulator_read_emulated_onepage(unsigned long addr,
4049 void *val,
4050 unsigned int bytes,
4051 struct x86_exception *exception,
4052 struct kvm_vcpu *vcpu)
4053{
4054 gpa_t gpa;
4055 int handled, ret;
4056
4057 if (vcpu->mmio_read_completed) {
4058 memcpy(val, vcpu->mmio_data, bytes);
4059 trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
4060 vcpu->mmio_phys_addr, *(u64 *)val);
4061 vcpu->mmio_read_completed = 0;
4062 return X86EMUL_CONTINUE;
4063 }
4064
4065 ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, false);
4066
4067 if (ret < 0)
4068 return X86EMUL_PROPAGATE_FAULT;
4069
4070 if (ret)
4071 goto mmio;
4072
4073 if (!kvm_read_guest(vcpu->kvm, gpa, val, bytes))
4074 return X86EMUL_CONTINUE;
4075
4076mmio:
4077 /*
4078 * Is this MMIO handled locally?
4079 */
4080 handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
4081
4082 if (handled == bytes)
4083 return X86EMUL_CONTINUE;
4084
4085 gpa += handled;
4086 bytes -= handled;
4087 val += handled;
4088
4089 trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
4090
4091 vcpu->mmio_needed = 1;
4092 vcpu->run->exit_reason = KVM_EXIT_MMIO;
4093 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
4094 vcpu->mmio_size = bytes;
4095 vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
4096 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
4097 vcpu->mmio_index = 0;
4098
4099 return X86EMUL_IO_NEEDED;
4100}
4101
4102static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
4103 unsigned long addr,
4104 void *val,
4105 unsigned int bytes,
4106 struct x86_exception *exception)
4107{
4108 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
4109
4110 /* Crossing a page boundary? */
4111 if (((addr + bytes - 1) ^ addr) & PAGE_MASK) {
4112 int rc, now;
4113
4114 now = -addr & ~PAGE_MASK;
4115 rc = emulator_read_emulated_onepage(addr, val, now, exception,
4116 vcpu);
4117 if (rc != X86EMUL_CONTINUE)
4118 return rc;
4119 addr += now;
4120 val += now;
4121 bytes -= now;
4122 }
4123 return emulator_read_emulated_onepage(addr, val, bytes, exception,
4124 vcpu);
4125}
4126
4127int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, 4048int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
4128 const void *val, int bytes) 4049 const void *val, int bytes)
4129{ 4050{
@@ -4208,16 +4129,21 @@ static struct read_write_emulator_ops write_emultor = {
4208 .write = true, 4129 .write = true,
4209}; 4130};
4210 4131
4211static int emulator_write_emulated_onepage(unsigned long addr, 4132static int emulator_read_write_onepage(unsigned long addr, void *val,
4212 const void *val, 4133 unsigned int bytes,
4213 unsigned int bytes, 4134 struct x86_exception *exception,
4214 struct x86_exception *exception, 4135 struct kvm_vcpu *vcpu,
4215 struct kvm_vcpu *vcpu) 4136 struct read_write_emulator_ops *ops)
4216{ 4137{
4217 gpa_t gpa; 4138 gpa_t gpa;
4218 int handled, ret; 4139 int handled, ret;
4140 bool write = ops->write;
4141
4142 if (ops->read_write_prepare &&
4143 ops->read_write_prepare(vcpu, val, bytes))
4144 return X86EMUL_CONTINUE;
4219 4145
4220 ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, true); 4146 ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
4221 4147
4222 if (ret < 0) 4148 if (ret < 0)
4223 return X86EMUL_PROPAGATE_FAULT; 4149 return X86EMUL_PROPAGATE_FAULT;
@@ -4226,15 +4152,14 @@ static int emulator_write_emulated_onepage(unsigned long addr,
4226 if (ret) 4152 if (ret)
4227 goto mmio; 4153 goto mmio;
4228 4154
4229 if (emulator_write_phys(vcpu, gpa, val, bytes)) 4155 if (ops->read_write_emulate(vcpu, gpa, val, bytes))
4230 return X86EMUL_CONTINUE; 4156 return X86EMUL_CONTINUE;
4231 4157
4232mmio: 4158mmio:
4233 trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
4234 /* 4159 /*
4235 * Is this MMIO handled locally? 4160 * Is this MMIO handled locally?
4236 */ 4161 */
4237 handled = vcpu_mmio_write(vcpu, gpa, bytes, val); 4162 handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
4238 if (handled == bytes) 4163 if (handled == bytes)
4239 return X86EMUL_CONTINUE; 4164 return X86EMUL_CONTINUE;
4240 4165
@@ -4243,23 +4168,20 @@ mmio:
4243 val += handled; 4168 val += handled;
4244 4169
4245 vcpu->mmio_needed = 1; 4170 vcpu->mmio_needed = 1;
4246 memcpy(vcpu->mmio_data, val, bytes);
4247 vcpu->run->exit_reason = KVM_EXIT_MMIO; 4171 vcpu->run->exit_reason = KVM_EXIT_MMIO;
4248 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; 4172 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
4249 vcpu->mmio_size = bytes; 4173 vcpu->mmio_size = bytes;
4250 vcpu->run->mmio.len = min(vcpu->mmio_size, 8); 4174 vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
4251 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1; 4175 vcpu->run->mmio.is_write = vcpu->mmio_is_write = write;
4252 memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
4253 vcpu->mmio_index = 0; 4176 vcpu->mmio_index = 0;
4254 4177
4255 return X86EMUL_CONTINUE; 4178 return ops->read_write_exit_mmio(vcpu, gpa, val, bytes);
4256} 4179}
4257 4180
4258int emulator_write_emulated(struct x86_emulate_ctxt *ctxt, 4181int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
4259 unsigned long addr, 4182 void *val, unsigned int bytes,
4260 const void *val, 4183 struct x86_exception *exception,
4261 unsigned int bytes, 4184 struct read_write_emulator_ops *ops)
4262 struct x86_exception *exception)
4263{ 4185{
4264 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); 4186 struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
4265 4187
@@ -4268,16 +4190,38 @@ int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
4268 int rc, now; 4190 int rc, now;
4269 4191
4270 now = -addr & ~PAGE_MASK; 4192 now = -addr & ~PAGE_MASK;
4271 rc = emulator_write_emulated_onepage(addr, val, now, exception, 4193 rc = emulator_read_write_onepage(addr, val, now, exception,
4272 vcpu); 4194 vcpu, ops);
4195
4273 if (rc != X86EMUL_CONTINUE) 4196 if (rc != X86EMUL_CONTINUE)
4274 return rc; 4197 return rc;
4275 addr += now; 4198 addr += now;
4276 val += now; 4199 val += now;
4277 bytes -= now; 4200 bytes -= now;
4278 } 4201 }
4279 return emulator_write_emulated_onepage(addr, val, bytes, exception, 4202
4280 vcpu); 4203 return emulator_read_write_onepage(addr, val, bytes, exception,
4204 vcpu, ops);
4205}
4206
4207static int emulator_read_emulated(struct x86_emulate_ctxt *ctxt,
4208 unsigned long addr,
4209 void *val,
4210 unsigned int bytes,
4211 struct x86_exception *exception)
4212{
4213 return emulator_read_write(ctxt, addr, val, bytes,
4214 exception, &read_emultor);
4215}
4216
4217int emulator_write_emulated(struct x86_emulate_ctxt *ctxt,
4218 unsigned long addr,
4219 const void *val,
4220 unsigned int bytes,
4221 struct x86_exception *exception)
4222{
4223 return emulator_read_write(ctxt, addr, (void *)val, bytes,
4224 exception, &write_emultor);
4281} 4225}
4282 4226
4283#define CMPXCHG_TYPE(t, ptr, old, new) \ 4227#define CMPXCHG_TYPE(t, ptr, old, new) \