aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2013-06-21 06:57:56 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2014-07-11 07:57:36 -0400
commit1a9b13056dde7e3092304d6041ccc60a913042ea (patch)
tree3e70b5ee93eb9c0bbc8271b240a19cf69a605bb2 /arch/arm64
parent45451914c875bba44903ce4f1445e047b7992bf7 (diff)
arm64: KVM: split GICv2 world switch from hyp code
Move the GICv2 world switch code into its own file, and add the necessary indirection to the arm64 switch code. Also introduce a new type field to the vgic_params structure. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/include/asm/kvm_asm.h4
-rw-r--r--arch/arm64/include/asm/kvm_host.h21
-rw-r--r--arch/arm64/kernel/asm-offsets.c3
-rw-r--r--arch/arm64/kvm/Makefile4
-rw-r--r--arch/arm64/kvm/hyp.S104
-rw-r--r--arch/arm64/kvm/vgic-v2-switch.S133
6 files changed, 180 insertions, 89 deletions
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index d0bfc4ba82c0..6252264341c8 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -105,6 +105,10 @@ extern void __kvm_flush_vm_context(void);
105extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa); 105extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
106 106
107extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); 107extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
108
109extern char __save_vgic_v2_state[];
110extern char __restore_vgic_v2_state[];
111
108#endif 112#endif
109 113
110#endif /* __ARM_KVM_ASM_H__ */ 114#endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 92242ce06309..4c182d0aae70 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -200,4 +200,25 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
200 hyp_stack_ptr, vector_ptr); 200 hyp_stack_ptr, vector_ptr);
201} 201}
202 202
203struct vgic_sr_vectors {
204 void *save_vgic;
205 void *restore_vgic;
206};
207
208static inline void vgic_arch_setup(const struct vgic_params *vgic)
209{
210 extern struct vgic_sr_vectors __vgic_sr_vectors;
211
212 switch(vgic->type)
213 {
214 case VGIC_V2:
215 __vgic_sr_vectors.save_vgic = __save_vgic_v2_state;
216 __vgic_sr_vectors.restore_vgic = __restore_vgic_v2_state;
217 break;
218
219 default:
220 BUG();
221 }
222}
223
203#endif /* __ARM64_KVM_HOST_H__ */ 224#endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 20fd4887aab6..dafc415dd52d 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -129,6 +129,9 @@ int main(void)
129 DEFINE(KVM_TIMER_ENABLED, offsetof(struct kvm, arch.timer.enabled)); 129 DEFINE(KVM_TIMER_ENABLED, offsetof(struct kvm, arch.timer.enabled));
130 DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm)); 130 DEFINE(VCPU_KVM, offsetof(struct kvm_vcpu, kvm));
131 DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu)); 131 DEFINE(VCPU_VGIC_CPU, offsetof(struct kvm_vcpu, arch.vgic_cpu));
132 DEFINE(VGIC_SAVE_FN, offsetof(struct vgic_sr_vectors, save_vgic));
133 DEFINE(VGIC_RESTORE_FN, offsetof(struct vgic_sr_vectors, restore_vgic));
134 DEFINE(VGIC_SR_VECTOR_SZ, sizeof(struct vgic_sr_vectors));
132 DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr)); 135 DEFINE(VGIC_V2_CPU_HCR, offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
133 DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr)); 136 DEFINE(VGIC_V2_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
134 DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr)); 137 DEFINE(VGIC_V2_CPU_MISR, offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 7e92952d139e..daf24dc59e2c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -19,5 +19,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o inject_fault.o regmap.o
19kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o 19kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
20kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o 20kvm-$(CONFIG_KVM_ARM_HOST) += guest.o reset.o sys_regs.o sys_regs_generic_v8.o
21 21
22kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o $(KVM)/arm/vgic-v2.o 22kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic.o
23kvm-$(CONFIG_KVM_ARM_VGIC) += $(KVM)/arm/vgic-v2.o
24kvm-$(CONFIG_KVM_ARM_VGIC) += vgic-v2-switch.o
23kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o 25kvm-$(CONFIG_KVM_ARM_TIMER) += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 9c5d0acb3654..56df9a352a81 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -16,7 +16,6 @@
16 */ 16 */
17 17
18#include <linux/linkage.h> 18#include <linux/linkage.h>
19#include <linux/irqchip/arm-gic.h>
20 19
21#include <asm/assembler.h> 20#include <asm/assembler.h>
22#include <asm/memory.h> 21#include <asm/memory.h>
@@ -376,100 +375,23 @@
376.endm 375.endm
377 376
378/* 377/*
379 * Save the VGIC CPU state into memory 378 * Call into the vgic backend for state saving
380 * x0: Register pointing to VCPU struct
381 * Do not corrupt x1!!!
382 */ 379 */
383.macro save_vgic_state 380.macro save_vgic_state
384 /* Get VGIC VCTRL base into x2 */ 381 adr x24, __vgic_sr_vectors
385 ldr x2, [x0, #VCPU_KVM] 382 ldr x24, [x24, VGIC_SAVE_FN]
386 kern_hyp_va x2 383 kern_hyp_va x24
387 ldr x2, [x2, #KVM_VGIC_VCTRL] 384 blr x24
388 kern_hyp_va x2
389 cbz x2, 2f // disabled
390
391 /* Compute the address of struct vgic_cpu */
392 add x3, x0, #VCPU_VGIC_CPU
393
394 /* Save all interesting registers */
395 ldr w4, [x2, #GICH_HCR]
396 ldr w5, [x2, #GICH_VMCR]
397 ldr w6, [x2, #GICH_MISR]
398 ldr w7, [x2, #GICH_EISR0]
399 ldr w8, [x2, #GICH_EISR1]
400 ldr w9, [x2, #GICH_ELRSR0]
401 ldr w10, [x2, #GICH_ELRSR1]
402 ldr w11, [x2, #GICH_APR]
403CPU_BE( rev w4, w4 )
404CPU_BE( rev w5, w5 )
405CPU_BE( rev w6, w6 )
406CPU_BE( rev w7, w7 )
407CPU_BE( rev w8, w8 )
408CPU_BE( rev w9, w9 )
409CPU_BE( rev w10, w10 )
410CPU_BE( rev w11, w11 )
411
412 str w4, [x3, #VGIC_V2_CPU_HCR]
413 str w5, [x3, #VGIC_V2_CPU_VMCR]
414 str w6, [x3, #VGIC_V2_CPU_MISR]
415 str w7, [x3, #VGIC_V2_CPU_EISR]
416 str w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
417 str w9, [x3, #VGIC_V2_CPU_ELRSR]
418 str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
419 str w11, [x3, #VGIC_V2_CPU_APR]
420
421 /* Clear GICH_HCR */
422 str wzr, [x2, #GICH_HCR]
423
424 /* Save list registers */
425 add x2, x2, #GICH_LR0
426 ldr w4, [x3, #VGIC_CPU_NR_LR]
427 add x3, x3, #VGIC_V2_CPU_LR
4281: ldr w5, [x2], #4
429CPU_BE( rev w5, w5 )
430 str w5, [x3], #4
431 sub w4, w4, #1
432 cbnz w4, 1b
4332:
434.endm 385.endm
435 386
436/* 387/*
437 * Restore the VGIC CPU state from memory 388 * Call into the vgic backend for state restoring
438 * x0: Register pointing to VCPU struct
439 */ 389 */
440.macro restore_vgic_state 390.macro restore_vgic_state
441 /* Get VGIC VCTRL base into x2 */ 391 adr x24, __vgic_sr_vectors
442 ldr x2, [x0, #VCPU_KVM] 392 ldr x24, [x24, #VGIC_RESTORE_FN]
443 kern_hyp_va x2 393 kern_hyp_va x24
444 ldr x2, [x2, #KVM_VGIC_VCTRL] 394 blr x24
445 kern_hyp_va x2
446 cbz x2, 2f // disabled
447
448 /* Compute the address of struct vgic_cpu */
449 add x3, x0, #VCPU_VGIC_CPU
450
451 /* We only restore a minimal set of registers */
452 ldr w4, [x3, #VGIC_V2_CPU_HCR]
453 ldr w5, [x3, #VGIC_V2_CPU_VMCR]
454 ldr w6, [x3, #VGIC_V2_CPU_APR]
455CPU_BE( rev w4, w4 )
456CPU_BE( rev w5, w5 )
457CPU_BE( rev w6, w6 )
458
459 str w4, [x2, #GICH_HCR]
460 str w5, [x2, #GICH_VMCR]
461 str w6, [x2, #GICH_APR]
462
463 /* Restore list registers */
464 add x2, x2, #GICH_LR0
465 ldr w4, [x3, #VGIC_CPU_NR_LR]
466 add x3, x3, #VGIC_V2_CPU_LR
4671: ldr w5, [x3], #4
468CPU_BE( rev w5, w5 )
469 str w5, [x2], #4
470 sub w4, w4, #1
471 cbnz w4, 1b
4722:
473.endm 395.endm
474 396
475.macro save_timer_state 397.macro save_timer_state
@@ -650,6 +572,12 @@ ENTRY(__kvm_flush_vm_context)
650 ret 572 ret
651ENDPROC(__kvm_flush_vm_context) 573ENDPROC(__kvm_flush_vm_context)
652 574
575 // struct vgic_sr_vectors __vgi_sr_vectors;
576 .align 3
577ENTRY(__vgic_sr_vectors)
578 .skip VGIC_SR_VECTOR_SZ
579ENDPROC(__vgic_sr_vectors)
580
653__kvm_hyp_panic: 581__kvm_hyp_panic:
654 // Guess the context by looking at VTTBR: 582 // Guess the context by looking at VTTBR:
655 // If zero, then we're already a host. 583 // If zero, then we're already a host.
diff --git a/arch/arm64/kvm/vgic-v2-switch.S b/arch/arm64/kvm/vgic-v2-switch.S
new file mode 100644
index 000000000000..ae211772f991
--- /dev/null
+++ b/arch/arm64/kvm/vgic-v2-switch.S
@@ -0,0 +1,133 @@
1/*
2 * Copyright (C) 2012,2013 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/linkage.h>
19#include <linux/irqchip/arm-gic.h>
20
21#include <asm/assembler.h>
22#include <asm/memory.h>
23#include <asm/asm-offsets.h>
24#include <asm/kvm.h>
25#include <asm/kvm_asm.h>
26#include <asm/kvm_arm.h>
27#include <asm/kvm_mmu.h>
28
29 .text
30 .pushsection .hyp.text, "ax"
31
32/*
33 * Save the VGIC CPU state into memory
34 * x0: Register pointing to VCPU struct
35 * Do not corrupt x1!!!
36 */
37ENTRY(__save_vgic_v2_state)
38__save_vgic_v2_state:
39 /* Get VGIC VCTRL base into x2 */
40 ldr x2, [x0, #VCPU_KVM]
41 kern_hyp_va x2
42 ldr x2, [x2, #KVM_VGIC_VCTRL]
43 kern_hyp_va x2
44 cbz x2, 2f // disabled
45
46 /* Compute the address of struct vgic_cpu */
47 add x3, x0, #VCPU_VGIC_CPU
48
49 /* Save all interesting registers */
50 ldr w4, [x2, #GICH_HCR]
51 ldr w5, [x2, #GICH_VMCR]
52 ldr w6, [x2, #GICH_MISR]
53 ldr w7, [x2, #GICH_EISR0]
54 ldr w8, [x2, #GICH_EISR1]
55 ldr w9, [x2, #GICH_ELRSR0]
56 ldr w10, [x2, #GICH_ELRSR1]
57 ldr w11, [x2, #GICH_APR]
58CPU_BE( rev w4, w4 )
59CPU_BE( rev w5, w5 )
60CPU_BE( rev w6, w6 )
61CPU_BE( rev w7, w7 )
62CPU_BE( rev w8, w8 )
63CPU_BE( rev w9, w9 )
64CPU_BE( rev w10, w10 )
65CPU_BE( rev w11, w11 )
66
67 str w4, [x3, #VGIC_V2_CPU_HCR]
68 str w5, [x3, #VGIC_V2_CPU_VMCR]
69 str w6, [x3, #VGIC_V2_CPU_MISR]
70 str w7, [x3, #VGIC_V2_CPU_EISR]
71 str w8, [x3, #(VGIC_V2_CPU_EISR + 4)]
72 str w9, [x3, #VGIC_V2_CPU_ELRSR]
73 str w10, [x3, #(VGIC_V2_CPU_ELRSR + 4)]
74 str w11, [x3, #VGIC_V2_CPU_APR]
75
76 /* Clear GICH_HCR */
77 str wzr, [x2, #GICH_HCR]
78
79 /* Save list registers */
80 add x2, x2, #GICH_LR0
81 ldr w4, [x3, #VGIC_CPU_NR_LR]
82 add x3, x3, #VGIC_V2_CPU_LR
831: ldr w5, [x2], #4
84CPU_BE( rev w5, w5 )
85 str w5, [x3], #4
86 sub w4, w4, #1
87 cbnz w4, 1b
882:
89 ret
90ENDPROC(__save_vgic_v2_state)
91
92/*
93 * Restore the VGIC CPU state from memory
94 * x0: Register pointing to VCPU struct
95 */
96ENTRY(__restore_vgic_v2_state)
97__restore_vgic_v2_state:
98 /* Get VGIC VCTRL base into x2 */
99 ldr x2, [x0, #VCPU_KVM]
100 kern_hyp_va x2
101 ldr x2, [x2, #KVM_VGIC_VCTRL]
102 kern_hyp_va x2
103 cbz x2, 2f // disabled
104
105 /* Compute the address of struct vgic_cpu */
106 add x3, x0, #VCPU_VGIC_CPU
107
108 /* We only restore a minimal set of registers */
109 ldr w4, [x3, #VGIC_V2_CPU_HCR]
110 ldr w5, [x3, #VGIC_V2_CPU_VMCR]
111 ldr w6, [x3, #VGIC_V2_CPU_APR]
112CPU_BE( rev w4, w4 )
113CPU_BE( rev w5, w5 )
114CPU_BE( rev w6, w6 )
115
116 str w4, [x2, #GICH_HCR]
117 str w5, [x2, #GICH_VMCR]
118 str w6, [x2, #GICH_APR]
119
120 /* Restore list registers */
121 add x2, x2, #GICH_LR0
122 ldr w4, [x3, #VGIC_CPU_NR_LR]
123 add x3, x3, #VGIC_V2_CPU_LR
1241: ldr w5, [x3], #4
125CPU_BE( rev w5, w5 )
126 str w5, [x2], #4
127 sub w4, w4, #1
128 cbnz w4, 1b
1292:
130 ret
131ENDPROC(__restore_vgic_v2_state)
132
133 .popsection