On Sun, Aug 20, 2023 at 10:39:46PM -0500, Scott Cheloha wrote: > pOn amd64 we lie about the interrupts established during > i8254_initclocks(). We claim they are MP-safe in order to mollify a > KASSERT in intr_establish() and continue booting. > > See amd64/isa/clock.c: > 279 void > 280 i8254_initclocks(void) > 281 { > 282 i8254_inittimecounter(); /* hook the interrupt-based > i8254 tc */ > 283 > 284 stathz = 128; > 285 profhz = 1024; /* XXX does not divide into 1 billion > */ > 286 clockintr_init(0); > 287 > 288 clockintr_cpu_init(NULL); > 289 > 290 /* > 291 * While the clock interrupt handler isn't really MPSAFE, the > 292 * i8254 can't really be used as a clock on a true MP system. > 293 */ > 294 isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK | IPL_MPSAFE, > 295 clockintr, 0, "clock"); > 296 isa_intr_establish(NULL, 8, IST_PULSE, IPL_STATCLOCK | > IPL_MPSAFE, > 297 rtcintr, 0, "rtc"); > > and amd64/amd64/intr.c: > > 332 void * > 333 intr_establish(int legacy_irq, struct pic *pic, int pin, int type, > int level, > 334 struct cpu_info *ci, int (*handler)(void *), void *arg, const > char *what) > 335 { > 336 struct intrhand **p, *q, *ih; > 337 int slot, error, idt_vec; > 338 struct intrsource *source; > 339 struct intrstub *stubp; > 340 int flags; > 341 > 342 #ifdef DIAGNOSTIC > 343 if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15)) > 344 panic("intr_establish: bad legacy IRQ value"); > 345 > 346 if (legacy_irq == -1 && pic == &i8259_pic) > 347 panic("intr_establish: non-legacy IRQ on i8259"); > 348 #endif > 349 > 350 flags = level & IPL_MPSAFE; > 351 level &= ~IPL_MPSAFE; > 352 > 353 KASSERT(level <= IPL_TTY || level >= IPL_CLOCK || flags & > IPL_MPSAFE); > > Can we do the same on i386? I'm trying to test the i8254 path on > modern hardware and I'm tripping the equivalent KASSERT in > apic_intr_establish(). > > See i386/i386/ioapic.c: > > 661 void * > 662 apic_intr_establish(int irq, int type, int level, int (*ih_fun)(void > *), > 663 void *ih_arg, const char *ih_what) > 664 { > 665 unsigned int ioapic = APIC_IRQ_APIC(irq); > 666 unsigned int intr = APIC_IRQ_PIN(irq); > 667 struct ioapic_softc *sc = ioapic_find(ioapic); > 668 struct ioapic_pin *pin; > 669 struct intrhand **p, *q, *ih; > 670 extern int cold; > 671 int minlevel, maxlevel; > 672 extern void intr_calculatemasks(void); /* XXX */ > 673 int flags; > 674 > 675 flags = level & IPL_MPSAFE; > 676 level &= ~IPL_MPSAFE; > 677 > 678 KASSERT(level <= IPL_TTY || flags & IPL_MPSAFE); > > The patch below lets me test the i8254 clockintr path on modern > hardware in 32-bit mode without needing to rototill the GENERIC > config to delete all the things that implicitly depend upon the > ioapic. > > I don't think lying in this case is harmful. We can only get to > i8254_initclocks() if we have no local APIC, or if > lapic_calibrate_timer() fails. > > ok? > > Index: clock.c > =================================================================== > RCS file: /cvs/src/sys/arch/i386/isa/clock.c,v > retrieving revision 1.65 > diff -u -p -r1.65 clock.c > --- clock.c 25 Jul 2023 18:16:20 -0000 1.65 > +++ clock.c 21 Aug 2023 03:26:39 -0000 > @@ -431,9 +431,9 @@ i8254_initclocks(void) > clockintr_cpu_init(NULL); > > /* When using i8254 for clock, we also use the rtc for profclock */ > - (void)isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK, > + (void)isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK | IPL_MPSAFE, > clockintr, 0, "clock"); > - (void)isa_intr_establish(NULL, 8, IST_PULSE, IPL_STATCLOCK, > + (void)isa_intr_establish(NULL, 8, IST_PULSE, IPL_STATCLOCK | IPL_MPSAFE, > rtcintr, 0, "rtc"); > > rtcstart(); /* start the mc146818 clock */
I think this is fine. I tried to come up with a scenario where you'd be doing smp i386 without a local apic and even the ancient 82489 (for 80486 systems) acted as a lapic. And since we don't run on real 80386 anymore, I think we can ignore someone trying to do smp there. ok mlarkin if it makes your work easier.