diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1453248723eb..f5c60a84fcf5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4136,6 +4136,78 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, | |||
4136 | return 1; | 4136 | return 1; |
4137 | } | 4137 | } |
4138 | 4138 | ||
4139 | struct read_write_emulator_ops { | ||
4140 | int (*read_write_prepare)(struct kvm_vcpu *vcpu, void *val, | ||
4141 | int bytes); | ||
4142 | int (*read_write_emulate)(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4143 | void *val, int bytes); | ||
4144 | int (*read_write_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4145 | int bytes, void *val); | ||
4146 | int (*read_write_exit_mmio)(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4147 | void *val, int bytes); | ||
4148 | bool write; | ||
4149 | }; | ||
4150 | |||
4151 | static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes) | ||
4152 | { | ||
4153 | if (vcpu->mmio_read_completed) { | ||
4154 | memcpy(val, vcpu->mmio_data, bytes); | ||
4155 | trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, | ||
4156 | vcpu->mmio_phys_addr, *(u64 *)val); | ||
4157 | vcpu->mmio_read_completed = 0; | ||
4158 | return 1; | ||
4159 | } | ||
4160 | |||
4161 | return 0; | ||
4162 | } | ||
4163 | |||
4164 | static int read_emulate(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4165 | void *val, int bytes) | ||
4166 | { | ||
4167 | return !kvm_read_guest(vcpu->kvm, gpa, val, bytes); | ||
4168 | } | ||
4169 | |||
4170 | static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4171 | void *val, int bytes) | ||
4172 | { | ||
4173 | return emulator_write_phys(vcpu, gpa, val, bytes); | ||
4174 | } | ||
4175 | |||
4176 | static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val) | ||
4177 | { | ||
4178 | trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val); | ||
4179 | return vcpu_mmio_write(vcpu, gpa, bytes, val); | ||
4180 | } | ||
4181 | |||
4182 | static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4183 | void *val, int bytes) | ||
4184 | { | ||
4185 | trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); | ||
4186 | return X86EMUL_IO_NEEDED; | ||
4187 | } | ||
4188 | |||
4189 | static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, | ||
4190 | void *val, int bytes) | ||
4191 | { | ||
4192 | memcpy(vcpu->mmio_data, val, bytes); | ||
4193 | memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8); | ||
4194 | return X86EMUL_CONTINUE; | ||
4195 | } | ||
4196 | |||
4197 | static struct read_write_emulator_ops read_emultor = { | ||
4198 | .read_write_prepare = read_prepare, | ||
4199 | .read_write_emulate = read_emulate, | ||
4200 | .read_write_mmio = vcpu_mmio_read, | ||
4201 | .read_write_exit_mmio = read_exit_mmio, | ||
4202 | }; | ||
4203 | |||
4204 | static struct read_write_emulator_ops write_emultor = { | ||
4205 | .read_write_emulate = write_emulate, | ||
4206 | .read_write_mmio = write_mmio, | ||
4207 | .read_write_exit_mmio = write_exit_mmio, | ||
4208 | .write = true, | ||
4209 | }; | ||
4210 | |||
4139 | static int emulator_write_emulated_onepage(unsigned long addr, | 4211 | static int emulator_write_emulated_onepage(unsigned long addr, |
4140 | const void *val, | 4212 | const void *val, |
4141 | unsigned int bytes, | 4213 | unsigned int bytes, |