11da177e4SLinus Torvalds/* This file is subject to the terms and conditions of the GNU General Public 21da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 31da177e4SLinus Torvalds * for more details. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 1999 by Helge Deller 61da177e4SLinus Torvalds * Copyright 1999 SuSE GmbH (Philipp Rumpf) 71da177e4SLinus Torvalds * Copyright 1999 Philipp Rumpf (prumpf@tux.org) 81da177e4SLinus Torvalds * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com) 91da177e4SLinus Torvalds * Copyright (C) 2001 Grant Grundler (Hewlett Packard) 101da177e4SLinus Torvalds * Copyright (C) 2004 Kyle McMartin <kyle@debian.org> 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de> 131da177e4SLinus Torvalds */ 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds#include <linux/autoconf.h> /* for CONFIG_SMP */ 161da177e4SLinus Torvalds 170013a854SSam Ravnborg#include <asm/asm-offsets.h> 181da177e4SLinus Torvalds#include <asm/psw.h> 191da177e4SLinus Torvalds#include <asm/pdc.h> 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds#include <asm/assembly.h> 221da177e4SLinus Torvalds#include <asm/pgtable.h> 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds .level LEVEL 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds .data 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds .export boot_args 291da177e4SLinus Torvaldsboot_args: 301da177e4SLinus Torvalds .word 0 /* arg0 */ 311da177e4SLinus Torvalds .word 0 /* arg1 */ 321da177e4SLinus Torvalds .word 0 /* arg2 */ 331da177e4SLinus Torvalds .word 0 /* arg3 */ 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds .text 361da177e4SLinus Torvalds .align 4 371da177e4SLinus Torvalds .import init_thread_union,data 381da177e4SLinus Torvalds .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ 391da177e4SLinus Torvalds#ifndef __LP64__ 401da177e4SLinus Torvalds .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ 411da177e4SLinus Torvalds .import $global$ /* forward declaration */ 421da177e4SLinus Torvalds#endif /*!LP64*/ 431da177e4SLinus Torvalds .export stext 441da177e4SLinus Torvalds .export _stext,data /* Kernel want it this way! */ 451da177e4SLinus Torvalds_stext: 461da177e4SLinus Torvaldsstext: 471da177e4SLinus Torvalds .proc 481da177e4SLinus Torvalds .callinfo 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds /* Make sure sr4-sr7 are set to zero for the kernel address space */ 511da177e4SLinus Torvalds mtsp %r0,%sr4 521da177e4SLinus Torvalds mtsp %r0,%sr5 531da177e4SLinus Torvalds mtsp %r0,%sr6 541da177e4SLinus Torvalds mtsp %r0,%sr7 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds /* Clear BSS (shouldn't the boot loader do this?) */ 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds .import __bss_start,data 591da177e4SLinus Torvalds .import __bss_stop,data 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds load32 PA(__bss_start),%r3 621da177e4SLinus Torvalds load32 PA(__bss_stop),%r4 631da177e4SLinus Torvalds$bss_loop: 641da177e4SLinus Torvalds cmpb,<<,n %r3,%r4,$bss_loop 651da177e4SLinus Torvalds stw,ma %r0,4(%r3) 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds /* Save away the arguments the boot loader passed in (32 bit args) */ 681da177e4SLinus Torvalds load32 PA(boot_args),%r1 691da177e4SLinus Torvalds stw,ma %arg0,4(%r1) 701da177e4SLinus Torvalds stw,ma %arg1,4(%r1) 711da177e4SLinus Torvalds stw,ma %arg2,4(%r1) 721da177e4SLinus Torvalds stw,ma %arg3,4(%r1) 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds /* Initialize startup VM. Just map first 8/16 MB of memory */ 751da177e4SLinus Torvalds load32 PA(swapper_pg_dir),%r4 761da177e4SLinus Torvalds mtctl %r4,%cr24 /* Initialize kernel root pointer */ 771da177e4SLinus Torvalds mtctl %r4,%cr25 /* Initialize user root pointer */ 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds#ifdef __LP64__ 801da177e4SLinus Torvalds /* Set pmd in pgd */ 811da177e4SLinus Torvalds load32 PA(pmd0),%r5 821da177e4SLinus Torvalds shrd %r5,PxD_VALUE_SHIFT,%r3 831da177e4SLinus Torvalds ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 841da177e4SLinus Torvalds stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4) 851da177e4SLinus Torvalds ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4 861da177e4SLinus Torvalds#else 871da177e4SLinus Torvalds /* 2-level page table, so pmd == pgd */ 881da177e4SLinus Torvalds ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4 891da177e4SLinus Torvalds#endif 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds /* Fill in pmd with enough pte directories */ 921da177e4SLinus Torvalds load32 PA(pg0),%r1 931da177e4SLinus Torvalds SHRREG %r1,PxD_VALUE_SHIFT,%r3 941da177e4SLinus Torvalds ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds ldi ASM_PT_INITIAL,%r1 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds1: 991da177e4SLinus Torvalds stw %r3,0(%r4) 1001da177e4SLinus Torvalds ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3 1011da177e4SLinus Torvalds addib,> -1,%r1,1b 1021da177e4SLinus Torvalds#ifdef __LP64__ 1031da177e4SLinus Torvalds ldo ASM_PMD_ENTRY_SIZE(%r4),%r4 1041da177e4SLinus Torvalds#else 1051da177e4SLinus Torvalds ldo ASM_PGD_ENTRY_SIZE(%r4),%r4 1061da177e4SLinus Torvalds#endif 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds /* Now initialize the PTEs themselves */ 1101da177e4SLinus Torvalds ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */ 1111da177e4SLinus Torvalds load32 PA(pg0),%r1 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds$pgt_fill_loop: 1141da177e4SLinus Torvalds STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1) 1151da177e4SLinus Torvalds ldo ASM_PAGE_SIZE(%r3),%r3 1161da177e4SLinus Torvalds bb,>= %r3,31-KERNEL_INITIAL_ORDER,$pgt_fill_loop 1171da177e4SLinus Torvalds nop 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds /* Load the return address...er...crash 'n burn */ 1201da177e4SLinus Torvalds copy %r0,%r2 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* And the RFI Target address too */ 1231da177e4SLinus Torvalds load32 start_kernel,%r11 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds /* And the initial task pointer */ 1261da177e4SLinus Torvalds load32 init_thread_union,%r6 1271da177e4SLinus Torvalds mtctl %r6,%cr30 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* And the stack pointer too */ 1301da177e4SLinus Torvalds ldo THREAD_SZ_ALGN(%r6),%sp 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds /* And the interrupt stack */ 1331da177e4SLinus Torvalds load32 interrupt_stack,%r6 1341da177e4SLinus Torvalds mtctl %r6,%cr31 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds#ifdef CONFIG_SMP 1371da177e4SLinus Torvalds /* Set the smp rendevous address into page zero. 1381da177e4SLinus Torvalds ** It would be safer to do this in init_smp_config() but 1391da177e4SLinus Torvalds ** it's just way easier to deal with here because 1401da177e4SLinus Torvalds ** of 64-bit function ptrs and the address is local to this file. 1411da177e4SLinus Torvalds */ 1421da177e4SLinus Torvalds load32 PA(smp_slave_stext),%r10 1431da177e4SLinus Torvalds stw %r10,0x10(%r0) /* MEM_RENDEZ */ 1441da177e4SLinus Torvalds stw %r0,0x28(%r0) /* MEM_RENDEZ_HI - assume addr < 4GB */ 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds /* FALLTHROUGH */ 1471da177e4SLinus Torvalds .procend 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds /* 1501da177e4SLinus Torvalds ** Code Common to both Monarch and Slave processors. 1511da177e4SLinus Torvalds ** Entry: 1521da177e4SLinus Torvalds ** 1531da177e4SLinus Torvalds ** 1.1: 1541da177e4SLinus Torvalds ** %r11 must contain RFI target address. 1551da177e4SLinus Torvalds ** %r25/%r26 args to pass to target function 1561da177e4SLinus Torvalds ** %r2 in case rfi target decides it didn't like something 1571da177e4SLinus Torvalds ** 1581da177e4SLinus Torvalds ** 2.0w: 1591da177e4SLinus Torvalds ** %r3 PDCE_PROC address 1601da177e4SLinus Torvalds ** %r11 RFI target address 1611da177e4SLinus Torvalds ** 1621da177e4SLinus Torvalds ** Caller must init: SR4-7, %sp, %r10, %cr24/25, 1631da177e4SLinus Torvalds */ 1641da177e4SLinus Torvaldscommon_stext: 1651da177e4SLinus Torvalds .proc 1661da177e4SLinus Torvalds .callinfo 1671da177e4SLinus Torvalds#else 1681da177e4SLinus Torvalds /* Clear PDC entry point - we won't use it */ 1691da177e4SLinus Torvalds stw %r0,0x10(%r0) /* MEM_RENDEZ */ 1701da177e4SLinus Torvalds stw %r0,0x28(%r0) /* MEM_RENDEZ_HI */ 1711da177e4SLinus Torvalds#endif /*CONFIG_SMP*/ 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds#ifdef __LP64__ 1741da177e4SLinus Torvalds tophys_r1 %sp 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds /* Save the rfi target address */ 1771da177e4SLinus Torvalds ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 1781da177e4SLinus Torvalds tophys_r1 %r10 1791da177e4SLinus Torvalds std %r11, TASK_PT_GR11(%r10) 1801da177e4SLinus Torvalds /* Switch to wide mode Superdome doesn't support narrow PDC 1811da177e4SLinus Torvalds ** calls. 1821da177e4SLinus Torvalds */ 1831da177e4SLinus Torvalds1: mfia %rp /* clear upper part of pcoq */ 1841da177e4SLinus Torvalds ldo 2f-1b(%rp),%rp 1851da177e4SLinus Torvalds depdi 0,31,32,%rp 1861da177e4SLinus Torvalds bv (%rp) 1871da177e4SLinus Torvalds ssm PSW_SM_W,%r0 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds /* Set Wide mode as the "Default" (eg for traps) 1901da177e4SLinus Torvalds ** First trap occurs *right* after (or part of) rfi for slave CPUs. 1911da177e4SLinus Torvalds ** Someday, palo might not do this for the Monarch either. 1921da177e4SLinus Torvalds */ 1931da177e4SLinus Torvalds2: 1941da177e4SLinus Torvalds#define MEM_PDC_LO 0x388 1951da177e4SLinus Torvalds#define MEM_PDC_HI 0x35C 1961da177e4SLinus Torvalds ldw MEM_PDC_LO(%r0),%r3 1971da177e4SLinus Torvalds ldw MEM_PDC_HI(%r0),%r6 1981da177e4SLinus Torvalds depd %r6, 31, 32, %r3 /* move to upper word */ 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds ldo PDC_PSW(%r0),%arg0 /* 21 */ 2011da177e4SLinus Torvalds ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ 2021da177e4SLinus Torvalds ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ 2031da177e4SLinus Torvalds load32 PA(stext_pdc_ret), %rp 2041da177e4SLinus Torvalds bv (%r3) 2051da177e4SLinus Torvalds copy %r0,%arg3 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvaldsstext_pdc_ret: 2081da177e4SLinus Torvalds /* restore rfi target address*/ 2091da177e4SLinus Torvalds ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 2101da177e4SLinus Torvalds tophys_r1 %r10 2111da177e4SLinus Torvalds ldd TASK_PT_GR11(%r10), %r11 2121da177e4SLinus Torvalds tovirt_r1 %sp 2131da177e4SLinus Torvalds#endif 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds /* PARANOID: clear user scratch/user space SR's */ 2161da177e4SLinus Torvalds mtsp %r0,%sr0 2171da177e4SLinus Torvalds mtsp %r0,%sr1 2181da177e4SLinus Torvalds mtsp %r0,%sr2 2191da177e4SLinus Torvalds mtsp %r0,%sr3 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds /* Initialize Protection Registers */ 2221da177e4SLinus Torvalds mtctl %r0,%cr8 2231da177e4SLinus Torvalds mtctl %r0,%cr9 2241da177e4SLinus Torvalds mtctl %r0,%cr12 2251da177e4SLinus Torvalds mtctl %r0,%cr13 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds /* Initialize the global data pointer */ 2281da177e4SLinus Torvalds loadgp 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds /* Set up our interrupt table. HPMCs might not work after this! 2311da177e4SLinus Torvalds * 2321da177e4SLinus Torvalds * We need to install the correct iva for PA1.1 or PA2.0. The 2331da177e4SLinus Torvalds * following short sequence of instructions can determine this 2341da177e4SLinus Torvalds * (without being illegal on a PA1.1 machine). 2351da177e4SLinus Torvalds */ 2361da177e4SLinus Torvalds#ifndef __LP64__ 2371da177e4SLinus Torvalds ldi 32,%r10 2381da177e4SLinus Torvalds mtctl %r10,%cr11 2391da177e4SLinus Torvalds .level 2.0 2401da177e4SLinus Torvalds mfctl,w %cr11,%r10 2411da177e4SLinus Torvalds .level 1.1 2421da177e4SLinus Torvalds comib,<>,n 0,%r10,$is_pa20 2431da177e4SLinus Torvalds ldil L%PA(fault_vector_11),%r10 2441da177e4SLinus Torvalds b $install_iva 2451da177e4SLinus Torvalds ldo R%PA(fault_vector_11)(%r10),%r10 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds$is_pa20: 2481da177e4SLinus Torvalds .level LEVEL /* restore 1.1 || 2.0w */ 2491da177e4SLinus Torvalds#endif /*!LP64*/ 2501da177e4SLinus Torvalds load32 PA(fault_vector_20),%r10 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds$install_iva: 2531da177e4SLinus Torvalds mtctl %r10,%cr14 2541da177e4SLinus Torvalds 255*896a3756SGrant Grundler b aligned_rfi /* Prepare to RFI! Man all the cannons! */ 2561da177e4SLinus Torvalds nop 2571da177e4SLinus Torvalds 258*896a3756SGrant Grundler .align 128 2591da177e4SLinus Torvaldsaligned_rfi: 260*896a3756SGrant Grundler pcxt_ssm_bug 2611da177e4SLinus Torvalds 262*896a3756SGrant Grundler rsm PSW_SM_QUIET,%r0 /* off troublesome PSW bits */ 263*896a3756SGrant Grundler /* Don't need NOPs, have 8 compliant insn before rfi */ 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds mtctl %r0,%cr17 /* Clear IIASQ tail */ 2661da177e4SLinus Torvalds mtctl %r0,%cr17 /* Clear IIASQ head */ 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds /* Load RFI target into PC queue */ 2691da177e4SLinus Torvalds mtctl %r11,%cr18 /* IIAOQ head */ 2701da177e4SLinus Torvalds ldo 4(%r11),%r11 2711da177e4SLinus Torvalds mtctl %r11,%cr18 /* IIAOQ tail */ 2721da177e4SLinus Torvalds 273*896a3756SGrant Grundler load32 KERNEL_PSW,%r10 274*896a3756SGrant Grundler mtctl %r10,%ipsw 275*896a3756SGrant Grundler 276*896a3756SGrant Grundler /* Jump through hyperspace to Virt Mode */ 2771da177e4SLinus Torvalds rfi 2781da177e4SLinus Torvalds nop 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds .procend 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds#ifdef CONFIG_SMP 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds .import smp_init_current_idle_task,data 2851da177e4SLinus Torvalds .import smp_callin,code 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds#ifndef __LP64__ 2881da177e4SLinus Torvaldssmp_callin_rtn: 2891da177e4SLinus Torvalds .proc 2901da177e4SLinus Torvalds .callinfo 2911da177e4SLinus Torvalds break 1,1 /* Break if returned from start_secondary */ 2921da177e4SLinus Torvalds nop 2931da177e4SLinus Torvalds nop 2941da177e4SLinus Torvalds .procend 2951da177e4SLinus Torvalds#endif /*!LP64*/ 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds/*************************************************************************** 2981da177e4SLinus Torvalds* smp_slave_stext is executed by all non-monarch Processors when the Monarch 2991da177e4SLinus Torvalds* pokes the slave CPUs in smp.c:smp_boot_cpus(). 3001da177e4SLinus Torvalds* 3011da177e4SLinus Torvalds* Once here, registers values are initialized in order to branch to virtual 3021da177e4SLinus Torvalds* mode. Once all available/eligible CPUs are in virtual mode, all are 3031da177e4SLinus Torvalds* released and start out by executing their own idle task. 3041da177e4SLinus Torvalds*****************************************************************************/ 3051da177e4SLinus Torvaldssmp_slave_stext: 3061da177e4SLinus Torvalds .proc 3071da177e4SLinus Torvalds .callinfo 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds /* 3101da177e4SLinus Torvalds ** Initialize Space registers 3111da177e4SLinus Torvalds */ 3121da177e4SLinus Torvalds mtsp %r0,%sr4 3131da177e4SLinus Torvalds mtsp %r0,%sr5 3141da177e4SLinus Torvalds mtsp %r0,%sr6 3151da177e4SLinus Torvalds mtsp %r0,%sr7 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* Initialize the SP - monarch sets up smp_init_current_idle_task */ 3181da177e4SLinus Torvalds load32 PA(smp_init_current_idle_task),%sp 3191da177e4SLinus Torvalds LDREG 0(%sp),%sp /* load task address */ 3201da177e4SLinus Torvalds tophys_r1 %sp 3211da177e4SLinus Torvalds LDREG TASK_THREAD_INFO(%sp),%sp 3221da177e4SLinus Torvalds mtctl %sp,%cr30 /* store in cr30 */ 3231da177e4SLinus Torvalds ldo THREAD_SZ_ALGN(%sp),%sp 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds /* point CPU to kernel page tables */ 3261da177e4SLinus Torvalds load32 PA(swapper_pg_dir),%r4 3271da177e4SLinus Torvalds mtctl %r4,%cr24 /* Initialize kernel root pointer */ 3281da177e4SLinus Torvalds mtctl %r4,%cr25 /* Initialize user root pointer */ 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds#ifdef __LP64__ 3311da177e4SLinus Torvalds /* Setup PDCE_PROC entry */ 3321da177e4SLinus Torvalds copy %arg0,%r3 3331da177e4SLinus Torvalds#else 3341da177e4SLinus Torvalds /* Load RFI *return* address in case smp_callin bails */ 3351da177e4SLinus Torvalds load32 smp_callin_rtn,%r2 3361da177e4SLinus Torvalds#endif 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds /* Load RFI target address. */ 3391da177e4SLinus Torvalds load32 smp_callin,%r11 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds /* ok...common code can handle the rest */ 3421da177e4SLinus Torvalds b common_stext 3431da177e4SLinus Torvalds nop 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds .procend 3461da177e4SLinus Torvalds#endif /* CONFIG_SMP */ 3471da177e4SLinus Torvalds#ifndef __LP64__ 3481da177e4SLinus Torvalds .data 3491da177e4SLinus Torvalds 3501da177e4SLinus Torvalds .align 4 3511da177e4SLinus Torvalds .export $global$,data 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds .type $global$,@object 3541da177e4SLinus Torvalds .size $global$,4 3551da177e4SLinus Torvalds$global$: 3561da177e4SLinus Torvalds .word 0 3571da177e4SLinus Torvalds#endif /*!LP64*/ 358