diff options
-rw-r--r-- | drivers/kvm/kvm.h | 1 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 48 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 2 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 2 | ||||
-rw-r--r-- | include/linux/kvm.h | 6 |
5 files changed, 53 insertions, 6 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 901b8d917b55..59cbc5b1d905 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -274,6 +274,7 @@ struct kvm_vcpu { | |||
274 | int mmio_size; | 274 | int mmio_size; |
275 | unsigned char mmio_data[8]; | 275 | unsigned char mmio_data[8]; |
276 | gpa_t mmio_phys_addr; | 276 | gpa_t mmio_phys_addr; |
277 | int pio_pending; | ||
277 | 278 | ||
278 | struct { | 279 | struct { |
279 | int active; | 280 | int active; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 42be8a8f299d..ff8bcfee76e5 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -1504,6 +1504,44 @@ void save_msrs(struct vmx_msr_entry *e, int n) | |||
1504 | } | 1504 | } |
1505 | EXPORT_SYMBOL_GPL(save_msrs); | 1505 | EXPORT_SYMBOL_GPL(save_msrs); |
1506 | 1506 | ||
1507 | static void complete_pio(struct kvm_vcpu *vcpu) | ||
1508 | { | ||
1509 | struct kvm_io *io = &vcpu->run->io; | ||
1510 | long delta; | ||
1511 | |||
1512 | kvm_arch_ops->cache_regs(vcpu); | ||
1513 | |||
1514 | if (!io->string) { | ||
1515 | if (io->direction == KVM_EXIT_IO_IN) | ||
1516 | memcpy(&vcpu->regs[VCPU_REGS_RAX], &io->value, | ||
1517 | io->size); | ||
1518 | } else { | ||
1519 | delta = 1; | ||
1520 | if (io->rep) { | ||
1521 | delta *= io->count; | ||
1522 | /* | ||
1523 | * The size of the register should really depend on | ||
1524 | * current address size. | ||
1525 | */ | ||
1526 | vcpu->regs[VCPU_REGS_RCX] -= delta; | ||
1527 | } | ||
1528 | if (io->string_down) | ||
1529 | delta = -delta; | ||
1530 | delta *= io->size; | ||
1531 | if (io->direction == KVM_EXIT_IO_IN) | ||
1532 | vcpu->regs[VCPU_REGS_RDI] += delta; | ||
1533 | else | ||
1534 | vcpu->regs[VCPU_REGS_RSI] += delta; | ||
1535 | } | ||
1536 | |||
1537 | vcpu->pio_pending = 0; | ||
1538 | vcpu->run->io_completed = 0; | ||
1539 | |||
1540 | kvm_arch_ops->decache_regs(vcpu); | ||
1541 | |||
1542 | kvm_arch_ops->skip_emulated_instruction(vcpu); | ||
1543 | } | ||
1544 | |||
1507 | static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1545 | static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
1508 | { | 1546 | { |
1509 | int r; | 1547 | int r; |
@@ -1518,9 +1556,13 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1518 | kvm_run->emulated = 0; | 1556 | kvm_run->emulated = 0; |
1519 | } | 1557 | } |
1520 | 1558 | ||
1521 | if (kvm_run->mmio_completed) { | 1559 | if (kvm_run->io_completed) { |
1522 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | 1560 | if (vcpu->pio_pending) |
1523 | vcpu->mmio_read_completed = 1; | 1561 | complete_pio(vcpu); |
1562 | else { | ||
1563 | memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); | ||
1564 | vcpu->mmio_read_completed = 1; | ||
1565 | } | ||
1524 | } | 1566 | } |
1525 | 1567 | ||
1526 | vcpu->mmio_needed = 0; | 1568 | vcpu->mmio_needed = 0; |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 6787f11738cf..c35b8c83bf3f 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -1037,6 +1037,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1037 | kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT); | 1037 | kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT); |
1038 | kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0; | 1038 | kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0; |
1039 | kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0; | 1039 | kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0; |
1040 | kvm_run->io.count = 1; | ||
1040 | 1041 | ||
1041 | if (kvm_run->io.string) { | 1042 | if (kvm_run->io.string) { |
1042 | unsigned addr_mask; | 1043 | unsigned addr_mask; |
@@ -1056,6 +1057,7 @@ static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1056 | } | 1057 | } |
1057 | } else | 1058 | } else |
1058 | kvm_run->io.value = vcpu->svm->vmcb->save.rax; | 1059 | kvm_run->io.value = vcpu->svm->vmcb->save.rax; |
1060 | vcpu->pio_pending = 1; | ||
1059 | return 0; | 1061 | return 0; |
1060 | } | 1062 | } |
1061 | 1063 | ||
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index a721b60f7385..4d5f40fcb651 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1459,12 +1459,14 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1459 | = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; | 1459 | = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; |
1460 | kvm_run->io.rep = (exit_qualification & 32) != 0; | 1460 | kvm_run->io.rep = (exit_qualification & 32) != 0; |
1461 | kvm_run->io.port = exit_qualification >> 16; | 1461 | kvm_run->io.port = exit_qualification >> 16; |
1462 | kvm_run->io.count = 1; | ||
1462 | if (kvm_run->io.string) { | 1463 | if (kvm_run->io.string) { |
1463 | if (!get_io_count(vcpu, &kvm_run->io.count)) | 1464 | if (!get_io_count(vcpu, &kvm_run->io.count)) |
1464 | return 1; | 1465 | return 1; |
1465 | kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS); | 1466 | kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS); |
1466 | } else | 1467 | } else |
1467 | kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */ | 1468 | kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */ |
1469 | vcpu->pio_pending = 1; | ||
1468 | return 0; | 1470 | return 0; |
1469 | } | 1471 | } |
1470 | 1472 | ||
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index d88e7508ee0a..19aeb3385188 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <asm/types.h> | 11 | #include <asm/types.h> |
12 | #include <linux/ioctl.h> | 12 | #include <linux/ioctl.h> |
13 | 13 | ||
14 | #define KVM_API_VERSION 5 | 14 | #define KVM_API_VERSION 6 |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * Architectural interrupt line count, and the size of the bitmap needed | 17 | * Architectural interrupt line count, and the size of the bitmap needed |
@@ -53,7 +53,7 @@ enum kvm_exit_reason { | |||
53 | struct kvm_run { | 53 | struct kvm_run { |
54 | /* in */ | 54 | /* in */ |
55 | __u32 emulated; /* skip current instruction */ | 55 | __u32 emulated; /* skip current instruction */ |
56 | __u32 mmio_completed; /* mmio request completed */ | 56 | __u32 io_completed; /* mmio/pio request completed */ |
57 | __u8 request_interrupt_window; | 57 | __u8 request_interrupt_window; |
58 | __u8 padding1[7]; | 58 | __u8 padding1[7]; |
59 | 59 | ||
@@ -80,7 +80,7 @@ struct kvm_run { | |||
80 | __u32 error_code; | 80 | __u32 error_code; |
81 | } ex; | 81 | } ex; |
82 | /* KVM_EXIT_IO */ | 82 | /* KVM_EXIT_IO */ |
83 | struct { | 83 | struct kvm_io { |
84 | #define KVM_EXIT_IO_IN 0 | 84 | #define KVM_EXIT_IO_IN 0 |
85 | #define KVM_EXIT_IO_OUT 1 | 85 | #define KVM_EXIT_IO_OUT 1 |
86 | __u8 direction; | 86 | __u8 direction; |