aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kvm
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/kvm
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/kvm')
-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
3 files changed, 152 insertions, 89 deletions
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