diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openbios/arch/sparc64/entry.S | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openbios/arch/sparc64/entry.S')
-rw-r--r-- | qemu/roms/openbios/arch/sparc64/entry.S | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/sparc64/entry.S b/qemu/roms/openbios/arch/sparc64/entry.S new file mode 100644 index 000000000..d03128af5 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/entry.S @@ -0,0 +1,287 @@ +/** + ** Standalone startup code for Linux PROM emulator. + ** Copyright 1999 Pete A. Zaitcev + ** This code is licensed under GNU General Public License. + **/ +/* + * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $ + */ + +#define __ASSEMBLY__ +#include <asm/asi.h> +#include "pstate.h" +#include "lsu.h" +#define NO_QEMU_PROTOS +#define NO_OPENBIOS_PROTOS +#include "arch/common/fw_cfg.h" + +#define PROM_ADDR 0x1fff0000000 +#define CFG_ADDR 0x1fe02000510 +#define HZ 1 * 1000 * 1000 +#define TICK_INT_DIS 0x8000000000000000 + + .globl entry, _entry + + .section ".text", "ax" + .align 8 + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch + .register %g7, #scratch + +/* + * Entry point + * We start execution from here. + */ +_entry: +entry: + ! Set up CPU state + wrpr %g0, PSTATE_PRIV, %pstate + wr %g0, 0, %fprs + wrpr %g0, 0x0, %tl + + ! Extract NWINDOWS from %ver + rdpr %ver, %g1 + and %g1, 0xf, %g1 + dec %g1 + wrpr %g1, 0, %cleanwin + wrpr %g1, 0, %cansave + wrpr %g0, 0, %canrestore + wrpr %g0, 0, %otherwin + wrpr %g0, 0, %wstate + ! disable timer now + setx TICK_INT_DIS, %g2, %g1 + wr %g1, 0, %tick_cmpr + + ! Disable I/D MMUs and caches + stxa %g0, [%g0] ASI_LSU_CONTROL + + ! Check signature "QEMU" + setx CFG_ADDR, %g2, %g5 + mov FW_CFG_SIGNATURE, %g2 + stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L + inc %g5 + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'Q' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'E' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'M' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'U' + bne bad_conf + nop + + ! Clear ITLB + mov 6 << 3, %g1 + stxa %g0, [%g1] ASI_IMMU + stxa %g0, [%g1] ASI_DMMU + mov 63 << 3, %g1 +1: stxa %g0, [%g1] ASI_ITLB_DATA_ACCESS + subcc %g1, 1 << 3, %g1 + bpos 1b + nop + + ! Clear DTLB + mov 63 << 3, %g1 +1: stxa %g0, [%g1] ASI_DTLB_DATA_ACCESS + subcc %g1, 1 << 3, %g1 + bpos 1b + nop + + ! Get memory size from configuration device + ! NB: little endian format + mov FW_CFG_RAM_SIZE, %g2 + dec %g5 + stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L + inc %g5 + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 8, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 16, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 24, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 32, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 40, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 48, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 56, %g3 + or %g3, %g4, %g1 + ! %g1 contains end of memory + + setx _end, %g7, %g3 + set 0x7ffff, %g2 + add %g3, %g2, %g3 + andn %g3, %g2, %g3 + setx _data, %g7, %g2 + sub %g3, %g2, %g2 + sub %g1, %g2, %g2 ! %g2 = start of private memory + mov %g2, %l0 + + ! setup .data & .bss + setx _data, %g7, %g4 + sub %g3, %g4, %g5 + srlx %g5, 19, %g6 ! %g6 = # of 512k .bss pages + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x76, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv, writable + set 48, %g7 +1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _data + N * 0x80000, ctx=0 + or %g2, %g3, %g5 + ! paddr = start_mem + N * 0x80000 + stxa %g5, [%g0] ASI_DTLB_DATA_IN + set 0x80000, %g5 + add %g2, %g5, %g2 + add %g4, %g5, %g4 + deccc %g6 + bne 1b + nop + + ! setup .rodata, also make .text readable + setx _data, %g7, %g5 + setx _start, %g7, %g4 + sub %g5, %g4, %g5 + srlx %g5, 19, %g6 ! %g6 = # of 512k .rodata pages + set 48, %g7 + set 0x80000, %g5 + setx PROM_ADDR, %l1, %l2 +1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _rodata, ctx=0 + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x74, %g3 + or %l2, %g3, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv + ! paddr = _rodata + N * 0x10000 + stxa %g3, [%g0] ASI_DTLB_DATA_IN + add %g4, %g5, %g4 + deccc %g6 + bne 1b + add %l2, %g5, %l2 + + membar #Sync + + setx _start, %g7, %g4 + setx _rodata, %g7, %g5 + sub %g5, %g4, %g5 + set 0x7ffff, %g7 + add %g5, %g7, %g5 ! round to 512k + srlx %g5, 19, %g6 ! %g6 = # of 512k .text pages + set 0x80000, %g5 + set 48, %g7 + setx PROM_ADDR, %l1, %l2 +1: stxa %g4, [%g7] ASI_IMMU ! vaddr = _start, ctx=0 + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x74, %g3 + or %l2, %g3, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv + ! paddr = _start + N * 0x80000 + stxa %g3, [%g0] ASI_ITLB_DATA_IN + add %g4, %g5, %g4 + deccc %g6 + bne 1b + add %l2, %g5, %l2 + + flush %g4 + + mov %g1, %g3 + + set 8, %g2 + sta %g0, [%g2] ASI_DMMU ! set primary ctx=0 + + ! Enable I/D MMUs and caches + setx lowmem, %g2, %g1 + set LSU_CONTROL_DM|LSU_CONTROL_IM|LSU_CONTROL_DC|LSU_CONTROL_IC, %g2 + jmp %g1 + stxa %g2, [%g0] ASI_LSU_CONTROL + +lowmem: + /* Copy the DATA section from ROM. */ + setx _data - 8, %o7, %o0 ! First address of DATA + setx _bss, %o7, %o1 ! Last address of DATA + setx _start, %o7, %o2 + sub %o0, %o2, %o2 ! _data - _start + setx PROM_ADDR, %o7, %o3 + add %o3, %o2, %o2 ! PROM_ADDR + (_data - _start) + ba 2f + nop +1: + ldxa [%o2] ASI_PHYS_BYPASS_EC_E, %g1 + stx %g1, [%o0] +2: + add %o2, 0x8, %o2 + subcc %o0, %o1, %g0 + bl 1b + add %o0, 0x8, %o0 + + /* Zero out our BSS section. */ + setx _bss - 8, %o7, %o0 ! First address of BSS + setx _end - 8, %o7, %o1 ! Last address of BSS + ba 2f + nop +1: + stx %g0, [%o0] +2: + subcc %o0, %o1, %g0 + bl 1b + add %o0, 0x8, %o0 + + setx trap_table, %g2, %g1 + wrpr %g1, %tba + + setx qemu_mem_size, %g7, %g1 + stx %g3, [%g1] + + setx _data, %g7, %g1 ! Store va->pa conversion factor + sub %g1, %l0, %g2 + setx va_shift, %g7, %g1 + stx %g2, [%g1] + + /* Finally, turn on traps so that we can call c-code. */ + wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate + + ! 100 Hz timer + setx TICK_INT_DIS, %g2, %g1 + rd %tick, %g2 + andn %g2, %g1, %g2 + set HZ, %g1 + add %g1, %g2, %g1 + wr %g1, 0, %tick_cmpr + + /* Switch to our main context. + * Main context is statically defined in C. + */ + + call __switch_context_nosave + nop + + /* We get here when the main context switches back to + * the boot context. + */ +bad_conf: + b bad_conf + nop |