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