summaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/fault.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
committer <ralf@linux-mips.org>1995-11-14 08:00:00 +0000
commite7c2a72e2680827d6a733931273a93461c0d8d1b (patch)
treec9abeda78ef7504062bb2e816bcf3e3c9d680112 /arch/sparc/mm/fault.c
parentec6044459060a8c9ce7f64405c465d141898548c (diff)
Import of Linux/MIPS 1.3.0
Diffstat (limited to 'arch/sparc/mm/fault.c')
-rw-r--r--arch/sparc/mm/fault.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
new file mode 100644
index 000000000..4c5fd0bc3
--- /dev/null
+++ b/arch/sparc/mm/fault.c
@@ -0,0 +1,173 @@
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/signal.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/openprom.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+extern unsigned long pg0[1024]; /* page table for 0-4MB for everybody */
+extern struct sparc_phys_banks sp_banks[14];
+
+extern void die_if_kernel(char *,struct pt_regs *,long);
+
+struct linux_romvec *romvec;
+
+/* foo */
+
+int tbase_needs_unmapping;
+
+/* At boot time we determine these two values necessary for setting
+ * up the segment maps and page table entries (pte's).
+ */
+
+int num_segmaps, num_contexts;
+int invalid_segment;
+
+/* various Virtual Address Cache parameters we find at boot time... */
+
+int vac_size, vac_linesize, vac_do_hw_vac_flushes;
+int vac_entries_per_context, vac_entries_per_segment;
+int vac_entries_per_page;
+
+/*
+ * Define this if things work differently on a i386 and a i486:
+ * it will (on a i486) warn about kernel memory accesses that are
+ * done without a 'verify_area(VERIFY_WRITE,..)'
+ */
+#undef CONFIG_TEST_VERIFY_AREA
+
+/* Traverse the memory lists in the prom to see how much physical we
+ * have.
+ */
+
+unsigned long
+probe_memory(void)
+{
+ register struct linux_romvec *lprom;
+ register struct linux_mlist_v0 *mlist;
+ register unsigned long bytes, base_paddr, tally;
+ register int i;
+
+ bytes = tally = 0;
+ base_paddr = 0;
+ i=0;
+ lprom = romvec;
+ switch(lprom->pv_romvers)
+ {
+ case 0:
+ mlist=(*(lprom->pv_v0mem.v0_totphys));
+ bytes = tally = mlist->num_bytes;
+ base_paddr = (unsigned long) mlist->start_adr;
+
+ sp_banks[0].base_addr = base_paddr;
+ sp_banks[0].num_bytes = bytes;
+
+ if(mlist->theres_more != (void *)0) {
+ i++;
+ mlist=mlist->theres_more;
+ bytes=mlist->num_bytes;
+ tally += bytes;
+ sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
+ sp_banks[i].num_bytes = mlist->num_bytes;
+ }
+ break;
+ case 2:
+ printk("no v2 memory probe support yet.\n");
+ (*(lprom->pv_halt))();
+ break;
+ }
+
+ i++;
+ sp_banks[i].base_addr = 0xdeadbeef;
+ sp_banks[i].num_bytes = 0;
+
+ return tally;
+}
+
+/* Sparc routine to reserve the mapping of the open boot prom */
+
+/* uncomment this for FAME and FORTUNE! */
+/* #define DEBUG_MAP_PROM */
+
+int
+map_the_prom(int curr_num_segs)
+{
+ register unsigned long prom_va_begin;
+ register unsigned long prom_va_end;
+ register int segmap_entry, i;
+
+ prom_va_begin = LINUX_OPPROM_BEGVM;
+ prom_va_end = LINUX_OPPROM_ENDVM;
+
+#ifdef DEBUG_MAP_PROM
+ printk("\ncurr_num_segs = 0x%x\n", curr_num_segs);
+#endif
+
+ while( prom_va_begin < prom_va_end)
+ {
+ segmap_entry=get_segmap(prom_va_begin);
+
+ curr_num_segs = ((segmap_entry<curr_num_segs)
+ ? segmap_entry : curr_num_segs);
+
+ for(i = num_contexts; --i > 0;)
+ (*romvec->pv_setctxt)(i, (char *) prom_va_begin,
+ segmap_entry);
+
+ if(segmap_entry == invalid_segment)
+ {
+
+#ifdef DEBUG_MAP_PROM
+ printk("invalid_segments, virt_addr 0x%x\n", prom_va_begin);
+#endif
+
+ prom_va_begin += 0x40000; /* num bytes per segment entry */
+ continue;
+ }
+
+ /* DUH, prom maps itself so that users can access it. This is
+ * broken.
+ */
+
+#ifdef DEBUG_MAP_PROM
+ printk("making segmap for prom privileged, va = 0x%x\n",
+ prom_va_begin);
+#endif
+
+ for(i = 0x40; --i >= 0; prom_va_begin+=4096)
+ {
+ put_pte(prom_va_begin, get_pte(prom_va_begin) | 0x20000000);
+ }
+
+ }
+
+ printk("Mapped the PROM in all contexts...\n");
+
+#ifdef DEBUG_MAP_PROM
+ printk("curr_num_segs = 0x%x\n", curr_num_segs);
+#endif
+
+ return curr_num_segs;
+
+}
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+ die_if_kernel("Oops", regs, error_code);
+ do_exit(SIGKILL);
+}
+
+
+
+