tools/testing/selftests/x86/entry_from_vm86.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/entry_from_vm86.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/x86/entry_from_vm86.c- Extension
.c- Size
- 9315 bytes
- Lines
- 329
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
assert.hstdlib.hsys/syscall.hsys/signal.hsys/ucontext.hunistd.hstdio.hstring.hinttypes.hsys/mman.herr.hstddef.hstdbool.herrno.hsys/vm86.hhelpers.h
Detected Declarations
struct table_descfunction sighandlerfunction do_testfunction do_umip_testsfunction main
Annotated Snippet
struct table_desc {
unsigned short limit;
unsigned long base;
} __attribute__((packed));
/* Initialize variables with arbitrary values */
struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 };
struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae };
struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 };
struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 };
unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737;
/* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */
do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests");
/* Results from displacement-only addressing */
msw1 = *(unsigned short *)(test_mem + 2052);
memcpy(&idt1, test_mem + 2054, sizeof(idt1));
memcpy(&gdt1, test_mem + 2060, sizeof(gdt1));
/* Results from register-indirect addressing */
msw2 = *(unsigned short *)(test_mem + 2066);
memcpy(&idt2, test_mem + 2068, sizeof(idt2));
memcpy(&gdt2, test_mem + 2074, sizeof(gdt2));
/* Results when using register operands */
msw3 = *(unsigned short *)(test_mem + 2080);
printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1);
printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n",
idt1.limit, idt1.base);
printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n",
gdt1.limit, gdt1.base);
if (msw1 != msw2 || msw1 != msw3)
printf("[FAIL]\tAll the results of SMSW should be the same.\n");
else
printf("[PASS]\tAll the results from SMSW are identical.\n");
if (memcmp(&gdt1, &gdt2, sizeof(gdt1)))
printf("[FAIL]\tAll the results of SGDT should be the same.\n");
else
printf("[PASS]\tAll the results from SGDT are identical.\n");
if (memcmp(&idt1, &idt2, sizeof(idt1)))
printf("[FAIL]\tAll the results of SIDT should be the same.\n");
else
printf("[PASS]\tAll the results from SIDT are identical.\n");
sethandler(SIGILL, sighandler, 0);
do_test(vm86, vmcode_umip_str - vmcode, VM86_SIGNAL, 0,
"STR instruction");
clearhandler(SIGILL);
sethandler(SIGILL, sighandler, 0);
do_test(vm86, vmcode_umip_sldt - vmcode, VM86_SIGNAL, 0,
"SLDT instruction");
clearhandler(SIGILL);
}
int main(void)
{
struct vm86plus_struct v86;
unsigned char *addr = mmap((void *)load_addr, 4096,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1,0);
if (addr != (unsigned char *)load_addr)
err(1, "mmap");
memcpy(addr, vmcode, end_vmcode - vmcode);
addr[2048] = 2;
addr[2050] = 3;
memset(&v86, 0, sizeof(v86));
v86.regs.cs = load_addr / 16;
v86.regs.ss = load_addr / 16;
v86.regs.ds = load_addr / 16;
v86.regs.es = load_addr / 16;
/* Use the end of the page as our stack. */
v86.regs.esp = 4096;
assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
/* #BR -- should deliver SIG??? */
do_test(&v86, vmcode_bound - vmcode, VM86_INTx, 5, "#BR");
/*
* SYSENTER -- should cause #GP or #UD depending on CPU.
Annotation
- Immediate include surface: `assert.h`, `stdlib.h`, `sys/syscall.h`, `sys/signal.h`, `sys/ucontext.h`, `unistd.h`, `stdio.h`, `string.h`.
- Detected declarations: `struct table_desc`, `function sighandler`, `function do_test`, `function do_umip_tests`, `function main`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.