[xtensa-cvscommit] linux/include/asm-xtensa pgtable.h,1.10,1.11
Brought to you by:
zankel
|
From: <ma...@us...> - 2003-04-01 22:26:58
|
Update of /cvsroot/xtensa/linux/include/asm-xtensa
In directory sc8-pr-cvs1:/tmp/cvs-serv25932
Modified Files:
pgtable.h
Log Message:
Fix multihit kernel bug -- essentially adjust pte_none() and related code.
Also fix definitions of PTE entry format for swapped files, add descriptive
comments, and other sundry cleanup.
Index: pgtable.h
===================================================================
RCS file: /cvsroot/xtensa/linux/include/asm-xtensa/pgtable.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -d -r1.10 -r1.11
*** pgtable.h 11 Mar 2003 19:17:00 -0000 1.10
--- pgtable.h 1 Apr 2003 22:26:53 -0000 1.11
***************
*** 11,16 ****
* for more details.
*
! * Copyright (C) 2001 Tensilica Inc.
! * Authors: Marc Gauthier
* Joe Taylor <jo...@te..., jo...@ya...>
*/
--- 11,16 ----
* for more details.
*
! * Copyright (C) 2001 - 2003 Tensilica Inc.
! * Authors: Marc Gauthier <ma...@te...> <ma...@al...>
* Joe Taylor <jo...@te..., jo...@ya...>
*/
***************
*** 23,26 ****
--- 23,27 ----
#ifndef _LANGUAGE_ASSEMBLY
+ #include <linux/sched.h>
#include <linux/linkage.h>
#include <linux/config.h>
***************
*** 35,46 ****
#if XTENSA_CACHE_ALIAS
! /* We provide our own get_unmapped_area to avoid cache alias issue */
#define HAVE_ARCH_UNMAPPED_AREA
#define PG_mapped PG_arch_1
! /* this is a mask of the naughty bits that can cause cache aliasing
! * problems. Because xtensa has a configurable cache size we have to
! * get funky.... Start with 0xffff_ffff and then mask off everything
! * else that is not a problem...
*/
#define XT_CACHE_WAYSIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
--- 36,46 ----
#if XTENSA_CACHE_ALIAS
! /* We provide our own get_unmapped_area to avoid cache alias issues */
#define HAVE_ARCH_UNMAPPED_AREA
#define PG_mapped PG_arch_1
! /* This is a mask of the bits that can cause cache aliasing problems.
! * Because Xtensa has a configurable cache size, we use
! * configuration information to compute the mask.
*/
#define XT_CACHE_WAYSIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
***************
*** 50,55 ****
! /* Only if the dcache is writeback do we still need to flush at
! * times. Cache aliasing is not allowed (yet) and not supported (yet).
*/
--- 50,55 ----
!
! /* If the dcache is writeback or we have cache aliasing, may need to flush.
*/
***************
*** 83,86 ****
--- 83,87 ----
+
/* 19feb2003 -- jn
* enabling dcache aliasing
***************
*** 100,107 ****
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
! /* Basically we have the same two-level (which is the logical three
! * level Linux page table layout folded) page tables as the i386. Use
! * the first min-wired way for mapping page-table pages. Page
! * coloring requires a second min-wired way.
*/
--- 101,107 ----
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
!
! /* Use the first min-wired way for mapping page-table pages.
! * Page coloring requires a second min-wired way.
*/
***************
*** 125,134 ****
! /* PMD_SHIFT determines the size of the area a second-level page table can map */
#define PMD_SHIFT 22
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
! /* PGDIR_SHIFT determines what a third-level page table entry can map */
#define PGDIR_SHIFT 22
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
--- 125,160 ----
! /*
! * The Xtensa architecture port of Linux uses essentially the same
! * two-level page tables as the i386, i.e. the logical three-level
! * Linux page table layout folded. That is, for each task's memory space:
! *
! * the PGD table (page directory), ie. 3rd-level page table,
! * is one page (4 kB) of 1024 (PTRS_PER_PGD) pointers to PTE tables
! * (are ptrs to PMD tables in arch's where PMDs are not folded).
! *
! * For a given task, the pointer to the PGD table is:
! * (t->mm ? t->mm : t->active_mm)->pgd
! * where t is (struct task_struct *) (eg. current()).
! *
! * the PMD tables (page middle-directory), ie. 2nd-level page tables,
! * are absent (folded, PTRS_PER_PMD == 1).
! *
! * the PTE tables (page table entry), ie. 1st-level page tables,
! * are one page (4 kB) of 1024 (PTRS_PER_PTE) PTEs;
! * special PTE tables include:
! * - invalid_pte_table (pointed to by PMD table, for absent mappings)
! *
! * individual pages are 4 kB;
! * special pages include:
! * - empty_zero_page
! */
!
! /* PMD_SHIFT determines the v.m. size a PMD table *entry* can map */
#define PMD_SHIFT 22
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
! /* PGDIR_SHIFT determines the v.m. size a PGD table *entry* can map */
#define PGDIR_SHIFT 22
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
***************
*** 142,146 ****
#define PTRS_PER_PGD 1024
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
! #define FIRST_USER_PGD_NR 0
/* 27feb2003 -- jn
--- 168,172 ----
#define PTRS_PER_PGD 1024
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
! #define FIRST_USER_PGD_NR 0 /* task VM starts at address zero */
/* 27feb2003 -- jn
***************
*** 154,169 ****
#if (XTENSA_CACHE_ALIAS)
! #define XTENSA_ALIAS_RESERVE_SIZE XCDCACHE_WAY_SIZE
! #define XTENSA_ALIAS_RESERVE_START 0xC0010000
! #define VMALLOC_START (XTENSA_ALIAS_RESERVE_START + XTENSA_ALIAS_RESERVE_SIZE)
#else
! #define VMALLOC_START 0xC0010000
#endif
! #define VMALLOC_VMADDR(x) ((unsigned long)(x))
! #define VMALLOC_END 0xC7FF0000
! /* Xtensa Linux config PTE layout:
* 31-12: PPN
* 11-6: software:
--- 180,211 ----
#if (XTENSA_CACHE_ALIAS)
! #define XTENSA_ALIAS_RESERVE_SIZE XCDCACHE_WAY_SIZE
! #define XTENSA_ALIAS_RESERVE_START 0xC0010000
! #define VMALLOC_START (XTENSA_ALIAS_RESERVE_START + XTENSA_ALIAS_RESERVE_SIZE)
#else
! #define VMALLOC_START 0xC0010000
#endif
! #define VMALLOC_VMADDR(x) ((unsigned long)(x))
! #define VMALLOC_END 0xC7FF0000
!
! /* More assumptions: */
! #if (XCHAL_MMU_RINGS != 4)
! #error Linux build assumes 4 ring levels.
! #endif
! #if (XCHAL_MMU_RING_BITS != 2)
! #error We assume exactly two bits for RING.
! #endif
! #if (XCHAL_MMU_CA_BITS != 4)
! #error We assume exactly four bits for CA.
! #endif
! #if (XCHAL_MMU_SR_BITS != 0)
! #error We have no room for SR bits.
! #endif
!
!
! /* Xtensa Linux config PTE layout (when present):
* 31-12: PPN
* 11-6: software:
***************
*** 184,205 ****
* process write to the page, this keeps a mod bit via the hardware
* dirty bit.
*/
! #if (XCHAL_MMU_RINGS != 4)
! #error Linux build assumes 4 ring levels.
! #endif
! #if (XCHAL_MMU_RING_BITS != 2)
! #error We assume exactly two bits for RING.
! #endif
! #if (XCHAL_MMU_CA_BITS != 4)
! #error We assume exactly four bits for CA.
! #endif
! #if (XCHAL_MMU_SR_BITS != 0)
! #error We have no room for SR bits.
! #endif
! #define GLOBAL_RING 3 /* global ring level */
! #define USER_RING 1 /* user ring level */
! #define KERNEL_RING 0 /* kernel ring level */
#define _PAGE_GLOBAL (GLOBAL_RING<<4) /* ring: global access (ring=3) */
--- 226,249 ----
* process write to the page, this keeps a mod bit via the hardware
* dirty bit.
+ *
+ * See further below for PTE layout for swapped-out pages.
*/
! #define GLOBAL_RING 3 /* global ring level (user-level) */
! #define USER_RING 1 /* user ring level */
! #define KERNEL_RING 0 /* kernel ring level (also global) */
! #define _PAGE_VALID (1<<0) /* ca: page is accessible
! (todo: replace with CA!=invalid) */
! #define _PAGE_SILENT_READ (1<<0) /* ca: (synonym)*/
! #define _PAGE_DIRTY (1<<1) /* ca: page is writable
! (because store attempted, so is "dirty") */
! #define _PAGE_SILENT_WRITE (1<<1) /* ca: (synonym) */
! /* None of these cache modes include MP coherency: */
! #define _CACHE_BYPASS (0<<2) /* ca: bypass cache non-speculative */
! #define _CACHE_CACHABLE_NONCOHERENT (1<<2) /* ca: cachable speculative */
! #define _CACHE_UNCACHED (2<<2) /* ca: uncached speculative */
! #define _CACHE_CACHABLE_SPECIAL (3<<2) /* ca: special (isolate, no execute, ...) */
! #define _CACHE_MASK (15<<0) /* ca: all CA bits */
#define _PAGE_GLOBAL (GLOBAL_RING<<4) /* ring: global access (ring=3) */
***************
*** 207,233 ****
#define _PAGE_USER (USER_RING<<4) /* ring: user access (ring=1) */
#define _PAGE_KERNEL (KERNEL_RING<<4) /* ring: kernel access (ring=0) */
! #define _PAGE_PRESENT (1<<6) /* software: (have translation / page not swapped out?) */
! #define _PAGE_READ (1<<7) /* software: page readable */
! #define _PAGE_WRITE (1<<8) /* software: page writable */
! #define _PAGE_ACCESSED (1<<9) /* software: page accessed (read) */
! #define _PAGE_MODIFIED (1<<10) /* software: page modified (written/dirty) */
!
! #define _PAGE_VALID (1<<0) /* ca: !! replaced with CA!=invalid */
! #define _PAGE_SILENT_READ (1<<0) /* ca: !! synonym */
! #define _PAGE_DIRTY (1<<1) /* ca: !! replaced with CA!=readonly (MIPS dirty bit) */
! #define _PAGE_SILENT_WRITE (1<<1) /* ca: ... */
! #define _CACHE_BYPASS (0<<2) /* ca: bypass cache non-speculative (no MP coherency) */
! #define _CACHE_CACHABLE_NONCOHERENT (1<<2) /* ca: cachable speculative (no MP coherency) */
! #define _CACHE_UNCACHED (2<<2) /* ca: uncached speculative (no MP coherency) */
! #define _CACHE_CACHABLE_SPECIAL (3<<2) /* ca: special (isolate, no execute, ...) (no MP coherency) */
! #define _CACHE_MASK (15<<0) /* ca: all CA bits */
!
! /*#define _CACHE_CACHABLE_NO_WA (0<<0)*/ /* R4600 only */
! /*#define _CACHE_CACHABLE_WA (1<<0)*/ /* R4600 only */
! /*#define _CACHE_CACHABLE_CE (4<<0)*/ /* R4[04]00 only */
! /*#define _CACHE_CACHABLE_COW (5<<0)*/ /* R4[04]00 only */
! /*#define _CACHE_CACHABLE_CUW (6<<0)*/ /* R4[04]00 only */
! /*#define _CACHE_CACHABLE_ACCELERATED (7<<0)*/ /* R10000 only */
#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
--- 251,261 ----
#define _PAGE_USER (USER_RING<<4) /* ring: user access (ring=1) */
#define _PAGE_KERNEL (KERNEL_RING<<4) /* ring: kernel access (ring=0) */
+ #define _PAGE_RING_MASK (3<<4) /* ring bits */
! #define _PAGE_PRESENT (1<<6) /* software: page not swapped out nor "none" */
! #define _PAGE_READ (1<<7) /* software: page readable */
! #define _PAGE_WRITE (1<<8) /* software: page writable */
! #define _PAGE_ACCESSED (1<<9) /* software: page accessed (read) */
! #define _PAGE_MODIFIED (1<<10) /* software: page modified (written/dirty) */
#define __READABLE (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
***************
*** 258,262 ****
* read. Also, write permissions may imply read permissions.
* What follows is the closest we can get by reasonable means..
! * See linux/mm/mmap.c for protection_map[] array that uses these definitions. */
#define __P000 PAGE_NONE /* private --- */
#define __P001 PAGE_READONLY /* private --r */
--- 286,291 ----
* read. Also, write permissions may imply read permissions.
* What follows is the closest we can get by reasonable means..
! * See linux/mm/mmap.c for protection_map[] array that uses these definitions.
! */
#define __P000 PAGE_NONE /* private --- */
#define __P001 PAGE_READONLY /* private --r */
***************
*** 280,291 ****
#define pte_ERROR(e) \
! printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
! printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
#define pgd_ERROR(e) \
! printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
/*
! * BAD_PAGETABLE is used when we need a bogus page-table, while
* BAD_PAGE is used for a bogus page.
*
--- 309,320 ----
#define pte_ERROR(e) \
! printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
! printk("%s:%d: bad pmd entry %08lx.\n", __FILE__, __LINE__, pmd_val(e))
#define pgd_ERROR(e) \
! printk("%s:%d: bad pgd entry %08lx.\n", __FILE__, __LINE__, pgd_val(e))
/*
! * BAD_PAGETABLE is used when we need a bogus (PTE) page-table, while
* BAD_PAGE is used for a bogus page.
*
***************
*** 319,324 ****
extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
! extern pgd_t invalid_pte_table[PAGE_SIZE/sizeof(pgd_t)];
! extern pte_t exception_pte_table[PAGE_SIZE/sizeof(pte_t)];
/* to find an entry in a page-table */
--- 348,352 ----
extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
! extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pgd_t)];
/* to find an entry in a page-table */
***************
*** 342,347 ****
}
! extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
! extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
/* Certain architectures need to do special things when pte's
--- 370,400 ----
}
! /*
! * Notes:
! * - Conditions pte_none() and pte_valid() are mutually exclusive.
! * - Conditions pte_none() and pte_present() are mutually exclusive.
! * - PTEs reported as neither pte_none() nor pte_present() contain information
! * about swapped out pages; the format of these is described further below
! * with the SWP_xxx() macro definitions.
! * - PTEs reported as pte_valid() are always pte_present(), but the reverse
! * is not always true.
! * - pte_clear() causes a PTE entry to satisfy the pte_none() condition.
! *
! * Certain virtual addresses must have specific non-zero ring levels.
! * Which means that a PTE cannot be all zeroes (at least not for
! * any virtual address that might ever be accessible by a user task)
! * to indicate the pte_none() condition. So we mask out the ring
! * in the pte_none() comparison.
! *
! * XTFIXME: we might get a slight optimization on this by assuming we
! * always use _PAGE_USER for pte_none() entries (which appears to be the
! * case currently), thus comparing the PTE with _PAGE_USER rather
! * than masking out ring bits then comparing to zero.
! */
! extern inline void set_pte(pte_t *ptep, pte_t pteval);
! extern inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PAGE_RING_MASK) == 0; }
! extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
! extern inline int pte_valid(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
! extern inline void pte_clear(pte_t *ptep) { set_pte(ptep, __pte(_PAGE_USER)); }
/* Certain architectures need to do special things when pte's
***************
*** 362,369 ****
}
- extern inline void pte_clear(pte_t *ptep)
- {
- set_pte(ptep, __pte(0));
- }
/*
--- 415,418 ----
***************
*** 393,396 ****
--- 442,446 ----
}
+
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
***************
*** 403,406 ****
--- 453,457 ----
extern inline void pgd_clear(pgd_t *pgdp) { }
+
/*
* Permanent address of a page.
***************
*** 409,416 ****
--- 460,469 ----
#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
+
extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
***************
*** 474,477 ****
--- 527,531 ----
}
+
/*
* Conversion functions: convert a page and protection to a page entry,
***************
*** 503,510 ****
}
! #define page_pte(page) page_pte_prot(page, __pgprot(0))
/* to find an entry in a kernel page-table-directory */
! #define pgd_offset_k(address) pgd_offset(&init_mm, address)
#define pgd_index(address) ((address) >> PGDIR_SHIFT)
--- 557,564 ----
}
! #define page_pte(page) page_pte_prot(page, __pgprot(0))
/* to find an entry in a kernel page-table-directory */
! #define pgd_offset_k(address) pgd_offset(&init_mm, address)
#define pgd_index(address) ((address) >> PGDIR_SHIFT)
***************
*** 603,609 ****
extern void paging_init(void);
! #define SWP_TYPE(x) (((x).val >> 1) & 0x3f)
! #define SWP_OFFSET(x) ((x).val >> 8)
! #define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define swp_entry_to_pte(x) ((pte_t) { (x).val })
--- 657,702 ----
extern void paging_init(void);
! /*
! * Define swap file entries, which are PTEs for swapped-out pages.
! *
! * Background:
! * Each PTE in a process VM's page table is either:
! * "present" -- valid and not swapped out, protection bits are meaningful;
! * "not present" -- which further subdivides in these two cases:
! * "none" -- no mapping at all; identified by pte_none(), set by pte_clear();
! * "swapped out" -- the page is swapped out, and the SWP macros below
! * are used to store swap file info in the PTE itself.
! *
! * In the Xtensa processor MMU, any PTE entries in user space (or anywhere
! * in virtual memory that can map differently across address spaces)
! * must have a correct ring value that represents the RASID field that
! * is changed when switching address spaces. Eg. such PTE entries cannot
! * be set to ring zero, because that can cause a (global) kernel ASID
! * entry to be created in the TLBs (even with invalid cache attribute),
! * potentially causing a multihit exception when going back to another
! * address space that mapped the same virtual address at another ring.
! *
! * SO: we avoid using ring bits (_PAGE_RING_MASK) in "not present" PTEs.
! * We also avoid using the _PAGE_VALID and _PAGE_PRESENT bits which must
! * be zero for non-present pages.
! *
! * We end up with the following available bits: 1..3 and 7..31.
! * We don't bother with 1..3 for now (we can use them later if needed),
! * and chose to allocate 6 bits for SWP_TYPE and the remaining 19 bits
! * for SWP_OFFSET. At least 5 bits are needed for SWP_TYPE, because it
! * is currently implemented as an index into swap_info[MAX_SWAPFILES]
! * and MAX_SWAPFILES is currently defined as 32 in <linux/swap.h>.
! * However, for some reason all other architectures in the 2.4 kernel
! * reserve either 6, 7, or 8 bits so I'll not detract from that for now. :)
! * SWP_OFFSET is an offset into the swap file in page-size units, so
! * with 4 kB pages, 19 bits supports a maximum swap file size of 2 GB.
! *
! * XTFIXME: 2 GB isn't very big. Other bits can be used to allow
! * larger swap sizes. In the meantime, it appears relatively easy to get
! * around the 2 GB limitation by simply using multiple swap files.
! */
! #define SWP_TYPE(x) (((x).val >> 7) & 0x3f)
! #define SWP_OFFSET(x) ((x).val >> 13)
! #define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 7) | ((offset) << 13) })
#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define swp_entry_to_pte(x) ((pte_t) { (x).val })
***************
*** 633,637 ****
unsigned long tmp;
__asm__ __volatile__ (" rsr %0, "XTSTR(RASID)"\n\t"
- " isync\n"
: "=a" (tmp));
return tmp;
--- 726,729 ----
***************
*** 714,718 ****
unsigned long tmp;
__asm__ __volatile__("rsr %0, "XTSTR(PTEVADDR)"\n\t"
- "dsync\n"
: "=a" (tmp));
return tmp;
--- 806,809 ----
***************
*** 836,844 ****
/* The kernel (in mm/memory.c) often invokes this macro when a page
* previously wasn't mapped. In handle_2nd_level_miss() when no page
! * is mapped, we map the exception_pte_table into the Page Table to
* generate another exception that exposes the type of access. After
* mapping in the appropriate page (often by calling the kernel's
* handle_mm_fault()), we need to remove the mapping of
! * exception_pte_table from the Page Table. This macro does this
* function. The 2nd-level miss handler will later fill in the
* correct mapping. */
--- 927,935 ----
/* The kernel (in mm/memory.c) often invokes this macro when a page
* previously wasn't mapped. In handle_2nd_level_miss() when no page
! * is mapped, we map the invalid_pte_table into the Page Table to
* generate another exception that exposes the type of access. After
* mapping in the appropriate page (often by calling the kernel's
* handle_mm_fault()), we need to remove the mapping of
! * invalid_pte_table from the Page Table. This macro does this
* function. The 2nd-level miss handler will later fill in the
* correct mapping. */
|