Commit 1f8d419e authored by David Gibson's avatar David Gibson Committed by Linus Torvalds

[PATCH] ppc64: pgtable.h and other header cleanups

This patch started as simply removing a few never-used macros from
asm-ppc64/pgtable.h, then kind of grew.  It now makes a bunch of
cleanups to the ppc64 low-level header files (with corresponding
changes to .c files where necessary) such as:
	- Abolishing never-used macros
	- Eliminating multiple #defines with the same purpose
	- Removing pointless macros (cases where just expanding the
macro everywhere turns out clearer and more sensible)
	- Removing some cases where macros which could be defined in
terms of each other weren't
	- Moving imalloc() related definitions from pgtable.h to their
own header file (imalloc.h)
	- Re-arranging headers to group things more logically
	- Moving all VSID allocation related things to mmu.h, instead
of being split between mmu.h and mmu_context.h
	- Removing some reserved space for flags from the PMD - we're
not using it.
	- Fix some bugs which broke compile with STRICT_MM_TYPECHECKS.
Signed-off-by: default avatarDavid Gibson <dwg@au1.ibm.com>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e685752d
...@@ -438,7 +438,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, ...@@ -438,7 +438,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
int i; int i;
if (page_is_ram(offset >> PAGE_SHIFT)) if (page_is_ram(offset >> PAGE_SHIFT))
return prot; return __pgprot(prot);
prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
......
...@@ -320,8 +320,7 @@ static void native_flush_hash_range(unsigned long context, ...@@ -320,8 +320,7 @@ static void native_flush_hash_range(unsigned long context,
j = 0; j = 0;
for (i = 0; i < number; i++) { for (i = 0; i < number; i++) {
if ((batch->addr[i] >= USER_START) && if (batch->addr[i] < KERNELBASE)
(batch->addr[i] <= USER_END))
vsid = get_vsid(context, batch->addr[i]); vsid = get_vsid(context, batch->addr[i]);
else else
vsid = get_kernel_vsid(batch->addr[i]); vsid = get_kernel_vsid(batch->addr[i]);
......
...@@ -298,24 +298,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -298,24 +298,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
int local = 0; int local = 0;
cpumask_t tmp; cpumask_t tmp;
if ((ea & ~REGION_MASK) > EADDR_MASK)
return 1;
switch (REGION_ID(ea)) { switch (REGION_ID(ea)) {
case USER_REGION_ID: case USER_REGION_ID:
user_region = 1; user_region = 1;
mm = current->mm; mm = current->mm;
if ((ea > USER_END) || (! mm)) if (! mm)
return 1; return 1;
vsid = get_vsid(mm->context.id, ea); vsid = get_vsid(mm->context.id, ea);
break; break;
case IO_REGION_ID: case IO_REGION_ID:
if (ea > IMALLOC_END)
return 1;
mm = &ioremap_mm; mm = &ioremap_mm;
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
break; break;
case VMALLOC_REGION_ID: case VMALLOC_REGION_ID:
if (ea > VMALLOC_END)
return 1;
mm = &init_mm; mm = &init_mm;
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
break; break;
...@@ -362,7 +361,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, ...@@ -362,7 +361,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
unsigned long vsid, vpn, va, hash, secondary, slot; unsigned long vsid, vpn, va, hash, secondary, slot;
unsigned long huge = pte_huge(pte); unsigned long huge = pte_huge(pte);
if ((ea >= USER_START) && (ea <= USER_END)) if (ea < KERNELBASE)
vsid = get_vsid(context, ea); vsid = get_vsid(context, ea);
else else
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/imalloc.h>
static DECLARE_MUTEX(imlist_sem); static DECLARE_MUTEX(imlist_sem);
struct vm_struct * imlist = NULL; struct vm_struct * imlist = NULL;
...@@ -23,11 +24,11 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr) ...@@ -23,11 +24,11 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
unsigned long addr; unsigned long addr;
struct vm_struct **p, *tmp; struct vm_struct **p, *tmp;
addr = IMALLOC_START; addr = ioremap_bot;
for (p = &imlist; (tmp = *p) ; p = &tmp->next) { for (p = &imlist; (tmp = *p) ; p = &tmp->next) {
if (size + addr < (unsigned long) tmp->addr) if (size + addr < (unsigned long) tmp->addr)
break; break;
if ((unsigned long)tmp->addr >= IMALLOC_START) if ((unsigned long)tmp->addr >= ioremap_bot)
addr = tmp->size + (unsigned long) tmp->addr; addr = tmp->size + (unsigned long) tmp->addr;
if (addr > IMALLOC_END-size) if (addr > IMALLOC_END-size)
return 1; return 1;
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/imalloc.h>
int mem_init_done; int mem_init_done;
unsigned long ioremap_bot = IMALLOC_BASE; unsigned long ioremap_bot = IMALLOC_BASE;
......
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/cputable.h> #include <asm/cputable.h>
struct stab_entry {
unsigned long esid_data;
unsigned long vsid_data;
};
/* Both the segment table and SLB code uses the following cache */ /* Both the segment table and SLB code uses the following cache */
#define NR_STAB_CACHE_ENTRIES 8 #define NR_STAB_CACHE_ENTRIES 8
DEFINE_PER_CPU(long, stab_cache_ptr); DEFINE_PER_CPU(long, stab_cache_ptr);
......
#ifndef _PPC64_IMALLOC_H
#define _PPC64_IMALLOC_H
/*
* Define the address range of the imalloc VM area.
*/
#define PHBS_IO_BASE IOREGIONBASE
#define IMALLOC_BASE (IOREGIONBASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
#define IMALLOC_END (IOREGIONBASE + EADDR_MASK)
/* imalloc region types */
#define IM_REGION_UNUSED 0x1
#define IM_REGION_SUBSET 0x2
#define IM_REGION_EXISTS 0x4
#define IM_REGION_OVERLAP 0x8
#define IM_REGION_SUPERSET 0x10
extern struct vm_struct * im_get_free_area(unsigned long size);
extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
int region_type);
unsigned long im_free(void *addr);
#endif /* _PPC64_IMALLOC_H */
...@@ -15,19 +15,10 @@ ...@@ -15,19 +15,10 @@
#include <linux/config.h> #include <linux/config.h>
#include <asm/page.h> #include <asm/page.h>
#include <linux/stringify.h>
#ifndef __ASSEMBLY__ /*
* Segment table
/* Time to allow for more things here */ */
typedef unsigned long mm_context_id_t;
typedef struct {
mm_context_id_t id;
#ifdef CONFIG_HUGETLB_PAGE
pgd_t *huge_pgdir;
u16 htlb_segs; /* bitmask */
#endif
} mm_context_t;
#define STE_ESID_V 0x80 #define STE_ESID_V 0x80
#define STE_ESID_KS 0x20 #define STE_ESID_KS 0x20
...@@ -36,15 +27,48 @@ typedef struct { ...@@ -36,15 +27,48 @@ typedef struct {
#define STE_VSID_SHIFT 12 #define STE_VSID_SHIFT 12
struct stab_entry { /* Location of cpu0's segment table */
unsigned long esid_data; #define STAB0_PAGE 0x9
unsigned long vsid_data; #define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT)
}; #define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR)
/*
* SLB
*/
/* Hardware Page Table Entry */ #define SLB_NUM_BOLTED 3
#define SLB_CACHE_ENTRIES 8
/* Bits in the SLB ESID word */
#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */
/* Bits in the SLB VSID word */
#define SLB_VSID_SHIFT 12
#define SLB_VSID_KS ASM_CONST(0x0000000000000800)
#define SLB_VSID_KP ASM_CONST(0x0000000000000400)
#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage 16M */
#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C)
#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS)
/*
* Hash table
*/
#define HPTES_PER_GROUP 8 #define HPTES_PER_GROUP 8
/* Values for PP (assumes Ks=0, Kp=1) */
/* pp0 will always be 0 for linux */
#define PP_RWXX 0 /* Supervisor read/write, User none */
#define PP_RWRX 1 /* Supervisor read/write, User read */
#define PP_RWRW 2 /* Supervisor read/write, User read/write */
#define PP_RXRX 3 /* Supervisor read, User read */
#ifndef __ASSEMBLY__
/* Hardware Page Table Entry */
typedef struct { typedef struct {
unsigned long avpn:57; /* vsid | api == avpn */ unsigned long avpn:57; /* vsid | api == avpn */
unsigned long : 2; /* Software use */ unsigned long : 2; /* Software use */
...@@ -90,14 +114,6 @@ typedef struct { ...@@ -90,14 +114,6 @@ typedef struct {
} dw1; } dw1;
} HPTE; } HPTE;
/* Values for PP (assumes Ks=0, Kp=1) */
/* pp0 will always be 0 for linux */
#define PP_RWXX 0 /* Supervisor read/write, User none */
#define PP_RWRX 1 /* Supervisor read/write, User read */
#define PP_RWRW 2 /* Supervisor read/write, User read/write */
#define PP_RXRX 3 /* Supervisor read, User read */
extern HPTE * htab_address; extern HPTE * htab_address;
extern unsigned long htab_hash_mask; extern unsigned long htab_hash_mask;
...@@ -174,31 +190,70 @@ extern int __hash_page(unsigned long ea, unsigned long access, ...@@ -174,31 +190,70 @@ extern int __hash_page(unsigned long ea, unsigned long access,
extern void htab_finish_init(void); extern void htab_finish_init(void);
extern void hpte_init_native(void);
extern void hpte_init_lpar(void);
extern void hpte_init_iSeries(void);
extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
int secondary, unsigned long hpteflags,
int bolted, int large);
extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long prpn, int secondary,
unsigned long hpteflags, int bolted, int large);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* /*
* Location of cpu0's segment table * VSID allocation
*
* We first generate a 36-bit "proto-VSID". For kernel addresses this
* is equal to the ESID, for user addresses it is:
* (context << 15) | (esid & 0x7fff)
*
* The two forms are distinguishable because the top bit is 0 for user
* addresses, whereas the top two bits are 1 for kernel addresses.
* Proto-VSIDs with the top two bits equal to 0b10 are reserved for
* now.
*
* The proto-VSIDs are then scrambled into real VSIDs with the
* multiplicative hash:
*
* VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
* where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
* VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
*
* This scramble is only well defined for proto-VSIDs below
* 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
* reserved. VSID_MULTIPLIER is prime, so in particular it is
* co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
* Because the modulus is 2^n-1 we can compute it efficiently without
* a divide or extra multiply (see below).
*
* This scheme has several advantages over older methods:
*
* - We have VSIDs allocated for every kernel address
* (i.e. everything above 0xC000000000000000), except the very top
* segment, which simplifies several things.
*
* - We allow for 15 significant bits of ESID and 20 bits of
* context for user addresses. i.e. 8T (43 bits) of address space for
* up to 1M contexts (although the page table structure and context
* allocation will need changes to take advantage of this).
*
* - The scramble function gives robust scattering in the hash
* table (at least based on some initial results). The previous
* method was more susceptible to pathological cases giving excessive
* hash collisions.
*/
/*
* WARNING - If you change these you must make sure the asm
* implementations in slb_allocate (slb_low.S), do_stab_bolted
* (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
*
* You'll also need to change the precomputed VSID values in head.S
* which are used by the iSeries firmware.
*/ */
#define STAB0_PAGE 0x9
#define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT)
#define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR)
#define SLB_NUM_BOLTED 3
#define SLB_CACHE_ENTRIES 8
/* Bits in the SLB ESID word */
#define SLB_ESID_V 0x0000000008000000 /* entry is valid */
/* Bits in the SLB VSID word */
#define SLB_VSID_SHIFT 12
#define SLB_VSID_KS 0x0000000000000800
#define SLB_VSID_KP 0x0000000000000400
#define SLB_VSID_N 0x0000000000000200 /* no-execute */
#define SLB_VSID_L 0x0000000000000100 /* largepage (4M) */
#define SLB_VSID_C 0x0000000000000080 /* class */
#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C)
#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS)
#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ #define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */
#define VSID_BITS 36 #define VSID_BITS 36
...@@ -239,4 +294,50 @@ extern void htab_finish_init(void); ...@@ -239,4 +294,50 @@ extern void htab_finish_init(void);
srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \
add rt,rt,rx add rt,rt,rx
#ifndef __ASSEMBLY__
typedef unsigned long mm_context_id_t;
typedef struct {
mm_context_id_t id;
#ifdef CONFIG_HUGETLB_PAGE
pgd_t *huge_pgdir;
u16 htlb_segs; /* bitmask */
#endif
} mm_context_t;
static inline unsigned long vsid_scramble(unsigned long protovsid)
{
#if 0
/* The code below is equivalent to this function for arguments
* < 2^VSID_BITS, which is all this should ever be called
* with. However gcc is not clever enough to compute the
* modulus (2^n-1) without a second multiply. */
return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
#else /* 1 */
unsigned long x;
x = protovsid * VSID_MULTIPLIER;
x = (x >> VSID_BITS) + (x & VSID_MODULUS);
return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
#endif /* 1 */
}
/* This is only valid for addresses >= KERNELBASE */
static inline unsigned long get_kernel_vsid(unsigned long ea)
{
return vsid_scramble(ea >> SID_SHIFT);
}
/* This is only valid for user addresses (which are below 2^41) */
static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
{
return vsid_scramble((context << USER_ESID_BITS)
| (ea >> SID_SHIFT));
}
#endif /* __ASSEMBLY */
#endif /* _PPC64_MMU_H_ */ #endif /* _PPC64_MMU_H_ */
...@@ -84,86 +84,4 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) ...@@ -84,86 +84,4 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
local_irq_restore(flags); local_irq_restore(flags);
} }
/* VSID allocation
* ===============
*
* We first generate a 36-bit "proto-VSID". For kernel addresses this
* is equal to the ESID, for user addresses it is:
* (context << 15) | (esid & 0x7fff)
*
* The two forms are distinguishable because the top bit is 0 for user
* addresses, whereas the top two bits are 1 for kernel addresses.
* Proto-VSIDs with the top two bits equal to 0b10 are reserved for
* now.
*
* The proto-VSIDs are then scrambled into real VSIDs with the
* multiplicative hash:
*
* VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
* where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
* VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
*
* This scramble is only well defined for proto-VSIDs below
* 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
* reserved. VSID_MULTIPLIER is prime, so in particular it is
* co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
* Because the modulus is 2^n-1 we can compute it efficiently without
* a divide or extra multiply (see below).
*
* This scheme has several advantages over older methods:
*
* - We have VSIDs allocated for every kernel address
* (i.e. everything above 0xC000000000000000), except the very top
* segment, which simplifies several things.
*
* - We allow for 15 significant bits of ESID and 20 bits of
* context for user addresses. i.e. 8T (43 bits) of address space for
* up to 1M contexts (although the page table structure and context
* allocation will need changes to take advantage of this).
*
* - The scramble function gives robust scattering in the hash
* table (at least based on some initial results). The previous
* method was more susceptible to pathological cases giving excessive
* hash collisions.
*/
/*
* WARNING - If you change these you must make sure the asm
* implementations in slb_allocate(), do_stab_bolted and mmu.h
* (ASM_VSID_SCRAMBLE macro) are changed accordingly.
*
* You'll also need to change the precomputed VSID values in head.S
* which are used by the iSeries firmware.
*/
static inline unsigned long vsid_scramble(unsigned long protovsid)
{
#if 0
/* The code below is equivalent to this function for arguments
* < 2^VSID_BITS, which is all this should ever be called
* with. However gcc is not clever enough to compute the
* modulus (2^n-1) without a second multiply. */
return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
#else /* 1 */
unsigned long x;
x = protovsid * VSID_MULTIPLIER;
x = (x >> VSID_BITS) + (x & VSID_MODULUS);
return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
#endif /* 1 */
}
/* This is only valid for addresses >= KERNELBASE */
static inline unsigned long get_kernel_vsid(unsigned long ea)
{
return vsid_scramble(ea >> SID_SHIFT);
}
/* This is only valid for user addresses (which are below 2^41) */
static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
{
return vsid_scramble((context << USER_ESID_BITS)
| (ea >> SID_SHIFT));
}
#endif /* __PPC64_MMU_CONTEXT_H */ #endif /* __PPC64_MMU_CONTEXT_H */
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#define PAGE_SHIFT 12 #define PAGE_SHIFT 12
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_OFFSET_MASK (PAGE_SIZE-1)
#define SID_SHIFT 28 #define SID_SHIFT 28
#define SID_MASK 0xfffffffffUL #define SID_MASK 0xfffffffffUL
...@@ -85,9 +84,6 @@ ...@@ -85,9 +84,6 @@
/* align addr on a size boundary - adjust address up if needed */ /* align addr on a size boundary - adjust address up if needed */
#define _ALIGN(addr,size) _ALIGN_UP(addr,size) #define _ALIGN(addr,size) _ALIGN_UP(addr,size)
/* to align the pointer to the (next) double word boundary */
#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long))
/* to align the pointer to the (next) page boundary */ /* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
...@@ -100,7 +96,6 @@ ...@@ -100,7 +96,6 @@
#define REGION_SIZE 4UL #define REGION_SIZE 4UL
#define REGION_SHIFT 60UL #define REGION_SHIFT 60UL
#define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
#define REGION_STRIDE (1UL << REGION_SHIFT)
static __inline__ void clear_page(void *addr) static __inline__ void clear_page(void *addr)
{ {
...@@ -209,13 +204,13 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */ ...@@ -209,13 +204,13 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
#define VMALLOCBASE ASM_CONST(0xD000000000000000) #define VMALLOCBASE ASM_CONST(0xD000000000000000)
#define IOREGIONBASE ASM_CONST(0xE000000000000000) #define IOREGIONBASE ASM_CONST(0xE000000000000000)
#define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT) #define IO_REGION_ID (IOREGIONBASE >> REGION_SHIFT)
#define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT) #define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT)
#define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT) #define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT)
#define USER_REGION_ID (0UL) #define USER_REGION_ID (0UL)
#define REGION_ID(X) (((unsigned long)(X))>>REGION_SHIFT) #define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
#define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE) #define __bpn_to_ba(x) ((((unsigned long)(x)) << PAGE_SHIFT) + KERNELBASE)
#define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT) #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
......
...@@ -17,16 +17,6 @@ ...@@ -17,16 +17,6 @@
#include <asm-generic/pgtable-nopud.h> #include <asm-generic/pgtable-nopud.h>
/* PMD_SHIFT determines what a second-level page table entry can map */
#define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#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 (PAGE_SHIFT + (PAGE_SHIFT - 3) + (PAGE_SHIFT - 2))
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
/* /*
* Entries per page directory level. The PTE level must use a 64b record * Entries per page directory level. The PTE level must use a 64b record
* for each page table entry. The PMD and PGD level use a 32b record for * for each page table entry. The PMD and PGD level use a 32b record for
...@@ -40,40 +30,30 @@ ...@@ -40,40 +30,30 @@
#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
#define USER_PTRS_PER_PGD (1024) /* PMD_SHIFT determines what a second-level page table entry can map */
#define FIRST_USER_ADDRESS 0 #define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ /* PGDIR_SHIFT determines what a third-level page table entry can map */
PGD_INDEX_SIZE + PAGE_SHIFT) #define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
#define FIRST_USER_ADDRESS 0
/* /*
* Size of EA range mapped by our pagetables. * Size of EA range mapped by our pagetables.
*/ */
#define PGTABLE_EA_BITS 41 #define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
#define PGTABLE_EA_MASK ((1UL<<PGTABLE_EA_BITS)-1) PGD_INDEX_SIZE + PAGE_SHIFT)
#define EADDR_MASK ((1UL << EADDR_SIZE) - 1)
/* /*
* Define the address range of the vmalloc VM area. * Define the address range of the vmalloc VM area.
*/ */
#define VMALLOC_START (0xD000000000000000ul) #define VMALLOC_START (0xD000000000000000ul)
#define VMALLOC_END (VMALLOC_START + PGTABLE_EA_MASK) #define VMALLOC_END (VMALLOC_START + EADDR_MASK)
/*
* Define the address range of the imalloc VM area.
* (used for ioremap)
*/
#define IMALLOC_START (ioremap_bot)
#define IMALLOC_VMADDR(x) ((unsigned long)(x))
#define PHBS_IO_BASE (0xE000000000000000ul) /* Reserve 2 gigs for PHBs */
#define IMALLOC_BASE (0xE000000080000000ul)
#define IMALLOC_END (IMALLOC_BASE + PGTABLE_EA_MASK)
/*
* Define the user address range
*/
#define USER_START (0UL)
#define USER_END (USER_START + PGTABLE_EA_MASK)
/* /*
* Bits in a linux-style PTE. These match the bits in the * Bits in a linux-style PTE. These match the bits in the
...@@ -168,10 +148,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; ...@@ -168,10 +148,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
/* shift to put page number into pte */ /* shift to put page number into pte */
#define PTE_SHIFT (17) #define PTE_SHIFT (17)
/* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD
* to give the PTE page number. The bottom two bits are for flags. */
#define PMD_TO_PTEPAGE_SHIFT (2)
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -200,13 +176,14 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); ...@@ -200,13 +176,14 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm);
*/ */
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
#define pfn_pte(pfn,pgprot) \ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
({ \ {
pte_t pte; \ pte_t pte;
pte_val(pte) = ((unsigned long)(pfn) << PTE_SHIFT) | \
pgprot_val(pgprot); \
pte; \ pte_val(pte) = (pfn << PTE_SHIFT) | pgprot_val(pgprot);
}) return pte;
}
#define pte_modify(_pte, newprot) \ #define pte_modify(_pte, newprot) \
(__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))) (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
...@@ -220,13 +197,12 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); ...@@ -220,13 +197,12 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm);
#define pte_page(x) pfn_to_page(pte_pfn(x)) #define pte_page(x) pfn_to_page(pte_pfn(x))
#define pmd_set(pmdp, ptep) \ #define pmd_set(pmdp, ptep) \
(pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT)) (pmd_val(*(pmdp)) = __ba_to_bpn(ptep))
#define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) == 0) #define pmd_bad(pmd) (pmd_val(pmd) == 0)
#define pmd_present(pmd) (pmd_val(pmd) != 0) #define pmd_present(pmd) (pmd_val(pmd) != 0)
#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0)
#define pmd_page_kernel(pmd) \ #define pmd_page_kernel(pmd) (__bpn_to_ba(pmd_val(pmd)))
(__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT))
#define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd))
#define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp))) #define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp)))
...@@ -266,8 +242,6 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); ...@@ -266,8 +242,6 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm);
/* to find an entry in the ioremap page-table-directory */ /* to find an entry in the ioremap page-table-directory */
#define pgd_offset_i(address) (ioremap_pgd + pgd_index(address)) #define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
/* /*
* The following only work if pte_present() is true. * The following only work if pte_present() is true.
* Undefined behaviour if not.. * Undefined behaviour if not..
...@@ -442,7 +416,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, ...@@ -442,7 +416,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_clear(mm, addr, ptep); pte_clear(mm, addr, ptep);
flush_tlb_pending(); flush_tlb_pending();
} }
*ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS; *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
} }
/* Set the dirty and/or accessed bits atomically in a linux PTE, this /* Set the dirty and/or accessed bits atomically in a linux PTE, this
...@@ -487,18 +461,13 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, ...@@ -487,18 +461,13 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
extern unsigned long ioremap_bot, ioremap_base; extern unsigned long ioremap_bot, ioremap_base;
#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
#define pte_ERROR(e) \
printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \ #define pmd_ERROR(e) \
printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e)) printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
#define pgd_ERROR(e) \ #define pgd_ERROR(e) \
printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e)) printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
extern pgd_t swapper_pg_dir[1024]; extern pgd_t swapper_pg_dir[];
extern pgd_t ioremap_dir[1024]; extern pgd_t ioremap_dir[];
extern void paging_init(void); extern void paging_init(void);
...@@ -540,43 +509,11 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); ...@@ -540,43 +509,11 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
*/ */
#define kern_addr_valid(addr) (1) #define kern_addr_valid(addr) (1)
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot) remap_pfn_range(vma, vaddr, pfn, size, prot)
#define MK_IOSPACE_PFN(space, pfn) (pfn)
#define GET_IOSPACE(pfn) 0
#define GET_PFN(pfn) (pfn)
void pgtable_cache_init(void); void pgtable_cache_init(void);
extern void hpte_init_native(void);
extern void hpte_init_lpar(void);
extern void hpte_init_iSeries(void);
/* imalloc region types */
#define IM_REGION_UNUSED 0x1
#define IM_REGION_SUBSET 0x2
#define IM_REGION_EXISTS 0x4
#define IM_REGION_OVERLAP 0x8
#define IM_REGION_SUPERSET 0x10
extern struct vm_struct * im_get_free_area(unsigned long size);
extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
int region_type);
unsigned long im_free(void *addr);
extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long va, unsigned long prpn,
int secondary, unsigned long hpteflags,
int bolted, int large);
extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
unsigned long prpn, int secondary,
unsigned long hpteflags, int bolted, int large);
/* /*
* find_linux_pte returns the address of a linux pte for a given * find_linux_pte returns the address of a linux pte for a given
* effective address and directory. If not found, it returns zero. * effective address and directory. If not found, it returns zero.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment