arm64: KVM: split GICv2 world switch from hyp code
[firefly-linux-kernel-4.4.55.git] / arch / arm64 / kvm / vgic-v2-switch.S
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  */
37 ENTRY(__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]
58 CPU_BE( rev     w4,  w4  )
59 CPU_BE( rev     w5,  w5  )
60 CPU_BE( rev     w6,  w6  )
61 CPU_BE( rev     w7,  w7  )
62 CPU_BE( rev     w8,  w8  )
63 CPU_BE( rev     w9,  w9  )
64 CPU_BE( rev     w10, w10 )
65 CPU_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
83 1:      ldr     w5, [x2], #4
84 CPU_BE( rev     w5, w5 )
85         str     w5, [x3], #4
86         sub     w4, w4, #1
87         cbnz    w4, 1b
88 2:
89         ret
90 ENDPROC(__save_vgic_v2_state)
91
92 /*
93  * Restore the VGIC CPU state from memory
94  * x0: Register pointing to VCPU struct
95  */
96 ENTRY(__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]
112 CPU_BE( rev     w4, w4 )
113 CPU_BE( rev     w5, w5 )
114 CPU_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
124 1:      ldr     w5, [x3], #4
125 CPU_BE( rev     w5, w5 )
126         str     w5, [x2], #4
127         sub     w4, w4, #1
128         cbnz    w4, 1b
129 2:
130         ret
131 ENDPROC(__restore_vgic_v2_state)
132
133         .popsection