2 |
- |
1 |
/*
|
|
|
2 |
* nvidia tegra 2 machine assist, definitions
|
|
|
3 |
* dual-core cortex-a9 processor
|
|
|
4 |
*
|
|
|
5 |
* R9 and R10 are used for `extern register' variables.
|
|
|
6 |
* R11 is used by the loader as a temporary, so avoid it.
|
|
|
7 |
*/
|
|
|
8 |
|
|
|
9 |
#include "mem.h"
|
|
|
10 |
#include "arm.h"
|
|
|
11 |
|
|
|
12 |
#undef B /* B is for 'botch' */
|
|
|
13 |
|
|
|
14 |
#define KADDR(pa) (KZERO | ((pa) & ~KSEGM))
|
|
|
15 |
#define PADDR(va) (PHYSDRAM | ((va) & ~KSEGM))
|
|
|
16 |
|
|
|
17 |
#define L1X(va) (((((va))>>20) & 0x0fff)<<2)
|
|
|
18 |
|
|
|
19 |
#define MACHADDR (L1-MACHSIZE) /* only room for cpu0's */
|
|
|
20 |
|
|
|
21 |
/* L1 pte values */
|
|
|
22 |
#define PTEDRAM (Dom0|L1AP(Krw)|Section|L1ptedramattrs)
|
|
|
23 |
#define PTEIO (Dom0|L1AP(Krw)|Section)
|
|
|
24 |
|
|
|
25 |
#define DOUBLEMAPMBS 512 /* megabytes of low dram to double-map */
|
|
|
26 |
|
|
|
27 |
/* steps on R0 */
|
|
|
28 |
#define DELAY(label, mloops) \
|
|
|
29 |
MOVW $((mloops)*1000000), R0; \
|
|
|
30 |
label: \
|
|
|
31 |
SUB.S $1, R0; \
|
|
|
32 |
BNE label
|
|
|
33 |
|
|
|
34 |
/* print a byte on the serial console; clobbers R0 & R6; needs R12 (SB) set */
|
|
|
35 |
#define PUTC(c) \
|
|
|
36 |
BARRIERS; \
|
|
|
37 |
MOVW $(c), R0; \
|
|
|
38 |
MOVW $PHYSCONS, R6; \
|
|
|
39 |
MOVW R0, (R6); \
|
|
|
40 |
BARRIERS
|
|
|
41 |
|
|
|
42 |
/*
|
|
|
43 |
* new instructions
|
|
|
44 |
*/
|
|
|
45 |
|
|
|
46 |
#define SMC WORD $0xe1600070 /* low 4-bits are call # (trustzone) */
|
|
|
47 |
/* flush branch-target cache */
|
|
|
48 |
#define FLBTC MTCP CpSC, 0, PC, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc
|
|
|
49 |
/* flush one entry of the branch-target cache, va in R0 (cortex) */
|
|
|
50 |
#define FLBTSE MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtse
|
|
|
51 |
|
|
|
52 |
/* arm v7 arch defines these */
|
|
|
53 |
#define DSB WORD $0xf57ff04f /* data synch. barrier; last f = SY */
|
|
|
54 |
#define DMB WORD $0xf57ff05f /* data mem. barrier; last f = SY */
|
|
|
55 |
#define ISB WORD $0xf57ff06f /* instr. sync. barrier; last f = SY */
|
|
|
56 |
|
|
|
57 |
#define WFI WORD $0xe320f003 /* wait for interrupt */
|
|
|
58 |
#define NOOP WORD $0xe320f000
|
|
|
59 |
|
|
|
60 |
#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s)) /* count leading 0s */
|
|
|
61 |
|
|
|
62 |
#define SETEND(o) WORD $(0xf1010000 | (o) << 9) /* o==0, little-endian */
|
|
|
63 |
|
|
|
64 |
#define CPSIE WORD $0xf1080080 /* intr enable: zeroes I bit */
|
|
|
65 |
#define CPSID WORD $0xf10c00c0 /* intr disable: sets I,F bits */
|
|
|
66 |
#define CPSAE WORD $0xf1080100 /* async abt enable: zeroes A bit */
|
|
|
67 |
#define CPSMODE(m) WORD $(0xf1020000 | (m)) /* switch to mode m (PsrM*) */
|
|
|
68 |
|
|
|
69 |
#define CLREX WORD $0xf57ff01f
|
|
|
70 |
|
|
|
71 |
/* floating point */
|
|
|
72 |
#define VMRS(fp, cpu) WORD $(0xeef00a10 | (fp)<<16 | (cpu)<<12) /* FP → arm */
|
|
|
73 |
#define VMSR(cpu, fp) WORD $(0xeee00a10 | (fp)<<16 | (cpu)<<12) /* arm → FP */
|
|
|
74 |
|
|
|
75 |
/*
|
|
|
76 |
* a popular code sequence used to write a pte for va is:
|
|
|
77 |
*
|
|
|
78 |
* MOVW R(n), TTB[LnX(va)]
|
|
|
79 |
* // clean the cache line
|
|
|
80 |
* DSB
|
|
|
81 |
* // invalidate tlb entry for va
|
|
|
82 |
* FLBTC
|
|
|
83 |
* DSB
|
|
|
84 |
* PFF (now ISB)
|
|
|
85 |
*/
|
|
|
86 |
#define BARRIERS FLBTC; DSB; ISB
|
|
|
87 |
|
|
|
88 |
/*
|
|
|
89 |
* invoked with PTE bits in R2, pa in R3, PTE pointed to by R4.
|
|
|
90 |
* fill PTE pointed to by R4 and increment R4 past it.
|
|
|
91 |
* increment R3 by a MB. clobbers R1.
|
|
|
92 |
*/
|
|
|
93 |
#define FILLPTE() \
|
|
|
94 |
ORR R3, R2, R1; /* pte bits in R2, pa in R3 */ \
|
|
|
95 |
MOVW R1, (R4); \
|
|
|
96 |
ADD $4, R4; /* bump PTE address */ \
|
|
|
97 |
ADD $MiB, R3; /* bump pa */ \
|
|
|
98 |
|
|
|
99 |
/* zero PTE pointed to by R4 and increment R4 past it. assumes R0 is 0. */
|
|
|
100 |
#define ZEROPTE() \
|
|
|
101 |
MOVW R0, (R4); \
|
|
|
102 |
ADD $4, R4; /* bump PTE address */
|
|
|
103 |
|
|
|
104 |
/*
|
|
|
105 |
* set kernel SB for zero segment (instead of usual KZERO segment).
|
|
|
106 |
* NB: the next line puts rubbish in R12:
|
|
|
107 |
* MOVW $setR12-KZERO(SB), R12
|
|
|
108 |
*/
|
|
|
109 |
#define SETZSB \
|
|
|
110 |
MOVW $setR12(SB), R12; /* load kernel's SB */ \
|
|
|
111 |
SUB $KZERO, R12; \
|
|
|
112 |
ADD $PHYSDRAM, R12
|
|
|
113 |
|
|
|
114 |
/*
|
|
|
115 |
* note that 5a's RFE is not the v6/7 arch. instruction (0xf8900a00),
|
|
|
116 |
* which loads CPSR from the word after the PC at (R13), but rather
|
|
|
117 |
* the pre-v6 simulation `MOVM.IA.S.W (R13), [R15]' (0xe8fd8000 since
|
|
|
118 |
* MOVM is LDM in this case), which loads CPSR not from memory but
|
|
|
119 |
* from SPSR due to `.S'.
|
|
|
120 |
*/
|
|
|
121 |
#define RFEV7(r) WORD $(0xf8900a00 | (r) << 16)
|
|
|
122 |
#define RFEV7W(r) WORD $(0xf8900a00 | (r) << 16 | 0x00200000) /* RFE.W */
|
|
|
123 |
#define RFEV7DB(r) WORD $(0xf9100a00 | (r) << 16) /* RFE.DB */
|
|
|
124 |
#define RFEV7DBW(r) WORD $(0xf9100a00 | (r) << 16 | 0x00200000) /* RFE.DB.W */
|
|
|
125 |
|
|
|
126 |
#define CKPSR(psr, tmp, bad)
|
|
|
127 |
#define CKCPSR(psrtmp, tmp, bad)
|
|
|
128 |
|
|
|
129 |
/* return with cpu id in r and condition codes set from "r == 0" */
|
|
|
130 |
#define CPUID(r) \
|
|
|
131 |
MFCP CpSC, 0, r, C(CpID), C(CpIDidct), CpIDmpid; \
|
|
|
132 |
AND.S $(MAXMACH-1), r /* mask out non-cpu-id bits */
|