diff options
Diffstat (limited to 'linux/arch/cris/kernel')
-rw-r--r-- | linux/arch/cris/kernel/Makefile | 17 | ||||
-rw-r--r-- | linux/arch/cris/kernel/asm-offsets.c | 59 | ||||
-rw-r--r-- | linux/arch/cris/kernel/crisksyms.c | 70 | ||||
-rw-r--r-- | linux/arch/cris/kernel/devicetree.c | 14 | ||||
-rw-r--r-- | linux/arch/cris/kernel/irq.c | 66 | ||||
-rw-r--r-- | linux/arch/cris/kernel/module.c | 82 | ||||
-rw-r--r-- | linux/arch/cris/kernel/process.c | 79 | ||||
-rw-r--r-- | linux/arch/cris/kernel/profile.c | 86 | ||||
-rw-r--r-- | linux/arch/cris/kernel/ptrace.c | 67 | ||||
-rw-r--r-- | linux/arch/cris/kernel/setup.c | 221 | ||||
-rw-r--r-- | linux/arch/cris/kernel/sys_cris.c | 35 | ||||
-rw-r--r-- | linux/arch/cris/kernel/time.c | 97 | ||||
-rw-r--r-- | linux/arch/cris/kernel/traps.c | 239 | ||||
-rw-r--r-- | linux/arch/cris/kernel/vmlinux.lds.S | 132 |
14 files changed, 1264 insertions, 0 deletions
diff --git a/linux/arch/cris/kernel/Makefile b/linux/arch/cris/kernel/Makefile new file mode 100644 index 00000000..edef71f1 --- /dev/null +++ b/linux/arch/cris/kernel/Makefile @@ -0,0 +1,17 @@ +# $Id: Makefile,v 1.12 2004/10/19 13:07:43 starvik Exp $ +# +# Makefile for the linux kernel. +# + +CPPFLAGS_vmlinux.lds := -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) +extra-y := vmlinux.lds + +obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o +obj-y += devicetree.o + +obj-$(CONFIG_MODULES) += crisksyms.o +obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_SYSTEM_PROFILER) += profile.o + +clean: + diff --git a/linux/arch/cris/kernel/asm-offsets.c b/linux/arch/cris/kernel/asm-offsets.c new file mode 100644 index 00000000..a5fd88d8 --- /dev/null +++ b/linux/arch/cris/kernel/asm-offsets.c @@ -0,0 +1,59 @@ +#include <linux/kbuild.h> +#include <linux/sched.h> +#include <asm/thread_info.h> + +/* + * Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed to extract + * and format the required data. + */ + +#if !defined(CONFIG_ETRAX_ARCH_V10) && !defined(CONFIG_ETRAX_ARCH_V32) +#error One of ARCH v10 and ARCH v32 must be true! +#endif + +int main(void) +{ +#define ENTRY(entry) DEFINE(PT_ ## entry, offsetof(struct pt_regs, entry)) + ENTRY(orig_r10); + ENTRY(r13); + ENTRY(r12); + ENTRY(r11); + ENTRY(r10); + ENTRY(r9); +#ifdef CONFIG_ETRAX_ARCH_V32 + ENTRY(acr); + ENTRY(srs); +#endif + ENTRY(mof); +#ifdef CONFIG_ETRAX_ARCH_V10 + ENTRY(dccr); +#else + ENTRY(ccs); +#endif + ENTRY(srp); + BLANK(); +#undef ENTRY +#define ENTRY(entry) DEFINE(TI_ ## entry, offsetof(struct thread_info, entry)) + ENTRY(task); + ENTRY(flags); + ENTRY(preempt_count); + BLANK(); +#undef ENTRY +#define ENTRY(entry) DEFINE(THREAD_ ## entry, offsetof(struct thread_struct, entry)) + ENTRY(ksp); + ENTRY(usp); +#ifdef CONFIG_ETRAX_ARCH_V10 + ENTRY(dccr); +#else + ENTRY(ccs); +#endif + BLANK(); +#undef ENTRY +#define ENTRY(entry) DEFINE(TASK_ ## entry, offsetof(struct task_struct, entry)) + ENTRY(pid); + BLANK(); + DEFINE(LCLONE_VM, CLONE_VM); + DEFINE(LCLONE_UNTRACED, CLONE_UNTRACED); + return 0; +} diff --git a/linux/arch/cris/kernel/crisksyms.c b/linux/arch/cris/kernel/crisksyms.c new file mode 100644 index 00000000..e704f81f --- /dev/null +++ b/linux/arch/cris/kernel/crisksyms.c @@ -0,0 +1,70 @@ +#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/pm.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/tty.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 unsigned long get_cmos_time(void); +extern void __Udiv(void); +extern void __Umod(void); +extern void __Div(void); +extern void __Mod(void); +extern void __ashldi3(void); +extern void __ashrdi3(void); +extern void __lshrdi3(void); +extern void __negdi2(void); +extern void iounmap(volatile void * __iomem); + +/* Platform dependent support */ +EXPORT_SYMBOL(get_cmos_time); +EXPORT_SYMBOL(loops_per_usec); + +/* Math functions */ +EXPORT_SYMBOL(__Udiv); +EXPORT_SYMBOL(__Umod); +EXPORT_SYMBOL(__Div); +EXPORT_SYMBOL(__Mod); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(__negdi2); + +/* Memory functions */ +EXPORT_SYMBOL(__ioremap); +EXPORT_SYMBOL(iounmap); + +#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_ARCH_V32 +#undef strcmp +EXPORT_SYMBOL(strcmp); +#endif + +#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 +EXPORT_SYMBOL(csum_partial); +EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_partial_copy_nocheck); diff --git a/linux/arch/cris/kernel/devicetree.c b/linux/arch/cris/kernel/devicetree.c new file mode 100644 index 00000000..53ff8d73 --- /dev/null +++ b/linux/arch/cris/kernel/devicetree.c @@ -0,0 +1,14 @@ +#include <linux/init.h> +#include <linux/bootmem.h> +#include <linux/printk.h> + +void __init early_init_dt_add_memory_arch(u64 base, u64 size) +{ + pr_err("%s(%llx, %llx)\n", + __func__, base, size); +} + +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) +{ + return alloc_bootmem_align(size, align); +} diff --git a/linux/arch/cris/kernel/irq.c b/linux/arch/cris/kernel/irq.c new file mode 100644 index 00000000..dd0be5de --- /dev/null +++ b/linux/arch/cris/kernel/irq.c @@ -0,0 +1,66 @@ +/* + * + * linux/arch/cris/kernel/irq.c + * + * Copyright (c) 2000,2007 Axis Communications AB + * + * Authors: Bjorn Wesen (bjornw@axis.com) + * + * This file contains the code used by various IRQ handling routines: + * asking for different IRQs 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. + * + */ + +/* + * IRQs 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/module.h> +#include <linux/ptrace.h> +#include <linux/irq.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/random.h> +#include <linux/init.h> +#include <linux/seq_file.h> +#include <linux/errno.h> +#include <linux/spinlock.h> + +#include <asm/io.h> +#include <arch/system.h> + +/* called by the assembler IRQ entry functions defined in irq.h + * to dispatch the interrupts to registered handlers + */ + +asmlinkage void do_IRQ(int irq, struct pt_regs * regs) +{ + unsigned long sp; + struct pt_regs *old_regs = set_irq_regs(regs); + irq_enter(); + sp = rdsp(); + if (unlikely((sp & (PAGE_SIZE - 1)) < (PAGE_SIZE/8))) { + printk("do_IRQ: stack overflow: %lX\n", sp); + show_stack(NULL, (unsigned long *)sp); + } + generic_handle_irq(irq); + irq_exit(); + set_irq_regs(old_regs); +} + +void weird_irq(void) +{ + local_irq_disable(); + printk("weird irq\n"); + while(1); +} + diff --git a/linux/arch/cris/kernel/module.c b/linux/arch/cris/kernel/module.c new file mode 100644 index 00000000..af04cb6b --- /dev/null +++ b/linux/arch/cris/kernel/module.c @@ -0,0 +1,82 @@ +/* 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> +#include <linux/slab.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +#ifdef CONFIG_ETRAX_KMALLOCED_MODULES +void *module_alloc(unsigned long size) +{ + return kmalloc(size, GFP_KERNEL); +} + +/* Free memory returned from module_alloc */ +void module_memfree(void *module_region) +{ + kfree(module_region); +} +#endif + +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 add 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)); + switch (ELF32_R_TYPE(rela[i].r_info)) { + case R_CRIS_32: + *loc = sym->st_value + rela[i].r_addend; + break; + case R_CRIS_32_PCREL: + *loc = sym->st_value - (unsigned)loc + rela[i].r_addend - 4; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rela[i].r_info)); + return -ENOEXEC; + } + } + + return 0; +} diff --git a/linux/arch/cris/kernel/process.c b/linux/arch/cris/kernel/process.c new file mode 100644 index 00000000..b78498eb --- /dev/null +++ b/linux/arch/cris/kernel/process.c @@ -0,0 +1,79 @@ +/* + * linux/arch/cris/kernel/process.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 2000-2002 Axis Communications AB + * + * Authors: Bjorn Wesen (bjornw@axis.com) + * + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#include <linux/atomic.h> +#include <asm/pgtable.h> +#include <asm/uaccess.h> +#include <asm/irq.h> +#include <linux/module.h> +#include <linux/spinlock.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> +#include <linux/reboot.h> +#include <linux/rcupdate.h> + +//#define DEBUG + +extern void default_idle(void); + +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + +void arch_cpu_idle(void) +{ + default_idle(); +} + +void hard_reset_now (void); + +void machine_restart(char *cmd) +{ + hard_reset_now(); +} + +/* + * 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) +{ +} + +/* If or when software power-off is implemented, add code here. */ + +void machine_power_off(void) +{ +} + +/* + * 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 fpu structure for a core dump. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) +{ + return 0; +} diff --git a/linux/arch/cris/kernel/profile.c b/linux/arch/cris/kernel/profile.c new file mode 100644 index 00000000..cd9f15b9 --- /dev/null +++ b/linux/arch/cris/kernel/profile.c @@ -0,0 +1,86 @@ +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/proc_fs.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <asm/ptrace.h> +#include <asm/uaccess.h> + +#define SAMPLE_BUFFER_SIZE 8192 + +static char *sample_buffer; +static char *sample_buffer_pos; +static int prof_running = 0; + +void cris_profile_sample(struct pt_regs *regs) +{ + if (!prof_running) + return; + + if (user_mode(regs)) + *(unsigned int*)sample_buffer_pos = current->pid; + else + *(unsigned int*)sample_buffer_pos = 0; + + *(unsigned int *)(sample_buffer_pos + 4) = instruction_pointer(regs); + sample_buffer_pos += 8; + + if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE) + sample_buffer_pos = sample_buffer; +} + +static ssize_t +read_cris_profile(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + ssize_t ret; + + ret = simple_read_from_buffer(buf, count, ppos, sample_buffer, + SAMPLE_BUFFER_SIZE); + if (ret < 0) + return ret; + + memset(sample_buffer + p, 0, ret); + + return ret; +} + +static ssize_t +write_cris_profile(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + sample_buffer_pos = sample_buffer; + memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE); + return count < SAMPLE_BUFFER_SIZE ? count : SAMPLE_BUFFER_SIZE; +} + +static const struct file_operations cris_proc_profile_operations = { + .read = read_cris_profile, + .write = write_cris_profile, + .llseek = default_llseek, +}; + +static int __init init_cris_profile(void) +{ + struct proc_dir_entry *entry; + + sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL); + if (!sample_buffer) { + return -ENOMEM; + } + + sample_buffer_pos = sample_buffer; + + entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL, + &cris_proc_profile_operations); + if (entry) { + proc_set_size(entry, SAMPLE_BUFFER_SIZE); + } + prof_running = 1; + + return 0; +} +__initcall(init_cris_profile); + diff --git a/linux/arch/cris/kernel/ptrace.c b/linux/arch/cris/kernel/ptrace.c new file mode 100644 index 00000000..fd3427e5 --- /dev/null +++ b/linux/arch/cris/kernel/ptrace.c @@ -0,0 +1,67 @@ +/* + * linux/arch/cris/kernel/ptrace.c + * + * Parts taken from the m68k port. + * + * Copyright (c) 2000, 2001, 2002 Axis Communications AB + * + * Authors: Bjorn Wesen + * + */ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/errno.h> +#include <linux/ptrace.h> +#include <linux/user.h> +#include <linux/tracehook.h> + +#include <asm/uaccess.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/processor.h> + + +/* notification of userspace execution resumption + * - triggered by current->work.notify_resume + */ +extern int do_signal(int canrestart, struct pt_regs *regs); + + +void do_notify_resume(int canrestart, struct pt_regs *regs, + __u32 thread_info_flags) +{ + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) + do_signal(canrestart,regs); + + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } +} + +void do_work_pending(int syscall, struct pt_regs *regs, + unsigned int thread_flags) +{ + do { + if (likely(thread_flags & _TIF_NEED_RESCHED)) { + schedule(); + } else { + if (unlikely(!user_mode(regs))) + return; + local_irq_enable(); + if (thread_flags & _TIF_SIGPENDING) { + do_signal(syscall, regs); + syscall = 0; + } else { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } + } + local_irq_disable(); + thread_flags = current_thread_info()->flags; + } while (thread_flags & _TIF_WORK_MASK); +} diff --git a/linux/arch/cris/kernel/setup.c b/linux/arch/cris/kernel/setup.c new file mode 100644 index 00000000..bb12aa93 --- /dev/null +++ b/linux/arch/cris/kernel/setup.c @@ -0,0 +1,221 @@ +/* + * + * linux/arch/cris/kernel/setup.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (c) 2001 Axis Communications AB + */ + +/* + * This file handles the architecture-dependent parts of initialization + */ + +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <asm/pgtable.h> +#include <linux/seq_file.h> +#include <linux/screen_info.h> +#include <linux/utsname.h> +#include <linux/pfn.h> +#include <linux/cpu.h> +#include <linux/of.h> +#include <linux/of_fdt.h> +#include <linux/of_platform.h> +#include <asm/setup.h> +#include <arch/system.h> + +/* + * Setup options + */ +struct screen_info screen_info; + +extern int root_mountflags; +extern char _etext, _edata, _end; + +char __initdata cris_command_line[COMMAND_LINE_SIZE] = { 0, }; + +extern const unsigned long text_start, edata; /* set by the linker script */ +extern unsigned long dram_start, dram_end; + +extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */ + +static struct cpu cpu_devices[NR_CPUS]; + +extern void show_etrax_copyright(void); /* arch-vX/kernel/setup.c */ + +/* This mainly sets up the memory area, and can be really confusing. + * + * The physical DRAM is virtually mapped into dram_start to dram_end + * (usually c0000000 to c0000000 + DRAM size). The physical address is + * given by the macro __pa(). + * + * In this DRAM, the kernel code and data is loaded, in the beginning. + * It really starts at c0004000 to make room for some special pages - + * the start address is text_start. The kernel data ends at _end. After + * this the ROM filesystem is appended (if there is any). + * + * Between this address and dram_end, we have RAM pages usable to the + * boot code and the system. + * + */ + +void __init setup_arch(char **cmdline_p) +{ + extern void init_etrax_debug(void); + unsigned long bootmap_size; + unsigned long start_pfn, max_pfn; + unsigned long memory_start; + +#ifdef CONFIG_OF + early_init_dt_scan(__dtb_start); +#endif + + /* register an initial console printing routine for printk's */ + + init_etrax_debug(); + + /* we should really poll for DRAM size! */ + + high_memory = &dram_end; + + if(romfs_in_flash || !romfs_length) { + /* if we have the romfs in flash, or if there is no rom filesystem, + * our free area starts directly after the BSS + */ + memory_start = (unsigned long) &_end; + } else { + /* otherwise the free area starts after the ROM filesystem */ + printk("ROM fs in RAM, size %lu bytes\n", romfs_length); + memory_start = romfs_start + romfs_length; + } + + /* process 1's initial memory region is the kernel code/data */ + + init_mm.start_code = (unsigned long) &text_start; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) &_end; + + /* min_low_pfn points to the start of DRAM, start_pfn points + * to the first DRAM pages after the kernel, and max_low_pfn + * to the end of DRAM. + */ + + /* + * partially used pages are not usable - thus + * we are rounding upwards: + */ + + start_pfn = PFN_UP(memory_start); /* usually c0000000 + kernel + romfs */ + max_pfn = PFN_DOWN((unsigned long)high_memory); /* usually c0000000 + dram size */ + + /* + * Initialize the boot-time allocator (start, end) + * + * We give it access to all our DRAM, but we could as well just have + * given it a small slice. No point in doing that though, unless we + * have non-contiguous memory and want the boot-stuff to be in, say, + * the smallest area. + * + * It will put a bitmap of the allocated pages in the beginning + * of the range we give it, but it won't mark the bitmaps pages + * as reserved. We have to do that ourselves below. + * + * We need to use init_bootmem_node instead of init_bootmem + * because our map starts at a quite high address (min_low_pfn). + */ + + max_low_pfn = max_pfn; + min_low_pfn = PAGE_OFFSET >> PAGE_SHIFT; + + bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, + min_low_pfn, + max_low_pfn); + + /* And free all memory not belonging to the kernel (addr, size) */ + + free_bootmem(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn - start_pfn)); + + /* + * Reserve the bootmem bitmap itself as well. We do this in two + * steps (first step was init_bootmem()) because this catches + * the (very unlikely) case of us accidentally initializing the + * bootmem allocator with an invalid RAM area. + * + * Arguments are start, size + */ + + reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size, BOOTMEM_DEFAULT); + + unflatten_and_copy_device_tree(); + + /* paging_init() sets up the MMU and marks all pages as reserved */ + + paging_init(); + + *cmdline_p = cris_command_line; + +#ifdef CONFIG_ETRAX_CMDLINE + if (!strcmp(cris_command_line, "")) { + strlcpy(cris_command_line, CONFIG_ETRAX_CMDLINE, COMMAND_LINE_SIZE); + cris_command_line[COMMAND_LINE_SIZE - 1] = '\0'; + } +#endif + + /* Save command line for future references. */ + memcpy(boot_command_line, cris_command_line, COMMAND_LINE_SIZE); + boot_command_line[COMMAND_LINE_SIZE - 1] = '\0'; + + /* give credit for the CRIS port */ + show_etrax_copyright(); + + /* Setup utsname */ + strcpy(init_utsname()->machine, cris_machine_name); +} + +#ifdef CONFIG_PROC_FS +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < nr_cpu_ids ? (void *)(int)(*pos + 1) : NULL; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +extern int show_cpuinfo(struct seq_file *m, void *v); + +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; +#endif /* CONFIG_PROC_FS */ + +static int __init topology_init(void) +{ + int i; + + for_each_possible_cpu(i) { + return register_cpu(&cpu_devices[i], i); + } + + return 0; +} + +subsys_initcall(topology_init); + +static int __init cris_of_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + return 0; +} +core_initcall(cris_of_init); diff --git a/linux/arch/cris/kernel/sys_cris.c b/linux/arch/cris/kernel/sys_cris.c new file mode 100644 index 00000000..7aa036ec --- /dev/null +++ b/linux/arch/cris/kernel/sys_cris.c @@ -0,0 +1,35 @@ +/* $Id: sys_cris.c,v 1.6 2004/03/11 11:38:40 starvik Exp $ + * + * linux/arch/cris/kernel/sys_cris.c + * + * This file contains various random system calls that + * have a non-standard calling sequence on some platforms. + * Since we don't have to do any backwards compatibility, our + * versions are done in the most "normal" way possible. + * + */ + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/syscalls.h> +#include <linux/mm.h> +#include <linux/fs.h> +#include <linux/smp.h> +#include <linux/sem.h> +#include <linux/msg.h> +#include <linux/shm.h> +#include <linux/stat.h> +#include <linux/mman.h> +#include <linux/file.h> +#include <linux/ipc.h> + +#include <asm/uaccess.h> +#include <asm/segment.h> + +asmlinkage long +sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long pgoff) +{ + /* bug(?): 8Kb pages here */ + return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); +} diff --git a/linux/arch/cris/kernel/time.c b/linux/arch/cris/kernel/time.c new file mode 100644 index 00000000..7780d379 --- /dev/null +++ b/linux/arch/cris/kernel/time.c @@ -0,0 +1,97 @@ +/* + * linux/arch/cris/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Copyright (C) 1999, 2000, 2001 Axis Communications AB + * + * 1994-07-02 Alan Modra + * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime + * 1995-03-26 Markus Kuhn + * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 + * precision CMOS clock update + * 1996-05-03 Ingo Molnar + * fixed time warps in do_[slow|fast]_gettimeoffset() + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + * + * Linux/CRIS specific code: + * + * Authors: Bjorn Wesen + * Johan Adolfsson + * + */ + +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/param.h> +#include <linux/jiffies.h> +#include <linux/bcd.h> +#include <linux/timex.h> +#include <linux/init.h> +#include <linux/profile.h> +#include <linux/sched.h> /* just for sched_clock() - funny that */ + + +#define D(x) + +#define TICK_SIZE tick + +extern unsigned long loops_per_jiffy; /* init/main.c */ +unsigned long loops_per_usec; + +int set_rtc_mmss(unsigned long nowtime) +{ + D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime)); + return 0; +} + +/* grab the time from the RTC chip */ +unsigned long get_cmos_time(void) +{ + return 0; +} + + +int update_persistent_clock(struct timespec now) +{ + return set_rtc_mmss(now.tv_sec); +} + +void read_persistent_clock(struct timespec *ts) +{ + ts->tv_sec = 0; + ts->tv_nsec = 0; +} + + +extern void cris_profile_sample(struct pt_regs* regs); + +void +cris_do_profile(struct pt_regs* regs) +{ + +#ifdef CONFIG_SYSTEM_PROFILER + cris_profile_sample(regs); +#endif + +#ifdef CONFIG_PROFILING + profile_tick(CPU_PROFILING); +#endif +} + +#ifndef CONFIG_GENERIC_SCHED_CLOCK +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) + + get_ns_in_jiffie(); +} +#endif + +static int +__init init_udelay(void) +{ + loops_per_usec = (loops_per_jiffy * HZ) / 1000000; + return 0; +} + +__initcall(init_udelay); diff --git a/linux/arch/cris/kernel/traps.c b/linux/arch/cris/kernel/traps.c new file mode 100644 index 00000000..da4c7240 --- /dev/null +++ b/linux/arch/cris/kernel/traps.c @@ -0,0 +1,239 @@ +/* + * linux/arch/cris/traps.c + * + * Here we handle the break vectors not used by the system call + * mechanism, as well as some general stack/register dumping + * things. + * + * Copyright (C) 2000-2007 Axis Communications AB + * + * Authors: Bjorn Wesen + * Hans-Peter Nilsson + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/utsname.h> +#ifdef CONFIG_KALLSYMS +#include <linux/kallsyms.h> +#endif + +#include <asm/pgtable.h> +#include <asm/uaccess.h> +#include <arch/system.h> + +extern void arch_enable_nmi(void); +extern void stop_watchdog(void); +extern void reset_watchdog(void); +extern void show_registers(struct pt_regs *regs); + +#ifdef CONFIG_DEBUG_BUGVERBOSE +extern void handle_BUG(struct pt_regs *regs); +#else +#define handle_BUG(regs) +#endif + +static int kstack_depth_to_print = 24; + +void (*nmi_handler)(struct pt_regs *); + +void show_trace(unsigned long *stack) +{ + unsigned long addr, module_start, module_end; + extern char _stext, _etext; + int i; + + pr_err("\nCall Trace: "); + + i = 1; + module_start = VMALLOC_START; + module_end = VMALLOC_END; + + while (((long)stack & (THREAD_SIZE - 1)) != 0) { + if (__get_user(addr, stack)) { + /* This message matches "failing address" marked + s390 in ksymoops, so lines containing it will + not be filtered out by ksymoops. */ + pr_err("Failing address 0x%lx\n", (unsigned long)stack); + break; + } + stack++; + + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (((addr >= (unsigned long)&_stext) && + (addr <= (unsigned long)&_etext)) || + ((addr >= module_start) && (addr <= module_end))) { +#ifdef CONFIG_KALLSYMS + print_ip_sym(addr); +#else + if (i && ((i % 8) == 0)) + pr_err("\n "); + pr_err("[<%08lx>] ", addr); + i++; +#endif + } + } +} + +/* + * These constants are for searching for possible module text + * segments. MODULE_RANGE is a guess of how much space is likely + * to be vmalloced. + */ + +#define MODULE_RANGE (8*1024*1024) + +/* + * The output (format, strings and order) is adjusted to be usable with + * ksymoops-2.4.1 with some necessary CRIS-specific patches. Please don't + * change it unless you're serious about adjusting ksymoops and syncing + * with the ksymoops maintainer. + */ + +void +show_stack(struct task_struct *task, unsigned long *sp) +{ + unsigned long *stack, addr; + int i; + + /* + * debugging aid: "show_stack(NULL);" prints a + * back trace. + */ + + if (sp == NULL) { + if (task) + sp = (unsigned long*)task->thread.ksp; + else + sp = (unsigned long*)rdsp(); + } + + stack = sp; + + pr_err("\nStack from %08lx:\n ", (unsigned long)stack); + for (i = 0; i < kstack_depth_to_print; i++) { + if (((long)stack & (THREAD_SIZE-1)) == 0) + break; + if (i && ((i % 8) == 0)) + pr_err("\n "); + if (__get_user(addr, stack)) { + /* This message matches "failing address" marked + s390 in ksymoops, so lines containing it will + not be filtered out by ksymoops. */ + pr_err("Failing address 0x%lx\n", (unsigned long)stack); + break; + } + stack++; + pr_err("%08lx ", addr); + } + show_trace(sp); +} + +#if 0 +/* displays a short stack trace */ + +int +show_stack(void) +{ + unsigned long *sp = (unsigned long *)rdusp(); + int i; + + pr_err("Stack dump [0x%08lx]:\n", (unsigned long)sp); + for (i = 0; i < 16; i++) + pr_err("sp + %d: 0x%08lx\n", i*4, sp[i]); + return 0; +} +#endif + +void set_nmi_handler(void (*handler)(struct pt_regs *)) +{ + nmi_handler = handler; + arch_enable_nmi(); +} + +#ifdef CONFIG_DEBUG_NMI_OOPS +void oops_nmi_handler(struct pt_regs *regs) +{ + stop_watchdog(); + oops_in_progress = 1; + pr_err("NMI!\n"); + show_registers(regs); + oops_in_progress = 0; + oops_exit(); + pr_err("\n"); /* Flush mtdoops. */ +} + +static int __init oops_nmi_register(void) +{ + set_nmi_handler(oops_nmi_handler); + return 0; +} + +__initcall(oops_nmi_register); + +#endif + +/* + * This gets called from entry.S when the watchdog has bitten. Show something + * similar to an Oops dump, and if the kernel is configured to be a nice + * doggy, then halt instead of reboot. + */ +void watchdog_bite_hook(struct pt_regs *regs) +{ +#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY + local_irq_disable(); + stop_watchdog(); + show_registers(regs); + + while (1) + ; /* Do nothing. */ +#else + show_registers(regs); +#endif +} + +/* This is normally the Oops function. */ +void die_if_kernel(const char *str, struct pt_regs *regs, long err) +{ + if (user_mode(regs)) + return; + +#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY + /* + * This printout might take too long and could trigger + * the watchdog normally. If NICE_DOGGY is set, simply + * stop the watchdog during the printout. + */ + stop_watchdog(); +#endif + + oops_enter(); + handle_BUG(regs); + + pr_err("Linux %s %s\n", utsname()->release, utsname()->version); + pr_err("%s: %04lx\n", str, err & 0xffff); + + show_registers(regs); + + oops_exit(); + oops_in_progress = 0; + pr_err("\n"); /* Flush mtdoops. */ + +#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY + reset_watchdog(); +#endif + do_exit(SIGSEGV); +} + +void __init trap_init(void) +{ + /* Nothing needs to be done */ +} diff --git a/linux/arch/cris/kernel/vmlinux.lds.S b/linux/arch/cris/kernel/vmlinux.lds.S new file mode 100644 index 00000000..a68b983d --- /dev/null +++ b/linux/arch/cris/kernel/vmlinux.lds.S @@ -0,0 +1,132 @@ +/* ld script to make the Linux/CRIS kernel + * Authors: Bjorn Wesen (bjornw@axis.com) + * + * It is VERY DANGEROUS to fiddle around with the symbols in this + * script. It is for example quite vital that all generated sections + * that are used are actually named here, otherwise the linker will + * put them at the end, where the init stuff is which is FREED after + * the kernel has booted. + */ + +#include <asm-generic/vmlinux.lds.h> +#include <asm/page.h> + +#ifdef CONFIG_ETRAX_VMEM_SIZE +#define __CONFIG_ETRAX_VMEM_SIZE CONFIG_ETRAX_VMEM_SIZE +#else +#define __CONFIG_ETRAX_VMEM_SIZE 0 +#endif + + +jiffies = jiffies_64; +SECTIONS +{ + . = DRAM_VIRTUAL_BASE; + dram_start = .; +#ifdef CONFIG_ETRAX_ARCH_V10 + ibr_start = .; +#else + ebp_start = .; + /* The boot section is only necessary until the VCS top */ + /* level testbench includes both flash and DRAM. */ + .boot : { *(.boot) } +#endif + + /* see head.S and pages reserved at the start */ + . = DRAM_VIRTUAL_BASE + 0x4000; + + _text = .; /* Text and read-only data. */ + text_start = .; /* Lots of aliases. */ + _stext = .; + __stext = .; + .text : { + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + *(.fixup) + *(.text.__*) + } + + _etext = . ; /* End of text section. */ + __etext = .; + + EXCEPTION_TABLE(4) + + _sdata = .; + RODATA + + . = ALIGN (4); + ___data_start = . ; + __Sdata = . ; + .data : { /* Data */ + CACHELINE_ALIGNED_DATA(32) + READ_MOSTLY_DATA(32) + DATA_DATA + } + __edata = . ; /* End of data section. */ + _edata = . ; + + INIT_TASK_DATA_SECTION(PAGE_SIZE) + + . = ALIGN(PAGE_SIZE); /* Init code and data. */ + __init_begin = .; + INIT_TEXT_SECTION(PAGE_SIZE) + .init.data : { INIT_DATA } + .init.setup : { INIT_SETUP(16) } + .initcall.init : { + INIT_CALLS + } + + .con_initcall.init : { + CON_INITCALL + } + SECURITY_INIT + + /* .exit.text is discarded at runtime, not link time, + * to deal with references from __bug_table + */ + .exit.text : { + EXIT_TEXT + } + .exit.data : { + EXIT_DATA + } + +#ifdef CONFIG_ETRAX_ARCH_V10 +#ifdef CONFIG_BLK_DEV_INITRD + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } +#endif +#endif + __vmlinux_end = .; /* Last address of the physical file. */ +#ifdef CONFIG_ETRAX_ARCH_V32 + PERCPU_SECTION(32) + + .init.ramfs : { + INIT_RAM_FS + } +#endif + + /* + * We fill to the next page, so we can discard all init + * pages without needing to consider what payload might be + * appended to the kernel image. + */ + . = ALIGN(PAGE_SIZE); + + __init_end = .; + + __data_end = . ; /* Move to _edata ? */ + BSS_SECTION(1, 1, 1) + + . = ALIGN (0x20); + _end = .; + __end = .; + + dram_end = dram_start + (CONFIG_ETRAX_DRAM_SIZE - __CONFIG_ETRAX_VMEM_SIZE)*1024*1024; + + DISCARDS +} |