]> err.no Git - linux-2.6/blob - drivers/kvm/x86.c
KVM: Move x86 msr handling to new files x86.[ch]
[linux-2.6] / drivers / kvm / x86.c
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  */
28 static 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
37 static unsigned num_msrs_to_save;
38
39 static u32 emulated_msrs[] = {
40         MSR_IA32_MISC_ENABLE,
41 };
42
43 long 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         }
80 out:
81         return r;
82 }
83
84 static __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 }