From: Josue Amaro <josue.amaro@oracle.com>
To: linux-ia64@vger.kernel.org
Subject: Re: [Linux-ia64] IA-32 LDT support patch
Date: Wed, 18 Apr 2001 07:57:53 +0000 [thread overview]
Message-ID: <marc-linux-ia64-105590693005422@msgid-missing> (raw)
In-Reply-To: <marc-linux-ia64-105590693005414@msgid-missing>
[-- Attachment #1: Type: text/plain, Size: 41260 bytes --]
David,
I'll test it as soon as I can.
Thanks,
David Mosberger wrote:
> Below is a patch that goes on top of the IA-64 Linux version of
> v2.4.3. It adds support for the IA-32 modify_ldt() system call which
> is needed to run certain x86 programs (such as programs linked against
> recent versions of x86 pthreads).
>
> Thanks to Don Dugger and Asit Mallick for reviewing the patch (all
> bugs are mine, of course...). I really know almost nothing about x86
> and I'm trying hard to keep it that way ;-), but the patch should work
> OK. At least "netscape" still works and a simple test program linked
> against a version of pthreads that uses modify_ldt() also seems to
> work fine.
>
> Enjoy,
>
> --david
>
> diff -urN lia64/arch/ia64/ia32/Makefile lia64-kdb/arch/ia64/ia32/Makefile
> --- lia64/arch/ia64/ia32/Makefile Wed Jan 3 23:06:42 2001
> +++ lia64-kdb/arch/ia64/ia32/Makefile Fri Apr 13 14:21:30 2001
> @@ -11,7 +11,8 @@
>
> O_TARGET := ia32.o
>
> -obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o ia32_support.o ia32_traps.o binfmt_elf32.o
> +obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o ia32_support.o ia32_traps.o \
> + binfmt_elf32.o ia32_ldt.o
>
> clean::
>
> diff -urN lia64/arch/ia64/ia32/binfmt_elf32.c lia64-kdb/arch/ia64/ia32/binfmt_elf32.c
> --- lia64/arch/ia64/ia32/binfmt_elf32.c Thu Apr 5 09:51:03 2001
> +++ lia64-kdb/arch/ia64/ia32/binfmt_elf32.c Fri Apr 13 19:34:37 2001
> @@ -2,8 +2,11 @@
> * IA-32 ELF support.
> *
> * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
> + * Copyright (C) 2001 Hewlett-Packard Co
> + * Copyright (C) 2001 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
> */
> #include <linux/config.h>
>
> @@ -35,8 +38,8 @@
> #undef CLOCKS_PER_SEC
> #define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC
>
> -extern void ia64_elf32_init(struct pt_regs *regs);
> -extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);
> +extern void ia64_elf32_init (struct pt_regs *regs);
> +extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address);
>
> #define ELF_PLAT_INIT(_r) ia64_elf32_init(_r)
> #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
> @@ -49,7 +52,7 @@
> unsigned long *ia32_gdt_table, *ia32_tss;
>
> struct page *
> -put_shared_page(struct task_struct * tsk, struct page *page, unsigned long address)
> +put_shared_page (struct task_struct * tsk, struct page *page, unsigned long address)
> {
> pgd_t * pgd;
> pmd_t * pmd;
> @@ -83,85 +86,87 @@
> return 0;
> }
>
> -void ia64_elf32_init(struct pt_regs *regs)
> +void
> +ia64_elf32_init (struct pt_regs *regs)
> {
> + struct vm_area_struct *vma;
> int nr;
>
> - put_shared_page(current, virt_to_page(ia32_gdt_table), IA32_PAGE_OFFSET);
> + /*
> + * Map GDT and TSS below 4GB, where the processor can find them. 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.
> + */
> + put_shared_page(current, virt_to_page(ia32_gdt_table), IA32_GDT_OFFSET);
> if (PAGE_SHIFT <= IA32_PAGE_SHIFT)
> - put_shared_page(current, virt_to_page(ia32_tss), IA32_PAGE_OFFSET + PAGE_SIZE);
> + put_shared_page(current, virt_to_page(ia32_tss), IA32_TSS_OFFSET);
>
> - nr = smp_processor_id();
> + /*
> + * Install LDT as anonymous memory. This gives us all-zero segment descriptors
> + * until a task modifies them via modify_ldt().
> + */
> + vma = kmem_cache_alloc(vm_area_cachep, SLAB_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;
> + vma->vm_ops = NULL;
> + vma->vm_pgoff = 0;
> + vma->vm_file = NULL;
> + vma->vm_private_data = NULL;
> + insert_vm_struct(current->mm, vma);
> + }
>
> - /* Do all the IA-32 setup here */
> + nr = smp_processor_id();
>
> - current->thread.map_base = 0x40000000;
> - current->thread.task_size = 0xc0000000; /* use what Linux/x86 uses... */
> + current->thread.map_base = IA32_PAGE_OFFSET/3;
> + current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
> set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
>
> - /* setup ia32 state for ia32_load_state */
> + /* 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 */
> +
> + /* Setup the segment descriptors */
> + regs->r24 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* ESD */
> + regs->r27 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* DSD */
> + regs->r28 = 0; /* FSD (null) */
> + regs->r29 = 0; /* GSD (null) */
> + regs->r30 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_LDT(nr)]); /* LDTD */
>
> - current->thread.eflag = IA32_EFLAG;
> - current->thread.csd = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0xBL, 1L, 3L, 1L, 1L, 1L);
> - current->thread.ssd = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
> - current->thread.tssd = IA64_SEG_DESCRIPTOR(IA32_PAGE_OFFSET + PAGE_SIZE, 0x1FFFL, 0xBL,
> - 1L, 3L, 1L, 1L, 1L);
> -
> - /* CS descriptor */
> - __asm__("mov ar.csd = %0" : /* no outputs */
> - : "r" IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0xBL, 1L,
> - 3L, 1L, 1L, 1L));
> - /* SS descriptor */
> - __asm__("mov ar.ssd = %0" : /* no outputs */
> - : "r" IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L,
> - 3L, 1L, 1L, 1L));
> - /* EFLAGS */
> - __asm__("mov ar.eflag = %0" : /* no outputs */ : "r" (IA32_EFLAG));
> -
> - /* Control registers */
> - __asm__("mov ar.fsr = %0"
> - : /* no outputs */
> - : "r" ((ulong)IA32_FSR_DEFAULT));
> - __asm__("mov ar.fcr = %0"
> - : /* no outputs */
> - : "r" ((ulong)IA32_FCR_DEFAULT));
> - __asm__("mov ar.fir = r0");
> - __asm__("mov ar.fdr = r0");
> - current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
> - ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
> -
> - /* Get the segment selectors right */
> - regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES == DS, GS, FS are zero */
> - regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32)
> - | (__USER_DS << 16) | __USER_CS;
> -
> - /* Setup other segment descriptors - ESD, DSD, FSD, GSD */
> - regs->r24 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
> - regs->r27 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
> - regs->r28 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
> - regs->r29 = IA64_SEG_DESCRIPTOR(0L, 0xFFFFFL, 0x3L, 1L, 3L, 1L, 1L, 1L);
> -
> - /* Setup the LDT and GDT */
> - regs->r30 = ia32_gdt_table[_LDT(nr)];
> - regs->r31 = IA64_SEG_DESCRIPTOR(0xc0000000L, 0x400L, 0x3L, 1L, 3L,
> - 1L, 1L, 1L);
> -
> - /* Clear psr.ac */
> - regs->cr_ipsr &= ~IA64_PSR_AC;
> + /*
> + * 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.
> + */
> + regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1, 0,
> + 0, 0, 0, 0, 0, 0));
>
> + ia64_psr(regs)->ac = 0; /* turn off alignment checking */
> regs->loadrs = 0;
> -}
>
> -#undef STACK_TOP
> -#define STACK_TOP ((IA32_PAGE_OFFSET/3) * 2)
> + 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;
> + current->thread.csd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_CS >> 3]);
> + current->thread.ssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]);
> + current->thread.tssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_TSS(nr)]);
> +
> + ia32_load_state(current);
> +}
>
> -int ia32_setup_arg_pages(struct linux_binprm *bprm)
> +int
> +ia32_setup_arg_pages (struct linux_binprm *bprm)
> {
> unsigned long stack_base;
> struct vm_area_struct *mpnt;
> int i;
>
> - stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
> + stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
>
> bprm->p += stack_base;
> if (bprm->loader)
> @@ -175,7 +180,7 @@
> {
> mpnt->vm_mm = current->mm;
> mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
> - mpnt->vm_end = STACK_TOP;
> + mpnt->vm_end = IA32_STACK_TOP;
> mpnt->vm_page_prot = PAGE_COPY;
> mpnt->vm_flags = VM_STACK_FLAGS;
> mpnt->vm_ops = NULL;
> @@ -197,15 +202,15 @@
> }
>
> static unsigned long
> -ia32_mm_addr(unsigned long addr)
> +ia32_mm_addr (unsigned long addr)
> {
> struct vm_area_struct *vma;
>
> if ((vma = find_vma(current->mm, addr)) == NULL)
> - return(ELF_PAGESTART(addr));
> + return ELF_PAGESTART(addr);
> if (vma->vm_start > addr)
> - return(ELF_PAGESTART(addr));
> - return(ELF_PAGEALIGN(addr));
> + return ELF_PAGESTART(addr);
> + return ELF_PAGEALIGN(addr);
> }
>
> /*
> @@ -232,22 +237,9 @@
> */
> if (addr == 0)
> addr += PAGE_SIZE;
> -#if 1
> set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz);
> memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz);
> kernel_read(filep, eppnt->p_offset, (char *) addr, eppnt->p_filesz);
> retval = (unsigned long) addr;
> -#else
> - /* doesn't work yet... */
> -# define IA32_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1))
> -# define IA32_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1))
> -# define IA32_PAGEALIGN(_v) (((_v) + ELF_EXEC_PAGESIZE - 1) & ~(ELF_EXEC_PAGESIZE - 1))
> -
> - down_write(¤t->mm->mmap_sem);
> - retval = ia32_do_mmap(filep, IA32_PAGESTART(addr),
> - eppnt->p_filesz + IA32_PAGEOFFSET(eppnt->p_vaddr), prot, type,
> - eppnt->p_offset - IA32_PAGEOFFSET(eppnt->p_vaddr));
> - up_write(¤t->mm->mmap_sem);
> -#endif
> return retval;
> }
> diff -urN lia64/arch/ia64/ia32/ia32_entry.S lia64-kdb/arch/ia64/ia32/ia32_entry.S
> --- lia64/arch/ia64/ia32/ia32_entry.S Wed Mar 28 21:42:44 2001
> +++ lia64-kdb/arch/ia64/ia32/ia32_entry.S Fri Apr 13 14:36:18 2001
> @@ -233,7 +233,7 @@
> data8 sys32_ni_syscall
> data8 sys_iopl /* 110 */
> data8 sys_vhangup
> - data8 sys32_ni_syscall // used to be sys_idle
> + data8 sys32_ni_syscall /* used to be sys_idle */
> data8 sys32_ni_syscall
> data8 sys32_wait4
> data8 sys_swapoff /* 115 */
> @@ -244,7 +244,7 @@
> data8 sys_clone /* 120 */
> data8 sys_setdomainname
> data8 sys32_newuname
> - data8 sys_modify_ldt
> + data8 sys32_modify_ldt
> data8 sys_adjtimex
> data8 sys32_mprotect /* 125 */
> data8 sys_sigprocmask
> diff -urN lia64/arch/ia64/ia32/ia32_ldt.c lia64-kdb/arch/ia64/ia32/ia32_ldt.c
> --- lia64/arch/ia64/ia32/ia32_ldt.c Wed Dec 31 16:00:00 1969
> +++ lia64-kdb/arch/ia64/ia32/ia32_ldt.c Fri Apr 13 20:23:48 2001
> @@ -0,0 +1,120 @@
> +/*
> + * Copyright (C) 2001 Hewlett-Packard Co
> + * Copyright (C) 2001 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/smp_lock.h>
> +#include <linux/vmalloc.h>
> +
> +#include <asm/uaccess.h>
> +#include <asm/ia32.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 *ptr, unsigned long bytecount)
> +{
> + char *src, *dst, buf[256]; /* temporary buffer (don't overflow kernel stack!) */
> + unsigned long bytes_left, n;
> +
> + if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
> + bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
> +
> + bytes_left = bytecount;
> +
> + src = (void *) 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
> +write_ldt (void * ptr, unsigned long bytecount, int oldmode)
> +{
> + struct ia32_modify_ldt_ldt_s ldt_info;
> + __u64 entry;
> +
> + 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().
> + */
> + return __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
> +}
> +
> +asmlinkage int
> +sys32_modify_ldt (int func, void *ptr, unsigned int bytecount)
> +{
> + int ret = -ENOSYS;
> +
> + switch (func) {
> + case 0:
> + ret = read_ldt(ptr, bytecount);
> + break;
> + case 1:
> + ret = write_ldt(ptr, bytecount, 1);
> + break;
> + case 0x11:
> + ret = write_ldt(ptr, bytecount, 0);
> + break;
> + }
> + return ret;
> +}
> diff -urN lia64/arch/ia64/ia32/ia32_support.c lia64-kdb/arch/ia64/ia32/ia32_support.c
> --- lia64/arch/ia64/ia32/ia32_support.c Wed Feb 21 16:05:28 2001
> +++ lia64-kdb/arch/ia64/ia32/ia32_support.c Fri Apr 13 20:20:49 2001
> @@ -1,6 +1,11 @@
> /*
> * 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 Hewlett-Packard Co
> + * Copyright (C) 2001 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
> */
> @@ -21,7 +26,7 @@
> extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
>
> void
> -ia32_save_state (struct thread_struct *thread)
> +ia32_save_state (struct task_struct *t)
> {
> unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
>
> @@ -33,28 +38,30 @@
> "mov %5=ar.csd;"
> "mov %6=ar.ssd;"
> : "=r"(eflag), "=r"(fsr), "=r"(fcr), "=r"(fir), "=r"(fdr), "=r"(csd), "=r"(ssd));
> - thread->eflag = eflag;
> - thread->fsr = fsr;
> - thread->fcr = fcr;
> - thread->fir = fir;
> - thread->fdr = fdr;
> - thread->csd = csd;
> - thread->ssd = ssd;
> - asm ("mov ar.k0=%0 ;;" :: "r"(thread->old_iob));
> + t->thread.eflag = eflag;
> + t->thread.fsr = fsr;
> + t->thread.fcr = fcr;
> + t->thread.fir = fir;
> + t->thread.fdr = fdr;
> + t->thread.csd = csd;
> + t->thread.ssd = ssd;
> + ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
> }
>
> void
> -ia32_load_state (struct thread_struct *thread)
> +ia32_load_state (struct task_struct *t)
> {
> unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
> + struct pt_regs *regs = ia64_task_regs(t);
> + int nr;
>
> - eflag = thread->eflag;
> - fsr = thread->fsr;
> - fcr = thread->fcr;
> - fir = thread->fir;
> - fdr = thread->fdr;
> - csd = thread->csd;
> - ssd = thread->ssd;
> + eflag = t->thread.eflag;
> + fsr = t->thread.fsr;
> + fcr = t->thread.fcr;
> + fir = t->thread.fir;
> + fdr = t->thread.fdr;
> + csd = t->thread.csd;
> + ssd = t->thread.ssd;
>
> asm volatile ("mov ar.eflag=%0;"
> "mov ar.fsr=%1;"
> @@ -64,17 +71,22 @@
> "mov ar.csd=%5;"
> "mov ar.ssd=%6;"
> :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr), "r"(csd), "r"(ssd));
> - asm ("mov %0=ar.k0 ;;" : "=r"(thread->old_iob));
> - asm ("mov ar.k0=%0 ;;" :: "r"(IA32_IOBASE));
> + current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
> + ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
> +
> + /* load TSS and LDT while preserving SS and CS: */
> + nr = smp_processor_id();
> + regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
> }
>
> /*
> - * Setup IA32 GDT and TSS
> + * Setup IA32 GDT and TSS
> */
> void
> -ia32_gdt_init(void)
> +ia32_gdt_init (void)
> {
> - unsigned long gdt_and_tss_page;
> + unsigned long gdt_and_tss_page, ldt_size;
> + int nr;
>
> /* allocate two IA-32 pages of memory: */
> gdt_and_tss_page = __get_free_pages(GFP_KERNEL,
> @@ -86,17 +98,28 @@
> /* Zero the gdt and tss */
> memset((void *) gdt_and_tss_page, 0, 2*IA32_PAGE_SIZE);
>
> - /* CS descriptor in IA-32 format */
> - ia32_gdt_table[4] = IA32_SEG_DESCRIPTOR(0L, 0xBFFFFFFFL, 0xBL, 1L,
> - 3L, 1L, 1L, 1L, 1L);
> -
> - /* DS descriptor in IA-32 format */
> - ia32_gdt_table[5] = IA32_SEG_DESCRIPTOR(0L, 0xBFFFFFFFL, 0x3L, 1L,
> - 3L, 1L, 1L, 1L, 1L);
> + /* CS descriptor in IA-32 (scrambled) format */
> + ia32_gdt_table[__USER_CS >> 3] =
> + IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
> + 0xb, 1, 3, 1, 1, 1, 1);
> +
> + /* DS descriptor in IA-32 (scrambled) format */
> + ia32_gdt_table[__USER_DS >> 3] =
> + IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
> + 0x3, 1, 3, 1, 1, 1, 1);
> +
> + /* We never change the TSS and LDT descriptors, so we can share them across all CPUs. */
> + ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
> + for (nr = 0; nr < NR_CPUS; ++nr) {
> + ia32_gdt_table[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
> + 0xb, 0, 3, 1, 1, 1, 0);
> + ia32_gdt_table[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
> + 0x2, 0, 3, 1, 1, 1, 0);
> + }
> }
>
> /*
> - * Handle bad IA32 interrupt via syscall
> + * Handle bad IA32 interrupt via syscall
> */
> void
> ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
> @@ -106,8 +129,7 @@
> die_if_kernel("Bad IA-32 interrupt", regs, int_num);
>
> siginfo.si_signo = SIGTRAP;
> - siginfo.si_errno = int_num; /* XXX is it legal to abuse si_errno like this? */
> + siginfo.si_errno = int_num; /* XXX is it OK to abuse si_errno like this? */
> siginfo.si_code = TRAP_BRKPT;
> force_sig_info(SIGTRAP, &siginfo, current);
> }
> -
> diff -urN lia64/arch/ia64/ia32/sys_ia32.c lia64-kdb/arch/ia64/ia32/sys_ia32.c
> --- lia64/arch/ia64/ia32/sys_ia32.c Thu Apr 5 09:51:22 2001
> +++ lia64-kdb/arch/ia64/ia32/sys_ia32.c Fri Apr 13 20:46:41 2001
> @@ -334,9 +334,9 @@
> down_write(¤t->mm->mmap_sem);
> retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset >> PAGE_SHIFT);
> up_write(¤t->mm->mmap_sem);
> -#else // CONFIG_IA64_PAGE_SIZE_4KB
> +#else
> retval = ia32_do_mmap(file, a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
> -#endif // CONFIG_IA64_PAGE_SIZE_4KB
> +#endif
> if (file)
> fput(file);
> return retval;
> @@ -1886,8 +1886,7 @@
> break;
>
> case SHMAT:
> - err = do_sys32_shmat (first, second, third,
> - version, (void *)AA(ptr));
> + err = do_sys32_shmat (first, second, third, version, (void *)AA(ptr));
> break;
> case SHMDT:
> err = sys_shmdt ((char *)AA(ptr));
> @@ -2334,8 +2333,8 @@
> * the address of `stack' will not be the address of the `pt_regs'.
> */
> asmlinkage long
> -sys32_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
> - long arg4, long arg5, long arg6, long arg7, long stack)
> +sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
> + long arg4, long arg5, long arg6, long arg7, long stack)
> {
> struct pt_regs *regs = (struct pt_regs *) &stack;
> struct task_struct *child;
> @@ -2379,7 +2378,7 @@
> case PTRACE_PEEKDATA: /* read word at location addr */
> ret = ia32_peek(regs, child, addr, &value);
> if (ret == 0)
> - ret = put_user(value, (unsigned int *)data);
> + ret = put_user(value, (unsigned int *)A(data));
> else
> ret = -EIO;
> goto out;
> @@ -2398,12 +2397,12 @@
> break;
>
> case IA32_PTRACE_GETREGS:
> - if (!access_ok(VERIFY_WRITE, (int *)data, 17*sizeof(int))) {
> + if (!access_ok(VERIFY_WRITE, (int *) A(data), 17*sizeof(int))) {
> ret = -EIO;
> break;
> }
> for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
> - __put_user(getreg(child, i),(unsigned int *) data);
> + __put_user(getreg(child, i), (unsigned int *) A(data));
> data += sizeof(int);
> }
> ret = 0;
> @@ -2412,12 +2411,12 @@
> case IA32_PTRACE_SETREGS:
> {
> unsigned int tmp;
> - if (!access_ok(VERIFY_READ, (int *)data, 17*sizeof(int))) {
> + if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
> ret = -EIO;
> break;
> }
> for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
> - __get_user(tmp, (unsigned int *) data);
> + __get_user(tmp, (unsigned int *) A(data));
> putreg(child, i, tmp);
> data += sizeof(int);
> }
> @@ -2426,11 +2425,11 @@
> }
>
> case IA32_PTRACE_GETFPREGS:
> - ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *)data);
> + ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *) A(data));
> break;
>
> case IA32_PTRACE_SETFPREGS:
> - ret = restore_ia32_fpstate(child, (struct _fpstate_ia32 *)data);
> + ret = restore_ia32_fpstate(child, (struct _fpstate_ia32 *) A(data));
> break;
>
> case PTRACE_SYSCALL: /* continue, stop after next syscall */
> @@ -2558,7 +2558,7 @@
> #define IOLEN ((65536 / 4) * 4096)
>
> asmlinkage long
> -sys_iopl (int level, long arg1, long arg2, long arg3)
> +sys_iopl (int level)
> {
> extern unsigned long ia64_iobase;
> int fd;
> @@ -2570,7 +2570,7 @@
> if (level != 3)
> return(-EINVAL);
> /* Trying to gain more privileges? */
> - __asm__ __volatile__("mov %0=ar.eflag ;;" : "=r"(old));
> + asm volatile ("mov %0=ar.eflag ;;" : "=r"(old));
> if (level > ((old >> 12) & 3)) {
> if (!capable(CAP_SYS_RAWIO))
> return -EPERM;
> @@ -2587,17 +2587,13 @@
> }
>
> down_write(¤t->mm->mmap_sem);
> - lock_kernel();
> -
> addr = do_mmap_pgoff(file, IA32_IOBASE,
> - IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
> - (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
> -
> - unlock_kernel();
> + IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
> + (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
> up_write(¤t->mm->mmap_sem);
>
> if (addr >= 0) {
> - __asm__ __volatile__("mov ar.k0=%0 ;;" :: "r"(addr));
> + ia64_set_kr(IA64_KR_IO_BASE, addr);
> old = (old & ~0x3000) | (level << 12);
> __asm__ __volatile__("mov ar.eflag=%0 ;;" :: "r"(old));
> }
> @@ -2608,7 +2604,7 @@
> }
>
> asmlinkage long
> -sys_ioperm (unsigned long from, unsigned long num, int on)
> +sys_ioperm (unsigned int from, unsigned int num, int on)
> {
>
> /*
> @@ -2621,7 +2617,7 @@
> * XXX proper ioperm() support should be emulated by
> * manipulating the page protections...
> */
> - return(sys_iopl(3, 0, 0, 0));
> + return sys_iopl(3);
> }
>
> typedef struct {
> diff -urN lia64/arch/ia64/kernel/semaphore.c lia64-kdb/arch/ia64/kernel/semaphore.c
> --- lia64/arch/ia64/kernel/semaphore.c Wed Dec 6 18:36:35 2000
> +++ lia64-kdb/arch/ia64/kernel/semaphore.c Fri Apr 13 20:48:40 2001
> @@ -321,13 +321,11 @@
>
> if (count == 0) {
> /* wake a writer */
> - if (xchg(&sem->write_bias_granted, 1))
> - BUG();
> + xchg(&sem->write_bias_granted, 1);
> wq = &sem->write_bias_wait;
> } else {
> /* wake reader(s) */
> - if (xchg(&sem->read_bias_granted, 1))
> - BUG();
> + xchg(&sem->read_bias_granted, 1);
> wq = &sem->wait;
> }
> wake_up(wq); /* wake up everyone on the wait queue */
> diff -urN lia64/arch/ia64/kernel/sys_ia64.c lia64-kdb/arch/ia64/kernel/sys_ia64.c
> --- lia64/arch/ia64/kernel/sys_ia64.c Thu Apr 5 09:57:58 2001
> +++ lia64-kdb/arch/ia64/kernel/sys_ia64.c Fri Apr 13 14:23:57 2001
> @@ -253,13 +253,6 @@
> return -ENOSYS;
> }
>
> -asmlinkage long
> -sys_modify_ldt (long arg0, long arg1, long arg2, long arg3)
> -{
> - printk(KERN_ERR "sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0, arg1, arg2, arg3);
> - return -ENOSYS;
> -}
> -
> asmlinkage unsigned long
> ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
> long arg4, long arg5, long arg6, long arg7, long stack)
> diff -urN lia64/arch/ia64/kernel/process.c lia64-kdb/arch/ia64/kernel/process.c
> --- lia64/arch/ia64/kernel/process.c Thu Apr 5 09:55:58 2001
> +++ lia64-kdb/arch/ia64/kernel/process.c Fri Apr 13 12:25:19 2001
> @@ -143,7 +143,7 @@
> pfm_save_regs(task);
> #endif
> if (IS_IA32_PROCESS(ia64_task_regs(task)))
> - ia32_save_state(&task->thread);
> + ia32_save_state(task);
> }
>
> void
> @@ -156,7 +156,7 @@
> pfm_load_regs(task);
> #endif
> if (IS_IA32_PROCESS(ia64_task_regs(task)))
> - ia32_load_state(&task->thread);
> + ia32_load_state(task);
> }
>
> /*
> diff -urN lia64/include/asm-ia64/ia32.h lia64-kdb/include/asm-ia64/ia32.h
> --- lia64/include/asm-ia64/ia32.h Thu Apr 5 11:51:44 2001
> +++ lia64-kdb/include/asm-ia64/ia32.h Fri Apr 13 20:14:04 2001
> @@ -108,7 +108,7 @@
> } sigset32_t;
>
> struct sigaction32 {
> - unsigned int sa_handler; /* Really a pointer, but need to deal
> + 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 */
> @@ -118,7 +118,7 @@
> typedef unsigned int old_sigset32_t; /* at least 32 bits */
>
> struct old_sigaction32 {
> - unsigned int sa_handler; /* Really a pointer, but need to deal
> + unsigned int sa_handler; /* Really a pointer, but need to deal
> with 32 bits */
> old_sigset32_t sa_mask; /* A 32 bit mask */
> unsigned int sa_flags;
> @@ -133,7 +133,7 @@
>
> struct ucontext_ia32 {
> unsigned int uc_flags;
> - unsigned int uc_link;
> + unsigned int uc_link;
> stack_ia32_t uc_stack;
> struct sigcontext_ia32 uc_mcontext;
> sigset_t uc_sigmask; /* mask last for extensibility */
> @@ -252,6 +252,15 @@
> #define ELF_ARCH EM_386
>
> #define IA32_PAGE_OFFSET 0xc0000000
> +#define IA32_STACK_TOP ((IA32_PAGE_OFFSET/3) * 2)
> +
> +/*
> + * 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 USE_ELF_CORE_DUMP
> #define ELF_EXEC_PAGESIZE IA32_PAGE_SIZE
> @@ -287,7 +296,7 @@
>
> /* This macro yields a bitmask that programs can use to figure out
> what instruction set this CPU supports. */
> -#define ELF_HWCAP 0
> +#define ELF_HWCAP 0
>
> /* This macro yields a string that ld.so will use to load
> implementation specific libraries for optimization. Not terribly
> @@ -304,58 +313,61 @@
> /*
> * IA-32 ELF specific definitions for IA-64.
> */
> -
> +
> #define __USER_CS 0x23
> #define __USER_DS 0x2B
>
> -#define SEG_LIM 32
> -#define SEG_TYPE 52
> -#define SEG_SYS 56
> -#define SEG_DPL 57
> -#define SEG_P 59
> -#define SEG_DB 62
> -#define SEG_G 63
> -
> #define FIRST_TSS_ENTRY 6
> #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
> #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
> #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
>
> -#define IA64_SEG_DESCRIPTOR(base, limit, segtype, nonsysseg, dpl, segpresent, segdb, granularity) \
> - ((base) | \
> - (limit << SEG_LIM) | \
> - (segtype << SEG_TYPE) | \
> - (nonsysseg << SEG_SYS) | \
> - (dpl << SEG_DPL) | \
> - (segpresent << SEG_P) | \
> - (segdb << SEG_DB) | \
> - (granularity << SEG_G))
> -
> -#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, granularity) \
> - ((limit & 0xFFFF) | \
> - (base & 0xFFFFFF << IA32_SEG_BASE) | \
> - (segtype << IA32_SEG_TYPE) | \
> - (nonsysseg << IA32_SEG_SYS) | \
> - (dpl << IA32_SEG_DPL) | \
> - (segpresent << IA32_SEG_P) | \
> - (((limit >> 16) & 0xF) << IA32_SEG_HIGH_LIMIT) | \
> - (avl << IA32_SEG_AVL) | \
> - (segdb << IA32_SEG_DB) | \
> - (granularity << IA32_SEG_G) | \
> - (((base >> 24) & 0xFF) << IA32_SEG_HIGH_BASE))
> +#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 0x2000000000000000 /* Virtual addres for I/O space */
> +#define IA32_IOBASE 0x2000000000000000 /* Virtual address for I/O space */
>
> #define IA32_CR0 0x80000001 /* Enable PG and PE bits */
> #define IA32_CR4 0 /* No architectural extensions */
> @@ -384,6 +396,25 @@
> 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. */
> +
> +struct ia32_modify_ldt_ldt_s {
> + 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;
> +};
> +
> extern void ia32_gdt_init (void);
> extern int ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
> sigset_t *set, struct pt_regs *regs);
> @@ -392,5 +423,5 @@
> extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
>
> #endif /* !CONFIG_IA32_SUPPORT */
> -
> +
> #endif /* _ASM_IA64_IA32_H */
> diff -urN lia64/include/asm-ia64/processor.h lia64-kdb/include/asm-ia64/processor.h
> --- lia64/include/asm-ia64/processor.h Thu Apr 5 11:51:41 2001
> +++ lia64-kdb/include/asm-ia64/processor.h Fri Apr 13 12:26:16 2001
> @@ -417,7 +417,7 @@
> /*
> * Free all resources held by a thread. This is called after the
> * parent of DEAD_TASK has collected the exist status of the task via
> - * wait(). This is a no-op on IA-64.
> + * wait().
> */
> #ifdef CONFIG_PERFMON
> extern void release_thread (struct task_struct *task);
> @@ -514,8 +514,8 @@
> extern void ia64_load_debug_regs (unsigned long *save_area);
>
> #ifdef CONFIG_IA32_SUPPORT
> -extern void ia32_save_state (struct thread_struct *thread);
> -extern void ia32_load_state (struct thread_struct *thread);
> +extern void ia32_save_state (struct task_struct *task);
> +extern void ia32_load_state (struct task_struct *task);
> #endif
>
> #ifdef CONFIG_PERFMON
>
> _______________________________________________
> Linux-IA64 mailing list
> Linux-IA64@linuxia64.org
> http://lists.linuxia64.org/lists/listinfo/linux-ia64
--
"When you see the correct course, act; do not wait for orders."
The Art of War
=======================================================================
Josue Emmanuel Amaro Josue.Amaro@oracle.com
Linux Products Manager Phone: 650.506.1239
Intel and Linux Technologies Group Fax: 650.413.0167
=======================================================================
[-- Attachment #2: Card for Josue Amaro --]
[-- Type: text/x-vcard, Size: 334 bytes --]
begin:vcard
n:Amaro;Josue
tel;fax:650 413 0167
tel;work:650 506 1239
x-mozilla-html:FALSE
url:www.oracle.com
org:Oracle Corporation
version:2.1
email;internet:josue.amaro@oracle.com
title:Linux Products Manager
adr;quoted-printable:;;500 Oracle Parkway=0D=0AMS 401 ip 4;Redwood Shores;CA;94065;United States
fn:Josue Amaro
end:vcard
prev parent reply other threads:[~2001-04-18 7:57 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-04-17 0:29 [Linux-ia64] IA-32 LDT support patch David Mosberger
2001-04-18 7:57 ` Josue Amaro [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=marc-linux-ia64-105590693005422@msgid-missing \
--to=josue.amaro@oracle.com \
--cc=linux-ia64@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox