1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/*
* xen/arch/arm/mode_switch.S
*
* Start-of day code to take a CPU from Secure mode to Hyp mode.
*
* Tim Deegan <tim@xen.org>
* Copyright (c) 2011-2012 Citrix Systems.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <asm/config.h>
#include <asm/page.h>
#include <asm/platform_vexpress.h>
#include <asm/asm_defns.h>
#include "gic.h"
/* XXX: Versatile Express specific code */
/* wake up secondary cpus */
.globl kick_cpus
kick_cpus:
/* write start paddr to v2m sysreg FLAGSSET register */
ldr r0, =(V2M_SYS_MMIO_BASE) /* base V2M sysreg MMIO address */
dsb
mov r2, #0xffffffff
str r2, [r0, #(V2M_SYS_FLAGSCLR)]
dsb
ldr r2, =start
add r2, r2, r10
str r2, [r0, #(V2M_SYS_FLAGSSET)]
dsb
/* send an interrupt */
ldr r0, =(GIC_BASE_ADDRESS + GIC_DR_OFFSET) /* base GICD MMIO address */
mov r2, #0x1
str r2, [r0, #(GICD_CTLR * 4)] /* enable distributor */
mov r2, #0xfe0000
str r2, [r0, #(GICD_SGIR * 4)] /* send IPI to everybody */
dsb
str r2, [r0, #(GICD_CTLR * 4)] /* disable distributor */
mov pc, lr
/* Get up a CPU into Hyp mode. Clobbers r0-r3.
*
* Expects r12 == CPU number
*
* This code is specific to the VE model, and not intended to be used
* on production systems. As such it's a bit hackier than the main
* boot code in head.S. In future it will be replaced by better
* integration with the bootloader/firmware so that Xen always starts
* in Hyp mode. */
.globl enter_hyp_mode
enter_hyp_mode:
mov r3, lr /* Put return address in non-banked reg */
cpsid aif, #0x16 /* Enter Monitor mode */
mrc CP32(r0, SCR)
orr r0, r0, #0x100 /* Set HCE */
orr r0, r0, #0xb1 /* Set SCD, AW, FW and NS */
bic r0, r0, #0xe /* Clear EA, FIQ and IRQ */
mcr CP32(r0, SCR)
/* Ugly: the system timer's frequency register is only
* programmable in Secure state. Since we don't know where its
* memory-mapped control registers live, we can't find out the
* right frequency. Use the VE model's default frequency here. */
ldr r0, =0x5f5e100 /* 100 MHz */
mcr CP32(r0, CNTFRQ)
ldr r0, =0x40c00 /* SMP, c11, c10 in non-secure mode */
mcr CP32(r0, NSACR)
mov r0, #GIC_BASE_ADDRESS
add r0, r0, #GIC_DR_OFFSET
/* Disable the GIC distributor, on the boot CPU only */
mov r1, #0
teq r12, #0 /* Is this the boot CPU? */
streq r1, [r0]
/* Continuing ugliness: Set up the GIC so NS state owns interrupts,
* The first 32 interrupts (SGIs & PPIs) must be configured on all
* CPUs while the remainder are SPIs and only need to be done one, on
* the boot CPU. */
add r0, r0, #0x80 /* GICD_IGROUP0 */
mov r2, #0xffffffff /* All interrupts to group 1 */
teq r12, #0 /* Boot CPU? */
str r2, [r0] /* Interrupts 0-31 (SGI & PPI) */
streq r2, [r0, #4] /* Interrupts 32-63 (SPI) */
streq r2, [r0, #8] /* Interrupts 64-95 (SPI) */
/* Disable the GIC CPU interface on all processors */
mov r0, #GIC_BASE_ADDRESS
add r0, r0, #GIC_CR_OFFSET
mov r1, #0
str r1, [r0]
/* Must drop priority mask below 0x80 before entering NS state */
ldr r1, =0xff
str r1, [r0, #0x4] /* -> GICC_PMR */
/* Reset a few config registers */
mov r0, #0
mcr CP32(r0, FCSEIDR)
mcr CP32(r0, CONTEXTIDR)
/* Allow non-secure access to coprocessors, FIQs, VFP and NEON */
ldr r1, =0x3fff /* 14 CP bits set, all others clear */
mcr CP32(r1, NSACR)
mrs r0, cpsr /* Copy the CPSR */
add r0, r0, #0x4 /* 0x16 (Monitor) -> 0x1a (Hyp) */
msr spsr_cxsf, r0 /* into the SPSR */
movs pc, r3 /* Exception-return into Hyp mode */
/*
* Local variables:
* mode: ASM
* indent-tabs-mode: nil
* End:
*/
|