diff options
Diffstat (limited to 'arch/um/sys-ppc')
-rw-r--r-- | arch/um/sys-ppc/Makefile | 69 | ||||
-rw-r--r-- | arch/um/sys-ppc/misc.S | 116 | ||||
-rw-r--r-- | arch/um/sys-ppc/miscthings.c | 53 | ||||
-rw-r--r-- | arch/um/sys-ppc/ptrace.c | 28 | ||||
-rw-r--r-- | arch/um/sys-ppc/ptrace_user.c | 39 | ||||
-rw-r--r-- | arch/um/sys-ppc/sigcontext.c | 15 | ||||
-rw-r--r-- | arch/um/sys-ppc/sysrq.c | 43 |
7 files changed, 363 insertions, 0 deletions
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile new file mode 100644 index 0000000..af20026 --- /dev/null +++ b/arch/um/sys-ppc/Makefile @@ -0,0 +1,69 @@ +OBJ = built-in.o + +.S.o: + $(CC) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + +OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \ + ptrace_user.o sysrq.o + +EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel + +all: $(OBJ) + +$(OBJ): $(OBJS) + rm -f $@ + $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ + +ptrace_user.o: ptrace_user.c + $(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + +sigcontext.o: sigcontext.c + $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + +semaphore.c: + rm -f $@ + ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + +checksum.S: + rm -f $@ + ln -s $(TOPDIR)/arch/ppc/lib/$@ $@ + +mk_defs.c: + rm -f $@ + ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + +ppc_defs.head: + rm -f $@ + ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@ + +ppc_defs.h: mk_defs.c ppc_defs.head \ + $(TOPDIR)/include/asm-ppc/mmu.h \ + $(TOPDIR)/include/asm-ppc/processor.h \ + $(TOPDIR)/include/asm-ppc/pgtable.h \ + $(TOPDIR)/include/asm-ppc/ptrace.h +# $(CC) $(CFLAGS) -S mk_defs.c + cp ppc_defs.head ppc_defs.h +# for bk, this way we can write to the file even if it's not checked out + echo '#define THREAD 608' >> ppc_defs.h + echo '#define PT_REGS 8' >> ppc_defs.h + echo '#define CLONE_VM 256' >> ppc_defs.h +# chmod u+w ppc_defs.h +# grep '^#define' mk_defs.s >> ppc_defs.h +# rm mk_defs.s + +# the asm link is horrible, and breaks the other targets. This is also +# not going to work with parallel makes. + +checksum.o: checksum.S + rm -f asm + ln -s $(TOPDIR)/include/asm-ppc asm + $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + rm -f asm + +misc.o: misc.S ppc_defs.h + rm -f asm + ln -s $(TOPDIR)/include/asm-ppc asm + $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o + rm -f asm + +clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S new file mode 100644 index 0000000..11b7bd7 --- /dev/null +++ b/arch/um/sys-ppc/misc.S @@ -0,0 +1,116 @@ +/* + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras. + * + * A couple of functions stolen from arch/ppc/kernel/misc.S for UML + * by Chris Emerson. + * + * 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. + * + */ + +#include <linux/config.h> +#include <asm/processor.h> +#include "ppc_asm.h" + +#if defined(CONFIG_4xx) || defined(CONFIG_8xx) +#define CACHE_LINE_SIZE 16 +#define LG_CACHE_LINE_SIZE 4 +#define MAX_COPY_PREFETCH 1 +#elif !defined(CONFIG_PPC64BRIDGE) +#define CACHE_LINE_SIZE 32 +#define LG_CACHE_LINE_SIZE 5 +#define MAX_COPY_PREFETCH 4 +#else +#define CACHE_LINE_SIZE 128 +#define LG_CACHE_LINE_SIZE 7 +#define MAX_COPY_PREFETCH 1 +#endif /* CONFIG_4xx || CONFIG_8xx */ + + .text + +/* + * Clear a page using the dcbz instruction, which doesn't cause any + * memory traffic (except to write out any cache lines which get + * displaced). This only works on cacheable memory. + */ +_GLOBAL(clear_page) + li r0,4096/CACHE_LINE_SIZE + mtctr r0 +#ifdef CONFIG_8xx + li r4, 0 +1: stw r4, 0(r3) + stw r4, 4(r3) + stw r4, 8(r3) + stw r4, 12(r3) +#else +1: dcbz 0,r3 +#endif + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + blr + +/* + * Copy a whole page. We use the dcbz instruction on the destination + * to reduce memory traffic (it eliminates the unnecessary reads of + * the destination into cache). This requires that the destination + * is cacheable. + */ +#define COPY_16_BYTES \ + lwz r6,4(r4); \ + lwz r7,8(r4); \ + lwz r8,12(r4); \ + lwzu r9,16(r4); \ + stw r6,4(r3); \ + stw r7,8(r3); \ + stw r8,12(r3); \ + stwu r9,16(r3) + +_GLOBAL(copy_page) + addi r3,r3,-4 + addi r4,r4,-4 + li r5,4 + +#ifndef CONFIG_8xx +#if MAX_COPY_PREFETCH > 1 + li r0,MAX_COPY_PREFETCH + li r11,4 + mtctr r0 +11: dcbt r11,r4 + addi r11,r11,CACHE_LINE_SIZE + bdnz 11b +#else /* MAX_COPY_PREFETCH == 1 */ + dcbt r5,r4 + li r11,CACHE_LINE_SIZE+4 +#endif /* MAX_COPY_PREFETCH */ +#endif /* CONFIG_8xx */ + + li r0,4096/CACHE_LINE_SIZE + mtctr r0 +1: +#ifndef CONFIG_8xx + dcbt r11,r4 + dcbz r5,r3 +#endif + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 32 + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 64 + COPY_16_BYTES + COPY_16_BYTES +#if CACHE_LINE_SIZE >= 128 + COPY_16_BYTES + COPY_16_BYTES + COPY_16_BYTES + COPY_16_BYTES +#endif +#endif +#endif + bdnz 1b + blr diff --git a/arch/um/sys-ppc/miscthings.c b/arch/um/sys-ppc/miscthings.c new file mode 100644 index 0000000..373061c --- /dev/null +++ b/arch/um/sys-ppc/miscthings.c @@ -0,0 +1,53 @@ +#include "linux/threads.h" +#include "linux/stddef.h" // for NULL +#include "linux/elf.h" // for AT_NULL + +/* The following function nicked from arch/ppc/kernel/process.c and + * adapted slightly */ +/* + * XXX ld.so expects the auxiliary table to start on + * a 16-byte boundary, so we have to find it and + * move it up. :-( + */ +void shove_aux_table(unsigned long sp) +{ + int argc; + char *p; + unsigned long e; + unsigned long aux_start, offset; + + argc = *(int *)sp; + sp += sizeof(int) + (argc + 1) * sizeof(char *); + /* skip over the environment pointers */ + do { + p = *(char **)sp; + sp += sizeof(char *); + } while (p != NULL); + aux_start = sp; + /* skip to the end of the auxiliary table */ + do { + e = *(unsigned long *)sp; + sp += 2 * sizeof(unsigned long); + } while (e != AT_NULL); + offset = ((aux_start + 15) & ~15) - aux_start; + if (offset != 0) { + do { + sp -= sizeof(unsigned long); + e = *(unsigned long *)sp; + *(unsigned long *)(sp + offset) = e; + } while (sp > aux_start); + } +} +/* END stuff taken from arch/ppc/kernel/process.c */ + + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c new file mode 100644 index 0000000..a971366d --- /dev/null +++ b/arch/um/sys-ppc/ptrace.c @@ -0,0 +1,28 @@ +#include "linux/sched.h" +#include "asm/ptrace.h" + +int putreg(struct task_struct *child, unsigned long regno, + unsigned long value) +{ + child->thread.process_regs.regs[regno >> 2] = value; + return 0; +} + +unsigned long getreg(struct task_struct *child, unsigned long regno) +{ + unsigned long retval = ~0UL; + + retval &= child->thread.process_regs.regs[regno >> 2]; + return retval; +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-ppc/ptrace_user.c b/arch/um/sys-ppc/ptrace_user.c new file mode 100644 index 0000000..ff0b9c0 --- /dev/null +++ b/arch/um/sys-ppc/ptrace_user.c @@ -0,0 +1,39 @@ +#include <errno.h> +#include <asm/ptrace.h> +#include "sysdep/ptrace.h" + +int ptrace_getregs(long pid, unsigned long *regs_out) +{ + int i; + for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { + errno = 0; + regs_out->regs[i] = ptrace(PTRACE_PEEKUSR, pid, i*4, 0); + if (errno) { + return -errno; + } + } + return 0; +} + +int ptrace_setregs(long pid, unsigned long *regs_in) +{ + int i; + for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) { + if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) { + if (ptrace(PTRACE_POKEUSR, pid, i*4, regs_in->regs[i]) < 0) { + return -errno; + } + } + } + return 0; +} +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-ppc/sigcontext.c b/arch/um/sys-ppc/sigcontext.c new file mode 100644 index 0000000..5d430fc --- /dev/null +++ b/arch/um/sys-ppc/sigcontext.c @@ -0,0 +1,15 @@ +#include "asm/ptrace.h" +#include "asm/sigcontext.h" +#include "sysdep/ptrace.h" +#include "user_util.h" + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/sys-ppc/sysrq.c b/arch/um/sys-ppc/sysrq.c new file mode 100644 index 0000000..82d6e93 --- /dev/null +++ b/arch/um/sys-ppc/sysrq.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/smp.h" +#include "asm/ptrace.h" +#include "sysrq.h" + +void show_regs(struct pt_regs_subarch *regs) +{ + printk("\n"); + printk("show_regs(): insert regs here.\n"); +#if 0 + printk("\n"); + printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs, regs->eip, + smp_processor_id()); + if (regs->xcs & 3) + printk(" ESP: %04x:%08lx",0xffff & regs->xss, regs->esp); + printk(" EFLAGS: %08lx\n", regs->eflags); + printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + printk("ESI: %08lx EDI: %08lx EBP: %08lx", + regs->esi, regs->edi, regs->ebp); + printk(" DS: %04x ES: %04x\n", + 0xffff & regs->xds, 0xffff & regs->xes); +#endif + + show_trace(®s->gpr[1]); +} + + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ |