summaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/init.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-06-30 00:21:34 +0000
commit3917ac5846dd0f9ad1238166f90caab9912052e6 (patch)
tree1c298935def4f29edb39192365a65d73de999155 /arch/mips/mm/init.c
parentaf2f803c8b2d469fe38e4a7ce952658dfcb6681a (diff)
o Merge with Linux 2.1.100.
o Cleanup the machine dependencies of floppy and rtc. The driver for the Dallas thingy in the Indy is still missing. o Handle allocation of zero'd pages correct for R4000SC / R4400SC. o Page colouring shit to match the virtual and physical colour of all mapped pages. This tends to produce extreme fragmentation problems, so it's deactivated for now. Users of R4000SC / R4400SC may re-enable the code in arch/mips/mm/init.c by removing the definition of CONF_GIVE_A_SHIT_ABOUT_COLOURS. Should get them somewhat further - but don't shake to hard ... o Fixed ptrace(2)-ing of syscalls, strace is now working again. o Fix the interrupt forwarding from the keyboard driver to the psaux driver, PS/2 mice are now working on the Indy. The fix is somewhat broken as it prevents generic kernels for Indy and machines which handle things different. o Things I can't remember.
Diffstat (limited to 'arch/mips/mm/init.c')
-rw-r--r--arch/mips/mm/init.c142
1 files changed, 133 insertions, 9 deletions
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index dd2fcbad2..f9ee7c554 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -1,11 +1,10 @@
-/*
+/* $Id: init.c,v 1.5 1998/04/05 11:23:54 ralf Exp $
+ *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
- *
- * $Id: init.c,v 1.4 1998/03/22 23:27:15 ralf Exp $
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Ralf Baechle
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -16,10 +15,12 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
+#include <linux/pagemap.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/swapctl.h>
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
@@ -28,13 +29,17 @@
#include <asm/cachectl.h>
#include <asm/dma.h>
#include <asm/jazzdma.h>
-#include <asm/vector.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#ifdef CONFIG_SGI
#include <asm/sgialib.h>
#endif
+/*
+ * Define this to effectivly disable the userpage colouring shit.
+ */
+#define CONF_GIVE_A_SHIT_ABOUT_COLOURS
+
extern void deskstation_tyne_dma_init(void);
extern void show_net_buffers(void);
@@ -48,6 +53,46 @@ asmlinkage int sys_cacheflush(void *addr, int bytes, int cache)
}
/*
+ * We have upto 8 empty zeroed pages so we can map one of the right colour
+ * when needed. This is necessary only on R4000 / R4400 SC and MC versions
+ * where we have to avoid VCED / VECI exceptions for good performance at
+ * any price. Since page is never written to after the initialization we
+ * don't have to care about aliases on other CPUs.
+ */
+unsigned long empty_zero_page, zero_page_mask;
+
+static inline unsigned long setup_zero_pages(void)
+{
+ unsigned long order, size, pg;
+
+ switch (mips_cputype) {
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ order = 3;
+ default:
+ order = 0;
+ }
+
+ empty_zero_page = __get_free_pages(GFP_KERNEL, order);
+ if (!empty_zero_page)
+ panic("Oh boy, that early out of memory?");
+
+ pg = MAP_NR(empty_zero_page);
+ while(pg < MAP_NR(empty_zero_page) + (1 << order)) {
+ set_bit(PG_reserved, &mem_map[pg].flags);
+ pg++;
+ }
+
+ size = PAGE_SIZE << order;
+ zero_page_mask = (size - 1) & PAGE_MASK;
+ memset((void *)empty_zero_page, 0, size);
+
+ return size;
+}
+
+/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
* do_exit(), but using this instead means there is less risk
@@ -126,6 +171,83 @@ pte_t __bad_page(void)
return pte_mkdirty(mk_pte(page, PAGE_SHARED));
}
+#ifdef __SMP__
+spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED;
+#endif
+struct upcache user_page_cache[8] __attribute__((aligned(32)));
+static unsigned long user_page_order;
+unsigned long user_page_colours;
+
+unsigned long get_user_page_slow(int which)
+{
+ unsigned long chunk;
+ struct upcache *up = &user_page_cache[0];
+ struct page *p, *res;
+ int i;
+
+ do {
+ chunk = __get_free_pages(GFP_KERNEL, user_page_order);
+ } while(chunk==0);
+
+ p = mem_map + MAP_NR(chunk);
+ res = p + which;
+ spin_lock(&user_page_lock);
+ for (i=user_page_colours; i>=0; i--,p++,up++,chunk+=PAGE_SIZE) {
+ atomic_set(&p->count, 1);
+ p->age = PAGE_INITIAL_AGE;
+
+ if (p != res) {
+ if(up->count < USER_PAGE_WATER) {
+ p->next = up->list;
+ up->list = p;
+ up->count++;
+ } else
+ free_pages(chunk, 0);
+ }
+ }
+ spin_unlock(&user_page_lock);
+
+ return page_address(res);
+}
+
+static inline void user_page_setup(void)
+{
+ unsigned long assoc = 0;
+ unsigned long dcache_log, icache_log, cache_log;
+ unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
+
+ switch(mips_cputype) {
+ case CPU_R4000SC:
+ case CPU_R4000MC:
+ case CPU_R4400SC:
+ case CPU_R4400MC:
+ cache_log = 3; /* => 32k, sucks */
+ break;
+
+ case CPU_R4600: /* two way set associative caches? */
+ case CPU_R4700:
+ case CPU_R5000:
+ case CPU_NEVADA:
+ assoc = 1;
+ /* fall through */
+ default:
+ /* use bigger cache */
+ icache_log = (config >> 9) & 7;
+ dcache_log = (config >> 6) & 7;
+ if (dcache_log > icache_log)
+ cache_log = dcache_log;
+ else
+ cache_log = icache_log;
+ }
+
+#ifdef CONF_GIVE_A_SHIT_ABOUT_COLOURS
+ cache_log = assoc = 0;
+#endif
+
+ user_page_order = cache_log - assoc;
+ user_page_colours = (1 << (cache_log - assoc)) - 1;
+}
+
void show_mem(void)
{
int i, free = 0, total = 0, reserved = 0;
@@ -178,9 +300,6 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
max_mapnr = num_physpages = MAP_NR(end_mem);
high_memory = (void *)end_mem;
- /* clear the zero-page */
- clear_page((unsigned long)empty_zero_page);
-
/* mark usable pages in the mem_map[] */
start_mem = PAGE_ALIGN(start_mem);
@@ -217,13 +336,18 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
free_page(tmp);
}
tmp = nr_free_pages << PAGE_SHIFT;
+
+ /* Setup zeroed pages. */
+ tmp -= setup_zero_pages();
+
printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
tmp >> 10,
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10));
- return;
+ /* Initialize allocator for colour matched mapped pages. */
+ user_page_setup();
}
extern char __init_begin, __init_end;