Commit 52e0ad26 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents cf0c97f1 4f8ad738
...@@ -54,7 +54,7 @@ extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1]; ...@@ -54,7 +54,7 @@ extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
*/ */
typedef struct { unsigned long pte; } pte_t; typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long iopte; } iopte_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 pgd; } pgd_t;
typedef struct { unsigned long ctxd; } ctxd_t; typedef struct { unsigned long ctxd; } ctxd_t;
typedef struct { unsigned long pgprot; } pgprot_t; typedef struct { unsigned long pgprot; } pgprot_t;
...@@ -62,7 +62,7 @@ typedef struct { unsigned long iopgprot; } iopgprot_t; ...@@ -62,7 +62,7 @@ typedef struct { unsigned long iopgprot; } iopgprot_t;
#define pte_val(x) ((x).pte) #define pte_val(x) ((x).pte)
#define iopte_val(x) ((x).iopte) #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 pgd_val(x) ((x).pgd)
#define ctxd_val(x) ((x).ctxd) #define ctxd_val(x) ((x).ctxd)
#define pgprot_val(x) ((x).pgprot) #define pgprot_val(x) ((x).pgprot)
...@@ -82,7 +82,7 @@ typedef struct { unsigned long iopgprot; } iopgprot_t; ...@@ -82,7 +82,7 @@ typedef struct { unsigned long iopgprot; } iopgprot_t;
*/ */
typedef unsigned long pte_t; typedef unsigned long pte_t;
typedef unsigned long iopte_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 pgd_t;
typedef unsigned long ctxd_t; typedef unsigned long ctxd_t;
typedef unsigned long pgprot_t; typedef unsigned long pgprot_t;
...@@ -90,14 +90,14 @@ typedef unsigned long iopgprot_t; ...@@ -90,14 +90,14 @@ typedef unsigned long iopgprot_t;
#define pte_val(x) (x) #define pte_val(x) (x)
#define iopte_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 pgd_val(x) (x)
#define ctxd_val(x) (x) #define ctxd_val(x) (x)
#define pgprot_val(x) (x) #define pgprot_val(x) (x)
#define iopgprot_val(x) (x) #define iopgprot_val(x) (x)
#define __pte(x) (x) #define __pte(x) (x)
#define __pmd(x) ((pmd_t) { { (x) }, }) #define __pmd(x) (x)
#define __iopte(x) (x) #define __iopte(x) (x)
#define __pgd(x) (x) #define __pgd(x) (x)
#define __ctxd(x) (x) #define __ctxd(x) (x)
...@@ -106,7 +106,7 @@ typedef unsigned long iopgprot_t; ...@@ -106,7 +106,7 @@ typedef unsigned long iopgprot_t;
#endif #endif
typedef struct page *pgtable_t; typedef pte_t *pgtable_t;
#define TASK_UNMAPPED_BASE 0x50000000 #define TASK_UNMAPPED_BASE 0x50000000
......
...@@ -50,23 +50,24 @@ static inline void free_pmd_fast(pmd_t * pmd) ...@@ -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(mm, pmd) free_pmd_fast(pmd)
#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, 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_populate(mm, pmd, pte) pmd_set(pmd, pte)
#define pmd_pgtable(pmd) pmd_page(pmd) #define pmd_pgtable(pmd) (pgtable_t)__pmd_page(pmd)
void pmd_set(pmd_t *pmdp, pte_t *ptep); 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); pgtable_t pte_alloc_one(struct mm_struct *mm);
static inline pte_t *pte_alloc_one_kernel(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) 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) #define pte_free_kernel(mm, pte) free_pte_fast(pte)
......
...@@ -11,6 +11,16 @@ ...@@ -11,6 +11,16 @@
#include <linux/const.h> #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__ #ifndef __ASSEMBLY__
#include <asm-generic/pgtable-nopud.h> #include <asm-generic/pgtable-nopud.h>
...@@ -34,17 +44,10 @@ unsigned long __init bootmem_init(unsigned long *pages_avail); ...@@ -34,17 +44,10 @@ unsigned long __init bootmem_init(unsigned long *pages_avail);
#define pmd_ERROR(e) __builtin_trap() #define pmd_ERROR(e) __builtin_trap()
#define pgd_ERROR(e) __builtin_trap() #define pgd_ERROR(e) __builtin_trap()
#define PMD_SHIFT 22 #define PTRS_PER_PTE 64
#define PMD_SIZE (1UL << PMD_SHIFT) #define PTRS_PER_PMD 64
#define PMD_MASK (~(PMD_SIZE-1)) #define PTRS_PER_PGD 256
#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK) #define USER_PTRS_PER_PGD PAGE_OFFSET / PGDIR_SIZE
#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 FIRST_USER_ADDRESS 0UL #define FIRST_USER_ADDRESS 0UL
#define PTE_SIZE (PTRS_PER_PTE*4) #define PTE_SIZE (PTRS_PER_PTE*4)
...@@ -132,6 +135,17 @@ static inline struct page *pmd_page(pmd_t pmd) ...@@ -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)); 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) static inline unsigned long pud_page_vaddr(pud_t pud)
{ {
if (srmmu_device_memory(pud_val(pud))) { if (srmmu_device_memory(pud_val(pud))) {
...@@ -179,9 +193,7 @@ static inline int pmd_none(pmd_t pmd) ...@@ -179,9 +193,7 @@ static inline int pmd_none(pmd_t pmd)
static inline void pmd_clear(pmd_t *pmdp) static inline void pmd_clear(pmd_t *pmdp)
{ {
int i; set_pte((pte_t *)&pmd_val(*pmdp), __pte(0));
for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++)
set_pte((pte_t *)&pmdp->pmdv[i], __pte(0));
} }
static inline int pud_none(pud_t pud) static inline int pud_none(pud_t pud)
......
...@@ -17,39 +17,9 @@ ...@@ -17,39 +17,9 @@
/* Number of contexts is implementation-dependent; 64k is the most we support */ /* Number of contexts is implementation-dependent; 64k is the most we support */
#define SRMMU_MAX_CONTEXTS 65536 #define SRMMU_MAX_CONTEXTS 65536
/* PMD_SHIFT determines the size of the area a second-level page table entry can map */ #define SRMMU_PTE_TABLE_SIZE (PTRS_PER_PTE*4)
#define SRMMU_REAL_PMD_SHIFT 18 #define SRMMU_PMD_TABLE_SIZE (PTRS_PER_PMD*4)
#define SRMMU_REAL_PMD_SIZE (1UL << SRMMU_REAL_PMD_SHIFT) #define SRMMU_PGD_TABLE_SIZE (PTRS_PER_PGD*4)
#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
/* Definition of the values in the ET field of PTD's and PTE's */ /* Definition of the values in the ET field of PTD's and PTE's */
#define SRMMU_ET_MASK 0x3 #define SRMMU_ET_MASK 0x3
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/mxcc.h> #include <asm/mxcc.h>
#include <asm/pgtable.h>
#include <asm/pgtsrmmu.h> #include <asm/pgtsrmmu.h>
/* Bits in the SRMMU control register for GNU/Viking modules. /* Bits in the SRMMU control register for GNU/Viking modules.
...@@ -227,7 +228,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr) ...@@ -227,7 +228,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr)
: "=r" (val) : "=r" (val)
: "r" (vaddr | 0x200), "i" (ASI_M_FLUSH_PROBE)); : "r" (vaddr | 0x200), "i" (ASI_M_FLUSH_PROBE));
if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) { if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
vaddr &= ~SRMMU_PGDIR_MASK; vaddr &= ~PGDIR_MASK;
vaddr >>= PAGE_SHIFT; vaddr >>= PAGE_SHIFT;
return val | (vaddr << 8); return val | (vaddr << 8);
} }
...@@ -237,7 +238,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr) ...@@ -237,7 +238,7 @@ static inline unsigned long viking_hwprobe(unsigned long vaddr)
: "=r" (val) : "=r" (val)
: "r" (vaddr | 0x100), "i" (ASI_M_FLUSH_PROBE)); : "r" (vaddr | 0x100), "i" (ASI_M_FLUSH_PROBE));
if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) { if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
vaddr &= ~SRMMU_REAL_PMD_MASK; vaddr &= ~PMD_MASK;
vaddr >>= PAGE_SHIFT; vaddr >>= PAGE_SHIFT;
return val | (vaddr << 8); return val | (vaddr << 8);
} }
......
...@@ -50,7 +50,7 @@ struct cpuinfo_tree { ...@@ -50,7 +50,7 @@ struct cpuinfo_tree {
/* Offsets into nodes[] for each level of the tree */ /* Offsets into nodes[] for each level of the tree */
struct cpuinfo_level level[CPUINFO_LVL_MAX]; struct cpuinfo_level level[CPUINFO_LVL_MAX];
struct cpuinfo_node nodes[0]; struct cpuinfo_node nodes[];
}; };
......
...@@ -87,7 +87,7 @@ struct ds_reg_req { ...@@ -87,7 +87,7 @@ struct ds_reg_req {
__u64 handle; __u64 handle;
__u16 major; __u16 major;
__u16 minor; __u16 minor;
char svc_id[0]; char svc_id[];
}; };
struct ds_reg_ack { struct ds_reg_ack {
...@@ -701,12 +701,12 @@ struct ds_var_hdr { ...@@ -701,12 +701,12 @@ struct ds_var_hdr {
struct ds_var_set_msg { struct ds_var_set_msg {
struct ds_var_hdr hdr; struct ds_var_hdr hdr;
char name_and_value[0]; char name_and_value[];
}; };
struct ds_var_delete_msg { struct ds_var_delete_msg {
struct ds_var_hdr hdr; struct ds_var_hdr hdr;
char name[0]; char name[];
}; };
struct ds_var_resp { struct ds_var_resp {
...@@ -989,7 +989,7 @@ struct ds_queue_entry { ...@@ -989,7 +989,7 @@ struct ds_queue_entry {
struct ds_info *dp; struct ds_info *dp;
int req_len; int req_len;
int __pad; int __pad;
u64 req[0]; u64 req[];
}; };
static void process_ds_work(void) static void process_ds_work(void)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include <asm/winmacro.h> #include <asm/winmacro.h>
#include <asm/thread_info.h> /* TI_UWINMASK */ #include <asm/thread_info.h> /* TI_UWINMASK */
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/pgtsrmmu.h> /* SRMMU_PGDIR_SHIFT */ #include <asm/pgtable.h> /* PGDIR_SHIFT */
#include <asm/export.h> #include <asm/export.h>
.data .data
...@@ -273,7 +273,7 @@ not_a_sun4: ...@@ -273,7 +273,7 @@ not_a_sun4:
lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd lda [%o1] ASI_M_BYPASS, %o2 ! This is the 0x0 16MB pgd
/* Calculate to KERNBASE entry. */ /* 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. */ /* Poke the entry into the calculated address. */
sta %o2, [%o3] ASI_M_BYPASS sta %o2, [%o3] ASI_M_BYPASS
...@@ -317,7 +317,7 @@ srmmu_not_viking: ...@@ -317,7 +317,7 @@ srmmu_not_viking:
sll %g1, 0x8, %g1 ! make phys addr for l1 tbl sll %g1, 0x8, %g1 ! make phys addr for l1 tbl
lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0 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 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
b go_to_highmem b go_to_highmem
nop ! wheee.... nop ! wheee....
...@@ -341,7 +341,7 @@ leon_remap: ...@@ -341,7 +341,7 @@ leon_remap:
sll %g1, 0x8, %g1 ! make phys addr for l1 tbl sll %g1, 0x8, %g1 ! make phys addr for l1 tbl
lda [%g1] ASI_M_BYPASS, %g2 ! get level1 entry for 0x0 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 sta %g2, [%g3] ASI_M_BYPASS ! place at KERNBASE entry
b go_to_highmem b go_to_highmem
nop ! wheee.... nop ! wheee....
......
...@@ -593,7 +593,7 @@ show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * ...@@ -593,7 +593,7 @@ show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char *
pdev = to_pci_dev(dev); pdev = to_pci_dev(dev);
dp = pdev->dev.of_node; dp = pdev->dev.of_node;
return snprintf (buf, PAGE_SIZE, "%pOF\n", dp); return scnprintf(buf, PAGE_SIZE, "%pOF\n", dp);
} }
static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL);
......
...@@ -46,82 +46,79 @@ enum sparc_regset { ...@@ -46,82 +46,79 @@ enum sparc_regset {
REGSET_FP, REGSET_FP,
}; };
static int regwindow32_get(struct task_struct *target,
const struct pt_regs *regs,
u32 *uregs)
{
unsigned long reg_window = regs->u_regs[UREG_I6];
int size = 16 * sizeof(u32);
if (target == current) {
if (copy_from_user(uregs, (void __user *)reg_window, size))
return -EFAULT;
} else {
if (access_process_vm(target, reg_window, uregs, size,
FOLL_FORCE) != size)
return -EFAULT;
}
return 0;
}
static int regwindow32_set(struct task_struct *target,
const struct pt_regs *regs,
u32 *uregs)
{
unsigned long reg_window = regs->u_regs[UREG_I6];
int size = 16 * sizeof(u32);
if (target == current) {
if (copy_to_user((void __user *)reg_window, uregs, size))
return -EFAULT;
} else {
if (access_process_vm(target, reg_window, uregs, size,
FOLL_FORCE | FOLL_WRITE) != size)
return -EFAULT;
}
return 0;
}
static int genregs32_get(struct task_struct *target, static int genregs32_get(struct task_struct *target,
const struct user_regset *regset, const struct user_regset *regset,
unsigned int pos, unsigned int count, unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf) void *kbuf, void __user *ubuf)
{ {
const struct pt_regs *regs = target->thread.kregs; const struct pt_regs *regs = target->thread.kregs;
unsigned long __user *reg_window; u32 uregs[16];
unsigned long *k = kbuf; int ret;
unsigned long __user *u = ubuf;
unsigned long reg;
if (target == current) if (target == current)
flush_user_windows(); flush_user_windows();
pos /= sizeof(reg); ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
count /= sizeof(reg); regs->u_regs,
0, 16 * sizeof(u32));
if (kbuf) { if (ret || !count)
for (; count > 0 && pos < 16; count--) return ret;
*k++ = regs->u_regs[pos++];
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
reg_window -= 16;
for (; count > 0 && pos < 32; count--) {
if (get_user(*k++, &reg_window[pos++]))
return -EFAULT;
}
} else {
for (; count > 0 && pos < 16; count--) {
if (put_user(regs->u_regs[pos++], u++))
return -EFAULT;
}
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
reg_window -= 16;
for (; count > 0 && pos < 32; count--) {
if (get_user(reg, &reg_window[pos++]) ||
put_user(reg, u++))
return -EFAULT;
}
}
while (count > 0) {
switch (pos) {
case 32: /* PSR */
reg = regs->psr;
break;
case 33: /* PC */
reg = regs->pc;
break;
case 34: /* NPC */
reg = regs->npc;
break;
case 35: /* Y */
reg = regs->y;
break;
case 36: /* WIM */
case 37: /* TBR */
reg = 0;
break;
default:
goto finish;
}
if (kbuf) if (pos < 32 * sizeof(u32)) {
*k++ = reg; if (regwindow32_get(target, regs, uregs))
else if (put_user(reg, u++))
return -EFAULT; return -EFAULT;
pos++; ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
count--; uregs,
16 * sizeof(u32), 32 * sizeof(u32));
if (ret || !count)
return ret;
} }
finish:
pos *= sizeof(reg);
count *= sizeof(reg);
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, uregs[0] = regs->psr;
38 * sizeof(reg), -1); uregs[1] = regs->pc;
uregs[2] = regs->npc;
uregs[3] = regs->y;
uregs[4] = 0; /* WIM */
uregs[5] = 0; /* TBR */
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
uregs,
32 * sizeof(u32), 38 * sizeof(u32));
} }
static int genregs32_set(struct task_struct *target, static int genregs32_set(struct task_struct *target,
...@@ -130,82 +127,58 @@ static int genregs32_set(struct task_struct *target, ...@@ -130,82 +127,58 @@ static int genregs32_set(struct task_struct *target,
const void *kbuf, const void __user *ubuf) const void *kbuf, const void __user *ubuf)
{ {
struct pt_regs *regs = target->thread.kregs; struct pt_regs *regs = target->thread.kregs;
unsigned long __user *reg_window; u32 uregs[16];
const unsigned long *k = kbuf; u32 psr;
const unsigned long __user *u = ubuf; int ret;
unsigned long reg;
if (target == current) if (target == current)
flush_user_windows(); flush_user_windows();
pos /= sizeof(reg); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
count /= sizeof(reg); regs->u_regs,
0, 16 * sizeof(u32));
if (kbuf) { if (ret || !count)
for (; count > 0 && pos < 16; count--) return ret;
regs->u_regs[pos++] = *k++;
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
reg_window -= 16;
for (; count > 0 && pos < 32; count--) {
if (put_user(*k++, &reg_window[pos++]))
return -EFAULT;
}
} else {
for (; count > 0 && pos < 16; count--) {
if (get_user(reg, u++))
return -EFAULT;
regs->u_regs[pos++] = reg;
}
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
reg_window -= 16;
for (; count > 0 && pos < 32; count--) {
if (get_user(reg, u++) ||
put_user(reg, &reg_window[pos++]))
return -EFAULT;
}
}
while (count > 0) {
unsigned long psr;
if (kbuf) if (pos < 32 * sizeof(u32)) {
reg = *k++; if (regwindow32_get(target, regs, uregs))
else if (get_user(reg, u++))
return -EFAULT; return -EFAULT;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
switch (pos) { uregs,
case 32: /* PSR */ 16 * sizeof(u32), 32 * sizeof(u32));
psr = regs->psr; if (ret)
psr &= ~(PSR_ICC | PSR_SYSCALL); return ret;
psr |= (reg & (PSR_ICC | PSR_SYSCALL)); if (regwindow32_set(target, regs, uregs))
regs->psr = psr; return -EFAULT;
break; if (!count)
case 33: /* PC */ return 0;
regs->pc = reg;
break;
case 34: /* NPC */
regs->npc = reg;
break;
case 35: /* Y */
regs->y = reg;
break;
case 36: /* WIM */
case 37: /* TBR */
break;
default:
goto finish;
}
pos++;
count--;
} }
finish: ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
pos *= sizeof(reg); &psr,
count *= sizeof(reg); 32 * sizeof(u32), 33 * sizeof(u32));
if (ret)
return ret;
regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
(psr & (PSR_ICC | PSR_SYSCALL));
if (!count)
return 0;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&regs->pc,
33 * sizeof(u32), 34 * sizeof(u32));
if (ret || !count)
return ret;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&regs->npc,
34 * sizeof(u32), 35 * sizeof(u32));
if (ret || !count)
return ret;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&regs->y,
35 * sizeof(u32), 36 * sizeof(u32));
if (ret || !count)
return ret;
return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
38 * sizeof(reg), -1); 36 * sizeof(u32), 38 * sizeof(u32));
} }
static int fpregs32_get(struct task_struct *target, static int fpregs32_get(struct task_struct *target,
......
...@@ -572,19 +572,13 @@ static int genregs32_get(struct task_struct *target, ...@@ -572,19 +572,13 @@ static int genregs32_get(struct task_struct *target,
for (; count > 0 && pos < 32; count--) { for (; count > 0 && pos < 32; count--) {
if (access_process_vm(target, if (access_process_vm(target,
(unsigned long) (unsigned long)
&reg_window[pos], &reg_window[pos++],
&reg, sizeof(reg), &reg, sizeof(reg),
FOLL_FORCE) FOLL_FORCE)
!= sizeof(reg)) != sizeof(reg))
return -EFAULT; return -EFAULT;
if (access_process_vm(target, if (put_user(reg, u++))
(unsigned long) u,
&reg, sizeof(reg),
FOLL_FORCE | FOLL_WRITE)
!= sizeof(reg))
return -EFAULT; return -EFAULT;
pos++;
u++;
} }
} }
} }
...@@ -684,12 +678,7 @@ static int genregs32_set(struct task_struct *target, ...@@ -684,12 +678,7 @@ static int genregs32_set(struct task_struct *target,
} }
} else { } else {
for (; count > 0 && pos < 32; count--) { for (; count > 0 && pos < 32; count--) {
if (access_process_vm(target, if (get_user(reg, u++))
(unsigned long)
u,
&reg, sizeof(reg),
FOLL_FORCE)
!= sizeof(reg))
return -EFAULT; return -EFAULT;
if (access_process_vm(target, if (access_process_vm(target,
(unsigned long) (unsigned long)
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <linux/msg.h> #include <linux/msg.h>
#include <linux/shm.h> #include <linux/shm.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/nfs_fs.h>
#include <linux/quota.h> #include <linux/quota.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/personality.h> #include <linux/personality.h>
......
...@@ -193,7 +193,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr, ...@@ -193,7 +193,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr,
vdev = to_vio_dev(dev); vdev = to_vio_dev(dev);
dp = vdev->dp; dp = vdev->dp;
return snprintf (buf, PAGE_SIZE, "%pOF\n", dp); return scnprintf(buf, PAGE_SIZE, "%pOF\n", dp);
} }
static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pgtsrmmu.h> #include <asm/pgtsrmmu.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -293,7 +294,7 @@ hypersparc_flush_tlb_range: ...@@ -293,7 +294,7 @@ hypersparc_flush_tlb_range:
cmp %o3, -1 cmp %o3, -1
be hypersparc_flush_tlb_range_out be hypersparc_flush_tlb_range_out
#endif #endif
sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4 sethi %hi(~((1 << PGDIR_SHIFT) - 1)), %o4
sta %o3, [%g1] ASI_M_MMUREGS sta %o3, [%g1] ASI_M_MMUREGS
and %o1, %o4, %o1 and %o1, %o4, %o1
add %o1, 0x200, %o1 add %o1, 0x200, %o1
......
...@@ -1649,29 +1649,29 @@ bool kern_addr_valid(unsigned long addr) ...@@ -1649,29 +1649,29 @@ bool kern_addr_valid(unsigned long addr)
pgd = pgd_offset_k(addr); pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) if (pgd_none(*pgd))
return 0; return false;
p4d = p4d_offset(pgd, addr); p4d = p4d_offset(pgd, addr);
if (p4d_none(*p4d)) if (p4d_none(*p4d))
return 0; return false;
pud = pud_offset(p4d, addr); pud = pud_offset(p4d, addr);
if (pud_none(*pud)) if (pud_none(*pud))
return 0; return false;
if (pud_large(*pud)) if (pud_large(*pud))
return pfn_valid(pud_pfn(*pud)); return pfn_valid(pud_pfn(*pud));
pmd = pmd_offset(pud, addr); pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd)) if (pmd_none(*pmd))
return 0; return false;
if (pmd_large(*pmd)) if (pmd_large(*pmd))
return pfn_valid(pmd_pfn(*pmd)); return pfn_valid(pmd_pfn(*pmd));
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
if (pte_none(*pte)) if (pte_none(*pte))
return 0; return false;
return pfn_valid(pte_pfn(*pte)); return pfn_valid(pte_pfn(*pte));
} }
......
...@@ -136,26 +136,8 @@ static void msi_set_sync(void) ...@@ -136,26 +136,8 @@ static void msi_set_sync(void)
void pmd_set(pmd_t *pmdp, pte_t *ptep) void pmd_set(pmd_t *pmdp, pte_t *ptep)
{ {
unsigned long ptp; /* Physical address, shifted right by 4 */ unsigned long ptp = __nocache_pa(ptep) >> 4;
int i; set_pte((pte_t *)&pmd_val(*pmdp), __pte(SRMMU_ET_PTD | ptp));
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);
}
} }
/* Find an entry in the third-level page table.. */ /* Find an entry in the third-level page table.. */
...@@ -163,7 +145,7 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address) ...@@ -163,7 +145,7 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address)
{ {
void *pte; 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 + return (pte_t *) pte +
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)); ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
} }
...@@ -175,18 +157,18 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address) ...@@ -175,18 +157,18 @@ pte_t *pte_offset_kernel(pmd_t *dir, unsigned long address)
*/ */
static void *__srmmu_get_nocache(int size, int align) static void *__srmmu_get_nocache(int size, int align)
{ {
int offset; int offset, minsz = 1 << SRMMU_NOCACHE_BITMAP_SHIFT;
unsigned long addr; unsigned long addr;
if (size < SRMMU_NOCACHE_BITMAP_SHIFT) { if (size < minsz) {
printk(KERN_ERR "Size 0x%x too small for nocache request\n", printk(KERN_ERR "Size 0x%x too small for nocache request\n",
size); size);
size = SRMMU_NOCACHE_BITMAP_SHIFT; size = minsz;
} }
if (size & (SRMMU_NOCACHE_BITMAP_SHIFT - 1)) { if (size & (minsz - 1)) {
printk(KERN_ERR "Size 0x%x unaligned int nocache request\n", printk(KERN_ERR "Size 0x%x unaligned in nocache request\n",
size); size);
size += SRMMU_NOCACHE_BITMAP_SHIFT - 1; size += minsz - 1;
} }
BUG_ON(align > SRMMU_NOCACHE_ALIGN_MAX); BUG_ON(align > SRMMU_NOCACHE_ALIGN_MAX);
...@@ -376,31 +358,33 @@ pgd_t *get_pgd_fast(void) ...@@ -376,31 +358,33 @@ pgd_t *get_pgd_fast(void)
*/ */
pgtable_t pte_alloc_one(struct mm_struct *mm) pgtable_t pte_alloc_one(struct mm_struct *mm)
{ {
unsigned long pte; pte_t *ptep;
struct page *page; struct page *page;
if ((pte = (unsigned long)pte_alloc_one_kernel(mm)) == 0) if ((ptep = 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);
return NULL; 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); page = pfn_to_page(__nocache_pa((unsigned long)ptep) >> PAGE_SHIFT);
p = (unsigned long)page_address(pte); /* Cached address (for test) */ spin_lock(&mm->page_table_lock);
if (p == 0) if (page_ref_dec_return(page) == 1)
BUG(); pgtable_pte_page_dtor(page);
p = page_to_pfn(pte) << PAGE_SHIFT; /* Physical address */ spin_unlock(&mm->page_table_lock);
/* free non cached virtual address*/ srmmu_free_nocache(ptep, SRMMU_PTE_TABLE_SIZE);
srmmu_free_nocache(__nocache_va(p), PTE_SIZE);
} }
/* context handling - a dynamically sized pool is used */ /* context handling - a dynamically sized pool is used */
...@@ -822,13 +806,13 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start, ...@@ -822,13 +806,13 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
what = 0; what = 0;
addr = start - PAGE_SIZE; addr = start - PAGE_SIZE;
if (!(start & ~(SRMMU_REAL_PMD_MASK))) { if (!(start & ~(PMD_MASK))) {
if (srmmu_probe(addr + SRMMU_REAL_PMD_SIZE) == probed) if (srmmu_probe(addr + PMD_SIZE) == probed)
what = 1; what = 1;
} }
if (!(start & ~(SRMMU_PGDIR_MASK))) { if (!(start & ~(PGDIR_MASK))) {
if (srmmu_probe(addr + SRMMU_PGDIR_SIZE) == probed) if (srmmu_probe(addr + PGDIR_SIZE) == probed)
what = 2; what = 2;
} }
...@@ -837,7 +821,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start, ...@@ -837,7 +821,7 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
pudp = pud_offset(p4dp, start); pudp = pud_offset(p4dp, start);
if (what == 2) { if (what == 2) {
*(pgd_t *)__nocache_fix(pgdp) = __pgd(probed); *(pgd_t *)__nocache_fix(pgdp) = __pgd(probed);
start += SRMMU_PGDIR_SIZE; start += PGDIR_SIZE;
continue; continue;
} }
if (pud_none(*(pud_t *)__nocache_fix(pudp))) { if (pud_none(*(pud_t *)__nocache_fix(pudp))) {
...@@ -849,6 +833,11 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start, ...@@ -849,6 +833,11 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
pud_set(__nocache_fix(pudp), pmdp); pud_set(__nocache_fix(pudp), pmdp);
} }
pmdp = pmd_offset(__nocache_fix(pgdp), start); 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))) { if (srmmu_pmd_none(*(pmd_t *)__nocache_fix(pmdp))) {
ptep = __srmmu_get_nocache(PTE_SIZE, PTE_SIZE); ptep = __srmmu_get_nocache(PTE_SIZE, PTE_SIZE);
if (ptep == NULL) if (ptep == NULL)
...@@ -856,19 +845,6 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start, ...@@ -856,19 +845,6 @@ static void __init srmmu_inherit_prom_mappings(unsigned long start,
memset(__nocache_fix(ptep), 0, PTE_SIZE); memset(__nocache_fix(ptep), 0, PTE_SIZE);
pmd_set(__nocache_fix(pmdp), ptep); 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); ptep = pte_offset_kernel(__nocache_fix(pmdp), start);
*(pte_t *)__nocache_fix(ptep) = __pte(probed); *(pte_t *)__nocache_fix(ptep) = __pte(probed);
start += PAGE_SIZE; start += PAGE_SIZE;
...@@ -890,9 +866,9 @@ static void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base ...@@ -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. */ /* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. */
static unsigned long __init map_spbank(unsigned long vbase, int sp_entry) 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 pstart = (sp_banks[sp_entry].base_addr & PGDIR_MASK);
unsigned long vstart = (vbase & SRMMU_PGDIR_MASK); unsigned long vstart = (vbase & PGDIR_MASK);
unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes); unsigned long vend = PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes);
/* Map "low" memory only */ /* Map "low" memory only */
const unsigned long min_vaddr = PAGE_OFFSET; const unsigned long min_vaddr = PAGE_OFFSET;
const unsigned long max_vaddr = PAGE_OFFSET + SRMMU_MAXMEM; 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) ...@@ -905,7 +881,7 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
while (vstart < vend) { while (vstart < vend) {
do_large_mapping(vstart, pstart); do_large_mapping(vstart, pstart);
vstart += SRMMU_PGDIR_SIZE; pstart += SRMMU_PGDIR_SIZE; vstart += PGDIR_SIZE; pstart += PGDIR_SIZE;
} }
return vstart; return vstart;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <asm/asi.h> #include <asm/asi.h>
#include <asm/mxcc.h> #include <asm/mxcc.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/pgtsrmmu.h> #include <asm/pgtsrmmu.h>
#include <asm/viking.h> #include <asm/viking.h>
...@@ -157,7 +158,7 @@ viking_flush_tlb_range: ...@@ -157,7 +158,7 @@ viking_flush_tlb_range:
cmp %o3, -1 cmp %o3, -1
be 2f be 2f
#endif #endif
sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4 sethi %hi(~((1 << PGDIR_SHIFT) - 1)), %o4
sta %o3, [%g1] ASI_M_MMUREGS sta %o3, [%g1] ASI_M_MMUREGS
and %o1, %o4, %o1 and %o1, %o4, %o1
add %o1, 0x200, %o1 add %o1, 0x200, %o1
...@@ -243,7 +244,7 @@ sun4dsmp_flush_tlb_range: ...@@ -243,7 +244,7 @@ sun4dsmp_flush_tlb_range:
ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + VMA_VM_MM], %o0
ld [%o0 + AOFF_mm_context], %o3 ld [%o0 + AOFF_mm_context], %o3
lda [%g1] ASI_M_MMUREGS, %g5 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 sta %o3, [%g1] ASI_M_MMUREGS
and %o1, %o4, %o1 and %o1, %o4, %o1
add %o1, 0x200, %o1 add %o1, 0x200, %o1
......
...@@ -410,9 +410,7 @@ static void dax_unlock_pages(struct dax_ctx *ctx, int ccb_index, int nelem) ...@@ -410,9 +410,7 @@ static void dax_unlock_pages(struct dax_ctx *ctx, int ccb_index, int nelem)
if (p) { if (p) {
dax_dbg("freeing page %p", p); dax_dbg("freeing page %p", p);
if (j == OUT) unpin_user_pages_dirty_lock(&p, 1, j == OUT);
set_page_dirty(p);
put_page(p);
ctx->pages[i][j] = NULL; ctx->pages[i][j] = NULL;
} }
} }
...@@ -425,13 +423,13 @@ static int dax_lock_page(void *va, struct page **p) ...@@ -425,13 +423,13 @@ static int dax_lock_page(void *va, struct page **p)
dax_dbg("uva %p", va); dax_dbg("uva %p", va);
ret = get_user_pages_fast((unsigned long)va, 1, FOLL_WRITE, p); ret = pin_user_pages_fast((unsigned long)va, 1, FOLL_WRITE, p);
if (ret == 1) { if (ret == 1) {
dax_dbg("locked page %p, for VA %p", *p, va); dax_dbg("locked page %p, for VA %p", *p, va);
return 0; return 0;
} }
dax_dbg("get_user_pages failed, va=%p, ret=%d", va, ret); dax_dbg("pin_user_pages failed, va=%p, ret=%d", va, ret);
return -1; return -1;
} }
......
...@@ -193,6 +193,9 @@ config MEMORY_HOTREMOVE ...@@ -193,6 +193,9 @@ config MEMORY_HOTREMOVE
# Default to 4 for wider testing, though 8 might be more appropriate. # Default to 4 for wider testing, though 8 might be more appropriate.
# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. # ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock.
# PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. # PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes.
# SPARC32 allocates multiple pte tables within a single page, and therefore
# a per-page lock leads to problems when multiple tables need to be locked
# at the same time (e.g. copy_page_range()).
# DEBUG_SPINLOCK and DEBUG_LOCK_ALLOC spinlock_t also enlarge struct page. # DEBUG_SPINLOCK and DEBUG_LOCK_ALLOC spinlock_t also enlarge struct page.
# #
config SPLIT_PTLOCK_CPUS config SPLIT_PTLOCK_CPUS
...@@ -200,6 +203,7 @@ config SPLIT_PTLOCK_CPUS ...@@ -200,6 +203,7 @@ config SPLIT_PTLOCK_CPUS
default "999999" if !MMU default "999999" if !MMU
default "999999" if ARM && !CPU_CACHE_VIPT default "999999" if ARM && !CPU_CACHE_VIPT
default "999999" if PARISC && !PA20 default "999999" if PARISC && !PA20
default "999999" if SPARC32
default "4" default "4"
config ARCH_ENABLE_SPLIT_PMD_PTLOCK config ARCH_ENABLE_SPLIT_PMD_PTLOCK
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment