Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36315
b: refs/heads/master
c: a6a3113
h: refs/heads/master
i:
  36313: 2e033a9
  36311: 6466b20
v: v3
  • Loading branch information
Paul Mundt committed Sep 27, 2006
1 parent 295ee8f commit 4a5906d
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 25 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2cb7ce3bb384f30a377f66336c78546b834604df
refs/heads/master: a6a31139897a5e539efe7ad3b7bd351fa9673ce8
10 changes: 10 additions & 0 deletions trunk/arch/sh/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ config DEBUG_STACK_USAGE

This option will slow down process creation somewhat.

config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
depends on DEBUG_KERNEL
help
If you say Y here the kernel will use a 4Kb stacksize for the
kernel stack attached to each process/thread. This facilitates
running more threads on a system and also reduces the pressure
on the VM subsystem for higher order allocations. This option
will also use IRQ stacks to compensate for the reduced stackspace.

config KGDB
bool "Include KGDB kernel debugger"
select FRAME_POINTER
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/sh/kernel/cpu/irq/ipr.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ void __init init_IRQ(void)
/* Perform the machine specific initialisation */
if (sh_mv.mv_init_irq != NULL)
sh_mv.mv_init_irq();

irq_ctx_init(smp_processor_id());
}

#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/sh/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,8 @@ ENTRY(handle_exception)
bt/s 1f ! It's a kernel to kernel transition.
mov r15, k0 ! save original stack to k0
/* User space to kernel */
mov #0x20, k1
shll8 k1 ! k1 := 8192 (== THREAD_SIZE)
mov #(THREAD_SIZE >> 8), k1
shll8 k1 ! k1 := THREAD_SIZE
add current, k1
mov k1, r15 ! change to kernel stack
!
Expand Down
5 changes: 2 additions & 3 deletions trunk/arch/sh/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/page.h>

#ifdef CONFIG_CPU_SH4A
#define SYNCO() synco
Expand Down Expand Up @@ -69,8 +68,8 @@ ENTRY(_stext)
!
mov.l 2f, r0
mov r0, r15 ! Set initial r15 (stack pointer)
mov #0x20, r1 !
shll8 r1 ! r1 = 8192
mov #(THREAD_SIZE >> 8), r1
shll8 r1 ! r1 = THREAD_SIZE
sub r1, r0 !
ldc r0, r7_bank ! ... and initial thread_info

Expand Down
153 changes: 149 additions & 4 deletions trunk/arch/sh/kernel/irq.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $
*
/*
* linux/arch/sh/kernel/irq.c
*
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
*
*
* SuperH version: Copyright (C) 1999 Niibe Yutaka
*/

#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <asm/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/thread_info.h>
#include <asm/cpu/mmu_context.h>

/*
Expand Down Expand Up @@ -60,11 +61,27 @@ int show_interrupts(struct seq_file *p, void *v)
}
#endif

#ifdef CONFIG_4KSTACKS
/*
* per-CPU IRQ handling contexts (thread information and stack)
*/
union irq_ctx {
struct thread_info tinfo;
u32 stack[THREAD_SIZE/sizeof(u32)];
};

static union irq_ctx *hardirq_ctx[NR_CPUS];
static union irq_ctx *softirq_ctx[NR_CPUS];
#endif

asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
int irq = r4;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
#endif

irq_enter();

Expand Down Expand Up @@ -102,7 +119,135 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif

irq = irq_demux(irq);
__do_IRQ(irq, &regs);

#ifdef CONFIG_4KSTACKS
curctx = (union irq_ctx *)current_thread_info();
irqctx = hardirq_ctx[smp_processor_id()];

/*
* this is where we switch to the IRQ stack. However, if we are
* already using the IRQ stack (because we interrupted a hardirq
* handler) we can't do that and just have to keep using the
* current stack (which is the irq stack already after all)
*/
if (curctx != irqctx) {
u32 *isp;

isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_sp = current_stack_pointer;

__asm__ __volatile__ (
"mov %0, r4 \n"
"mov %1, r5 \n"
"mov r15, r9 \n"
"jsr @%2 \n"
/* swith to the irq stack */
" mov %3, r15 \n"
/* restore the stack (ring zero) */
"mov r9, r15 \n"
: /* no outputs */
: "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
/* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "t", "pr"
);
} else
#endif
__do_IRQ(irq, &regs);

irq_exit();

return 1;
}

#ifdef CONFIG_4KSTACKS
/*
* These should really be __section__(".bss.page_aligned") as well, but
* gcc's 3.0 and earlier don't handle that correctly.
*/
static char softirq_stack[NR_CPUS * THREAD_SIZE]
__attribute__((__aligned__(THREAD_SIZE)));

static char hardirq_stack[NR_CPUS * THREAD_SIZE]
__attribute__((__aligned__(THREAD_SIZE)));

/*
* allocate per-cpu stacks for hardirq and for softirq processing
*/
void irq_ctx_init(int cpu)
{
union irq_ctx *irqctx;

if (hardirq_ctx[cpu])
return;

irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE];
irqctx->tinfo.task = NULL;
irqctx->tinfo.exec_domain = NULL;
irqctx->tinfo.cpu = cpu;
irqctx->tinfo.preempt_count = HARDIRQ_OFFSET;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);

hardirq_ctx[cpu] = irqctx;

irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE];
irqctx->tinfo.task = NULL;
irqctx->tinfo.exec_domain = NULL;
irqctx->tinfo.cpu = cpu;
irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);

softirq_ctx[cpu] = irqctx;

printk("CPU %u irqstacks, hard=%p soft=%p\n",
cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
}

void irq_ctx_exit(int cpu)
{
hardirq_ctx[cpu] = NULL;
}

extern asmlinkage void __do_softirq(void);

asmlinkage void do_softirq(void)
{
unsigned long flags;
struct thread_info *curctx;
union irq_ctx *irqctx;
u32 *isp;

if (in_interrupt())
return;

local_irq_save(flags);

if (local_softirq_pending()) {
curctx = current_thread_info();
irqctx = softirq_ctx[smp_processor_id()];
irqctx->tinfo.task = curctx->task;
irqctx->tinfo.previous_sp = current_stack_pointer;

/* build the stack frame on the softirq stack */
isp = (u32 *)((char *)irqctx + sizeof(*irqctx));

__asm__ __volatile__ (
"mov r15, r9 \n"
"jsr @%0 \n"
/* switch to the softirq stack */
" mov %1, r15 \n"
/* restore the thread stack */
"mov r9, r15 \n"
: /* no outputs */
: "r" (__do_softirq), "r" (isp)
/* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);
}

local_irq_restore(flags);
}
EXPORT_SYMBOL(do_softirq);
#endif
18 changes: 5 additions & 13 deletions trunk/arch/sh/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,20 +741,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
unsigned long module_end = VMALLOC_END;
int i = 1;

if (tsk && !sp) {
if (!tsk)
tsk = current;
if (tsk == current)
sp = (unsigned long *)current_stack_pointer;
else
sp = (unsigned long *)tsk->thread.sp;
}

if (!sp) {
__asm__ __volatile__ (
"mov r15, %0\n\t"
"stc r7_bank, %1\n\t"
: "=r" (module_start),
"=r" (module_end)
);

sp = (unsigned long *)module_start;
}

stack = sp;

Expand Down
1 change: 0 additions & 1 deletion trunk/arch/sh/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Written by Niibe Yutaka
*/
#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>

#ifdef CONFIG_CPU_LITTLE_ENDIAN
Expand Down
9 changes: 9 additions & 0 deletions trunk/include/asm-sh/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,15 @@ static inline int generic_irq_demux(int irq)
#define irq_canonicalize(irq) (irq)
#define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq))

#ifdef CONFIG_4KSTACKS
extern void irq_ctx_init(int cpu);
extern void irq_ctx_exit(int cpu);
# define __ARCH_HAS_DO_SOFTIRQ
#else
# define irq_ctx_init(cpu) do { } while (0)
# define irq_ctx_exit(cpu) do { } while (0)
#endif

#if defined(CONFIG_CPU_SUBTYPE_SH73180)
#include <asm/irq-sh73180.h>
#endif
Expand Down
12 changes: 11 additions & 1 deletion trunk/include/asm-sh/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
* Copyright (C) 2002 David Howells (dhowells@redhat.com)
* - Incorporating suggestions made by Linus Torvalds and Dave Miller
*/

#ifdef __KERNEL__
#include <asm/page.h>

#ifndef __ASSEMBLY__
#include <asm/processor.h>
Expand All @@ -23,13 +23,20 @@ struct thread_info {
int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space */
struct restart_block restart_block;
unsigned long previous_sp; /* sp of previous stack in case
of nested IRQ stacks */
__u8 supervisor_stack[0];
};

#endif

#define PREEMPT_ACTIVE 0x10000000

#ifdef CONFIG_4KSTACKS
#define THREAD_SIZE (PAGE_SIZE)
#else
#define THREAD_SIZE (PAGE_SIZE * 2)
#endif
#define STACK_WARN (THREAD_SIZE / 8)

/*
Expand All @@ -52,6 +59,9 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)

/* how to get the current stack pointer from C */
register unsigned long current_stack_pointer asm("r15") __attribute_used__;

/* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void)
{
Expand Down

0 comments on commit 4a5906d

Please sign in to comment.