summaryrefslogtreecommitdiffstats
path: root/arch/alpha/mm
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /arch/alpha/mm
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (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.c42
-rw-r--r--arch/alpha/mm/fault.c6
-rw-r--r--arch/alpha/mm/init.c67
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)