Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc64 / entry.S
diff --git a/qemu/roms/openbios/arch/sparc64/entry.S b/qemu/roms/openbios/arch/sparc64/entry.S
new file mode 100644 (file)
index 0000000..d03128a
--- /dev/null
@@ -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