Commit 494ec6f3 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/linux-ia64-release-2.6.9

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents ed81c78c 67da3ff6
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.9-rc1
# Fri Aug 27 22:00:00 2004
# Linux kernel version: 2.6.9-rc2
# Fri Sep 17 13:58:32 2004
#
#
......@@ -13,6 +13,7 @@ CONFIG_CLEAN_COMPILE=y
#
# General setup
#
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
......@@ -33,6 +34,8 @@ CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
......@@ -54,6 +57,7 @@ CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
# CONFIG_IA64_GENERIC is not set
# CONFIG_IA64_DIG is not set
# CONFIG_IA64_HP_ZX1 is not set
......@@ -210,7 +214,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
......@@ -277,7 +280,8 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
CONFIG_SCSI_SATA=y
# CONFIG_SCSI_SATA_SVW is not set
# CONFIG_SCSI_ATA_PIIX is not set
......@@ -334,8 +338,7 @@ CONFIG_DM_ZERO=m
# Fusion MPT device support
#
CONFIG_FUSION=y
CONFIG_FUSION_MAX_SGE=40
CONFIG_FUSION_ISENSE=m
CONFIG_FUSION_MAX_SGE=128
CONFIG_FUSION_CTL=m
#
......@@ -550,7 +553,6 @@ CONFIG_SERIAL_SGI_L1_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_QIC02_TAPE is not set
#
# IPMI
......@@ -575,6 +577,7 @@ CONFIG_EFI_RTC=y
CONFIG_RAW_DRIVER=m
# CONFIG_HPET is not set
CONFIG_MAX_RAW_DEVS=256
CONFIG_MMTIMER=y
#
# I2C support
......
......@@ -48,6 +48,7 @@ static void elf32_set_personality (void);
extern struct page *ia32_shared_page[];
extern unsigned long *ia32_gdt;
extern struct page *ia32_gate_page;
struct page *
ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type)
......@@ -59,10 +60,25 @@ ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int
return pg;
}
struct page *
ia32_install_gate_page (struct vm_area_struct *vma, unsigned long address, int *type)
{
struct page *pg = ia32_gate_page;
get_page(pg);
if (type)
*type = VM_FAULT_MINOR;
return pg;
}
static struct vm_operations_struct ia32_shared_page_vm_ops = {
.nopage = ia32_install_shared_page
};
static struct vm_operations_struct ia32_gate_page_vm_ops = {
.nopage = ia32_install_gate_page
};
void
ia64_elf32_init (struct pt_regs *regs)
{
......@@ -89,6 +105,29 @@ ia64_elf32_init (struct pt_regs *regs)
up_write(&current->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_alloc(vm_area_cachep, SLAB_KERNEL);
if (vma) {
memset(vma, 0, sizeof(*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(&current->mm->mmap_sem);
{
insert_vm_struct(current->mm, vma);
}
up_write(&current->mm->mmap_sem);
}
/*
* Install LDT as anonymous memory. This gives us all-zero segment descriptors
* until a task modifies them via modify_ldt().
......
......@@ -311,7 +311,7 @@ ia32_syscall_table:
data8 sys_ni_syscall /* old profil syscall holder */
data8 compat_sys_statfs
data8 compat_sys_fstatfs /* 100 */
data8 sys32_ioperm
data8 sys_ni_syscall /* ioperm */
data8 compat_sys_socketcall
data8 sys_syslog
data8 compat_sys_setitimer
......@@ -320,7 +320,7 @@ ia32_syscall_table:
data8 compat_sys_newlstat
data8 compat_sys_newfstat
data8 sys_ni_syscall
data8 sys32_iopl /* 110 */
data8 sys_ni_syscall /* iopl */ /* 110 */
data8 sys_vhangup
data8 sys_ni_syscall /* used to be sys_idle */
data8 sys_ni_syscall
......
......@@ -853,14 +853,19 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs
unsigned int restorer = IA32_SA_RESTORER(ka);
err |= __put_user(restorer, &frame->pretcode);
} else {
err |= __put_user((long)frame->retcode, &frame->pretcode);
/* This is popl %eax ; movl $,%eax ; int $0x80 */
err |= __put_user(0xb858, (short *)(frame->retcode+0));
err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
err |= __put_user(0x80cd, (short *)(frame->retcode+6));
/* Pointing to restorer in ia32 gate page */
err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode);
}
/* This is popl %eax ; movl $,%eax ; int $0x80
* and there for historical reasons only.
* See arch/i386/kernel/signal.c
*/
err |= __put_user(0xb858, (short *)(frame->retcode+0));
err |= __put_user(__IA32_NR_sigreturn, (int *)(frame->retcode+2));
err |= __put_user(0x80cd, (short *)(frame->retcode+6));
if (err)
goto give_sigsegv;
......@@ -922,13 +927,19 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
unsigned int restorer = IA32_SA_RESTORER(ka);
err |= __put_user(restorer, &frame->pretcode);
} else {
err |= __put_user((long)frame->retcode, &frame->pretcode);
/* This is movl $,%eax ; int $0x80 */
err |= __put_user(0xb8, (char *)(frame->retcode+0));
err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
err |= __put_user(0x80cd, (short *)(frame->retcode+5));
/* Pointing to rt_restorer in ia32 gate page */
err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode);
}
/* This is movl $,%eax ; int $0x80
* and there for historical reasons only.
* See arch/i386/kernel/signal.c
*/
err |= __put_user(0xb8, (char *)(frame->retcode+0));
err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
err |= __put_user(0x80cd, (short *)(frame->retcode+5));
if (err)
goto give_sigsegv;
......
......@@ -33,6 +33,7 @@ struct exec_domain ia32_exec_domain;
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)
......@@ -158,7 +159,7 @@ ia32_gdt_init (void)
/*
* Setup IA32 GDT and TSS
*/
void
static void
ia32_boot_gdt_init (void)
{
unsigned long ldt_size;
......@@ -172,12 +173,12 @@ ia32_boot_gdt_init (void)
/* CS descriptor in IA-32 (scrambled) format */
ia32_boot_gdt[__USER_CS >> 3]
= IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
= 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_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
= 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);
......@@ -187,6 +188,27 @@ ia32_boot_gdt_init (void)
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
*/
......
......@@ -168,6 +168,9 @@ struct ia32_user_fxsr_struct {
#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;
......@@ -324,14 +327,16 @@ struct old_linux32_dirent {
#define IA32_PAGE_OFFSET 0xc0000000
#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)
#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
#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
......
......@@ -1913,73 +1913,6 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
return ret;
}
/*
* The IA64 maps 4 I/O ports for each 4K page
*/
#define IOLEN ((65536 / 4) * 4096)
asmlinkage long
sys32_iopl (int level)
{
extern unsigned long ia64_iobase;
int fd;
struct file * file;
unsigned int old;
unsigned long addr;
mm_segment_t old_fs = get_fs ();
if (level != 3)
return(-EINVAL);
/* Trying to gain more privileges? */
old = ia64_getreg(_IA64_REG_AR_EFLAG);
if ((unsigned int) level > ((old >> 12) & 3)) {
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
}
set_fs(KERNEL_DS);
fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
set_fs(old_fs);
if (fd < 0)
return fd;
file = fget(fd);
if (file == NULL) {
sys_close(fd);
return(-EFAULT);
}
down_write(&current->mm->mmap_sem);
addr = do_mmap_pgoff(file, IA32_IOBASE,
IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
(ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
up_write(&current->mm->mmap_sem);
if (addr >= 0) {
old = (old & ~0x3000) | (level << 12);
ia64_setreg(_IA64_REG_AR_EFLAG, old);
}
fput(file);
sys_close(fd);
return 0;
}
asmlinkage long
sys32_ioperm (unsigned int from, unsigned int num, int on)
{
/*
* Since IA64 doesn't have permission bits we'd have to go to
* a lot of trouble to simulate them in software. There's
* no point, only trusted programs can make this call so we'll
* just turn it into an iopl call and let the process have
* access to all I/O ports.
*
* XXX proper ioperm() support should be emulated by
* manipulating the page protections...
*/
return sys32_iopl(3);
}
typedef struct {
unsigned int ss_sp;
unsigned int ss_flags;
......
......@@ -587,6 +587,6 @@ mem_init (void)
setup_gate();
#ifdef CONFIG_IA32_SUPPORT
ia32_boot_gdt_init();
ia32_mem_init();
#endif
}
......@@ -14,7 +14,7 @@
# ifdef CONFIG_IA32_SUPPORT
extern void ia32_cpu_init (void);
extern void ia32_boot_gdt_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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment