1/* $OpenBSD: mptramp.s,v 1.17 2015/04/26 09:48:29 kettenis Exp $ */ 2 3/*- 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by RedBack Networks Inc. 9 * 10 * Author: Bill Sommerfeld 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34/* 35 * Copyright (c) 1999 Stefan Grefen 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the NetBSD 48 * Foundation, Inc. and its contributors. 49 * 4. Neither the name of The NetBSD Foundation nor the names of its 50 * contributors may be used to endorse or promote products derived 51 * from this software without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 54 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 */ 65/* 66 * MP startup ... 67 * the stuff from cpu_spinup_trampoline to mp_startup 68 * is copied into the first 640 KB 69 * 70 * We startup the processors now when the kthreads become ready. 71 * The steps are: 72 * 1) Get the processors running kernel-code from a special 73 * page-table and stack page, do chip identification. 74 * 2) halt the processors waiting for them to be enabled 75 * by a idle-thread 76 */ 77 78#include "assym.h" 79#include <machine/param.h> 80#include <machine/asm.h> 81#include <machine/specialreg.h> 82#include <machine/segments.h> 83#include <machine/gdt.h> 84#include <machine/mpbiosvar.h> 85#include <machine/i82489reg.h> 86 87#define GDTE(a,b) .byte 0xff,0xff,0x0,0x0,0x0,a,b,0x0 88#define _RELOC(x) ((x) - KERNBASE) 89#define RELOC(x) _RELOC(_C_LABEL(x)) 90 91#define _TRMP_LABEL(a) a = . - _C_LABEL(cpu_spinup_trampoline) + MP_TRAMPOLINE 92#define _TRMP_OFFSET(a) a = . - _C_LABEL(cpu_spinup_trampoline) 93 94/* 95 * Debug code to stop aux. processors in various stages based on the 96 * value in cpu_trace. 97 * 98 * %edi points at cpu_trace; cpu_trace[0] is the "hold point"; 99 * cpu_trace[1] is the point which the cpu has reached. 100 * cpu_trace[2] is the last value stored by HALTT. 101 */ 102 103 104#ifdef MPDEBUG 105#define HALT(x) 1: movl (%edi),%ebx;cmpl $ x,%ebx ; jle 1b ; movl $x,4(%edi) 106#define HALTT(x,y) movl y,8(%edi); HALT(x) 107#else 108#define HALT(x) 109#define HALTT(x,y) 110#endif 111 112 .globl _C_LABEL(cpu),_C_LABEL(cpu_id),_C_LABEL(cpu_vendor) 113 .globl _C_LABEL(cpuid_level),_C_LABEL(cpu_feature) 114 115 .global _C_LABEL(cpu_spinup_trampoline) 116 .global _C_LABEL(cpu_spinup_trampoline_end) 117 .global _C_LABEL(cpu_hatch) 118 .global _C_LABEL(mp_pdirpa) 119 .global _C_LABEL(gdt), _C_LABEL(local_apic) 120 121 .text 122 .align 4,0x0 123 .code16 124_C_LABEL(cpu_spinup_trampoline): 125 cli 126 movw %cs, %ax 127 movw %ax, %ds 128 movw %ax, %es 129 movw %ax, %ss 130 data32 addr32 lgdt (gdt_desc) # load flat descriptor table 131 movl %cr0, %eax # get cr0 132 orl $0x1, %eax # enable protected mode 133 movl %eax, %cr0 # doit 134 ljmpl $0x8, $mp_startup 135 136_TRMP_LABEL(mp_startup) 137 .code32 138 139 movl $0x10, %eax # data segment 140 movw %ax, %ds 141 movw %ax, %ss 142 movw %ax, %es 143 movw %ax, %fs 144 movw %ax, %gs 145 movl $(MP_TRAMPOLINE+NBPG-16),%esp # bootstrap stack end, 146 # with scratch space.. 147 148#ifdef MPDEBUG 149 leal RELOC(cpu_trace),%edi 150#endif 151 152 HALT(0x1) 153 /* First, reset the PSL. */ 154 pushl $PSL_MBO 155 popfl 156 157 movl RELOC(mp_pdirpa),%ecx 158 HALTT(0x5,%ecx) 159 160 /* Load base of page directory and enable mapping. */ 161 movl %ecx,%cr3 # load ptd addr into mmu 162#ifndef SMALL_KERNEL 163 movl $_C_LABEL(pmap_pte_set_pae),%eax 164 cmpl RELOC(_C_LABEL(pmap_pte_set_p)),%eax 165 jne nopae 166 167 movl %cr4,%eax 168 orl $CR4_PAE,%eax 169 movl %eax, %cr4 170 171 movl $MSR_EFER,%ecx 172 rdmsr 173 orl $EFER_NXE, %eax 174 wrmsr 175 176nopae: 177#endif 178 movl %cr0,%eax # get control word 179 # enable paging & NPX emulation 180 orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_EM|CR0_MP|CR0_WP),%eax 181 movl %eax,%cr0 # and let's page NOW! 182 183#ifdef MPDEBUG 184 leal _C_LABEL(cpu_trace),%edi 185#endif 186 HALT(0x6) 187 188# ok, we're now running with paging enabled and sharing page tables with cpu0. 189# figure out which processor we really are, what stack we should be on, etc. 190 191 movl _C_LABEL(local_apic)+LAPIC_ID,%eax 192 shrl $LAPIC_ID_SHIFT,%eax 193 xorl %ebx,%ebx 1941: 195 leal 0(,%ebx,4),%ecx 196 incl %ebx 197 movl _C_LABEL(cpu_info)(%ecx),%ecx 198 movl CPU_INFO_APICID(%ecx),%edx 199 cmpl %eax,%edx 200 jne 1b 201 202 HALTT(0x7, %ecx) 203 204# %ecx points at our cpu_info structure.. 205 206 movw $(MAXGDTSIZ-1), 6(%esp) # prepare segment descriptor 207 movl CPU_INFO_GDT(%ecx), %eax # for real gdt 208 movl %eax, 8(%esp) 209 HALTT(0x8, %eax) 210 lgdt 6(%esp) 211 HALT(0x9) 212 jmp 1f 213 nop 2141: 215 HALT(0xa) 216 movl $GSEL(GDATA_SEL, SEL_KPL),%eax #switch to new segment 217 HALTT(0x10, %eax) 218 movw %ax,%ds 219 HALT(0x11) 220 movw %ax,%es 221 HALT(0x12) 222 movw %ax,%ss 223 HALT(0x13) 224 pushl $GSEL(GCODE_SEL, SEL_KPL) 225 pushl $mp_cont 226 HALT(0x14) 227 lret 228 .align 4,0x0 229_TRMP_LABEL(gdt_table) 230 .word 0x0,0x0,0x0,0x0 # null GDTE 231 GDTE(0x9f,0xcf) # Kernel text 232 GDTE(0x93,0xcf) # Kernel data 233_TRMP_OFFSET(gdt_desc) 234 .word 0x17 # limit 3 entries 235 .long gdt_table # where is gdt 236 237_C_LABEL(cpu_spinup_trampoline_end): #end of code copied to MP_TRAMPOLINE 238mp_cont: 239 240 movl CPU_INFO_IDLE_PCB(%ecx),%esi 241 242# %esi now points at our PCB. 243 244 HALTT(0x19, %esi) 245 246 movl PCB_ESP(%esi),%esp 247 movl PCB_EBP(%esi),%ebp 248 249 HALT(0x20) 250 /* Switch address space. */ 251 movl PCB_CR3(%esi),%eax 252 HALTT(0x22, %eax) 253 movl %eax,%cr3 254 HALT(0x25) 255 /* Load segment registers. */ 256 movl $GSEL(GCPU_SEL, SEL_KPL),%eax 257 HALTT(0x26,%eax) 258 movl %eax,%fs 259 xorl %eax,%eax 260 HALTT(0x27,%eax) 261 movl %eax,%gs 262 movl PCB_CR0(%esi),%eax 263 HALTT(0x28,%eax) 264 movl %eax,%cr0 265 HALTT(0x30,%ecx) 266 pushl %ecx 267 call _C_LABEL(cpu_hatch) 268 /* NOTREACHED */ 269 270 .data 271_C_LABEL(mp_pdirpa): 272 .long 0 273#ifdef MPDEBUG 274 .global _C_LABEL(cpu_trace) 275_C_LABEL(cpu_trace): 276 .long 0x40 277 .long 0xff 278 .long 0xff 279#endif 280