Hello, David Bidner, le mer. 07 oct. 2026 05:21:39 +0200, a ecrit: > When an AP starts, apboot32 loads the null IDT with > > mov apboot_idt_ptr, %ebx > lidt (%ebx) > > The first instruction loads the contents of apboot_idt_ptr, which is zero, > so lidt then loads the pseudo-descriptor from DS:0. The AP is running with > the early per-CPU segment base of -KERNELBASE (0x40000000), so that is > linear address 0x40000000, i.e. physical address 0x40000000. > > That physical address is RAM only when the guest has more than 1 GiB. On a > two-CPU i386 PAE machine with 512 or 1024 MiB it is the start of the PCI > hole, the AP never retires lidt, and the BSP spins forever in the unbounded > "Waiting for AP 1" loop in mp_desc.c. With 1280 MiB or more the read lands > in RAM and the AP happens to continue. > > Load the address instead, matching the amd64 path: > > movl $apboot_idt_ptr, %ebx > lidt (%ebx) > > so that the null pseudo-descriptor (limit 0, base 0) is read from > apboot_idt_ptr itself.
Heh! Nice typo :) Thanks for noticing, Samuel > Tested by booting a two-CPU i386 PAE QEMU/KVM guest at 512, 1024 and > 1536 MiB: before this change the 512 and 1024 MiB guests hang in > "Waiting for AP 1", after it they reach userland with the AP online. A > single-CPU i386 guest and two-CPU amd64 guests at the same sizes are > unaffected. Only i386 PAE boot-to-userland was exercised; no long-running > behaviour was tested. > --- > i386/i386/cpuboot.S | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/i386/i386/cpuboot.S b/i386/i386/cpuboot.S > index fd3d6323..b939100a 100644 > --- a/i386/i386/cpuboot.S > +++ b/i386/i386/cpuboot.S > @@ -214,7 +214,7 @@ apboot32: > movw %ax, %gs > > /* Load null Interrupt descriptor table */ > - mov apboot_idt_ptr, %ebx > + movl $apboot_idt_ptr, %ebx > lidt (%ebx) > > /* Enable local apic in xAPIC mode */
