aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/kvm/Makefile2
-rw-r--r--drivers/kvm/kvm.h4
-rw-r--r--drivers/kvm/kvm_main.c69
-rw-r--r--drivers/kvm/x86.c102
-rw-r--r--drivers/kvm/x86.h16
5 files changed, 126 insertions, 67 deletions
diff --git a/drivers/kvm/Makefile b/drivers/kvm/Makefile
index e5a8f4d3e973..cf18ad46e987 100644
--- a/drivers/kvm/Makefile
+++ b/drivers/kvm/Makefile
@@ -2,7 +2,7 @@
2# Makefile for Kernel-based Virtual Machine module 2# Makefile for Kernel-based Virtual Machine module
3# 3#
4 4
5kvm-objs := kvm_main.o mmu.o x86_emulate.o i8259.o irq.o lapic.o ioapic.o 5kvm-objs := kvm_main.o x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o ioapic.o
6obj-$(CONFIG_KVM) += kvm.o 6obj-$(CONFIG_KVM) += kvm.o
7kvm-intel-objs = vmx.o 7kvm-intel-objs = vmx.o
8obj-$(CONFIG_KVM_INTEL) += kvm-intel.o 8obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 3eaed4dafec7..9c9c1d7f5b30 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -653,6 +653,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
653 653
654int kvm_fix_hypercall(struct kvm_vcpu *vcpu); 654int kvm_fix_hypercall(struct kvm_vcpu *vcpu);
655 655
656long kvm_arch_dev_ioctl(struct file *filp,
657 unsigned int ioctl, unsigned long arg);
658__init void kvm_arch_init(void);
659
656static inline void kvm_guest_enter(void) 660static inline void kvm_guest_enter(void)
657{ 661{
658 current->flags |= PF_VCPU; 662 current->flags |= PF_VCPU;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 22b143feb66d..ec696887b222 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include "kvm.h" 18#include "kvm.h"
19#include "x86.h"
19#include "x86_emulate.h" 20#include "x86_emulate.h"
20#include "segment_descriptor.h" 21#include "segment_descriptor.h"
21#include "irq.h" 22#include "irq.h"
@@ -2508,43 +2509,6 @@ void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
2508EXPORT_SYMBOL_GPL(kvm_get_cs_db_l_bits); 2509EXPORT_SYMBOL_GPL(kvm_get_cs_db_l_bits);
2509 2510
2510/* 2511/*
2511 * List of msr numbers which we expose to userspace through KVM_GET_MSRS
2512 * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
2513 *
2514 * This list is modified at module load time to reflect the
2515 * capabilities of the host cpu.
2516 */
2517static u32 msrs_to_save[] = {
2518 MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
2519 MSR_K6_STAR,
2520#ifdef CONFIG_X86_64
2521 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
2522#endif
2523 MSR_IA32_TIME_STAMP_COUNTER,
2524};
2525
2526static unsigned num_msrs_to_save;
2527
2528static u32 emulated_msrs[] = {
2529 MSR_IA32_MISC_ENABLE,
2530};
2531
2532static __init void kvm_init_msr_list(void)
2533{
2534 u32 dummy[2];
2535 unsigned i, j;
2536
2537 for (i = j = 0; i < ARRAY_SIZE(msrs_to_save); i++) {
2538 if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
2539 continue;
2540 if (j < i)
2541 msrs_to_save[j] = msrs_to_save[i];
2542 j++;
2543 }
2544 num_msrs_to_save = j;
2545}
2546
2547/*
2548 * Adapt set_msr() to msr_io()'s calling convention 2512 * Adapt set_msr() to msr_io()'s calling convention
2549 */ 2513 */
2550static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data) 2514static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
@@ -3356,33 +3320,6 @@ static long kvm_dev_ioctl(struct file *filp,
3356 goto out; 3320 goto out;
3357 r = kvm_dev_ioctl_create_vm(); 3321 r = kvm_dev_ioctl_create_vm();
3358 break; 3322 break;
3359 case KVM_GET_MSR_INDEX_LIST: {
3360 struct kvm_msr_list __user *user_msr_list = argp;
3361 struct kvm_msr_list msr_list;
3362 unsigned n;
3363
3364 r = -EFAULT;
3365 if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
3366 goto out;
3367 n = msr_list.nmsrs;
3368 msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
3369 if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
3370 goto out;
3371 r = -E2BIG;
3372 if (n < num_msrs_to_save)
3373 goto out;
3374 r = -EFAULT;
3375 if (copy_to_user(user_msr_list->indices, &msrs_to_save,
3376 num_msrs_to_save * sizeof(u32)))
3377 goto out;
3378 if (copy_to_user(user_msr_list->indices
3379 + num_msrs_to_save * sizeof(u32),
3380 &emulated_msrs,
3381 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
3382 goto out;
3383 r = 0;
3384 break;
3385 }
3386 case KVM_CHECK_EXTENSION: { 3323 case KVM_CHECK_EXTENSION: {
3387 int ext = (long)argp; 3324 int ext = (long)argp;
3388 3325
@@ -3406,7 +3343,7 @@ static long kvm_dev_ioctl(struct file *filp,
3406 r = 2 * PAGE_SIZE; 3343 r = 2 * PAGE_SIZE;
3407 break; 3344 break;
3408 default: 3345 default:
3409 ; 3346 return kvm_arch_dev_ioctl(filp, ioctl, arg);
3410 } 3347 }
3411out: 3348out:
3412 return r; 3349 return r;
@@ -3770,7 +3707,7 @@ static __init int kvm_init(void)
3770 3707
3771 kvm_init_debug(); 3708 kvm_init_debug();
3772 3709
3773 kvm_init_msr_list(); 3710 kvm_arch_init();
3774 3711
3775 bad_page = alloc_page(GFP_KERNEL); 3712 bad_page = alloc_page(GFP_KERNEL);
3776 3713
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
new file mode 100644
index 000000000000..437902cf178d
--- /dev/null
+++ b/drivers/kvm/x86.c
@@ -0,0 +1,102 @@
1/*
2 * Kernel-based Virtual Machine driver for Linux
3 *
4 * derived from drivers/kvm/kvm_main.c
5 *
6 * Copyright (C) 2006 Qumranet, Inc.
7 *
8 * Authors:
9 * Avi Kivity <avi@qumranet.com>
10 * Yaniv Kamay <yaniv@qumranet.com>
11 *
12 * This work is licensed under the terms of the GNU GPL, version 2. See
13 * the COPYING file in the top-level directory.
14 *
15 */
16
17#include "x86.h"
18
19#include <asm/uaccess.h>
20
21/*
22 * List of msr numbers which we expose to userspace through KVM_GET_MSRS
23 * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
24 *
25 * This list is modified at module load time to reflect the
26 * capabilities of the host cpu.
27 */
28static u32 msrs_to_save[] = {
29 MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
30 MSR_K6_STAR,
31#ifdef CONFIG_X86_64
32 MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
33#endif
34 MSR_IA32_TIME_STAMP_COUNTER,
35};
36
37static unsigned num_msrs_to_save;
38
39static u32 emulated_msrs[] = {
40 MSR_IA32_MISC_ENABLE,
41};
42
43long kvm_arch_dev_ioctl(struct file *filp,
44 unsigned int ioctl, unsigned long arg)
45{
46 void __user *argp = (void __user *)arg;
47 long r;
48
49 switch (ioctl) {
50 case KVM_GET_MSR_INDEX_LIST: {
51 struct kvm_msr_list __user *user_msr_list = argp;
52 struct kvm_msr_list msr_list;
53 unsigned n;
54
55 r = -EFAULT;
56 if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
57 goto out;
58 n = msr_list.nmsrs;
59 msr_list.nmsrs = num_msrs_to_save + ARRAY_SIZE(emulated_msrs);
60 if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
61 goto out;
62 r = -E2BIG;
63 if (n < num_msrs_to_save)
64 goto out;
65 r = -EFAULT;
66 if (copy_to_user(user_msr_list->indices, &msrs_to_save,
67 num_msrs_to_save * sizeof(u32)))
68 goto out;
69 if (copy_to_user(user_msr_list->indices
70 + num_msrs_to_save * sizeof(u32),
71 &emulated_msrs,
72 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
73 goto out;
74 r = 0;
75 break;
76 }
77 default:
78 r = -EINVAL;
79 }
80out:
81 return r;
82}
83
84static __init void kvm_init_msr_list(void)
85{
86 u32 dummy[2];
87 unsigned i, j;
88
89 for (i = j = 0; i < ARRAY_SIZE(msrs_to_save); i++) {
90 if (rdmsr_safe(msrs_to_save[i], &dummy[0], &dummy[1]) < 0)
91 continue;
92 if (j < i)
93 msrs_to_save[j] = msrs_to_save[i];
94 j++;
95 }
96 num_msrs_to_save = j;
97}
98
99__init void kvm_arch_init(void)
100{
101 kvm_init_msr_list();
102}
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h
new file mode 100644
index 000000000000..1e2f71bd805d
--- /dev/null
+++ b/drivers/kvm/x86.h
@@ -0,0 +1,16 @@
1#/*
2 * Kernel-based Virtual Machine driver for Linux
3 *
4 * This header defines architecture specific interfaces, x86 version
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2. See
7 * the COPYING file in the top-level directory.
8 *
9 */
10
11#ifndef KVM_X86_H
12#define KVM_X86_H
13
14#include "kvm.h"
15
16#endif