LAPIC: fixed timer interrupts after reloading of LAPIC Timer Divide Configuration register

This commit is contained in:
Stanislav Shwartsman 2012-05-12 11:52:29 +00:00
parent 3202afb48e
commit 03162d86f5
4 changed files with 28 additions and 21 deletions

View File

@ -15,6 +15,7 @@ Changes after 2.5.1 release:
! Added AMD Phenom X3 8650 (Toliman) configuration to the CPUDB ! Added AMD Phenom X3 8650 (Toliman) configuration to the CPUDB
! Added Corei7 3770K (Ivy Bridge) configuration to the CPUDB ! Added Corei7 3770K (Ivy Bridge) configuration to the CPUDB
- Bugfixes for CPU emulation correctness and stability - Bugfixes for CPU emulation correctness and stability
(critical fixes for VMX and XOP emulation)
- Bochs Debugger and Instrumentation - Bochs Debugger and Instrumentation
- Implemented new debugger command 'info device [string]' that shows the - Implemented new debugger command 'info device [string]' that shows the

View File

@ -1077,20 +1077,23 @@ void bx_local_apic_c::periodic(void)
Bit32u timervec = lvt[APIC_LVT_TIMER]; Bit32u timervec = lvt[APIC_LVT_TIMER];
// If timer is not masked, trigger interrupt. // If timer is not masked, trigger interrupt
if((timervec & 0x10000)==0) { if((timervec & 0x10000)==0) {
trigger_irq(timervec & 0xff, APIC_EDGE_TRIGGERED); trigger_irq(timervec & 0xff, APIC_EDGE_TRIGGERED);
} }
else { else {
BX_DEBUG(("local apic timer LVT masked")); BX_DEBUG(("local apic timer LVT masked"));
} }
// timer reached zero since the last call to periodic. // timer reached zero since the last call to periodic
if(timervec & 0x20000) { if(timervec & 0x20000) {
// Periodic mode - reload timer values // Periodic mode - reload timer values
timer_current = timer_initial; timer_current = timer_initial;
timer_active = 1;
ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count
BX_DEBUG(("local apic timer(periodic) triggered int, reset counter to 0x%08x", timer_current)); BX_DEBUG(("local apic timer(periodic) triggered int, reset counter to 0x%08x", timer_current));
bx_pc_system.activate_timer_ticks(timer_handle,
Bit64u(timer_initial) * Bit64u(timer_divide_factor), 0);
} }
else { else {
// one-shot mode // one-shot mode
@ -1104,7 +1107,7 @@ void bx_local_apic_c::periodic(void)
void bx_local_apic_c::set_divide_configuration(Bit32u value) void bx_local_apic_c::set_divide_configuration(Bit32u value)
{ {
BX_ASSERT(value == (value & 0x0b)); BX_ASSERT(value == (value & 0x0b));
// move bit 3 down to bit 0. // move bit 3 down to bit 0
value = ((value & 8) >> 1) | (value & 3); value = ((value & 8) >> 1) | (value & 3);
BX_ASSERT(value >= 0 && value <= 7); BX_ASSERT(value >= 0 && value <= 7);
timer_divide_factor = (value==7) ? 1 : (2 << value); timer_divide_factor = (value==7) ? 1 : (2 << value);
@ -1136,10 +1139,9 @@ void bx_local_apic_c::set_initial_timer_count(Bit32u value)
BX_DEBUG(("APIC: Initial Timer Count Register = %u", value)); BX_DEBUG(("APIC: Initial Timer Count Register = %u", value));
timer_current = timer_initial; timer_current = timer_initial;
timer_active = 1; timer_active = 1;
bx_bool continuous = (timervec & 0x20000) > 0;
ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count
bx_pc_system.activate_timer_ticks(timer_handle, bx_pc_system.activate_timer_ticks(timer_handle,
Bit64u(timer_initial) * Bit64u(timer_divide_factor), continuous); Bit64u(timer_initial) * Bit64u(timer_divide_factor), 0);
} }
} }

View File

@ -274,7 +274,7 @@ int DoMatch(const char *text, const char *p, bx_bool IsCaseSensitive)
// NO BREAK HERE // NO BREAK HERE
default: default:
if (IsCaseSensitive != FALSE) if (IsCaseSensitive)
{ {
if (text[pT] != p[pP]) if (text[pT] != p[pP])
return MATCH_FALSE; return MATCH_FALSE;
@ -1000,7 +1000,7 @@ void LoadRegList()
cols[1] = regtxt; cols[1] = regtxt;
cols[2] = regtxt + 40; cols[2] = regtxt + 40;
itemnum = 0; itemnum = 0;
if (In64Mode != FALSE) if (In64Mode)
{ {
showEreg = SeeReg[0]; // get user option setting for EAX, etc. showEreg = SeeReg[0]; // get user option setting for EAX, etc.
for (i = RAX_Rnum; i <= R15_Rnum; i++) for (i = RAX_Rnum; i <= R15_Rnum; i++)
@ -1978,7 +1978,7 @@ void FillDataX(char* t, char C, bx_bool doHex)
*d = AsciiHex[2* (unsigned char)C]; *d = AsciiHex[2* (unsigned char)C];
d[1] = AsciiHex[2* (unsigned char)C + 1]; d[1] = AsciiHex[2* (unsigned char)C + 1];
d[2] = 0; d[2] = 0;
if (isLittleEndian != FALSE) // little endian => reverse hex digits if (isLittleEndian) // little endian => reverse hex digits
{ {
strcat(d,t); strcat(d,t);
strcpy(t,d); // so append the new bytes to the FRONT of t strcpy(t,d); // so append the new bytes to the FRONT of t
@ -2206,7 +2206,7 @@ void OnBreak()
In32Mode = d_b; In32Mode = d_b;
} }
} }
if (CpuModeChange != FALSE) if (CpuModeChange)
{ {
GrayMenuItem ((int) In64Mode, CMD_EREG); GrayMenuItem ((int) In64Mode, CMD_EREG);
BottomAsmLA = ~0; // force an ASM autoload BottomAsmLA = ~0; // force an ASM autoload
@ -2285,20 +2285,21 @@ bx_bool InitDataDump(bx_bool isLinear, Bit64u newDS)
} }
// load 4k DataDump array from bochs emulated linear or physical memory // load 4k DataDump array from bochs emulated linear or physical memory
if (isLinear != FALSE) if (isLinear)
{ {
// cannot read linear mem across a 4K boundary -- so break the read in two // cannot read linear mem across a 4K boundary -- so break the read in two
// -- calculate location of 4K boundary (h): // -- calculate location of 4K boundary (h):
unsigned int len = (int) newDS & 0xfff; unsigned len = (int) newDS & 0xfff;
unsigned int i = 4096 - len; unsigned i = 4096 - len;
Bit64u h = newDS + i; Bit64u h = newDS + i;
retval = ReadBxLMem(newDS,i,(Bit8u *)DataDump); retval = ReadBxLMem(newDS,i,(Bit8u *)DataDump);
if (retval != FALSE && len != 0) if (retval != FALSE && len != 0)
retval = ReadBxLMem(h,len,(Bit8u *)DataDump + i); retval = ReadBxLMem(h,len,(Bit8u *)DataDump + i);
} }
else else {
retval = (bx_bool) bx_mem.dbg_fetch_mem( BX_CPU(CurrentCPU), retval = (bx_bool) bx_mem.dbg_fetch_mem(BX_CPU(CurrentCPU),
(bx_phy_address)newDS, 4096, (Bit8u *)DataDump); (bx_phy_address)newDS, 4096, (Bit8u *)DataDump);
}
if (retval == FALSE) if (retval == FALSE)
{ {
// assume that the DataDump array is still valid -- fetch_mem should error without damage // assume that the DataDump array is still valid -- fetch_mem should error without damage
@ -2306,6 +2307,7 @@ bx_bool InitDataDump(bx_bool isLinear, Bit64u newDS)
DispMessage ("Address range was not legal memory","Memory Error"); DispMessage ("Address range was not legal memory","Memory Error");
return retval; return retval;
} }
SA_valid = FALSE; // any previous MemDump click is now irrelevant SA_valid = FALSE; // any previous MemDump click is now irrelevant
ResizeColmns = TRUE; // autosize column 0 once ResizeColmns = TRUE; // autosize column 0 once
DumpInitted = TRUE; // OK to refresh the Dump window in the future (it has data) DumpInitted = TRUE; // OK to refresh the Dump window in the future (it has data)
@ -2721,7 +2723,7 @@ void SetMemLine(int L)
char *x = tmpcb; char *x = tmpcb;
upr(x); // force input string to uppercase upr(x); // force input string to uppercase
if (LinearDump != FALSE) // is h is a LINEAR address? Convert to physical! if (LinearDump) // is h is a LINEAR address? Convert to physical!
{ {
// use the ReadBx function to calculate the lin->phys offset // use the ReadBx function to calculate the lin->phys offset
if (ReadBxLMem(h,0,(Bit8u *)addrstr) == FALSE) // "read" 0 bytes if (ReadBxLMem(h,0,(Bit8u *)addrstr) == FALSE) // "read" 0 bytes

View File

@ -222,9 +222,11 @@ void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u value)
void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level) void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level)
{ {
/*
if (int_in == 0) { // timer connected to pin #2 if (int_in == 0) { // timer connected to pin #2
int_in = 2; int_in = 2;
} }
*/
BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level)); BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level));
if (int_in < BX_IOAPIC_NUM_PINS) { if (int_in < BX_IOAPIC_NUM_PINS) {
Bit32u bit = 1<<int_in; Bit32u bit = 1<<int_in;