2003-06-24 22:59:52

by Randy.Dunlap

[permalink] [raw]
Subject: [PATCH] unexpected IO-APIC update


Hi,

Recently there has been a rash of Unexpected IO APIC reports on
the linux-smp mailing list. Most of the most recent ones are due
to some newer Intel chipsets (865, 875).

The IO APIC Version register doesn't indicate the differences in
these IO APICs.

I have an patch that addresses these chipsets. It has been
tested by a few people with good results and has been blessed
by Maciej Rozycki.

Other than conditionally decoding IO APIC registers 2 and 3,
we could alternately ignore them since Linux doesn't use the values
for anything other than printing them.

This patch ignores IO APIC register 2 if it's the same value as IO APIC
register 1. It also reads IO APIC register 3 if the IO APIC
version is >= 0x20, but some chipsets don't support this
register, so it is also ignored if its value if the same as IO APIC
register 1 or 2.

Another possible(?) alternative is to read the PID/VID of the
device to determine which registers it supports. However,
PCI devices have not been scanned at this point in init, so it
would require scanning PCI config space directly and I don't
yet see the point of doing that.

Oh, and the UNEXPECTED_IO_APIC() function doesn't print anything
in 2.5.current and I didn't change that.

Patch for 2.5.73 is below. Please apply.

--
~Randy
~ http://developer.osdl.org/rddunlap/ ~ http://www.xenotime.net/linux/ ~



patch_name: ioapic_update_2573.patch
patch_version: 2003-06-24.15:43:44
author: Randy.Dunlap <[email protected]>
description: support newer Intel chipset IO APICs;
product: Linux
product_versions: linux-2573
maintainer: Maciej W. Rozycki <[email protected]>
diffstat: =
arch/i386/kernel/io_apic.c | 26 +++++++++++++++++++++++++-
include/asm-i386/io_apic.h | 5 +++++
2 files changed, 30 insertions(+), 1 deletion(-)


diff -Naur ./include/asm-i386/io_apic.h~ioap ./include/asm-i386/io_apic.h
--- ./include/asm-i386/io_apic.h~ioap 2003-06-14 12:18:25.000000000 -0700
+++ ./include/asm-i386/io_apic.h 2003-06-14 20:17:44.000000000 -0700
@@ -44,6 +44,11 @@
__reserved_1 : 4;
} __attribute__ ((packed));

+struct IO_APIC_reg_03 {
+ __u32 boot_DT : 1,
+ __reserved_1 : 31;
+} __attribute__ ((packed));
+
/*
* # of IO-APICs and # of IRQ routing registers
*/
diff -Naur ./arch/i386/kernel/io_apic.c~ioap ./arch/i386/kernel/io_apic.c
--- ./arch/i386/kernel/io_apic.c~ioap 2003-06-14 12:18:06.000000000 -0700
+++ ./arch/i386/kernel/io_apic.c 2003-06-14 20:43:19.000000000 -0700
@@ -1275,6 +1278,7 @@
struct IO_APIC_reg_00 reg_00;
struct IO_APIC_reg_01 reg_01;
struct IO_APIC_reg_02 reg_02;
+ struct IO_APIC_reg_03 reg_03;
unsigned long flags;

printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1295,6 +1299,8 @@
*(int *)&reg_01 = io_apic_read(apic, 1);
if (reg_01.version >= 0x10)
*(int *)&reg_02 = io_apic_read(apic, 2);
+ if (reg_01.version >= 0x20)
+ *(int *)&reg_03 = io_apic_read(apic, 3);
spin_unlock_irqrestore(&ioapic_lock, flags);

printk("\n");
@@ -1332,13 +1336,31 @@
if (reg_01.__reserved_1 || reg_01.__reserved_2)
UNEXPECTED_IO_APIC();

- if (reg_01.version >= 0x10) {
+ /*
+ * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02,
+ * but the value of reg_02 is read as the previous read register
+ * value, so ignore it if reg_02 == reg_01.
+ */
+ if (reg_01.version >= 0x10 && *(int *)&reg_02 != *(int *)&reg_01) {
printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)&reg_02);
printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration);
if (reg_02.__reserved_1 || reg_02.__reserved_2)
UNEXPECTED_IO_APIC();
}

+ /*
+ * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02
+ * or reg_03, but the value of reg_0[23] is read as the previous read
+ * register value, so ignore it if reg_03 == reg_0[12].
+ */
+ if (reg_01.version >= 0x20 && *(int *)&reg_03 != *(int *)&reg_02 &&
+ *(int *)&reg_03 != *(int *)&reg_01) {
+ printk(KERN_DEBUG ".... register #03: %08X\n", *(int *)&reg_03);
+ printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.boot_DT);
+ if (reg_03.__reserved_1)
+ UNEXPECTED_IO_APIC();
+ }
+
printk(KERN_DEBUG ".... IRQ redirection table:\n");

printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"


2003-06-25 01:19:59

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] unexpected IO-APIC update


On Tue, 24 Jun 2003, Randy.Dunlap wrote:
>
> + if (reg_01.version >= 0x20)
> + *(int *)&reg_03 = io_apic_read(apic, 3);

There's a lot of these

*(int *)&reg_03

kinds of things there, and the fact is, gcc's alias analysis doesn't like
them, _and_ they are ugly.

The alias analysis I could care less about, since a good alias analysis
would take static address information into account, and gcc at least last
time I looked wasn't. So we don't even bother using it for now.

We may want to reconsider that eventually, though, since more recent
versions of gcc at least try to make their alias analysis useful with
things like "attribute((may_alias))" or whatever the syntax was.

But the ugliness part I care about, and I wonder if it wouldn't be better
in this case to just make the register definition a "union", and have
something like

union reg_03 {
u32 value;
struct {
u32 boot_DT:1,
reserved:31;
} bits;
};

and then you can avoid the ugly dereference/cast/address-of thing, and
just say

reg_03.value

or

reg_03.bits.boot_DT

which looks a lot cleaner.

This is what unions are _designed_ for.

Linus

2003-06-25 15:46:23

by Randy.Dunlap

[permalink] [raw]
Subject: Re: [PATCH] unexpected IO-APIC update

On Tue, 24 Jun 2003 18:31:12 -0700 (PDT) Linus Torvalds <[email protected]> wrote:

|
| On Tue, 24 Jun 2003, Randy.Dunlap wrote:
| >
| > + if (reg_01.version >= 0x20)
| > + *(int *)&reg_03 = io_apic_read(apic, 3);
|
| There's a lot of these
|
| *(int *)&reg_03
|
| kinds of things there, and the fact is, gcc's alias analysis doesn't like
| them, _and_ they are ugly.
|
[snippage]
|
| But the ugliness part I care about, and I wonder if it wouldn't be better
| in this case to just make the register definition a "union", and have
| something like
|
| union reg_03 {
| u32 value;
| struct {
| u32 boot_DT:1,
| reserved:31;
| } bits;
| };
|
| and then you can avoid the ugly dereference/cast/address-of thing, and
| just say
|
| reg_03.value
|
| or
|
| reg_03.bits.boot_DT
|
| which looks a lot cleaner.
|
| This is what unions are _designed_ for.

Sure, I'll do that.

--
~Randy
~ http://developer.osdl.org/rddunlap/ ~ http://www.xenotime.net/linux/ ~

2003-06-25 15:56:50

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [PATCH] unexpected IO-APIC update

On Wed, 25 Jun 2003, Randy.Dunlap wrote:

> | But the ugliness part I care about, and I wonder if it wouldn't be better
> | in this case to just make the register definition a "union", and have
> | something like
> |
> | union reg_03 {
> | u32 value;
> | struct {
> | u32 boot_DT:1,
> | reserved:31;
> | } bits;
> | };
[...]
> Sure, I'll do that.

Perhaps using "raw" instead of "value" would be prettier and certainly we
would save two characters per reference. ;-) Anyway, it's indeed a good
opportunity to do a clean-up while fiddling with these bits.

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +

2003-06-25 18:13:29

by Randy.Dunlap

[permalink] [raw]
Subject: [PATCH] IO-APIC unions

On Wed, 25 Jun 2003 18:11:06 +0200 (MET DST) "Maciej W. Rozycki" <[email protected]> wrote:

| On Wed, 25 Jun 2003, Randy.Dunlap wrote:
|
| > | But the ugliness part I care about, and I wonder if it wouldn't be better
| > | in this case to just make the register definition a "union", and have
| > | something like
| > |
| > | union reg_03 {
| > | u32 value;
| > | struct {
| > | u32 boot_DT:1,
| > | reserved:31;
| > | } bits;
| > | };
| [...]
| > Sure, I'll do that.
|
| Perhaps using "raw" instead of "value" would be prettier and certainly we
| would save two characters per reference. ;-) Anyway, it's indeed a good
| opportunity to do a clean-up while fiddling with these bits.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I prefer that name also. Patch is below.

Linus, this patch is on top of yesterday's patch (or on top of
today's -bk3 snapshot). Please apply. Builds and boots.


--
~Randy
~ http://developer.osdl.org/rddunlap/ ~ http://www.xenotime.net/linux/ ~


patch_name: ioapic_union.patch
patch_version: 2003-06-25.10:52:07
author: Randy.Dunlap <[email protected]>
description: use unions in IO APIC data structs;
product: Linux
product_versions: linux-2.5.73
maintainer: Maciej W. Rozycki <[email protected]>
diffstat: =
arch/i386/kernel/io_apic.c | 138 ++++++++++++++++++++++-----------------------
include/asm-i386/io_apic.h | 58 +++++++++++-------
2 files changed, 104 insertions(+), 92 deletions(-)


diff -Naur ./arch/i386/kernel/io_apic.c~union ./arch/i386/kernel/io_apic.c
--- ./arch/i386/kernel/io_apic.c~union 2003-06-25 10:51:59.000000000 -0700
+++ ./arch/i386/kernel/io_apic.c 2003-06-25 10:50:00.000000000 -0700
@@ -1272,10 +1272,10 @@
void __init print_IO_APIC(void)
{
int apic, i;
- struct IO_APIC_reg_00 reg_00;
- struct IO_APIC_reg_01 reg_01;
- struct IO_APIC_reg_02 reg_02;
- struct IO_APIC_reg_03 reg_03;
+ union IO_APIC_reg_00 reg_00;
+ union IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_02 reg_02;
+ union IO_APIC_reg_03 reg_03;
unsigned long flags;

printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
@@ -1292,47 +1292,47 @@
for (apic = 0; apic < nr_ioapics; apic++) {

spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_00 = io_apic_read(apic, 0);
- *(int *)&reg_01 = io_apic_read(apic, 1);
- if (reg_01.version >= 0x10)
- *(int *)&reg_02 = io_apic_read(apic, 2);
- if (reg_01.version >= 0x20)
- *(int *)&reg_03 = io_apic_read(apic, 3);
+ reg_00.raw = io_apic_read(apic, 0);
+ reg_01.raw = io_apic_read(apic, 1);
+ if (reg_01.bits.version >= 0x10)
+ reg_02.raw = io_apic_read(apic, 2);
+ if (reg_01.bits.version >= 0x20)
+ reg_03.raw = io_apic_read(apic, 3);
spin_unlock_irqrestore(&ioapic_lock, flags);

printk("\n");
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
- printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)&reg_00);
- printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID);
- printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type);
- printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS);
- if (reg_00.ID >= APIC_BROADCAST_ID)
+ printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
+ printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID);
+ printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type);
+ printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS);
+ if (reg_00.bits.ID >= APIC_BROADCAST_ID)
UNEXPECTED_IO_APIC();
- if (reg_00.__reserved_1 || reg_00.__reserved_2)
+ if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2)
UNEXPECTED_IO_APIC();

- printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
- printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries);
- if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */
- (reg_01.entries != 0x17) && /* typical ISA+PCI boards */
- (reg_01.entries != 0x1b) && /* Compaq Proliant boards */
- (reg_01.entries != 0x1f) && /* dual Xeon boards */
- (reg_01.entries != 0x22) && /* bigger Xeon boards */
- (reg_01.entries != 0x2E) &&
- (reg_01.entries != 0x3F)
+ printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw);
+ printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries);
+ if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */
+ (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */
+ (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */
+ (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */
+ (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */
+ (reg_01.bits.entries != 0x2E) &&
+ (reg_01.bits.entries != 0x3F)
)
UNEXPECTED_IO_APIC();

- printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ);
- printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version);
- if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */
- (reg_01.version != 0x10) && /* oldest IO-APICs */
- (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
- (reg_01.version != 0x13) && /* Xeon IO-APICs */
- (reg_01.version != 0x20) /* Intel P64H (82806 AA) */
+ printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ);
+ printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version);
+ if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */
+ (reg_01.bits.version != 0x10) && /* oldest IO-APICs */
+ (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */
+ (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */
+ (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */
)
UNEXPECTED_IO_APIC();
- if (reg_01.__reserved_1 || reg_01.__reserved_2)
+ if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2)
UNEXPECTED_IO_APIC();

/*
@@ -1340,10 +1340,10 @@
* but the value of reg_02 is read as the previous read register
* value, so ignore it if reg_02 == reg_01.
*/
- if (reg_01.version >= 0x10 && *(int *)&reg_02 != *(int *)&reg_01) {
- printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)&reg_02);
- printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration);
- if (reg_02.__reserved_1 || reg_02.__reserved_2)
+ if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) {
+ printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw);
+ printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration);
+ if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2)
UNEXPECTED_IO_APIC();
}

@@ -1352,11 +1352,11 @@
* or reg_03, but the value of reg_0[23] is read as the previous read
* register value, so ignore it if reg_03 == reg_0[12].
*/
- if (reg_01.version >= 0x20 && *(int *)&reg_03 != *(int *)&reg_02 &&
- *(int *)&reg_03 != *(int *)&reg_01) {
- printk(KERN_DEBUG ".... register #03: %08X\n", *(int *)&reg_03);
- printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.boot_DT);
- if (reg_03.__reserved_1)
+ if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw &&
+ reg_03.raw != reg_01.raw) {
+ printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw);
+ printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT);
+ if (reg_03.bits.__reserved_1)
UNEXPECTED_IO_APIC();
}

@@ -1365,7 +1365,7 @@
printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol"
" Stat Dest Deli Vect: \n");

- for (i = 0; i <= reg_01.entries; i++) {
+ for (i = 0; i <= reg_01.bits.entries; i++) {
struct IO_APIC_route_entry entry;

spin_lock_irqsave(&ioapic_lock, flags);
@@ -1546,7 +1546,7 @@

static void __init enable_IO_APIC(void)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
int i;
unsigned long flags;

@@ -1563,9 +1563,9 @@
*/
for (i = 0; i < nr_ioapics; i++) {
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_01 = io_apic_read(i, 1);
+ reg_01.raw = io_apic_read(i, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[i] = reg_01.entries+1;
+ nr_ioapic_registers[i] = reg_01.bits.entries+1;
}

/*
@@ -1597,7 +1597,7 @@
#ifndef CONFIG_X86_NUMAQ
static void __init setup_ioapic_ids_from_mpc(void)
{
- struct IO_APIC_reg_00 reg_00;
+ union IO_APIC_reg_00 reg_00;
unsigned long phys_id_present_map;
int apic;
int i;
@@ -1617,7 +1617,7 @@

/* Read the register 0 value */
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_00 = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(apic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);

old_id = mp_ioapics[apic].mpc_apicid;
@@ -1626,8 +1626,8 @@
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
apic, mp_ioapics[apic].mpc_apicid);
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
- reg_00.ID);
- mp_ioapics[apic].mpc_apicid = reg_00.ID;
+ reg_00.bits.ID);
+ mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
}

/*
@@ -1671,18 +1671,18 @@
printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic].mpc_apicid);

- reg_00.ID = mp_ioapics[apic].mpc_apicid;
+ reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apic, 0, *(int *)&reg_00);
+ io_apic_write(apic, 0, reg_00.raw);
spin_unlock_irqrestore(&ioapic_lock, flags);

/*
* Sanity check
*/
spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_00 = io_apic_read(apic, 0);
+ reg_00.raw = io_apic_read(apic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);
- if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
+ if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
panic("could not set ID!\n");
else
printk(" ok.\n");
@@ -2220,7 +2220,7 @@

int __init io_apic_get_unique_id (int ioapic, int apic_id)
{
- struct IO_APIC_reg_00 reg_00;
+ union IO_APIC_reg_00 reg_00;
static unsigned long apic_id_map = 0;
unsigned long flags;
int i = 0;
@@ -2238,13 +2238,13 @@
apic_id_map = phys_cpu_present_map;

spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_00 = io_apic_read(ioapic, 0);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);

if (apic_id >= IO_APIC_MAX_ID) {
printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
- "%d\n", ioapic, apic_id, reg_00.ID);
- apic_id = reg_00.ID;
+ "%d\n", ioapic, apic_id, reg_00.bits.ID);
+ apic_id = reg_00.bits.ID;
}

/*
@@ -2269,16 +2269,16 @@

apic_id_map |= apicid_to_cpu_present(apic_id);

- if (reg_00.ID != apic_id) {
- reg_00.ID = apic_id;
+ if (reg_00.bits.ID != apic_id) {
+ reg_00.bits.ID = apic_id;

spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic, 0, *(int *)&reg_00);
- *(int *)&reg_00 = io_apic_read(ioapic, 0);
+ io_apic_write(ioapic, 0, reg_00.raw);
+ reg_00.raw = io_apic_read(ioapic, 0);
spin_unlock_irqrestore(&ioapic_lock, flags);

/* Sanity check */
- if (reg_00.ID != apic_id)
+ if (reg_00.bits.ID != apic_id)
panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
}

@@ -2290,27 +2290,27 @@

int __init io_apic_get_version (int ioapic)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
unsigned long flags;

spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_01 = io_apic_read(ioapic, 1);
+ reg_01.raw = io_apic_read(ioapic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);

- return reg_01.version;
+ return reg_01.bits.version;
}


int __init io_apic_get_redir_entries (int ioapic)
{
- struct IO_APIC_reg_01 reg_01;
+ union IO_APIC_reg_01 reg_01;
unsigned long flags;

spin_lock_irqsave(&ioapic_lock, flags);
- *(int *)&reg_01 = io_apic_read(ioapic, 1);
+ reg_01.raw = io_apic_read(ioapic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);

- return reg_01.entries;
+ return reg_01.bits.entries;
}


diff -Naur ./include/asm-i386/io_apic.h~union ./include/asm-i386/io_apic.h
--- ./include/asm-i386/io_apic.h~union 2003-06-24 13:44:21.000000000 -0700
+++ ./include/asm-i386/io_apic.h 2003-06-25 10:05:50.000000000 -0700
@@ -22,32 +22,44 @@
/*
* The structure of the IO-APIC:
*/
-struct IO_APIC_reg_00 {
- __u32 __reserved_2 : 14,
- LTS : 1,
- delivery_type : 1,
- __reserved_1 : 8,
- ID : 8;
-} __attribute__ ((packed));
+union IO_APIC_reg_00 {
+ u32 raw;
+ struct {
+ u32 __reserved_2 : 14,
+ LTS : 1,
+ delivery_type : 1,
+ __reserved_1 : 8,
+ ID : 8;
+ } __attribute__ ((packed)) bits;
+};

-struct IO_APIC_reg_01 {
- __u32 version : 8,
- __reserved_2 : 7,
- PRQ : 1,
- entries : 8,
- __reserved_1 : 8;
-} __attribute__ ((packed));
+union IO_APIC_reg_01 {
+ u32 raw;
+ struct {
+ u32 version : 8,
+ __reserved_2 : 7,
+ PRQ : 1,
+ entries : 8,
+ __reserved_1 : 8;
+ } __attribute__ ((packed)) bits;
+};

-struct IO_APIC_reg_02 {
- __u32 __reserved_2 : 24,
- arbitration : 4,
- __reserved_1 : 4;
-} __attribute__ ((packed));
+union IO_APIC_reg_02 {
+ u32 raw;
+ struct {
+ u32 __reserved_2 : 24,
+ arbitration : 4,
+ __reserved_1 : 4;
+ } __attribute__ ((packed)) bits;
+};

-struct IO_APIC_reg_03 {
- __u32 boot_DT : 1,
- __reserved_1 : 31;
-} __attribute__ ((packed));
+union IO_APIC_reg_03 {
+ u32 raw;
+ struct {
+ u32 boot_DT : 1,
+ __reserved_1 : 31;
+ } __attribute__ ((packed)) bits;
+};

/*
* # of IO-APICs and # of IRQ routing registers

2003-06-26 13:32:19

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [PATCH] IO-APIC unions

On Wed, 25 Jun 2003, Randy.Dunlap wrote:

> Linus, this patch is on top of yesterday's patch (or on top of
> today's -bk3 snapshot). Please apply. Builds and boots.

It looks OK for me -- thanks a lot for the boring work. My system is
still down, so I'll do a run-time test later.

--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +