Commit d6ab9fc7 authored by Helge Deller's avatar Helge Deller

parisc: Enable TOC (transfer of contents) feature unconditionally

Before this patch, the TOC code used a pre-allocated stack of 16kb for
each possible CPU. That space overhead was the reason why the TOC
feature wasn't enabled by default for 32-bit kernels.

This patch rewrites the TOC code to use a per-cpu stack. That way we use
much less memory now and as such we enable the TOC feature by default on
all kernels.

Additionally the dump of the registers and the stacktrace wasn't
serialized, which led to multiple CPUs printing the stack backtrace at
once which rendered the output unreadable.
Now the backtraces are nicely serialized by a lock.
Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent 6968e707
...@@ -287,20 +287,6 @@ config SMP ...@@ -287,20 +287,6 @@ config SMP
If you don't know what to do here, say N. If you don't know what to do here, say N.
config TOC
bool "Support TOC switch"
default y if 64BIT || !SMP
help
Most PA-RISC machines have either a switch at the back of the machine
or a command in BMC to trigger a TOC interrupt. If you say Y here a
handler will be installed which will either show a backtrace on all
CPUs, or enter a possible configured debugger like kgdb/kdb.
Note that with this option enabled, the kernel will use an additional 16KB
per possible CPU as a special stack for the TOC handler.
If you don't want to debug the Kernel, say N.
config PARISC_CPU_TOPOLOGY config PARISC_CPU_TOPOLOGY
bool "Support cpu topology definition" bool "Support cpu topology definition"
depends on SMP depends on SMP
......
...@@ -10,7 +10,7 @@ obj-y := cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \ ...@@ -10,7 +10,7 @@ obj-y := cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \
ptrace.o hardware.o inventory.o drivers.o alternative.o \ ptrace.o hardware.o inventory.o drivers.o alternative.o \
signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \
patch.o patch.o toc.o toc_asm.o
ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_FUNCTION_TRACER
# Do not profile debug and lowlevel utilities # Do not profile debug and lowlevel utilities
...@@ -39,4 +39,3 @@ obj-$(CONFIG_KGDB) += kgdb.o ...@@ -39,4 +39,3 @@ obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o obj-$(CONFIG_KEXEC_CORE) += kexec.o relocate_kernel.o
obj-$(CONFIG_KEXEC_FILE) += kexec_file.o obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
obj-$(CONFIG_TOC) += toc.o toc_asm.o
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
int main(void) int main(void)
{ {
DEFINE(TASK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); DEFINE(TASK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
#ifdef CONFIG_SMP
DEFINE(TASK_TI_CPU, offsetof(struct task_struct, thread_info.cpu));
#endif
DEFINE(TASK_STACK, offsetof(struct task_struct, stack)); DEFINE(TASK_STACK, offsetof(struct task_struct, stack));
DEFINE(TASK_PAGEFAULT_DISABLED, offsetof(struct task_struct, pagefault_disabled)); DEFINE(TASK_PAGEFAULT_DISABLED, offsetof(struct task_struct, pagefault_disabled));
BLANK(); BLANK();
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
#include <asm/pdc.h> #include <asm/pdc.h>
#include <asm/pdc_chassis.h> #include <asm/pdc_chassis.h>
#include <asm/ldcw.h>
unsigned int __aligned(16) toc_lock = 1; static unsigned int __aligned(16) toc_lock = 1;
DEFINE_PER_CPU_PAGE_ALIGNED(char [16384], toc_stack);
static void toc20_to_pt_regs(struct pt_regs *regs, struct pdc_toc_pim_20 *toc) static void toc20_to_pt_regs(struct pt_regs *regs, struct pdc_toc_pim_20 *toc)
{ {
...@@ -63,7 +65,8 @@ void notrace __noreturn __cold toc_intr(struct pt_regs *regs) ...@@ -63,7 +65,8 @@ void notrace __noreturn __cold toc_intr(struct pt_regs *regs)
struct pdc_toc_pim_20 pim_data20; struct pdc_toc_pim_20 pim_data20;
struct pdc_toc_pim_11 pim_data11; struct pdc_toc_pim_11 pim_data11;
nmi_enter(); /* verify we wrote regs to the correct stack */
BUG_ON(regs != (struct pt_regs *)&per_cpu(toc_stack, raw_smp_processor_id()));
if (boot_cpu_data.cpu_type >= pcxu) { if (boot_cpu_data.cpu_type >= pcxu) {
if (pdc_pim_toc20(&pim_data20)) if (pdc_pim_toc20(&pim_data20))
...@@ -76,14 +79,25 @@ void notrace __noreturn __cold toc_intr(struct pt_regs *regs) ...@@ -76,14 +79,25 @@ void notrace __noreturn __cold toc_intr(struct pt_regs *regs)
} }
#ifdef CONFIG_KGDB #ifdef CONFIG_KGDB
nmi_enter();
if (atomic_read(&kgdb_active) != -1) if (atomic_read(&kgdb_active) != -1)
kgdb_nmicallback(raw_smp_processor_id(), regs); kgdb_nmicallback(raw_smp_processor_id(), regs);
kgdb_handle_exception(9, SIGTRAP, 0, regs); kgdb_handle_exception(9, SIGTRAP, 0, regs);
#endif #endif
/* serialize output, otherwise all CPUs write backtrace at once */
while (__ldcw(&toc_lock) == 0)
; /* wait */
show_regs(regs); show_regs(regs);
toc_lock = 1; /* release lock for next CPU */
if (raw_smp_processor_id() != 0)
while (1) ; /* all but monarch CPU will wait endless. */
/* give other CPUs time to show their backtrace */ /* give other CPUs time to show their backtrace */
mdelay(2000); mdelay(2000);
machine_restart("TOC"); machine_restart("TOC");
/* should never reach this */ /* should never reach this */
......
...@@ -5,34 +5,25 @@ ...@@ -5,34 +5,25 @@
.level 1.1 .level 1.1
#include <asm/assembly.h> #include <asm/assembly.h>
#include <asm/psw.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/linkage.h> #include <linux/linkage.h>
.text .text
.import toc_intr,code .import toc_intr,code
.import toc_lock,data .import toc_stack,data
.align 16 .align 16
ENTRY_CFI(toc_handler) ENTRY_CFI(toc_handler)
/*
* synchronize CPUs and obtain offset
* for stack setup.
*/
load32 PA(toc_lock),%r1
0: ldcw,co 0(%r1),%r2
cmpib,= 0,%r2,0b
nop
addi 1,%r2,%r4
stw %r4,0(%r1)
addi -1,%r2,%r4
load32 PA(toc_stack),%sp load32 PA(toc_stack),%sp
/*
* deposit CPU number into stack address, #ifdef CONFIG_SMP
* so every CPU will have its own stack. /* get per-cpu toc_stack address. */
*/ mfctl %cr30, %r1
SHLREG %r4,14,%r4 tophys %r1,%r2 /* task_struct */
LDREG TASK_TI_CPU(%r2),%r4 /* cpu */
load32 PA(__per_cpu_offset),%r1
LDREGX %r4(%r1),%r4
add %r4,%sp,%sp add %r4,%sp,%sp
#endif
/* /*
* setup pt_regs on stack and save the * setup pt_regs on stack and save the
...@@ -82,7 +73,3 @@ ENDPROC_CFI(toc_handler) ...@@ -82,7 +73,3 @@ ENDPROC_CFI(toc_handler)
*/ */
SYM_DATA(toc_handler_csum, .long 0) SYM_DATA(toc_handler_csum, .long 0)
SYM_DATA(toc_handler_size, .long . - toc_handler) SYM_DATA(toc_handler_size, .long . - toc_handler)
__PAGE_ALIGNED_BSS
.align 64
SYM_DATA(toc_stack, .block 16384*NR_CPUS)
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