forked from Minki/linux
x86-64: Convert irqstacks to per-cpu
Move the irqstackptr variable from the PDA to per-cpu. Make the stacks themselves per-cpu, removing some specific allocation code. Add a seperate flag (is_boot_cpu) to simplify the per-cpu boot adjustments. tj: * sprinkle some underbars around. * irq_stack_ptr is not used till traps_init(), no reason to initialize it early. On SMP, just leaving it NULL till proper initialization in setup_per_cpu_areas() works. Dropped is_boot_cpu and early irq_stack_ptr initialization. * do DECLARE/DEFINE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack) instead of (char, irq_stack[IRQ_STACK_SIZE]). Signed-off-by: Brian Gerst <brgerst@gmail.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
9eb912d1aa
commit
26f80bd6a9
@ -13,8 +13,8 @@
|
||||
#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1)
|
||||
#define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)
|
||||
|
||||
#define IRQSTACK_ORDER 2
|
||||
#define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER)
|
||||
#define IRQ_STACK_ORDER 2
|
||||
#define IRQ_STACK_SIZE (PAGE_SIZE << IRQ_STACK_ORDER)
|
||||
|
||||
#define STACKFAULT_STACK 1
|
||||
#define DOUBLEFAULT_STACK 2
|
||||
|
@ -22,7 +22,6 @@ struct x8664_pda {
|
||||
/* gcc-ABI: this canary MUST be at
|
||||
offset 40!!! */
|
||||
#endif
|
||||
char *irqstackptr;
|
||||
short nodenumber; /* number of current node (32k max) */
|
||||
short in_bootmem; /* pda lives in bootmem */
|
||||
short isidle;
|
||||
|
@ -378,6 +378,9 @@ union thread_xstate {
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
DECLARE_PER_CPU(struct orig_ist, orig_ist);
|
||||
|
||||
DECLARE_PER_CPU(char[IRQ_STACK_SIZE], irq_stack);
|
||||
DECLARE_PER_CPU(char *, irq_stack_ptr);
|
||||
#endif
|
||||
|
||||
extern void print_cpu_info(struct cpuinfo_x86 *);
|
||||
|
@ -54,7 +54,6 @@ int main(void)
|
||||
ENTRY(pcurrent);
|
||||
ENTRY(irqcount);
|
||||
ENTRY(cpunumber);
|
||||
ENTRY(irqstackptr);
|
||||
DEFINE(pda_size, sizeof(struct x8664_pda));
|
||||
BLANK();
|
||||
#undef ENTRY
|
||||
|
@ -881,7 +881,13 @@ __setup("clearcpuid=", setup_disablecpuid);
|
||||
#ifdef CONFIG_X86_64
|
||||
struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
|
||||
|
||||
static char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss;
|
||||
DEFINE_PER_CPU_PAGE_ALIGNED(char[IRQ_STACK_SIZE], irq_stack);
|
||||
#ifdef CONFIG_SMP
|
||||
DEFINE_PER_CPU(char *, irq_stack_ptr); /* will be set during per cpu init */
|
||||
#else
|
||||
DEFINE_PER_CPU(char *, irq_stack_ptr) =
|
||||
per_cpu_var(irq_stack) + IRQ_STACK_SIZE - 64;
|
||||
#endif
|
||||
|
||||
void __cpuinit pda_init(int cpu)
|
||||
{
|
||||
@ -901,18 +907,7 @@ void __cpuinit pda_init(int cpu)
|
||||
if (cpu == 0) {
|
||||
/* others are initialized in smpboot.c */
|
||||
pda->pcurrent = &init_task;
|
||||
pda->irqstackptr = boot_cpu_stack;
|
||||
pda->irqstackptr += IRQSTACKSIZE - 64;
|
||||
} else {
|
||||
if (!pda->irqstackptr) {
|
||||
pda->irqstackptr = (char *)
|
||||
__get_free_pages(GFP_ATOMIC, IRQSTACK_ORDER);
|
||||
if (!pda->irqstackptr)
|
||||
panic("cannot allocate irqstack for cpu %d",
|
||||
cpu);
|
||||
pda->irqstackptr += IRQSTACKSIZE - 64;
|
||||
}
|
||||
|
||||
if (pda->nodenumber == 0 && cpu_to_node(cpu) != NUMA_NO_NODE)
|
||||
pda->nodenumber = cpu_to_node(cpu);
|
||||
}
|
||||
|
@ -106,7 +106,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
|
||||
const struct stacktrace_ops *ops, void *data)
|
||||
{
|
||||
const unsigned cpu = get_cpu();
|
||||
unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
|
||||
unsigned long *irq_stack_end =
|
||||
(unsigned long *)per_cpu(irq_stack_ptr, cpu);
|
||||
unsigned used = 0;
|
||||
struct thread_info *tinfo;
|
||||
int graph = 0;
|
||||
@ -160,23 +161,23 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
|
||||
stack = (unsigned long *) estack_end[-2];
|
||||
continue;
|
||||
}
|
||||
if (irqstack_end) {
|
||||
unsigned long *irqstack;
|
||||
irqstack = irqstack_end -
|
||||
(IRQSTACKSIZE - 64) / sizeof(*irqstack);
|
||||
if (irq_stack_end) {
|
||||
unsigned long *irq_stack;
|
||||
irq_stack = irq_stack_end -
|
||||
(IRQ_STACK_SIZE - 64) / sizeof(*irq_stack);
|
||||
|
||||
if (stack >= irqstack && stack < irqstack_end) {
|
||||
if (stack >= irq_stack && stack < irq_stack_end) {
|
||||
if (ops->stack(data, "IRQ") < 0)
|
||||
break;
|
||||
bp = print_context_stack(tinfo, stack, bp,
|
||||
ops, data, irqstack_end, &graph);
|
||||
ops, data, irq_stack_end, &graph);
|
||||
/*
|
||||
* We link to the next stack (which would be
|
||||
* the process stack normally) the last
|
||||
* pointer (index -1 to end) in the IRQ stack:
|
||||
*/
|
||||
stack = (unsigned long *) (irqstack_end[-1]);
|
||||
irqstack_end = NULL;
|
||||
stack = (unsigned long *) (irq_stack_end[-1]);
|
||||
irq_stack_end = NULL;
|
||||
ops->stack(data, "EOI");
|
||||
continue;
|
||||
}
|
||||
@ -199,10 +200,10 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||
unsigned long *stack;
|
||||
int i;
|
||||
const int cpu = smp_processor_id();
|
||||
unsigned long *irqstack_end =
|
||||
(unsigned long *) (cpu_pda(cpu)->irqstackptr);
|
||||
unsigned long *irqstack =
|
||||
(unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
|
||||
unsigned long *irq_stack_end =
|
||||
(unsigned long *)(per_cpu(irq_stack_ptr, cpu));
|
||||
unsigned long *irq_stack =
|
||||
(unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE);
|
||||
|
||||
/*
|
||||
* debugging aid: "show_stack(NULL, NULL);" prints the
|
||||
@ -218,9 +219,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
|
||||
|
||||
stack = sp;
|
||||
for (i = 0; i < kstack_depth_to_print; i++) {
|
||||
if (stack >= irqstack && stack <= irqstack_end) {
|
||||
if (stack == irqstack_end) {
|
||||
stack = (unsigned long *) (irqstack_end[-1]);
|
||||
if (stack >= irq_stack && stack <= irq_stack_end) {
|
||||
if (stack == irq_stack_end) {
|
||||
stack = (unsigned long *) (irq_stack_end[-1]);
|
||||
printk(" <EOI> ");
|
||||
}
|
||||
} else {
|
||||
|
@ -345,7 +345,7 @@ ENTRY(save_args)
|
||||
1: incl %gs:pda_irqcount
|
||||
jne 2f
|
||||
popq_cfi %rax /* move return address... */
|
||||
mov %gs:pda_irqstackptr,%rsp
|
||||
mov PER_CPU_VAR(irq_stack_ptr),%rsp
|
||||
EMPTY_FRAME 0
|
||||
pushq_cfi %rax /* ... to the new stack */
|
||||
/*
|
||||
@ -1261,7 +1261,7 @@ ENTRY(call_softirq)
|
||||
mov %rsp,%rbp
|
||||
CFI_DEF_CFA_REGISTER rbp
|
||||
incl %gs:pda_irqcount
|
||||
cmove %gs:pda_irqstackptr,%rsp
|
||||
cmove PER_CPU_VAR(irq_stack_ptr),%rsp
|
||||
push %rbp # backlink for old unwinder
|
||||
call __do_softirq
|
||||
leaveq
|
||||
@ -1300,7 +1300,7 @@ ENTRY(xen_do_hypervisor_callback) # do_hypervisor_callback(struct *pt_regs)
|
||||
11: incl %gs:pda_irqcount
|
||||
movq %rsp,%rbp
|
||||
CFI_DEF_CFA_REGISTER rbp
|
||||
cmovzq %gs:pda_irqstackptr,%rsp
|
||||
cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp
|
||||
pushq %rbp # backlink for old unwinder
|
||||
call xen_evtchn_do_upcall
|
||||
popq %rsp
|
||||
|
@ -192,7 +192,10 @@ void __init setup_per_cpu_areas(void)
|
||||
|
||||
memcpy(ptr, __per_cpu_load, __per_cpu_end - __per_cpu_start);
|
||||
per_cpu_offset(cpu) = ptr - __per_cpu_start;
|
||||
per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
|
||||
#ifdef CONFIG_X86_64
|
||||
per_cpu(irq_stack_ptr, cpu) =
|
||||
(char *)per_cpu(irq_stack, cpu) + IRQ_STACK_SIZE - 64;
|
||||
/*
|
||||
* CPU0 modified pda in the init data area, reload pda
|
||||
* offset for CPU0 and clear the area for others.
|
||||
@ -202,7 +205,6 @@ void __init setup_per_cpu_areas(void)
|
||||
else
|
||||
memset(cpu_pda(cpu), 0, sizeof(*cpu_pda(cpu)));
|
||||
#endif
|
||||
per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
|
||||
|
||||
DBG("PERCPU: cpu %4d %p\n", cpu, ptr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user