[PATCH] Fix to make check_pgt_cache work on !i386 architectures

Jakub Jelinek (jj@sunsite.ms.mff.cuni.cz)
Fri, 31 Jul 1998 15:27:24 +0200 (MET DST)


Hi!

When I was writing the page table cache stuff for all the architectures, I
put the check_pgt_cache routine into memory.c because it was used by most
architectures, but not all, particularly only those where all page table
levels are of size PAGE_SIZE. I'm sorry I have not put there a clear comment
telling that, but I did not expect anybody else to call it anyway.
check_pgt_cache is not able to handle more complicated cases where a lot of
page tables are cached in one page, particularly sparc32/srmmu, where there
are 16 page tables in one page.
So, I have two possible solutions (one is implemented below), and would like
to ask you if you could tell us which way to go (as this has to touch
generic code). Without such knowledge, I guess full merge of other
architectures cannot happen (unless we e.g. waste one full page for one page
table when it is 1/16 of that size, which would be much worse than 2.0).
The first solution is to add a platform specific do_check_pgt_cache()
function, as implemented below.
The other solution would be to move check_pgt_cache function from memory.c
into all arch specific directories and edit it if the port needs it.
The affected ports are:

sparc32 on sun4m, sun4d
sparc64 on UP
m68k (your tree caches now only pte tables, but caching of pgd/pmd is in the
works and will help a lot, as m68k does a lot of expensive tricks with
the page tables (turning cacheability on and off etc.)).

When Bill Hawes posted a question if it is safe to do that, I have been on
holidays, so I could not react.

--- ./mm/memory.c.jj Sun Jul 26 22:55:43 1998
+++ ./mm/memory.c Fri Jul 31 11:01:07 1998
@@ -136,7 +136,7 @@ void clear_page_tables(struct task_struc
free_one_pgd(page_dir + i);

/* keep the page table cache within bounds */
- check_pgt_cache();
+ do_check_pgt_cache();
return;

out_bad:
@@ -165,7 +165,7 @@ void free_page_tables(struct mm_struct *
pgd_free(page_dir);

/* keep the page table cache within bounds */
- check_pgt_cache();
+ do_check_pgt_cache();
out:
return;

@@ -952,6 +952,12 @@ void make_pages_present(unsigned long ad
The system should try to have pgt_water[0] <= cache elements <= pgt_water[1]
*/
int pgt_cache_water[2] = { 25, 50 };
+
+/*
+ * Note: this is just a helper function most (but not all) architectures
+ * use. You should not call it directly from generic code. See asm/pgtable.h
+ * for do_check_pgt_cache(). -jj
+ */

void check_pgt_cache(void)
{
--- ./include/asm-i386/pgtable.h.jj Tue Jul 28 22:51:19 1998
+++ ./include/asm-i386/pgtable.h Fri Jul 31 14:52:43 1998
@@ -574,6 +574,8 @@ extern inline void set_pgdir(unsigned lo
#endif
}

+#define do_check_pgt_cache() check_pgt_cache()
+
extern pgd_t swapper_pg_dir[1024];

/*
--- ./include/asm-mips/pgtable.h.jj Fri May 8 09:13:26 1998
+++ ./include/asm-mips/pgtable.h Fri Jul 31 14:54:22 1998
@@ -489,6 +489,8 @@ extern inline pgd_t *pgd_alloc(void)
return (pgd_t *) page;
}

+#define do_check_pgt_cache() check_pgt_cache()
+
extern pgd_t swapper_pg_dir[1024];

extern void (*update_mmu_cache)(struct vm_area_struct *vma,
--- ./include/asm-alpha/pgtable.h.jj Wed Jul 22 21:44:49 1998
+++ ./include/asm-alpha/pgtable.h Fri Jul 31 14:51:47 1998
@@ -575,6 +575,8 @@ extern inline void set_pgdir(unsigned lo
pgd[(address >> PGDIR_SHIFT) & (PTRS_PER_PAGE - 1)] = entry;
}

+#define do_check_pgt_cache() check_pgt_cache()
+
extern pgd_t swapper_pg_dir[1024];

/*
--- ./include/asm-m68k/pgtable.h.jj Thu Jun 25 20:03:43 1998
+++ ./include/asm-m68k/pgtable.h Fri Jul 31 14:53:52 1998
@@ -776,6 +776,8 @@ extern inline void set_pgdir(unsigned lo
/* Nothing to do on m68k */
}

+#define do_check_pgt_cache() check_pgt_cache()
+
/*
* Check if the addr/len goes up to the end of a physical
* memory chunk. Used for DMA functions.
--- ./include/asm-sparc/pgtable.h.jj Wed Apr 15 02:44:23 1998
+++ ./include/asm-sparc/pgtable.h Fri Jul 31 14:59:46 1998
@@ -23,6 +23,7 @@
#include <asm/sbus.h>
#include <asm/btfixup.h>
#include <asm/spinlock.h>
+#include <asm/system.h>

extern void load_mmu(void);
extern int io_remap_page_range(unsigned long from, unsigned long to,
@@ -120,6 +121,16 @@ BTFIXUPDEF_INT(page_kernel)
BTFIXUPDEF_CALL(void, set_pgdir, unsigned long, pgd_t)

#define set_pgdir(address,entry) BTFIXUP_CALL(set_pgdir)(address,entry)
+
+extern void srmmu_check_pgt_cache(void);
+
+extern __inline__ void do_check_pgt_cache(void)
+{
+ if (ARCH_SUN4C_SUN4)
+ check_pgt_cache();
+ else
+ srmmu_check_pgt_cache(void);
+}

/* Top-level page directory */
extern pgd_t swapper_pg_dir[1024];
--- ./include/asm-ppc/pgtable.h.jj Thu May 21 03:55:15 1998
+++ ./include/asm-ppc/pgtable.h Fri Jul 31 14:54:50 1998
@@ -540,6 +540,8 @@ extern inline void set_pgdir(unsigned lo
#endif
}

+#define do_check_pgt_cache() check_pgt_cache()
+
extern pgd_t swapper_pg_dir[1024];

extern __inline__ pte_t *find_pte(struct mm_struct *mm,unsigned long va)
--- ./include/asm-sparc64/pgtable.h.jj Fri May 8 09:11:36 1998
+++ ./include/asm-sparc64/pgtable.h Fri Jul 31 14:46:51 1998
@@ -546,6 +546,30 @@ extern inline void set_pgdir(unsigned lo
/* Nothing to do on sparc64 :) */
}

+/* Low and high watermarks for page table cache.
+ The system should try to have pgt_water[0] <= cache elements <= pgt_water[1]
+ */
+extern int pgt_cache_water[2];
+
+#ifdef __SMP__
+
+#define do_check_pgt_cache() do { \
+if(pgtable_cache_size > pgt_cache_water[1]) \
+ check_pgt_cache(); \
+} while(0)
+
+#else
+
+extern void ultra_check_pgt_cache(void);
+
+#define do_check_pgt_cache() do { \
+if(pgtable_cache_size > pgt_cache_water[1] || \
+ pgd_cache_size > pgt_cache_water[1] / 4) \
+ ultra_check_pgt_cache(); \
+} while(0)
+
+#endif
+
extern pgd_t swapper_pg_dir[1024];

extern inline void SET_PAGE_DIR(struct task_struct *tsk, pgd_t *pgdir)
--- ./include/asm-arm/pgtable.h.jj Wed Jan 21 01:39:42 1998
+++ ./include/asm-arm/pgtable.h Fri Jul 31 14:52:16 1998
@@ -7,4 +7,6 @@
#define module_map vmalloc
#define module_unmap vfree

+#define do_check_pgt_cache() check_pgt_cache()
+
#endif /* _ASMARM_PGTABLE_H */
--- ./arch/sparc/kernel/process.c.jj Thu May 21 23:24:05 1998
+++ ./arch/sparc/kernel/process.c Fri Jul 31 14:58:39 1998
@@ -40,7 +40,6 @@
#include <asm/elf.h>

extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
-extern void srmmu_check_pgt_cache(void);

struct task_struct *current_set[NR_CPUS] = {&init_task, };

--- ./arch/sparc64/kernel/process.c.jj Thu May 21 23:24:05 1998
+++ ./arch/sparc64/kernel/process.c Fri Jul 31 14:41:09 1998
@@ -43,9 +43,7 @@

#ifndef __SMP__

-extern int pgt_cache_water[2];
-
-static inline void ultra_check_pgt_cache(void)
+void ultra_check_pgt_cache(void)
{
struct page *page, *page2;

Cheers,
Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
Ultralinux - first 64bit OS to take full power of the UltraSparc
Linux version 2.1.112 on a sparc64 machine (498.80 BogoMips).
___________________________________________________________________

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html