1d94d71cbSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22a342ed5SAlexander Graf /*
32a342ed5SAlexander Graf * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved.
4940b45ecSScott Wood * Copyright 2010-2011 Freescale Semiconductor, Inc.
52a342ed5SAlexander Graf *
62a342ed5SAlexander Graf * Authors:
72a342ed5SAlexander Graf * Alexander Graf <agraf@suse.de>
82a342ed5SAlexander Graf */
92a342ed5SAlexander Graf
102a342ed5SAlexander Graf #include <linux/kvm_host.h>
112a342ed5SAlexander Graf #include <linux/init.h>
1266b15db6SPaul Gortmaker #include <linux/export.h>
13298a32b1SCatalin Marinas #include <linux/kmemleak.h>
142a342ed5SAlexander Graf #include <linux/kvm_para.h>
152a342ed5SAlexander Graf #include <linux/slab.h>
162a342ed5SAlexander Graf #include <linux/of.h>
179f9eae5cSMathieu Malaterre #include <linux/pagemap.h>
182a342ed5SAlexander Graf
192a342ed5SAlexander Graf #include <asm/reg.h>
202a342ed5SAlexander Graf #include <asm/sections.h>
212a342ed5SAlexander Graf #include <asm/cacheflush.h>
222a342ed5SAlexander Graf #include <asm/disassemble.h>
23940b45ecSScott Wood #include <asm/ppc-opcode.h>
242e1ae9c0SLiu Yu-B13201 #include <asm/epapr_hcalls.h>
252a342ed5SAlexander Graf
26d17051cbSAlexander Graf #define KVM_MAGIC_PAGE (-4096L)
27d17051cbSAlexander Graf #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
28d17051cbSAlexander Graf
29d1293c92SAlexander Graf #define KVM_INST_LWZ 0x80000000
30d1293c92SAlexander Graf #define KVM_INST_STW 0x90000000
31d1293c92SAlexander Graf #define KVM_INST_LD 0xe8000000
32d1293c92SAlexander Graf #define KVM_INST_STD 0xf8000000
33d1293c92SAlexander Graf #define KVM_INST_NOP 0x60000000
34d1293c92SAlexander Graf #define KVM_INST_B 0x48000000
35d1293c92SAlexander Graf #define KVM_INST_B_MASK 0x03ffffff
36d1293c92SAlexander Graf #define KVM_INST_B_MAX 0x01ffffff
37940b45ecSScott Wood #define KVM_INST_LI 0x38000000
38d1293c92SAlexander Graf
3973a18109SAlexander Graf #define KVM_MASK_RT 0x03e00000
40512ba59eSAlexander Graf #define KVM_RT_30 0x03c00000
41cbe487faSAlexander Graf #define KVM_MASK_RB 0x0000f800
42d1293c92SAlexander Graf #define KVM_INST_MFMSR 0x7c0000a6
43d1293c92SAlexander Graf
44b5904972SScott Wood #define SPR_FROM 0
45b5904972SScott Wood #define SPR_TO 0x100
46b5904972SScott Wood
47b5904972SScott Wood #define KVM_INST_SPR(sprn, moveto) (0x7c0002a6 | \
48b5904972SScott Wood (((sprn) & 0x1f) << 16) | \
49b5904972SScott Wood (((sprn) & 0x3e0) << 6) | \
50b5904972SScott Wood (moveto))
51b5904972SScott Wood
52b5904972SScott Wood #define KVM_INST_MFSPR(sprn) KVM_INST_SPR(sprn, SPR_FROM)
53b5904972SScott Wood #define KVM_INST_MTSPR(sprn) KVM_INST_SPR(sprn, SPR_TO)
5473a18109SAlexander Graf
55d1290b15SAlexander Graf #define KVM_INST_TLBSYNC 0x7c00046c
5678109277SAlexander Graf #define KVM_INST_MTMSRD_L0 0x7c000164
57819a63dcSAlexander Graf #define KVM_INST_MTMSRD_L1 0x7c010164
5878109277SAlexander Graf #define KVM_INST_MTMSR 0x7c000124
59d1290b15SAlexander Graf
60940b45ecSScott Wood #define KVM_INST_WRTEE 0x7c000106
61644bfa01SAlexander Graf #define KVM_INST_WRTEEI_0 0x7c000146
62644bfa01SAlexander Graf #define KVM_INST_WRTEEI_1 0x7c008146
63644bfa01SAlexander Graf
64cbe487faSAlexander Graf #define KVM_INST_MTSRIN 0x7c0001e4
65cbe487faSAlexander Graf
6673a18109SAlexander Graf static bool kvm_patching_worked = true;
670cb0837fSMichael Ellerman extern char kvm_tmp[];
680cb0837fSMichael Ellerman extern char kvm_tmp_end[];
692d4f5671SAlexander Graf static int kvm_tmp_index;
7073a18109SAlexander Graf
kvm_patch_ins(u32 * inst,u32 new_inst)71731dade1SMichael Ellerman static void __init kvm_patch_ins(u32 *inst, u32 new_inst)
7273a18109SAlexander Graf {
7373a18109SAlexander Graf *inst = new_inst;
7473a18109SAlexander Graf flush_icache_range((ulong)inst, (ulong)inst + 4);
7573a18109SAlexander Graf }
7673a18109SAlexander Graf
kvm_patch_ins_ll(u32 * inst,long addr,u32 rt)77731dade1SMichael Ellerman static void __init kvm_patch_ins_ll(u32 *inst, long addr, u32 rt)
78512ba59eSAlexander Graf {
79512ba59eSAlexander Graf #ifdef CONFIG_64BIT
80512ba59eSAlexander Graf kvm_patch_ins(inst, KVM_INST_LD | rt | (addr & 0x0000fffc));
81512ba59eSAlexander Graf #else
82512ba59eSAlexander Graf kvm_patch_ins(inst, KVM_INST_LWZ | rt | (addr & 0x0000fffc));
83512ba59eSAlexander Graf #endif
84512ba59eSAlexander Graf }
85512ba59eSAlexander Graf
kvm_patch_ins_ld(u32 * inst,long addr,u32 rt)86731dade1SMichael Ellerman static void __init kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
87d1293c92SAlexander Graf {
88d1293c92SAlexander Graf #ifdef CONFIG_64BIT
89d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_LD | rt | (addr & 0x0000fffc));
90d1293c92SAlexander Graf #else
91d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc));
92d1293c92SAlexander Graf #endif
93d1293c92SAlexander Graf }
94d1293c92SAlexander Graf
kvm_patch_ins_lwz(u32 * inst,long addr,u32 rt)95731dade1SMichael Ellerman static void __init kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
96d1293c92SAlexander Graf {
97d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_LWZ | rt | (addr & 0x0000ffff));
98d1293c92SAlexander Graf }
99d1293c92SAlexander Graf
kvm_patch_ins_std(u32 * inst,long addr,u32 rt)100731dade1SMichael Ellerman static void __init kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
101d1293c92SAlexander Graf {
102d1293c92SAlexander Graf #ifdef CONFIG_64BIT
103d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_STD | rt | (addr & 0x0000fffc));
104d1293c92SAlexander Graf #else
105d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc));
106d1293c92SAlexander Graf #endif
107d1293c92SAlexander Graf }
108d1293c92SAlexander Graf
kvm_patch_ins_stw(u32 * inst,long addr,u32 rt)109731dade1SMichael Ellerman static void __init kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
110d1293c92SAlexander Graf {
111d1293c92SAlexander Graf kvm_patch_ins(inst, KVM_INST_STW | rt | (addr & 0x0000fffc));
112d1293c92SAlexander Graf }
113d1293c92SAlexander Graf
kvm_patch_ins_nop(u32 * inst)114731dade1SMichael Ellerman static void __init kvm_patch_ins_nop(u32 *inst)
115d1290b15SAlexander Graf {
116d1290b15SAlexander Graf kvm_patch_ins(inst, KVM_INST_NOP);
117d1290b15SAlexander Graf }
118d1290b15SAlexander Graf
kvm_patch_ins_b(u32 * inst,int addr)119731dade1SMichael Ellerman static void __init kvm_patch_ins_b(u32 *inst, int addr)
12071ee8e34SAlexander Graf {
121a36be100SScott Wood #if defined(CONFIG_RELOCATABLE) && defined(CONFIG_PPC_BOOK3S)
12271ee8e34SAlexander Graf /* On relocatable kernels interrupts handlers and our code
12371ee8e34SAlexander Graf can be in different regions, so we don't patch them */
12471ee8e34SAlexander Graf
12571ee8e34SAlexander Graf if ((ulong)inst < (ulong)&__end_interrupts)
12671ee8e34SAlexander Graf return;
12771ee8e34SAlexander Graf #endif
12871ee8e34SAlexander Graf
12971ee8e34SAlexander Graf kvm_patch_ins(inst, KVM_INST_B | (addr & KVM_INST_B_MASK));
13071ee8e34SAlexander Graf }
13171ee8e34SAlexander Graf
kvm_alloc(int len)132731dade1SMichael Ellerman static u32 * __init kvm_alloc(int len)
1332d4f5671SAlexander Graf {
1342d4f5671SAlexander Graf u32 *p;
1352d4f5671SAlexander Graf
1360cb0837fSMichael Ellerman if ((kvm_tmp_index + len) > (kvm_tmp_end - kvm_tmp)) {
1372d4f5671SAlexander Graf printk(KERN_ERR "KVM: No more space (%d + %d)\n",
1382d4f5671SAlexander Graf kvm_tmp_index, len);
1392d4f5671SAlexander Graf kvm_patching_worked = false;
1402d4f5671SAlexander Graf return NULL;
1412d4f5671SAlexander Graf }
1422d4f5671SAlexander Graf
1432d4f5671SAlexander Graf p = (void*)&kvm_tmp[kvm_tmp_index];
1442d4f5671SAlexander Graf kvm_tmp_index += len;
1452d4f5671SAlexander Graf
1462d4f5671SAlexander Graf return p;
1472d4f5671SAlexander Graf }
1482d4f5671SAlexander Graf
149819a63dcSAlexander Graf extern u32 kvm_emulate_mtmsrd_branch_offs;
150819a63dcSAlexander Graf extern u32 kvm_emulate_mtmsrd_reg_offs;
151df08bd10SAlexander Graf extern u32 kvm_emulate_mtmsrd_orig_ins_offs;
152819a63dcSAlexander Graf extern u32 kvm_emulate_mtmsrd_len;
153819a63dcSAlexander Graf extern u32 kvm_emulate_mtmsrd[];
154819a63dcSAlexander Graf
kvm_patch_ins_mtmsrd(u32 * inst,u32 rt)155731dade1SMichael Ellerman static void __init kvm_patch_ins_mtmsrd(u32 *inst, u32 rt)
156819a63dcSAlexander Graf {
157819a63dcSAlexander Graf u32 *p;
158819a63dcSAlexander Graf int distance_start;
159819a63dcSAlexander Graf int distance_end;
160819a63dcSAlexander Graf ulong next_inst;
161819a63dcSAlexander Graf
162819a63dcSAlexander Graf p = kvm_alloc(kvm_emulate_mtmsrd_len * 4);
163819a63dcSAlexander Graf if (!p)
164819a63dcSAlexander Graf return;
165819a63dcSAlexander Graf
166819a63dcSAlexander Graf /* Find out where we are and put everything there */
167819a63dcSAlexander Graf distance_start = (ulong)p - (ulong)inst;
168819a63dcSAlexander Graf next_inst = ((ulong)inst + 4);
169819a63dcSAlexander Graf distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsrd_branch_offs];
170819a63dcSAlexander Graf
171819a63dcSAlexander Graf /* Make sure we only write valid b instructions */
172819a63dcSAlexander Graf if (distance_start > KVM_INST_B_MAX) {
173819a63dcSAlexander Graf kvm_patching_worked = false;
174819a63dcSAlexander Graf return;
175819a63dcSAlexander Graf }
176819a63dcSAlexander Graf
177819a63dcSAlexander Graf /* Modify the chunk to fit the invocation */
178819a63dcSAlexander Graf memcpy(p, kvm_emulate_mtmsrd, kvm_emulate_mtmsrd_len * 4);
179819a63dcSAlexander Graf p[kvm_emulate_mtmsrd_branch_offs] |= distance_end & KVM_INST_B_MASK;
180df08bd10SAlexander Graf switch (get_rt(rt)) {
181df08bd10SAlexander Graf case 30:
182df08bd10SAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsrd_reg_offs],
183df08bd10SAlexander Graf magic_var(scratch2), KVM_RT_30);
184df08bd10SAlexander Graf break;
185df08bd10SAlexander Graf case 31:
186df08bd10SAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsrd_reg_offs],
187df08bd10SAlexander Graf magic_var(scratch1), KVM_RT_30);
188df08bd10SAlexander Graf break;
189df08bd10SAlexander Graf default:
190819a63dcSAlexander Graf p[kvm_emulate_mtmsrd_reg_offs] |= rt;
191df08bd10SAlexander Graf break;
192df08bd10SAlexander Graf }
193df08bd10SAlexander Graf
194df08bd10SAlexander Graf p[kvm_emulate_mtmsrd_orig_ins_offs] = *inst;
195819a63dcSAlexander Graf flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsrd_len * 4);
196819a63dcSAlexander Graf
197819a63dcSAlexander Graf /* Patch the invocation */
198819a63dcSAlexander Graf kvm_patch_ins_b(inst, distance_start);
199819a63dcSAlexander Graf }
200819a63dcSAlexander Graf
20178109277SAlexander Graf extern u32 kvm_emulate_mtmsr_branch_offs;
20278109277SAlexander Graf extern u32 kvm_emulate_mtmsr_reg1_offs;
20378109277SAlexander Graf extern u32 kvm_emulate_mtmsr_reg2_offs;
20478109277SAlexander Graf extern u32 kvm_emulate_mtmsr_orig_ins_offs;
20578109277SAlexander Graf extern u32 kvm_emulate_mtmsr_len;
20678109277SAlexander Graf extern u32 kvm_emulate_mtmsr[];
20778109277SAlexander Graf
kvm_patch_ins_mtmsr(u32 * inst,u32 rt)208731dade1SMichael Ellerman static void __init kvm_patch_ins_mtmsr(u32 *inst, u32 rt)
20978109277SAlexander Graf {
21078109277SAlexander Graf u32 *p;
21178109277SAlexander Graf int distance_start;
21278109277SAlexander Graf int distance_end;
21378109277SAlexander Graf ulong next_inst;
21478109277SAlexander Graf
21578109277SAlexander Graf p = kvm_alloc(kvm_emulate_mtmsr_len * 4);
21678109277SAlexander Graf if (!p)
21778109277SAlexander Graf return;
21878109277SAlexander Graf
21978109277SAlexander Graf /* Find out where we are and put everything there */
22078109277SAlexander Graf distance_start = (ulong)p - (ulong)inst;
22178109277SAlexander Graf next_inst = ((ulong)inst + 4);
22278109277SAlexander Graf distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs];
22378109277SAlexander Graf
22478109277SAlexander Graf /* Make sure we only write valid b instructions */
22578109277SAlexander Graf if (distance_start > KVM_INST_B_MAX) {
22678109277SAlexander Graf kvm_patching_worked = false;
22778109277SAlexander Graf return;
22878109277SAlexander Graf }
22978109277SAlexander Graf
23078109277SAlexander Graf /* Modify the chunk to fit the invocation */
23178109277SAlexander Graf memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4);
23278109277SAlexander Graf p[kvm_emulate_mtmsr_branch_offs] |= distance_end & KVM_INST_B_MASK;
233512ba59eSAlexander Graf
234512ba59eSAlexander Graf /* Make clobbered registers work too */
235512ba59eSAlexander Graf switch (get_rt(rt)) {
236512ba59eSAlexander Graf case 30:
237512ba59eSAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg1_offs],
238512ba59eSAlexander Graf magic_var(scratch2), KVM_RT_30);
239512ba59eSAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg2_offs],
240512ba59eSAlexander Graf magic_var(scratch2), KVM_RT_30);
241512ba59eSAlexander Graf break;
242512ba59eSAlexander Graf case 31:
243512ba59eSAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg1_offs],
244512ba59eSAlexander Graf magic_var(scratch1), KVM_RT_30);
245512ba59eSAlexander Graf kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg2_offs],
246512ba59eSAlexander Graf magic_var(scratch1), KVM_RT_30);
247512ba59eSAlexander Graf break;
248512ba59eSAlexander Graf default:
24978109277SAlexander Graf p[kvm_emulate_mtmsr_reg1_offs] |= rt;
25078109277SAlexander Graf p[kvm_emulate_mtmsr_reg2_offs] |= rt;
251512ba59eSAlexander Graf break;
252512ba59eSAlexander Graf }
253512ba59eSAlexander Graf
25478109277SAlexander Graf p[kvm_emulate_mtmsr_orig_ins_offs] = *inst;
25578109277SAlexander Graf flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4);
25678109277SAlexander Graf
25778109277SAlexander Graf /* Patch the invocation */
25878109277SAlexander Graf kvm_patch_ins_b(inst, distance_start);
25978109277SAlexander Graf }
26078109277SAlexander Graf
261644bfa01SAlexander Graf #ifdef CONFIG_BOOKE
262644bfa01SAlexander Graf
263940b45ecSScott Wood extern u32 kvm_emulate_wrtee_branch_offs;
264940b45ecSScott Wood extern u32 kvm_emulate_wrtee_reg_offs;
265940b45ecSScott Wood extern u32 kvm_emulate_wrtee_orig_ins_offs;
266940b45ecSScott Wood extern u32 kvm_emulate_wrtee_len;
267940b45ecSScott Wood extern u32 kvm_emulate_wrtee[];
268644bfa01SAlexander Graf
kvm_patch_ins_wrtee(u32 * inst,u32 rt,int imm_one)269731dade1SMichael Ellerman static void __init kvm_patch_ins_wrtee(u32 *inst, u32 rt, int imm_one)
270644bfa01SAlexander Graf {
271644bfa01SAlexander Graf u32 *p;
272644bfa01SAlexander Graf int distance_start;
273644bfa01SAlexander Graf int distance_end;
274644bfa01SAlexander Graf ulong next_inst;
275644bfa01SAlexander Graf
276940b45ecSScott Wood p = kvm_alloc(kvm_emulate_wrtee_len * 4);
277644bfa01SAlexander Graf if (!p)
278644bfa01SAlexander Graf return;
279644bfa01SAlexander Graf
280644bfa01SAlexander Graf /* Find out where we are and put everything there */
281644bfa01SAlexander Graf distance_start = (ulong)p - (ulong)inst;
282644bfa01SAlexander Graf next_inst = ((ulong)inst + 4);
283940b45ecSScott Wood distance_end = next_inst - (ulong)&p[kvm_emulate_wrtee_branch_offs];
284644bfa01SAlexander Graf
285644bfa01SAlexander Graf /* Make sure we only write valid b instructions */
286644bfa01SAlexander Graf if (distance_start > KVM_INST_B_MAX) {
287644bfa01SAlexander Graf kvm_patching_worked = false;
288644bfa01SAlexander Graf return;
289644bfa01SAlexander Graf }
290644bfa01SAlexander Graf
291644bfa01SAlexander Graf /* Modify the chunk to fit the invocation */
292940b45ecSScott Wood memcpy(p, kvm_emulate_wrtee, kvm_emulate_wrtee_len * 4);
293940b45ecSScott Wood p[kvm_emulate_wrtee_branch_offs] |= distance_end & KVM_INST_B_MASK;
294940b45ecSScott Wood
295940b45ecSScott Wood if (imm_one) {
296940b45ecSScott Wood p[kvm_emulate_wrtee_reg_offs] =
297c75df6f9SMichael Neuling KVM_INST_LI | __PPC_RT(R30) | MSR_EE;
298940b45ecSScott Wood } else {
299940b45ecSScott Wood /* Make clobbered registers work too */
300940b45ecSScott Wood switch (get_rt(rt)) {
301940b45ecSScott Wood case 30:
302940b45ecSScott Wood kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
303940b45ecSScott Wood magic_var(scratch2), KVM_RT_30);
304940b45ecSScott Wood break;
305940b45ecSScott Wood case 31:
306940b45ecSScott Wood kvm_patch_ins_ll(&p[kvm_emulate_wrtee_reg_offs],
307940b45ecSScott Wood magic_var(scratch1), KVM_RT_30);
308940b45ecSScott Wood break;
309940b45ecSScott Wood default:
310940b45ecSScott Wood p[kvm_emulate_wrtee_reg_offs] |= rt;
311940b45ecSScott Wood break;
312940b45ecSScott Wood }
313940b45ecSScott Wood }
314940b45ecSScott Wood
315940b45ecSScott Wood p[kvm_emulate_wrtee_orig_ins_offs] = *inst;
316940b45ecSScott Wood flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrtee_len * 4);
317940b45ecSScott Wood
318940b45ecSScott Wood /* Patch the invocation */
319940b45ecSScott Wood kvm_patch_ins_b(inst, distance_start);
320940b45ecSScott Wood }
321940b45ecSScott Wood
322940b45ecSScott Wood extern u32 kvm_emulate_wrteei_0_branch_offs;
323940b45ecSScott Wood extern u32 kvm_emulate_wrteei_0_len;
324940b45ecSScott Wood extern u32 kvm_emulate_wrteei_0[];
325940b45ecSScott Wood
kvm_patch_ins_wrteei_0(u32 * inst)326731dade1SMichael Ellerman static void __init kvm_patch_ins_wrteei_0(u32 *inst)
327940b45ecSScott Wood {
328940b45ecSScott Wood u32 *p;
329940b45ecSScott Wood int distance_start;
330940b45ecSScott Wood int distance_end;
331940b45ecSScott Wood ulong next_inst;
332940b45ecSScott Wood
333940b45ecSScott Wood p = kvm_alloc(kvm_emulate_wrteei_0_len * 4);
334940b45ecSScott Wood if (!p)
335940b45ecSScott Wood return;
336940b45ecSScott Wood
337940b45ecSScott Wood /* Find out where we are and put everything there */
338940b45ecSScott Wood distance_start = (ulong)p - (ulong)inst;
339940b45ecSScott Wood next_inst = ((ulong)inst + 4);
340940b45ecSScott Wood distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_0_branch_offs];
341940b45ecSScott Wood
342940b45ecSScott Wood /* Make sure we only write valid b instructions */
343940b45ecSScott Wood if (distance_start > KVM_INST_B_MAX) {
344940b45ecSScott Wood kvm_patching_worked = false;
345940b45ecSScott Wood return;
346940b45ecSScott Wood }
347940b45ecSScott Wood
348940b45ecSScott Wood memcpy(p, kvm_emulate_wrteei_0, kvm_emulate_wrteei_0_len * 4);
349940b45ecSScott Wood p[kvm_emulate_wrteei_0_branch_offs] |= distance_end & KVM_INST_B_MASK;
350940b45ecSScott Wood flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_0_len * 4);
351644bfa01SAlexander Graf
352644bfa01SAlexander Graf /* Patch the invocation */
353644bfa01SAlexander Graf kvm_patch_ins_b(inst, distance_start);
354644bfa01SAlexander Graf }
355644bfa01SAlexander Graf
356644bfa01SAlexander Graf #endif
357644bfa01SAlexander Graf
358cbe487faSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_32
359cbe487faSAlexander Graf
360cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin_branch_offs;
361cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin_reg1_offs;
362cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin_reg2_offs;
363cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin_orig_ins_offs;
364cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin_len;
365cbe487faSAlexander Graf extern u32 kvm_emulate_mtsrin[];
366cbe487faSAlexander Graf
kvm_patch_ins_mtsrin(u32 * inst,u32 rt,u32 rb)367731dade1SMichael Ellerman static void __init kvm_patch_ins_mtsrin(u32 *inst, u32 rt, u32 rb)
368cbe487faSAlexander Graf {
369cbe487faSAlexander Graf u32 *p;
370cbe487faSAlexander Graf int distance_start;
371cbe487faSAlexander Graf int distance_end;
372cbe487faSAlexander Graf ulong next_inst;
373cbe487faSAlexander Graf
374cbe487faSAlexander Graf p = kvm_alloc(kvm_emulate_mtsrin_len * 4);
375cbe487faSAlexander Graf if (!p)
376cbe487faSAlexander Graf return;
377cbe487faSAlexander Graf
378cbe487faSAlexander Graf /* Find out where we are and put everything there */
379cbe487faSAlexander Graf distance_start = (ulong)p - (ulong)inst;
380cbe487faSAlexander Graf next_inst = ((ulong)inst + 4);
381cbe487faSAlexander Graf distance_end = next_inst - (ulong)&p[kvm_emulate_mtsrin_branch_offs];
382cbe487faSAlexander Graf
383cbe487faSAlexander Graf /* Make sure we only write valid b instructions */
384cbe487faSAlexander Graf if (distance_start > KVM_INST_B_MAX) {
385cbe487faSAlexander Graf kvm_patching_worked = false;
386cbe487faSAlexander Graf return;
387cbe487faSAlexander Graf }
388cbe487faSAlexander Graf
389cbe487faSAlexander Graf /* Modify the chunk to fit the invocation */
390cbe487faSAlexander Graf memcpy(p, kvm_emulate_mtsrin, kvm_emulate_mtsrin_len * 4);
391cbe487faSAlexander Graf p[kvm_emulate_mtsrin_branch_offs] |= distance_end & KVM_INST_B_MASK;
392cbe487faSAlexander Graf p[kvm_emulate_mtsrin_reg1_offs] |= (rb << 10);
393cbe487faSAlexander Graf p[kvm_emulate_mtsrin_reg2_offs] |= rt;
394cbe487faSAlexander Graf p[kvm_emulate_mtsrin_orig_ins_offs] = *inst;
395cbe487faSAlexander Graf flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtsrin_len * 4);
396cbe487faSAlexander Graf
397cbe487faSAlexander Graf /* Patch the invocation */
398cbe487faSAlexander Graf kvm_patch_ins_b(inst, distance_start);
399cbe487faSAlexander Graf }
400cbe487faSAlexander Graf
401cbe487faSAlexander Graf #endif
402cbe487faSAlexander Graf
kvm_map_magic_page(void * data)403731dade1SMichael Ellerman static void __init kvm_map_magic_page(void *data)
40473a18109SAlexander Graf {
4057508e16cSAlexander Graf u32 *features = data;
4067508e16cSAlexander Graf
4071820a8d2SBharat Bhushan ulong in[8] = {0};
4087508e16cSAlexander Graf ulong out[8];
4097508e16cSAlexander Graf
4107508e16cSAlexander Graf in[0] = KVM_MAGIC_PAGE;
4115c165aecSAlexander Graf in[1] = KVM_MAGIC_PAGE | MAGIC_PAGE_FLAG_NOT_MAPPED_NX;
4127508e16cSAlexander Graf
4131820a8d2SBharat Bhushan epapr_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
4147508e16cSAlexander Graf
4157508e16cSAlexander Graf *features = out[0];
41673a18109SAlexander Graf }
41773a18109SAlexander Graf
kvm_check_ins(u32 * inst,u32 features)418731dade1SMichael Ellerman static void __init kvm_check_ins(u32 *inst, u32 features)
41973a18109SAlexander Graf {
42073a18109SAlexander Graf u32 _inst = *inst;
42173a18109SAlexander Graf u32 inst_no_rt = _inst & ~KVM_MASK_RT;
42273a18109SAlexander Graf u32 inst_rt = _inst & KVM_MASK_RT;
42373a18109SAlexander Graf
42473a18109SAlexander Graf switch (inst_no_rt) {
425d1293c92SAlexander Graf /* Loads */
426d1293c92SAlexander Graf case KVM_INST_MFMSR:
427d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
428d1293c92SAlexander Graf break;
429b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG0):
430d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
431d1293c92SAlexander Graf break;
432b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG1):
433d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
434d1293c92SAlexander Graf break;
435b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG2):
436d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
437d1293c92SAlexander Graf break;
438b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG3):
439d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
440d1293c92SAlexander Graf break;
441b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SRR0):
442d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
443d1293c92SAlexander Graf break;
444b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SRR1):
445d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
446d1293c92SAlexander Graf break;
447b5904972SScott Wood #ifdef CONFIG_BOOKE
448b5904972SScott Wood case KVM_INST_MFSPR(SPRN_DEAR):
449b5904972SScott Wood #else
450b5904972SScott Wood case KVM_INST_MFSPR(SPRN_DAR):
451b5904972SScott Wood #endif
452d1293c92SAlexander Graf kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
453d1293c92SAlexander Graf break;
454b5904972SScott Wood case KVM_INST_MFSPR(SPRN_DSISR):
455d1293c92SAlexander Graf kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
456d1293c92SAlexander Graf break;
457d1293c92SAlexander Graf
458*aa5f59dfSChristophe Leroy #ifdef CONFIG_PPC_E500
459b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS0):
460b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
461b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas0), inst_rt);
462b5904972SScott Wood break;
463b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS1):
464b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
465b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas1), inst_rt);
466b5904972SScott Wood break;
467b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS2):
468b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
469b5904972SScott Wood kvm_patch_ins_ld(inst, magic_var(mas2), inst_rt);
470b5904972SScott Wood break;
471b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS3):
472b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
473b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas7_3) + 4, inst_rt);
474b5904972SScott Wood break;
475b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS4):
476b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
477b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas4), inst_rt);
478b5904972SScott Wood break;
479b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS6):
480b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
481b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas6), inst_rt);
482b5904972SScott Wood break;
483b5904972SScott Wood case KVM_INST_MFSPR(SPRN_MAS7):
484b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
485b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(mas7_3), inst_rt);
486b5904972SScott Wood break;
487*aa5f59dfSChristophe Leroy #endif /* CONFIG_PPC_E500 */
488b5904972SScott Wood
489b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG4):
490b5904972SScott Wood #ifdef CONFIG_BOOKE
491b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG4R):
492b5904972SScott Wood #endif
493b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
494b5904972SScott Wood kvm_patch_ins_ld(inst, magic_var(sprg4), inst_rt);
495b5904972SScott Wood break;
496b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG5):
497b5904972SScott Wood #ifdef CONFIG_BOOKE
498b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG5R):
499b5904972SScott Wood #endif
500b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
501b5904972SScott Wood kvm_patch_ins_ld(inst, magic_var(sprg5), inst_rt);
502b5904972SScott Wood break;
503b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG6):
504b5904972SScott Wood #ifdef CONFIG_BOOKE
505b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG6R):
506b5904972SScott Wood #endif
507b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
508b5904972SScott Wood kvm_patch_ins_ld(inst, magic_var(sprg6), inst_rt);
509b5904972SScott Wood break;
510b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG7):
511b5904972SScott Wood #ifdef CONFIG_BOOKE
512b5904972SScott Wood case KVM_INST_MFSPR(SPRN_SPRG7R):
513b5904972SScott Wood #endif
514b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
515b5904972SScott Wood kvm_patch_ins_ld(inst, magic_var(sprg7), inst_rt);
516b5904972SScott Wood break;
517b5904972SScott Wood
518b5904972SScott Wood #ifdef CONFIG_BOOKE
519b5904972SScott Wood case KVM_INST_MFSPR(SPRN_ESR):
520b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
521b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(esr), inst_rt);
522b5904972SScott Wood break;
523b5904972SScott Wood #endif
524b5904972SScott Wood
525b5904972SScott Wood case KVM_INST_MFSPR(SPRN_PIR):
526b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
527b5904972SScott Wood kvm_patch_ins_lwz(inst, magic_var(pir), inst_rt);
528b5904972SScott Wood break;
529b5904972SScott Wood
530b5904972SScott Wood
531d1293c92SAlexander Graf /* Stores */
532b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG0):
533d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
534d1293c92SAlexander Graf break;
535b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG1):
536d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
537d1293c92SAlexander Graf break;
538b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG2):
539d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
540d1293c92SAlexander Graf break;
541b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG3):
542d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
543d1293c92SAlexander Graf break;
544b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SRR0):
545d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
546d1293c92SAlexander Graf break;
547b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SRR1):
548d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
549d1293c92SAlexander Graf break;
550b5904972SScott Wood #ifdef CONFIG_BOOKE
551b5904972SScott Wood case KVM_INST_MTSPR(SPRN_DEAR):
552b5904972SScott Wood #else
553b5904972SScott Wood case KVM_INST_MTSPR(SPRN_DAR):
554b5904972SScott Wood #endif
555d1293c92SAlexander Graf kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
556d1293c92SAlexander Graf break;
557b5904972SScott Wood case KVM_INST_MTSPR(SPRN_DSISR):
558d1293c92SAlexander Graf kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
559d1293c92SAlexander Graf break;
560*aa5f59dfSChristophe Leroy #ifdef CONFIG_PPC_E500
561b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS0):
562b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
563b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas0), inst_rt);
564b5904972SScott Wood break;
565b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS1):
566b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
567b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas1), inst_rt);
568b5904972SScott Wood break;
569b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS2):
570b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
571b5904972SScott Wood kvm_patch_ins_std(inst, magic_var(mas2), inst_rt);
572b5904972SScott Wood break;
573b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS3):
574b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
575b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas7_3) + 4, inst_rt);
576b5904972SScott Wood break;
577b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS4):
578b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
579b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas4), inst_rt);
580b5904972SScott Wood break;
581b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS6):
582b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
583b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas6), inst_rt);
584b5904972SScott Wood break;
585b5904972SScott Wood case KVM_INST_MTSPR(SPRN_MAS7):
586b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
587b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(mas7_3), inst_rt);
588b5904972SScott Wood break;
589*aa5f59dfSChristophe Leroy #endif /* CONFIG_PPC_E500 */
590b5904972SScott Wood
591b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG4):
592b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
593b5904972SScott Wood kvm_patch_ins_std(inst, magic_var(sprg4), inst_rt);
594b5904972SScott Wood break;
595b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG5):
596b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
597b5904972SScott Wood kvm_patch_ins_std(inst, magic_var(sprg5), inst_rt);
598b5904972SScott Wood break;
599b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG6):
600b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
601b5904972SScott Wood kvm_patch_ins_std(inst, magic_var(sprg6), inst_rt);
602b5904972SScott Wood break;
603b5904972SScott Wood case KVM_INST_MTSPR(SPRN_SPRG7):
604b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
605b5904972SScott Wood kvm_patch_ins_std(inst, magic_var(sprg7), inst_rt);
606b5904972SScott Wood break;
607b5904972SScott Wood
608b5904972SScott Wood #ifdef CONFIG_BOOKE
609b5904972SScott Wood case KVM_INST_MTSPR(SPRN_ESR):
610b5904972SScott Wood if (features & KVM_MAGIC_FEAT_MAS0_TO_SPRG7)
611b5904972SScott Wood kvm_patch_ins_stw(inst, magic_var(esr), inst_rt);
612b5904972SScott Wood break;
613b5904972SScott Wood #endif
614d1290b15SAlexander Graf
615d1290b15SAlexander Graf /* Nops */
616d1290b15SAlexander Graf case KVM_INST_TLBSYNC:
617d1290b15SAlexander Graf kvm_patch_ins_nop(inst);
618d1290b15SAlexander Graf break;
619819a63dcSAlexander Graf
620819a63dcSAlexander Graf /* Rewrites */
621819a63dcSAlexander Graf case KVM_INST_MTMSRD_L1:
622819a63dcSAlexander Graf kvm_patch_ins_mtmsrd(inst, inst_rt);
623819a63dcSAlexander Graf break;
62478109277SAlexander Graf case KVM_INST_MTMSR:
62578109277SAlexander Graf case KVM_INST_MTMSRD_L0:
62678109277SAlexander Graf kvm_patch_ins_mtmsr(inst, inst_rt);
62778109277SAlexander Graf break;
628940b45ecSScott Wood #ifdef CONFIG_BOOKE
629940b45ecSScott Wood case KVM_INST_WRTEE:
630940b45ecSScott Wood kvm_patch_ins_wrtee(inst, inst_rt, 0);
631940b45ecSScott Wood break;
632940b45ecSScott Wood #endif
63373a18109SAlexander Graf }
63473a18109SAlexander Graf
635cbe487faSAlexander Graf switch (inst_no_rt & ~KVM_MASK_RB) {
636cbe487faSAlexander Graf #ifdef CONFIG_PPC_BOOK3S_32
637cbe487faSAlexander Graf case KVM_INST_MTSRIN:
638cbe487faSAlexander Graf if (features & KVM_MAGIC_FEAT_SR) {
639cbe487faSAlexander Graf u32 inst_rb = _inst & KVM_MASK_RB;
640cbe487faSAlexander Graf kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb);
641cbe487faSAlexander Graf }
642cbe487faSAlexander Graf break;
643cbe487faSAlexander Graf #endif
644cbe487faSAlexander Graf }
645cbe487faSAlexander Graf
64673a18109SAlexander Graf switch (_inst) {
647644bfa01SAlexander Graf #ifdef CONFIG_BOOKE
648644bfa01SAlexander Graf case KVM_INST_WRTEEI_0:
649940b45ecSScott Wood kvm_patch_ins_wrteei_0(inst);
650940b45ecSScott Wood break;
651940b45ecSScott Wood
652644bfa01SAlexander Graf case KVM_INST_WRTEEI_1:
653940b45ecSScott Wood kvm_patch_ins_wrtee(inst, 0, 1);
654644bfa01SAlexander Graf break;
655644bfa01SAlexander Graf #endif
65673a18109SAlexander Graf }
65773a18109SAlexander Graf }
65873a18109SAlexander Graf
659befdc0a6SLiu Yu-B13201 extern u32 kvm_template_start[];
660befdc0a6SLiu Yu-B13201 extern u32 kvm_template_end[];
661befdc0a6SLiu Yu-B13201
kvm_use_magic_page(void)662731dade1SMichael Ellerman static void __init kvm_use_magic_page(void)
66373a18109SAlexander Graf {
66473a18109SAlexander Graf u32 *p;
66573a18109SAlexander Graf u32 *start, *end;
6667508e16cSAlexander Graf u32 features;
66773a18109SAlexander Graf
66873a18109SAlexander Graf /* Tell the host to map the magic page to -4096 on all CPUs */
6697508e16cSAlexander Graf on_each_cpu(kvm_map_magic_page, &features, 1);
67073a18109SAlexander Graf
67173a18109SAlexander Graf /* Quick self-test to see if the mapping works */
672bb523b40SAndreas Gruenbacher if (fault_in_readable((const char __user *)KVM_MAGIC_PAGE,
673bb523b40SAndreas Gruenbacher sizeof(u32))) {
67473a18109SAlexander Graf kvm_patching_worked = false;
67573a18109SAlexander Graf return;
67673a18109SAlexander Graf }
67773a18109SAlexander Graf
67873a18109SAlexander Graf /* Now loop through all code and find instructions */
67973a18109SAlexander Graf start = (void*)_stext;
68073a18109SAlexander Graf end = (void*)_etext;
68173a18109SAlexander Graf
682b5904972SScott Wood /*
683b5904972SScott Wood * Being interrupted in the middle of patching would
684b5904972SScott Wood * be bad for SPRG4-7, which KVM can't keep in sync
685b5904972SScott Wood * with emulated accesses because reads don't trap.
686b5904972SScott Wood */
687b5904972SScott Wood local_irq_disable();
688b5904972SScott Wood
689befdc0a6SLiu Yu-B13201 for (p = start; p < end; p++) {
690befdc0a6SLiu Yu-B13201 /* Avoid patching the template code */
691befdc0a6SLiu Yu-B13201 if (p >= kvm_template_start && p < kvm_template_end) {
692befdc0a6SLiu Yu-B13201 p = kvm_template_end - 1;
693befdc0a6SLiu Yu-B13201 continue;
694befdc0a6SLiu Yu-B13201 }
6957508e16cSAlexander Graf kvm_check_ins(p, features);
696befdc0a6SLiu Yu-B13201 }
69773a18109SAlexander Graf
698b5904972SScott Wood local_irq_enable();
699b5904972SScott Wood
70073a18109SAlexander Graf printk(KERN_INFO "KVM: Live patching for a fast VM %s\n",
70173a18109SAlexander Graf kvm_patching_worked ? "worked" : "failed");
70273a18109SAlexander Graf }
70373a18109SAlexander Graf
kvm_guest_init(void)70473a18109SAlexander Graf static int __init kvm_guest_init(void)
70573a18109SAlexander Graf {
70673a18109SAlexander Graf if (!kvm_para_available())
7070cb0837fSMichael Ellerman return 0;
70873a18109SAlexander Graf
7092e1ae9c0SLiu Yu-B13201 if (!epapr_paravirt_enabled)
7100cb0837fSMichael Ellerman return 0;
71173a18109SAlexander Graf
71273a18109SAlexander Graf if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE))
71373a18109SAlexander Graf kvm_use_magic_page();
71473a18109SAlexander Graf
715591bd8e7SAlexander Graf #ifdef CONFIG_PPC_BOOK3S_64
716ad087376SAlexander Graf /* Enable napping */
717ad087376SAlexander Graf powersave_nap = 1;
718591bd8e7SAlexander Graf #endif
719ad087376SAlexander Graf
72073a18109SAlexander Graf return 0;
72173a18109SAlexander Graf }
72273a18109SAlexander Graf
72373a18109SAlexander Graf postcore_initcall(kvm_guest_init);
724