#ifndef PROCESS_H_ #define PROCESS_H_ #include #include #include #include /* 8 MB stack */ #define RLIMIT_STACK_VAL 0x800000 #define TASK_KERNEL 0x1 #define TASK_NOSCHED 0x2 /* * memory map for processes * 0xFFFFFFFF8000000 and up, kernel, can copy kernel pml4 entries * program load at 4 MB * stack at 128 TB = 8000 0000 0000 (and down) * mmaps at 127 TB = 7F00 0000 0000 (and down) * heap at 96 TB = 6000 0000 0000 (and up) * heap at 2 TB? * heap after program load... * program at 4 MB = 40 0000 */ /* so, to create a process, * allocate 2 MB for stack, * allocate whatever is needed for the code * load in the code to the code base * set up the registers * set up the stack for the iretq or sysret * iretq or sysret to start the task */ struct registers { uint64_t kerrno; uint64_t rax; uint64_t rbx; uint64_t rcx; uint64_t rdx; uint64_t rdi; uint64_t rsi; uint64_t rsp; uint64_t rbp; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t rip; uint64_t rflags; uint64_t cr3; uint64_t kernel_stack; uint64_t cs; uint64_t ss; __attribute__((aligned(16))) uint8_t fpuenv[512]; } __attribute__((packed)); /* flags bits */ /* user or kernel process */ #define TM_USER 0x1 /* needs re-scheduled */ #define TM_SCHEDULE 0x2 /* in syscall */ #define TM_SYSCALL 0x4 /* in interrupt */ #define TM_INTERRUPTED 0x8 #define TM_RUNNABLE 0x10 struct process { pid_t pid; pid_t ppid; /* todo just use a user or kernel process, maybe a flag */ int pl; /* privilege level, 0 for kernel, 3 for users */ uint64_t flags; /* bit flags */ struct registers reg; vaddr_t kstack; /* pointer to the kernel stack */ vaddr_t stacks; vaddr_t usp; /* user stack pointer */ vaddr_t heap; struct process *next, *prev; /* scheduling */ /* sleep should probably be a struct timespec */ uint64_t sleep; /* don't need to sleep for 64 bits of ticks */ int status; /* return status from main/exit */ unsigned int quantum; /* how many more ticks */ // struct inode *cwd; // struct sigaction_t sigaction[NUM_SIGNALS]; // uint64_t signal_pending; int (*main)(int ac, char **av); }; uint64_t getrflags(); /* assembly */ void init_tasking(); pid_t create_task(struct process *task, void (*main)(), uint64_t rflags, uint64_t pagedir, uint64_t flags); struct process *new_task(void (*entry)(), uint64_t rflags, uint64_t pagedir, uint64_t flags); void sleep(uint32_t ticks); void schedule(); void do_schedule(); int need_schedule(); void preempt(); // Switch task frontend void switch_task(struct registers *old, struct registers *new); void switch_task_iret(struct registers *old, struct registers *new); /* in assembly */ void usermodetrampoline(void (*main)(), uint64_t rflags); #endif