1 /* $NetBSD: testldt.c,v 1.13 2005/12/24 21:43:51 perry Exp $ */
4 * Copyright (c) 1993 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
38 #include <machine/segments.h>
39 #include <machine/sysarch.h>
42 set_fs(unsigned int val
)
44 __asm
volatile("mov %0,%%fs"::"r" ((unsigned short) val
));
48 get_fs_byte(const char *addr
)
52 __asm ("movb %%fs:%1,%0":"=q" (_v
):"m" (*addr
));
61 __asm ("movw %%cs,%0": "=r" ((unsigned short) _v
));
68 unsigned int sel
= LSEL(desc
, SEL_UPL
);
70 return(get_fs_byte((char *) 0));
76 printf("Called from call gate...");
77 __asm
volatile("movl %ebp,%esp");
78 __asm
volatile("popl %ebp");
79 __asm
volatile(".byte 0xcb");
82 static union descriptor
*
83 make_sd(void *basep
, unsigned limit
, int type
, int dpl
, int seg32
, int inpgs
)
85 static union descriptor d
;
86 unsigned long base
= (unsigned long)basep
;
88 d
.sd
.sd_lolimit
= limit
& 0x0000ffff;
89 d
.sd
.sd_lobase
= base
& 0x00ffffff;
90 d
.sd
.sd_type
= type
& 0x01f;
91 d
.sd
.sd_dpl
= dpl
& 0x3;
93 d
.sd
.sd_hilimit
= (limit
& 0x00ff0000) >> 16;
95 d
.sd
.sd_def32
= seg32
?1:0;
96 d
.sd
.sd_gran
= inpgs
?1:0;
97 d
.sd
.sd_hibase
= (base
& 0xff000000) >> 24;
102 static union descriptor
*
103 make_gd(void *func
, unsigned int sel
, unsigned stkcpy
, int type
, int dpl
)
105 static union descriptor d
;
106 unsigned long offset
= (unsigned long)func
;
108 d
.gd
.gd_looffset
= offset
& 0x0000ffff;
109 d
.gd
.gd_selector
= sel
& 0xffff;
110 d
.gd
.gd_stkcpy
= stkcpy
& 0x1ff;
111 d
.gd
.gd_type
= type
& 0x1ff;
112 d
.gd
.gd_dpl
= dpl
& 0x3;
114 d
.gd
.gd_hioffset
= (offset
& 0xffff0000) >> 16;
121 "SYSNULL", "SYS286TSS", "SYSLDT", "SYS286BSY",
122 "SYS286CGT", "SYSTASKGT", "SYS286IGT", "SYS286TGT",
123 "SYSNULL2", "SYS386TSS", "SYSNULL3", "SYS386BSY",
124 "SYS386CGT", "SYSNULL4", "SYS386IGT", "SYS386TGT",
125 "MEMRO", "MEMROA", "MEMRW", "MEMRWA",
126 "MEMROD", "MEMRODA", "MEMRWD", "MEMRWDA",
127 "MEME", "MEMEA", "MEMER", "MEMERA",
128 "MEMEC", "MEMEAC", "MEMERC", "MEMERAC"
132 segtype(unsigned int type
)
135 return "Out of range";
137 return seg_type_name
[type
];
142 print_ldt(union descriptor
*dp
)
144 unsigned long base_addr
, limit
, offset
, stack_copy
;
145 unsigned int type
, dpl
;
148 (void) memcpy(lp
, dp
, sizeof(lp
));
150 base_addr
= dp
->sd
.sd_lobase
| (dp
->sd
.sd_hibase
<< 24);
151 limit
= dp
->sd
.sd_lolimit
| (dp
->sd
.sd_hilimit
<< 16);
152 offset
= dp
->gd
.gd_looffset
| (dp
->gd
.gd_hioffset
<< 16);
154 type
= dp
->sd
.sd_type
;
156 stack_copy
= dp
->gd
.gd_stkcpy
;
158 if (type
== SDT_SYS386CGT
|| type
== SDT_SYS286CGT
)
159 printf("LDT: Gate Off %8.8lx, Sel %5.5x, Stkcpy %lu DPL %d,"
161 offset
, dp
->gd
.gd_selector
, stack_copy
, dpl
,
162 type
, segtype(type
));
164 printf("LDT: Seg Base %8.8lx, Limit %5.5lx, DPL %d, "
166 base_addr
, limit
, dpl
,
167 type
, segtype(type
));
170 printf("Accessed, ");
173 if (type
!= SDT_SYS386CGT
&& type
!= SDT_SYS286CGT
) {
183 printf("page limit, ");
185 printf("byte limit, ");
188 printf(" Raw descriptor: %08lx %08lx\n", lp
[0], lp
[1]);
195 errx(1, "%s\n - investigate.", sys_siglist
[signo
]);
201 errx(status
, "Usage: testldt [-v]");
204 #define MAX_USER_LDT 1024
207 main(int argc
, char *argv
[])
209 union descriptor ldt
[MAX_USER_LDT
];
212 unsigned int cs
= get_cs();
214 union descriptor
*sd
, *gd
;
215 unsigned char one
= 1, two
= 2, val
;
216 struct sigaction segv_act
;
219 segv_act
.sa_handler
= busfault
;
220 if (sigaction(SIGBUS
, &segv_act
, NULL
) < 0)
223 while ((ch
= getopt(argc
, argv
, "v")) != -1) {
234 printf("Testing i386_get_ldt...\n");
235 if ((num
= i386_get_ldt(0, ldt
, MAX_USER_LDT
)) < 0)
239 errx(1, "i386_get_ldt() returned empty initial LDT");
242 printf("Got %d (initial) LDT entries\n", num
);
243 for (n
=0; n
< num
; n
++) {
244 printf("Entry %d: ", n
);
250 * mmap a data area and assign an LDT to it
252 printf("Testing i386_set_ldt...\n");
253 data
= (void *) mmap( (char *)0x005f0000, 0x0fff,
254 PROT_EXEC
| PROT_READ
| PROT_WRITE
,
255 MAP_FIXED
| MAP_PRIVATE
| MAP_ANON
, -1, (off_t
)0);
260 printf("data address: %p\n", data
);
264 /* Get the next free LDT and set it to the allocated data. */
265 sd
= make_sd(data
, 2048, SDT_MEMRW
, SEL_UPL
, 0, 0);
266 if ((num
= i386_set_ldt(1024, sd
, 1)) < 0)
269 if (verbose
) printf("setldt returned: %d\n", num
);
270 if ((n
= i386_get_ldt(num
, ldt
, 1)) < 0)
274 printf("Entry %d: ", num
);
279 printf("Checking desc (should be 0x97): 0x%x\n",
281 if (check_desc(num
) != 0x97)
282 errx(1, "ERROR: descriptor check failed; "
283 "expected 0x97, got 0x%x", check_desc(num
));
288 printf("Making Call Gate\n");
291 gd
= make_gd((void *)gated_call
, cs
, 0, SDT_SYS386CGT
, SEL_UPL
);
292 if ((num
= i386_set_ldt(4095, gd
, 1)) < 0)
293 err(1, "set_ldt: call gate");
296 printf("setldt returned: %d\n", num
);
297 printf("Call gate sel = 0x%x\n", LSEL(num
, SEL_UPL
));
300 if ((n
= i386_get_ldt(num
, ldt
, 1)) < 0)
304 printf("Entry %d: ", num
);
308 printf("Testing call gate...");
311 * Long call to call gate.
312 * Only the selector matters; offset is irrelevant.
314 __asm
volatile("lcall $0x7fff,$0x0");
316 printf("Gated call returned\n");
319 * Test multiple sets.
322 printf("Testing multiple descriptors at once.\n");
324 sd
= (union descriptor
*)malloc (sizeof(*sd
) * 2);
326 err(1, "can't malloc");
328 sd
[0] = *make_sd(&one
, 1, SDT_MEMRO
, SEL_UPL
, 1, 0);
329 sd
[1] = *make_sd(&two
, 1, SDT_MEMRO
, SEL_UPL
, 1, 0);
331 if ((num
= i386_set_ldt(8000, (union descriptor
*)sd
, 2)) < 0)
334 if (verbose
) printf("setldt returned: %d\n", num
);
335 if ((n
= i386_get_ldt(num
, ldt
, 2)) < 0)
339 printf("Entry %d: ", num
);
341 printf("Entry %d: ", num
+1);
344 val
= check_desc(num
);
345 printf("contents of segment ONE: %x\n", val
);
347 errx(1, "ONE has unexpected value %x", val
);
349 val
= check_desc(num
+1);
350 printf("contents of segment TWO: %x\n", val
);
352 errx(1, "TWO has unexpected value %x", val
);
354 if ((n
= i386_get_ldt(num
, ldt
, 2)) < 0)
358 printf("Entry %d: ", num
);
360 printf("Entry %d: ", num
+1);