summaryrefslogtreecommitdiff
path: root/src/vectors.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/vectors.S')
-rw-r--r--src/vectors.S466
1 files changed, 466 insertions, 0 deletions
diff --git a/src/vectors.S b/src/vectors.S
new file mode 100644
index 0000000..691d568
--- /dev/null
+++ b/src/vectors.S
@@ -0,0 +1,466 @@
+/*
+ * <vectors.S>
+ *
+ * Second stage boot-loader and exception vectors for Open Hack'Ware.
+ *
+ * Copyright (C) 2004-2005 Jocelyn Mayer (l_indien@magic.fr)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License V2
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define ASSEMBLY_CODE
+#include "bios.h"
+
+.section .text
+.align 2
+
+.globl _start
+_start:
+ /* Entry point */
+ li r0, 0 ;
+_turn_off_mmu:
+ /* Be sure MMU is off and we are in 32 bits mode (for PPC64) */
+ lis r11, _hw_init@h ;
+ ori r11, r11, _hw_init@l ;
+ mtspr 26, r11 ;
+ mtspr 27, r0 ;
+ rfi ;
+_hw_init:
+ /* May need more hw init here */
+_load_bios:
+ /* Load the full BIOS into RAM */
+ lis r12, bios_base@h ;
+ ori r12, r12, bios_base@l ;
+ lmw r29, 0(r12) ;
+ /* Set up the C stack */
+ addis r1, r29, 0x0040 ;
+ clrrwi r1, r1, 19 ;
+ stw r1, -16(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ /* Skip frame pointer */
+ stwu r0, -8(r1) ;
+ stwu r0, -4(r1) ;
+ stwu r0, -4(r1) ;
+ /* Start copying */
+ mtctr r30 ;
+ subi r12, r3, 4 ;
+ subi r13, r29, 4 ;
+_bios_copy_loop:
+ lwzu r14, 4(r12) ;
+ stwu r14, 4(r13) ;
+ bdnz _bios_copy_loop ;
+ /* Synchronize the whole execution context */
+ /* Also enable FPU */
+ ori r0, r0, (1 << 13) ;
+ mtspr 26, r29 ;
+ mtspr 27, r0 ;
+ rfi ;
+ /* If we ever return, stop */
+ bl bug ;
+
+.org 0x0080
+.section .text
+.align 2
+bug:
+ /* Dump the exception and its context */
+ mflr r3 ;
+ mfspr r4, SRR0 ;
+ mfspr r5, SRR1 ;
+ mfspr r6, DAR ;
+ mfspr r7, DSISR ;
+ /* Turn MMU off */
+ lis r0, _bug_no_mmu@h ;
+ ori r0, r0, _bug_no_mmu@l ;
+ mtspr 26, r0 ;
+ li r0, 0 ;
+ mtspr 27, r0 ;
+ rfi ;
+_bug_no_mmu:
+ bl dump_exception ;
+_forever:
+ /* Loop forever */
+ b _forever ;
+
+skip_exception:
+ /* Skip external interrupts and decrementer exception */
+ /* BEWARE: be sure not to modify any register */
+ stw r11, save_area@l(0) ;
+ mfspr r11, 27 ;
+ clrlwi r11, r11, 16 ;
+ mtspr 27, r11 ;
+ lwz r11, save_area@l(0) ;
+ rfi ;
+
+#define EXCP_BUG(entry) \
+.org 0x##entry ; \
+.section .text ; \
+.align 2 ; \
+excp_##entry: ; \
+ bl bug
+
+#define EXCP_SKIP(entry) \
+.org 0x##entry ; \
+.section .text ; \
+.align 2 ; \
+excp_##entry##: ; \
+ b skip_exception
+
+ /* Exception vectors */
+ /* Reset exception */
+ EXCP_BUG(0100) ;
+
+ /* Machine check exception */
+ EXCP_BUG(0200) ;
+
+ /* DSI exception */
+ EXCP_BUG(0300) ;
+
+ /* ISI exception */
+ EXCP_BUG(0400) ;
+
+ /* External interrupt: skip it */
+ EXCP_SKIP(0500) ;
+
+ /* Alignment exception */
+ EXCP_BUG(0600) ;
+
+ /* Program exception */
+ EXCP_BUG(0700) ;
+
+ /* No floating point exception */
+ EXCP_BUG(0800) ;
+
+ /* Decrementer exception: skip it */
+ EXCP_SKIP(0900) ;
+
+ /* Reserved A exception */
+ EXCP_BUG(0A00) ;
+
+ /* Reserved B exception */
+ EXCP_BUG(0B00) ;
+
+ /* System call exception */
+ EXCP_BUG(0C00) ;
+
+ /* Trace exception */
+ EXCP_BUG(0D00) ;
+
+ /* Floating point assist exception */
+ EXCP_BUG(0E00) ;
+
+ /* Performance monitor exception */
+ EXCP_BUG(0F00) ;
+
+ /* Instruction TLB miss exception */
+ EXCP_BUG(1000) ;
+
+ /* Data TLB miss for store exception */
+ EXCP_BUG(1100) ;
+
+ /* Data TLB miss for load exception */
+ EXCP_BUG(1200) ;
+
+ /* Instruction address breakpoint exception */
+ EXCP_BUG(1300) ;
+
+ /* System management interrupt exception */
+ EXCP_BUG(1400) ;
+
+ /* Thermal management exception */
+ EXCP_BUG(1500) ;
+
+ /* Unknown exceptions */
+ EXCP_BUG(1600) ;
+
+ EXCP_BUG(1700) ;
+
+ EXCP_BUG(1800) ;
+
+ EXCP_BUG(1900) ;
+
+ EXCP_BUG(1A00) ;
+
+ EXCP_BUG(1B00) ;
+
+ EXCP_BUG(1C00) ;
+
+ EXCP_BUG(1D00) ;
+
+ EXCP_BUG(1E00) ;
+
+ EXCP_BUG(1F00) ;
+ /* End of exception vectors list */
+
+.org 0x2000
+.section .text
+.align 2
+helpers_start:
+
+outb:
+ /* void outb (uint32_t port, uint32_t data);
+ * Writes a single character on an IO port.
+ * Used for serial console.
+ */
+ stb r4, 0(r3) ;
+ eieio ;
+ blr ;
+
+outstr:
+ /* void outstr (uint32_t port, const unsigned char *str);
+ * Writes a string on an IO port.
+ */
+ mflr r20 ;
+ subi r11, r4, 1 ;
+
+_outstr_next:
+ lbzu r4, 1(r11) ;
+ cmpi 0, r4, 0 ;
+ beq _outstr_done ;
+ bl outb ;
+ b _outstr_next ;
+_outstr_done:
+ mtlr r20 ;
+ blr ;
+
+outdigit:
+ /* void outdigit (uint32_t port, uint32_t digit);
+ * Dumps a single digit on serial port.
+ */
+ mflr r20 ;
+ addi r4, r4, '0' ;
+ bl outb ;
+ mtlr r20 ;
+ blr ;
+
+outhex:
+ /* void outhex (uint32_t port, uint32_t value);
+ * Dumps a 32 bits hex number on serial port
+ */
+ mflr r21
+ li r11, 8 ;
+ mtctr r11 ;
+ mr r11, r4 ;
+_outhex_next:
+ rlwinm r11, r11, 4, 0, 31 ;
+ clrlwi r4, r11, 28 ;
+ cmpi 0, r4, 9 ;
+ bgt _outhex_xdigit ;
+ bl outdigit ;
+ bdnz _outhex_next ;
+ b _outhex_done ;
+_outhex_xdigit:
+ addi r4, r4, 'a' - 10 ;
+ bl outb ;
+ bdnz _outhex_next ;
+_outhex_done:
+ mtlr r21 ;
+ blr ;
+
+ /* void dump_exception (uint32_t lr, uint32_t srr0, uint32_t srr1,
+ * uint32_t dar, uint32_t dsisr);
+ * Dump a message when catching an exception
+ */
+dump_exception:
+ /* Save call parameters */
+ mflr r19 ;
+ mr r22, r3 ;
+ mr r23, r4 ;
+ mr r24, r5 ;
+ mr r25, r6 ;
+ mr r26, r7 ;
+ lis r11, registers_area@h ;
+ ori r11, r11, registers_area@l ;
+ lmw r27, 0(r11) ;
+ /* Now, serial IO port is in r27,
+ * message table start is in r28,
+ * first exception message offset is in r29,
+ * and last known exception number is in r30
+ */
+ /* Print error prompt message */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ /* Find message corresponding to the caught exception */
+ srwi r12, r22, 8 ;
+ cmp 0, r12, r30 ;
+ ble _dump_excp_msg ;
+ subi r12, r30, 1 ;
+_dump_excp_msg:
+ rlwinm r12, r12, 2, 0, 31 ;
+ /* Dump execption message */
+ mr r3, r27 ;
+ lwzx r4, r12, r29 ;
+ bl outstr ;
+ /* Complete exception message */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ /* Dump nip */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ mr r3, r27 ;
+ mr r4, r23 ;
+ bl outhex ;
+ /* dump msr */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ mr r3, r27 ;
+ mr r4, r24 ;
+ bl outhex ;
+ /* dump dar */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ mr r3, r27 ;
+ mr r4, r25 ;
+ bl outhex ;
+ /* dump dsisr */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ mr r3, r27 ;
+ mr r4, r26 ;
+ bl outhex ;
+ /* All done, dump last message and return */
+ mr r3, r27 ;
+ lwzu r4, 4(r28) ;
+ bl outstr ;
+ mtlr r19 ;
+ blr ;
+
+.section .rodata
+.align 2
+_BUG_message_0:
+ .string "ERROR: BUG caught...\n"
+_BUG_message_1:
+ .string " exception"
+_BUG_message_2:
+ .string "\nnip=0x"
+_BUG_message_3:
+ .string " msr=0x"
+_BUG_message_4:
+ .string " dar=0x"
+_BUG_message_5:
+ .string " dsisr=0x"
+_BUG_message_6:
+ .string "\nStopping execution\n"
+
+_excp_message_0x00:
+ .string "BIOS execution"
+_excp_message_0x01:
+ .string "Reset"
+_excp_message_0x02:
+ .string "Machine check"
+_excp_message_0x03:
+ .string "Data memory access"
+_excp_message_0x04:
+ .string "Instruction fetch"
+_excp_message_0x05:
+ .string "External"
+_excp_message_0x06:
+ .string "Alignment"
+_excp_message_0x07:
+ .string "Program"
+_excp_message_0x08:
+ .string "No floating point"
+_excp_message_0x09:
+ .string "Decrementer"
+_excp_message_0x0a:
+ .string "Reserved A"
+_excp_message_0x0b:
+ .string "Reserved B"
+_excp_message_0x0c:
+ .string "System call"
+_excp_message_0x0d:
+ .string "Trace"
+_excp_message_0x0e:
+ .string "Floating point assist"
+_excp_message_0x0f:
+ .string "Performance monitor"
+_excp_message_0x10:
+ .string "Instruction TLB miss"
+_excp_message_0x11:
+ .string "Data TLB miss for store"
+_excp_message_0x12:
+ .string "Data TLB miss for load"
+_excp_message_0x13:
+ .string "Instruction address breakpoint"
+_excp_message_0x14:
+ .string "System management"
+_excp_message_0x15:
+ .string "Thermal management"
+_excp_message_0x16:
+ .string "Unknown"
+_messages_table:
+ .long _BUG_message_0
+ .long _BUG_message_1
+ .long _BUG_message_2
+ .long _BUG_message_3
+ .long _BUG_message_4
+ .long _BUG_message_5
+ .long _BUG_message_6
+_excp_messages_table:
+ .long _excp_message_0x00
+ .long _excp_message_0x01
+ .long _excp_message_0x02
+ .long _excp_message_0x03
+ .long _excp_message_0x04
+ .long _excp_message_0x05
+ .long _excp_message_0x06
+ .long _excp_message_0x07
+ .long _excp_message_0x08
+ .long _excp_message_0x09
+ .long _excp_message_0x0a
+ .long _excp_message_0x0b
+ .long _excp_message_0x0c
+ .long _excp_message_0x0d
+ .long _excp_message_0x0e
+ .long _excp_message_0x0f
+ .long _excp_message_0x10
+ .long _excp_message_0x11
+ .long _excp_message_0x12
+ .long _excp_message_0x13
+ .long _excp_message_0x14
+ .long _excp_message_0x15
+ .long _excp_message_0x16
+_last_excp_message:
+
+bios_base:
+ .long BIOS_BASE
+bios_size:
+ .long BIOS_SIZE / 4
+_dummy_0:
+ .long 0x00000000
+
+registers_area: /* To be loaded in register when an exception is caught */
+_serial_IO: /* r27 */
+ .long 0x800003F8
+_messages_start: /* r28 */
+ .long _messages_table - 4
+_excp_messages: /* r29 */
+ .long _excp_messages_table
+_max_excp: /* r30 */
+ .long (_last_excp_message - _excp_messages_table) / 4
+_dummy_1: /* r31: dummy */
+ .long 0x00000000
+
+.section .data
+.align 2
+save_area: /* Area for r11 save when an exception is skipped */
+ .long 0x00000000