From 47f52d56fac1acc9410a351dbf603c462bf3994c Mon Sep 17 00:00:00 2001 From: Robin Krens Date: Tue, 22 Oct 2019 21:04:20 +0200 Subject: [PATCH] SYSCALL naked assembly working --- Makefile | 11 +++-- include/lib/syscall.h | 2 + include/sys/robsys.h | 3 ++ ivt.c | 45 +++++++++++++++-- lib/syscall.c | 38 +++++++++++++++ main.c | 43 ++++++++++++++++- start.asm | 14 ++++-- syscall.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 include/lib/syscall.h create mode 100644 lib/syscall.c create mode 100644 syscall.c diff --git a/Makefile b/Makefile index d6a161a..6d3ec19 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,9 @@ MKIMG=arm-none-eabi-objcopy # Compiler flags LDFLAGS+= -mthumb -mcpu=cortex-m3 -ASFLAGS+= -mcpu=cortex-m3 -mthumb -g -CFLAGS+= -mcpu=cortex-m3 -mthumb -g -ffreestanding +ASFLAGS+= -mcpu=cortex-m3 -mthumb +CFLAGS+= -mcpu=cortex-m3 -mthumb -ffreestanding +#CFLAGS+= -mcpu=cortex-m3 -mthumb -g -ffreestanding # Include directory INCLUDE+= -Iinclude @@ -20,7 +21,7 @@ INCLUDE+= -Iinclude BIN = bin ODIR = obj -_OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o rtc.o heap.o +_OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o rtc.o heap.o syscall.o OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ)) DDIR = obj/drivers @@ -28,7 +29,7 @@ _DRIVERS = uart.o tm1637.o led.o tsensor.o at24c.o mk450_joystick.o st7735s.o DRIVERS = $(patsubst %, $(DDIR)/%,$(_DRIVERS)) LDIR = obj/lib -_LIBS = string.o stdio.o regfunc.o pool.o tinyprintf.o +_LIBS = string.o stdio.o regfunc.o pool.o tinyprintf.o syscall.o LIBS = $(patsubst %, $(LDIR)/%,$(_LIBS)) $(DDIR)/%.o: drivers/%.c @@ -57,7 +58,7 @@ kernel: $(OBJ) $(DRIVERS) $(LIBS) # Run in Qemu; note this is a patched version for stm32-f103c8 run: - /usr/local/bin/qemu-system-arm -serial stdio -M stm32-f103c8 -kernel $(BIN)/kernel.bin + /usr/local/bin/qemu-system-arm -monitor stdio -serial stdio -M stm32-f103c8 -kernel $(BIN)/kernel.bin # Examine all sections examine-all: diff --git a/include/lib/syscall.h b/include/lib/syscall.h new file mode 100644 index 0000000..ddf6882 --- /dev/null +++ b/include/lib/syscall.h @@ -0,0 +1,2 @@ +/* syscall.h */ +extern void theos_test(); diff --git a/include/sys/robsys.h b/include/sys/robsys.h index 9d1db41..705bd8c 100644 --- a/include/sys/robsys.h +++ b/include/sys/robsys.h @@ -37,6 +37,9 @@ extern void * kalloc(void * s); extern void kfree(void * s, void * p); extern void kheap_info(void * s); +/* SYSCALL.C */ +extern void syscall_init(); + /* TERM.C */ extern void terminal(); diff --git a/ivt.c b/ivt.c index a271487..0e2d1f2 100644 --- a/ivt.c +++ b/ivt.c @@ -76,6 +76,9 @@ char * messages[] = { "BUS FAULT", "USAGE FAULT", "RESERVED", + "RESERVED", + "RESERVED", + "RESERVED", "SVC", "DEBUG MONITOR", "RESERVED", @@ -109,8 +112,44 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) { /* Dummy interrupt: comment out the comment to use a naked * function */ -__attribute__ ((interrupt)) -void * dummy_isr( struct interrupt_frame * frame ) { +struct interrupt_frame * frame; + +//__attribute__ ((interrupt)) +void * dummy_isr( struct interrupt_frame * f ) { + + //uint32_t link_register = 0; + //asm ("mov %0, #33" : "=r" (lp)); + + /* Check Link Register: + * If you ever need to debug these: here are the most common + * values + * 0xFFFFFFF1: return to handler mode (nested interrupts + * 0xFFFFFFF9: return to thread mode using main stack + * 0xFFFFFFFD: return to thread mode using process stack */ + // asm ("mov %0, lr" : "=r" (link_register)); + // printf("%x\n", link_register); + // for(;;); + +// asm volatile ("push {r0-r12}"); +// int * stack; +// asm volatile ("tst lr, #4" "\n\t" +// "ite eq" "\n\t" +// "mrseq %0, msp" "\n\t" +// "mrsne r0, psp" : "=r" (stack)); +// +// printf("STACK: %x, %x, %x, %x, %x", stack[32], stack[28], stack[24], stack[20], stack[16]); + +// asm volatile ("CPSID f"); + +// uint32_t tmp = args[0]; +// uint32_t tmp2 = args[1]; +// printf("%x, %x\n", tmp, tmp2); +// uint32_t tmp3 = args[2]; +// uint32_t tmp4 = args[3]; +// printf("%x, %x\n", tmp3, tmp4); + + struct interrupt_frame * frame = (struct interrupt_frame * )kalloc(get_kheap()); + memcpy(frame, f, sizeof(struct interrupt_frame)); uint8_t nr = *SCB_VTOR_ST & 0xFF; printf("EXCEPTION: %s\n", exception_message(nr)); @@ -124,7 +163,7 @@ void * dummy_isr( struct interrupt_frame * frame ) { printf("PC:%p\n",frame->pc); printf("PSR:%p\n",frame->psr); - for(;;); + for(;;); } /* Initialize interrupt vector */ diff --git a/lib/syscall.c b/lib/syscall.c new file mode 100644 index 0000000..106c235 --- /dev/null +++ b/lib/syscall.c @@ -0,0 +1,38 @@ + +/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL + * + * $LOG$ + * 2019/9/21 - ROBIN KRENS + * Initial version + * + * $DESCRIPTION$ + * System calls for user functions + * + */ + +#include +#include +#include + +#include + + +//__attribute__ ((naked)) +static int theos_syscall(int SYSCALL_N, int SYSCALL_N2) { + + asm volatile ("svc 11"); + + return 0; +} + +//__attribute__ ((naked)) +void theos_test(int dummy, int dummy2) { + + theos_syscall(0xB1, 0xB2); +} + +/* void theos_cputs(const char * str, size_t len) { + + //syscall(#, 0, 0, 0 ..); + theos_syscall(22, 44); +} */ diff --git a/main.c b/main.c index 26a7305..e87131a 100644 --- a/main.c +++ b/main.c @@ -32,6 +32,40 @@ #include +#include + +int test3(int i, int j) { + + volatile uint32_t * sp = get_msp(); + + /* asm volatile ( + "tst lr, #4" "\n\t" + "ite eq" "\n\t" + "mrseq %0, msp" "\n\t" + "mrsne r0, psp" : "=r" (sp) ); */ + + for (int i = 0; (sp + i) < 0x20010000; i++) { + printf("ADDRESS: %p, VALUE: %x\n", (sp + i), *(sp + i)); + } + + for(;;); + return 0xCC; + +} +int test2(int i, int j) { + + int x = i * j; + test3(0x3A, 0x3B); + + +} +int test(int i, int j) { + + test2(0x2A, 0x2B); + + return 0xAA; +} + void main() { @@ -56,7 +90,7 @@ void main() init_printf(NULL, putc); /* Heap init */ - kheap_init(); + //kheap_init(); //printf("%p\n", get_kheap()); /* Display some basic info at startup */ @@ -66,8 +100,13 @@ void main() led_init(); /* Real time clock */ - rtc_init(); + //rtc_init(); + +// printf("press any key to start\n"); +// asm volatile ("wfi"); + syscall_init(); + theos_test(0xA1, 0xA2); /* Eeprom Driver eeprom_at24c_init(); diff --git a/start.asm b/start.asm index f2c16bc..e6d08c6 100644 --- a/start.asm +++ b/start.asm @@ -13,6 +13,7 @@ .text .global _start .global reset, nmi, hardfault + .global _svc_handler .code 16 .syntax unified _start: @@ -28,14 +29,17 @@ reset: /* These are consequently the nmi and hardfault vector handlers before booting and entering main, these can actually be called (machine somehow has a failure). That's why they are included here. - Later the interrupt vector - will be relocated to SRAM and the will be copied / modified. */ + Later the interrupt vector will be relocated to SRAM and modified. */ nmi: b nmi -hardfault: - b hardfault - +hardfault: + mov r5, 9 + b hardfault2 + +hardfault2: + b hardfault2 + .end diff --git a/syscall.c b/syscall.c new file mode 100644 index 0000000..f6e1cba --- /dev/null +++ b/syscall.c @@ -0,0 +1,130 @@ +/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL + * + * $LOG$ + * 2019/9/20 - ROBIN KRENS + * Initial version + * + * $DESCRIPTION$ + * + * |----------------------------| + * | SYSTEM CALL | # | + * |--------------------|-------| + * | THEOS_getenv | | + * | THEOS_killenv | | + * | THEOS_setenv | | + * | THEOS_newenv | | + * | THEOS_cputs | | + * | THEOS_omnigod | | + * | THEOS_brk | | + * | THEOS_time | | + * | THEOS_magic | | + * |----------------------------| + * + * TODO: include in header enum + * */ + + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* the function gets called for + * */ +__attribute__ ((naked)) +void * __svc_handler__(int x) { + + uint8_t svc_nr; + + asm volatile ( + "tst lr, #4" "\n\t" + "ite eq" "\n\t" + "mrseq r0, msp" "\n\t" + "mrsne r0, psp" "\n\t" + "ldr r0, [r0, #24]" "\n\t" + "ldrb %0, [r0, #-2]" : "=r" (svc_nr) ); + + printf("SYSTEM CALL NR: %d", svc_nr); + + for(;;); + + volatile uint32_t * sp; + + asm volatile ( + "tst lr, #4" "\n\t" + "ite eq" "\n\t" + "mrseq %0, msp" "\n\t" + "mrsne r0, psp" : "=r" (sp) ); + + + for (int i = 0; (sp + i) < 0x20010000; i++) { + printf("ADDRESS: %p, VALUE: %x\n", (sp + i), *(sp + i)); + } + + for (;;); + //asm ("mov %0, pc" : "=r" (link_register)); + //printf("%x\n", link_register); + + volatile uint32_t * svc_number = (uint32_t *) 0x20022222; + *svc_number = sp[-6]; + // = sp[6]; + //uint8_t tmp = link_register[-2]; + printf("SVC nr: %x", *svc_number); + //printf("%d, %d, %d, %d, %d, %d\n", msp[6], msp[0], msp[1], msp[2], msp[3], msp[4]); + + for (;;); + //return NULL; + return 0; + +} + +void syscall(unsigned int * args) { + + uint32_t svc_number = 99; + printf("SYSCALL NR: %x", svc_number); + + for(;;); + /* switch(SYSCALL_NO) { + case THEOS_cputs: + kernel_cputs(a1, a2); + break; + default: + for (;;); + } */ + +} + +void syscall_init() { + + + /* SVC is located at position 11 in the interrupt vector table */ +// extern void * _syscall; + extern void * hardfault; + + ivt_set_gate(11, __svc_handler__, 0); + + +} + +static void kernel_cputs(char * s, size_t l) { + + // TODO +} + + +void kernel_omnigod() { + + /* */ + +} + + + -- 2.7.4