Commit 2dc3864f authored by David Mosberger's avatar David Mosberger

ia64: Sync up with 2.5.59.

	Add light-weight version of set_tid_address() system call.
parent 67d8f3d0
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
----------------------------------- -----------------------------------
Started: 13-Jan-2002 Started: 13-Jan-2002
Last update: 15-Jan-2002 Last update: 24-Jan-2002
David Mosberger-Tang David Mosberger-Tang
<davidm@hpl.hp.com> <davidm@hpl.hp.com>
...@@ -89,6 +89,7 @@ The entry and exit-state of an fsyscall handler is as follows: ...@@ -89,6 +89,7 @@ The entry and exit-state of an fsyscall handler is as follows:
** Machine state on entry to fsyscall handler: ** Machine state on entry to fsyscall handler:
- r10 = 0
- r11 = saved ar.pfs (a user-level value) - r11 = saved ar.pfs (a user-level value)
- r15 = system call number - r15 = system call number
- r16 = "current" task pointer (in normal kernel-mode, this is in r13) - r16 = "current" task pointer (in normal kernel-mode, this is in r13)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# License. See the file "COPYING" in the main directory of this archive # License. See the file "COPYING" in the main directory of this archive
# for more details. # for more details.
# #
# Copyright (C) 1998-2002 by David Mosberger-Tang <davidm@hpl.hp.com> # Copyright (C) 1998-2003 by David Mosberger-Tang <davidm@hpl.hp.com>
# #
NM := $(CROSS_COMPILE)nm -B NM := $(CROSS_COMPILE)nm -B
...@@ -48,30 +48,37 @@ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ ...@@ -48,30 +48,37 @@ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/ drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/ia64/boot $(1) boot := arch/ia64/boot
maketool =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/ia64/tools $(1) tools := arch/ia64/tools
.PHONY: boot compressed archclean archmrproper include/asm-ia64/offsets.h .PHONY: boot compressed archclean archmrproper include/asm-ia64/offsets.h
all compressed: vmlinux.gz all: vmlinux
compressed: vmlinux.gz
vmlinux.gz: vmlinux vmlinux.gz: vmlinux
$(call makeboot,vmlinux.gz) $(Q)$(MAKE) $(build)=$(boot) vmlinux.gz
check: vmlinux check: vmlinux
arch/ia64/scripts/unwcheck.sh vmlinux arch/ia64/scripts/unwcheck.sh vmlinux
archmrproper: archmrproper:
archclean: archclean:
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/ia64/boot $(Q)$(MAKE) $(clean)=$(boot)
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/ia64/tools $(Q)$(MAKE) $(clean)=$(tools)
CLEAN_FILES += include/asm-ia64/offsets.h vmlinux.gz bootloader CLEAN_FILES += include/asm-ia64/offsets.h vmlinux.gz bootloader
prepare: include/asm-ia64/offsets.h prepare: include/asm-ia64/offsets.h
boot: lib/lib.a vmlinux boot: lib/lib.a vmlinux
$(call makeboot,$@) $(Q)$(MAKE) $(build)=$(boot) $@
include/asm-ia64/offsets.h: include/asm include/linux/version.h include/config/MARKER include/asm-ia64/offsets.h: include/asm include/linux/version.h include/config/MARKER
$(call maketool,$@) $(Q)$(MAKE) $(build)=$(tools) $@
define archhelp
echo ' compressed - Build compressed kernel image'
echo ' boot - Build vmlinux and bootloader for Ski simulator'
endef
/* /*
* Misc. support for HP zx1 chipset support * Misc. support for HP zx1 chipset support
* *
* Copyright (C) 2002 Hewlett-Packard Co * Copyright (C) 2002-2003 Hewlett-Packard Co
* Copyright (C) 2002 Alex Williamson <alex_williamson@hp.com> * Alex Williamson <alex_williamson@hp.com>
* Copyright (C) 2002 Bjorn Helgaas <bjorn_helgaas@hp.com> * Bjorn Helgaas <bjorn_helgaas@hp.com>
*/ */
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/iosapic.h> #include <asm/iosapic.h>
extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, struct acpi_object_list *,
unsigned long *); unsigned long *);
#define PFX "hpzx1: " #define PFX "hpzx1: "
...@@ -190,31 +190,31 @@ hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned ...@@ -190,31 +190,31 @@ hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned
hpzx1_devices++; hpzx1_devices++;
} }
typedef struct { struct acpi_hp_vendor_long {
u8 guid_id; u8 guid_id;
u8 guid[16]; u8 guid[16];
u8 csr_base[8]; u8 csr_base[8];
u8 csr_length[8]; u8 csr_length[8];
} acpi_hp_vendor_long; };
#define HP_CCSR_LENGTH 0x21 #define HP_CCSR_LENGTH 0x21
#define HP_CCSR_TYPE 0x2 #define HP_CCSR_TYPE 0x2
#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ #define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \
0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
extern acpi_status acpi_get_crs(acpi_handle, acpi_buffer *); extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *);
extern acpi_resource *acpi_get_crs_next(acpi_buffer *, int *); extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *);
extern acpi_resource_data *acpi_get_crs_type(acpi_buffer *, int *, int); extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int);
extern void acpi_dispose_crs(acpi_buffer *); extern void acpi_dispose_crs(struct acpi_buffer *);
static acpi_status static acpi_status
hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
{ {
int i, offset = 0; int i, offset = 0;
acpi_status status; acpi_status status;
acpi_buffer buf; struct acpi_buffer buf;
acpi_resource_vendor *res; struct acpi_resource_vendor *res;
acpi_hp_vendor_long *hp_res; struct acpi_hp_vendor_long *hp_res;
efi_guid_t vendor_guid; efi_guid_t vendor_guid;
*csr_base = 0; *csr_base = 0;
...@@ -226,14 +226,14 @@ hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) ...@@ -226,14 +226,14 @@ hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
return status; return status;
} }
res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);
if (!res) { if (!res) {
printk(KERN_ERR PFX "Failed to find config space for device\n"); printk(KERN_ERR PFX "Failed to find config space for device\n");
acpi_dispose_crs(&buf); acpi_dispose_crs(&buf);
return AE_NOT_FOUND; return AE_NOT_FOUND;
} }
hp_res = (acpi_hp_vendor_long *)(res->reserved); hp_res = (struct acpi_hp_vendor_long *)(res->reserved);
if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {
printk(KERN_ERR PFX "Unknown Vendor data\n"); printk(KERN_ERR PFX "Unknown Vendor data\n");
...@@ -288,7 +288,7 @@ hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret) ...@@ -288,7 +288,7 @@ hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
{ {
u64 csr_base = 0, csr_length = 0; u64 csr_base = 0, csr_length = 0;
acpi_status status; acpi_status status;
NATIVE_UINT busnum; acpi_native_uint busnum;
char *name = context; char *name = context;
char fullname[32]; char fullname[32];
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 2000-2002 Hewlett-Packard Co * Copyright (C) 2000-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* *
* These routines maintain argument size conversion between 32bit and 64bit * These routines maintain argument size conversion between 32bit and 64bit
...@@ -2348,7 +2348,7 @@ shmctl32 (int first, int second, void *uptr) ...@@ -2348,7 +2348,7 @@ shmctl32 (int first, int second, void *uptr)
static long static long
semtimedop32(int semid, struct sembuf *tsems, int nsems, semtimedop32(int semid, struct sembuf *tsems, int nsems,
const struct timespec32 *timeout32) const struct compat_timespec *timeout32)
{ {
struct timespec t; struct timespec t;
if (get_user (t.tv_sec, &timeout32->tv_sec) || if (get_user (t.tv_sec, &timeout32->tv_sec) ||
...@@ -2371,7 +2371,7 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) ...@@ -2371,7 +2371,7 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL); return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL);
case SEMTIMEDOP: case SEMTIMEDOP:
return semtimedop32(first, (struct sembuf *)AA(ptr), second, return semtimedop32(first, (struct sembuf *)AA(ptr), second,
(const struct timespec32 *)AA(fifth)); (const struct compat_timespec *)AA(fifth));
case SEMGET: case SEMGET:
return sys_semget(first, second, third); return sys_semget(first, second, third);
case SEMCTL: case SEMCTL:
......
...@@ -128,7 +128,7 @@ acpi_get_sysname (void) ...@@ -128,7 +128,7 @@ acpi_get_sysname (void)
* with a list of acpi_resource structures. * with a list of acpi_resource structures.
*/ */
acpi_status acpi_status
acpi_get_crs (acpi_handle obj, acpi_buffer *buf) acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf)
{ {
acpi_status result; acpi_status result;
buf->length = 0; buf->length = 0;
...@@ -144,10 +144,10 @@ acpi_get_crs (acpi_handle obj, acpi_buffer *buf) ...@@ -144,10 +144,10 @@ acpi_get_crs (acpi_handle obj, acpi_buffer *buf)
return acpi_get_current_resources(obj, buf); return acpi_get_current_resources(obj, buf);
} }
acpi_resource * struct acpi_resource *
acpi_get_crs_next (acpi_buffer *buf, int *offset) acpi_get_crs_next (struct acpi_buffer *buf, int *offset)
{ {
acpi_resource *res; struct acpi_resource *res;
if (*offset >= buf->length) if (*offset >= buf->length)
return NULL; return NULL;
...@@ -157,11 +157,11 @@ acpi_get_crs_next (acpi_buffer *buf, int *offset) ...@@ -157,11 +157,11 @@ acpi_get_crs_next (acpi_buffer *buf, int *offset)
return res; return res;
} }
acpi_resource_data * union acpi_resource_data *
acpi_get_crs_type (acpi_buffer *buf, int *offset, int type) acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type)
{ {
for (;;) { for (;;) {
acpi_resource *res = acpi_get_crs_next(buf, offset); struct acpi_resource *res = acpi_get_crs_next(buf, offset);
if (!res) if (!res)
return NULL; return NULL;
if (res->id == type) if (res->id == type)
...@@ -170,7 +170,7 @@ acpi_get_crs_type (acpi_buffer *buf, int *offset, int type) ...@@ -170,7 +170,7 @@ acpi_get_crs_type (acpi_buffer *buf, int *offset, int type)
} }
void void
acpi_dispose_crs (acpi_buffer *buf) acpi_dispose_crs (struct acpi_buffer *buf)
{ {
kfree(buf->pointer); kfree(buf->pointer);
} }
...@@ -638,7 +638,7 @@ static int __init ...@@ -638,7 +638,7 @@ static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size) acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{ {
struct acpi_table_header *fadt_header; struct acpi_table_header *fadt_header;
fadt_descriptor_rev2 *fadt; struct fadt_descriptor_rev2 *fadt;
u32 sci_irq, gsi_base; u32 sci_irq, gsi_base;
char *iosapic_address; char *iosapic_address;
...@@ -649,7 +649,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size) ...@@ -649,7 +649,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (fadt_header->revision != 3) if (fadt_header->revision != 3)
return -ENODEV; /* Only deal with ACPI 2.0 FADT */ return -ENODEV; /* Only deal with ACPI 2.0 FADT */
fadt = (fadt_descriptor_rev2 *) fadt_header; fadt = (struct fadt_descriptor_rev2 *) fadt_header;
if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
acpi_kbd_controller_present = 0; acpi_kbd_controller_present = 0;
......
...@@ -10,6 +10,28 @@ ...@@ -10,6 +10,28 @@
#include <asm/offsets.h> #include <asm/offsets.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
/*
* See Documentation/ia64/fsys.txt for details on fsyscalls.
*
* On entry to an fsyscall handler:
* r10 = 0 (i.e., defaults to "successful syscall return")
* r11 = saved ar.pfs (a user-level value)
* r15 = system call number
* r16 = "current" task pointer (in normal kernel-mode, this is in r13)
* r32-r39 = system call arguments
* b6 = return address (a user-level value)
* ar.pfs = previous frame-state (a user-level value)
* PSR.be = cleared to zero (i.e., little-endian byte order is in effect)
* all other registers may contain values passed in from user-mode
*
* On return from an fsyscall handler:
* r11 = saved ar.pfs (as passed into the fsyscall handler)
* r15 = system call number (as passed into the fsyscall handler)
* r32-r39 = system call arguments (as passed into the fsyscall handler)
* b6 = return address (as passed into the fsyscall handler)
* ar.pfs = previous frame-state (as passed into the fsyscall handler)
*/
ENTRY(fsys_ni_syscall) ENTRY(fsys_ni_syscall)
mov r8=ENOSYS mov r8=ENOSYS
mov r10=-1 mov r10=-1
...@@ -32,6 +54,30 @@ ENTRY(fsys_getpid) ...@@ -32,6 +54,30 @@ ENTRY(fsys_getpid)
br.ret.sptk.many b6 br.ret.sptk.many b6
END(fsys_getpid) END(fsys_getpid)
ENTRY(fsys_set_tid_address)
add r9=TI_FLAGS+IA64_TASK_SIZE,r16
;;
ld4 r9=[r9]
tnat.z p6,p7=r32 // check argument register for being NaT
;;
and r9=TIF_ALLWORK_MASK,r9
add r8=IA64_TASK_PID_OFFSET,r16
add r18=IA64_TASK_CLEAR_CHILD_TID_OFFSET,r16
;;
ld4 r8=[r8]
cmp.ne p8,p0=0,r9
mov r17=-1
;;
(p6) st8 [r18]=r32
(p7) st8 [r18]=r17
(p8) br.spnt.many fsys_fallback_syscall
;;
mov r17=0 // don't leak kernel bits...
mov r18=0 // don't leak kernel bits...
MCKINLEY_E9_WORKAROUND
br.ret.sptk.many b6
END(fsys_set_tid_address)
.rodata .rodata
.align 8 .align 8
.globl fsyscall_table .globl fsyscall_table
...@@ -245,9 +291,9 @@ fsyscall_table: ...@@ -245,9 +291,9 @@ fsyscall_table:
data8 fsys_fallback_syscall // futex // 1230 data8 fsys_fallback_syscall // futex // 1230
data8 fsys_fallback_syscall // sched_setaffinity data8 fsys_fallback_syscall // sched_setaffinity
data8 fsys_fallback_syscall // sched_getaffinity data8 fsys_fallback_syscall // sched_getaffinity
data8 fsys_fallback_syscall // set_tid_address data8 fsys_set_tid_address // set_tid_address
data8 fsys_fallback_syscall // alloc_hugepages data8 fsys_fallback_syscall // unused
data8 fsys_fallback_syscall // free_hugepages // 1235 data8 fsys_fallback_syscall // unused // 1235
data8 fsys_fallback_syscall // exit_group data8 fsys_fallback_syscall // exit_group
data8 fsys_fallback_syscall // lookup_dcookie data8 fsys_fallback_syscall // lookup_dcookie
data8 fsys_fallback_syscall // io_setup data8 fsys_fallback_syscall // io_setup
......
...@@ -144,12 +144,14 @@ show_regs (struct pt_regs *regs) ...@@ -144,12 +144,14 @@ show_regs (struct pt_regs *regs)
void void
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{ {
#ifdef CONFIG_FSYS
if (fsys_mode(current, &scr->pt)) { if (fsys_mode(current, &scr->pt)) {
/* defer signal-handling etc. until we return to privilege-level 0. */ /* defer signal-handling etc. until we return to privilege-level 0. */
if (!ia64_psr(&scr->pt)->lp) if (!ia64_psr(&scr->pt)->lp)
ia64_psr(&scr->pt)->lp = 1; ia64_psr(&scr->pt)->lp = 1;
return; return;
} }
#endif
#ifdef CONFIG_PERFMON #ifdef CONFIG_PERFMON
if (current->thread.pfm_ovfl_block_reset) if (current->thread.pfm_ovfl_block_reset)
......
...@@ -524,6 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -524,6 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case 29: /* Debug */ case 29: /* Debug */
case 35: /* Taken Branch Trap */ case 35: /* Taken Branch Trap */
case 36: /* Single Step Trap */ case 36: /* Single Step Trap */
#ifdef CONFIG_FSYS
if (fsys_mode(current, regs)) { if (fsys_mode(current, regs)) {
extern char syscall_via_break[], __start_gate_section[]; extern char syscall_via_break[], __start_gate_section[];
/* /*
...@@ -541,6 +542,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, ...@@ -541,6 +542,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
ia64_psr(regs)->cpl = 3; ia64_psr(regs)->cpl = 3;
return; return;
} }
#endif
switch (vector) { switch (vector) {
case 29: case 29:
siginfo.si_code = TRAP_HWBKPT; siginfo.si_code = TRAP_HWBKPT;
......
...@@ -1294,12 +1294,12 @@ within_logging_rate_limit (void) ...@@ -1294,12 +1294,12 @@ within_logging_rate_limit (void)
void void
ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
{ {
struct exception_fixup fix = { 0 };
struct ia64_psr *ipsr = ia64_psr(regs); struct ia64_psr *ipsr = ia64_psr(regs);
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
unsigned long bundle[2]; unsigned long bundle[2];
unsigned long opcode; unsigned long opcode;
struct siginfo si; struct siginfo si;
const struct exception_table_entry *eh = NULL;
union { union {
unsigned long l; unsigned long l;
load_store_t insn; load_store_t insn;
...@@ -1317,10 +1317,9 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) ...@@ -1317,10 +1317,9 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
* user-level unaligned accesses. Otherwise, a clever program could trick this * user-level unaligned accesses. Otherwise, a clever program could trick this
* handler into reading an arbitrary kernel addresses... * handler into reading an arbitrary kernel addresses...
*/ */
if (!user_mode(regs)) { if (!user_mode(regs))
fix = SEARCH_EXCEPTION_TABLE(regs); eh = SEARCH_EXCEPTION_TABLE(regs);
} if (user_mode(regs) || eh) {
if (user_mode(regs) || fix.cont) {
if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0)
goto force_sigbus; goto force_sigbus;
...@@ -1486,8 +1485,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) ...@@ -1486,8 +1485,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
failure: failure:
/* something went wrong... */ /* something went wrong... */
if (!user_mode(regs)) { if (!user_mode(regs)) {
if (fix.cont) { if (eh) {
handle_exception(regs, fix); handle_exception(regs, eh);
goto done; goto done;
} }
die_if_kernel("error during unaligned kernel access\n", regs, ret); die_if_kernel("error during unaligned kernel access\n", regs, ret);
......
...@@ -10,22 +10,21 @@ ...@@ -10,22 +10,21 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/module.h> #include <asm/module.h>
extern const struct exception_table_entry __start___ex_table[]; const struct exception_table_entry *
extern const struct exception_table_entry __stop___ex_table[]; search_extable (const struct exception_table_entry *first,
const struct exception_table_entry *last,
static inline const struct exception_table_entry * unsigned long ip)
search_one_table (const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long ip, unsigned long gp)
{ {
while (first <= last) { const struct exception_table_entry *mid;
const struct exception_table_entry *mid; unsigned long mid_ip;
long diff; long diff, base = (long) first;
while (first <= last) {
mid = &first[(last - first)/2]; mid = &first[(last - first)/2];
diff = (mid->addr + gp) - ip; mid_ip = base + mid->addr;
diff = mid_ip - ip;
if (diff == 0) if (diff == 0)
return mid; return (void *) ((long) base + mid->cont);
else if (diff < 0) else if (diff < 0)
first = mid + 1; first = mid + 1;
else else
...@@ -34,50 +33,13 @@ search_one_table (const struct exception_table_entry *first, ...@@ -34,50 +33,13 @@ search_one_table (const struct exception_table_entry *first,
return 0; return 0;
} }
#ifndef CONFIG_MODULES
register unsigned long main_gp __asm__("gp");
#endif
struct exception_fixup
search_exception_table (unsigned long addr)
{
const struct exception_table_entry *entry;
struct exception_fixup fix = { 0 };
#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
entry = search_one_table(__start___ex_table, __stop___ex_table - 1, addr, main_gp);
if (entry)
fix.cont = entry->cont + main_gp;
return fix;
#else
struct archdata *archdata;
struct module *mp;
/* The kernel is the last "module" -- no need to treat it special. */
for (mp = module_list; mp; mp = mp->next) {
if (!mp->ex_table_start)
continue;
archdata = (struct archdata *) mp->archdata_start;
if (!archdata)
continue;
entry = search_one_table(mp->ex_table_start, mp->ex_table_end - 1,
addr, (unsigned long) archdata->gp);
if (entry) {
fix.cont = entry->cont + (unsigned long) archdata->gp;
return fix;
}
}
#endif
return fix;
}
void void
handle_exception (struct pt_regs *regs, struct exception_fixup fix) handle_exception (struct pt_regs *regs, const struct exception_table_entry *e)
{ {
long fix = (long) e;
regs->r8 = -EFAULT; regs->r8 = -EFAULT;
if (fix.cont & 4) if (fix & 4)
regs->r9 = 0; regs->r9 = 0;
regs->cr_iip = (long) fix.cont & ~0xf; regs->cr_iip = fix & ~0xf;
ia64_psr(regs)->ri = fix.cont & 0x3; /* set continuation slot number */ ia64_psr(regs)->ri = fix & 0x3; /* set continuation slot number */
} }
...@@ -56,6 +56,7 @@ tab[] = ...@@ -56,6 +56,7 @@ tab[] =
{ "IA64_TASK_THREAD_ON_USTACK_OFFSET", offsetof (struct task_struct, thread.on_ustack) }, { "IA64_TASK_THREAD_ON_USTACK_OFFSET", offsetof (struct task_struct, thread.on_ustack) },
{ "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) }, { "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
{ "IA64_TASK_TGID_OFFSET", offsetof (struct task_struct, tgid) }, { "IA64_TASK_TGID_OFFSET", offsetof (struct task_struct, tgid) },
{ "IA64_TASK_CLEAR_CHILD_TID_OFFSET",offsetof (struct task_struct, clear_child_tid) },
{ "IA64_PT_REGS_CR_IPSR_OFFSET", offsetof (struct pt_regs, cr_ipsr) }, { "IA64_PT_REGS_CR_IPSR_OFFSET", offsetof (struct pt_regs, cr_ipsr) },
{ "IA64_PT_REGS_CR_IIP_OFFSET", offsetof (struct pt_regs, cr_iip) }, { "IA64_PT_REGS_CR_IIP_OFFSET", offsetof (struct pt_regs, cr_iip) },
{ "IA64_PT_REGS_CR_IFS_OFFSET", offsetof (struct pt_regs, cr_ifs) }, { "IA64_PT_REGS_CR_IFS_OFFSET", offsetof (struct pt_regs, cr_ifs) },
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#define LOAD_OFFSET PAGE_OFFSET #define LOAD_OFFSET PAGE_OFFSET
#include <asm-generic/vmlinux.lds.h> #include <asm-generic/vmlinux.lds.h>
OUTPUT_FORMAT("elf64-ia64-little") OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64) OUTPUT_ARCH(ia64)
ENTRY(phys_start) ENTRY(phys_start)
...@@ -29,9 +29,29 @@ SECTIONS ...@@ -29,9 +29,29 @@ SECTIONS
_text = .; _text = .;
_stext = .; _stext = .;
.text : AT(ADDR(.text) - PAGE_OFFSET)
.text.ivt : AT(ADDR(.text.ivt) - PAGE_OFFSET)
{ {
*(.text.ivt) *(.text.ivt)
}
/*
* Due to a linker bug (still present as of binutils 2.13.90.0.10),
* the exception table must come before any code that uses the
* uaccess.h macros; otherwise, the linker will silently truncate negative @secrel()
* values to 0!! Just love it when bugs like these sneak in...
*/
/* Exception table */
. = ALIGN(16);
__ex_table : AT(ADDR(__ex_table) - PAGE_OFFSET)
{
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}
.text : AT(ADDR(.text) - PAGE_OFFSET)
{
*(.text) *(.text)
} }
.text2 : AT(ADDR(.text2) - PAGE_OFFSET) .text2 : AT(ADDR(.text2) - PAGE_OFFSET)
...@@ -47,13 +67,6 @@ SECTIONS ...@@ -47,13 +67,6 @@ SECTIONS
/* Global data */ /* Global data */
_data = .; _data = .;
/* Exception table */
. = ALIGN(16);
__start___ex_table = .;
__ex_table : AT(ADDR(__ex_table) - PAGE_OFFSET)
{ *(__ex_table) }
__stop___ex_table = .;
#if defined(CONFIG_IA64_GENERIC) #if defined(CONFIG_IA64_GENERIC)
/* Machine Vector */ /* Machine Vector */
. = ALIGN(16); . = ALIGN(16);
......
...@@ -44,18 +44,18 @@ ...@@ -44,18 +44,18 @@
.previous .previous
#if __GNUC__ >= 3 #if __GNUC__ >= 3
# define EX(y,x...) \ # define EX(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y); \ .xdata4 "__ex_table", @secrel(99f), @secrel(y); \
[99:] x [99:] x
# define EXCLR(y,x...) \ # define EXCLR(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y)+4; \ .xdata4 "__ex_table", @secrel(99f), @secrel(y)+4; \
[99:] x [99:] x
#else #else
# define EX(y,x...) \ # define EX(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y); \ .xdata4 "__ex_table", @secrel(99f), @secrel(y); \
99: x 99: x
# define EXCLR(y,x...) \ # define EXCLR(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y)+4; \ .xdata4 "__ex_table", @secrel(99f), @secrel(y)+4; \
99: x 99: x
#endif #endif
......
...@@ -177,7 +177,10 @@ activate_context (struct mm_struct *mm) ...@@ -177,7 +177,10 @@ activate_context (struct mm_struct *mm)
} while (unlikely(context != mm->context)); } while (unlikely(context != mm->context));
} }
#define deactivate_mm(tsk,mm) do { } while (0) #define deactivate_mm(tsk,mm) \
do { \
MMU_TRACE('d', smp_processor_id(), mm, mm->context); \
} while (0)
/* /*
* Switch from address space PREV to address space NEXT. * Switch from address space PREV to address space NEXT.
......
...@@ -219,11 +219,11 @@ struct switch_stack { ...@@ -219,11 +219,11 @@ struct switch_stack {
# define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr) # define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr)
# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0) # define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
# define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs)) # define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs))
# define fsys_mode(task,regs) \ # define fsys_mode(task,regs) \
({ \ ({ \
struct task_struct *_task = (task); \ struct task_struct *_task = (task); \
struct pt_regs *_regs = (regs); \ struct pt_regs *_regs = (regs); \
!user_mode(regs) && user_stack(task, regs); \ !user_mode(_regs) && user_stack(_task, _regs); \
}) })
struct task_struct; /* forward decl */ struct task_struct; /* forward decl */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* on information published in the Processor Abstraction Layer * on information published in the Processor Abstraction Layer
* and the System Abstraction Layer manual. * and the System Abstraction Layer manual.
* *
* Copyright (C) 1998-2002 Hewlett-Packard Co * Copyright (C) 1998-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com> * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com> * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <asm/kregs.h> #include <asm/kregs.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <asm/percpu.h>
#define KERNEL_START (PAGE_OFFSET + 68*1024*1024) #define KERNEL_START (PAGE_OFFSET + 68*1024*1024)
......
#ifndef _ASM_IA64_TLB_H #ifndef _ASM_IA64_TLB_H
#define _ASM_IA64_TLB_H #define _ASM_IA64_TLB_H
/* /*
* Copyright (C) 2002 Hewlett-Packard Co * Copyright (C) 2002-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* *
* This file was derived from asm-generic/tlb.h. * This file was derived from asm-generic/tlb.h.
...@@ -70,8 +70,7 @@ extern struct mmu_gather mmu_gathers[NR_CPUS]; ...@@ -70,8 +70,7 @@ extern struct mmu_gather mmu_gathers[NR_CPUS];
* freed pages that where gathered up to this point. * freed pages that where gathered up to this point.
*/ */
static inline void static inline void
ia64_tlb_flush_mmu(struct mmu_gather *tlb, ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
unsigned long start, unsigned long end)
{ {
unsigned int nr; unsigned int nr;
...@@ -197,8 +196,7 @@ tlb_remove_page (struct mmu_gather *tlb, struct page *page) ...@@ -197,8 +196,7 @@ tlb_remove_page (struct mmu_gather *tlb, struct page *page)
* PTE, not just those pointing to (normal) physical memory. * PTE, not just those pointing to (normal) physical memory.
*/ */
static inline void static inline void
__tlb_remove_tlb_entry(struct mmu_gather *tlb, __tlb_remove_tlb_entry (struct mmu_gather *tlb, pte_t *ptep, unsigned long address)
pte_t *ptep, unsigned long address)
{ {
if (tlb->start_addr == ~0UL) if (tlb->start_addr == ~0UL)
tlb->start_addr = address; tlb->start_addr = address;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and * associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
* then resumes execution at the continuation point. * then resumes execution at the continuation point.
* *
* Copyright (C) 1998, 1999, 2001-2002 Hewlett-Packard Co * Copyright (C) 1998, 1999, 2001-2003 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
...@@ -140,25 +140,25 @@ asm (".section \"__ex_table\", \"a\"\n\t.previous"); ...@@ -140,25 +140,25 @@ asm (".section \"__ex_table\", \"a\"\n\t.previous");
#define __get_user_64(addr) \ #define __get_user_64(addr) \
asm ("\n"_LL"\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ asm ("\n"_LL"\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)+4\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)+4\n" \
_LL \ _LL \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_32(addr) \ #define __get_user_32(addr) \
asm ("\n"_LL"\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ asm ("\n"_LL"\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)+4\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)+4\n" \
_LL \ _LL \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_16(addr) \ #define __get_user_16(addr) \
asm ("\n"_LL"\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ asm ("\n"_LL"\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)+4\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)+4\n" \
_LL \ _LL \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_8(addr) \ #define __get_user_8(addr) \
asm ("\n"_LL"\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \ asm ("\n"_LL"\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)+4\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)+4\n" \
_LL \ _LL \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err)); : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
...@@ -202,28 +202,28 @@ extern void __put_user_unknown (void); ...@@ -202,28 +202,28 @@ extern void __put_user_unknown (void);
#define __put_user_64(x,addr) \ #define __put_user_64(x,addr) \
asm volatile ( \ asm volatile ( \
"\n"_LL"\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ "\n"_LL"\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)\n" \
_LL \ _LL \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_32(x,addr) \ #define __put_user_32(x,addr) \
asm volatile ( \ asm volatile ( \
"\n"_LL"\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ "\n"_LL"\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)\n" \
_LL \ _LL \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_16(x,addr) \ #define __put_user_16(x,addr) \
asm volatile ( \ asm volatile ( \
"\n"_LL"\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ "\n"_LL"\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)\n" \
_LL \ _LL \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_8(x,addr) \ #define __put_user_8(x,addr) \
asm volatile ( \ asm volatile ( \
"\n"_LL"\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \ "\n"_LL"\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
"\t.xdata4 \"__ex_table\", @gprel(1b), @gprel(1f)\n" \ "\t.xdata4 \"__ex_table\", @secrel(1b), @secrel(1f)\n" \
_LL \ _LL \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
...@@ -314,26 +314,22 @@ struct exception_table_entry { ...@@ -314,26 +314,22 @@ struct exception_table_entry {
int cont; /* gp-relative continuation address; if bit 2 is set, r9 is set to 0 */ int cont; /* gp-relative continuation address; if bit 2 is set, r9 is set to 0 */
}; };
struct exception_fixup { extern void handle_exception (struct pt_regs *regs, const struct exception_table_entry *e);
unsigned long cont; /* continuation point (bit 2: clear r9 if set) */ extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
};
extern struct exception_fixup search_exception_table (unsigned long addr);
extern void handle_exception (struct pt_regs *regs, struct exception_fixup fixup);
#ifdef GAS_HAS_LOCAL_TAGS #ifdef GAS_HAS_LOCAL_TAGS
#define SEARCH_EXCEPTION_TABLE(regs) search_exception_table(regs->cr_iip + ia64_psr(regs)->ri); # define SEARCH_EXCEPTION_TABLE(regs) search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri)
#else #else
#define SEARCH_EXCEPTION_TABLE(regs) search_exception_table(regs->cr_iip); # define SEARCH_EXCEPTION_TABLE(regs) search_exception_tables(regs->cr_iip)
#endif #endif
static inline int static inline int
done_with_exception (struct pt_regs *regs) done_with_exception (struct pt_regs *regs)
{ {
struct exception_fixup fix; const struct exception_table_entry *e;
fix = SEARCH_EXCEPTION_TABLE(regs); e = SEARCH_EXCEPTION_TABLE(regs);
if (fix.cont) { if (e) {
handle_exception(regs, fix); handle_exception(regs, e);
return 1; return 1;
} }
return 0; return 0;
......
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