aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/kvm.h3
-rw-r--r--drivers/kvm/kvm_main.c16
-rw-r--r--drivers/kvm/svm.c7
-rw-r--r--drivers/kvm/vmx.c27
-rw-r--r--include/linux/kvm.h2
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
387static inline struct kvm_pic *pic_irqchip(struct kvm *kvm) 388static 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
472extern struct kvm_x86_ops *kvm_x86_ops; 475extern 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
2664static 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
1442static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
1443{
1444 return 0;
1445}
1446
1442static void save_db_regs(unsigned long *db_regs) 1447static 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
1749static int __init svm_init(void) 1756static 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
1106static gva_t rmode_tss_base(struct kvm *kvm) 1106static 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
1112static void fix_rmode_seg(int seg, struct kvm_save_segment *save) 1116static 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
1742static 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
1738static void kvm_guest_debug_pre(struct kvm_vcpu *vcpu) 1759static 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
2548static int __init vmx_init(void) 2571static 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.