aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/kernel')
-rw-r--r--arch/cris/kernel/Makefile15
-rw-r--r--arch/cris/kernel/crisksyms.c103
-rw-r--r--arch/cris/kernel/irq.c297
-rw-r--r--arch/cris/kernel/module.c121
-rw-r--r--arch/cris/kernel/process.c280
-rw-r--r--arch/cris/kernel/ptrace.c119
-rw-r--r--arch/cris/kernel/semaphore.c130
-rw-r--r--arch/cris/kernel/setup.c193
-rw-r--r--arch/cris/kernel/sys_cris.c174
-rw-r--r--arch/cris/kernel/time.c232
-rw-r--r--arch/cris/kernel/traps.c144
11 files changed, 1808 insertions, 0 deletions
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
new file mode 100644
index 000000000000..1546a0e74047
--- /dev/null
+++ b/arch/cris/kernel/Makefile
@@ -0,0 +1,15 @@
1# $Id: Makefile,v 1.10 2004/05/14 10:18:12 starvik Exp $
2#
3# Makefile for the linux kernel.
4#
5
6extra-y := vmlinux.lds
7
8obj-y := process.o traps.o irq.o ptrace.o setup.o \
9 time.o sys_cris.o semaphore.o
10
11obj-$(CONFIG_MODULES) += crisksyms.o
12obj-$(CONFIG_MODULES) += module.o
13
14clean:
15
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
new file mode 100644
index 000000000000..7141bbecd7e4
--- /dev/null
+++ b/arch/cris/kernel/crisksyms.c
@@ -0,0 +1,103 @@
1#include <linux/config.h>
2#include <linux/module.h>
3#include <linux/user.h>
4#include <linux/elfcore.h>
5#include <linux/sched.h>
6#include <linux/in6.h>
7#include <linux/interrupt.h>
8#include <linux/smp_lock.h>
9#include <linux/pm.h>
10#include <linux/kernel.h>
11#include <linux/string.h>
12#include <linux/tty.h>
13
14#include <asm/semaphore.h>
15#include <asm/processor.h>
16#include <asm/uaccess.h>
17#include <asm/checksum.h>
18#include <asm/io.h>
19#include <asm/delay.h>
20#include <asm/irq.h>
21#include <asm/pgtable.h>
22#include <asm/fasttimer.h>
23
24extern void dump_thread(struct pt_regs *, struct user *);
25extern unsigned long get_cmos_time(void);
26extern void __Udiv(void);
27extern void __Umod(void);
28extern void __Div(void);
29extern void __Mod(void);
30extern void __ashrdi3(void);
31extern void iounmap(void *addr);
32
33/* Platform dependent support */
34EXPORT_SYMBOL(dump_thread);
35EXPORT_SYMBOL(enable_irq);
36EXPORT_SYMBOL(disable_irq);
37EXPORT_SYMBOL(kernel_thread);
38EXPORT_SYMBOL(get_cmos_time);
39EXPORT_SYMBOL(loops_per_usec);
40
41/* String functions */
42EXPORT_SYMBOL(memcmp);
43EXPORT_SYMBOL(memmove);
44EXPORT_SYMBOL(strpbrk);
45EXPORT_SYMBOL(strstr);
46EXPORT_SYMBOL(strcpy);
47EXPORT_SYMBOL(strchr);
48EXPORT_SYMBOL(strcmp);
49EXPORT_SYMBOL(strlen);
50EXPORT_SYMBOL(strcat);
51EXPORT_SYMBOL(strncat);
52EXPORT_SYMBOL(strncmp);
53EXPORT_SYMBOL(strncpy);
54
55/* Math functions */
56EXPORT_SYMBOL(__Udiv);
57EXPORT_SYMBOL(__Umod);
58EXPORT_SYMBOL(__Div);
59EXPORT_SYMBOL(__Mod);
60EXPORT_SYMBOL(__ashrdi3);
61
62/* Memory functions */
63EXPORT_SYMBOL(__ioremap);
64EXPORT_SYMBOL(iounmap);
65
66/* Semaphore functions */
67EXPORT_SYMBOL(__up);
68EXPORT_SYMBOL(__down);
69EXPORT_SYMBOL(__down_interruptible);
70EXPORT_SYMBOL(__down_trylock);
71
72/* Export shadow registers for the CPU I/O pins */
73EXPORT_SYMBOL(genconfig_shadow);
74EXPORT_SYMBOL(port_pa_data_shadow);
75EXPORT_SYMBOL(port_pa_dir_shadow);
76EXPORT_SYMBOL(port_pb_data_shadow);
77EXPORT_SYMBOL(port_pb_dir_shadow);
78EXPORT_SYMBOL(port_pb_config_shadow);
79EXPORT_SYMBOL(port_g_data_shadow);
80
81/* Userspace access functions */
82EXPORT_SYMBOL(__copy_user_zeroing);
83EXPORT_SYMBOL(__copy_user);
84
85/* Cache flush functions */
86EXPORT_SYMBOL(flush_etrax_cache);
87EXPORT_SYMBOL(prepare_rx_descriptor);
88
89#undef memcpy
90#undef memset
91extern void * memset(void *, int, __kernel_size_t);
92extern void * memcpy(void *, const void *, __kernel_size_t);
93EXPORT_SYMBOL(memcpy);
94EXPORT_SYMBOL(memset);
95
96#ifdef CONFIG_ETRAX_FAST_TIMER
97/* Fast timer functions */
98EXPORT_SYMBOL(fast_timer_list);
99EXPORT_SYMBOL(start_one_shot_timer);
100EXPORT_SYMBOL(del_fast_timer);
101EXPORT_SYMBOL(schedule_usleep);
102#endif
103
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
new file mode 100644
index 000000000000..d848b9407457
--- /dev/null
+++ b/arch/cris/kernel/irq.c
@@ -0,0 +1,297 @@
1/*
2 *
3 * linux/arch/cris/kernel/irq.c
4 *
5 * Copyright (c) 2000,2001 Axis Communications AB
6 *
7 * Authors: Bjorn Wesen (bjornw@axis.com)
8 *
9 * This file contains the code used by various IRQ handling routines:
10 * asking for different IRQ's should be done through these routines
11 * instead of just grabbing them. Thus setups with different IRQ numbers
12 * shouldn't result in any weird surprises, and installing new handlers
13 * should be easier.
14 *
15 * Notice Linux/CRIS: these routines do not care about SMP
16 *
17 */
18
19/*
20 * IRQ's are in fact implemented a bit like signal handlers for the kernel.
21 * Naturally it's not a 1:1 relation, but there are similarities.
22 */
23
24#include <linux/config.h>
25#include <linux/module.h>
26#include <linux/ptrace.h>
27
28#include <linux/kernel_stat.h>
29#include <linux/signal.h>
30#include <linux/sched.h>
31#include <linux/ioport.h>
32#include <linux/interrupt.h>
33#include <linux/timex.h>
34#include <linux/slab.h>
35#include <linux/random.h>
36#include <linux/init.h>
37#include <linux/seq_file.h>
38#include <linux/errno.h>
39#include <linux/bitops.h>
40
41#include <asm/io.h>
42
43/* Defined in arch specific irq.c */
44extern void arch_setup_irq(int irq);
45extern void arch_free_irq(int irq);
46
47void
48disable_irq(unsigned int irq_nr)
49{
50 unsigned long flags;
51
52 local_save_flags(flags);
53 local_irq_disable();
54 mask_irq(irq_nr);
55 local_irq_restore(flags);
56}
57
58void
59enable_irq(unsigned int irq_nr)
60{
61 unsigned long flags;
62 local_save_flags(flags);
63 local_irq_disable();
64 unmask_irq(irq_nr);
65 local_irq_restore(flags);
66}
67
68unsigned long
69probe_irq_on()
70{
71 return 0;
72}
73
74EXPORT_SYMBOL(probe_irq_on);
75
76int
77probe_irq_off(unsigned long x)
78{
79 return 0;
80}
81
82EXPORT_SYMBOL(probe_irq_off);
83
84/*
85 * Initial irq handlers.
86 */
87
88static struct irqaction *irq_action[NR_IRQS];
89
90int show_interrupts(struct seq_file *p, void *v)
91{
92 int i = *(loff_t *) v;
93 struct irqaction * action;
94 unsigned long flags;
95
96 if (i < NR_IRQS) {
97 local_irq_save(flags);
98 action = irq_action[i];
99 if (!action)
100 goto skip;
101 seq_printf(p, "%2d: %10u %c %s",
102 i, kstat_this_cpu.irqs[i],
103 (action->flags & SA_INTERRUPT) ? '+' : ' ',
104 action->name);
105 for (action = action->next; action; action = action->next) {
106 seq_printf(p, ",%s %s",
107 (action->flags & SA_INTERRUPT) ? " +" : "",
108 action->name);
109 }
110 seq_putc(p, '\n');
111skip:
112 local_irq_restore(flags);
113 }
114 return 0;
115}
116
117/* called by the assembler IRQ entry functions defined in irq.h
118 * to dispatch the interrupts to registred handlers
119 * interrupts are disabled upon entry - depending on if the
120 * interrupt was registred with SA_INTERRUPT or not, interrupts
121 * are re-enabled or not.
122 */
123
124asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
125{
126 struct irqaction *action;
127 int do_random, cpu;
128 int ret, retval = 0;
129
130 cpu = smp_processor_id();
131 irq_enter();
132 kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++;
133 action = irq_action[irq - FIRST_IRQ];
134
135 if (action) {
136 if (!(action->flags & SA_INTERRUPT))
137 local_irq_enable();
138 do_random = 0;
139 do {
140 ret = action->handler(irq, action->dev_id, regs);
141 if (ret == IRQ_HANDLED)
142 do_random |= action->flags;
143 retval |= ret;
144 action = action->next;
145 } while (action);
146
147 if (retval != 1) {
148 if (retval) {
149 printk("irq event %d: bogus retval mask %x\n",
150 irq, retval);
151 } else {
152 printk("irq %d: nobody cared\n", irq);
153 }
154 }
155
156 if (do_random & SA_SAMPLE_RANDOM)
157 add_interrupt_randomness(irq);
158 local_irq_disable();
159 }
160 irq_exit();
161}
162
163/* this function links in a handler into the chain of handlers for the
164 given irq, and if the irq has never been registred, the appropriate
165 handler is entered into the interrupt vector
166*/
167
168int setup_irq(int irq, struct irqaction * new)
169{
170 int shared = 0;
171 struct irqaction *old, **p;
172 unsigned long flags;
173
174 p = irq_action + irq - FIRST_IRQ;
175 if ((old = *p) != NULL) {
176 /* Can't share interrupts unless both agree to */
177 if (!(old->flags & new->flags & SA_SHIRQ))
178 return -EBUSY;
179
180 /* Can't share interrupts unless both are same type */
181 if ((old->flags ^ new->flags) & SA_INTERRUPT)
182 return -EBUSY;
183
184 /* add new interrupt at end of irq queue */
185 do {
186 p = &old->next;
187 old = *p;
188 } while (old);
189 shared = 1;
190 }
191
192 if (new->flags & SA_SAMPLE_RANDOM)
193 rand_initialize_irq(irq);
194
195 local_save_flags(flags);
196 local_irq_disable();
197 *p = new;
198
199 if (!shared) {
200 /* if the irq wasn't registred before, enter it into the vector table
201 and unmask it physically
202 */
203 arch_setup_irq(irq);
204 unmask_irq(irq);
205 }
206
207 local_irq_restore(flags);
208 return 0;
209}
210
211/* this function is called by a driver to register an irq handler
212 Valid flags:
213 SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
214 no signal checking etc is performed upon exit
215 SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
216 is required to check if the irq was "aimed" at it explicitely
217 SA_RANDOM -> the interrupt will add to the random generators entropy
218*/
219
220int request_irq(unsigned int irq,
221 irqreturn_t (*handler)(int, void *, struct pt_regs *),
222 unsigned long irqflags,
223 const char * devname,
224 void *dev_id)
225{
226 int retval;
227 struct irqaction * action;
228
229 if(!handler)
230 return -EINVAL;
231
232 /* allocate and fill in a handler structure and setup the irq */
233
234 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
235 if (!action)
236 return -ENOMEM;
237
238 action->handler = handler;
239 action->flags = irqflags;
240 cpus_clear(action->mask);
241 action->name = devname;
242 action->next = NULL;
243 action->dev_id = dev_id;
244
245 retval = setup_irq(irq, action);
246
247 if (retval)
248 kfree(action);
249 return retval;
250}
251
252EXPORT_SYMBOL(request_irq);
253
254void free_irq(unsigned int irq, void *dev_id)
255{
256 struct irqaction * action, **p;
257 unsigned long flags;
258
259 if (irq >= NR_IRQS) {
260 printk("Trying to free IRQ%d\n",irq);
261 return;
262 }
263 for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) {
264 if (action->dev_id != dev_id)
265 continue;
266
267 /* Found it - now free it */
268 local_save_flags(flags);
269 local_irq_disable();
270 *p = action->next;
271 if (!irq_action[irq - FIRST_IRQ]) {
272 mask_irq(irq);
273 arch_free_irq(irq);
274 }
275 local_irq_restore(flags);
276 kfree(action);
277 return;
278 }
279 printk("Trying to free free IRQ%d\n",irq);
280}
281
282EXPORT_SYMBOL(free_irq);
283
284void weird_irq(void)
285{
286 local_irq_disable();
287 printk("weird irq\n");
288 while(1);
289}
290
291#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
292/* Used by other archs to show/control IRQ steering during SMP */
293void __init
294init_irq_proc(void)
295{
296}
297#endif
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
new file mode 100644
index 000000000000..f1d3e784f30c
--- /dev/null
+++ b/arch/cris/kernel/module.c
@@ -0,0 +1,121 @@
1/* Kernel module help for i386.
2 Copyright (C) 2001 Rusty Russell.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18#include <linux/moduleloader.h>
19#include <linux/elf.h>
20#include <linux/vmalloc.h>
21#include <linux/fs.h>
22#include <linux/string.h>
23#include <linux/kernel.h>
24
25#if 0
26#define DEBUGP printk
27#else
28#define DEBUGP(fmt , ...)
29#endif
30
31void *module_alloc(unsigned long size)
32{
33 if (size == 0)
34 return NULL;
35 return vmalloc(size);
36}
37
38
39/* Free memory returned from module_alloc */
40void module_free(struct module *mod, void *module_region)
41{
42 vfree(module_region);
43 /* FIXME: If module_region == mod->init_region, trim exception
44 table entries. */
45}
46
47/* We don't need anything special. */
48int module_frob_arch_sections(Elf_Ehdr *hdr,
49 Elf_Shdr *sechdrs,
50 char *secstrings,
51 struct module *mod)
52{
53 return 0;
54}
55
56int apply_relocate(Elf32_Shdr *sechdrs,
57 const char *strtab,
58 unsigned int symindex,
59 unsigned int relsec,
60 struct module *me)
61{
62 unsigned int i;
63 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
64 Elf32_Sym *sym;
65 uint32_t *location;
66
67 DEBUGP("Applying relocate section %u to %u\n", relsec,
68 sechdrs[relsec].sh_info);
69 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
70 /* This is where to make the change */
71 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
72 + rel[i].r_offset;
73 /* This is the symbol it is referring to. Note that all
74 undefined symbols have been resolved. */
75 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
76 + ELF32_R_SYM(rel[i].r_info);
77
78 /* We add the value into the location given */
79 *location += sym->st_value;
80 }
81 return 0;
82}
83
84int apply_relocate_add(Elf32_Shdr *sechdrs,
85 const char *strtab,
86 unsigned int symindex,
87 unsigned int relsec,
88 struct module *me)
89{
90 unsigned int i;
91 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
92
93 DEBUGP ("Applying relocate section %u to %u\n", relsec,
94 sechdrs[relsec].sh_info);
95
96 for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) {
97 /* This is where to make the change */
98 uint32_t *loc
99 = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
100 + rela[i].r_offset);
101 /* This is the symbol it is referring to. Note that all
102 undefined symbols have been resolved. */
103 Elf32_Sym *sym
104 = ((Elf32_Sym *)sechdrs[symindex].sh_addr
105 + ELF32_R_SYM (rela[i].r_info));
106 *loc = sym->st_value + rela[i].r_addend;
107 }
108
109 return 0;
110}
111
112int module_finalize(const Elf_Ehdr *hdr,
113 const Elf_Shdr *sechdrs,
114 struct module *me)
115{
116 return 0;
117}
118
119void module_arch_cleanup(struct module *mod)
120{
121}
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
new file mode 100644
index 000000000000..9f7cad7c7849
--- /dev/null
+++ b/arch/cris/kernel/process.c
@@ -0,0 +1,280 @@
1/* $Id: process.c,v 1.17 2004/04/05 13:53:48 starvik Exp $
2 *
3 * linux/arch/cris/kernel/process.c
4 *
5 * Copyright (C) 1995 Linus Torvalds
6 * Copyright (C) 2000-2002 Axis Communications AB
7 *
8 * Authors: Bjorn Wesen (bjornw@axis.com)
9 *
10 * $Log: process.c,v $
11 * Revision 1.17 2004/04/05 13:53:48 starvik
12 * Merge of Linux 2.6.5
13 *
14 * Revision 1.16 2003/10/27 08:04:33 starvik
15 * Merge of Linux 2.6.0-test9
16 *
17 * Revision 1.15 2003/09/11 07:29:52 starvik
18 * Merge of Linux 2.6.0-test5
19 *
20 * Revision 1.14 2003/06/10 10:21:12 johana
21 * Moved thread_saved_pc() from arch/cris/kernel/process.c to
22 * subarch specific process.c. arch-v32 has an erp, no irp.
23 *
24 * Revision 1.13 2003/04/09 05:20:47 starvik
25 * Merge of Linux 2.5.67
26 *
27 * Revision 1.12 2002/12/11 15:41:11 starvik
28 * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/kernel
29 *
30 * Revision 1.11 2002/12/10 09:00:10 starvik
31 * Merge of Linux 2.5.51
32 *
33 * Revision 1.10 2002/11/27 08:42:34 starvik
34 * Argument to user_regs() is thread_info*
35 *
36 * Revision 1.9 2002/11/26 09:44:21 starvik
37 * New threads exits through ret_from_fork (necessary for preemptive scheduling)
38 *
39 * Revision 1.8 2002/11/19 14:35:24 starvik
40 * Changes from linux 2.4
41 * Changed struct initializer syntax to the currently prefered notation
42 *
43 * Revision 1.7 2002/11/18 07:39:42 starvik
44 * thread_saved_pc moved here from processor.h
45 *
46 * Revision 1.6 2002/11/14 06:51:27 starvik
47 * Made cpu_idle more similar with other archs
48 * init_task_union -> init_thread_union
49 * Updated for new interrupt macros
50 * sys_clone and do_fork have a new argument, user_tid
51 *
52 * Revision 1.5 2002/11/05 06:45:11 starvik
53 * Merge of Linux 2.5.45
54 *
55 * Revision 1.4 2002/02/05 15:37:44 bjornw
56 * Need init_task.h
57 *
58 * Revision 1.3 2002/01/21 15:22:49 bjornw
59 * current->counter is gone
60 *
61 * Revision 1.22 2001/11/13 09:40:43 orjanf
62 * Added dump_fpu (needed for core dumps).
63 *
64 * Revision 1.21 2001/11/12 18:26:21 pkj
65 * Fixed compiler warnings.
66 *
67 * Revision 1.20 2001/10/03 08:21:39 jonashg
68 * cause_of_death does not exist if CONFIG_SVINTO_SIM is defined.
69 *
70 * Revision 1.19 2001/09/26 11:52:54 bjornw
71 * INIT_MMAP is gone in 2.4.10
72 *
73 * Revision 1.18 2001/08/21 21:43:51 hp
74 * Move last watchdog fix inside #ifdef CONFIG_ETRAX_WATCHDOG
75 *
76 * Revision 1.17 2001/08/21 13:48:01 jonashg
77 * Added fix by HP to avoid oops when doing a hard_reset_now.
78 *
79 * Revision 1.16 2001/06/21 02:00:40 hp
80 * * entry.S: Include asm/unistd.h.
81 * (_sys_call_table): Use section .rodata, not .data.
82 * (_kernel_thread): Move from...
83 * * process.c: ... here.
84 * * entryoffsets.c (VAL): Break out from...
85 * (OF): Use VAL.
86 * (LCLONE_VM): New asmified value from CLONE_VM.
87 *
88 * Revision 1.15 2001/06/20 16:31:57 hp
89 * Add comments to describe empty functions according to review.
90 *
91 * Revision 1.14 2001/05/29 11:27:59 markusl
92 * Fixed so that hard_reset_now will do reset even if watchdog wasn't enabled
93 *
94 * Revision 1.13 2001/03/20 19:44:06 bjornw
95 * Use the 7th syscall argument for regs instead of current_regs
96 *
97 */
98
99/*
100 * This file handles the architecture-dependent parts of process handling..
101 */
102
103#include <asm/atomic.h>
104#include <asm/pgtable.h>
105#include <asm/uaccess.h>
106#include <asm/irq.h>
107#include <linux/module.h>
108#include <linux/spinlock.h>
109#include <linux/fs_struct.h>
110#include <linux/init_task.h>
111#include <linux/sched.h>
112#include <linux/fs.h>
113#include <linux/user.h>
114#include <linux/elfcore.h>
115#include <linux/mqueue.h>
116
117//#define DEBUG
118
119/*
120 * Initial task structure. Make this a per-architecture thing,
121 * because different architectures tend to have different
122 * alignment requirements and potentially different initial
123 * setup.
124 */
125
126static struct fs_struct init_fs = INIT_FS;
127static struct files_struct init_files = INIT_FILES;
128static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
129static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
130struct mm_struct init_mm = INIT_MM(init_mm);
131
132EXPORT_SYMBOL(init_mm);
133
134/*
135 * Initial thread structure.
136 *
137 * We need to make sure that this is 8192-byte aligned due to the
138 * way process stacks are handled. This is done by having a special
139 * "init_task" linker map entry..
140 */
141union thread_union init_thread_union
142 __attribute__((__section__(".data.init_task"))) =
143 { INIT_THREAD_INFO(init_task) };
144
145/*
146 * Initial task structure.
147 *
148 * All other task structs will be allocated on slabs in fork.c
149 */
150struct task_struct init_task = INIT_TASK(init_task);
151
152EXPORT_SYMBOL(init_task);
153
154/*
155 * The hlt_counter, disable_hlt and enable_hlt is just here as a hook if
156 * there would ever be a halt sequence (for power save when idle) with
157 * some largish delay when halting or resuming *and* a driver that can't
158 * afford that delay. The hlt_counter would then be checked before
159 * executing the halt sequence, and the driver marks the unhaltable
160 * region by enable_hlt/disable_hlt.
161 */
162
163static int hlt_counter=0;
164
165void disable_hlt(void)
166{
167 hlt_counter++;
168}
169
170EXPORT_SYMBOL(disable_hlt);
171
172void enable_hlt(void)
173{
174 hlt_counter--;
175}
176
177EXPORT_SYMBOL(enable_hlt);
178
179/*
180 * The following aren't currently used.
181 */
182void (*pm_idle)(void);
183
184extern void default_idle(void);
185
186/*
187 * The idle thread. There's no useful work to be
188 * done, so just try to conserve power and have a
189 * low exit latency (ie sit in a loop waiting for
190 * somebody to say that they'd like to reschedule)
191 */
192void cpu_idle (void)
193{
194 /* endless idle loop with no priority at all */
195 while (1) {
196 while (!need_resched()) {
197 void (*idle)(void) = pm_idle;
198
199 if (!idle)
200 idle = default_idle;
201
202 idle();
203 }
204 schedule();
205 }
206
207}
208
209void hard_reset_now (void);
210
211void machine_restart(void)
212{
213 hard_reset_now();
214}
215
216EXPORT_SYMBOL(machine_restart);
217
218/*
219 * Similar to machine_power_off, but don't shut off power. Add code
220 * here to freeze the system for e.g. post-mortem debug purpose when
221 * possible. This halt has nothing to do with the idle halt.
222 */
223
224void machine_halt(void)
225{
226}
227
228EXPORT_SYMBOL(machine_halt);
229
230/* If or when software power-off is implemented, add code here. */
231
232void machine_power_off(void)
233{
234}
235
236EXPORT_SYMBOL(machine_power_off);
237
238/*
239 * When a process does an "exec", machine state like FPU and debug
240 * registers need to be reset. This is a hook function for that.
241 * Currently we don't have any such state to reset, so this is empty.
242 */
243
244void flush_thread(void)
245{
246}
247
248/*
249 * fill in the user structure for a core dump..
250 */
251void dump_thread(struct pt_regs * regs, struct user * dump)
252{
253#if 0
254 int i;
255
256 /* changed the size calculations - should hopefully work better. lbt */
257 dump->magic = CMAGIC;
258 dump->start_code = 0;
259 dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
260 dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
261 dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
262 dump->u_dsize -= dump->u_tsize;
263 dump->u_ssize = 0;
264 for (i = 0; i < 8; i++)
265 dump->u_debugreg[i] = current->debugreg[i];
266
267 if (dump->start_stack < TASK_SIZE)
268 dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
269
270 dump->regs = *regs;
271
272 dump->u_fpvalid = dump_fpu (regs, &dump->i387);
273#endif
274}
275
276/* Fill in the fpu structure for a core dump. */
277int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
278{
279 return 0;
280}
diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
new file mode 100644
index 000000000000..e85a2fdd9acf
--- /dev/null
+++ b/arch/cris/kernel/ptrace.c
@@ -0,0 +1,119 @@
1/*
2 * linux/arch/cris/kernel/ptrace.c
3 *
4 * Parts taken from the m68k port.
5 *
6 * Copyright (c) 2000, 2001, 2002 Axis Communications AB
7 *
8 * Authors: Bjorn Wesen
9 *
10 * $Log: ptrace.c,v $
11 * Revision 1.9 2003/07/04 12:56:11 tobiasa
12 * Moved arch-specific code to arch-specific files.
13 *
14 * Revision 1.8 2003/04/09 05:20:47 starvik
15 * Merge of Linux 2.5.67
16 *
17 * Revision 1.7 2002/11/27 08:42:34 starvik
18 * Argument to user_regs() is thread_info*
19 *
20 * Revision 1.6 2002/11/20 11:56:11 starvik
21 * Merge of Linux 2.5.48
22 *
23 * Revision 1.5 2002/11/18 07:41:19 starvik
24 * Removed warning
25 *
26 * Revision 1.4 2002/11/11 12:47:28 starvik
27 * SYSCALL_TRACE has been moved to thread flags
28 *
29 * Revision 1.3 2002/02/05 15:37:18 bjornw
30 * * Add do_notify_resume (replaces do_signal in the callchain)
31 * * syscall_trace is now do_syscall_trace
32 * * current->ptrace flag PT_TRACESYS -> PT_SYSCALLTRACE
33 * * Keep track of the current->work.syscall_trace counter
34 *
35 * Revision 1.2 2001/12/18 13:35:20 bjornw
36 * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15).
37 *
38 * Revision 1.8 2001/11/12 18:26:21 pkj
39 * Fixed compiler warnings.
40 *
41 * Revision 1.7 2001/09/26 11:53:49 bjornw
42 * PTRACE_DETACH works more simple in 2.4.10
43 *
44 * Revision 1.6 2001/07/25 16:08:47 bjornw
45 * PTRACE_ATTACH bulk moved into arch-independent code in 2.4.7
46 *
47 * Revision 1.5 2001/03/26 14:24:28 orjanf
48 * * Changed loop condition.
49 * * Added comment documenting non-standard ptrace behaviour.
50 *
51 * Revision 1.4 2001/03/20 19:44:41 bjornw
52 * Use the user_regs macro instead of thread.esp0
53 *
54 * Revision 1.3 2000/12/18 23:45:25 bjornw
55 * Linux/CRIS first version
56 *
57 *
58 */
59
60#include <linux/kernel.h>
61#include <linux/sched.h>
62#include <linux/mm.h>
63#include <linux/smp.h>
64#include <linux/smp_lock.h>
65#include <linux/errno.h>
66#include <linux/ptrace.h>
67#include <linux/user.h>
68
69#include <asm/uaccess.h>
70#include <asm/page.h>
71#include <asm/pgtable.h>
72#include <asm/system.h>
73#include <asm/processor.h>
74
75/*
76 * Get contents of register REGNO in task TASK.
77 */
78inline long get_reg(struct task_struct *task, unsigned int regno)
79{
80 /* USP is a special case, it's not in the pt_regs struct but
81 * in the tasks thread struct
82 */
83
84 if (regno == PT_USP)
85 return task->thread.usp;
86 else if (regno < PT_MAX)
87 return ((unsigned long *)user_regs(task->thread_info))[regno];
88 else
89 return 0;
90}
91
92/*
93 * Write contents of register REGNO in task TASK.
94 */
95inline int put_reg(struct task_struct *task, unsigned int regno,
96 unsigned long data)
97{
98 if (regno == PT_USP)
99 task->thread.usp = data;
100 else if (regno < PT_MAX)
101 ((unsigned long *)user_regs(task->thread_info))[regno] = data;
102 else
103 return -1;
104 return 0;
105}
106
107/* notification of userspace execution resumption
108 * - triggered by current->work.notify_resume
109 */
110extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
111
112
113void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs,
114 __u32 thread_info_flags )
115{
116 /* deal with pending signal delivery */
117 if (thread_info_flags & _TIF_SIGPENDING)
118 do_signal(canrestart,oldset,regs);
119}
diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c
new file mode 100644
index 000000000000..b884263d3cd4
--- /dev/null
+++ b/arch/cris/kernel/semaphore.c
@@ -0,0 +1,130 @@
1/*
2 * Generic semaphore code. Buyer beware. Do your own
3 * specific changes in <asm/semaphore-helper.h>
4 */
5
6#include <linux/sched.h>
7#include <linux/init.h>
8#include <asm/semaphore-helper.h>
9
10/*
11 * Semaphores are implemented using a two-way counter:
12 * The "count" variable is decremented for each process
13 * that tries to sleep, while the "waking" variable is
14 * incremented when the "up()" code goes to wake up waiting
15 * processes.
16 *
17 * Notably, the inline "up()" and "down()" functions can
18 * efficiently test if they need to do any extra work (up
19 * needs to do something only if count was negative before
20 * the increment operation.
21 *
22 * waking_non_zero() (from asm/semaphore.h) must execute
23 * atomically.
24 *
25 * When __up() is called, the count was negative before
26 * incrementing it, and we need to wake up somebody.
27 *
28 * This routine adds one to the count of processes that need to
29 * wake up and exit. ALL waiting processes actually wake up but
30 * only the one that gets to the "waking" field first will gate
31 * through and acquire the semaphore. The others will go back
32 * to sleep.
33 *
34 * Note that these functions are only called when there is
35 * contention on the lock, and as such all this is the
36 * "non-critical" part of the whole semaphore business. The
37 * critical part is the inline stuff in <asm/semaphore.h>
38 * where we want to avoid any extra jumps and calls.
39 */
40void __up(struct semaphore *sem)
41{
42 wake_one_more(sem);
43 wake_up(&sem->wait);
44}
45
46/*
47 * Perform the "down" function. Return zero for semaphore acquired,
48 * return negative for signalled out of the function.
49 *
50 * If called from __down, the return is ignored and the wait loop is
51 * not interruptible. This means that a task waiting on a semaphore
52 * using "down()" cannot be killed until someone does an "up()" on
53 * the semaphore.
54 *
55 * If called from __down_interruptible, the return value gets checked
56 * upon return. If the return value is negative then the task continues
57 * with the negative value in the return register (it can be tested by
58 * the caller).
59 *
60 * Either form may be used in conjunction with "up()".
61 *
62 */
63
64#define DOWN_VAR \
65 struct task_struct *tsk = current; \
66 wait_queue_t wait; \
67 init_waitqueue_entry(&wait, tsk);
68
69#define DOWN_HEAD(task_state) \
70 \
71 \
72 tsk->state = (task_state); \
73 add_wait_queue(&sem->wait, &wait); \
74 \
75 /* \
76 * Ok, we're set up. sem->count is known to be less than zero \
77 * so we must wait. \
78 * \
79 * We can let go the lock for purposes of waiting. \
80 * We re-acquire it after awaking so as to protect \
81 * all semaphore operations. \
82 * \
83 * If "up()" is called before we call waking_non_zero() then \
84 * we will catch it right away. If it is called later then \
85 * we will have to go through a wakeup cycle to catch it. \
86 * \
87 * Multiple waiters contend for the semaphore lock to see \
88 * who gets to gate through and who has to wait some more. \
89 */ \
90 for (;;) {
91
92#define DOWN_TAIL(task_state) \
93 tsk->state = (task_state); \
94 } \
95 tsk->state = TASK_RUNNING; \
96 remove_wait_queue(&sem->wait, &wait);
97
98void __sched __down(struct semaphore * sem)
99{
100 DOWN_VAR
101 DOWN_HEAD(TASK_UNINTERRUPTIBLE)
102 if (waking_non_zero(sem))
103 break;
104 schedule();
105 DOWN_TAIL(TASK_UNINTERRUPTIBLE)
106}
107
108int __sched __down_interruptible(struct semaphore * sem)
109{
110 int ret = 0;
111 DOWN_VAR
112 DOWN_HEAD(TASK_INTERRUPTIBLE)
113
114 ret = waking_non_zero_interruptible(sem, tsk);
115 if (ret)
116 {
117 if (ret == 1)
118 /* ret != 0 only if we get interrupted -arca */
119 ret = 0;
120 break;
121 }
122 schedule();
123 DOWN_TAIL(TASK_INTERRUPTIBLE)
124 return ret;
125}
126
127int __down_trylock(struct semaphore * sem)
128{
129 return waking_non_zero_trylock(sem);
130}
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
new file mode 100644
index 000000000000..6ec2671078bf
--- /dev/null
+++ b/arch/cris/kernel/setup.c
@@ -0,0 +1,193 @@
1/*
2 *
3 * linux/arch/cris/kernel/setup.c
4 *
5 * Copyright (C) 1995 Linus Torvalds
6 * Copyright (c) 2001 Axis Communications AB
7 */
8
9/*
10 * This file handles the architecture-dependent parts of initialization
11 */
12
13#include <linux/config.h>
14#include <linux/init.h>
15#include <linux/mm.h>
16#include <linux/bootmem.h>
17#include <asm/pgtable.h>
18#include <linux/seq_file.h>
19#include <linux/tty.h>
20
21#include <asm/setup.h>
22
23/*
24 * Setup options
25 */
26struct drive_info_struct { char dummy[32]; } drive_info;
27struct screen_info screen_info;
28
29extern int root_mountflags;
30extern char _etext, _edata, _end;
31
32static char command_line[COMMAND_LINE_SIZE] = { 0, };
33
34extern const unsigned long text_start, edata; /* set by the linker script */
35extern unsigned long dram_start, dram_end;
36
37extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */
38
39extern void show_etrax_copyright(void); /* arch-vX/kernel/setup.c */
40
41/* This mainly sets up the memory area, and can be really confusing.
42 *
43 * The physical DRAM is virtually mapped into dram_start to dram_end
44 * (usually c0000000 to c0000000 + DRAM size). The physical address is
45 * given by the macro __pa().
46 *
47 * In this DRAM, the kernel code and data is loaded, in the beginning.
48 * It really starts at c0004000 to make room for some special pages -
49 * the start address is text_start. The kernel data ends at _end. After
50 * this the ROM filesystem is appended (if there is any).
51 *
52 * Between this address and dram_end, we have RAM pages usable to the
53 * boot code and the system.
54 *
55 */
56
57void __init
58setup_arch(char **cmdline_p)
59{
60 extern void init_etrax_debug(void);
61 unsigned long bootmap_size;
62 unsigned long start_pfn, max_pfn;
63 unsigned long memory_start;
64
65 /* register an initial console printing routine for printk's */
66
67 init_etrax_debug();
68
69 /* we should really poll for DRAM size! */
70
71 high_memory = &dram_end;
72
73 if(romfs_in_flash || !romfs_length) {
74 /* if we have the romfs in flash, or if there is no rom filesystem,
75 * our free area starts directly after the BSS
76 */
77 memory_start = (unsigned long) &_end;
78 } else {
79 /* otherwise the free area starts after the ROM filesystem */
80 printk("ROM fs in RAM, size %lu bytes\n", romfs_length);
81 memory_start = romfs_start + romfs_length;
82 }
83
84 /* process 1's initial memory region is the kernel code/data */
85
86 init_mm.start_code = (unsigned long) &text_start;
87 init_mm.end_code = (unsigned long) &_etext;
88 init_mm.end_data = (unsigned long) &_edata;
89 init_mm.brk = (unsigned long) &_end;
90
91#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
92#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
93#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
94
95 /* min_low_pfn points to the start of DRAM, start_pfn points
96 * to the first DRAM pages after the kernel, and max_low_pfn
97 * to the end of DRAM.
98 */
99
100 /*
101 * partially used pages are not usable - thus
102 * we are rounding upwards:
103 */
104
105 start_pfn = PFN_UP(memory_start); /* usually c0000000 + kernel + romfs */
106 max_pfn = PFN_DOWN((unsigned long)high_memory); /* usually c0000000 + dram size */
107
108 /*
109 * Initialize the boot-time allocator (start, end)
110 *
111 * We give it access to all our DRAM, but we could as well just have
112 * given it a small slice. No point in doing that though, unless we
113 * have non-contiguous memory and want the boot-stuff to be in, say,
114 * the smallest area.
115 *
116 * It will put a bitmap of the allocated pages in the beginning
117 * of the range we give it, but it won't mark the bitmaps pages
118 * as reserved. We have to do that ourselves below.
119 *
120 * We need to use init_bootmem_node instead of init_bootmem
121 * because our map starts at a quite high address (min_low_pfn).
122 */
123
124 max_low_pfn = max_pfn;
125 min_low_pfn = PAGE_OFFSET >> PAGE_SHIFT;
126
127 bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
128 min_low_pfn,
129 max_low_pfn);
130
131 /* And free all memory not belonging to the kernel (addr, size) */
132
133 free_bootmem(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn - start_pfn));
134
135 /*
136 * Reserve the bootmem bitmap itself as well. We do this in two
137 * steps (first step was init_bootmem()) because this catches
138 * the (very unlikely) case of us accidentally initializing the
139 * bootmem allocator with an invalid RAM area.
140 *
141 * Arguments are start, size
142 */
143
144 reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size);
145
146 /* paging_init() sets up the MMU and marks all pages as reserved */
147
148 paging_init();
149
150 /* We don't use a command line yet, so just re-initialize it without
151 saving anything that might be there. */
152
153 *cmdline_p = command_line;
154
155#ifdef CONFIG_ETRAX_CMDLINE
156 strlcpy(command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE);
157 command_line[COMMAND_LINE_SIZE - 1] = '\0';
158
159 /* Save command line for future references. */
160 memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
161 saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
162#endif
163
164 /* give credit for the CRIS port */
165 show_etrax_copyright();
166}
167
168static void *c_start(struct seq_file *m, loff_t *pos)
169{
170 /* We only got one CPU... */
171 return *pos < 1 ? (void *)1 : NULL;
172}
173
174static void *c_next(struct seq_file *m, void *v, loff_t *pos)
175{
176 ++*pos;
177 return NULL;
178}
179
180static void c_stop(struct seq_file *m, void *v)
181{
182}
183
184extern int show_cpuinfo(struct seq_file *m, void *v);
185
186struct seq_operations cpuinfo_op = {
187 .start = c_start,
188 .next = c_next,
189 .stop = c_stop,
190 .show = show_cpuinfo,
191};
192
193
diff --git a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c
new file mode 100644
index 000000000000..0aa0e0ebb3a9
--- /dev/null
+++ b/arch/cris/kernel/sys_cris.c
@@ -0,0 +1,174 @@
1/* $Id: sys_cris.c,v 1.6 2004/03/11 11:38:40 starvik Exp $
2 *
3 * linux/arch/cris/kernel/sys_cris.c
4 *
5 * This file contains various random system calls that
6 * have a non-standard calling sequence on some platforms.
7 * Since we don't have to do any backwards compatibility, our
8 * versions are done in the most "normal" way possible.
9 *
10 */
11
12#include <linux/errno.h>
13#include <linux/sched.h>
14#include <linux/syscalls.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
17#include <linux/smp_lock.h>
18#include <linux/sem.h>
19#include <linux/msg.h>
20#include <linux/shm.h>
21#include <linux/stat.h>
22#include <linux/mman.h>
23#include <linux/file.h>
24
25#include <asm/uaccess.h>
26#include <asm/ipc.h>
27#include <asm/segment.h>
28
29/*
30 * sys_pipe() is the normal C calling standard for creating
31 * a pipe. It's not the way Unix traditionally does this, though.
32 */
33asmlinkage int sys_pipe(unsigned long __user * fildes)
34{
35 int fd[2];
36 int error;
37
38 lock_kernel();
39 error = do_pipe(fd);
40 unlock_kernel();
41 if (!error) {
42 if (copy_to_user(fildes, fd, 2*sizeof(int)))
43 error = -EFAULT;
44 }
45 return error;
46}
47
48/* common code for old and new mmaps */
49static inline long
50do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
51 unsigned long flags, unsigned long fd, unsigned long pgoff)
52{
53 int error = -EBADF;
54 struct file * file = NULL;
55
56 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
57 if (!(flags & MAP_ANONYMOUS)) {
58 file = fget(fd);
59 if (!file)
60 goto out;
61 }
62
63 down_write(&current->mm->mmap_sem);
64 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
65 up_write(&current->mm->mmap_sem);
66
67 if (file)
68 fput(file);
69out:
70 return error;
71}
72
73asmlinkage unsigned long old_mmap(unsigned long __user *args)
74{
75 unsigned long buffer[6];
76 int err = -EFAULT;
77
78 if (copy_from_user(&buffer, args, sizeof(buffer)))
79 goto out;
80
81 err = -EINVAL;
82 if (buffer[5] & ~PAGE_MASK) /* verify that offset is on page boundary */
83 goto out;
84
85 err = do_mmap2(buffer[0], buffer[1], buffer[2], buffer[3],
86 buffer[4], buffer[5] >> PAGE_SHIFT);
87out:
88 return err;
89}
90
91asmlinkage long
92sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
93 unsigned long flags, unsigned long fd, unsigned long pgoff)
94{
95 return do_mmap2(addr, len, prot, flags, fd, pgoff);
96}
97
98/*
99 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
100 *
101 * This is really horribly ugly. (same as arch/i386)
102 */
103
104asmlinkage int sys_ipc (uint call, int first, int second,
105 int third, void __user *ptr, long fifth)
106{
107 int version, ret;
108
109 version = call >> 16; /* hack for backward compatibility */
110 call &= 0xffff;
111
112 switch (call) {
113 case SEMOP:
114 return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
115 case SEMTIMEDOP:
116 return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
117 (const struct timespec __user *)fifth);
118
119 case SEMGET:
120 return sys_semget (first, second, third);
121 case SEMCTL: {
122 union semun fourth;
123 if (!ptr)
124 return -EINVAL;
125 if (get_user(fourth.__pad, (void * __user *) ptr))
126 return -EFAULT;
127 return sys_semctl (first, second, third, fourth);
128 }
129
130 case MSGSND:
131 return sys_msgsnd (first, (struct msgbuf __user *) ptr,
132 second, third);
133 case MSGRCV:
134 switch (version) {
135 case 0: {
136 struct ipc_kludge tmp;
137 if (!ptr)
138 return -EINVAL;
139
140 if (copy_from_user(&tmp,
141 (struct ipc_kludge __user *) ptr,
142 sizeof (tmp)))
143 return -EFAULT;
144 return sys_msgrcv (first, tmp.msgp, second,
145 tmp.msgtyp, third);
146 }
147 default:
148 return sys_msgrcv (first,
149 (struct msgbuf __user *) ptr,
150 second, fifth, third);
151 }
152 case MSGGET:
153 return sys_msgget ((key_t) first, second);
154 case MSGCTL:
155 return sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
156
157 case SHMAT: {
158 ulong raddr;
159 ret = do_shmat (first, (char __user *) ptr, second, &raddr);
160 if (ret)
161 return ret;
162 return put_user (raddr, (ulong __user *) third);
163 }
164 case SHMDT:
165 return sys_shmdt ((char __user *)ptr);
166 case SHMGET:
167 return sys_shmget (first, second, third);
168 case SHMCTL:
169 return sys_shmctl (first, second,
170 (struct shmid_ds __user *) ptr);
171 default:
172 return -ENOSYS;
173 }
174}
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
new file mode 100644
index 000000000000..6c28b0e7f7b4
--- /dev/null
+++ b/arch/cris/kernel/time.c
@@ -0,0 +1,232 @@
1/* $Id: time.c,v 1.14 2004/06/01 05:38:11 starvik Exp $
2 *
3 * linux/arch/cris/kernel/time.c
4 *
5 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
6 * Copyright (C) 1999, 2000, 2001 Axis Communications AB
7 *
8 * 1994-07-02 Alan Modra
9 * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
10 * 1995-03-26 Markus Kuhn
11 * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
12 * precision CMOS clock update
13 * 1996-05-03 Ingo Molnar
14 * fixed time warps in do_[slow|fast]_gettimeoffset()
15 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
16 * "A Kernel Model for Precision Timekeeping" by Dave Mills
17 *
18 * Linux/CRIS specific code:
19 *
20 * Authors: Bjorn Wesen
21 * Johan Adolfsson
22 *
23 */
24
25#include <asm/rtc.h>
26#include <linux/errno.h>
27#include <linux/module.h>
28#include <linux/param.h>
29#include <linux/jiffies.h>
30#include <linux/bcd.h>
31#include <linux/timex.h>
32#include <linux/init.h>
33
34u64 jiffies_64 = INITIAL_JIFFIES;
35
36EXPORT_SYMBOL(jiffies_64);
37
38int have_rtc; /* used to remember if we have an RTC or not */;
39
40#define TICK_SIZE tick
41
42extern unsigned long wall_jiffies;
43extern unsigned long loops_per_jiffy; /* init/main.c */
44unsigned long loops_per_usec;
45
46extern unsigned long do_slow_gettimeoffset(void);
47static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
48
49/*
50 * This version of gettimeofday has near microsecond resolution.
51 *
52 * Note: Division is quite slow on CRIS and do_gettimeofday is called
53 * rather often. Maybe we should do some kind of approximation here
54 * (a naive approximation would be to divide by 1024).
55 */
56void do_gettimeofday(struct timeval *tv)
57{
58 unsigned long flags;
59 signed long usec, sec;
60 local_irq_save(flags);
61 local_irq_disable();
62 usec = do_gettimeoffset();
63 {
64 unsigned long lost = jiffies - wall_jiffies;
65 if (lost)
66 usec += lost * (1000000 / HZ);
67 }
68
69 /*
70 * If time_adjust is negative then NTP is slowing the clock
71 * so make sure not to go into next possible interval.
72 * Better to lose some accuracy than have time go backwards..
73 */
74 if (unlikely(time_adjust < 0) && usec > tickadj)
75 usec = tickadj;
76
77 sec = xtime.tv_sec;
78 usec += xtime.tv_nsec / 1000;
79 local_irq_restore(flags);
80
81 while (usec >= 1000000) {
82 usec -= 1000000;
83 sec++;
84 }
85
86 tv->tv_sec = sec;
87 tv->tv_usec = usec;
88}
89
90EXPORT_SYMBOL(do_gettimeofday);
91
92int do_settimeofday(struct timespec *tv)
93{
94 time_t wtm_sec, sec = tv->tv_sec;
95 long wtm_nsec, nsec = tv->tv_nsec;
96
97 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
98 return -EINVAL;
99
100 write_seqlock_irq(&xtime_lock);
101 /*
102 * This is revolting. We need to set "xtime" correctly. However, the
103 * value in this location is the value at the most recent update of
104 * wall time. Discover what correction gettimeofday() would have
105 * made, and then undo it!
106 */
107 nsec -= do_gettimeoffset() * NSEC_PER_USEC;
108 nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
109
110 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
111 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
112
113 set_normalized_timespec(&xtime, sec, nsec);
114 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
115
116 time_adjust = 0; /* stop active adjtime() */
117 time_status |= STA_UNSYNC;
118 time_maxerror = NTP_PHASE_LIMIT;
119 time_esterror = NTP_PHASE_LIMIT;
120 write_sequnlock_irq(&xtime_lock);
121 clock_was_set();
122 return 0;
123}
124
125EXPORT_SYMBOL(do_settimeofday);
126
127
128/*
129 * BUG: This routine does not handle hour overflow properly; it just
130 * sets the minutes. Usually you'll only notice that after reboot!
131 */
132
133int set_rtc_mmss(unsigned long nowtime)
134{
135 int retval = 0;
136 int real_seconds, real_minutes, cmos_minutes;
137
138 printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime);
139
140 if(!have_rtc)
141 return 0;
142
143 cmos_minutes = CMOS_READ(RTC_MINUTES);
144 BCD_TO_BIN(cmos_minutes);
145
146 /*
147 * since we're only adjusting minutes and seconds,
148 * don't interfere with hour overflow. This avoids
149 * messing with unknown time zones but requires your
150 * RTC not to be off by more than 15 minutes
151 */
152 real_seconds = nowtime % 60;
153 real_minutes = nowtime / 60;
154 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
155 real_minutes += 30; /* correct for half hour time zone */
156 real_minutes %= 60;
157
158 if (abs(real_minutes - cmos_minutes) < 30) {
159 BIN_TO_BCD(real_seconds);
160 BIN_TO_BCD(real_minutes);
161 CMOS_WRITE(real_seconds,RTC_SECONDS);
162 CMOS_WRITE(real_minutes,RTC_MINUTES);
163 } else {
164 printk(KERN_WARNING
165 "set_rtc_mmss: can't update from %d to %d\n",
166 cmos_minutes, real_minutes);
167 retval = -1;
168 }
169
170 return retval;
171}
172
173/* grab the time from the RTC chip */
174
175unsigned long
176get_cmos_time(void)
177{
178 unsigned int year, mon, day, hour, min, sec;
179
180 sec = CMOS_READ(RTC_SECONDS);
181 min = CMOS_READ(RTC_MINUTES);
182 hour = CMOS_READ(RTC_HOURS);
183 day = CMOS_READ(RTC_DAY_OF_MONTH);
184 mon = CMOS_READ(RTC_MONTH);
185 year = CMOS_READ(RTC_YEAR);
186
187 printk(KERN_DEBUG
188 "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n",
189 sec, min, hour, day, mon, year);
190
191 BCD_TO_BIN(sec);
192 BCD_TO_BIN(min);
193 BCD_TO_BIN(hour);
194 BCD_TO_BIN(day);
195 BCD_TO_BIN(mon);
196 BCD_TO_BIN(year);
197
198 if ((year += 1900) < 1970)
199 year += 100;
200
201 return mktime(year, mon, day, hour, min, sec);
202}
203
204/* update xtime from the CMOS settings. used when /dev/rtc gets a SET_TIME.
205 * TODO: this doesn't reset the fancy NTP phase stuff as do_settimeofday does.
206 */
207
208void
209update_xtime_from_cmos(void)
210{
211 if(have_rtc) {
212 xtime.tv_sec = get_cmos_time();
213 xtime.tv_nsec = 0;
214 }
215}
216
217/*
218 * Scheduler clock - returns current time in nanosec units.
219 */
220unsigned long long sched_clock(void)
221{
222 return (unsigned long long)jiffies * (1000000000 / HZ);
223}
224
225static int
226__init init_udelay(void)
227{
228 loops_per_usec = (loops_per_jiffy * HZ) / 1000000;
229 return 0;
230}
231
232__initcall(init_udelay);
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
new file mode 100644
index 000000000000..d4dfa050e3a5
--- /dev/null
+++ b/arch/cris/kernel/traps.c
@@ -0,0 +1,144 @@
1/* $Id: traps.c,v 1.9 2004/05/11 12:28:26 starvik Exp $
2 *
3 * linux/arch/cris/traps.c
4 *
5 * Here we handle the break vectors not used by the system call
6 * mechanism, as well as some general stack/register dumping
7 * things.
8 *
9 * Copyright (C) 2000-2002 Axis Communications AB
10 *
11 * Authors: Bjorn Wesen
12 * Hans-Peter Nilsson
13 *
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <asm/pgtable.h>
19#include <asm/uaccess.h>
20
21static int kstack_depth_to_print = 24;
22
23void show_trace(unsigned long * stack)
24{
25 unsigned long addr, module_start, module_end;
26 extern char _stext, _etext;
27 int i;
28
29 printk("\nCall Trace: ");
30
31 i = 1;
32 module_start = VMALLOC_START;
33 module_end = VMALLOC_END;
34
35 while (((long) stack & (THREAD_SIZE-1)) != 0) {
36 if (__get_user (addr, stack)) {
37 /* This message matches "failing address" marked
38 s390 in ksymoops, so lines containing it will
39 not be filtered out by ksymoops. */
40 printk ("Failing address 0x%lx\n", (unsigned long)stack);
41 break;
42 }
43 stack++;
44
45 /*
46 * If the address is either in the text segment of the
47 * kernel, or in the region which contains vmalloc'ed
48 * memory, it *may* be the address of a calling
49 * routine; if so, print it so that someone tracing
50 * down the cause of the crash will be able to figure
51 * out the call path that was taken.
52 */
53 if (((addr >= (unsigned long) &_stext) &&
54 (addr <= (unsigned long) &_etext)) ||
55 ((addr >= module_start) && (addr <= module_end))) {
56 if (i && ((i % 8) == 0))
57 printk("\n ");
58 printk("[<%08lx>] ", addr);
59 i++;
60 }
61 }
62}
63
64/*
65 * These constants are for searching for possible module text
66 * segments. MODULE_RANGE is a guess of how much space is likely
67 * to be vmalloced.
68 */
69
70#define MODULE_RANGE (8*1024*1024)
71
72/*
73 * The output (format, strings and order) is adjusted to be usable with
74 * ksymoops-2.4.1 with some necessary CRIS-specific patches. Please don't
75 * change it unless you're serious about adjusting ksymoops and syncing
76 * with the ksymoops maintainer.
77 */
78
79void
80show_stack(struct task_struct *task, unsigned long *sp)
81{
82 unsigned long *stack, addr;
83 int i;
84
85 /*
86 * debugging aid: "show_stack(NULL);" prints a
87 * back trace.
88 */
89
90 if(sp == NULL) {
91 if (task)
92 sp = (unsigned long*)task->thread.ksp;
93 else
94 sp = (unsigned long*)rdsp();
95 }
96
97 stack = sp;
98
99 printk("\nStack from %08lx:\n ", (unsigned long)stack);
100 for(i = 0; i < kstack_depth_to_print; i++) {
101 if (((long) stack & (THREAD_SIZE-1)) == 0)
102 break;
103 if (i && ((i % 8) == 0))
104 printk("\n ");
105 if (__get_user (addr, stack)) {
106 /* This message matches "failing address" marked
107 s390 in ksymoops, so lines containing it will
108 not be filtered out by ksymoops. */
109 printk ("Failing address 0x%lx\n", (unsigned long)stack);
110 break;
111 }
112 stack++;
113 printk("%08lx ", addr);
114 }
115 show_trace(sp);
116}
117
118#if 0
119/* displays a short stack trace */
120
121int
122show_stack()
123{
124 unsigned long *sp = (unsigned long *)rdusp();
125 int i;
126 printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
127 for(i = 0; i < 16; i++)
128 printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
129 return 0;
130}
131#endif
132
133void dump_stack(void)
134{
135 show_stack(NULL, NULL);
136}
137
138EXPORT_SYMBOL(dump_stack);
139
140void __init
141trap_init(void)
142{
143 /* Nothing needs to be done */
144}