From: James Bottomley <James.Bottomley@steeleye.com>
To: PARISC list <parisc-linux@lists.parisc-linux.org>
Cc: parisc-linux-cvs@lists.parisc-linux.org
Subject: [parisc-linux] Re: [parisc-linux-cvs] linux-2.6 jejb
Date: 03 May 2004 15:51:09 -0500 [thread overview]
Message-ID: <1083617469.2417.10.camel@mulgrave> (raw)
In-Reply-To: <20040502161601.DC7C24945C7@palinux.hppa>
On Sun, 2004-05-02 at 11:16, James Bottomley wrote:
> CVSROOT: /var/cvs
> Module name: linux-2.6
> Changes by: jejb 04/05/02 10:16:01
>
> Modified files:
> . : Makefile
> arch/parisc/kernel: asm-offsets.c entry.S init_task.c
> include/asm-parisc: pgalloc.h pgtable.h
>
> Log message:
> Implement L2/L3 hybrid page tables for 64 bit kernels
Index: arch/parisc/kernel/asm-offsets.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/asm-offsets.c,v
retrieving revision 1.7
diff -u -r1.7 asm-offsets.c
--- a/arch/parisc/kernel/asm-offsets.c 1 May 2004 20:03:11 -0000 1.7
+++ b/arch/parisc/kernel/asm-offsets.c 2 May 2004 15:53:49 -0000
@@ -282,6 +282,7 @@
DEFINE(ASM_BITS_PER_PGD, BITS_PER_PGD);
DEFINE(ASM_BITS_PER_PMD, BITS_PER_PMD);
DEFINE(ASM_BITS_PER_PTE, BITS_PER_PTE);
+ DEFINE(ASM_PGD_PMD_OFFSET, -(PAGE_SIZE << PGD_ORDER));
DEFINE(ASM_PMD_ENTRY, ((PAGE_OFFSET & PMD_MASK) >> PMD_SHIFT));
DEFINE(ASM_PGD_ENTRY, PAGE_OFFSET >> PGDIR_SHIFT);
DEFINE(ASM_PGD_ENTRY_SIZE, PGD_ENTRY_SIZE);
Index: arch/parisc/kernel/entry.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/entry.S,v
retrieving revision 1.13
diff -u -r1.13 entry.S
--- a/arch/parisc/kernel/entry.S 1 May 2004 20:03:11 -0000 1.13
+++ b/arch/parisc/kernel/entry.S 2 May 2004 15:53:51 -0000
@@ -474,11 +474,24 @@
bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault
.endm
- /* Look up PTE in a 3-Level scheme */
+ /* Look up PTE in a 3-Level scheme.
+ *
+ * Here we implement a Hybrid L2/L3 scheme: we allocate the
+ * first pmd adjacent to the pgd. This means that we can
+ * subtract a constant offset to get to it. The pmd and pgd
+ * sizes are arranged so that a single pmd covers 4GB (giving
+ * a full LP64 process access to 8TB) so our lookups are
+ * effectively L2 for the first 4GB of the kernel (i.e. for
+ * all ILP32 processes and all the kernel for machines with
+ * under 4GB of memory) */
.macro L3_ptep pgd,pte,index,va,fault
extrd,u \va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
copy %r0,\pte
+ extrd,u,*= \va,31,32,%r0
ldw,s \index(\pgd),\pgd
+ extrd,u,*<> \va,31,32,%r0
+ ldo ASM_PGD_PMD_OFFSET(\pgd),\pgd
+ extrd,u,*= \va,31,32,%r0
bb,>=,n \pgd,_PAGE_PRESENT_BIT,\fault
L2_ptep \pgd,\pte,\index,\va,\fault
.endm
Index: arch/parisc/kernel/init_task.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/init_task.c,v
retrieving revision 1.5
diff -u -r1.5 init_task.c
--- a/arch/parisc/kernel/init_task.c 1 May 2004 16:05:55 -0000 1.5
+++ b/arch/parisc/kernel/init_task.c 2 May 2004 15:53:51 -0000
@@ -52,11 +52,13 @@
__attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE<<PGD_ORDER))) = { {0}, };
#ifdef __LP64__
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { {0}, };
+/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
+ * with the first pmd adjacent to the pgd and below it */
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
#endif
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(4096))) = { {0}, };
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
/*
* Initial task structure.
Index: include/asm-parisc/pgalloc.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/pgalloc.h,v
retrieving revision 1.4
diff -u -r1.4 pgalloc.h
--- a/include/asm-parisc/pgalloc.h 1 May 2004 20:03:11 -0000 1.4
+++ b/include/asm-parisc/pgalloc.h 2 May 2004 15:54:10 -0000
@@ -10,18 +10,44 @@
#include <asm/pgtable.h>
#include <asm/cache.h>
+/* Allocate the top level pgd (page directory)
+ *
+ * Here (for 64 bit kernels) we implement a Hybrid L2/L3 scheme: we
+ * allocate the first pmd adjacent to the pgd. This means that we can
+ * subtract a constant offset to get to it. The pmd and pgd sizes are
+ * arranged so that a single pmd covers 4GB (giving a full LP64
+ * process access to 8TB) so our lookups are effectively L2 for the
+ * first 4GB of the kernel (i.e. for all ILP32 processes and all the
+ * kernel for machines with under 4GB of memory) */
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
- pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, PGD_ORDER);
-
- if (likely(pgd != NULL))
- memset(pgd, 0, PAGE_SIZE<<PGD_ORDER);
- return pgd;
+ pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|GFP_DMA,
+ PGD_ALLOC_ORDER);
+ pgd_t *actual_pgd = pgd;
+
+ if (likely(pgd != NULL)) {
+ memset(pgd, 0, PAGE_SIZE<<PGD_ALLOC_ORDER);
+#ifdef __LP64__
+ actual_pgd += PTRS_PER_PGD;
+ /* Populate first pmd with allocated memory. We mark it
+ * with _PAGE_GATEWAY as a signal to the system that this
+ * pmd entry may not be cleared. */
+ pgd_val(*actual_pgd) = (_PAGE_TABLE | _PAGE_GATEWAY) +
+ (__u32)__pa((unsigned long)pgd);
+ /* The first pmd entry also is marked with _PAGE_GATEWAY as
+ * a signal that this pmd may not be freed */
+ pgd_val(*pgd) = _PAGE_GATEWAY;
+#endif
+ }
+ return actual_pgd;
}
static inline void pgd_free(pgd_t *pgd)
{
- free_pages((unsigned long)pgd, PGD_ORDER);
+#ifdef __LP64__
+ pgd -= PTRS_PER_PGD;
+#endif
+ free_pages((unsigned long)pgd, PGD_ALLOC_ORDER);
}
#if PT_NLEVELS == 3
@@ -46,6 +72,12 @@
static inline void pmd_free(pmd_t *pmd)
{
+#ifdef __LP64__
+ if(pmd_val(*pmd) & _PAGE_GATEWAY)
+ /* This is the permanent pmd attached to the pgd;
+ * cannot free it */
+ return;
+#endif
free_pages((unsigned long)pmd, PMD_ORDER);
}
@@ -67,7 +99,15 @@
static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
{
- pmd_val(*pmd) = _PAGE_TABLE + (__u32)__pa((unsigned long)pte);
+#ifdef __LP64__
+ /* preserve the gateway marker if this is the beginning of
+ * the permanent pmd */
+ if(pmd_val(*pmd) & _PAGE_GATEWAY)
+ pmd_val(*pmd) = (_PAGE_TABLE | _PAGE_GATEWAY)
+ + (__u32)__pa((unsigned long)pte);
+ else
+#endif
+ pmd_val(*pmd) = _PAGE_TABLE + (__u32)__pa((unsigned long)pte);
}
#define pmd_populate(mm, pmd, pte_page) \
Index: include/asm-parisc/pgtable.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/pgtable.h,v
retrieving revision 1.8
diff -u -r1.8 pgtable.h
--- a/include/asm-parisc/pgtable.h 1 May 2004 20:03:11 -0000 1.8
+++ b/include/asm-parisc/pgtable.h 2 May 2004 15:54:11 -0000
@@ -67,10 +67,12 @@
#define PT_INITIAL 4 /* Number of initial page tables */
#define PGD_ORDER 1 /* Number of pages per pgd */
#define PMD_ORDER 1 /* Number of pages per pmd */
+#define PGD_ALLOC_ORDER 2 /* first pgd contains pmd */
#else
#define PT_NLEVELS 2
#define PT_INITIAL 2 /* Number of initial page tables */
#define PGD_ORDER 0 /* Number of pages per pgd */
+#define PGD_ALLOC_ORDER PGD_ORDER
#endif
/* Definitions for 3rd level (we use PLD here for Page Lower directory
@@ -242,10 +244,26 @@
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
#define pte_clear(xp) do { pte_val(*(xp)) = 0; } while (0)
+#ifdef __LP64__
+/* The first entry of the permanent pmd is not there if it contains
+ * the gateway marker */
+#define pmd_none(x) (!pmd_val(x) || pmd_val(x) == _PAGE_GATEWAY)
+#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK) != _PAGE_TABLE && (pmd_val(x) & ~PAGE_MASK) != (_PAGE_TABLE | _PAGE_GATEWAY))
+#else
#define pmd_none(x) (!pmd_val(x))
#define pmd_bad(x) ((pmd_val(x) & ~PAGE_MASK) != _PAGE_TABLE)
+#endif
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
+static inline void pmd_clear(pmd_t *pmd) {
+#ifdef __LP64__
+ if(pmd_val(*pmd) & _PAGE_GATEWAY)
+ /* This is the entry pointing to the permanent pmd
+ * attached to the pgd; cannot clear it */
+ pmd_val(*pmd) = _PAGE_GATEWAY;
+ else
+#endif
+ pmd_val(*pmd) = 0;
+}
@@ -255,9 +273,21 @@
/* For 64 bit we have three level tables */
#define pgd_none(x) (!pgd_val(x))
+#ifdef __LP64__
+#define pgd_bad(x) ((pgd_val(x) & ~PAGE_MASK) != _PAGE_TABLE && (pgd_val(x) & ~PAGE_MASK) != (_PAGE_TABLE | _PAGE_GATEWAY))
+#else
#define pgd_bad(x) ((pgd_val(x) & ~PAGE_MASK) != _PAGE_TABLE)
+#endif
#define pgd_present(x) (pgd_val(x) & _PAGE_PRESENT)
-#define pgd_clear(xp) do { pgd_val(*(xp)) = 0; } while (0)
+static inline void pgd_clear(pgd_t *pgd) {
+#ifdef __LP64__
+ if(pgd_val(*pgd) & _PAGE_GATEWAY)
+ /* This is the permanent pmd attached to the pgd; cannot
+ * free it */
+ return;
+#endif
+ pgd_val(*pgd) = 0;
+}
#else
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
next parent reply other threads:[~2004-05-03 20:51 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20040502161601.DC7C24945C7@palinux.hppa>
2004-05-03 20:51 ` James Bottomley [this message]
[not found] <20040505204811.27F0C4945E4@palinux.hppa>
2004-05-05 20:50 ` [parisc-linux] Re: [parisc-linux-cvs] linux-2.6 jejb James Bottomley
2004-05-06 5:05 ` Randolph Chung
2004-05-06 5:22 ` Randolph Chung
2004-05-06 9:33 ` M. Grabert
2004-05-06 13:25 ` Kyle McMartin
[not found] <20040501200312.40BB74945E1@palinux.hppa>
2004-05-01 20:09 ` James Bottomley
2004-05-03 8:57 ` Joel Soete
[not found] <20040501160556.D07DC4945CA@palinux.hppa>
2004-05-01 16:13 ` James Bottomley
[not found] <20040430162037.9D2B94945CD@palinux.hppa>
2004-04-30 16:25 ` James Bottomley
[not found] <20040427171140.706074945BD@palinux.hppa>
2004-04-27 17:15 ` James Bottomley
[not found] <20040425145051.10F5C4942B8@palinux.hppa>
2004-04-25 14:55 ` James Bottomley
[not found] <20040414174535.81173494194@palinux.hppa>
2004-04-14 17:53 ` James Bottomley
[not found] <20040412154800.D31F6494194@palinux.hppa>
2004-04-12 15:55 ` James Bottomley
[not found] <20040407004901.031D3494194@palinux.hppa>
2004-04-07 0:54 ` James Bottomley
2004-04-08 6:15 ` Joel Soete
2004-04-08 12:36 ` James Bottomley
[not found] <20040406213446.CB675494194@palinux.hppa>
2004-04-06 21:37 ` James Bottomley
[not found] <20040405174131.84BF1494194@palinux.hppa>
2004-04-06 13:21 ` Carlos O'Donell
2004-04-06 14:18 ` James Bottomley
2004-04-06 15:40 ` Randolph Chung
[not found] <20040405024740.9330F494194@palinux.hppa>
2004-04-05 2:49 ` James Bottomley
2004-04-05 2:54 ` James Bottomley
[not found] <20040320210116.7A727494553@palinux.hppa>
2004-03-20 21:04 ` James Bottomley
2004-03-20 21:10 ` Helge Deller
2004-03-20 21:13 ` Helge Deller
[not found] <20040228212407.DB126494190@palinux.hppa>
2004-02-28 22:21 ` Joel Soete
2004-02-28 22:42 ` James Bottomley
2004-02-29 9:39 ` Joel Soete
2004-03-04 16:39 ` Joel Soete
2004-02-06 7:31 [parisc-linux] " Joel Soete
2004-02-06 17:50 ` Grant Grundler
2004-02-06 18:06 ` bame
2004-02-06 19:16 ` Randolph Chung
2004-02-06 17:08 ` Joel Soete
2004-02-07 6:40 ` Randolph Chung
2004-02-09 7:26 ` Joel Soete
[not found] <20040204182455.1CC11494191@palinux.hppa>
2004-02-05 9:20 ` [parisc-linux] " Randolph Chung
2004-02-05 15:19 ` James Bottomley
2004-02-05 15:29 ` [parisc-linux] " Joel Soete
2004-02-05 20:31 ` Randolph Chung
2004-02-05 18:49 ` Joel Soete
[not found] <20040113155603.CBCC249425A@palinux.hppa>
2004-01-13 15:58 ` [parisc-linux] " James Bottomley
[not found] <20030924175431.D51BC49408B@palinux.hppa>
2003-09-24 18:01 ` James Bottomley
[not found] <20030919010356.148684940A4@palinux.hppa>
2003-09-19 1:06 ` James Bottomley
2003-09-19 11:24 ` Randolph Chung
2003-09-19 14:02 ` James Bottomley
2003-09-19 18:24 ` Jim Hull
[not found] <20030903200300.8B7B7494064@palinux.hppa>
2003-09-03 20:07 ` James Bottomley
[not found] <20030903165113.138BF494064@palinux.hppa>
2003-09-03 16:56 ` James Bottomley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1083617469.2417.10.camel@mulgrave \
--to=james.bottomley@steeleye.com \
--cc=parisc-linux-cvs@lists.parisc-linux.org \
--cc=parisc-linux@lists.parisc-linux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox