Basic exceptions, irq, cache mgmt support

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-01-17 00:45:10 +09:00
parent 73e79c5372
commit 81aaf2ed35
17 changed files with 447 additions and 57 deletions

View file

@ -8,8 +8,9 @@ LDFLAGS := -T m1n1.ld -EL -maarch64elf --no-undefined -X -shared -Bsymbolic \
-z notext --no-apply-dynamic-relocs --orphan-handling=warn --strip-debug \
-z nocopyreloc --gc-sections -pie
OBJECTS := adt.o bootlogo_128.o bootlogo_256.o fb.o main.o proxy.o start.o startup.o \
string.o uart.o uartproxy.o utils.o utils_asm.o vsprintf.o
OBJECTS := adt.o bootlogo_128.o bootlogo_256.o exception.o exception_asm.o fb.o \
main.o memory.o proxy.o start.o startup.o string.o uart.o uartproxy.o utils.o \
utils_asm.o vsprintf.o
BUILD_OBJS := $(patsubst %,build/%,$(OBJECTS))
NAME := m1n1
@ -42,14 +43,14 @@ build/%.o: src/%.c
build/$(NAME).elf: $(BUILD_OBJS) m1n1.ld
@echo " LD $@"
@$(LD) $(LDFLAGS) -o $@ $(BUILD_OBJS)
build/$(NAME).macho: build/$(NAME).elf
@echo " MACHO $@"
@$(OBJCOPY) -O binary $< $@
build/build_tag.h:
@echo " TAG $@"
@echo "#define BUILD_TAG \"$$(git describe --always --dirty)\"" > $@
@echo "#define BUILD_TAG \"$$(git describe --always --dirty)\"" > $@
build/%.bin: data/%.png
@echo " IMG $@"

10
m1n1.ld
View file

@ -30,7 +30,7 @@ SECTIONS {
LONG(_cmd_end - _cmd_start); /* sizeofcmds */
LONG(4); /* flags */
LONG(0); /* reserved */
_cmd_start = .;
/* unix_thread (entrypoint) */
@ -41,7 +41,7 @@ SECTIONS {
. += 32 * 8; /* useless registers */
QUAD(_start + _va_off) /* pc */
. += 8; /* useless registers */
ASSERT(. - _cmd_start == 0x120, "Bad unix_thread structure");
/* segment: mach-o structures */
@ -57,7 +57,7 @@ SECTIONS {
LONG(PROT_READ); /* initprot */
LONG(0); /* nsects */
LONG(0); /* flags */
/* segment: text */
LONG(0x19); /* type = SEGMENT_64 */
LONG(0x48); /* cmdsize */
@ -101,7 +101,7 @@ SECTIONS {
LONG(0); /* flags */
_cmd_end = .;
. = ALIGN(0x4000);
_hdr_end = .;
} :hdr
@ -171,7 +171,7 @@ SECTIONS {
*(.data.rel.ro)
}
ASSERT(SIZEOF(.empty) == 0, "Unexpected sections detected!")
.got.plt (NOLOAD) : {
*(.got.plt)
}

View file

@ -25,7 +25,7 @@ print("Loading %d bytes to 0x%x" % (len(payload), new_base))
iface.writemem(new_base + 0x4000, payload[0x4000:], True)
entry = new_base + 0x4000
entry = new_base + 0x4800
print("Jumping to 0x%x" % entry)

View file

@ -259,10 +259,17 @@ class M1N1Proxy:
P_MEMSET16 = 0x206
P_MEMSET8 = 0x207
P_DC_FLUSHRANGE = 0x300
P_DC_INVALRANGE = 0x301
P_DC_FLUSHALL = 0x302
P_IC_INVALALL = 0x303
P_IC_IALLUIS = 0x300
P_IC_IALLU = 0x301
P_IC_IVAU = 0x302
P_DC_IVAC = 0x303
P_DC_ISW = 0x304
P_DC_CSW = 0x305
P_DC_CISW = 0x306
P_DC_ZVA = 0x307
P_DC_CVAC = 0x308
P_DC_CVAU = 0x309
P_DC_CIVAC = 0x30a
def __init__(self, iface, debug=False):
self.debug = debug
@ -417,15 +424,29 @@ class M1N1Proxy:
self.request(self.P_MEMSET16, dst, src, size)
def memset8(self, dst, src, size):
self.request(self.P_MEMSET8, dst, src, size)
def dc_flushrange(self, addr, size):
self.request(self.P_DC_FLUSHRANGE, addr, size)
def dc_invalrange(self, addr, size):
self.request(self.P_DC_INVALRANGE, addr, size)
def dc_flushall(self):
self.request(self.P_DC_FLUSHALL)
def ic_invalall(self):
self.request(self.P_IC_INVALALL)
def ic_ialluis(self):
self.request(self.P_IC_IALLUIS)
def ic_iallu(self):
self.request(self.P_IC_IALLU)
def ic_ivau(self, addr, size):
self.request(self.P_IC_IVAU, addr, size)
def ic_ivac(self, addr, size):
self.request(self.P_IC_IVAC, addr, size)
def dc_isw(self, sw):
self.request(self.P_DC_ISW, sw)
def dc_csw(self, sw):
self.request(self.P_DC_CSW, sw)
def dc_cisw(self, sw):
self.request(self.P_DC_CISW, sw)
def dc_zva(self, addr, size):
self.request(self.P_DC_ZVA, addr, size)
def dc_cvac(self, addr, size):
self.request(self.P_DC_CVAC, addr, size)
def dc_cvau(self, addr, size):
self.request(self.P_DC_CVAU, addr, size)
def dc_civac(self, addr, size):
self.request(self.P_DC_CIVAC, addr, size)
if __name__ == "__main__":
import serial

84
src/exception.c Normal file
View file

@ -0,0 +1,84 @@
/* SPDX-License-Identifier: MIT */
#include "uart.h"
#include "utils.h"
extern char _vectors_start[0];
void exception_initialize(void)
{
printf("Initializing exceptions...\n");
msr(vbar_el2, _vectors_start);
}
void print_regs(u64 *regs)
{
u64 sp = ((u64)(regs)) - (8 * 31);
printf("Running in EL%d\n", mrs(CurrentEL) >> 2);
printf("Registers: (@%p)\n", regs);
printf(" x0-x3: %016lx %016lx %016lx %016lx\n", regs[0], regs[1], regs[2],
regs[3]);
printf(" x4-x7: %016lx %016lx %016lx %016lx\n", regs[4], regs[5], regs[6],
regs[7]);
printf(" x8-x11: %016lx %016lx %016lx %016lx\n", regs[8], regs[9], regs[10],
regs[11]);
printf("x12-x15: %016lx %016lx %016lx %016lx\n", regs[12], regs[13],
regs[14], regs[15]);
printf("x16-x19: %016lx %016lx %016lx %016lx\n", regs[16], regs[17],
regs[18], regs[19]);
printf("x20-x23: %016lx %016lx %016lx %016lx\n", regs[20], regs[21],
regs[22], regs[23]);
printf("x24-x27: %016lx %016lx %016lx %016lx\n", regs[24], regs[25],
regs[26], regs[27]);
printf("x28-x30: %016lx %016lx %016lx\n", regs[28], regs[29], regs[30]);
u64 elr = mrs(elr_el2);
printf("PC: 0x%lx (rel: 0x%lx)\n", elr, elr - (u64)_base);
printf("SPSEL: 0x%lx\n", mrs(spsel));
printf("SP: 0x%lx\n", sp);
printf("SPSR_EL2: 0x%x\n", mrs(spsr_el2));
}
void exc_sync(u64 *regs)
{
uart_puts("Exception: SYNC");
print_regs(regs);
reboot();
}
void exc_irq(u64 *regs)
{
uart_puts("Exception: IRQ");
u32 reason = read32(0x23b102004);
printf(" type: %d num: %d\n", reason >> 16, reason & 0xffff);
// print_regs(regs);
}
void exc_fiq(u64 *regs)
{
uart_puts("Exception: FIQ");
u32 timer_ctl = mrs(CNTP_CTL_EL0);
if (timer_ctl == 0x5) {
uart_puts(" timer IRQ, masking");
msr(CNTP_CTL_EL0, 7);
}
// print_regs(regs);
}
void exc_serr(u64 *regs)
{
printf("Exception: SError\n");
print_regs(regs);
reboot();
}

8
src/exception.h Normal file
View file

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: MIT */
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
void exception_initialize(void);
#endif

84
src/exception_asm.S Normal file
View file

@ -0,0 +1,84 @@
/* spDx-License-Identifier: MIT */
.globl exc_sync
.globl exc_irq
.globl exc_fiq
.globl exc_serr
.globl _vectors_start
.globl _v_sp0_sync
.type _v_sp0_sync, @function
_v_sp0_sync:
str x30, [sp, #-16]!
bl _exc_entry
bl exc_sync
b _exc_return
.globl _v_sp0_irq
.type _v_sp0_irq, @function
_v_sp0_irq:
str x30, [sp, #-16]!
bl _exc_entry
bl exc_irq
b _exc_return
.globl _v_sp0_fiq
.type _v_sp0_fiq, @function
_v_sp0_fiq:
str x30, [sp, #-16]!
bl _exc_entry
bl exc_fiq
b _exc_return
.globl _v_sp0_serr
.type _v_sp0_serr, @function
_v_sp0_serr:
str x30, [sp, #-16]!
bl _exc_entry
bl exc_serr
b _exc_return
.globl push_hi_regs
.type push_hi_regs, @function
push_hi_regs:
_exc_entry:
stp x28, x29, [sp, #-16]!
stp x26, x27, [sp, #-16]!
stp x24, x25, [sp, #-16]!
stp x22, x23, [sp, #-16]!
stp x20, x21, [sp, #-16]!
stp x18, x19, [sp, #-16]!
stp x16, x17, [sp, #-16]!
stp x14, x15, [sp, #-16]!
stp x12, x13, [sp, #-16]!
stp x10, x11, [sp, #-16]!
stp x8, x9, [sp, #-16]!
stp x6, x7, [sp, #-16]!
stp x4, x5, [sp, #-16]!
stp x2, x3, [sp, #-16]!
stp x0, x1, [sp, #-16]!
mov x0, sp
ret
.globl _exc_return
.type _exc_return, @function
_exc_return:
ldp x0, x1, [sp], #16
ldp x2, x3, [sp], #16
ldp x4, x5, [sp], #16
ldp x6, x7, [sp], #16
ldp x8, x9, [sp], #16
ldp x10, x11, [sp], #16
ldp x12, x13, [sp], #16
ldp x14, x15, [sp], #16
add sp, sp, #112
ldr x30, [sp], #16
eret

View file

@ -10,7 +10,7 @@
#include "../build/build_tag.h"
//#define LOGO
// #define LOGO
void print_info(void)
{
@ -65,7 +65,9 @@ void m1n1_main(void)
{
printf("\n\nm1n1 v%s\n", BUILD_TAG);
printf("Copyright (C) 2021 The Asahi Linux Contributors\n");
printf("Licensed under the MIT license\n");
printf("Licensed under the MIT license\n\n");
printf("Running in EL%d\n\n", mrs(CurrentEL) >> 2);
#ifdef LOGO
fb_init();
@ -75,15 +77,6 @@ void m1n1_main(void)
print_info();
disable_wdt();
/*
u64 dtaddr = ((u64)cur_boot_args.devtree) - cur_boot_args.virt_base +
cur_boot_args.phys_base;*/
// hexdump((void *)dtaddr, cur_boot_args.devtree_size);
//
// while (1)
// uart_putbyte(uart_getbyte());
printf("Running proxy...\n");
uartproxy_run();

24
src/memory.c Normal file
View file

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: MIT */
#include "memory.h"
#include "utils.h"
#define CACHE_LINE_SIZE 64
#define CACHE_RANGE_OP(func, op) \
void func(void *addr, size_t length) \
{ \
u64 p = (u64)addr; \
u64 end = p + length; \
while (p < end) { \
cacheop(op, p); \
p += CACHE_LINE_SIZE; \
} \
}
CACHE_RANGE_OP(ic_ivau_range, "ic ivau")
CACHE_RANGE_OP(dc_ivac_range, "dc ivac")
CACHE_RANGE_OP(dc_zva_range, "dc zva")
CACHE_RANGE_OP(dc_cvac_range, "dc cvac")
CACHE_RANGE_OP(dc_cvau_range, "dc cvau")
CACHE_RANGE_OP(dc_civac_range, "dc civac")

15
src/memory.h Normal file
View file

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: MIT */
#ifndef MEMORY_H
#define MEMORY_H
#include "types.h"
void ic_ivau_range(void *addr, size_t length);
void dc_ivac_range(void *addr, size_t length);
void dc_zva_range(void *addr, size_t length);
void dc_cvac_range(void *addr, size_t length);
void dc_cvau_range(void *addr, size_t length);
void dc_civac_range(void *addr, size_t length);
#endif

View file

@ -1,11 +1,10 @@
#include "proxy.h"
#include "memory.h"
#include "types.h"
#include "uart.h"
#include "utils.h"
#include "xnuboot.h"
extern char _base[0];
int proxy_process(ProxyRequest *request, ProxyReply *reply)
{
callfunc *f;
@ -145,13 +144,39 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
request->args[2]);
break;
/*
case P_DC_FLUSHRANGE: dc_flushrange((void*)request->args[0],
request->args[1]); break; case P_DC_INVALRANGE:
dc_invalidaterange((void*)request->args[0], request->args[1]);
break; case P_DC_FLUSHALL: dc_flushall(); break; case
P_IC_INVALALL: ic_invalidateall(); break;
*/
case P_IC_IALLUIS:
ic_ialluis();
break;
case P_IC_IALLU:
ic_iallu();
break;
case P_IC_IVAU:
ic_ivau_range((void *)request->args[0], request->args[1]);
break;
case P_DC_IVAC:
dc_ivac_range((void *)request->args[0], request->args[1]);
break;
case P_DC_ISW:
dc_isw((void *)request->args[0]);
break;
case P_DC_CSW:
dc_csw((void *)request->args[0]);
break;
case P_DC_CISW:
dc_cisw((void *)request->args[0]);
break;
case P_DC_ZVA:
dc_zva_range((void *)request->args[0], request->args[1]);
break;
case P_DC_CVAC:
dc_cvac_range((void *)request->args[0], request->args[1]);
break;
case P_DC_CVAU:
dc_cvau_range((void *)request->args[0], request->args[1]);
break;
case P_DC_CIVAC:
dc_civac_range((void *)request->args[0], request->args[1]);
break;
default:
reply->status = S_BADCMD;

View file

@ -41,10 +41,17 @@ typedef enum {
P_MEMSET16,
P_MEMSET8,
P_DC_FLUSHRANGE = 0x300, // Cache and memory ops
P_DC_INVALRANGE,
P_DC_FLUSHALL,
P_IC_INVALALL,
P_IC_IALLUIS = 0x300, // Cache and memory ops
P_IC_IALLU,
P_IC_IVAU,
P_DC_IVAC,
P_DC_ISW,
P_DC_CSW,
P_DC_CISW,
P_DC_ZVA,
P_DC_CVAC,
P_DC_CVAU,
P_DC_CIVAC,
} ProxyOp;

View file

@ -4,11 +4,68 @@
#define UTRSTAT 0x010
#define UTXH 0x020
#define WDT_BASE 0x23d2b0000
#define WDT_COUNT 0x10
#define WDT_ALARM 0x14
#define WDT_CTL 0x1c
.extern _start_c
.extern _stack_bot
.extern _v_sp0_sync
.extern _v_sp0_irq
.extern _v_sp0_fiq
.extern _v_sp0_serr
.section .init, "ax"
.globl _vectors_start
_vectors_start:
mov x9, '0'
b exc_unk
.align 7
mov x9, '1'
b exc_unk
.align 7
mov x9, '2'
b exc_unk
.align 7
mov x9, '3'
b exc_unk
.align 7
b _v_sp0_sync
.align 7
b _v_sp0_irq
.align 7
b _v_sp0_fiq
.align 7
b _v_sp0_serr
.align 7
mov x9, 'a'
b exc_unk
.align 7
mov x9, 'b'
b exc_unk
.align 7
mov x9, 'c'
b exc_unk
.align 7
mov x9, 'd'
b exc_unk
.align 7
mov x9, 'p'
b exc_unk
.align 7
mov x9, 'q'
b exc_unk
.align 7
mov x9, 'r'
b exc_unk
.align 7
mov x9, 's'
b exc_unk
.align 7
.globl _start
.type _start, @function
_start:
@ -46,6 +103,33 @@ _start:
bl _start_c
b .
.globl exc_unk
.type exc_unk, @function
exc_unk:
mov w0, '\r'
bl debug_putc
mov w0, '\n'
bl debug_putc
mov w0, '!'
bl debug_putc
mov w0, 'E'
bl debug_putc
mov w0, 'x'
bl debug_putc
mov w0, 'C'
bl debug_putc
mov w0, ':'
bl debug_putc
mov w0, w9
bl debug_putc
mov w0, '!'
bl debug_putc
mov w0, '\r'
bl debug_putc
mov w0, '\n'
bl debug_putc
b reboot
.globl debug_putc
.type debug_putc, @function
debug_putc:
@ -58,4 +142,16 @@ debug_putc:
str w0, [x1, UTXH]
ret
.pool
.globl reboot
.type reboot, @function
reboot:
ldr x1, =WDT_BASE
mov w0, #0x100000
str w0, [x1, #WDT_ALARM]
mov w0, #0
str w0, [x1, #WDT_COUNT]
mov w0, #4
str w0, [x1, #WDT_CTL]
b .
.pool

View file

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: MIT */
#include "exception.h"
#include "string.h"
#include "types.h"
#include "uart.h"
@ -79,5 +80,6 @@ void _start_c(void *boot_args, void *base)
adt = (void *)(((u64)cur_boot_args.devtree) - cur_boot_args.virt_base +
cur_boot_args.phys_base);
exception_initialize();
m1n1_main();
}

View file

@ -3,6 +3,8 @@
#ifndef UART_H
#define UART_H
#include "types.h"
void uart_init(void);
void uart_putbyte(u8 c);

View file

@ -193,6 +193,33 @@ static inline u8 mask8(u64 addr, u8 clear, u8 set)
return data;
}
#define mrs(reg) \
({ \
u64 val; \
__asm__ volatile("mrs\t%0, " #reg : "=r"(val)); \
val; \
})
#define msr(reg, val) ({ __asm__ volatile("msr\t" #reg ", %0" : : "r"(val)); })
#define sysop(op) __asm__ volatile(op)
#define cacheop(op, val) ({ __asm__ volatile(op ", %0" : : "r"(val)); })
#define ic_ialluis() sysop("ic ialluis")
#define ic_iallu() sysop("ic iallu")
#define ic_iavau(p) cacheop("ic ivau", p)
#define dc_ivac(p) cacheop("dc ivac", p)
#define dc_isw(p) cacheop("dc isw", p)
#define dc_csw(p) cacheop("dc csw", p)
#define dc_cisw(p) cacheop("dc cisw", p)
#define dc_zva(p) cacheop("dc zva", p)
#define dc_cvac(p) cacheop("dc cvac", p)
#define dc_cvau(p) cacheop("dc cvau", p)
#define dc_civac(p) cacheop("dc civac", p)
extern char _base[0];
/*
* These functions are guaranteed to copy by reading from src and writing to dst
* in <n>-bit units If size is not aligned, the remaining bytes are not copied
@ -211,5 +238,6 @@ void regdump(u64 addr, int len);
int sprintf(char *str, const char *fmt, ...);
int debug_printf(const char *fmt, ...);
void udelay(u32 d);
void reboot(void);
#endif

View file

@ -11,7 +11,7 @@ memcpy64:
str x3, [x0], #8
subs x2, x2, #8
bne 1b
2:
2:
ret
.globl memset64
@ -22,7 +22,7 @@ memset64:
1: str x1, [x0], #8
subs x2, x2, #8
bne 1b
2:
2:
ret
.globl memcpy32
@ -30,11 +30,11 @@ memset64:
memcpy32:
ands x2, x2, #~3
beq 2f
1: ldr x3, [x1], #4
1: ldr w3, [x1], #4
str w3, [x0], #4
subs x2, x2, #4
bne 1b
2:
2:
ret
.globl memset32
@ -45,7 +45,7 @@ memset32:
1: str w1, [x0], #4
subs x2, x2, #4
bne 1b
2:
2:
ret
.globl memcpy16
@ -57,7 +57,7 @@ memcpy16:
strh w3, [x0], #2
subs x2, x2, #2
bne 1b
2:
2:
ret
.globl memset16
@ -68,7 +68,7 @@ memset16:
1: strh w1, [x0], #2
subs x2, x2, #2
bne 1b
2:
2:
ret
.globl memcpy8
@ -80,7 +80,7 @@ memcpy8:
strb w3, [x0], #1
subs x2, x2, #1
bne 1b
2:
2:
ret
.globl memset8
@ -91,5 +91,5 @@ memset8:
1: strb w1, [x0], #1
subs x2, x2, #1
bne 1b
2:
2:
ret