small optimizations for apic code
This commit is contained in:
parent
7be90a7426
commit
31a367283a
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: apic.cc,v 1.121 2009-02-18 22:38:58 sshwarts Exp $
|
||||
// $Id: apic.cc,v 1.122 2009-02-19 23:19:10 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
#define LOG_THIS this->
|
||||
|
||||
#define BX_CPU_APIC(i) (&(BX_CPU(i)->lapic))
|
||||
|
||||
#define APIC_UNKNOWN_ID 0xff
|
||||
|
||||
#define APIC_BROADCAST_PHYSICAL_DESTINATION_MODE (APIC_MAX_ID)
|
||||
@ -38,14 +40,13 @@
|
||||
|
||||
///////////// APIC BUS /////////////
|
||||
|
||||
int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, Bit8u dest_mode, bx_bool level, bx_bool trig_mode)
|
||||
int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, bx_bool logical_dest, bx_bool level, bx_bool trig_mode)
|
||||
{
|
||||
if(delivery_mode == APIC_DM_LOWPRI)
|
||||
{
|
||||
if(dest_mode == 0) {
|
||||
if(logical_dest == 0) {
|
||||
// I/O subsytem initiated interrupt with lowest priority delivery
|
||||
// mode is not supported in physical destination mode
|
||||
// BX_ERROR(("Ignoring lowest priority interrupt in physical dest mode !"));
|
||||
// which is not supported in physical destination mode
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
@ -54,9 +55,9 @@ int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, Bi
|
||||
}
|
||||
|
||||
// determine destination local apics and deliver
|
||||
if(dest_mode == 0) {
|
||||
if(dest == APIC_BROADCAST_PHYSICAL_DESTINATION_MODE)
|
||||
{
|
||||
if(logical_dest == 0) {
|
||||
// physical destination mode
|
||||
if(dest == APIC_BROADCAST_PHYSICAL_DESTINATION_MODE) {
|
||||
return apic_bus_broadcast_interrupt(vector, delivery_mode, trig_mode, APIC_MAX_ID);
|
||||
}
|
||||
else {
|
||||
@ -169,7 +170,7 @@ void apic_bus_broadcast_smi(void)
|
||||
////////////////////////////////////
|
||||
|
||||
bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu)
|
||||
: base_addr(BX_LAPIC_BASE_ADDR), cpu(mycpu), cpu_id(cpu->which_cpu())
|
||||
: base_addr(BX_LAPIC_BASE_ADDR), cpu(mycpu)
|
||||
{
|
||||
put("APIC?");
|
||||
id = APIC_UNKNOWN_ID;
|
||||
@ -200,7 +201,7 @@ void bx_local_apic_c::init()
|
||||
// default address for a local APIC, can be moved
|
||||
base_addr = BX_LAPIC_BASE_ADDR;
|
||||
error_status = shadow_error_status = 0;
|
||||
log_dest = 0;
|
||||
ldr = 0;
|
||||
dest_format = 0xf;
|
||||
icr_hi = 0;
|
||||
icr_lo = 0;
|
||||
@ -226,18 +227,18 @@ void bx_local_apic_c::init()
|
||||
|
||||
spurious_vector = 0xff; // software disabled(bit 8)
|
||||
software_enabled = 0;
|
||||
global_enabled = 1;
|
||||
focus_disable = 0;
|
||||
mode = BX_APIC_XAPIC_MODE;
|
||||
}
|
||||
|
||||
void bx_local_apic_c::set_base(bx_phy_address newbase)
|
||||
{
|
||||
global_enabled = (newbase >> 11) & 1;
|
||||
mode = (newbase >> 10) & 3;
|
||||
newbase &= ~((bx_phy_address) 0xfff);
|
||||
base_addr = newbase;
|
||||
if (id != APIC_UNKNOWN_ID) {
|
||||
BX_INFO(("allocate APIC id=%d (%s) to 0x" FMT_PHY_ADDRX,
|
||||
id, global_enabled ? "enabled" : "disabled", newbase));
|
||||
BX_INFO(("allocate APIC id=%d (MMIO %s) to 0x" FMT_PHY_ADDRX,
|
||||
id, (mode == BX_APIC_XAPIC_MODE) ? "enabled" : "disabled", newbase));
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,7 +262,7 @@ void bx_local_apic_c::set_id(Bit32u new_id)
|
||||
|
||||
bx_bool bx_local_apic_c::is_selected(bx_phy_address addr)
|
||||
{
|
||||
if (! global_enabled) return 0;
|
||||
if (mode != BX_APIC_XAPIC_MODE) return 0;
|
||||
|
||||
if((addr & ~0xfff) == base_addr) {
|
||||
if((addr & 0xf) != 0)
|
||||
@ -277,8 +278,7 @@ void bx_local_apic_c::read(bx_phy_address addr, void *data, unsigned len)
|
||||
BX_PANIC(("APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", addr));
|
||||
return;
|
||||
}
|
||||
Bit32u value;
|
||||
read_aligned(addr & ~0x3, &value);
|
||||
Bit32u value = read_aligned(addr & ~0x3);
|
||||
if(len == 4) { // must be 32-bit aligned
|
||||
*((Bit32u *)data) = value;
|
||||
return;
|
||||
@ -305,38 +305,82 @@ void bx_local_apic_c::write(bx_phy_address addr, void *data, unsigned len)
|
||||
return;
|
||||
}
|
||||
|
||||
write_aligned(addr, (Bit32u*) data);
|
||||
write_aligned(addr, *((Bit32u*) data));
|
||||
}
|
||||
|
||||
#define BX_LAPIC_ID 0x020
|
||||
#define BX_LAPIC_VERSION 0x030
|
||||
#define BX_LAPIC_TPR 0x080
|
||||
#define BX_LAPIC_ARBITRATION_PRIORITY 0x090
|
||||
#define BX_LAPIC_PPR 0x0A0
|
||||
#define BX_LAPIC_EOI 0x0B0
|
||||
#define BX_LAPIC_LDR 0x0D0
|
||||
#define BX_LAPIC_DESTINATION_FORMAT 0x0E0
|
||||
#define BX_LAPIC_SPURIOUS_VECTOR 0x0F0
|
||||
#define BX_LAPIC_ISR1 0x100
|
||||
#define BX_LAPIC_ISR2 0x110
|
||||
#define BX_LAPIC_ISR3 0x120
|
||||
#define BX_LAPIC_ISR4 0x130
|
||||
#define BX_LAPIC_ISR5 0x140
|
||||
#define BX_LAPIC_ISR6 0x150
|
||||
#define BX_LAPIC_ISR7 0x160
|
||||
#define BX_LAPIC_ISR8 0x170
|
||||
#define BX_LAPIC_TMR1 0x180
|
||||
#define BX_LAPIC_TMR2 0x190
|
||||
#define BX_LAPIC_TMR3 0x1A0
|
||||
#define BX_LAPIC_TMR4 0x1B0
|
||||
#define BX_LAPIC_TMR5 0x1C0
|
||||
#define BX_LAPIC_TMR6 0x1D0
|
||||
#define BX_LAPIC_TMR7 0x1E0
|
||||
#define BX_LAPIC_TMR8 0x1F0
|
||||
#define BX_LAPIC_IRR1 0x200
|
||||
#define BX_LAPIC_IRR2 0x210
|
||||
#define BX_LAPIC_IRR3 0x220
|
||||
#define BX_LAPIC_IRR4 0x230
|
||||
#define BX_LAPIC_IRR5 0x240
|
||||
#define BX_LAPIC_IRR6 0x250
|
||||
#define BX_LAPIC_IRR7 0x260
|
||||
#define BX_LAPIC_IRR8 0x270
|
||||
#define BX_LAPIC_ESR 0x280
|
||||
#define BX_LAPIC_LVT_CMCI 0x2F0
|
||||
#define BX_LAPIC_ICR_LO 0x300
|
||||
#define BX_LAPIC_ICR_HI 0x310
|
||||
#define BX_LAPIC_LVT_TIMER 0x320
|
||||
#define BX_LAPIC_LVT_THERMAL 0x330
|
||||
#define BX_LAPIC_LVT_PERFMON 0x340
|
||||
#define BX_LAPIC_LVT_LINT0 0x350
|
||||
#define BX_LAPIC_LVT_LINT1 0x360
|
||||
#define BX_LAPIC_LVT_ERROR 0x370
|
||||
#define BX_LAPIC_TIMER_INITIAL_COUNT 0x380
|
||||
#define BX_LAPIC_TIMER_CURRENT_COUNT 0x390
|
||||
#define BX_LAPIC_TIMER_DIVIDE_CFG 0x3E0
|
||||
#define BX_LAPIC_SELF_IPI 0x3F0
|
||||
|
||||
// APIC write: 4 byte write to 16-byte aligned APIC address
|
||||
void bx_local_apic_c::write_aligned(bx_phy_address addr, Bit32u *data)
|
||||
void bx_local_apic_c::write_aligned(bx_phy_address addr, Bit32u value)
|
||||
{
|
||||
BX_DEBUG(("%s: LAPIC write 0x" FMT_PHY_ADDRX " to address %08x", cpu->name, *data, addr));
|
||||
BX_ASSERT((addr & 0xf) == 0);
|
||||
Bit32u apic_reg = addr & 0xff0;
|
||||
Bit32u value = *data;
|
||||
unsigned apic_reg = addr & 0xff0;
|
||||
BX_DEBUG(("%s: LAPIC write 0x%08x to register 0x%04x", cpu->name, value, apic_reg));
|
||||
switch(apic_reg) {
|
||||
case 0x20: // local APIC id
|
||||
id = (value>>24) & APIC_ID_MASK;
|
||||
break;
|
||||
case 0x80: // task priority
|
||||
case BX_LAPIC_TPR: // task priority
|
||||
set_tpr(value & 0xff);
|
||||
break;
|
||||
case 0xb0: // EOI
|
||||
case BX_LAPIC_EOI: // EOI
|
||||
receive_EOI(value);
|
||||
break;
|
||||
case 0xd0: // logical destination
|
||||
log_dest = (value >> 24) & APIC_ID_MASK;
|
||||
BX_DEBUG(("set logical destination to %02x", log_dest));
|
||||
case BX_LAPIC_LDR: // logical destination
|
||||
ldr = (value >> 24) & APIC_ID_MASK;
|
||||
BX_DEBUG(("set logical destination to %08x", ldr));
|
||||
break;
|
||||
case 0xe0: // destination format
|
||||
case BX_LAPIC_DESTINATION_FORMAT:
|
||||
dest_format = (value >> 28) & 0xf;
|
||||
BX_DEBUG(("set destination format to %02x", dest_format));
|
||||
break;
|
||||
case 0xf0: // spurious interrupt vector
|
||||
case BX_LAPIC_SPURIOUS_VECTOR:
|
||||
write_spurious_interrupt_register(value);
|
||||
break;
|
||||
case 0x280: // error status reg
|
||||
case BX_LAPIC_ESR: // error status reg
|
||||
// Here's what the IA-devguide-3 says on p.7-45:
|
||||
// The ESR is a read/write register and is reset after being written to
|
||||
// by the processor. A write to the ESR must be done just prior to
|
||||
@ -344,60 +388,63 @@ void bx_local_apic_c::write_aligned(bx_phy_address addr, Bit32u *data)
|
||||
error_status = shadow_error_status;
|
||||
shadow_error_status = 0;
|
||||
break;
|
||||
case 0x300: // interrupt command reg 0-31
|
||||
case BX_LAPIC_ICR_LO: // interrupt command reg 0-31
|
||||
icr_lo = value & ~(1<<12); // force delivery status bit = 0(idle)
|
||||
send_ipi();
|
||||
break;
|
||||
case 0x310: // interrupt command reg 31-63
|
||||
case BX_LAPIC_ICR_HI: // interrupt command reg 31-63
|
||||
icr_hi = value & 0xff000000;
|
||||
break;
|
||||
case 0x320: // LVT Timer Reg
|
||||
lvt[APIC_LVT_TIMER] = value & 0x300ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_TIMER] |= 0x10000;
|
||||
break;
|
||||
case 0x330: // LVT Thermal Monitor
|
||||
lvt[APIC_LVT_THERMAL] = value & 0x107ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_THERMAL] |= 0x10000;
|
||||
break;
|
||||
case 0x340: // LVT Performance Counter
|
||||
lvt[APIC_LVT_PERFORM] = value & 0x107ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_PERFORM] |= 0x10000;
|
||||
break;
|
||||
case 0x350: // LVT LINT0 Reg
|
||||
lvt[APIC_LVT_LINT0] = value & 0x1a7ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_LINT0] |= 0x10000;
|
||||
break;
|
||||
case 0x360: // LVT Lint1 Reg
|
||||
lvt[APIC_LVT_LINT1] = value & 0x1a7ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_LINT1] |= 0x10000;
|
||||
break;
|
||||
case 0x370: // LVT Error Reg
|
||||
lvt[APIC_LVT_ERROR] = value & 0x100ff;
|
||||
if(! software_enabled) lvt[APIC_LVT_ERROR] |= 0x10000;
|
||||
break;
|
||||
case 0x380: // initial count for timer
|
||||
case BX_LAPIC_LVT_TIMER: // LVT Timer Reg
|
||||
case BX_LAPIC_LVT_THERMAL: // LVT Thermal Monitor
|
||||
case BX_LAPIC_LVT_PERFMON: // LVT Performance Counter
|
||||
case BX_LAPIC_LVT_LINT0: // LVT LINT0 Reg
|
||||
case BX_LAPIC_LVT_LINT1: // LVT LINT1 Reg
|
||||
case BX_LAPIC_LVT_ERROR: // LVT Error Reg
|
||||
{
|
||||
static Bit32u lvt_mask[] = {
|
||||
0x000310ff, /* TIMER */
|
||||
0x000117ff, /* THERMAL */
|
||||
0x000117ff, /* PERFMON */
|
||||
0x0001f7ff, /* LINT0 */
|
||||
0x0001f7ff, /* LINT1 */
|
||||
0x000110ff /* ERROR */
|
||||
};
|
||||
unsigned lvt_entry = (apic_reg - BX_LAPIC_LVT_TIMER) >> 4;
|
||||
lvt[lvt_entry] = value & lvt_mask[lvt_entry];
|
||||
if(! software_enabled) lvt[lvt_entry] |= 0x10000;
|
||||
break;
|
||||
}
|
||||
case BX_LAPIC_TIMER_INITIAL_COUNT:
|
||||
set_initial_timer_count(value);
|
||||
break;
|
||||
case 0x3e0: // timer divide configuration
|
||||
case BX_LAPIC_TIMER_DIVIDE_CFG:
|
||||
// only bits 3, 1, and 0 are writable
|
||||
timer_divconf = value & 0xb;
|
||||
set_divide_configuration(timer_divconf);
|
||||
break;
|
||||
/* all read-only registers go here */
|
||||
case 0x30: // local APIC version
|
||||
case 0x90: // arbitration priority
|
||||
case 0xa0: // processor priority
|
||||
case BX_LAPIC_ID: // local APIC id
|
||||
case BX_LAPIC_VERSION: // local APIC version
|
||||
case BX_LAPIC_ARBITRATION_PRIORITY:
|
||||
case BX_LAPIC_PPR: // processor priority
|
||||
// ISRs not writable
|
||||
case 0x100: case 0x110: case 0x120: case 0x130:
|
||||
case 0x140: case 0x150: case 0x160: case 0x170:
|
||||
case BX_LAPIC_ISR1: case BX_LAPIC_ISR2:
|
||||
case BX_LAPIC_ISR3: case BX_LAPIC_ISR4:
|
||||
case BX_LAPIC_ISR5: case BX_LAPIC_ISR6:
|
||||
case BX_LAPIC_ISR7: case BX_LAPIC_ISR8:
|
||||
// TMRs not writable
|
||||
case 0x180: case 0x190: case 0x1a0: case 0x1b0:
|
||||
case 0x1c0: case 0x1d0: case 0x1e0: case 0x1f0:
|
||||
case BX_LAPIC_TMR1: case BX_LAPIC_TMR2:
|
||||
case BX_LAPIC_TMR3: case BX_LAPIC_TMR4:
|
||||
case BX_LAPIC_TMR5: case BX_LAPIC_TMR6:
|
||||
case BX_LAPIC_TMR7: case BX_LAPIC_TMR8:
|
||||
// IRRs not writable
|
||||
case 0x200: case 0x210: case 0x220: case 0x230:
|
||||
case 0x240: case 0x250: case 0x260: case 0x270:
|
||||
// current count for timer
|
||||
case 0x390:
|
||||
case BX_LAPIC_IRR1: case BX_LAPIC_IRR2:
|
||||
case BX_LAPIC_IRR3: case BX_LAPIC_IRR4:
|
||||
case BX_LAPIC_IRR5: case BX_LAPIC_IRR6:
|
||||
case BX_LAPIC_IRR7: case BX_LAPIC_IRR8:
|
||||
// current count for timer
|
||||
case BX_LAPIC_TIMER_CURRENT_COUNT:
|
||||
// all read-only registers should fall into this line
|
||||
BX_INFO(("warning: write to read-only APIC register 0x%x", apic_reg));
|
||||
break;
|
||||
@ -414,7 +461,7 @@ void bx_local_apic_c::send_ipi(void)
|
||||
int dest_shorthand = (icr_lo >> 18) & 3;
|
||||
int trig_mode = (icr_lo >> 15) & 1;
|
||||
int level = (icr_lo >> 14) & 1;
|
||||
int dest_mode = (icr_lo >> 11) & 1;
|
||||
int logical_dest = (icr_lo >> 11) & 1;
|
||||
int delivery_mode = (icr_lo >> 8) & 7;
|
||||
int vector = (icr_lo & 0xff);
|
||||
int accepted = 0;
|
||||
@ -433,7 +480,7 @@ void bx_local_apic_c::send_ipi(void)
|
||||
|
||||
switch(dest_shorthand) {
|
||||
case 0: // no shorthand, use real destination value
|
||||
accepted = apic_bus_deliver_interrupt(vector, dest, delivery_mode, dest_mode, level, trig_mode);
|
||||
accepted = apic_bus_deliver_interrupt(vector, dest, delivery_mode, logical_dest, level, trig_mode);
|
||||
break;
|
||||
case 1: // self
|
||||
trigger_irq(vector, trig_mode);
|
||||
@ -497,130 +544,131 @@ void bx_local_apic_c::receive_EOI(Bit32u value)
|
||||
if(bx_dbg.apic) print_status();
|
||||
}
|
||||
|
||||
void bx_local_apic_c::startup_msg(Bit32u vector)
|
||||
void bx_local_apic_c::startup_msg(Bit8u vector)
|
||||
{
|
||||
cpu->deliver_SIPI(vector);
|
||||
}
|
||||
|
||||
// APIC read: 4 byte read from 16-byte aligned APIC address
|
||||
void bx_local_apic_c::read_aligned(bx_phy_address addr, Bit32u *data)
|
||||
Bit32u bx_local_apic_c::read_aligned(bx_phy_address addr)
|
||||
{
|
||||
BX_DEBUG(("%s: LAPIC read from address 0x" FMT_PHY_ADDRX, cpu->name, addr));
|
||||
BX_ASSERT((addr & 0xf) == 0);
|
||||
*data = 0; // default value for unimplemented registers
|
||||
bx_phy_address apic_reg = addr & 0xff0;
|
||||
Bit32u data = 0; // default value for unimplemented registers
|
||||
unsigned apic_reg = addr & 0xff0;
|
||||
BX_DEBUG(("%s: LAPIC read from register 0x%04x", cpu->name, apic_reg));
|
||||
switch(apic_reg) {
|
||||
case 0x20: // local APIC id
|
||||
*data = (id) << 24; break;
|
||||
case 0x30: // local APIC version
|
||||
*data = BX_LAPIC_VERSION_ID; break;
|
||||
case 0x80: // task priority
|
||||
*data = task_priority & 0xff; break;
|
||||
case 0x90: // arbitration priority
|
||||
*data = get_apr(); break;
|
||||
case 0xa0: // processor priority
|
||||
*data = get_ppr(); break;
|
||||
case 0xb0: // EOI
|
||||
case BX_LAPIC_ID: // local APIC id
|
||||
data = (id) << 24; break;
|
||||
case BX_LAPIC_VERSION: // local APIC version
|
||||
data = BX_LAPIC_VERSION_ID; break;
|
||||
case BX_LAPIC_TPR: // task priority
|
||||
data = task_priority & 0xff; break;
|
||||
case BX_LAPIC_ARBITRATION_PRIORITY:
|
||||
data = get_apr(); break;
|
||||
case BX_LAPIC_PPR: // processor priority
|
||||
data = get_ppr(); break;
|
||||
case BX_LAPIC_EOI: // EOI
|
||||
/*
|
||||
* Read-modify-write operations should operate without generating
|
||||
* exceptions, and are used by some operating systems to EOI.
|
||||
* The results of reads should be ignored by the OS.
|
||||
*/
|
||||
break;
|
||||
case 0xd0: // logical destination
|
||||
*data = (log_dest & APIC_ID_MASK) << 24; break;
|
||||
case 0xe0: // destination format
|
||||
*data = ((dest_format & 0xf) << 24) | 0x0fffffff; break;
|
||||
case 0xf0: // spurious interrupt vector
|
||||
case BX_LAPIC_LDR: // logical destination
|
||||
data = (ldr & APIC_ID_MASK) << 24; break;
|
||||
case BX_LAPIC_DESTINATION_FORMAT:
|
||||
data = ((dest_format & 0xf) << 24) | 0x0fffffff; break;
|
||||
case BX_LAPIC_SPURIOUS_VECTOR:
|
||||
{
|
||||
Bit32u reg = spurious_vector;
|
||||
if(software_enabled) reg |= 0x100;
|
||||
if(focus_disable) reg |= 0x200;
|
||||
*data = reg;
|
||||
data = reg;
|
||||
}
|
||||
break;
|
||||
case 0x100: case 0x110:
|
||||
case 0x120: case 0x130:
|
||||
case 0x140: case 0x150:
|
||||
case 0x160: case 0x170:
|
||||
case BX_LAPIC_ISR1: case BX_LAPIC_ISR2:
|
||||
case BX_LAPIC_ISR3: case BX_LAPIC_ISR4:
|
||||
case BX_LAPIC_ISR5: case BX_LAPIC_ISR6:
|
||||
case BX_LAPIC_ISR7: case BX_LAPIC_ISR8:
|
||||
{
|
||||
unsigned index = (apic_reg - 0x100) << 1;
|
||||
unsigned index = (apic_reg - BX_LAPIC_ISR1) << 1;
|
||||
Bit32u value = 0, mask = 1;
|
||||
for(int i=0;i<32;i++) {
|
||||
if(isr[index+i]) value |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
*data = value;
|
||||
data = value;
|
||||
}
|
||||
break;
|
||||
case 0x180: case 0x190:
|
||||
case 0x1a0: case 0x1b0:
|
||||
case 0x1c0: case 0x1d0:
|
||||
case 0x1e0: case 0x1f0:
|
||||
case BX_LAPIC_TMR1: case BX_LAPIC_TMR2:
|
||||
case BX_LAPIC_TMR3: case BX_LAPIC_TMR4:
|
||||
case BX_LAPIC_TMR5: case BX_LAPIC_TMR6:
|
||||
case BX_LAPIC_TMR7: case BX_LAPIC_TMR8:
|
||||
{
|
||||
unsigned index = (apic_reg - 0x180) << 1;
|
||||
unsigned index = (apic_reg - BX_LAPIC_TMR1) << 1;
|
||||
Bit32u value = 0, mask = 1;
|
||||
for(int i=0;i<32;i++) {
|
||||
if(tmr[index+i]) value |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
*data = value;
|
||||
data = value;
|
||||
}
|
||||
break;
|
||||
case 0x200: case 0x210:
|
||||
case 0x220: case 0x230:
|
||||
case 0x240: case 0x250:
|
||||
case 0x260: case 0x270:
|
||||
case BX_LAPIC_IRR1: case BX_LAPIC_IRR2:
|
||||
case BX_LAPIC_IRR3: case BX_LAPIC_IRR4:
|
||||
case BX_LAPIC_IRR5: case BX_LAPIC_IRR6:
|
||||
case BX_LAPIC_IRR7: case BX_LAPIC_IRR8:
|
||||
{
|
||||
unsigned index = (apic_reg - 0x200) << 1;
|
||||
unsigned index = (apic_reg - BX_LAPIC_IRR1) << 1;
|
||||
Bit32u value = 0, mask = 1;
|
||||
for(int i=0;i<32;i++) {
|
||||
if(irr[index+i]) value |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
*data = value;
|
||||
data = value;
|
||||
}
|
||||
break;
|
||||
case 0x280: // error status reg
|
||||
*data = error_status; break;
|
||||
case 0x300: // interrupt command reg 0-31
|
||||
*data = icr_lo; break;
|
||||
case 0x310: // interrupt command reg 31-63
|
||||
*data = icr_hi; break;
|
||||
case 0x320: // LVT Timer Reg
|
||||
case 0x330: // LVT Thermal Monitor
|
||||
case 0x340: // LVT Performance Counter
|
||||
case 0x350: // LVT LINT0 Reg
|
||||
case 0x360: // LVT Lint1 Reg
|
||||
case 0x370: // LVT Error Reg
|
||||
case BX_LAPIC_ESR: // error status reg
|
||||
data = error_status; break;
|
||||
case BX_LAPIC_ICR_LO: // interrupt command reg 0-31
|
||||
data = icr_lo; break;
|
||||
case BX_LAPIC_ICR_HI: // interrupt command reg 31-63
|
||||
data = icr_hi; break;
|
||||
case BX_LAPIC_LVT_TIMER: // LVT Timer Reg
|
||||
case BX_LAPIC_LVT_THERMAL: // LVT Thermal Monitor
|
||||
case BX_LAPIC_LVT_PERFMON: // LVT Performance Counter
|
||||
case BX_LAPIC_LVT_LINT0: // LVT LINT0 Reg
|
||||
case BX_LAPIC_LVT_LINT1: // LVT Lint1 Reg
|
||||
case BX_LAPIC_LVT_ERROR: // LVT Error Reg
|
||||
{
|
||||
int index = (apic_reg - 0x320) >> 4;
|
||||
*data = lvt[index];
|
||||
int index = (apic_reg - BX_LAPIC_LVT_TIMER) >> 4;
|
||||
data = lvt[index];
|
||||
break;
|
||||
}
|
||||
case 0x380: // initial count for timer
|
||||
*data = timer_initial;
|
||||
case BX_LAPIC_TIMER_INITIAL_COUNT: // initial count for timer
|
||||
data = timer_initial;
|
||||
break;
|
||||
case 0x390: // current count for timer
|
||||
case BX_LAPIC_TIMER_CURRENT_COUNT: // current count for timer
|
||||
if(timer_active==0) {
|
||||
*data = timer_current;
|
||||
data = timer_current;
|
||||
} else {
|
||||
Bit64u delta64 = (bx_pc_system.time_ticks() - ticksInitial) / timer_divide_factor;
|
||||
Bit32u delta32 = (Bit32u) delta64;
|
||||
if(delta32 > timer_initial)
|
||||
BX_PANIC(("APIC: R(curr timer count): delta < initial"));
|
||||
timer_current = timer_initial - delta32;
|
||||
*data = timer_current;
|
||||
data = timer_current;
|
||||
}
|
||||
break;
|
||||
case 0x3e0: // timer divide configuration
|
||||
*data = timer_divconf;
|
||||
case BX_LAPIC_TIMER_DIVIDE_CFG: // timer divide configuration
|
||||
data = timer_divconf;
|
||||
break;
|
||||
default:
|
||||
BX_INFO(("APIC register %08x not implemented", apic_reg));
|
||||
}
|
||||
|
||||
BX_DEBUG(("%s: read from APIC address 0x" FMT_PHY_ADDRX " = %08x", cpu->name, addr, *data));
|
||||
BX_DEBUG(("%s: read from APIC address 0x" FMT_PHY_ADDRX " = %08x", cpu->name, addr, data));
|
||||
return data;
|
||||
}
|
||||
|
||||
int bx_local_apic_c::highest_priority_int(Bit8u *array)
|
||||
@ -693,7 +741,7 @@ bx_bool bx_local_apic_c::deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_m
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bx_local_apic_c::trigger_irq(unsigned vector, unsigned trigger_mode, bx_bool bypass_irr_isr)
|
||||
void bx_local_apic_c::trigger_irq(Bit8u vector, unsigned trigger_mode, bx_bool bypass_irr_isr)
|
||||
{
|
||||
BX_DEBUG(("Local apic on %s: trigger interrupt vector=0x%x", cpu->name, vector));
|
||||
|
||||
@ -720,7 +768,7 @@ service_vector:
|
||||
service_local_apic();
|
||||
}
|
||||
|
||||
void bx_local_apic_c::untrigger_irq(unsigned vector, unsigned trigger_mode)
|
||||
void bx_local_apic_c::untrigger_irq(Bit8u vector, unsigned trigger_mode)
|
||||
{
|
||||
BX_DEBUG(("Local apic on %s: untrigger interrupt vector=0x%x", cpu->name, vector));
|
||||
// hardware says "no more". clear the bit. If the CPU hasn't yet
|
||||
@ -775,17 +823,17 @@ bx_bool bx_local_apic_c::match_logical_addr(Bit8u address)
|
||||
|
||||
if (dest_format == 0xf) {
|
||||
// flat model
|
||||
match = ((address & log_dest) != 0);
|
||||
match = ((address & ldr) != 0);
|
||||
BX_DEBUG(("%s: comparing MDA %02x to my LDR %02x -> %s", cpu->name,
|
||||
address, log_dest, match? "Match" : "Not a match"));
|
||||
address, ldr, match? "Match" : "Not a match"));
|
||||
}
|
||||
else if (dest_format == 0) {
|
||||
// cluster model
|
||||
if (address == 0xff) // broadcast all
|
||||
return 1;
|
||||
|
||||
if ((unsigned)(address & 0xf0) == (unsigned)(log_dest & 0xf0))
|
||||
match = ((address & log_dest & 0x0f) != 0);
|
||||
if ((unsigned)(address & 0xf0) == (unsigned)(ldr & 0xf0))
|
||||
match = ((address & ldr & 0x0f) != 0);
|
||||
}
|
||||
else {
|
||||
BX_PANIC(("bx_local_apic_c::match_logical_addr: unsupported dest format 0x%x", dest_format));
|
||||
@ -806,12 +854,7 @@ Bit8u bx_local_apic_c::get_ppr(void)
|
||||
return ppr;
|
||||
}
|
||||
|
||||
Bit8u bx_local_apic_c::get_tpr(void)
|
||||
{
|
||||
return task_priority;
|
||||
}
|
||||
|
||||
void bx_local_apic_c::set_tpr(Bit8u priority)
|
||||
void bx_local_apic_c::set_tpr(Bit8u priority)
|
||||
{
|
||||
if(priority < task_priority) {
|
||||
task_priority = priority;
|
||||
@ -941,13 +984,12 @@ void bx_local_apic_c::register_state(bx_param_c *parent)
|
||||
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, base_addr);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, id);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, mode);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, spurious_vector);
|
||||
BXRS_PARAM_BOOL(lapic, software_enabled, software_enabled);
|
||||
BXRS_PARAM_BOOL(lapic, global_enabled, global_enabled);
|
||||
BXRS_PARAM_BOOL(lapic, focus_disable, focus_disable);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, task_priority);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, spurious_vector);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, log_dest);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, ldr);
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, dest_format);
|
||||
|
||||
bx_list_c *ISR = new bx_list_c(lapic, "isr", BX_LAPIC_MAX_INTS);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: apic.h,v 1.43 2009-02-18 22:24:55 sshwarts Exp $
|
||||
// $Id: apic.h,v 1.44 2009-02-19 23:19:11 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
|
||||
@ -34,8 +34,6 @@
|
||||
|
||||
#ifdef BX_INCLUDE_LOCAL_APIC
|
||||
|
||||
#define BX_CPU_APIC(i) (&(BX_CPU(i)->lapic))
|
||||
|
||||
#ifdef BX_IMPLEMENT_XAPIC
|
||||
# define BX_LAPIC_VERSION_ID 0x00050014 // P4 has 6 LVT entries
|
||||
#else
|
||||
@ -46,18 +44,23 @@
|
||||
#define BX_NUM_LOCAL_APICS BX_SMP_PROCESSORS
|
||||
#define BX_LAPIC_MAX_INTS 256
|
||||
|
||||
#define BX_APIC_GLOBALLY_DISABLED 0
|
||||
#define BX_APIC_STATE_INVALID 1
|
||||
#define BX_APIC_XAPIC_MODE 2
|
||||
#define BX_APIC_X2APIC_MODE 3
|
||||
|
||||
class BOCHSAPI bx_local_apic_c : public logfunctions
|
||||
{
|
||||
bx_phy_address base_addr;
|
||||
Bit32u id;
|
||||
bx_bool global_enabled;
|
||||
unsigned mode;
|
||||
|
||||
bx_bool software_enabled;
|
||||
Bit32u spurious_vector;
|
||||
bx_bool focus_disable;
|
||||
|
||||
Bit32u task_priority; // Task priority (TPR)
|
||||
Bit32u log_dest; // Logical destination (LDR)
|
||||
Bit32u ldr; // Logical destination (LDR)
|
||||
Bit32u dest_format; // Destination format (DFR)
|
||||
|
||||
// ISR=in-service register. When an IRR bit is cleared, the corresponding
|
||||
@ -90,7 +93,7 @@ class BOCHSAPI bx_local_apic_c : public logfunctions
|
||||
Bit32u lvt[APIC_LVT_ENTRIES];
|
||||
#define APIC_LVT_TIMER 0
|
||||
#define APIC_LVT_THERMAL 1
|
||||
#define APIC_LVT_PERFORM 2
|
||||
#define APIC_LVT_PERFMON 2
|
||||
#define APIC_LVT_LINT0 3
|
||||
#define APIC_LVT_LINT1 4
|
||||
#define APIC_LVT_ERROR 5
|
||||
@ -118,9 +121,6 @@ class BOCHSAPI bx_local_apic_c : public logfunctions
|
||||
|
||||
BX_CPU_C *cpu;
|
||||
|
||||
// corresponding BX_CPU_ID for the local APIC
|
||||
unsigned cpu_id;
|
||||
|
||||
public:
|
||||
bx_bool INTR;
|
||||
bx_local_apic_c(BX_CPU_C *cpu);
|
||||
@ -134,14 +134,14 @@ public:
|
||||
bx_bool is_selected(bx_phy_address addr);
|
||||
void read(bx_phy_address addr, void *data, unsigned len);
|
||||
void write(bx_phy_address addr, void *data, unsigned len);
|
||||
void write_aligned(bx_phy_address addr, Bit32u *data);
|
||||
void read_aligned(bx_phy_address address, Bit32u *data);
|
||||
void startup_msg(Bit32u vector);
|
||||
void write_aligned(bx_phy_address addr, Bit32u data);
|
||||
Bit32u read_aligned(bx_phy_address address);
|
||||
void startup_msg(Bit8u vector);
|
||||
// on local APIC, trigger means raise the CPU's INTR line. For now
|
||||
// I also have to raise pc_system.INTR but that should be replaced
|
||||
// with the cpu-specific INTR signals.
|
||||
void trigger_irq(unsigned num, unsigned trigger_mode, bx_bool bypass_irr_isr = 0);
|
||||
void untrigger_irq(unsigned num, unsigned trigger_mode);
|
||||
void trigger_irq(Bit8u vector, unsigned trigger_mode, bx_bool bypass_irr_isr = 0);
|
||||
void untrigger_irq(Bit8u vector, unsigned trigger_mode);
|
||||
Bit8u acknowledge_int(void); // only the local CPU should call this
|
||||
int highest_priority_int(Bit8u *array);
|
||||
void receive_EOI(Bit32u value);
|
||||
@ -151,7 +151,7 @@ public:
|
||||
void print_status(void);
|
||||
bx_bool match_logical_addr (Bit8u address);
|
||||
bx_bool deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode);
|
||||
Bit8u get_tpr(void);
|
||||
Bit8u get_tpr(void) { return task_priority; }
|
||||
void set_tpr(Bit8u tpr);
|
||||
Bit8u get_ppr(void);
|
||||
Bit8u get_apr(void);
|
||||
@ -175,7 +175,7 @@ public:
|
||||
#endif
|
||||
|
||||
int apic_bus_deliver_lowest_priority(Bit8u vector, Bit8u dest, bx_bool trig_mode, bx_bool broadcast);
|
||||
int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, Bit8u dest_mode, bx_bool level, bx_bool trig_mode);
|
||||
int apic_bus_deliver_interrupt(Bit8u vector, Bit8u dest, Bit8u delivery_mode, bx_bool logical_dest, bx_bool level, bx_bool trig_mode);
|
||||
int apic_bus_broadcast_interrupt(Bit8u vector, Bit8u delivery_mode, bx_bool trig_mode, int exclude_cpu);
|
||||
|
||||
#endif // if BX_SUPPORT_APIC
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ioapic.cc,v 1.46 2009-02-18 22:25:02 sshwarts Exp $
|
||||
// $Id: ioapic.cc,v 1.47 2009-02-19 23:19:11 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -69,7 +69,7 @@ static bx_bool ioapic_write(bx_phy_address a20addr, unsigned len, void *data, vo
|
||||
return 1;
|
||||
}
|
||||
|
||||
bx_ioapic.write_aligned(a20addr, (Bit32u*) data);
|
||||
bx_ioapic.write_aligned(a20addr, *((Bit32u*) data));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ Bit32u bx_ioapic_c::read_aligned(bx_phy_address address)
|
||||
BX_PANIC(("IOAPIC: read from unsupported address"));
|
||||
}
|
||||
|
||||
Bit32u data;
|
||||
Bit32u data = 0;
|
||||
|
||||
// only reached when reading data register
|
||||
switch (ioregsel) {
|
||||
@ -146,7 +146,6 @@ Bit32u bx_ioapic_c::read_aligned(bx_phy_address address)
|
||||
break;
|
||||
case 0x02:
|
||||
BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
|
||||
data = 0;
|
||||
break;
|
||||
default:
|
||||
int index = (ioregsel - 0x10) >> 1;
|
||||
@ -161,12 +160,12 @@ Bit32u bx_ioapic_c::read_aligned(bx_phy_address address)
|
||||
return data;
|
||||
}
|
||||
|
||||
void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
|
||||
void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u value)
|
||||
{
|
||||
BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", address, *value));
|
||||
BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", (unsigned) address, value));
|
||||
address &= 0xff;
|
||||
if (address == 0x00) {
|
||||
ioregsel = *value;
|
||||
ioregsel = value;
|
||||
return;
|
||||
} else {
|
||||
if (address != 0x10)
|
||||
@ -176,7 +175,7 @@ void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
|
||||
switch (ioregsel) {
|
||||
case 0x00: // set APIC ID
|
||||
{
|
||||
Bit8u newid = (*value >> 24) & APIC_ID_MASK;
|
||||
Bit8u newid = (value >> 24) & APIC_ID_MASK;
|
||||
BX_INFO(("IOAPIC: setting id to 0x%x", newid));
|
||||
set_id (newid);
|
||||
return;
|
||||
@ -190,9 +189,9 @@ void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
|
||||
if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
|
||||
bx_io_redirect_entry_t *entry = ioredtbl + index;
|
||||
if (ioregsel&1)
|
||||
entry->set_hi_part(*value);
|
||||
entry->set_hi_part(value);
|
||||
else
|
||||
entry->set_lo_part(*value);
|
||||
entry->set_lo_part(value);
|
||||
char buf[1024];
|
||||
entry->sprintf_self(buf);
|
||||
BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ioapic.h,v 1.30 2009-02-18 22:25:04 sshwarts Exp $
|
||||
// $Id: ioapic.h,v 1.31 2009-02-19 23:19:11 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -101,7 +101,7 @@ public:
|
||||
Bit32u get_id() const { return id; }
|
||||
|
||||
Bit32u read_aligned(bx_phy_address address);
|
||||
void write_aligned(bx_phy_address address, Bit32u *data);
|
||||
void write_aligned(bx_phy_address address, Bit32u data);
|
||||
|
||||
void set_irq_level(Bit8u int_in, bx_bool level);
|
||||
void receive_eoi(Bit8u vector);
|
||||
|
Loading…
Reference in New Issue
Block a user