support for apic global disable
separate between I/O apic and local apic
This commit is contained in:
parent
87b705d036
commit
1b72e66bb3
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: apic.cc,v 1.118 2009-02-17 19:44:01 sshwarts Exp $
|
||||
// $Id: apic.cc,v 1.119 2009-02-18 22:24:52 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
|
||||
@ -29,6 +29,8 @@
|
||||
|
||||
#define LOG_THIS this->
|
||||
|
||||
#define APIC_UNKNOWN_ID 0xff
|
||||
|
||||
#define APIC_BROADCAST_PHYSICAL_DESTINATION_MODE (APIC_MAX_ID)
|
||||
|
||||
#define BX_LAPIC_FIRST_VECTOR 0x10
|
||||
@ -166,78 +168,13 @@ void apic_bus_broadcast_smi(void)
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
bx_generic_apic_c::bx_generic_apic_c(bx_phy_address base)
|
||||
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())
|
||||
{
|
||||
put("APIC?");
|
||||
id = APIC_UNKNOWN_ID;
|
||||
set_base(base);
|
||||
}
|
||||
|
||||
void bx_generic_apic_c::set_base(bx_phy_address newbase)
|
||||
{
|
||||
newbase &= (~0xfff);
|
||||
base_addr = newbase;
|
||||
if (id != APIC_UNKNOWN_ID)
|
||||
BX_INFO(("relocate APIC id=%d to 0x" FMT_PHY_ADDRX, id, newbase));
|
||||
}
|
||||
|
||||
void bx_generic_apic_c::set_id(Bit32u newid)
|
||||
{
|
||||
BX_INFO(("set APIC ID to %d", newid));
|
||||
id = newid;
|
||||
}
|
||||
|
||||
bx_bool bx_generic_apic_c::is_selected(bx_phy_address addr, unsigned len)
|
||||
{
|
||||
if((addr & ~0xfff) == get_base()) {
|
||||
if((addr & 0xf) != 0)
|
||||
BX_INFO(("warning: misaligned APIC access. addr=0x" FMT_PHY_ADDRX ", len=%d", addr, len));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bx_generic_apic_c::read(bx_phy_address addr, void *data, unsigned len)
|
||||
{
|
||||
if((addr & ~0x3) != ((addr+len-1) & ~0x3)) {
|
||||
BX_PANIC(("APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", addr));
|
||||
return;
|
||||
}
|
||||
Bit32u value;
|
||||
read_aligned(addr & ~0x3, &value);
|
||||
if(len == 4) { // must be 32-bit aligned
|
||||
*((Bit32u *)data) = value;
|
||||
return;
|
||||
}
|
||||
// handle partial read, independent of endian-ness
|
||||
value >>= (addr&3)*8;
|
||||
if (len == 1)
|
||||
*((Bit8u *) data) = value & 0xff;
|
||||
else if (len == 2)
|
||||
*((Bit16u *)data) = value & 0xffff;
|
||||
else
|
||||
BX_PANIC(("Unsupported APIC read at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len));
|
||||
}
|
||||
|
||||
void bx_generic_apic_c::write(bx_phy_address addr, void *data, unsigned len)
|
||||
{
|
||||
if (len != 4) {
|
||||
BX_PANIC(("APIC write with len=%d (should be 4)", len));
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr & 0xf) {
|
||||
BX_PANIC(("APIC write at unaligned address 0x" FMT_PHY_ADDRX, addr));
|
||||
return;
|
||||
}
|
||||
|
||||
write_aligned(addr, (Bit32u*) data);
|
||||
}
|
||||
|
||||
bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu)
|
||||
: bx_generic_apic_c(BX_LAPIC_BASE_ADDR), cpu(mycpu), cpu_id(cpu->which_cpu())
|
||||
{
|
||||
// KPL: Register a non-active timer for use when the timer is started.
|
||||
// Register a non-active timer for use when the timer is started.
|
||||
timer_handle = bx_pc_system.register_timer_ticks(this,
|
||||
BX_CPU(0)->lapic.periodic_smf, 0, 0, 0, "lapic");
|
||||
timer_active = 0;
|
||||
@ -249,8 +186,6 @@ bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu)
|
||||
|
||||
void bx_local_apic_c::reset(unsigned type)
|
||||
{
|
||||
UNUSED(type);
|
||||
|
||||
/* same as INIT but also sets arbitration ID and APIC ID */
|
||||
init();
|
||||
}
|
||||
@ -259,8 +194,6 @@ void bx_local_apic_c::init()
|
||||
{
|
||||
int i;
|
||||
|
||||
bx_generic_apic_c::init();
|
||||
|
||||
BX_INFO(("local apic in %s initializing",
|
||||
(cpu && cpu->name) ? cpu->name : "?"));
|
||||
|
||||
@ -293,13 +226,24 @@ void bx_local_apic_c::init()
|
||||
|
||||
spurious_vector = 0xff; // software disabled(bit 8)
|
||||
software_enabled = 0;
|
||||
focus_disable = 0;
|
||||
global_enabled = 1;
|
||||
focus_disable = 0;
|
||||
}
|
||||
|
||||
void bx_local_apic_c::set_id(Bit8u newid)
|
||||
void bx_local_apic_c::set_base(bx_phy_address newbase)
|
||||
{
|
||||
bx_generic_apic_c::set_id(newid);
|
||||
sprintf(cpu->name, "CPU apicid=%02x",(Bit32u)id);
|
||||
global_enabled = (newbase >> 11) & 1;
|
||||
newbase &= ~((bx_phy_address) 0xfff);
|
||||
base_addr = newbase;
|
||||
if (id != APIC_UNKNOWN_ID)
|
||||
BX_INFO(("relocate APIC id=%d to 0x" FMT_PHY_ADDRX, id, newbase));
|
||||
}
|
||||
|
||||
void bx_local_apic_c::set_id(Bit32u new_id)
|
||||
{
|
||||
id = new_id;
|
||||
sprintf(cpu->name, "CPU apicid=%02x", id);
|
||||
|
||||
if(id < APIC_MAX_ID) {
|
||||
char buffer[16];
|
||||
sprintf(buffer, "APIC%x", id);
|
||||
@ -307,12 +251,61 @@ void bx_local_apic_c::set_id(Bit8u newid)
|
||||
sprintf(buffer, "CPU%x", id);
|
||||
cpu->put(buffer);
|
||||
} else {
|
||||
BX_INFO(("naming convention for apics requires id=0-%d only", APIC_MAX_ID));
|
||||
BX_INFO(("naming convention for APICs requires id=0-%d only", APIC_MAX_ID));
|
||||
}
|
||||
|
||||
BX_INFO(("80%d86", BX_CPU_LEVEL));
|
||||
}
|
||||
|
||||
bx_bool bx_local_apic_c::is_selected(bx_phy_address addr)
|
||||
{
|
||||
if (! global_enabled) return 0;
|
||||
|
||||
if((addr & ~0xfff) == base_addr) {
|
||||
if((addr & 0xf) != 0)
|
||||
BX_INFO(("warning: misaligned APIC access. addr=0x" FMT_PHY_ADDRX, addr));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bx_local_apic_c::read(bx_phy_address addr, void *data, unsigned len)
|
||||
{
|
||||
if((addr & ~0x3) != ((addr+len-1) & ~0x3)) {
|
||||
BX_PANIC(("APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", addr));
|
||||
return;
|
||||
}
|
||||
Bit32u value;
|
||||
read_aligned(addr & ~0x3, &value);
|
||||
if(len == 4) { // must be 32-bit aligned
|
||||
*((Bit32u *)data) = value;
|
||||
return;
|
||||
}
|
||||
// handle partial read, independent of endian-ness
|
||||
value >>= (addr&3)*8;
|
||||
if (len == 1)
|
||||
*((Bit8u *) data) = value & 0xff;
|
||||
else if (len == 2)
|
||||
*((Bit16u *)data) = value & 0xffff;
|
||||
else
|
||||
BX_PANIC(("Unsupported APIC read at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len));
|
||||
}
|
||||
|
||||
void bx_local_apic_c::write(bx_phy_address addr, void *data, unsigned len)
|
||||
{
|
||||
if (len != 4) {
|
||||
BX_PANIC(("APIC write with len=%d (should be 4)", len));
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr & 0xf) {
|
||||
BX_PANIC(("APIC write at unaligned address 0x" FMT_PHY_ADDRX, addr));
|
||||
return;
|
||||
}
|
||||
|
||||
write_aligned(addr, (Bit32u*) data);
|
||||
}
|
||||
|
||||
// APIC write: 4 byte write to 16-byte aligned APIC address
|
||||
void bx_local_apic_c::write_aligned(bx_phy_address addr, Bit32u *data)
|
||||
{
|
||||
@ -948,6 +941,7 @@ void bx_local_apic_c::register_state(bx_param_c *parent)
|
||||
BXRS_HEX_PARAM_SIMPLE(lapic, id);
|
||||
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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: apic.h,v 1.42 2009-02-17 19:44:02 sshwarts Exp $
|
||||
// $Id: apic.h,v 1.43 2009-02-18 22:24:55 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
|
||||
@ -32,28 +32,6 @@
|
||||
#define APIC_LEVEL_TRIGGERED 1
|
||||
#define APIC_EDGE_TRIGGERED 0
|
||||
|
||||
class BOCHSAPI bx_generic_apic_c : public logfunctions {
|
||||
protected:
|
||||
bx_phy_address base_addr;
|
||||
Bit32u id;
|
||||
#define APIC_UNKNOWN_ID 0xff
|
||||
public:
|
||||
bx_generic_apic_c(bx_phy_address base);
|
||||
virtual ~bx_generic_apic_c() { }
|
||||
// init is called during RESET and when an INIT message is delivered
|
||||
virtual void init() { }
|
||||
virtual void reset(unsigned type) {}
|
||||
bx_phy_address get_base(void) const { return base_addr; }
|
||||
void set_base(bx_phy_address newbase);
|
||||
void set_id(Bit32u newid);
|
||||
Bit32u get_id() const { return id; }
|
||||
bx_bool is_selected(bx_phy_address addr, unsigned len);
|
||||
virtual void read_aligned(bx_phy_address address, Bit32u *data) = 0;
|
||||
void read(bx_phy_address addr, void *data, unsigned len);
|
||||
virtual void write_aligned(bx_phy_address address, Bit32u *data) = 0;
|
||||
void write(bx_phy_address addr, void *data, unsigned len);
|
||||
};
|
||||
|
||||
#ifdef BX_INCLUDE_LOCAL_APIC
|
||||
|
||||
#define BX_CPU_APIC(i) (&(BX_CPU(i)->lapic))
|
||||
@ -68,10 +46,14 @@ public:
|
||||
#define BX_NUM_LOCAL_APICS BX_SMP_PROCESSORS
|
||||
#define BX_LAPIC_MAX_INTS 256
|
||||
|
||||
class BOCHSAPI bx_local_apic_c : public bx_generic_apic_c
|
||||
class BOCHSAPI bx_local_apic_c : public logfunctions
|
||||
{
|
||||
Bit32u spurious_vector;
|
||||
bx_phy_address base_addr;
|
||||
Bit32u id;
|
||||
bx_bool global_enabled;
|
||||
|
||||
bx_bool software_enabled;
|
||||
Bit32u spurious_vector;
|
||||
bx_bool focus_disable;
|
||||
|
||||
Bit32u task_priority; // Task priority (TPR)
|
||||
@ -142,12 +124,18 @@ class BOCHSAPI bx_local_apic_c : public bx_generic_apic_c
|
||||
public:
|
||||
bx_bool INTR;
|
||||
bx_local_apic_c(BX_CPU_C *cpu);
|
||||
virtual ~bx_local_apic_c() { }
|
||||
virtual void reset(unsigned type);
|
||||
virtual void init(void);
|
||||
void set_id(Bit8u newid); // redefine to set cpu->name
|
||||
virtual void write_aligned(bx_phy_address addr, Bit32u *data);
|
||||
virtual void read_aligned(bx_phy_address address, Bit32u *data);
|
||||
~bx_local_apic_c() { }
|
||||
void reset(unsigned type);
|
||||
void init(void);
|
||||
bx_phy_address get_base(void) const { return base_addr; }
|
||||
void set_base(bx_phy_address newbase);
|
||||
void set_id(Bit32u newid);
|
||||
Bit32u get_id() const { return id; }
|
||||
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);
|
||||
// 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: cpu.h,v 1.573 2009-02-17 19:44:02 sshwarts Exp $
|
||||
// $Id: cpu.h,v 1.574 2009-02-18 22:24:56 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -3129,7 +3129,7 @@ public: // for now...
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
BX_SMF void relocate_apic(Bit64u val_64);
|
||||
BX_SMF bx_bool relocate_apic(Bit64u val_64);
|
||||
#endif
|
||||
|
||||
BX_SMF void jump_protected(bxInstruction_c *, Bit16u cs, bx_address disp) BX_CPP_AttrRegparmN(3);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: msr.cc,v 1.14 2009-02-17 19:44:02 sshwarts Exp $
|
||||
// $Id: msr.cc,v 1.15 2009-02-18 22:24:57 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2008 Stanislav Shwartsman
|
||||
@ -394,8 +394,7 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
case BX_MSR_APICBASE:
|
||||
relocate_apic(val_64);
|
||||
break;
|
||||
return relocate_apic(val_64);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX
|
||||
@ -512,7 +511,7 @@ bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
|
||||
#endif // BX_CPU_LEVEL >= 5
|
||||
|
||||
#if BX_SUPPORT_APIC
|
||||
void BX_CPU_C::relocate_apic(Bit64u val_64)
|
||||
bx_bool BX_CPU_C::relocate_apic(Bit64u val_64)
|
||||
{
|
||||
/* MSR_APICBASE
|
||||
* 0:7 Reserved
|
||||
@ -523,14 +522,22 @@ void BX_CPU_C::relocate_apic(Bit64u val_64)
|
||||
* 12:35 APIC Base Address (physical)
|
||||
* 36:63 Reserved
|
||||
*/
|
||||
|
||||
#define BX_MSR_APICBASE_RESERVED_BITS 0x6ff
|
||||
|
||||
if (BX_CPU_THIS_PTR msr.apicbase & 0x800) {
|
||||
Bit32u val32_hi = GET32H(val_64), val32_lo = GET32L(val_64);
|
||||
BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", val32_hi, val32_lo));
|
||||
#if BX_PHY_ADDRESS_WIDTH == 32
|
||||
if (val32_hi != 0) {
|
||||
BX_PANIC(("MSR_APICBASE: Only 32 bit physical address space is emulated !"));
|
||||
#if BX_SUPPORT_X86_64
|
||||
if (! IsValidPhyAddr(val_64)) {
|
||||
BX_ERROR(("relocate_apic: invalid physical address"));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (val32_lo & BX_MSR_APICBASE_RESERVED_BITS) {
|
||||
BX_ERROR(("relocate_apic: attempt to set reserved bits"));
|
||||
return 0;
|
||||
}
|
||||
BX_CPU_THIS_PTR msr.apicbase = val_64;
|
||||
BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase);
|
||||
// TLB flush is required for emulation correctness
|
||||
@ -539,6 +546,8 @@ void BX_CPU_C::relocate_apic(Bit64u val_64)
|
||||
else {
|
||||
BX_INFO(("WRMSR: MSR_APICBASE APIC global enable bit cleared !"));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: paging.cc,v 1.169 2009-02-17 19:20:47 sshwarts Exp $
|
||||
// $Id: paging.cc,v 1.170 2009-02-18 22:24:58 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001 MandrakeSoft S.A.
|
||||
@ -1657,7 +1657,7 @@ void BX_CPU_C::access_write_physical(bx_phy_address paddr, unsigned len, void *d
|
||||
{
|
||||
bx_phy_address a20addr = A20ADDR(paddr);
|
||||
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(a20addr, len)) {
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(a20addr)) {
|
||||
BX_CPU_THIS_PTR lapic.write(a20addr, data, len);
|
||||
return;
|
||||
}
|
||||
@ -1669,7 +1669,7 @@ void BX_CPU_C::access_read_physical(bx_phy_address paddr, unsigned len, void *da
|
||||
{
|
||||
bx_phy_address a20addr = A20ADDR(paddr);
|
||||
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(a20addr, len)) {
|
||||
if (BX_CPU_THIS_PTR lapic.is_selected(a20addr)) {
|
||||
BX_CPU_THIS_PTR lapic.read(a20addr, data, len);
|
||||
return;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ TODO (know issues in CPU model):
|
||||
|
||||
[!] Some of APIC functionality still not implemented, for example
|
||||
|
||||
- Globally disabled APIC
|
||||
- LVT pins handling
|
||||
- Filter interrupts according processor priority (PPR)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ioapic.cc,v 1.45 2009-02-08 09:05:52 vruppert Exp $
|
||||
// $Id: ioapic.cc,v 1.46 2009-02-18 22:25:02 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -36,14 +36,31 @@ class bx_ioapic_c bx_ioapic;
|
||||
|
||||
static bx_bool ioapic_read(bx_phy_address a20addr, unsigned len, void *data, void *param)
|
||||
{
|
||||
bx_ioapic.read(a20addr, data, len);
|
||||
if((a20addr & ~0x3) != ((a20addr+len-1) & ~0x3)) {
|
||||
BX_PANIC(("I/O APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", a20addr));
|
||||
return 1;
|
||||
}
|
||||
Bit32u value = bx_ioapic.read_aligned(a20addr & ~0x3);
|
||||
if(len == 4) { // must be 32-bit aligned
|
||||
*((Bit32u *)data) = value;
|
||||
return 1;
|
||||
}
|
||||
// handle partial read, independent of endian-ness
|
||||
value >>= (a20addr&3)*8;
|
||||
if (len == 1)
|
||||
*((Bit8u *) data) = value & 0xff;
|
||||
else if (len == 2)
|
||||
*((Bit16u *)data) = value & 0xffff;
|
||||
else
|
||||
BX_PANIC(("Unsupported I/O APIC read at address 0x" FMT_PHY_ADDRX ", len=%d", a20addr, len));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bx_bool ioapic_write(bx_phy_address a20addr, unsigned len, void *data, void *param)
|
||||
{
|
||||
if (len != 4) {
|
||||
BX_PANIC (("I/O apic write with len=%d (should be 4)", len));
|
||||
BX_PANIC(("I/O apic write with len=%d (should be 4)", len));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -76,22 +93,18 @@ void bx_io_redirect_entry_t::register_state(bx_param_c *parent)
|
||||
BXRS_HEX_PARAM_SIMPLE(parent, hi);
|
||||
}
|
||||
|
||||
#define BX_IOAPIC_BASE_ADDR (0xfec00000)
|
||||
#define BX_IOAPIC_BASE_ADDR (0xfec00000)
|
||||
#define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)
|
||||
|
||||
bx_ioapic_c::bx_ioapic_c()
|
||||
: bx_generic_apic_c(BX_IOAPIC_BASE_ADDR)
|
||||
bx_ioapic_c::bx_ioapic_c(): base_addr(BX_IOAPIC_BASE_ADDR)
|
||||
{
|
||||
set_id(BX_IOAPIC_DEFAULT_ID);
|
||||
put("IOAP");
|
||||
}
|
||||
|
||||
#define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)
|
||||
|
||||
void bx_ioapic_c::init(void)
|
||||
{
|
||||
bx_generic_apic_c::init();
|
||||
BX_INFO(("initializing I/O APIC"));
|
||||
base_addr = BX_IOAPIC_BASE_ADDR;
|
||||
set_id(BX_IOAPIC_DEFAULT_ID);
|
||||
DEV_register_memory_handlers(&bx_ioapic,
|
||||
ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
|
||||
reset(BX_RESET_HARDWARE);
|
||||
@ -109,39 +122,43 @@ void bx_ioapic_c::reset(unsigned type)
|
||||
ioregsel = 0;
|
||||
}
|
||||
|
||||
void bx_ioapic_c::read_aligned(bx_phy_address address, Bit32u *data)
|
||||
Bit32u bx_ioapic_c::read_aligned(bx_phy_address address)
|
||||
{
|
||||
BX_DEBUG(("IOAPIC: read aligned addr=%08x", address));
|
||||
address &= 0xff;
|
||||
if (address == 0x00) {
|
||||
// select register
|
||||
*data = ioregsel;
|
||||
return;
|
||||
return ioregsel;
|
||||
} else {
|
||||
if (address != 0x10)
|
||||
BX_PANIC(("IOAPIC: read from unsupported address"));
|
||||
}
|
||||
|
||||
Bit32u data;
|
||||
|
||||
// only reached when reading data register
|
||||
switch (ioregsel) {
|
||||
case 0x00: // APIC ID, note this is 4bits, the upper 4 are reserved
|
||||
*data = ((id & APIC_ID_MASK) << 24);
|
||||
return;
|
||||
data = ((id & APIC_ID_MASK) << 24);
|
||||
break;
|
||||
case 0x01: // version
|
||||
*data = BX_IOAPIC_VERSION_ID;
|
||||
return;
|
||||
data = BX_IOAPIC_VERSION_ID;
|
||||
break;
|
||||
case 0x02:
|
||||
BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
|
||||
*data = 0;
|
||||
return;
|
||||
data = 0;
|
||||
break;
|
||||
default:
|
||||
int index = (ioregsel - 0x10) >> 1;
|
||||
if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
|
||||
bx_io_redirect_entry_t *entry = ioredtbl + index;
|
||||
*data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
|
||||
return;
|
||||
data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
|
||||
break;
|
||||
}
|
||||
BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
|
||||
@ -262,6 +279,7 @@ void bx_ioapic_c::service_ioapic()
|
||||
void bx_ioapic_c::register_state(void)
|
||||
{
|
||||
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "ioapic", "IOAPIC State", 4);
|
||||
|
||||
BXRS_HEX_PARAM_SIMPLE(list, ioregsel);
|
||||
BXRS_HEX_PARAM_SIMPLE(list, intin);
|
||||
BXRS_HEX_PARAM_SIMPLE(list, irr);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: ioapic.h,v 1.29 2009-02-08 09:05:52 vruppert Exp $
|
||||
// $Id: ioapic.h,v 1.30 2009-02-18 22:25:04 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -73,8 +73,11 @@ public:
|
||||
void register_state(bx_param_c *parent);
|
||||
};
|
||||
|
||||
class bx_ioapic_c : public bx_generic_apic_c
|
||||
class bx_ioapic_c : public logfunctions
|
||||
{
|
||||
bx_phy_address base_addr;
|
||||
Bit32u id;
|
||||
|
||||
Bit32u ioregsel; // selects between various registers
|
||||
Bit32u intin;
|
||||
// interrupt request bitmask, not visible from the outside. Bits in the
|
||||
@ -88,14 +91,22 @@ class bx_ioapic_c : public bx_generic_apic_c
|
||||
|
||||
public:
|
||||
bx_ioapic_c();
|
||||
virtual ~bx_ioapic_c() {}
|
||||
virtual void init();
|
||||
virtual void reset(unsigned type);
|
||||
virtual void read_aligned(bx_phy_address address, Bit32u *data);
|
||||
virtual void write_aligned(bx_phy_address address, Bit32u *data);
|
||||
~bx_ioapic_c() {}
|
||||
|
||||
void init();
|
||||
void reset(unsigned type);
|
||||
|
||||
bx_phy_address get_base(void) const { return base_addr; }
|
||||
void set_id(Bit32u new_id) { id = new_id; }
|
||||
Bit32u get_id() const { return id; }
|
||||
|
||||
Bit32u read_aligned(bx_phy_address address);
|
||||
void write_aligned(bx_phy_address address, Bit32u *data);
|
||||
|
||||
void set_irq_level(Bit8u int_in, bx_bool level);
|
||||
void receive_eoi(Bit8u vector);
|
||||
void service_ioapic(void);
|
||||
|
||||
void register_state(void);
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: misc_mem.cc,v 1.124 2009-02-17 19:20:47 sshwarts Exp $
|
||||
// $Id: misc_mem.cc,v 1.125 2009-02-18 22:25:04 sshwarts Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -75,7 +75,7 @@ void BX_MEM_C::init_memory(Bit32u memsize)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.124 2009-02-17 19:20:47 sshwarts Exp $"));
|
||||
BX_DEBUG(("Init $Id: misc_mem.cc,v 1.125 2009-02-18 22:25:04 sshwarts Exp $"));
|
||||
|
||||
if (BX_MEM_THIS actual_vector != NULL) {
|
||||
BX_INFO (("freeing existing memory vector"));
|
||||
@ -514,8 +514,7 @@ Bit8u *BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, bx_phy_address a20Addr, unsigned
|
||||
{
|
||||
#if BX_SUPPORT_APIC
|
||||
if (cpu != NULL) {
|
||||
bx_generic_apic_c *lapic = &cpu->lapic;
|
||||
if (lapic->get_base() == (a20Addr & ~0xfff))
|
||||
if (cpu->lapic.is_selected(a20Addr))
|
||||
return(NULL); // Vetoed! APIC address space
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user