Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: [S390] make page table upgrade work again [S390] make page table walking more robust [S390] Dont check for pfn_valid() in uaccess_pt.c [S390] ftrace/mcount: fix kernel stack backchain [S390] topology: define SD_MC_INIT to fix performance regression [S390] __div64_31 broken for CONFIG_MARCH_G5
This commit is contained in:
commit
caa81d671f
8 changed files with 48 additions and 40 deletions
|
@ -22,4 +22,9 @@
|
||||||
#define MCL_CURRENT 1 /* lock all current mappings */
|
#define MCL_CURRENT 1 /* lock all current mappings */
|
||||||
#define MCL_FUTURE 2 /* lock all future mappings */
|
#define MCL_FUTURE 2 /* lock all future mappings */
|
||||||
|
|
||||||
|
#if defined(__KERNEL__) && !defined(__ASSEMBLY__) && defined(CONFIG_64BIT)
|
||||||
|
int s390_mmap_check(unsigned long addr, unsigned long len);
|
||||||
|
#define arch_mmap_check(addr,len,flags) s390_mmap_check(addr,len)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __S390_MMAN_H__ */
|
#endif /* __S390_MMAN_H__ */
|
||||||
|
|
|
@ -61,7 +61,7 @@ extern void print_cpu_info(struct cpuinfo_S390 *);
|
||||||
extern int get_cpu_capability(unsigned int *);
|
extern int get_cpu_capability(unsigned int *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User space process size: 2GB for 31 bit, 4TB for 64 bit.
|
* User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
|
||||||
*/
|
*/
|
||||||
#ifndef __s390x__
|
#ifndef __s390x__
|
||||||
|
|
||||||
|
@ -70,8 +70,7 @@ extern int get_cpu_capability(unsigned int *);
|
||||||
|
|
||||||
#else /* __s390x__ */
|
#else /* __s390x__ */
|
||||||
|
|
||||||
#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk,TIF_31BIT) ? \
|
#define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit)
|
||||||
(1UL << 31) : (1UL << 53))
|
|
||||||
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \
|
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \
|
||||||
(1UL << 30) : (1UL << 41))
|
(1UL << 30) : (1UL << 41))
|
||||||
#define TASK_SIZE TASK_SIZE_OF(current)
|
#define TASK_SIZE TASK_SIZE_OF(current)
|
||||||
|
|
|
@ -30,6 +30,8 @@ static inline void s390_init_cpu_topology(void)
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SD_MC_INIT SD_CPU_INIT
|
||||||
|
|
||||||
#include <asm-generic/topology.h>
|
#include <asm-generic/topology.h>
|
||||||
|
|
||||||
#endif /* _ASM_S390_TOPOLOGY_H */
|
#endif /* _ASM_S390_TOPOLOGY_H */
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <asm/asm-offsets.h>
|
||||||
|
|
||||||
#ifndef CONFIG_64BIT
|
#ifndef CONFIG_64BIT
|
||||||
.globl _mcount
|
.globl _mcount
|
||||||
_mcount:
|
_mcount:
|
||||||
|
@ -14,7 +16,7 @@ _mcount:
|
||||||
ahi %r15,-96
|
ahi %r15,-96
|
||||||
l %r3,100(%r15)
|
l %r3,100(%r15)
|
||||||
la %r2,0(%r14)
|
la %r2,0(%r14)
|
||||||
st %r1,0(%r15)
|
st %r1,__SF_BACKCHAIN(%r15)
|
||||||
la %r3,0(%r3)
|
la %r3,0(%r3)
|
||||||
bras %r14,0f
|
bras %r14,0f
|
||||||
.long ftrace_trace_function
|
.long ftrace_trace_function
|
||||||
|
@ -38,7 +40,7 @@ _mcount:
|
||||||
stg %r14,112(%r15)
|
stg %r14,112(%r15)
|
||||||
lgr %r1,%r15
|
lgr %r1,%r15
|
||||||
aghi %r15,-160
|
aghi %r15,-160
|
||||||
stg %r1,0(%r15)
|
stg %r1,__SF_BACKCHAIN(%r15)
|
||||||
lgr %r2,%r14
|
lgr %r2,%r14
|
||||||
lg %r3,168(%r15)
|
lg %r3,168(%r15)
|
||||||
larl %r14,ftrace_trace_function
|
larl %r14,ftrace_trace_function
|
||||||
|
|
|
@ -61,7 +61,7 @@ static uint32_t __div64_31(uint64_t *n, uint32_t base)
|
||||||
" clr %0,%3\n"
|
" clr %0,%3\n"
|
||||||
" jl 0f\n"
|
" jl 0f\n"
|
||||||
" slr %0,%3\n"
|
" slr %0,%3\n"
|
||||||
" alr %1,%2\n"
|
" ahi %1,1\n"
|
||||||
"0:\n"
|
"0:\n"
|
||||||
: "+d" (reg2), "+d" (reg3), "=d" (tmp)
|
: "+d" (reg2), "+d" (reg3), "=d" (tmp)
|
||||||
: "d" (base), "2" (1UL) : "cc" );
|
: "d" (base), "2" (1UL) : "cc" );
|
||||||
|
|
|
@ -119,8 +119,6 @@ retry:
|
||||||
goto fault;
|
goto fault;
|
||||||
|
|
||||||
pfn = pte_pfn(*pte);
|
pfn = pte_pfn(*pte);
|
||||||
if (!pfn_valid(pfn))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
offset = uaddr & (PAGE_SIZE - 1);
|
offset = uaddr & (PAGE_SIZE - 1);
|
||||||
size = min(n - done, PAGE_SIZE - offset);
|
size = min(n - done, PAGE_SIZE - offset);
|
||||||
|
@ -135,7 +133,6 @@ retry:
|
||||||
done += size;
|
done += size;
|
||||||
uaddr += size;
|
uaddr += size;
|
||||||
} while (done < n);
|
} while (done < n);
|
||||||
out:
|
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return n - done;
|
return n - done;
|
||||||
fault:
|
fault:
|
||||||
|
@ -163,9 +160,6 @@ retry:
|
||||||
goto fault;
|
goto fault;
|
||||||
|
|
||||||
pfn = pte_pfn(*pte);
|
pfn = pte_pfn(*pte);
|
||||||
if (!pfn_valid(pfn))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
|
ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -244,11 +238,6 @@ retry:
|
||||||
goto fault;
|
goto fault;
|
||||||
|
|
||||||
pfn = pte_pfn(*pte);
|
pfn = pte_pfn(*pte);
|
||||||
if (!pfn_valid(pfn)) {
|
|
||||||
done = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = uaddr & (PAGE_SIZE-1);
|
offset = uaddr & (PAGE_SIZE-1);
|
||||||
addr = (char *)(pfn << PAGE_SHIFT) + offset;
|
addr = (char *)(pfn << PAGE_SHIFT) + offset;
|
||||||
len = min(count - done, PAGE_SIZE - offset);
|
len = min(count - done, PAGE_SIZE - offset);
|
||||||
|
@ -256,7 +245,6 @@ retry:
|
||||||
done += len_str;
|
done += len_str;
|
||||||
uaddr += len_str;
|
uaddr += len_str;
|
||||||
} while ((len_str == len) && (done < count));
|
} while ((len_str == len) && (done < count));
|
||||||
out:
|
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return done + 1;
|
return done + 1;
|
||||||
fault:
|
fault:
|
||||||
|
@ -325,12 +313,7 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
pfn_from = pte_pfn(*pte_from);
|
pfn_from = pte_pfn(*pte_from);
|
||||||
if (!pfn_valid(pfn_from))
|
|
||||||
goto out;
|
|
||||||
pfn_to = pte_pfn(*pte_to);
|
pfn_to = pte_pfn(*pte_to);
|
||||||
if (!pfn_valid(pfn_to))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
offset_from = uaddr_from & (PAGE_SIZE-1);
|
offset_from = uaddr_from & (PAGE_SIZE-1);
|
||||||
offset_to = uaddr_from & (PAGE_SIZE-1);
|
offset_to = uaddr_from & (PAGE_SIZE-1);
|
||||||
offset_max = max(offset_from, offset_to);
|
offset_max = max(offset_from, offset_to);
|
||||||
|
@ -342,7 +325,6 @@ retry:
|
||||||
uaddr_from += size;
|
uaddr_from += size;
|
||||||
uaddr_to += size;
|
uaddr_to += size;
|
||||||
} while (done < n);
|
} while (done < n);
|
||||||
out:
|
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return n - done;
|
return n - done;
|
||||||
fault:
|
fault:
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
* Leave an at least ~128 MB hole.
|
* Leave an at least ~128 MB hole.
|
||||||
*/
|
*/
|
||||||
#define MIN_GAP (128*1024*1024)
|
#define MIN_GAP (128*1024*1024)
|
||||||
#define MAX_GAP (TASK_SIZE/6*5)
|
#define MAX_GAP (STACK_TOP/6*5)
|
||||||
|
|
||||||
static inline unsigned long mmap_base(void)
|
static inline unsigned long mmap_base(void)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ static inline unsigned long mmap_base(void)
|
||||||
else if (gap > MAX_GAP)
|
else if (gap > MAX_GAP)
|
||||||
gap = MAX_GAP;
|
gap = MAX_GAP;
|
||||||
|
|
||||||
return TASK_SIZE - (gap & PAGE_MASK);
|
return STACK_TOP - (gap & PAGE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mmap_is_legacy(void)
|
static inline int mmap_is_legacy(void)
|
||||||
|
@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
int s390_mmap_check(unsigned long addr, unsigned long len)
|
||||||
|
{
|
||||||
|
if (!test_thread_flag(TIF_31BIT) &&
|
||||||
|
len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
|
||||||
|
return crst_table_upgrade(current->mm, 1UL << 53);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
|
unsigned long area;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||||
if (addr & ~PAGE_MASK)
|
if (!(area & ~PAGE_MASK))
|
||||||
return addr;
|
return area;
|
||||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
if (area == -ENOMEM &&
|
||||||
rc = crst_table_upgrade(mm, addr + len);
|
!test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
|
||||||
|
/* Upgrade the page table to 4 levels and retry. */
|
||||||
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||||
}
|
}
|
||||||
return addr;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
|
||||||
const unsigned long len, const unsigned long pgoff,
|
const unsigned long len, const unsigned long pgoff,
|
||||||
const unsigned long flags)
|
const unsigned long flags)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = current->mm;
|
struct mm_struct *mm = current->mm;
|
||||||
unsigned long addr = addr0;
|
unsigned long area;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
||||||
if (addr & ~PAGE_MASK)
|
if (!(area & ~PAGE_MASK))
|
||||||
return addr;
|
return area;
|
||||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
if (area == -ENOMEM &&
|
||||||
rc = crst_table_upgrade(mm, addr + len);
|
!test_thread_flag(TIF_31BIT) && TASK_SIZE < (1UL << 53)) {
|
||||||
|
/* Upgrade the page table to 4 levels and retry. */
|
||||||
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
area = arch_get_unmapped_area_topdown(filp, addr, len,
|
||||||
|
pgoff, flags);
|
||||||
}
|
}
|
||||||
return addr;
|
return area;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* This function, called very early during the creation of a new
|
* This function, called very early during the creation of a new
|
||||||
|
|
|
@ -117,6 +117,7 @@ repeat:
|
||||||
crst_table_init(table, entry);
|
crst_table_init(table, entry);
|
||||||
pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
|
pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
|
||||||
mm->pgd = (pgd_t *) table;
|
mm->pgd = (pgd_t *) table;
|
||||||
|
mm->task_size = mm->context.asce_limit;
|
||||||
table = NULL;
|
table = NULL;
|
||||||
}
|
}
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
|
@ -154,6 +155,7 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
|
mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
|
||||||
|
mm->task_size = mm->context.asce_limit;
|
||||||
crst_table_free(mm, (unsigned long *) pgd);
|
crst_table_free(mm, (unsigned long *) pgd);
|
||||||
}
|
}
|
||||||
update_mm(mm, current);
|
update_mm(mm, current);
|
||||||
|
|
Loading…
Add table
Reference in a new issue