1 /*
2  * vmcb.c: VMCB management
3  * Copyright (c) 2005-2007, Advanced Micro Devices, Inc.
4  * Copyright (c) 2004, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include <xen/init.h>
21 #include <xen/lib.h>
22 #include <xen/keyhandler.h>
23 #include <xen/mm.h>
24 #include <xen/rcupdate.h>
25 #include <xen/sched.h>
26 #include <asm/hvm/svm/vmcb.h>
27 #include <asm/msr-index.h>
28 #include <asm/p2m.h>
29 #include <asm/hvm/support.h>
30 #include <asm/hvm/svm/svm.h>
31 #include <asm/hvm/svm/svmdebug.h>
32 
alloc_vmcb(void)33 struct vmcb_struct *alloc_vmcb(void)
34 {
35     struct vmcb_struct *vmcb;
36 
37     vmcb = alloc_xenheap_page();
38     if ( vmcb == NULL )
39     {
40         printk(XENLOG_WARNING "Warning: failed to allocate vmcb.\n");
41         return NULL;
42     }
43 
44     clear_page(vmcb);
45     return vmcb;
46 }
47 
free_vmcb(struct vmcb_struct * vmcb)48 void free_vmcb(struct vmcb_struct *vmcb)
49 {
50     free_xenheap_page(vmcb);
51 }
52 
53 /* This function can directly access fields which are covered by clean bits. */
construct_vmcb(struct vcpu * v)54 static int construct_vmcb(struct vcpu *v)
55 {
56     struct svm_vcpu *svm = &v->arch.hvm.svm;
57     struct vmcb_struct *vmcb = svm->vmcb;
58 
59     vmcb->_general1_intercepts =
60         GENERAL1_INTERCEPT_INTR        | GENERAL1_INTERCEPT_NMI         |
61         GENERAL1_INTERCEPT_SMI         | GENERAL1_INTERCEPT_INIT        |
62         GENERAL1_INTERCEPT_CPUID       | GENERAL1_INTERCEPT_INVD        |
63         GENERAL1_INTERCEPT_HLT         | GENERAL1_INTERCEPT_INVLPG      |
64         GENERAL1_INTERCEPT_INVLPGA     | GENERAL1_INTERCEPT_IOIO_PROT   |
65         GENERAL1_INTERCEPT_MSR_PROT    | GENERAL1_INTERCEPT_SHUTDOWN_EVT|
66         GENERAL1_INTERCEPT_TASK_SWITCH;
67     vmcb->_general2_intercepts =
68         GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
69         GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
70         GENERAL2_INTERCEPT_STGI        | GENERAL2_INTERCEPT_CLGI        |
71         GENERAL2_INTERCEPT_SKINIT      | GENERAL2_INTERCEPT_MWAIT       |
72         GENERAL2_INTERCEPT_WBINVD      | GENERAL2_INTERCEPT_MONITOR     |
73         GENERAL2_INTERCEPT_XSETBV      | GENERAL2_INTERCEPT_ICEBP;
74 
75     /* Intercept all debug-register writes. */
76     vmcb->_dr_intercepts = ~0u;
77 
78     /* Intercept all control-register accesses except for CR2 and CR8. */
79     vmcb->_cr_intercepts = ~(CR_INTERCEPT_CR2_READ |
80                              CR_INTERCEPT_CR2_WRITE |
81                              CR_INTERCEPT_CR8_READ |
82                              CR_INTERCEPT_CR8_WRITE);
83 
84     svm->vmcb_sync_state = vmcb_needs_vmload;
85 
86     /* I/O and MSR permission bitmaps. */
87     svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE), 0);
88     if ( svm->msrpm == NULL )
89         return -ENOMEM;
90     memset(svm->msrpm, 0xff, MSRPM_SIZE);
91 
92     svm_disable_intercept_for_msr(v, MSR_FS_BASE);
93     svm_disable_intercept_for_msr(v, MSR_GS_BASE);
94     svm_disable_intercept_for_msr(v, MSR_SHADOW_GS_BASE);
95     svm_disable_intercept_for_msr(v, MSR_CSTAR);
96     svm_disable_intercept_for_msr(v, MSR_LSTAR);
97     svm_disable_intercept_for_msr(v, MSR_STAR);
98     svm_disable_intercept_for_msr(v, MSR_SYSCALL_MASK);
99 
100     vmcb->_msrpm_base_pa = virt_to_maddr(svm->msrpm);
101     vmcb->_iopm_base_pa = __pa(v->domain->arch.hvm.io_bitmap);
102 
103     /* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */
104     vmcb->_vintr.fields.intr_masking = 1;
105 
106     /* Don't need to intercept RDTSC if CPU supports TSC rate scaling */
107     if ( v->domain->arch.vtsc && !cpu_has_tsc_ratio )
108     {
109         vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
110         vmcb->_general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;
111     }
112 
113     /* Guest segment limits. */
114     vmcb->cs.limit = ~0u;
115     vmcb->es.limit = ~0u;
116     vmcb->ss.limit = ~0u;
117     vmcb->ds.limit = ~0u;
118     vmcb->fs.limit = ~0u;
119     vmcb->gs.limit = ~0u;
120 
121     /* Guest segment AR bytes. */
122     vmcb->es.attr = 0xc93; /* read/write, accessed */
123     vmcb->ss.attr = 0xc93;
124     vmcb->ds.attr = 0xc93;
125     vmcb->fs.attr = 0xc93;
126     vmcb->gs.attr = 0xc93;
127     vmcb->cs.attr = 0xc9b; /* exec/read, accessed */
128 
129     /* Guest TSS. */
130     vmcb->tr.attr = 0x08b; /* 32-bit TSS (busy) */
131     vmcb->tr.limit = 0xff;
132 
133     v->arch.hvm.guest_cr[0] = X86_CR0_PE | X86_CR0_ET;
134     hvm_update_guest_efer(v);
135     hvm_update_guest_cr(v, 0);
136     hvm_update_guest_cr(v, 4);
137 
138     paging_update_paging_modes(v);
139 
140     vmcb->_exception_intercepts =
141         HVM_TRAP_MASK |
142         (v->arch.fully_eager_fpu ? 0 : (1U << TRAP_no_device));
143 
144     if ( paging_mode_hap(v->domain) )
145     {
146         vmcb->_np_enable = 1; /* enable nested paging */
147         vmcb->_g_pat = MSR_IA32_CR_PAT_RESET; /* guest PAT */
148         vmcb->_h_cr3 = pagetable_get_paddr(
149             p2m_get_pagetable(p2m_get_hostp2m(v->domain)));
150 
151         /* No point in intercepting CR3 reads/writes. */
152         vmcb->_cr_intercepts &=
153             ~(CR_INTERCEPT_CR3_READ|CR_INTERCEPT_CR3_WRITE);
154 
155         /*
156          * No point in intercepting INVLPG if we don't have shadow pagetables
157          * that need to be fixed up.
158          */
159         vmcb->_general1_intercepts &= ~GENERAL1_INTERCEPT_INVLPG;
160 
161         /* PAT is under complete control of SVM when using nested paging. */
162         svm_disable_intercept_for_msr(v, MSR_IA32_CR_PAT);
163     }
164     else
165     {
166         vmcb->_exception_intercepts |= (1U << TRAP_page_fault);
167     }
168 
169     if ( cpu_has_pause_filter )
170     {
171         vmcb->_pause_filter_count = SVM_PAUSEFILTER_INIT;
172         vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_PAUSE;
173 
174         if ( cpu_has_pause_thresh )
175             vmcb->_pause_filter_thresh = SVM_PAUSETHRESH_INIT;
176     }
177 
178     return 0;
179 }
180 
svm_create_vmcb(struct vcpu * v)181 int svm_create_vmcb(struct vcpu *v)
182 {
183     struct nestedvcpu *nv = &vcpu_nestedhvm(v);
184     struct svm_vcpu *svm = &v->arch.hvm.svm;
185     int rc;
186 
187     if ( (nv->nv_n1vmcx == NULL) &&
188          (nv->nv_n1vmcx = alloc_vmcb()) == NULL )
189     {
190         printk("Failed to create a new VMCB\n");
191         return -ENOMEM;
192     }
193 
194     svm->vmcb = nv->nv_n1vmcx;
195     rc = construct_vmcb(v);
196     if ( rc != 0 )
197     {
198         free_vmcb(nv->nv_n1vmcx);
199         nv->nv_n1vmcx = NULL;
200         svm->vmcb = NULL;
201         return rc;
202     }
203 
204     svm->vmcb_pa = nv->nv_n1vmcx_pa = virt_to_maddr(svm->vmcb);
205     return 0;
206 }
207 
svm_destroy_vmcb(struct vcpu * v)208 void svm_destroy_vmcb(struct vcpu *v)
209 {
210     struct nestedvcpu *nv = &vcpu_nestedhvm(v);
211     struct svm_vcpu *svm = &v->arch.hvm.svm;
212 
213     if ( nv->nv_n1vmcx != NULL )
214         free_vmcb(nv->nv_n1vmcx);
215 
216     if ( svm->msrpm != NULL )
217     {
218         free_xenheap_pages(
219             svm->msrpm, get_order_from_bytes(MSRPM_SIZE));
220         svm->msrpm = NULL;
221     }
222 
223     nv->nv_n1vmcx = NULL;
224     nv->nv_n1vmcx_pa = INVALID_PADDR;
225     svm->vmcb = NULL;
226 }
227 
vmcb_dump(unsigned char ch)228 static void vmcb_dump(unsigned char ch)
229 {
230     struct domain *d;
231     struct vcpu *v;
232 
233     printk("*********** VMCB Areas **************\n");
234 
235     rcu_read_lock(&domlist_read_lock);
236 
237     for_each_domain ( d )
238     {
239         if ( !is_hvm_domain(d) )
240             continue;
241         printk("\n>>> Domain %d <<<\n", d->domain_id);
242         for_each_vcpu ( d, v )
243         {
244             printk("\tVCPU %d\n", v->vcpu_id);
245             svm_vmcb_dump("key_handler", v->arch.hvm.svm.vmcb);
246         }
247     }
248 
249     rcu_read_unlock(&domlist_read_lock);
250 
251     printk("**************************************\n");
252 }
253 
setup_vmcb_dump(void)254 void __init setup_vmcb_dump(void)
255 {
256     register_keyhandler('v', vmcb_dump, "dump AMD-V VMCBs", 1);
257 }
258 
build_assertions(void)259 static void __init __maybe_unused build_assertions(void)
260 {
261     struct vmcb_struct vmcb;
262 
263     /* Build-time check of the VMCB layout. */
264     BUILD_BUG_ON(sizeof(vmcb) != PAGE_SIZE);
265     BUILD_BUG_ON(offsetof(typeof(vmcb), _pause_filter_thresh) != 0x03c);
266     BUILD_BUG_ON(offsetof(typeof(vmcb), _vintr)               != 0x060);
267     BUILD_BUG_ON(offsetof(typeof(vmcb), event_inj)            != 0x0a8);
268     BUILD_BUG_ON(offsetof(typeof(vmcb), es)                   != 0x400);
269     BUILD_BUG_ON(offsetof(typeof(vmcb), _cpl)                 != 0x4cb);
270     BUILD_BUG_ON(offsetof(typeof(vmcb), _cr4)                 != 0x548);
271     BUILD_BUG_ON(offsetof(typeof(vmcb), rsp)                  != 0x5d8);
272     BUILD_BUG_ON(offsetof(typeof(vmcb), rax)                  != 0x5f8);
273     BUILD_BUG_ON(offsetof(typeof(vmcb), _g_pat)               != 0x668);
274 
275     /* Check struct segment_register against the VMCB segment layout. */
276     BUILD_BUG_ON(sizeof(vmcb.es)       != 16);
277     BUILD_BUG_ON(sizeof(vmcb.es.sel)   != 2);
278     BUILD_BUG_ON(sizeof(vmcb.es.attr)  != 2);
279     BUILD_BUG_ON(sizeof(vmcb.es.limit) != 4);
280     BUILD_BUG_ON(sizeof(vmcb.es.base)  != 8);
281     BUILD_BUG_ON(offsetof(typeof(vmcb.es), sel)   != 0);
282     BUILD_BUG_ON(offsetof(typeof(vmcb.es), attr)  != 2);
283     BUILD_BUG_ON(offsetof(typeof(vmcb.es), limit) != 4);
284     BUILD_BUG_ON(offsetof(typeof(vmcb.es), base)  != 8);
285 }
286 
287 /*
288  * Local variables:
289  * mode: C
290  * c-file-style: "BSD"
291  * c-basic-offset: 4
292  * tab-width: 4
293  * indent-tabs-mode: nil
294  * End:
295  */
296