mp_locore.S revision 203838
189051Sjake/*- 289051Sjake * Copyright (c) 2002 Jake Burkholder. 3182916Smarius * Copyright (c) 2008 Marius Strobl <marius@FreeBSD.org> 489051Sjake * All rights reserved. 589051Sjake * 689051Sjake * Redistribution and use in source and binary forms, with or without 789051Sjake * modification, are permitted provided that the following conditions 889051Sjake * are met: 989051Sjake * 1. Redistributions of source code must retain the above copyright 1089051Sjake * notice, this list of conditions and the following disclaimer. 1189051Sjake * 2. Redistributions in binary form must reproduce the above copyright 1289051Sjake * notice, this list of conditions and the following disclaimer in the 1389051Sjake * documentation and/or other materials provided with the distribution. 1489051Sjake * 1589051Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1689051Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1789051Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1889051Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1989051Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2089051Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2189051Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2289051Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2389051Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2489051Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2589051Sjake * SUCH DAMAGE. 2689051Sjake */ 2789051Sjake 28114188Sjake#include <machine/asm.h> 29114188Sjake__FBSDID("$FreeBSD: head/sys/sparc64/sparc64/mp_locore.S 203838 2010-02-13 16:52:33Z marius $"); 30114188Sjake 3189051Sjake#include <machine/asi.h> 3289051Sjake#include <machine/asmacros.h> 3389051Sjake#include <machine/ktr.h> 3489051Sjake#include <machine/pstate.h> 35166105Smarius#include <machine/smp.h> 36182730Smarius#include <machine/ver.h> 3789051Sjake 3889051Sjake#include "assym.s" 3989051Sjake 4089051Sjake .register %g2, #ignore 4189051Sjake .register %g3, #ignore 4289051Sjake 4391617Sjake .text 44100899Sjake _ALIGN_TEXT 45182916Smarius /* 46203833Smarius * Initialize misc. state to known values: interrupts disabled, normal 47203833Smarius * globals, windows flushed (cr = 0, cs = nwindows - 1), PIL 0 and 48203833Smarius * floating point disabled. 49203833Smarius * Note that some firmware versions don't implement a clean window 50203833Smarius * trap handler so we unfortunately can't clear the windows by setting 51203833Smarius * %cleanwin to zero here. 52182916Smarius */ 53182916Smarius1: wrpr %g0, PSTATE_NORMAL, %pstate 54182916Smarius wrpr %g0, 0, %pil 55182916Smarius wr %g0, 0, %fprs 56182916Smarius 57182916Smarius rdpr %ver, %l7 58182916Smarius srlx %l7, VER_IMPL_SHIFT, %l7 59182916Smarius sll %l7, VER_IMPL_SIZE, %l7 60182916Smarius srl %l7, VER_IMPL_SIZE, %l7 61182916Smarius cmp %l7, CPU_IMPL_ULTRASPARCIIIp 62182916Smarius bne %icc, 3f 63182916Smarius nop 64182916Smarius 65182916Smarius /* 66182916Smarius * Relocate the locked entry in it16 slot 0 (if existent) 67182916Smarius * as part of working around Cheetah+ erratum 34. 68182916Smarius */ 69182916Smarius 70182916Smarius setx TD_V | TD_L, %l1, %l0 71182916Smarius /* 72203833Smarius * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work 73182916Smarius * around errata of USIII and beyond. 74182916Smarius */ 75182916Smarius ldxa [%g0] ASI_ITLB_DATA_ACCESS_REG, %g0 76182916Smarius ldxa [%g0] ASI_ITLB_DATA_ACCESS_REG, %l6 77182916Smarius and %l6, %l0, %l1 78182916Smarius cmp %l0, %l1 79182916Smarius bne %xcc, 3f 80182916Smarius nop 81182916Smarius 82182916Smarius /* Flush the mapping of slot 0. */ 83182916Smarius ldxa [%g0] ASI_ITLB_TAG_READ_REG, %l5 84182916Smarius srlx %l5, TAR_VPN_SHIFT, %l0 85182916Smarius sllx %l0, TAR_VPN_SHIFT, %l0 86182916Smarius or %l0, TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, %l0 87182916Smarius stxa %g0, [%l0] ASI_IMMU_DEMAP 88182916Smarius /* The USIII-family ignores the address. */ 89182916Smarius flush %g0 90182916Smarius 91182916Smarius /* 92182916Smarius * Search a replacement slot != 0 and enter the data and tag 93182916Smarius * that formerly were in slot 0. 94182916Smarius */ 95182916Smarius mov (1 << TLB_DAR_SLOT_SHIFT), %l4 96182916Smarius setx TD_V, %l1, %l0 97182916Smarius /* 98203833Smarius * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work 99182916Smarius * around errata of USIII and beyond. 100182916Smarius */ 101182916Smarius2: ldxa [%l4] ASI_ITLB_DATA_ACCESS_REG, %g0 102182916Smarius ldxa [%l4] ASI_ITLB_DATA_ACCESS_REG, %l1 103182916Smarius and %l1, %l0, %l1 104182916Smarius cmp %l0, %l1 105182916Smarius be,a %xcc, 2b 106182916Smarius add %l4, (1 << TLB_DAR_SLOT_SHIFT), %l4 107182916Smarius wr %g0, ASI_IMMU, %asi 108182916Smarius stxa %l5, [%g0 + AA_IMMU_TAR] %asi 109182916Smarius stxa %l6, [%l4] ASI_ITLB_DATA_ACCESS_REG 110182916Smarius /* The USIII-family ignores the address. */ 111182916Smarius flush %g0 112182916Smarius 113182916Smarius3: rd %pc, %l6 114182916Smarius ldx [%l6 + (9f-3b)], %l1 115182916Smarius add %l6, (11f-3b), %l2 11691617Sjake clr %l3 117182916Smarius4: cmp %l3, %l1 118182916Smarius be %xcc, 8f 11991617Sjake nop 12091617Sjake ldx [%l2 + TTE_VPN], %l4 12191617Sjake ldx [%l2 + TTE_DATA], %l5 122102040Sjake srlx %l4, TV_SIZE_BITS, %l4 123102040Sjake sllx %l4, PAGE_SHIFT_4M, %l4 12491617Sjake wr %g0, ASI_DMMU, %asi 12591617Sjake stxa %l4, [%g0 + AA_DMMU_TAR] %asi 12691617Sjake stxa %l5, [%g0] ASI_DTLB_DATA_IN_REG 127182916Smarius membar #Sync 128182916Smarius 129182916Smarius cmp %l7, CPU_IMPL_ULTRASPARCIIIp 130182916Smarius bne %icc, 6f 131182916Smarius wr %g0, ASI_IMMU, %asi 132182916Smarius 133182916Smarius /* 134182916Smarius * Search an unused slot != 0 and explicitly enter the data 135182916Smarius * and tag there in order to avoid Cheetah+ erratum 34. 136182916Smarius */ 137182916Smarius mov (1 << TLB_DAR_SLOT_SHIFT), %l0 138182916Smarius setx TD_V, %o1, %o0 139182916Smarius /* 140203833Smarius * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work 141182916Smarius * around errata of USIII and beyond. 142182916Smarius */ 143182916Smarius5: ldxa [%l0] ASI_ITLB_DATA_ACCESS_REG, %g0 144182916Smarius ldxa [%l0] ASI_ITLB_DATA_ACCESS_REG, %o1 145182916Smarius and %o1, %o0, %o1 146182916Smarius cmp %o0, %o1 147182916Smarius be,a %xcc, 5b 148182916Smarius add %l0, (1 << TLB_DAR_SLOT_SHIFT), %l0 149182916Smarius sethi %hi(KERNBASE), %o0 15091617Sjake stxa %l4, [%g0 + AA_IMMU_TAR] %asi 151182916Smarius stxa %l5, [%l0] ASI_ITLB_DATA_ACCESS_REG 152182916Smarius flush %o0 153182916Smarius ba %xcc, 7f 154182916Smarius nop 155182916Smarius 156182916Smarius6: sethi %hi(KERNBASE), %l0 157182916Smarius stxa %l4, [%g0 + AA_IMMU_TAR] %asi 15891617Sjake stxa %l5, [%g0] ASI_ITLB_DATA_IN_REG 159182916Smarius flush %l0 160182916Smarius7: add %l2, 1 << TTE_SHIFT, %l2 16191617Sjake add %l3, 1, %l3 162182916Smarius ba %xcc, 4b 16391617Sjake nop 164182916Smarius8: ldx [%l6 + (10f-3b)], %l1 16591617Sjake jmpl %l1, %g0 16691617Sjake nop 167100899Sjake _ALIGN_DATA 168182916Smarius9: .xword 0x0 169182916Smarius10: .xword 0x0 170182916Smarius11: 17191617Sjake 17291617SjakeDATA(mp_tramp_code) 17391617Sjake .xword 1b 17491617SjakeDATA(mp_tramp_code_len) 175182916Smarius .xword 11b-1b 17691617SjakeDATA(mp_tramp_tlb_slots) 177182916Smarius .xword 9b-1b 17891617SjakeDATA(mp_tramp_func) 179182916Smarius .xword 10b-1b 18091617Sjake 18189051Sjake/* 18291617Sjake * void mp_startup(void) 18389051Sjake */ 18491617SjakeENTRY(mp_startup) 18591617Sjake SET(cpu_start_args, %l1, %l0) 18691617Sjake 187182730Smarius mov CPU_TICKSYNC, %l1 18889051Sjake membar #StoreLoad 18991617Sjake stw %l1, [%l0 + CSA_STATE] 19089051Sjake 19191617Sjake1: ldx [%l0 + CSA_TICK], %l1 19291617Sjake brz %l1, 1b 19391617Sjake nop 19491617Sjake wrpr %l1, 0, %tick 19591617Sjake 196182730Smarius rdpr %ver, %l1 197182730Smarius stx %l1, [%l0 + CSA_VER] 19891617Sjake 199182730Smarius srlx %l1, VER_IMPL_SHIFT, %l1 200182730Smarius sll %l1, VER_IMPL_SIZE, %l1 201182730Smarius srl %l1, VER_IMPL_SIZE, %l1 202182730Smarius cmp %l1, CPU_IMPL_ULTRASPARCIII 203182730Smarius bl %icc, 3f 204182730Smarius nop 205182730Smarius mov CPU_STICKSYNC, %l1 206182730Smarius membar #StoreLoad 207182730Smarius stw %l1, [%l0 + CSA_STATE] 208182730Smarius 209182730Smarius2: ldx [%l0 + CSA_STICK], %l1 210182730Smarius brz %l1, 2b 211182730Smarius nop 212182730Smarius wr %l1, 0, %asr24 213182730Smarius 214203838Smarius3: call cpu_get_mid 215203838Smarius nop 216182730Smarius 21789051Sjake /* 21891617Sjake * Inform the boot processor we have inited. 21989051Sjake */ 22091617Sjake mov CPU_INIT, %l1 22191617Sjake membar #LoadStore 22291617Sjake stw %l1, [%l0 + CSA_STATE] 22391617Sjake 22491617Sjake /* 22591617Sjake * Wait till its our turn to bootstrap. 22691617Sjake */ 227182730Smarius4: lduw [%l0 + CSA_MID], %l1 22891617Sjake cmp %l1, %o0 229182730Smarius bne %xcc, 4b 23089051Sjake nop 23189051Sjake 23291783Sjake add %l0, CSA_TTES, %l1 23391783Sjake clr %l2 23491783Sjake 23589051Sjake /* 236181701Smarius * Map the per-CPU pages. 23789051Sjake */ 238182730Smarius5: sllx %l2, TTE_SHIFT, %l3 23991783Sjake add %l1, %l3, %l3 24089051Sjake 24191783Sjake ldx [%l3 + TTE_VPN], %l4 24291783Sjake ldx [%l3 + TTE_DATA], %l5 24391783Sjake 24489051Sjake wr %g0, ASI_DMMU, %asi 245102040Sjake srlx %l4, TV_SIZE_BITS, %l4 246102040Sjake sllx %l4, PAGE_SHIFT_8K, %l4 24791783Sjake stxa %l4, [%g0 + AA_DMMU_TAR] %asi 24891783Sjake stxa %l5, [%g0] ASI_DTLB_DATA_IN_REG 24989051Sjake membar #Sync 25089051Sjake 25191783Sjake add %l2, 1, %l2 25291783Sjake cmp %l2, PCPU_PAGES 253182730Smarius bne %xcc, 5b 25491783Sjake nop 25591783Sjake 25689051Sjake /* 257181701Smarius * Get onto our per-CPU panic stack, which precedes the struct pcpu 258181701Smarius * in the per-CPU page. 25989051Sjake */ 26091783Sjake ldx [%l0 + CSA_PCPU], %l1 26191617Sjake set PCPU_PAGES * PAGE_SIZE - PC_SIZEOF, %l2 26291617Sjake add %l1, %l2, %l1 26391617Sjake sub %l1, SPOFF + CCFSZ, %sp 26489051Sjake 26589051Sjake /* 26689051Sjake * Enable interrupts. 26789051Sjake */ 26889051Sjake wrpr %g0, PSTATE_KERNEL, %pstate 26989051Sjake 27089051Sjake#if KTR_COMPILE & KTR_SMP 27189051Sjake CATR(KTR_SMP, 272203838Smarius "mp_startup: bootstrap cpuid=%d mid=%d pcpu=%#lx data=%#lx sp=%#lx" 27389051Sjake , %g1, %g2, %g3, 7, 8, 9) 27491783Sjake lduw [%l1 + PC_CPUID], %g2 27589051Sjake stx %g2, [%g1 + KTR_PARM1] 27691783Sjake lduw [%l1 + PC_MID], %g2 27789051Sjake stx %g2, [%g1 + KTR_PARM2] 27891783Sjake stx %l1, [%g1 + KTR_PARM3] 27989051Sjake stx %sp, [%g1 + KTR_PARM5] 28089051Sjake9: 28189051Sjake#endif 28289051Sjake 28389051Sjake /* 28489051Sjake * And away we go. This doesn't return. 28589051Sjake */ 28689051Sjake call cpu_mp_bootstrap 28791617Sjake mov %l1, %o0 28889051Sjake sir 28989051Sjake ! NOTREACHED 29091617SjakeEND(mp_startup) 291