OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [ia32/] [binfmt_elf32.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * IA-32 ELF support.
3
 *
4
 * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
5
 * Copyright (C) 2001 Hewlett-Packard Co
6
 *      David Mosberger-Tang <davidm@hpl.hp.com>
7
 *
8
 * 06/16/00     A. Mallick      initialize csd/ssd/tssd/cflg for ia32_load_state
9
 * 04/13/01     D. Mosberger    dropped saving tssd in ar.k1---it's not needed
10
 * 09/14/01     D. Mosberger    fixed memory management for gdt/tss page
11
 */
12
#include <linux/config.h>
13
 
14
#include <linux/types.h>
15
 
16
#include <asm/param.h>
17
#include <asm/signal.h>
18
#include <asm/ia32.h>
19
 
20
#define CONFIG_BINFMT_ELF32
21
 
22
/* Override some function names */
23
#undef start_thread
24
#define start_thread                    ia32_start_thread
25
#define elf_format                      elf32_format
26
#define init_elf_binfmt                 init_elf32_binfmt
27
#define exit_elf_binfmt                 exit_elf32_binfmt
28
 
29
#undef CONFIG_BINFMT_ELF
30
#ifdef CONFIG_BINFMT_ELF32
31
# define CONFIG_BINFMT_ELF              CONFIG_BINFMT_ELF32
32
#endif
33
 
34
#undef CONFIG_BINFMT_ELF_MODULE
35
#ifdef CONFIG_BINFMT_ELF32_MODULE
36
# define CONFIG_BINFMT_ELF_MODULE       CONFIG_BINFMT_ELF32_MODULE
37
#endif
38
 
39
#undef CLOCKS_PER_SEC
40
#define CLOCKS_PER_SEC  IA32_CLOCKS_PER_SEC
41
 
42
extern void ia64_elf32_init (struct pt_regs *regs);
43
extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address);
44
 
45
static void elf32_set_personality (void);
46
 
47
#define ELF_PLAT_INIT(_r, load_addr)    ia64_elf32_init(_r)
48
#define setup_arg_pages(bprm)           ia32_setup_arg_pages(bprm)
49
#define elf_map                         elf32_map
50
 
51
#undef SET_PERSONALITY
52
#define SET_PERSONALITY(ex, ibcs2)      elf32_set_personality()
53
 
54
/* Ugly but avoids duplication */
55
#include "../../../fs/binfmt_elf.c"
56
 
57
extern struct page *ia32_shared_page[];
58
extern unsigned long *ia32_gdt;
59
 
60
struct page *
61
ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int no_share)
62
{
63
        struct page *pg = ia32_shared_page[(address - vma->vm_start)/PAGE_SIZE];
64
 
65
        get_page(pg);
66
        return pg;
67
}
68
 
69
static struct vm_operations_struct ia32_shared_page_vm_ops = {
70
        .nopage =ia32_install_shared_page
71
};
72
 
73
void
74
ia64_elf32_init (struct pt_regs *regs)
75
{
76
        struct vm_area_struct *vma;
77
 
78
        /*
79
         * Map GDT and TSS below 4GB, where the processor can find them.  We need to map
80
         * it with privilege level 3 because the IVE uses non-privileged accesses to these
81
         * tables.  IA-32 segmentation is used to protect against IA-32 accesses to them.
82
         */
83
        vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
84
        if (vma) {
85
                vma->vm_mm = current->mm;
86
                vma->vm_start = IA32_GDT_OFFSET;
87
                vma->vm_end = vma->vm_start + max(PAGE_SIZE, 2*IA32_PAGE_SIZE);
88
                vma->vm_page_prot = PAGE_SHARED;
89
                vma->vm_flags = VM_READ|VM_MAYREAD;
90
                vma->vm_ops = &ia32_shared_page_vm_ops;
91
                vma->vm_pgoff = 0;
92
                vma->vm_file = NULL;
93
                vma->vm_private_data = NULL;
94
                down_write(&current->mm->mmap_sem);
95
                {
96
                        insert_vm_struct(current->mm, vma);
97
                }
98
                up_write(&current->mm->mmap_sem);
99
        }
100
 
101
        /*
102
         * Install LDT as anonymous memory.  This gives us all-zero segment descriptors
103
         * until a task modifies them via modify_ldt().
104
         */
105
        vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
106
        if (vma) {
107
                vma->vm_mm = current->mm;
108
                vma->vm_start = IA32_LDT_OFFSET;
109
                vma->vm_end = vma->vm_start + PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
110
                vma->vm_page_prot = PAGE_SHARED;
111
                vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE;
112
                vma->vm_ops = NULL;
113
                vma->vm_pgoff = 0;
114
                vma->vm_file = NULL;
115
                vma->vm_private_data = NULL;
116
                down_write(&current->mm->mmap_sem);
117
                {
118
                        insert_vm_struct(current->mm, vma);
119
                }
120
                up_write(&current->mm->mmap_sem);
121
        }
122
 
123
        ia64_psr(regs)->ac = 0;          /* turn off alignment checking */
124
        regs->loadrs = 0;
125
        /*
126
         *  According to the ABI %edx points to an `atexit' handler.  Since we don't have
127
         *  one we'll set it to 0 and initialize all the other registers just to make
128
         *  things more deterministic, ala the i386 implementation.
129
         */
130
        regs->r8 = 0;    /* %eax */
131
        regs->r11 = 0;   /* %ebx */
132
        regs->r9 = 0;    /* %ecx */
133
        regs->r10 = 0;   /* %edx */
134
        regs->r13 = 0;   /* %ebp */
135
        regs->r14 = 0;   /* %esi */
136
        regs->r15 = 0;   /* %edi */
137
 
138
        current->thread.eflag = IA32_EFLAG;
139
        current->thread.fsr = IA32_FSR_DEFAULT;
140
        current->thread.fcr = IA32_FCR_DEFAULT;
141
        current->thread.fir = 0;
142
        current->thread.fdr = 0;
143
 
144
        /*
145
         * Setup GDTD.  Note: GDTD is the descrambled version of the pseudo-descriptor
146
         * format defined by Figure 3-11 "Pseudo-Descriptor Format" in the IA-32
147
         * architecture manual. Also note that the only fields that are not ignored are
148
         * `base', `limit', 'G', `P' (must be 1) and `S' (must be 0).
149
         */
150
        regs->r31 = IA32_SEG_UNSCRAMBLE(IA32_SEG_DESCRIPTOR(IA32_GDT_OFFSET, IA32_PAGE_SIZE - 1,
151
                                                            0, 0, 0, 1, 0, 0, 0));
152
        /* Setup the segment selectors */
153
        regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES == DS, GS, FS are zero */
154
        regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */
155
 
156
        ia32_load_segment_descriptors(current);
157
        ia32_load_state(current);
158
}
159
 
160
int
161
ia32_setup_arg_pages (struct linux_binprm *bprm)
162
{
163
        unsigned long stack_base;
164
        struct vm_area_struct *mpnt;
165
        int i;
166
 
167
        stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
168
 
169
        bprm->p += stack_base;
170
        if (bprm->loader)
171
                bprm->loader += stack_base;
172
        bprm->exec += stack_base;
173
 
174
        mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
175
        if (!mpnt)
176
                return -ENOMEM;
177
 
178
        down_write(&current->mm->mmap_sem);
179
        {
180
                mpnt->vm_mm = current->mm;
181
                mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
182
                mpnt->vm_end = IA32_STACK_TOP;
183
                mpnt->vm_page_prot = PAGE_COPY;
184
                mpnt->vm_flags = VM_STACK_FLAGS;
185
                mpnt->vm_ops = NULL;
186
                mpnt->vm_pgoff = 0;
187
                mpnt->vm_file = NULL;
188
                mpnt->vm_private_data = 0;
189
                insert_vm_struct(current->mm, mpnt);
190
                current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
191
        }
192
 
193
        for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
194
                struct page *page = bprm->page[i];
195
                if (page) {
196
                        bprm->page[i] = NULL;
197
                        put_dirty_page(current, page, stack_base);
198
                }
199
                stack_base += PAGE_SIZE;
200
        }
201
        up_write(&current->mm->mmap_sem);
202
 
203
        return 0;
204
}
205
 
206
static void
207
elf32_set_personality (void)
208
{
209
        set_personality(PER_LINUX32);
210
        current->thread.map_base  = IA32_PAGE_OFFSET/3;
211
        current->thread.task_size = IA32_PAGE_OFFSET;   /* use what Linux/x86 uses... */
212
        current->thread.flags |= IA64_THREAD_XSTACK;    /* data must be executable */
213
        set_fs(USER_DS);                                /* set addr limit for new TASK_SIZE */
214
}
215
 
216
static unsigned long
217
elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
218
{
219
        unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
220
 
221
        return ia32_do_mmap(filep, (addr & IA32_PAGE_MASK), eppnt->p_filesz + pgoff, prot, type,
222
                            eppnt->p_offset - pgoff);
223
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.