diff options
-rw-r--r-- | drivers/kvm/kvm.h | 3 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 16 | ||||
-rw-r--r-- | drivers/kvm/svm.c | 7 | ||||
-rw-r--r-- | drivers/kvm/vmx.c | 27 | ||||
-rw-r--r-- | include/linux/kvm.h | 2 |
5 files changed, 53 insertions, 2 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 82c3b13e5d0a..3d07d9b1b815 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -382,6 +382,7 @@ struct kvm { | |||
382 | struct kvm_pic *vpic; | 382 | struct kvm_pic *vpic; |
383 | struct kvm_ioapic *vioapic; | 383 | struct kvm_ioapic *vioapic; |
384 | int round_robin_prev_vcpu; | 384 | int round_robin_prev_vcpu; |
385 | unsigned int tss_addr; | ||
385 | }; | 386 | }; |
386 | 387 | ||
387 | static inline struct kvm_pic *pic_irqchip(struct kvm *kvm) | 388 | static inline struct kvm_pic *pic_irqchip(struct kvm *kvm) |
@@ -467,6 +468,8 @@ struct kvm_x86_ops { | |||
467 | void (*inject_pending_irq)(struct kvm_vcpu *vcpu); | 468 | void (*inject_pending_irq)(struct kvm_vcpu *vcpu); |
468 | void (*inject_pending_vectors)(struct kvm_vcpu *vcpu, | 469 | void (*inject_pending_vectors)(struct kvm_vcpu *vcpu, |
469 | struct kvm_run *run); | 470 | struct kvm_run *run); |
471 | |||
472 | int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); | ||
470 | }; | 473 | }; |
471 | 474 | ||
472 | extern struct kvm_x86_ops *kvm_x86_ops; | 475 | extern struct kvm_x86_ops *kvm_x86_ops; |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a044856bd02b..50fd040b9ea9 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -2661,6 +2661,16 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu) | |||
2661 | return fd; | 2661 | return fd; |
2662 | } | 2662 | } |
2663 | 2663 | ||
2664 | static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr) | ||
2665 | { | ||
2666 | int ret; | ||
2667 | |||
2668 | if (addr > (unsigned int)(-3 * PAGE_SIZE)) | ||
2669 | return -1; | ||
2670 | ret = kvm_x86_ops->set_tss_addr(kvm, addr); | ||
2671 | return ret; | ||
2672 | } | ||
2673 | |||
2664 | /* | 2674 | /* |
2665 | * Creates some virtual cpus. Good luck creating more than one. | 2675 | * Creates some virtual cpus. Good luck creating more than one. |
2666 | */ | 2676 | */ |
@@ -2957,6 +2967,11 @@ static long kvm_vm_ioctl(struct file *filp, | |||
2957 | int r = -EINVAL; | 2967 | int r = -EINVAL; |
2958 | 2968 | ||
2959 | switch (ioctl) { | 2969 | switch (ioctl) { |
2970 | case KVM_SET_TSS_ADDR: | ||
2971 | r = kvm_vm_ioctl_set_tss_addr(kvm, arg); | ||
2972 | if (r < 0) | ||
2973 | goto out; | ||
2974 | break; | ||
2960 | case KVM_CREATE_VCPU: | 2975 | case KVM_CREATE_VCPU: |
2961 | r = kvm_vm_ioctl_create_vcpu(kvm, arg); | 2976 | r = kvm_vm_ioctl_create_vcpu(kvm, arg); |
2962 | if (r < 0) | 2977 | if (r < 0) |
@@ -3183,6 +3198,7 @@ static long kvm_dev_ioctl(struct file *filp, | |||
3183 | case KVM_CAP_HLT: | 3198 | case KVM_CAP_HLT: |
3184 | case KVM_CAP_MMU_SHADOW_CACHE_CONTROL: | 3199 | case KVM_CAP_MMU_SHADOW_CACHE_CONTROL: |
3185 | case KVM_CAP_USER_MEMORY: | 3200 | case KVM_CAP_USER_MEMORY: |
3201 | case KVM_CAP_SET_TSS_ADDR: | ||
3186 | r = 1; | 3202 | r = 1; |
3187 | break; | 3203 | break; |
3188 | default: | 3204 | default: |
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 953c111544e1..beb1e684b68a 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -1439,6 +1439,11 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, | |||
1439 | control->intercept &= ~(1ULL << INTERCEPT_VINTR); | 1439 | control->intercept &= ~(1ULL << INTERCEPT_VINTR); |
1440 | } | 1440 | } |
1441 | 1441 | ||
1442 | static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) | ||
1443 | { | ||
1444 | return 0; | ||
1445 | } | ||
1446 | |||
1442 | static void save_db_regs(unsigned long *db_regs) | 1447 | static void save_db_regs(unsigned long *db_regs) |
1443 | { | 1448 | { |
1444 | asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0])); | 1449 | asm volatile ("mov %%dr0, %0" : "=r"(db_regs[0])); |
@@ -1744,6 +1749,8 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
1744 | .set_irq = svm_set_irq, | 1749 | .set_irq = svm_set_irq, |
1745 | .inject_pending_irq = svm_intr_assist, | 1750 | .inject_pending_irq = svm_intr_assist, |
1746 | .inject_pending_vectors = do_interrupt_requests, | 1751 | .inject_pending_vectors = do_interrupt_requests, |
1752 | |||
1753 | .set_tss_addr = svm_set_tss_addr, | ||
1747 | }; | 1754 | }; |
1748 | 1755 | ||
1749 | static int __init svm_init(void) | 1756 | static int __init svm_init(void) |
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c index 768ea88beb45..46b29184a4d8 100644 --- a/drivers/kvm/vmx.c +++ b/drivers/kvm/vmx.c | |||
@@ -1105,8 +1105,12 @@ static void enter_pmode(struct kvm_vcpu *vcpu) | |||
1105 | 1105 | ||
1106 | static gva_t rmode_tss_base(struct kvm *kvm) | 1106 | static gva_t rmode_tss_base(struct kvm *kvm) |
1107 | { | 1107 | { |
1108 | gfn_t base_gfn = kvm->memslots[0].base_gfn + kvm->memslots[0].npages - 3; | 1108 | if (!kvm->tss_addr) { |
1109 | return base_gfn << PAGE_SHIFT; | 1109 | gfn_t base_gfn = kvm->memslots[0].base_gfn + |
1110 | kvm->memslots[0].npages - 3; | ||
1111 | return base_gfn << PAGE_SHIFT; | ||
1112 | } | ||
1113 | return kvm->tss_addr; | ||
1110 | } | 1114 | } |
1111 | 1115 | ||
1112 | static void fix_rmode_seg(int seg, struct kvm_save_segment *save) | 1116 | static void fix_rmode_seg(int seg, struct kvm_save_segment *save) |
@@ -1735,6 +1739,23 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, | |||
1735 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); | 1739 | vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); |
1736 | } | 1740 | } |
1737 | 1741 | ||
1742 | static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr) | ||
1743 | { | ||
1744 | int ret; | ||
1745 | struct kvm_userspace_memory_region tss_mem = { | ||
1746 | .slot = 8, | ||
1747 | .guest_phys_addr = addr, | ||
1748 | .memory_size = PAGE_SIZE * 3, | ||
1749 | .flags = 0, | ||
1750 | }; | ||
1751 | |||
1752 | ret = kvm_set_memory_region(kvm, &tss_mem, 0); | ||
1753 | if (ret) | ||
1754 | return ret; | ||
1755 | kvm->tss_addr = addr; | ||
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1738 | static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) | 1759 | static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) |
1739 | { | 1760 | { |
1740 | struct kvm_guest_debug *dbg = &vcpu->guest_debug; | 1761 | struct kvm_guest_debug *dbg = &vcpu->guest_debug; |
@@ -2543,6 +2564,8 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
2543 | .set_irq = vmx_inject_irq, | 2564 | .set_irq = vmx_inject_irq, |
2544 | .inject_pending_irq = vmx_intr_assist, | 2565 | .inject_pending_irq = vmx_intr_assist, |
2545 | .inject_pending_vectors = do_interrupt_requests, | 2566 | .inject_pending_vectors = do_interrupt_requests, |
2567 | |||
2568 | .set_tss_addr = vmx_set_tss_addr, | ||
2546 | }; | 2569 | }; |
2547 | 2570 | ||
2548 | static int __init vmx_init(void) | 2571 | static int __init vmx_init(void) |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 971f465e26fa..71d33d62944f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -358,6 +358,7 @@ struct kvm_signal_mask { | |||
358 | #define KVM_CAP_HLT 1 | 358 | #define KVM_CAP_HLT 1 |
359 | #define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2 | 359 | #define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2 |
360 | #define KVM_CAP_USER_MEMORY 3 | 360 | #define KVM_CAP_USER_MEMORY 3 |
361 | #define KVM_CAP_SET_TSS_ADDR 4 | ||
361 | 362 | ||
362 | /* | 363 | /* |
363 | * ioctls for VM fds | 364 | * ioctls for VM fds |
@@ -367,6 +368,7 @@ struct kvm_signal_mask { | |||
367 | #define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45) | 368 | #define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45) |
368 | #define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\ | 369 | #define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46,\ |
369 | struct kvm_userspace_memory_region) | 370 | struct kvm_userspace_memory_region) |
371 | #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) | ||
370 | /* | 372 | /* |
371 | * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns | 373 | * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns |
372 | * a vcpu fd. | 374 | * a vcpu fd. |