Commit 1821c54f authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] UML: add some pudding

This adds pud_t support to UML.
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ffc8a499
...@@ -135,7 +135,8 @@ pte_t *kmap_pte; ...@@ -135,7 +135,8 @@ pte_t *kmap_pte;
pgprot_t kmap_prot; pgprot_t kmap_prot;
#define kmap_get_fixmap_pte(vaddr) \ #define kmap_get_fixmap_pte(vaddr) \
pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
(vaddr)), (vaddr))
void __init kmap_init(void) void __init kmap_init(void)
{ {
......
...@@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, ...@@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out) pte_t *pte_out)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
if(task->mm == NULL) if(task->mm == NULL)
return(ERR_PTR(-EINVAL)); return(ERR_PTR(-EINVAL));
pgd = pgd_offset(task->mm, addr); pgd = pgd_offset(task->mm, addr);
pmd = pmd_offset(pgd, addr); if(!pgd_present(*pgd))
return(ERR_PTR(-EINVAL));
pud = pud_offset(pgd, addr);
if(!pud_present(*pud))
return(ERR_PTR(-EINVAL));
pmd = pmd_offset(pud, addr);
if(!pmd_present(*pmd)) if(!pmd_present(*pmd))
return(ERR_PTR(-EINVAL)); return(ERR_PTR(-EINVAL));
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte)) if(!pte_present(*pte))
return(ERR_PTR(-EINVAL)); return(ERR_PTR(-EINVAL));
if(pte_out != NULL) if(pte_out != NULL)
*pte_out = *pte; *pte_out = *pte;
return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
......
...@@ -18,6 +18,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, ...@@ -18,6 +18,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force) unsigned long end_addr, int force)
{ {
pgd_t *npgd; pgd_t *npgd;
pmd_t *npud;
pmd_t *npmd; pmd_t *npmd;
pte_t *npte; pte_t *npte;
unsigned long addr; unsigned long addr;
...@@ -27,7 +28,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, ...@@ -27,7 +28,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
fd = mm->context.skas.mm_fd; fd = mm->context.skas.mm_fd;
for(addr = start_addr; addr < end_addr;){ for(addr = start_addr; addr < end_addr;){
npgd = pgd_offset(mm, addr); npgd = pgd_offset(mm, addr);
npmd = pmd_offset(npgd, addr); npud = pud_offset(npgd, addr);
npmd = pmd_offset(npud, addr);
if(pmd_present(*npmd)){ if(pmd_present(*npmd)){
npte = pte_offset_kernel(npmd, addr); npte = pte_offset_kernel(npmd, addr);
r = pte_read(*npte); r = pte_read(*npte);
...@@ -79,7 +81,8 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end) ...@@ -79,7 +81,8 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
mm = &init_mm; mm = &init_mm;
for(addr = start; addr < end;){ for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr); pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){ if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte) || pte_newpage(*pte)){ if(!pte_present(*pte) || pte_newpage(*pte)){
......
...@@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address) ...@@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
return(pgd_offset(mm, address)); return(pgd_offset(mm, address));
} }
pmd_t *pmd_offset_proc(pgd_t *pgd, unsigned long address) pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{ {
return(pmd_offset(pgd, address)); return(pud_offset(pgd, address));
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
return(pmd_offset(pud, address));
} }
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
...@@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address) ...@@ -71,8 +76,11 @@ pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
pte_t *addr_pte(struct task_struct *task, unsigned long addr) pte_t *addr_pte(struct task_struct *task, unsigned long addr)
{ {
return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr), pgd_t *pgd = pgd_offset(task->mm, addr);
addr)); pud_t *pud = pud_offset(pgd, addr);
pmd_t *pmd = pmd_offset(pud, addr);
return(pte_offset_map(pmd, addr));
} }
/* /*
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "linux/ptrace.h" #include "linux/ptrace.h"
#include "asm/semaphore.h" #include "asm/semaphore.h"
#include "asm/pgtable.h" #include "asm/pgtable.h"
#include "asm/pgalloc.h"
#include "asm/tlbflush.h" #include "asm/tlbflush.h"
#include "asm/a.out.h" #include "asm/a.out.h"
#include "asm/current.h" #include "asm/current.h"
...@@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, ...@@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
struct vm_area_struct *vma; struct vm_area_struct *vma;
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
unsigned long page; unsigned long page;
...@@ -54,8 +56,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, ...@@ -54,8 +56,9 @@ int handle_page_fault(unsigned long address, unsigned long ip,
if(is_write && !(vma->vm_flags & VM_WRITE)) if(is_write && !(vma->vm_flags & VM_WRITE))
goto out; goto out;
page = address & PAGE_MASK; page = address & PAGE_MASK;
pgd = pgd_offset(mm, page); pgd = pgd_offset(mm);
pmd = pmd_offset(pgd, page); pud = pud_offset(pgd, page);
pmd = pmd_offset(pud, page);
do { do {
survive: survive:
switch (handle_mm_fault(mm, vma, address, is_write)){ switch (handle_mm_fault(mm, vma, address, is_write)){
......
...@@ -19,6 +19,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, ...@@ -19,6 +19,7 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
unsigned long end_addr, int force) unsigned long end_addr, int force)
{ {
pgd_t *npgd; pgd_t *npgd;
pud_t *npud;
pmd_t *npmd; pmd_t *npmd;
pte_t *npte; pte_t *npte;
unsigned long addr; unsigned long addr;
...@@ -42,7 +43,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr, ...@@ -42,7 +43,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
continue; continue;
} }
npgd = pgd_offset(mm, addr); npgd = pgd_offset(mm, addr);
npmd = pmd_offset(npgd, addr); npud = pud_offset(npgd, addr);
npmd = pmd_offset(npud, addr);
if(pmd_present(*npmd)){ if(pmd_present(*npmd)){
npte = pte_offset_kernel(npmd, addr); npte = pte_offset_kernel(npmd, addr);
r = pte_read(*npte); r = pte_read(*npte);
...@@ -90,6 +92,7 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, ...@@ -90,6 +92,7 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end,
{ {
struct mm_struct *mm; struct mm_struct *mm;
pgd_t *pgd; pgd_t *pgd;
pud_t *pmd;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
unsigned long addr; unsigned long addr;
...@@ -98,7 +101,8 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end, ...@@ -98,7 +101,8 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end,
mm = &init_mm; mm = &init_mm;
for(addr = start; addr < end;){ for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr); pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){ if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte) || pte_newpage(*pte)){ if(!pte_present(*pte) || pte_newpage(*pte)){
...@@ -155,6 +159,7 @@ void mprotect_kernel_vm(int w) ...@@ -155,6 +159,7 @@ void mprotect_kernel_vm(int w)
{ {
struct mm_struct *mm; struct mm_struct *mm;
pgd_t *pgd; pgd_t *pgd;
pud_t *pud;
pmd_t *pmd; pmd_t *pmd;
pte_t *pte; pte_t *pte;
unsigned long addr; unsigned long addr;
...@@ -162,7 +167,8 @@ void mprotect_kernel_vm(int w) ...@@ -162,7 +167,8 @@ void mprotect_kernel_vm(int w)
mm = &init_mm; mm = &init_mm;
for(addr = start_vm; addr < end_vm;){ for(addr = start_vm; addr < end_vm;){
pgd = pgd_offset(mm, addr); pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr); pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){ if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if(pte_present(*pte)) protect_vm_page(addr, w, 0); if(pte_present(*pte)) protect_vm_page(addr, w, 0);
......
...@@ -13,12 +13,14 @@ ...@@ -13,12 +13,14 @@
#define pmd_populate_kernel(mm, pmd, pte) \ #define pmd_populate_kernel(mm, pmd, pte) \
set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)))
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, #define pmd_populate(mm, pmd, pte) \
struct page *pte) set_pmd(pmd, __pmd(_PAGE_TABLE + \
{ ((unsigned long long)page_to_pfn(pte) << \
set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte))); (unsigned long long) PAGE_SHIFT)))
}
/*
* Allocate and free page tables.
*/
extern pgd_t *pgd_alloc(struct mm_struct *); extern pgd_t *pgd_alloc(struct mm_struct *);
extern void pgd_free(pgd_t *pgd); extern void pgd_free(pgd_t *pgd);
...@@ -45,7 +47,7 @@ static inline void pte_free(struct page *pte) ...@@ -45,7 +47,7 @@ static inline void pte_free(struct page *pte)
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(x) do { } while (0) #define pmd_free(x) do { } while (0)
#define __pmd_free_tlb(tlb,x) do { } while (0) #define __pmd_free_tlb(tlb,x) do { } while (0)
#define pgd_populate(mm, pmd, pte) BUG() #define pud_populate(mm, pmd, pte) BUG()
#define check_pgt_cache() do { } while (0) #define check_pgt_cache() do { } while (0)
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
#ifndef __UM_PGTABLE_H #ifndef __UM_PGTABLE_H
#define __UM_PGTABLE_H #define __UM_PGTABLE_H
#include <asm-generic/4level-fixup.h>
#include "linux/sched.h" #include "linux/sched.h"
#include "asm/processor.h" #include "asm/processor.h"
#include "asm/page.h" #include "asm/page.h"
...@@ -23,7 +21,6 @@ extern unsigned long *empty_zero_page; ...@@ -23,7 +21,6 @@ extern unsigned long *empty_zero_page;
#define pgtable_cache_init() do ; while (0) #define pgtable_cache_init() do ; while (0)
/* PMD_SHIFT determines the size of the area a second-level page table can map */ /* 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_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1)) #define PMD_MASK (~(PMD_SIZE-1))
...@@ -39,7 +36,6 @@ extern unsigned long *empty_zero_page; ...@@ -39,7 +36,6 @@ extern unsigned long *empty_zero_page;
#define PTRS_PER_PTE 1024 #define PTRS_PER_PTE 1024
#define PTRS_PER_PMD 1 #define PTRS_PER_PMD 1
#define PTRS_PER_PGD 1024 #define PTRS_PER_PGD 1024
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_PGD_NR 0 #define FIRST_USER_PGD_NR 0
#define pte_ERROR(e) \ #define pte_ERROR(e) \
...@@ -176,6 +172,15 @@ extern pte_t * __bad_pagetable(void); ...@@ -176,6 +172,15 @@ extern pte_t * __bad_pagetable(void);
#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE) #define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE) #define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE)
#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
static inline pud_t *__pud_alloc(struct mm_struct *mm, pgd_t *pgd,
unsigned long addr)
{
BUG();
}
/* /*
* The "pgd_xxx()" functions here are trivial for a folded two-level * The "pgd_xxx()" functions here are trivial for a folded two-level
* setup: the pgd is never bad, and a pmd always exists (as it's folded * setup: the pgd is never bad, and a pmd always exists (as it's folded
...@@ -374,15 +379,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ...@@ -374,15 +379,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* this macro returns the index of the entry in the pgd page which would * this macro returns the index of the entry in the pgd page which would
* control the given virtual address * control the given virtual address
*/ */
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
#define pgd_index_k(addr) pgd_index(addr)
/* /*
* pgd_offset() returns a (pgd_t *) * pgd_offset() returns a (pgd_t *)
* pgd_index() is used get the offset into the pgd page's array of pgd_t's; * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
*/ */
#define pgd_offset(mm, address) \ #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
((mm)->pgd + ((address) >> PGDIR_SHIFT))
/* /*
* a shortcut which implies the use of the kernel's pgd, instead * a shortcut which implies the use of the kernel's pgd, instead
...@@ -390,15 +395,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ...@@ -390,15 +395,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
*/ */
#define pgd_offset_k(address) pgd_offset(&init_mm, address) #define pgd_offset_k(address) pgd_offset(&init_mm, address)
/*
* the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
*
* this macro returns the index of the entry in the pmd page which would
* control the given virtual address
*/
#define pmd_index(address) \ #define pmd_index(address) \
(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
/* Find an entry in the second-level page table.. */
static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
{
return (pmd_t *) dir;
}
/* /*
* the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
* *
...@@ -430,6 +435,8 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) ...@@ -430,6 +435,8 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
#include <asm-generic/pgtable.h> #include <asm-generic/pgtable.h>
#include <asm-um/pgtable-nopud.h>
#endif #endif
#endif #endif
......
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