IO APIC read write inconsistent problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
yuq
Posts: 17
Joined: Tue Jan 11, 2011 2:06 am

IO APIC read write inconsistent problem

Post by yuq »

Hi, guys. I'm writing IOAPIC code. I follow every guide I can get but I have some problem:
I write 0x0100000000000022 to IOAPIC redirect table register pin2, it seems work because the CPU get correct interrupt. But when I read it out, it becomes 0x0010000000100000 0x0000002200000022, the value shift to pin3 and double the first 32bit value. If I read the value twice, it won't shift to pin3 but still double 32bit.
My code:

Code: Select all

static inline unsigned int ioapic_read(unsigned int reg)
{
    writel(IOAPIC_BASE+IOAPIC_IOREGSEL, reg);
    return readl(IOAPIC_BASE+IOAPIC_IOWIN);
}

static inline void ioapic_write(unsigned int reg, unsigned int value)
{
    writel(IOAPIC_BASE+IOAPIC_IOREGSEL, reg);
    writel(IOAPIC_BASE+IOAPIC_IOWIN, value);
}

uint64_t get_ioapic_entry(int irq)
{
    uint64_t ret;

    ret = ioapic_read(IOAPIC_IOREDTBL + 2*irq + 1);
    ret <<= 32;
    ret |= ioapic_read(IOAPIC_IOREDTBL+2*irq);
    return ret;
}

void set_ioapic_entry(int irq, int level, int share)
{
    unsigned int h, l;

    // if share is true, broadcast the interrupt
    if (share)
	h = 0xff000000;
    else
	h = 0x01000000;

    // physical destination mode, fixed delivery mode
    if (level)
	l = 0x0000a000;
    else
	l = 0;

    ioapic_write(IOAPIC_IOREDTBL + 2*irq + 1, h);
    ioapic_write(IOAPIC_IOREDTBL + 2*irq, l + T_IRQ + irq);
}

the print code:
 cprintf("\n======== IOAPIC interrupt redirect table =========\n");
    for (i=0; i<24; i++) {
	//get_ioapic_entry(i);
	//get_ioapic_entry(i);
	cprintf("%02d:%016llx ", i, get_ioapic_entry(i));
	if (((i+1)%4) == 0)
	    cprintf("\n");
    }
help me!! [-o<

EDIT: Brendan added code tags..
yuq
Posts: 17
Joined: Tue Jan 11, 2011 2:06 am

Re: IO APIC read write inconsistent problem

Post by yuq »

I find why:
the writel and readl inline function is optimized by gcc.

Code: Select all

static __inline uint32_t readl(uint32_t addr)
{
    return *(uint32_t *)(addr);
}
static __inline void writel(uint32_t addr, uint32_t data)
{
    *(uint32_t *)(addr) = data;
}
I'm trying to find how to volatile this.

EDIT: Brendan added code tags
User avatar
Darwish
Posts: 21
Joined: Sat Oct 17, 2009 4:32 am

Re: IO APIC read write inconsistent problem

Post by Darwish »

yuq wrote:I find why:
the writel and readl inline function is optimized by gcc.
...
I'm trying to find how to volatile this.
The wiki doesn't bite; what you need to know is already covered in the Apic article. Good luck.
For latest news, please check my homepage and my blog.
—Darwish
Post Reply