From: Tulio A M Mendes Date: Fri, 13 Feb 2026 19:42:45 +0000 (-0300) Subject: refactor: decouple struct process from arch-specific struct registers X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=2a8d8bf09ecd4a35c8709e90fbc4064867063407;p=AdrOS.git refactor: decouple struct process from arch-specific struct registers - Replace embedded 'struct registers user_regs' with opaque uint8_t user_regs[ARCH_REGS_SIZE] - Add include/arch_types.h dispatcher and include/arch/x86/arch_types.h (ARCH_REGS_SIZE=64) - Change arch_regs_set_retval, arch_regs_set_ustack, hal_usermode_enter_regs, arch_sigreturn to accept void* instead of struct registers* — arch implementations cast internally - process_fork_create and process_clone_create now take const void* child_regs - Remove #include interrupts.h from process.h, arch_process.h, hal/usermode.h, arch_signal.h - process.h is now fully architecture-agnostic (no x86 register names visible) 20/20 smoke, cppcheck clean --- diff --git a/include/arch/x86/arch_types.h b/include/arch/x86/arch_types.h new file mode 100644 index 00000000..edcb6cfc --- /dev/null +++ b/include/arch/x86/arch_types.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#ifndef ARCH_X86_TYPES_H +#define ARCH_X86_TYPES_H + +/* + * Size in bytes of the saved user-mode register frame (struct registers). + * x86: ds(4) + pusha(32) + int_no+err(8) + iret_frame(20) = 64 + * + * Used by struct process to hold an opaque register snapshot without + * pulling in the full x86 IDT / register definitions. + */ +#define ARCH_REGS_SIZE 64 + +#endif /* ARCH_X86_TYPES_H */ diff --git a/include/arch_process.h b/include/arch_process.h index a8f6560b..884a786a 100644 --- a/include/arch_process.h +++ b/include/arch_process.h @@ -11,7 +11,6 @@ #define ARCH_PROCESS_H #include -#include "interrupts.h" /* * arch_kstack_init — Prepare a kernel stack for a brand-new process/thread @@ -32,13 +31,15 @@ uintptr_t arch_kstack_init(void* stack_top, /* * Set the "return value" register in a saved trapframe. * On x86 this is EAX; on ARM it would be R0, etc. + * regs points to the opaque user_regs[] buffer in struct process. */ -void arch_regs_set_retval(struct registers* regs, uint32_t val); +void arch_regs_set_retval(void* regs, uint32_t val); /* * Set the user-mode stack pointer in a saved trapframe. * On x86 this is useresp; on ARM it would be SP_usr, etc. + * regs points to the opaque user_regs[] buffer in struct process. */ -void arch_regs_set_ustack(struct registers* regs, uintptr_t sp); +void arch_regs_set_ustack(void* regs, uintptr_t sp); #endif /* ARCH_PROCESS_H */ diff --git a/include/arch_signal.h b/include/arch_signal.h index 436fc573..6d4d7eef 100644 --- a/include/arch_signal.h +++ b/include/arch_signal.h @@ -10,19 +10,18 @@ #ifndef ARCH_SIGNAL_H #define ARCH_SIGNAL_H -#include "interrupts.h" - /* * arch_sigreturn — Restore user registers from a signal frame on the * user stack. Architecture-specific because the frame * layout and register sanitisation depend on the ISA. * * regs : current trapframe (will be overwritten on success). + * Points to the arch-specific register struct (e.g. struct registers on x86). * user_frame : user-space pointer to the signal frame pushed by the * signal delivery trampoline. * * Returns 0 on success, negative errno on failure. */ -int arch_sigreturn(struct registers* regs, const void* user_frame); +int arch_sigreturn(void* regs, const void* user_frame); #endif /* ARCH_SIGNAL_H */ diff --git a/include/arch_types.h b/include/arch_types.h new file mode 100644 index 00000000..065d67f8 --- /dev/null +++ b/include/arch_types.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018, Tulio A M Mendes + * All rights reserved. + * See LICENSE for details. + * + * Source: https://github.com/tadryanom/AdrOS + */ + +#ifndef ARCH_TYPES_H +#define ARCH_TYPES_H + +/* + * Architecture-specific type constants. + * This header provides opaque sizing information so that generic kernel + * headers (e.g. process.h) can embed arch data without including the + * full arch register / interrupt definitions. + */ + +#if defined(__i386__) || defined(__x86_64__) +#include "arch/x86/arch_types.h" +#else +/* Fallback for non-x86: define a generous default */ +#define ARCH_REGS_SIZE 64 +#endif + +#endif /* ARCH_TYPES_H */ diff --git a/include/hal/usermode.h b/include/hal/usermode.h index acba1737..9c5d8aee 100644 --- a/include/hal/usermode.h +++ b/include/hal/usermode.h @@ -11,10 +11,9 @@ #define HAL_USERMODE_H #include -#include "interrupts.h" int hal_usermode_enter(uintptr_t user_eip, uintptr_t user_esp); -void hal_usermode_enter_regs(const struct registers* regs); +void hal_usermode_enter_regs(const void* regs); #endif diff --git a/include/process.h b/include/process.h index 223bf1af..ca06b090 100644 --- a/include/process.h +++ b/include/process.h @@ -11,7 +11,7 @@ #define PROCESS_H #include -#include "interrupts.h" // For struct registers +#include "arch_types.h" #include "fs.h" #include "signal.h" @@ -74,7 +74,7 @@ struct process { int exit_status; int has_user_regs; - struct registers user_regs; + uint8_t user_regs[ARCH_REGS_SIZE]; /* opaque arch register snapshot */ // Minimal signals: per-signal action, blocked mask and pending mask. // sa_handler == 0 => default @@ -162,12 +162,14 @@ int process_kill(uint32_t pid, int sig); int process_kill_pgrp(uint32_t pgrp, int sig); // Create a child process that will resume in usermode from a saved register frame. -struct process* process_fork_create(uintptr_t child_as, const struct registers* child_regs); +// child_regs points to an opaque arch register snapshot (ARCH_REGS_SIZE bytes). +struct process* process_fork_create(uintptr_t child_as, const void* child_regs); // Create a thread (clone) sharing the parent's address space. +// child_regs points to an opaque arch register snapshot (ARCH_REGS_SIZE bytes). struct process* process_clone_create(uint32_t clone_flags, uintptr_t child_stack, - const struct registers* child_regs, + const void* child_regs, uintptr_t tls_base); // Look up a process by PID (scheduler lock must NOT be held). diff --git a/src/arch/x86/arch_process.c b/src/arch/x86/arch_process.c index 3e88b07e..80f92fe6 100644 --- a/src/arch/x86/arch_process.c +++ b/src/arch/x86/arch_process.c @@ -48,13 +48,15 @@ uintptr_t arch_kstack_init(void* stack_top, return (uintptr_t)sp; } -void arch_regs_set_retval(struct registers* regs, uint32_t val) +void arch_regs_set_retval(void* opaque, uint32_t val) { + struct registers* regs = (struct registers*)opaque; if (regs) regs->eax = val; } -void arch_regs_set_ustack(struct registers* regs, uintptr_t sp) +void arch_regs_set_ustack(void* opaque, uintptr_t sp) { + struct registers* regs = (struct registers*)opaque; if (regs) regs->useresp = (uint32_t)sp; } diff --git a/src/arch/x86/signal.c b/src/arch/x86/signal.c index 89705e1b..85ebb7b3 100644 --- a/src/arch/x86/signal.c +++ b/src/arch/x86/signal.c @@ -15,8 +15,9 @@ #if defined(__i386__) -int arch_sigreturn(struct registers* regs, const void* user_frame) +int arch_sigreturn(void* opaque, const void* user_frame) { + struct registers* regs = (struct registers*)opaque; if (!regs) return -EINVAL; if (!current_process) return -EINVAL; if ((regs->cs & 3U) != 3U) return -EPERM; diff --git a/src/hal/x86/usermode.c b/src/hal/x86/usermode.c index 4ebc4e46..579f30a0 100644 --- a/src/hal/x86/usermode.c +++ b/src/hal/x86/usermode.c @@ -23,9 +23,9 @@ int hal_usermode_enter(uintptr_t user_eip, uintptr_t user_esp) { #endif } -void hal_usermode_enter_regs(const struct registers* regs) { +void hal_usermode_enter_regs(const void* regs) { #if defined(__i386__) - x86_enter_usermode_regs(regs); + x86_enter_usermode_regs((const struct registers*)regs); #else (void)regs; #endif diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index eab3bde5..b5328c22 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -424,10 +424,10 @@ static void fork_child_trampoline(void) { vmm_as_activate(current_process->addr_space); } - hal_usermode_enter_regs(¤t_process->user_regs); + hal_usermode_enter_regs(current_process->user_regs); } -struct process* process_fork_create(uintptr_t child_as, const struct registers* child_regs) { +struct process* process_fork_create(uintptr_t child_as, const void* child_regs) { if (!child_as || !child_regs) return NULL; uintptr_t flags = spin_lock_irqsave(&sched_lock); @@ -466,7 +466,7 @@ struct process* process_fork_create(uintptr_t child_as, const struct registers* } proc->has_user_regs = 1; - proc->user_regs = *child_regs; + memcpy(proc->user_regs, child_regs, ARCH_REGS_SIZE); proc->tgid = proc->pid; proc->flags = 0; proc->tls_base = 0; @@ -520,12 +520,12 @@ static void clone_child_trampoline(void) { hal_cpu_set_tls(current_process->tls_base); } - hal_usermode_enter_regs(¤t_process->user_regs); + hal_usermode_enter_regs(current_process->user_regs); } struct process* process_clone_create(uint32_t clone_flags, uintptr_t child_stack, - const struct registers* child_regs, + const void* child_regs, uintptr_t tls_base) { if (!child_regs || !current_process) return NULL; @@ -610,12 +610,12 @@ struct process* process_clone_create(uint32_t clone_flags, } proc->has_user_regs = 1; - proc->user_regs = *child_regs; - arch_regs_set_retval(&proc->user_regs, 0); /* child returns 0 */ + memcpy(proc->user_regs, child_regs, ARCH_REGS_SIZE); + arch_regs_set_retval(proc->user_regs, 0); /* child returns 0 */ /* If child_stack specified, override user stack pointer */ if (child_stack) { - arch_regs_set_ustack(&proc->user_regs, child_stack); + arch_regs_set_ustack(proc->user_regs, child_stack); } /* Allocate kernel stack */