Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / entry.S
diff --git a/qemu/roms/openbios/arch/sparc32/entry.S b/qemu/roms/openbios/arch/sparc32/entry.S
new file mode 100644 (file)
index 0000000..72cb338
--- /dev/null
@@ -0,0 +1,532 @@
+/**
+ ** 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 "psr.h"
+#include "asm/asi.h"
+#include "asm/crs.h"
+#define NO_QEMU_PROTOS
+#define NO_OPENBIOS_PROTOS
+#include "arch/common/fw_cfg.h"
+
+#define CFG_ADDR 0x00000510
+#define CFG_ASI  0x2d
+
+#define PHYS_JJ_INTR0  0x71E00000  /* CPU0 interrupt control registers */
+
+#define PHYS_SS10_INTR0        0xf1400000
+
+#define PHYS_SS2_INTR0         0xf5000000
+#define SER_ADDR2       0xf1000004
+
+#define PHYS_SS1000_SBI         0x02800000
+#define SER_ADDR1000            0x00200004
+
+#define WRITE_PAUSE    nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+        .globl entry, _entry
+
+       .section ".text", "ax"
+       .align  8
+
+        /* Memory map:
+        *
+        * Top +-------------------------+
+        *     | SMP CPU table           |
+        *     | s + 0x1f00 ... 0x1f0f   |
+        *     | s + 0x1f0c valid        |
+        *     | s + 0x1f08 entry        |
+        *     | s + 0x1f04 ctxtbl       |
+        *     | s + 0x1f00 ctx          |
+        *     +-------------------------+
+        *     | Bootstrap               |
+        *     | MMU L3 tables 8 * 0x100 |
+        *     | s + 0xa00 ... 0x11ff    |
+        *     +-------------------------+
+        *     | Bootstrap               |
+        *     | MMU L2 tables 2 * 0x100 |
+        *     | s + 0x800 ... 0x9ff     |
+        *     +-------------------------+
+        *     | Bootstrap               |
+        *     | MMU L1 table 0x400      |
+        *     | s + 0x400 ... 0x7ff     |
+        *     +-------------------------+
+        *     | Bootstrap               |
+        *     | MMU L0/ctx table 0x400  |
+        *     | s + 0x000 ... 0x3ff     |
+        *     +-------------------------+
+        *     |                         |
+        *     | ROM into RAM            |
+        *     |                         |
+        *     +-------------------------+
+        *     :                         :
+        * Bottom
+        */
+
+/*
+ * Entry point
+ * We start execution from here.
+ */
+_entry:
+entry:
+        /* Switch to our main context.
+         * Main context is statically defined in C.
+         */
+
+        ! Check signature "QEMU"
+        set     CFG_ADDR, %g5
+        mov     FW_CFG_SIGNATURE, %g2
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g2
+        cmp     %g2, 'Q'
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
+        cmp     %g2, 'E'
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
+        cmp     %g2, 'M'
+        bne     bad_conf
+         nop
+        lduba   [%g5] CFG_ASI, %g2
+        cmp     %g2, 'U'
+        bne     bad_conf
+         nop
+
+        ! Get memory size from configuration device
+        ! NB: little endian format
+        mov     FW_CFG_RAM_SIZE, %g2
+        sub     %g5, 2, %g5
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 8, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 16, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 24, %g3
+        or      %g3, %g4, %g1
+        ! %g1 contains end of memory
+
+        ! Get kernel address from configuration device
+        ! NB: little endian format
+        mov     FW_CFG_KERNEL_ADDR, %g2
+        sub     %g5, 2, %g5
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 8, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 16, %g3
+        or      %g3, %g4, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 24, %g3
+        or      %g3, %g4, %g4
+
+        ! If kernel address is set, don't clear from base of RAM in order to
+        ! leave the kernel image intact
+        mov     0, %g6
+        cmp     %g4, 0
+        beq     clear_mem
+         nop
+
+        ! Start from 16M
+        set     0x1000000, %g6
+
+clear_mem:
+        sta     %g0, [%g6] ASI_M_BYPASS
+        add     %g6, 0x4, %g6
+        cmp     %g6, %g1
+        bl      clear_mem
+         nop
+
+clear_done:
+        ! Start of private memory in %g6
+        set     0x2000, %g3
+        sub     %g1, %g3, %g6
+
+        ! Check if this is the boot CPU and skip SMP table check if yes
+        ! XXX: not all CPUs should have MXCC
+        set     0x1c00f00, %g2
+        ldda    [%g2] ASI_CONTROL, %g2
+        srl     %g3, 24, %g7
+        sub     %g7, 8, %g7
+        tst     %g7
+        bz      skip_table
+         nop
+
+        ! Calculate SMP table location
+       set     0x1f0c, %g2
+        add     %g6, %g2, %g2                 ! valid?
+        lda     [%g2] ASI_M_BYPASS, %g7
+        sta     %g0, [%g2] ASI_M_BYPASS
+
+skip_table:
+        ! Get machine ID from configuration device
+        mov     FW_CFG_MACHINE_ID, %g2
+        sub     %g5, 2, %g5
+        stha    %g2, [%g5] CFG_ASI
+        add     %g5, 2, %g5
+        lduba   [%g5] CFG_ASI, %g4
+
+        lduba   [%g5] CFG_ASI, %g3
+        sll     %g3, 8, %g3
+        or      %g3, %g4, %g4
+        mov     %g4, %y
+
+        cmp     %g4, 96
+        bgeu    ss1000
+         cmp    %g4, 64
+        bgeu    ss10
+         cmp    %g4, 32
+        blu     ss2
+         nop
+
+        ! Ok, this is SS-5
+
+        tst     %g7
+        bz      first_cpu
+         nop
+
+        ! Clear softints used for SMP CPU startup
+        set     PHYS_JJ_INTR0 + 0x04, %g1
+        sll     %g2, 12, %g2
+        add     %g1, %g2, %g2
+        set     0xffffffff, %g1
+        sta     %g1, [%g2] ASI_M_BYPASS         ! clear softints
+        add     %g2, 4, %g2
+        sta     %g0, [%g2] ASI_M_BYPASS         ! clear softints
+
+load_ctx:
+        ! SMP init, jump to user specified address
+       set     0x1f04, %g5
+        add     %g6, %g5, %g5                 ! ctxtbl
+        lda     [%g5] ASI_M_BYPASS, %g2
+        sta     %g0, [%g5] ASI_M_BYPASS
+        set     AC_M_CTPR, %g1
+        sta     %g2, [%g1] ASI_M_MMUREGS        ! set ctx table ptr
+       set     0x1f00, %g5
+        add     %g6, %g5, %g5                 ! ctx
+        lda     [%g5] ASI_M_BYPASS, %g2
+        sta     %g0, [%g5] ASI_M_BYPASS
+        set     AC_M_CXR, %g1
+        sta     %g2, [%g1] ASI_M_MMUREGS        ! set context
+       set     0x1f08, %g5
+        add     %g6, %g5, %g5                 ! entry
+        lda     [%g5] ASI_M_BYPASS, %g2
+        sta     %g0, [%g5] ASI_M_BYPASS
+        set     1, %g1
+        jmp     %g2                             ! jump to kernel
+         sta    %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
+
+ss10:
+        ! Ok, this is SS-10 or SS-600MP
+        tst     %g7
+        bz      first_cpu
+         nop
+
+        ! Clear softints used for SMP CPU startup
+        set     PHYS_SS10_INTR0 + 0x04, %g1
+        sll     %g2, 12, %g2
+        add     %g1, %g2, %g2
+        set     0xffffffff, %g1
+        sta     %g1, [%g2] ASI_M_CTL            ! clear softints
+        add     %g2, 4, %g2
+        b       load_ctx
+         sta    %g0, [%g2] ASI_M_CTL            ! clear softints
+
+ss2:
+        ! Ok, this is SS-2
+        set     ss2_error, %o2
+        b       ss2_ss1000_halt
+         nop
+
+ss1000:
+        ! Ok, this is SS-1000 or SS-2000
+        set     ss1000_error, %o2
+        b       ss2_ss1000_halt
+         nop
+
+first_cpu:
+        /* Create temporary page tables and map the ROM area to end of
+       RAM. This will be done properly in iommu.c later. */
+        ! Calculate start of page tables etc. to %g6
+        set     0x2000, %g4
+        sub     %g1, %g4, %g6                   ! start of private memory
+
+        mov     %g6, %g2                        ! ctx table at s+0x0
+        add    %g2, 0x400, %g3                 ! l1 table at s+0x400
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 0x400, %g2                 ! s+0x400
+        add    %g2, 0x400, %g3                 ! l2 table for ram (00xxxxxx) at s+0x800
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 0x500, %g3                 ! l2 table for rom (ffxxxxxx) at s+0x900
+        add    %g2, 0x3fc, %g2                 ! s+0x7fc
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 0x4, %g2                   ! s+0x800
+#if 0
+        set     0x40, %g6
+        set    ((7 << 2) | 2), %g3             ! 7 = U: --- S: RWX (main memory)
+1:      sta    %g3, [%g2] ASI_M_BYPASS
+        add     %g2, 4, %g2
+        deccc   %g6
+        bne     1b
+         nop
+#else
+        add     %g2, 0x100, %g2
+#endif
+                                                ! s+0x900
+        add    %g2, 0xa00 - 0x900, %g3         ! l3 table for rom at s+0xa00
+        add    %g2, 0x0d0, %g2                 ! s+0x9d0
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9d4
+        add    %g2, 0xb00 - 0x9d4, %g3         ! 2nd l3 table for rom at s+0xb00
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9d8
+        add    %g2, 0xc00 - 0x9d8, %g3         ! 3rd l3 table for rom at s+0xc00
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9dc
+        add    %g2, 0xd00 - 0x9dc, %g3         ! 4th l3 table for rom at s+0xd00
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9e0
+        add    %g2, 0xe00 - 0x9e0, %g3         ! 5th l3 table for rom at s+0xe00
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9e4
+        add    %g2, 0xf00 - 0x9e4, %g3         ! 6th l3 table for rom at s+0xf00
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9e8
+        add    %g2, 0x1000 - 0x9e8, %g3        ! 7th l3 table for rom at s+0x1000
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2                     ! s+0x9ec
+        add    %g2, 0x1100 - 0x9ec, %g3        ! 8th l3 table for rom at s+0x1100
+        srl    %g3, 0x4, %g3
+        or     %g3, 0x1, %g3
+        sta    %g3, [%g2] ASI_M_BYPASS
+      add      %g2, 0xa00-0x9ec, %g2           ! s+0xa00
+
+        /* Use end of ram for code, rodata, data, and bss
+       sections. SunOS wants to write to trap table... */
+        set    _end, %g6
+        set    _start, %g4
+        sub     %g6, %g4, %g6
+        sub     %g1, %g6, %g3
+        set    0x1000, %g5
+        sub     %g3, %g5, %g3
+        sub     %g3, %g5, %g3                   ! start of ROM copy
+        mov     %g3, %g7                        ! save in %g7
+        srl     %g6, 12, %g6                    ! # of all pages
+1:      srl    %g3, 0x4, %g4
+        or     %g4, ((7 << 2) | 2), %g4        ! 7 = U: --- S: RWX
+        sta    %g4, [%g2] ASI_M_BYPASS
+        add    %g2, 4, %g2
+        add    %g3, %g5, %g3
+        deccc  %g6
+        bne    1b
+         nop
+
+        mov    %g1, %g6                        ! %g6 = memory size
+
+        /* Copy the code, rodata and data sections from ROM. */
+        sub     %g7, 4, %g3
+        set    _start - 4, %g4                 ! First address of TEXT - 4
+        set    _bss, %g5                       ! Last address of DATA
+        ba     2f
+         nop
+1:
+        lda     [%g4] ASI_M_KERNELTXT, %g1
+        sta    %g1, [%g3] ASI_M_BYPASS
+2:
+        cmp     %g4, %g5
+        add     %g3, 0x4, %g3
+        bl      1b
+         add    %g4, 0x4, %g4
+
+        set     0x2000, %g3
+        sub     %g6, %g3, %g7                   ! ctx table at s+0x0
+        set     AC_M_CTPR, %g2
+        srl     %g7, 4, %g7
+        sta     %g7, [%g2] ASI_M_MMUREGS       ! set ctx table ptr
+        set     AC_M_CXR, %g2
+        sta     %g0, [%g2] ASI_M_MMUREGS       ! context 0
+        set     highmem, %g2
+        set    1, %g1
+        jmp     %g2
+         sta    %g1, [%g0] ASI_M_MMUREGS       ! enable mmu
+highmem:
+        /*
+         * The code which enables traps is a simplified version of
+         * kernel head.S.
+         *
+         * We know number of windows as 8 so we do not calculate them.
+         * The deadwood is here for any case.
+         */
+
+        /* Turn on Supervisor, EnableFloating, and all the PIL bits.
+         * Also puts us in register window zero with traps off.
+         */
+        set    (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
+        wr     %g2, 0x0, %psr
+        WRITE_PAUSE
+
+        /* Zero out our BSS section. */
+        set    _bss - 4, %o0           ! First address of BSS
+        set    _estack - 4, %o1        ! Last address of BSS
+        ba     2f
+         nop
+1:
+        st     %g0, [%o0]
+2:
+        subcc  %o0, %o1, %g0
+        bl     1b
+         add   %o0, 0x4, %o0
+
+        set     trap_table, %g1
+        wr      %g1, 0x0, %tbr
+
+        set     qemu_mem_size, %g1
+        st      %g6, [%g1]
+
+        set     _end, %o0                       ! Store va->pa conversion factor
+        set     _start, %o2
+        sub     %o0, %o2, %o0
+        sub     %g6, %o0, %o0
+        set     0x2000, %o1
+        sub     %o0, %o1, %o0                   ! start of ROM copy
+        sub     %o2, %o0, %o0                   ! start of ROM copy
+        set     va_shift, %g1
+        st      %o0, [%g1]
+
+        set     qemu_machine_type, %g1
+        mov     %y, %g2
+        st      %g2, [%g1]
+
+        /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
+         * in the V8 manual. Ok, this method seems to work, Sparc is cool...
+         * No, it doesn't work, have to play the save/readCWP/restore trick.
+         */
+
+        wr      %g0, 0x0, %wim                  ! so we do not get a trap
+        WRITE_PAUSE
+
+        save
+
+        rd      %psr, %g3
+
+        restore
+
+        and     %g3, 0x1f, %g3
+        add     %g3, 0x1, %g3
+
+        mov     2, %g1
+        wr      %g1, 0x0, %wim                  ! make window 1 invalid
+        WRITE_PAUSE
+
+        cmp     %g3, 0x7
+        bne     1f
+         nop
+
+        /* Adjust our window handling routines to
+         * do things correctly on 7 window Sparcs.
+         */
+#define PATCH_INSN(src, dest) \
+        set     src, %g5; \
+        set     dest, %g2; \
+        ld      [%g5], %g4; \
+        st      %g4, [%g2];
+
+        /* Patch for window spills... */
+        PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
+        PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
+
+        /* Patch for window fills... */
+        PATCH_INSN(fnwin_patch1_7win, fnwin_patch1)
+        PATCH_INSN(fnwin_patch2_7win, fnwin_patch2)
+
+1:
+        /* Finally, turn on traps so that we can call c-code. */
+        rd     %psr, %g3
+        wr     %g3, 0x0, %psr
+        WRITE_PAUSE
+
+        wr     %g3, PSR_ET, %psr
+        WRITE_PAUSE
+
+        set     0, %fp
+        call    __switch_context_nosave
+         nop
+
+        /* We get here when the main context switches back to
+         * the boot context.
+         * Return to previous bootloader.
+         */
+        ret
+         nop
+
+ss2_ss1000_halt:
+        set     SER_ADDR2, %o0
+        set     SER_ADDR1000, %o1
+        mov     0x05, %o3 /* Reg 5, TXCTRL2 */
+        stba    %o3, [%o0] ASI_M_BYPASS
+        stba    %o3, [%o1] ASI_M_CTL
+        mov     0x68, %o3 /* 8 bits, Tx enabled */
+        stba    %o3, [%o0] ASI_M_BYPASS
+        stba    %o3, [%o1] ASI_M_CTL
+        add     %o0, 2, %o0
+        add     %o1, 2, %o1
+
+1:      lduba   [%o2] ASI_M_KERNELTXT, %o3
+        cmp     %o3, 0
+        be      2f
+         nop
+        stba    %o3, [%o0] ASI_M_BYPASS
+        stba    %o3, [%o1] ASI_M_CTL
+        b       1b
+         inc    %o2
+bad_conf:
+2:      b       2b
+         nop
+
+        .section .rodata
+ss2_error:
+        .string "Sun4c machines are not supported by OpenBIOS yet, freezing\r\n"
+ss1000_error:
+        .string "Sun4d machines are not supported by OpenBIOS yet, freezing\r\n"