# HG changeset patch # User Paul Boddie # Date 1456618689 -3600 # Node ID c39fcc82cc152e153cd983605fa4353e2fe0053a # Parent 38459046fa3f8e1b30888cc4a1c22a93c40a6a6c Introduced kernel regions for task register storage. Removed the invoke_task function. diff -r 38459046fa3f -r c39fcc82cc15 stage2/cpu.c --- a/stage2/cpu.c Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/cpu.c Sun Feb 28 01:18:09 2016 +0100 @@ -125,41 +125,22 @@ ); } -void init_stack(u32 top, u32 got, void (*function)(), u32 args[], u8 nargs) +void init_registers(u32 *base, u32 got, void (*function)(), u32 args[], u8 nargs) { u8 i; - asm volatile( - "move $t3, %0\n" /* refer to the stack frame */ - "addi $t3, $t3, -16\n" /* refer to the first parameter */ - : - : "r" (top) - ); - /* Provide arguments to the function. */ for (i = 0; i < nargs; i++) { - asm volatile( - "sw %0, 0($t3)\n" - "addi $t3, $t3, -4\n" - : - : "r" (args[i]) - ); + base[i+4] = args[i]; } /* Store essential data for the function environment. */ - asm volatile( - "subu %1, %1, 0x80000000\n" /* obtain user mode addresses */ - "subu %2, %2, 0x80000000\n" - "sw %2, -100(%0)\n" /* store the function address as t9 */ - "sw %1, -104(%0)\n" /* store the global pointer */ - "sw %2, -112(%0)\n" /* store the function address as ra (for invoke_task) */ - "sw %2, -116(%0)\n" /* store the function address as EPC (for the handler) */ - : - : "r" (top), "r" (got), "r" (function) - ); + base[25] = (u32) function - 0x80000000; /* store the function address as t9 */ + base[26] = got - 0x80000000; /* store the global pointer */ + base[29] = (u32) function - 0x80000000; /* store the function address as EPC (for the handler) */ } void enter_user_mode(void) @@ -174,14 +155,18 @@ void init_tlb(void) { - /* Wire in the kseg0 mapping and the page tables. */ + unsigned short first_random = 0; asm volatile( - "li $t1, 1\n" /* index of first randomly-replaced entry */ - "mtc0 $t1, $6\n" /* CP0_WIRED */ "mtc0 $zero, $4\n" /* CP0_CONTEXT */ "mtc0 $zero, $10\n" /* CP0_ENTRYHI */ - "nop\n"); + "mtc0 $zero, $2\n" /* CP0_ENTRYLO0 */ + "mtc0 $zero, $3\n" /* CP0_ENTRYLO1 */ + "mtc0 %0, $6\n" /* CP0_WIRED */ + "nop" + : + : "r" (first_random) + ); } void map_page_index(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid, u32 index) diff -r 38459046fa3f -r c39fcc82cc15 stage2/cpu.h --- a/stage2/cpu.h Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/cpu.h Sun Feb 28 01:18:09 2016 +0100 @@ -7,7 +7,7 @@ void handle_error_level(void); void enter_user_mode(void); void set_task(u8); -void init_stack(u32, u32, void (*)(), u32[], u8); +void init_registers(u32 *, u32, void (*)(), u32[], u8); void enable_interrupts(void); void init_interrupts(void); void init_tlb(void); diff -r 38459046fa3f -r c39fcc82cc15 stage2/entry.S --- a/stage2/entry.S Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/entry.S Sun Feb 28 01:18:09 2016 +0100 @@ -19,6 +19,8 @@ .text .extern interrupt_handler +.extern current_registers +.extern current_stack_pointer .globl _tlb_entry .globl _exc_entry .globl _irq_entry @@ -111,14 +113,40 @@ nop _irq_entry: + /* Set the ASID. */ + + mtc0 $zero, $10 /* CP0_ENTRYHI */ + nop + + /* Obtain the kernel global offset table. */ + + move $k0, $gp + lui $gp, %hi(_GLOBAL_OFFSET_TABLE_) + ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_) + + /* Obtain a store of registers for the current task. */ + + la $k1, current_registers + lw $k1, 0($k1) + /* Save registers that the assembler wants to trash. */ - sw $t9, -100($sp) - sw $gp, -104($sp) - sw $ra, -112($sp) + sw $t9, 100($k1) + sw $k0, 104($k1) /* old gp */ + sw $ra, 112($k1) + + /* Record the stack pointer. */ - lui $gp, %hi(_GLOBAL_OFFSET_TABLE_) - ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_) + la $k1, current_stack_pointer + lw $k1, 0($k1) /* &stack_pointers[current_task] */ + sw $sp, 0($k1) + + /* Switch to the kernel stack. */ + + li $sp, 0x80070000 + + /* Invoke the rest of the interrupt handling process. */ + la $k0, interrupt_handler jr $k0 nop diff -r 38459046fa3f -r c39fcc82cc15 stage2/handlers.S --- a/stage2/handlers.S Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/handlers.S Sun Feb 28 01:18:09 2016 +0100 @@ -20,6 +20,7 @@ .text .extern irq_handle +.extern current_registers .extern current_stack_pointer .extern current_task .globl interrupt_handler @@ -32,11 +33,6 @@ jal save_state nop - /* Record the stack pointer. */ - - la $k0, current_stack_pointer - sw $sp, 0($k0) - /* Invoke the handler. */ jal irq_handle @@ -45,7 +41,8 @@ /* Switch the stack pointer. */ la $k0, current_stack_pointer - lw $sp, 0($k0) + lw $k1, 0($k0) /* &stack_pointers[current_task] */ + lw $sp, 0($k1) /* Set the current task ASID. */ @@ -54,81 +51,89 @@ mtc0 $k1, $10 /* CP0_ENTRYHI */ nop + /* Obtain the current task's registers. */ + j load_and_return nop save_state: - sw $at, -4($sp) - sw $v0, -8($sp) - sw $v1, -12($sp) - sw $a0, -16($sp) - sw $a1, -20($sp) - sw $a2, -24($sp) - sw $a3, -28($sp) - sw $t0, -32($sp) - sw $t1, -36($sp) - sw $t2, -40($sp) - sw $t3, -44($sp) - sw $t4, -48($sp) - sw $t5, -52($sp) - sw $t6, -56($sp) - sw $t7, -60($sp) - sw $s0, -64($sp) - sw $s1, -68($sp) - sw $s2, -72($sp) - sw $s3, -76($sp) - sw $s4, -80($sp) - sw $s5, -84($sp) - sw $s6, -88($sp) - sw $s7, -92($sp) - sw $t8, -96($sp) - /* sw $t9, -100($sp) */ - /* sw $gp, -104($sp) */ - sw $fp, -108($sp) - /* sw $ra, -112($sp) */ + /* Obtain a store of registers for the current task. */ + + la $k0, current_registers + lw $k1, 0($k0) + + sw $at, 4($k1) + sw $v0, 8($k1) + sw $v1, 12($k1) + sw $a0, 16($k1) + sw $a1, 20($k1) + sw $a2, 24($k1) + sw $a3, 28($k1) + sw $t0, 32($k1) + sw $t1, 36($k1) + sw $t2, 40($k1) + sw $t3, 44($k1) + sw $t4, 48($k1) + sw $t5, 52($k1) + sw $t6, 56($k1) + sw $t7, 60($k1) + sw $s0, 64($k1) + sw $s1, 68($k1) + sw $s2, 72($k1) + sw $s3, 76($k1) + sw $s4, 80($k1) + sw $s5, 84($k1) + sw $s6, 88($k1) + sw $s7, 92($k1) + sw $t8, 96($k1) + + /* t9, gp and ra are already saved */ + + sw $fp, 108($k1) mfc0 $k0, $14 /* CP0_EPC */ nop - sw $k0, -116($sp) + sw $k0, 116($k1) - addi $sp, $sp, -120 j $ra nop load_and_return: + /* Obtain a store of registers for the current task. */ - addi $sp, $sp, 120 + la $k0, current_registers + lw $k1, 0($k0) - lw $at, -4($sp) - lw $v0, -8($sp) - lw $v1, -12($sp) - lw $a0, -16($sp) - lw $a1, -20($sp) - lw $a2, -24($sp) - lw $a3, -28($sp) - lw $t0, -32($sp) - lw $t1, -36($sp) - lw $t2, -40($sp) - lw $t3, -44($sp) - lw $t4, -48($sp) - lw $t5, -52($sp) - lw $t6, -56($sp) - lw $t7, -60($sp) - lw $s0, -64($sp) - lw $s1, -68($sp) - lw $s2, -72($sp) - lw $s3, -76($sp) - lw $s4, -80($sp) - lw $s5, -84($sp) - lw $s6, -88($sp) - lw $s7, -92($sp) - lw $t8, -96($sp) - lw $t9, -100($sp) - lw $gp, -104($sp) - lw $fp, -108($sp) - lw $ra, -112($sp) + lw $at, 4($k1) + lw $v0, 8($k1) + lw $v1, 12($k1) + lw $a0, 16($k1) + lw $a1, 20($k1) + lw $a2, 24($k1) + lw $a3, 28($k1) + lw $t0, 32($k1) + lw $t1, 36($k1) + lw $t2, 40($k1) + lw $t3, 44($k1) + lw $t4, 48($k1) + lw $t5, 52($k1) + lw $t6, 56($k1) + lw $t7, 60($k1) + lw $s0, 64($k1) + lw $s1, 68($k1) + lw $s2, 72($k1) + lw $s3, 76($k1) + lw $s4, 80($k1) + lw $s5, 84($k1) + lw $s6, 88($k1) + lw $s7, 92($k1) + lw $t8, 96($k1) + lw $t9, 100($k1) + lw $gp, 104($k1) + lw $fp, 108($k1) + lw $ra, 112($k1) - lw $k0, -116($sp) + lw $k0, 116($k1) mtc0 $k0, $14 /* CP0_EPC */ nop diff -r 38459046fa3f -r c39fcc82cc15 stage2/irq.c --- a/stage2/irq.c Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/irq.c Sun Feb 28 01:18:09 2016 +0100 @@ -47,14 +47,17 @@ enum { max_tasks = 3 }; static u32 stack_pointers[max_tasks]; -u8 current_task = 0; -u32 current_stack_pointer; +static u32 registers[max_tasks][32]; + +u8 current_task; +u32 *current_stack_pointer; +u32 *current_registers; + extern u32 _got_copy_start; const u32 stack_start = 0x80080000; const u32 stack_size = 0x00002000; const u32 pagesize = 4 * 1024; -const u32 framesize = 120; /* see the handlers */ /* Tasks. */ @@ -106,6 +109,13 @@ } } +void init_tasks() +{ + current_task = 0; + current_stack_pointer = &stack_pointers[current_task]; + current_registers = registers[current_task]; +} + void start_task(unsigned short task) { u32 args[] = {task, 0, (task - 1) * 60}; @@ -116,89 +126,30 @@ physical memory, but at the same address in virtual memory. */ - physical = stack_start + stack_size * task; + physical = stack_start - stack_size * task; virtual = physical; init_page_table(page_table_start, virtual - pagesize * 2, physical - pagesize * 2, pagesize, 0x1e, task); + stack_pointers[task] = virtual; + /* - Set the stack for the new task, initialising the global pointer and + Set the registers for the new task, initialising the global pointer and return address. */ - init_stack(physical, _got_copy_start, (void (*)()) plot_pattern, args, 3); - - /* Advance the stack pointer so that the adopted frame will be found. */ - - stack_pointers[task] = virtual - framesize; + init_registers(registers[task], _got_copy_start, (void (*)()) plot_pattern, args, 3); } void switch_task() { - /* - Get the current stack pointer. This is obtained just after saving the - task's state. - */ - - stack_pointers[current_task] = current_stack_pointer; - /* Switch the current task. */ current_task++; if (current_task == max_tasks) current_task = 1; - /* - Set the current stack pointer. This is actually set just before - restoring the task's state. - */ - - current_stack_pointer = stack_pointers[current_task]; -} - -void invoke_task(unsigned short task) -{ - current_task = task; - current_stack_pointer = stack_pointers[current_task]; - set_task(current_task); + /* Indicate the current stack pointer and task registers. */ - asm volatile( - ".set noat\n" - "move $sp, %0\n" - "addi $sp, $sp, 120\n" - "lw $at, -4($sp)\n" - "lw $v0, -8($sp)\n" - "lw $v1, -12($sp)\n" - "lw $a0, -16($sp)\n" - "lw $a1, -20($sp)\n" - "lw $a2, -24($sp)\n" - "lw $a3, -28($sp)\n" - "lw $t0, -32($sp)\n" - "lw $t1, -36($sp)\n" - "lw $t2, -40($sp)\n" - "lw $t3, -44($sp)\n" - "lw $t4, -48($sp)\n" - "lw $t5, -52($sp)\n" - "lw $t6, -56($sp)\n" - "lw $t7, -60($sp)\n" - "lw $s0, -64($sp)\n" - "lw $s1, -68($sp)\n" - "lw $s2, -72($sp)\n" - "lw $s3, -76($sp)\n" - "lw $s4, -80($sp)\n" - "lw $s5, -84($sp)\n" - "lw $s6, -88($sp)\n" - "lw $s7, -92($sp)\n" - "lw $t8, -96($sp)\n" - "lw $t9, -100($sp)\n" - "lw $gp, -104($sp)\n" - "lw $fp, -108($sp)\n" - "lw $ra, -112($sp)\n" - "lw $k0, -116($sp)\n" - "mtc0 $k0, $14\n" /* CP0_EPC */ - "nop\n" - "jr $ra\n" - "nop" - : - : "r" (current_stack_pointer) - ); + current_stack_pointer = &stack_pointers[current_task]; + current_registers = registers[current_task]; } diff -r 38459046fa3f -r c39fcc82cc15 stage2/irq.h --- a/stage2/irq.h Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/irq.h Sun Feb 28 01:18:09 2016 +0100 @@ -4,9 +4,9 @@ /* Initialisation functions. */ void irq_init(void); +void init_tasks(void); void start_task(unsigned short); void switch_task(void); -void invoke_task(unsigned short); void plot_pattern(unsigned short, unsigned short, unsigned short); #endif /* __IRQ_H__ */ diff -r 38459046fa3f -r c39fcc82cc15 stage2/stage2.c --- a/stage2/stage2.c Sat Feb 27 23:41:17 2016 +0100 +++ b/stage2/stage2.c Sun Feb 28 01:18:09 2016 +0100 @@ -48,6 +48,7 @@ /* Start the tasks. */ + init_tasks(); start_task(1); start_task(2);