patch-2.4.8 linux/arch/cris/mm/tlb.c
Next file: linux/arch/i386/boot/Makefile
Previous file: linux/arch/cris/mm/init.c
Back to the patch index
Back to the overall index
- Lines: 145
- Date:
Thu Jul 26 15:10:06 2001
- Orig file:
v2.4.7/linux/arch/cris/mm/tlb.c
- Orig date:
Wed Jul 25 17:10:17 2001
diff -u --recursive --new-file v2.4.7/linux/arch/cris/mm/tlb.c linux/arch/cris/mm/tlb.c
@@ -40,6 +40,10 @@
*
* The last page_id is never running - it is used as an invalid page_id
* so we can make TLB entries that will never match.
+ *
+ * Notice that we need to make the flushes atomic, otherwise an interrupt
+ * handler that uses vmalloced memory might cause a TLB load in the middle
+ * of a flush causing.
*/
struct mm_struct *page_id_map[NUM_PAGEID];
@@ -49,17 +53,18 @@
/* invalidate all TLB entries */
void
-flush_tlb_all()
+flush_tlb_all(void)
{
int i;
+ unsigned long flags;
/* the vpn of i & 0xf is so we dont write similar TLB entries
* in the same 4-way entry group. details..
*/
+ save_and_cli(flags); /* flush needs to be atomic */
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
-
*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
IO_FIELD(R_TLB_HI, vpn, i & 0xf ) );
@@ -69,6 +74,7 @@
IO_STATE(R_TLB_LO, we, no ) |
IO_FIELD(R_TLB_LO, pfn, 0 ) );
}
+ restore_flags(flags);
D(printk("tlb: flushed all\n"));
}
@@ -79,6 +85,7 @@
{
int i;
int page_id = mm->context;
+ unsigned long flags;
D(printk("tlb: flush mm context %d (%p)\n", page_id, mm));
@@ -90,6 +97,7 @@
* global pages. is it worth the extra I/O ?
*/
+ save_and_cli(flags); /* flush needs to be atomic */
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
@@ -103,6 +111,7 @@
IO_FIELD(R_TLB_LO, pfn, 0 ) );
}
}
+ restore_flags(flags);
}
/* invalidate a single page */
@@ -114,6 +123,7 @@
struct mm_struct *mm = vma->vm_mm;
int page_id = mm->context;
int i;
+ unsigned long flags;
D(printk("tlb: flush page %p in context %d (%p)\n", addr, page_id, mm));
@@ -126,6 +136,7 @@
* and the virtual address requested
*/
+ save_and_cli(flags); /* flush needs to be atomic */
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
unsigned long tlb_hi;
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
@@ -142,6 +153,7 @@
IO_FIELD(R_TLB_LO, pfn, 0 ) );
}
}
+ restore_flags(flags);
}
/* invalidate a page range */
@@ -153,6 +165,7 @@
{
int page_id = mm->context;
int i;
+ unsigned long flags;
D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
start, end, page_id, mm));
@@ -167,6 +180,7 @@
* and the virtual address range
*/
+ save_and_cli(flags); /* flush needs to be atomic */
for(i = 0; i < NUM_TLB_ENTRIES; i++) {
unsigned long tlb_hi, vpn;
*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
@@ -184,8 +198,30 @@
IO_FIELD(R_TLB_LO, pfn, 0 ) );
}
}
+ restore_flags(flags);
}
+/* dump the entire TLB for debug purposes */
+
+#if 0
+void
+dump_tlb_all(void)
+{
+ int i;
+ unsigned long flags;
+
+ printk("TLB dump. LO is: pfn | reserved | global | valid | kernel | we |\n");
+
+ save_and_cli(flags);
+ for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+ *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
+ printk("Entry %d: HI 0x%08lx, LO 0x%08lx\n",
+ i, *R_TLB_HI, *R_TLB_LO);
+ }
+ restore_flags(flags);
+}
+#endif
+
/*
* Initialize the context related info for a new mm_struct
* instance.
@@ -228,8 +264,7 @@
map_replace_ptr++;
if(map_replace_ptr == INVALID_PAGEID)
- map_replace_ptr = 0; /* wrap around */
-
+ map_replace_ptr = 0; /* wrap around */
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)