// top half page fault handler void page_fault(registers_struct* regs) { uint32 addr; _asm { mov eax, cr2 mov dword ptr addr, eax } // push thread in the exception queue if (thread_get_current()) { thread_exception te; te.exception_number = 14; te.target_thread = thread_get_current(); te.data[0] = addr; te.data[1] = regs->err_code; if (!queue_spsc_insert(&thread_get_current()->exceptions, te)) WARNING("queue_lf insertion error"); } else PANIC("Page fault occured but threading is not enabled!"); }
inline static bool thread_current_is_attached(void) { threadobject *t; t = thread_get_current(); if (t == NULL) return false; return thread_is_attached(t); }
uint32_t thread_get_pc(struct thread *t) { if (t == NULL) t = thread_get_current(); if (t == NULL) { fprintf(stderr, "mvm: thread not initialized!\n"); mvm_halt(); } return t->pc; }
struct vm_stack * thread_get_vm_stack(struct thread *t) { if (t == NULL) t = thread_get_current(); if (t == NULL) { fprintf(stderr, "mvm: thread not initialized!\n"); mvm_halt(); } return t->vm_stack; }
struct thread_dmp * thread_get_dmp(struct thread *t) { if (t == NULL) t = thread_get_current(); if (t == NULL) { fprintf(stderr, "mvm: thread not initialized!\n"); mvm_halt(); } return t->dmp; }
int table_run_equals(struct table *t, struct object *o, struct object *p) { int ref; int32_t value; uint32_t pc; struct integer *integer; struct object *object; struct vm_stack *vm_stack; struct frame *frame; struct operand_stack *operand_stack; struct thread *thread; if (t == NULL) { fprintf(stderr, "mvm: table not initialized!\n"); mvm_halt(); } thread = thread_get_current(); pc = thread_get_pc(thread); vm_stack = thread_get_vm_stack(thread); frame = vm_stack_peek(vm_stack); operand_stack = frame_get_operand_stack(frame); operand_stack_push(operand_stack, object_get_ref(o)); operand_stack_push(operand_stack, object_get_ref(p)); invoke_virtual_method_by_name(thread, object_get_ref(o), pc, "equals", 1, "Object"); ref = operand_stack_peek(operand_stack); object = heap_fetch_object(heap, ref); integer = object_get_integer(object); value = integer_get_value(integer); operand_stack_pop(operand_stack); return value; }
/*** * Return the java.lang.Thread object for the current thread. */ inline static java_handle_t *thread_get_current_object(void) { return LLNI_WRAP(thread_get_current()->object); }
/* maThread = create_kernel_thread( (kernel_thread_start_routine_t) Thread::start, (void*) this); } void Threads::exit_thread(vaddr_t stack_vaddr) { }*/ void Threads::suspend(int suspID){ sched_set_waiting(thread_get_current(),suspID); }
void page_fault_bottom(thread_exception te) { thread_exception_print(&te); uint32& addr = te.data[0]; uint32& code = te.data[1]; serial_printf("PAGE_FALUT: PROC: %u ADDRESS: %h, THREAD: %u, CODE: %h\n", process_get_current()->id, addr, thread_get_current()->id, code); if (process_get_current()->contract_spinlock == 1) PANIC("PAge fault spinlock is already reserved\n"); spinlock_acquire(&process_get_current()->contract_spinlock); vm_area* p_area = vm_contract_find_area(&thread_get_current()->parent->memory_contract, addr); if (p_area == 0) { serial_printf("could not find address %h in memory contract", addr); PANIC(""); // terminate thread and process with SIGSEGV } vm_area area = *p_area; spinlock_release(&process_get_current()->contract_spinlock); // tried to acccess inaccessible page if ((area.flags & MMAP_PROTECTION) == MMAP_NO_ACCESS) { serial_printf("address: %h is inaccessible\n", addr); PANIC(""); } // tried to write to read-only or inaccessible page if (page_fault_error_is_write(code) && (area.flags & MMAP_WRITE) != MMAP_WRITE) { serial_printf("cannot write to address: %h\n", addr); PANIC(""); } // tried to read a write-only or inaccesible page ???what??? /*if (!page_fault_error_is_write(code) && CHK_BIT(area.flags, MMAP_READ)) { serial_printf("cannot read from address: %h", addr); PANIC(""); }*/ // if the page is present then a violation happened (we do not implement swap out/shared anonymous yet) if (page_fault_error_is_page_present(code) == true) { serial_printf("memory violation at address: %h with code: %h\n", addr, code); serial_printf("area flags: %h\n", area.flags); PANIC(""); } // here we found out that the page is not present, so we need to allocate it properly if (CHK_BIT(area.flags, MMAP_PRIVATE)) { if (CHK_BIT(area.flags, MMAP_ALLOC_IMMEDIATE)) { // loop through all addresses and map them for (virtual_addr address = area.start_addr; address < area.end_addr; address += 4096) //if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) ALLOC_IMMEDIATE works only for anonymous (imposed in mmap) page_fault_alloc_page(area.flags, address); } else { if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) page_fault_alloc_page(area.flags, addr & (~0xFFF)); else { uint32 flags = page_fault_calculate_present_flags(area.flags); vmmngr_alloc_page_f(addr & (~0xFFF), flags); uint32 read_start = area.offset + ((addr - area.start_addr) / PAGE_SIZE) * PAGE_SIZE; // file read start uint32 read_size = PAGE_SIZE; // we read one page at a time (not the whole area as this may not be necessary) //if (read_start < area.start_addr + PAGE_SIZE) // we are reading the first page so subtract offset from read_size // read_size -= area.offset; serial_printf("gfd: %u, reading at mem: %h, phys: %h file: %h, size: %u\n", area.fd, addr & (~0xfff), vmmngr_get_phys_addr(addr & (~0xfff)), read_start, read_size); gfe* entry = gft_get(area.fd); if (entry == 0) { serial_printf("area.fd = %u", area.fd); PANIC("page fault gfd entry = 0"); } // read one page from the file offset given at the 4KB-aligned fault address if (read_file_global(area.fd, read_start, read_size, addr & (~0xFFF), VFS_CAP_READ | VFS_CAP_CACHE) != read_size) { serial_printf("read fd: %u\n", area.fd); PANIC("mmap anonymous file read less bytes than expected"); } } } } else // MMAP_SHARED { if (CHK_BIT(area.flags, MMAP_ANONYMOUS)) PANIC("A shared area cannot be marked as anonymous yet."); else { // in the shared file mapping the address to read is ignored as data are read only to page cache. uint32 read_start = area.offset + ((addr & (~0xfff)) - area.start_addr); gfe* entry = gft_get(area.fd); if (read_file_global(area.fd, read_start, PAGE_SIZE, -1, VFS_CAP_READ | VFS_CAP_CACHE) != PAGE_SIZE) PANIC("mmap shared file failed"); virtual_addr used_cache = page_cache_get_buffer(area.fd, read_start / PAGE_SIZE); //serial_printf("m%h\n", used_cache); uint32 flags = page_fault_calculate_present_flags(area.flags); vmmngr_map_page(vmmngr_get_directory(), vmmngr_get_phys_addr(used_cache), addr & (~0xfff), flags/*DEFAULT_FLAGS*/); //serial_printf("shared mapping fd: %u, cache: %h, phys cache: %h, read: %u, addr: %h\n", area.fd, used_cache, used_cache, read_start, addr); } } }