summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/Kconfig.debug8
-rw-r--r--arch/s390/kernel/entry.S7
-rw-r--r--arch/s390/kernel/entry64.S7
-rw-r--r--arch/s390/kernel/ipl.c27
-rw-r--r--arch/s390/kernel/setup.c14
-rw-r--r--arch/s390/kernel/smp.c13
-rw-r--r--arch/s390/kernel/stacktrace.c31
-rw-r--r--arch/s390/kernel/traps.c5
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/mm/init.c27
-rw-r--r--arch/s390/mm/vmem.c5
12 files changed, 108 insertions, 46 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 82cbffd0365..92a4f7b4323 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT
config STACKTRACE_SUPPORT
def_bool y
+config HAVE_LATENCYTOP_SUPPORT
+ def_bool y
+
config RWSEM_GENERIC_SPINLOCK
bool
@@ -47,6 +50,11 @@ config NO_IOMEM
config NO_DMA
def_bool y
+config GENERIC_LOCKBREAK
+ bool
+ default y
+ depends on SMP && PREEMPT
+
mainmenu "Linux Kernel Configuration"
config S390
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 2283933a9a9..4599fa06bd8 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -6,4 +6,12 @@ config TRACE_IRQFLAGS_SUPPORT
source "lib/Kconfig.debug"
+config DEBUG_PAGEALLOC
+ bool "Debug page memory allocations"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a slowdown, but helps to find certain types of
+ memory corruptions.
+
endmenu
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1a6dac8df6f..6766e37fe8e 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -830,9 +831,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -845,9 +844,7 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index a3e47b893f0..efde6e178f6 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -11,6 +11,7 @@
#include <linux/sys.h>
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/cache.h>
#include <asm/lowcore.h>
#include <asm/errno.h>
@@ -801,9 +802,7 @@ mcck_return:
* Restart interruption handler, kick starter for additional CPUs
*/
#ifdef CONFIG_SMP
-#ifndef CONFIG_HOTPLUG_CPU
- .section .init.text,"ax"
-#endif
+ __CPUINIT
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -814,9 +813,7 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
-#ifndef CONFIG_HOTPLUG_CPU
.previous
-#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index db28cca81fe..60acdc266db 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -439,7 +439,7 @@ static void ipl_run(struct shutdown_trigger *trigger)
reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
}
-static int ipl_init(void)
+static int __init ipl_init(void)
{
int rc;
@@ -471,8 +471,11 @@ out:
return 0;
}
-static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
- ipl_init};
+static struct shutdown_action __refdata ipl_action = {
+ .name = SHUTDOWN_ACTION_IPL_STR,
+ .fn = ipl_run,
+ .init = ipl_init,
+};
/*
* reipl shutdown action: Reboot Linux on shutdown.
@@ -792,7 +795,7 @@ static int __init reipl_fcp_init(void)
return 0;
}
-static int reipl_init(void)
+static int __init reipl_init(void)
{
int rc;
@@ -819,8 +822,11 @@ static int reipl_init(void)
return 0;
}
-static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
- reipl_run, reipl_init};
+static struct shutdown_action __refdata reipl_action = {
+ .name = SHUTDOWN_ACTION_REIPL_STR,
+ .fn = reipl_run,
+ .init = reipl_init,
+};
/*
* dump shutdown action: Dump Linux on shutdown.
@@ -998,7 +1004,7 @@ static int __init dump_fcp_init(void)
return 0;
}
-static int dump_init(void)
+static int __init dump_init(void)
{
int rc;
@@ -1020,8 +1026,11 @@ static int dump_init(void)
return 0;
}
-static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
- dump_run, dump_init};
+static struct shutdown_action __refdata dump_action = {
+ .name = SHUTDOWN_ACTION_DUMP_STR,
+ .fn = dump_run,
+ .init = dump_init,
+};
/*
* vmcmd shutdown action: Trigger vm command on shutdown.
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 766c783bd7a..29ae165d174 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -77,7 +77,7 @@ unsigned long machine_flags = 0;
unsigned long elf_hwcap = 0;
char elf_platform[ELF_PLATFORM_SIZE];
-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
+struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
static unsigned long __initdata memory_end;
@@ -145,7 +145,7 @@ __setup("condev=", condev_setup);
static int __init conmode_setup(char *str)
{
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
SET_CONSOLE_SCLP;
#endif
@@ -183,7 +183,7 @@ static void __init conmode_default(void)
*/
cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
return;
@@ -193,7 +193,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#elif defined(CONFIG_TN3215_CONSOLE)
SET_CONSOLE_3215;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
} else if (strncmp(ptr + 8, "3215", 4) == 0) {
@@ -201,7 +201,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3215;
#elif defined(CONFIG_TN3270_CONSOLE)
SET_CONSOLE_3270;
-#elif defined(CONFIG_SCLP_CONSOLE)
+#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -212,7 +212,7 @@ static void __init conmode_default(void)
SET_CONSOLE_3270;
#endif
} else {
-#if defined(CONFIG_SCLP_CONSOLE)
+#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
SET_CONSOLE_SCLP;
#endif
}
@@ -528,7 +528,7 @@ static void __init setup_memory_end(void)
memory_size = 0;
memory_end &= PAGE_MASK;
- max_mem = memory_end ? min(VMALLOC_START, memory_end) : VMALLOC_START;
+ max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS;
memory_end = min(max_mem, memory_end);
/*
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index aa37fa15451..85060659fb1 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -225,12 +225,11 @@ EXPORT_SYMBOL(smp_call_function_single);
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler.
*/
-int
-smp_call_function_mask(cpumask_t mask,
- void (*func)(void *), void *info,
- int wait)
+int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
+ int wait)
{
preempt_disable();
+ cpu_clear(smp_processor_id(), mask);
__smp_call_function_map(func, info, 0, wait, mask);
preempt_enable();
return 0;
@@ -1008,7 +1007,7 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
.notifier_call = smp_cpu_notify,
};
-static int smp_add_present_cpu(int cpu)
+static int __devinit smp_add_present_cpu(int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
struct sys_device *s = &c->sysdev;
@@ -1036,8 +1035,8 @@ out:
}
#ifdef CONFIG_HOTPLUG_CPU
-static ssize_t rescan_store(struct sys_device *dev, const char *buf,
- size_t count)
+static ssize_t __ref rescan_store(struct sys_device *dev,
+ const char *buf, size_t count)
{
cpumask_t newcpus;
int cpu;
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index da692472996..85e46a5d0e0 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -14,7 +14,8 @@
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
unsigned long low,
- unsigned long high)
+ unsigned long high,
+ int savesched)
{
struct stack_frame *sf;
struct pt_regs *regs;
@@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace,
return sp;
regs = (struct pt_regs *)sp;
addr = regs->psw.addr & PSW_ADDR_INSN;
- if (!trace->skip)
- trace->entries[trace->nr_entries++] = addr;
- else
- trace->skip--;
+ if (savesched || !in_sched_functions(addr)) {
+ if (!trace->skip)
+ trace->entries[trace->nr_entries++] = addr;
+ else
+ trace->skip--;
+ }
if (trace->nr_entries >= trace->max_entries)
return sp;
low = sp;
@@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace)
orig_sp = sp & PSW_ADDR_INSN;
new_sp = save_context_stack(trace, orig_sp,
S390_lowcore.panic_stack - PAGE_SIZE,
- S390_lowcore.panic_stack);
+ S390_lowcore.panic_stack, 1);
if (new_sp != orig_sp)
return;
new_sp = save_context_stack(trace, new_sp,
S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
+ S390_lowcore.async_stack, 1);
if (new_sp != orig_sp)
return;
save_context_stack(trace, new_sp,
S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+ S390_lowcore.thread_info + THREAD_SIZE, 1);
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+ unsigned long sp, low, high;
+
+ sp = tsk->thread.ksp & PSW_ADDR_INSN;
+ low = (unsigned long) task_stack_page(tsk);
+ high = (unsigned long) task_pt_regs(tsk);
+ save_context_stack(trace, sp, low, high, 0);
+ if (trace->nr_entries < trace->max_entries)
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 52b8342c6bf..1a2fdb6991d 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -271,7 +271,10 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("PREEMPT ");
#endif
#ifdef CONFIG_SMP
- printk("SMP");
+ printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 7d43c3cd3ef..b4607155e8d 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -35,7 +35,7 @@ SECTIONS
KPROBES_TEXT
*(.fixup)
*(.gnu.warning)
- } = 0x0700
+ } :text = 0x0700
_etext = .; /* End of text section */
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index b234bb4a6da..983ec6ec0e7 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -167,6 +167,33 @@ void __init mem_init(void)
PFN_ALIGN((unsigned long)&_eshared) - 1);
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long address;
+ int i;
+
+ for (i = 0; i < numpages; i++) {
+ address = page_to_phys(page + i);
+ pgd = pgd_offset_k(address);
+ pud = pud_offset(pgd, address);
+ pmd = pmd_offset(pud, address);
+ pte = pte_offset_kernel(pmd, address);
+ if (!enable) {
+ ptep_invalidate(address, pte);
+ continue;
+ }
+ *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
+ /* Flush cpu write queue. */
+ mb();
+ }
+}
+#endif
+
void free_initmem(void)
{
unsigned long addr;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 79d13a166a3..7c1287ccf78 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -62,7 +62,7 @@ void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
}
}
-static void __init_refok *vmem_alloc_pages(unsigned int order)
+static void __ref *vmem_alloc_pages(unsigned int order)
{
if (slab_is_available())
return (void *)__get_free_pages(GFP_KERNEL, order);
@@ -250,7 +250,7 @@ static int insert_memory_segment(struct memory_segment *seg)
{
struct memory_segment *tmp;
- if (seg->start + seg->size >= VMALLOC_START ||
+ if (seg->start + seg->size >= VMEM_MAX_PHYS ||
seg->start + seg->size < seg->start)
return -ERANGE;
@@ -360,7 +360,6 @@ void __init vmem_map_init(void)
{
int i;
- BUILD_BUG_ON((unsigned long)VMEM_MAP + VMEM_MAP_SIZE > VMEM_MAP_MAX);
NODE_DATA(0)->node_mem_map = VMEM_MAP;
for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);