authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-06-26 00:57:28-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:14-04:00
log41832aa1e651a4a19f3ab275a54c28ed27180cd5
tree4970a07b74b92a19b44f07ec6916c4d03f112f57
parent6abf1fbfe6f7f3c06e70e331a3c9e5101624d501

linux: add getcontext for x86_64


2 files changed, 70 insertions(+), 1 deletions(-)

lib/std/os/linux.zig+2-1
......@@ -86,6 +86,7 @@ pub const timeval = arch_bits.timeval;
8686pub const timezone = arch_bits.timezone;
8787pub const ucontext_t = arch_bits.ucontext_t;
8888pub const user_desc = arch_bits.user_desc;
89pub const getcontext = arch_bits.getcontext;
8990
9091pub const tls = @import("linux/tls.zig");
9192pub const pie = @import("linux/start_pie.zig");
......@@ -4694,7 +4695,7 @@ else
46944695 /// processes.
46954696 RTPRIO,
46964697
4697 /// Maximum CPU time in µs that a process scheduled under a real-time
4698 /// Maximum CPU time in µs that a process scheduled under a real-time
46984699 /// scheduling policy may consume without making a blocking system
46994700 /// call before being forcibly descheduled.
47004701 RTTIME,
lib/std/os/linux/x86_64.zig+68
......@@ -395,3 +395,71 @@ pub const ucontext_t = extern struct {
395395 sigmask: sigset_t,
396396 fpregs_mem: [64]usize,
397397};
398
399fn gpRegisterOffset(comptime reg_index: comptime_int) usize {
400 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;
401}
402
403pub inline fn getcontext(context: *ucontext_t) usize {
404 asm volatile (
405 \\ movq %%r8, (%[r8_offset])(%[context])
406 \\ movq %%r9, (%[r9_offset])(%[context])
407 \\ movq %%r10, (%[r10_offset])(%[context])
408 \\ movq %%r11, (%[r11_offset])(%[context])
409 \\ movq %%r12, (%[r12_offset])(%[context])
410 \\ movq %%r13, (%[r13_offset])(%[context])
411 \\ movq %%r14, (%[r14_offset])(%[context])
412 \\ movq %%r15, (%[r15_offset])(%[context])
413 \\ movq %%rdi, (%[rdi_offset])(%[context])
414 \\ movq %%rsi, (%[rsi_offset])(%[context])
415 \\ movq %%rbp, (%[rbp_offset])(%[context])
416 \\ movq %%rbx, (%[rbx_offset])(%[context])
417 \\ movq %%rdx, (%[rdx_offset])(%[context])
418 \\ movq %%rax, (%[rax_offset])(%[context])
419 \\ movq %%rcx, (%[rcx_offset])(%[context])
420 \\ movq %%rsp, (%[rsp_offset])(%[context])
421 \\ leaq (%%rip), %%rcx
422 \\ movq %%rcx, (%[rip_offset])(%[context])
423 \\ pushfq
424 \\ popq (%[efl_offset])(%[context])
425 \\ leaq (%[fpmem_offset])(%[context]), %%rcx
426 \\ movq %%rcx, (%[fpstate_offset])(%[context])
427 \\ fnstenv (%%rcx)
428 \\ stmxcsr (%[mxcsr_offset])(%[context])
429 :
430 : [context] "{rdi}" (context),
431 [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)),
432 [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)),
433 [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)),
434 [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)),
435 [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)),
436 [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)),
437 [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)),
438 [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)),
439 [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)),
440 [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)),
441 [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)),
442 [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)),
443 [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)),
444 [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)),
445 [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)),
446 [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)),
447 [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)),
448 [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)),
449 [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
450 [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")),
451 [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),
452 : "memory", "rcx"
453 );
454
455 // TODO: Read GS/FS registers?
456
457 // TODO: `flags` isn't present in the getcontext man page, figure out what to write here
458 context.flags = 0;
459 context.link = null;
460
461 const altstack_result = linux.sigaltstack(null, &context.stack);
462 if (altstack_result != 0) return altstack_result;
463
464 return linux.sigprocmask(0, null, &context.sigmask);
465}