Commit 9cb51c16 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: core

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

s390 core changes:
 - Rename idle_cpu_mask to nohz_cpu_mask as agreed with Dipankar.
 - Refine compiler version check for "Q" constraints in uaccess.h.
 - Store per process ptrace information to the correct place.
 - Fix per cpu data access for 64-bit modules.
 - Add topology_init function for cpu hotplug.
 - Define TASK_SIZE dependent on TIF_31BIT and define MM_VM_SIZE
   to 4TB to get rid of elf_map32 and arch_get_unmapped_area.
parent 1b9407d7
...@@ -433,7 +433,6 @@ CONFIG_SUNRPC=y ...@@ -433,7 +433,6 @@ CONFIG_SUNRPC=y
# CONFIG_CIFS is not set # CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set # CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set # CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set # CONFIG_AFS_FS is not set
# #
...@@ -505,9 +504,11 @@ CONFIG_CRYPTO=y ...@@ -505,9 +504,11 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_TEST is not set # CONFIG_CRYPTO_TEST is not set
# #
# Library routines # Library routines
# #
# CONFIG_CRC32 is not set # CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
...@@ -32,10 +32,6 @@ ...@@ -32,10 +32,6 @@
#define NUM_FPRS 16 #define NUM_FPRS 16
#define NUM_ACRS 16 #define NUM_ACRS 16
#define TASK31_SIZE (0x80000000UL)
#undef TASK_SIZE
#define TASK_SIZE TASK31_SIZE
/* For SVR4/S390 the function pointer to be registered with `atexit` is /* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */ passed in R14. */
#define ELF_PLAT_INIT(_r, load_addr) \ #define ELF_PLAT_INIT(_r, load_addr) \
...@@ -51,7 +47,7 @@ ...@@ -51,7 +47,7 @@
the loader. We need to make sure that it is out of the way of the program the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */ that it will "exec", and that there is sufficient room for the brk. */
#define ELF_ET_DYN_BASE (TASK31_SIZE / 3 * 2) #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
/* Wow, the "main" arch needs arch dependent functions too.. :) */ /* Wow, the "main" arch needs arch dependent functions too.. :) */
...@@ -169,7 +165,6 @@ struct elf_prpsinfo32 ...@@ -169,7 +165,6 @@ struct elf_prpsinfo32
#undef start_thread #undef start_thread
#define start_thread start_thread31 #define start_thread start_thread31
#define setup_arg_pages(bprm, exec) setup_arg_pages32(bprm, exec) #define setup_arg_pages(bprm, exec) setup_arg_pages32(bprm, exec)
#define elf_map elf_map32
MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries," MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
" Copyright 2000 IBM Corporation"); " Copyright 2000 IBM Corporation");
...@@ -188,19 +183,3 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) ...@@ -188,19 +183,3 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
#include "../../../fs/binfmt_elf.c" #include "../../../fs/binfmt_elf.c"
static unsigned long
elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
{
unsigned long map_addr;
if (!addr)
addr = TASK_UNMAPPED_BASE;
down_write(&current->mm->mmap_sem);
map_addr = do_mmap(filep, ELF_PAGESTART(addr),
eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr),
prot, type,
eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
up_write(&current->mm->mmap_sem);
return(map_addr);
}
...@@ -34,9 +34,6 @@ ...@@ -34,9 +34,6 @@
#endif #endif
#undef STACK_TOP
#define STACK_TOP TASK31_SIZE
int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack) int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack)
{ {
unsigned long stack_base; unsigned long stack_base;
......
...@@ -471,9 +471,10 @@ pgm_per: ...@@ -471,9 +471,10 @@ pgm_per:
pgm_per_std: pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
GET_THREAD_INFO GET_THREAD_INFO
mvc __THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID l %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_address(4,%r9),__LC_PER_ADDRESS mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
la %r4,0x7f la %r4,0x7f
l %r3,__LC_PGM_ILC # load program interruption code l %r3,__LC_PGM_ILC # load program interruption code
nr %r4,%r3 # clear per-event-bit and ilc nr %r4,%r3 # clear per-event-bit and ilc
...@@ -495,11 +496,12 @@ pgm_per_only: ...@@ -495,11 +496,12 @@ pgm_per_only:
pgm_svcper: pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
lh %r7,0x8a # get svc number from lowcore lh %r7,0x8a # get svc number from lowcore
stosm 24(%r15),0x03 # reenable interrupts
GET_THREAD_INFO # load pointer to task_struct to R9 GET_THREAD_INFO # load pointer to task_struct to R9
mvc __THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID l %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_address(4,%r9),__LC_PER_ADDRESS mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
stosm 24(%r15),0x03 # reenable interrupts
sla %r7,2 # *4 and test for svc 0 sla %r7,2 # *4 and test for svc 0
bnz BASED(pgm_svcstd) # svc number > 0 ? bnz BASED(pgm_svcstd) # svc number > 0 ?
# svc 0: system call number in %r1 # svc 0: system call number in %r1
......
...@@ -505,9 +505,10 @@ pgm_per: ...@@ -505,9 +505,10 @@ pgm_per:
pgm_per_std: pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
GET_THREAD_INFO GET_THREAD_INFO
mvc __THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID lg %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_address(8,%r9),__LC_PER_ADDRESS mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
lghi %r4,0x7f lghi %r4,0x7f
lgf %r3,__LC_PGM_ILC # load program interruption code lgf %r3,__LC_PGM_ILC # load program interruption code
nr %r4,%r3 # clear per-event-bit and ilc nr %r4,%r3 # clear per-event-bit and ilc
...@@ -528,11 +529,12 @@ pgm_per_only: ...@@ -528,11 +529,12 @@ pgm_per_only:
pgm_svcper: pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
stosm 48(%r15),0x03 # reenable interrupts
GET_THREAD_INFO # load pointer to task_struct to R9 GET_THREAD_INFO # load pointer to task_struct to R9
mvc __THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID lg %r1,__TI_task(%r9)
mvc __THREAD_per+__PER_address(8,%r9),__LC_PER_ADDRESS mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
mvc __THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
stosm 48(%r15),0x03 # reenable interrupts
slag %r7,%r7,2 # *4 and test for svc 0 slag %r7,%r7,2 # *4 and test for svc 0
jnz pgm_svcstd jnz pgm_svcstd
# svc 0: system call number in %r1 # svc 0: system call number in %r1
......
...@@ -277,7 +277,8 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, ...@@ -277,7 +277,8 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
*(unsigned int *) loc = val; *(unsigned int *) loc = val;
else if (r_type == R_390_GOTENT || else if (r_type == R_390_GOTENT ||
r_type == R_390_GOTPLTENT) r_type == R_390_GOTPLTENT)
*(unsigned int *) loc = val >> 1; *(unsigned int *) loc =
(val + (Elf_Addr) me->module_core - loc) >> 1;
else if (r_type == R_390_GOT64 || else if (r_type == R_390_GOT64 ||
r_type == R_390_GOTPLT64) r_type == R_390_GOTPLT64)
*(unsigned long *) loc = val; *(unsigned long *) loc = val;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/cpu.h>
#include <asm/sigp.h> #include <asm/sigp.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -651,6 +652,24 @@ int setup_profiling_timer(unsigned int multiplier) ...@@ -651,6 +652,24 @@ int setup_profiling_timer(unsigned int multiplier)
return 0; return 0;
} }
static DEFINE_PER_CPU(struct cpu, cpu_devices);
static int __init topology_init(void)
{
int cpu;
int ret;
for_each_cpu(cpu) {
ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
if (ret)
printk(KERN_WARNING "topology_init: register_cpu %d "
"failed (%d)\n", cpu, ret);
}
return 0;
}
subsys_initcall(topology_init);
EXPORT_SYMBOL(cpu_possible_map); EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(lowcore_ptr); EXPORT_SYMBOL(lowcore_ptr);
EXPORT_SYMBOL(smp_ctl_set_bit); EXPORT_SYMBOL(smp_ctl_set_bit);
......
...@@ -138,38 +138,6 @@ asmlinkage long old_select(struct sel_arg_struct *arg) ...@@ -138,38 +138,6 @@ asmlinkage long old_select(struct sel_arg_struct *arg)
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
} }
#else /* CONFIG_ARCH_S390X */
unsigned long
arch_get_unmapped_area(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
struct vm_area_struct *vma;
unsigned long end;
if (test_thread_flag(TIF_31BIT)) {
if (!addr)
addr = 0x40000000;
end = 0x80000000;
} else {
if (!addr)
addr = TASK_SIZE / 2;
end = TASK_SIZE;
}
if (len > end)
return -ENOMEM;
addr = PAGE_ALIGN(addr);
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
/* At this point: (!vma || addr < vma->vm_end). */
if (end - len < addr)
return -ENOMEM;
if (!vma || addr + len <= vma->vm_start)
return addr;
addr = vma->vm_end;
}
}
#endif /* CONFIG_ARCH_S390X */ #endif /* CONFIG_ARCH_S390X */
/* /*
......
...@@ -468,7 +468,7 @@ void start_hz_timer(struct pt_regs *regs) ...@@ -468,7 +468,7 @@ void start_hz_timer(struct pt_regs *regs)
__u64 tmp; __u64 tmp;
__u32 ticks; __u32 ticks;
if (!cpu_isset(smp_processor_id(), idle_cpu_mask)) if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
return; return;
/* Calculate how many ticks have passed */ /* Calculate how many ticks have passed */
...@@ -511,7 +511,7 @@ void start_hz_timer(struct pt_regs *regs) ...@@ -511,7 +511,7 @@ void start_hz_timer(struct pt_regs *regs)
do_timer(regs); do_timer(regs);
#endif #endif
} }
cpu_clear(smp_processor_id(), idle_cpu_mask); cpu_clear(smp_processor_id(), nohz_cpu_mask);
} }
/* /*
...@@ -536,7 +536,7 @@ int stop_hz_timer(void) ...@@ -536,7 +536,7 @@ int stop_hz_timer(void)
* This cpu is going really idle. Set up the clock comparator * This cpu is going really idle. Set up the clock comparator
* for the next event. * for the next event.
*/ */
cpu_set(smp_processor_id(), idle_cpu_mask); cpu_set(smp_processor_id(), nohz_cpu_mask);
timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (timer)); asm volatile ("SCKC %0" : : "m" (timer));
......
...@@ -69,7 +69,7 @@ void show_mem(void) ...@@ -69,7 +69,7 @@ void show_mem(void)
else if (PageSwapCache(mem_map+i)) else if (PageSwapCache(mem_map+i))
cached++; cached++;
else if (page_count(mem_map+i)) else if (page_count(mem_map+i))
shared += atomic_read(&mem_map[i].count) - 1; shared += page_count(mem_map+i) - 1;
} }
printk("%d pages of RAM\n",total); printk("%d pages of RAM\n",total);
printk("%d reserved pages\n",reserved); printk("%d reserved pages\n",reserved);
......
...@@ -5,10 +5,26 @@ ...@@ -5,10 +5,26 @@
#include <asm/lowcore.h> #include <asm/lowcore.h>
/* /*
* s390 uses the generic implementation for per cpu data, with the exception that * For builtin kernel code s390 uses the generic implementation for
* the offset of the cpu local data area is cached in the cpu's lowcore memory * per cpu data, with the exception that the offset of the cpu local
* data area is cached in the cpu's lowcore memory
* For 64 bit module code s390 forces the use of a GOT slot for the
* address of the per cpu variable. This is needed because the module
* may be more than 4G above the per cpu area.
*/ */
#if defined(__s390x__) && defined(MODULE)
#define __get_got_cpu_var(var,offset) \
(*({ unsigned long *__ptr; \
asm ( "larl %0,per_cpu__"#var"@GOTENT" : "=a" (__ptr) ); \
((typeof(&per_cpu__##var))((*__ptr) + offset)); \
}))
#undef __get_cpu_var
#define __get_cpu_var(var) __get_got_cpu_var(var,S390_lowcore.percpu_offset)
#undef per_cpu
#define per_cpu(var,cpu) __get_got_cpu_var(var,__per_cpu_offset[cpu])
#else
#undef __get_cpu_var #undef __get_cpu_var
#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, S390_lowcore.percpu_offset)) #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, S390_lowcore.percpu_offset))
#endif
#endif /* __ARCH_S390_PERCPU__ */ #endif /* __ARCH_S390_PERCPU__ */
...@@ -784,10 +784,6 @@ typedef pte_t *pte_addr_t; ...@@ -784,10 +784,6 @@ typedef pte_t *pte_addr_t;
*/ */
#define pgtable_cache_init() do { } while (0) #define pgtable_cache_init() do { } while (0)
#ifdef __s390x__
# define HAVE_ARCH_UNMAPPED_AREA
#endif /* __s390x__ */
#define __HAVE_ARCH_PTEP_ESTABLISH #define __HAVE_ARCH_PTEP_ESTABLISH
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
......
...@@ -63,16 +63,19 @@ extern struct task_struct *last_task_used_math; ...@@ -63,16 +63,19 @@ extern struct task_struct *last_task_used_math;
# define TASK_SIZE (0x80000000UL) # define TASK_SIZE (0x80000000UL)
# define TASK_UNMAPPED_BASE (TASK_SIZE / 2) # define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
# define DEFAULT_TASK_SIZE (0x80000000UL)
#else /* __s390x__ */ #else /* __s390x__ */
# define TASK_SIZE (0x40000000000UL) # define TASK_SIZE (test_thread_flag(TIF_31BIT) ? \
# define TASK31_SIZE (0x80000000UL) (0x80000000UL) : (0x40000000000UL))
# define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ # define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
(TASK31_SIZE / 2) : (TASK_SIZE / 2)) # define DEFAULT_TASK_SIZE (0x40000000000UL)
#endif /* __s390x__ */ #endif /* __s390x__ */
#define MM_VM_SIZE(mm) DEFAULT_TASK_SIZE
typedef struct { typedef struct {
__u32 ar4; __u32 ar4;
} mm_segment_t; } mm_segment_t;
......
...@@ -119,7 +119,7 @@ struct exception_table_entry ...@@ -119,7 +119,7 @@ struct exception_table_entry
* These are the main single-value transfer routines. They automatically * These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type. * use the right size if we just have the right pointer type.
*/ */
#if __GNUC__ > 2 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __put_user_asm(x, ptr, err) \ #define __put_user_asm(x, ptr, err) \
({ \ ({ \
err = 0; \ err = 0; \
...@@ -174,7 +174,7 @@ struct exception_table_entry ...@@ -174,7 +174,7 @@ struct exception_table_entry
extern int __put_user_bad(void); extern int __put_user_bad(void);
#if __GNUC__ > 2 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __get_user_asm(x, ptr, err) \ #define __get_user_asm(x, ptr, err) \
({ \ ({ \
err = 0; \ err = 0; \
......
...@@ -150,7 +150,7 @@ extern void sched_init(void); ...@@ -150,7 +150,7 @@ extern void sched_init(void);
extern void sched_init_smp(void); extern void sched_init_smp(void);
extern void init_idle(task_t *idle, int cpu); extern void init_idle(task_t *idle, int cpu);
extern cpumask_t idle_cpu_mask; extern cpumask_t nohz_cpu_mask;
extern void show_state(void); extern void show_state(void);
extern void show_regs(struct pt_regs *); extern void show_regs(struct pt_regs *);
......
...@@ -113,7 +113,7 @@ static void rcu_start_batch(long newbatch) ...@@ -113,7 +113,7 @@ static void rcu_start_batch(long newbatch)
return; return;
} }
/* Can't change, since spin lock held. */ /* Can't change, since spin lock held. */
active = idle_cpu_mask; active = nohz_cpu_mask;
cpus_complement(active); cpus_complement(active);
cpus_and(rcu_ctrlblk.rcu_cpu_mask, cpu_online_map, active); cpus_and(rcu_ctrlblk.rcu_cpu_mask, cpu_online_map, active);
} }
......
...@@ -3231,13 +3231,13 @@ void __devinit init_idle(task_t *idle, int cpu) ...@@ -3231,13 +3231,13 @@ void __devinit init_idle(task_t *idle, int cpu)
} }
/* /*
* In a system that switches off the HZ timer idle_cpu_mask * In a system that switches off the HZ timer nohz_cpu_mask
* indicates which cpus entered this state. This is used * indicates which cpus entered this state. This is used
* in the rcu update to wait only for active cpus. For system * in the rcu update to wait only for active cpus. For system
* which do not switch off the HZ timer idle_cpu_mask should * which do not switch off the HZ timer nohz_cpu_mask should
* always be CPU_MASK_NONE. * always be CPU_MASK_NONE.
*/ */
cpumask_t idle_cpu_mask = CPU_MASK_NONE; cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* /*
......
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