diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2011-07-13 02:32:31 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-09-25 12:17:17 -0400 |
commit | 22388a3c8ce2a2a004ce764194cce8a2f9b13d66 (patch) | |
tree | 73d190bd75bcd7ff264d1c665cc7b1b2c59fdc30 | |
parent | 77d197b2ca37b33b0461ab1e2dbe40cbe4a6fd6a (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.c | 146 |
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 | ||
4048 | static 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 | |||
4076 | mmio: | ||
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 | |||
4102 | static 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 | |||
4127 | int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, | 4048 | int 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 | ||
4211 | static int emulator_write_emulated_onepage(unsigned long addr, | 4132 | static 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 | ||
4232 | mmio: | 4158 | mmio: |
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 | ||
4258 | int emulator_write_emulated(struct x86_emulate_ctxt *ctxt, | 4181 | int 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 | |||
4207 | static 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 | |||
4217 | int 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) \ |