📄 head.s
字号:
* 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#define mmu_next_logical 8#define mmu_start_physical 12#define mmu_next_physical 16#define MMU_PRINT_INVALID -1#define MMU_PRINT_VALID 1#define MMU_PRINT_UNINITED 0#define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2:func_start mmu_print,%a0-%a6/%d0-%d7 movel %pc@(L(kernel_pgdir_ptr)),%a5 lea %pc@(L(mmu_print_data)),%a0 movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid) is_not_040_or_060(mmu_030_print)mmu_040_print: puts "\nMMU040\n" puts "rp:" putn %a5 putc '\n'#if 0 /* * The following #if/#endif block is a tight algorithm for dumping the 040 * MMU Map in gory detail. It really isn't that practical unless the * MMU Map algorithm appears to go awry and you need to debug it at the * entry per entry level. */ movel #ROOT_TABLE_SIZE,%d5#if 0 movel %a5@+,%d7 | Burn an entry to skip the kernel mappings, subql #1,%d5 | they (might) work#endif1: tstl %d5 jbeq mmu_print_done subq #1,%d5 movel %a5@+,%d7 btst #1,%d7 jbeq 1b2: putn %d7 andil #0xFFFFFE00,%d7 movel %d7,%a4 movel #PTR_TABLE_SIZE,%d4 putc ' '3: tstl %d4 jbeq 11f subq #1,%d4 movel %a4@+,%d7 btst #1,%d7 jbeq 3b4: putn %d7 andil #0xFFFFFF00,%d7 movel %d7,%a3 movel #PAGE_TABLE_SIZE,%d35: movel #8,%d26: tstl %d3 jbeq 31f subq #1,%d3 movel %a3@+,%d6 btst #0,%d6 jbeq 6b7: tstl %d2 jbeq 8f subq #1,%d2 putc ' ' jbra 91f8: putc '\n' movel #8+1+8+1+1,%d29: putc ' ' dbra %d2,9b movel #7,%d291: putn %d6 jbra 6b31: putc '\n' movel #8+1,%d232: putc ' ' dbra %d2,32b jbra 3b11: putc '\n' jbra 1b#endif /* MMU 040 Dumping code that's gory and detailed */ lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a5 movel %a5,%a0 /* a0 has the address of the root table ptr */ movel #0x00000000,%a4 /* logical address */ moveql #0,%d040: /* Increment the logical address and preserve in d5 */ movel %a4,%d5 addil #PAGESIZE<<13,%d5 movel %a0@+,%d6 btst #1,%d6 jbne 41f jbsr mmu_print_tuple_invalidate jbra 48f41: movel #0,%d1 andil #0xfffffe00,%d6 movel %d6,%a142: movel %a4,%d5 addil #PAGESIZE<<6,%d5 movel %a1@+,%d6 btst #1,%d6 jbne 43f jbsr mmu_print_tuple_invalidate jbra 47f43: movel #0,%d2 andil #0xffffff00,%d6 movel %d6,%a244: movel %a4,%d5 addil #PAGESIZE,%d5 movel %a2@+,%d6 btst #0,%d6 jbne 45f jbsr mmu_print_tuple_invalidate jbra 46f45: moveml %d0-%d1,%sp@- movel %a4,%d0 movel %d6,%d1 andil #0xfffff4e0,%d1 lea %pc@(mmu_040_print_flags),%a6 jbsr mmu_print_tuple moveml %sp@+,%d0-%d146: movel %d5,%a4 addq #1,%d2 cmpib #64,%d2 jbne 44b47: movel %d5,%a4 addq #1,%d1 cmpib #128,%d1 jbne 42b48: movel %d5,%a4 /* move to the next logical address */ addq #1,%d0 cmpib #128,%d0 jbne 40b .chip 68040 movec %dtt1,%d0 movel %d0,%d1 andiw #0x8000,%d1 /* is it valid ? */ jbeq 1f /* No, bail out */ movel %d0,%d1 andil #0xff000000,%d1 /* Get the address */ putn %d1 puts "==" putn %d1 movel %d0,%d6 jbsr mmu_040_print_flags_tt1: movec %dtt0,%d0 movel %d0,%d1 andiw #0x8000,%d1 /* is it valid ? */ jbeq 1f /* No, bail out */ movel %d0,%d1 andil #0xff000000,%d1 /* Get the address */ putn %d1 puts "==" putn %d1 movel %d0,%d6 jbsr mmu_040_print_flags_tt1: .chip 68k jbra mmu_print_donemmu_040_print_flags: btstl #10,%d6 putZc(' ','G') /* global bit */ btstl #7,%d6 putZc(' ','S') /* supervisor bit */mmu_040_print_flags_tt: btstl #6,%d6 jbne 3f putc 'C' btstl #5,%d6 putZc('w','c') /* write through or copy-back */ jbra 4f3: putc 'N' btstl #5,%d6 putZc('s',' ') /* serialized non-cacheable, or non-cacheable */4: rtsmmu_030_print_flags: btstl #6,%d6 putZc('C','I') /* write through or copy-back */ rtsmmu_030_print: puts "\nMMU030\n" puts "\nrp:" putn %a5 putc '\n' movel %a5,%d0 andil #0xfffffff0,%d0 movel %d0,%a0 movel #0x00000000,%a4 /* logical address */ movel #0,%d030: movel %a4,%d5 addil #PAGESIZE<<13,%d5 movel %a0@+,%d6 btst #1,%d6 /* is it a ptr? */ jbne 31f /* yes */ btst #0,%d6 /* is it early terminating? */ jbeq 1f /* no */ jbsr mmu_030_print_helper jbra 38f1: jbsr mmu_print_tuple_invalidate jbra 38f31: movel #0,%d1 andil #0xfffffff0,%d6 movel %d6,%a132: movel %a4,%d5 addil #PAGESIZE<<6,%d5 movel %a1@+,%d6 btst #1,%d6 jbne 33f btst #0,%d6 jbeq 1f /* no */ jbsr mmu_030_print_helper jbra 37f1: jbsr mmu_print_tuple_invalidate jbra 37f33: movel #0,%d2 andil #0xfffffff0,%d6 movel %d6,%a234: movel %a4,%d5 addil #PAGESIZE,%d5 movel %a2@+,%d6 btst #0,%d6 jbne 35f jbsr mmu_print_tuple_invalidate jbra 36f35: jbsr mmu_030_print_helper36: movel %d5,%a4 addq #1,%d2 cmpib #64,%d2 jbne 34b37: movel %d5,%a4 addq #1,%d1 cmpib #128,%d1 jbne 32b38: movel %d5,%a4 /* move to the next logical address */ addq #1,%d0 cmpib #128,%d0 jbne 30bmmu_print_done: puts "\n\n"func_return mmu_printmmu_030_print_helper: moveml %d0-%d1,%sp@- movel %a4,%d0 movel %d6,%d1 lea %pc@(mmu_030_print_flags),%a6 jbsr mmu_print_tuple moveml %sp@+,%d0-%d1 rtsmmu_print_tuple_invalidate: moveml %a0/%d7,%sp@- lea %pc@(L(mmu_print_data)),%a0 tstl %a0@(mmu_next_valid) jbmi mmu_print_tuple_invalidate_exit movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid) putn %a4 puts "##\n"mmu_print_tuple_invalidate_exit: moveml %sp@+,%a0/%d7 rtsmmu_print_tuple: moveml %d0-%d7/%a0,%sp@- lea %pc@(L(mmu_print_data)),%a0 tstl %a0@(mmu_next_valid) jble mmu_print_tuple_print cmpl %a0@(mmu_next_physical),%d1 jbeq mmu_print_tuple_incrementmmu_print_tuple_print: putn %d0 puts "->" putn %d1 movel %d1,%d6 jbsr %a6@mmu_print_tuple_record: movel #MMU_PRINT_VALID,%a0@(mmu_next_valid) movel %d1,%a0@(mmu_next_physical)mmu_print_tuple_increment: movel %d5,%d7 subl %a4,%d7 addl %d7,%a0@(mmu_next_physical)mmu_print_tuple_exit: moveml %sp@+,%d0-%d7/%a0 rtsmmu_print_machine_cpu_types: puts "machine: " is_not_amiga(1f) puts "amiga" jbra 9f1: is_not_atari(2f) puts "atari" jbra 9f2: is_not_mac(3f) puts "macintosh" jbra 9f3: puts "unknown"9: putc '\n' puts "cputype: 0" is_not_060(1f) putc '6' jbra 9f1: is_not_040_or_060(2f) putc '4' jbra 9f2: putc '3'9: putc '0' putc '\n' rts#endif /* MMU_PRINT *//* * mmu_map_tt * * This is a specific function which works on all 680x0 machines. * On 030, 040 & 060 it will attempt to use Transparent Translation * registers (tt1). * On 020 it will call the standard mmu_map which will use early * terminating descriptors. */func_start mmu_map_tt,%d0/%d1/%a0,4 dputs "mmu_map_tt:" dputn ARG1 dputn ARG2 dputn ARG3 dputn ARG4 dputc '\n' is_020(L(do_map)) /* Extract the highest bit set */ bfffo ARG3{#0,#32},%d1 cmpw #8,%d1 jcc L(do_map) /* And get the mask */ moveq #-1,%d0 lsrl %d1,%d0 lsrl #1,%d0 /* Mask the address */ movel %d0,%d1 notl %d1 andl ARG2,%d1 /* Generate the upper 16bit of the tt register */ lsrl #8,%d0 orl %d0,%d1 clrw %d1 is_040_or_060(L(mmu_map_tt_040)) /* set 030 specific bits (read/write access for supervisor mode * (highest function code set, lower two bits masked)) */ orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d1 movel ARG4,%d0 btst #6,%d0 jeq 1f orw #TTR_CI,%d11: lea STACK,%a0 dputn %d1 movel %d1,%a0@ .chip 68030 tstl ARG1 jne 1f pmove %a0@,%tt0 jra 2f1: pmove %a0@,%tt12: .chip 68k jra L(mmu_map_tt_done) /* set 040 specific bits */L(mmu_map_tt_040): orw #TTR_ENABLE+TTR_KERNELMODE,%d1 orl ARG4,%d1 dputn %d1 .chip 68040 tstl ARG1 jne 1f movec %d1,%itt0 movec %d1,%dtt0 jra 2f1: movec %d1,%itt1 movec %d1,%dtt12: .chip 68k jra L(mmu_map_tt_done)L(do_map): mmu_map_eq ARG2,ARG3,ARG4L(mmu_map_tt_done):func_return mmu_map_tt/* * mmu_map * * This routine will map a range of memory using a pointer * table and allocating the pages on the fly from the kernel. * The pointer table does not have to be already linked into
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -