Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 42590
b: refs/heads/master
c: 99a596f
h: refs/heads/master
v: v3
  • Loading branch information
Stuart Menefy authored and Paul Mundt committed Dec 6, 2006
1 parent 573ba4c commit a43ae1e
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 49 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6e4662ff49c6b94e16a47bfddb920576963b5a20
refs/heads/master: 99a596f93be10001c50894bcab69e458a49a3b8c
40 changes: 40 additions & 0 deletions trunk/arch/sh/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,45 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
mm = tsk->mm;
si_code = SEGV_MAPERR;

if (unlikely(address >= TASK_SIZE)) {
/*
* Synchronize this task's top level page-table
* with the 'reference' page table.
*
* Do _not_ use "tsk" here. We might be inside
* an interrupt in the middle of a task switch..
*/
int offset = pgd_index(address);
pgd_t *pgd, *pgd_k;
pud_t *pud, *pud_k;
pmd_t *pmd, *pmd_k;

pgd = get_TTB() + offset;
pgd_k = swapper_pg_dir + offset;

/* This will never happen with the folded page table. */
if (!pgd_present(*pgd)) {
if (!pgd_present(*pgd_k))
goto bad_area_nosemaphore;
set_pgd(pgd, *pgd_k);
return;
}

pud = pud_offset(pgd, address);
pud_k = pud_offset(pgd_k, address);
if (pud_present(*pud) || !pud_present(*pud_k))
goto bad_area_nosemaphore;
set_pud(pud, *pud_k);

pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
if (pmd_present(*pmd) || !pmd_present(*pmd_k))
goto bad_area_nosemaphore;
set_pmd(pmd, *pmd_k);

return;
}

/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
Expand Down Expand Up @@ -109,6 +148,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
bad_area:
up_read(&mm->mmap_sem);

bad_area_nosemaphore:
if (user_mode(regs)) {
info.si_signo = SIGSEGV;
info.si_errno = 0;
Expand Down
26 changes: 9 additions & 17 deletions trunk/arch/sh/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
pmd_t *pmd;
pte_t *pte;

pgd = swapper_pg_dir + pgd_index(addr);
pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) {
pgd_ERROR(*pgd);
return;
}

pud = pud_offset(pgd, addr);
if (pud_none(*pud)) {
pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
set_pud(pud, __pud(__pa(pmd) | _PAGE_TABLE));
if (pmd != pmd_offset(pud, 0)) {
pud_ERROR(*pud);
return;
}
pud = pud_alloc(NULL, pgd, addr);
if (unlikely(!pud)) {
pud_ERROR(*pud);
return;
}

pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) {
pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE));
if (pte != pte_offset_kernel(pmd, 0)) {
pmd_ERROR(*pmd);
return;
}
pmd = pmd_alloc(NULL, pud, addr);
if (unlikely(!pmd)) {
pmd_ERROR(*pmd);
return;
}

pte = pte_offset_kernel(pmd, addr);
Expand Down
20 changes: 16 additions & 4 deletions trunk/include/asm-sh/pgalloc.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
#ifndef __ASM_SH_PGALLOC_H
#define __ASM_SH_PGALLOC_H

#define pmd_populate_kernel(mm, pmd, pte) \
set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
pte_t *pte)
{
set_pmd(pmd, __pmd((unsigned long)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)));
set_pmd(pmd, __pmd((unsigned long)page_address(pte)));
}

/*
* Allocate and free page tables.
*/
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);

if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
memcpy(pgd + USER_PTRS_PER_PGD,
swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}

return pgd;
}

static inline void pgd_free(pgd_t *pgd)
Expand Down
38 changes: 11 additions & 27 deletions trunk/include/asm-sh/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,26 +203,18 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#ifndef __ASSEMBLY__

#if defined(CONFIG_X2TLB) /* SH-X2 TLB */
#define _PAGE_TABLE \
(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | \
_PAGE_EXT(_PAGE_EXT_USER_READ | _PAGE_EXT_USER_WRITE))

#define _KERNPG_TABLE \
(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | \
_PAGE_EXT(_PAGE_EXT_KERN_READ | _PAGE_EXT_KERN_WRITE))

#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \
_PAGE_ACCESSED | _PAGE_FLAGS_HARD)

#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
_PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_USER_READ | \
_PAGE_EXT_USER_WRITE))
_PAGE_EXT_USER_WRITE))

#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
_PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_USER_EXEC | \
_PAGE_EXT_USER_READ))
_PAGE_EXT_USER_READ))

#define PAGE_COPY PAGE_EXECREAD

Expand All @@ -237,45 +229,40 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
_PAGE_CACHABLE | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_USER_WRITE | \
_PAGE_EXT_USER_READ | \
_PAGE_EXT_USER_READ | \
_PAGE_EXT_USER_EXEC))

#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \
_PAGE_DIRTY | _PAGE_ACCESSED | \
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_KERN_READ | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_EXEC))

#define PAGE_KERNEL_NOCACHE \
__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \
_PAGE_ACCESSED | _PAGE_HW_SHARED | \
_PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_KERN_READ | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_EXEC))

#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \
_PAGE_DIRTY | _PAGE_ACCESSED | \
_PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_KERN_READ | \
_PAGE_EXT_KERN_EXEC))
_PAGE_EXT_KERN_EXEC))

#define PAGE_KERNEL_PCC(slot, type) \
__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \
_PAGE_ACCESSED | _PAGE_FLAGS_HARD | \
_PAGE_EXT(_PAGE_EXT_KERN_READ | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_WRITE | \
_PAGE_EXT_KERN_EXEC) \
(slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \
(type))

#elif defined(CONFIG_MMU) /* SH-X TLB */
#define _PAGE_TABLE \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
#define _KERNPG_TABLE \
(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)

#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \
_PAGE_ACCESSED | _PAGE_FLAGS_HARD)

Expand Down Expand Up @@ -390,9 +377,9 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)

#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
#define pmd_present(x) (pmd_val(x))
#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK)

#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
#define pte_page(x) phys_to_page(pte_val(x)&PTE_PHYS_MASK)
Expand Down Expand Up @@ -477,11 +464,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
return pte;
}

#define pmd_page_vaddr(pmd) \
((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))

#define pmd_page(pmd) \
(phys_to_page(pmd_val(pmd)))
#define pmd_page_vaddr(pmd) pmd_val(pmd)
#define pmd_page(pmd) (virt_to_page(pmd_val(pmd)))

/* to find an entry in a page-table-directory. */
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
Expand Down

0 comments on commit a43ae1e

Please sign in to comment.