Commit 233382d3 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] parisc updates

arch/parisc, drivers/parisc and include/asm-parisc updates:

 - Fixups for struct timespec changes (James Bottomley)
 - Add CONFIG_FRAME_POINTER (Thibaut Varene)
 - Fix hpux ustat emulation (Helge Deller)
 - Add a ->remove operation to struct parisc_device (James Bottomley)
 - More work on modules (James Bottomley)
 - More unaligned instructions handled (LaMont Jones)
 - Fix byteswap assembly (Grant Grundler)
 - Allow ISA support to be selected (Matthew Wilcox)
 - Fix swapping (James Bottomley)
parent 05081dcb
#
# For a description of the syntax of this configuration file,
# see the Configure script.
# see Documentation/kbuild/kconfig-language.txt.
#
mainmenu "Linux/PA-RISC Kernel Configuration"
......@@ -289,12 +289,19 @@ config MAGIC_SYSRQ
config KALLSYMS
bool "Load all symbols for debugging/kksymoops"
depends on DEBUG_KERNEL
help
Say Y here to let the kernel print out symbolic crash information and
symbolic stack backtraces. This increases the size of the kernel
somewhat, as all symbols have to be loaded into the kernel image.
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame pointers.
endmenu
source "security/Kconfig"
......
......@@ -121,7 +121,7 @@ static int hpux_ustat(dev_t dev, struct hpux_ustat *ubuf)
{
struct super_block *s;
struct hpux_ustat tmp; /* Changed to hpux_ustat */
struct statfs sbuf;
struct kstatfs sbuf;
int err = -EINVAL;
s = user_get_super(dev);
......
......@@ -112,7 +112,9 @@ static int parisc_driver_probe(struct device *dev)
static int parisc_driver_remove(struct device *dev)
{
struct parisc_device *pa_dev = to_parisc_device(dev);
struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
if (pa_drv->remove)
pa_drv->remove(pa_dev);
release_mem_region(pa_dev->hpa, 0x1000);
return 0;
......
......@@ -36,8 +36,9 @@
#include <linux/mtio.h>
#include <linux/cdrom.h>
#include <linux/loop.h>
#include <linux/auto_fs.h>
#include <linux/auto_fs4.h>
#include <linux/devfs_fs.h>
#include <linux/ncp_fs.h>
#include <linux/tty.h>
#include <linux/vt_kern.h>
#include <linux/fb.h>
......
......@@ -671,6 +671,11 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
int i;
unsigned long nsyms;
const char *strtab = NULL;
Elf_Sym *newptr, *oldptr;
Elf_Shdr *symhdr = NULL;
#ifdef DEBUG
struct fdesc_entry *entry;
u32 *addr;
......@@ -691,6 +696,48 @@ int module_finalize(const Elf_Ehdr *hdr,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
/* haven't filled in me->symtab yet, so have to find it
* ourselves */
for (i = 1; i < hdr->e_shnum; i++) {
if(sechdrs[i].sh_type == SHT_SYMTAB
&& (sechdrs[i].sh_type & SHF_ALLOC)) {
int strindex = sechdrs[i].sh_link;
/* FIXME: AWFUL HACK
* The cast is to drop the const from
* the sechdrs pointer */
symhdr = (Elf_Shdr *)&sechdrs[i];
strtab = (char *)sechdrs[strindex].sh_addr;
break;
}
}
printk("module %s: strtab %p, symhdr %p\n",
me->name, strtab, symhdr);
/* no symbol table */
if(symhdr == NULL)
return 0;
oldptr = (void *)symhdr->sh_addr;
newptr = oldptr + 1; /* we start counting at 1 */
nsyms = symhdr->sh_size / sizeof(Elf_Sym);
DEBUGP("OLD num_symtab %lu\n", nsyms);
for (i = 1; i < nsyms; i++) {
oldptr++; /* note, count starts at 1 so preincrement */
if(strncmp(strtab + oldptr->st_name,
".L", 2) == 0)
continue;
if(newptr != oldptr)
*newptr++ = *oldptr;
else
newptr++;
}
nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
DEBUGP("NEW num_symtab %lu\n", nsyms);
symhdr->sh_size = nsyms * sizeof(Elf_Sym);
return 0;
}
......
......@@ -10,11 +10,12 @@
* Copyright (C) 1999-2001 Grant Grundler
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h> /* for __init and __devinit */
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/system.h>
......
......@@ -418,11 +418,11 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
}
asmlinkage int
sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz)
{
struct timeval ktv;
struct timezone ktz;
extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
if (tv) {
if (get_compat_timeval(tv, &ktv))
......
......@@ -188,7 +188,7 @@ do_gettimeofday (struct timeval *tv)
}
int
do_settimeofday (struct timeval *tv)
do_settimeofday (struct timespec *tv)
{
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
......
......@@ -126,7 +126,7 @@ void show_regs(struct pt_regs *regs)
void dump_stack(void)
{
unsigned long stack;
show_trace(&stack);
show_trace(current, &stack);
}
......@@ -136,7 +136,7 @@ static int kstack_depth_to_print = 64 * 4;
static int kstack_depth_to_print = 128 * 4;
#endif
void show_stack(unsigned long *sp)
void show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long *stack;
int i;
......@@ -145,8 +145,10 @@ void show_stack(unsigned long *sp)
* debugging aid: "show_stack(NULL);" prints the
* back trace for this cpu.
*/
if (sp==NULL)
if (task==NULL)
sp = (unsigned long*)&sp;
else if(sp == NULL)
sp = (unsigned long*)task->thread.regs.ksp;
stack = sp;
printk("\n" KERN_CRIT "Stack Dump:\n");
......@@ -160,11 +162,11 @@ void show_stack(unsigned long *sp)
printk(RFMT " ", *stack--);
}
printk("\n" KERN_CRIT "\n");
show_trace(sp);
show_trace(task, sp);
}
void show_trace(unsigned long *stack)
void show_trace(struct task_struct *task, unsigned long *stack)
{
unsigned long *startstack;
unsigned long addr;
......@@ -201,7 +203,7 @@ void show_trace(unsigned long *stack)
void show_trace_task(struct task_struct *tsk)
{
show_trace((unsigned long *)tsk->thread.regs.ksp);
show_trace(tsk, (unsigned long *)tsk->thread.regs.ksp);
}
void die_if_kernel(char *str, struct pt_regs *regs, long err)
......@@ -426,7 +428,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
if (code == 1)
transfer_pim_to_trap_frame(regs);
show_stack((unsigned long *)regs->gr[30]);
show_stack(NULL, (unsigned long *)regs->gr[30]);
printk("\n");
printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
......
......@@ -92,6 +92,15 @@
#define OPCODE_STWA OPCODE1(0x03,1,0xe)
#define OPCODE_STDA OPCODE1(0x03,1,0xf)
#define OPCODE_FLDWX OPCODE1(0x09,0,0x0)
#define OPCODE_FSTWX OPCODE1(0x09,0,0x4)
#define OPCODE_FLDWS OPCODE1(0x09,1,0x0)
#define OPCODE_FSTWS OPCODE1(0x09,1,0x4)
#define OPCODE_FLDDX OPCODE1(0x0b,0,0x0)
#define OPCODE_FSTDX OPCODE1(0x0b,0,0x4)
#define OPCODE_FLDDS OPCODE1(0x0b,1,0x0)
#define OPCODE_FSTDS OPCODE1(0x0b,1,0x4)
#define OPCODE_LDD_L OPCODE2(0x14,0)
#define OPCODE_FLDD_L OPCODE2(0x14,1)
#define OPCODE_STD_L OPCODE2(0x1c,0)
......@@ -113,6 +122,7 @@
#define R1(i) (((i)>>21)&0x1f)
#define R2(i) (((i)>>16)&0x1f)
#define R3(i) ((i)&0x1f)
#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
#define IM5_2(i) IM((i)>>16,5)
#define IM5_3(i) IM((i),5)
......@@ -146,7 +156,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
return 0;
}
static int emulate_ldw(struct pt_regs *regs, int toreg)
static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
{
unsigned long saddr = regs->ior;
unsigned long val = 0;
......@@ -169,20 +179,26 @@ static int emulate_ldw(struct pt_regs *regs, int toreg)
DPRINTF("val = 0x" RFMT "\n", val);
if (toreg)
if (flop)
((__u32*)(regs->fr))[toreg] = val;
else if (toreg)
regs->gr[toreg] = val;
return 0;
}
#ifdef __LP64__
static int emulate_ldd(struct pt_regs *regs, int toreg)
static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
{
unsigned long saddr = regs->ior;
unsigned long val = 0;
__u64 val = 0;
DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n",
regs->isr, regs->ior, toreg);
#ifdef CONFIG_PA20
#ifndef __LP64__
if (!flop)
return -1;
#endif
__asm__ __volatile__ (
" depd,z %2,60,3,%%r19\n" /* r19=(ofs&7)*8 */
" mtsp %3, %%sr1\n"
......@@ -195,15 +211,36 @@ static int emulate_ldd(struct pt_regs *regs, int toreg)
: "=r" (val)
: "0" (val), "r" (saddr), "r" (regs->isr)
: "r19", "r20" );
#else
{
unsigned long valh=0,vall=0;
__asm__ __volatile__ (
" zdep %4,29,2,%%r19\n" /* r19=(ofs&3)*8 */
" mtsp %5, %%sr1\n"
" dep %%r0,31,2,%4\n"
" ldw 0(%%sr1,%5),%0\n"
" ldw 4(%%sr1,%5),%1\n"
" ldw 8(%%sr1,%5),%%r20\n"
" subi 32,%%r19,%%r19\n"
" mtsar %%r19\n"
" vshd %0,%1,%0\n"
" vshd %1,%%r20,%1\n"
: "=r" (valh), "=r" (vall)
: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
: "r19", "r20" );
val=((__u64)valh<<32)|(__u64)vall;
}
#endif
DPRINTF("val = 0x" RFMT "\n", val);
if (toreg)
if (flop)
regs->fr[toreg] = val;
else if (toreg)
regs->gr[toreg] = val;
return 0;
}
#endif
static int emulate_sth(struct pt_regs *regs, int frreg)
{
......@@ -212,7 +249,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
val = 0;
DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg,
regs->gr[frreg], regs->isr, regs->ior);
val, regs->isr, regs->ior);
__asm__ __volatile__ (
" mtsp %2, %%sr1\n"
......@@ -225,14 +262,19 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
return 0;
}
static int emulate_stw(struct pt_regs *regs, int frreg)
static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
{
unsigned long val = regs->gr[frreg];
if (!frreg)
unsigned long val;
if (flop)
val = ((__u32*)(regs->fr))[frreg];
else if (frreg)
val = regs->gr[frreg];
else
val = 0;
DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg,
regs->gr[frreg], regs->isr, regs->ior);
val, regs->isr, regs->ior);
__asm__ __volatile__ (
......@@ -257,17 +299,25 @@ static int emulate_stw(struct pt_regs *regs, int frreg)
return 0;
}
#ifdef __LP64__
static int emulate_std(struct pt_regs *regs, int frreg)
static int emulate_std(struct pt_regs *regs, int frreg, int flop)
{
unsigned long val = regs->gr[frreg];
if (!frreg)
val = 0;
__u64 val;
DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 8 bytes\n", frreg,
regs->gr[frreg], regs->isr, regs->ior);
if (flop)
val = regs->fr[frreg];
else if (frreg)
val = regs->gr[frreg];
else
val = 0;
DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg,
val, regs->isr, regs->ior);
#ifdef CONFIG_PA20
#ifndef __LP64__
if (!flop)
return -1;
#endif
__asm__ __volatile__ (
" mtsp %2, %%sr1\n"
" depd,z %1, 60, 3, %%r19\n"
......@@ -287,19 +337,45 @@ static int emulate_std(struct pt_regs *regs, int frreg)
:
: "r" (val), "r" (regs->ior), "r" (regs->isr)
: "r19", "r20", "r21", "r22", "r1" );
#else
{
unsigned long valh=(val>>32),vall=(val&0xffffffffl);
__asm__ __volatile__ (
" mtsp %3, %%sr1\n"
" zdep %1, 29, 2, %%r19\n"
" dep %%r0, 31, 2, %1\n"
" mtsar %%r19\n"
" zvdepi -2, 32, %%r19\n"
" ldw 0(%%sr1,%2),%%r20\n"
" ldw 8(%%sr1,%2),%%r21\n"
" vshd %0, %1, %%r1\n"
" vshd %%r0, %0, %0\n"
" vshd %1, %%r0, %1\n"
" and %%r20, %%r19, %%r20\n"
" andcm %%r21, %%r19, %%r21\n"
" or %0, %%r20, %0\n"
" or %1, %%r21, %1\n"
" stw %0,0(%%sr1,%2)\n"
" stw %%r1,4(%%sr1,%2)\n"
" stw %1,8(%%sr1,%2)\n"
:
: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
: "r19", "r20", "r21", "r1" );
}
#endif
return 0;
}
#endif
void handle_unaligned(struct pt_regs *regs)
{
unsigned long unaligned_count = 0;
unsigned long last_time = 0;
unsigned long newbase = regs->gr[R1(regs->iir)];
unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
int modify = 0;
int ret = -1;
struct siginfo si;
register int flop=0; /* true if this is a flop */
/* if the unaligned access is inside the kernel:
* if the access is caused by a syscall, then we fault the calling
......@@ -383,9 +459,9 @@ void handle_unaligned(struct pt_regs *regs)
case OPCODE_LDDA_I:
shift= 3; break;
}
newbase += regs->gr[R2(regs->iir)]<<shift;
newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
} else /* simple indexed */
newbase += regs->gr[R2(regs->iir)];
newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
}
break;
case 0x13:
......@@ -438,7 +514,7 @@ void handle_unaligned(struct pt_regs *regs)
case OPCODE_LDWA_I:
case OPCODE_LDW_S:
case OPCODE_LDWA_S:
ret = emulate_ldw(regs, R3(regs->iir));
ret = emulate_ldw(regs, R3(regs->iir),0);
break;
case OPCODE_STH:
......@@ -447,23 +523,47 @@ void handle_unaligned(struct pt_regs *regs)
case OPCODE_STW:
case OPCODE_STWA:
ret = emulate_stw(regs, R2(regs->iir));
ret = emulate_stw(regs, R2(regs->iir),0);
break;
#ifdef __LP64__
#ifdef CONFIG_PA20
case OPCODE_LDD_I:
case OPCODE_LDDA_I:
case OPCODE_LDD_S:
case OPCODE_LDDA_S:
ret = emulate_ldd(regs, R3(regs->iir));
ret = emulate_ldd(regs, R3(regs->iir),0);
break;
case OPCODE_STD:
case OPCODE_STDA:
ret = emulate_std(regs, R2(regs->iir));
ret = emulate_std(regs, R2(regs->iir),0);
break;
#endif
case OPCODE_FLDWX:
case OPCODE_FLDWS:
flop=1;
ret = emulate_ldw(regs,FR3(regs->iir),1);
break;
case OPCODE_FLDDX:
case OPCODE_FLDDS:
flop=1;
ret = emulate_ldd(regs,R3(regs->iir),1);
break;
case OPCODE_FSTWX:
case OPCODE_FSTWS:
flop=1;
ret = emulate_stw(regs,FR3(regs->iir),1);
break;
case OPCODE_FSTDX:
case OPCODE_FSTDS:
flop=1;
ret = emulate_std(regs,R3(regs->iir),1);
break;
case OPCODE_LDCD_I:
case OPCODE_LDCW_I:
case OPCODE_LDCD_S:
......@@ -471,30 +571,44 @@ void handle_unaligned(struct pt_regs *regs)
ret = -1; /* "undefined", but lets kill them. */
break;
}
#ifdef __LP64__
#ifdef CONFIG_PA20
switch (regs->iir & OPCODE2_MASK)
{
case OPCODE_LDD_L:
case OPCODE_FLDD_L:
ret = emulate_ldd(regs, R2(regs->iir));
flop=1;
ret = emulate_ldd(regs,R2(regs->iir),1);
break;
case OPCODE_FSTD_L:
flop=1;
ret = emulate_std(regs, R2(regs->iir),1);
break;
#ifdef CONFIG_PA20
case OPCODE_LDD_L:
ret = emulate_ldd(regs, R2(regs->iir),0);
break;
case OPCODE_STD_L:
case OPCODE_FSTD_L:
ret = emulate_std(regs, R2(regs->iir));
ret = emulate_std(regs, R2(regs->iir),0);
break;
#endif
}
#endif
switch (regs->iir & OPCODE3_MASK)
{
case OPCODE_LDW_M:
case OPCODE_FLDW_L:
ret = emulate_ldw(regs, R2(regs->iir));
flop=1;
ret = emulate_ldw(regs, R2(regs->iir),0);
break;
case OPCODE_LDW_M:
ret = emulate_ldw(regs, R2(regs->iir),1);
break;
case OPCODE_FSTW_L:
flop=1;
ret = emulate_stw(regs, R2(regs->iir),1);
break;
case OPCODE_STW_M:
ret = emulate_stw(regs, R2(regs->iir));
ret = emulate_stw(regs, R2(regs->iir),0);
break;
}
switch (regs->iir & OPCODE4_MASK)
......@@ -504,19 +618,18 @@ void handle_unaligned(struct pt_regs *regs)
break;
case OPCODE_LDW_L:
case OPCODE_LDWM:
ret = emulate_ldw(regs, R2(regs->iir));
ret = emulate_ldw(regs, R2(regs->iir),0);
break;
case OPCODE_STH_L:
ret = emulate_sth(regs, R2(regs->iir));
break;
case OPCODE_STW_L:
case OPCODE_STWM:
ret = emulate_stw(regs, R2(regs->iir));
ret = emulate_stw(regs, R2(regs->iir),0);
break;
}
/* XXX LJ - need to handle float load/store */
if (modify)
if (modify && R1(regs->iir))
regs->gr[R1(regs->iir)] = newbase;
......@@ -540,9 +653,8 @@ void handle_unaligned(struct pt_regs *regs)
return;
}
/* else we handled it, advance the PC.... */
regs->iaoq[0] = regs->iaoq[1];
regs->iaoq[1] = regs->iaoq[0] + 4;
/* else we handled it, let life go on. */
regs->gr[0]|=PSW_N;
}
/*
......
......@@ -57,8 +57,11 @@ config EISA
source "drivers/eisa/Kconfig"
config ISA
bool
bool "ISA support"
depends on EISA
help
If you want to plug an ISA card into your EISA bus, say Y here.
Most people should say N.
config PCI
bool "PCI support"
......
......@@ -30,9 +30,9 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
*/
static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
__u64 temp;
__asm__("permh 3210, %0, %0\n\t"
__asm__("permh,3210 %0, %0\n\t"
"hshl %0, 8, %1\n\t"
"hshr u, %0, 8, %0\n\t"
"hshr,u %0, 8, %0\n\t"
"or %1, %0, %0"
: "=r" (x), "=&r" (temp)
: "0" (x));
......
......@@ -33,6 +33,7 @@ struct parisc_driver {
char *name;
const struct parisc_device_id *id_table;
int (*probe) (struct parisc_device *dev); /* New device discovered */
int (*remove) (struct parisc_device *dev);
struct device_driver drv;
};
......
......@@ -368,11 +368,11 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
/* Encode and de-code a swap entry */
#define __swp_type(x) ((x).val & 0x1f)
#define __swp_offset(x) ( (((x).val >> 5) & 0xf) | \
(((x).val >> 7) & ~0xf) )
#define __swp_offset(x) ( (((x).val >> 6) & 0x7) | \
(((x).val >> 8) & ~0x7) )
#define __swp_entry(type, offset) ((swp_entry_t) { (type) | \
((offset & 0xf) << 5) | \
((offset & ~0xf) << 7) })
((offset & 0x7) << 6) | \
((offset & ~0x7) << 8) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
......
......@@ -142,6 +142,7 @@ struct thread_struct {
*/
unsigned long thread_saved_pc(struct task_struct *t);
void show_trace(struct task_struct *task, unsigned long *stack);
/*
* Start user thread in another space.
......
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