1 /*
2  * nestedsvm.h: Nested Virtualization
3  * Copyright (c) 2011, Advanced Micro Devices, Inc
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 #ifndef __ASM_X86_HVM_SVM_NESTEDSVM_H__
19 #define __ASM_X86_HVM_SVM_NESTEDSVM_H__
20 
21 #include <asm/hvm/hvm.h>
22 #include <asm/hvm/svm/vmcb.h>
23 
24 /* SVM specific intblk types, cannot be an enum because gcc 4.5 complains */
25 /* GIF cleared */
26 #define hvm_intblk_svm_gif      hvm_intblk_arch
27 
28 struct nestedsvm {
29     bool_t ns_gif;
30     uint64_t ns_msr_hsavepa; /* MSR HSAVE_PA value */
31 
32     /* l1 guest physical address of virtual vmcb used by prior VMRUN.
33      * Needed for VMCB Cleanbit emulation.
34      */
35     uint64_t ns_ovvmcb_pa;
36 
37     /* virtual tscratio holding the value l1 guest writes to the
38      * MSR_AMD64_TSC_RATIO MSR.
39      */
40     uint64_t ns_tscratio;
41 
42     /* Cached real intercepts of the l2 guest */
43     uint32_t ns_cr_intercepts;
44     uint32_t ns_dr_intercepts;
45     uint32_t ns_exception_intercepts;
46     uint32_t ns_general1_intercepts;
47     uint32_t ns_general2_intercepts;
48 
49     /* Cached real lbr of the l2 guest */
50     lbrctrl_t ns_lbr_control;
51 
52     /* Cached real MSR permission bitmaps of the l2 guest */
53     unsigned long *ns_cached_msrpm;
54     /* Merged MSR permission bitmap */
55     unsigned long *ns_merged_msrpm;
56 
57     /* guest physical address of virtual io permission map */
58     paddr_t ns_iomap_pa, ns_oiomap_pa;
59     /* Shadow io permission map */
60     unsigned long *ns_iomap;
61 
62     uint64_t ns_cr0; /* Cached guest_cr[0] of l1 guest while l2 guest runs.
63                       * Needed to handle FPU context switching */
64 
65     /* Cache guest cr3/host cr3 the guest sets up for the l2 guest.
66      * Used by Shadow-on-Shadow and Nested-on-Nested.
67      * ns_vmcb_guestcr3: in l2 guest physical address space and points to
68      *     the l2 guest page table
69      * ns_vmcb_hostcr3: in l1 guest physical address space and points to
70      *     the l1 guest nested page table
71      */
72     uint64_t ns_vmcb_guestcr3, ns_vmcb_hostcr3;
73     uint32_t ns_guest_asid;
74 
75     bool_t ns_hap_enabled;
76 
77     /* Only meaningful when vmexit_pending flag is set */
78     struct {
79         uint64_t exitcode;  /* native exitcode to inject into l1 guest */
80         uint64_t exitinfo1; /* additional information to the exitcode */
81         uint64_t exitinfo2; /* additional information to the exitcode */
82     } ns_vmexit;
83     union {
84         uint32_t bytes;
85         struct {
86             uint32_t rflagsif: 1;
87             uint32_t vintrmask: 1;
88             uint32_t reserved: 30;
89         } fields;
90     } ns_hostflags;
91 };
92 
93 #define vcpu_nestedsvm(v) (vcpu_nestedhvm(v).u.nsvm)
94 
95 /* True when l1 guest enabled SVM in EFER */
96 #define nsvm_efer_svm_enabled(v) \
97     (!!((v)->arch.hvm_vcpu.guest_efer & EFER_SVME))
98 
99 int nestedsvm_vmcb_map(struct vcpu *v, uint64_t vmcbaddr);
100 void nestedsvm_vmexit_defer(struct vcpu *v,
101     uint64_t exitcode, uint64_t exitinfo1, uint64_t exitinfo2);
102 enum nestedhvm_vmexits
103 nestedsvm_vmexit_n2n1(struct vcpu *v, struct cpu_user_regs *regs);
104 enum nestedhvm_vmexits
105 nestedsvm_check_intercepts(struct vcpu *v, struct cpu_user_regs *regs,
106     uint64_t exitcode);
107 
108 /* Interface methods */
109 void nsvm_vcpu_destroy(struct vcpu *v);
110 int nsvm_vcpu_initialise(struct vcpu *v);
111 int nsvm_vcpu_reset(struct vcpu *v);
112 int nsvm_vcpu_vmrun(struct vcpu *v, struct cpu_user_regs *regs);
113 int nsvm_vcpu_vmexit_event(struct vcpu *v, const struct x86_event *event);
114 uint64_t nsvm_vcpu_hostcr3(struct vcpu *v);
115 bool_t nsvm_vmcb_guest_intercepts_event(
116     struct vcpu *v, unsigned int vector, int errcode);
117 bool_t nsvm_vmcb_hap_enabled(struct vcpu *v);
118 enum hvm_intblk nsvm_intr_blocked(struct vcpu *v);
119 
120 /* MSRs */
121 int nsvm_rdmsr(struct vcpu *v, unsigned int msr, uint64_t *msr_content);
122 int nsvm_wrmsr(struct vcpu *v, unsigned int msr, uint64_t msr_content);
123 
124 /* Interrupts, vGIF */
125 void svm_vmexit_do_clgi(struct cpu_user_regs *regs, struct vcpu *v);
126 void svm_vmexit_do_stgi(struct cpu_user_regs *regs, struct vcpu *v);
127 bool_t nestedsvm_gif_isset(struct vcpu *v);
128 int nsvm_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
129                          unsigned int *page_order, uint8_t *p2m_acc,
130                          bool_t access_r, bool_t access_w, bool_t access_x);
131 
132 #define NSVM_INTR_NOTHANDLED     3
133 #define NSVM_INTR_NOTINTERCEPTED 2
134 #define NSVM_INTR_FORCEVMEXIT    1
135 #define NSVM_INTR_MASKED         0
136 int nestedsvm_vcpu_interrupt(struct vcpu *v, const struct hvm_intack intack);
137 
138 #endif /* ASM_X86_HVM_SVM_NESTEDSVM_H__ */
139 
140 /*
141  * Local variables:
142  * mode: C
143  * c-file-style: "BSD"
144  * c-basic-offset: 4
145  * tab-width: 4
146  * indent-tabs-mode: nil
147  * End:
148  */
149