void G1PageBasedVirtualSpace::initialize_with_page_size(ReservedSpace rs, size_t used_size, size_t page_size) { guarantee(rs.is_reserved(), "Given reserved space must have been reserved already."); vmassert(_low_boundary == NULL, "VirtualSpace already initialized"); vmassert(page_size > 0, "Page size must be non-zero."); guarantee(is_ptr_aligned(rs.base(), page_size), "Reserved space base " PTR_FORMAT " is not aligned to requested page size " SIZE_FORMAT, p2i(rs.base()), page_size); guarantee(is_size_aligned(used_size, os::vm_page_size()), "Given used reserved space size needs to be OS page size aligned (%d bytes) but is " SIZE_FORMAT, os::vm_page_size(), used_size); guarantee(used_size <= rs.size(), "Used size of reserved space " SIZE_FORMAT " bytes is smaller than reservation at " SIZE_FORMAT " bytes", used_size, rs.size()); guarantee(is_size_aligned(rs.size(), page_size), "Expected that the virtual space is size aligned, but " SIZE_FORMAT " is not aligned to page size " SIZE_FORMAT, rs.size(), page_size); _low_boundary = rs.base(); _high_boundary = _low_boundary + used_size; _special = rs.special(); _executable = rs.executable(); _page_size = page_size; vmassert(_committed.size() == 0, "virtual space initialized more than once"); BitMap::idx_t size_in_pages = rs.size() / page_size; _committed.initialize(size_in_pages); if (_special) { _dirty.initialize(size_in_pages); } _tail_size = used_size % _page_size; }
/*===========================================================================* * schedcheck * *===========================================================================*/ PUBLIC struct proc * schedcheck(void) { /* This function is called an instant before proc_ptr is * to be scheduled again. */ NOREC_ENTER(schedch); vmassert(intr_disabled()); /* * if the current process is still runnable check the misc flags and let * it run unless it becomes not runnable in the meantime */ if (proc_is_runnable(proc_ptr)) goto check_misc_flags; /* * if a process becomes not runnable while handling the misc flags, we * need to pick a new one here and start from scratch. Also if the * current process wasn' runnable, we pick a new one here */ not_runnable_pick_new: if (proc_is_preempted(proc_ptr)) { proc_ptr->p_rts_flags &= ~RTS_PREEMPTED; if (proc_is_runnable(proc_ptr)) enqueue_head(proc_ptr); } /* this enqueues the process again */ if (proc_no_quantum(proc_ptr)) RTS_UNSET(proc_ptr, RTS_NO_QUANTUM); /* * if we have no process to run, set IDLE as the current process for * time accounting and put the cpu in and idle state. After the next * timer interrupt the execution resumes here and we can pick another * process. If there is still nothing runnable we "schedule" IDLE again */ while( !(proc_ptr = pick_proc())) { proc_ptr = proc_addr(IDLE); if (priv(proc_ptr)->s_flags & BILLABLE) bill_ptr = proc_ptr; idle(); } check_misc_flags: vmassert(proc_ptr); vmassert(proc_is_runnable(proc_ptr)); while (proc_ptr->p_misc_flags & (MF_DELIVERMSG | MF_SC_DEFER | MF_SC_TRACE | MF_SC_ACTIVE)) { vmassert(proc_is_runnable(proc_ptr)); if (proc_ptr->p_misc_flags & MF_DELIVERMSG) { TRACE(VF_SCHEDULING, printf("delivering to %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint);); if(delivermsg(proc_ptr) == VMSUSPEND) { TRACE(VF_SCHEDULING, printf("suspending %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint););
void G1PageBasedVirtualSpace::commit_preferred_pages(size_t start, size_t num_pages) { vmassert(num_pages > 0, "No full pages to commit"); vmassert(start + num_pages <= _committed.size(), "Tried to commit area from page " SIZE_FORMAT " to page " SIZE_FORMAT " " "that is outside of managed space of " SIZE_FORMAT " pages", start, start + num_pages, _committed.size()); char* start_addr = page_start(start); size_t size = num_pages * _page_size; os::commit_memory_or_exit(start_addr, size, _page_size, _executable, err_msg("Failed to commit area from " PTR_FORMAT " to " PTR_FORMAT " of length " SIZE_FORMAT ".", p2i(start_addr), p2i(start_addr + size), size)); }
void controlled_crash(int how) { if (how == 0) return; // If asserts are disabled, use the corresponding guarantee instead. NOT_DEBUG(if (how <= 2) how += 2); const char* const str = "hello"; const size_t num = (size_t)os::vm_page_size(); const char* const eol = os::line_separator(); const char* const msg = "this message should be truncated during formatting"; char * const dataPtr = NULL; // bad data pointer const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer // Keep this in sync with test/runtime/6888954/vmerrors.sh. switch (how) { case 1: vmassert(str == NULL, "expected null"); case 2: vmassert(num == 1023 && *str == 'X', err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); case 3: guarantee(str == NULL, "expected null"); case 4: guarantee(num == 1023 && *str == 'X', err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); case 5: fatal("expected null"); case 6: fatal(err_msg("num=" SIZE_FORMAT " str=\"%s\"", num, str)); case 7: fatal(err_msg("%s%s# %s%s# %s%s# %s%s# %s%s# " "%s%s# %s%s# %s%s# %s%s# %s%s# " "%s%s# %s%s# %s%s# %s%s# %s", msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg, eol, msg)); case 8: vm_exit_out_of_memory(num, OOM_MALLOC_ERROR, "ChunkPool::allocate"); case 9: ShouldNotCallThis(); case 10: ShouldNotReachHere(); case 11: Unimplemented(); // There's no guarantee the bad data pointer will crash us // so "break" out to the ShouldNotReachHere(). case 12: *dataPtr = '\0'; break; // There's no guarantee the bad function pointer will crash us // so "break" out to the ShouldNotReachHere(). case 13: (*funcPtr)(); break; case 14: crash_with_segfault(); break; case 15: crash_with_sigfpe(); break; default: tty->print_cr("ERROR: %d: unexpected test_num value.", how); } ShouldNotReachHere(); }
void G1PageBasedVirtualSpace::commit_tail() { vmassert(_tail_size > 0, "The size of the tail area must be > 0 when reaching here"); char* const aligned_end_address = (char*)align_ptr_down(_high_boundary, _page_size); os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), _executable, err_msg("Failed to commit tail area from " PTR_FORMAT " to " PTR_FORMAT " of length " SIZE_FORMAT ".", p2i(aligned_end_address), p2i(_high_boundary), _tail_size)); }
/*===========================================================================* * QueueMess * *===========================================================================*/ PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst) { int k; phys_bytes addr; NOREC_ENTER(queuemess); /* Queue a message from the src process (in memory) to the dst * process (using dst process table entry). Do actual copy to * kernel here; it's an error if the copy fails into kernel. */ vmassert(!(dst->p_misc_flags & MF_DELIVERMSG)); vmassert(dst->p_delivermsg_lin); vmassert(isokendpt(ep, &k)); #if 0 if(INMEMORY(dst)) { PHYS_COPY_CATCH(msg_lin, dst->p_delivermsg_lin, sizeof(message), addr); if(!addr) { PHYS_COPY_CATCH(vir2phys(&ep), dst->p_delivermsg_lin, sizeof(ep), addr); if(!addr) { NOREC_RETURN(queuemess, OK); } } } #endif PHYS_COPY_CATCH(msg_lin, vir2phys(&dst->p_delivermsg), sizeof(message), addr); if(addr) { NOREC_RETURN(queuemess, EFAULT); } dst->p_delivermsg.m_source = ep; dst->p_misc_flags |= MF_DELIVERMSG; NOREC_RETURN(queuemess, OK); }
/*===========================================================================* * sys_task * *===========================================================================*/ PUBLIC void sys_task() { /* Main entry point of sys_task. Get the message and dispatch on type. */ static message m; register int result; register struct proc *caller_ptr; int s; int call_nr; int n = 0; /* Initialize the system task. */ initialize(); while (TRUE) { struct proc *restarting; restarting = vmrestart_check(&m); if(!restarting) { int r; /* Get work. Block and wait until a request message arrives. */ if((r=receive(ANY, &m)) != OK) minix_panic("receive() failed", r); } sys_call_code = (unsigned) m.m_type; call_nr = sys_call_code - KERNEL_CALL; who_e = m.m_source; okendpt(who_e, &who_p); caller_ptr = proc_addr(who_p); /* See if the caller made a valid request and try to handle it. */ if (call_nr < 0 || call_nr >= NR_SYS_CALLS) { /* check call number */ kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source); result = EBADREQUEST; /* illegal message type */ } else if (!GET_BIT(priv(caller_ptr)->s_k_call_mask, call_nr)) { result = ECALLDENIED; /* illegal message type */ } else { result = (*call_vec[call_nr])(&m); /* handle the system call */ } if(result == VMSUSPEND) { /* Special case: message has to be saved for handling * until VM tells us it's allowed. VM has been notified * and we must wait for its reply to restart the call. */ vmassert(RTS_ISSET(caller_ptr, VMREQUEST)); vmassert(caller_ptr->p_vmrequest.type == VMSTYPE_KERNELCALL); memcpy(&caller_ptr->p_vmrequest.saved.reqmsg, &m, sizeof(m)); } else if (result != EDONTREPLY) { /* Send a reply, unless inhibited by a handler function. * Use the kernel function lock_send() to prevent a system * call trap. */ if(restarting) { vmassert(!RTS_ISSET(restarting, VMREQUEST)); #if 0 vmassert(!RTS_ISSET(restarting, VMREQTARGET)); #endif } m.m_type = result; /* report status of call */ if(WILLRECEIVE(caller_ptr, SYSTEM)) { if (OK != (s=lock_send(m.m_source, &m))) { kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); } } else { kprintf("SYSTEM: not replying to %d; not ready\n", caller_ptr->p_endpoint); } } } }
BitMapView make_view(idx_t bits, bm_word_t value) { vmassert(BitMap::calc_size_in_words(bits) <= _words, "invalid request"); STATIC_ASSERT(sizeof(bm_word_t) == sizeof(HeapWord)); Copy::fill_to_aligned_words((HeapWord*)_memory, _words, value); return BitMapView(_memory, bits); }
/*===========================================================================* * lin_lin_copy * *===========================================================================*/ PRIVATE int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes) { u32_t addr; int procslot; NOREC_ENTER(linlincopy); vmassert(vm_running); vmassert(nfreepdes >= 3); vmassert(ptproc); vmassert(proc_ptr); vmassert(read_cr3() == ptproc->p_seg.p_cr3); procslot = ptproc->p_nr; vmassert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES); while(bytes > 0) { phys_bytes srcptr, dstptr; vir_bytes chunk = bytes; int srcpde, dstpde; int srctype, dsttype; /* Set up 4MB ranges. */ inusepde = NOPDE; CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes, srcpde, srctype); CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes, dstpde, dsttype); /* Copy pages. */ PHYS_COPY_CATCH(srcptr, dstptr, chunk, addr); DONEPDE(srcpde); DONEPDE(dstpde); if(addr) { /* If addr is nonzero, a page fault was caught. */ if(addr >= srcptr && addr < (srcptr + chunk)) { WIPEPDE(srcpde); WIPEPDE(dstpde); NOREC_RETURN(linlincopy, EFAULT_SRC); } if(addr >= dstptr && addr < (dstptr + chunk)) { WIPEPDE(srcpde); WIPEPDE(dstpde); NOREC_RETURN(linlincopy, EFAULT_DST); } minix_panic("lin_lin_copy fault out of range", NO_NUM); /* Not reached. */ NOREC_RETURN(linlincopy, EFAULT); } WIPEPDE(srcpde); WIPEPDE(dstpde); /* Update counter and addresses for next iteration, if any. */ bytes -= chunk; srclinaddr += chunk; dstlinaddr += chunk; } NOREC_RETURN(linlincopy, OK); }