From 6496a23add642b7c9203411bdff3ff761835a80a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 27 Mar 2009 14:25:26 +0100 Subject: microblaze_v8: process and init task function Reviewed-by: Ingo Molnar Acked-by: Stephen Neuendorffer Acked-by: John Linn Acked-by: John Williams Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 187 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 arch/microblaze/kernel/process.c (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c new file mode 100644 index 00000000000..60e9ed7d313 --- /dev/null +++ b/arch/microblaze/kernel/process.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008-2009 Michal Simek + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +void show_regs(struct pt_regs *regs) +{ + printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->kernel_mode); + printk(KERN_INFO " r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n", + regs->r1, regs->r2, regs->r3, regs->r4); + printk(KERN_INFO " r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n", + regs->r5, regs->r6, regs->r7, regs->r8); + printk(KERN_INFO " r9=%08lX, r10=%08lX, r11=%08lX, r12=%08lX\n", + regs->r9, regs->r10, regs->r11, regs->r12); + printk(KERN_INFO " r13=%08lX, r14=%08lX, r15=%08lX, r16=%08lX\n", + regs->r13, regs->r14, regs->r15, regs->r16); + printk(KERN_INFO " r17=%08lX, r18=%08lX, r19=%08lX, r20=%08lX\n", + regs->r17, regs->r18, regs->r19, regs->r20); + printk(KERN_INFO " r21=%08lX, r22=%08lX, r23=%08lX, r24=%08lX\n", + regs->r21, regs->r22, regs->r23, regs->r24); + printk(KERN_INFO " r25=%08lX, r26=%08lX, r27=%08lX, r28=%08lX\n", + regs->r25, regs->r26, regs->r27, regs->r28); + printk(KERN_INFO " r29=%08lX, r30=%08lX, r31=%08lX, rPC=%08lX\n", + regs->r29, regs->r30, regs->r31, regs->pc); + printk(KERN_INFO " msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n", + regs->msr, regs->ear, regs->esr, regs->fsr); + while (1) + ; +} + +void (*pm_idle)(void); +void (*pm_power_off)(void) = NULL; +EXPORT_SYMBOL(pm_power_off); + +static int hlt_counter = 1; + +void disable_hlt(void) +{ + hlt_counter++; +} +EXPORT_SYMBOL(disable_hlt); + +void enable_hlt(void) +{ + hlt_counter--; +} +EXPORT_SYMBOL(enable_hlt); + +static int __init nohlt_setup(char *__unused) +{ + hlt_counter = 1; + return 1; +} +__setup("nohlt", nohlt_setup); + +static int __init hlt_setup(char *__unused) +{ + hlt_counter = 0; + return 1; +} +__setup("hlt", hlt_setup); + +void default_idle(void) +{ + if (!hlt_counter) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + local_irq_disable(); + while (!need_resched()) + cpu_sleep(); + local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); + } else + while (!need_resched()) + cpu_relax(); +} + +void cpu_idle(void) +{ + set_thread_flag(TIF_POLLING_NRFLAG); + + /* endless idle loop with no priority at all */ + while (1) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + tick_nohz_stop_sched_tick(1); + while (!need_resched()) + idle(); + tick_nohz_restart_sched_tick(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); + } +} + +void flush_thread(void) +{ +} + +/* FIXME - here will be a proposed change -> remove nr parameter */ +int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) +{ + struct pt_regs *childregs = task_pt_regs(p); + struct thread_info *ti = task_thread_info(p); + + *childregs = *regs; + if (user_mode(regs)) + childregs->r1 = usp; + else + childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; + + memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); + ti->cpu_context.r1 = (unsigned long)childregs; + ti->cpu_context.msr = (unsigned long)childregs->msr; + ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8; + + if (clone_flags & CLONE_SETTLS) + ; + + return 0; +} + +/* + * Return saved PC of a blocked thread. + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + struct cpu_context *ctx = + &(((struct thread_info *)(tsk->stack))->cpu_context); + + /* Check whether the thread is blocked in resume() */ + if (in_sched_functions(ctx->r15)) + return (unsigned long)ctx->r15; + else + return ctx->r14; +} + +static void kernel_thread_helper(int (*fn)(void *), void *arg) +{ + fn(arg); + do_exit(-1); +} + +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + int ret; + + memset(®s, 0, sizeof(regs)); + /* store them in non-volatile registers */ + regs.r5 = (unsigned long)fn; + regs.r6 = (unsigned long)arg; + local_save_flags(regs.msr); + regs.pc = (unsigned long)kernel_thread_helper; + regs.kernel_mode = 1; + + ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + ®s, 0, NULL, NULL); + + return ret; +} + +unsigned long get_wchan(struct task_struct *p) +{ +/* TBD (used by procfs) */ + return 0; +} -- cgit v1.2.3-70-g09d2 From a8fb748e89957426fafb2e2efccd5ce635d6f530 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 14 Apr 2009 09:18:19 +0200 Subject: microblaze: Simplify copy_thread() Removing nr parameter from copy_tread function commit 6f2c55b843836d26528c56a0968689accaedbc67 Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 60e9ed7d313..436f26ccbfa 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -115,8 +115,7 @@ void flush_thread(void) { } -/* FIXME - here will be a proposed change -> remove nr parameter */ -int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, +int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct *p, struct pt_regs *regs) { -- cgit v1.2.3-70-g09d2 From 51eb6dc9ca40d086c102bb868ba7f29f33a30f6f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2009 10:41:45 +0200 Subject: microblaze: Remove while(1) loop from show_regs function I removed it because of show_regs can't break die function. If process/kernel failed, die (do_exit) function resolve it. Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 436f26ccbfa..bdc8b2c6c57 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -37,8 +37,6 @@ void show_regs(struct pt_regs *regs) regs->r29, regs->r30, regs->r31, regs->pc); printk(KERN_INFO " msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n", regs->msr, regs->ear, regs->esr, regs->fsr); - while (1) - ; } void (*pm_idle)(void); -- cgit v1.2.3-70-g09d2 From ac3efab50621bd6d01e5b40f3134dc7824788390 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2009 10:58:47 +0200 Subject: microblaze: Rename kernel_mode to pt_mode in pt_regs Signed-off-by: Michal Simek --- arch/microblaze/include/asm/processor.h | 2 +- arch/microblaze/include/asm/ptrace.h | 4 ++-- arch/microblaze/kernel/asm-offsets.c | 2 +- arch/microblaze/kernel/process.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index d8e15434ba2..4bed76d0a6c 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -62,7 +62,7 @@ static inline void start_thread(struct pt_regs *regs, { regs->pc = pc; regs->r1 = usp; - regs->kernel_mode = 0; + regs->pt_mode = 0; } /* Free all resources held by a thread. */ diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h index f1f03486428..55015bce5e4 100644 --- a/arch/microblaze/include/asm/ptrace.h +++ b/arch/microblaze/include/asm/ptrace.h @@ -52,10 +52,10 @@ struct pt_regs { microblaze_reg_t ear; microblaze_reg_t esr; microblaze_reg_t fsr; - int kernel_mode; + int pt_mode; }; -#define kernel_mode(regs) ((regs)->kernel_mode) +#define kernel_mode(regs) ((regs)->pt_mode) #define user_mode(regs) (!kernel_mode(regs)) #define instruction_pointer(regs) ((regs)->pc) diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c index 38e1a2e8ad0..aabd9e9423a 100644 --- a/arch/microblaze/kernel/asm-offsets.c +++ b/arch/microblaze/kernel/asm-offsets.c @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) DEFINE(PT_R29, offsetof(struct pt_regs, r29)); DEFINE(PT_R30, offsetof(struct pt_regs, r30)); DEFINE(PT_R31, offsetof(struct pt_regs, r31)); - DEFINE(PT_MODE, offsetof(struct pt_regs, kernel_mode)); + DEFINE(PT_MODE, offsetof(struct pt_regs, pt_mode)); BLANK(); /* Magic offsets for PTRACE PEEK/POKE etc */ diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index bdc8b2c6c57..40cc1480810 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -18,7 +18,7 @@ void show_regs(struct pt_regs *regs) { - printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->kernel_mode); + printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->pt_mode); printk(KERN_INFO " r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n", regs->r1, regs->r2, regs->r3, regs->r4); printk(KERN_INFO " r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n", @@ -169,7 +169,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.r6 = (unsigned long)arg; local_save_flags(regs.msr); regs.pc = (unsigned long)kernel_thread_helper; - regs.kernel_mode = 1; + regs.pt_mode = 1; ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -- cgit v1.2.3-70-g09d2 From e1c4bd0897b6d03eff4b32197d6ab017f83fc836 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2009 11:30:16 +0200 Subject: microblaze: Move start_thread to process.c This change is due to upcomming MMU merge Signed-off-by: Michal Simek --- arch/microblaze/include/asm/processor.h | 13 +++---------- arch/microblaze/kernel/process.c | 9 +++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index cea42a36d16..89aa3956929 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -29,6 +29,9 @@ extern const struct seq_operations cpuinfo_op; #define task_pt_regs(tsk) \ (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1) +/* Do necessary setup to start up a newly executed thread. */ +void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); + /* * User space process size: memory size * @@ -58,16 +61,6 @@ struct task_struct; struct thread_struct { }; # define INIT_THREAD { } -/* Do necessary setup to start up a newly executed thread. */ -static inline void start_thread(struct pt_regs *regs, - unsigned long pc, - unsigned long usp) -{ - regs->pc = pc; - regs->r1 = usp; - regs->pt_mode = 0; -} - /* Free all resources held by a thread. */ static inline void release_thread(struct task_struct *dead_task) { diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 40cc1480810..dd15de9cde3 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -182,3 +182,12 @@ unsigned long get_wchan(struct task_struct *p) /* TBD (used by procfs) */ return 0; } + +/* Set up a thread for executing a new program */ +void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) +{ + set_fs(USER_DS); + regs->pc = pc; + regs->r1 = usp; + regs->pt_mode = 0; +} -- cgit v1.2.3-70-g09d2 From 6714fcc34e1bcf247fe542ebdea36b699ff8e2b8 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 16 Apr 2009 11:32:21 +0200 Subject: microblaze: Remove redundant variable Signed-off-by: Michal Simek --- arch/microblaze/kernel/process.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch/microblaze/kernel/process.c') diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index dd15de9cde3..07d4fa339ed 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -161,7 +161,6 @@ static void kernel_thread_helper(int (*fn)(void *), void *arg) int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { struct pt_regs regs; - int ret; memset(®s, 0, sizeof(regs)); /* store them in non-volatile registers */ @@ -171,10 +170,8 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.pc = (unsigned long)kernel_thread_helper; regs.pt_mode = 1; - ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); - - return ret; } unsigned long get_wchan(struct task_struct *p) -- cgit v1.2.3-70-g09d2