Commit 44d80c37 authored by Yoshinori Sato's avatar Yoshinori Sato Committed by Linus Torvalds

[PATCH] h8300: arch update

H8S architecture support
signal handling problem fix
gcc-3.3 support
vfork/clone return value fix
added show_stack
build error and warning fix
blkdev location cleanup
parent 398f5798
......@@ -40,7 +40,6 @@ int main(void)
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr));
DEFINE(THREAD_VFORK, offsetof(struct thread_struct, vfork_ret));
DEFINE(PT_PTRACED, PT_PTRACED);
DEFINE(PT_DTRACE, PT_DTRACE);
......
......@@ -6,7 +6,7 @@
*/
/*
* H8/300H Internal I/O Port Management
* Internal I/O Port Management
*/
#include <linux/config.h>
......@@ -15,50 +15,56 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/init.h>
#define _(addr) (volatile unsigned char *)(addr)
#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
#define P1DDR (unsigned char *)0xfee000
#define P2DDR (unsigned char *)0xfee001
#define P3DDR (unsigned char *)0xfee002
#define P4DDR (unsigned char *)0xfee003
#define P5DDR (unsigned char *)0xfee004
#define P6DDR (unsigned char *)0xfee005
#define P8DDR (unsigned char *)0xfee007
#define P9DDR (unsigned char *)0xfee008
#define PADDR (unsigned char *)0xfee009
#define PBDDR (unsigned char *)0xfee00A
#endif
#if defined(CONFIG_H83002) || defined(CONFIG_H8048)
#define P1DDR (unsigned char *)0xffffc0
#define P2DDR (unsigned char *)0xffffc1
#define P3DDR (unsigned char *)0xffffc4
#define P4DDR (unsigned char *)0xffffc5
#define P5DDR (unsigned char *)0xffffc8
#define P6DDR (unsigned char *)0xffffc9
#define P8DDR (unsigned char *)0xffffcd
#define P9DDR (unsigned char *)0xffffd0
#define PADDR (unsigned char *)0xffffd1
#define PBDDR (unsigned char *)0xffffd4
#include <asm/regs306x.h>
static volatile unsigned char *ddrs[] = {
_(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
};
#define MAX_PORT 11
#endif
#if defined(P1DDR)
#if defined(CONFIG_H83002) || defined(CONFIG_H8048)
/* Fix me!! */
#include <asm/regs306x.h>
static volatile unsigned char *ddrs[] = {
_(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
};
#define MAX_PORT 11
#endif
#if defined(CONFIG_H8S2678)
#include <asm/regs267x.h>
static volatile unsigned char *ddrs[] = {
_(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR),
_(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR),
_(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR),
_(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR),
_(PGDDR),_(PHDDR)
};
#define MAX_PORT 17
#endif
#undef _
#if !defined(P1DDR)
#error Unsuppoted CPU Selection
#endif
static struct {
unsigned char used;
unsigned char ddr;
} gpio_regs[MAX_PORT];
static volatile unsigned char *ddrs[] = {
P1DDR,P2DDR,P3DDR,P4DDR,P5DDR,P6DDR,NULL,P8DDR,P9DDR,PADDR,PBDDR,
};
extern char *_platform_gpio_table(int length);
int h8300_reserved_gpio(int port, unsigned int bits)
{
unsigned char *used;
if (port < 0 || port >= MAX_PORT)
return -1;
used = &(gpio_regs[port].used);
......@@ -71,6 +77,7 @@ int h8300_reserved_gpio(int port, unsigned int bits)
int h8300_free_gpio(int port, unsigned int bits)
{
unsigned char *used;
if (port < 0 || port >= MAX_PORT)
return -1;
used = &(gpio_regs[port].used);
......@@ -82,16 +89,16 @@ int h8300_free_gpio(int port, unsigned int bits)
int h8300_set_gpio_dir(int port_bit,int dir)
{
const unsigned char mask[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int port = (port_bit >> 8) & 0xff;
int bit = port_bit & 0x07;
int bit = port_bit & 0xff;
if (ddrs[port] == NULL)
return 0;
if (gpio_regs[port].used & mask[bit]) {
if (gpio_regs[port].used & bit) {
if (dir)
gpio_regs[port].ddr |= mask[bit];
gpio_regs[port].ddr |= bit;
else
gpio_regs[port].ddr &= ~mask[bit];
gpio_regs[port].ddr &= ~bit;
*ddrs[port] = gpio_regs[port].ddr;
return 1;
} else
......@@ -100,13 +107,13 @@ int h8300_set_gpio_dir(int port_bit,int dir)
int h8300_get_gpio_dir(int port_bit)
{
const unsigned char mask[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int port = (port_bit >> 8) & 0xff;
int bit = port_bit & 0x07;
int bit = port_bit & 0xff;
if (ddrs[port] == NULL)
return 0;
if (gpio_regs[port].used & mask[bit]) {
return (gpio_regs[port].ddr & mask[bit]) != 0;
if (gpio_regs[port].used & bit) {
return (gpio_regs[port].ddr & bit) != 0;
} else
return -1;
}
......@@ -132,10 +139,11 @@ static char *port_status(int portno)
return result;
}
static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int unused)
static int gpio_proc_read(char *buf, char **start, off_t offset,
int len, int *unused_i, void *unused_v)
{
int c,outlen;
const static char port_name[]="123456789AB";
const static char port_name[]="123456789ABCDEFGH";
outlen = 0;
for (c = 0; c < MAX_PORT; c++) {
if (ddrs[c] == NULL)
......@@ -147,20 +155,20 @@ static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int un
return outlen;
}
static const struct proc_dir_entry proc_gpio = {
0, 4,"gpio",S_IFREG | S_IRUGO, 1, 0, 0, 0, NULL, gpio_proc_read,
};
static __init int register_proc(void)
{
struct proc_dir_entry *proc_gpio;
proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL);
if (proc_gpio)
proc_gpio->read_proc = gpio_proc_read;
return proc_gpio != NULL;
}
__initcall(register_proc);
#endif
int h8300_gpio_init(void)
void __init h8300_gpio_init(void)
{
memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs));
#if 0 && defined(CONFIG_PROC_FS)
proc_register(&proc_root,&proc_gpio);
#endif
return 0;
}
#else
#error Unsuppoted CPU Selection
#endif
......@@ -44,12 +44,12 @@
#include <asm/setup.h>
#include <asm/pgtable.h>
asmlinkage void ret_from_exception(void);
asmlinkage void ret_from_fork(void);
/*
* The idle loop on an H8/300..
*/
#if !defined(CONFIG_H8300H_SIM)
#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
void default_idle(void)
{
while(1) {
......@@ -85,20 +85,20 @@ void cpu_idle(void)
void machine_restart(char * __unused)
{
cli();
local_irq_disable();
__asm__("jmp @@0");
}
void machine_halt(void)
{
cli();
local_irq_disable();
__asm__("sleep");
for (;;);
}
void machine_power_off(void)
{
cli();
local_irq_disable();
__asm__("sleep");
for (;;);
}
......@@ -110,10 +110,13 @@ void show_regs(struct pt_regs * regs)
regs->pc, regs->ccr);
printk("ORIG_ER0: %08lx ER0: %08lx ER1: %08lx\n",
regs->orig_er0, regs->er0, regs->er1);
printk("ER2: %08lx ER3: %08lx\n",
regs->er2, regs->er3);
if (!(regs->ccr & 0x10))
printk("ER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx\n",
regs->er2, regs->er3, regs->er4, regs->er5);
printk("ER6' %08lx ",regs->er6);
if (user_mode(regs))
printk("USP: %08lx\n", rdusp());
else
printk("\n");
}
/*
......@@ -122,34 +125,29 @@ void show_regs(struct pt_regs * regs)
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
long retval;
register long clone_arg asm("er1");
long clone_arg;
mm_segment_t fs;
fs = get_fs();
set_fs (KERNEL_DS);
clone_arg = flags | CLONE_VM;
__asm__ __volatile__ (
"mov.l sp, er2\n\t"
"mov.l %1,er0\n\t"
"mov.l %5,er1\n\t"
"trapa #0\n\t"
"cmp.l sp, er2\n\t"
"beq 1f\n\t"
"mov.l %3, er0\n\t"
"jsr @%4\n\t"
"mov.l %2, er0\n\t"
"trapa #0\n"
"1:\n\t"
"mov.l er0,%0"
: "=r" (retval)
: "i" (__NR_clone),
"i" (__NR_exit),
"r" (arg),
"r" (fn),
"r" (clone_arg)
: "cc", "er0", "er1", "er2", "er3");
__asm__("mov.l sp,er3\n\t"
"sub.l er2,er2\n\t"
"mov.l %2,er1\n\t"
"mov.l %1,er0\n\t"
"trapa #0\n\t"
"cmp.l sp,er3\n\t"
"beq 1f\n\t"
"mov.l %4,er0\n\t"
"mov.l %3,er1\n\t"
"jsr @er1\n\t"
"mov.l %5,er0\n\t"
"trapa #0\n"
"1:\n\t"
"mov.l er0,%0"
:"=r"(retval)
:"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit)
:"er0","er1","er2","er3");
set_fs (fs);
return retval;
}
......@@ -172,24 +170,20 @@ asmlinkage int h8300_fork(struct pt_regs *regs)
asmlinkage int h8300_vfork(struct pt_regs *regs)
{
struct task_struct *p;
p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
}
asmlinkage int h8300_clone(struct pt_regs *regs)
{
unsigned long clone_flags;
unsigned long newsp;
struct task_struct *p;
/* syscall2 puts clone_flags in er1 and usp in er2 */
clone_flags = regs->er1;
newsp = regs->er2;
if (!newsp)
newsp = rdusp();
p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
}
......@@ -198,25 +192,15 @@ int copy_thread(int nr, unsigned long clone_flags,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
struct switch_stack * childstack, *stack;
unsigned long stack_offset, *retp;
stack_offset = KTHREAD_SIZE - sizeof(struct pt_regs);
childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
*childregs = *regs;
retp = (unsigned long *) regs-2;
stack = ((struct switch_stack *) retp) - 1;
childstack = ((struct switch_stack *) childregs) - 1;
*childstack = *stack;
childregs->retpc = (unsigned long) ret_from_fork;
childregs->er0 = 0;
childstack->retpc = (unsigned long) ret_from_exception;
p->thread.usp = usp;
p->thread.ksp = (unsigned long)childstack;
p->thread.vfork_ret = 0;
p->thread.ksp = (unsigned long)childregs;
return 0;
}
......@@ -226,8 +210,6 @@ int copy_thread(int nr, unsigned long clone_flags,
*/
void dump_thread(struct pt_regs * regs, struct user * dump)
{
struct switch_stack *sw;
/* changed the size calculations - should hopefully work better. lbt */
dump->magic = CMAGIC;
dump->start_code = 0;
......@@ -239,14 +221,13 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_ssize = 0;
dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump)));
sw = ((struct switch_stack *)regs) - 1;
dump->regs.er0 = regs->er0;
dump->regs.er1 = regs->er1;
dump->regs.er2 = regs->er2;
dump->regs.er3 = regs->er3;
dump->regs.er4 = sw->er4;
dump->regs.er5 = sw->er5;
dump->regs.er6 = sw->er6;
dump->regs.er4 = regs->er4;
dump->regs.er5 = regs->er5;
dump->regs.er6 = regs->er6;
dump->regs.orig_er0 = regs->orig_er0;
dump->regs.ccr = regs->ccr;
dump->regs.pc = regs->pc;
......@@ -259,7 +240,7 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...)
{
int error;
char * filename;
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy+4);
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
lock_kernel();
filename = getname(name);
......@@ -283,14 +264,7 @@ extern void scheduling_functions_end_here(void);
unsigned long thread_saved_pc(struct task_struct *tsk)
{
struct switch_stack *sw = (struct switch_stack *)(tsk->thread.ksp);
/* Check whether the thread is blocked in resume() */
if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
sw->retpc < (unsigned long)scheduling_functions_end_here)
return ((unsigned long *)sw->er6)[1];
else
return sw->retpc;
return ((struct pt_regs *)tsk->thread.esp0)->pc;
}
unsigned long get_wchan(struct task_struct *p)
......@@ -302,7 +276,7 @@ unsigned long get_wchan(struct task_struct *p)
return 0;
stack_page = (unsigned long)p;
fp = ((struct switch_stack *)p->thread.ksp)->er6;
fp = ((struct pt_regs *)p->thread.ksp)->er6;
do {
if (fp < stack_page+sizeof(struct task_struct) ||
fp >= 8184+stack_page)
......
......@@ -46,14 +46,12 @@
/* Find the stack offset for a register, relative to thread.esp0. */
#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
- sizeof(struct switch_stack))
/* Mapping from PT_xxx to the stack offset at which the register is
saved. Notice that usp has no stack-slot and needs to be treated
specially (see get_reg/put_reg below). */
static const int regoff[] = {
PT_REG(er1), PT_REG(er2), PT_REG(er3), SW_REG(er4),
SW_REG(er5), SW_REG(er6), PT_REG(er0), PT_REG(orig_er0),
PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
PT_REG(ccr), PT_REG(pc)
};
......
/*
* linux/arch/h8300h/kernel/setup.c
* linux/arch/h8300/kernel/setup.c
*
* Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
* Copyright (C) 1999,2000 Greg Ungerer (gerg@snapgear.com)
......@@ -9,7 +9,7 @@
* Copyright (C) 2000 Lineo Inc. (www.lineo.com)
* Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
*
* H8/300H porting Yoshinori Sato <ysato@users.sourceforge.jp>
* H8/300 porting Yoshinori Sato <ysato@users.sourceforge.jp>
*/
/*
......@@ -38,10 +38,22 @@
#include <asm/pgtable.h>
#endif
#if defined(CONFIG_CPU_H8300H)
#if defined(__H8300H__)
#define CPU "H8/300H"
#endif
#if defined(__H8300S__)
#define CPU "H8S"
#endif
#if defined(CONFIG_INTELFLASH)
#define BLKOFFSET 512
#else
#define BLKOFFSET 0
#endif
#define STUBSIZE 0xc000;
unsigned long rom_length;
unsigned long memory_start;
unsigned long memory_end;
......@@ -54,10 +66,12 @@ char saved_command_line[512];
extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
extern int _ramstart, _ramend;
extern char _target_name[];
extern void h8300_gpio_init(void);
#if defined(CONFIG_H8300H_SIM) && defined(CONFIG_GDB_MAGICPRINT)
#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \
&& defined(CONFIG_GDB_MAGICPRINT)
/* printk with gdb service */
static void gdb_console_output(struct console *c, char *msg, unsigned len)
static void gdb_console_output(struct console *c, const char *msg, unsigned len)
{
for (; len > 0; len--) {
asm("mov.w %0,r2\n\t"
......@@ -77,7 +91,7 @@ static int __init gdb_console_setup(struct console *co, char *options)
}
static const struct console gdb_console = {
name: "gdb",
name: "gdb_con",
write: gdb_console_output,
device: NULL,
setup: gdb_console_setup,
......@@ -86,26 +100,48 @@ static const struct console gdb_console = {
};
#endif
void setup_arch(char **cmdline_p)
void __init setup_arch(char **cmdline_p)
{
int bootmap_size;
memory_start = PAGE_ALIGN((unsigned long)(&_ramstart));
memory_end = &_ramend; /* by now the stack is part of the init task */
memory_start = (unsigned long) &_ramstart;
/* allow for ROMFS on the end of the kernel */
if (memcmp((void *)(memory_start + BLKOFFSET), "-rom1fs-", 8) == 0) {
#if defined(CONFIG_BLK_DEV_INITRD)
initrd_start = memory_start += BLKOFFSET;
initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]);
#else
memory_start += BLKOFFSET;
memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]);
#endif
}
memory_start = PAGE_ALIGN(memory_start);
#if !defined(CONFIG_BLKDEV_RESERVE)
memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */
#if defined(CONFIG_GDB_DEBUG)
memory_end -= STUBSIZE;
#endif
#else
if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) &&
(memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS)
/* overlap userarea */
memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS;
#endif
init_mm.start_code = (unsigned long) &_stext;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) 0;
#if defined(CONFIG_H8300H_SIM) && defined(CONFIG_GDB_MAGICPRINT)
#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT)
register_console(&gdb_console);
#endif
printk("\x0F\r\n\nuClinux " CPU "\n");
printk("\r\n\nuClinux " CPU "\n");
printk("Target Hardware: %s\n",_target_name);
printk("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
printk("H8/300H support by Yoshinori Sato <ysato@users.sourceforge.jp>\n");
printk("H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n");
#ifdef DEBUG
printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
......@@ -157,6 +193,7 @@ void setup_arch(char **cmdline_p)
* get kmalloc into gear
*/
paging_init();
h8300_gpio_init();
#ifdef DEBUG
printk("Done setup_arch\n");
#endif
......
......@@ -9,7 +9,8 @@
*/
/*
* uClinux H8/300 support by Yoshinori Sato
* uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
* and David McCullough <davidm@snapgear.com>
*
* Based on
* Linux/m68k by Hamish Macdonald
......@@ -151,26 +152,29 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
struct sigframe
{
long dummy_er0;
long dummy_vector;
#if defined(CONFIG_CPU_H8S)
short dummy_exr;
#endif
char *pretcode;
int sig;
int code;
struct sigcontext *psc;
char retcode[6];
unsigned char retcode[8];
unsigned long extramask[_NSIG_WORDS-1];
struct sigcontext sc;
};
} __attribute__((aligned(2),packed));
struct rt_sigframe
{
long dummy_er0;
long dummy_vector;
#if defined(CONFIG_CPU_H8S)
short dummy_exr;
#endif
char *pretcode;
int sig;
struct siginfo *pinfo;
void *puc;
char retcode[6];
unsigned char retcode[8];
struct siginfo info;
struct ucontext uc;
};
} __attribute__((aligned(2),packed));
static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
......@@ -200,8 +204,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
}
static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
struct ucontext *uc, int *pd0)
rt_restore_ucontext(struct pt_regs *regs, struct ucontext *uc, int *pd0)
{
int temp;
greg_t *gregs = uc->uc_mcontext.gregs;
......@@ -216,9 +219,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
err |= __get_user(regs->er1, &gregs[1]);
err |= __get_user(regs->er2, &gregs[2]);
err |= __get_user(regs->er3, &gregs[3]);
err |= __get_user(sw->er4, &gregs[4]);
err |= __get_user(sw->er5, &gregs[5]);
err |= __get_user(sw->er6, &gregs[6]);
err |= __get_user(regs->er4, &gregs[4]);
err |= __get_user(regs->er5, &gregs[5]);
err |= __get_user(regs->er6, &gregs[6]);
err |= __get_user(usp, &gregs[7]);
wrusp(usp);
err |= __get_user(regs->pc, &gregs[8]);
......@@ -238,8 +241,7 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
asmlinkage int do_sigreturn(unsigned long __unused,...)
{
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
struct pt_regs *regs = (struct pt_regs *) &__unused;
unsigned long usp = rdusp();
struct sigframe *frame = (struct sigframe *)(usp - 4);
sigset_t set;
......@@ -270,8 +272,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
{
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
struct pt_regs *regs = (struct pt_regs *) &__unused;
unsigned long usp = rdusp();
struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
sigset_t set;
......@@ -288,7 +289,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
recalc_sigpending();
spin_lock_irq(&current->sighand->siglock);
if (rt_restore_ucontext(regs, sw, &frame->uc, &er0))
if (rt_restore_ucontext(regs, &frame->uc, &er0))
goto badframe;
return er0;
......@@ -312,7 +313,6 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
{
struct switch_stack *sw = (struct switch_stack *)regs - 1;
greg_t *gregs = uc->uc_mcontext.gregs;
int err = 0;
......@@ -321,9 +321,9 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
err |= __put_user(regs->er1, &gregs[1]);
err |= __put_user(regs->er2, &gregs[2]);
err |= __put_user(regs->er3, &gregs[3]);
err |= __put_user(sw->er4, &gregs[4]);
err |= __put_user(sw->er5, &gregs[5]);
err |= __put_user(sw->er6, &gregs[6]);
err |= __put_user(regs->er4, &gregs[4]);
err |= __put_user(regs->er5, &gregs[5]);
err |= __put_user(regs->er6, &gregs[6]);
err |= __put_user(rdusp(), &gregs[7]);
err |= __put_user(regs->pc, &gregs[8]);
err |= __put_user(regs->ccr, &gregs[9]);
......@@ -355,15 +355,6 @@ static void setup_frame (int sig, struct k_sigaction *ka,
frame = get_sigframe(ka, regs, sizeof(*frame));
err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
err |= __put_user(&frame->sc, &frame->psc);
if (_NSIG_WORDS > 1)
err |= copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
......@@ -376,8 +367,8 @@ static void setup_frame (int sig, struct k_sigaction *ka,
/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
(long *)(frame->retcode + 0));
err |= __put_user(0x5700, (short *)(frame->retcode + 4));
(unsigned long *)(frame->retcode + 0));
err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
if (err)
......@@ -386,6 +377,12 @@ static void setup_frame (int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */
wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler;
regs->er0 = (current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig);
regs->er1 = (unsigned long)&(frame->sc);
return;
......@@ -403,14 +400,6 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
frame = get_sigframe(ka, regs, sizeof(*frame));
err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig),
&frame->sig);
err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info);
/* Create the ucontext. */
......@@ -438,7 +427,14 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler;
regs->pc = (unsigned long) ka->sa.sa_handler;
regs->er0 = (current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig);
regs->er1 = (unsigned long)&(frame->info);
regs->er2 = (unsigned long)&frame->uc;
return;
......
......@@ -281,9 +281,8 @@ asmlinkage int sys_getpagesize(void)
#if defined(CONFIG_SYSCALL_PRINT)
asmlinkage void syscall_print(void *dummy,...)
{
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy);
unsigned long *usp=rdusp()+8;
printk("call %06x:%d 1:%08x,2:%08x,3:%08x,ret:%08x\n",
((*usp) & 0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n",
((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
}
#endif
......@@ -312,3 +312,7 @@ SYMBOL_NAME_LABEL(sys_fork)
mov.l #SYMBOL_NAME(h8300_fork),er0
jmp @SYMBOL_NAME(syscall_trampoline)
SYMBOL_NAME_LABEL(sys_vfork)
mov.l #SYMBOL_NAME(h8300_vfork),er0
jmp @SYMBOL_NAME(syscall_trampoline)
......@@ -110,8 +110,11 @@ void do_gettimeofday(struct timeval *tv)
tv->tv_usec = usec;
}
void do_settimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv)
{
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
write_lock_irq(&xtime_lock);
/* This is revolting. We need to set the xtime.tv_usec
* correctly. However, the value in this location is
......@@ -119,16 +122,17 @@ void do_settimeofday(struct timeval *tv)
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
while (tv->tv_usec < 0) {
tv->tv_usec += 1000000;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = (tv->tv_usec * 1000);
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_unlock_irq(&xtime_lock);
write_sequnlock_irq(&xtime_lock);
return 0;
}
......@@ -72,15 +72,17 @@ static void dump(struct pt_regs *fp)
(int) current->mm->end_data,
(int) current->mm->end_data,
(int) current->mm->brk);
printk("USER-STACK=%08x KERNEL-STACK=%08x\n\n",
printk("USER-STACK=%08x KERNEL-STACK=%08lx\n\n",
(int) current->mm->start_stack,
(int) PAGE_SIZE+(unsigned long)current);
}
printk("PC: %08lx\n", (long)fp->pc);
printk("CCR: %08lx SP: %08lx\n", fp->ccr, (long) fp);
printk("CCR: %02x SP: %08lx\n", fp->ccr, (long) fp);
printk("ER0: %08lx ER1: %08lx ER2: %08lx ER3: %08lx\n",
fp->er0, fp->er1, fp->er2, fp->er3);
printk("ER4: %08lx ER5: %08lx ER6: %08lx\n",
fp->er4, fp->er5, fp->er6);
printk("\nCODE:");
tp = ((unsigned char *) fp->pc) - 0x20;
for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
......@@ -122,3 +124,53 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
do_exit(SIGSEGV);
}
extern char _start, _etext;
#define check_kernel_text(addr) \
((addr >= (unsigned long)(&_start)) && \
(addr < (unsigned long)(&_etext)))
static int kstack_depth_to_print = 24;
void show_stack(struct task_struct *task, unsigned long *esp)
{
unsigned long *stack, addr;
int i;
if (esp == NULL)
esp = (unsigned long *) &esp;
stack = esp;
printk("Stack from %08lx:", (unsigned long)stack);
for (i = 0; i < kstack_depth_to_print; i++) {
if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0)
break;
if (i % 8 == 0)
printk("\n ");
printk(" %08lx", *stack++);
}
printk("\nCall Trace:");
i = 0;
stack = esp;
while (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) {
addr = *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 (check_kernel_text(addr)) {
if (i % 4 == 0)
printk("\n ");
printk(" [<%08lx>]", addr);
i++;
}
}
printk("\n");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment