/* $NetBSD: locore.s,v 1.114 2026/04/28 03:29:10 thorpej Exp $ */ /* * Copyright (c) 1998 Darrin B. Jewell * Copyright (c) 1980, 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: locore.s 1.66 92/12/22$ * * @(#)locore.s 8.6 (Berkeley) 5/27/94 */ /* * Copyright (c) 1994, 1995 Gordon W. Ross * Copyright (c) 1988 University of Utah. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: Utah $Hdr: locore.s 1.66 92/12/22$ * * @(#)locore.s 8.6 (Berkeley) 5/27/94 */ /* This is currently amid development by * Darrin Jewell <jewell@mit.edu> Fri Jan 2 14:36:47 1998 * for the next68k port */ #include "opt_compat_netbsd.h" #include "opt_compat_sunos.h" #include "opt_ddb.h" #include "opt_fpsp.h" #include "opt_kgdb.h" #include "opt_lockdebug.h" #include "opt_fpu_emulate.h" #include "opt_useleds.h" #include "opt_m68k_arch.h" #include "assym.h" #include <machine/asm.h> #include <machine/trap.h> #if (!defined(M68040)) #error "M68040 is not defined! (check that the generated assym.h is not empty)" #endif #include "ksyms.h" /* * This is for kvm_mkdb, and should be the address of the beginning * of the kernel text segment (not necessarily the same as kernbase). */ .text GLOBAL(kernel_text) /* * Leave page zero empty so it can be unmapped */ .space PAGE_SIZE /* * Temporary stack for a variety of purposes. */ .data GLOBAL(endstack) .space PAGE_SIZE GLOBAL(bgnstack) ASGLOBAL(tmpstk) /* * Macro to relocate a symbol, used before MMU is enabled. * On the NeXT, memory is laid out as in the mach header * so therefore we need to relocate symbols until the MMU * is turned on. */ #define _RELOC(var, ar) \ lea var,ar; \ addl %a5,ar #define RELOC(var, ar) _RELOC(_C_LABEL(var), ar) #define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar) /* * Initialization info as per grossman's boot loader: * * We are called from the boot prom, not the boot loader. We have the * prom's stack initialized for us and we were called like this: * start(mg, mg->mg_console_i, mg->mg_console_o, * mg->mg_boot_dev, mg->mg_boot_arg, mg->mg_boot_info, * mg->mg_sid, mg->mg_pagesize, 4, mg->mg_region, * etheraddr, mg->mg_boot_file); * so we actually only really need the first parameter from the stack. * Exceptions will be handled by the prom until we feel ready to handle * them ourselves. * By the way, we get loaded at our final address i.e. PA==VA for the kernel. */ /* I think the PA==VA comment to be a lie, but I have yet to verify it. * Darrin B Jewell <jewell@mit.edu> Sun Jan 11 01:05:54 1998 */ BSS(lowram,4) BSS(esym,4) ASENTRY_NOPROFILE(start) movw #PSL_HIGHIPL,%sr | no interrupts movl #CACHE_OFF,%d0 movc %d0,%cacr | clear and disable on-chip cache(s) moveal #NEXT_RAMBASE,%a5 | amount to RELOC by. RELOC(lowram,%a0) | store base of memory. movl %a5,%a0@ | Create a new stack at address tmpstk, and push | The existing sp onto it as an arg for next68k_bootargs. ASRELOC(tmpstk, %a0) movel %sp,%a0@- moveal %a0,%sp moveal #0,%a6 /* Read the header to get our segment list */ RELOC(next68k_bootargs,%a0) jbsr %a0@ | next68k_bootargs(args) addqw #4,%sp | clear arg from stack. /* * All data registers are now free. All address registers * except %a5 are free. %a5 is used by the RELOC() macro on hp300 * and cannot be used until after the MMU is enabled. */ /* determine our CPU/MMU combo - check for all regardless of kernel config */ movl #0x200,%d0 | data freeze bit movc %d0,%cacr | only exists on 68030 movc %cacr,%d0 | read it back tstl %d0 | zero? jeq Lnot68030 | yes, we have 68020/68040 /* * 68030 models */ RELOC(mmutype, %a0) | no, we have 68030 movl #MMU_68030,%a0@ | set to reflect 68030 PMMU RELOC(cputype, %a0) movl #CPU_68030,%a0@ | and 68030 CPU RELOC(machineid, %a0) movl #30,%a0@ | @@@ useless jra Lstart1 /* * End of 68030 section */ Lnot68030: bset #31,%d0 | data cache enable bit movc %d0,%cacr | only exists on 68040 movc %cacr,%d0 | read it back tstl %d0 | zero? beq Lis68020 | yes, we have 68020 moveq #0,%d0 | now turn it back off movec %d0,%cacr | before we access any data /* * 68040 models */ RELOC(mmutype, %a0) movl #MMU_68040,%a0@ | with a 68040 MMU RELOC(cputype, %a0) movl #CPU_68040,%a0@ | and a 68040 CPU RELOC(fputype, %a0) movl #FPU_68040,%a0@ | ...and FPU RELOC(machineid, %a0) movl #40,%a0@ | @@@ useless jra Lstart1 /* * End of 68040 section */ /* * 68020 models * (There are no 68020 models of NeXT, but we'll pretend) */ Lis68020: RELOC(mmutype, %a0) movl #MMU_68851,%a0@ | no, we have PMMU RELOC(fputype, %a0) | all of the 68020 systems movl #FPU_68881,%a0@ | have a 68881 FPU RELOC(cputype, %a0) movl #CPU_68020,%a0@ | and a 68020 CPU RELOC(machineid, %a0) movl #20,%a0@ | @@@ useless jra Lstart1 /* * End of 68020 section */ Lstart1: /* configure kernel and lwp0 VA space so we can get going */ #if NKSYMS || defined(DDB) || defined(MODULAR) RELOC(esym,%a0) | end of static kernel test/data/syms movl %a0@,%a4 tstl %a4 jne Lstart3 #endif movl #_C_LABEL(end),%a4 | end of static kernel text/data Lstart3: addl %a5,%a4 | convert to PA pea %a5@ | reloff pea %a4@ | nextpa RELOC(pmap_bootstrap1,%a0) jbsr %a0@ | pmap_bootstrap1(nextpa, reloff) addql #8,%sp /* * Updated nextpa returned in %d0. We need to squirrel * that away in a callee-saved register to use later, * after the MMU is enabled. */ movl %d0, %d7 /* NOTE: %d7 is now off-limits!! */ /* * Prepare to enable MMU. * Since the kernel is not mapped logical == physical we must insure * that when the MMU is turned on, all prefetched addresses (including * the PC) are valid. In order guarantee that, we use the transparent * translation registers (which provide PA == VA mappings) and just * turns on the MMU, then jump from the VA == PA address (at 0x40XXXXXX) * to the actual kernel virtual address (at 0x00XXXXXX) code via a far * jump instruction so that we can defeat the prefetch. * * The TT register values are pre-initialized in the mmu_tt{30,40}[] * arrays (see genassym.cf) and loaded from there before the MMU is * turned on. */ #include <m68k/m68k/mmu_enable.s> /* * Should be running mapped from this point on */ Lmmuenabled: /* * Now that the MMU is enabled, we need to clear out the TT value * arrays (so no other code gets confused and thinks we're using them) * and disable the TT registers. */ lea _ASM_LABEL(tmpstk),%sp | re-load temporary stack moveq #0,%d0 #ifdef M68030 lea _C_LABEL(mmu_tt30),%a0 | zap the 2 '030 TT slots movl %d0,%a0@+ movl %d0,%a0@+ #endif #ifdef M68040 lea _C_LABEL(mmu_tt40),%a0 | zap the 4 '040 TT slots movl %d0,%a0@+ movl %d0,%a0@+ movl %d0,%a0@+ movl %d0,%a0@+ cmpl #MMU_68040,_C_LABEL(mmutype) jne 1f /* disable '040 TTs */ pea _C_LABEL(mmu_tt40) jbsr _C_LABEL(mmu_load_tt40) jra 2f 1: #endif #ifdef M68030 /* disable '030 TTs */ pea _C_LABEL(mmu_tt30) jbsr _C_LABEL(mmu_load_tt30) #endif 2: lea _ASM_LABEL(tmpstk),%sp | re-load temporary stack jbsr _C_LABEL(vec_init) | initialize vector table /* phase 2 of pmap setup, returns lwp0 SP in %a0 */ jbsr _C_LABEL(pmap_bootstrap2) movl %a0,%sp | now running on lwp0's stack movl #0,%a6 | terminate the stack back trace movl %d7,%sp@- | push nextpa saved above jbsr _C_LABEL(machine_init) | additional pre-main initialization addql #4,%sp jra _C_LABEL(main) | main() (never returns) /* * Interrupt handlers. * * For auto-vectored interrupts, the CPU provides the * vector 0x18+level. Note we count spurious interrupts, * but don't do anything else with them. * * intrhand_autovec is the entry point for auto-vectored * interrupts. * * For vectored interrupts, we pull the pc, evec, and exception frame * and pass them to the vectored interrupt dispatcher. The vectored * interrupt dispatcher will deal with strays. */ ENTRY_NOPROFILE(lev7intr) /* level 7: parity errors, reset key */ addql #1,_C_LABEL(m68k_intr_evcnt)+NMI_INTRCNT clrl %sp@- moveml #0xFFFF,%sp@- | save registers movl %usp,%a0 | and save movl %a0,%sp@(FR_SP) | the user stack pointer jbsr _C_LABEL(nmihand) | call handler movl %sp@(FR_SP),%a0 | restore movl %a0,%usp | user SP moveml %sp@+,#0x7FFF | and remaining registers addql #8,%sp | pop SP and stack adjust jra _ASM_LABEL(rei) | all done /* * Handle the nitty-gritty of rebooting the machine. * Basically we just turn off the MMU and jump to the appropriate ROM routine. * Note that we must be running in an address range that is mapped one-to-one * logical to physical so that the PC is still valid immediately after the MMU * is turned off. We have conveniently mapped the last page of physical * memory this way. */ ENTRY_NOPROFILE(machine_reboot) movw #PSL_HIGHIPL,%sr | no interrupts movl #CACHE_OFF,%d0 movc %d0,%cacr | clear and disable on-chip cache(s) | Turn on physical memory mapping. | @@@ This is also 68040 specific and needs fixing. movel #0x0200c040,%d0 | intio devices are at 0x02000000 .long 0x4e7b0004 | movc %d0,%itt0 .long 0x4e7b0006 | movc %d0,%dtt0 movel #0x0403c000,%d0 | kernel text and data at 0x04000000 .long 0x4e7b0005 | movc %d0,%itt1 .long 0x4e7b0007 | movc %d0,%dtt1 moveal #NEXT_RAMBASE,%a5 | amount to RELOC by. | Create a new stack at address tmpstk, and push | The existing sp onto it for kicks. ASRELOC(tmpstk, %a0) movel %sp,%a0@- moveal %a0,%sp moveal #0,%a6 ASRELOC(Ldoboot1, %a0) jmp %a0@ | jump into physical address space. Ldoboot1: RELOC(saved_vbr, %a0) movl %a0@,%d0 movc %d0,%vbr | reset the registers as the boot rom likes them: movel #0x0200c040,%d0 | .long 0x4e7b0004 | movc %d0,%itt0 .long 0x4e7b0006 | movc %d0,%dtt0 movel #0x00ffc000,%d0 | .long 0x4e7b0005 | movc %d0,%itt1 .long 0x4e7b0007 | movc %d0,%dtt1 RELOC(monbootflag, %a0) movl %a0,%d0 trap #13 1: bra 1b | This shouldn't be reached. /* * Misc. global variables. */ .data GLOBAL(machineid) .long 0xdeadbeef | default to @@@ GLOBAL(mmuid) .long 0 | default to nothing GLOBAL(mmutype) .long 0xdeadbeef | default to 68040 mmu GLOBAL(cputype) .long 0xdeadbeef | default to 68020 CPU GLOBAL(prototc) .long 0 | prototype translation control GLOBAL(intiobase) .long 0 | KVA of base of internal IO space GLOBAL(fbbase) .long 0 | KVA of base of framebuffer GLOBAL(fbmapsize) .long 0 | size of framebuffer (page-rounded) GLOBAL(fbbasepa) .long MONOBASE | PA of base of framebuffer GLOBAL(monbootflag) .long 0 #ifdef DEBUG ASGLOBAL(fulltflush) .long 0 ASGLOBAL(fullcflush) .long 0 #endif