Merge branch 'audit.b3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit...
[powerpc.git] / arch / sparc64 / kernel / head.S
index 2434049..3eadac5 100644 (file)
 #include <asm/head.h>
 #include <asm/ttable.h>
 #include <asm/mmu.h>
+#include <asm/cpudata.h>
        
 /* This section from from _start to sparc64_boot_end should fit into
- * 0x0000.0000.0040.4000 to 0x0000.0000.0040.8000 and will be sharing space
- * with bootup_user_stack, which is from 0x0000.0000.0040.4000 to
- * 0x0000.0000.0040.6000 and empty_bad_page, which is from
- * 0x0000.0000.0040.6000 to 0x0000.0000.0040.8000. 
+ * 0x0000000000404000 to 0x0000000000408000.
  */
-
        .text
        .globl  start, _start, stext, _stext
 _start:
 start:
 _stext:
 stext:
-bootup_user_stack:
 ! 0x0000000000404000
        b       sparc64_boot
         flushw                                 /* Flush register file.      */
@@ -99,12 +95,17 @@ sparc64_boot:
        wrpr    %g1, 0x0, %pstate
        ba,a,pt %xcc, 1f
 
-       .globl  prom_finddev_name, prom_chosen_path
-       .globl  prom_getprop_name, prom_mmu_name
-       .globl  prom_callmethod_name, prom_translate_name
+       .globl  prom_finddev_name, prom_chosen_path, prom_root_node
+       .globl  prom_getprop_name, prom_mmu_name, prom_peer_name
+       .globl  prom_callmethod_name, prom_translate_name, prom_root_compatible
        .globl  prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
        .globl  prom_boot_mapped_pc, prom_boot_mapping_mode
        .globl  prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
+       .globl  is_sun4v
+prom_peer_name:
+       .asciz  "peer"
+prom_compatible_name:
+       .asciz  "compatible"
 prom_finddev_name:
        .asciz  "finddevice"
 prom_chosen_path:
@@ -121,7 +122,13 @@ prom_map_name:
        .asciz  "map"
 prom_unmap_name:
        .asciz  "unmap"
+prom_sun4v_name:
+       .asciz  "sun4v"
        .align  4
+prom_root_compatible:
+       .skip   64
+prom_root_node:
+       .word   0
 prom_mmu_ihandle_cache:
        .word   0
 prom_boot_mapped_pc:
@@ -133,8 +140,54 @@ prom_boot_mapping_phys_high:
        .xword  0
 prom_boot_mapping_phys_low:
        .xword  0
+is_sun4v:
+       .word   0
 1:
        rd      %pc, %l0
+
+       mov     (1b - prom_peer_name), %l1
+       sub     %l0, %l1, %l1
+       mov     0, %l2
+
+       /* prom_root_node = prom_peer(0) */
+       stx     %l1, [%sp + 2047 + 128 + 0x00]  ! service, "peer"
+       mov     1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 1
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
+       stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1, 0
+       stx     %g0, [%sp + 2047 + 128 + 0x20]  ! ret1
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
+       ldx     [%sp + 2047 + 128 + 0x20], %l4  ! prom root node
+       mov     (1b - prom_root_node), %l1
+       sub     %l0, %l1, %l1
+       stw     %l4, [%l1]
+
+       mov     (1b - prom_getprop_name), %l1
+       mov     (1b - prom_compatible_name), %l2
+       mov     (1b - prom_root_compatible), %l5
+       sub     %l0, %l1, %l1
+       sub     %l0, %l2, %l2
+       sub     %l0, %l5, %l5
+
+       /* prom_getproperty(prom_root_node, "compatible",
+        *                  &prom_root_compatible, 64)
+        */
+       stx     %l1, [%sp + 2047 + 128 + 0x00]  ! service, "getprop"
+       mov     4, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x08]  ! num_args, 4
+       mov     1, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 1
+       stx     %l4, [%sp + 2047 + 128 + 0x18]  ! arg1, prom_root_node
+       stx     %l2, [%sp + 2047 + 128 + 0x20]  ! arg2, "compatible"
+       stx     %l5, [%sp + 2047 + 128 + 0x28]  ! arg3, &prom_root_compatible
+       mov     64, %l3
+       stx     %l3, [%sp + 2047 + 128 + 0x30]  ! arg4, size
+       stx     %g0, [%sp + 2047 + 128 + 0x38]  ! ret1
+       call    %l7
+        add    %sp, (2047 + 128), %o0          ! argument array
+
        mov     (1b - prom_finddev_name), %l1
        mov     (1b - prom_chosen_path), %l2
        mov     (1b - prom_boot_mapped_pc), %l3
@@ -191,8 +244,9 @@ prom_boot_mapping_phys_low:
        stx     %l3, [%sp + 2047 + 128 + 0x10]  ! num_rets, 5
        stx     %l2, [%sp + 2047 + 128 + 0x18]  ! arg1: "translate"
        stx     %l5, [%sp + 2047 + 128 + 0x20]  ! arg2: prom_mmu_ihandle_cache
-       srlx    %l0, 22, %l3
-       sllx    %l3, 22, %l3
+       /* PAGE align */
+       srlx    %l0, 13, %l3
+       sllx    %l3, 13, %l3
        stx     %l3, [%sp + 2047 + 128 + 0x28]  ! arg3: vaddr, our PC
        stx     %g0, [%sp + 2047 + 128 + 0x30]  ! res1
        stx     %g0, [%sp + 2047 + 128 + 0x38]  ! res2
@@ -211,6 +265,9 @@ prom_boot_mapping_phys_low:
        ldx     [%sp + 2047 + 128 + 0x48], %l2  ! physaddr high
        stx     %l2, [%l4 + 0x0]
        ldx     [%sp + 2047 + 128 + 0x50], %l3  ! physaddr low
+       /* 4MB align */
+       srlx    %l3, 22, %l3
+       sllx    %l3, 22, %l3
        stx     %l3, [%l4 + 0x8]
 
        /* Leave service as-is, "call-method" */
@@ -239,6 +296,27 @@ prom_boot_mapping_phys_low:
        add     %sp, (192 + 128), %sp
 
 sparc64_boot_after_remap:
+       sethi   %hi(prom_root_compatible), %g1
+       or      %g1, %lo(prom_root_compatible), %g1
+       sethi   %hi(prom_sun4v_name), %g7
+       or      %g7, %lo(prom_sun4v_name), %g7
+       mov     5, %g3
+1:     ldub    [%g7], %g2
+       ldub    [%g1], %g4
+       cmp     %g2, %g4
+       bne,pn  %icc, 2f
+        add    %g7, 1, %g7
+       subcc   %g3, 1, %g3
+       bne,pt  %xcc, 1b
+        add    %g1, 1, %g1
+
+       sethi   %hi(is_sun4v), %g1
+       or      %g1, %lo(is_sun4v), %g1
+       mov     1, %g7
+       stw     %g7, [%g1]
+
+2:
+       BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
        BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
        BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
        ba,pt   %xcc, spitfire_boot
@@ -302,20 +380,58 @@ jump_to_sun4u_init:
         nop
 
 sun4u_init:
+       BRANCH_IF_SUN4V(g1, sun4v_init)
+
        /* Set ctx 0 */
-       mov     PRIMARY_CONTEXT, %g7
-       stxa    %g0, [%g7] ASI_DMMU
-       membar  #Sync
+       mov             PRIMARY_CONTEXT, %g7
+       stxa            %g0, [%g7] ASI_DMMU
+       membar          #Sync
 
-       mov     SECONDARY_CONTEXT, %g7
-       stxa    %g0, [%g7] ASI_DMMU
+       mov             SECONDARY_CONTEXT, %g7
+       stxa            %g0, [%g7] ASI_DMMU
        membar  #Sync
 
-       BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
+       ba,pt           %xcc, sun4u_continue
+        nop
+
+sun4v_init:
+       /* Set ctx 0 */
+       mov             PRIMARY_CONTEXT, %g7
+       stxa            %g0, [%g7] ASI_MMU
+       membar          #Sync
+
+       mov             SECONDARY_CONTEXT, %g7
+       stxa            %g0, [%g7] ASI_MMU
+       membar          #Sync
+       ba,pt           %xcc, niagara_tlb_fixup
+        nop
+
+sun4u_continue:
+       BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
 
        ba,pt   %xcc, spitfire_tlb_fixup
         nop
 
+niagara_tlb_fixup:
+       mov     3, %g2          /* Set TLB type to hypervisor. */
+       sethi   %hi(tlb_type), %g1
+       stw     %g2, [%g1 + %lo(tlb_type)]
+
+       /* Patch copy/clear ops.  */
+       call    niagara_patch_copyops
+        nop
+       call    niagara_patch_bzero
+        nop
+       call    niagara_patch_pageops
+        nop
+
+       /* Patch TLB/cache ops.  */
+       call    hypervisor_patch_cachetlbops
+        nop
+
+       ba,pt   %xcc, tlb_fixup_done
+        nop
+
 cheetah_tlb_fixup:
        mov     2, %g2          /* Set TLB type to cheetah+. */
        BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
@@ -382,69 +498,85 @@ tlb_fixup_done:
         nop
        /* Not reached... */
 
-/* IMPORTANT NOTE: Whenever making changes here, check
- * trampoline.S as well. -jj */
-       .globl  setup_tba
-setup_tba:     /* i0 = is_starfire */
-       save    %sp, -160, %sp
-
-       rdpr    %tba, %g7
-       sethi   %hi(prom_tba), %o1
-       or      %o1, %lo(prom_tba), %o1
-       stx     %g7, [%o1]
+       /* This is meant to allow the sharing of this code between
+        * boot processor invocation (via setup_tba() below) and
+        * secondary processor startup (via trampoline.S).  The
+        * former does use this code, the latter does not yet due
+        * to some complexities.  That should be fixed up at some
+        * point.
+        *
+        * There used to be enormous complexity wrt. transferring
+        * over from the firwmare's trap table to the Linux kernel's.
+        * For example, there was a chicken & egg problem wrt. building
+        * the OBP page tables, yet needing to be on the Linux kernel
+        * trap table (to translate PAGE_OFFSET addresses) in order to
+        * do that.
+        *
+        * We now handle OBP tlb misses differently, via linear lookups
+        * into the prom_trans[] array.  So that specific problem no
+        * longer exists.  Yet, unfortunately there are still some issues
+        * preventing trampoline.S from using this code... ho hum.
+        */
+       .globl  setup_trap_table
+setup_trap_table:
+       save    %sp, -192, %sp
 
-       /* Setup "Linux" globals 8-) */
+       /* Force interrupts to be disabled. */
        rdpr    %pstate, %o1
-       mov     %g6, %o2
-       wrpr    %o1, (PSTATE_AG|PSTATE_IE), %pstate
-       sethi   %hi(sparc64_ttable_tl0), %g1
-       wrpr    %g1, %tba
-       mov     %o2, %g6
+       andn    %o1, PSTATE_IE, %o1
+       wrpr    %o1, 0x0, %pstate
+       wrpr    %g0, 15, %pil
+
+       /* Make the firmware call to jump over to the Linux trap table.  */
+       sethi   %hi(is_sun4v), %o0
+       lduw    [%o0 + %lo(is_sun4v)], %o0
+       brz,pt  %o0, 1f
+        nop
 
-       /* Set up MMU globals */
-       wrpr    %o1, (PSTATE_MG|PSTATE_IE), %pstate
+       TRAP_LOAD_TRAP_BLOCK(%g2, %g3)
+       add     %g2, TRAP_PER_CPU_FAULT_INFO, %g2
+       stxa    %g2, [%g0] ASI_SCRATCHPAD
 
-       /* Set fixed globals used by dTLB miss handler. */
-#define KERN_HIGHBITS          ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
-#define KERN_LOWBITS           (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
+       /* Compute physical address:
+        *
+        * paddr = kern_base + (mmfsa_vaddr - KERNBASE)
+        */
+       sethi   %hi(KERNBASE), %g3
+       sub     %g2, %g3, %g2
+       sethi   %hi(kern_base), %g3
+       ldx     [%g3 + %lo(kern_base)], %g3
+       add     %g2, %g3, %o1
 
-       mov     TSB_REG, %g1
-       stxa    %g0, [%g1] ASI_DMMU
-       membar  #Sync
-       stxa    %g0, [%g1] ASI_IMMU
-       membar  #Sync
-       mov     TLB_SFSR, %g1
-       sethi   %uhi(KERN_HIGHBITS), %g2
-       or      %g2, %ulo(KERN_HIGHBITS), %g2
-       sllx    %g2, 32, %g2
-       or      %g2, KERN_LOWBITS, %g2
-
-       BRANCH_IF_ANY_CHEETAH(g3,g7,cheetah_vpte_base)
-       ba,pt   %xcc, spitfire_vpte_base
+       call    prom_set_trap_table_sun4v
+        sethi  %hi(sparc64_ttable_tl0), %o0
+
+       ba,pt   %xcc, 2f
         nop
 
-cheetah_vpte_base:
-       sethi           %uhi(VPTE_BASE_CHEETAH), %g3
-       or              %g3, %ulo(VPTE_BASE_CHEETAH), %g3
-       ba,pt           %xcc, 2f
-        sllx           %g3, 32, %g3
+1:     call    prom_set_trap_table
+        sethi  %hi(sparc64_ttable_tl0), %o0
 
-spitfire_vpte_base:
-       sethi           %uhi(VPTE_BASE_SPITFIRE), %g3
-       or              %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
-       sllx            %g3, 32, %g3
+       /* Start using proper page size encodings in ctx register.  */
+2:     sethi   %hi(sparc64_kern_pri_context), %g3
+       ldx     [%g3 + %lo(sparc64_kern_pri_context)], %g2
 
-2:
-       clr     %g7
-#undef KERN_HIGHBITS
-#undef KERN_LOWBITS
+       mov             PRIMARY_CONTEXT, %g1
+
+661:   stxa            %g2, [%g1] ASI_DMMU
+       .section        .sun4v_1insn_patch, "ax"
+       .word           661b
+       stxa            %g2, [%g1] ASI_MMU
+       .previous
+
+       membar  #Sync
 
        /* Kill PROM timer */
        sethi   %hi(0x80000000), %o2
        sllx    %o2, 32, %o2
        wr      %o2, 0, %tick_cmpr
 
-       BRANCH_IF_ANY_CHEETAH(o2,o3,1f)
+       BRANCH_IF_SUN4V(o2, 1f)
+       BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
 
        ba,pt   %xcc, 2f
         nop
@@ -455,61 +587,69 @@ spitfire_vpte_base:
        sllx    %o2, 32, %o2
        wr      %o2, %asr25
 
-       /* Ok, we're done setting up all the state our trap mechanims needs,
-        * now get back into normal globals and let the PROM know what is up.
-        */
 2:
        wrpr    %g0, %g0, %wstate
-       wrpr    %o1, PSTATE_IE, %pstate
 
        call    init_irqwork_curcpu
         nop
 
-       call    prom_set_trap_table
-        sethi  %hi(sparc64_ttable_tl0), %o0
-
-       /* Start using proper page size encodings in ctx register.  */
-       sethi   %hi(sparc64_kern_pri_context), %g3
-       ldx     [%g3 + %lo(sparc64_kern_pri_context)], %g2
-       mov     PRIMARY_CONTEXT, %g1
-       stxa    %g2, [%g1] ASI_DMMU
-       membar  #Sync
-
+       /* Now we can turn interrupts back on. */
        rdpr    %pstate, %o1
        or      %o1, PSTATE_IE, %o1
        wrpr    %o1, 0, %pstate
+       wrpr    %g0, 0x0, %pil
 
        ret
         restore
 
-/*
- * The following skips make sure the trap table in ttable.S is aligned
- * on a 32K boundary as required by the v9 specs for TBA register.
- */
-sparc64_boot_end:
-       .skip   0x2000 + _start - sparc64_boot_end
-bootup_user_stack_end:
-       .skip   0x2000
+       .globl  setup_tba
+setup_tba:
+       save    %sp, -192, %sp
 
-#ifdef CONFIG_SBUS
-/* This is just a hack to fool make depend config.h discovering
-   strategy: As the .S files below need config.h, but
-   make depend does not find it for them, we include config.h
-   in head.S */
-#endif
+       /* The boot processor is the only cpu which invokes this
+        * routine, the other cpus set things up via trampoline.S.
+        * So save the OBP trap table address here.
+        */
+       rdpr    %tba, %g7
+       sethi   %hi(prom_tba), %o1
+       or      %o1, %lo(prom_tba), %o1
+       stx     %g7, [%o1]
 
-! 0x0000000000408000
+       call    setup_trap_table
+        nop
+
+       ret
+        restore
+sparc64_boot_end:
 
-#include "ttable.S"
-#include "systbls.S"
 #include "ktlb.S"
+#include "tsb.S"
 #include "etrap.S"
 #include "rtrap.S"
 #include "winfixup.S"
 #include "entry.S"
+#include "sun4v_tlb_miss.S"
+#include "sun4v_ivec.S"
+
+/*
+ * The following skip makes sure the trap table in ttable.S is aligned
+ * on a 32K boundary as required by the v9 specs for TBA register.
+ *
+ * We align to a 32K boundary, then we have the 32K kernel TSB,
+ * then the 32K aligned trap table.
+ */
+1:
+       .skip   0x4000 + _start - 1b
+
+       .globl  swapper_tsb
+swapper_tsb:
+       .skip   (32 * 1024)
+
+! 0x0000000000408000
 
-       /* This is just anal retentiveness on my part... */
-       .align  16384
+#include "ttable.S"
+
+#include "systbls.S"
 
        .data
        .align  8