Skip to content

Commit

Permalink
sh: Generalise the pte handling code for the fixmap path
Browse files Browse the repository at this point in the history
Generalise the code for setting and clearing pte's and allow TLB entries
to be pinned and unpinned if the _PAGE_WIRED flag is present.

Signed-off-by: Matt Fleming <matt@console-pimps.org>
  • Loading branch information
Matt Fleming committed Jan 16, 2010
1 parent 24ef7fc commit 07cad4d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
1 change: 1 addition & 0 deletions arch/sh/include/asm/fixmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ enum fixed_addresses {

extern void __set_fixmap(enum fixed_addresses idx,
unsigned long phys, pgprot_t flags);
extern void __clear_fixmap(enum fixed_addresses idx, pgprot_t flags);

#define set_fixmap(idx, phys) \
__set_fixmap(idx, phys, PAGE_KERNEL)
Expand Down
44 changes: 40 additions & 4 deletions arch/sh/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ unsigned long cached_to_uncached = P2SEG - P1SEG;
#endif

#ifdef CONFIG_MMU
static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
static pte_t *__get_pte_phys(unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
Expand All @@ -49,29 +49,53 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) {
pgd_ERROR(*pgd);
return;
return NULL;
}

pud = pud_alloc(NULL, pgd, addr);
if (unlikely(!pud)) {
pud_ERROR(*pud);
return;
return NULL;
}

pmd = pmd_alloc(NULL, pud, addr);
if (unlikely(!pmd)) {
pmd_ERROR(*pmd);
return;
return NULL;
}

pte = pte_offset_kernel(pmd, addr);
return pte;
}

static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
{
pte_t *pte;

pte = __get_pte_phys(addr);
if (!pte_none(*pte)) {
pte_ERROR(*pte);
return;
}

set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
local_flush_tlb_one(get_asid(), addr);

if (pgprot_val(prot) & _PAGE_WIRED)
tlb_wire_entry(NULL, addr, *pte);
}

static void clear_pte_phys(unsigned long addr, pgprot_t prot)
{
pte_t *pte;

pte = __get_pte_phys(addr);

if (pgprot_val(prot) & _PAGE_WIRED)
tlb_unwire_entry();

set_pte(pte, pfn_pte(0, __pgprot(0)));
local_flush_tlb_one(get_asid(), addr);
}

/*
Expand Down Expand Up @@ -101,6 +125,18 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
set_pte_phys(address, phys, prot);
}

void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
{
unsigned long address = __fix_to_virt(idx);

if (idx >= __end_of_fixed_addresses) {
BUG();
return;
}

clear_pte_phys(address, prot);
}

void __init page_table_range_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
Expand Down

0 comments on commit 07cad4d

Please sign in to comment.