diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/cris/kernel |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/cris/kernel')
-rw-r--r-- | arch/cris/kernel/Makefile | 15 | ||||
-rw-r--r-- | arch/cris/kernel/crisksyms.c | 103 | ||||
-rw-r--r-- | arch/cris/kernel/irq.c | 297 | ||||
-rw-r--r-- | arch/cris/kernel/module.c | 121 | ||||
-rw-r--r-- | arch/cris/kernel/process.c | 280 | ||||
-rw-r--r-- | arch/cris/kernel/ptrace.c | 119 | ||||
-rw-r--r-- | arch/cris/kernel/semaphore.c | 130 | ||||
-rw-r--r-- | arch/cris/kernel/setup.c | 193 | ||||
-rw-r--r-- | arch/cris/kernel/sys_cris.c | 174 | ||||
-rw-r--r-- | arch/cris/kernel/time.c | 232 | ||||
-rw-r--r-- | arch/cris/kernel/traps.c | 144 |
11 files changed, 1808 insertions, 0 deletions
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile new file mode 100644 index 00000000000..1546a0e7404 --- /dev/null +++ b/arch/cris/kernel/Makefile @@ -0,0 +1,15 @@ +# $Id: Makefile,v 1.10 2004/05/14 10:18:12 starvik Exp $ +# +# Makefile for the linux kernel. +# + +extra-y := vmlinux.lds + +obj-y := process.o traps.o irq.o ptrace.o setup.o \ + time.o sys_cris.o semaphore.o + +obj-$(CONFIG_MODULES) += crisksyms.o +obj-$(CONFIG_MODULES) += module.o + +clean: + diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c new file mode 100644 index 00000000000..7141bbecd7e --- /dev/null +++ b/arch/cris/kernel/crisksyms.c @@ -0,0 +1,103 @@ +#include <linux/config.h> +#include <linux/module.h> +#include <linux/user.h> +#include <linux/elfcore.h> +#include <linux/sched.h> +#include <linux/in6.h> +#include <linux/interrupt.h> +#include <linux/smp_lock.h> +#include <linux/pm.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/tty.h> + +#include <asm/semaphore.h> +#include <asm/processor.h> +#include <asm/uaccess.h> +#include <asm/checksum.h> +#include <asm/io.h> +#include <asm/delay.h> +#include <asm/irq.h> +#include <asm/pgtable.h> +#include <asm/fasttimer.h> + +extern void dump_thread(struct pt_regs *, struct user *); +extern unsigned long get_cmos_time(void); +extern void __Udiv(void); +extern void __Umod(void); +extern void __Div(void); +extern void __Mod(void); +extern void __ashrdi3(void); +extern void iounmap(void *addr); + +/* Platform dependent support */ +EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(get_cmos_time); +EXPORT_SYMBOL(loops_per_usec); + +/* String functions */ +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strpbrk); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strncpy); + +/* Math functions */ +EXPORT_SYMBOL(__Udiv); +EXPORT_SYMBOL(__Umod); +EXPORT_SYMBOL(__Div); +EXPORT_SYMBOL(__Mod); +EXPORT_SYMBOL(__ashrdi3); + +/* Memory functions */ +EXPORT_SYMBOL(__ioremap); +EXPORT_SYMBOL(iounmap); + +/* Semaphore functions */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); + +/* Export shadow registers for the CPU I/O pins */ +EXPORT_SYMBOL(genconfig_shadow); +EXPORT_SYMBOL(port_pa_data_shadow); +EXPORT_SYMBOL(port_pa_dir_shadow); +EXPORT_SYMBOL(port_pb_data_shadow); +EXPORT_SYMBOL(port_pb_dir_shadow); +EXPORT_SYMBOL(port_pb_config_shadow); +EXPORT_SYMBOL(port_g_data_shadow); + +/* Userspace access functions */ +EXPORT_SYMBOL(__copy_user_zeroing); +EXPORT_SYMBOL(__copy_user); + +/* Cache flush functions */ +EXPORT_SYMBOL(flush_etrax_cache); +EXPORT_SYMBOL(prepare_rx_descriptor); + +#undef memcpy +#undef memset +extern void * memset(void *, int, __kernel_size_t); +extern void * memcpy(void *, const void *, __kernel_size_t); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); + +#ifdef CONFIG_ETRAX_FAST_TIMER +/* Fast timer functions */ +EXPORT_SYMBOL(fast_timer_list); +EXPORT_SYMBOL(start_one_shot_timer); +EXPORT_SYMBOL(del_fast_timer); +EXPORT_SYMBOL(schedule_usleep); +#endif + diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c new file mode 100644 index 00000000000..d848b940745 --- /dev/null +++ b/arch/cris/kernel/irq.c @@ -0,0 +1,297 @@ +/* + * + * linux/arch/cris/kernel/irq.c + * + * Copyright (c) 2000,2001 Axis Communications AB + * + * Authors: Bjorn Wesen (bjornw@axis.com) + * + * This file contains the code used by various IRQ handling routines: + * asking for different IRQ's should be done through these routines + * instead of just grabbing them. Thus setups with different IRQ numbers + * shouldn't result in any weird surprises, and installing new handlers + * should be easier. + * + * Notice Linux/CRIS: these routines do not care about SMP + * + */ + +/* + * IRQ's are in fact implemented a bit like signal handlers for the kernel. + * Naturally it's not a 1:1 relation, but there are similarities. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/ptrace.h> + +#include <linux/kernel_stat.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/ioport.h> +#include <linux/interrupt.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/init.h> +#include <linux/seq_file.h> +#include <linux/errno.h> +#include <linux/bitops.h> + +#include <asm/io.h> + +/* Defined in arch specific irq.c */ +extern void arch_setup_irq(int irq); +extern void arch_free_irq(int irq); + +void +disable_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_save_flags(flags); + local_irq_disable(); + mask_irq(irq_nr); + local_irq_restore(flags); +} + +void +enable_irq(unsigned int irq_nr) +{ + unsigned long flags; + local_save_flags(flags); + local_irq_disable(); + unmask_irq(irq_nr); + local_irq_restore(flags); +} + +unsigned long +probe_irq_on() +{ + return 0; +} + +EXPORT_SYMBOL(probe_irq_on); + +int +probe_irq_off(unsigned long x) +{ + return 0; +} + +EXPORT_SYMBOL(probe_irq_off); + +/* + * Initial irq handlers. + */ + +static struct irqaction *irq_action[NR_IRQS]; + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *) v; + struct irqaction * action; + unsigned long flags; + + if (i < NR_IRQS) { + local_irq_save(flags); + action = irq_action[i]; + if (!action) + goto skip; + seq_printf(p, "%2d: %10u %c %s", + i, kstat_this_cpu.irqs[i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action = action->next; action; action = action->next) { + seq_printf(p, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + seq_putc(p, '\n'); +skip: + local_irq_restore(flags); + } + return 0; +} + +/* called by the assembler IRQ entry functions defined in irq.h + * to dispatch the interrupts to registred handlers + * interrupts are disabled upon entry - depending on if the + * interrupt was registred with SA_INTERRUPT or not, interrupts + * are re-enabled or not. + */ + +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + struct irqaction *action; + int do_random, cpu; + int ret, retval = 0; + + cpu = smp_processor_id(); + irq_enter(); + kstat_cpu(cpu).irqs[irq - FIRST_IRQ]++; + action = irq_action[irq - FIRST_IRQ]; + + if (action) { + if (!(action->flags & SA_INTERRUPT)) + local_irq_enable(); + do_random = 0; + do { + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + do_random |= action->flags; + retval |= ret; + action = action->next; + } while (action); + + if (retval != 1) { + if (retval) { + printk("irq event %d: bogus retval mask %x\n", + irq, retval); + } else { + printk("irq %d: nobody cared\n", irq); + } + } + + if (do_random & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + local_irq_disable(); + } + irq_exit(); +} + +/* this function links in a handler into the chain of handlers for the + given irq, and if the irq has never been registred, the appropriate + handler is entered into the interrupt vector +*/ + +int setup_irq(int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + + p = irq_action + irq - FIRST_IRQ; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) + return -EBUSY; + + /* Can't share interrupts unless both are same type */ + if ((old->flags ^ new->flags) & SA_INTERRUPT) + return -EBUSY; + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + if (new->flags & SA_SAMPLE_RANDOM) + rand_initialize_irq(irq); + + local_save_flags(flags); + local_irq_disable(); + *p = new; + + if (!shared) { + /* if the irq wasn't registred before, enter it into the vector table + and unmask it physically + */ + arch_setup_irq(irq); + unmask_irq(irq); + } + + local_irq_restore(flags); + return 0; +} + +/* this function is called by a driver to register an irq handler + Valid flags: + SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and + no signal checking etc is performed upon exit + SA_SHIRQ -> the interrupt can be shared between different handlers, the handler + is required to check if the irq was "aimed" at it explicitely + SA_RANDOM -> the interrupt will add to the random generators entropy +*/ + +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action; + + if(!handler) + return -EINVAL; + + /* allocate and fill in a handler structure and setup the irq */ + + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + cpus_clear(action->mask); + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_irq(irq, action); + + if (retval) + kfree(action); + return retval; +} + +EXPORT_SYMBOL(request_irq); + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction * action, **p; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk("Trying to free IRQ%d\n",irq); + return; + } + for (p = irq - FIRST_IRQ + irq_action; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + local_save_flags(flags); + local_irq_disable(); + *p = action->next; + if (!irq_action[irq - FIRST_IRQ]) { + mask_irq(irq); + arch_free_irq(irq); + } + local_irq_restore(flags); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); +} + +EXPORT_SYMBOL(free_irq); + +void weird_irq(void) +{ + local_irq_disable(); + printk("weird irq\n"); + while(1); +} + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) +/* Used by other archs to show/control IRQ steering during SMP */ +void __init +init_irq_proc(void) +{ +} +#endif diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c new file mode 100644 index 00000000000..f1d3e784f30 --- /dev/null +++ b/arch/cris/kernel/module.c @@ -0,0 +1,121 @@ +/* Kernel module help for i386. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include <linux/moduleloader.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/kernel.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* We don't need anything special. */ +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + /* We add the value into the location given */ + *location += sym->st_value; + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; + + DEBUGP ("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { + /* This is where to make the change */ + uint32_t *loc + = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rela[i].r_offset); + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + Elf32_Sym *sym + = ((Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM (rela[i].r_info)); + *loc = sym->st_value + rela[i].r_addend; + } + + return 0; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c new file mode 100644 index 00000000000..9f7cad7c784 --- /dev/null +++ b/arch/cris/kernel/process.c @@ -0,0 +1,280 @@ +/* $Id: process.c,v 1.17 2004/04/05 13:53:48 starvik Exp $ + * + * linux/arch/cris/kernel/process.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 2000-2002 Axis Communications AB + * + * Authors: Bjorn Wesen (bjornw@axis.com) + * + * $Log: process.c,v $ + * Revision 1.17 2004/04/05 13:53:48 starvik + * Merge of Linux 2.6.5 + * + * Revision 1.16 2003/10/27 08:04:33 starvik + * Merge of Linux 2.6.0-test9 + * + * Revision 1.15 2003/09/11 07:29:52 starvik + * Merge of Linux 2.6.0-test5 + * + * Revision 1.14 2003/06/10 10:21:12 johana + * Moved thread_saved_pc() from arch/cris/kernel/process.c to + * subarch specific process.c. arch-v32 has an erp, no irp. + * + * Revision 1.13 2003/04/09 05:20:47 starvik + * Merge of Linux 2.5.67 + * + * Revision 1.12 2002/12/11 15:41:11 starvik + * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/kernel + * + * Revision 1.11 2002/12/10 09:00:10 starvik + * Merge of Linux 2.5.51 + * + * Revision 1.10 2002/11/27 08:42:34 starvik + * Argument to user_regs() is thread_info* + * + * Revision 1.9 2002/11/26 09:44:21 starvik + * New threads exits through ret_from_fork (necessary for preemptive scheduling) + * + * Revision 1.8 2002/11/19 14:35:24 starvik + * Changes from linux 2.4 + * Changed struct initializer syntax to the currently prefered notation + * + * Revision 1.7 2002/11/18 07:39:42 starvik + * thread_saved_pc moved here from processor.h + * + * Revision 1.6 2002/11/14 06:51:27 starvik + * Made cpu_idle more similar with other archs + * init_task_union -> init_thread_union + * Updated for new interrupt macros + * sys_clone and do_fork have a new argument, user_tid + * + * Revision 1.5 2002/11/05 06:45:11 starvik + * Merge of Linux 2.5.45 + * + * Revision 1.4 2002/02/05 15:37:44 bjornw + * Need init_task.h + * + * Revision 1.3 2002/01/21 15:22:49 bjornw + * current->counter is gone + * + * Revision 1.22 2001/11/13 09:40:43 orjanf + * Added dump_fpu (needed for core dumps). + * + * Revision 1.21 2001/11/12 18:26:21 pkj + * Fixed compiler warnings. + * + * Revision 1.20 2001/10/03 08:21:39 jonashg + * cause_of_death does not exist if CONFIG_SVINTO_SIM is defined. + * + * Revision 1.19 2001/09/26 11:52:54 bjornw + * INIT_MMAP is gone in 2.4.10 + * + * Revision 1.18 2001/08/21 21:43:51 hp + * Move last watchdog fix inside #ifdef CONFIG_ETRAX_WATCHDOG + * + * Revision 1.17 2001/08/21 13:48:01 jonashg + * Added fix by HP to avoid oops when doing a hard_reset_now. + * + * Revision 1.16 2001/06/21 02:00:40 hp + * * entry.S: Include asm/unistd.h. + * (_sys_call_table): Use section .rodata, not .data. + * (_kernel_thread): Move from... + * * process.c: ... here. + * * entryoffsets.c (VAL): Break out from... + * (OF): Use VAL. + * (LCLONE_VM): New asmified value from CLONE_VM. + * + * Revision 1.15 2001/06/20 16:31:57 hp + * Add comments to describe empty functions according to review. + * + * Revision 1.14 2001/05/29 11:27:59 markusl + * Fixed so that hard_reset_now will do reset even if watchdog wasn't enabled + * + * Revision 1.13 2001/03/20 19:44:06 bjornw + * Use the 7th syscall argument for regs instead of current_regs + * + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#include <asm/atomic.h> +#include <asm/pgtable.h> +#include <asm/uaccess.h> +#include <asm/irq.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/fs_struct.h> +#include <linux/init_task.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/user.h> +#include <linux/elfcore.h> +#include <linux/mqueue.h> + +//#define DEBUG + +/* + * Initial task structure. Make this a per-architecture thing, + * because different architectures tend to have different + * alignment requirements and potentially different initial + * setup. + */ + +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); +struct mm_struct init_mm = INIT_MM(init_mm); + +EXPORT_SYMBOL(init_mm); + +/* + * Initial thread structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry.. + */ +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); + +EXPORT_SYMBOL(init_task); + +/* + * The hlt_counter, disable_hlt and enable_hlt is just here as a hook if + * there would ever be a halt sequence (for power save when idle) with + * some largish delay when halting or resuming *and* a driver that can't + * afford that delay. The hlt_counter would then be checked before + * executing the halt sequence, and the driver marks the unhaltable + * region by enable_hlt/disable_hlt. + */ + +static int hlt_counter=0; + +void disable_hlt(void) +{ + hlt_counter++; +} + +EXPORT_SYMBOL(disable_hlt); + +void enable_hlt(void) +{ + hlt_counter--; +} + +EXPORT_SYMBOL(enable_hlt); + +/* + * The following aren't currently used. + */ +void (*pm_idle)(void); + +extern void default_idle(void); + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle (void) +{ + /* endless idle loop with no priority at all */ + while (1) { + while (!need_resched()) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + idle(); + } + schedule(); + } + +} + +void hard_reset_now (void); + +void machine_restart(void) +{ + hard_reset_now(); +} + +EXPORT_SYMBOL(machine_restart); + +/* + * Similar to machine_power_off, but don't shut off power. Add code + * here to freeze the system for e.g. post-mortem debug purpose when + * possible. This halt has nothing to do with the idle halt. + */ + +void machine_halt(void) +{ +} + +EXPORT_SYMBOL(machine_halt); + +/* If or when software power-off is implemented, add code here. */ + +void machine_power_off(void) +{ +} + +EXPORT_SYMBOL(machine_power_off); + +/* + * When a process does an "exec", machine state like FPU and debug + * registers need to be reset. This is a hook function for that. + * Currently we don't have any such state to reset, so this is empty. + */ + +void flush_thread(void) +{ +} + +/* + * fill in the user structure for a core dump.. + */ +void dump_thread(struct pt_regs * regs, struct user * dump) +{ +#if 0 + int i; + + /* changed the size calculations - should hopefully work better. lbt */ + dump->magic = CMAGIC; + dump->start_code = 0; + dump->start_stack = regs->esp & ~(PAGE_SIZE - 1); + dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; + dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; + dump->u_dsize -= dump->u_tsize; + dump->u_ssize = 0; + for (i = 0; i < 8; i++) + dump->u_debugreg[i] = current->debugreg[i]; + + if (dump->start_stack < TASK_SIZE) + dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; + + dump->regs = *regs; + + dump->u_fpvalid = dump_fpu (regs, &dump->i387); +#endif +} + +/* Fill in the fpu structure for a core dump. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) +{ + return 0; +} diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c new file mode 100644 index 00000000000..e85a2fdd9ac --- /dev/null +++ b/arch/cris/kernel/ptrace.c @@ -0,0 +1,119 @@ +/* + * linux/arch/cris/kernel/ptrace.c + * + * Parts taken from the m68k port. + * + * Copyright (c) 2000, 2001, 2002 Axis Communications AB + * + * Authors: Bjorn Wesen + * + * $Log: ptrace.c,v $ + * Revision 1.9 2003/07/04 12:56:11 tobiasa + * Moved arch-specific code to arch-specific files. + * + * Revision 1.8 2003/04/09 05:20:47 starvik + * Merge of Linux 2.5.67 + * + * Revision 1.7 2002/11/27 08:42:34 starvik + * Argument to user_regs() is thread_info* + * + * Revision 1.6 2002/11/20 11:56:11 starvik + * Merge of Linux 2.5.48 + * + * Revision 1.5 2002/11/18 07:41:19 starvik + * Removed warning + * + * Revision 1.4 2002/11/11 12:47:28 starvik + * SYSCALL_TRACE has been moved to thread flags + * + * Revision 1.3 2002/02/05 15:37:18 bjornw + * * Add do_notify_resume (replaces do_signal in the callchain) + * * syscall_trace is now do_syscall_trace + * * current->ptrace flag PT_TRACESYS -> PT_SYSCALLTRACE + * * Keep track of the current->work.syscall_trace counter + * + * Revision 1.2 2001/12/18 13:35:20 bjornw + * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15). + * + * Revision 1.8 2001/11/12 18:26:21 pkj + * Fixed compiler warnings. + * + * Revision 1.7 2001/09/26 11:53:49 bjornw + * PTRACE_DETACH works more simple in 2.4.10 + * + * Revision 1.6 2001/07/25 16:08:47 bjornw + * PTRACE_ATTACH bulk moved into arch-independent code in 2.4.7 + * + * Revision 1.5 2001/03/26 14:24:28 orjanf + * * Changed loop condition. + * * Added comment documenting non-standard ptrace behaviour. + * + * Revision 1.4 2001/03/20 19:44:41 bjornw + * Use the user_regs macro instead of thread.esp0 + * + * Revision 1.3 2000/12/18 23:45:25 bjornw + * Linux/CRIS first version + * + * + */ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/errno.h> +#include <linux/ptrace.h> +#include <linux/user.h> + +#include <asm/uaccess.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/processor.h> + +/* + * Get contents of register REGNO in task TASK. + */ +inline long get_reg(struct task_struct *task, unsigned int regno) +{ + /* USP is a special case, it's not in the pt_regs struct but + * in the tasks thread struct + */ + + if (regno == PT_USP) + return task->thread.usp; + else if (regno < PT_MAX) + return ((unsigned long *)user_regs(task->thread_info))[regno]; + else + return 0; +} + +/* + * Write contents of register REGNO in task TASK. + */ +inline int put_reg(struct task_struct *task, unsigned int regno, + unsigned long data) +{ + if (regno == PT_USP) + task->thread.usp = data; + else if (regno < PT_MAX) + ((unsigned long *)user_regs(task->thread_info))[regno] = data; + else + return -1; + return 0; +} + +/* notification of userspace execution resumption + * - triggered by current->work.notify_resume + */ +extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs); + + +void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs, + __u32 thread_info_flags ) +{ + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) + do_signal(canrestart,oldset,regs); +} diff --git a/arch/cris/kernel/semaphore.c b/arch/cris/kernel/semaphore.c new file mode 100644 index 00000000000..b884263d3cd --- /dev/null +++ b/arch/cris/kernel/semaphore.c @@ -0,0 +1,130 @@ +/* + * Generic semaphore code. Buyer beware. Do your own + * specific changes in <asm/semaphore-helper.h> + */ + +#include <linux/sched.h> +#include <linux/init.h> +#include <asm/semaphore-helper.h> + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to sleep, while the "waking" variable is + * incremented when the "up()" code goes to wake up waiting + * processes. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * waking_non_zero() (from asm/semaphore.h) must execute + * atomically. + * + * When __up() is called, the count was negative before + * incrementing it, and we need to wake up somebody. + * + * This routine adds one to the count of processes that need to + * wake up and exit. ALL waiting processes actually wake up but + * only the one that gets to the "waking" field first will gate + * through and acquire the semaphore. The others will go back + * to sleep. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in <asm/semaphore.h> + * where we want to avoid any extra jumps and calls. + */ +void __up(struct semaphore *sem) +{ + wake_one_more(sem); + wake_up(&sem->wait); +} + +/* + * Perform the "down" function. Return zero for semaphore acquired, + * return negative for signalled out of the function. + * + * If called from __down, the return is ignored and the wait loop is + * not interruptible. This means that a task waiting on a semaphore + * using "down()" cannot be killed until someone does an "up()" on + * the semaphore. + * + * If called from __down_interruptible, the return value gets checked + * upon return. If the return value is negative then the task continues + * with the negative value in the return register (it can be tested by + * the caller). + * + * Either form may be used in conjunction with "up()". + * + */ + +#define DOWN_VAR \ + struct task_struct *tsk = current; \ + wait_queue_t wait; \ + init_waitqueue_entry(&wait, tsk); + +#define DOWN_HEAD(task_state) \ + \ + \ + tsk->state = (task_state); \ + add_wait_queue(&sem->wait, &wait); \ + \ + /* \ + * Ok, we're set up. sem->count is known to be less than zero \ + * so we must wait. \ + * \ + * We can let go the lock for purposes of waiting. \ + * We re-acquire it after awaking so as to protect \ + * all semaphore operations. \ + * \ + * If "up()" is called before we call waking_non_zero() then \ + * we will catch it right away. If it is called later then \ + * we will have to go through a wakeup cycle to catch it. \ + * \ + * Multiple waiters contend for the semaphore lock to see \ + * who gets to gate through and who has to wait some more. \ + */ \ + for (;;) { + +#define DOWN_TAIL(task_state) \ + tsk->state = (task_state); \ + } \ + tsk->state = TASK_RUNNING; \ + remove_wait_queue(&sem->wait, &wait); + +void __sched __down(struct semaphore * sem) +{ + DOWN_VAR + DOWN_HEAD(TASK_UNINTERRUPTIBLE) + if (waking_non_zero(sem)) + break; + schedule(); + DOWN_TAIL(TASK_UNINTERRUPTIBLE) +} + +int __sched __down_interruptible(struct semaphore * sem) +{ + int ret = 0; + DOWN_VAR + DOWN_HEAD(TASK_INTERRUPTIBLE) + + ret = waking_non_zero_interruptible(sem, tsk); + if (ret) + { + if (ret == 1) + /* ret != 0 only if we get interrupted -arca */ + ret = 0; |