LAPIC: fixed timer interrupts after reloading of LAPIC Timer Divide Configuration register
This commit is contained in:
parent
3202afb48e
commit
03162d86f5
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user