aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIzik Eidus <izike@qumranet.com>2007-10-24 18:29:55 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:56 -0500
commitcbc9402297b9a233981f74587786364cda21c771 (patch)
tree35ba97693ffc506bb08f6bafa9e61a260bc8189f
parente0d62c7f48605119a7f9fa632e77561c89928963 (diff)
KVM: Add ioctl to tss address from userspace,
Currently kvm has a wart in that it requires three extra pages for use as a tss when emulating real mode on Intel. This patch moves the allocation internally, only requiring userspace to tell us where in the physical address space we can place the tss. Signed-off-by: Izik Eidus <izike@qumranet.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-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.