summaryrefslogtreecommitdiff
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/cache.c9
-rw-r--r--arch/s390/kernel/compat_signal.c14
-rw-r--r--arch/s390/kernel/entry.S32
-rw-r--r--arch/s390/kernel/entry64.S26
-rw-r--r--arch/s390/kernel/head_kdump.S10
-rw-r--r--arch/s390/kernel/perf_cpum_cf.c6
-rw-r--r--arch/s390/kernel/sclp.S8
-rw-r--r--arch/s390/kernel/signal.c14
-rw-r--r--arch/s390/kernel/topology.c6
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
10 files changed, 59 insertions, 68 deletions
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
index 8df8d8a19c98..64b24650e4f8 100644
--- a/arch/s390/kernel/cache.c
+++ b/arch/s390/kernel/cache.c
@@ -59,8 +59,8 @@ enum {
enum {
CACHE_TI_UNIFIED = 0,
- CACHE_TI_INSTRUCTION = 0,
- CACHE_TI_DATA,
+ CACHE_TI_DATA = 0,
+ CACHE_TI_INSTRUCTION,
};
struct cache_info {
@@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type)
cache = kzalloc(sizeof(*cache), GFP_KERNEL);
if (!cache)
return -ENOMEM;
- ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+ if (type == CACHE_TYPE_INSTRUCTION)
+ ti = CACHE_TI_INSTRUCTION;
+ else
+ ti = CACHE_TI_UNIFIED;
cache->size = ecag(EXTRACT_SIZE, level, ti);
cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index a1e8a8694bb7..593fcc9253fc 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+ /* Check for invalid user address space control. */
+ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
+ /* Force 31 bit amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__force __u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame;
- regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */
+ /* Force 31 bit amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->gprs[2] = map_signal(sig);
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index ef46f66bc0d6..aa8f2ba6289b 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -330,40 +330,18 @@ ENTRY(ret_from_fork)
la %r11,STACK_FRAME_OVERHEAD(%r15)
l %r12,__LC_THREAD_INFO
l %r13,__LC_SVC_NEW_PSW+4
- tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?
- je 1f
l %r1,BASED(.Lschedule_tail)
basr %r14,%r1 # call schedule_tail
TRACE_IRQS_ON
ssm __LC_SVC_NEW_PSW # reenable interrupts
- j sysc_tracenogo
-
-1: # it's a kernel thread
- st %r15,__PT_R15(%r11) # store stack pointer for new kthread
- l %r1,BASED(.Lschedule_tail)
- basr %r14,%r1 # call schedule_tail
- TRACE_IRQS_ON
- ssm __LC_SVC_NEW_PSW # reenable interrupts
- lm %r9,%r11,__PT_R9(%r11) # load gprs
+ tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?
+ jne sysc_tracenogo
+ # it's a kernel thread
+ lm %r9,%r10,__PT_R9(%r11) # load gprs
ENTRY(kernel_thread_starter)
la %r2,0(%r10)
basr %r14,%r9
- la %r2,0
- br %r11 # do_exit
-
-#
-# kernel_execve function needs to deal with pt_regs that is not
-# at the usual place
-#
-ENTRY(ret_from_kernel_execve)
- ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts
- lr %r15,%r2
- lr %r11,%r2
- ahi %r15,-STACK_FRAME_OVERHEAD
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
- l %r12,__LC_THREAD_INFO
- ssm __LC_SVC_NEW_PSW # reenable interrupts
- j sysc_return
+ j sysc_tracenogo
/*
* Program check handler routine
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 07d8de353984..499e95e90f38 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -352,33 +352,17 @@ sysc_tracenogo:
ENTRY(ret_from_fork)
la %r11,STACK_FRAME_OVERHEAD(%r15)
lg %r12,__LC_THREAD_INFO
- tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?
- je 1f
brasl %r14,schedule_tail
TRACE_IRQS_ON
ssm __LC_SVC_NEW_PSW # reenable interrupts
- j sysc_tracenogo
-1: # it's a kernel thread
- stg %r15,__PT_R15(%r11) # store stack pointer for new kthread
- brasl %r14,schedule_tail
- TRACE_IRQS_ON
- ssm __LC_SVC_NEW_PSW # reenable interrupts
- lmg %r9,%r11,__PT_R9(%r11) # load gprs
+ tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?
+ jne sysc_tracenogo
+ # it's a kernel thread
+ lmg %r9,%r10,__PT_R9(%r11) # load gprs
ENTRY(kernel_thread_starter)
la %r2,0(%r10)
basr %r14,%r9
- la %r2,0
- br %r11 # do_exit
-
-ENTRY(ret_from_kernel_execve)
- ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts
- lgr %r15,%r2
- lgr %r11,%r2
- aghi %r15,-STACK_FRAME_OVERHEAD
- xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
- lg %r12,__LC_THREAD_INFO
- ssm __LC_SVC_NEW_PSW # reenable interrupts
- j sysc_return
+ j sysc_tracenogo
/*
* Program check handler routine
diff --git a/arch/s390/kernel/head_kdump.S b/arch/s390/kernel/head_kdump.S
index acaaaf4b7055..085a95eb315f 100644
--- a/arch/s390/kernel/head_kdump.S
+++ b/arch/s390/kernel/head_kdump.S
@@ -85,16 +85,10 @@
.align 2
startup_kdump_relocated:
basr %r13,0
-0:
- mvc 0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
- sam31 # Switch to 31 bit addr mode
- sr %r1,%r1 # Erase register r1
- sr %r2,%r2 # Erase register r2
- sigp %r1,%r2,SIGP_SET_ARCHITECTURE # Switch to 31 bit arch mode
- lpsw 0 # Start new kernel...
+0: lpswe .Lrestart_psw-0b(%r13) # Start new kernel...
.align 8
.Lrestart_psw:
- .long 0x00080000,0x80000000 + startup
+ .quad 0x0000000080000000,0x0000000000000000 + startup
#else
.align 2
.Lep_startup_kdump:
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index 9871b1971ed7..c4e7269d4a09 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -94,7 +94,7 @@ static int get_counter_set(u64 event)
set = CPUMF_CTR_SET_USER;
else if (event < 128)
set = CPUMF_CTR_SET_CRYPTO;
- else if (event < 160)
+ else if (event < 256)
set = CPUMF_CTR_SET_EXT;
return set;
@@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
case CPUMF_CTR_SET_EXT:
if (cpuhw->info.csvn < 1)
err = -EOPNOTSUPP;
+ if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
+ (cpuhw->info.csvn == 2 && hwc->config > 175) ||
+ (cpuhw->info.csvn > 2 && hwc->config > 255))
+ err = -EOPNOTSUPP;
break;
}
diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S
index bf053898630d..b6506ee32a36 100644
--- a/arch/s390/kernel/sclp.S
+++ b/arch/s390/kernel/sclp.S
@@ -44,6 +44,12 @@ _sclp_wait_int:
#endif
mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
mvc 0(16,%r8),0(%r9)
+#ifdef CONFIG_64BIT
+ epsw %r6,%r7 # set current addressing mode
+ nill %r6,0x1 # in new psw (31 or 64 bit mode)
+ nilh %r7,0x8000
+ stm %r6,%r7,0(%r8)
+#endif
lhi %r6,0x0200 # cr mask for ext int (cr0.54)
ltr %r2,%r2
jz .LsetctS1
@@ -87,7 +93,7 @@ _sclp_wait_int:
.long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
#ifdef CONFIG_64BIT
.LextpswS1_64:
- .quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit
+ .quad 0, .LwaitS1 # PSW to handle ext int, 64 bit
#endif
.LwaitpswS1:
.long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index c13a2a37ef00..d1259d875074 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(user_sregs.regs.psw.mask & PSW_MASK_USER);
+ /* Check for invalid user address space control. */
+ if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+ regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
/* Check for invalid amode */
if (regs->psw.mask & PSW_MASK_EA)
regs->psw.mask |= PSW_MASK_BA;
@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
+ /* Force default amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame;
- regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */
+ /* Force default amode and default user address space control. */
+ regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+ (psw_user_bits & PSW_MASK_ASC) |
+ (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig);
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 54d93f4b6818..dd55f7c20104 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock);
static struct mask_info core_info;
cpumask_t cpu_core_map[NR_CPUS];
unsigned char cpu_core_id[NR_CPUS];
+unsigned char cpu_socket_id[NR_CPUS];
static struct mask_info book_info;
cpumask_t cpu_book_map[NR_CPUS];
@@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
cpumask_set_cpu(lcpu, &book->mask);
cpu_book_id[lcpu] = book->id;
cpumask_set_cpu(lcpu, &core->mask);
+ cpu_core_id[lcpu] = rcpu;
if (one_core_per_cpu) {
- cpu_core_id[lcpu] = rcpu;
+ cpu_socket_id[lcpu] = rcpu;
core = core->next;
} else {
- cpu_core_id[lcpu] = core->id;
+ cpu_socket_id[lcpu] = core->id;
}
smp_cpu_set_polarization(lcpu, tl_cpu->pp);
}
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index de8fa9bbd35e..79cb51adc741 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -8,7 +8,7 @@
#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
ENTRY(startup)
jiffies = jiffies_64 + 4;
#else