Page 1 of 1

Is IO wait necessary, when remapping IRQs on x86-64?

Posted: Fri Feb 07, 2025 12:05 pm
by sandras
From https://wiki.osdev.org/8259_PIC, regarding IRQ remapping:
Note the presence of io_wait() calls, on older machines its necessary to give the PIC some time to react to commands as they might not be processed quickly
I'm wondering, do I need to perform IO wait when remapping IRQs on x86-64?

Just saying "older machines" is vague. Perhaps we could clarify what it means in this context?

Re: Is IO wait necessary, when remapping IRQs on x86-64?

Posted: Fri Feb 07, 2025 1:47 pm
by Octocontrabass
It probably isn't necessary on any 64-bit PCs, but it's tough to know for sure without testing all of them.

Re: Is IO wait necessary, when remapping IRQs on x86-64?

Posted: Fri Feb 07, 2025 4:06 pm
by sandras
OK, I understand. I have a follow-up question, though.

In the wiki, there's this code example:

Code: Select all

/* reinitialize the PIC controllers, giving them specified vector offsets
   rather than 8h and 70h, as configured by default */

#define ICW1_ICW4	0x01		/* Indicates that ICW4 will be present */
#define ICW1_SINGLE	0x02		/* Single (cascade) mode */
#define ICW1_INTERVAL4	0x04		/* Call address interval 4 (8) */
#define ICW1_LEVEL	0x08		/* Level triggered (edge) mode */
#define ICW1_INIT	0x10		/* Initialization - required! */

#define ICW4_8086	0x01		/* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO	0x02		/* Auto (normal) EOI */
#define ICW4_BUF_SLAVE	0x08		/* Buffered mode/slave */
#define ICW4_BUF_MASTER	0x0C		/* Buffered mode/master */
#define ICW4_SFNM	0x10		/* Special fully nested (not) */

/*
arguments:
	offset1 - vector offset for master PIC
		vectors on the master become offset1..offset1+7
	offset2 - same for slave PIC: offset2..offset2+7
*/
void PIC_remap(int offset1, int offset2)
{
	uint8_t a1, a2;
	
	a1 = inb(PIC1_DATA);                        // save masks
	a2 = inb(PIC2_DATA);
	
	outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);  // starts the initialization sequence (in cascade mode)
	io_wait();
	outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
	io_wait();
	outb(PIC1_DATA, offset1);                 // ICW2: Master PIC vector offset
	io_wait();
	outb(PIC2_DATA, offset2);                 // ICW2: Slave PIC vector offset
	io_wait();
	outb(PIC1_DATA, 4);                       // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100)
	io_wait();
	outb(PIC2_DATA, 2);                       // ICW3: tell Slave PIC its cascade identity (0000 0010)
	io_wait();
	
	outb(PIC1_DATA, ICW4_8086);               // ICW4: have the PICs use 8086 mode (and not 8080 mode)
	io_wait();
	outb(PIC2_DATA, ICW4_8086);
	io_wait();
	
	outb(PIC1_DATA, a1);   // restore saved masks.
	outb(PIC2_DATA, a2);
}
Say I'm remapping IRQs right before loading IDT and enabling interrupts. Wouldn't it be more correct to also wait after "restoring saved masks"?

Re: Is IO wait necessary, when remapping IRQs on x86-64?

Posted: Fri Feb 07, 2025 5:49 pm
by Octocontrabass
Probably, yes, but in practice it doesn't seem to be necessary.

Also, you wouldn't want to restore the masks set by the firmware. I'm not sure why the wiki example does that.

Re: Is IO wait necessary, when remapping IRQs on x86-64?

Posted: Sat Feb 08, 2025 7:27 am
by sandras
I think I'll do what seems correct to me and wait after setting the masks too.

To me it seems that the wiki example tries to be general in nature - a function to remap IRQs at any time and restore the masks to their previous state, while everyone probably just remaps IRQs once at boot time, and sets the masks to known values once or twice during the run of the kernel. I'll try to simplify the masking in the wiki.