Skip to content

Commit cabc6f7

Browse files
committed
move GOOS=tamago MMU initialization and exception handling to linked application
1 parent f419902 commit cabc6f7

File tree

2 files changed

+97
-418
lines changed

2 files changed

+97
-418
lines changed

src/runtime/os_tamago_arm.go

+35-253
Original file line numberDiff line numberDiff line change
@@ -10,55 +10,8 @@ import (
1010
"unsafe"
1111
)
1212

13-
const tamagoDebug = true
14-
1513
const _PAGESIZE uintptr = 0x1000
1614

17-
// ARM processor modes
18-
// Table B1-1 ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
19-
const (
20-
USR_MODE = 0b10000
21-
FIQ_MODE = 0b10001
22-
IRQ_MODE = 0b10010
23-
SVC_MODE = 0b10011
24-
MON_MODE = 0b10110
25-
ABT_MODE = 0b10111
26-
HYP_MODE = 0b11010
27-
UND_MODE = 0b11011
28-
SYS_MODE = 0b11111
29-
)
30-
31-
// Memory region attributes
32-
// Table B3-10 ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
33-
const (
34-
TTE_SECTION_1MB uint32 = 0x2
35-
TTE_SECTION_16MB uint32 = 0x40002
36-
TTE_EXECUTE_NEVER uint32 = 0x10
37-
TTE_CACHEABLE uint32 = 0x8
38-
TTE_BUFFERABLE uint32 = 0x4
39-
)
40-
41-
// MMU access permissions
42-
// Table B3-8 ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
43-
const (
44-
// PL1: no access PL0: no access
45-
TTE_AP_000 uint32 = 0b000000 << 10
46-
// PL1: read/write PL0: no access
47-
TTE_AP_001 uint32 = 0b000001 << 10
48-
// PL1: read/write PL0: read only
49-
TTE_AP_010 uint32 = 0b000010 << 10
50-
// PL1: read/write PL0: read/write
51-
TTE_AP_011 uint32 = 0b000011 << 10
52-
// Reserved
53-
TTE_AP_100 uint32 = 0b100000 << 10
54-
// PL1: read only PL0: no access
55-
TTE_AP_101 uint32 = 0b100001 << 10
56-
// PL1: read only PL0: read only
57-
TTE_AP_110 uint32 = 0b100010 << 10
58-
// PL1: read only PL0: read only
59-
TTE_AP_111 uint32 = 0b100011 << 10
60-
)
61-
6215
// the following variables must be provided externally
6316
var ramStart uint32
6417
var ramStackOffset uint32
@@ -70,83 +23,53 @@ var ramStackOffset uint32
7023
// the following functions must be provided externally
7124
func hwinit()
7225
func printk(byte)
73-
func exceptionHandler()
7426
func getRandomData([]byte)
7527
func initRNG()
7628

7729
// the following functions must be provided externally
7830
// (but are already stubbed somewhere else in the runtime)
7931
//func nanotime1() int64
8032

81-
// the following functions are defined in sys_tamago_arm.s
82-
func set_vbar(addr unsafe.Pointer)
83-
func set_ttbr0(addr unsafe.Pointer)
84-
func set_exc_stack(addr unsafe.Pointer)
85-
func processor_mode() uint32
33+
// GetRandomData generates len(r) random bytes from the random source provided
34+
// externally by the linked application.
35+
func GetRandomData(r []byte) {
36+
getRandomData(r)
37+
}
38+
39+
// CallOnG0 calls a function (func(off int)) on g0 stack.
40+
//
41+
// The function arguments must be passed through the following registers
42+
// (rather than on the frame pointer):
43+
//
44+
// * R0: fn argument (vector table offset)
45+
// * R1: fn pointer
46+
// * R2: size of stack area reserved for caller registers
47+
// * R3: caller program counter
48+
func CallOnG0()
8649

87-
//go:nosplit
88-
func dmb()
50+
// MemRegion returns the start and end addresses of the physical RAM assigned
51+
// to the Go runtime.
52+
func MemRegion() (start uint32, end uint32) {
53+
return ramStart, ramStart + ramSize
54+
}
8955

9056
// stubs for unused/unimplemented functionality
9157
type mOS struct{}
9258
type sigset struct{}
9359
type gsignalStack struct{}
9460

95-
func goenvs() {}
96-
func sigsave(p *sigset) {}
97-
func msigrestore(sigmask sigset) {}
98-
func clearSignalHandlers() {}
99-
func sigblock(exiting bool) {}
100-
func minit() {}
101-
func unminit() {}
102-
func mdestroy(mp *m) {}
103-
func madvise(addr unsafe.Pointer, n uintptr, flags int32) {}
104-
func munmap(addr unsafe.Pointer, n uintptr) {}
105-
func setProcessCPUProfiler(hz int32) {}
106-
func setThreadCPUProfiler(hz int32) {}
107-
func initsig(preinit bool) {}
108-
func sigdisable(uint32) {}
109-
func sigenable(uint32) {}
110-
func sigignore(uint32) {}
111-
func closeonexec(int32) {}
112-
func osyield() {}
113-
114-
// global variables
115-
var vt *vector_table
116-
117-
var vecTableOffset uint32 = 0
118-
var vecTableSize uint32 = 0x4000 // 16 kB
119-
120-
var l1pageTableOffset uint32 = 0x4000 // 16 kB
121-
var l1pageTableSize uint32 = 0x4000 // 16 kB
122-
123-
var excStackOffset uint32 = 0x8000 // 32 kB
124-
var excStackSize uint32 = 0x4000 // 16 kB
125-
126-
// the following variables are set in sys_tamago_arm.s
127-
var stackBottom uint32
128-
129-
// Table 11-1 ARM® Cortex™ -A Series Programmer’s Guide
130-
type vector_table struct {
131-
// jump entries
132-
reset uint32
133-
undefined uint32
134-
svc uint32
135-
prefetch_abort uint32
136-
data_abort uint32
137-
_unused uint32
138-
irq uint32
139-
fiq uint32
140-
// call pointers
141-
reset_addr uint32
142-
undefined_addr uint32
143-
svc_addr uint32
144-
prefetch_abort_addr uint32
145-
data_abort_addr uint32
146-
_unused_addr uint32
147-
irq_addr uint32
148-
fiq_addr uint32
149-
}
61+
func goenvs() {}
62+
func sigsave(p *sigset) {}
63+
func msigrestore(sigmask sigset) {}
64+
func clearSignalHandlers() {}
65+
func sigblock(exiting bool) {}
66+
func minit() {}
67+
func unminit() {}
68+
func mdestroy(mp *m) {}
69+
func setProcessCPUProfiler(hz int32) {}
70+
func setThreadCPUProfiler(hz int32) {}
71+
func initsig(preinit bool) {}
72+
func osyield() {}
15073

15174
// May run with m.p==nil, so write barriers are not allowed.
15275
//go:nowritebarrier
@@ -177,10 +100,7 @@ func osinit() {
177100
}
178101

179102
func signame(sig uint32) string {
180-
if sig >= uint32(len(sigtable)) {
181-
return ""
182-
}
183-
return sigtable[sig].name
103+
return ""
184104
}
185105

186106
func checkgoarm() {
@@ -212,142 +132,6 @@ func crash() {
212132
*(*int32)(nil) = 0
213133
}
214134

215-
func GetRandomData(r []byte) {
216-
getRandomData(r)
217-
}
218-
219-
// the following functions are defined in sys_tamago_arm.s
220-
func resetHandler()
221-
func undefinedHandler()
222-
func svcHandler()
223-
func prefetchAbortHandler()
224-
func dataAbortHandler()
225-
func irqHandler()
226-
func fiqHandler()
227-
228-
func fnAddress(fn func()) uint32 {
229-
return **((**uint32)(unsafe.Pointer(&fn)))
230-
}
231-
232-
//go:nosplit
233-
func vecinit() {
234-
if processor_mode() != SYS_MODE {
235-
return
236-
}
237-
238-
// Allocate the vector table
239-
vecTableStart := ramStart + vecTableOffset
240-
memclrNoHeapPointers(unsafe.Pointer(uintptr(vecTableStart)), uintptr(vecTableSize))
241-
dmb()
242-
243-
// ldr pc, [pc, #24]
244-
resetVectorWord := uint32(0xe59ff018)
245-
246-
vt = (*vector_table)(unsafe.Pointer(uintptr(vecTableStart)))
247-
vt.reset = resetVectorWord
248-
vt.undefined = resetVectorWord
249-
vt.svc = resetVectorWord
250-
vt.prefetch_abort = resetVectorWord
251-
vt.data_abort = resetVectorWord
252-
vt._unused = resetVectorWord
253-
vt.irq = resetVectorWord
254-
vt.fiq = resetVectorWord
255-
256-
vt.reset_addr = fnAddress(resetHandler)
257-
vt.undefined_addr = fnAddress(undefinedHandler)
258-
vt.svc_addr = fnAddress(svcHandler)
259-
vt.prefetch_abort_addr = fnAddress(prefetchAbortHandler)
260-
vt.data_abort_addr = fnAddress(dataAbortHandler)
261-
vt.irq_addr = fnAddress(irqHandler)
262-
vt.fiq_addr = fnAddress(fiqHandler)
263-
264-
set_vbar(unsafe.Pointer(vt))
265-
266-
// Allocate stack pointer for exception modes to provide a stack to the
267-
// g0 goroutine when summoned by exception vectors.
268-
excStackStart := ramStart + excStackOffset
269-
memclrNoHeapPointers(unsafe.Pointer(uintptr(excStackStart)), uintptr(excStackSize))
270-
dmb()
271-
272-
set_exc_stack(unsafe.Pointer(uintptr(excStackStart + excStackSize)))
273-
274-
if !tamagoDebug {
275-
return
276-
}
277-
278-
print("vecTableStart ", hex(vecTableStart), "\n")
279-
print("vecTableSize ", hex(vecTableSize), "\n")
280-
print("excStackStart ", hex(excStackStart), "\n")
281-
print("excStackSize ", hex(excStackSize), "\n")
282-
print("stackBottom ", hex(stackBottom), "\n")
283-
print("g0.stackguard0 ", hex(g0.stackguard0), "\n")
284-
print("g0.stackguard1 ", hex(g0.stackguard1), "\n")
285-
print("g0.stack.lo ", hex(g0.stack.lo), "\n")
286-
print("g0.stack.hi ", hex(g0.stack.hi), "\n")
287-
print("-- ELF image layout (firstmoduledata dump) --\n")
288-
print(".text ", hex(firstmoduledata.text), " - ", hex(firstmoduledata.etext), "\n")
289-
print(".noptrdata ", hex(firstmoduledata.noptrdata), " - ", hex(firstmoduledata.enoptrdata), "\n")
290-
print(".data ", hex(firstmoduledata.data), " - ", hex(firstmoduledata.edata), "\n")
291-
print(".bss ", hex(firstmoduledata.bss), " - ", hex(firstmoduledata.ebss), "\n")
292-
print(".noptrbss ", hex(firstmoduledata.noptrbss), " - ", hex(firstmoduledata.enoptrbss), "\n")
293-
print(".end ", hex(firstmoduledata.end), "\n")
294-
295-
imageSize := uint32(firstmoduledata.end - firstmoduledata.text)
296-
heapSize := uint32(g0.stack.lo - firstmoduledata.end)
297-
stackSize := uint32(g0.stack.hi - g0.stack.lo)
298-
unusedSize := uint32(firstmoduledata.text) - (excStackStart + excStackSize) + ramStackOffset
299-
totalSize := vecTableSize + l1pageTableSize + excStackSize + imageSize + heapSize + stackSize + unusedSize
300-
301-
print("-- Memory section sizes ---------------------\n")
302-
print("vector table: ", vecTableSize, " (", vecTableSize/1024, " kB)\n")
303-
print("L1 page table: ", l1pageTableSize, " (", l1pageTableSize/1024, " kB)\n")
304-
print("exception stack: ", excStackSize, " (", excStackSize/1024, " kB)\n")
305-
print("program image: ", imageSize, " (", imageSize/1024, " kB)\n")
306-
print("heap: ", heapSize, " (", heapSize/1024, " kB)\n")
307-
print("g0 stack: ", stackSize, " (", stackSize/1024, " kB)\n")
308-
print("total unused: ", unusedSize, " (", unusedSize/1024, " kB)\n")
309-
print("total: ", totalSize, " (", totalSize/1024, " kB)\n")
310-
print("---------------------------------------------\n")
311-
}
312-
313-
//go:nosplit
314-
func mmuinit() {
315-
// Initialize page tables and map regions in privileged system area.
316-
//
317-
// MMU initialization is required to take advantage of data cache.
318-
//
319-
// Define a flat L1 page table, the MMU is enabled only for caching to work.
320-
// The L1 page table is located 16KB after ramStart.
321-
322-
if processor_mode() != SYS_MODE {
323-
return
324-
}
325-
326-
l1pageTableStart := ramStart + l1pageTableOffset
327-
memclrNoHeapPointers(unsafe.Pointer(uintptr(l1pageTableStart)), uintptr(l1pageTableSize))
328-
329-
memAttr := uint32(TTE_AP_011 | TTE_CACHEABLE | TTE_BUFFERABLE | TTE_SECTION_1MB)
330-
devAttr := uint32(TTE_AP_011 | TTE_SECTION_1MB)
331-
332-
// skip page zero to trap null pointers
333-
for i := uint32(1); i < l1pageTableSize/4; i++ {
334-
if i >= (ramStart>>20) && i < ((ramStart+ramSize)>>20) {
335-
*(*uint32)(unsafe.Pointer(uintptr(l1pageTableStart + 4*i))) = (i << 20) | memAttr
336-
} else {
337-
*(*uint32)(unsafe.Pointer(uintptr(l1pageTableStart + 4*i))) = (i << 20) | devAttr
338-
}
339-
}
340-
341-
dmb()
342-
343-
if tamagoDebug {
344-
print("l1pageTableStart ", hex(l1pageTableStart), "\n")
345-
print("l1pageTableSize ", hex(l1pageTableSize), "\n")
346-
}
347-
348-
set_ttbr0(unsafe.Pointer(uintptr(l1pageTableStart)))
349-
}
350-
351135
//go:linkname syscall
352136
func syscall(number, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
353137
switch number {
@@ -416,7 +200,5 @@ func exitThread(wait *uint32) {
416200
const preemptMSupported = false
417201

418202
func preemptM(mp *m) {
419-
// Not currently supported.
420-
//
421-
// TODO: Use a note like we use signals on POSIX OSes
203+
// No threads, so nothing to do.
422204
}

0 commit comments

Comments
 (0)