Commit 56f41d50 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds
Browse files

[PATCH] PA-RISC updates

PA-RISC updates for 2.6.0-test6
 - Some more support for 64-bit userspace
 - Move many EXPORT_SYMBOLs out of parisc_ksyms.c
 - Make both the OSS and ALSA harmony drivers build
 - ioctl typechecking
 - Make math-emu build without warnings.
 - Persuade SuckyIO to not crash the machine.
parent 7e2552dc
......@@ -150,6 +150,7 @@ config COMPAT
config HPUX
bool "Support for HP-UX binaries"
depends on !PARISC64
config NR_CPUS
int "Maximum number of CPUs (2-32)"
......@@ -190,6 +191,8 @@ source drivers/message/fusion/Kconfig
#source drivers/message/i2o/Kconfig
source "net/Kconfig"
#source "drivers/isdn/Kconfig"
#source "drivers/telephony/Kconfig"
......
......@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/thread_info.h>
#include <linux/version.h>
#include <linux/ptrace.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
......@@ -249,5 +250,8 @@ int main(void)
DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count));
DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop));
BLANK();
DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT);
DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT);
BLANK();
return 0;
}
......@@ -88,7 +88,9 @@ struct elf_prpsinfo32
*/
#define SET_PERSONALITY(ex, ibcs2) \
current->personality = PER_LINUX_32BIT
current->personality = PER_LINUX32; \
current->thread.map_base = DEFAULT_MAP_BASE32; \
current->thread.task_size = DEFAULT_TASK_SIZE32 \
#define jiffies_to_timeval jiffies_to_compat_timeval
static __inline__ void
......@@ -99,3 +101,25 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
}
#include "../../../fs/binfmt_elf.c"
/* Set up a separate execution domain for ELF32 binaries running
* on an ELF64 kernel */
static struct exec_domain parisc32_exec_domain = {
.name = "Linux/ELF32",
.pers_low = PER_LINUX32,
.pers_high = PER_LINUX32,
};
static int __init parisc32_exec_init(void)
{
/* steal the identity signal mappings from the default domain */
parisc32_exec_domain.signal_map = default_exec_domain.signal_map;
parisc32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
register_exec_domain(&parisc32_exec_domain);
return 0;
}
__initcall(parisc32_exec_init);
......@@ -28,6 +28,7 @@
/* See comments in include/asm-parisc/pci.h */
struct hppa_dma_ops *hppa_dma_ops;
EXPORT_SYMBOL(hppa_dma_ops);
static struct parisc_device root;
......@@ -155,6 +156,7 @@ int register_parisc_driver(struct parisc_driver *driver)
return driver_register(&driver->drv);
}
EXPORT_SYMBOL(register_parisc_driver);
/**
* count_parisc_driver - count # of devices this driver would match
......@@ -187,6 +189,7 @@ int unregister_parisc_driver(struct parisc_driver *driver)
driver_unregister(&driver->drv);
return 0;
}
EXPORT_SYMBOL(unregister_parisc_driver);
static struct parisc_device *find_device_by_addr(unsigned long hpa)
{
......@@ -257,7 +260,7 @@ char *print_pa_hwpath(struct parisc_device *dev, char *output)
path.mod = dev->hw_path;
return print_hwpath(&path, output);
}
EXPORT_SYMBOL(print_pa_hwpath);
#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
/**
......@@ -289,6 +292,7 @@ void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path)
padev = padev->parent;
}
}
EXPORT_SYMBOL(get_pci_node_path);
/**
* print_pci_hwpath - Returns hardware path for PCI devices
......@@ -306,6 +310,8 @@ char *print_pci_hwpath(struct pci_dev *dev, char *output)
get_pci_node_path(dev, &path);
return print_hwpath(&path, output);
}
EXPORT_SYMBOL(print_pci_hwpath);
#endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
......
......@@ -2225,18 +2225,23 @@ syscall_exit:
LDREG TI_TASK(%r1),%r1
STREG %r28,TASK_PT_GR28(%r1)
/* Save other hpux returns if personality is PER_HPUX */
#ifdef CONFIG_HPUX
/* <linux/personality.h> cannot be easily included */
#define PER_HPUX 0x10
LDREG TASK_PERSONALITY(%r1),%r19
#warning the ldo+CMPIB could probably be done better but 0x10 i soutside of range of CMPIB
/* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
ldo -PER_HPUX(%r19), %r19
CMPIB<>,n 0,%r19,1f
/* Save other hpux returns if personality is PER_HPUX */
STREG %r22,TASK_PT_GR22(%r1)
STREG %r29,TASK_PT_GR29(%r1)
1:
#endif /* CONFIG_HPUX */
/* Seems to me that dp could be wrong here, if the syscall involved
* calling a module, and nothing got round to restoring dp on return.
*/
......@@ -2315,18 +2320,16 @@ syscall_restore:
depi 3,31,2,%r31 /* ensure return to user mode. */
#ifdef __LP64__
/* Since we are returning to a 32 bit user process, we always
* clear the W bit. This means that the be (and mtsp) gets
* executed in narrow mode, but that is OK, since we are
* returning to a 32 bit process. When we support 64 bit processes
* we won't clear the W bit, so the be will run in wide mode.
*/
be 0(%sr3,%r31) /* return to user space */
/* decide whether to reset the wide mode bit
*
* For a syscall, the W bit is stored in the lowest bit
* of sp. Extract it and reset W if it is zero */
extrd,u,*<> %r30,63,1,%r1
rsm PSW_SM_W, %r0
#else
be,n 0(%sr3,%r31) /* return to user space */
/* now reset the lowest bit of sp if it was set */
xor %r30,%r1,%r30
#endif
be,n 0(%sr3,%r31) /* return to user space */
/* We have to return via an RFI, so that PSW T and R bits can be set
* appropriately.
......@@ -2340,12 +2343,19 @@ syscall_restore_rfi:
LDREG TASK_PT_PSW(%r1),%r2 /* Get old PSW */
ldi 0x0b,%r20 /* Create new PSW */
depi -1,13,1,%r20 /* C, Q, D, and I bits */
bb,>=,n %r19,15,try_tbit /* PT_SINGLESTEP */
/* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are
* set in include/linux/ptrace.h and converted to PA bitmap
* numbers in asm-offsets.c */
/* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */
extru,= %r19,PA_SINGLESTEP_BIT,1,%r0
depi -1,27,1,%r20 /* R bit */
try_tbit:
bb,>=,n %r19,14,psw_setup /* PT_BLOCKSTEP, see ptrace.c */
/* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */
extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0
depi -1,7,1,%r20 /* T bit */
psw_setup:
STREG %r20,TASK_PT_PSW(%r1)
/* Always store space registers, since sr3 can be changed (e.g. fork) */
......
......@@ -41,19 +41,20 @@
* prumpf 991016
*/
#include <stdarg.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/page.h>
#include <asm/pdc.h>
#include <asm/system.h>
#include <asm/processor.h> /* for boot_cpu_data */
#include <stdarg.h>
static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
......@@ -151,6 +152,7 @@ int pdc_add_valid(unsigned long address)
return retval;
}
EXPORT_SYMBOL(pdc_add_valid);
/**
* pdc_chassis_info - Return chassis information.
......@@ -264,6 +266,7 @@ int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
return retval;
}
EXPORT_SYMBOL(pdc_iodc_read);
/**
* pdc_system_map_find_mods - Locate unarchitected modules.
......@@ -518,6 +521,7 @@ int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
return retval;
}
EXPORT_SYMBOL(pdc_lan_station_id);
/**
......@@ -594,6 +598,7 @@ int pdc_get_initiator( struct hardware_path *hwpath, unsigned char *scsi_id,
spin_unlock_irq(&pdc_lock);
return retval >= PDC_OK;
}
EXPORT_SYMBOL(pdc_get_initiator);
/**
......@@ -660,6 +665,7 @@ int pdc_tod_read(struct pdc_tod *tod)
return retval;
}
EXPORT_SYMBOL(pdc_tod_read);
/**
* pdc_tod_set - Set the Time-Of-Day clock.
......@@ -678,6 +684,7 @@ int pdc_tod_set(unsigned long sec, unsigned long usec)
return retval;
}
EXPORT_SYMBOL(pdc_tod_set);
#ifdef __LP64__
int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
......@@ -772,20 +779,34 @@ int pdc_soft_power_button(int sw_control)
}
/*
* pdc_suspend_usb - Stop USB controller
* pdc_io_reset - Hack to avoid overlapping range registers of Bridges devices.
* Primarily a problem on T600 (which parisc-linux doesn't support) but
* who knows what other platform firmware might do with this OS "hook".
*/
void pdc_io_reset(void)
{
spin_lock_irq(&pdc_lock);
mem_pdc_call(PDC_IO, PDC_IO_RESET, 0);
spin_unlock_irq(&pdc_lock);
}
/*
* pdc_io_reset_devices - Hack to Stop USB controller
*
* If PDC used the usb controller, the usb controller
* is still running and will crash the machines during iommu
* setup, because of still running DMA. This PDC call
* stops the USB controller
* stops the USB controller.
* Normally called after calling pdc_io_reset().
*/
void pdc_suspend_usb(void)
void pdc_io_reset_devices(void)
{
spin_lock_irq(&pdc_lock);
mem_pdc_call(PDC_IO, PDC_IO_SUSPEND_USB, 0);
mem_pdc_call(PDC_IO, PDC_IO_RESET_DEVICES, 0);
spin_unlock_irq(&pdc_lock);
}
/**
* pdc_iodc_putc - Console character print using IODC.
* @c: the character to output.
......@@ -905,6 +926,7 @@ int pdc_sti_call(unsigned long func, unsigned long flags,
return retval;
}
EXPORT_SYMBOL(pdc_sti_call);
#ifdef __LP64__
/**
......
......@@ -526,12 +526,14 @@ static void __init system_map_inventory(void)
int i;
long status = PDC_OK;
#if defined(CONFIG_IOMMU_SBA) && defined(CONFIG_SUPERIO)
/*
* first stop the usb controller, otherwise the machine
* might crash during iommu setup
* Stop the suckyio usb controller on Astro based systems.
* Otherwise the machine might crash during iommu setup.
*/
#warning We still probably need to worry about USB here, but how?
/* pdc_suspend_usb(); */
pdc_io_reset();
pdc_io_reset_devices();
#endif
for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) {
struct parisc_device *dev;
......
......@@ -193,6 +193,7 @@ void disable_irq(int irq)
else
BUG();
}
EXPORT_SYMBOL(disable_irq);
void enable_irq(int irq)
{
......@@ -208,6 +209,7 @@ void enable_irq(int irq)
else
BUG();
}
EXPORT_SYMBOL(enable_irq);
int show_interrupts(struct seq_file *p, void *v)
{
......@@ -698,6 +700,7 @@ void synchronize_irq(unsigned int irqnum)
{
while (in_irq()) ;
}
EXPORT_SYMBOL(synchronize_irq);
#endif
......@@ -847,6 +850,7 @@ unsigned int probe_irq_mask(unsigned long irqs)
{
return 0;
}
EXPORT_SYMBOL(probe_irq_mask);
void __init init_IRQ(void)
{
......
......@@ -73,10 +73,7 @@ struct got_entry {
Elf32_Addr addr;
};
struct fdesc_entry {
Elf32_Addr addr;
Elf32_Addr gp;
};
#define Elf_Fdesc Elf32_Fdesc
struct stub_entry {
Elf32_Word insns[2]; /* each stub entry has two insns */
......@@ -86,11 +83,7 @@ struct got_entry {
Elf64_Addr addr;
};
struct fdesc_entry {
Elf64_Addr dummy[2];
Elf64_Addr addr;
Elf64_Addr gp;
};
#define Elf_Fdesc Elf64_Fdesc
struct stub_entry {
Elf64_Word insns[4]; /* each stub entry has four insns */
......@@ -276,7 +269,7 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
me->core_size = ALIGN(me->core_size, 16);
me->arch.fdesc_offset = me->core_size;
me->core_size += fdescs * sizeof(struct fdesc_entry);
me->core_size += fdescs * sizeof(Elf_Fdesc);
me->core_size = ALIGN(me->core_size, 16);
me->arch.stub_offset = me->core_size;
......@@ -322,7 +315,7 @@ static Elf64_Word get_got(struct module *me, unsigned long value, long addend)
#ifdef __LP64__
static Elf_Addr get_fdesc(struct module *me, unsigned long value)
{
struct fdesc_entry *fdesc = me->module_core + me->arch.fdesc_offset;
Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
if (!value) {
printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
......@@ -664,7 +657,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
*loc64 = get_fdesc(me, val+addend);
DEBUGP("FDESC for %s at %p points to %lx\n",
strtab + sym->st_name, *loc64,
((struct fdesc_entry *)*loc64)->addr);
((Elf_Fdesc *)*loc64)->addr);
} else {
/* if the symbol is not local to this
* module then val+addend is a pointer
......@@ -696,10 +689,10 @@ int module_finalize(const Elf_Ehdr *hdr,
Elf_Sym *newptr, *oldptr;
Elf_Shdr *symhdr = NULL;
#ifdef DEBUG
struct fdesc_entry *entry;
Elf_Fdesc *entry;
u32 *addr;
entry = (struct fdesc_entry *)me->init;
entry = (Elf_Fdesc *)me->init;
printk("FINALIZE, ->init FPTR is %p, GP %lx ADDR %lx\n", entry,
entry->gp, entry->addr);
addr = (u32 *)entry->addr;
......
......@@ -26,19 +26,6 @@ EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strpbrk);
#include <asm/hardware.h> /* struct parisc_device for asm/pci.h */
#include <linux/pci.h>
EXPORT_SYMBOL(hppa_dma_ops);
#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
EXPORT_SYMBOL(get_pci_node_path);
#endif
#include <linux/sched.h>
#include <asm/irq.h>
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(probe_irq_mask);
#include <asm/processor.h>
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(boot_cpu_data);
......@@ -46,10 +33,6 @@ EXPORT_SYMBOL(boot_cpu_data);
#include <linux/pm.h>
EXPORT_SYMBOL(pm_power_off);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(synchronize_irq);
#endif /* CONFIG_SMP */
#include <asm/atomic.h>
EXPORT_SYMBOL(__xchg8);
EXPORT_SYMBOL(__xchg32);
......@@ -74,14 +57,6 @@ extern int $global$;
EXPORT_SYMBOL($global$);
#endif
EXPORT_SYMBOL(register_parisc_driver);
EXPORT_SYMBOL(unregister_parisc_driver);
EXPORT_SYMBOL(print_pci_hwpath);
EXPORT_SYMBOL(print_pa_hwpath);
EXPORT_SYMBOL(pdc_iodc_read);
EXPORT_SYMBOL(pdc_tod_read);
EXPORT_SYMBOL(pdc_tod_set);
#include <asm/io.h>
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
......@@ -89,22 +64,6 @@ EXPORT_SYMBOL(__memcpy_toio);
EXPORT_SYMBOL(__memcpy_fromio);
EXPORT_SYMBOL(__memset_io);
#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
EXPORT_SYMBOL(inb);
EXPORT_SYMBOL(inw);
EXPORT_SYMBOL(inl);
EXPORT_SYMBOL(outb);
EXPORT_SYMBOL(outw);
EXPORT_SYMBOL(outl);
EXPORT_SYMBOL(insb);
EXPORT_SYMBOL(insw);
EXPORT_SYMBOL(insl);
EXPORT_SYMBOL(outsb);
EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(outsl);
#endif
#include <asm/cache.h>
EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
EXPORT_SYMBOL(flush_kernel_dcache_page);
......@@ -130,17 +89,6 @@ EXPORT_SYMBOL(__up);
EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(__down);
#include <linux/in6.h>
#include <asm/checksum.h>
EXPORT_SYMBOL(csum_partial_copy_nocheck);
EXPORT_SYMBOL(csum_partial_copy_from_user);
#include <asm/pdc.h>
EXPORT_SYMBOL(pdc_add_valid);
EXPORT_SYMBOL(pdc_lan_station_id);
EXPORT_SYMBOL(pdc_get_initiator);
EXPORT_SYMBOL(pdc_sti_call);
extern void $$divI(void);
extern void $$divU(void);
extern void $$remI(void);
......@@ -218,6 +166,3 @@ EXPORT_SYMBOL(__moddi3);
extern void $$dyncall(void);
EXPORT_SYMBOL($$dyncall);
#endif
#include <asm/pgtable.h>
EXPORT_SYMBOL(vmalloc_start);
......@@ -88,7 +88,8 @@ u##size in##type (int addr) \
EISA_IN(size); \
if (!parisc_pci_hba[b]) return (u##size) -1; \
return pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
}
} \
EXPORT_SYMBOL(in##type);
PCI_PORT_IN(b, 8)
PCI_PORT_IN(w, 16)
......@@ -102,7 +103,8 @@ void out##type (u##size d, int addr) \
EISA_OUT(size); \
if (!parisc_pci_hba[b]) return; \
pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
}
} \
EXPORT_SYMBOL(out##type);
PCI_PORT_OUT(b, 8)
PCI_PORT_OUT(w, 16)
......
......@@ -23,16 +23,6 @@
#include <asm/processor.h>
#include <asm/offsets.h>
/* These are used in entry.S, syscall_restore_rfi. We need to record the
* current stepping mode somewhere other than in PSW, because there is no
* concept of saving and restoring the users PSW over a syscall. We choose
* to use these two bits in task->ptrace. These bits must not clash with
* any PT_* defined in include/linux/sched.h, and must match with the bit
* tests in entry.S
*/
#define PT_SINGLESTEP 0x10000
#define PT_BLOCKSTEP 0x20000
/* PSW bits we allow the debugger to modify */
#define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB)
......
......@@ -43,6 +43,7 @@
#include <asm/led.h>
#include <asm/machdep.h> /* for pa7300lc_init() proto */
#include <asm/pdc_chassis.h>
#include <asm/io.h>
#define COMMAND_LINE_SIZE 1024
char saved_command_line[COMMAND_LINE_SIZE];
......@@ -208,27 +209,32 @@ static void __init parisc_proc_mkdir(void)
proc_runway_root = proc_mkdir("bus/runway", 0);
}
break;
default:
/* FIXME: this was added to prevent the compiler
* complaining about missing pcx, pcxs and pcxt
* I'm assuming they have neither gsc nor runway */
break;
}
}
static struct resource central_bus = {
.name = "Central Bus",
.start = (unsigned long)0xfffffffffff80000,
.end = (unsigned long)0xfffffffffffaffff,
.start = F_EXTEND(0xfff80000),
.end = F_EXTEND(0xfffaffff),
.flags = IORESOURCE_MEM,
};
static struct resource local_broadcast = {
.name = "Local Broadcast",
.start = (unsigned long)0xfffffffffffb0000,
.end = (unsigned long)0xfffffffffffdffff,
.start = F_EXTEND(0xfffb0000),
.end = F_EXTEND(0xfffdffff),
.flags = IORESOURCE_MEM,
};
static struct resource global_broadcast = {
.name = "Global Broadcast",
.start = (unsigned long)0xfffffffffffe0000,
.end = (unsigned long)0xffffffffffffffff,
.start = F_EXTEND(0xfffe0000),
.end = F_EXTEND(0xffffffff),
.flags = IORESOURCE_MEM,
};
......
......@@ -25,6 +25,8 @@
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/compat.h>
#include <linux/elf.h>
#include <linux/personality.h>
#include <asm/ucontext.h>
#include <asm/rt_sigframe.h>
#include <asm/uaccess.h>
......@@ -41,8 +43,11 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* Use this to get at 32-bit user passed pointers.
* See sys_sparc32.c for description about these. */
/* gcc will complain if a pointer is cast to an integer of different
* size. If you really need to do this (and we do for an ELF32 user
* application in an ELF64 kernel) then you have to do a cast to an
* integer of the same size first. The A() macro accomplishes
* this. */
#define A(__x) ((unsigned long)(__x))
int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
......@@ -166,11 +171,17 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
struct rt_sigframe *frame;
struct siginfo si;
sigset_t set;
unsigned long usp = regs->gr[30];
unsigned long usp = (regs->gr[30] & ~(0x01UL));
unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
#ifdef __LP64__
if(personality(current->personality) == PER_LINUX32)
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
#endif
/* Unwind the user stack to get the rt_sigframe structure. */
frame = (struct rt_sigframe *)
(usp - PARISC_RT_SIGFRAME_SIZE);
(usp - sigframe_size);
DBG(("in sys_rt_sigreturn, frame is %p\n", frame));
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
......@@ -271,11 +282,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs, int in_syscall)
{
struct rt_sigframe *frame;
unsigned long rp, usp, haddr;
unsigned long rp, usp;
unsigned long haddr, sigframe_size;
struct siginfo si;
int err = 0;
usp = regs->gr[30];
usp = (regs->gr[30] & ~(0x01UL));
frame = get_sigframe(ka, usp, sizeof(*frame));
DBG(("setup_rt_frame 1: frame %p info %p\n", frame, info));
......@@ -308,64 +320,86 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
#endif
#undef CACHE_FLUSHING_IS_NOT_BROKEN
#ifdef CACHE_FLUSHING_IS_NOT_BROKEN
flush_user_dcache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[4]);
flush_user_icache_range((unsigned long) &frame->tramp[0],
(unsigned long) &frame->tramp[4]);
#else
/* It should *always* be cache line-aligned, but the compiler
sometimes screws up. */
asm volatile("fdc 0(%%sr3,%0)\n\t"
"fdc %1(%%sr3,%0)\n\t"
"sync\n\t"
"fic 0(%%sr3,%0)\n\t"
"fic %1(%%sr3,%0)\n\t"
"sync\n\t"
: : "r" (frame->tramp), "r" (L1_CACHE_BYTES));
#endif
rp = (unsigned long) frame->tramp;
if (err)
goto give_sigsegv;
/* Much more has to happen with signals than this -- but it'll at least */
/* provide a pointer to some places which definitely need a look. */
#define HACK u32
haddr = A(ka->sa.sa_handler);
/* The sa_handler may be a pointer to a function descriptor */
#ifdef __LP64__
if(personality(current->personality) == PER_LINUX32) {
#endif
if (haddr & PA_PLABEL_FDESC) {
Elf32_Fdesc fdesc;
Elf32_Fdesc *ufdesc = (Elf32_Fdesc *)A(haddr & ~3);
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
haddr = (HACK)A(ka->sa.sa_handler);
/* ARGH! Fucking brain damage. You don't want to know. */
if (haddr & 2) {
HACK *plabel;
HACK ltp;
if (err)
goto give_sigsegv;
plabel = (HACK *) (haddr & ~3);
err |= __get_user(haddr, plabel);
err |= __get_user(ltp, plabel + 1);
haddr = fdesc.addr;
regs->gr[19] = fdesc.gp;
}
#ifdef __LP64__
} else {
Elf64_Fdesc fdesc;
Elf64_Fdesc *ufdesc = (Elf64_Fdesc *)A(haddr & ~3);
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
if (err)
goto give_sigsegv;
regs->gr[19] = ltp;
haddr = fdesc.addr;
regs->gr[19] = fdesc.gp;
DBG(("64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
haddr, regs->gr[19], in_syscall));
}
#endif
/* The syscall return path will create IAOQ values from r31.
*/
if (in_syscall)
regs->gr[31] = (HACK) haddr;
else {
regs->gr[0] = USER_PSW;
regs->iaoq[0] = (HACK) haddr | 3;
sigframe_size = PARISC_RT_SIGFRAME_SIZE;
#ifdef __LP64__
if(personality(current->personality) == PER_LINUX32)
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
#endif
if (in_syscall) {
regs->gr[31] = haddr;
#ifdef __LP64__
if(personality(current->personality) == PER_LINUX)
sigframe_size |= 1;
#endif
} else {
unsigned long psw = USER_PSW;
#ifdef __LP64__
if(personality(current->personality) == PER_LINUX)
psw |= PSW_W;
#endif
regs->gr[0] = psw;
regs->iaoq[0] = haddr | 3;
regs->iaoq[1] = regs->iaoq[0] + 4;
}
regs->gr[2] = rp; /* userland return pointer */
regs->gr[26] = sig; /* signal number */
regs->gr[25] = (HACK)A(&frame->info); /* siginfo pointer */
regs->gr[24] = (HACK)A(&frame->uc); /* ucontext pointer */
regs->gr[25] = A(&frame->info); /* siginfo pointer */
regs->gr[24] = A(&frame->uc); /* ucontext pointer */
DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",
regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
regs->gr[30] + PARISC_RT_SIGFRAME_SIZE));
regs->gr[30], sigframe_size,
regs->gr[30] + sigframe_size));
/* Raise the user stack pointer to make a proper call frame. */
regs->gr[30] = ((HACK)A(frame) + PARISC_RT_SIGFRAME_SIZE);
regs->gr[30] = (A(frame) + sigframe_size);
DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
current->comm, current->pid, frame, regs->gr[30],
......
......@@ -65,7 +65,7 @@ static int get_offset(struct address_space *mapping)
*/
static int get_offset(struct address_space *mapping)
{
int offset = (int) mapping << (PAGE_SHIFT - 8);
int offset = (unsigned long) mapping << (PAGE_SHIFT - 8);
return offset & 0x3FF000;
}
#endif
......@@ -165,12 +165,13 @@ long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
return raddr;
}
/* Fucking broken ABI */
#ifdef CONFIG_PARISC64
extern asmlinkage long sys_truncate(const char *, unsigned long);
extern asmlinkage long sys_ftruncate(unsigned int, unsigned long);
extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
asmlinkage long parisc_truncate64(const char * path,
unsigned int high, unsigned int low)
{
......@@ -182,6 +183,21 @@ asmlinkage long parisc_ftruncate64(unsigned int fd,
{
return sys_ftruncate(fd, (long)high << 32 | low);
}
/* stubs for the benefit of the syscall_table since truncate64 and truncate
* are identical on LP64 */
asmlinkage long sys_truncate64(const char * path, unsigned long length)
{
return sys_truncate(path, length);
}
asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
{
return sys_ftruncate(fd, length);
}
asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
{
return sys_fcntl(fd, cmd, arg);
}
#else
extern asmlinkage long sys_truncate64(const char *, loff_t);
......
......@@ -69,9 +69,14 @@ linux_gateway_entry:
* exit from the syscall, and also use that value to know
* whether to do narrow or wide syscalls. -PB
*/
ssm PSW_SM_W, %r0
ssm PSW_SM_W, %r1
extrd,u %r1,PSW_W_BIT,1,%r1
/* sp must be aligned on 4, so deposit the W bit setting into
* the bottom of sp temporarily */
or,ev %r1,%r30,%r30
b,n 1f
/* The top halves of argument registers must be cleared on syscall
* entry.
* entry from narrow executable.
*/
depdi 0, 31, 32, %r26
depdi 0, 31, 32, %r25
......@@ -79,11 +84,13 @@ linux_gateway_entry:
depdi 0, 31, 32, %r23
depdi 0, 31, 32, %r22
depdi 0, 31, 32, %r21
1:
#endif
mfctl %cr30,%r1
xor %r1,%r30,%r30 /* ye olde xor trick */
xor %r1,%r30,%r1
xor %r1,%r30,%r30
ldo THREAD_SZ_ALGN+FRAME_SIZE(%r30),%r30 /* set up kernel stack */
/* N.B.: It is critical that we don't set sr7 to 0 until r30
......@@ -104,9 +111,19 @@ linux_gateway_entry:
PSW value is stored. This is needed for gdb and sys_ptrace. */
STREG %r0, TASK_PT_PSW(%r1)
STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */
STREG %r19, TASK_PT_GR19(%r1)
LDREGM -FRAME_SIZE(%r30), %r2 /* get users sp back */
#ifdef __LP64__
extrd,u %r2,63,1,%r19 /* W hidden in bottom bit */
#if 0
xor %r19,%r2,%r2 /* clear bottom bit */
depd,z %r19,1,1,%r19
std %r19,TASK_PT_PSW(%r1)
#endif
#endif
STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
STREG %r19, TASK_PT_GR19(%r1)
STREG %r20, TASK_PT_GR20(%r1)
STREG %r21, TASK_PT_GR21(%r1)
STREG %r22, TASK_PT_GR22(%r1)
......@@ -130,6 +147,7 @@ linux_gateway_entry:
#ifdef __LP64__
ldo -16(%r30),%r29 /* Reference param save area */
copy %r19,%r2 /* W bit back to r2 */
#else
/* no need to save these on stack in wide mode because the first 8
* args are passed in registers */
......@@ -144,9 +162,17 @@ linux_gateway_entry:
/* Note! We cannot use the syscall table that is mapped
nearby since the gateway page is mapped execute-only. */
#ifdef __LP64__
ldil L%sys_call_table, %r1
or,= %r2,%r2,%r2
addil L%(sys_call_table64-sys_call_table), %r1
ldo R%sys_call_table(%r1), %r19
or,= %r2,%r2,%r2
ldo R%sys_call_table64(%r1), %r19
#else
ldil L%sys_call_table, %r1
ldo R%sys_call_table(%r1), %r19
#endif
comiclr,>>= __NR_Linux_syscalls, %r20, %r0
b,n .Lsyscall_nosys
......@@ -317,304 +343,21 @@ tracesys_sigexit:
ldil L%syscall_exit_rfi,%r1
be,n R%syscall_exit_rfi(%sr7,%r1)
#ifdef __LP64__
/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
* narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
* implementation is required on wide palinux. Use ENTRY_COMP where
* the compatability layer has a useful 32-bit implementation.
*/
#define ENTRY_SAME(_name_) .dword sys_##_name_
#define ENTRY_DIFF(_name_) .dword sys32_##_name_
#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
#define ENTRY_OURS(_name_) .dword parisc_##_name_
#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
#else
#define ENTRY_SAME(_name_) .word sys_##_name_
#define ENTRY_DIFF(_name_) .word sys_##_name_
#define ENTRY_UHOH(_name_) .word sys_##_name_
#define ENTRY_OURS(_name_) .word parisc_##_name_
#define ENTRY_COMP(_name_) .word sys_##_name_
#endif
.align 8
.align 4096
.export sys_call_table
.Lsys_call_table:
sys_call_table:
ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
ENTRY_SAME(exit)
ENTRY_SAME(fork_wrapper)
ENTRY_SAME(read)
ENTRY_SAME(write)
ENTRY_SAME(open) /* 5 */
ENTRY_SAME(close)
ENTRY_SAME(waitpid)
ENTRY_SAME(creat)
ENTRY_SAME(link)
ENTRY_SAME(unlink) /* 10 */
ENTRY_DIFF(execve_wrapper)
ENTRY_SAME(chdir)
/* See comments in kernel/time.c!!! Maybe we don't need this? */
ENTRY_DIFF(time)
ENTRY_SAME(mknod)
ENTRY_SAME(chmod) /* 15 */
ENTRY_SAME(lchown)
ENTRY_SAME(socket)
/* struct stat is MAYBE identical wide and narrow ?? */
ENTRY_COMP(newstat)
ENTRY_DIFF(lseek)
ENTRY_SAME(getpid) /* 20 */
/* the 'void * data' parameter may need re-packing in wide */
ENTRY_DIFF(mount)
/* concerned about struct sockaddr in wide/narrow */
/* ---> I think sockaddr is OK unless the compiler packs the struct */
/* differently to align the char array */
ENTRY_SAME(bind)
ENTRY_SAME(setuid)
ENTRY_SAME(getuid)
ENTRY_SAME(stime) /* 25 */
ENTRY_SAME(ptrace)
ENTRY_SAME(alarm)
/* see stat comment */
ENTRY_COMP(newfstat)
ENTRY_SAME(pause)
/* struct utimbuf uses time_t which might vary */
ENTRY_COMP(utime) /* 30 */
/* struct sockaddr... */
ENTRY_SAME(connect)
ENTRY_SAME(listen)
ENTRY_SAME(access)
ENTRY_SAME(nice)
/* struct sockaddr... */
ENTRY_SAME(accept) /* 35 */
ENTRY_SAME(sync)
ENTRY_SAME(kill)
ENTRY_SAME(rename)
ENTRY_SAME(mkdir)
ENTRY_SAME(rmdir) /* 40 */
ENTRY_SAME(dup)
ENTRY_SAME(pipe)
ENTRY_COMP(times)
/* struct sockaddr... */
ENTRY_SAME(getsockname)
/* it seems possible brk() could return a >4G pointer... */
ENTRY_SAME(brk) /* 45 */
ENTRY_SAME(setgid)
ENTRY_SAME(getgid)
ENTRY_SAME(signal)
ENTRY_SAME(geteuid)
ENTRY_SAME(getegid) /* 50 */
ENTRY_SAME(acct)
ENTRY_SAME(umount)
/* struct sockaddr... */
ENTRY_SAME(getpeername)
ENTRY_COMP(ioctl)
ENTRY_COMP(fcntl) /* 55 */
ENTRY_SAME(socketpair)
ENTRY_SAME(setpgid)
ENTRY_SAME(send)
ENTRY_SAME(newuname)
ENTRY_SAME(umask) /* 60 */
ENTRY_SAME(chroot)
ENTRY_SAME(ustat)
ENTRY_SAME(dup2)
ENTRY_SAME(getppid)
ENTRY_SAME(getpgrp) /* 65 */
ENTRY_SAME(setsid)
ENTRY_SAME(pivot_root)
/* I don't like this */
ENTRY_UHOH(sgetmask)
ENTRY_UHOH(ssetmask)
ENTRY_SAME(setreuid) /* 70 */
ENTRY_SAME(setregid)
ENTRY_SAME(mincore)
ENTRY_COMP(sigpending)
ENTRY_SAME(sethostname)
/* Following 3 have linux-common-code structs containing longs -( */
ENTRY_COMP(setrlimit) /* 75 */
ENTRY_COMP(getrlimit)
ENTRY_COMP(getrusage)
/* struct timeval and timezone are maybe?? consistent wide and narrow */
ENTRY_DIFF(gettimeofday)
ENTRY_DIFF(settimeofday)
ENTRY_SAME(getgroups) /* 80 */
ENTRY_SAME(setgroups)
/* struct socketaddr... */
ENTRY_SAME(sendto)
ENTRY_SAME(symlink)
/* see stat comment */
ENTRY_COMP(newlstat)
ENTRY_SAME(readlink) /* 85 */
ENTRY_SAME(ni_syscall) /* was uselib */
ENTRY_SAME(swapon)
ENTRY_SAME(reboot)
ENTRY_SAME(mmap2)
ENTRY_SAME(mmap) /* 90 */
ENTRY_SAME(munmap)
ENTRY_SAME(truncate)
ENTRY_SAME(ftruncate)
ENTRY_SAME(fchmod)
ENTRY_SAME(fchown) /* 95 */
ENTRY_SAME(getpriority)
ENTRY_SAME(setpriority)
ENTRY_SAME(recv)
ENTRY_COMP(statfs)
ENTRY_COMP(fstatfs) /* 100 */
ENTRY_SAME(stat64)
ENTRY_SAME(ni_syscall) /* was socketcall */
ENTRY_SAME(syslog)
/* even though manpage says struct timeval contains longs, ours has
* time_t and suseconds_t -- both of which are safe wide/narrow */
ENTRY_COMP(setitimer)
ENTRY_COMP(getitimer) /* 105 */
ENTRY_SAME(capget)
ENTRY_SAME(capset)
ENTRY_OURS(pread64)
ENTRY_OURS(pwrite64)
ENTRY_SAME(getcwd) /* 110 */
ENTRY_SAME(vhangup)
ENTRY_SAME(fstat64)
ENTRY_SAME(vfork_wrapper)
/* struct rusage contains longs... */
ENTRY_COMP(wait4)
ENTRY_SAME(swapoff) /* 115 */
ENTRY_DIFF(sysinfo)
ENTRY_SAME(shutdown)
ENTRY_SAME(fsync)
ENTRY_SAME(madvise)
ENTRY_SAME(clone_wrapper) /* 120 */
ENTRY_SAME(setdomainname)
ENTRY_DIFF(sendfile)
/* struct sockaddr... */
ENTRY_SAME(recvfrom)
/* struct timex contains longs */
ENTRY_DIFF(adjtimex)
ENTRY_SAME(mprotect) /* 125 */
/* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
ENTRY_COMP(sigprocmask)
ENTRY_SAME(ni_syscall) /* create_module */
ENTRY_SAME(init_module)
ENTRY_SAME(delete_module)
ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
/* time_t inside struct dqblk */
ENTRY_SAME(quotactl)
ENTRY_SAME(getpgid)
ENTRY_SAME(fchdir)
ENTRY_SAME(bdflush)
ENTRY_SAME(sysfs) /* 135 */
ENTRY_SAME(personality)
ENTRY_SAME(ni_syscall) /* for afs_syscall */
ENTRY_SAME(setfsuid)
ENTRY_SAME(setfsgid)
/* I think this might work */
ENTRY_SAME(llseek) /* 140 */
/* struct linux_dirent has longs, like 'unsigned long d_ino' which
* almost definitely should be 'ino_t d_ino' but it's too late now */
ENTRY_DIFF(getdents)
/* it is POSSIBLE that select will be OK because even though fd_set
* contains longs, the macros and sizes are clever. */
ENTRY_DIFF(select)
ENTRY_SAME(flock)
ENTRY_SAME(msync)
/* struct iovec contains pointers */
ENTRY_DIFF(readv) /* 145 */
ENTRY_DIFF(writev)
ENTRY_SAME(getsid)
ENTRY_SAME(fdatasync)
/* struct __sysctl_args is a mess */
ENTRY_DIFF(sysctl)
ENTRY_SAME(mlock) /* 150 */
ENTRY_SAME(munlock)
ENTRY_SAME(mlockall)
ENTRY_SAME(munlockall)
/* struct sched_param is ok for now */
ENTRY_SAME(sched_setparam)
ENTRY_SAME(sched_getparam) /* 155 */
ENTRY_SAME(sched_setscheduler)
ENTRY_SAME(sched_getscheduler)
ENTRY_SAME(sched_yield)
ENTRY_SAME(sched_get_priority_max)
ENTRY_SAME(sched_get_priority_min) /* 160 */
/* These 2 would've worked if someone had defined struct timespec
* carefully, like timeval for example (which is about the same).
* Unfortunately it contains a long :-( */
ENTRY_DIFF(sched_rr_get_interval)
ENTRY_COMP(nanosleep)
ENTRY_SAME(mremap)
ENTRY_SAME(setresuid)
ENTRY_SAME(getresuid) /* 165 */
ENTRY_DIFF(sigaltstack_wrapper)
ENTRY_SAME(ni_syscall) /* query_module */
ENTRY_SAME(poll)
/* structs contain pointers and an in_addr... */
ENTRY_DIFF(nfsservctl)
ENTRY_SAME(setresgid) /* 170 */
ENTRY_SAME(getresgid)
ENTRY_SAME(prctl)
/* signals need a careful review */
ENTRY_SAME(rt_sigreturn_wrapper)
ENTRY_DIFF(rt_sigaction)
ENTRY_DIFF(rt_sigprocmask) /* 175 */
ENTRY_DIFF(rt_sigpending)
ENTRY_UHOH(rt_sigtimedwait)
/* even though the struct siginfo_t is different, it appears like
* all the paths use values which should be same wide and narrow.
* Also the struct is padded to 128 bytes which means we don't have
* to worry about faulting trying to copy in a larger 64-bit
* struct from a 32-bit user-space app.
*/
ENTRY_SAME(rt_sigqueueinfo)
ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
ENTRY_SAME(chown) /* 180 */
/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
ENTRY_COMP(setsockopt)
ENTRY_SAME(getsockopt)
ENTRY_COMP(sendmsg)
ENTRY_COMP(recvmsg)
ENTRY_SAME(semop) /* 185 */
ENTRY_SAME(semget)
ENTRY_DIFF(semctl_broken)
ENTRY_DIFF(msgsnd)
ENTRY_DIFF(msgrcv)
ENTRY_SAME(msgget) /* 190 */
ENTRY_SAME(msgctl_broken)
ENTRY_SAME(shmat_wrapper)
ENTRY_SAME(shmdt)
ENTRY_SAME(shmget)
ENTRY_SAME(shmctl_broken) /* 195 */
ENTRY_SAME(ni_syscall) /* streams1 */
ENTRY_SAME(ni_syscall) /* streams2 */
ENTRY_SAME(lstat64)
ENTRY_OURS(truncate64)
ENTRY_OURS(ftruncate64) /* 200 */
ENTRY_SAME(getdents64)
ENTRY_COMP(fcntl64)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall) /* 205 */
ENTRY_SAME(gettid)
ENTRY_OURS(readahead)
ENTRY_SAME(ni_syscall) /* tkill */
ENTRY_SAME(sendfile64)
ENTRY_COMP(futex) /* 210 */
ENTRY_COMP(sched_setaffinity)
ENTRY_COMP(sched_getaffinity)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(io_setup) /* 215 */
ENTRY_SAME(io_destroy)
ENTRY_SAME(io_getevents)
ENTRY_SAME(io_submit)
ENTRY_SAME(io_cancel)
ENTRY_SAME(alloc_hugepages) /* 220 */
ENTRY_SAME(free_hugepages)
ENTRY_SAME(exit_group)
ENTRY_DIFF(lookup_dcookie)
ENTRY_SAME(epoll_create)
ENTRY_SAME(epoll_ctl) /* 225 */
ENTRY_SAME(epoll_wait)
ENTRY_SAME(remap_file_pages)
#include "syscall_table.S"
.end
#ifdef __LP64__
.align 4096
.export sys_call_table64
.Lsys_call_table64:
sys_call_table64:
#define SYSCALL_TABLE_64BIT
#include "syscall_table.S"
#endif
/* Make sure nothing else is placed on this page */
......
#undef ENTRY_SAME
#undef ENTRY_DIFF
#undef ENTRY_UHOH
#undef ENTRY_COMP
#undef ENTRY_OURS
#if defined(__LP64__) && !defined(SYSCALL_TABLE_64BIT)
/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
* narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
* implementation is required on wide palinux. Use ENTRY_COMP where
* the compatability layer has a useful 32-bit implementation.
*/
#define ENTRY_SAME(_name_) .dword sys_##_name_
#define ENTRY_DIFF(_name_) .dword sys32_##_name_
#define ENTRY_UHOH(_name_) .dword sys32_##unimplemented
#define ENTRY_OURS(_name_) .dword parisc_##_name_
#define ENTRY_COMP(_name_) .dword compat_sys_##_name_
#elif defined(__LP64__) && defined(SYSCALL_TABLE_64BIT)
#define ENTRY_SAME(_name_) .dword sys_##_name_
#define ENTRY_DIFF(_name_) .dword sys_##_name_
#define ENTRY_UHOH(_name_) .dword sys_##_name_
#define ENTRY_OURS(_name_) .dword sys_##_name_
#define ENTRY_COMP(_name_) .dword sys_##_name_
#else
#define ENTRY_SAME(_name_) .word sys_##_name_
#define ENTRY_DIFF(_name_) .word sys_##_name_
#define ENTRY_UHOH(_name_) .word sys_##_name_
#define ENTRY_OURS(_name_) .word parisc_##_name_
#define ENTRY_COMP(_name_) .word sys_##_name_
#endif
ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/
ENTRY_SAME(exit)
ENTRY_SAME(fork_wrapper)
ENTRY_SAME(read)
ENTRY_SAME(write)
ENTRY_SAME(open) /* 5 */
ENTRY_SAME(close)
ENTRY_SAME(waitpid)
ENTRY_SAME(creat)
ENTRY_SAME(link)
ENTRY_SAME(unlink) /* 10 */
ENTRY_DIFF(execve_wrapper)
ENTRY_SAME(chdir)
/* See comments in kernel/time.c!!! Maybe we don't need this? */
ENTRY_DIFF(time)
ENTRY_SAME(mknod)
ENTRY_SAME(chmod) /* 15 */
ENTRY_SAME(lchown)
ENTRY_SAME(socket)
/* struct stat is MAYBE identical wide and narrow ?? */
ENTRY_COMP(newstat)
ENTRY_DIFF(lseek)
ENTRY_SAME(getpid) /* 20 */
/* the 'void * data' parameter may need re-packing in wide */
ENTRY_DIFF(mount)
/* concerned about struct sockaddr in wide/narrow */
/* ---> I think sockaddr is OK unless the compiler packs the struct */
/* differently to align the char array */
ENTRY_SAME(bind)
ENTRY_SAME(setuid)
ENTRY_SAME(getuid)
ENTRY_SAME(stime) /* 25 */
ENTRY_SAME(ptrace)
ENTRY_SAME(alarm)
/* see stat comment */
ENTRY_COMP(newfstat)
ENTRY_SAME(pause)
/* struct utimbuf uses time_t which might vary */
ENTRY_COMP(utime) /* 30 */
/* struct sockaddr... */
ENTRY_SAME(connect)
ENTRY_SAME(listen)
ENTRY_SAME(access)
ENTRY_SAME(nice)
/* struct sockaddr... */
ENTRY_SAME(accept) /* 35 */
ENTRY_SAME(sync)
ENTRY_SAME(kill)
ENTRY_SAME(rename)
ENTRY_SAME(mkdir)
ENTRY_SAME(rmdir) /* 40 */
ENTRY_SAME(dup)
ENTRY_SAME(pipe)
ENTRY_COMP(times)
/* struct sockaddr... */
ENTRY_SAME(getsockname)
/* it seems possible brk() could return a >4G pointer... */
ENTRY_SAME(brk) /* 45 */
ENTRY_SAME(setgid)
ENTRY_SAME(getgid)
ENTRY_SAME(signal)
ENTRY_SAME(geteuid)
ENTRY_SAME(getegid) /* 50 */
ENTRY_SAME(acct)
ENTRY_SAME(umount)
/* struct sockaddr... */
ENTRY_SAME(getpeername)
ENTRY_COMP(ioctl)
ENTRY_COMP(fcntl) /* 55 */
ENTRY_SAME(socketpair)
ENTRY_SAME(setpgid)
ENTRY_SAME(send)
ENTRY_SAME(newuname)
ENTRY_SAME(umask) /* 60 */
ENTRY_SAME(chroot)
ENTRY_SAME(ustat)
ENTRY_SAME(dup2)
ENTRY_SAME(getppid)
ENTRY_SAME(getpgrp) /* 65 */
ENTRY_SAME(setsid)
ENTRY_SAME(pivot_root)
/* I don't like this */
ENTRY_UHOH(sgetmask)
ENTRY_UHOH(ssetmask)
ENTRY_SAME(setreuid) /* 70 */
ENTRY_SAME(setregid)
ENTRY_SAME(mincore)
ENTRY_COMP(sigpending)
ENTRY_SAME(sethostname)
/* Following 3 have linux-common-code structs containing longs -( */
ENTRY_COMP(setrlimit) /* 75 */
ENTRY_COMP(getrlimit)
ENTRY_COMP(getrusage)
/* struct timeval and timezone are maybe?? consistent wide and narrow */
ENTRY_DIFF(gettimeofday)
ENTRY_DIFF(settimeofday)
ENTRY_SAME(getgroups) /* 80 */
ENTRY_SAME(setgroups)
/* struct socketaddr... */
ENTRY_SAME(sendto)
ENTRY_SAME(symlink)
/* see stat comment */
ENTRY_COMP(newlstat)
ENTRY_SAME(readlink) /* 85 */
ENTRY_SAME(ni_syscall) /* was uselib */
ENTRY_SAME(swapon)
ENTRY_SAME(reboot)
ENTRY_SAME(mmap2)
ENTRY_SAME(mmap) /* 90 */
ENTRY_SAME(munmap)
ENTRY_SAME(truncate)
ENTRY_SAME(ftruncate)
ENTRY_SAME(fchmod)
ENTRY_SAME(fchown) /* 95 */
ENTRY_SAME(getpriority)
ENTRY_SAME(setpriority)
ENTRY_SAME(recv)
ENTRY_COMP(statfs)
ENTRY_COMP(fstatfs) /* 100 */
ENTRY_SAME(stat64)
ENTRY_SAME(ni_syscall) /* was socketcall */
ENTRY_SAME(syslog)
/* even though manpage says struct timeval contains longs, ours has
* time_t and suseconds_t -- both of which are safe wide/narrow */
ENTRY_COMP(setitimer)
ENTRY_COMP(getitimer) /* 105 */
ENTRY_SAME(capget)
ENTRY_SAME(capset)
ENTRY_OURS(pread64)
ENTRY_OURS(pwrite64)
ENTRY_SAME(getcwd) /* 110 */
ENTRY_SAME(vhangup)
ENTRY_SAME(fstat64)
ENTRY_SAME(vfork_wrapper)
/* struct rusage contains longs... */
ENTRY_COMP(wait4)
ENTRY_SAME(swapoff) /* 115 */
ENTRY_DIFF(sysinfo)
ENTRY_SAME(shutdown)
ENTRY_SAME(fsync)
ENTRY_SAME(madvise)
ENTRY_SAME(clone_wrapper) /* 120 */
ENTRY_SAME(setdomainname)
ENTRY_DIFF(sendfile)
/* struct sockaddr... */
ENTRY_SAME(recvfrom)
/* struct timex contains longs */
ENTRY_DIFF(adjtimex)
ENTRY_SAME(mprotect) /* 125 */
/* old_sigset_t forced to 32 bits. Beware glibc sigset_t */
ENTRY_COMP(sigprocmask)
ENTRY_SAME(ni_syscall) /* create_module */
ENTRY_SAME(init_module)
ENTRY_SAME(delete_module)
ENTRY_SAME(ni_syscall) /* 130: get_kernel_syms */
/* time_t inside struct dqblk */
ENTRY_SAME(quotactl)
ENTRY_SAME(getpgid)
ENTRY_SAME(fchdir)
ENTRY_SAME(bdflush)
ENTRY_SAME(sysfs) /* 135 */
ENTRY_SAME(personality)
ENTRY_SAME(ni_syscall) /* for afs_syscall */
ENTRY_SAME(setfsuid)
ENTRY_SAME(setfsgid)
/* I think this might work */
ENTRY_SAME(llseek) /* 140 */
/* struct linux_dirent has longs, like 'unsigned long d_ino' which
* almost definitely should be 'ino_t d_ino' but it's too late now */
ENTRY_DIFF(getdents)
/* it is POSSIBLE that select will be OK because even though fd_set
* contains longs, the macros and sizes are clever. */
ENTRY_DIFF(select)
ENTRY_SAME(flock)
ENTRY_SAME(msync)
/* struct iovec contains pointers */
ENTRY_DIFF(readv) /* 145 */
ENTRY_DIFF(writev)
ENTRY_SAME(getsid)
ENTRY_SAME(fdatasync)
/* struct __sysctl_args is a mess */
ENTRY_DIFF(sysctl)
ENTRY_SAME(mlock) /* 150 */
ENTRY_SAME(munlock)
ENTRY_SAME(mlockall)
ENTRY_SAME(munlockall)
/* struct sched_param is ok for now */
ENTRY_SAME(sched_setparam)
ENTRY_SAME(sched_getparam) /* 155 */
ENTRY_SAME(sched_setscheduler)
ENTRY_SAME(sched_getscheduler)
ENTRY_SAME(sched_yield)
ENTRY_SAME(sched_get_priority_max)
ENTRY_SAME(sched_get_priority_min) /* 160 */
/* These 2 would've worked if someone had defined struct timespec
* carefully, like timeval for example (which is about the same).
* Unfortunately it contains a long :-( */
ENTRY_DIFF(sched_rr_get_interval)
ENTRY_COMP(nanosleep)
ENTRY_SAME(mremap)
ENTRY_SAME(setresuid)
ENTRY_SAME(getresuid) /* 165 */
ENTRY_DIFF(sigaltstack_wrapper)
ENTRY_SAME(ni_syscall) /* query_module */
ENTRY_SAME(poll)
/* structs contain pointers and an in_addr... */
ENTRY_DIFF(nfsservctl)
ENTRY_SAME(setresgid) /* 170 */
ENTRY_SAME(getresgid)
ENTRY_SAME(prctl)
/* signals need a careful review */
ENTRY_SAME(rt_sigreturn_wrapper)
ENTRY_DIFF(rt_sigaction)
ENTRY_DIFF(rt_sigprocmask) /* 175 */
ENTRY_DIFF(rt_sigpending)
ENTRY_UHOH(rt_sigtimedwait)
/* even though the struct siginfo_t is different, it appears like
* all the paths use values which should be same wide and narrow.
* Also the struct is padded to 128 bytes which means we don't have
* to worry about faulting trying to copy in a larger 64-bit
* struct from a 32-bit user-space app.
*/
ENTRY_SAME(rt_sigqueueinfo)
ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
ENTRY_SAME(chown) /* 180 */
/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
ENTRY_COMP(setsockopt)
ENTRY_SAME(getsockopt)
ENTRY_COMP(sendmsg)
ENTRY_COMP(recvmsg)
ENTRY_SAME(semop) /* 185 */
ENTRY_SAME(semget)
ENTRY_DIFF(semctl_broken)
ENTRY_DIFF(msgsnd)
ENTRY_DIFF(msgrcv)
ENTRY_SAME(msgget) /* 190 */
ENTRY_SAME(msgctl_broken)
ENTRY_SAME(shmat_wrapper)
ENTRY_SAME(shmdt)
ENTRY_SAME(shmget)
ENTRY_SAME(shmctl_broken) /* 195 */
ENTRY_SAME(ni_syscall) /* streams1 */
ENTRY_SAME(ni_syscall) /* streams2 */
ENTRY_SAME(lstat64)
ENTRY_OURS(truncate64)
ENTRY_OURS(ftruncate64) /* 200 */
ENTRY_SAME(getdents64)
ENTRY_COMP(fcntl64)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall) /* 205 */
ENTRY_SAME(gettid)
ENTRY_OURS(readahead)
ENTRY_SAME(ni_syscall) /* tkill */
ENTRY_SAME(sendfile64)
ENTRY_COMP(futex) /* 210 */
ENTRY_COMP(sched_setaffinity)
ENTRY_COMP(sched_getaffinity)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(ni_syscall)
ENTRY_SAME(io_setup) /* 215 */
ENTRY_SAME(io_destroy)
ENTRY_SAME(io_getevents)
ENTRY_SAME(io_submit)
ENTRY_SAME(io_cancel)
ENTRY_SAME(alloc_hugepages) /* 220 */
ENTRY_SAME(free_hugepages)
ENTRY_SAME(exit_group)
ENTRY_DIFF(lookup_dcookie)
ENTRY_SAME(epoll_create)
ENTRY_SAME(epoll_ctl) /* 225 */
ENTRY_SAME(epoll_wait)
ENTRY_SAME(remap_file_pages)
......@@ -48,7 +48,9 @@ static inline void
parisc_do_profile(struct pt_regs *regs)
{
unsigned long pc = regs->iaoq[0];
#if 0
extern unsigned long prof_cpu_mask;
#endif
extern char _stext;
profile_hook(regs);
......@@ -60,6 +62,10 @@ parisc_do_profile(struct pt_regs *regs)
return;
#if 0
/* FIXME: when we have irq affinity to cpu, we need to
* only look at the cpus specified in this mask
*/
if (!((1 << smp_processor_id()) & prof_cpu_mask))
return;
#endif
......@@ -206,7 +212,6 @@ do_settimeofday (struct timespec *tv)
* done, and then undo it!
*/
nsec -= gettimeoffset() * 1000;
nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
......@@ -223,6 +228,16 @@ do_settimeofday (struct timespec *tv)
return 0;
}
/*
* XXX: We can do better than this.
* Returns nanoseconds
*/
unsigned long long sched_clock(void)
{
return (unsigned long long)jiffies * (1000000000 / HZ);
}
void __init time_init(void)
{
......
......@@ -678,12 +678,13 @@ void handle_interruption(int code, struct pt_regs *regs)
}
if (user_mode(regs)) {
if (fault_space != regs->sr[7]) {
if ((fault_space>>SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
#ifdef PRINT_USER_FAULTS
if (fault_space == 0)
printk(KERN_DEBUG "User Fault on Kernel Space ");
else
printk(KERN_DEBUG "User Fault (long pointer) ");
printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
code);
printk("pid=%d command='%s'\n", current->pid, current->comm);
show_regs(regs);
#endif
......
......@@ -369,8 +369,8 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
void handle_unaligned(struct pt_regs *regs)
{
unsigned long unaligned_count = 0;
unsigned long last_time = 0;
static unsigned long unaligned_count = 0;
static unsigned long last_time = 0;
unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
int modify = 0;
int ret = -1;
......@@ -380,7 +380,6 @@ void handle_unaligned(struct pt_regs *regs)
/* if the unaligned access is inside the kernel:
* if the access is caused by a syscall, then we fault the calling
* user process
* otherwise we halt the kernel
*/
if (!user_mode(regs))
{
......@@ -427,10 +426,10 @@ void handle_unaligned(struct pt_regs *regs)
show_regs(regs);
#endif
}
}
if (!unaligned_enabled)
goto force_sigbus;
if (!unaligned_enabled)
goto force_sigbus;
}
/* handle modification - OK, it's ugly, see the instruction manual */
switch (MAJOR_OP(regs->iir))
......
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