2 * LDT manipulation functions
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
19 #include <linux/unistd.h>
20 #include <linux/head.h>
21 #include <linux/ldt.h>
23 _syscall3(int, modify_ldt
, int, func
, void *, ptr
, unsigned long, bytecount
)
26 #if defined(__NetBSD__) || defined(__FreeBSD__)
27 #include <machine/segments.h>
29 extern int i386_get_ldt(int, union descriptor
*, int);
30 extern int i386_set_ldt(int, union descriptor
*, int);
31 #endif /* __NetBSD__ || __FreeBSD__ */
33 #endif /* ifndef WINELIB */
36 /***********************************************************************
39 * Convert the raw bytes of the descriptor to an ldt_entry structure.
41 static void LDT_BytesToEntry( unsigned long *buffer
, ldt_entry
*content
)
43 content
->base
= (*buffer
>> 16) & 0x0000ffff;
44 content
->limit
= *buffer
& 0x0000ffff;
46 content
->base
|= (*buffer
& 0xff000000) | ((*buffer
<< 16) & 0x00ff0000);
47 content
->limit
|= (*buffer
& 0x000f0000);
48 content
->type
= (*buffer
>> 10) & 3;
49 content
->seg_32bit
= (*buffer
& 0x00400000) != 0;
50 content
->read_only
= (*buffer
& 0x00000200) == 0;
51 content
->limit_in_pages
= (*buffer
& 0x00800000) != 0;
55 /***********************************************************************
58 * Retrieve an LDT entry.
60 int LDT_GetEntry( int entry
, ldt_entry
*content
)
65 content
->base
= ldt_copy
[entry
].base
;
66 content
->limit
= ldt_copy
[entry
].limit
;
67 content
->type
= SEGMENT_DATA
;
68 content
->seg_32bit
= 0;
69 content
->read_only
= 0;
70 content
->limit_in_pages
= 0;
74 int size
= (entry
+ 1) * 2 * sizeof(long);
75 long *buffer
= (long *) malloc( size
);
76 ret
= modify_ldt( 0, buffer
, size
);
77 LDT_BytesToEntry( &buffer
[entry
*2], content
);
81 #if defined(__NetBSD__) || defined(__FreeBSD__)
83 ret
= i386_get_ldt( entry
, (union descriptor
*)buffer
, 1 );
84 LDT_BytesToEntry( buffer
, content
);
85 #endif /* __NetBSD__ || __FreeBSD__ */
93 /***********************************************************************
98 int LDT_SetEntry( int entry
, ldt_entry
*content
)
103 "LDT_SetEntry: entry=%04x base=%08lx limit=%05lx %s %d-bit flags=%c%c%c\n",
104 entry
, content
->base
, content
->limit
,
105 content
->limit_in_pages
? "pages" : "bytes",
106 content
->seg_32bit
? 32 : 16,
107 content
->read_only
&& (content
->type
& SEGMENT_CODE
) ? '-' : 'r',
108 content
->read_only
|| (content
->type
& SEGMENT_CODE
) ? '-' : 'w',
109 (content
->type
& SEGMENT_CODE
) ? 'x' : '-' );
114 struct modify_ldt_ldt_s ldt_info
;
116 memset( &ldt_info
, 0, sizeof(ldt_info
) );
117 ldt_info
.entry_number
= entry
;
118 ldt_info
.base_addr
= content
->base
;
119 ldt_info
.limit
= content
->limit
;
120 ldt_info
.seg_32bit
= content
->seg_32bit
!= 0;
121 ldt_info
.contents
= content
->type
;
122 ldt_info
.read_exec_only
= content
->read_only
!= 0;
123 ldt_info
.limit_in_pages
= content
->limit_in_pages
!= 0;
124 ret
= modify_ldt(1, &ldt_info
, sizeof(ldt_info
));
128 #if defined(__NetBSD__) || defined(__FreeBSD__)
132 d
[0] = ((content
->base
& 0x0000ffff) << 16) |
133 (content
->limit
& 0x0ffff);
134 d
[1] = (content
->base
& 0xff000000) |
135 ((content
->base
& 0x00ff0000)>>16) |
136 (content
->limit
& 0xf0000) |
137 (content
->type
<< 10) |
138 ((content
->read_only
== 0) << 9) |
139 ((content
->seg_32bit
!= 0) << 22) |
140 ((content
->limit_in_pages
!= 0) << 23) |
142 ret
= i386_set_ldt(entry
, (union descriptor
*)d
, 1);
145 perror("i386_set_ldt");
147 "Did you reconfigure the kernel with \"options USER_LDT\"?\n");
151 #endif /* __NetBSD__ || __FreeBSD__ */
152 #endif /* ifndef WINELIB */
154 if (ret
< 0) return ret
;
155 ldt_copy
[entry
].base
= content
->base
;
156 if (!content
->limit_in_pages
) ldt_copy
[entry
].limit
= content
->limit
;
157 else ldt_copy
[entry
].limit
= (content
->limit
<< 12) | 0x0fff;
162 /***********************************************************************
165 * Print the content of the LDT on stdout.
172 for (i
= 0; i
< LDT_SIZE
; i
++)
174 if (ldt_copy
[i
].base
|| ldt_copy
[i
].limit
)
176 fprintf( stderr
, "%04x: sel=%04x base=%08x limit=%05x\n",
177 i
, ENTRY_TO_SELECTOR(i
),
178 ldt_copy
[i
].base
, ldt_copy
[i
].limit
);
183 long buffer
[2*LDT_SIZE
];
188 n
= modify_ldt( 0, buffer
, sizeof(buffer
) ) / 8;
190 #if defined(__NetBSD__) || defined(__FreeBSD__)
191 n
= i386_get_ldt( 0, (union descriptor
*)buffer
, LDT_SIZE
);
192 #endif /* __NetBSD__ || __FreeBSD__ */
193 for (i
= 0; i
< n
; i
++)
195 LDT_BytesToEntry( &buffer
[2*i
], &content
);
196 if (content
.base
|| content
.limit
)
198 fprintf( stderr
, "%04x: sel=%04x base=%08lx limit=%05lx %s type=%d\n",
199 i
, ENTRY_TO_SELECTOR(i
),
200 content
.base
, content
.limit
,
201 content
.limit_in_pages
? "(pages)" : "(bytes)",