Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next
Pull sparc updates from David Miller: - Rework the sparc32 page tables so that READ_ONCE(*pmd), as done by generic code, operates on a word sized element. From Will Deacon. - Some scnprintf() conversions, from Chen Zhou. - A pin_user_pages() conversion from John Hubbard. - Several 32-bit ptrace register handling fixes and such from Al Viro. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next: fix a braino in "sparc32: fix register window handling in genregs32_[gs]et()" sparc32: mm: Only call ctor()/dtor() functions for first and last user sparc32: mm: Disable SPLIT_PTLOCK_CPUS sparc32: mm: Don't try to free page-table pages if ctor() fails sparc32: register memory occupied by kernel as memblock.memory sparc: remove unused header file nfs_fs.h sparc32: fix register window handling in genregs32_[gs]et() sparc64: fix misuses of access_process_vm() in genregs32_[sg]et() oradax: convert get_user_pages() --> pin_user_pages() sparc: use scnprintf() in show_pciobppath_attr() in vio.c sparc: use scnprintf() in show_pciobppath_attr() in pci.c tty: vcc: Fix error return code in vcc_probe() sparc32: mm: Reduce allocation size for PMD and PTE tables sparc32: mm: Change pgtable_t type to pte_t * instead of struct page * sparc32: mm: Restructure sparc32 MMU page-table layout sparc32: mm: Fix argument checking in __srmmu_get_nocache() sparc64: Replace zero-length array with flexible-array sparc: mm: return true,false in kern_addr_valid()
Cette révision appartient à :
@@ -10,6 +10,7 @@
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgtsrmmu.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
@@ -293,7 +294,7 @@ hypersparc_flush_tlb_range:
|
||||
cmp %o3, -1
|
||||
be hypersparc_flush_tlb_range_out
|
||||
#endif
|
||||
sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
|
||||
sethi %hi(~((1 << PGDIR_SHIFT) - 1)), %o4
|
||||
sta %o3, [%g1] ASI_M_MMUREGS
|
||||
and %o1, %o4, %o1
|
||||
add %o1, 0x200, %o1
|
||||
|
@@ -1649,29 +1649,29 @@ bool kern_addr_valid(unsigned long addr)
|
||||
|
||||
pgd = pgd_offset_k(addr);
|
||||
if (pgd_none(*pgd))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
if (p4d_none(*p4d))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
pud = pud_offset(p4d, addr);
|
||||
if (pud_none(*pud))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (pud_large(*pud))
|
||||
return pfn_valid(pud_pfn(*pud));
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
if (pmd_none(*pmd))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (pmd_large(*pmd))
|
||||
return pfn_valid(pmd_pfn(*pmd));
|
||||
|
||||
pte = pte_offset_kernel(pmd, addr);
|
||||
if (pte_none(*pte))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return pfn_valid(pte_pfn(*pte));
|
||||
}
|
||||
|
@@ -136,26 +136,8 @@ static void msi_set_sync(void)
|
||||
|
||||
void pmd_set(pmd_t *pmdp, pte_t *ptep)
|
||||
{
|
||||
unsigned long ptp; /* Physical address, shifted right by 4 */
|
||||
int i;
|
||||
|
||||
ptp = __nocache_pa(ptep) >> 4;
|
||||
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
|
||||
set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
|
||||
ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
|
||||
{
|
||||
unsigned long ptp; /* Physical address, shifted right by 4 */
|
||||
int i;
|
||||
|
||||
ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4); /* watch for overflow */
|
||||
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
|
||||
set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
|
||||
ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
|
||||
}
|
||||
unsigned long ptp = __nocache_pa(ptep) >> 4;
|
||||
set_pte((pte_t *)&pmd_val(*pmdp), __pte(SRMMU_ET_PTD | ptp));
|
||||
}
|
||||
|
||||
/* Find an entry in the third-level page table.. */
|
||||
@@ -163,7 +145,7 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address)
|
||||
{
|
||||
void *pte;
|
||||
|
||||
pte = __nocache_va((dir->pmdv[0] & SRMMU_PTD_PMASK) << 4);
|
||||
pte = __nocache_va((pmd_val(*dir) & SRMMU_PTD_PMASK) << 4);
|
||||
return (pte_t *) pte +
|
||||
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
|
||||
}
|
||||
@@ -175,18 +157,18 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address)
|
||||
*/
|
||||
static void *__srmmu_get_nocache(int size, int align)
|
||||
{
|
||||
int offset;
|
||||
int offset, minsz = 1 << SRMMU_NOCACHE_BITMAP_SHIFT;
|
||||
unsigned long addr;
|
||||
|
||||
if (size < SRMMU_NOCACHE_BITMAP_SHIFT) {
|
||||
if (size < minsz) {
|
||||
printk(KERN_ERR "Size 0x%x too small for nocache request\n",
|
||||
size);
|
||||
size = SRMMU_NOCACHE_BITMAP_SHIFT;
|
||||
size = minsz;
|
||||
}
|
||||
if (size & (SRMMU_NOCACHE_BITMAP_SHIFT - 1)) {
|
||||
printk(KERN_ERR "Size 0x%x unaligned int nocache request\n",
|
||||
if (size & (minsz - 1)) {
|
||||
printk(KERN_ERR "Size 0x%x unaligned in nocache request\n",
|
||||
size);
|
||||
size += SRMMU_NOCACHE_BITMAP_SHIFT - 1;
|
||||
size += minsz - 1;
|
||||
}
|
||||
BUG_ON(align > SRMMU_NOCACHE_ALIGN_MAX);
|
||||
|
||||
@@ -376,31 +358,33 @@ pgd_t *get_pgd_fast(void)
|
||||
*/
|
||||
pgtable_t pte_alloc_one(struct mm_struct *mm)
|
||||
{
|
||||
unsigned long pte;
|
||||
pte_t *ptep;
|
||||
struct page *page;
|
||||
|
||||
if ((pte = (unsigned long)pte_alloc_one_kernel(mm)) == 0)
|
||||
return NULL;
|
||||
page = pfn_to_page(__nocache_pa(pte) >> PAGE_SHIFT);
|
||||
if (!pgtable_pte_page_ctor(page)) {
|
||||
__free_page(page);
|
||||
if ((ptep = pte_alloc_one_kernel(mm)) == 0)
|
||||
return NULL;
|
||||
page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT);
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (page_ref_inc_return(page) == 2 && !pgtable_pte_page_ctor(page)) {
|
||||
page_ref_dec(page);
|
||||
ptep = NULL;
|
||||
}
|
||||
return page;
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
return ptep;
|
||||
}
|
||||
|
||||
void pte_free(struct mm_struct *mm, pgtable_t pte)
|
||||
void pte_free(struct mm_struct *mm, pgtable_t ptep)
|
||||
{
|
||||
unsigned long p;
|
||||
struct page *page;
|
||||
|
||||
pgtable_pte_page_dtor(pte);
|
||||
p = (unsigned long)page_address(pte); /* Cached address (for test) */
|
||||
if (p == 0)
|
||||
BUG();
|
||||
p = page_to_pfn(pte) << PAGE_SHIFT; /* Physical address */
|
||||
page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT);
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (page_ref_dec_return(page) == 1)
|
||||
pgtable_pte_page_dtor(page);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
/* free non cached virtual address*/
|
||||
srmmu_free_nocache(__nocache_va(p), PTE_SIZE);
|
||||
srmmu_free_nocache(ptep, SRMMU_PTE_TABLE_SIZE);
|
||||
}
|
||||
|
||||
/* context handling - a dynamically sized pool is used */
|
||||
@@ -822,13 +806,13 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||
what = 0;
|
||||
addr = start - PAGE_SIZE;
|
||||
|
||||
if (!(start & ~(SRMMU_REAL_PMD_MASK))) {
|
||||
if (srmmu_probe(addr + SRMMU_REAL_PMD_SIZE) == probed)
|
||||
if (!(start & ~(PMD_MASK))) {
|
||||
if (srmmu_probe(addr + PMD_SIZE) == probed)
|
||||
what = 1;
|
||||
}
|
||||
|
||||
if (!(start & ~(SRMMU_PGDIR_MASK))) {
|
||||
if (srmmu_probe(addr + SRMMU_PGDIR_SIZE) == probed)
|
||||
if (!(start & ~(PGDIR_MASK))) {
|
||||
if (srmmu_probe(addr + PGDIR_SIZE) == probed)
|
||||
what = 2;
|
||||
}
|
||||
|
||||
@@ -837,7 +821,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||
pudp = pud_offset(p4dp, start);
|
||||
if (what == 2) {
|
||||
*(pgd_t *)__nocache_fix(pgdp) = __pgd(probed);
|
||||
start += SRMMU_PGDIR_SIZE;
|
||||
start += PGDIR_SIZE;
|
||||
continue;
|
||||
}
|
||||
if (pud_none(*(pud_t *)__nocache_fix(pudp))) {
|
||||
@@ -849,6 +833,11 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||
pud_set(__nocache_fix(pudp), pmdp);
|
||||
}
|
||||
pmdp = pmd_offset(__nocache_fix(pgdp), start);
|
||||
if (what == 1) {
|
||||
*(pmd_t *)__nocache_fix(pmdp) = __pmd(probed);
|
||||
start += PMD_SIZE;
|
||||
continue;
|
||||
}
|
||||
if (srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
|
||||
ptep = __srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
|
||||
if (ptep == NULL)
|
||||
@@ -856,19 +845,6 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
|
||||
memset(__nocache_fix(ptep), 0, PTE_SIZE);
|
||||
pmd_set(__nocache_fix(pmdp), ptep);
|
||||
}
|
||||
if (what == 1) {
|
||||
/* We bend the rule where all 16 PTPs in a pmd_t point
|
||||
* inside the same PTE page, and we leak a perfectly
|
||||
* good hardware PTE piece. Alternatives seem worse.
|
||||
*/
|
||||
unsigned int x; /* Index of HW PMD in soft cluster */
|
||||
unsigned long *val;
|
||||
x = (start >> PMD_SHIFT) & 15;
|
||||
val = &pmdp->pmdv[x];
|
||||
*(unsigned long *)__nocache_fix(val) = probed;
|
||||
start += SRMMU_REAL_PMD_SIZE;
|
||||
continue;
|
||||
}
|
||||
ptep = pte_offset_kernel(__nocache_fix(pmdp), start);
|
||||
*(pte_t *)__nocache_fix(ptep) = __pte(probed);
|
||||
start += PAGE_SIZE;
|
||||
@@ -890,9 +866,9 @@ static void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base
|
||||
/* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. */
|
||||
static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
|
||||
{
|
||||
unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK);
|
||||
unsigned long vstart = (vbase & SRMMU_PGDIR_MASK);
|
||||
unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes);
|
||||
unsigned long pstart = (sp_banks[sp_entry].base_addr & PGDIR_MASK);
|
||||
unsigned long vstart = (vbase & PGDIR_MASK);
|
||||
unsigned long vend = PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes);
|
||||
/* Map "low" memory only */
|
||||
const unsigned long min_vaddr = PAGE_OFFSET;
|
||||
const unsigned long max_vaddr = PAGE_OFFSET + SRMMU_MAXMEM;
|
||||
@@ -905,7 +881,7 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
|
||||
|
||||
while (vstart < vend) {
|
||||
do_large_mapping(vstart, pstart);
|
||||
vstart += SRMMU_PGDIR_SIZE; pstart += SRMMU_PGDIR_SIZE;
|
||||
vstart += PGDIR_SIZE; pstart += PGDIR_SIZE;
|
||||
}
|
||||
return vstart;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <asm/asi.h>
|
||||
#include <asm/mxcc.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgtsrmmu.h>
|
||||
#include <asm/viking.h>
|
||||
|
||||
@@ -157,7 +158,7 @@ viking_flush_tlb_range:
|
||||
cmp %o3, -1
|
||||
be 2f
|
||||
#endif
|
||||
sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
|
||||
sethi %hi(~((1 << PGDIR_SHIFT) - 1)), %o4
|
||||
sta %o3, [%g1] ASI_M_MMUREGS
|
||||
and %o1, %o4, %o1
|
||||
add %o1, 0x200, %o1
|
||||
@@ -243,7 +244,7 @@ sun4dsmp_flush_tlb_range:
|
||||
ld [%o0 + VMA_VM_MM], %o0
|
||||
ld [%o0 + AOFF_mm_context], %o3
|
||||
lda [%g1] ASI_M_MMUREGS, %g5
|
||||
sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4
|
||||
sethi %hi(~((1 << PGDIR_SHIFT) - 1)), %o4
|
||||
sta %o3, [%g1] ASI_M_MMUREGS
|
||||
and %o1, %o4, %o1
|
||||
add %o1, 0x200, %o1
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur