summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/sparc64/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/sparc64/entry.S')
-rw-r--r--qemu/roms/openbios/arch/sparc64/entry.S287
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