diff --git a/service/ptos/arch/amd64/ps/thread.c b/service/ptos/arch/amd64/ps/thread.c index bb01c41..996ffc8 100644 --- a/service/ptos/arch/amd64/ps/thread.c +++ b/service/ptos/arch/amd64/ps/thread.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* @@ -32,6 +33,44 @@ ThreadAllocKStack(VOID) return RANGE_PTR(&StackRange); } +/* + * Allocate a user stack and map it into the process + * address space. + * + * @Vas: Virtual address space to map to + */ +static UPTR +ThreadAllocUStack(MMU_VAS *Vas) +{ + MM_PFN StackPfn; + UPTR PhysicalBase; + MM_RANGE MapRange; + PT_STATUS Status; + + StackPfn = MmRequestFrame(); + if (StackPfn == PFN_ERROR) { + return 0; + } + + PhysicalBase = PFN_TO_ADDRESS(StackPfn); + MapRange.VirtualBase = PhysicalBase; + MapRange.PhysicalBase = PhysicalBase; + MapRange.Length = PAGESIZE; + Status = MmMapRange( + Vas, + &MapRange, + PAGE_READ | PAGE_WRITE | PAGE_USER, + PAGESIZE_4K + ); + + if (PT_ERROR(Status)) { + MmReclaimFrame(StackPfn); + return 0; + } + + return PhysicalBase; +} + /* * Initialize a thread control block * @@ -52,7 +91,18 @@ ThreadInitTcb(THREAD *Thread, TCB *Tcb, UPTR Ip) } Parent = Thread->Parent; - Thread->StackBase = (UPTR)ThreadAllocKStack(); + + /* + * Allocate a userstack or kernel stack depending on the + * flags set for the parent process. + */ + if (ISSET(Parent->Flags, PS_USER)) { + Thread->StackBase = ThreadAllocUStack(&Parent->Vas); + } else { + Thread->StackBase = (UPTR)ThreadAllocKStack(); + } + + /* Did the stack allocation fail? */ if (Thread->StackBase == 0) { return STATUS_NO_MEMORY; }