Skip to content

Commit

Permalink
Merge branch 'Rework-sparc32-page-table-layout'
Browse files Browse the repository at this point in the history
Will Deacon says:

====================
Rework sparc32 page-table layout

This is a reposting of the patch series I sent previously to rework the
sparc32 page-table layout so that 'pmd_t' can be used safely with
READ_ONCE():

https://lore.kernel.org/lkml/20200324104005.11279-1-will@kernel.org

This is blocking the READ_ONCE() rework, which in turn allows us to
bump the minimum GCC version for building the kernel up to 4.8.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 13, 2020
2 parents 24085f7 + 8c8f315 commit a012c1e
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 130 deletions.
12 changes: 6 additions & 6 deletions arch/sparc/include/asm/page_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
*/
typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long iopte; } iopte_t;
typedef struct { unsigned long pmdv[16]; } pmd_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long ctxd; } ctxd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
typedef struct { unsigned long iopgprot; } iopgprot_t;

#define pte_val(x) ((x).pte)
#define iopte_val(x) ((x).iopte)
#define pmd_val(x) ((x).pmdv[0])
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define ctxd_val(x) ((x).ctxd)
#define pgprot_val(x) ((x).pgprot)
Expand All @@ -82,22 +82,22 @@ typedef struct { unsigned long iopgprot; } iopgprot_t;
*/
typedef unsigned long pte_t;
typedef unsigned long iopte_t;
typedef struct { unsigned long pmdv[16]; } pmd_t;
typedef unsigned long pmd_t;
typedef unsigned long pgd_t;
typedef unsigned long ctxd_t;
typedef unsigned long pgprot_t;
typedef unsigned long iopgprot_t;

#define pte_val(x) (x)
#define iopte_val(x) (x)
#define pmd_val(x) ((x).pmdv[0])
#define pmd_val(x) (x)
#define pgd_val(x) (x)
#define ctxd_val(x) (x)
#define pgprot_val(x) (x)
#define iopgprot_val(x) (x)

#define __pte(x) (x)
#define __pmd(x) ((pmd_t) { { (x) }, })
#define __pmd(x) (x)
#define __iopte(x) (x)
#define __pgd(x) (x)
#define __ctxd(x) (x)
Expand All @@ -106,7 +106,7 @@ typedef unsigned long iopgprot_t;

#endif

typedef struct page *pgtable_t;
typedef pte_t *pgtable_t;

#define TASK_UNMAPPED_BASE 0x50000000

Expand Down
11 changes: 6 additions & 5 deletions arch/sparc/include/asm/pgalloc_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,24 @@ static inline void free_pmd_fast(pmd_t * pmd)
#define pmd_free(mm, pmd) free_pmd_fast(pmd)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)

void pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep);
#define pmd_pgtable(pmd) pmd_page(pmd)
#define pmd_populate(mm, pmd, pte) pmd_set(pmd, pte)
#define pmd_pgtable(pmd) (pgtable_t)__pmd_page(pmd)

void pmd_set(pmd_t *pmdp, pte_t *ptep);
#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(PMD, PTE)
#define pmd_populate_kernel pmd_populate

pgtable_t pte_alloc_one(struct mm_struct *mm);

static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
{
return srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
return srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE,
SRMMU_PTE_TABLE_SIZE);
}


static inline void free_pte_fast(pte_t *pte)
{
srmmu_free_nocache(pte, PTE_SIZE);
srmmu_free_nocache(pte, SRMMU_PTE_TABLE_SIZE);
}

#define pte_free_kernel(mm, pte) free_pte_fast(pte)
Expand Down
40 changes: 26 additions & 14 deletions arch/sparc/include/asm/pgtable_32.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@

#include <linux/const.h>

#define PMD_SHIFT 18
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK)

#define PGDIR_SHIFT 24
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
#define PGDIR_ALIGN(__addr) (((__addr) + ~PGDIR_MASK) & PGDIR_MASK)

#ifndef __ASSEMBLY__
#include <asm-generic/pgtable-nopud.h>

Expand All @@ -34,17 +44,10 @@ unsigned long __init bootmem_init(unsigned long *pages_avail);
#define pmd_ERROR(e) __builtin_trap()
#define pgd_ERROR(e) __builtin_trap()

#define PMD_SHIFT 22
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK)
#define PGDIR_SHIFT SRMMU_PGDIR_SHIFT
#define PGDIR_SIZE SRMMU_PGDIR_SIZE
#define PGDIR_MASK SRMMU_PGDIR_MASK
#define PTRS_PER_PTE 1024
#define PTRS_PER_PMD SRMMU_PTRS_PER_PMD
#define PTRS_PER_PGD SRMMU_PTRS_PER_PGD
#define USER_PTRS_PER_PGD PAGE_OFFSET / SRMMU_PGDIR_SIZE
#define PTRS_PER_PTE 64
#define PTRS_PER_PMD 64
#define PTRS_PER_PGD 256
#define USER_PTRS_PER_PGD PAGE_OFFSET / PGDIR_SIZE
#define FIRST_USER_ADDRESS 0UL
#define PTE_SIZE (PTRS_PER_PTE*4)

Expand Down Expand Up @@ -132,6 +135,17 @@ static inline struct page *pmd_page(pmd_t pmd)
return pfn_to_page((pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4));
}

static inline unsigned long __pmd_page(pmd_t pmd)
{
unsigned long v;

if (srmmu_device_memory(pmd_val(pmd)))
BUG();

v = pmd_val(pmd) & SRMMU_PTD_PMASK;
return (unsigned long)__nocache_va(v << 4);
}

static inline unsigned long pud_page_vaddr(pud_t pud)
{
if (srmmu_device_memory(pud_val(pud))) {
Expand Down Expand Up @@ -179,9 +193,7 @@ static inline int pmd_none(pmd_t pmd)

static inline void pmd_clear(pmd_t *pmdp)
{
int i;
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
set_pte((pte_t *)&pmd_val(*pmdp), __pte(0));
}

static inline int pud_none(pud_t pud)
Expand Down
36 changes: 3 additions & 33 deletions arch/sparc/include/asm/pgtsrmmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,9 @@
/* Number of contexts is implementation-dependent; 64k is the most we support */
#define SRMMU_MAX_CONTEXTS 65536

/* PMD_SHIFT determines the size of the area a second-level page table entry can map */
#define SRMMU_REAL_PMD_SHIFT 18
#define SRMMU_REAL_PMD_SIZE (1UL << SRMMU_REAL_PMD_SHIFT)
#define SRMMU_REAL_PMD_MASK (~(SRMMU_REAL_PMD_SIZE-1))
#define SRMMU_REAL_PMD_ALIGN(__addr) (((__addr)+SRMMU_REAL_PMD_SIZE-1)&SRMMU_REAL_PMD_MASK)

/* PGDIR_SHIFT determines what a third-level page table entry can map */
#define SRMMU_PGDIR_SHIFT 24
#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT)
#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1))
#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)

#define SRMMU_REAL_PTRS_PER_PTE 64
#define SRMMU_REAL_PTRS_PER_PMD 64
#define SRMMU_PTRS_PER_PGD 256

#define SRMMU_REAL_PTE_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PTE*4)
#define SRMMU_PMD_TABLE_SIZE (SRMMU_REAL_PTRS_PER_PMD*4)
#define SRMMU_PGD_TABLE_SIZE (SRMMU_PTRS_PER_PGD*4)

/*
* To support pagetables in highmem, Linux introduces APIs which
* return struct page* and generally manipulate page tables when
* they are not mapped into kernel space. Our hardware page tables
* are smaller than pages. We lump hardware tabes into big, page sized
* software tables.
*
* PMD_SHIFT determines the size of the area a second-level page table entry
* can map, and our pmd_t is 16 times larger than normal. The values which
* were once defined here are now generic for 4c and srmmu, so they're
* found in pgtable.h.
*/
#define SRMMU_PTRS_PER_PMD 4
#define SRMMU_PTE_TABLE_SIZE (PTRS_PER_PTE*4)
#define SRMMU_PMD_TABLE_SIZE (PTRS_PER_PMD*4)
#define SRMMU_PGD_TABLE_SIZE (PTRS_PER_PGD*4)

/* Definition of the values in the ET field of PTD's and PTE's */
#define SRMMU_ET_MASK 0x3
Expand Down
5 changes: 3 additions & 2 deletions arch/sparc/include/asm/viking.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <asm/asi.h>
#include <asm/mxcc.h>
#include <asm/pgtable.h>
#include <asm/pgtsrmmu.h>

/* Bits in the SRMMU control register for GNU/Viking modules.
Expand Down Expand Up @@ -227,7 +228,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr)
: "=r" (val)
: "r" (vaddr | 0x200), "i" (ASI_M_FLUSH_PROBE));
if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
vaddr &= ~SRMMU_PGDIR_MASK;
vaddr &= ~PGDIR_MASK;
vaddr >>= PAGE_SHIFT;
return val | (vaddr << 8);
}
Expand All @@ -237,7 +238,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr)
: "=r" (val)
: "r" (vaddr | 0x100), "i" (ASI_M_FLUSH_PROBE));
if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
vaddr &= ~SRMMU_REAL_PMD_MASK;
vaddr &= ~PMD_MASK;
vaddr >>= PAGE_SHIFT;
return val | (vaddr << 8);
}
Expand Down
8 changes: 4 additions & 4 deletions arch/sparc/kernel/head_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <asm/winmacro.h>
#include <asm/thread_info.h> /* TI_UWINMASK */
#include <asm/errno.h>
#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */
#include <asm/pgtable.h> /* PGDIR_SHIFT */
#include <asm/export.h>

.data
Expand Down Expand Up @@ -273,7 +273,7 @@ not_a_sun4:
lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd

/* Calculate to KERNBASE entry. */
add %o1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %o3
add %o1, KERNBASE >> (PGDIR_SHIFT - 2), %o3

/* Poke the entry into the calculated address. */
sta %o2, [%o3] ASI_M_BYPASS
Expand Down Expand Up @@ -317,7 +317,7 @@ srmmu_not_viking:
sll %g1, 0x8, %g1 ! make phys addr for l1 tbl

lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0
add %g1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %g3
add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3
sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
b go_to_highmem
nop ! wheee....
Expand All @@ -341,7 +341,7 @@ leon_remap:
sll %g1, 0x8, %g1 ! make phys addr for l1 tbl

lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0
add %g1, KERNBASE >> (SRMMU_PGDIR_SHIFT - 2), %g3
add %g1, KERNBASE >> (PGDIR_SHIFT - 2), %g3
sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
b go_to_highmem
nop ! wheee....
Expand Down
3 changes: 2 additions & 1 deletion arch/sparc/mm/hypersparc.S
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit a012c1e

Please sign in to comment.