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