📄 head.s
字号:
is_not_mvme147(L(not147)) /* * On MVME147 we have already created kernel page tables for * 4MB of RAM at address 0, so now need to do a transparent * mapping of the top of memory space. Make it 0.5GByte for now, * so we can access on-board i/o areas. */ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 jbra L(mmu_init_done)L(not147):#endif /* CONFIG_MVME147 */#ifdef CONFIG_MVME16x is_not_mvme16x(L(not16x)) /* * On MVME16x we have already created kernel page tables for * 4MB of RAM at address 0, so now need to do a transparent * mapping of the top of memory space. Make it 0.5GByte for now. * Supervisor only access, so transparent mapping doesn't * clash with User code virtual address space. * this covers IO devices, PROM and SRAM. The PROM and SRAM * mapping is needed to allow 167Bug to run. * IO is in the range 0xfff00000 to 0xfffeffff. * PROM is 0xff800000->0xffbfffff and SRAM is * 0xffe00000->0xffe1ffff. */ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done)L(not16x):#endif /* CONFIG_MVME162 | CONFIG_MVME167 */#ifdef CONFIG_BVME6000 is_not_bvme6000(L(not6000)) /* * On BVME6000 we have already created kernel page tables for * 4MB of RAM at address 0, so now need to do a transparent * mapping of the top of memory space. Make it 0.5GByte for now, * so we can access on-board i/o areas. * Supervisor only access, so transparent mapping doesn't * clash with User code virtual address space. */ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done)L(not6000):#endif /* CONFIG_BVME6000 *//* * mmu_init_mac * * The Macintosh mappings are less clear. * * Even as of this writing, it is unclear how the * Macintosh mappings will be done. However, as * the first author of this code I'm proposing the * following model: * * Map the kernel (that's already done), * Map the I/O (on most machines that's the * 0x5000.0000 ... 0x5300.0000 range, * Map the video frame buffer using as few pages * as absolutely (this requirement mostly stems from * the fact that when the frame buffer is at * 0x0000.0000 then we know there is valid RAM just * above the screen that we don't want to waste!). * * By the way, if the frame buffer is at 0x0000.0000 * then the Macintosh is known as an RBV based Mac. * * By the way 2, the code currently maps in a bunch of * regions. But I'd like to cut that out. (And move most * of the mappings up into the kernel proper ... or only * map what's necessary.) */#ifdef CONFIG_MACL(mmu_init_mac): is_not_mac(L(mmu_init_not_mac)) putc 'F' is_not_040_or_060(1f) moveq #_PAGE_NOCACHE_S,%d3 jbra 2f1: moveq #_PAGE_NOCACHE030,%d32: /* * Mac Note: screen address of logical 0xF000.0000 -> <screen physical> * we simply map the 4MB that contains the videomem */ movel #VIDEOMEMMASK,%d0 andl %pc@(L(mac_videobase)),%d0 mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3 /* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */ mmu_map_eq #0x40000000,#0x02000000,%d3 /* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */ mmu_map_eq #0x50000000,#0x03000000,%d3 /* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */ mmu_map_tt #1,#0xf8000000,#0x08000000,%d3 jbra L(mmu_init_done)L(mmu_init_not_mac):#endif#ifdef CONFIG_SUN3X is_not_sun3x(L(notsun3x)) /* oh, the pain.. We're gonna want the prom code after * starting the MMU, so we copy the mappings, translating * from 8k -> 4k pages as we go. */ /* copy maps from 0xfee00000 to 0xff000000 */ movel #0xfee00000, %d0 moveq #ROOT_INDEX_SHIFT, %d1 lsrl %d1,%d0 mmu_get_root_table_entry %d0 movel #0xfee00000, %d0 moveq #PTR_INDEX_SHIFT, %d1 lsrl %d1,%d0 andl #PTR_TABLE_SIZE-1, %d0 mmu_get_ptr_table_entry %a0,%d0 movel #0xfee00000, %d0 moveq #PAGE_INDEX_SHIFT, %d1 lsrl %d1,%d0 andl #PAGE_TABLE_SIZE-1, %d0 mmu_get_page_table_entry %a0,%d0 /* this is where the prom page table lives */ movel 0xfefe00d4, %a1 movel %a1@, %a1 movel #((0x200000 >> 13)-1), %d11: movel %a1@+, %d3 movel %d3,%a0@+ addl #0x1000,%d3 movel %d3,%a0@+ dbra %d1,1b /* setup tt1 for I/O */ mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done)L(notsun3x):#endif#ifdef CONFIG_APOLLO is_not_apollo(L(notapollo)) putc 'P' mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030L(notapollo): jbra L(mmu_init_done)#endifL(mmu_init_done): putc 'G' leds 0x8/* * mmu_fixup * * On the 040 class machines, all pages that are used for the * mmu have to be fixed up. According to Motorola, pages holding mmu * tables should be non-cacheable on a '040 and write-through on a * '060. But analysis of the reasons for this, and practical * experience, showed that write-through also works on a '040. * * Allocated memory so far goes from kernel_end to memory_start that * is used for all kind of tables, for that the cache attributes * are now fixed. */L(mmu_fixup): is_not_040_or_060(L(mmu_fixup_done))#ifdef MMU_NOCACHE_KERNEL jbra L(mmu_fixup_done)#endif /* first fix the page at the start of the kernel, that * contains also kernel_pg_dir. */ movel %pc@(L(phys_kernel_start)),%d0 subl #PAGE_OFFSET,%d0 lea %pc@(_stext),%a0 subl %d0,%a0 mmu_fixup_page_mmu_cache %a0 movel %pc@(L(kernel_end)),%a0 subl %d0,%a0 movel %pc@(L(memory_start)),%a1 subl %d0,%a1 bra 2f1: mmu_fixup_page_mmu_cache %a0 addw #PAGESIZE,%a02: cmpl %a0,%a1 jgt 1bL(mmu_fixup_done):#ifdef MMU_PRINT mmu_print#endif/* * mmu_engage * * This chunk of code performs the gruesome task of engaging the MMU. * The reason its gruesome is because when the MMU becomes engaged it * maps logical addresses to physical addresses. The Program Counter * register is then passed through the MMU before the next instruction * is fetched (the instruction following the engage MMU instruction). * This may mean one of two things: * 1. The Program Counter falls within the logical address space of * the kernel of which there are two sub-possibilities: * A. The PC maps to the correct instruction (logical PC == physical * code location), or * B. The PC does not map through and the processor will read some * data (or instruction) which is not the logically next instr. * As you can imagine, A is good and B is bad. * Alternatively, * 2. The Program Counter does not map through the MMU. The processor * will take a Bus Error. * Clearly, 2 is bad. * It doesn't take a wiz kid to figure you want 1.A. * This code creates that possibility. * There are two possible 1.A. states (we now ignore the other above states): * A. The kernel is located at physical memory addressed the same as * the logical memory for the kernel, i.e., 0x01000. * B. The kernel is located some where else. e.g., 0x0400.0000 * * Under some conditions the Macintosh can look like A or B. * [A friend and I once noted that Apple hardware engineers should be * wacked twice each day: once when they show up at work (as in, Whack!, * "This is for the screwy hardware we know you're going to design today."), * and also at the end of the day (as in, Whack! "I don't know what * you designed today, but I'm sure it wasn't good."). -- rst] * * This code works on the following premise: * If the kernel start (%d5) is within the first 16 Meg of RAM, * then create a mapping for the kernel at logical 0x8000.0000 to * the physical location of the pc. And, create a transparent * translation register for the first 16 Meg. Then, after the MMU * is engaged, the PC can be moved up into the 0x8000.0000 range * and then the transparent translation can be turned off and then * the PC can jump to the correct logical location and it will be * home (finally). This is essentially the code that the Amiga used * to use. Now, it's generalized for all processors. Which means * that a fresh (but temporary) mapping has to be created. The mapping * is made in page 0 (an as of yet unused location -- except for the * stack!). This temporary mapping will only require 1 pointer table * and a single page table (it can map 256K). * * OK, alternatively, imagine that the Program Counter is not within * the first 16 Meg. Then, just use Transparent Translation registers * to do the right thing. * * Last, if _start is already at 0x01000, then there's nothing special * to do (in other words, in a degenerate case of the first case above, * do nothing). * * Let's do it. * * */ putc 'H' mmu_engage/* * After this point no new memory is allocated and * the start of available memory is stored in availmem. * (The bootmem allocator requires now the physicall address.) */ movel L(memory_start),availmem#ifdef CONFIG_AMIGA is_not_amiga(1f) /* fixup the Amiga custom register location before printing */ clrl L(custom)1:#endif#ifdef CONFIG_ATARI is_not_atari(1f) /* fixup the Atari iobase register location before printing */ movel #0xff000000,L(iobase)1:#endif#ifdef CONFIG_MAC is_not_mac(1f) movel #~VIDEOMEMMASK,%d0 andl L(mac_videobase),%d0 addl #VIDEOMEMBASE,%d0 movel %d0,L(mac_videobase)#if defined(CONSOLE) movel %pc@(L(phys_kernel_start)),%d0 subl #PAGE_OFFSET,%d0 subl %d0,L(console_font) subl %d0,L(console_font_data)#endif#ifdef MAC_SERIAL_DEBUG orl #0x50000000,L(mac_sccbase)#endif1:#endif#ifdef CONFIG_HP300 is_not_hp300(1f) /* * Fix up the iobase register to point to the new location of the LEDs. */ movel #0xf0000000,L(iobase) /* * Energise the FPU and caches. */ is_040(1f) movel #0x60,0xf05f400c jbra 2f /* * 040: slightly different, apparently. */1: movew #0,0xf05f400e movew #0x64,0xf05f400e2:#endif#ifdef CONFIG_SUN3X is_not_sun3x(1f) /* enable copro */ oriw #0x4000,0x610000001:#endif#ifdef CONFIG_APOLLO is_not_apollo(1f) /* * Fix up the iobase before printing */ movel #0x80000000,L(iobase)1:#endif putc 'I' leds 0x10/* * Enable caches */ is_not_040_or_060(L(cache_not_680460))L(cache680460): .chip 68040 nop cpusha %bc nop is_060(L(cache68060)) movel #CC6_ENABLE_D+CC6_ENABLE_I,%d0 /* MMU stuff works in copyback mode now, so enable the cache */ movec %d0,%cacr jra L(cache_done)L(cache68060): movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0 /* MMU stuff works in copyback mode now, so enable the cache */ movec %d0,%cacr /* enable superscalar dispatch in PCR */ moveq #1,%d0 .chip 68060 movec %d0,%pcr jbra L(cache_done)L(cache_not_680460):L(cache68030): .chip 68030 movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0 movec %d0,%cacr jra L(cache_done) .chip 68kL(cache_done): putc 'J'/* * Setup initial stack pointer */ lea init_task,%curptr lea init_thread_union+THREAD_SIZE,%sp putc 'K' subl %a6,%a6 /* clear a6 for gdb *//* * The new 64bit printf support requires an early exception initialization. */ jbsr base_trap_init/* jump to the kernel start */ putc '\n' leds 0x55 jbsr start_kernel/* * Find a tag record in the bootinfo structure * The bootinfo structure is located right after the kernel bss * Returns: d0: size (-1 if not found) * a0: data pointer (end-of-records if not found) */func_start get_bi_record,%d1 movel ARG1,%d0 lea %pc@(_end),%a01: tstw %a0@(BIR_TAG) jeq 3f cmpw %a0@(BIR_TAG),%d0 jeq 2f addw %a0@(BIR_SIZE),%a0 jra 1b2: moveq #0,%d0 movew %a0@(BIR_SIZE),%d0 lea %a0@(BIR_DATA),%a0 jra 4f3: moveq #-1,%d0 lea %a0@(BIR_SIZE),%a04:func_return get_bi_record/* * MMU Initialization Begins Here * * The structure of the MMU tables on the 68k machines * is thus: * Root Table * Logical addresses are translated through * a hierarchical translation mechanism where the high-order * seven bits of the logical address (LA) are used as an * index into the "root table." Each entry in the root * table has a bit which specifies if it's a valid pointer to a * pointer table. Each entry defines a 32KMeg range of memory. * If an entry is invalid then that logical range of 32M is * invalid and references to that range of memory (when the MMU * is enabled) will fault. If the entry is valid, then it does * one of two things. On 040/060 class machines, it points to * a pointer table which then describes more finely the memory * within that 32M range. On 020/030 class machines, a technique * called "early terminating descriptors" are used. This technique * allows an entire 32Meg to be described by a single entry in the * root table. Thus, this entry in the root table, contains the * physical address of the memory or I/O at the logical address * which the entry represents and it also contains the necessary * cache bits for this region. * * Pointer Tables * Per the Root Table, there will be one or more * pointer tables. Each pointer table defines a 32M range. * Not all of the 32M range need be defined. Again, the next * seven bits of the logical address are used an index into * the pointer table to point to page tables (if the pointer * is valid). There will undoubtedly be more than one * pointer table for the kernel because each pointer table * defines a range of only 32M. Valid pointer table entries * point to page tables, or are early terminating entries * themselves. * * Page Tables * Per the Pointer Tables, each page table entry points * to the physical page in memory that supports the logical * address that translates to the particular index. * * In short, the Logical Address gets translated as follows: * bits 31..26 - index into the Root Table * bits 25..18 - index into the Pointer Table * bits 17..12 - index into the Page Table * bits 11..0 - offset into a particular 4K page * * The algorithms which follows do one thing: they abstract * the MMU hardware. For example, there are three kinds of * cache settings that are relevant. Either, memory is * being mapped in which case it is either Kernel Code (or * the RamDisk) or it is MMU data. On the 030, the MMU data * option also describes the kernel. Or, I/O is being mapped * in which case it has its own kind of cache bits. There * are constants which abstract these notions from the code that * actually makes the call to map some range of memory. * * * */#ifdef MMU_PRINT/* * mmu_print * * This algorithm will print out the current MMU mappings. * * Input: * %a5 points to the root table. Everything else is calculated * from this. */#define mmu_next_valid 0#define mmu_start_logical 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -