#define CONFIG_KERNEL_STACK_BASE ((void*)0xffffe000)
#endif /* !__ASSEMBLY_SOURCE */
#define CONFIG_USER_STACK_SIZE 4096
+#define CONFIG_USER_STACK_LIMIT (16 * 1048576)
#define CONFIG_PROC_MAXTASKS 8
#define CONFIG_MUTEX_WAITQLEN 8
#define CONFIG_SEM_WAITQLEN 8
return;
}
+static int _handle_pagefault(process_t *proc, task_t *task, u32_t addr)
+{
+ pg_dir_t *pd;
+ int ret_val;
+
+ ret_val = process_get_pagedir(proc, &pd);
+
+ if(!ret_val) {
+ /*
+ * pg_dir_grow_ustack() checks the address and only grows the
+ * stack if would not exceed the statically defined limit.
+ */
+ ret_val = pg_dir_grow_ustack(pd, (void*)addr);
+ }
+
+ return(ret_val);
+}
+
void _exc_handle(stack_frame_t ctx)
{
process_t *cproc;
/* kernel bug */
dbg_printf("Exception %u [%s] occurred. Error code 0x%08x.\n",
- ctx.intn, ctx.intn < EXC_MAX ? _exc_name[ctx.intn] : 0, ctx.error);
+ ctx.intn, ctx.intn < EXC_MAX ? _exc_name[ctx.intn] : 0, ctx.error);
dbg_printf("In context %p [pid %u]\n", cproc, process_get_id(cproc));
dbg_printf("Fault in 0x%02x:%08x; EFLAGS = 0x%08x\n", ctx.cs, ctx.eip, ctx.eflags);
int sig;
- dbg_printf("User-mode exception %u at 0x%08x\n", ctx.intn, ctx.eip);
+ dbg_printf("User-mode exception %u in pid %u at 0x%08x\n",
+ ctx.intn, process_get_id(cproc), ctx.eip);
if(ctx.intn == EXC_PAGEFAULT) {
u32_t cr2;
- pg_dir_t *pd;
asm volatile("movl %%cr2, %%eax; movl %%eax, %0" : "=r"(cr2));
dbg_printf("CR2: 0x%08x\n", cr2);
- if(process_get_pagedir(cproc, &pd) == 0) {
- pg_fault_debug(pd, (void*)cr2);
+ if(_handle_pagefault(cproc, ctask, cr2) >= 0) {
+ goto skip_signal;
}
}
+ for(;;);
+
switch(ctx.intn) {
default:
case EXC_DEBUG:
task_signal_deliver(ctask, &ctx, sig, NULL);
}
- return;
+skip_signal:
+ return;
}
void _sys_handle(stack_frame_t ctx)
return(ret_val);
}
+void* pg_dir_get_ustack_top(struct pagedir *pgdir)
+{
+ struct region *reg;
+ void *ret_val;
+ int i;
+
+ for(ret_val = NULL, i = 0; i < CONFIG_PAGING_DIR_MAXREGIONS; i++) {
+ reg = pgdir->pd_regions[i];
+
+ if(reg->reg_type == REGION_STACK) {
+ ret_val = (char*)reg->reg_base + reg->reg_size;
+ break;
+ }
+ }
+
+ return(ret_val);
+}
+
+int pg_dir_grow_ustack(struct pagedir *pgdir, void *new_bottom)
+{
+ struct region *stack;
+ char *stack_max;
+ char *stack_min;
+ char *new_aligned;
+ int ret_val;
+ int i;
+
+ for(stack = NULL, i = 0; i < CONFIG_PAGING_DIR_MAXREGIONS; i++) {
+ if(pgdir->pd_regions[i]->reg_type == REGION_STACK) {
+ stack = pgdir->pd_regions[i];
+ break;
+ }
+ }
+
+ if(!stack) {
+ ret_val = -EBADFD;
+ goto gtfo;
+ }
+
+ stack_max = (char*)stack->reg_base + stack->reg_size;
+ stack_min = stack_max - CONFIG_USER_STACK_LIMIT;
+ new_aligned = (char*)((unsigned long)new_bottom &
+ ~(stack->reg_pgsize - 1));
+
+ if(stack_min < new_aligned && new_aligned < stack_max) {
+ unsigned long map_size;
+
+ map_size = (unsigned long)stack->reg_base -
+ (unsigned long)new_aligned;
+
+ ret_val = pg_dir_map(pgdir, 0, new_aligned, map_size,
+ stack->reg_attrs);
+
+ if(!ret_val) {
+ stack->reg_base = new_aligned;
+ stack->reg_size = (unsigned long)stack_max -
+ (unsigned long)new_aligned;
+
+ dbg_printf("%s: Mapped %u bytes at 0x%08x\n", __func__,
+ map_size, new_aligned);
+ dbg_printf("%s: Stack is now at 0x%08x+0x%08x\n",
+ __func__, stack->reg_base, stack->reg_size);
+ }
+ } else {
+ ret_val = -ENOMEM;
+ }
+
+gtfo:
+ return(ret_val);
+}
+
int pg_dir_memcpy(struct pagedir *ddir, void *dvaddr,
struct pagedir *sdir, void *svaddr, u32_t bytes)
{
int _pg_dir_vpxlate(pg_dir_t*, u32_t, u32_t*);
void* pg_dir_get_kstack(pg_dir_t*);
void* pg_dir_get_ustack(pg_dir_t*);
+void* pg_dir_get_ustack_top(pg_dir_t*);
+int pg_dir_grow_ustack(pg_dir_t*, void*);
void* pg_dir_sbrk(pg_dir_t*, i32_t);
int pg_dir_foreach_region(pg_dir_t*, int(*)(pg_dir_t*, struct region*, void*), void*);
int pg_dir_memcpy(pg_dir_t*, void*, pg_dir_t*, void*, u32_t);