aboutsummaryrefslogtreecommitdiffstats
path: root/arch/h8300/kernel
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/h8300/kernel
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'arch/h8300/kernel')
-rw-r--r--arch/h8300/kernel/Makefile2
-rw-r--r--arch/h8300/kernel/entry.S9
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c1
-rw-r--r--arch/h8300/kernel/irq.c1
-rw-r--r--arch/h8300/kernel/process.c108
-rw-r--r--arch/h8300/kernel/ptrace.c1
-rw-r--r--arch/h8300/kernel/setup.c23
-rw-r--r--arch/h8300/kernel/signal.c133
-rw-r--r--arch/h8300/kernel/sys_h8300.c25
-rw-r--r--arch/h8300/kernel/syscalls.S15
-rw-r--r--arch/h8300/kernel/time.c1
-rw-r--r--arch/h8300/kernel/timer/itu.c2
-rw-r--r--arch/h8300/kernel/timer/timer16.c2
-rw-r--r--arch/h8300/kernel/timer/timer8.c2
-rw-r--r--arch/h8300/kernel/timer/tpu.c2
-rw-r--r--arch/h8300/kernel/traps.c1
16 files changed, 253 insertions, 75 deletions
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index 1cc57f872d3..8d4d2a54be9 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := vmlinux.lds
6 6
7obj-y := process.o traps.o ptrace.o irq.o \ 7obj-y := process.o traps.o ptrace.o irq.o \
8 sys_h8300.o time.o signal.o \ 8 sys_h8300.o time.o signal.o \
9 setup.o gpio.o syscalls.o \ 9 setup.o gpio.o init_task.o syscalls.o \
10 entry.o timer/ 10 entry.o timer/
11 11
12obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 12obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
index 617a6878787..ca743169030 100644
--- a/arch/h8300/kernel/entry.S
+++ b/arch/h8300/kernel/entry.S
@@ -158,7 +158,6 @@ INTERRUPTS = 128
158.globl SYMBOL_NAME(system_call) 158.globl SYMBOL_NAME(system_call)
159.globl SYMBOL_NAME(ret_from_exception) 159.globl SYMBOL_NAME(ret_from_exception)
160.globl SYMBOL_NAME(ret_from_fork) 160.globl SYMBOL_NAME(ret_from_fork)
161.globl SYMBOL_NAME(ret_from_kernel_thread)
162.globl SYMBOL_NAME(ret_from_interrupt) 161.globl SYMBOL_NAME(ret_from_interrupt)
163.globl SYMBOL_NAME(interrupt_redirect_table) 162.globl SYMBOL_NAME(interrupt_redirect_table)
164.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) 163.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
@@ -331,14 +330,6 @@ SYMBOL_NAME_LABEL(ret_from_fork)
331 jsr @SYMBOL_NAME(schedule_tail) 330 jsr @SYMBOL_NAME(schedule_tail)
332 jmp @SYMBOL_NAME(ret_from_exception) 331 jmp @SYMBOL_NAME(ret_from_exception)
333 332
334SYMBOL_NAME_LABEL(ret_from_kernel_thread)
335 mov.l er2,er0
336 jsr @SYMBOL_NAME(schedule_tail)
337 mov.l @(LER4:16,sp),er0
338 mov.l @(LER5:16,sp),er1
339 jsr @er1
340 jmp @SYMBOL_NAME(ret_from_exception)
341
342SYMBOL_NAME_LABEL(resume) 333SYMBOL_NAME_LABEL(resume)
343 /* 334 /*
344 * Beware - when entering resume, offset of tss is in d1, 335 * Beware - when entering resume, offset of tss is in d1,
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 53d7c0e4bd8..6866bd9c7fb 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -33,6 +33,7 @@ EXPORT_SYMBOL(strncmp);
33 33
34EXPORT_SYMBOL(ip_fast_csum); 34EXPORT_SYMBOL(ip_fast_csum);
35 35
36EXPORT_SYMBOL(kernel_thread);
36EXPORT_SYMBOL(enable_irq); 37EXPORT_SYMBOL(enable_irq);
37EXPORT_SYMBOL(disable_irq); 38EXPORT_SYMBOL(disable_irq);
38 39
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
index 2fa8ac7b79b..1f67fed476a 100644
--- a/arch/h8300/kernel/irq.c
+++ b/arch/h8300/kernel/irq.c
@@ -16,6 +16,7 @@
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18 18
19#include <asm/system.h>
19#include <asm/traps.h> 20#include <asm/traps.h>
20#include <asm/io.h> 21#include <asm/io.h>
21#include <asm/setup.h> 22#include <asm/setup.h>
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index b609f63f159..933bd388efb 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -36,9 +36,9 @@
36#include <linux/reboot.h> 36#include <linux/reboot.h>
37#include <linux/fs.h> 37#include <linux/fs.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/rcupdate.h>
40 39
41#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41#include <asm/system.h>
42#include <asm/traps.h> 42#include <asm/traps.h>
43#include <asm/setup.h> 43#include <asm/setup.h>
44#include <asm/pgtable.h> 44#include <asm/pgtable.h>
@@ -47,7 +47,6 @@ void (*pm_power_off)(void) = NULL;
47EXPORT_SYMBOL(pm_power_off); 47EXPORT_SYMBOL(pm_power_off);
48 48
49asmlinkage void ret_from_fork(void); 49asmlinkage void ret_from_fork(void);
50asmlinkage void ret_from_kernel_thread(void);
51 50
52/* 51/*
53 * The idle loop on an H8/300.. 52 * The idle loop on an H8/300..
@@ -80,11 +79,11 @@ void (*idle)(void) = default_idle;
80void cpu_idle(void) 79void cpu_idle(void)
81{ 80{
82 while (1) { 81 while (1) {
83 rcu_idle_enter();
84 while (!need_resched()) 82 while (!need_resched())
85 idle(); 83 idle();
86 rcu_idle_exit(); 84 preempt_enable_no_resched();
87 schedule_preempt_disabled(); 85 schedule();
86 preempt_disable();
88 } 87 }
89} 88}
90 89
@@ -123,34 +122,113 @@ void show_regs(struct pt_regs * regs)
123 printk("\n"); 122 printk("\n");
124} 123}
125 124
125/*
126 * Create a kernel thread
127 */
128int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
129{
130 long retval;
131 long clone_arg;
132 mm_segment_t fs;
133
134 fs = get_fs();
135 set_fs (KERNEL_DS);
136 clone_arg = flags | CLONE_VM;
137 __asm__("mov.l sp,er3\n\t"
138 "sub.l er2,er2\n\t"
139 "mov.l %2,er1\n\t"
140 "mov.l %1,er0\n\t"
141 "trapa #0\n\t"
142 "cmp.l sp,er3\n\t"
143 "beq 1f\n\t"
144 "mov.l %4,er0\n\t"
145 "mov.l %3,er1\n\t"
146 "jsr @er1\n\t"
147 "mov.l %5,er0\n\t"
148 "trapa #0\n"
149 "1:\n\t"
150 "mov.l er0,%0"
151 :"=r"(retval)
152 :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit)
153 :"er0","er1","er2","er3");
154 set_fs (fs);
155 return retval;
156}
157
126void flush_thread(void) 158void flush_thread(void)
127{ 159{
128} 160}
129 161
162/*
163 * "h8300_fork()".. By the time we get here, the
164 * non-volatile registers have also been saved on the
165 * stack. We do some ugly pointer stuff here.. (see
166 * also copy_thread)
167 */
168
169asmlinkage int h8300_fork(struct pt_regs *regs)
170{
171 return -EINVAL;
172}
173
174asmlinkage int h8300_vfork(struct pt_regs *regs)
175{
176 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
177}
178
179asmlinkage int h8300_clone(struct pt_regs *regs)
180{
181 unsigned long clone_flags;
182 unsigned long newsp;
183
184 /* syscall2 puts clone_flags in er1 and usp in er2 */
185 clone_flags = regs->er1;
186 newsp = regs->er2;
187 if (!newsp)
188 newsp = rdusp();
189 return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
190
191}
192
130int copy_thread(unsigned long clone_flags, 193int copy_thread(unsigned long clone_flags,
131 unsigned long usp, unsigned long topstk, 194 unsigned long usp, unsigned long topstk,
132 struct task_struct * p) 195 struct task_struct * p, struct pt_regs * regs)
133{ 196{
134 struct pt_regs * childregs; 197 struct pt_regs * childregs;
135 198
136 childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; 199 childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
137 200
138 if (unlikely(p->flags & PF_KTHREAD)) { 201 *childregs = *regs;
139 memset(childregs, 0, sizeof(struct pt_regs));
140 childregs->retpc = (unsigned long) ret_from_kernel_thread;
141 childregs->er4 = topstk; /* arg */
142 childregs->er5 = usp; /* fn */
143 p->thread.ksp = (unsigned long)childregs;
144 }
145 *childregs = *current_pt_regs();
146 childregs->retpc = (unsigned long) ret_from_fork; 202 childregs->retpc = (unsigned long) ret_from_fork;
147 childregs->er0 = 0; 203 childregs->er0 = 0;
148 p->thread.usp = usp ?: rdusp(); 204
205 p->thread.usp = usp;
149 p->thread.ksp = (unsigned long)childregs; 206 p->thread.ksp = (unsigned long)childregs;
150 207
151 return 0; 208 return 0;
152} 209}
153 210
211/*
212 * sys_execve() executes a new program.
213 */
214asmlinkage int sys_execve(const char *name,
215 const char *const *argv,
216 const char *const *envp,
217 int dummy, ...)
218{
219 int error;
220 char * filename;
221 struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
222
223 filename = getname(name);
224 error = PTR_ERR(filename);
225 if (IS_ERR(filename))
226 return error;
227 error = do_execve(filename, argv, envp, regs);
228 putname(filename);
229 return error;
230}
231
154unsigned long thread_saved_pc(struct task_struct *tsk) 232unsigned long thread_saved_pc(struct task_struct *tsk)
155{ 233{
156 return ((struct pt_regs *)tsk->thread.esp0)->pc; 234 return ((struct pt_regs *)tsk->thread.esp0)->pc;
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 748cf6585aa..497fa89b5df 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -27,6 +27,7 @@
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <asm/page.h> 28#include <asm/page.h>
29#include <asm/pgtable.h> 29#include <asm/pgtable.h>
30#include <asm/system.h>
30#include <asm/processor.h> 31#include <asm/processor.h>
31#include <asm/signal.h> 32#include <asm/signal.h>
32 33
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
index d0b1607f271..68d651081bd 100644
--- a/arch/h8300/kernel/setup.c
+++ b/arch/h8300/kernel/setup.c
@@ -35,7 +35,6 @@
35#include <asm/setup.h> 35#include <asm/setup.h>
36#include <asm/irq.h> 36#include <asm/irq.h>
37#include <asm/pgtable.h> 37#include <asm/pgtable.h>
38#include <asm/sections.h>
39 38
40#if defined(__H8300H__) 39#if defined(__H8300H__)
41#define CPU "H8/300H" 40#define CPU "H8/300H"
@@ -55,6 +54,7 @@ unsigned long memory_end;
55 54
56char __initdata command_line[COMMAND_LINE_SIZE]; 55char __initdata command_line[COMMAND_LINE_SIZE];
57 56
57extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
58extern int _ramstart, _ramend; 58extern int _ramstart, _ramend;
59extern char _target_name[]; 59extern char _target_name[];
60extern void h8300_gpio_init(void); 60extern void h8300_gpio_init(void);
@@ -119,9 +119,9 @@ void __init setup_arch(char **cmdline_p)
119 memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; 119 memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS;
120#endif 120#endif
121 121
122 init_mm.start_code = (unsigned long) _stext; 122 init_mm.start_code = (unsigned long) &_stext;
123 init_mm.end_code = (unsigned long) _etext; 123 init_mm.end_code = (unsigned long) &_etext;
124 init_mm.end_data = (unsigned long) _edata; 124 init_mm.end_data = (unsigned long) &_edata;
125 init_mm.brk = (unsigned long) 0; 125 init_mm.brk = (unsigned long) 0;
126 126
127#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT) 127#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT)
@@ -134,12 +134,15 @@ void __init setup_arch(char **cmdline_p)
134 printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n"); 134 printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n");
135 135
136#ifdef DEBUG 136#ifdef DEBUG
137 printk(KERN_DEBUG "KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p " 137 printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
138 "BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start, 138 "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
139 __bss_stop); 139 (int) &_sdata, (int) &_edata,
140 printk(KERN_DEBUG "KERNEL -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx " 140 (int) &_sbss, (int) &_ebss);
141 "STACK=0x%06lx-0x%p\n", __bss_stop, memory_start, memory_start, 141 printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
142 memory_end, memory_end, &_ramend); 142 "STACK=0x%06x-0x%06x\n",
143 (int) &_ebss, (int) memory_start,
144 (int) memory_start, (int) memory_end,
145 (int) memory_end, (int) &_ramend);
143#endif 146#endif
144 147
145#ifdef CONFIG_DEFAULT_CMDLINE 148#ifdef CONFIG_DEFAULT_CMDLINE
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 0e81b96c642..af842c369d2 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -38,6 +38,7 @@
38#include <linux/personality.h> 38#include <linux/personality.h>
39#include <linux/tty.h> 39#include <linux/tty.h>
40#include <linux/binfmts.h> 40#include <linux/binfmts.h>
41#include <linux/freezer.h>
41#include <linux/tracehook.h> 42#include <linux/tracehook.h>
42 43
43#include <asm/setup.h> 44#include <asm/setup.h>
@@ -46,15 +47,62 @@
46#include <asm/traps.h> 47#include <asm/traps.h>
47#include <asm/ucontext.h> 48#include <asm/ucontext.h>
48 49
50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
51
52asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
53
49/* 54/*
50 * Atomically swap in the new signal mask, and wait for a signal. 55 * Atomically swap in the new signal mask, and wait for a signal.
51 */ 56 */
57asmlinkage int do_sigsuspend(struct pt_regs *regs)
58{
59 old_sigset_t mask = regs->er3;
60 sigset_t saveset;
61
62 mask &= _BLOCKABLE;
63 spin_lock_irq(&current->sighand->siglock);
64 saveset = current->blocked;
65 siginitset(&current->blocked, mask);
66 recalc_sigpending();
67 spin_unlock_irq(&current->sighand->siglock);
68
69 regs->er0 = -EINTR;
70 while (1) {
71 current->state = TASK_INTERRUPTIBLE;
72 schedule();
73 if (do_signal(regs, &saveset))
74 return -EINTR;
75 }
76}
77
52asmlinkage int 78asmlinkage int
53sys_sigsuspend(int unused1, int unused2, old_sigset_t mask) 79do_rt_sigsuspend(struct pt_regs *regs)
54{ 80{
55 sigset_t blocked; 81 sigset_t *unewset = (sigset_t *)regs->er1;
56 siginitset(&blocked, mask); 82 size_t sigsetsize = (size_t)regs->er2;
57 return sigsuspend(&blocked); 83 sigset_t saveset, newset;
84
85 /* XXX: Don't preclude handling different sized sigset_t's. */
86 if (sigsetsize != sizeof(sigset_t))
87 return -EINVAL;
88
89 if (copy_from_user(&newset, unewset, sizeof(newset)))
90 return -EFAULT;
91 sigdelsetmask(&newset, ~_BLOCKABLE);
92
93 spin_lock_irq(&current->sighand->siglock);
94 saveset = current->blocked;
95 current->blocked = newset;
96 recalc_sigpending();
97 spin_unlock_irq(&current->sighand->siglock);
98
99 regs->er0 = -EINTR;
100 while (1) {
101 current->state = TASK_INTERRUPTIBLE;
102 schedule();
103 if (do_signal(regs, &saveset))
104 return -EINTR;
105 }
58} 106}
59 107
60asmlinkage int 108asmlinkage int
@@ -68,10 +116,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
68 old_sigset_t mask; 116 old_sigset_t mask;
69 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 117 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
70 __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 118 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
71 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || 119 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
72 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
73 __get_user(mask, &act->sa_mask))
74 return -EFAULT; 120 return -EFAULT;
121 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
122 __get_user(mask, &act->sa_mask);
75 siginitset(&new_ka.sa.sa_mask, mask); 123 siginitset(&new_ka.sa.sa_mask, mask);
76 } 124 }
77 125
@@ -80,10 +128,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
80 if (!ret && oact) { 128 if (!ret && oact) {
81 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 129 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
82 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 130 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
83 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || 131 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
84 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
85 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
86 return -EFAULT; 132 return -EFAULT;
133 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
134 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
87 } 135 }
88 136
89 return ret; 137 return ret;
@@ -183,7 +231,11 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
183 sizeof(frame->extramask)))) 231 sizeof(frame->extramask))))
184 goto badframe; 232 goto badframe;
185 233
186 set_current_blocked(&set); 234 sigdelsetmask(&set, ~_BLOCKABLE);
235 spin_lock_irq(&current->sighand->siglock);
236 current->blocked = set;
237 recalc_sigpending();
238 spin_unlock_irq(&current->sighand->siglock);
187 239
188 if (restore_sigcontext(regs, &frame->sc, &er0)) 240 if (restore_sigcontext(regs, &frame->sc, &er0))
189 goto badframe; 241 goto badframe;
@@ -207,7 +259,11 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
207 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 259 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
208 goto badframe; 260 goto badframe;
209 261
210 set_current_blocked(&set); 262 sigdelsetmask(&set, ~_BLOCKABLE);
263 spin_unlock_irq(&current->sighand->siglock);
264 current->blocked = set;
265 recalc_sigpending();
266 spin_lock_irq(&current->sighand->siglock);
211 267
212 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) 268 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
213 goto badframe; 269 goto badframe;
@@ -258,7 +314,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
258 return (void *)((usp - frame_size) & -8UL); 314 return (void *)((usp - frame_size) & -8UL);
259} 315}
260 316
261static int setup_frame (int sig, struct k_sigaction *ka, 317static void setup_frame (int sig, struct k_sigaction *ka,
262 sigset_t *set, struct pt_regs *regs) 318 sigset_t *set, struct pt_regs *regs)
263{ 319{
264 struct sigframe *frame; 320 struct sigframe *frame;
@@ -319,14 +375,13 @@ static int setup_frame (int sig, struct k_sigaction *ka,
319 regs->er1 = (unsigned long)&(frame->sc); 375 regs->er1 = (unsigned long)&(frame->sc);
320 regs->er5 = current->mm->start_data; /* GOT base */ 376 regs->er5 = current->mm->start_data; /* GOT base */
321 377
322 return 0; 378 return;
323 379
324give_sigsegv: 380give_sigsegv:
325 force_sigsegv(sig, current); 381 force_sigsegv(sig, current);
326 return -EFAULT;
327} 382}
328 383
329static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, 384static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
330 sigset_t *set, struct pt_regs *regs) 385 sigset_t *set, struct pt_regs *regs)
331{ 386{
332 struct rt_sigframe *frame; 387 struct rt_sigframe *frame;
@@ -395,11 +450,10 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
395 regs->er2 = (unsigned long)&frame->uc; 450 regs->er2 = (unsigned long)&frame->uc;
396 regs->er5 = current->mm->start_data; /* GOT base */ 451 regs->er5 = current->mm->start_data; /* GOT base */
397 452
398 return 0; 453 return;
399 454
400give_sigsegv: 455give_sigsegv:
401 force_sigsegv(sig, current); 456 force_sigsegv(sig, current);
402 return -EFAULT;
403} 457}
404 458
405/* 459/*
@@ -407,10 +461,8 @@ give_sigsegv:
407 */ 461 */
408static void 462static void
409handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 463handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
410 struct pt_regs * regs) 464 sigset_t *oldset, struct pt_regs * regs)
411{ 465{
412 sigset_t *oldset = sigmask_to_save();
413 int ret;
414 /* are we from a system call? */ 466 /* are we from a system call? */
415 if (regs->orig_er0 >= 0) { 467 if (regs->orig_er0 >= 0) {
416 switch (regs->er0) { 468 switch (regs->er0) {
@@ -433,12 +485,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
433 485
434 /* set up the stack frame */ 486 /* set up the stack frame */
435 if (ka->sa.sa_flags & SA_SIGINFO) 487 if (ka->sa.sa_flags & SA_SIGINFO)
436 ret = setup_rt_frame(sig, ka, info, oldset, regs); 488 setup_rt_frame(sig, ka, info, oldset, regs);
437 else 489 else
438 ret = setup_frame(sig, ka, oldset, regs); 490 setup_frame(sig, ka, oldset, regs);
439 491
440 if (!ret) 492 spin_lock_irq(&current->sighand->siglock);
441 signal_delivered(sig, info, ka, regs, 0); 493 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
494 if (!(ka->sa.sa_flags & SA_NODEFER))
495 sigaddset(&current->blocked,sig);
496 recalc_sigpending();
497 spin_unlock_irq(&current->sighand->siglock);
442} 498}
443 499
444/* 500/*
@@ -446,7 +502,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
446 * want to handle. Thus you cannot kill init even with a SIGKILL even by 502 * want to handle. Thus you cannot kill init even with a SIGKILL even by
447 * mistake. 503 * mistake.
448 */ 504 */
449static void do_signal(struct pt_regs *regs) 505asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
450{ 506{
451 siginfo_t info; 507 siginfo_t info;
452 int signr; 508 int signr;
@@ -459,16 +515,23 @@ static void do_signal(struct pt_regs *regs)
459 * if so. 515 * if so.
460 */ 516 */
461 if ((regs->ccr & 0x10)) 517 if ((regs->ccr & 0x10))
462 return; 518 return 1;
519
520 if (try_to_freeze())
521 goto no_signal;
463 522
464 current->thread.esp0 = (unsigned long) regs; 523 current->thread.esp0 = (unsigned long) regs;
465 524
525 if (!oldset)
526 oldset = &current->blocked;
527
466 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 528 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
467 if (signr > 0) { 529 if (signr > 0) {
468 /* Whee! Actually deliver the signal. */ 530 /* Whee! Actually deliver the signal. */
469 handle_signal(signr, &info, &ka, regs); 531 handle_signal(signr, &info, &ka, oldset, regs);
470 return; 532 return 1;
471 } 533 }
534 no_signal:
472 /* Did we come from a system call? */ 535 /* Did we come from a system call? */
473 if (regs->orig_er0 >= 0) { 536 if (regs->orig_er0 >= 0) {
474 /* Restart the system call - no handlers present */ 537 /* Restart the system call - no handlers present */
@@ -483,18 +546,18 @@ static void do_signal(struct pt_regs *regs)
483 regs->pc -= 2; 546 regs->pc -= 2;
484 } 547 }
485 } 548 }
486 549 return 0;
487 /* If there's no signal to deliver, we just restore the saved mask. */
488 restore_saved_sigmask();
489} 550}
490 551
491asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) 552asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
492{ 553{
493 if (thread_info_flags & _TIF_SIGPENDING) 554 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
494 do_signal(regs); 555 do_signal(regs, NULL);
495 556
496 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 557 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
497 clear_thread_flag(TIF_NOTIFY_RESUME); 558 clear_thread_flag(TIF_NOTIFY_RESUME);
498 tracehook_notify_resume(regs); 559 tracehook_notify_resume(regs);
560 if (current->replacement_session_keyring)
561 key_replace_session_keyring();
499 } 562 }
500} 563}
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index bf350cb7f59..aaf5e5a48f9 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -46,3 +46,28 @@ asmlinkage void syscall_print(void *dummy,...)
46 ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); 46 ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
47} 47}
48#endif 48#endif
49
50/*
51 * Do a system call from kernel instead of calling sys_execve so we
52 * end up with proper pt_regs.
53 */
54int kernel_execve(const char *filename,
55 const char *const argv[],
56 const char *const envp[])
57{
58 register long res __asm__("er0");
59 register const char *const *_c __asm__("er3") = envp;
60 register const char *const *_b __asm__("er2") = argv;
61 register const char * _a __asm__("er1") = filename;
62 __asm__ __volatile__ ("mov.l %1,er0\n\t"
63 "trapa #0\n\t"
64 : "=r" (res)
65 : "g" (__NR_execve),
66 "g" (_a),
67 "g" (_b),
68 "g" (_c)
69 : "cc", "memory");
70 return res;
71}
72
73
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index b74dd0ade58..4be2ea2fbe2 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -340,12 +340,27 @@ SYMBOL_NAME_LABEL(sys_call_table)
340 bra SYMBOL_NAME(syscall_trampoline):8 340 bra SYMBOL_NAME(syscall_trampoline):8
341 .endm 341 .endm
342 342
343SYMBOL_NAME_LABEL(sys_clone)
344 call_sp h8300_clone
345
346SYMBOL_NAME_LABEL(sys_sigsuspend)
347 call_sp do_sigsuspend
348
349SYMBOL_NAME_LABEL(sys_rt_sigsuspend)
350 call_sp do_rt_sigsuspend
351
343SYMBOL_NAME_LABEL(sys_sigreturn) 352SYMBOL_NAME_LABEL(sys_sigreturn)
344 call_sp do_sigreturn 353 call_sp do_sigreturn
345 354
346SYMBOL_NAME_LABEL(sys_rt_sigreturn) 355SYMBOL_NAME_LABEL(sys_rt_sigreturn)
347 call_sp do_rt_sigreturn 356 call_sp do_rt_sigreturn
348 357
358SYMBOL_NAME_LABEL(sys_fork)
359 call_sp h8300_fork
360
361SYMBOL_NAME_LABEL(sys_vfork)
362 call_sp h8300_vfork
363
349SYMBOL_NAME_LABEL(syscall_trampoline) 364SYMBOL_NAME_LABEL(syscall_trampoline)
350 mov.l sp,er0 365 mov.l sp,er0
351 jmp @er6 366 jmp @er6
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index e0f74191d55..32263a138aa 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -27,7 +27,6 @@
27#include <linux/profile.h> 27#include <linux/profile.h>
28 28
29#include <asm/io.h> 29#include <asm/io.h>
30#include <asm/irq_regs.h>
31#include <asm/timer.h> 30#include <asm/timer.h>
32 31
33#define TICK_SIZE (tick_nsec / 1000) 32#define TICK_SIZE (tick_nsec / 1000)
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c
index 0a8b5cd5bf3..a2ae5e95213 100644
--- a/arch/h8300/kernel/timer/itu.c
+++ b/arch/h8300/kernel/timer/itu.c
@@ -62,7 +62,7 @@ static struct irqaction itu_irq = {
62 .flags = IRQF_DISABLED | IRQF_TIMER, 62 .flags = IRQF_DISABLED | IRQF_TIMER,
63}; 63};
64 64
65static const int __initconst divide_rate[] = {1, 2, 4, 8}; 65static const int __initdata divide_rate[] = {1, 2, 4, 8};
66 66
67void __init h8300_timer_setup(void) 67void __init h8300_timer_setup(void)
68{ 68{
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c
index 462d9f58171..ae0d3816113 100644
--- a/arch/h8300/kernel/timer/timer16.c
+++ b/arch/h8300/kernel/timer/timer16.c
@@ -57,7 +57,7 @@ static struct irqaction timer16_irq = {
57 .flags = IRQF_DISABLED | IRQF_TIMER, 57 .flags = IRQF_DISABLED | IRQF_TIMER,
58}; 58};
59 59
60static const int __initconst divide_rate[] = {1, 2, 4, 8}; 60static const int __initdata divide_rate[] = {1, 2, 4, 8};
61 61
62void __init h8300_timer_setup(void) 62void __init h8300_timer_setup(void)
63{ 63{
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
index 505f3415b40..7a1533fad47 100644
--- a/arch/h8300/kernel/timer/timer8.c
+++ b/arch/h8300/kernel/timer/timer8.c
@@ -77,7 +77,7 @@ static struct irqaction timer8_irq = {
77 .flags = IRQF_DISABLED | IRQF_TIMER, 77 .flags = IRQF_DISABLED | IRQF_TIMER,
78}; 78};
79 79
80static const int __initconst divide_rate[] = {8, 64, 8192}; 80static const int __initdata divide_rate[] = {8, 64, 8192};
81 81
82void __init h8300_timer_setup(void) 82void __init h8300_timer_setup(void)
83{ 83{
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c
index 0350f6204ec..2193a2e2859 100644
--- a/arch/h8300/kernel/timer/tpu.c
+++ b/arch/h8300/kernel/timer/tpu.c
@@ -66,7 +66,7 @@ static struct irqaction tpu_irq = {
66 .flags = IRQF_DISABLED | IRQF_TIMER, 66 .flags = IRQF_DISABLED | IRQF_TIMER,
67}; 67};
68 68
69static const int __initconst divide_rate[] = { 69static const int __initdata divide_rate[] = {
70#if CONFIG_H8300_TPU_CH == 0 70#if CONFIG_H8300_TPU_CH == 0
71 1,4,16,64,0,0,0,0, 71 1,4,16,64,0,0,0,0,
72#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5) 72#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
index 7833aa3e7c7..dfa05bd908b 100644
--- a/arch/h8300/kernel/traps.c
+++ b/arch/h8300/kernel/traps.c
@@ -22,6 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/bug.h> 23#include <linux/bug.h>
24 24
25#include <asm/system.h>
25#include <asm/irq.h> 26#include <asm/irq.h>
26#include <asm/traps.h> 27#include <asm/traps.h>
27#include <asm/page.h> 28#include <asm/page.h>