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:
Коммит
caa81d671f
|
@ -22,4 +22,9 @@
|
|||
#define MCL_CURRENT 1 /* lock all current 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__ */
|
||||
|
|
|
@ -61,7 +61,7 @@ extern void print_cpu_info(struct cpuinfo_S390 *);
|
|||
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__
|
||||
|
||||
|
@ -70,8 +70,7 @@ extern int get_cpu_capability(unsigned int *);
|
|||
|
||||
#else /* __s390x__ */
|
||||
|
||||
#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk,TIF_31BIT) ? \
|
||||
(1UL << 31) : (1UL << 53))
|
||||
#define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit)
|
||||
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \
|
||||
(1UL << 30) : (1UL << 41))
|
||||
#define TASK_SIZE TASK_SIZE_OF(current)
|
||||
|
|
|
@ -30,6 +30,8 @@ static inline void s390_init_cpu_topology(void)
|
|||
};
|
||||
#endif
|
||||
|
||||
#define SD_MC_INIT SD_CPU_INIT
|
||||
|
||||
#include <asm-generic/topology.h>
|
||||
|
||||
#endif /* _ASM_S390_TOPOLOGY_H */
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
#ifndef CONFIG_64BIT
|
||||
.globl _mcount
|
||||
_mcount:
|
||||
|
@ -14,7 +16,7 @@ _mcount:
|
|||
ahi %r15,-96
|
||||
l %r3,100(%r15)
|
||||
la %r2,0(%r14)
|
||||
st %r1,0(%r15)
|
||||
st %r1,__SF_BACKCHAIN(%r15)
|
||||
la %r3,0(%r3)
|
||||
bras %r14,0f
|
||||
.long ftrace_trace_function
|
||||
|
@ -38,7 +40,7 @@ _mcount:
|
|||
stg %r14,112(%r15)
|
||||
lgr %r1,%r15
|
||||
aghi %r15,-160
|
||||
stg %r1,0(%r15)
|
||||
stg %r1,__SF_BACKCHAIN(%r15)
|
||||
lgr %r2,%r14
|
||||
lg %r3,168(%r15)
|
||||
larl %r14,ftrace_trace_function
|
||||
|
|
|
@ -61,7 +61,7 @@ static uint32_t __div64_31(uint64_t *n, uint32_t base)
|
|||
" clr %0,%3\n"
|
||||
" jl 0f\n"
|
||||
" slr %0,%3\n"
|
||||
" alr %1,%2\n"
|
||||
" ahi %1,1\n"
|
||||
"0:\n"
|
||||
: "+d" (reg2), "+d" (reg3), "=d" (tmp)
|
||||
: "d" (base), "2" (1UL) : "cc" );
|
||||
|
|
|
@ -119,8 +119,6 @@ retry:
|
|||
goto fault;
|
||||
|
||||
pfn = pte_pfn(*pte);
|
||||
if (!pfn_valid(pfn))
|
||||
goto out;
|
||||
|
||||
offset = uaddr & (PAGE_SIZE - 1);
|
||||
size = min(n - done, PAGE_SIZE - offset);
|
||||
|
@ -135,7 +133,6 @@ retry:
|
|||
done += size;
|
||||
uaddr += size;
|
||||
} while (done < n);
|
||||
out:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return n - done;
|
||||
fault:
|
||||
|
@ -163,9 +160,6 @@ retry:
|
|||
goto fault;
|
||||
|
||||
pfn = pte_pfn(*pte);
|
||||
if (!pfn_valid(pfn))
|
||||
goto out;
|
||||
|
||||
ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
|
||||
out:
|
||||
return ret;
|
||||
|
@ -244,11 +238,6 @@ retry:
|
|||
goto fault;
|
||||
|
||||
pfn = pte_pfn(*pte);
|
||||
if (!pfn_valid(pfn)) {
|
||||
done = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
offset = uaddr & (PAGE_SIZE-1);
|
||||
addr = (char *)(pfn << PAGE_SHIFT) + offset;
|
||||
len = min(count - done, PAGE_SIZE - offset);
|
||||
|
@ -256,7 +245,6 @@ retry:
|
|||
done += len_str;
|
||||
uaddr += len_str;
|
||||
} while ((len_str == len) && (done < count));
|
||||
out:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return done + 1;
|
||||
fault:
|
||||
|
@ -325,12 +313,7 @@ retry:
|
|||
}
|
||||
|
||||
pfn_from = pte_pfn(*pte_from);
|
||||
if (!pfn_valid(pfn_from))
|
||||
goto out;
|
||||
pfn_to = pte_pfn(*pte_to);
|
||||
if (!pfn_valid(pfn_to))
|
||||
goto out;
|
||||
|
||||
offset_from = uaddr_from & (PAGE_SIZE-1);
|
||||
offset_to = uaddr_from & (PAGE_SIZE-1);
|
||||
offset_max = max(offset_from, offset_to);
|
||||
|
@ -342,7 +325,6 @@ retry:
|
|||
uaddr_from += size;
|
||||
uaddr_to += size;
|
||||
} while (done < n);
|
||||
out:
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
return n - done;
|
||||
fault:
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* Leave an at least ~128 MB hole.
|
||||
*/
|
||||
#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)
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ static inline unsigned long mmap_base(void)
|
|||
else if (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)
|
||||
|
@ -89,42 +89,58 @@ EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
|
|||
|
||||
#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
|
||||
s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long area;
|
||||
int rc;
|
||||
|
||||
addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
if (addr & ~PAGE_MASK)
|
||||
return addr;
|
||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
||||
rc = crst_table_upgrade(mm, addr + len);
|
||||
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
if (!(area & ~PAGE_MASK))
|
||||
return area;
|
||||
if (area == -ENOMEM &&
|
||||
!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)
|
||||
return (unsigned long) rc;
|
||||
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||
}
|
||||
return addr;
|
||||
return area;
|
||||
}
|
||||
|
||||
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 flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
unsigned long area;
|
||||
int rc;
|
||||
|
||||
addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
||||
if (addr & ~PAGE_MASK)
|
||||
return addr;
|
||||
if (unlikely(mm->context.asce_limit < addr + len)) {
|
||||
rc = crst_table_upgrade(mm, addr + len);
|
||||
area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
|
||||
if (!(area & ~PAGE_MASK))
|
||||
return area;
|
||||
if (area == -ENOMEM &&
|
||||
!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)
|
||||
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
|
||||
|
|
|
@ -117,6 +117,7 @@ repeat:
|
|||
crst_table_init(table, entry);
|
||||
pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
|
||||
mm->pgd = (pgd_t *) table;
|
||||
mm->task_size = mm->context.asce_limit;
|
||||
table = NULL;
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
@ -154,6 +155,7 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
|
|||
BUG();
|
||||
}
|
||||
mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
|
||||
mm->task_size = mm->context.asce_limit;
|
||||
crst_table_free(mm, (unsigned long *) pgd);
|
||||
}
|
||||
update_mm(mm, current);
|
||||
|
|
Загрузка…
Ссылка в новой задаче