Added debug prints for APIC

This commit is contained in:
Stanislav Shwartsman 2005-04-26 18:30:30 +00:00
parent b49ece26ac
commit 76af95a9a7

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.49 2005-04-23 17:52:51 sshwarts Exp $
// $Id: apic.cc,v 1.50 2005-04-26 18:30:30 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
@ -28,9 +28,7 @@ void bx_generic_apic_c::set_arb_id (int new_arb_id)
}
// init is called during RESET and when an INIT message is delivered.
void bx_generic_apic_c::init ()
{
}
void bx_generic_apic_c::init () { }
void bx_generic_apic_c::set_base (bx_address newbase)
{
@ -220,6 +218,7 @@ bx_bool bx_generic_apic_c::deliver (Bit8u dest, Bit8u dest_mode, Bit8u delivery_
/* once = false */
break;
case APIC_DM_INIT:
BX_DEBUG (("INIT received with deliver_bitmask=%u", deliver_bitmask));
// NOTE: special behavior of local apics is handled in
// bx_local_apic_c::deliver
@ -279,6 +278,41 @@ bx_bool bx_generic_apic_c::deliver (Bit8u dest, Bit8u dest_mode, Bit8u delivery_
return 1;
}
Bit32u bx_local_apic_c::get_delivery_bitmask (Bit8u dest, Bit8u dest_mode)
{
int dest_shorthand = (icr_low >> 18) & 3;
Bit32u mask = 0; /* stop compiler warnings */
switch (dest_shorthand) {
case 0: // no shorthand, use real destination value
mask = bx_generic_apic_c::get_delivery_bitmask (dest, dest_mode);
break;
case 1: // self
mask = (1<<id);
break;
case 2: // all including self
mask = (LOCAL_APIC_ALL_MASK);
break;
case 3: // all but self
mask = (LOCAL_APIC_ALL_MASK) & ~(1<<id);
break;
default:
BX_PANIC(("Invalid desination shorthand %#x\n", dest_shorthand));
}
// prune nonexistents apics from list
for (int bit=0; bit<BX_LOCAL_APIC_NUM; bit++)
{
if (!local_apic_index[bit]) mask &= ~(1<<bit);
}
BX_DEBUG (("local::get_delivery_bitmask returning 0x%04x shorthand=%#x", mask, dest_shorthand));
if (mask == 0)
BX_INFO((">>WARNING<< returning a mask of 0x0, dest=%#x dest_mode=%#x", dest, dest_mode));
return mask;
}
bx_bool bx_local_apic_c::deliver (Bit8u dest, Bit8u dest_mode, Bit8u delivery_mode,
Bit8u vector, Bit8u level, Bit8u trig_mode)
{
@ -363,6 +397,8 @@ void bx_local_apic_c::hwreset ()
void bx_local_apic_c::init ()
{
int i;
bx_generic_apic_c::init ();
BX_INFO(("local apic in %s initializing",
@ -375,10 +411,22 @@ void bx_local_apic_c::init ()
err_status = 0;
log_dest = 0;
dest_format = 0xf;
for (int bit=0; bit<BX_LOCAL_APIC_MAX_INTS; bit++) {
irr[bit] = isr[bit] = tmr[bit] = 0;
}
icr_high = icr_low = log_dest = task_priority = 0;
for (i=0; i<BX_LOCAL_APIC_MAX_INTS; i++) {
irr[i] = isr[i] = tmr[i] = 0;
}
timer_divconf = 0;
timer_divide_factor = 1;
timer_initial = 0;
timer_current = 0;
timer_active = 0;
for (i=0; i<APIC_LVT_ENTRIES; i++) {
lvt[i] = 0x10000;
}
spurious_vec = 0xff; // software disabled (bit 8)
// KPL: Register a non-active timer for use when the timer is started.
@ -419,7 +467,7 @@ void bx_local_apic_c::set_divide_configuration (Bit32u value)
value = ((value & 8) >> 1) | (value & 3);
BX_ASSERT (value >= 0 && value <= 7);
timer_divide_factor = (value==7)? 1 : (2 << value);
BX_DEBUG(("%s: set timer divide factor to %d", cpu->name, timer_divide_factor));
BX_INFO(("%s: set timer divide factor to %d", cpu->name, timer_divide_factor));
}
void bx_local_apic_c::write (Bit32u addr, Bit32u *data, unsigned len)
@ -488,30 +536,32 @@ void bx_local_apic_c::write (Bit32u addr, Bit32u *data, unsigned len)
// for all APICs.
bx_bool accepted =
deliver (dest, dest_mode, delivery_mode, vector, level, trig_mode);
if (!accepted)
if (!accepted) {
BX_DEBUG(("An IPI didn't accepted, raise APIC_ERR_TX_ACCEPT_ERR"));
err_status |= APIC_ERR_TX_ACCEPT_ERR;
}
}
break;
case 0x310: // interrupt command reg 31-63
icr_high = value & 0xff000000;
break;
case 0x320: // LVT Timer Reg
lvt[APIC_LVT_TIMER] = value & 0x310ff;
lvt[APIC_LVT_TIMER] = value & 0x300ff;
break;
case 0x330: // LVT Thermal Monitor
lvt[APIC_LVT_THERMAL] = value & 0x117ff;
lvt[APIC_LVT_THERMAL] = value & 0x107ff;
break;
case 0x340: // LVT Performance Counter
lvt[APIC_LVT_PERFORM] = value & 0x117ff;
lvt[APIC_LVT_PERFORM] = value & 0x107ff;
break;
case 0x350: // LVT LINT0 Reg
lvt[APIC_LVT_LINT0] = value & 0x1f7ff;
lvt[APIC_LVT_LINT0] = value & 0x1a7ff;
break;
case 0x360: // LVT Lint1 Reg
lvt[APIC_LVT_LINT1] = value & 0x1f7ff;
lvt[APIC_LVT_LINT1] = value & 0x1a7ff;
break;
case 0x370: // LVT Error Reg
lvt[APIC_LVT_ERROR] = value & 0x117ff;
lvt[APIC_LVT_ERROR] = value & 0x100ff;
break;
case 0x380: // initial count for timer
{
@ -646,10 +696,9 @@ void bx_local_apic_c::read_aligned (Bit32u addr, Bit32u *data, unsigned len)
//fprintf(stderr, "APIC: R(Initial Count Register) = %u\n", *data);
break;
case 0x390: // current count for timer
{
if (timer_active==0)
if (timer_active==0) {
*data = timer_current;
else {
} else {
Bit64u delta64;
Bit32u delta32;
delta64 = (bx_pc_system.time_ticks() - ticksInitial) / timer_divide_factor;
@ -658,12 +707,11 @@ void bx_local_apic_c::read_aligned (Bit32u addr, Bit32u *data, unsigned len)
BX_PANIC(("APIC: R(curr timer count): delta < initial"));
timer_current = timer_initial - delta32;
*data = timer_current;
}
//fprintf(stderr, "APIC: R(Current Count Register) = %u\n", *data);
}
break;
case 0x3e0: // timer divide configuration
*data = timer_divconf; break;
*data = timer_divconf;
break;
default:
BX_INFO(("APIC register %08x not implemented", addr));
}
@ -711,7 +759,7 @@ void bx_local_apic_c::trigger_irq (unsigned vector, unsigned from, unsigned trig
if (vector > BX_APIC_LAST_VECTOR) {
err_status |= APIC_ERR_RX_ILLEGAL_VEC;
BX_INFO(("bogus vector %#x, ignoring", vector));
BX_INFO(("bogus vector %#x, ignoring ...", vector));
return;
}
@ -724,6 +772,7 @@ void bx_local_apic_c::trigger_irq (unsigned vector, unsigned from, unsigned trig
}
if (irr[vector] != 0) {
BX_INFO(("triggered vector %#02x not accepted, raise APIC_ERR_TX_ACCEPT_ERR", vector));
err_status |= APIC_ERR_TX_ACCEPT_ERR;
return;
}
@ -793,41 +842,6 @@ bx_bool bx_local_apic_c::match_logical_addr (Bit8u address)
return match;
}
Bit32u bx_local_apic_c::get_delivery_bitmask (Bit8u dest, Bit8u dest_mode)
{
int dest_shorthand = (icr_low >> 18) & 3;
Bit32u mask = 0; /* stop compiler warnings */
switch (dest_shorthand) {
case 0: // no shorthand, use real destination value
mask = bx_generic_apic_c::get_delivery_bitmask (dest, dest_mode);
break;
case 1: // self
mask = (1<<id);
break;
case 2: // all including self
mask = (LOCAL_APIC_ALL_MASK);
break;
case 3: // all but self
mask = (LOCAL_APIC_ALL_MASK) & ~(1<<id);
break;
default:
BX_PANIC(("Invalid desination shorthand %#x\n", dest_shorthand));
}
// prune nonexistents apics from list
for (int bit=0; bit<BX_LOCAL_APIC_NUM; bit++)
{
if (!local_apic_index[bit]) mask &= ~(1<<bit);
}
BX_DEBUG (("local::get_delivery_bitmask returning 0x%04x shorthand=%#x", mask, dest_shorthand));
if (mask == 0)
BX_INFO((">>WARNING<< returning a mask of 0x0, dest=%#x dest_mode=%#x", dest, dest_mode));
return mask;
}
Bit8u bx_local_apic_c::get_ppr ()
{
int ppr = highest_priority_int (isr);
@ -896,25 +910,24 @@ void bx_local_apic_c::adjust_arb_id(int winning_id)
void bx_local_apic_c::periodic_smf(void *this_ptr)
{
bx_local_apic_c *class_ptr = (bx_local_apic_c *) this_ptr;
class_ptr->periodic();
}
void bx_local_apic_c::periodic(void) // KPL: changed prototype
void bx_local_apic_c::periodic(void)
{
if (!timer_active) {
BX_ERROR(("%s: bx_local_apic_c::periodic called, timer_active==0", cpu->name));
return;
}
BX_DEBUG(("%s: bx_local_apic_c::periodic called", cpu->name));
// timer reached zero since the last call to periodic.
Bit32u timervec = lvt[APIC_LVT_TIMER];
if (timervec & 0x20000) {
// Periodic mode.
// If timer is not masked, trigger interrupt.
if ((timervec & 0x10000)==0)
if ((timervec & 0x10000)==0) {
trigger_irq (timervec & 0xff, id, APIC_EDGE_TRIGGERED);
}
// Reload timer values.
timer_current = timer_initial;
ticksInitial = bx_pc_system.getTicksTotal(); // Take a reading.
@ -924,11 +937,12 @@ void bx_local_apic_c::periodic(void) // KPL: changed prototype
// one-shot mode
timer_current = 0;
// If timer is not masked, trigger interrupt.
if ((timervec & 0x10000)==0)
if ((timervec & 0x10000)==0) {
trigger_irq (timervec & 0xff, id, APIC_EDGE_TRIGGERED);
}
timer_active = 0;
BX_DEBUG (("%s: local apic timer (one-shot) triggered int", cpu->name));
bx_pc_system.deactivate_timer(timer_handle); // Make sure.
bx_pc_system.deactivate_timer(timer_handle);
}
}