diff options
-rw-r--r-- | arch/powerpc/include/asm/kvm_44x.h | 47 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 13 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 14 | ||||
-rw-r--r-- | arch/powerpc/kvm/44x.c | 62 | ||||
-rw-r--r-- | arch/powerpc/kvm/44x_tlb.c | 37 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke_interrupts.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 23 |
9 files changed, 154 insertions, 63 deletions
diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h new file mode 100644 index 000000000000..dece09350712 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_44x.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License, version 2, as | ||
4 | * published by the Free Software Foundation. | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, | ||
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | * GNU General Public License for more details. | ||
10 | * | ||
11 | * You should have received a copy of the GNU General Public License | ||
12 | * along with this program; if not, write to the Free Software | ||
13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
14 | * | ||
15 | * Copyright IBM Corp. 2008 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #ifndef __ASM_44X_H__ | ||
21 | #define __ASM_44X_H__ | ||
22 | |||
23 | #include <linux/kvm_host.h> | ||
24 | |||
25 | /* XXX Can't include mmu-44x.h because it redefines struct mm_context. */ | ||
26 | #define PPC44x_TLB_SIZE 64 | ||
27 | |||
28 | struct kvmppc_vcpu_44x { | ||
29 | /* Unmodified copy of the guest's TLB. */ | ||
30 | struct kvmppc_44x_tlbe guest_tlb[PPC44x_TLB_SIZE]; | ||
31 | /* TLB that's actually used when the guest is running. */ | ||
32 | struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE]; | ||
33 | /* Pages which are referenced in the shadow TLB. */ | ||
34 | struct page *shadow_pages[PPC44x_TLB_SIZE]; | ||
35 | |||
36 | /* Track which TLB entries we've modified in the current exit. */ | ||
37 | u8 shadow_tlb_mod[PPC44x_TLB_SIZE]; | ||
38 | |||
39 | struct kvm_vcpu vcpu; | ||
40 | }; | ||
41 | |||
42 | static inline struct kvmppc_vcpu_44x *to_44x(struct kvm_vcpu *vcpu) | ||
43 | { | ||
44 | return container_of(vcpu, struct kvmppc_vcpu_44x, vcpu); | ||
45 | } | ||
46 | |||
47 | #endif /* __ASM_44X_H__ */ | ||
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index f5850d7d57a5..765d8ec8b7d6 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -74,20 +74,7 @@ struct kvmppc_44x_tlbe { | |||
74 | struct kvm_arch { | 74 | struct kvm_arch { |
75 | }; | 75 | }; |
76 | 76 | ||
77 | /* XXX Can't include mmu-44x.h because it redefines struct mm_context. */ | ||
78 | #define PPC44x_TLB_SIZE 64 | ||
79 | |||
80 | struct kvm_vcpu_arch { | 77 | struct kvm_vcpu_arch { |
81 | /* Unmodified copy of the guest's TLB. */ | ||
82 | struct kvmppc_44x_tlbe guest_tlb[PPC44x_TLB_SIZE]; | ||
83 | /* TLB that's actually used when the guest is running. */ | ||
84 | struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE]; | ||
85 | /* Pages which are referenced in the shadow TLB. */ | ||
86 | struct page *shadow_pages[PPC44x_TLB_SIZE]; | ||
87 | |||
88 | /* Track which TLB entries we've modified in the current exit. */ | ||
89 | u8 shadow_tlb_mod[PPC44x_TLB_SIZE]; | ||
90 | |||
91 | u32 host_stack; | 78 | u32 host_stack; |
92 | u32 host_pid; | 79 | u32 host_pid; |
93 | u32 host_dbcr0; | 80 | u32 host_dbcr0; |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index d59332575b4d..976ecc4b322e 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -62,6 +62,9 @@ extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); | |||
62 | 62 | ||
63 | /* Core-specific hooks */ | 63 | /* Core-specific hooks */ |
64 | 64 | ||
65 | extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, | ||
66 | unsigned int id); | ||
67 | extern void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu); | ||
65 | extern int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu); | 68 | extern int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu); |
66 | extern int kvmppc_core_check_processor_compat(void); | 69 | extern int kvmppc_core_check_processor_compat(void); |
67 | extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | 70 | extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, |
@@ -85,6 +88,9 @@ extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
85 | extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs); | 88 | extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs); |
86 | extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt); | 89 | extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt); |
87 | 90 | ||
91 | extern int kvmppc_booke_init(void); | ||
92 | extern void kvmppc_booke_exit(void); | ||
93 | |||
88 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); | 94 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); |
89 | 95 | ||
90 | #endif /* __POWERPC_KVM_PPC_H__ */ | 96 | #endif /* __POWERPC_KVM_PPC_H__ */ |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0264c97e02b5..393c7f36a1e8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -23,9 +23,6 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/suspend.h> | 24 | #include <linux/suspend.h> |
25 | #include <linux/hrtimer.h> | 25 | #include <linux/hrtimer.h> |
26 | #ifdef CONFIG_KVM | ||
27 | #include <linux/kvm_host.h> | ||
28 | #endif | ||
29 | #ifdef CONFIG_PPC64 | 26 | #ifdef CONFIG_PPC64 |
30 | #include <linux/time.h> | 27 | #include <linux/time.h> |
31 | #include <linux/hardirq.h> | 28 | #include <linux/hardirq.h> |
@@ -51,6 +48,9 @@ | |||
51 | #ifdef CONFIG_PPC_ISERIES | 48 | #ifdef CONFIG_PPC_ISERIES |
52 | #include <asm/iseries/alpaca.h> | 49 | #include <asm/iseries/alpaca.h> |
53 | #endif | 50 | #endif |
51 | #ifdef CONFIG_KVM | ||
52 | #include <asm/kvm_44x.h> | ||
53 | #endif | ||
54 | 54 | ||
55 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | 55 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) |
56 | #include "head_booke.h" | 56 | #include "head_booke.h" |
@@ -359,10 +359,14 @@ int main(void) | |||
359 | #ifdef CONFIG_KVM | 359 | #ifdef CONFIG_KVM |
360 | DEFINE(TLBE_BYTES, sizeof(struct kvmppc_44x_tlbe)); | 360 | DEFINE(TLBE_BYTES, sizeof(struct kvmppc_44x_tlbe)); |
361 | 361 | ||
362 | DEFINE(VCPU_TO_44X, offsetof(struct kvmppc_vcpu_44x, vcpu)); | ||
363 | DEFINE(VCPU44x_SHADOW_TLB, | ||
364 | offsetof(struct kvmppc_vcpu_44x, shadow_tlb)); | ||
365 | DEFINE(VCPU44x_SHADOW_MOD, | ||
366 | offsetof(struct kvmppc_vcpu_44x, shadow_tlb_mod)); | ||
367 | |||
362 | DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); | 368 | DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); |
363 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); | 369 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); |
364 | DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb)); | ||
365 | DEFINE(VCPU_SHADOW_MOD, offsetof(struct kvm_vcpu, arch.shadow_tlb_mod)); | ||
366 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); | 370 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); |
367 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); | 371 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); |
368 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); | 372 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); |
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c index f5d7028eeb09..22054b164b5a 100644 --- a/arch/powerpc/kvm/44x.c +++ b/arch/powerpc/kvm/44x.c | |||
@@ -18,9 +18,13 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kvm_host.h> | 20 | #include <linux/kvm_host.h> |
21 | #include <linux/err.h> | ||
22 | |||
21 | #include <asm/reg.h> | 23 | #include <asm/reg.h> |
22 | #include <asm/cputable.h> | 24 | #include <asm/cputable.h> |
23 | #include <asm/tlbflush.h> | 25 | #include <asm/tlbflush.h> |
26 | #include <asm/kvm_44x.h> | ||
27 | #include <asm/kvm_ppc.h> | ||
24 | 28 | ||
25 | #include "44x_tlb.h" | 29 | #include "44x_tlb.h" |
26 | 30 | ||
@@ -124,7 +128,8 @@ int kvmppc_core_check_processor_compat(void) | |||
124 | 128 | ||
125 | int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | 129 | int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) |
126 | { | 130 | { |
127 | struct kvmppc_44x_tlbe *tlbe = &vcpu->arch.guest_tlb[0]; | 131 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
132 | struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0]; | ||
128 | 133 | ||
129 | tlbe->tid = 0; | 134 | tlbe->tid = 0; |
130 | tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; | 135 | tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; |
@@ -150,6 +155,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | |||
150 | int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | 155 | int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, |
151 | struct kvm_translation *tr) | 156 | struct kvm_translation *tr) |
152 | { | 157 | { |
158 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
153 | struct kvmppc_44x_tlbe *gtlbe; | 159 | struct kvmppc_44x_tlbe *gtlbe; |
154 | int index; | 160 | int index; |
155 | gva_t eaddr; | 161 | gva_t eaddr; |
@@ -166,7 +172,7 @@ int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | |||
166 | return 0; | 172 | return 0; |
167 | } | 173 | } |
168 | 174 | ||
169 | gtlbe = &vcpu->arch.guest_tlb[index]; | 175 | gtlbe = &vcpu_44x->guest_tlb[index]; |
170 | 176 | ||
171 | tr->physical_address = tlb_xlate(gtlbe, eaddr); | 177 | tr->physical_address = tlb_xlate(gtlbe, eaddr); |
172 | /* XXX what does "writeable" and "usermode" even mean? */ | 178 | /* XXX what does "writeable" and "usermode" even mean? */ |
@@ -174,3 +180,55 @@ int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | |||
174 | 180 | ||
175 | return 0; | 181 | return 0; |
176 | } | 182 | } |
183 | |||
184 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
185 | { | ||
186 | struct kvmppc_vcpu_44x *vcpu_44x; | ||
187 | struct kvm_vcpu *vcpu; | ||
188 | int err; | ||
189 | |||
190 | vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); | ||
191 | if (!vcpu_44x) { | ||
192 | err = -ENOMEM; | ||
193 | goto out; | ||
194 | } | ||
195 | |||
196 | vcpu = &vcpu_44x->vcpu; | ||
197 | err = kvm_vcpu_init(vcpu, kvm, id); | ||
198 | if (err) | ||
199 | goto free_vcpu; | ||
200 | |||
201 | return vcpu; | ||
202 | |||
203 | free_vcpu: | ||
204 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | ||
205 | out: | ||
206 | return ERR_PTR(err); | ||
207 | } | ||
208 | |||
209 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | ||
210 | { | ||
211 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
212 | |||
213 | kvm_vcpu_uninit(vcpu); | ||
214 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | ||
215 | } | ||
216 | |||
217 | static int kvmppc_44x_init(void) | ||
218 | { | ||
219 | int r; | ||
220 | |||
221 | r = kvmppc_booke_init(); | ||
222 | if (r) | ||
223 | return r; | ||
224 | |||
225 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), THIS_MODULE); | ||
226 | } | ||
227 | |||
228 | static void kvmppc_44x_exit(void) | ||
229 | { | ||
230 | kvmppc_booke_exit(); | ||
231 | } | ||
232 | |||
233 | module_init(kvmppc_44x_init); | ||
234 | module_exit(kvmppc_44x_exit); | ||
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index bb6da134cadb..8b65fbd6c57d 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/highmem.h> | 24 | #include <linux/highmem.h> |
25 | #include <asm/mmu-44x.h> | 25 | #include <asm/mmu-44x.h> |
26 | #include <asm/kvm_ppc.h> | 26 | #include <asm/kvm_ppc.h> |
27 | #include <asm/kvm_44x.h> | ||
27 | 28 | ||
28 | #include "44x_tlb.h" | 29 | #include "44x_tlb.h" |
29 | 30 | ||
@@ -43,7 +44,7 @@ void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) | |||
43 | "nr", "tid", "word0", "word1", "word2"); | 44 | "nr", "tid", "word0", "word1", "word2"); |
44 | 45 | ||
45 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { | 46 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { |
46 | tlbe = &vcpu->arch.guest_tlb[i]; | 47 | tlbe = &vcpu_44x->guest_tlb[i]; |
47 | if (tlbe->word0 & PPC44x_TLB_VALID) | 48 | if (tlbe->word0 & PPC44x_TLB_VALID) |
48 | printk(" G%2d | %02X | %08X | %08X | %08X |\n", | 49 | printk(" G%2d | %02X | %08X | %08X | %08X |\n", |
49 | i, tlbe->tid, tlbe->word0, tlbe->word1, | 50 | i, tlbe->tid, tlbe->word0, tlbe->word1, |
@@ -51,7 +52,7 @@ void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) | |||
51 | } | 52 | } |
52 | 53 | ||
53 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { | 54 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { |
54 | tlbe = &vcpu->arch.shadow_tlb[i]; | 55 | tlbe = &vcpu_44x->shadow_tlb[i]; |
55 | if (tlbe->word0 & PPC44x_TLB_VALID) | 56 | if (tlbe->word0 & PPC44x_TLB_VALID) |
56 | printk(" S%2d | %02X | %08X | %08X | %08X |\n", | 57 | printk(" S%2d | %02X | %08X | %08X | %08X |\n", |
57 | i, tlbe->tid, tlbe->word0, tlbe->word1, | 58 | i, tlbe->tid, tlbe->word0, tlbe->word1, |
@@ -82,11 +83,12 @@ static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode) | |||
82 | int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, | 83 | int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, |
83 | unsigned int as) | 84 | unsigned int as) |
84 | { | 85 | { |
86 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
85 | int i; | 87 | int i; |
86 | 88 | ||
87 | /* XXX Replace loop with fancy data structures. */ | 89 | /* XXX Replace loop with fancy data structures. */ |
88 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { | 90 | for (i = 0; i < PPC44x_TLB_SIZE; i++) { |
89 | struct kvmppc_44x_tlbe *tlbe = &vcpu->arch.guest_tlb[i]; | 91 | struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[i]; |
90 | unsigned int tid; | 92 | unsigned int tid; |
91 | 93 | ||
92 | if (eaddr < get_tlb_eaddr(tlbe)) | 94 | if (eaddr < get_tlb_eaddr(tlbe)) |
@@ -114,25 +116,27 @@ int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, | |||
114 | struct kvmppc_44x_tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, | 116 | struct kvmppc_44x_tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, |
115 | gva_t eaddr) | 117 | gva_t eaddr) |
116 | { | 118 | { |
119 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
117 | unsigned int as = !!(vcpu->arch.msr & MSR_IS); | 120 | unsigned int as = !!(vcpu->arch.msr & MSR_IS); |
118 | unsigned int index; | 121 | unsigned int index; |
119 | 122 | ||
120 | index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | 123 | index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); |
121 | if (index == -1) | 124 | if (index == -1) |
122 | return NULL; | 125 | return NULL; |
123 | return &vcpu->arch.guest_tlb[index]; | 126 | return &vcpu_44x->guest_tlb[index]; |
124 | } | 127 | } |
125 | 128 | ||
126 | struct kvmppc_44x_tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, | 129 | struct kvmppc_44x_tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, |
127 | gva_t eaddr) | 130 | gva_t eaddr) |
128 | { | 131 | { |
132 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
129 | unsigned int as = !!(vcpu->arch.msr & MSR_DS); | 133 | unsigned int as = !!(vcpu->arch.msr & MSR_DS); |
130 | unsigned int index; | 134 | unsigned int index; |
131 | 135 | ||
132 | index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | 136 | index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); |
133 | if (index == -1) | 137 | if (index == -1) |
134 | return NULL; | 138 | return NULL; |
135 | return &vcpu->arch.guest_tlb[index]; | 139 | return &vcpu_44x->guest_tlb[index]; |
136 | } | 140 | } |
137 | 141 | ||
138 | static int kvmppc_44x_tlbe_is_writable(struct kvmppc_44x_tlbe *tlbe) | 142 | static int kvmppc_44x_tlbe_is_writable(struct kvmppc_44x_tlbe *tlbe) |
@@ -143,8 +147,9 @@ static int kvmppc_44x_tlbe_is_writable(struct kvmppc_44x_tlbe *tlbe) | |||
143 | static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu, | 147 | static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu, |
144 | unsigned int index) | 148 | unsigned int index) |
145 | { | 149 | { |
146 | struct kvmppc_44x_tlbe *stlbe = &vcpu->arch.shadow_tlb[index]; | 150 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
147 | struct page *page = vcpu->arch.shadow_pages[index]; | 151 | struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[index]; |
152 | struct page *page = vcpu_44x->shadow_pages[index]; | ||
148 | 153 | ||
149 | if (get_tlb_v(stlbe)) { | 154 | if (get_tlb_v(stlbe)) { |
150 | if (kvmppc_44x_tlbe_is_writable(stlbe)) | 155 | if (kvmppc_44x_tlbe_is_writable(stlbe)) |
@@ -164,7 +169,9 @@ void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu) | |||
164 | 169 | ||
165 | void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i) | 170 | void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i) |
166 | { | 171 | { |
167 | vcpu->arch.shadow_tlb_mod[i] = 1; | 172 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
173 | |||
174 | vcpu_44x->shadow_tlb_mod[i] = 1; | ||
168 | } | 175 | } |
169 | 176 | ||
170 | /* Caller must ensure that the specified guest TLB entry is safe to insert into | 177 | /* Caller must ensure that the specified guest TLB entry is safe to insert into |
@@ -172,6 +179,7 @@ void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i) | |||
172 | void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, | 179 | void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, |
173 | u32 flags) | 180 | u32 flags) |
174 | { | 181 | { |
182 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
175 | struct page *new_page; | 183 | struct page *new_page; |
176 | struct kvmppc_44x_tlbe *stlbe; | 184 | struct kvmppc_44x_tlbe *stlbe; |
177 | hpa_t hpaddr; | 185 | hpa_t hpaddr; |
@@ -182,7 +190,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, | |||
182 | victim = kvmppc_tlb_44x_pos++; | 190 | victim = kvmppc_tlb_44x_pos++; |
183 | if (kvmppc_tlb_44x_pos > tlb_44x_hwater) | 191 | if (kvmppc_tlb_44x_pos > tlb_44x_hwater) |
184 | kvmppc_tlb_44x_pos = 0; | 192 | kvmppc_tlb_44x_pos = 0; |
185 | stlbe = &vcpu->arch.shadow_tlb[victim]; | 193 | stlbe = &vcpu_44x->shadow_tlb[victim]; |
186 | 194 | ||
187 | /* Get reference to new page. */ | 195 | /* Get reference to new page. */ |
188 | new_page = gfn_to_page(vcpu->kvm, gfn); | 196 | new_page = gfn_to_page(vcpu->kvm, gfn); |
@@ -196,7 +204,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, | |||
196 | /* Drop reference to old page. */ | 204 | /* Drop reference to old page. */ |
197 | kvmppc_44x_shadow_release(vcpu, victim); | 205 | kvmppc_44x_shadow_release(vcpu, victim); |
198 | 206 | ||
199 | vcpu->arch.shadow_pages[victim] = new_page; | 207 | vcpu_44x->shadow_pages[victim] = new_page; |
200 | 208 | ||
201 | /* XXX Make sure (va, size) doesn't overlap any other | 209 | /* XXX Make sure (va, size) doesn't overlap any other |
202 | * entries. 440x6 user manual says the result would be | 210 | * entries. 440x6 user manual says the result would be |
@@ -224,12 +232,13 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, | |||
224 | static void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, | 232 | static void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, |
225 | gva_t eend, u32 asid) | 233 | gva_t eend, u32 asid) |
226 | { | 234 | { |
235 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
227 | unsigned int pid = !(asid & 0xff); | 236 | unsigned int pid = !(asid & 0xff); |
228 | int i; | 237 | int i; |
229 | 238 | ||
230 | /* XXX Replace loop with fancy data structures. */ | 239 | /* XXX Replace loop with fancy data structures. */ |
231 | for (i = 0; i <= tlb_44x_hwater; i++) { | 240 | for (i = 0; i <= tlb_44x_hwater; i++) { |
232 | struct kvmppc_44x_tlbe *stlbe = &vcpu->arch.shadow_tlb[i]; | 241 | struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i]; |
233 | unsigned int tid; | 242 | unsigned int tid; |
234 | 243 | ||
235 | if (!get_tlb_v(stlbe)) | 244 | if (!get_tlb_v(stlbe)) |
@@ -259,12 +268,13 @@ static void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
259 | * switching address spaces. */ | 268 | * switching address spaces. */ |
260 | void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) | 269 | void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) |
261 | { | 270 | { |
271 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
262 | int i; | 272 | int i; |
263 | 273 | ||
264 | if (vcpu->arch.swap_pid) { | 274 | if (vcpu->arch.swap_pid) { |
265 | /* XXX Replace loop with fancy data structures. */ | 275 | /* XXX Replace loop with fancy data structures. */ |
266 | for (i = 0; i <= tlb_44x_hwater; i++) { | 276 | for (i = 0; i <= tlb_44x_hwater; i++) { |
267 | struct kvmppc_44x_tlbe *stlbe = &vcpu->arch.shadow_tlb[i]; | 277 | struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i]; |
268 | 278 | ||
269 | /* Future optimization: clear only userspace mappings. */ | 279 | /* Future optimization: clear only userspace mappings. */ |
270 | kvmppc_44x_shadow_release(vcpu, i); | 280 | kvmppc_44x_shadow_release(vcpu, i); |
@@ -303,6 +313,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, | |||
303 | 313 | ||
304 | int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) | 314 | int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) |
305 | { | 315 | { |
316 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
306 | u64 eaddr; | 317 | u64 eaddr; |
307 | u64 raddr; | 318 | u64 raddr; |
308 | u64 asid; | 319 | u64 asid; |
@@ -317,7 +328,7 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) | |||
317 | return EMULATE_FAIL; | 328 | return EMULATE_FAIL; |
318 | } | 329 | } |
319 | 330 | ||
320 | tlbe = &vcpu->arch.guest_tlb[index]; | 331 | tlbe = &vcpu_44x->guest_tlb[index]; |
321 | 332 | ||
322 | /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */ | 333 | /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */ |
323 | if (tlbe->word0 & PPC44x_TLB_VALID) { | 334 | if (tlbe->word0 & PPC44x_TLB_VALID) { |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index c619d1b912c5..883e9db5f00c 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -573,7 +573,7 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, | |||
573 | return kvmppc_core_vcpu_translate(vcpu, tr); | 573 | return kvmppc_core_vcpu_translate(vcpu, tr); |
574 | } | 574 | } |
575 | 575 | ||
576 | static int kvmppc_booke_init(void) | 576 | int kvmppc_booke_init(void) |
577 | { | 577 | { |
578 | unsigned long ivor[16]; | 578 | unsigned long ivor[16]; |
579 | unsigned long max_ivor = 0; | 579 | unsigned long max_ivor = 0; |
@@ -618,14 +618,11 @@ static int kvmppc_booke_init(void) | |||
618 | flush_icache_range(kvmppc_booke_handlers, | 618 | flush_icache_range(kvmppc_booke_handlers, |
619 | kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); | 619 | kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); |
620 | 620 | ||
621 | return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); | 621 | return 0; |
622 | } | 622 | } |
623 | 623 | ||
624 | static void __exit kvmppc_booke_exit(void) | 624 | void __exit kvmppc_booke_exit(void) |
625 | { | 625 | { |
626 | free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER); | 626 | free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER); |
627 | kvm_exit(); | 627 | kvm_exit(); |
628 | } | 628 | } |
629 | |||
630 | module_init(kvmppc_booke_init) | ||
631 | module_exit(kvmppc_booke_exit) | ||
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 95e165baf85f..8d6929b7fdb6 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S | |||
@@ -349,8 +349,8 @@ lightweight_exit: | |||
349 | lis r5, tlb_44x_hwater@ha | 349 | lis r5, tlb_44x_hwater@ha |
350 | lwz r5, tlb_44x_hwater@l(r5) | 350 | lwz r5, tlb_44x_hwater@l(r5) |
351 | mtctr r5 | 351 | mtctr r5 |
352 | addi r9, r4, VCPU_SHADOW_TLB | 352 | addi r9, r4, -VCPU_TO_44X + VCPU44x_SHADOW_TLB |
353 | addi r5, r4, VCPU_SHADOW_MOD | 353 | addi r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD |
354 | li r3, 0 | 354 | li r3, 0 |
355 | 1: | 355 | 1: |
356 | lbzx r7, r3, r5 | 356 | lbzx r7, r3, r5 |
@@ -377,7 +377,7 @@ lightweight_exit: | |||
377 | /* Clear bitmap of modified TLB entries */ | 377 | /* Clear bitmap of modified TLB entries */ |
378 | li r5, PPC44x_TLB_SIZE>>2 | 378 | li r5, PPC44x_TLB_SIZE>>2 |
379 | mtctr r5 | 379 | mtctr r5 |
380 | addi r5, r4, VCPU_SHADOW_MOD - 4 | 380 | addi r5, r4, -VCPU_TO_44X + VCPU44x_SHADOW_MOD - 4 |
381 | li r6, 0 | 381 | li r6, 0 |
382 | 1: | 382 | 1: |
383 | stwu r6, 4(r5) | 383 | stwu r6, 4(r5) |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 8d0aaf96d838..237f3ba68d27 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -171,31 +171,12 @@ void kvm_arch_flush_shadow(struct kvm *kvm) | |||
171 | 171 | ||
172 | struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) | 172 | struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) |
173 | { | 173 | { |
174 | struct kvm_vcpu *vcpu; | 174 | return kvmppc_core_vcpu_create(kvm, id); |
175 | int err; | ||
176 | |||
177 | vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); | ||
178 | if (!vcpu) { | ||
179 | err = -ENOMEM; | ||
180 | goto out; | ||
181 | } | ||
182 | |||
183 | err = kvm_vcpu_init(vcpu, kvm, id); | ||
184 | if (err) | ||
185 | goto free_vcpu; | ||
186 | |||
187 | return vcpu; | ||
188 | |||
189 | free_vcpu: | ||
190 | kmem_cache_free(kvm_vcpu_cache, vcpu); | ||
191 | out: | ||
192 | return ERR_PTR(err); | ||
193 | } | 175 | } |
194 | 176 | ||
195 | void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) | 177 | void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) |
196 | { | 178 | { |
197 | kvm_vcpu_uninit(vcpu); | 179 | kvmppc_core_vcpu_free(vcpu); |
198 | kmem_cache_free(kvm_vcpu_cache, vcpu); | ||
199 | } | 180 | } |
200 | 181 | ||
201 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | 182 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) |