diff options
-rw-r--r-- | arch/x86/kvm/x86.c | 59 |
1 files changed, 26 insertions, 33 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7ba1ab73fd03..a2154487917d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4349,32 +4349,24 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | |||
4349 | return r; | 4349 | return r; |
4350 | } | 4350 | } |
4351 | 4351 | ||
4352 | 4352 | static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size, | |
4353 | static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, | 4353 | unsigned short port, void *val, |
4354 | int size, unsigned short port, void *val, | 4354 | unsigned int count, bool in) |
4355 | unsigned int count) | ||
4356 | { | 4355 | { |
4357 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); | 4356 | trace_kvm_pio(!in, port, size, count); |
4358 | |||
4359 | if (vcpu->arch.pio.count) | ||
4360 | goto data_avail; | ||
4361 | |||
4362 | trace_kvm_pio(0, port, size, count); | ||
4363 | 4357 | ||
4364 | vcpu->arch.pio.port = port; | 4358 | vcpu->arch.pio.port = port; |
4365 | vcpu->arch.pio.in = 1; | 4359 | vcpu->arch.pio.in = in; |
4366 | vcpu->arch.pio.count = count; | 4360 | vcpu->arch.pio.count = count; |
4367 | vcpu->arch.pio.size = size; | 4361 | vcpu->arch.pio.size = size; |
4368 | 4362 | ||
4369 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { | 4363 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { |
4370 | data_avail: | ||
4371 | memcpy(val, vcpu->arch.pio_data, size * count); | ||
4372 | vcpu->arch.pio.count = 0; | 4364 | vcpu->arch.pio.count = 0; |
4373 | return 1; | 4365 | return 1; |
4374 | } | 4366 | } |
4375 | 4367 | ||
4376 | vcpu->run->exit_reason = KVM_EXIT_IO; | 4368 | vcpu->run->exit_reason = KVM_EXIT_IO; |
4377 | vcpu->run->io.direction = KVM_EXIT_IO_IN; | 4369 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; |
4378 | vcpu->run->io.size = size; | 4370 | vcpu->run->io.size = size; |
4379 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | 4371 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; |
4380 | vcpu->run->io.count = count; | 4372 | vcpu->run->io.count = count; |
@@ -4383,36 +4375,37 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, | |||
4383 | return 0; | 4375 | return 0; |
4384 | } | 4376 | } |
4385 | 4377 | ||
4386 | static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt, | 4378 | static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, |
4387 | int size, unsigned short port, | 4379 | int size, unsigned short port, void *val, |
4388 | const void *val, unsigned int count) | 4380 | unsigned int count) |
4389 | { | 4381 | { |
4390 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); | 4382 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); |
4383 | int ret; | ||
4391 | 4384 | ||
4392 | trace_kvm_pio(1, port, size, count); | 4385 | if (vcpu->arch.pio.count) |
4393 | 4386 | goto data_avail; | |
4394 | vcpu->arch.pio.port = port; | ||
4395 | vcpu->arch.pio.in = 0; | ||
4396 | vcpu->arch.pio.count = count; | ||
4397 | vcpu->arch.pio.size = size; | ||
4398 | |||
4399 | memcpy(vcpu->arch.pio_data, val, size * count); | ||
4400 | 4387 | ||
4401 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { | 4388 | ret = emulator_pio_in_out(vcpu, size, port, val, count, true); |
4389 | if (ret) { | ||
4390 | data_avail: | ||
4391 | memcpy(val, vcpu->arch.pio_data, size * count); | ||
4402 | vcpu->arch.pio.count = 0; | 4392 | vcpu->arch.pio.count = 0; |
4403 | return 1; | 4393 | return 1; |
4404 | } | 4394 | } |
4405 | 4395 | ||
4406 | vcpu->run->exit_reason = KVM_EXIT_IO; | ||
4407 | vcpu->run->io.direction = KVM_EXIT_IO_OUT; | ||
4408 | vcpu->run->io.size = size; | ||
4409 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | ||
4410 | vcpu->run->io.count = count; | ||
4411 | vcpu->run->io.port = port; | ||
4412 | |||
4413 | return 0; | 4396 | return 0; |
4414 | } | 4397 | } |
4415 | 4398 | ||
4399 | static int emulator_pio_out_emulated(struct x86_emulate_ctxt *ctxt, | ||
4400 | int size, unsigned short port, | ||
4401 | const void *val, unsigned int count) | ||
4402 | { | ||
4403 | struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); | ||
4404 | |||
4405 | memcpy(vcpu->arch.pio_data, val, size * count); | ||
4406 | return emulator_pio_in_out(vcpu, size, port, (void *)val, count, false); | ||
4407 | } | ||
4408 | |||
4416 | static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) | 4409 | static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) |
4417 | { | 4410 | { |
4418 | return kvm_x86_ops->get_segment_base(vcpu, seg); | 4411 | return kvm_x86_ops->get_segment_base(vcpu, seg); |