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 @@
-----------------------------------
Started: 13-Jan-2002
Last update: 15-Jan-2002
Last update: 24-Jan-2002
David Mosberger-Tang
<davidm@hpl.hp.com>
......@@ -89,6 +89,7 @@ The entry and exit-state of an fsyscall handler is as follows:
** Machine state on entry to fsyscall handler:
- r10 = 0
- r11 = saved ar.pfs (a user-level value)
- r15 = system call number
- r16 = "current" task pointer (in normal kernel-mode, this is in r13)
......
......@@ -5,7 +5,7 @@
# License. See the file "COPYING" in the main directory of this archive
# 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
......@@ -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_SGI_SN) += arch/ia64/sn/fakeprom/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/ia64/boot $(1)
maketool =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/ia64/tools $(1)
boot := arch/ia64/boot
tools := arch/ia64/tools
.PHONY: boot compressed archclean archmrproper include/asm-ia64/offsets.h
all compressed: vmlinux.gz
all: vmlinux
compressed: vmlinux.gz
vmlinux.gz: vmlinux
$(call makeboot,vmlinux.gz)
$(Q)$(MAKE) $(build)=$(boot) vmlinux.gz
check: vmlinux
arch/ia64/scripts/unwcheck.sh vmlinux
archmrproper:
archclean:
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/ia64/boot
$(Q)$(MAKE) -f scripts/Makefile.clean obj=arch/ia64/tools
$(Q)$(MAKE) $(clean)=$(boot)
$(Q)$(MAKE) $(clean)=$(tools)
CLEAN_FILES += include/asm-ia64/offsets.h vmlinux.gz bootloader
prepare: include/asm-ia64/offsets.h
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
$(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
*
* Copyright (C) 2002 Hewlett-Packard Co
* Copyright (C) 2002 Alex Williamson <alex_williamson@hp.com>
* Copyright (C) 2002 Bjorn Helgaas <bjorn_helgaas@hp.com>
* Copyright (C) 2002-2003 Hewlett-Packard Co
* Alex Williamson <alex_williamson@hp.com>
* Bjorn Helgaas <bjorn_helgaas@hp.com>
*/
......@@ -17,7 +17,7 @@
#include <asm/dma.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 *);
#define PFX "hpzx1: "
......@@ -190,31 +190,31 @@ hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned
hpzx1_devices++;
}
typedef struct {
struct acpi_hp_vendor_long {
u8 guid_id;
u8 guid[16];
u8 csr_base[8];
u8 csr_length[8];
} acpi_hp_vendor_long;
};
#define HP_CCSR_LENGTH 0x21
#define HP_CCSR_TYPE 0x2
#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \
0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
extern acpi_status acpi_get_crs(acpi_handle, acpi_buffer *);
extern acpi_resource *acpi_get_crs_next(acpi_buffer *, int *);
extern acpi_resource_data *acpi_get_crs_type(acpi_buffer *, int *, int);
extern void acpi_dispose_crs(acpi_buffer *);
extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *);
extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *);
extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int);
extern void acpi_dispose_crs(struct acpi_buffer *);
static acpi_status
hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
{
int i, offset = 0;
acpi_status status;
acpi_buffer buf;
acpi_resource_vendor *res;
acpi_hp_vendor_long *hp_res;
struct acpi_buffer buf;
struct acpi_resource_vendor *res;
struct acpi_hp_vendor_long *hp_res;
efi_guid_t vendor_guid;
*csr_base = 0;
......@@ -226,14 +226,14 @@ hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
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) {
printk(KERN_ERR PFX "Failed to find config space for device\n");
acpi_dispose_crs(&buf);
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) {
printk(KERN_ERR PFX "Unknown Vendor data\n");
......@@ -288,7 +288,7 @@ hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret)
{
u64 csr_base = 0, csr_length = 0;
acpi_status status;
NATIVE_UINT busnum;
acpi_native_uint busnum;
char *name = context;
char fullname[32];
......
......@@ -6,7 +6,7 @@
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* 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>
*
* These routines maintain argument size conversion between 32bit and 64bit
......@@ -2348,7 +2348,7 @@ shmctl32 (int first, int second, void *uptr)
static long
semtimedop32(int semid, struct sembuf *tsems, int nsems,
const struct timespec32 *timeout32)
const struct compat_timespec *timeout32)
{
struct timespec t;
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)
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL);
case SEMTIMEDOP:
return semtimedop32(first, (struct sembuf *)AA(ptr), second,
(const struct timespec32 *)AA(fifth));
(const struct compat_timespec *)AA(fifth));
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL:
......
......@@ -128,7 +128,7 @@ acpi_get_sysname (void)
* with a list of acpi_resource structures.
*/
acpi_status
acpi_get_crs (acpi_handle obj, acpi_buffer *buf)
acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf)
{
acpi_status result;
buf->length = 0;
......@@ -144,10 +144,10 @@ acpi_get_crs (acpi_handle obj, acpi_buffer *buf)
return acpi_get_current_resources(obj, buf);
}
acpi_resource *
acpi_get_crs_next (acpi_buffer *buf, int *offset)
struct acpi_resource *
acpi_get_crs_next (struct acpi_buffer *buf, int *offset)
{
acpi_resource *res;
struct acpi_resource *res;
if (*offset >= buf->length)
return NULL;
......@@ -157,11 +157,11 @@ acpi_get_crs_next (acpi_buffer *buf, int *offset)
return res;
}
acpi_resource_data *
acpi_get_crs_type (acpi_buffer *buf, int *offset, int type)
union acpi_resource_data *
acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type)
{
for (;;) {
acpi_resource *res = acpi_get_crs_next(buf, offset);
struct acpi_resource *res = acpi_get_crs_next(buf, offset);
if (!res)
return NULL;
if (res->id == type)
......@@ -170,7 +170,7 @@ acpi_get_crs_type (acpi_buffer *buf, int *offset, int type)
}
void
acpi_dispose_crs (acpi_buffer *buf)
acpi_dispose_crs (struct acpi_buffer *buf)
{
kfree(buf->pointer);
}
......@@ -638,7 +638,7 @@ static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{
struct acpi_table_header *fadt_header;
fadt_descriptor_rev2 *fadt;
struct fadt_descriptor_rev2 *fadt;
u32 sci_irq, gsi_base;
char *iosapic_address;
......@@ -649,7 +649,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (fadt_header->revision != 3)
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))
acpi_kbd_controller_present = 0;
......
......@@ -10,6 +10,28 @@
#include <asm/offsets.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)
mov r8=ENOSYS
mov r10=-1
......@@ -32,6 +54,30 @@ ENTRY(fsys_getpid)
br.ret.sptk.many b6
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
.align 8
.globl fsyscall_table
......@@ -245,9 +291,9 @@ fsyscall_table:
data8 fsys_fallback_syscall // futex // 1230
data8 fsys_fallback_syscall // sched_setaffinity
data8 fsys_fallback_syscall // sched_getaffinity
data8 fsys_fallback_syscall // set_tid_address
data8 fsys_fallback_syscall // alloc_hugepages
data8 fsys_fallback_syscall // free_hugepages // 1235
data8 fsys_set_tid_address // set_tid_address
data8 fsys_fallback_syscall // unused
data8 fsys_fallback_syscall // unused // 1235
data8 fsys_fallback_syscall // exit_group
data8 fsys_fallback_syscall // lookup_dcookie
data8 fsys_fallback_syscall // io_setup
......
......@@ -144,12 +144,14 @@ show_regs (struct pt_regs *regs)
void
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{
#ifdef CONFIG_FSYS
if (fsys_mode(current, &scr->pt)) {
/* defer signal-handling etc. until we return to privilege-level 0. */
if (!ia64_psr(&scr->pt)->lp)
ia64_psr(&scr->pt)->lp = 1;
return;
}
#endif
#ifdef CONFIG_PERFMON
if (current->thread.pfm_ovfl_block_reset)
......
......@@ -524,6 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case 29: /* Debug */
case 35: /* Taken Branch Trap */
case 36: /* Single Step Trap */
#ifdef CONFIG_FSYS
if (fsys_mode(current, regs)) {
extern char syscall_via_break[], __start_gate_section[];
/*
......@@ -541,6 +542,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
ia64_psr(regs)->cpl = 3;
return;
}
#endif
switch (vector) {
case 29:
siginfo.si_code = TRAP_HWBKPT;
......
......@@ -1294,12 +1294,12 @@ within_logging_rate_limit (void)
void
ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
{
struct exception_fixup fix = { 0 };
struct ia64_psr *ipsr = ia64_psr(regs);
mm_segment_t old_fs = get_fs();
unsigned long bundle[2];
unsigned long opcode;
struct siginfo si;
const struct exception_table_entry *eh = NULL;
union {
unsigned long l;
load_store_t insn;
......@@ -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
* handler into reading an arbitrary kernel addresses...
*/
if (!user_mode(regs)) {
fix = SEARCH_EXCEPTION_TABLE(regs);
}
if (user_mode(regs) || fix.cont) {
if (!user_mode(regs))
eh = SEARCH_EXCEPTION_TABLE(regs);
if (user_mode(regs) || eh) {
if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0)
goto force_sigbus;
......@@ -1486,8 +1485,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
failure:
/* something went wrong... */
if (!user_mode(regs)) {
if (fix.cont) {
handle_exception(regs, fix);
if (eh) {
handle_exception(regs, eh);
goto done;
}
die_if_kernel("error during unaligned kernel access\n", regs, ret);
......
......@@ -10,22 +10,21 @@
#include <asm/uaccess.h>
#include <asm/module.h>
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
static inline const struct exception_table_entry *
search_one_table (const struct exception_table_entry *first,
const struct exception_table_entry *
search_extable (const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long ip, unsigned long gp)
unsigned long ip)
{
while (first <= last) {
const struct exception_table_entry *mid;
long diff;
unsigned long mid_ip;
long diff, base = (long) first;
while (first <= last) {
mid = &first[(last - first)/2];
diff = (mid->addr + gp) - ip;
mid_ip = base + mid->addr;
diff = mid_ip - ip;
if (diff == 0)
return mid;
return (void *) ((long) base + mid->cont);
else if (diff < 0)
first = mid + 1;
else
......@@ -34,50 +33,13 @@ search_one_table (const struct exception_table_entry *first,
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
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;
if (fix.cont & 4)
if (fix & 4)
regs->r9 = 0;
regs->cr_iip = (long) fix.cont & ~0xf;
ia64_psr(regs)->ri = fix.cont & 0x3; /* set continuation slot number */
regs->cr_iip = fix & ~0xf;
ia64_psr(regs)->ri = fix & 0x3; /* set continuation slot number */
}
......@@ -56,6 +56,7 @@ tab[] =
{ "IA64_TASK_THREAD_ON_USTACK_OFFSET", offsetof (struct task_struct, thread.on_ustack) },
{ "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
{ "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_IIP_OFFSET", offsetof (struct pt_regs, cr_iip) },
{ "IA64_PT_REGS_CR_IFS_OFFSET", offsetof (struct pt_regs, cr_ifs) },
......
......@@ -29,9 +29,29 @@ SECTIONS
_text = .;
_stext = .;
.text : AT(ADDR(.text) - PAGE_OFFSET)
.text.ivt : AT(ADDR(.text.ivt) - PAGE_OFFSET)
{
*(.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)
}
.text2 : AT(ADDR(.text2) - PAGE_OFFSET)
......@@ -47,13 +67,6 @@ SECTIONS
/* Global 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)
/* Machine Vector */
. = ALIGN(16);
......
......@@ -45,17 +45,17 @@
#if __GNUC__ >= 3
# define EX(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y); \
.xdata4 "__ex_table", @secrel(99f), @secrel(y); \
[99:] x
# define EXCLR(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y)+4; \
.xdata4 "__ex_table", @secrel(99f), @secrel(y)+4; \
[99:] x
#else
# define EX(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y); \
.xdata4 "__ex_table", @secrel(99f), @secrel(y); \
99: x
# define EXCLR(y,x...) \
.xdata4 "__ex_table", @gprel(99f), @gprel(y)+4; \
.xdata4 "__ex_table", @secrel(99f), @secrel(y)+4; \
99: x
#endif
......
......@@ -177,7 +177,10 @@ activate_context (struct mm_struct *mm)
} 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.
......
......@@ -223,7 +223,7 @@ struct switch_stack {
({ \
struct task_struct *_task = (task); \
struct pt_regs *_regs = (regs); \
!user_mode(regs) && user_stack(task, regs); \
!user_mode(_regs) && user_stack(_task, _regs); \
})
struct task_struct; /* forward decl */
......
......@@ -7,7 +7,7 @@
* on information published in the Processor Abstraction Layer
* 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>
* Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
......@@ -17,6 +17,7 @@
#include <asm/kregs.h>
#include <asm/page.h>
#include <asm/pal.h>
#include <asm/percpu.h>
#define KERNEL_START (PAGE_OFFSET + 68*1024*1024)
......
#ifndef _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>
*
* This file was derived from asm-generic/tlb.h.
......@@ -70,8 +70,7 @@ extern struct mmu_gather mmu_gathers[NR_CPUS];
* freed pages that where gathered up to this point.
*/
static inline void
ia64_tlb_flush_mmu(struct mmu_gather *tlb,
unsigned long start, unsigned long end)
ia64_tlb_flush_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
unsigned int nr;
......@@ -197,8 +196,7 @@ tlb_remove_page (struct mmu_gather *tlb, struct page *page)
* PTE, not just those pointing to (normal) physical memory.
*/
static inline void
__tlb_remove_tlb_entry(struct mmu_gather *tlb,
pte_t *ptep, unsigned long address)
__tlb_remove_tlb_entry (struct mmu_gather *tlb, pte_t *ptep, unsigned long address)
{
if (tlb->start_addr == ~0UL)
tlb->start_addr = address;
......
......@@ -26,7 +26,7 @@
* associated and, if so, sets r8 to -EFAULT and clears r9 to 0 and
* 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>
*/
......@@ -140,25 +140,25 @@ asm (".section \"__ex_table\", \"a\"\n\t.previous");
#define __get_user_64(addr) \
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 \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_32(addr) \
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 \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_16(addr) \
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 \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
#define __get_user_8(addr) \
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 \
: "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));
......@@ -202,28 +202,28 @@ extern void __put_user_unknown (void);
#define __put_user_64(x,addr) \
asm volatile ( \
"\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 \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_32(x,addr) \
asm volatile ( \
"\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 \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_16(x,addr) \
asm volatile ( \
"\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 \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
#define __put_user_8(x,addr) \
asm volatile ( \
"\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 \
: "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
......@@ -314,26 +314,22 @@ struct exception_table_entry {
int cont; /* gp-relative continuation address; if bit 2 is set, r9 is set to 0 */
};
struct exception_fixup {
unsigned long cont; /* continuation point (bit 2: clear r9 if set) */
};
extern struct exception_fixup search_exception_table (unsigned long addr);
extern void handle_exception (struct pt_regs *regs, struct exception_fixup fixup);
extern void handle_exception (struct pt_regs *regs, const struct exception_table_entry *e);
extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
#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
#define SEARCH_EXCEPTION_TABLE(regs) search_exception_table(regs->cr_iip);
# define SEARCH_EXCEPTION_TABLE(regs) search_exception_tables(regs->cr_iip)
#endif
static inline int
done_with_exception (struct pt_regs *regs)
{
struct exception_fixup fix;
fix = SEARCH_EXCEPTION_TABLE(regs);
if (fix.cont) {
handle_exception(regs, fix);
const struct exception_table_entry *e;
e = SEARCH_EXCEPTION_TABLE(regs);
if (e) {
handle_exception(regs, e);
return 1;
}
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