write to apic must be 16-byte aligned

This commit is contained in:
Stanislav Shwartsman 2009-02-03 20:42:15 +00:00
parent 8b608fe045
commit 7d5e058dfe
4 changed files with 19 additions and 36 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.cc,v 1.115 2009-02-03 19:25:37 sshwarts Exp $
// $Id: apic.cc,v 1.116 2009-02-03 20:42:15 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
@ -221,33 +221,17 @@ void bx_generic_apic_c::read(bx_phy_address addr, void *data, unsigned len)
void bx_generic_apic_c::write(bx_phy_address addr, void *data, unsigned len)
{
if((addr & ~0x3) != ((addr+len-1) & ~0x3)) {
BX_PANIC(("APIC write at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", addr));
if (len != 4) {
BX_PANIC(("APIC write with len=%d (should be 4)", len));
return;
}
bx_phy_address addr_aligned = addr & ~0x3;
if(len == 4) { // must be 32-bit aligned
write_aligned(addr_aligned, (Bit32u*) data);
if(addr & 0xf) {
BX_PANIC(("APIC write at unaligned address 0x" FMT_PHY_ADDRX, addr));
return;
}
// partial write to the apic register, need to update some bytes
// and do not touch the others, i.e. to do RMW operation
Bit32u value;
read_aligned(addr_aligned, &value); // apic read has no side effects
// handle partial write, independent of endian-ness
unsigned shift = (addr&3)*8;
if (len == 1) {
value &= ~(0xff << shift);
value |= (*((Bit8u *) data) << shift);
}
else if (len == 2) {
value &= ~(0xffff << shift);
value |= (*((Bit16u *)data) << shift);
}
else {
BX_PANIC(("Unsupported APIC write at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len));
}
write_aligned(addr_aligned, &value);
write_aligned(addr, (Bit32u*) data);
}
bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu)
@ -325,10 +309,8 @@ void bx_local_apic_c::set_id(Bit8u newid)
} else {
BX_INFO(("naming convention for apics requires id=0-%d only", APIC_MAX_ID));
}
if(BX_CPU_LEVEL<2)
BX_INFO(("8086"));
else
BX_INFO(("80%d86", BX_CPU_LEVEL));
BX_INFO(("80%d86", BX_CPU_LEVEL));
}
// APIC write: 4 byte write to 16-byte aligned APIC address

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: apic.h,v 1.39 2009-01-16 18:18:58 sshwarts Exp $
// $Id: apic.h,v 1.40 2009-02-03 20:42:15 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002 Zwane Mwaikambo, Stanislav Shwartsman
@ -48,10 +48,10 @@ public:
void set_id(Bit8u newid);
Bit8u get_id() const { return id; }
bx_bool is_selected(bx_phy_address addr, unsigned len);
void read(bx_phy_address addr, void *data, unsigned len);
virtual void read_aligned(bx_phy_address address, Bit32u *data) = 0;
void write(bx_phy_address address, void *value, unsigned len);
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

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.cc,v 1.42 2009-02-03 19:12:00 sshwarts Exp $
// $Id: ioapic.cc,v 1.43 2009-02-03 20:42:15 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -46,7 +46,7 @@ static bx_bool ioapic_write(bx_phy_address a20addr, unsigned len, void *data, vo
return 1;
}
if(a20addr & 3) {
if(a20addr & 0xf) {
BX_PANIC(("I/O apic write at unaligned address 0x" FMT_PHY_ADDRX, a20addr));
return 1;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.h,v 1.26 2008-11-17 20:06:16 sshwarts Exp $
// $Id: ioapic.h,v 1.27 2009-02-03 20:42:15 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -82,8 +82,9 @@ class bx_ioapic_c : public bx_generic_apic_c
// It's not clear if this is how the real device works.
Bit32u irr;
public:
bx_io_redirect_entry_t ioredtbl[BX_IOAPIC_NUM_PINS]; // table of redirections
public:
bx_ioapic_c();
virtual ~bx_ioapic_c() {}
virtual void init();
@ -93,7 +94,7 @@ public:
void set_irq_level(Bit8u int_in, bx_bool level);
void receive_eoi(Bit8u vector);
void service_ioapic(void);
virtual void register_state(void);
void register_state(void);
};
#endif