void bx_virt_timer_c::periodic(Bit64u time_passed) { //Assert that we haven't skipped any events. BX_ASSERT (time_passed <= timers_next_event_time); BX_ASSERT(!in_timer_handler); //Update time variables. timers_next_event_time -= time_passed; current_timers_time += time_passed; //If no events are occurring, just pass the time and we're done. if (time_passed < timers_next_event_time) return; //Starting timer handler calls. in_timer_handler = 1; //Otherwise, cause any events to occur that should. unsigned i; for (i=0;i<numTimers;i++) { if (timer[i].inUse && timer[i].active) { //Assert that we haven't skipped any timers. BX_ASSERT(current_timers_time <= timer[i].timeToFire); if(timer[i].timeToFire == current_timers_time) { if(timer[i].continuous) { timer[i].timeToFire += timer[i].period; } else { timer[i].active = 0; } //This function MUST return, or the timer mechanism // will be broken. timer[i].funct(timer[i].this_ptr); } } } //Finished timer handler calls. in_timer_handler = 0; //Use a second FOR loop so that a timer function call can // change the behavior of another timer. //timers_next_event_time normally contains a cycle count, not a cycle time. // here we use it as a temporary variable that IS a cycle time, // but then convert it back to a cycle count afterwards. timers_next_event_time = current_timers_time + BX_MAX_VIRTUAL_TIME; for (i=0;i<numTimers;i++) { if (timer[i].inUse && timer[i].active && ((timer[i].timeToFire)<timers_next_event_time)) { timers_next_event_time = timer[i].timeToFire; } } timers_next_event_time -= current_timers_time; next_event_time_update(); //FIXME }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); Bit32u count; #if BX_CPU_LEVEL >= 3 if (i->as32L()) count = ECX; else #endif count = CX; count--; if ((count!=0) && get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); if (i->os32L()==0) new_EIP &= 0x0000ffff; branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID); } #endif if (i->as32L()) ECX--; else CX--; }
//Get the current virtual time. // This will return a monotonically increasing value. // MUST NOT be called from within a timer interrupt. Bit64u bx_virt_timer_c::time_usec_sequential(void) { if (!use_virtual_timers) { return bx_pc_system.time_usec_sequential(); } //Can't prevent call stack loops here, so this // MUST NOT be called from within a timer handler. BX_ASSERT(timers_next_event_time>0); BX_ASSERT(!in_timer_handler); if (last_sequential_time >= current_timers_time) { periodic(1); last_sequential_time = current_timers_time; } return current_timers_time; }
static int builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, const char *name, Bit8u mask) { BX_ASSERT(mask<8); bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask); pluginlog->ldebug("plugin %s registered default I/O write ", name); return 0; }
static int builtinUnregisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, unsigned base, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_write_handler (thisPtr, callback, base, mask); pluginlog->ldebug("plugin unregistered I/O write address at %04x", base); return ret; }
static int builtinRegisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_write_handler_range (thisPtr, callback, base, end, name, mask); pluginlog->ldebug("plugin %s registered I/O write addresses %04x to %04x", name, base, end); return ret; }
static int builtinUnregisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback, unsigned begin, unsigned end, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_write_handler_range (thisPtr, callback, begin, end, mask); pluginlog->ldebug("plugin unregistered I/O write addresses %04x to %04x", begin, end); return ret; }
static int builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback, unsigned base, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask); pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base); return ret; }
void bx_virt_timer_c::advance_virtual_time(Bit64u time_passed) { BX_ASSERT(time_passed <= virtual_next_event_time); current_virtual_time += time_passed; virtual_next_event_time -= time_passed; if (current_virtual_time > current_timers_time) { periodic(current_virtual_time - current_timers_time); } }
//Called when next_event_time changes. void bx_virt_timer_c::next_event_time_update(void) { virtual_next_event_time = timers_next_event_time + current_timers_time - current_virtual_time; if (init_done) { bx_pc_system.deactivate_timer(system_timer_id); BX_ASSERT(virtual_next_event_time); bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), 0); } }
//Register a timer handler to go off after a given interval. //Register a timer handler to go off with a periodic interval. int bx_virt_timer_c::register_timer(void *this_ptr, bx_timer_handler_t handler, Bit32u useconds, bx_bool continuous, bx_bool active, const char *id) { if (!use_virtual_timers) { return bx_pc_system.register_timer(this_ptr, handler, useconds, continuous, active, id); } //We don't like starting with a zero period timer. BX_ASSERT((!active) || (useconds>0)); //Search for an unused timer. unsigned int i; for (i=0; i < numTimers; i++) { if ((timer[i].inUse == 0) || (i == numTimers)) break; } // If we didn't find a free slot, increment the bound, numTimers. if (i == numTimers) numTimers++; // One new timer installed. BX_ASSERT(numTimers<BX_MAX_VIRTUAL_TIMERS); timer[i].inUse = 1; timer[i].period = useconds; timer[i].timeToFire = current_timers_time + (Bit64u)useconds; timer[i].active = active; timer[i].continuous = continuous; timer[i].funct = handler; timer[i].this_ptr = this_ptr; strncpy(timer[i].id, id, BxMaxTimerIDLen); timer[i].id[BxMaxTimerIDLen-1]=0; //I like null terminated strings. if (useconds < timers_next_event_time) { timers_next_event_time = useconds; next_event_time_update(); //FIXME } return i; }
//deactivate (but don't unregister) a currently registered timer. void bx_virt_timer_c::deactivate_timer(unsigned timer_index) { if (!use_virtual_timers) { bx_pc_system.deactivate_timer(timer_index); return; } BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS); //No need to prevent doing this to unused/inactive timers. timer[timer_index].active = 0; }
BX_CPU_C::read_RMW_virtual_qword_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit64u data; BX_INSTR_MEM_DATA_ACCESS(BX_CPU_ID, s, offset, 8, BX_RW); Bit64u laddr = BX_CPU_THIS_PTR get_laddr64(s, offset); #if BX_SupportGuest2HostTLB unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); Bit64u lpf = AlignedAccessLPFOf(laddr, 7); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (tlbEntry->accessBits & (0x10 << CPL)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); BX_INSTR_LIN_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 8, BX_RW); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); #if BX_SUPPORT_ICACHE pageWriteStampTable.decWriteStamp(tlbEntry->ppf); #endif ReadHostQWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_DBG_LIN_MEMORY_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 8, CPL, BX_READ, (Bit8u*) &data); return data; } } #endif if (! IsCanonical(laddr)) { BX_ERROR(("read_RMW_virtual_qword_64(): canonical failure")); exception(int_number(seg), 0, 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("read_RMW_virtual_qword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0, 0); } } #endif access_read_linear(laddr, 8, CPL, BX_RW, (void *) &data); return data; }
// assuming the write happens in legacy mode void BX_CPU_C::write_new_stack_dword_32(bx_segment_reg_t *seg, bx_address offset, unsigned curr_pl, Bit32u data) { Bit32u laddr; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK4G) { accessOK: laddr = (Bit32u)(seg->cache.u.segment.base + offset); #if BX_SupportGuest2HostTLB unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); bx_address lpf = AlignedAccessLPFOf(laddr, 3); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (tlbEntry->accessBits & (0x10 << CPL)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); BX_INSTR_LIN_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 4, BX_WRITE); BX_DBG_LIN_MEMORY_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 4, curr_pl, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); #if BX_SUPPORT_ICACHE pageWriteStampTable.decWriteStamp(tlbEntry->ppf); #endif WriteHostDWordToLittleEndian(hostAddr, data); return; } } #endif #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && curr_pl == 3) { if (laddr & 3) { BX_ERROR(("write_new_stack_dword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0, 0); } } #endif access_write_linear(laddr, 4, curr_pl, (void *) &data); return; } if (seg->cache.valid & SegAccessWOK) { if (offset < (seg->cache.u.segment.limit_scaled-2)) goto accessOK; } write_virtual_checks(seg, offset, 4); goto accessOK; }
//activate a deactivated but registered timer. void bx_virt_timer_c::activate_timer(unsigned timer_index, Bit32u useconds, bx_bool continuous) { if (!use_virtual_timers) { bx_pc_system.activate_timer(timer_index, useconds, continuous); return; } BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS); BX_ASSERT(timer[timer_index].inUse); BX_ASSERT(useconds>0); timer[timer_index].period = useconds; timer[timer_index].timeToFire = current_timers_time + (Bit64u)useconds; timer[timer_index].active = 1; timer[timer_index].continuous = continuous; if (useconds < timers_next_event_time) { timers_next_event_time = useconds; next_event_time_update(); //FIXME } }
// LES/LDS can't be called from long64 mode BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LDS_GdMp(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u ds = read_virtual_word_32(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword_32(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS], ds); BX_WRITE_32BIT_REGZ(i->nnn(), reg_32); BX_NEXT_INSTR(i); }
void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, char *name) { device_t *device; device = (device_t *)malloc (sizeof (device_t)); if (!device) { pluginlog->panic("can't allocate device_t"); } device->name = name; BX_ASSERT (devmodel != NULL); device->devmodel = devmodel; device->plugin = plugin; // this can be NULL device->next = NULL; // Don't add every kind of device to the list. switch (type) { case PLUGTYPE_CORE: // Core devices are present whether or not we are using plugins, so // they are managed by the same code in iodev/devices.cc whether // plugins are on or off. free(device); return; // Do not add core devices to the devices list. case PLUGTYPE_OPTIONAL: case PLUGTYPE_USER: default: // The plugin system will manage optional and user devices only. break; } if (!devices) { /* Empty list, this become the first entry. */ devices = device; } else { /* Non-empty list. Add to end. */ device_t *temp = devices; while (temp->next) temp = temp->next; temp->next = device; } }
//unregister a previously registered timer. bx_bool bx_virt_timer_c::unregisterTimer(unsigned timerID) { if (!use_virtual_timers) return bx_pc_system.unregisterTimer(timerID); BX_ASSERT(timerID < BX_MAX_VIRTUAL_TIMERS); if (timer[timerID].active) { BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[timerID].id)); return(0); // Fail. } //No need to prevent doing this to unused timers. timer[timerID].inUse = 0; if (timerID == (numTimers-1)) numTimers--; return(1); }
static Bit32s get_next_word(char *output) { char *copyp = output; // find first nonspace while (*lineptr && isspace(*lineptr)) lineptr++; if (!*lineptr) return -1; // nothing but spaces until end of line if (*lineptr == '#') return -1; // nothing but a comment // copy nonspaces into the output while (*lineptr && !isspace(*lineptr)) *copyp++ = *lineptr++; *copyp=0; // null terminate the copy // there must be at least one nonspace, since that's why we stopped the // first loop! BX_ASSERT (copyp != output); return 0; }
bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr) { bxICacheEntry_c *e = BX_CPU_THIS_PTR iCache.get_entry(pAddr); if ((e->pAddr == pAddr) && (e->writeStamp == entry->writeStamp)) { // determine max amount of instruction to take from another entry unsigned max_length = e->ilen; if (max_length + entry->ilen > BX_MAX_TRACE_LENGTH) max_length = BX_MAX_TRACE_LENGTH - entry->ilen; if(max_length == 0) return 0; memcpy(i, e->i, sizeof(bxInstruction_c)*max_length); entry->ilen += max_length; BX_ASSERT(entry->ilen <= BX_MAX_TRACE_LENGTH); return 1; } return 0; }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JCXZ_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); Bit32u temp_ECX; if (i->as32L()) temp_ECX = ECX; else temp_ECX = CX; if (temp_ECX == 0) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); if (i->os32L()==0) new_EIP &= 0x0000ffff; branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP); return; } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID); }
BX_CPU_C::write_virtual_byte_64(unsigned s, Bit64u offset, Bit8u data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_INSTR_MEM_DATA_ACCESS(BX_CPU_ID, s, offset, 1, BX_WRITE); Bit64u laddr = BX_CPU_THIS_PTR get_laddr64(s, offset); #if BX_SupportGuest2HostTLB unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (tlbEntry->accessBits & (0x10 << CPL)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); BX_INSTR_LIN_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 1, BX_WRITE); BX_DBG_LIN_MEMORY_ACCESS(BX_CPU_ID, laddr, tlbEntry->ppf | pageOffset, 1, CPL, BX_WRITE, (Bit8u*) &data); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); #if BX_SUPPORT_ICACHE pageWriteStampTable.decWriteStamp(tlbEntry->ppf); #endif *hostAddr = data; return; } } #endif if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_byte_64(): canonical failure")); exception(int_number(seg), 0, 0); } access_write_linear(laddr, 1, CPL, (void *) &data); }
void plugin_load(char *name, char *args, plugintype_t type) { plugin_t *plugin, *temp; if (plugins != NULL) { temp = plugins; while (temp != NULL) { if (!strcmp(name, temp->name)) { BX_PANIC(("plugin '%s' already loaded", name)); return; } temp = temp->next; } } plugin = (plugin_t *)malloc (sizeof(plugin_t)); if (!plugin) { BX_PANIC(("malloc plugin_t failed")); } plugin->type = type; plugin->name = name; plugin->args = args; plugin->initialized = 0; char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN]; sprintf(buf, PLUGIN_FILENAME_FORMAT, name); sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf); // Set context so that any devices that the plugin registers will // be able to see which plugin created them. The registration will // be called from either dlopen (global constructors) or plugin_init. BX_ASSERT(current_plugin_context == NULL); current_plugin_context = plugin; #if defined(_MSC_VER) plugin->handle = LoadLibrary(plugin_filename); BX_INFO(("DLL handle is %p", plugin->handle)); if (!plugin->handle) { current_plugin_context = NULL; BX_PANIC(("LoadLibrary failed for module '%s': error=%d", name, GetLastError())); free(plugin); return; } #else plugin->handle = lt_dlopen (plugin_filename); BX_INFO(("lt_dlhandle is %p", plugin->handle)); if (!plugin->handle) { current_plugin_context = NULL; BX_PANIC(("dlopen failed for module '%s': %s", name, lt_dlerror ())); free(plugin); return; } #endif if (type != PLUGTYPE_USER) { sprintf(buf, PLUGIN_INIT_FMT_STRING, name); } else { sprintf(buf, PLUGIN_INIT_FMT_STRING, "user"); } #if defined(_MSC_VER) plugin->plugin_init = (plugin_init_t) GetProcAddress(plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_init: error=%d", GetLastError()); plugin_abort (); } #else plugin->plugin_init = (plugin_init_t) lt_dlsym (plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_init: %s", lt_dlerror ()); plugin_abort (); } #endif if (type != PLUGTYPE_USER) { sprintf(buf, PLUGIN_FINI_FMT_STRING, name); } else { sprintf(buf, PLUGIN_FINI_FMT_STRING, "user"); } #if defined(_MSC_VER) plugin->plugin_fini = (plugin_fini_t) GetProcAddress(plugin->handle, buf); if (plugin->plugin_fini == NULL) { pluginlog->panic("could not find plugin_fini: error=%d", GetLastError()); plugin_abort (); } #else plugin->plugin_fini = (plugin_fini_t) lt_dlsym (plugin->handle, buf); if (plugin->plugin_fini == NULL) { pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ()); plugin_abort(); } #endif pluginlog->info("loaded plugin %s",plugin_filename); /* Insert plugin at the _end_ of the plugin linked list. */ plugin->next = NULL; if (!plugins) { /* Empty list, this become the first entry. */ plugins = plugin; } else { /* Non-empty list. Add to end. */ temp = plugins; while (temp->next) temp = temp->next; temp->next = plugin; } plugin_init_one(plugin); // check that context didn't change. This should only happen if we // need a reentrant plugin_load. BX_ASSERT(current_plugin_context == plugin); current_plugin_context = NULL; }
void plugin_load(char *name, char *args, plugintype_t type) { plugin_t *plugin; plugin = (plugin_t *)malloc (sizeof(plugin_t)); if (!plugin) { BX_PANIC(("malloc plugin_t failed")); } plugin->type = type; plugin->name = name; plugin->args = args; plugin->initialized = 0; char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN]; sprintf(buf, PLUGIN_FILENAME_FORMAT, name); sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf); // Set context so that any devices that the plugin registers will // be able to see which plugin created them. The registration will // be called from either dlopen (global constructors) or plugin_init. BX_ASSERT (current_plugin_context == NULL); current_plugin_context = plugin; plugin->handle = lt_dlopen (plugin_filename); BX_INFO (("lt_dlhandle is %p", plugin->handle)); if (!plugin->handle) { current_plugin_context = NULL; BX_PANIC (("dlopen failed for module '%s': %s", name, lt_dlerror ())); free (plugin); return; } sprintf(buf, PLUGIN_INIT_FMT_STRING, name); plugin->plugin_init = (int (*)(struct _plugin_t *, enum plugintype_t, int, char *[])) /* monster typecast */ lt_dlsym (plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_init: %s", lt_dlerror ()); plugin_abort (); } sprintf(buf, PLUGIN_FINI_FMT_STRING, name); plugin->plugin_fini = (void (*)(void)) lt_dlsym (plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ()); plugin_abort (); } pluginlog->info("loaded plugin %s",plugin_filename); /* Insert plugin at the _end_ of the plugin linked list. */ plugin->next = NULL; if (!plugins) { /* Empty list, this become the first entry. */ plugins = plugin; } else { /* Non-empty list. Add to end. */ plugin_t *temp = plugins; while (temp->next) temp = temp->next; temp->next = plugin; } plugin_init_one(plugin); // check that context didn't change. This should only happen if we // need a reentrant plugin_load. BX_ASSERT (current_plugin_context == plugin); current_plugin_context = NULL; return; }
void bx_virt_timer_c::timer_handler(void) { if(!virtual_timers_realtime) { Bit64u temp_final_time = bx_pc_system.time_usec(); temp_final_time -= current_virtual_time; while (temp_final_time) { if((temp_final_time)>(virtual_next_event_time)) { temp_final_time -= virtual_next_event_time; advance_virtual_time(virtual_next_event_time); } else { advance_virtual_time(temp_final_time); temp_final_time -= temp_final_time; } } bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,(virtual_next_event_time>2)?(virtual_next_event_time-2):1), 0); return; } Bit64u usec_delta = bx_pc_system.time_usec()-last_usec; if (usec_delta) { #if BX_HAVE_REALTIME_USEC Bit64u ticks_delta = 0; Bit64u real_time_delta = GET_VIRT_REALTIME64_USEC() - last_real_time - real_time_delay; Bit64u real_time_total = real_time_delta + total_real_usec; Bit64u system_time_delta = (Bit64u)usec_delta + (Bit64u)stored_delta; if(real_time_delta) { last_realtime_delta = real_time_delta; last_realtime_ticks = total_ticks; } ticks_per_second = USEC_PER_SECOND; //Start out with the number of ticks we would like // to have to line up with real time. ticks_delta = real_time_total - total_ticks; if(real_time_total < total_ticks) { //This slows us down if we're already ahead. // probably only an issue on startup, but it solves some problems. ticks_delta = 0; } if(ticks_delta + total_ticks - last_realtime_ticks > (F2I(MAX_MULT * I2F(last_realtime_delta)))) { //This keeps us from going too fast in relation to real time. #if 0 ticks_delta = (F2I(MAX_MULT * I2F(last_realtime_delta))) + last_realtime_ticks - total_ticks; #endif ticks_per_second = F2I(MAX_MULT * I2F(USEC_PER_SECOND)); } if(ticks_delta > system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND) { //This keeps us from having too few instructions between ticks. ticks_delta = system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND; } if(ticks_delta > virtual_next_event_time) { //This keeps us from missing ticks. ticks_delta = virtual_next_event_time; } if(ticks_delta) { # if DEBUG_REALTIME_WITH_PRINTF //Every second print some info. if(((last_real_time + real_time_delta) / USEC_PER_SECOND) > (last_real_time / USEC_PER_SECOND)) { Bit64u temp1, temp2, temp3, temp4; temp1 = (Bit64u) total_real_usec; temp2 = (total_real_usec); temp3 = (Bit64u)total_ticks; temp4 = (Bit64u)((total_real_usec) - total_ticks); printf("useconds: " FMT_LL "u, ", temp1); printf("expect ticks: " FMT_LL "u, ", temp2); printf("ticks: " FMT_LL "u, ", temp3); printf("diff: "FMT_LL "u\n", temp4); } # endif last_real_time += real_time_delta; total_real_usec += real_time_delta; last_system_usec += system_time_delta; stored_delta = 0; total_ticks += ticks_delta; } else { stored_delta = system_time_delta; } Bit64u a = usec_per_second, b; if(real_time_delta) { //FIXME Bit64u em_realtime_delta = last_system_usec + stored_delta - em_last_realtime; b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta); em_last_realtime = last_system_usec + stored_delta; } else { b=a; } usec_per_second = ALPHA_LOWER(a,b); #else BX_ASSERT(0); #endif #if BX_HAVE_REALTIME_USEC advance_virtual_time(ticks_delta); #endif } last_usec=last_usec + usec_delta; bx_pc_system.deactivate_timer(system_timer_id); BX_ASSERT(virtual_next_event_time); bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), 0); }
//______________________________________________________________________________ // [] //` CreateEnumObjects [] // [] void BX_SingleObject::CreateEnumObjects(void) { if ( !CLEAR_FILE_SYSTEM_BEFORE_START && m_pOC_Registry->m_Language.GetSize()!=0 // !!! -- СДЕЛАТЬ СПЕЦ ФЛАГ. ) { return; } string tempStr; //----------------------------------------------------------------------------[] //`Language BX_Language_Args language_args; GetAdminPassword(language_args.AdminPassword); language_args.OwnName = "Русский язык"; language_args.ShortName = "RUS"; SERVER_DEBUG_ASSERT (BX_Language_New(language_args) == BX_OK, "CreateEnumObjects(): Error in BX_Language_New."); language_args.objID = NA; language_args.OwnName = "English language"; language_args.ShortName = "ENG"; language_args.Language. Add("Russian language"); language_args.Name. Add("Английский язык"); SERVER_DEBUG_ASSERT (BX_Language_New(language_args) == BX_OK, "CreateEnumObjects(): Error in BX_Language_New."); //----------------------------------------------------------------------------[] ConceptCompiler(); //----------------------------------------------------------------------------[] // VBN 1 BX_Concept_Args concept_args; SERVER_DEBUG_ASSERT(BX_Concept_Enumerate(concept_args) == BX_OK, "CreateEnumObjects(): Error in BX_Concept_Enumerate."); BX_VBN_Args vbn_arg; BX_User_Args user_arg; BX_Site_Args site_arg; CREATE_PREDEFINED_OBJECTS; concept_args.ConceptType.Erase(); concept_args.ConceptType.Add("Concept.Viewer.OS" ); concept_args.ConceptType.Add("Concept.Viewer.Browser" ); concept_args.ConceptType.Add("Concept.Viewer.Charset" ); concept_args.ConceptType.Add("Concept.Viewer.Language" ); concept_args.ConceptType.Add("Concept.Viewer.ScreenSize" ); concept_args.ConceptType.Add("Concept.Viewer.Colors" ); concept_args.ConceptType.Add("Concept.Viewer.JavaScriptVersion"); concept_args.ConceptType.Add("Concept.Viewer.Java" ); concept_args.ConceptType.Add("Concept.Banner" ); concept_args.ConceptType.Add("Concept.Banner.Appearance" ); concept_args.ConceptType.Add("Concept.Banner.Shape" ); concept_args.ConceptType.Add("Concept.Banner.Format" ); concept_args.ConceptType.Add("Concept.Goods&Services" ); concept_args.ConceptType.Add("Concept.Goods&Services.Goods" ); concept_args.ConceptType.Add("Concept.Goods&Services.Soft" ); concept_args.ConceptType.Add("Concept.Goods&Services.Services" ); concept_args.ConceptType.Add("Concept.Goods&Services.Price" ); BX_ASSERT(BX_Concept_SetFilter(concept_args)); return; }