1.1 --- a/stage2/cpu.c Mon Feb 22 20:31:50 2016 +0100
1.2 +++ b/stage2/cpu.c Mon Feb 22 23:23:52 2016 +0100
1.3 @@ -145,7 +145,7 @@
1.4
1.5 void map_page(u32 virtual, u32 physical, u32 pagesize)
1.6 {
1.7 - u32 start = virtual & 0xffffe000;
1.8 + u32 start = virtual & 0xffffe000; /* VPN2 */
1.9 u32 flags = 0x1f; /* C=3, dirty, global, valid */
1.10 u32 lower = ((physical & 0xffffc000) >> 6) | flags;
1.11 u32 upper = (((physical + pagesize) & 0xffffc000) >> 6) | flags;
1.12 @@ -153,8 +153,6 @@
1.13
1.14 asm volatile(
1.15 "mtc0 %3, $5\n" /* CP0_PAGEMASK */
1.16 - "li $t1, 2\n" /* index of first randomly-replaced entry */
1.17 - "mtc0 $t1, $6\n" /* CP0_WIRED */
1.18
1.19 /* Set physical address. */
1.20
1.21 @@ -172,3 +170,23 @@
1.22 : "r" (lower), "r" (upper), "r" (start), "r" (pagemask)
1.23 );
1.24 }
1.25 +
1.26 +void tlb_handle(void)
1.27 +{
1.28 + u32 context, virtual;
1.29 +
1.30 + /* Obtain the bad virtual address. */
1.31 +
1.32 + asm volatile(
1.33 + "mfc0 %0, $4\n" /* CP0_CONTEXT */
1.34 + : "=r" (context)
1.35 + );
1.36 +
1.37 + /* Obtain a virtual address region with 8KB resolution. */
1.38 +
1.39 + virtual = (context & 0x007ffff0) << 9;
1.40 +
1.41 + /* Request a physical region mapping two 4KB pages. */
1.42 +
1.43 + map_page(virtual, virtual, 4 * 1024);
1.44 +}
2.1 --- a/stage2/cpu.h Mon Feb 22 20:31:50 2016 +0100
2.2 +++ b/stage2/cpu.h Mon Feb 22 23:23:52 2016 +0100
2.3 @@ -9,5 +9,6 @@
2.4 void init_interrupts(void);
2.5 void init_tlb(void);
2.6 void map_page(u32, u32, u32);
2.7 +void tlb_handle(void);
2.8
2.9 #endif /* __CPU_H__ */
3.1 --- a/stage2/entry.S Mon Feb 22 20:31:50 2016 +0100
3.2 +++ b/stage2/entry.S Mon Feb 22 23:23:52 2016 +0100
3.3 @@ -1,7 +1,7 @@
3.4 /*
3.5 - * Interrupt handling support.
3.6 + * Interrupt and TLB miss handling support.
3.7 *
3.8 - * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
3.9 + * Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
3.10 *
3.11 * This program is free software: you can redistribute it and/or modify
3.12 * it under the terms of the GNU General Public License as published by
3.13 @@ -18,11 +18,19 @@
3.14 */
3.15
3.16 .text
3.17 +.extern tlb_handler
3.18 .extern interrupt_handler
3.19 +.globl _tlb_entry
3.20 .globl _irq_entry
3.21 .globl _end_entries
3.22 .set noreorder
3.23
3.24 +_tlb_entry:
3.25 + lui $k0, %hi(tlb_handler)
3.26 + ori $k0, $k0, %lo(tlb_handler)
3.27 + jr $k0
3.28 + nop
3.29 +
3.30 _irq_entry:
3.31 lui $k0, %hi(interrupt_handler)
3.32 ori $k0, $k0, %lo(interrupt_handler)
4.1 --- a/stage2/handlers.S Mon Feb 22 20:31:50 2016 +0100
4.2 +++ b/stage2/handlers.S Mon Feb 22 23:23:52 2016 +0100
4.3 @@ -19,12 +19,40 @@
4.4 */
4.5
4.6 .text
4.7 +.extern tlb_handle
4.8 .extern irq_handle
4.9 +.globl tlb_handler
4.10 .globl interrupt_handler
4.11 .set noreorder
4.12 .set noat
4.13
4.14 +tlb_handler:
4.15 + sw $ra, -112($sp)
4.16 + jal save_state
4.17 + nop
4.18 +
4.19 + /* Invoke the handler. */
4.20 +
4.21 + jal tlb_handle
4.22 + nop
4.23 +
4.24 + j load_and_return
4.25 + nop
4.26 +
4.27 interrupt_handler:
4.28 + sw $ra, -112($sp)
4.29 + jal save_state
4.30 + nop
4.31 +
4.32 + /* Invoke the handler. */
4.33 +
4.34 + jal irq_handle
4.35 + nop
4.36 +
4.37 + j load_and_return
4.38 + nop
4.39 +
4.40 +save_state:
4.41
4.42 /* Save the status, mask interrupts. */
4.43
4.44 @@ -61,18 +89,17 @@
4.45 sw $t9, -100($sp)
4.46 sw $gp, -104($sp)
4.47 sw $fp, -108($sp)
4.48 - sw $ra, -112($sp)
4.49 + /* sw $ra, -112($sp) */
4.50
4.51 mfc0 $k0, $14 /* CP0_EPC */
4.52 nop
4.53 sw $k0, -116($sp)
4.54
4.55 addi $sp, $sp, -120
4.56 -
4.57 - /* Invoke the handler. */
4.58 + j $ra
4.59 + nop
4.60
4.61 - jal irq_handle
4.62 - nop
4.63 +load_and_return:
4.64
4.65 addi $sp, $sp, 120
4.66
5.1 --- a/stage2/head2.S Mon Feb 22 20:31:50 2016 +0100
5.2 +++ b/stage2/head2.S Mon Feb 22 23:23:52 2016 +0100
5.3 @@ -56,6 +56,14 @@
5.4
5.5 move $k0, $ra
5.6
5.7 + /* Copy TLB handling instructions. */
5.8 +
5.9 + la $t0, _tlb_entry /* start */
5.10 + li $t1, 0x80000000
5.11 + la $t2, _irq_entry /* end */
5.12 + jal _copy
5.13 + nop
5.14 +
5.15 /* Copy IRQ handling instructions. */
5.16
5.17 la $t0, _irq_entry /* start */