Pull rmia32 into release branch
This commit is contained in:
commit
8d6339b8a5
|
@ -499,23 +499,6 @@ config ARCH_PROC_KCORE_TEXT
|
|||
def_bool y
|
||||
depends on PROC_KCORE
|
||||
|
||||
config IA32_SUPPORT
|
||||
bool "Support for Linux/x86 binaries"
|
||||
help
|
||||
IA-64 processors can execute IA-32 (X86) instructions. By
|
||||
saying Y here, the kernel will include IA-32 system call
|
||||
emulation support which makes it possible to transparently
|
||||
run IA-32 Linux binaries on an IA-64 Linux system.
|
||||
If in doubt, say Y.
|
||||
|
||||
config COMPAT
|
||||
bool
|
||||
depends on IA32_SUPPORT
|
||||
default y
|
||||
|
||||
config COMPAT_FOR_U64_ALIGNMENT
|
||||
def_bool COMPAT
|
||||
|
||||
config IA64_MCA_RECOVERY
|
||||
tristate "MCA recovery from errors other than TLB."
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
|
|||
|
||||
libs-y += arch/ia64/lib/
|
||||
core-y += arch/ia64/kernel/ arch/ia64/mm/
|
||||
core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/
|
||||
core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
|
||||
core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/
|
||||
core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
|
||||
|
|
|
@ -131,8 +131,6 @@ CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
|
|||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
# CONFIG_VIRTUAL_MEM_MAP is not set
|
||||
CONFIG_IA32_SUPPORT=y
|
||||
CONFIG_COMPAT=y
|
||||
# CONFIG_IA64_MCA_RECOVERY is not set
|
||||
CONFIG_PERFMON=y
|
||||
CONFIG_IA64_PALINFO=y
|
||||
|
|
|
@ -205,8 +205,6 @@ CONFIG_VIRTUAL_MEM_MAP=y
|
|||
CONFIG_HOLES_IN_ZONE=y
|
||||
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
|
||||
CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
|
||||
CONFIG_IA32_SUPPORT=y
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
|
||||
CONFIG_IA64_MCA_RECOVERY=y
|
||||
CONFIG_PERFMON=y
|
||||
|
|
|
@ -139,8 +139,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
|||
CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
|
||||
CONFIG_IA32_SUPPORT=y
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_IA64_MCA_RECOVERY=y
|
||||
CONFIG_PERFMON=y
|
||||
CONFIG_IA64_PALINFO=y
|
||||
|
|
|
@ -130,8 +130,6 @@ CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
|
|||
CONFIG_ARCH_FLATMEM_ENABLE=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
# CONFIG_VIRTUAL_MEM_MAP is not set
|
||||
CONFIG_IA32_SUPPORT=y
|
||||
CONFIG_COMPAT=y
|
||||
# CONFIG_IA64_MCA_RECOVERY is not set
|
||||
# CONFIG_PERFMON is not set
|
||||
CONFIG_IA64_PALINFO=m
|
||||
|
|
|
@ -154,7 +154,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
|||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_VIRTUAL_MEM_MAP=y
|
||||
CONFIG_HOLES_IN_ZONE=y
|
||||
# CONFIG_IA32_SUPPORT is not set
|
||||
CONFIG_IA64_MCA_RECOVERY=y
|
||||
CONFIG_PERFMON=y
|
||||
CONFIG_IA64_PALINFO=y
|
||||
|
|
|
@ -200,8 +200,6 @@ CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
|||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_VIRTUAL_MEM_MAP=y
|
||||
CONFIG_HOLES_IN_ZONE=y
|
||||
# CONFIG_IA32_SUPPORT is not set
|
||||
# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
|
||||
CONFIG_IA64_MCA_RECOVERY=y
|
||||
CONFIG_PERFMON=y
|
||||
CONFIG_IA64_PALINFO=y
|
||||
|
|
|
@ -150,8 +150,6 @@ CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
|
|||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_VIRTUAL_MEM_MAP=y
|
||||
CONFIG_HOLES_IN_ZONE=y
|
||||
CONFIG_IA32_SUPPORT=y
|
||||
CONFIG_COMPAT=y
|
||||
CONFIG_IA64_MCA_RECOVERY=y
|
||||
CONFIG_PERFMON=y
|
||||
CONFIG_IA64_PALINFO=y
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#
|
||||
# Makefile for the ia32 kernel emulation subsystem.
|
||||
#
|
||||
|
||||
obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
|
||||
ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
|
||||
# Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and
|
||||
# restore_ia32_fpstate_live() can be sure the live register contain user-level state.
|
||||
CFLAGS_ia32_signal.o += -mfixed-range=f16-f31
|
|
@ -1,42 +0,0 @@
|
|||
#include "../../x86/include/asm/unistd_32.h"
|
||||
|
||||
unsigned ia32_dir_class[] = {
|
||||
#include <asm-generic/audit_dir_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_chattr_class[] = {
|
||||
#include <asm-generic/audit_change_attr.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_write_class[] = {
|
||||
#include <asm-generic/audit_write.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_read_class[] = {
|
||||
#include <asm-generic/audit_read.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
unsigned ia32_signal_class[] = {
|
||||
#include <asm-generic/audit_signal.h>
|
||||
~0U
|
||||
};
|
||||
|
||||
int ia32_classify_syscall(unsigned syscall)
|
||||
{
|
||||
switch(syscall) {
|
||||
case __NR_open:
|
||||
return 2;
|
||||
case __NR_openat:
|
||||
return 3;
|
||||
case __NR_socketcall:
|
||||
return 4;
|
||||
case __NR_execve:
|
||||
return 5;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* IA-32 ELF support.
|
||||
*
|
||||
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
|
||||
* Copyright (C) 2001 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* 06/16/00 A. Mallick initialize csd/ssd/tssd/cflg for ia32_load_state
|
||||
* 04/13/01 D. Mosberger dropped saving tssd in ar.k1---it's not needed
|
||||
* 09/14/01 D. Mosberger fixed memory management for gdt/tss page
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include <asm/param.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
#include "ia32priv.h"
|
||||
#include "elfcore32.h"
|
||||
|
||||
/* Override some function names */
|
||||
#undef start_thread
|
||||
#define start_thread ia32_start_thread
|
||||
#define elf_format elf32_format
|
||||
#define init_elf_binfmt init_elf32_binfmt
|
||||
#define exit_elf_binfmt exit_elf32_binfmt
|
||||
|
||||
#undef CLOCKS_PER_SEC
|
||||
#define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC
|
||||
|
||||
extern void ia64_elf32_init (struct pt_regs *regs);
|
||||
|
||||
static void elf32_set_personality (void);
|
||||
|
||||
static unsigned long __attribute ((unused))
|
||||
randomize_stack_top(unsigned long stack_top);
|
||||
|
||||
#define setup_arg_pages(bprm,tos,exec) ia32_setup_arg_pages(bprm,exec)
|
||||
#define elf_map elf32_map
|
||||
|
||||
#undef SET_PERSONALITY
|
||||
#define SET_PERSONALITY(ex) elf32_set_personality()
|
||||
|
||||
#define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
|
||||
|
||||
/* Ugly but avoids duplication */
|
||||
#include "../../../fs/binfmt_elf.c"
|
||||
|
||||
extern struct page *ia32_shared_page[];
|
||||
extern unsigned long *ia32_gdt;
|
||||
extern struct page *ia32_gate_page;
|
||||
|
||||
int
|
||||
ia32_install_shared_page (struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
vmf->page = ia32_shared_page[smp_processor_id()];
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ia32_install_gate_page (struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
vmf->page = ia32_gate_page;
|
||||
get_page(vmf->page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const struct vm_operations_struct ia32_shared_page_vm_ops = {
|
||||
.fault = ia32_install_shared_page
|
||||
};
|
||||
|
||||
static const struct vm_operations_struct ia32_gate_page_vm_ops = {
|
||||
.fault = ia32_install_gate_page
|
||||
};
|
||||
|
||||
void
|
||||
ia64_elf32_init (struct pt_regs *regs)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
/*
|
||||
* Map GDT below 4GB, where the processor can find it. We need to map
|
||||
* it with privilege level 3 because the IVE uses non-privileged accesses to these
|
||||
* tables. IA-32 segmentation is used to protect against IA-32 accesses to them.
|
||||
*/
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_GDT_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_SIZE;
|
||||
vma->vm_page_prot = PAGE_SHARED;
|
||||
vma->vm_flags = VM_READ|VM_MAYREAD|VM_RESERVED;
|
||||
vma->vm_ops = &ia32_shared_page_vm_ops;
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
{
|
||||
if (insert_vm_struct(current->mm, vma)) {
|
||||
kmem_cache_free(vm_area_cachep, vma);
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* When user stack is not executable, push sigreturn code to stack makes
|
||||
* segmentation fault raised when returning to kernel. So now sigreturn
|
||||
* code is locked in specific gate page, which is pointed by pretcode
|
||||
* when setup_frame_ia32
|
||||
*/
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_GATE_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_SIZE;
|
||||
vma->vm_page_prot = PAGE_COPY_EXEC;
|
||||
vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC
|
||||
| VM_MAYEXEC | VM_RESERVED;
|
||||
vma->vm_ops = &ia32_gate_page_vm_ops;
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
{
|
||||
if (insert_vm_struct(current->mm, vma)) {
|
||||
kmem_cache_free(vm_area_cachep, vma);
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install LDT as anonymous memory. This gives us all-zero segment descriptors
|
||||
* until a task modifies them via modify_ldt().
|
||||
*/
|
||||
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma) {
|
||||
vma->vm_mm = current->mm;
|
||||
vma->vm_start = IA32_LDT_OFFSET;
|
||||
vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
|
||||
vma->vm_page_prot = PAGE_SHARED;
|
||||
vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE;
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
{
|
||||
if (insert_vm_struct(current->mm, vma)) {
|
||||
kmem_cache_free(vm_area_cachep, vma);
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
}
|
||||
|
||||
ia64_psr(regs)->ac = 0; /* turn off alignment checking */
|
||||
regs->loadrs = 0;
|
||||
/*
|
||||
* According to the ABI %edx points to an `atexit' handler. Since we don't have
|
||||
* one we'll set it to 0 and initialize all the other registers just to make
|
||||
* things more deterministic, ala the i386 implementation.
|
||||
*/
|
||||
regs->r8 = 0; /* %eax */
|
||||
regs->r11 = 0; /* %ebx */
|
||||
regs->r9 = 0; /* %ecx */
|
||||
regs->r10 = 0; /* %edx */
|
||||
regs->r13 = 0; /* %ebp */
|
||||
regs->r14 = 0; /* %esi */
|
||||
regs->r15 = 0; /* %edi */
|
||||
|
||||
current->thread.eflag = IA32_EFLAG;
|
||||
current->thread.fsr = IA32_FSR_DEFAULT;
|
||||
current->thread.fcr = IA32_FCR_DEFAULT;
|
||||
current->thread.fir = 0;
|
||||
current->thread.fdr = 0;
|
||||
|
||||
/*
|
||||
* Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor
|
||||
* format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32
|
||||
* architecture manual. Also note that the only fields that are not ignored are
|
||||
* `base', `limit', 'G', `P' (must be 1) and `S' (must be 0).
|
||||
*/
|
||||
regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1,
|
||||
0, 0, 0, 1, 0, 0, 0));
|
||||
/* Setup the segment selectors */
|
||||
regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */
|
||||
regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */
|
||||
|
||||
ia32_load_segment_descriptors(current);
|
||||
ia32_load_state(current);
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the override of setup_arg_pages() without this ia32_setup_arg_pages()
|
||||
* will suffer infinite self recursion.
|
||||
*/
|
||||
#undef setup_arg_pages
|
||||
|
||||
int
|
||||
ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setup_arg_pages(bprm, IA32_STACK_TOP, executable_stack);
|
||||
if (!ret) {
|
||||
/*
|
||||
* Can't do it in ia64_elf32_init(). Needs to be done before
|
||||
* calls to elf32_map()
|
||||
*/
|
||||
current->thread.ppl = ia32_init_pp_list();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
elf32_set_personality (void)
|
||||
{
|
||||
set_personality(PER_LINUX32);
|
||||
current->thread.map_base = IA32_PAGE_OFFSET/3;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
elf32_map(struct file *filep, unsigned long addr, struct elf_phdr *eppnt,
|
||||
int prot, int type, unsigned long unused)
|
||||
{
|
||||
unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
|
||||
|
||||
return ia32_do_mmap(filep, (addr & IA32_PAGE_MASK), eppnt->p_filesz + pgoff, prot, type,
|
||||
eppnt->p_offset - pgoff);
|
||||
}
|
||||
|
||||
#define cpu_uses_ia32el() (local_cpu_data->family > 0x1f)
|
||||
|
||||
static int __init check_elf32_binfmt(void)
|
||||
{
|
||||
if (cpu_uses_ia32el()) {
|
||||
printk("Please use IA-32 EL for executing IA-32 binaries\n");
|
||||
unregister_binfmt(&elf_format);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(check_elf32_binfmt)
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* IA-32 ELF core dump support.
|
||||
*
|
||||
* Copyright (C) 2003 Arun Sharma <arun.sharma@intel.com>
|
||||
*
|
||||
* Derived from the x86_64 version
|
||||
*/
|
||||
#ifndef _ELFCORE32_H_
|
||||
#define _ELFCORE32_H_
|
||||
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/* Override elfcore.h */
|
||||
#define _LINUX_ELFCORE_H 1
|
||||
typedef unsigned int elf_greg_t;
|
||||
|
||||
#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef struct ia32_user_i387_struct elf_fpregset_t;
|
||||
typedef struct ia32_user_fxsr_struct elf_fpxregset_t;
|
||||
|
||||
struct elf_siginfo
|
||||
{
|
||||
int si_signo; /* signal number */
|
||||
int si_code; /* extra code */
|
||||
int si_errno; /* errno */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
|
||||
/*
|
||||
* Hacks are here since types between compat_timeval (= pair of s32) and
|
||||
* ia64-native timeval (= pair of s64) are not compatible, at least a file
|
||||
* arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on
|
||||
* use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval().
|
||||
*/
|
||||
#define cputime_to_timeval(a,b) \
|
||||
do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0)
|
||||
#else
|
||||
#define jiffies_to_timeval(a,b) \
|
||||
do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0)
|
||||
#endif
|
||||
|
||||
struct elf_prstatus
|
||||
{
|
||||
struct elf_siginfo pr_info; /* Info associated with signal */
|
||||
short pr_cursig; /* Current signal */
|
||||
unsigned int pr_sigpend; /* Set of pending signals */
|
||||
unsigned int pr_sighold; /* Set of held signals */
|
||||
pid_t pr_pid;
|
||||
pid_t pr_ppid;
|
||||
pid_t pr_pgrp;
|
||||
pid_t pr_sid;
|
||||
struct compat_timeval pr_utime; /* User time */
|
||||
struct compat_timeval pr_stime; /* System time */
|
||||
struct compat_timeval pr_cutime; /* Cumulative user time */
|
||||
struct compat_timeval pr_cstime; /* Cumulative system time */
|
||||
elf_gregset_t pr_reg; /* GP registers */
|
||||
int pr_fpvalid; /* True if math co-processor being used. */
|
||||
};
|
||||
|
||||
#define ELF_PRARGSZ (80) /* Number of chars for args */
|
||||
|
||||
struct elf_prpsinfo
|
||||
{
|
||||
char pr_state; /* numeric process state */
|
||||
char pr_sname; /* char for pr_state */
|
||||
char pr_zomb; /* zombie */
|
||||
char pr_nice; /* nice val */
|
||||
unsigned int pr_flag; /* flags */
|
||||
__u16 pr_uid;
|
||||
__u16 pr_gid;
|
||||
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
/* Lots missing */
|
||||
char pr_fname[16]; /* filename of executable */
|
||||
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
|
||||
};
|
||||
|
||||
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
|
||||
pr_reg[0] = regs->r11; \
|
||||
pr_reg[1] = regs->r9; \
|
||||
pr_reg[2] = regs->r10; \
|
||||
pr_reg[3] = regs->r14; \
|
||||
pr_reg[4] = regs->r15; \
|
||||
pr_reg[5] = regs->r13; \
|
||||
pr_reg[6] = regs->r8; \
|
||||
pr_reg[7] = regs->r16 & 0xffff; \
|
||||
pr_reg[8] = (regs->r16 >> 16) & 0xffff; \
|
||||
pr_reg[9] = (regs->r16 >> 32) & 0xffff; \
|
||||
pr_reg[10] = (regs->r16 >> 48) & 0xffff; \
|
||||
pr_reg[11] = regs->r1; \
|
||||
pr_reg[12] = regs->cr_iip; \
|
||||
pr_reg[13] = regs->r17 & 0xffff; \
|
||||
pr_reg[14] = ia64_getreg(_IA64_REG_AR_EFLAG); \
|
||||
pr_reg[15] = regs->r12; \
|
||||
pr_reg[16] = (regs->r17 >> 16) & 0xffff;
|
||||
|
||||
static inline void elf_core_copy_regs(elf_gregset_t *elfregs,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
ELF_CORE_COPY_REGS((*elfregs), regs)
|
||||
}
|
||||
|
||||
static inline int elf_core_copy_task_regs(struct task_struct *t,
|
||||
elf_gregset_t* elfregs)
|
||||
{
|
||||
ELF_CORE_COPY_REGS((*elfregs), task_pt_regs(t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu)
|
||||
{
|
||||
struct ia32_user_i387_struct *fpstate = (void*)fpu;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
if (!tsk_used_math(tsk))
|
||||
return 0;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate);
|
||||
set_fs(old_fs);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define ELF_CORE_COPY_XFPREGS 1
|
||||
#define ELF_CORE_XFPREG_TYPE NT_PRXFPREG
|
||||
static inline int
|
||||
elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
|
||||
{
|
||||
struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
if (!tsk_used_math(tsk))
|
||||
return 0;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate);
|
||||
set_fs(old_fs);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* _ELFCORE32_H_ */
|
|
@ -1,468 +0,0 @@
|
|||
#include <asm/asmmacro.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#include "../kernel/minstate.h"
|
||||
|
||||
/*
|
||||
* execve() is special because in case of success, we need to
|
||||
* setup a null register window frame (in case an IA-32 process
|
||||
* is exec'ing an IA-64 program).
|
||||
*/
|
||||
ENTRY(ia32_execve)
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
|
||||
alloc loc1=ar.pfs,3,2,4,0
|
||||
mov loc0=rp
|
||||
.body
|
||||
zxt4 out0=in0 // filename
|
||||
;; // stop bit between alloc and call
|
||||
zxt4 out1=in1 // argv
|
||||
zxt4 out2=in2 // envp
|
||||
add out3=16,sp // regs
|
||||
br.call.sptk.few rp=sys32_execve
|
||||
1: cmp.ge p6,p0=r8,r0
|
||||
mov ar.pfs=loc1 // restore ar.pfs
|
||||
;;
|
||||
(p6) mov ar.pfs=r0 // clear ar.pfs in case of success
|
||||
sxt4 r8=r8 // return 64-bit result
|
||||
mov rp=loc0
|
||||
br.ret.sptk.few rp
|
||||
END(ia32_execve)
|
||||
|
||||
ENTRY(ia32_clone)
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
|
||||
alloc r16=ar.pfs,5,2,6,0
|
||||
DO_SAVE_SWITCH_STACK
|
||||
mov loc0=rp
|
||||
mov loc1=r16 // save ar.pfs across do_fork
|
||||
.body
|
||||
zxt4 out1=in1 // newsp
|
||||
mov out3=16 // stacksize (compensates for 16-byte scratch area)
|
||||
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s
|
||||
mov out0=in0 // out0 = clone_flags
|
||||
zxt4 out4=in2 // out4 = parent_tidptr
|
||||
zxt4 out5=in4 // out5 = child_tidptr
|
||||
br.call.sptk.many rp=do_fork
|
||||
.ret0: .restore sp
|
||||
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
|
||||
mov ar.pfs=loc1
|
||||
mov rp=loc0
|
||||
br.ret.sptk.many rp
|
||||
END(ia32_clone)
|
||||
|
||||
GLOBAL_ENTRY(ia32_ret_from_clone)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
{ /*
|
||||
* Some versions of gas generate bad unwind info if the first instruction of a
|
||||
* procedure doesn't go into the first slot of a bundle. This is a workaround.
|
||||
*/
|
||||
nop.m 0
|
||||
nop.i 0
|
||||
/*
|
||||
* We need to call schedule_tail() to complete the scheduling process.
|
||||
* Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
|
||||
* address of the previously executing task.
|
||||
*/
|
||||
br.call.sptk.many rp=ia64_invoke_schedule_tail
|
||||
}
|
||||
.ret1:
|
||||
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
ld4 r2=[r2]
|
||||
;;
|
||||
mov r8=0
|
||||
and r2=_TIF_SYSCALL_TRACEAUDIT,r2
|
||||
;;
|
||||
cmp.ne p6,p0=r2,r0
|
||||
(p6) br.cond.spnt .ia32_strace_check_retval
|
||||
;; // prevent RAW on r8
|
||||
END(ia32_ret_from_clone)
|
||||
// fall through
|
||||
GLOBAL_ENTRY(ia32_ret_from_syscall)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
|
||||
cmp.ge p6,p7=r8,r0 // syscall executed successfully?
|
||||
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
|
||||
;;
|
||||
alloc r3=ar.pfs,0,0,0,0 // drop the syscall argument frame
|
||||
st8 [r2]=r8 // store return value in slot for r8
|
||||
br.cond.sptk.many ia64_leave_kernel
|
||||
END(ia32_ret_from_syscall)
|
||||
|
||||
//
|
||||
// Invoke a system call, but do some tracing before and after the call.
|
||||
// We MUST preserve the current register frame throughout this routine
|
||||
// because some system calls (such as ia64_execve) directly
|
||||
// manipulate ar.pfs.
|
||||
//
|
||||
// Input:
|
||||
// r8 = syscall number
|
||||
// b6 = syscall entry point
|
||||
//
|
||||
GLOBAL_ENTRY(ia32_trace_syscall)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
mov r3=-38
|
||||
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
|
||||
;;
|
||||
st8 [r2]=r3 // initialize return code to -ENOSYS
|
||||
br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args
|
||||
cmp.lt p6,p0=r8,r0 // check tracehook
|
||||
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
|
||||
;;
|
||||
(p6) st8.spill [r2]=r8 // store return value in slot for r8
|
||||
(p6) br.spnt.few .ret4
|
||||
.ret2: // Need to reload arguments (they may be changed by the tracing process)
|
||||
adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1
|
||||
adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13
|
||||
mov r15=IA32_NR_syscalls
|
||||
;;
|
||||
ld4 r8=[r2],IA64_PT_REGS_R9_OFFSET-IA64_PT_REGS_R1_OFFSET
|
||||
movl r16=ia32_syscall_table
|
||||
;;
|
||||
ld4 r33=[r2],8 // r9 == ecx
|
||||
ld4 r37=[r3],16 // r13 == ebp
|
||||
cmp.ltu.unc p6,p7=r8,r15
|
||||
;;
|
||||
ld4 r34=[r2],8 // r10 == edx
|
||||
ld4 r36=[r3],8 // r15 == edi
|
||||
(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
|
||||
;;
|
||||
ld8 r16=[r16]
|
||||
;;
|
||||
ld4 r32=[r2],8 // r11 == ebx
|
||||
mov b6=r16
|
||||
ld4 r35=[r3],8 // r14 == esi
|
||||
br.call.sptk.few rp=b6 // do the syscall
|
||||
.ia32_strace_check_retval:
|
||||
cmp.lt p6,p0=r8,r0 // syscall failed?
|
||||
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
|
||||
;;
|
||||
st8.spill [r2]=r8 // store return value in slot for r8
|
||||
br.call.sptk.few rp=syscall_trace_leave // give parent a chance to catch return value
|
||||
.ret4: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
|
||||
br.cond.sptk.many ia64_leave_kernel
|
||||
END(ia32_trace_syscall)
|
||||
|
||||
GLOBAL_ENTRY(sys32_vfork)
|
||||
alloc r16=ar.pfs,2,2,4,0;;
|
||||
mov out0=IA64_CLONE_VFORK|IA64_CLONE_VM|SIGCHLD // out0 = clone_flags
|
||||
br.cond.sptk.few .fork1 // do the work
|
||||
END(sys32_vfork)
|
||||
|
||||
GLOBAL_ENTRY(sys32_fork)
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
|
||||
alloc r16=ar.pfs,2,2,4,0
|
||||
mov out0=SIGCHLD // out0 = clone_flags
|
||||
;;
|
||||
.fork1:
|
||||
mov loc0=rp
|
||||
mov loc1=r16 // save ar.pfs across do_fork
|
||||
DO_SAVE_SWITCH_STACK
|
||||
|
||||
.body
|
||||
|
||||
mov out1=0
|
||||
mov out3=0
|
||||
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s
|
||||
br.call.sptk.few rp=do_fork
|
||||
.ret5: .restore sp
|
||||
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
|
||||
mov ar.pfs=loc1
|
||||
mov rp=loc0
|
||||
br.ret.sptk.many rp
|
||||
END(sys32_fork)
|
||||
|
||||
.rodata
|
||||
.align 8
|
||||
.globl ia32_syscall_table
|
||||
ia32_syscall_table:
|
||||
data8 sys_ni_syscall /* 0 - old "setup(" system call*/
|
||||
data8 sys_exit
|
||||
data8 sys32_fork
|
||||
data8 sys_read
|
||||
data8 sys_write
|
||||
data8 compat_sys_open /* 5 */
|
||||
data8 sys_close
|
||||
data8 sys32_waitpid
|
||||
data8 sys_creat
|
||||
data8 sys_link
|
||||
data8 sys_unlink /* 10 */
|
||||
data8 ia32_execve
|
||||
data8 sys_chdir
|
||||
data8 compat_sys_time
|
||||
data8 sys_mknod
|
||||
data8 sys_chmod /* 15 */
|
||||
data8 sys_lchown /* 16-bit version */
|
||||
data8 sys_ni_syscall /* old break syscall holder */
|
||||
data8 sys_ni_syscall
|
||||
data8 sys32_lseek
|
||||
data8 sys_getpid /* 20 */
|
||||
data8 compat_sys_mount
|
||||
data8 sys_oldumount
|
||||
data8 sys_setuid /* 16-bit version */
|
||||
data8 sys_getuid /* 16-bit version */
|
||||
data8 compat_sys_stime /* 25 */
|
||||
data8 compat_sys_ptrace
|
||||
data8 sys32_alarm
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_pause
|
||||
data8 compat_sys_utime /* 30 */
|
||||
data8 sys_ni_syscall /* old stty syscall holder */
|
||||
data8 sys_ni_syscall /* old gtty syscall holder */
|
||||
data8 sys_access
|
||||
data8 sys_nice
|
||||
data8 sys_ni_syscall /* 35 */ /* old ftime syscall holder */
|
||||
data8 sys_sync
|
||||
data8 sys_kill
|
||||
data8 sys_rename
|
||||
data8 sys_mkdir
|
||||
data8 sys_rmdir /* 40 */
|
||||
data8 sys_dup
|
||||
data8 sys_ia64_pipe
|
||||
data8 compat_sys_times
|
||||
data8 sys_ni_syscall /* old prof syscall holder */
|
||||
data8 sys32_brk /* 45 */
|
||||
data8 sys_setgid /* 16-bit version */
|
||||
data8 sys_getgid /* 16-bit version */
|
||||
data8 sys32_signal
|
||||
data8 sys_geteuid /* 16-bit version */
|
||||
data8 sys_getegid /* 16-bit version */ /* 50 */
|
||||
data8 sys_acct
|
||||
data8 sys_umount /* recycled never used phys( */
|
||||
data8 sys_ni_syscall /* old lock syscall holder */
|
||||
data8 compat_sys_ioctl
|
||||
data8 compat_sys_fcntl /* 55 */
|
||||
data8 sys_ni_syscall /* old mpx syscall holder */
|
||||
data8 sys_setpgid
|
||||
data8 sys_ni_syscall /* old ulimit syscall holder */
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_umask /* 60 */
|
||||
data8 sys_chroot
|
||||
data8 compat_sys_ustat
|
||||
data8 sys_dup2
|
||||
data8 sys_getppid
|
||||
data8 sys_getpgrp /* 65 */
|
||||
data8 sys_setsid
|
||||
data8 sys32_sigaction
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_setreuid /* 16-bit version */ /* 70 */
|
||||
data8 sys_setregid /* 16-bit version */
|
||||
data8 sys32_sigsuspend
|
||||
data8 compat_sys_sigpending
|
||||
data8 sys_sethostname
|
||||
data8 compat_sys_setrlimit /* 75 */
|
||||
data8 compat_sys_old_getrlimit
|
||||
data8 compat_sys_getrusage
|
||||
data8 compat_sys_gettimeofday
|
||||
data8 compat_sys_settimeofday
|
||||
data8 sys32_getgroups16 /* 80 */
|
||||
data8 sys32_setgroups16
|
||||
data8 sys32_old_select
|
||||
data8 sys_symlink
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_readlink /* 85 */
|
||||
data8 sys_uselib
|
||||
data8 sys_swapon
|
||||
data8 sys_reboot
|
||||
data8 compat_sys_old_readdir
|
||||
data8 sys32_mmap /* 90 */
|
||||
data8 sys32_munmap
|
||||
data8 sys_truncate
|
||||
data8 sys_ftruncate
|
||||
data8 sys_fchmod
|
||||
data8 sys_fchown /* 16-bit version */ /* 95 */
|
||||
data8 sys_getpriority
|
||||
data8 sys_setpriority
|
||||
data8 sys_ni_syscall /* old profil syscall holder */
|
||||
data8 compat_sys_statfs
|
||||
data8 compat_sys_fstatfs /* 100 */
|
||||
data8 sys_ni_syscall /* ioperm */
|
||||
data8 compat_sys_socketcall
|
||||
data8 sys_syslog
|
||||
data8 compat_sys_setitimer
|
||||
data8 compat_sys_getitimer /* 105 */
|
||||
data8 compat_sys_newstat
|
||||
data8 compat_sys_newlstat
|
||||
data8 compat_sys_newfstat
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_ni_syscall /* iopl */ /* 110 */
|
||||
data8 sys_vhangup
|
||||
data8 sys_ni_syscall /* used to be sys_idle */
|
||||
data8 sys_ni_syscall
|
||||
data8 compat_sys_wait4
|
||||
data8 sys_swapoff /* 115 */
|
||||
data8 compat_sys_sysinfo
|
||||
data8 sys32_ipc
|
||||
data8 sys_fsync
|
||||
data8 sys32_sigreturn
|
||||
data8 ia32_clone /* 120 */
|
||||
data8 sys_setdomainname
|
||||
data8 sys32_newuname
|
||||
data8 sys32_modify_ldt
|
||||
data8 compat_sys_adjtimex
|
||||
data8 sys32_mprotect /* 125 */
|
||||
data8 compat_sys_sigprocmask
|
||||
data8 sys_ni_syscall /* create_module */
|
||||
data8 sys_ni_syscall /* init_module */
|
||||
data8 sys_ni_syscall /* delete_module */
|
||||
data8 sys_ni_syscall /* get_kernel_syms */ /* 130 */
|
||||
data8 sys32_quotactl
|
||||
data8 sys_getpgid
|
||||
data8 sys_fchdir
|
||||
data8 sys_ni_syscall /* sys_bdflush */
|
||||
data8 sys_sysfs /* 135 */
|
||||
data8 sys32_personality
|
||||
data8 sys_ni_syscall /* for afs_syscall */
|
||||
data8 sys_setfsuid /* 16-bit version */
|
||||
data8 sys_setfsgid /* 16-bit version */
|
||||
data8 sys_llseek /* 140 */
|
||||
data8 compat_sys_getdents
|
||||
data8 compat_sys_select
|
||||
data8 sys_flock
|
||||
data8 sys32_msync
|
||||
data8 compat_sys_readv /* 145 */
|
||||
data8 compat_sys_writev
|
||||
data8 sys_getsid
|
||||
data8 sys_fdatasync
|
||||
data8 compat_sys_sysctl
|
||||
data8 sys_mlock /* 150 */
|
||||
data8 sys_munlock
|
||||
data8 sys_mlockall
|
||||
data8 sys_munlockall
|
||||
data8 sys_sched_setparam
|
||||
data8 sys_sched_getparam /* 155 */
|
||||
data8 sys_sched_setscheduler
|
||||
data8 sys_sched_getscheduler
|
||||
data8 sys_sched_yield
|
||||
data8 sys_sched_get_priority_max
|
||||
data8 sys_sched_get_priority_min /* 160 */
|
||||
data8 sys32_sched_rr_get_interval
|
||||
data8 compat_sys_nanosleep
|
||||
data8 sys32_mremap
|
||||
data8 sys_setresuid /* 16-bit version */
|
||||
data8 sys32_getresuid16 /* 16-bit version */ /* 165 */
|
||||
data8 sys_ni_syscall /* vm86 */
|
||||
data8 sys_ni_syscall /* sys_query_module */
|
||||
data8 sys_poll
|
||||
data8 sys_ni_syscall /* nfsservctl */
|
||||
data8 sys_setresgid /* 170 */
|
||||
data8 sys32_getresgid16
|
||||
data8 sys_prctl
|
||||
data8 sys32_rt_sigreturn
|
||||
data8 sys32_rt_sigaction
|
||||
data8 sys32_rt_sigprocmask /* 175 */
|
||||
data8 sys_rt_sigpending
|
||||
data8 compat_sys_rt_sigtimedwait
|
||||
data8 sys32_rt_sigqueueinfo
|
||||
data8 compat_sys_rt_sigsuspend
|
||||
data8 sys32_pread /* 180 */
|
||||
data8 sys32_pwrite
|
||||
data8 sys_chown /* 16-bit version */
|
||||
data8 sys_getcwd
|
||||
data8 sys_capget
|
||||
data8 sys_capset /* 185 */
|
||||
data8 sys32_sigaltstack
|
||||
data8 sys32_sendfile
|
||||
data8 sys_ni_syscall /* streams1 */
|
||||
data8 sys_ni_syscall /* streams2 */
|
||||
data8 sys32_vfork /* 190 */
|
||||
data8 compat_sys_getrlimit
|
||||
data8 sys32_mmap2
|
||||
data8 sys32_truncate64
|
||||
data8 sys32_ftruncate64
|
||||
data8 sys32_stat64 /* 195 */
|
||||
data8 sys32_lstat64
|
||||
data8 sys32_fstat64
|
||||
data8 sys_lchown
|
||||
data8 sys_getuid
|
||||
data8 sys_getgid /* 200 */
|
||||
data8 sys_geteuid
|
||||
data8 sys_getegid
|
||||
data8 sys_setreuid
|
||||
data8 sys_setregid
|
||||
data8 sys_getgroups /* 205 */
|
||||
data8 sys_setgroups
|
||||
data8 sys_fchown
|
||||
data8 sys_setresuid
|
||||
data8 sys_getresuid
|
||||
data8 sys_setresgid /* 210 */
|
||||
data8 sys_getresgid
|
||||
data8 sys_chown
|
||||
data8 sys_setuid
|
||||
data8 sys_setgid
|
||||
data8 sys_setfsuid /* 215 */
|
||||
data8 sys_setfsgid
|
||||
data8 sys_pivot_root
|
||||
data8 sys_mincore
|
||||
data8 sys_madvise
|
||||
data8 compat_sys_getdents64 /* 220 */
|
||||
data8 compat_sys_fcntl64
|
||||
data8 sys_ni_syscall /* reserved for TUX */
|
||||
data8 sys_ni_syscall /* reserved for Security */
|
||||
data8 sys_gettid
|
||||
data8 sys_readahead /* 225 */
|
||||
data8 sys_setxattr
|
||||
data8 sys_lsetxattr
|
||||
data8 sys_fsetxattr
|
||||
data8 sys_getxattr
|
||||
data8 sys_lgetxattr /* 230 */
|
||||
data8 sys_fgetxattr
|
||||
data8 sys_listxattr
|
||||
data8 sys_llistxattr
|
||||
data8 sys_flistxattr
|
||||
data8 sys_removexattr /* 235 */
|
||||
data8 sys_lremovexattr
|
||||
data8 sys_fremovexattr
|
||||
data8 sys_tkill
|
||||
data8 sys_sendfile64
|
||||
data8 compat_sys_futex /* 240 */
|
||||
data8 compat_sys_sched_setaffinity
|
||||
data8 compat_sys_sched_getaffinity
|
||||
data8 sys32_set_thread_area
|
||||
data8 sys32_get_thread_area
|
||||
data8 compat_sys_io_setup /* 245 */
|
||||
data8 sys_io_destroy
|
||||
data8 compat_sys_io_getevents
|
||||
data8 compat_sys_io_submit
|
||||
data8 sys_io_cancel
|
||||
data8 sys_fadvise64 /* 250 */
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_exit_group
|
||||
data8 sys_lookup_dcookie
|
||||
data8 sys_epoll_create
|
||||
data8 sys32_epoll_ctl /* 255 */
|
||||
data8 sys32_epoll_wait
|
||||
data8 sys_remap_file_pages
|
||||
data8 sys_set_tid_address
|
||||
data8 compat_sys_timer_create
|
||||
data8 compat_sys_timer_settime /* 260 */
|
||||
data8 compat_sys_timer_gettime
|
||||
data8 sys_timer_getoverrun
|
||||
data8 sys_timer_delete
|
||||
data8 compat_sys_clock_settime
|
||||
data8 compat_sys_clock_gettime /* 265 */
|
||||
data8 compat_sys_clock_getres
|
||||
data8 compat_sys_clock_nanosleep
|
||||
data8 compat_sys_statfs64
|
||||
data8 compat_sys_fstatfs64
|
||||
data8 sys_tgkill /* 270 */
|
||||
data8 compat_sys_utimes
|
||||
data8 sys32_fadvise64_64
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_ni_syscall
|
||||
data8 sys_ni_syscall /* 275 */
|
||||
data8 sys_ni_syscall
|
||||
data8 compat_sys_mq_open
|
||||
data8 sys_mq_unlink
|
||||
data8 compat_sys_mq_timedsend
|
||||
data8 compat_sys_mq_timedreceive /* 280 */
|
||||
data8 compat_sys_mq_notify
|
||||
data8 compat_sys_mq_getsetattr
|
||||
data8 sys_ni_syscall /* reserved for kexec */
|
||||
data8 compat_sys_waitid
|
||||
|
||||
// guard against failures to increase IA32_NR_syscalls
|
||||
.org ia32_syscall_table + 8*IA32_NR_syscalls
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2001, 2004 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* Adapted from arch/i386/kernel/ldt.c
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "ia32priv.h"
|
||||
|
||||
/*
|
||||
* read_ldt() is not really atomic - this is not a problem since synchronization of reads
|
||||
* and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
|
||||
* to protect the security checks done on new descriptors.
|
||||
*/
|
||||
static int
|
||||
read_ldt (void __user *ptr, unsigned long bytecount)
|
||||
{
|
||||
unsigned long bytes_left, n;
|
||||
char __user *src, *dst;
|
||||
char buf[256]; /* temporary buffer (don't overflow kernel stack!) */
|
||||
|
||||
if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
|
||||
bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
|
||||
|
||||
bytes_left = bytecount;
|
||||
|
||||
src = (void __user *) IA32_LDT_OFFSET;
|
||||
dst = ptr;
|
||||
|
||||
while (bytes_left) {
|
||||
n = sizeof(buf);
|
||||
if (n > bytes_left)
|
||||
n = bytes_left;
|
||||
|
||||
/*
|
||||
* We know we're reading valid memory, but we still must guard against
|
||||
* running out of memory.
|
||||
*/
|
||||
if (__copy_from_user(buf, src, n))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_to_user(dst, buf, n))
|
||||
return -EFAULT;
|
||||
|
||||
src += n;
|
||||
dst += n;
|
||||
bytes_left -= n;
|
||||
}
|
||||
return bytecount;
|
||||
}
|
||||
|
||||
static int
|
||||
read_default_ldt (void __user * ptr, unsigned long bytecount)
|
||||
{
|
||||
unsigned long size;
|
||||
int err;
|
||||
|
||||
/* XXX fix me: should return equivalent of default_ldt[0] */
|
||||
err = 0;
|
||||
size = 8;
|
||||
if (size > bytecount)
|
||||
size = bytecount;
|
||||
|
||||
err = size;
|
||||
if (clear_user(ptr, size))
|
||||
err = -EFAULT;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
write_ldt (void __user * ptr, unsigned long bytecount, int oldmode)
|
||||
{
|
||||
struct ia32_user_desc ldt_info;
|
||||
__u64 entry;
|
||||
int ret;
|
||||
|
||||
if (bytecount != sizeof(ldt_info))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
|
||||
return -EFAULT;
|
||||
|
||||
if (ldt_info.entry_number >= IA32_LDT_ENTRIES)
|
||||
return -EINVAL;
|
||||
if (ldt_info.contents == 3) {
|
||||
if (oldmode)
|
||||
return -EINVAL;
|
||||
if (ldt_info.seg_not_present == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ldt_info.base_addr == 0 && ldt_info.limit == 0
|
||||
&& (oldmode || (ldt_info.contents == 0 && ldt_info.read_exec_only == 1
|
||||
&& ldt_info.seg_32bit == 0 && ldt_info.limit_in_pages == 0
|
||||
&& ldt_info.seg_not_present == 1 && ldt_info.useable == 0)))
|
||||
/* allow LDTs to be cleared by the user */
|
||||
entry = 0;
|
||||
else
|
||||
/* we must set the "Accessed" bit as IVE doesn't emulate it */
|
||||
entry = IA32_SEG_DESCRIPTOR(ldt_info.base_addr, ldt_info.limit,
|
||||
(((ldt_info.read_exec_only ^ 1) << 1)
|
||||
| (ldt_info.contents << 2)) | 1,
|
||||
1, 3, ldt_info.seg_not_present ^ 1,
|
||||
(oldmode ? 0 : ldt_info.useable),
|
||||
ldt_info.seg_32bit,
|
||||
ldt_info.limit_in_pages);
|
||||
/*
|
||||
* Install the new entry. We know we're accessing valid (mapped) user-level
|
||||
* memory, but we still need to guard against out-of-memory, hence we must use
|
||||
* put_user().
|
||||
*/
|
||||
ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number);
|
||||
ia32_load_segment_descriptors(current);
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
|
||||
{
|
||||
int ret = -ENOSYS;
|
||||
|
||||
switch (func) {
|
||||
case 0:
|
||||
ret = read_ldt(compat_ptr(ptr), bytecount);
|
||||
break;
|
||||
case 1:
|
||||
ret = write_ldt(compat_ptr(ptr), bytecount, 1);
|
||||
break;
|
||||
case 2:
|
||||
ret = read_default_ldt(compat_ptr(ptr), bytecount);
|
||||
break;
|
||||
case 0x11:
|
||||
ret = write_ldt(compat_ptr(ptr), bytecount, 0);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* IA32 helper functions
|
||||
*
|
||||
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
|
||||
* Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* 06/16/00 A. Mallick added csd/ssd/tssd for ia32 thread context
|
||||
* 02/19/01 D. Mosberger dropped tssd; it's not needed
|
||||
* 09/14/01 D. Mosberger fixed memory management for gdt/tss page
|
||||
* 09/29/01 D. Mosberger added ia32_load_segment_descriptors()
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "ia32priv.h"
|
||||
|
||||
extern int die_if_kernel (char *str, struct pt_regs *regs, long err);
|
||||
|
||||
struct page *ia32_shared_page[NR_CPUS];
|
||||
unsigned long *ia32_boot_gdt;
|
||||
unsigned long *cpu_gdt_table[NR_CPUS];
|
||||
struct page *ia32_gate_page;
|
||||
|
||||
static unsigned long
|
||||
load_desc (u16 selector)
|
||||
{
|
||||
unsigned long *table, limit, index;
|
||||
|
||||
if (!selector)
|
||||
return 0;
|
||||
if (selector & IA32_SEGSEL_TI) {
|
||||
table = (unsigned long *) IA32_LDT_OFFSET;
|
||||
limit = IA32_LDT_ENTRIES;
|
||||
} else {
|
||||
table = cpu_gdt_table[smp_processor_id()];
|
||||
limit = IA32_PAGE_SIZE / sizeof(ia32_boot_gdt[0]);
|
||||
}
|
||||
index = selector >> IA32_SEGSEL_INDEX_SHIFT;
|
||||
if (index >= limit)
|
||||
return 0;
|
||||
return IA32_SEG_UNSCRAMBLE(table[index]);
|
||||
}
|
||||
|
||||
void
|
||||
ia32_load_segment_descriptors (struct task_struct *task)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(task);
|
||||
|
||||
/* Setup the segment descriptors */
|
||||
regs->r24 = load_desc(regs->r16 >> 16); /* ESD */
|
||||
regs->r27 = load_desc(regs->r16 >> 0); /* DSD */
|
||||
regs->r28 = load_desc(regs->r16 >> 32); /* FSD */
|
||||
regs->r29 = load_desc(regs->r16 >> 48); /* GSD */
|
||||
regs->ar_csd = load_desc(regs->r17 >> 0); /* CSD */
|
||||
regs->ar_ssd = load_desc(regs->r17 >> 16); /* SSD */
|
||||
}
|
||||
|
||||
int
|
||||
ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs)
|
||||
{
|
||||
struct desc_struct *desc;
|
||||
struct ia32_user_desc info;
|
||||
int idx;
|
||||
|
||||
if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info)))
|
||||
return -EFAULT;
|
||||
if (LDT_empty(&info))
|
||||
return -EINVAL;
|
||||
|
||||
idx = info.entry_number;
|
||||
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
|
||||
desc->a = LDT_entry_a(&info);
|
||||
desc->b = LDT_entry_b(&info);
|
||||
|
||||
/* XXX: can this be done in a cleaner way ? */
|
||||
load_TLS(&child->thread, smp_processor_id());
|
||||
ia32_load_segment_descriptors(child);
|
||||
load_TLS(¤t->thread, smp_processor_id());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ia32_save_state (struct task_struct *t)
|
||||
{
|
||||
t->thread.eflag = ia64_getreg(_IA64_REG_AR_EFLAG);
|
||||
t->thread.fsr = ia64_getreg(_IA64_REG_AR_FSR);
|
||||
t->thread.fcr = ia64_getreg(_IA64_REG_AR_FCR);
|
||||
t->thread.fir = ia64_getreg(_IA64_REG_AR_FIR);
|
||||
t->thread.fdr = ia64_getreg(_IA64_REG_AR_FDR);
|
||||
ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
|
||||
ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1);
|
||||
}
|
||||
|
||||
void
|
||||
ia32_load_state (struct task_struct *t)
|
||||
{
|
||||
unsigned long eflag, fsr, fcr, fir, fdr, tssd;
|
||||
struct pt_regs *regs = task_pt_regs(t);
|
||||
|
||||
eflag = t->thread.eflag;
|
||||
fsr = t->thread.fsr;
|
||||
fcr = t->thread.fcr;
|
||||
fir = t->thread.fir;
|
||||
fdr = t->thread.fdr;
|
||||
tssd = load_desc(_TSS); /* TSSD */
|
||||
|
||||
ia64_setreg(_IA64_REG_AR_EFLAG, eflag);
|
||||
ia64_setreg(_IA64_REG_AR_FSR, fsr);
|
||||
ia64_setreg(_IA64_REG_AR_FCR, fcr);
|
||||
ia64_setreg(_IA64_REG_AR_FIR, fir);
|
||||
ia64_setreg(_IA64_REG_AR_FDR, fdr);
|
||||
current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
|
||||
current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD);
|
||||
ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
|
||||
ia64_set_kr(IA64_KR_TSSD, tssd);
|
||||
|
||||
regs->r17 = (_TSS << 48) | (_LDT << 32) | (__u32) regs->r17;
|
||||
regs->r30 = load_desc(_LDT); /* LDTD */
|
||||
load_TLS(&t->thread, smp_processor_id());
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup IA32 GDT and TSS
|
||||
*/
|
||||
void
|
||||
ia32_gdt_init (void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
ia32_shared_page[cpu] = alloc_page(GFP_KERNEL);
|
||||
if (!ia32_shared_page[cpu])
|
||||
panic("failed to allocate ia32_shared_page[%d]\n", cpu);
|
||||
|
||||
cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]);
|
||||
|
||||
/* Copy from the boot cpu's GDT */
|
||||
memcpy(cpu_gdt_table[cpu], ia32_boot_gdt, PAGE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup IA32 GDT and TSS
|
||||
*/
|
||||
static void
|
||||
ia32_boot_gdt_init (void)
|
||||
{
|
||||
unsigned long ldt_size;
|
||||
|
||||
ia32_shared_page[0] = alloc_page(GFP_KERNEL);
|
||||
if (!ia32_shared_page[0])
|
||||
panic("failed to allocate ia32_shared_page[0]\n");
|
||||
|
||||
ia32_boot_gdt = page_address(ia32_shared_page[0]);
|
||||
cpu_gdt_table[0] = ia32_boot_gdt;
|
||||
|
||||
/* CS descriptor in IA-32 (scrambled) format */
|
||||
ia32_boot_gdt[__USER_CS >> 3]
|
||||
= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
|
||||
0xb, 1, 3, 1, 1, 1, 1);
|
||||
|
||||
/* DS descriptor in IA-32 (scrambled) format */
|
||||
ia32_boot_gdt[__USER_DS >> 3]
|
||||
= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
|
||||
0x3, 1, 3, 1, 1, 1, 1);
|
||||
|
||||
ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
|
||||
ia32_boot_gdt[TSS_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
|
||||
0xb, 0, 3, 1, 1, 1, 0);
|
||||
ia32_boot_gdt[LDT_ENTRY] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
|
||||
0x2, 0, 3, 1, 1, 1, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ia32_gate_page_init(void)
|
||||
{
|
||||
unsigned long *sr;
|
||||
|
||||
ia32_gate_page = alloc_page(GFP_KERNEL);
|
||||
sr = page_address(ia32_gate_page);
|
||||
/* This is popl %eax ; movl $,%eax ; int $0x80 */
|
||||
*sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48);
|
||||
|
||||
/* This is movl $,%eax ; int $0x80 */
|
||||
*sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40);
|
||||
}
|
||||
|
||||
void
|
||||
ia32_mem_init(void)
|
||||
{
|
||||
ia32_boot_gdt_init();
|
||||
ia32_gate_page_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle bad IA32 interrupt via syscall
|
||||
*/
|
||||
void
|
||||
ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t siginfo;
|
||||
|
||||
if (die_if_kernel("Bad IA-32 interrupt", regs, int_num))
|
||||
return;
|
||||
|
||||
siginfo.si_signo = SIGTRAP;
|
||||
siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */
|
||||
siginfo.si_flags = 0;
|
||||
siginfo.si_isr = 0;
|
||||
siginfo.si_addr = NULL;
|
||||
siginfo.si_imm = 0;
|
||||
siginfo.si_code = TRAP_BRKPT;
|
||||
force_sig_info(SIGTRAP, &siginfo, current);
|
||||
}
|
||||
|
||||
void
|
||||
ia32_cpu_init (void)
|
||||
{
|
||||
/* initialize global ia32 state - CR0 and CR4 */
|
||||
ia64_setreg(_IA64_REG_AR_CFLAG, (((ulong) IA32_CR4 << 32) | IA32_CR0));
|
||||
}
|
||||
|
||||
static int __init
|
||||
ia32_init (void)
|
||||
{
|
||||
#if PAGE_SHIFT > IA32_PAGE_SHIFT
|
||||
{
|
||||
extern struct kmem_cache *ia64_partial_page_cachep;
|
||||
|
||||
ia64_partial_page_cachep = kmem_cache_create("ia64_partial_page_cache",
|
||||
sizeof(struct ia64_partial_page),
|
||||
0, SLAB_PANIC, NULL);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(ia32_init);
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* IA-32 exception handlers
|
||||
*
|
||||
* Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
|
||||
* Copyright (C) 2001-2002 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* 06/16/00 A. Mallick added siginfo for most cases (close to IA32)
|
||||
* 09/29/00 D. Mosberger added ia32_intercept()
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "ia32priv.h"
|
||||
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
int
|
||||
ia32_intercept (struct pt_regs *regs, unsigned long isr)
|
||||
{
|
||||
switch ((isr >> 16) & 0xff) {
|
||||
case 0: /* Instruction intercept fault */
|
||||
case 4: /* Locked Data reference fault */
|
||||
case 1: /* Gate intercept trap */
|
||||
return -1;
|
||||
|
||||
case 2: /* System flag trap */
|
||||
if (((isr >> 14) & 0x3) >= 2) {
|
||||
/* MOV SS, POP SS instructions */
|
||||
ia64_psr(regs)->id = 1;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ia32_exception (struct pt_regs *regs, unsigned long isr)
|
||||
{
|
||||
struct siginfo siginfo;
|
||||
|
||||
/* initialize these fields to avoid leaking kernel bits to user space: */
|
||||
siginfo.si_errno = 0;
|
||||
siginfo.si_flags = 0;
|
||||
siginfo.si_isr = 0;
|
||||
siginfo.si_imm = 0;
|
||||
switch ((isr >> 16) & 0xff) {
|
||||
case 1:
|
||||
case 2:
|
||||
siginfo.si_signo = SIGTRAP;
|
||||
if (isr == 0)
|
||||
siginfo.si_code = TRAP_TRACE;
|
||||
else if (isr & 0x4)
|
||||
siginfo.si_code = TRAP_BRANCH;
|
||||
else
|
||||
siginfo.si_code = TRAP_BRKPT;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
siginfo.si_signo = SIGTRAP;
|
||||
siginfo.si_code = TRAP_BRKPT;
|
||||
break;
|
||||
|
||||
case 0: /* Divide fault */
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_code = FPE_INTDIV;
|
||||
break;
|
||||
|
||||
case 4: /* Overflow */
|
||||
case 5: /* Bounds fault */
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_code = 0;
|
||||
break;
|
||||
|
||||
case 6: /* Invalid Op-code */
|
||||
siginfo.si_signo = SIGILL;
|
||||
siginfo.si_code = ILL_ILLOPN;
|
||||
break;
|
||||
|
||||
case 7: /* FP DNA */
|
||||
case 8: /* Double Fault */
|
||||
case 9: /* Invalid TSS */
|
||||
case 11: /* Segment not present */
|
||||
case 12: /* Stack fault */
|
||||
case 13: /* General Protection Fault */
|
||||
siginfo.si_signo = SIGSEGV;
|
||||
siginfo.si_code = 0;
|
||||
break;
|
||||
|
||||
case 16: /* Pending FP error */
|
||||
{
|
||||
unsigned long fsr, fcr;
|
||||
|
||||
fsr = ia64_getreg(_IA64_REG_AR_FSR);
|
||||
fcr = ia64_getreg(_IA64_REG_AR_FCR);
|
||||
|
||||
siginfo.si_signo = SIGFPE;
|
||||
/*
|
||||
* (~cwd & swd) will mask out exceptions that are not set to unmasked
|
||||
* status. 0x3f is the exception bits in these regs, 0x200 is the
|
||||
* C1 reg you need in case of a stack fault, 0x040 is the stack
|
||||
* fault bit. We should only be taking one exception at a time,
|
||||
* so if this combination doesn't produce any single exception,
|
||||
* then we have a bad program that isn't synchronizing its FPU usage
|
||||
* and it will suffer the consequences since we won't be able to
|
||||
* fully reproduce the context of the exception
|
||||
*/
|
||||
siginfo.si_isr = isr;
|
||||
siginfo.si_flags = __ISR_VALID;
|
||||
switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
|
||||
case 0x000:
|
||||
default:
|
||||
siginfo.si_code = 0;
|
||||
break;
|
||||
case 0x001: /* Invalid Op */
|
||||
case 0x040: /* Stack Fault */
|
||||
case 0x240: /* Stack Fault | Direction */
|
||||
siginfo.si_code = FPE_FLTINV;
|
||||
break;
|
||||
case 0x002: /* Denormalize */
|
||||
case 0x010: /* Underflow */
|
||||
siginfo.si_code = FPE_FLTUND;
|
||||
break;
|
||||
case 0x004: /* Zero Divide */
|
||||
siginfo.si_code = FPE_FLTDIV;
|
||||
break;
|
||||
case 0x008: /* Overflow */
|
||||
siginfo.si_code = FPE_FLTOVF;
|
||||
break;
|
||||
case 0x020: /* Precision */
|
||||
siginfo.si_code = FPE_FLTRES;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 17: /* Alignment check */
|
||||
siginfo.si_signo = SIGSEGV;
|
||||
siginfo.si_code = BUS_ADRALN;
|
||||
break;
|
||||
|
||||
case 19: /* SSE Numeric error */
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_code = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
force_sig_info(siginfo.si_signo, &siginfo, current);
|
||||
return 0;
|
||||
}
|
|
@ -1,532 +0,0 @@
|
|||
#ifndef _ASM_IA64_IA32_PRIV_H
|
||||
#define _ASM_IA64_IA32_PRIV_H
|
||||
|
||||
|
||||
#include <asm/ia32.h>
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
/*
|
||||
* 32 bit structures for IA32 support.
|
||||
*/
|
||||
|
||||
#define IA32_PAGE_SIZE (1UL << IA32_PAGE_SHIFT)
|
||||
#define IA32_PAGE_MASK (~(IA32_PAGE_SIZE - 1))
|
||||
#define IA32_PAGE_ALIGN(addr) (((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK)
|
||||
#define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */
|
||||
|
||||
/*
|
||||
* partially mapped pages provide precise accounting of which 4k sub pages
|
||||
* are mapped and which ones are not, thereby improving IA-32 compatibility.
|
||||
*/
|
||||
struct ia64_partial_page {
|
||||
struct ia64_partial_page *next; /* linked list, sorted by address */
|
||||
struct rb_node pp_rb;
|
||||
/* 64K is the largest "normal" page supported by ia64 ABI. So 4K*64
|
||||
* should suffice.*/
|
||||
unsigned long bitmap;
|
||||
unsigned int base;
|
||||
};
|
||||
|
||||
struct ia64_partial_page_list {
|
||||
struct ia64_partial_page *pp_head; /* list head, points to the lowest
|
||||
* addressed partial page */
|
||||
struct rb_root ppl_rb;
|
||||
struct ia64_partial_page *pp_hint; /* pp_hint->next is the last
|
||||
* accessed partial page */
|
||||
atomic_t pp_count; /* reference count */
|
||||
};
|
||||
|
||||
#if PAGE_SHIFT > IA32_PAGE_SHIFT
|
||||
struct ia64_partial_page_list* ia32_init_pp_list (void);
|
||||
#else
|
||||
# define ia32_init_pp_list() 0
|
||||
#endif
|
||||
|
||||
/* sigcontext.h */
|
||||
/*
|
||||
* As documented in the iBCS2 standard..
|
||||
*
|
||||
* The first part of "struct _fpstate" is just the
|
||||
* normal i387 hardware setup, the extra "status"
|
||||
* word is used to save the coprocessor status word
|
||||
* before entering the handler.
|
||||
*/
|
||||
struct _fpreg_ia32 {
|
||||
unsigned short significand[4];
|
||||
unsigned short exponent;
|
||||
};
|
||||
|
||||
struct _fpxreg_ia32 {
|
||||
unsigned short significand[4];
|
||||
unsigned short exponent;
|
||||
unsigned short padding[3];
|
||||
};
|
||||
|
||||
struct _xmmreg_ia32 {
|
||||
unsigned int element[4];
|
||||
};
|
||||
|
||||
|
||||
struct _fpstate_ia32 {
|
||||
unsigned int cw,
|
||||
sw,
|
||||
tag,
|
||||
ipoff,
|
||||
cssel,
|
||||
dataoff,
|
||||
datasel;
|
||||
struct _fpreg_ia32 _st[8];
|
||||
unsigned short status;
|
||||
unsigned short magic; /* 0xffff = regular FPU data only */
|
||||
|
||||
/* FXSR FPU environment */
|
||||
unsigned int _fxsr_env[6]; /* FXSR FPU env is ignored */
|
||||
unsigned int mxcsr;
|
||||
unsigned int reserved;
|
||||
struct _fpxreg_ia32 _fxsr_st[8]; /* FXSR FPU reg data is ignored */
|
||||
struct _xmmreg_ia32 _xmm[8];
|
||||
unsigned int padding[56];
|
||||
};
|
||||
|
||||
struct sigcontext_ia32 {
|
||||
unsigned short gs, __gsh;
|
||||
unsigned short fs, __fsh;
|
||||
unsigned short es, __esh;
|
||||
unsigned short ds, __dsh;
|
||||
unsigned int edi;
|
||||
unsigned int esi;
|
||||
unsigned int ebp;
|
||||
unsigned int esp;
|
||||
unsigned int ebx;
|
||||
unsigned int edx;
|
||||
unsigned int ecx;
|
||||
unsigned int eax;
|
||||
unsigned int trapno;
|
||||
unsigned int err;
|
||||
unsigned int eip;
|
||||
unsigned short cs, __csh;
|
||||
unsigned int eflags;
|
||||
unsigned int esp_at_signal;
|
||||
unsigned short ss, __ssh;
|
||||
unsigned int fpstate; /* really (struct _fpstate_ia32 *) */
|
||||
unsigned int oldmask;
|
||||
unsigned int cr2;
|
||||
};
|
||||
|
||||
/* user.h */
|
||||
/*
|
||||
* IA32 (Pentium III/4) FXSR, SSE support
|
||||
*
|
||||
* Provide support for the GDB 5.0+ PTRACE_{GET|SET}FPXREGS requests for
|
||||
* interacting with the FXSR-format floating point environment. Floating
|
||||
* point data can be accessed in the regular format in the usual manner,
|
||||
* and both the standard and SIMD floating point data can be accessed via
|
||||
* the new ptrace requests. In either case, changes to the FPU environment
|
||||
* will be reflected in the task's state as expected.
|
||||
*/
|
||||
struct ia32_user_i387_struct {
|
||||
int cwd;
|
||||
int swd;
|
||||
int twd;
|
||||
int fip;
|
||||
int fcs;
|
||||
int foo;
|
||||
int fos;
|
||||
/* 8*10 bytes for each FP-reg = 80 bytes */
|
||||
struct _fpreg_ia32 st_space[8];
|
||||
};
|
||||
|
||||
struct ia32_user_fxsr_struct {
|
||||
unsigned short cwd;
|
||||
unsigned short swd;
|
||||
unsigned short twd;
|
||||
unsigned short fop;
|
||||
int fip;
|
||||
int fcs;
|
||||
int foo;
|
||||
int fos;
|
||||
int mxcsr;
|
||||
int reserved;
|
||||
int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
|
||||
int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */
|
||||
int padding[56];
|
||||
};
|
||||
|
||||
/* signal.h */
|
||||
#define IA32_SET_SA_HANDLER(ka,handler,restorer) \
|
||||
((ka)->sa.sa_handler = (__sighandler_t) \
|
||||
(((unsigned long)(restorer) << 32) \
|
||||
| ((handler) & 0xffffffff)))
|
||||
#define IA32_SA_HANDLER(ka) ((unsigned long) (ka)->sa.sa_handler & 0xffffffff)
|
||||
#define IA32_SA_RESTORER(ka) ((unsigned long) (ka)->sa.sa_handler >> 32)
|
||||
|
||||
#define __IA32_NR_sigreturn 119
|
||||
#define __IA32_NR_rt_sigreturn 173
|
||||
|
||||
struct sigaction32 {
|
||||
unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */
|
||||
unsigned int sa_flags;
|
||||
unsigned int sa_restorer; /* Another 32 bit pointer */
|
||||
compat_sigset_t sa_mask; /* A 32 bit mask */
|
||||
};
|
||||
|
||||
struct old_sigaction32 {
|
||||
unsigned int sa_handler; /* Really a pointer, but need to deal
|
||||
with 32 bits */
|
||||
compat_old_sigset_t sa_mask; /* A 32 bit mask */
|
||||
unsigned int sa_flags;
|
||||
unsigned int sa_restorer; /* Another 32 bit pointer */
|
||||
};
|
||||
|
||||
typedef struct sigaltstack_ia32 {
|
||||
unsigned int ss_sp;
|
||||
int ss_flags;
|
||||
unsigned int ss_size;
|
||||
} stack_ia32_t;
|
||||
|
||||
struct ucontext_ia32 {
|
||||
unsigned int uc_flags;
|
||||
unsigned int uc_link;
|
||||
stack_ia32_t uc_stack;
|
||||
struct sigcontext_ia32 uc_mcontext;
|
||||
sigset_t uc_sigmask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
struct stat64 {
|
||||
unsigned long long st_dev;
|
||||
unsigned char __pad0[4];
|
||||
unsigned int __st_ino;
|
||||
unsigned int st_mode;
|
||||
unsigned int st_nlink;
|
||||
unsigned int st_uid;
|
||||
unsigned int st_gid;
|
||||
unsigned long long st_rdev;
|
||||
unsigned char __pad3[4];
|
||||
unsigned int st_size_lo;
|
||||
unsigned int st_size_hi;
|
||||
unsigned int st_blksize;
|
||||
unsigned int st_blocks; /* Number 512-byte blocks allocated. */
|
||||
unsigned int __pad4; /* future possible st_blocks high bits */
|
||||
unsigned int st_atime;
|
||||
unsigned int st_atime_nsec;
|
||||
unsigned int st_mtime;
|
||||
unsigned int st_mtime_nsec;
|
||||
unsigned int st_ctime;
|
||||
unsigned int st_ctime_nsec;
|
||||
unsigned int st_ino_lo;
|
||||
unsigned int st_ino_hi;
|
||||
};
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[((128/sizeof(int)) - 3)];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
char _pad[sizeof(unsigned int) - sizeof(int)];
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
unsigned int _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
unsigned int _addr; /* faulting insn/memory ref. */
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
/*
|
||||
* IA-32 ELF specific definitions for IA-64.
|
||||
*/
|
||||
|
||||
#define _ASM_IA64_ELF_H /* Don't include elf.h */
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
#define elf_check_arch(x) ((x)->e_machine == EM_386)
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_DATA ELFDATA2LSB
|
||||
#define ELF_ARCH EM_386
|
||||
|
||||
#define IA32_STACK_TOP IA32_PAGE_OFFSET
|
||||
#define IA32_GATE_OFFSET IA32_PAGE_OFFSET
|
||||
#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
|
||||
|
||||
/*
|
||||
* The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
|
||||
* access them.
|
||||
*/
|
||||
#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
|
||||
#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
|
||||
#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE)
|
||||
|
||||
#define ELF_EXEC_PAGESIZE IA32_PAGE_SIZE
|
||||
|
||||
/*
|
||||
* This is the location that an ET_DYN program is loaded if exec'ed.
|
||||
* Typical use of this is to invoke "./ld.so someprog" to test out a
|
||||
* new version of the loader. We need to make sure that it is out of
|
||||
* the way of the program that it will "exec", and that there is
|
||||
* sufficient room for the brk.
|
||||
*/
|
||||
#define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000)
|
||||
|
||||
void ia64_elf32_init(struct pt_regs *regs);
|
||||
#define ELF_PLAT_INIT(_r, load_addr) ia64_elf32_init(_r)
|
||||
|
||||
/* This macro yields a bitmask that programs can use to figure out
|
||||
what instruction set this CPU supports. */
|
||||
#define ELF_HWCAP 0
|
||||
|
||||
/* This macro yields a string that ld.so will use to load
|
||||
implementation specific libraries for optimization. Not terribly
|
||||
relevant until we have real hardware to play with... */
|
||||
#define ELF_PLATFORM NULL
|
||||
|
||||
#ifdef __KERNEL__
|
||||
# define SET_PERSONALITY(EX) \
|
||||
(current->personality = PER_LINUX)
|
||||
#endif
|
||||
|
||||
#define IA32_EFLAG 0x200
|
||||
|
||||
/*
|
||||
* IA-32 ELF specific definitions for IA-64.
|
||||
*/
|
||||
|
||||
#define __USER_CS 0x23
|
||||
#define __USER_DS 0x2B
|
||||
|
||||
/*
|
||||
* The per-cpu GDT has 32 entries: see <asm-i386/segment.h>
|
||||
*/
|
||||
#define GDT_ENTRIES 32
|
||||
|
||||
#define GDT_SIZE (GDT_ENTRIES * 8)
|
||||
|
||||
#define TSS_ENTRY 14
|
||||
#define LDT_ENTRY (TSS_ENTRY + 1)
|
||||
|
||||
#define IA32_SEGSEL_RPL (0x3 << 0)
|
||||
#define IA32_SEGSEL_TI (0x1 << 2)
|
||||
#define IA32_SEGSEL_INDEX_SHIFT 3
|
||||
|
||||
#define _TSS ((unsigned long) TSS_ENTRY << IA32_SEGSEL_INDEX_SHIFT)
|
||||
#define _LDT ((unsigned long) LDT_ENTRY << IA32_SEGSEL_INDEX_SHIFT)
|
||||
|
||||
#define IA32_SEG_BASE 16
|
||||
#define IA32_SEG_TYPE 40
|
||||
#define IA32_SEG_SYS 44
|
||||
#define IA32_SEG_DPL 45
|
||||
#define IA32_SEG_P 47
|
||||
#define IA32_SEG_HIGH_LIMIT 48
|
||||
#define IA32_SEG_AVL 52
|
||||
#define IA32_SEG_DB 54
|
||||
#define IA32_SEG_G 55
|
||||
#define IA32_SEG_HIGH_BASE 56
|
||||
|
||||
#define IA32_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, avl, segdb, gran) \
|
||||
(((limit) & 0xffff) \
|
||||
| (((unsigned long) (base) & 0xffffff) << IA32_SEG_BASE) \
|
||||
| ((unsigned long) (segtype) << IA32_SEG_TYPE) \
|
||||
| ((unsigned long) (nonsysseg) << IA32_SEG_SYS) \
|
||||
| ((unsigned long) (dpl) << IA32_SEG_DPL) \
|
||||
| ((unsigned long) (segpresent) << IA32_SEG_P) \
|
||||
| ((((unsigned long) (limit) >> 16) & 0xf) << IA32_SEG_HIGH_LIMIT) \
|
||||
| ((unsigned long) (avl) << IA32_SEG_AVL) \
|
||||
| ((unsigned long) (segdb) << IA32_SEG_DB) \
|
||||
| ((unsigned long) (gran) << IA32_SEG_G) \
|
||||
| ((((unsigned long) (base) >> 24) & 0xff) << IA32_SEG_HIGH_BASE))
|
||||
|
||||
#define SEG_LIM 32
|
||||
#define SEG_TYPE 52
|
||||
#define SEG_SYS 56
|
||||
#define SEG_DPL 57
|
||||
#define SEG_P 59
|
||||
#define SEG_AVL 60
|
||||
#define SEG_DB 62
|
||||
#define SEG_G 63
|
||||
|
||||
/* Unscramble an IA-32 segment descriptor into the IA-64 format. */
|
||||
#define IA32_SEG_UNSCRAMBLE(sd) \
|
||||
( (((sd) >> IA32_SEG_BASE) & 0xffffff) | ((((sd) >> IA32_SEG_HIGH_BASE) & 0xff) << 24) \
|
||||
| ((((sd) & 0xffff) | ((((sd) >> IA32_SEG_HIGH_LIMIT) & 0xf) << 16)) << SEG_LIM) \
|
||||
| ((((sd) >> IA32_SEG_TYPE) & 0xf) << SEG_TYPE) \
|
||||
| ((((sd) >> IA32_SEG_SYS) & 0x1) << SEG_SYS) \
|
||||
| ((((sd) >> IA32_SEG_DPL) & 0x3) << SEG_DPL) \
|
||||
| ((((sd) >> IA32_SEG_P) & 0x1) << SEG_P) \
|
||||
| ((((sd) >> IA32_SEG_AVL) & 0x1) << SEG_AVL) \
|
||||
| ((((sd) >> IA32_SEG_DB) & 0x1) << SEG_DB) \
|
||||
| ((((sd) >> IA32_SEG_G) & 0x1) << SEG_G))
|
||||
|
||||
#define IA32_IOBASE 0x2000000000000000UL /* Virtual address for I/O space */
|
||||
|
||||
#define IA32_CR0 0x80000001 /* Enable PG and PE bits */
|
||||
#define IA32_CR4 0x600 /* MMXEX and FXSR on */
|
||||
|
||||
/*
|
||||
* IA32 floating point control registers starting values
|
||||
*/
|
||||
|
||||
#define IA32_FSR_DEFAULT 0x55550000 /* set all tag bits */
|
||||
#define IA32_FCR_DEFAULT 0x17800000037fUL /* extended precision, all masks */
|
||||
|
||||
#define IA32_PTRACE_GETREGS 12
|
||||
#define IA32_PTRACE_SETREGS 13
|
||||
#define IA32_PTRACE_GETFPREGS 14
|
||||
#define IA32_PTRACE_SETFPREGS 15
|
||||
#define IA32_PTRACE_GETFPXREGS 18
|
||||
#define IA32_PTRACE_SETFPXREGS 19
|
||||
|
||||
#define ia32_start_thread(regs,new_ip,new_sp) do { \
|
||||
set_fs(USER_DS); \
|
||||
ia64_psr(regs)->cpl = 3; /* set user mode */ \
|
||||
ia64_psr(regs)->ri = 0; /* clear return slot number */ \
|
||||
ia64_psr(regs)->is = 1; /* IA-32 instruction set */ \
|
||||
regs->cr_iip = new_ip; \
|
||||
regs->ar_rsc = 0xc; /* enforced lazy mode, priv. level 3 */ \
|
||||
regs->ar_rnat = 0; \
|
||||
regs->loadrs = 0; \
|
||||
regs->r12 = new_sp; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Local Descriptor Table (LDT) related declarations.
|
||||
*/
|
||||
|
||||
#define IA32_LDT_ENTRIES 8192 /* Maximum number of LDT entries supported. */
|
||||
#define IA32_LDT_ENTRY_SIZE 8 /* The size of each LDT entry. */
|
||||
|
||||
#define LDT_entry_a(info) \
|
||||
((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
|
||||
|
||||
#define LDT_entry_b(info) \
|
||||
(((info)->base_addr & 0xff000000) | \
|
||||
(((info)->base_addr & 0x00ff0000) >> 16) | \
|
||||
((info)->limit & 0xf0000) | \
|
||||
(((info)->read_exec_only ^ 1) << 9) | \
|
||||
((info)->contents << 10) | \
|
||||
(((info)->seg_not_present ^ 1) << 15) | \
|
||||
((info)->seg_32bit << 22) | \
|
||||
((info)->limit_in_pages << 23) | \
|
||||
((info)->useable << 20) | \
|
||||
0x7100)
|
||||
|
||||
#define LDT_empty(info) ( \
|
||||
(info)->base_addr == 0 && \
|
||||
(info)->limit == 0 && \
|
||||
(info)->contents == 0 && \
|
||||
(info)->read_exec_only == 1 && \
|
||||
(info)->seg_32bit == 0 && \
|
||||
(info)->limit_in_pages == 0 && \
|
||||
(info)->seg_not_present == 1 && \
|
||||
(info)->useable == 0 )
|
||||
|
||||
static inline void
|
||||
load_TLS (struct thread_struct *t, unsigned int cpu)
|
||||
{
|
||||
extern unsigned long *cpu_gdt_table[NR_CPUS];
|
||||
|
||||
memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 0, &t->tls_array[0], sizeof(long));
|
||||
memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 1, &t->tls_array[1], sizeof(long));
|
||||
memcpy(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN + 2, &t->tls_array[2], sizeof(long));
|
||||
}
|
||||
|
||||
struct ia32_user_desc {
|
||||
unsigned int entry_number;
|
||||
unsigned int base_addr;
|
||||
unsigned int limit;
|
||||
unsigned int seg_32bit:1;
|
||||
unsigned int contents:2;
|
||||
unsigned int read_exec_only:1;
|
||||
unsigned int limit_in_pages:1;
|
||||
unsigned int seg_not_present:1;
|
||||
unsigned int useable:1;
|
||||
};
|
||||
|
||||
struct linux_binprm;
|
||||
|
||||
extern void ia32_init_addr_space (struct pt_regs *regs);
|
||||
extern int ia32_setup_arg_pages (struct linux_binprm *bprm, int exec_stack);
|
||||
extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t);
|
||||
extern void ia32_load_segment_descriptors (struct task_struct *task);
|
||||
|
||||
#define ia32f2ia64f(dst,src) \
|
||||
do { \
|
||||
ia64_ldfe(6,src); \
|
||||
ia64_stop(); \
|
||||
ia64_stf_spill(dst, 6); \
|
||||
} while(0)
|
||||
|
||||
#define ia64f2ia32f(dst,src) \
|
||||
do { \
|
||||
ia64_ldf_fill(6, src); \
|
||||
ia64_stop(); \
|
||||
ia64_stfe(dst, 6); \
|
||||
} while(0)
|
||||
|
||||
struct user_regs_struct32 {
|
||||
__u32 ebx, ecx, edx, esi, edi, ebp, eax;
|
||||
unsigned short ds, __ds, es, __es;
|
||||
unsigned short fs, __fs, gs, __gs;
|
||||
__u32 orig_eax, eip;
|
||||
unsigned short cs, __cs;
|
||||
__u32 eflags, esp;
|
||||
unsigned short ss, __ss;
|
||||
};
|
||||
|
||||
/* Prototypes for use in elfcore32.h */
|
||||
extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
|
||||
extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
|
||||
|
||||
#endif /* !CONFIG_IA32_SUPPORT */
|
||||
|
||||
#endif /* _ASM_IA64_IA32_PRIV_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,40 +0,0 @@
|
|||
#ifndef _ASM_IA64_IA32_H
|
||||
#define _ASM_IA64_IA32_H
|
||||
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
#define IA32_NR_syscalls 285 /* length of syscall table */
|
||||
#define IA32_PAGE_SHIFT 12 /* 4KB pages */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
# ifdef CONFIG_IA32_SUPPORT
|
||||
|
||||
#define IA32_PAGE_OFFSET 0xc0000000
|
||||
|
||||
extern void ia32_cpu_init (void);
|
||||
extern void ia32_mem_init (void);
|
||||
extern void ia32_gdt_init (void);
|
||||
extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
|
||||
extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
|
||||
extern int ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs);
|
||||
|
||||
# endif /* !CONFIG_IA32_SUPPORT */
|
||||
|
||||
/* Declare this unconditionally, so we don't get warnings for unreachable code. */
|
||||
extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs);
|
||||
#if PAGE_SHIFT > IA32_PAGE_SHIFT
|
||||
extern int ia32_copy_ia64_partial_page_list(struct task_struct *,
|
||||
unsigned long);
|
||||
extern void ia32_drop_ia64_partial_page_list(struct task_struct *);
|
||||
#else
|
||||
# define ia32_copy_ia64_partial_page_list(a1, a2) 0
|
||||
# define ia32_drop_ia64_partial_page_list(a1) do { ; } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_IA64_IA32_H */
|
|
@ -270,23 +270,6 @@ typedef struct {
|
|||
(int __user *) (addr)); \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
struct desc_struct {
|
||||
unsigned int a, b;
|
||||
};
|
||||
|
||||
#define desc_empty(desc) (!((desc)->a | (desc)->b))
|
||||
#define desc_equal(desc1, desc2) (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
|
||||
|
||||
#define GDT_ENTRY_TLS_ENTRIES 3
|
||||
#define GDT_ENTRY_TLS_MIN 6
|
||||
#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
|
||||
|
||||
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
|
||||
|
||||
struct ia64_partial_page_list;
|
||||
#endif
|
||||
|
||||
struct thread_struct {
|
||||
__u32 flags; /* various thread flags (see IA64_THREAD_*) */
|
||||
/* writing on_ustack is performance-critical, so it's worth spending 8 bits on it... */
|
||||
|
@ -298,29 +281,6 @@ struct thread_struct {
|
|||
__u64 rbs_bot; /* the base address for the RBS */
|
||||
int last_fph_cpu; /* CPU that may hold the contents of f32-f127 */
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
__u64 eflag; /* IA32 EFLAGS reg */
|
||||
__u64 fsr; /* IA32 floating pt status reg */
|
||||
__u64 fcr; /* IA32 floating pt control reg */
|
||||
__u64 fir; /* IA32 fp except. instr. reg */
|
||||
__u64 fdr; /* IA32 fp except. data reg */
|
||||
__u64 old_k1; /* old value of ar.k1 */
|
||||
__u64 old_iob; /* old IOBase value */
|
||||
struct ia64_partial_page_list *ppl; /* partial page list for 4K page size issue */
|
||||
/* cached TLS descriptors. */
|
||||
struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
|
||||
|
||||
# define INIT_THREAD_IA32 .eflag = 0, \
|
||||
.fsr = 0, \
|
||||
.fcr = 0x17800000037fULL, \
|
||||
.fir = 0, \
|
||||
.fdr = 0, \
|
||||
.old_k1 = 0, \
|
||||
.old_iob = 0, \
|
||||
.ppl = NULL,
|
||||
#else
|
||||
# define INIT_THREAD_IA32
|
||||
#endif /* CONFIG_IA32_SUPPORT */
|
||||
#ifdef CONFIG_PERFMON
|
||||
void *pfm_context; /* pointer to detailed PMU context */
|
||||
unsigned long pfm_needs_checking; /* when >0, pending perfmon work on kernel exit */
|
||||
|
@ -342,7 +302,6 @@ struct thread_struct {
|
|||
.rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
|
||||
.task_size = DEFAULT_TASK_SIZE, \
|
||||
.last_fph_cpu = -1, \
|
||||
INIT_THREAD_IA32 \
|
||||
INIT_THREAD_PM \
|
||||
.dbr = {0, }, \
|
||||
.ibr = {0, }, \
|
||||
|
@ -485,11 +444,6 @@ extern void __ia64_load_fpu (struct ia64_fpreg *fph);
|
|||
extern void ia64_save_debug_regs (unsigned long *save_area);
|
||||
extern void ia64_load_debug_regs (unsigned long *save_area);
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
extern void ia32_save_state (struct task_struct *task);
|
||||
extern void ia32_load_state (struct task_struct *task);
|
||||
#endif
|
||||
|
||||
#define ia64_fph_enable() do { ia64_rsm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
|
||||
#define ia64_fph_disable() do { ia64_ssm(IA64_PSR_DFH); ia64_srlz_d(); } while (0)
|
||||
|
||||
|
|
|
@ -22,33 +22,18 @@ static inline long syscall_get_nr(struct task_struct *task,
|
|||
if ((long)regs->cr_ifs < 0) /* Not a syscall */
|
||||
return -1;
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs))
|
||||
return regs->r1;
|
||||
#endif
|
||||
|
||||
return regs->r15;
|
||||
}
|
||||
|
||||
static inline void syscall_rollback(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs))
|
||||
regs->r8 = regs->r1;
|
||||
#endif
|
||||
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static inline long syscall_get_error(struct task_struct *task,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs))
|
||||
return regs->r8;
|
||||
#endif
|
||||
|
||||
return regs->r10 == -1 ? regs->r8:0;
|
||||
}
|
||||
|
||||
|
@ -62,13 +47,6 @@ static inline void syscall_set_return_value(struct task_struct *task,
|
|||
struct pt_regs *regs,
|
||||
int error, long val)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs)) {
|
||||
regs->r8 = (long) error ? error : val;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (error) {
|
||||
/* error < 0, but ia64 uses > 0 return value */
|
||||
regs->r8 = -error;
|
||||
|
@ -89,37 +67,6 @@ static inline void syscall_get_arguments(struct task_struct *task,
|
|||
{
|
||||
BUG_ON(i + n > 6);
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs)) {
|
||||
switch (i + n) {
|
||||
case 6:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r13;
|
||||
case 5:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r15;
|
||||
case 4:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r14;
|
||||
case 3:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r10;
|
||||
case 2:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r9;
|
||||
case 1:
|
||||
if (!n--) break;
|
||||
*args++ = regs->r11;
|
||||
case 0:
|
||||
if (!n--) break;
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ia64_syscall_get_set_arguments(task, regs, i, n, args, 0);
|
||||
}
|
||||
|
||||
|
@ -130,34 +77,6 @@ static inline void syscall_set_arguments(struct task_struct *task,
|
|||
{
|
||||
BUG_ON(i + n > 6);
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(regs)) {
|
||||
switch (i + n) {
|
||||
case 6:
|
||||
if (!n--) break;
|
||||
regs->r13 = *args++;
|
||||
case 5:
|
||||
if (!n--) break;
|
||||
regs->r15 = *args++;
|
||||
case 4:
|
||||
if (!n--) break;
|
||||
regs->r14 = *args++;
|
||||
case 3:
|
||||
if (!n--) break;
|
||||
regs->r10 = *args++;
|
||||
case 2:
|
||||
if (!n--) break;
|
||||
regs->r9 = *args++;
|
||||
case 1:
|
||||
if (!n--) break;
|
||||
regs->r11 = *args++;
|
||||
case 0:
|
||||
if (!n--) break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ia64_syscall_get_set_arguments(task, regs, i, n, args, 1);
|
||||
}
|
||||
#endif /* _ASM_SYSCALL_H */
|
||||
|
|
|
@ -191,15 +191,6 @@ do { \
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
# define IS_IA32_PROCESS(regs) (ia64_psr(regs)->is != 0)
|
||||
#else
|
||||
# define IS_IA32_PROCESS(regs) 0
|
||||
struct task_struct;
|
||||
static inline void ia32_save_state(struct task_struct *t __attribute__((unused))){}
|
||||
static inline void ia32_load_state(struct task_struct *t __attribute__((unused))){}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Context switch from one thread to another. If the two threads have
|
||||
* different address spaces, schedule() has already taken care of
|
||||
|
@ -233,7 +224,7 @@ extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct
|
|||
|
||||
#define IA64_HAS_EXTRA_STATE(t) \
|
||||
((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \
|
||||
|| IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE())
|
||||
|| PERFMON_IS_SYSWIDE())
|
||||
|
||||
#define __switch_to(prev,next,last) do { \
|
||||
IA64_ACCOUNT_ON_SWITCH(prev, next); \
|
||||
|
|
|
@ -335,20 +335,6 @@
|
|||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
# define __ARCH_WANT_SYS_FADVISE64
|
||||
# define __ARCH_WANT_SYS_GETPGRP
|
||||
# define __ARCH_WANT_SYS_LLSEEK
|
||||
# define __ARCH_WANT_SYS_NICE
|
||||
# define __ARCH_WANT_SYS_OLD_GETRLIMIT
|
||||
# define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
# define __ARCH_WANT_SYS_PAUSE
|
||||
# define __ARCH_WANT_SYS_SIGPENDING
|
||||
# define __ARCH_WANT_SYS_SIGPROCMASK
|
||||
# define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||
# define __ARCH_WANT_COMPAT_SYS_TIME
|
||||
#endif
|
||||
|
||||
#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
|
||||
|
||||
#include <linux/types.h>
|
||||
|
|
|
@ -30,20 +30,11 @@ static unsigned signal_class[] = {
|
|||
|
||||
int audit_classify_arch(int arch)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (arch == AUDIT_ARCH_I386)
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audit_classify_syscall(int abi, unsigned syscall)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
extern int ia32_classify_syscall(unsigned);
|
||||
if (abi == AUDIT_ARCH_I386)
|
||||
return ia32_classify_syscall(syscall);
|
||||
#endif
|
||||
switch(syscall) {
|
||||
case __NR_open:
|
||||
return 2;
|
||||
|
@ -58,18 +49,6 @@ int audit_classify_syscall(int abi, unsigned syscall)
|
|||
|
||||
static int __init audit_classes_init(void)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
extern __u32 ia32_dir_class[];
|
||||
extern __u32 ia32_write_class[];
|
||||
extern __u32 ia32_read_class[];
|
||||
extern __u32 ia32_chattr_class[];
|
||||
extern __u32 ia32_signal_class[];
|
||||
audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
|
||||
audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
|
||||
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
|
||||
audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
|
||||
#endif
|
||||
audit_register_class(AUDIT_CLASS_WRITE, write_class);
|
||||
audit_register_class(AUDIT_CLASS_READ, read_class);
|
||||
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
|
||||
|
|
|
@ -71,15 +71,6 @@ ENTRY(ia64_execve)
|
|||
add out3=16,sp // regs
|
||||
br.call.sptk.many rp=sys_execve
|
||||
.ret0:
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
/*
|
||||
* Check if we're returning to ia32 mode. If so, we need to restore ia32 registers
|
||||
* from pt_regs.
|
||||
*/
|
||||
adds r16=PT(CR_IPSR)+16,sp
|
||||
;;
|
||||
ld8 r16=[r16]
|
||||
#endif
|
||||
cmp4.ge p6,p7=r8,r0
|
||||
mov ar.pfs=loc1 // restore ar.pfs
|
||||
sxt4 r8=r8 // return 64-bit result
|
||||
|
@ -108,12 +99,6 @@ ENTRY(ia64_execve)
|
|||
ldf.fill f23=[sp]; ldf.fill f24=[sp]; mov f25=f0
|
||||
ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0
|
||||
ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
tbit.nz p6,p0=r16, IA64_PSR_IS_BIT
|
||||
movl loc0=ia64_ret_from_ia32_execve
|
||||
;;
|
||||
(p6) mov rp=loc0
|
||||
#endif
|
||||
br.ret.sptk.many rp
|
||||
END(ia64_execve)
|
||||
|
||||
|
@ -848,30 +833,6 @@ __paravirt_work_processed_syscall:
|
|||
br.cond.sptk.many rbs_switch // B
|
||||
END(__paravirt_leave_syscall)
|
||||
|
||||
#ifdef __IA64_ASM_PARAVIRTUALIZED_NATIVE
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
|
||||
adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
|
||||
;;
|
||||
.mem.offset 0,0
|
||||
st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
|
||||
.mem.offset 8,0
|
||||
st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
;;
|
||||
// don't fall through, ia64_leave_kernel may be #define'd
|
||||
br.cond.sptk.few ia64_leave_kernel
|
||||
;;
|
||||
#endif /* CONFIG_PARAVIRT */
|
||||
END(ia64_ret_from_ia32_execve)
|
||||
#ifndef CONFIG_PARAVIRT
|
||||
// fall through
|
||||
#endif
|
||||
#endif /* CONFIG_IA32_SUPPORT */
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
||||
GLOBAL_ENTRY(__paravirt_leave_kernel)
|
||||
PT_REGS_UNWIND_INFO(0)
|
||||
/*
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm/break.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/kregs.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -1386,28 +1385,6 @@ END(ia32_exception)
|
|||
// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
|
||||
ENTRY(ia32_intercept)
|
||||
DBG_FAULT(46)
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
mov r31=pr
|
||||
MOV_FROM_ISR(r16)
|
||||
;;
|
||||
extr.u r17=r16,16,8 // get ISR.code
|
||||
mov r18=ar.eflag
|
||||
MOV_FROM_IIM(r19) // old eflag value
|
||||
;;
|
||||
cmp.ne p6,p0=2,r17
|
||||
(p6) br.cond.spnt 1f // not a system flag fault
|
||||
xor r16=r18,r19
|
||||
;;
|
||||
extr.u r17=r16,18,1 // get the eflags.ac bit
|
||||
;;
|
||||
cmp.eq p6,p0=0,r17
|
||||
(p6) br.cond.spnt 1f // eflags.ac bit didn't change
|
||||
;;
|
||||
mov pr=r31,-1 // restore predicate registers
|
||||
RFI
|
||||
|
||||
1:
|
||||
#endif // CONFIG_IA32_SUPPORT
|
||||
FAULT(46)
|
||||
END(ia32_intercept)
|
||||
|
||||
|
@ -1416,12 +1393,7 @@ END(ia32_intercept)
|
|||
// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
|
||||
ENTRY(ia32_interrupt)
|
||||
DBG_FAULT(47)
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
mov r31=pr
|
||||
br.sptk.many dispatch_to_ia32_handler
|
||||
#else
|
||||
FAULT(47)
|
||||
#endif
|
||||
END(ia32_interrupt)
|
||||
|
||||
.org ia64_ivt+0x6c00
|
||||
|
@ -1715,89 +1687,3 @@ ENTRY(dispatch_illegal_op_fault)
|
|||
(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
|
||||
br.sptk.many ia64_leave_kernel
|
||||
END(dispatch_illegal_op_fault)
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
|
||||
/*
|
||||
* There is no particular reason for this code to be here, other than that
|
||||
* there happens to be space here that would go unused otherwise. If this
|
||||
* fault ever gets "unreserved", simply moved the following code to a more
|
||||
* suitable spot...
|
||||
*/
|
||||
|
||||
// IA32 interrupt entry point
|
||||
|
||||
ENTRY(dispatch_to_ia32_handler)
|
||||
SAVE_MIN
|
||||
;;
|
||||
MOV_FROM_ISR(r14)
|
||||
SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(r3, r24)
|
||||
// guarantee that interruption collection is on
|
||||
;;
|
||||
SSM_PSR_I(p15, p15, r3)
|
||||
adds r3=8,r2 // Base pointer for SAVE_REST
|
||||
;;
|
||||
SAVE_REST
|
||||
;;
|
||||
mov r15=0x80
|
||||
shr r14=r14,16 // Get interrupt number
|
||||
;;
|
||||
cmp.ne p6,p0=r14,r15
|
||||
(p6) br.call.dpnt.many b6=non_ia32_syscall
|
||||
|
||||
adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
|
||||
adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
|
||||
;;
|
||||
cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
|
||||
ld8 r8=[r14] // get r8
|
||||
;;
|
||||
st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
|
||||
;;
|
||||
alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
|
||||
;;
|
||||
ld4 r8=[r14],8 // r8 == eax (syscall number)
|
||||
mov r15=IA32_NR_syscalls
|
||||
;;
|
||||
cmp.ltu.unc p6,p7=r8,r15
|
||||
ld4 out1=[r14],8 // r9 == ecx
|
||||
;;
|
||||
ld4 out2=[r14],8 // r10 == edx
|
||||
;;
|
||||
ld4 out0=[r14] // r11 == ebx
|
||||
adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
|
||||
;;
|
||||
ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
|
||||
;;
|
||||
ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
|
||||
adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
|
||||
;;
|
||||
ld4 out4=[r14] // r15 == edi
|
||||
movl r16=ia32_syscall_table
|
||||
;;
|
||||
(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
|
||||
ld4 r2=[r2] // r2 = current_thread_info()->flags
|
||||
;;
|
||||
ld8 r16=[r16]
|
||||
and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
|
||||
;;
|
||||
mov b6=r16
|
||||
movl r15=ia32_ret_from_syscall
|
||||
cmp.eq p8,p0=r2,r0
|
||||
;;
|
||||
mov rp=r15
|
||||
(p8) br.call.sptk.many b6=b6
|
||||
br.cond.sptk ia32_trace_syscall
|
||||
|
||||
non_ia32_syscall:
|
||||
alloc r15=ar.pfs,0,0,2,0
|
||||
mov out0=r14 // interrupt #
|
||||
add out1=16,sp // pointer to pt_regs
|
||||
;; // avoid WAW on CFM
|
||||
br.call.sptk.many rp=ia32_bad_interrupt
|
||||
.ret1: movl r15=ia64_leave_kernel
|
||||
;;
|
||||
mov rp=r15
|
||||
br.ret.sptk.many rp
|
||||
END(dispatch_to_ia32_handler)
|
||||
|
||||
#endif /* CONFIG_IA32_SUPPORT */
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <asm/cpu.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
@ -358,11 +357,6 @@ ia64_save_extra (struct task_struct *task)
|
|||
if (info & PFM_CPUINFO_SYST_WIDE)
|
||||
pfm_syst_wide_update_task(task, info, 0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(task_pt_regs(task)))
|
||||
ia32_save_state(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -383,11 +377,6 @@ ia64_load_extra (struct task_struct *task)
|
|||
if (info & PFM_CPUINFO_SYST_WIDE)
|
||||
pfm_syst_wide_update_task(task, info, 1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(task_pt_regs(task)))
|
||||
ia32_load_state(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -426,7 +415,7 @@ copy_thread(unsigned long clone_flags,
|
|||
unsigned long user_stack_base, unsigned long user_stack_size,
|
||||
struct task_struct *p, struct pt_regs *regs)
|
||||
{
|
||||
extern char ia64_ret_from_clone, ia32_ret_from_clone;
|
||||
extern char ia64_ret_from_clone;
|
||||
struct switch_stack *child_stack, *stack;
|
||||
unsigned long rbs, child_rbs, rbs_size;
|
||||
struct pt_regs *child_ptregs;
|
||||
|
@ -457,7 +446,7 @@ copy_thread(unsigned long clone_flags,
|
|||
memcpy((void *) child_rbs, (void *) rbs, rbs_size);
|
||||
|
||||
if (likely(user_mode(child_ptregs))) {
|
||||
if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs))
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
|
||||
if (user_stack_base) {
|
||||
child_ptregs->r12 = user_stack_base + user_stack_size - 16;
|
||||
|
@ -477,10 +466,7 @@ copy_thread(unsigned long clone_flags,
|
|||
child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
|
||||
}
|
||||
child_stack->ar_bspstore = child_rbs + rbs_size;
|
||||
if (IS_IA32_PROCESS(regs))
|
||||
child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
|
||||
else
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
|
||||
/* copy parts of thread_struct: */
|
||||
p->thread.ksp = (unsigned long) child_stack - 16;
|
||||
|
@ -515,22 +501,6 @@ copy_thread(unsigned long clone_flags,
|
|||
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
|
||||
| THREAD_FLAGS_TO_SET);
|
||||
ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
/*
|
||||
* If we're cloning an IA32 task then save the IA32 extra
|
||||
* state from the current task to the new task
|
||||
*/
|
||||
if (IS_IA32_PROCESS(task_pt_regs(current))) {
|
||||
ia32_save_state(p);
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
retval = ia32_clone_tls(p, child_ptregs);
|
||||
|
||||
/* Copy partially mapped page list */
|
||||
if (!retval)
|
||||
retval = ia32_copy_ia64_partial_page_list(p,
|
||||
clone_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if (current->thread.pfm_context)
|
||||
|
@ -704,15 +674,6 @@ EXPORT_SYMBOL(kernel_thread);
|
|||
int
|
||||
kernel_thread_helper (int (*fn)(void *), void *arg)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(task_pt_regs(current))) {
|
||||
/* A kernel thread is always a 64-bit process. */
|
||||
current->thread.map_base = DEFAULT_MAP_BASE;
|
||||
current->thread.task_size = DEFAULT_TASK_SIZE;
|
||||
ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
|
||||
ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
|
||||
}
|
||||
#endif
|
||||
return (*fn)(arg);
|
||||
}
|
||||
|
||||
|
@ -725,14 +686,6 @@ flush_thread (void)
|
|||
/* drop floating-point and debug-register state if it exists: */
|
||||
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
|
||||
ia64_drop_fpu(current);
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(task_pt_regs(current))) {
|
||||
ia32_drop_ia64_partial_page_list(current);
|
||||
current->thread.task_size = IA32_PAGE_OFFSET;
|
||||
set_fs(USER_DS);
|
||||
memset(current->thread.tls_array, 0, sizeof(current->thread.tls_array));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -753,8 +706,6 @@ exit_thread (void)
|
|||
if (current->thread.flags & IA64_THREAD_DBG_VALID)
|
||||
pfm_release_debug_registers(current);
|
||||
#endif
|
||||
if (IS_IA32_PROCESS(task_pt_regs(current)))
|
||||
ia32_drop_ia64_partial_page_list(current);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
|
|
|
@ -1250,13 +1250,8 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
|
|||
long syscall;
|
||||
int arch;
|
||||
|
||||
if (IS_IA32_PROCESS(®s)) {
|
||||
syscall = regs.r1;
|
||||
arch = AUDIT_ARCH_I386;
|
||||
} else {
|
||||
syscall = regs.r15;
|
||||
arch = AUDIT_ARCH_IA64;
|
||||
}
|
||||
syscall = regs.r15;
|
||||
arch = AUDIT_ARCH_IA64;
|
||||
|
||||
audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
@ -2172,11 +2167,6 @@ static const struct user_regset_view user_ia64_view = {
|
|||
|
||||
const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
extern const struct user_regset_view user_ia32_view;
|
||||
if (IS_IA32_PROCESS(task_pt_regs(tsk)))
|
||||
return &user_ia32_view;
|
||||
#endif
|
||||
return &user_ia64_view;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include <linux/kexec.h>
|
||||
#include <linux/crash_dump.h>
|
||||
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/mca.h>
|
||||
#include <asm/meminit.h>
|
||||
|
@ -1016,10 +1015,6 @@ cpu_init (void)
|
|||
ia64_mmu_init(ia64_imva(cpu_data));
|
||||
ia64_mca_cpu_init(ia64_imva(cpu_data));
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
ia32_cpu_init();
|
||||
#endif
|
||||
|
||||
/* Clear ITC to eliminate sched_clock() overflows in human time. */
|
||||
ia64_set_itc(0);
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <linux/unistd.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/rse.h>
|
||||
|
@ -425,14 +424,8 @@ static long
|
|||
handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset,
|
||||
struct sigscratch *scr)
|
||||
{
|
||||
if (IS_IA32_PROCESS(&scr->pt)) {
|
||||
/* send signal to IA-32 process */
|
||||
if (!ia32_setup_frame1(sig, ka, info, oldset, &scr->pt))
|
||||
return 0;
|
||||
} else
|
||||
/* send signal to IA-64 process */
|
||||
if (!setup_frame(sig, ka, info, oldset, scr))
|
||||
return 0;
|
||||
if (!setup_frame(sig, ka, info, oldset, scr))
|
||||
return 0;
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
|
@ -462,7 +455,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
|||
siginfo_t info;
|
||||
long restart = in_syscall;
|
||||
long errno = scr->pt.r8;
|
||||
# define ERR_CODE(c) (IS_IA32_PROCESS(&scr->pt) ? -(c) : (c))
|
||||
|
||||
/*
|
||||
* In the ia64_leave_kernel code path, we want the common case to go fast, which
|
||||
|
@ -490,14 +482,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
|||
* inferior call), thus it's important to check for restarting _after_
|
||||
* get_signal_to_deliver().
|
||||
*/
|
||||
if (IS_IA32_PROCESS(&scr->pt)) {
|
||||
if (in_syscall) {
|
||||
if (errno >= 0)
|
||||
restart = 0;
|
||||
else
|
||||
errno = -errno;
|
||||
}
|
||||
} else if ((long) scr->pt.r10 != -1)
|
||||
if ((long) scr->pt.r10 != -1)
|
||||
/*
|
||||
* A system calls has to be restarted only if one of the error codes
|
||||
* ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10
|
||||
|
@ -513,22 +498,18 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
|||
switch (errno) {
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
case ERESTARTNOHAND:
|
||||
scr->pt.r8 = ERR_CODE(EINTR);
|
||||
scr->pt.r8 = EINTR;
|
||||
/* note: scr->pt.r10 is already -1 */
|
||||
break;
|
||||
|
||||
case ERESTARTSYS:
|
||||
if ((ka.sa.sa_flags & SA_RESTART) == 0) {
|
||||
scr->pt.r8 = ERR_CODE(EINTR);
|
||||
scr->pt.r8 = EINTR;
|
||||
/* note: scr->pt.r10 is already -1 */
|
||||
break;
|
||||
}
|
||||
case ERESTARTNOINTR:
|
||||
if (IS_IA32_PROCESS(&scr->pt)) {
|
||||
scr->pt.r8 = scr->pt.r1;
|
||||
scr->pt.cr_iip -= 2;
|
||||
} else
|
||||
ia64_decrement_ip(&scr->pt);
|
||||
ia64_decrement_ip(&scr->pt);
|
||||
restart = 0; /* don't restart twice if handle_signal() fails... */
|
||||
}
|
||||
}
|
||||
|
@ -555,21 +536,14 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
|||
if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR
|
||||
|| errno == ERESTART_RESTARTBLOCK)
|
||||
{
|
||||
if (IS_IA32_PROCESS(&scr->pt)) {
|
||||
scr->pt.r8 = scr->pt.r1;
|
||||
scr->pt.cr_iip -= 2;
|
||||
if (errno == ERESTART_RESTARTBLOCK)
|
||||
scr->pt.r8 = 0; /* x86 version of __NR_restart_syscall */
|
||||
} else {
|
||||
/*
|
||||
* Note: the syscall number is in r15 which is saved in
|
||||
* pt_regs so all we need to do here is adjust ip so that
|
||||
* the "break" instruction gets re-executed.
|
||||
*/
|
||||
ia64_decrement_ip(&scr->pt);
|
||||
if (errno == ERESTART_RESTARTBLOCK)
|
||||
scr->pt.r15 = __NR_restart_syscall;
|
||||
}
|
||||
/*
|
||||
* Note: the syscall number is in r15 which is saved in
|
||||
* pt_regs so all we need to do here is adjust ip so that
|
||||
* the "break" instruction gets re-executed.
|
||||
*/
|
||||
ia64_decrement_ip(&scr->pt);
|
||||
if (errno == ERESTART_RESTARTBLOCK)
|
||||
scr->pt.r15 = __NR_restart_syscall;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <asm/cache.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/machvec.h>
|
||||
|
@ -443,10 +442,6 @@ smp_callin (void)
|
|||
calibrate_delay();
|
||||
local_cpu_data->loops_per_jiffy = loops_per_jiffy;
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
ia32_gdt_init();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allow the master to continue.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/kdebug.h>
|
||||
|
||||
#include <asm/fpswa.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/intrinsics.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -626,10 +625,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
break;
|
||||
|
||||
case 45:
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (ia32_exception(®s, isr) == 0)
|
||||
return;
|
||||
#endif
|
||||
printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
|
||||
printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
|
||||
iip, ifa, isr);
|
||||
|
@ -637,10 +632,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
break;
|
||||
|
||||
case 46:
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (ia32_intercept(®s, isr) == 0)
|
||||
return;
|
||||
#endif
|
||||
printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
|
||||
printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
|
||||
iip, ifa, isr, iim);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/kexec.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/numa.h>
|
||||
|
@ -668,10 +667,6 @@ mem_init (void)
|
|||
fsyscall_table[i] = sys_call_table[i] | 1;
|
||||
}
|
||||
setup_gate();
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
ia32_mem_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
|
|
|
@ -58,11 +58,6 @@ __HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA)
|
|||
__HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR)
|
||||
__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR)
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG)
|
||||
__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8
|
||||
#endif /* CONFIG_IA32_SUPPORT */
|
||||
|
||||
GLOBAL_ENTRY(xen_set_rr0_to_rr4)
|
||||
mov r8=r32
|
||||
mov r9=r33
|
||||
|
|
|
@ -301,11 +301,6 @@ static void xen_setreg(int regnum, unsigned long val)
|
|||
case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7:
|
||||
xen_set_kr(regnum - _IA64_REG_AR_KR0, val);
|
||||
break;
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
case _IA64_REG_AR_EFLAG:
|
||||
xen_set_eflag(val);
|
||||
break;
|
||||
#endif
|
||||
case _IA64_REG_AR_ITC:
|
||||
xen_set_itc(val);
|
||||
break;
|
||||
|
@ -332,11 +327,6 @@ static unsigned long xen_getreg(int regnum)
|
|||
case _IA64_REG_PSR:
|
||||
res = xen_get_psr();
|
||||
break;
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
case _IA64_REG_AR_EFLAG:
|
||||
res = xen_get_eflag();
|
||||
break;
|
||||
#endif
|
||||
case _IA64_REG_AR_ITC:
|
||||
res = xen_get_itc();
|
||||
break;
|
||||
|
@ -710,9 +700,6 @@ extern unsigned long xen_getreg(int regnum);
|
|||
|
||||
__DEFINE_FUNC(getreg,
|
||||
__DEFINE_GET_REG(PSR, PSR)
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
__DEFINE_GET_REG(AR_EFLAG, EFLAG)
|
||||
#endif
|
||||
|
||||
/* get_itc */
|
||||
"mov r2 = " __stringify(_IA64_REG_AR_ITC) "\n"
|
||||
|
@ -789,9 +776,6 @@ __DEFINE_FUNC(setreg,
|
|||
";;\n"
|
||||
"(p6) br.cond.spnt xen_set_itc\n"
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
__DEFINE_SET_REG(AR_EFLAG, SET_EFLAG)
|
||||
#endif
|
||||
__DEFINE_SET_REG(CR_TPR, SET_TPR)
|
||||
__DEFINE_SET_REG(CR_EOI, EOI)
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
you why the ifdefs are needed? Think about it again. -AK */
|
||||
#ifdef CONFIG_X86_64
|
||||
# define INPUT_COMPAT_TEST is_compat_task()
|
||||
#elif defined(CONFIG_IA64)
|
||||
# define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
|
||||
#elif defined(CONFIG_S390)
|
||||
# define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT)
|
||||
#elif defined(CONFIG_MIPS)
|
||||
|
|
Loading…
Reference in New Issue