From cf9ca80d1ac4ea4c63d2a62e6608b39e9f54d5aa Mon Sep 17 00:00:00 2001 From: Robin Krens Date: Tue, 22 Oct 2019 22:31:43 +0200 Subject: [PATCH] SYSCALL cleanup and ivt rewrite --- ivt.c | 84 +++++++++++++++++++++++---------------------------------------- main.c | 31 ----------------------- syscall.c | 73 +++++++++++++++++++++++------------------------------- 3 files changed, 61 insertions(+), 127 deletions(-) diff --git a/ivt.c b/ivt.c index 0e2d1f2..0d3b8ff 100644 --- a/ivt.c +++ b/ivt.c @@ -34,9 +34,8 @@ /* * These values are pushed on the stack just before - * entering the ISR. Normally, this would require - * assembly or inline assembly code. I use a so-called - * 'naked function' __attribute__ ((interrupt)) which + * entering the ISR. I use a so-called + * 'naked function' __attribute__ ((naked)) which * gives me a little bit more control over the caller * * The following register are pushed to the stack @@ -53,7 +52,7 @@ struct interrupt_frame { uint32_t lr; uint32_t pc; uint32_t psr; // N-4 -}; +} frame; /* * Vector table, each entry contains an interrupt @@ -64,7 +63,7 @@ struct interrupt_frame { * */ uint32_t __attribute__((aligned(0x100))) ivt[92]; -/* Each message corresponds to each and every exception. */ +/* Each message corresponds to an exception in the vector table. */ char * exception_message(uint8_t intnr) { char * messages[] = { @@ -98,70 +97,47 @@ if (intnr < 20) // TODO: strlen return messages[intnr]; return "UNKNOWN"; + } +/* Function to set entries of the interrupt vector table + * */ void ivt_set_gate(unsigned char num, void * isr(), short pri) { ivt[num] = (uint32_t) isr; -// if (num <= 32) -// *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F)); + //if (num <= 32) + //*NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F)); /* TODO: Priorities */ } -/* Dummy interrupt: comment out the comment to use a naked - * function */ +/* Dummy interrupt: shows the saved stack registers and then + * halts */ +__attribute__ ((naked)) void * dummy_isr(void) { -struct interrupt_frame * frame; + uint32_t * current_sp; -//__attribute__ ((interrupt)) -void * dummy_isr( struct interrupt_frame * f ) { + /* Test whether system call was invoked from supervisor (use MSP) or + * user (use PSP) mode */ + asm volatile ( + "tst lr, #4" "\n\t" + "ite eq" "\n\t" + "mrseq %0, msp" "\n\t" + "mrsne %0, psp" : "=r" (current_sp)); - //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)); + memcpy(&frame, current_sp, sizeof(struct interrupt_frame)); uint8_t nr = *SCB_VTOR_ST & 0xFF; printf("EXCEPTION: %s\n", exception_message(nr)); - printf("STACK TRACE:\n"); - printf("R0:%p\n",frame->r0); - printf("R1:%p\n",frame->r1); - printf("R2:%p\n",frame->r2); - printf("R3:%p\n",frame->r3); - printf("R12:%p\n",frame->r12); - printf("LR:%p\n",frame->lr); - printf("PC:%p\n",frame->pc); - printf("PSR:%p\n",frame->psr); + printf("STACKFRAME:\n"); + printf("R0:%p\n",frame.r0); + printf("R1:%p\n",frame.r1); + printf("R2:%p\n",frame.r2); + printf("R3:%p\n",frame.r3); + printf("R12:%p\n",frame.r12); + printf("LR:%p\n",frame.lr); + printf("PC:%p\n",frame.pc); + printf("PSR:%p\n",frame.psr); for(;;); } diff --git a/main.c b/main.c index e87131a..1543a12 100644 --- a/main.c +++ b/main.c @@ -34,37 +34,6 @@ #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() { diff --git a/syscall.c b/syscall.c index f6e1cba..9f33ad5 100644 --- a/syscall.c +++ b/syscall.c @@ -37,52 +37,46 @@ #include -/* the function gets called for - * */ +/* + * This is a so-called first interrupt handler + * The naked attribute makes sure the compiler doesn't + * places registers on the stack. */ + __attribute__ ((naked)) -void * __svc_handler__(int x) { +void * _svc_handler(void) { - uint8_t svc_nr; + uint32_t * current_sp; + /* Test whether system call was invoked from supervisor (use MSP) or + * user (use PSP) mode */ 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) ); + "mrseq %0, msp" "\n\t" + "mrsne %0, psp" : "=r" (current_sp)); + + /* An exception (or interrupt) before entering this handler + * places the following on the stack + * + * R0 + * R1 + * R2 + * R3 + * R12 + * LR + * PC <- placed at current_sp[6] + * PSR + * + * PC contains the return address that will continue after this SVC handler + * is finised. The previous address (the svc # call) is at PC - 2, the + * first byte contains the svc number. + * */ + + uint8_t svc_nr = ((char *) current_sp[6])[-2]; 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; } @@ -104,13 +98,8 @@ void syscall(unsigned int * args) { 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); - + ivt_set_gate(11, _svc_handler, 0); } -- 2.7.4