1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <config.h>
8
9#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
10
11#include <machine/assembler.h>
12#include <sel4/sel4_arch/constants.h>
13
14/*** Hypervisor coprocessor registers ***/
15#define   HVBAR(reg)    p15, 4, reg, c12, c0, 0
16#define     HCR(reg)    p15, 4, reg, c1 , c1, 0
17#define  HSCTLR(reg)    p15, 4, reg, c1 , c0, 0
18#define  HACTLR(reg)    p15, 4, reg, c1 , c0, 1
19#define    HDCR(reg)    p15, 4, reg, c1 , c1, 1
20#define   HCPTR(reg)    p15, 4, reg, c1 , c1, 2
21#define    HSTR(reg)    p15, 4, reg, c1 , c1, 3
22#define    HACR(reg)    p15, 4, reg, c1 , c1, 7
23#define    HTCR(reg)    p15, 4, reg, c2 , c0, 2
24#define  HADFSR(reg)    p15, 4, reg, c5 , c1, 0
25#define  HAIFSR(reg)    p15, 4, reg, c5 , c1, 1
26#define     HSR(reg)    p15, 4, reg, c5 , c2, 0
27#define   HDFAR(reg)    p15, 4, reg, c6 , c0, 0
28#define   HIFAR(reg)    p15, 4, reg, c6 , c0, 2
29#define   HPFAR(reg)    p15, 4, reg, c6 , c0, 4
30#define  HMAIR0(reg)    p15, 4, reg, c10, c2, 0
31#define  HMAIR1(reg)    p15, 4, reg, c10, c2, 1
32#define HAMAIR0(reg)    p15, 4, reg, c10, c3, 0
33#define HAMAIR1(reg)    p15, 4, reg, c10, c3, 1
34#define  HTPIDR(reg)    p15, 4, reg, c13, c0, 2
35#define   HTTBR(rh,rl)  p15, 4, rl, rh, c2
36
37/*** VMM coprocessor registers ***/
38#define    VTCR(reg)    p15, 4, reg, c2 , c1, 2
39#define   VTTBR(rh,rl)  p15, 6, rl, rh, c2
40
41
42#define  DTLBIALL(reg) p15, 0, reg, c8, c6, 0
43#define   TLBIALL(reg) p15, 0, reg, c8, c7, 0
44#define DTLBIASID(reg) p15, 0, reg, c8, c6, 2
45#define  TLBIASID(reg) p15, 0, reg, c8, c7, 2
46
47/*** Hyp mode TLB maintenance ***/
48/* Invalidate entire Hyp unified TLB Inner Shareable */
49#define TLBIALLHIS()     p15, 4,  r0, c8, c7, 0
50/* Invalidate Hyp unified TLB entry by MVA Inner Shareable MVA */
51#define TLBIMVAHIS(mva)  p15, 4, mva, c8, c7, 0
52/* Invalidate entire Non-secure Non-Hyp unified TLB Inner Shareable */
53#define TLBIALLNSNHIS()  p15, 4,  r0, c8, c7, 0
54/* Invalidate entire Hyp unified TLB */
55#define TLBIALLH()       p15, 4,  r0, c8, c7, 0
56/* Invalidate Hyp unified TLB entry by MVA */
57#define TLBIMVAH(mva)    p15, 4, mva, c8, c7, 0
58/* Invalidate entire Non-secure Non-Hyp unified TLB  */
59#define TLBIALLNSNH()    p15, 4,  r0, c8, c7, 0
60
61.code 32
62.section .vectors, "ax"
63BEGIN_FUNC(arm_vector_table)
64    ldr pc, =arm_hyp_reset_exception
65    ldr pc, =arm_hyp_undefined_inst_exception
66    ldr pc, =arm_hyp_syscall
67    ldr pc, =arm_hyp_prefetch_abort_exception
68    ldr pc, =arm_hyp_data_abort_exception
69    ldr pc, =arm_hyp_trap
70    ldr pc, =arm_hyp_irq_exception
71    ldr pc, =arm_hyp_fiq_exception
72END_FUNC(arm_vector_table)
73
74.ltorg
75
76.section .vectors.text, "ax"
77
78#include <arch/api/syscall.h>
79#include <arch/machine/hardware.h>
80
81#include <arch/machine/registerset.h>
82
83#define HSREC_SHIFT          26
84#define HSREC_MASK           (0x3f << HSREC_SHIFT)
85#define HSREC_UNKNOWN        0x00
86#define HSREC_WFI            0x01
87#define HSREC_SVC            0x11
88#define HSREC_HVC            0x12
89#define HSREC_SMC            0x13
90#define HSREC_PREFETCH_ABORT 0x20
91#define HSREC_DATA_ABORT     0x24
92#define HSRIL32              (1 << 25)
93
94.macro EX_ENTRY
95    /* Create some scratch space */
96    push {lr}
97    /* Store ELR */
98    mrs lr, elr_hyp
99    str lr, [sp, #4]
100    /* Store SPSR */
101    mrs lr, spsr_hyp
102    str lr, [sp, #8]
103    /* Store SP_usr */
104    mrs lr, sp_usr
105    push {lr}
106.endm
107
108/* Prepare to enter the kernel */
109.macro PUSH_STACK
110    /* store FaultIP */
111    str lr, [sp, #(PT_FaultIP - PT_SP)]
112    /* Stack all user registers */
113    push {r0-r12}
114    /* Load the kernel's real stack pointer */
115    /* the hyp mode uses HTPIDR */
116    mrc p15, 4, sp, c13, c0, 2
117.endm
118
119/********************************
120 ***  Traps taken to HYP mode ***
121 ********************************/
122
123BEGIN_FUNC(arm_hyp_trap)
124    EX_ENTRY
125
126    /* ARM_ARM B3.13.6 */
127    mrc HSR(lr)
128    and lr, lr, #(HSREC_MASK)
129    cmp lr, #(HSREC_SVC << HSREC_SHIFT)
130    beq arm_syscall
131    cmp lr, #(HSREC_HVC << HSREC_SHIFT)
132    beq arm_syscall
133    cmp lr, #(HSREC_PREFETCH_ABORT << HSREC_SHIFT)
134    beq arm_prefetch_abort
135    cmp lr, #(HSREC_DATA_ABORT << HSREC_SHIFT)
136    beq arm_data_abort
137    cmp lr, #(HSREC_UNKNOWN << HSREC_SHIFT)
138    beq arm_undefined_inst
139
140    /** Everything else is assumed to be a VCPU trap **/
141    mrs lr, elr_hyp
142    PUSH_STACK
143    mrc HSR(r0)
144    b c_handle_vcpu_fault
145END_FUNC(arm_hyp_trap)
146
147
148BEGIN_FUNC(arm_undefined_inst)
149    mrs lr, elr_hyp
150    PUSH_STACK
151    b c_handle_undefined_instruction
152END_FUNC(arm_undefined_inst)
153
154BEGIN_FUNC(arm_prefetch_abort)
155    mrs lr, elr_hyp
156    PUSH_STACK
157    b c_handle_instruction_fault
158END_FUNC(arm_prefetch_abort)
159
160BEGIN_FUNC(arm_data_abort)
161    mrs lr, elr_hyp
162    PUSH_STACK
163    b c_handle_data_fault
164END_FUNC(arm_data_abort)
165
166BEGIN_FUNC(arm_syscall)
167    mrs lr, elr_hyp
168    sub lr, lr, #4
169    PUSH_STACK
170    /* r0: cptr, r1: msgInfo, r2: syscallNo */
171    mov r2, r7
172    b c_handle_syscall
173END_FUNC(arm_syscall)
174
175/*********************************
176 *** Traps taken from HYP mode ***
177 *********************************/
178
179BEGIN_FUNC(arm_hyp_prefetch_abort_exception)
180#ifdef DEBUG
181    mrc p15, 4, sp, c13, c0, 2
182    mrs r0, elr_hyp
183    blx kernelPrefetchAbort
184#endif
185    mrc HSR(r9)    /* Get Hype Syndrome Register. */
186    mrc HIFAR(r10) /* Get fault address register. */
1871: b 1b
188END_FUNC(arm_hyp_prefetch_abort_exception)
189
190BEGIN_FUNC(arm_hyp_data_abort_exception)
191#ifdef DEBUG
192    mrc p15, 4, sp, c13, c0, 2
193    mrs r0, elr_hyp
194    blx kernelDataAbort
195#endif
196    mrc HSR(r9)    /* Get Hype Syndrome Register. */
197    mrc HDFAR(r10) /* Get fault address register. */
1981: b 1b
199END_FUNC(arm_hyp_data_abort_exception)
200
201BEGIN_FUNC(arm_hyp_undefined_inst_exception)
202#ifdef DEBUG
203    mrc p15, 4, sp, c13, c0, 2
204    mrs r0, elr_hyp
205    blx kernelUndefinedInstruction
206#endif
207    mrc HSR(r9)    /* Get Hype Syndrome Register. */
208    mrc HIFAR(r10) /* Get fault address register. */
2091: b 1b
210END_FUNC(arm_hyp_undefined_inst_exception)
211
212BEGIN_FUNC(arm_hyp_syscall)
213    b arm_hyp_undefined_inst_exception
214END_FUNC(arm_hyp_syscall)
215
216/************************
217 *** Other exceptions ***
218 ************************/
219
220BEGIN_FUNC(arm_hyp_irq_exception)
221    EX_ENTRY
222    mrs lr, elr_hyp
223    PUSH_STACK
224    b c_handle_interrupt
225END_FUNC(arm_hyp_irq_exception)
226
227BEGIN_FUNC(arm_hyp_reset_exception)
228    blx halt
229END_FUNC(arm_hyp_reset_exception)
230
231BEGIN_FUNC(arm_hyp_fiq_exception)
232    blx halt
233END_FUNC(arm_hyp_fiq_exception)
234
235#endif /* CONFIG_ARM_HYP */
236