Revision 6dbad63e tests/test-i386.c
b/tests/test-i386.c | ||
---|---|---|
1 | 1 |
#include <stdlib.h> |
2 | 2 |
#include <stdio.h> |
3 |
#include <inttypes.h> |
|
3 | 4 |
#include <math.h> |
4 | 5 |
|
5 | 6 |
#define xglue(x, y) x ## y |
... | ... | |
612 | 613 |
TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); |
613 | 614 |
} |
614 | 615 |
|
616 |
/**********************************************/ |
|
617 |
/* segmentation tests */ |
|
618 |
|
|
619 |
#include <asm/ldt.h> |
|
620 |
#include <linux/unistd.h> |
|
621 |
|
|
622 |
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) |
|
623 |
|
|
624 |
uint8_t seg_data1[4096]; |
|
625 |
uint8_t seg_data2[4096]; |
|
626 |
|
|
627 |
#define MK_SEL(n) (((n) << 3) | 4) |
|
628 |
|
|
629 |
/* NOTE: we use Linux modify_ldt syscall */ |
|
630 |
void test_segs(void) |
|
631 |
{ |
|
632 |
struct modify_ldt_ldt_s ldt; |
|
633 |
long long ldt_table[3]; |
|
634 |
int i, res, res2; |
|
635 |
char tmp; |
|
636 |
|
|
637 |
ldt.entry_number = 1; |
|
638 |
ldt.base_addr = (unsigned long)&seg_data1; |
|
639 |
ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; |
|
640 |
ldt.seg_32bit = 1; |
|
641 |
ldt.contents = MODIFY_LDT_CONTENTS_DATA; |
|
642 |
ldt.read_exec_only = 0; |
|
643 |
ldt.limit_in_pages = 1; |
|
644 |
ldt.seg_not_present = 0; |
|
645 |
ldt.useable = 1; |
|
646 |
modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
|
647 |
|
|
648 |
ldt.entry_number = 2; |
|
649 |
ldt.base_addr = (unsigned long)&seg_data2; |
|
650 |
ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; |
|
651 |
ldt.seg_32bit = 1; |
|
652 |
ldt.contents = MODIFY_LDT_CONTENTS_DATA; |
|
653 |
ldt.read_exec_only = 0; |
|
654 |
ldt.limit_in_pages = 1; |
|
655 |
ldt.seg_not_present = 0; |
|
656 |
ldt.useable = 1; |
|
657 |
modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
|
658 |
|
|
659 |
modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ |
|
660 |
for(i=0;i<3;i++) |
|
661 |
printf("%d: %016Lx\n", i, ldt_table[i]); |
|
662 |
|
|
663 |
/* do some tests with fs or gs */ |
|
664 |
asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); |
|
665 |
asm volatile ("movl %0, %%gs" : : "r" (MK_SEL(2))); |
|
666 |
|
|
667 |
seg_data1[1] = 0xaa; |
|
668 |
seg_data2[1] = 0x55; |
|
669 |
|
|
670 |
asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); |
|
671 |
printf("FS[1] = %02x\n", res); |
|
672 |
|
|
673 |
asm volatile ("gs movzbl 0x1, %0" : "=r" (res)); |
|
674 |
printf("GS[1] = %02x\n", res); |
|
675 |
|
|
676 |
/* tests with ds/ss (implicit segment case) */ |
|
677 |
tmp = 0xa5; |
|
678 |
asm volatile ("pushl %%ebp\n\t" |
|
679 |
"pushl %%ds\n\t" |
|
680 |
"movl %2, %%ds\n\t" |
|
681 |
"movl %3, %%ebp\n\t" |
|
682 |
"movzbl 0x1, %0\n\t" |
|
683 |
"movzbl (%%ebp), %1\n\t" |
|
684 |
"popl %%ds\n\t" |
|
685 |
"popl %%ebp\n\t" |
|
686 |
: "=r" (res), "=r" (res2) |
|
687 |
: "r" (MK_SEL(1)), "r" (&tmp)); |
|
688 |
printf("DS[1] = %02x\n", res); |
|
689 |
printf("SS[tmp] = %02x\n", res2); |
|
690 |
} |
|
615 | 691 |
|
616 | 692 |
static void *call_end __init_call = NULL; |
617 | 693 |
|
... | ... | |
628 | 704 |
test_bsx(); |
629 | 705 |
test_mul(); |
630 | 706 |
test_jcc(); |
631 |
test_lea(); |
|
632 | 707 |
test_floats(); |
633 | 708 |
test_bcd(); |
709 |
test_lea(); |
|
710 |
test_segs(); |
|
634 | 711 |
return 0; |
635 | 712 |
} |
Also available in: Unified diff