<<>> Apr. 25, 2001 Masahiro ABE (C) 2001 A&D Co., Ltd. -------------------------------------------------------------------------------- 0. Table of contents 1. Preface 2. What is sh-ipl+g? 3. Memory Map 4. Sequence of System Start-up 5. Exception and Interrupt Handling 5.1 VBR 5.2 Types of Exception Handlers 5.3 Entry Point of Exception Handling - general_exception/tlb_miss/interrupt (entry.S) 5.4 Dispatch to the Actual Handler - do_exception (entry.S) 5.5 Actual Exception Handlers 5.5.1 Address Error - address_error_load/store 5.5.2 Non-Maskable Interrupt - nmi 5.5.3 Other Exceptions - unconditional_trap, reserved_instruction, illegal_slot_instruction, user_break 5.5.4 Interrupts - do_IRQ 5.5.5 Timer Interrupt - do_timer 5.5.6 SCIF Break Interrupt - break 5.6 Handling BIOS call - handle_bios_call (main.c) 5.7 gdb exception handling - gdb_handle_exception (sh-stub.c) -------------------------------------------------------------------------------- 1. Preface This document is the result of analysis of execution sequence of "sh-ipl+g" by reading source code. "sh-ipl+g" is used as IPL(Initial Program Loader) among GNU/Linux on SuperH project. This is written based on source code of sh-ipl+g Ver.0.8(2001/01/13). This document must contain many wrong, misunderstood information because of lack of knowledge of the author. When you find them, please kindly notify me. This document is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. Author assumes no responsibility to the contents of this document. Anyone can display and/or copy the document for any purpose. All explanation is based on the case that SolutionEngine(MS7750SE01) of Hitachi ULSI Systems Co. Ltd., is used and executed from CompactFlash I would like to appreciate everyone on the GNU/Linux on SuperH project, and especially Mr. NIIBE Yutaka who is the author of sh-ipl+g. [Attention] Because of my interests, this document focuses on the analysis of sh-ipl+g as IPL, and doesn't give any explanation about the other important function: gdb-stub. I wish someone may contribute some on that subject in the future. Also I must admit that I've never read any SH-related document in English. There are several places I mention about them, but those are of Japanese documents, and exact wording might be different. Or, even such document may not exist. If you notice some, please clarify me. -------------------------------------------------------------------------------- 2. What is sh-ipl+g? It is an Initial Program Loader(IPL) of many SH-based systems booting Linux kernel. It functions as gdb-stub to provide the way to communicate with GNU gdb debugger. Also, it acts as a BIOS of the system. -------------------------------------------------------------------------------- 3. Memory Map sh-ipl+g is usually placed in the EPROM or FlashROM located at address 0x00000000. SuperH CPU starts execution from 0xa0000000(P2 area) on reset or power up. That address represents same external address as 0x00000000. This fact proves that this program is the one first executed on the system. By the way, linker script(sh-stub.lds.S or machine/sesh4.mem) specifies that this program be located at 0x80000000. This is also same external address as 0x00000000, and it is in P1 area. Every addresses inside this program are allocated regarding this specification(You can see this by objdump-ing sh-stub.exe). (???entry.S has comments that VBR be located in P2 area???) Here is the summary of memory map. external mem. P1 area media contents 0x 0000 0000 0x 8000 0000---------------------------------------------------- FlashROM code of start(entry.S) 0x 0000 0100 0x 8000 0100 -------------------------------- exception handler(general_exception) 0x 0000 0400 0x 8000 0400 -------------------------------- exception handler(tlb_miss) 0x 0000 0600 0x 8000 0600 -------------------------------- exception handler(interrupt) exception handling table actual handler code code of main.c 0x 0400 0000 0x 8400 0000---------------------------------------------------- 0x 0c00 0000 0x 8c00 0000---------------------------------------------------- RAM global variable of sh-ipl+g 0x 0c00 0a00 0x 8c00 0a00 -------------------------------- stack area of sh-ipl+g 0x 0c00 0f00 0x 8c00 0f00 -------------------------------- 0x 0c20 0000 0x 8c20 0000 -------------------------------- MBR will be loaded here 0x 1000 0000 0x 9000 0000---------------------------------------------------- (???stack size seems 1280 byte, not 1536???) -------------------------------------------------------------------------------- 4. Sequence of System Start-up It is defined in the Makefile that the assembled code of entry.S be located at the beginning of sh-stub.exe. This means that function "start" is the entry point of sh-ipl+g. 4.1 start (entry.S) function "start" does the following. -disable cache -initialize BSC(Bus State Controller)-->init_bsc(init_xxx.S) -initialize cache -initialize VBR(Vector Base Register) -initialize SR(Status Register) -initialize stack area used by sh-ipl+g -zero-clear BSS area -initialize serial port-->init_serial(sh-sci.c) -(if specified at config time)initialize IDE--->init_ide(ide.c) -jump to the next function--->start_main(main.c) These are pretty much primitive operations, do only absolutely necessary jobs. BSC must be initialized before linux kernel boots. It must be initialized so that it suits each individual machine/board setting, so init_xx.S are prepared for for each of them. This means that if one wants port sh-ipl+g and kernel to new machine, init_xx.S must be prepared. VBR, used for exception and interrupt handling, is initialized in this routine. Meaning of value and the way to handle them are described in the later chapter. 4.2 start_main (main.c) This function waits for the input after displaying banner message. When "b" is pressed, control flows like this: -ide_detect_devices (ide.c) -ide_reset (ide.c) -ide_device_selection (ide.c) -ide_register_check (ide.c) -ide_identify_device (ide.c) -ide_startup_devices (ide.c) -ide_set_transfer_mode (ide.c) -ide_set_device_params (ide.c) -ide_idle (ide.c) -boot (main.c) "boot" calls up BIOS by issuing trapa instruction to load the first sector(MBR) of IDE device to the address specified as CONFIG_RAM_BOOT, and jumps to there. (Please see the next chapter about trapa exception handling sequence.) MBR should contain boot loader, written by lilo. Control moves there from here. Please see the sh-lilo document for further sequence. -------------------------------------------------------------------------------- 5. Exception and Interrupt Handling It is said that VBR is set up inside "start"(entry.S). Here I add some explanation, and describe the sequence when actual exception or interrupt occurs. 5.1 VBR VBR of SH3/4 should point the base address of exception handler. When exception or interrupt occurs, control jumps to the location pointed by VBR with certain offset based on the kind of exception/interrupt. (Some cases don't use VBR, but here I want to simplify explanation and omit them.) 5.2 Types of Exception Handlers There are three kinds of exceptions, categorized by the offset of the handler from VBR. (See "SH-4 Hardware Manual" from Hitachi Semiconductor for detail) -General exception(exclude TLB miss and interrupts) --- VBR + 0x100 -TLB miss exception --- VBR + 0x400 -Interrupts(both external and internal modules) --- VBR + 0x600 sh-ipl+g sets the address of "start" function to VBR, and locates those three entry points with certain offset. -VBR + 0x100 --- general_exception -VBR + 0x400 --- tlb_miss -VBR + 0x600 --- interrupt Here I explain those entries. 5.3 Entry Point of Exception Handling - general_exception/tlb_miss/interrupt (entry.S) When the control reach one of those entry points, exception code is set to EXPEVT register for the first two entries, and INTEVT for the last entry. Then the contents of one of those register is copied to r2 register, and control jumps to "do_exception". 5.4 Dispatch to the Actual Handler - do_exception (entry.S) This part does the following: -Change register bank to RB=0 -Right-shift exception code by three bits -Jump to the address specified by exception_handling_table and shifted exception code exception_handling_table has the address of actual handlers. Those are like these. Exception code Entry -0x0E0 - address_error_load -0x100 - address_error_store -0x160 - unconditional_trap -0x180 - reserved_instruction -0x1A0 - illegal_slot_instruction -0x1C0 - nmi -0x1E0 - user_break -0x200->0x3C0, 0x420->0x720, 0x760 - do_IRQ -0x400 - do_timer -0x740 - break These entries are all defined in entry.S. 5.5 Actual Exception Handlers Here I explain each entry. 5.5.1 Address Error - address_error_load/store This handles instruction address error and data address error(both read/write). "dofault" variable defined in sh_stub.c changes the way of handling. If dofault=1, (???jumps to the label 1, but label 1 is at handleError entry???) If dofault=0, jumps to the "handle_buserror"(sh_stub.c) function. 5.5.2 Non-Maskable Interrupt - nmi Pushes r0 and r1 to the stack and rte, when not nesting NMI. 5.5.3 Other Exceptions - unconditional_trap, reserved_instruction, illegal_slot_instruction, user_break They do following: -reserve 4 bytes on the stack -push r0 and r1 to the stack -enable interrupt -store exception code to the reserved area on the stack -jump to saveRegisters Then in the saveRegisters, -Store registers to "registers" variable -execute "handle_exception"(sh-stub.c) with exception code as an argument -jump to restoreRegisters, which restore registers and rte Inside "handle_exception", it calls "handle_bios_call"(main.c) if exception is BIOS_CALL_TRAP(0x3f), or "gdb_handle_exception"(sh-stub.c) otherwise. I'll add some explanation about those later. 5.5.4 Interrupts - do_IRQ This does nothing but rte. 5.5.5 Timer Interrupt - do_timer This sets timer control register of channel 1 as following and rte. (???Writing 0xfeff but bit15-9,7,6 are reserved and said to write 0???) -underflow flag UNF <- 0 -underflow interrupt control UNIE <- 1 -clock edge CKEG0/1 <- 1 -timer prescaler TPSC0-2 <- 1 5.5.6 SCIF Break Interrupt - break Interrupt of SCIF(serial with FIFO) break is handled as following: -push r0,r1,r2,r3 to the stack -jump to handleError(sh-sci.c) -pop r3 and r2 from stack -jump to "enable interrupts" of 4.4.3 -...same as 4.4.3 "handleError" does the following. -clear Serial Status Register (???Writing 0x0063 but it is said that we can't write 1(Hardware manual 16.2.7) ???) -clear Line Control Register 5.6 Handling BIOS call - handle_bios_call (main.c) handle_bios_call responds to the BIOS requests. There are following functionalities provided. Number is the kind of request, and it is passed using r0 when trapa issued. 0 : Serial output 1 : Serial input 2 : Read sector from secondary storage 3 : Query System Feature 4 : Query Memory size 5 : Query IO base address 6 : Cache control (enable/disable) 7 : Reset Ethernet 8 : Transmit with Ethernet 9 : Receive from Ethernet 10 : Query Ethernet address 11 : Shutdown/Restart 12 : Operate on RealTimeClock(Initialize, start, stop, read, write, sleep) 31 : Serial output one char 32 : Serial output string 254 : Query gdb communication mode 255 : Exit from gdb communication mode Not all features above are available for all configuration. It is determined by the configuration detail at config time. 5.7 gdb exception handling - gdb_handle_exception (sh-stub.c) --- to be written by someone, later ---