]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/teg2/arm.s
devarch: restrict i/o port access to 64K, disallow msr 32-bit wrap arround (thanks...
[plan9front.git] / sys / src / 9 / teg2 / arm.s
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 */