Import 2.3.9pre5
[davej-history.git] / arch / mips / mm / r6000.c
blob25a24f4aa6534829f9aa698557669e8425963e0a
1 /* $Id: r6000.c,v 1.6 1999/01/04 16:03:54 ralf Exp $
3 * r6000.c: MMU and cache routines for the R6000 processors.
5 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
6 */
7 #include <linux/init.h>
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/mm.h>
12 #include <asm/cacheops.h>
13 #include <asm/page.h>
14 #include <asm/pgtable.h>
15 #include <asm/system.h>
16 #include <asm/sgialib.h>
17 #include <asm/mmu_context.h>
19 __asm__(".set mips3"); /* because we know... */
21 /* Cache operations. XXX Write these dave... */
22 static inline void r6000_flush_cache_all(void)
24 /* XXX */
27 static void r6000_flush_cache_mm(struct mm_struct *mm)
29 /* XXX */
32 static void r6000_flush_cache_range(struct mm_struct *mm,
33 unsigned long start,
34 unsigned long end)
36 /* XXX */
39 static void r6000_flush_cache_page(struct vm_area_struct *vma,
40 unsigned long page)
42 /* XXX */
45 static void r6000_flush_page_to_ram(unsigned long page)
47 /* XXX */
50 static void r6000_flush_cache_sigtramp(unsigned long page)
52 /* XXX */
55 /* TLB operations. XXX Write these dave... */
56 static inline void r6000_flush_tlb_all(void)
58 /* XXX */
61 static void r6000_flush_tlb_mm(struct mm_struct *mm)
63 /* XXX */
66 static void r6000_flush_tlb_range(struct mm_struct *mm, unsigned long start,
67 unsigned long end)
69 /* XXX */
72 static void r6000_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
74 /* XXX */
77 static void r6000_load_pgd(unsigned long pg_dir)
81 static void r6000_pgd_init(unsigned long page)
83 unsigned long dummy1, dummy2;
86 * This version is optimized for the R6000. We generate dirty lines
87 * in the datacache, overwrite these lines with zeros and then flush
88 * the cache. Sounds horribly complicated but is just a trick to
89 * avoid unnecessary loads of from memory and uncached stores which
90 * are very expensive. Not tested yet as the R6000 is a rare CPU only
91 * available in SGI machines and I don't have one.
93 __asm__ __volatile__(
94 ".set\tnoreorder\n"
95 "1:\t"
96 "cache\t%5,(%0)\n\t"
97 "sw\t%2,(%0)\n\t"
98 "sw\t%2,4(%0)\n\t"
99 "sw\t%2,8(%0)\n\t"
100 "sw\t%2,12(%0)\n\t"
101 "cache\t%5,16(%0)\n\t"
102 "sw\t%2,16(%0)\n\t"
103 "sw\t%2,20(%0)\n\t"
104 "sw\t%2,24(%0)\n\t"
105 "sw\t%2,28(%0)\n\t"
106 "subu\t%1,1\n\t"
107 "bnez\t%1,1b\n\t"
108 "addiu\t%0,32\n\t"
109 ".set\treorder"
110 :"=r" (dummy1),
111 "=r" (dummy2)
112 :"r" ((unsigned long) invalid_pte_table),
113 "0" (page),
114 "1" (USER_PTRS_PER_PGD/8),
115 "i" (Create_Dirty_Excl_D));
118 static void r6000_update_mmu_cache(struct vm_area_struct * vma,
119 unsigned long address, pte_t pte)
121 r6000_flush_tlb_page(vma, address);
123 * FIXME: We should also reload a new entry into the TLB to
124 * avoid unnecessary exceptions.
128 static void r6000_show_regs(struct pt_regs * regs)
131 * Saved main processor registers
133 printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
134 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
135 (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
136 (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
137 (unsigned long) regs->regs[7]);
138 printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
139 (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
140 (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
141 (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
142 (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
143 printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
144 (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
145 (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
146 (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
147 (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
148 printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
149 (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
150 (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
151 (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
154 * Saved cp0 registers
156 printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
157 (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
158 (unsigned int) regs->cp0_cause);
161 static void r6000_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
162 unsigned long entryhi, unsigned long pagemask)
164 /* XXX */
167 static int r6000_user_mode(struct pt_regs *regs)
169 return !(regs->cp0_status & 0x4);
172 __initfunc(void ld_mmu_r6000(void))
174 flush_cache_all = r6000_flush_cache_all;
175 flush_cache_mm = r6000_flush_cache_mm;
176 flush_cache_range = r6000_flush_cache_range;
177 flush_cache_page = r6000_flush_cache_page;
178 flush_cache_sigtramp = r6000_flush_cache_sigtramp;
179 flush_page_to_ram = r6000_flush_page_to_ram;
181 flush_tlb_all = r6000_flush_tlb_all;
182 flush_tlb_mm = r6000_flush_tlb_mm;
183 flush_tlb_range = r6000_flush_tlb_range;
184 flush_tlb_page = r6000_flush_tlb_page;
185 r6000_asid_setup();
187 load_pgd = r6000_load_pgd;
188 pgd_init = r6000_pgd_init;
189 update_mmu_cache = r6000_update_mmu_cache;
191 show_regs = r6000_show_regs;
193 add_wired_entry = r6000_add_wired_entry;
195 user_mode = r6000_user_mode;
197 flush_cache_all();
198 flush_tlb_all();