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;
pgprot_t kmap_prot;
#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)
{
......
......@@ -235,18 +235,28 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
if(task->mm == NULL)
return(ERR_PTR(-EINVAL));
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))
return(ERR_PTR(-EINVAL));
pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte))
return(ERR_PTR(-EINVAL));
if(pte_out != NULL)
*pte_out = *pte;
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,
unsigned long end_addr, int force)
{
pgd_t *npgd;
pmd_t *npud;
pmd_t *npmd;
pte_t *npte;
unsigned long addr;
......@@ -27,7 +28,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
fd = mm->context.skas.mm_fd;
for(addr = start_addr; addr < end_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)){
npte = pte_offset_kernel(npmd, addr);
r = pte_read(*npte);
......@@ -79,7 +81,8 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
mm = &init_mm;
for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte) || pte_newpage(*pte)){
......
......@@ -59,9 +59,14 @@ pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long 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)
......@@ -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)
{
return(pte_offset_kernel(pmd_offset(pgd_offset(task->mm, addr), addr),
addr));
pgd_t *pgd = pgd_offset(task->mm, 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 @@
#include "linux/ptrace.h"
#include "asm/semaphore.h"
#include "asm/pgtable.h"
#include "asm/pgalloc.h"
#include "asm/tlbflush.h"
#include "asm/a.out.h"
#include "asm/current.h"
......@@ -32,6 +33,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long page;
......@@ -54,8 +56,9 @@ int handle_page_fault(unsigned long address, unsigned long ip,
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
page = address & PAGE_MASK;
pgd = pgd_offset(mm, page);
pmd = pmd_offset(pgd, page);
pgd = pgd_offset(mm);
pud = pud_offset(pgd, page);
pmd = pmd_offset(pud, page);
do {
survive:
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,
unsigned long end_addr, int force)
{
pgd_t *npgd;
pud_t *npud;
pmd_t *npmd;
pte_t *npte;
unsigned long addr;
......@@ -42,7 +43,8 @@ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
continue;
}
npgd = pgd_offset(mm, addr);
npmd = pmd_offset(npgd, addr);
npud = pud_offset(npgd, addr);
npmd = pmd_offset(npud, addr);
if(pmd_present(*npmd)){
npte = pte_offset_kernel(npmd, addr);
r = pte_read(*npte);
......@@ -90,6 +92,7 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end,
{
struct mm_struct *mm;
pgd_t *pgd;
pud_t *pmd;
pmd_t *pmd;
pte_t *pte;
unsigned long addr;
......@@ -98,7 +101,8 @@ static void flush_kernel_vm_range(unsigned long start, unsigned long end,
mm = &init_mm;
for(addr = start; addr < end;){
pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr);
if(!pte_present(*pte) || pte_newpage(*pte)){
......@@ -155,6 +159,7 @@ void mprotect_kernel_vm(int w)
{
struct mm_struct *mm;
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long addr;
......@@ -162,7 +167,8 @@ void mprotect_kernel_vm(int w)
mm = &init_mm;
for(addr = start_vm; addr < end_vm;){
pgd = pgd_offset(mm, addr);
pmd = pmd_offset(pgd, addr);
pud = pud_offset(pgd, addr);
pmd = pmd_offset(pud, addr);
if(pmd_present(*pmd)){
pte = pte_offset_kernel(pmd, addr);
if(pte_present(*pte)) protect_vm_page(addr, w, 0);
......
......@@ -13,12 +13,14 @@
#define pmd_populate_kernel(mm, pmd, pte) \
set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte)))
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
struct page *pte)
{
set_pmd(pmd, __pmd(_PAGE_TABLE + page_to_phys(pte)));
}
#define pmd_populate(mm, pmd, pte) \
set_pmd(pmd, __pmd(_PAGE_TABLE + \
((unsigned long long)page_to_pfn(pte) << \
(unsigned long long) PAGE_SHIFT)))
/*
* Allocate and free page tables.
*/
extern pgd_t *pgd_alloc(struct mm_struct *);
extern void pgd_free(pgd_t *pgd);
......@@ -45,7 +47,7 @@ static inline void pte_free(struct page *pte)
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(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)
......
......@@ -7,8 +7,6 @@
#ifndef __UM_PGTABLE_H
#define __UM_PGTABLE_H
#include <asm-generic/4level-fixup.h>
#include "linux/sched.h"
#include "asm/processor.h"
#include "asm/page.h"
......@@ -23,7 +21,6 @@ extern unsigned long *empty_zero_page;
#define pgtable_cache_init() do ; while (0)
/* 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))
......@@ -39,7 +36,6 @@ extern unsigned long *empty_zero_page;
#define PTRS_PER_PTE 1024
#define PTRS_PER_PMD 1
#define PTRS_PER_PGD 1024
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_PGD_NR 0
#define pte_ERROR(e) \
......@@ -176,6 +172,15 @@ extern pte_t * __bad_pagetable(void);
#define pmd_newpage(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
* 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)
* this macro returns the index of the entry in the pgd page which would
* 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_index() is used get the offset into the pgd page's array of pgd_t's;
*/
#define pgd_offset(mm, address) \
((mm)->pgd + ((address) >> PGDIR_SHIFT))
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/*
* 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)
*/
#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) \
(((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]
*
......@@ -430,6 +435,8 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
#include <asm-generic/pgtable.h>
#include <asm-um/pgtable-nopud.h>
#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