1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 2 /* >> 3 * head.S: The initial boot code for the Sparc port of Linux. 3 * 4 * 4 * Copyright (C) 1991, 1992 Linus Torvalds !! 5 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) >> 6 * Copyright (C) 1995,1999 Pete Zaitcev (zaitcev@yahoo.com) >> 7 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) >> 8 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) >> 9 * Copyright (C) 1997 Michael A. Griffith (grif@acm.org) 5 * 10 * 6 * Enhanced CPU detection and feature setting !! 11 * CompactPCI platform by Eric Brower, 1999. 7 * and Martin Mares, November 1997. << 8 */ 12 */ 9 13 10 .text << 11 #include <linux/export.h> 14 #include <linux/export.h> 12 #include <linux/threads.h> !! 15 #include <linux/version.h> 13 #include <linux/init.h> 16 #include <linux/init.h> 14 #include <linux/linkage.h> << 15 #include <asm/segment.h> << 16 #include <asm/page_types.h> << 17 #include <asm/pgtable_types.h> << 18 #include <asm/cache.h> << 19 #include <asm/thread_info.h> << 20 #include <asm/asm-offsets.h> << 21 #include <asm/setup.h> << 22 #include <asm/processor-flags.h> << 23 #include <asm/msr-index.h> << 24 #include <asm/cpufeatures.h> << 25 #include <asm/percpu.h> << 26 #include <asm/nops.h> << 27 #include <asm/nospec-branch.h> << 28 #include <asm/bootparam.h> << 29 #include <asm/pgtable_32.h> << 30 17 31 /* Physical address */ !! 18 #include <asm/head.h> 32 #define pa(X) ((X) - __PAGE_OFFSET) !! 19 #include <asm/asi.h> >> 20 #include <asm/contregs.h> >> 21 #include <asm/ptrace.h> >> 22 #include <asm/psr.h> >> 23 #include <asm/page.h> >> 24 #include <asm/kdebug.h> >> 25 #include <asm/winmacro.h> >> 26 #include <asm/thread_info.h> /* TI_UWINMASK */ >> 27 #include <asm/errno.h> >> 28 #include <asm/pgtable.h> /* PGDIR_SHIFT */ 33 29 34 /* !! 30 .data 35 * References to members of the new_cpu_data s !! 31 /* The following are used with the prom_vector node-ops to figure out >> 32 * the cpu-type 36 */ 33 */ >> 34 .align 4 >> 35 .globl cputypval >> 36 cputypval: >> 37 .asciz "sun4m" >> 38 .ascii " " 37 39 38 #define X86 new_cpu_data+CPUINFO_x !! 40 /* Tested on SS-5, SS-10 */ 39 #define X86_VENDOR new_cpu_data+CPUINFO_x !! 41 .align 4 40 #define X86_MODEL new_cpu_data+CPUINFO_x !! 42 cputypvar: 41 #define X86_STEPPING new_cpu_data+CPUINFO_x !! 43 .asciz "compatible" 42 #define X86_HARD_MATH new_cpu_data+CPUINFO_h << 43 #define X86_CPUID new_cpu_data+CPUINFO_c << 44 #define X86_CAPABILITY new_cpu_data+CPUINFO_x << 45 #define X86_VENDOR_ID new_cpu_data+CPUINFO_x << 46 44 47 /* !! 45 .align 4 48 * Worst-case size of the kernel mapping we ne << 49 * a relocatable kernel can live anywhere in l << 50 * to map all of lowmem. << 51 */ << 52 KERNEL_PAGES = LOWMEM_PAGES << 53 46 54 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) !! 47 notsup: 55 RESERVE_BRK(pagetables, INIT_MAP_SIZE) !! 48 .asciz "Sparc-Linux sun4/sun4c or MMU-less not supported\n\n" >> 49 .align 4 56 50 57 /* !! 51 sun4e_notsup: 58 * 32-bit kernel entrypoint; only used by the !! 52 .asciz "Sparc-Linux sun4e support does not exist\n\n" 59 * %esi points to the real-mode code as a 32-b !! 53 .align 4 60 * CS and DS must be 4 GB flat segments, but w << 61 * any particular GDT layout, because we load << 62 * can. << 63 */ << 64 __HEAD << 65 SYM_CODE_START(startup_32) << 66 movl pa(initial_stack),%ecx << 67 << 68 /* << 69 * Set segments to known values. << 70 */ << 71 lgdt pa(boot_gdt_descr) << 72 movl $(__BOOT_DS),%eax << 73 movl %eax,%ds << 74 movl %eax,%es << 75 movl %eax,%fs << 76 movl %eax,%gs << 77 movl %eax,%ss << 78 leal -__PAGE_OFFSET(%ecx),%esp << 79 54 80 /* !! 55 /* The trap-table - located in the __HEAD section */ 81 * Clear BSS first so that there are no surpri !! 56 #include "ttable_32.S" 82 */ << 83 cld << 84 xorl %eax,%eax << 85 movl $pa(__bss_start),%edi << 86 movl $pa(__bss_stop),%ecx << 87 subl %edi,%ecx << 88 shrl $2,%ecx << 89 rep ; stosl << 90 /* << 91 * Copy bootup parameters out of the way. << 92 * Note: %esi still has the pointer to the rea << 93 * With the kexec as boot loader, parameter se << 94 * kernel image and might not even be addressa << 95 * (kexec on panic case). Hence copy out the p << 96 * page tables. << 97 */ << 98 movl $pa(boot_params),%edi << 99 movl $(PARAM_SIZE/4),%ecx << 100 cld << 101 rep << 102 movsl << 103 movl pa(boot_params) + NEW_CL_POINTER, << 104 andl %esi,%esi << 105 jz 1f # No command l << 106 movl $pa(boot_command_line),%edi << 107 movl $(COMMAND_LINE_SIZE/4),%ecx << 108 rep << 109 movsl << 110 1: << 111 57 112 #ifdef CONFIG_OLPC !! 58 .align PAGE_SIZE 113 /* save OFW's pgdir table for later us << 114 movl %cr3, %eax << 115 movl %eax, pa(olpc_ofw_pgd) << 116 #endif << 117 59 118 /* Create early pagetables. */ !! 60 /* This was the only reasonable way I could think of to properly align 119 call mk_early_pgtbl_32 !! 61 * these page-table data structures. >> 62 */ >> 63 .globl empty_zero_page >> 64 empty_zero_page: .skip PAGE_SIZE >> 65 EXPORT_SYMBOL(empty_zero_page) 120 66 121 /* Do early initialization of the fixm !! 67 .global root_flags 122 movl $pa(initial_pg_fixmap)+PDE_IDENT_ !! 68 .global ram_flags 123 #ifdef CONFIG_X86_PAE !! 69 .global root_dev 124 #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) / !! 70 .global sparc_ramdisk_image 125 movl %eax,pa(initial_pg_pmd+0x1000*KPM !! 71 .global sparc_ramdisk_size 126 #else !! 72 127 movl %eax,pa(initial_page_table+0xffc) !! 73 /* This stuff has to be in sync with SILO and other potential boot loaders 128 #endif !! 74 * Fields should be kept upward compatible and whenever any change is made, >> 75 * HdrS version should be incremented. >> 76 */ >> 77 .ascii "HdrS" >> 78 .word LINUX_VERSION_CODE >> 79 .half 0x0203 /* HdrS version */ >> 80 root_flags: >> 81 .half 1 >> 82 root_dev: >> 83 .half 0 >> 84 ram_flags: >> 85 .half 0 >> 86 sparc_ramdisk_image: >> 87 .word 0 >> 88 sparc_ramdisk_size: >> 89 .word 0 >> 90 .word reboot_command >> 91 .word 0, 0, 0 >> 92 .word _end >> 93 >> 94 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in >> 95 * %g7 and at prom_vector_p. And also quickly check whether we are on >> 96 * a v0, v2, or v3 prom. >> 97 */ >> 98 gokernel: >> 99 /* Ok, it's nice to know, as early as possible, if we >> 100 * are already mapped where we expect to be in virtual >> 101 * memory. The Solaris /boot elf format bootloader >> 102 * will peek into our elf header and load us where >> 103 * we want to be, otherwise we have to re-map. >> 104 * >> 105 * Some boot loaders don't place the jmp'rs address >> 106 * in %o7, so we do a pc-relative call to a local >> 107 * label, then see what %o7 has. >> 108 */ >> 109 >> 110 mov %o7, %g4 ! Save %o7 >> 111 >> 112 /* Jump to it, and pray... */ >> 113 current_pc: >> 114 call 1f >> 115 nop 129 116 130 jmp .Ldefault_entry !! 117 1: 131 SYM_CODE_END(startup_32) !! 118 mov %o7, %g3 132 119 133 /* !! 120 tst %o0 134 * Non-boot CPU entry point; entered from tram !! 121 bne 2f 135 * We can't lgdt here, because lgdt itself use !! 122 mov %g4, %o7 /* Previous %o7. */ 136 * we know the trampoline has already loaded t !! 123 sethi %hi(no_sun4u_here), %l1 137 * !! 124 jmpl %l1 + %lo(no_sun4u_here), %g0 138 * If cpu hotplug is not supported then this c !! 125 nop 139 * which will be freed later !! 126 2: 140 */ !! 127 mov %o0, %l0 ! stash away romvec 141 SYM_FUNC_START(startup_32_smp) !! 128 mov %o0, %g7 ! put it here too 142 cld !! 129 mov %o1, %l1 ! stash away debug_vec too 143 movl $(__BOOT_DS),%eax !! 130 144 movl %eax,%ds !! 131 /* Ok, let's check out our run time program counter. */ 145 movl %eax,%es !! 132 set current_pc, %g5 146 movl %eax,%fs !! 133 cmp %g3, %g5 147 movl %eax,%gs !! 134 be already_mapped 148 movl pa(initial_stack),%ecx !! 135 nop 149 movl %eax,%ss !! 136 150 leal -__PAGE_OFFSET(%ecx),%esp !! 137 /* %l6 will hold the offset we have to subtract 151 !! 138 * from absolute symbols in order to access areas 152 .Ldefault_entry: !! 139 * in our own image. If already mapped this is 153 movl $(CR0_STATE & ~X86_CR0_PG),%eax !! 140 * just plain zero, else it is KERNBASE. 154 movl %eax,%cr0 !! 141 */ >> 142 set KERNBASE, %l6 >> 143 b copy_prom_lvl14 >> 144 nop >> 145 >> 146 already_mapped: >> 147 mov 0, %l6 >> 148 >> 149 /* Copy over the Prom's level 14 clock handler. */ >> 150 copy_prom_lvl14: >> 151 #if 1 >> 152 /* DJHR >> 153 * preserve our linked/calculated instructions >> 154 */ >> 155 set lvl14_save, %g1 >> 156 set t_irq14, %g3 >> 157 sub %g1, %l6, %g1 ! translate to physical >> 158 sub %g3, %l6, %g3 ! translate to physical >> 159 ldd [%g3], %g4 >> 160 std %g4, [%g1] >> 161 ldd [%g3+8], %g4 >> 162 std %g4, [%g1+8] >> 163 #endif >> 164 rd %tbr, %g1 >> 165 andn %g1, 0xfff, %g1 ! proms trap table base >> 166 or %g0, (0x1e<<4), %g2 ! offset to lvl14 intr >> 167 or %g1, %g2, %g2 >> 168 set t_irq14, %g3 >> 169 sub %g3, %l6, %g3 >> 170 ldd [%g2], %g4 >> 171 std %g4, [%g3] >> 172 ldd [%g2 + 0x8], %g4 >> 173 std %g4, [%g3 + 0x8] ! Copy proms handler >> 174 >> 175 /* DON'T TOUCH %l0 thru %l5 in these remapping routines, >> 176 * we need their values afterwards! >> 177 */ >> 178 >> 179 /* Now check whether we are already mapped, if we >> 180 * are we can skip all this garbage coming up. >> 181 */ >> 182 copy_prom_done: >> 183 cmp %l6, 0 >> 184 be go_to_highmem ! this will be a nop then >> 185 nop >> 186 >> 187 /* Validate that we are in fact running on an >> 188 * SRMMU based cpu. >> 189 */ >> 190 set 0x4000, %g6 >> 191 cmp %g7, %g6 >> 192 bne not_a_sun4 >> 193 nop >> 194 >> 195 halt_notsup: >> 196 ld [%g7 + 0x68], %o1 >> 197 set notsup, %o0 >> 198 sub %o0, %l6, %o0 >> 199 call %o1 >> 200 nop >> 201 sethi %hi(halt_me), %o0 >> 202 jmpl %o0 + %lo(halt_me), %g0 >> 203 nop >> 204 >> 205 not_a_sun4: >> 206 /* It looks like this is a machine we support. >> 207 * Now find out what MMU we are dealing with >> 208 * LEON - identified by the psr.impl field >> 209 * Viking - identified by the psr.impl field >> 210 * In all other cases a sun4m srmmu. >> 211 * We check that the MMU is enabled in all cases. >> 212 */ >> 213 >> 214 /* Check if this is a LEON CPU */ >> 215 rd %psr, %g3 >> 216 srl %g3, PSR_IMPL_SHIFT, %g3 >> 217 and %g3, PSR_IMPL_SHIFTED_MASK, %g3 >> 218 cmp %g3, PSR_IMPL_LEON >> 219 be leon_remap /* It is a LEON - jump */ >> 220 nop >> 221 >> 222 /* Sanity-check, is MMU enabled */ >> 223 lda [%g0] ASI_M_MMUREGS, %g1 >> 224 andcc %g1, 1, %g0 >> 225 be halt_notsup >> 226 nop >> 227 >> 228 /* Check for a viking (TI) module. */ >> 229 cmp %g3, PSR_IMPL_TI >> 230 bne srmmu_not_viking >> 231 nop >> 232 >> 233 /* Figure out what kind of viking we are on. >> 234 * We need to know if we have to play with the >> 235 * AC bit and disable traps or not. >> 236 */ >> 237 >> 238 /* I've only seen MicroSparc's on SparcClassics with this >> 239 * bit set. >> 240 */ >> 241 set 0x800, %g2 >> 242 lda [%g0] ASI_M_MMUREGS, %g3 ! peek in the control reg >> 243 and %g2, %g3, %g3 >> 244 subcc %g3, 0x0, %g0 >> 245 bnz srmmu_not_viking ! is in mbus mode >> 246 nop >> 247 >> 248 rd %psr, %g3 ! DO NOT TOUCH %g3 >> 249 andn %g3, PSR_ET, %g2 >> 250 wr %g2, 0x0, %psr >> 251 WRITE_PAUSE >> 252 >> 253 /* Get context table pointer, then convert to >> 254 * a physical address, which is 36 bits. >> 255 */ >> 256 set AC_M_CTPR, %g4 >> 257 lda [%g4] ASI_M_MMUREGS, %g4 >> 258 sll %g4, 0x4, %g4 ! We use this below >> 259 ! DO NOT TOUCH %g4 >> 260 >> 261 /* Set the AC bit in the Viking's MMU control reg. */ >> 262 lda [%g0] ASI_M_MMUREGS, %g5 ! DO NOT TOUCH %g5 >> 263 set 0x8000, %g6 ! AC bit mask >> 264 or %g5, %g6, %g6 ! Or it in... >> 265 sta %g6, [%g0] ASI_M_MMUREGS ! Close your eyes... >> 266 >> 267 /* Grrr, why does it seem like every other load/store >> 268 * on the sun4m is in some ASI space... >> 269 * Fine with me, let's get the pointer to the level 1 >> 270 * page table directory and fetch its entry. >> 271 */ >> 272 lda [%g4] ASI_M_BYPASS, %o1 ! This is a level 1 ptr >> 273 srl %o1, 0x4, %o1 ! Clear low 4 bits >> 274 sll %o1, 0x8, %o1 ! Make physical >> 275 >> 276 /* Ok, pull in the PTD. */ >> 277 lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd >> 278 >> 279 /* Calculate to KERNBASE entry. */ >> 280 add %o1, KERNBASE >> (PGDIR_SHIFT - 2), %o3 >> 281 >> 282 /* Poke the entry into the calculated address. */ >> 283 sta %o2, [%o3] ASI_M_BYPASS >> 284 >> 285 /* I don't get it Sun, if you engineered all these >> 286 * boot loaders and the PROM (thank you for the debugging >> 287 * features btw) why did you not have them load kernel >> 288 * images up in high address space, since this is necessary >> 289 * for ABI compliance anyways? Does this low-mapping provide >> 290 * enhanced interoperability? >> 291 * >> 292 * "The PROM is the computer." >> 293 */ >> 294 >> 295 /* Ok, restore the MMU control register we saved in %g5 */ >> 296 sta %g5, [%g0] ASI_M_MMUREGS ! POW... ouch >> 297 >> 298 /* Turn traps back on. We saved it in %g3 earlier. */ >> 299 wr %g3, 0x0, %psr ! tick tock, tick tock >> 300 >> 301 /* Now we burn precious CPU cycles due to bad engineering. */ >> 302 WRITE_PAUSE >> 303 >> 304 /* Wow, all that just to move a 32-bit value from one >> 305 * place to another... Jump to high memory. >> 306 */ >> 307 b go_to_highmem >> 308 nop >> 309 >> 310 srmmu_not_viking: >> 311 /* This works on viking's in Mbus mode and all >> 312 * other MBUS modules. It is virtually the same as >> 313 * the above madness sans turning traps off and flipping >> 314 * the AC bit. >> 315 */ >> 316 set AC_M_CTPR, %g1 >> 317 lda [%g1] ASI_M_MMUREGS, %g1 ! get ctx table ptr >> 318 sll %g1, 0x4, %g1 ! make physical addr >> 319 lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table >> 320 srl %g1, 0x4, %g1 >> 321 sll %g1, 0x8, %g1 ! make phys addr for l1 tbl >> 322 >> 323 lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0 >> 324 add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3 >> 325 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry >> 326 b go_to_highmem >> 327 nop ! wheee.... >> 328 >> 329 >> 330 leon_remap: >> 331 /* Sanity-check, is MMU enabled */ >> 332 lda [%g0] ASI_LEON_MMUREGS, %g1 >> 333 andcc %g1, 1, %g0 >> 334 be halt_notsup >> 335 nop >> 336 >> 337 /* Same code as in the srmmu_not_viking case, >> 338 * with the LEON ASI for mmuregs >> 339 */ >> 340 set AC_M_CTPR, %g1 >> 341 lda [%g1] ASI_LEON_MMUREGS, %g1 ! get ctx table ptr >> 342 sll %g1, 0x4, %g1 ! make physical addr >> 343 lda [%g1] ASI_M_BYPASS, %g1 ! ptr to level 1 pg_table >> 344 srl %g1, 0x4, %g1 >> 345 sll %g1, 0x8, %g1 ! make phys addr for l1 tbl >> 346 >> 347 lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0 >> 348 add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3 >> 349 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry >> 350 b go_to_highmem >> 351 nop ! wheee.... >> 352 >> 353 /* Now do a non-relative jump so that PC is in high-memory */ >> 354 go_to_highmem: >> 355 set execute_in_high_mem, %g1 >> 356 jmpl %g1, %g0 >> 357 nop >> 358 >> 359 /* The code above should be at beginning and we have to take care about >> 360 * short jumps, as branching to .init.text section from .text is usually >> 361 * impossible */ >> 362 __INIT >> 363 /* Acquire boot time privileged register values, this will help debugging. >> 364 * I figure out and store nwindows and nwindowsm1 later on. >> 365 */ >> 366 execute_in_high_mem: >> 367 mov %l0, %o0 ! put back romvec >> 368 mov %l1, %o1 ! and debug_vec >> 369 >> 370 sethi %hi(prom_vector_p), %g1 >> 371 st %o0, [%g1 + %lo(prom_vector_p)] >> 372 >> 373 sethi %hi(linux_dbvec), %g1 >> 374 st %o1, [%g1 + %lo(linux_dbvec)] >> 375 >> 376 /* Get the machine type via the romvec >> 377 * getprops node operation >> 378 */ >> 379 add %g7, 0x1c, %l1 >> 380 ld [%l1], %l0 >> 381 ld [%l0], %l0 >> 382 call %l0 >> 383 or %g0, %g0, %o0 ! next_node(0) = first_node >> 384 or %o0, %g0, %g6 >> 385 >> 386 sethi %hi(cputypvar), %o1 ! First node has cpu-arch >> 387 or %o1, %lo(cputypvar), %o1 >> 388 sethi %hi(cputypval), %o2 ! information, the string >> 389 or %o2, %lo(cputypval), %o2 >> 390 ld [%l1], %l0 ! 'compatible' tells >> 391 ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where >> 392 call %l0 ! x is one of 'm', 'd' or 'e'. >> 393 nop ! %o2 holds pointer >> 394 ! to a buf where above string >> 395 ! will get stored by the prom. >> 396 >> 397 >> 398 /* Check value of "compatible" property. >> 399 * "value" => "model" >> 400 * leon => sparc_leon >> 401 * sun4m => sun4m >> 402 * sun4s => sun4m >> 403 * sun4d => sun4d >> 404 * sun4e => "no_sun4e_here" >> 405 * '*' => "no_sun4u_here" >> 406 * Check single letters only >> 407 */ >> 408 >> 409 set cputypval, %o2 >> 410 /* If cputypval[0] == 'l' (lower case letter L) this is leon */ >> 411 ldub [%o2], %l1 >> 412 cmp %l1, 'l' >> 413 be leon_init >> 414 nop >> 415 >> 416 /* Check cputypval[4] to find the sun model */ >> 417 ldub [%o2 + 0x4], %l1 >> 418 >> 419 cmp %l1, 'm' >> 420 be sun4m_init >> 421 cmp %l1, 's' >> 422 be sun4m_init >> 423 cmp %l1, 'd' >> 424 be sun4d_init >> 425 cmp %l1, 'e' >> 426 be no_sun4e_here ! Could be a sun4e. >> 427 nop >> 428 b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) >> 429 nop >> 430 >> 431 leon_init: >> 432 /* LEON CPU - set boot_cpu_id */ >> 433 sethi %hi(boot_cpu_id), %g2 ! boot-cpu index >> 434 >> 435 #ifdef CONFIG_SMP >> 436 ldub [%g2 + %lo(boot_cpu_id)], %g1 >> 437 cmp %g1, 0xff ! unset means first CPU >> 438 be 1f >> 439 sethi %hi(leon_smp_cpu_startup), %g1 >> 440 jmpl %g1 + %lo(leon_smp_cpu_startup), %g0 >> 441 nop >> 442 1: >> 443 #endif >> 444 /* Get CPU-ID from most significant 4-bit of ASR17 */ >> 445 rd %asr17, %g1 >> 446 srl %g1, 28, %g1 >> 447 >> 448 /* Update boot_cpu_id only on boot cpu */ >> 449 stub %g1, [%g2 + %lo(boot_cpu_id)] >> 450 >> 451 ba continue_boot >> 452 nop >> 453 >> 454 /* CPUID in bootbus can be found at PA 0xff0140000 */ >> 455 #define SUN4D_BOOTBUS_CPUID 0xf0140000 >> 456 >> 457 sun4d_init: >> 458 /* Need to patch call to handler_irq */ >> 459 set patch_handler_irq, %g4 >> 460 set sun4d_handler_irq, %g5 >> 461 sethi %hi(0x40000000), %g3 ! call >> 462 sub %g5, %g4, %g5 >> 463 srl %g5, 2, %g5 >> 464 or %g5, %g3, %g5 >> 465 st %g5, [%g4] >> 466 >> 467 #ifdef CONFIG_SMP >> 468 /* Get our CPU id out of bootbus */ >> 469 set SUN4D_BOOTBUS_CPUID, %g3 >> 470 lduba [%g3] ASI_M_CTL, %g3 >> 471 and %g3, 0xf8, %g3 >> 472 srl %g3, 3, %g4 >> 473 sta %g4, [%g0] ASI_M_VIKING_TMP1 >> 474 sethi %hi(boot_cpu_id), %g5 >> 475 stb %g4, [%g5 + %lo(boot_cpu_id)] >> 476 #endif 155 477 156 /* !! 478 /* Fall through to sun4m_init */ 157 * We want to start out with EFLAGS unambiguou << 158 * bits like NT set. This would confuse the de << 159 * initialize them properly now before switchi << 160 * DF in particular (even though we have clear << 161 * command line) because GCC expects it. << 162 */ << 163 pushl $0 << 164 popfl << 165 479 166 /* !! 480 sun4m_init: 167 * New page tables may be in 4Mbyte page mode !! 481 /* Ok, the PROM could have done funny things and apple cider could still 168 * !! 482 * be sitting in the fault status/address registers. Read them all to 169 * NOTE! If we are on a 486 we may have no cr4 !! 483 * clear them so we don't get magic faults later on. 170 * if and only if CPUID exists and has flags o !! 484 */ 171 */ !! 485 /* This sucks, apparently this makes Vikings call prom panic, will fix later */ 172 movl $-1,pa(X86_CPUID) # pres !! 486 2: 173 movl $X86_EFLAGS_ID,%ecx !! 487 rd %psr, %o1 174 pushl %ecx !! 488 srl %o1, PSR_IMPL_SHIFT, %o1 ! Get a type of the CPU 175 popfl # set !! 489 176 pushfl !! 490 subcc %o1, PSR_IMPL_TI, %g0 ! TI: Viking or MicroSPARC 177 popl %eax # get !! 491 be continue_boot 178 testl $X86_EFLAGS_ID,%eax # did !! 492 nop 179 jz .Lenable_paging # hw d !! 493 180 # whic !! 494 set AC_M_SFSR, %o0 181 !! 495 lda [%o0] ASI_M_MMUREGS, %g0 182 xorl %eax,%eax !! 496 set AC_M_SFAR, %o0 183 cpuid !! 497 lda [%o0] ASI_M_MMUREGS, %g0 184 movl %eax,pa(X86_CPUID) # save !! 498 185 !! 499 /* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */ 186 movl $1,%eax !! 500 subcc %o1, 0, %g0 187 cpuid !! 501 be continue_boot 188 andl $~1,%edx # Igno !! 502 nop 189 jz .Lenable_paging # No f !! 503 190 !! 504 set AC_M_AFSR, %o0 191 movl pa(mmu_cr4_features),%eax !! 505 lda [%o0] ASI_M_MMUREGS, %g0 192 movl %eax,%cr4 !! 506 set AC_M_AFAR, %o0 193 !! 507 lda [%o0] ASI_M_MMUREGS, %g0 194 testb $X86_CR4_PAE, %al # chec !! 508 nop 195 jz .Lenable_paging !! 509 196 !! 510 197 /* Check if extended functions are imp !! 511 continue_boot: 198 movl $0x80000000, %eax !! 512 199 cpuid !! 513 /* Aieee, now set PC and nPC, enable traps, give ourselves a stack and it's 200 /* Value must be in the range 0x800000 !! 514 * show-time! 201 subl $0x80000001, %eax !! 515 */ 202 cmpl $(0x8000ffff-0x80000001), %eax !! 516 /* Turn on Supervisor, EnableFloating, and all the PIL bits. 203 ja .Lenable_paging !! 517 * Also puts us in register window zero with traps off. 204 !! 518 */ 205 /* Clear bogus XD_DISABLE bits */ !! 519 set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2 206 call verify_cpu !! 520 wr %g2, 0x0, %psr 207 !! 521 WRITE_PAUSE 208 mov $0x80000001, %eax !! 522 209 cpuid !! 523 /* I want a kernel stack NOW! */ 210 /* Execute Disable bit supported? */ !! 524 set init_thread_union, %g1 211 btl $(X86_FEATURE_NX & 31), %edx !! 525 set (THREAD_SIZE - STACKFRAME_SZ - TRACEREG_SZ), %g2 212 jnc .Lenable_paging !! 526 add %g1, %g2, %sp 213 !! 527 mov 0, %fp /* And for good luck */ 214 /* Setup EFER (Extended Feature Enable !! 528 215 movl $MSR_EFER, %ecx !! 529 /* Zero out our BSS section. */ 216 rdmsr !! 530 set __bss_start , %o0 ! First address of BSS 217 !! 531 set _end , %o1 ! Last address of BSS 218 btsl $_EFER_NX, %eax !! 532 add %o0, 0x1, %o0 219 /* Make changes effective */ !! 533 1: 220 wrmsr !! 534 stb %g0, [%o0] >> 535 subcc %o0, %o1, %g0 >> 536 bl 1b >> 537 add %o0, 0x1, %o0 >> 538 >> 539 /* If boot_cpu_id has not been setup by machine specific >> 540 * init-code above we default it to zero. >> 541 */ >> 542 sethi %hi(boot_cpu_id), %g2 >> 543 ldub [%g2 + %lo(boot_cpu_id)], %g3 >> 544 cmp %g3, 0xff >> 545 bne 1f >> 546 nop >> 547 mov %g0, %g3 >> 548 stub %g3, [%g2 + %lo(boot_cpu_id)] >> 549 >> 550 1: sll %g3, 2, %g3 >> 551 >> 552 /* Initialize the uwinmask value for init task just in case. >> 553 * But first make current_set[boot_cpu_id] point to something useful. >> 554 */ >> 555 set init_thread_union, %g6 >> 556 set current_set, %g2 >> 557 #ifdef CONFIG_SMP >> 558 st %g6, [%g2] >> 559 add %g2, %g3, %g2 >> 560 #endif >> 561 st %g6, [%g2] 221 562 222 .Lenable_paging: !! 563 st %g0, [%g6 + TI_UWINMASK] 223 564 224 /* !! 565 /* Compute NWINDOWS and stash it away. Now uses %wim trick explained 225 * Enable paging !! 566 * in the V8 manual. Ok, this method seems to work, Sparc is cool... 226 */ !! 567 * No, it doesn't work, have to play the save/readCWP/restore trick. 227 movl $pa(initial_page_table), %eax !! 568 */ 228 movl %eax,%cr3 /* set the pag !! 569 229 movl $CR0_STATE,%eax !! 570 wr %g0, 0x0, %wim ! so we do not get a trap 230 movl %eax,%cr0 /* ..and set p !! 571 WRITE_PAUSE 231 ljmp $__BOOT_CS,$1f /* Clear prefe !! 572 >> 573 save >> 574 >> 575 rd %psr, %g3 >> 576 >> 577 restore >> 578 >> 579 and %g3, 0x1f, %g3 >> 580 add %g3, 0x1, %g3 >> 581 >> 582 mov 2, %g1 >> 583 wr %g1, 0x0, %wim ! make window 1 invalid >> 584 WRITE_PAUSE >> 585 >> 586 cmp %g3, 0x7 >> 587 bne 2f >> 588 nop >> 589 >> 590 /* Adjust our window handling routines to >> 591 * do things correctly on 7 window Sparcs. >> 592 */ >> 593 >> 594 #define PATCH_INSN(src, dest) \ >> 595 set src, %g5; \ >> 596 set dest, %g2; \ >> 597 ld [%g5], %g4; \ >> 598 st %g4, [%g2]; >> 599 >> 600 /* Patch for window spills... */ >> 601 PATCH_INSN(spnwin_patch1_7win, spnwin_patch1) >> 602 PATCH_INSN(spnwin_patch2_7win, spnwin_patch2) >> 603 PATCH_INSN(spnwin_patch3_7win, spnwin_patch3) >> 604 >> 605 /* Patch for window fills... */ >> 606 PATCH_INSN(fnwin_patch1_7win, fnwin_patch1) >> 607 PATCH_INSN(fnwin_patch2_7win, fnwin_patch2) >> 608 >> 609 /* Patch for trap entry setup... */ >> 610 PATCH_INSN(tsetup_7win_patch1, tsetup_patch1) >> 611 PATCH_INSN(tsetup_7win_patch2, tsetup_patch2) >> 612 PATCH_INSN(tsetup_7win_patch3, tsetup_patch3) >> 613 PATCH_INSN(tsetup_7win_patch4, tsetup_patch4) >> 614 PATCH_INSN(tsetup_7win_patch5, tsetup_patch5) >> 615 PATCH_INSN(tsetup_7win_patch6, tsetup_patch6) >> 616 >> 617 /* Patch for returning from traps... */ >> 618 PATCH_INSN(rtrap_7win_patch1, rtrap_patch1) >> 619 PATCH_INSN(rtrap_7win_patch2, rtrap_patch2) >> 620 PATCH_INSN(rtrap_7win_patch3, rtrap_patch3) >> 621 PATCH_INSN(rtrap_7win_patch4, rtrap_patch4) >> 622 PATCH_INSN(rtrap_7win_patch5, rtrap_patch5) >> 623 >> 624 /* Patch for killing user windows from the register file. */ >> 625 PATCH_INSN(kuw_patch1_7win, kuw_patch1) >> 626 >> 627 /* Now patch the kernel window flush sequences. >> 628 * This saves 2 traps on every switch and fork. >> 629 */ >> 630 set 0x01000000, %g4 >> 631 set flush_patch_one, %g5 >> 632 st %g4, [%g5 + 0x18] >> 633 st %g4, [%g5 + 0x1c] >> 634 set flush_patch_two, %g5 >> 635 st %g4, [%g5 + 0x18] >> 636 st %g4, [%g5 + 0x1c] >> 637 set flush_patch_three, %g5 >> 638 st %g4, [%g5 + 0x18] >> 639 st %g4, [%g5 + 0x1c] >> 640 set flush_patch_four, %g5 >> 641 st %g4, [%g5 + 0x18] >> 642 st %g4, [%g5 + 0x1c] >> 643 set flush_patch_exception, %g5 >> 644 st %g4, [%g5 + 0x18] >> 645 st %g4, [%g5 + 0x1c] >> 646 set flush_patch_switch, %g5 >> 647 st %g4, [%g5 + 0x18] >> 648 st %g4, [%g5 + 0x1c] >> 649 >> 650 2: >> 651 sethi %hi(nwindows), %g4 >> 652 st %g3, [%g4 + %lo(nwindows)] ! store final value >> 653 sub %g3, 0x1, %g3 >> 654 sethi %hi(nwindowsm1), %g4 >> 655 st %g3, [%g4 + %lo(nwindowsm1)] >> 656 >> 657 /* Here we go, start using Linux's trap table... */ >> 658 set trapbase, %g3 >> 659 wr %g3, 0x0, %tbr >> 660 WRITE_PAUSE >> 661 >> 662 /* Finally, turn on traps so that we can call c-code. */ >> 663 rd %psr, %g3 >> 664 wr %g3, 0x0, %psr >> 665 WRITE_PAUSE >> 666 >> 667 wr %g3, PSR_ET, %psr >> 668 WRITE_PAUSE >> 669 >> 670 /* Call sparc32_start_kernel(struct linux_romvec *rp) */ >> 671 sethi %hi(prom_vector_p), %g5 >> 672 ld [%g5 + %lo(prom_vector_p)], %o0 >> 673 call sparc32_start_kernel >> 674 nop >> 675 >> 676 /* We should not get here. */ >> 677 call halt_me >> 678 nop >> 679 >> 680 no_sun4e_here: >> 681 ld [%g7 + 0x68], %o1 >> 682 set sun4e_notsup, %o0 >> 683 call %o1 >> 684 nop >> 685 b halt_me >> 686 nop >> 687 >> 688 __INITDATA >> 689 >> 690 sun4u_1: >> 691 .asciz "finddevice" >> 692 .align 4 >> 693 sun4u_2: >> 694 .asciz "/chosen" >> 695 .align 4 >> 696 sun4u_3: >> 697 .asciz "getprop" >> 698 .align 4 >> 699 sun4u_4: >> 700 .asciz "stdout" >> 701 .align 4 >> 702 sun4u_5: >> 703 .asciz "write" >> 704 .align 4 >> 705 sun4u_6: >> 706 .asciz "\n\rOn sun4u you have to use sparc64 kernel\n\rand not a sparc32 version\n\r\n\r" >> 707 sun4u_6e: >> 708 .align 4 >> 709 sun4u_7: >> 710 .asciz "exit" >> 711 .align 8 >> 712 sun4u_a1: >> 713 .word 0, sun4u_1, 0, 1, 0, 1, 0, sun4u_2, 0 >> 714 sun4u_r1: >> 715 .word 0 >> 716 sun4u_a2: >> 717 .word 0, sun4u_3, 0, 4, 0, 1, 0 >> 718 sun4u_i2: >> 719 .word 0, 0, sun4u_4, 0, sun4u_1, 0, 8, 0 >> 720 sun4u_r2: >> 721 .word 0 >> 722 sun4u_a3: >> 723 .word 0, sun4u_5, 0, 3, 0, 1, 0 >> 724 sun4u_i3: >> 725 .word 0, 0, sun4u_6, 0, sun4u_6e - sun4u_6 - 1, 0 >> 726 sun4u_r3: >> 727 .word 0 >> 728 sun4u_a4: >> 729 .word 0, sun4u_7, 0, 0, 0, 0 >> 730 sun4u_r4: >> 731 >> 732 __INIT >> 733 no_sun4u_here: >> 734 set sun4u_a1, %o0 >> 735 set current_pc, %l2 >> 736 cmp %l2, %g3 >> 737 be 1f >> 738 mov %o4, %l0 >> 739 sub %g3, %l2, %l6 >> 740 add %o0, %l6, %o0 >> 741 mov %o0, %l4 >> 742 mov sun4u_r4 - sun4u_a1, %l3 >> 743 ld [%l4], %l5 >> 744 2: >> 745 add %l4, 4, %l4 >> 746 cmp %l5, %l2 >> 747 add %l5, %l6, %l5 >> 748 bgeu,a 3f >> 749 st %l5, [%l4 - 4] >> 750 3: >> 751 subcc %l3, 4, %l3 >> 752 bne 2b >> 753 ld [%l4], %l5 232 1: 754 1: 233 /* Shift the stack pointer to a virtua !! 755 call %l0 234 addl $__PAGE_OFFSET, %esp !! 756 mov %o0, %l1 235 757 236 /* !! 758 ld [%l1 + (sun4u_r1 - sun4u_a1)], %o1 237 * Check if it is 486 !! 759 add %l1, (sun4u_a2 - sun4u_a1), %o0 238 */ !! 760 call %l0 239 movb $4,X86 # at l !! 761 st %o1, [%o0 + (sun4u_i2 - sun4u_a2)] 240 cmpl $-1,X86_CPUID !! 762 241 je .Lis486 !! 763 ld [%l1 + (sun4u_1 - sun4u_a1)], %o1 242 !! 764 add %l1, (sun4u_a3 - sun4u_a1), %o0 243 /* get vendor info */ !! 765 call %l0 244 xorl %eax,%eax # call !! 766 st %o1, [%o0 + (sun4u_i3 - sun4u_a3)] 245 cpuid !! 767 246 movl %eax,X86_CPUID # save !! 768 call %l0 247 movl %ebx,X86_VENDOR_ID # lo 4 !! 769 add %l1, (sun4u_a4 - sun4u_a1), %o0 248 movl %edx,X86_VENDOR_ID+4 # next !! 770 249 movl %ecx,X86_VENDOR_ID+8 # last !! 771 /* Not reached */ 250 !! 772 halt_me: 251 orl %eax,%eax # do w !! 773 ld [%g7 + 0x74], %o0 252 je .Lis486 !! 774 call %o0 ! Get us out of here... 253 !! 775 nop ! Apparently Solaris is better. 254 movl $1,%eax # Use the CPUI << 255 cpuid << 256 movb %al,%cl # save reg for << 257 andb $0x0f,%ah # mask process << 258 movb %ah,X86 << 259 andb $0xf0,%al # mask model << 260 shrb $4,%al << 261 movb %al,X86_MODEL << 262 andb $0x0f,%cl # mask mask re << 263 movb %cl,X86_STEPPING << 264 movl %edx,X86_CAPABILITY << 265 << 266 .Lis486: << 267 movl $0x50022,%ecx # set AM, WP, << 268 movl %cr0,%eax << 269 andl $0x80000011,%eax # Save PG,PE,E << 270 orl %ecx,%eax << 271 movl %eax,%cr0 << 272 << 273 lgdt early_gdt_descr << 274 ljmp $(__KERNEL_CS),$1f << 275 1: movl $(__KERNEL_DS),%eax # relo << 276 movl %eax,%ss # afte << 277 << 278 movl $(__USER_DS),%eax # DS/E << 279 movl %eax,%ds << 280 movl %eax,%es << 281 << 282 movl $(__KERNEL_PERCPU), %eax << 283 movl %eax,%fs # set << 284 << 285 xorl %eax,%eax << 286 movl %eax,%gs # clea << 287 << 288 xorl %eax,%eax # Clea << 289 lldt %ax << 290 << 291 call *(initial_code) << 292 1: jmp 1b << 293 SYM_FUNC_END(startup_32_smp) << 294 << 295 #include "verify_cpu.S" << 296 << 297 __INIT << 298 SYM_FUNC_START(early_idt_handler_array) << 299 # 36(%esp) %eflags << 300 # 32(%esp) %cs << 301 # 28(%esp) %eip << 302 # 24(%rsp) error code << 303 i = 0 << 304 .rept NUM_EXCEPTION_VECTORS << 305 .if ((EXCEPTION_ERRCODE_MASK >> i) & 1 << 306 pushl $0 # Dummy error << 307 .endif << 308 pushl $i # 20(%esp) Vec << 309 jmp early_idt_handler_common << 310 i = i + 1 << 311 .fill early_idt_handler_array + i*EARL << 312 .endr << 313 SYM_FUNC_END(early_idt_handler_array) << 314 << 315 SYM_CODE_START_LOCAL(early_idt_handler_common) << 316 /* << 317 * The stack is the hardware frame, an << 318 * vector number. << 319 */ << 320 cld << 321 << 322 incl %ss:early_recursion_flag << 323 << 324 /* The vector number is in pt_regs->gs << 325 << 326 cld << 327 pushl %fs /* pt_regs->fs << 328 pushl %es /* pt_regs->es << 329 pushl %ds /* pt_regs->ds << 330 pushl %eax /* pt_regs->ax << 331 pushl %ebp /* pt_regs->bp << 332 pushl %edi /* pt_regs->di << 333 pushl %esi /* pt_regs->si << 334 pushl %edx /* pt_regs->dx << 335 pushl %ecx /* pt_regs->cx << 336 pushl %ebx /* pt_regs->bx << 337 << 338 /* Fix up DS and ES */ << 339 movl $(__KERNEL_DS), %ecx << 340 movl %ecx, %ds << 341 movl %ecx, %es << 342 << 343 /* Load the vector number into EDX */ << 344 movl PT_GS(%esp), %edx << 345 << 346 /* Load GS into pt_regs->gs (and maybe << 347 movw %gs, PT_GS(%esp) << 348 << 349 movl %esp, %eax /* args are pt << 350 call early_fixup_exception << 351 << 352 popl %ebx /* pt_regs->bx << 353 popl %ecx /* pt_regs->cx << 354 popl %edx /* pt_regs->dx << 355 popl %esi /* pt_regs->si << 356 popl %edi /* pt_regs->di << 357 popl %ebp /* pt_regs->bp << 358 popl %eax /* pt_regs->ax << 359 popl %ds /* pt_regs->ds << 360 popl %es /* pt_regs->es << 361 popl %fs /* pt_regs->fs << 362 popl %gs /* pt_regs->gs << 363 decl %ss:early_recursion_flag << 364 addl $4, %esp /* pop pt_regs << 365 iret << 366 SYM_CODE_END(early_idt_handler_common) << 367 << 368 /* This is the default interrupt "handler" :-) << 369 SYM_FUNC_START(early_ignore_irq) << 370 cld << 371 #ifdef CONFIG_PRINTK << 372 pushl %eax << 373 pushl %ecx << 374 pushl %edx << 375 pushl %es << 376 pushl %ds << 377 movl $(__KERNEL_DS),%eax << 378 movl %eax,%ds << 379 movl %eax,%es << 380 cmpl $2,early_recursion_flag << 381 je hlt_loop << 382 incl early_recursion_flag << 383 pushl 16(%esp) << 384 pushl 24(%esp) << 385 pushl 32(%esp) << 386 pushl 40(%esp) << 387 pushl $int_msg << 388 call _printk << 389 << 390 call dump_stack << 391 << 392 addl $(5*4),%esp << 393 popl %ds << 394 popl %es << 395 popl %edx << 396 popl %ecx << 397 popl %eax << 398 #endif << 399 iret << 400 776 401 hlt_loop: !! 777 /* Ok, now we continue in the .data/.text sections */ 402 hlt << 403 jmp hlt_loop << 404 SYM_FUNC_END(early_ignore_irq) << 405 << 406 __INITDATA << 407 .align 4 << 408 SYM_DATA(early_recursion_flag, .long 0) << 409 778 410 __REFDATA !! 779 .data 411 .align 4 780 .align 4 412 SYM_DATA(initial_code, .long i386_sta << 413 << 414 #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION << 415 #define PGD_ALIGN (2 * PAGE_SIZE) << 416 #define PTI_USER_PGD_FILL 1024 << 417 #else << 418 #define PGD_ALIGN (PAGE_SIZE) << 419 #define PTI_USER_PGD_FILL 0 << 420 #endif << 421 /* << 422 * BSS section << 423 */ << 424 __PAGE_ALIGNED_BSS << 425 .align PGD_ALIGN << 426 #ifdef CONFIG_X86_PAE << 427 .globl initial_pg_pmd << 428 initial_pg_pmd: << 429 .fill 1024*KPMDS,4,0 << 430 #else << 431 .globl initial_page_table << 432 initial_page_table: << 433 .fill 1024,4,0 << 434 #endif << 435 .align PGD_ALIGN << 436 initial_pg_fixmap: << 437 .fill 1024,4,0 << 438 .globl swapper_pg_dir << 439 .align PGD_ALIGN << 440 swapper_pg_dir: << 441 .fill 1024,4,0 << 442 .fill PTI_USER_PGD_FILL,4,0 << 443 .globl empty_zero_page << 444 empty_zero_page: << 445 .fill 4096,1,0 << 446 EXPORT_SYMBOL(empty_zero_page) << 447 781 448 /* 782 /* 449 * This starts the data section. !! 783 * Fill up the prom vector, note in particular the kind first element, >> 784 * no joke. I don't need all of them in here as the entire prom vector >> 785 * gets initialized in c-code so all routines can use it. 450 */ 786 */ 451 #ifdef CONFIG_X86_PAE << 452 __PAGE_ALIGNED_DATA << 453 /* Page-aligned for the benefit of par << 454 .align PGD_ALIGN << 455 SYM_DATA_START(initial_page_table) << 456 .long pa(initial_pg_pmd+PGD_IDENT_AT << 457 # if KPMDS == 3 << 458 .long pa(initial_pg_pmd+PGD_IDENT_AT << 459 .long pa(initial_pg_pmd+PGD_IDENT_AT << 460 .long pa(initial_pg_pmd+PGD_IDENT_AT << 461 # elif KPMDS == 2 << 462 .long 0,0 << 463 .long pa(initial_pg_pmd+PGD_IDENT_AT << 464 .long pa(initial_pg_pmd+PGD_IDENT_AT << 465 # elif KPMDS == 1 << 466 .long 0,0 << 467 .long 0,0 << 468 .long pa(initial_pg_pmd+PGD_IDENT_AT << 469 # else << 470 # error "Kernel PMDs should be 1, 2 or 3" << 471 # endif << 472 .align PAGE_SIZE /* nee << 473 << 474 #ifdef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION << 475 /* << 476 * PTI needs another page so sync_init << 477 * and does not scribble over the data << 478 * actual initial_page_table. See clon << 479 */ << 480 .fill 1024, 4, 0 << 481 #endif << 482 << 483 SYM_DATA_END(initial_page_table) << 484 #endif << 485 << 486 .data << 487 .balign 4 << 488 SYM_DATA(initial_stack, .long __top_init_kerne << 489 << 490 __INITRODATA << 491 int_msg: << 492 .asciz "Unknown interrupt or fault at: << 493 787 494 #include "../xen/xen-head.S" !! 788 prom_vector_p: >> 789 .word 0 495 790 496 /* !! 791 /* We calculate the following at boot time, window fills/spills and trap entry 497 * The IDT and GDT 'descriptors' are a strange !! 792 * code uses these to keep track of the register windows. 498 * only used by the lidt and lgdt instructions << 499 * like usual segment descriptors - they consi << 500 * segment size, and 32-bit linear address val << 501 */ 793 */ 502 794 503 .data !! 795 .align 4 504 ALIGN !! 796 .globl nwindows 505 # early boot GDT descriptor (must use 1:1 addr !! 797 .globl nwindowsm1 506 .word 0 # 32 b !! 798 nwindows: 507 SYM_DATA_START_LOCAL(boot_gdt_descr) !! 799 .word 8 508 .word __BOOT_DS+7 !! 800 nwindowsm1: 509 .long boot_gdt - __PAGE_OFFSET !! 801 .word 7 510 SYM_DATA_END(boot_gdt_descr) << 511 << 512 # boot GDT descriptor (later on used by CPU#0) << 513 .word 0 # 32 b << 514 SYM_DATA_START(early_gdt_descr) << 515 .word GDT_ENTRIES*8-1 << 516 .long gdt_page /* Ove << 517 SYM_DATA_END(early_gdt_descr) << 518 802 519 /* !! 803 /* Boot time debugger vector value. We need this later on. */ 520 * The boot_gdt must mirror the equivalent in !! 804 521 * used only for booting. !! 805 .align 4 522 */ !! 806 .globl linux_dbvec 523 .align L1_CACHE_BYTES !! 807 linux_dbvec: 524 SYM_DATA_START(boot_gdt) !! 808 .word 0 525 .fill GDT_ENTRY_BOOT_CS,8,0 !! 809 .word 0 526 .quad 0x00cf9a000000ffff /* ker !! 810 527 .quad 0x00cf92000000ffff /* ker !! 811 .align 8 528 SYM_DATA_END(boot_gdt) !! 812 >> 813 .globl lvl14_save >> 814 lvl14_save: >> 815 .word 0 >> 816 .word 0 >> 817 .word 0 >> 818 .word 0 >> 819 .word t_irq14
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.