comparison loader/ldt_keeper.c @ 7386:174e2a58b4cd

avifile sync - 95% cosmetics 5% bug
author arpi
date Fri, 13 Sep 2002 19:43:17 +0000
parents 02576893af2a
children 9d3e1476ecd0
comparison
equal deleted inserted replaced
7385:e2fcdd7608b1 7386:174e2a58b4cd
2 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3 * This file MUST be in main library because LDT must 3 * This file MUST be in main library because LDT must
4 * be modified before program creates first thread 4 * be modified before program creates first thread
5 * - avifile includes this file from C++ code 5 * - avifile includes this file from C++ code
6 * and initializes it at the start of player! 6 * and initializes it at the start of player!
7 * it might sound like a hack and it really is - but
8 * as aviplay is deconding video with more than just one
9 * thread currently it's necessary to do it this way
10 * this might change in the future
7 */ 11 */
8 12
13 /* applied some modification to make make our xine friend more happy */
9 #include "ldt_keeper.h" 14 #include "ldt_keeper.h"
10 15
11 #include <string.h> 16 #include <string.h>
12 #include <stdlib.h> 17 #include <stdlib.h>
13 #include <errno.h> 18 #include <errno.h>
17 #include <stdio.h> 22 #include <stdio.h>
18 #include <unistd.h> 23 #include <unistd.h>
19 #ifdef __linux__ 24 #ifdef __linux__
20 #include <asm/unistd.h> 25 #include <asm/unistd.h>
21 #include <asm/ldt.h> 26 #include <asm/ldt.h>
27 /* prototype it here, so we won't depend on kernel headers */
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 int modify_ldt(int func, void *ptr, unsigned long bytecount);
32 #ifdef __cplusplus
33 }
34 #endif
22 #else 35 #else
23 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) 36 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
24 #include <machine/segments.h> 37 #include <machine/segments.h>
25 #include <machine/sysarch.h> 38 #include <machine/sysarch.h>
26 #endif 39 #endif
31 44
32 /* solaris x86: add missing prototype for sysi86() */ 45 /* solaris x86: add missing prototype for sysi86() */
33 #ifdef __cplusplus 46 #ifdef __cplusplus
34 extern "C" { 47 extern "C" {
35 #endif 48 #endif
36 extern int sysi86(int, void*); 49 int sysi86(int, void*);
37 #ifdef __cplusplus 50 #ifdef __cplusplus
38 } 51 }
39 #endif 52 #endif
40 53
41 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */ 54 #ifndef NUMSYSLDTS /* SunOS 2.5.1 does not define NUMSYSLDTS */
67 80
68 81
69 /* user level (privilege level: 3) ldt (1<<2) segment selector */ 82 /* user level (privilege level: 3) ldt (1<<2) segment selector */
70 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3) 83 #define LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3)
71 84
85 /* i got this value from wine sources, it's the first free LDT entry */
72 #ifndef TEB_SEL_IDX 86 #ifndef TEB_SEL_IDX
73 #define TEB_SEL_IDX 1 87 #define TEB_SEL_IDX 17
74 #endif 88 #endif
89
75 #define TEB_SEL LDT_SEL(TEB_SEL_IDX) 90 #define TEB_SEL LDT_SEL(TEB_SEL_IDX)
76 91
77 /**
78 *
79 * This should be performed before we create first thread. See remarks
80 * for write_ldt(), linux/kernel/ldt.c.
81 *
82 */
83
84 void* fs_seg = NULL;
85 static char* prev_struct = NULL;
86 /** 92 /**
87 * here is a small logical problem with Restore for multithreaded programs - 93 * here is a small logical problem with Restore for multithreaded programs -
88 * in C++ we use static class for this... 94 * in C++ we use static class for this...
89 */ 95 */
90 96
96 __asm__ __volatile__( 102 __asm__ __volatile__(
97 "movl %0,%%eax; movw %%ax, %%fs" : : "i" (TEB_SEL) 103 "movl %0,%%eax; movw %%ax, %%fs" : : "i" (TEB_SEL)
98 ); 104 );
99 } 105 }
100 106
107 /* we don't need this - use modify_ldt instead */
108 #if 0
101 #ifdef __linux__ 109 #ifdef __linux__
102 /* XXX: why is this routine from libc redefined here? */ 110 /* XXX: why is this routine from libc redefined here? */
103 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */ 111 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */
104 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr, 112 static int LDT_Modify( int func, struct modify_ldt_ldt_s *ptr,
105 unsigned long count ) 113 unsigned long count )
128 if (res >= 0) return res; 136 if (res >= 0) return res;
129 errno = -res; 137 errno = -res;
130 return -1; 138 return -1;
131 } 139 }
132 #endif 140 #endif
141 #endif
133 142
134 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) 143 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
135 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content ) 144 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content )
136 { 145 {
137 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) | 146 *buffer++ = ((content->base_addr & 0x0000ffff) << 16) |
145 ((content->limit_in_pages != 0) << 23) | 154 ((content->limit_in_pages != 0) << 23) |
146 0xf000; 155 0xf000;
147 } 156 }
148 #endif 157 #endif
149 158
150 void Setup_LDT_Keeper(void) 159 //void* fs_seg=0;
160
161 ldt_fs_t* Setup_LDT_Keeper(void)
151 { 162 {
152 struct modify_ldt_ldt_s array; 163 struct modify_ldt_ldt_s array;
153 int fd;
154 int ret; 164 int ret;
155 165 ldt_fs_t* ldt_fs = (ldt_fs_t*) malloc(sizeof(ldt_fs_t));
156 if (fs_seg) 166
157 return; 167 if (!ldt_fs)
158 168 return NULL;
159 prev_struct = 0; 169
160 fd = open("/dev/zero", O_RDWR); 170 ldt_fs->fd = open("/dev/zero", O_RDWR);
161 if(fd<0){ 171 if(ldt_fs->fd<0){
162 perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " ); 172 perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: ");
163 return; 173 return NULL;
164 } 174 }
165 fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, 175 // fs_seg=
166 fd, 0); 176 ldt_fs->fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE,
167 if(fs_seg==(void*)-1) 177 ldt_fs->fd, 0);
178 if (ldt_fs->fs_seg == (void*)-1)
168 { 179 {
169 perror("ERROR: Couldn't allocate memory for fs segment"); 180 perror("ERROR: Couldn't allocate memory for fs segment");
170 return; 181 close(ldt_fs->fd);
171 } 182 free(ldt_fs);
172 // printf("fs seg %p\n", fs_seg); 183 return NULL;
173 *(void**)((char*)fs_seg+0x18) = fs_seg; 184 }
174 array.base_addr=(int)fs_seg; 185 *(void**)((char*)ldt_fs->fs_seg+0x18) = ldt_fs->fs_seg;
186 array.base_addr=(int)ldt_fs->fs_seg;
175 array.entry_number=TEB_SEL_IDX; 187 array.entry_number=TEB_SEL_IDX;
176 array.limit=array.base_addr+getpagesize()-1; 188 array.limit=array.base_addr+getpagesize()-1;
177 array.seg_32bit=1; 189 array.seg_32bit=1;
178 array.read_exec_only=0; 190 array.read_exec_only=0;
179 array.seg_not_present=0; 191 array.seg_not_present=0;
180 array.contents=MODIFY_LDT_CONTENTS_DATA; 192 array.contents=MODIFY_LDT_CONTENTS_DATA;
181 array.limit_in_pages=0; 193 array.limit_in_pages=0;
182 #ifdef __linux__ 194 #ifdef __linux__
183 ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s)); 195 //ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s));
196 ret=modify_ldt(0x1, &array, sizeof(struct modify_ldt_ldt_s));
184 if(ret<0) 197 if(ret<0)
185 { 198 {
186 perror("install_fs"); 199 perror("install_fs");
187 printf("Couldn't install fs segment, expect segfault\n"); 200 printf("Couldn't install fs segment, expect segfault\n");
188 } 201 }
198 { 211 {
199 perror("install_fs"); 212 perror("install_fs");
200 printf("Couldn't install fs segment, expect segfault\n"); 213 printf("Couldn't install fs segment, expect segfault\n");
201 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n"); 214 printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n");
202 } 215 }
203 printf("Set_LDT\n");
204 } 216 }
205 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */ 217 #endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
206 218
207 #if defined(__svr4__) 219 #if defined(__svr4__)
208 { 220 {
221 } 233 }
222 #endif 234 #endif
223 235
224 Setup_FS_Segment(); 236 Setup_FS_Segment();
225 237
226 prev_struct = (char*)malloc(sizeof(char) * 8); 238 ldt_fs->prev_struct = (char*)malloc(sizeof(char) * 8);
227 *(void**)array.base_addr = prev_struct; 239 *(void**)array.base_addr = ldt_fs->prev_struct;
228 close(fd); 240
229 } 241 return ldt_fs;
230 242 }
231 void Restore_LDT_Keeper(void) 243
232 { 244 void Restore_LDT_Keeper(ldt_fs_t* ldt_fs)
233 if (fs_seg == 0) 245 {
246 if (ldt_fs == NULL || ldt_fs->fs_seg == 0)
234 return; 247 return;
235 if (prev_struct) 248 if (ldt_fs->prev_struct)
236 free(prev_struct); 249 free(ldt_fs->prev_struct);
237 munmap((char*)fs_seg, getpagesize()); 250 munmap((char*)ldt_fs->fs_seg, getpagesize());
238 fs_seg = 0; 251 ldt_fs->fs_seg = 0;
239 } 252 close(ldt_fs->fd);
253 free(ldt_fs);
254 }