提交 07cad4dc 编写于 作者: M Matt Fleming

sh: Generalise the pte handling code for the fixmap path

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: NMatt Fleming <matt@console-pimps.org>
上级 24ef7fc4
...@@ -65,6 +65,7 @@ enum fixed_addresses { ...@@ -65,6 +65,7 @@ enum fixed_addresses {
extern void __set_fixmap(enum fixed_addresses idx, extern void __set_fixmap(enum fixed_addresses idx,
unsigned long phys, pgprot_t flags); unsigned long phys, pgprot_t flags);
extern void __clear_fixmap(enum fixed_addresses idx, pgprot_t flags);
#define set_fixmap(idx, phys) \ #define set_fixmap(idx, phys) \
__set_fixmap(idx, phys, PAGE_KERNEL) __set_fixmap(idx, phys, PAGE_KERNEL)
......
...@@ -39,7 +39,7 @@ unsigned long cached_to_uncached = P2SEG - P1SEG; ...@@ -39,7 +39,7 @@ unsigned long cached_to_uncached = P2SEG - P1SEG;
#endif #endif
#ifdef CONFIG_MMU #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; pgd_t *pgd;
pud_t *pud; pud_t *pud;
...@@ -49,22 +49,30 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) ...@@ -49,22 +49,30 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
pgd = pgd_offset_k(addr); pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) { if (pgd_none(*pgd)) {
pgd_ERROR(*pgd); pgd_ERROR(*pgd);
return; return NULL;
} }
pud = pud_alloc(NULL, pgd, addr); pud = pud_alloc(NULL, pgd, addr);
if (unlikely(!pud)) { if (unlikely(!pud)) {
pud_ERROR(*pud); pud_ERROR(*pud);
return; return NULL;
} }
pmd = pmd_alloc(NULL, pud, addr); pmd = pmd_alloc(NULL, pud, addr);
if (unlikely(!pmd)) { if (unlikely(!pmd)) {
pmd_ERROR(*pmd); pmd_ERROR(*pmd);
return; return NULL;
} }
pte = pte_offset_kernel(pmd, addr); 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)) { if (!pte_none(*pte)) {
pte_ERROR(*pte); pte_ERROR(*pte);
return; return;
...@@ -72,6 +80,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) ...@@ -72,6 +80,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
local_flush_tlb_one(get_asid(), addr); 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);
} }
/* /*
...@@ -101,6 +125,18 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) ...@@ -101,6 +125,18 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
set_pte_phys(address, phys, 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, void __init page_table_range_init(unsigned long start, unsigned long end,
pgd_t *pgd_base) pgd_t *pgd_base)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册