diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-19 22:45:37 +0000 |
commit | 6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch) | |
tree | 0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /arch/alpha/mm | |
parent | ecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff) |
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine
status unknown.
Diffstat (limited to 'arch/alpha/mm')
-rw-r--r-- | arch/alpha/mm/extable.c | 42 | ||||
-rw-r--r-- | arch/alpha/mm/fault.c | 6 | ||||
-rw-r--r-- | arch/alpha/mm/init.c | 67 |
3 files changed, 80 insertions, 35 deletions
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 12a1f4803..d3a02fe27 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -36,12 +36,12 @@ search_one_table(const struct exception_table_entry *first, register unsigned long gp __asm__("$29"); -unsigned -search_exception_table(unsigned long addr) +static unsigned +search_exception_table_without_gp(unsigned long addr) { unsigned ret; -#ifndef CONFIG_MODULE +#ifndef CONFIG_MODULES /* There is only the kernel to search. */ ret = search_one_table(__start___ex_table, __stop___ex_table - 1, addr - gp); @@ -60,3 +60,39 @@ search_exception_table(unsigned long addr) return 0; } + +unsigned +search_exception_table(unsigned long addr, unsigned long exc_gp) +{ + unsigned ret; + +#ifndef CONFIG_MODULES + ret = search_one_table(__start___ex_table, __stop___ex_table - 1, + addr - exc_gp); + if (ret) return ret; +#else + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + for (mp = module_list; mp ; mp = mp->next) { + if (!mp->ex_table_start) + continue; + ret = search_one_table(mp->ex_table_start, + mp->ex_table_end - 1, addr - exc_gp); + if (ret) return ret; + } +#endif + + /* + * The search failed with the exception gp. To be safe, try the + * old method before giving up. + */ + ret = search_exception_table_without_gp(addr); + if (ret) { + printk(KERN_ALERT, "%s: [%lx] EX_TABLE search fail with" + "exc frame GP, success with raw GP\n", + current->comm, addr); + return ret; + } + + return 0; +} diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 1639972db..bf4839b8f 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -164,11 +164,13 @@ bad_area: no_context: /* Are we prepared to handle this fault as an exception? */ - if ((fixup = search_exception_table(regs->pc)) != 0) { + if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) { unsigned long newpc; newpc = fixup_exception(dpf_reg, fixup, regs->pc); - printk("%s: Exception at [<%lx>] (%lx)\n", +#if 1 + printk("%s: Exception at [<%lx>] (%lx) handled successfully\n", current->comm, regs->pc, newpc); +#endif regs->pc = newpc; return; } diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index 2cbe9bb0f..84b608f45 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -182,43 +182,15 @@ load_PCB(struct thread_struct * pcb) return __reload_thread(pcb); } -/* - * paging_init() sets up the page tables: in the alpha version this actually - * unmaps the bootup page table (as we're now in KSEG, so we don't need it). - */ +/* switch_to_system_map() sets up some necessary page tables. */ void -paging_init(void) +switch_to_system_map(void) { unsigned long newptbr; unsigned long original_pcb_ptr; - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned long dma_pfn, high_pfn; - - dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; - high_pfn = max_low_pfn; - -#define ORDER_MASK (~((1 << (MAX_ORDER-1))-1)) -#define ORDER_ALIGN(n) (((n) + ~ORDER_MASK) & ORDER_MASK) - - dma_pfn = ORDER_ALIGN(dma_pfn); - high_pfn = ORDER_ALIGN(high_pfn); - -#undef ORDER_MASK -#undef ORDER_ALIGN - - if (dma_pfn > high_pfn) - zones_size[ZONE_DMA] = high_pfn; - else { - zones_size[ZONE_DMA] = dma_pfn; - zones_size[ZONE_NORMAL] = high_pfn - dma_pfn; - } - - /* Initialize mem_map[]. */ - free_area_init(zones_size); /* Initialize the kernel's page tables. Linux puts the vptb in the last slot of the L1 page table. */ - memset((void *)ZERO_PGE, 0, PAGE_SIZE); memset(swapper_pg_dir, 0, PAGE_SIZE); newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT; pgd_val(swapper_pg_dir[1023]) = @@ -253,6 +225,41 @@ paging_init(void) original_pcb = *(struct thread_struct *) original_pcb_ptr; } +/* + * paging_init() sets up the memory map. + */ +void +paging_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long dma_pfn, high_pfn; + + dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + high_pfn = max_low_pfn; + +#define ORDER_MASK (~((1L << (MAX_ORDER-1))-1)) +#define ORDER_ALIGN(n) (((n) + ~ORDER_MASK) & ORDER_MASK) + + dma_pfn = ORDER_ALIGN(dma_pfn); + high_pfn = ORDER_ALIGN(high_pfn); + +#undef ORDER_MASK +#undef ORDER_ALIGN + + if (dma_pfn > high_pfn) + zones_size[ZONE_DMA] = high_pfn; + else { + zones_size[ZONE_DMA] = dma_pfn; + zones_size[ZONE_NORMAL] = high_pfn - dma_pfn; + } + + /* Initialize mem_map[]. */ + free_area_init(zones_size); + + /* Initialize the kernel's ZERO_PGE. */ + memset((void *)ZERO_PGE, 0, PAGE_SIZE); +} + #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM) void srm_paging_stop (void) |