Applied, thanks!
David Bidner, le ven. 06 nov. 2026 11:57:23 +0100, a ecrit:
> The SMP AP bring-up used the ICR "all excluding self" shorthand for the
> INIT assert/deassert and the two STARTUP IPIs. Some hypervisors reject
> that broadcast shorthand (bhyve returns an error on the ICR write and
> aborts the VM), and it is not the documented per-AP INIT/SIPI sequence.
>
> Send INIT (assert then deassert) and two STARTUP IPIs targeted at each
> AP's APIC ID taken from the MADT, with STARTUP level asserted.
>
> No other change to the AP bring-up path.
>
> Tested in QEMU/NVMM on current master with "i386: allocate AP
> descriptor tables before starting secondary CPUs" applied (sent
> separately; without it the APs corrupt kernel memory once they run),
> i386 PAE: -smp 1, 2 and 4 boot, with --enable-ncpus=4 all APs come
> online, and 300 s runs of a heavy load (apt-get update plus three
> parallel 200 MB downloads) are clean. Earlier, on b46c2dfa, it was
> also tested in QEMU TCG and with x86_64 guests: with --enable-ncpus=2
> and -smp 4 the guest boots once instead of resetting in a loop.
> ---
> i386/i386/smp.c | 36 ++++++++++++++++++++++++------------
> 1 file changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/i386/i386/smp.c b/i386/i386/smp.c
> index 6b610020..510fd4cb 100644
> --- a/i386/i386/smp.c
> +++ b/i386/i386/smp.c
> @@ -85,7 +85,7 @@ wait_for_ipi(void)
> }
>
> static int
> -smp_send_ipi_init(int bsp_apic_id)
> +smp_send_ipi_init(int apic_id)
> {
> int err;
>
> @@ -94,9 +94,10 @@ smp_send_ipi_init(int bsp_apic_id)
>
> /* Assert INIT IPI:
> *
> - * This is EDGE triggered to match the deassert
> + * This is EDGE triggered to match the deassert, and is targeted at one
> + * AP by its APIC ID rather than broadcast.
> */
> - apic_send_ipi(ALL_EXCLUDING_SELF, INIT, PHYSICAL, ASSERT, EDGE, 0,
> bsp_apic_id);
> + apic_send_ipi(NO_SHORTHAND, INIT, PHYSICAL, ASSERT, EDGE, 0, apic_id);
>
> /* Wait for delivery */
> wait_for_ipi();
> @@ -108,7 +109,7 @@ smp_send_ipi_init(int bsp_apic_id)
> * that does not support STARTUP IPIs at all, and instead jump
> * via a warm reset vector.
> */
> - apic_send_ipi(ALL_EXCLUDING_SELF, INIT, PHYSICAL, DE_ASSERT, EDGE, 0,
> bsp_apic_id);
> + apic_send_ipi(NO_SHORTHAND, INIT, PHYSICAL, DE_ASSERT, EDGE, 0, apic_id);
>
> /* Wait for delivery */
> wait_for_ipi();
> @@ -121,7 +122,7 @@ smp_send_ipi_init(int bsp_apic_id)
> }
>
> static int
> -smp_send_ipi_startup_twice(int bsp_apic_id, int vector)
> +smp_send_ipi_startup_twice(int apic_id, int vector)
> {
> int i, accept_err, send_err;
> volatile int err;
> @@ -137,7 +138,7 @@ smp_send_ipi_startup_twice(int bsp_apic_id, int vector)
> * Have not seen any documentation for trigger mode for this IPI
> * but it seems to work with EDGE. (AMD BKDG FAM16h document
> specifies dont care)
> */
> - apic_send_ipi(ALL_EXCLUDING_SELF, STARTUP, PHYSICAL, DE_ASSERT,
> EDGE, vector, bsp_apic_id);
> + apic_send_ipi(NO_SHORTHAND, STARTUP, PHYSICAL, ASSERT, EDGE, vector,
> apic_id);
>
> pit_udelay(10);
>
> @@ -166,6 +167,8 @@ smp_send_ipi_startup_twice(int bsp_apic_id, int vector)
> int smp_startup_cpus(unsigned bsp_apic_id, phys_addr_t start_eip)
> {
> int err;
> + uint8_t ncpus;
> + int cpu;
> #if 0
> /* This block goes with a legacy method of INIT that only works with
> * old hardware that does not support SIPIs.
> @@ -190,12 +193,21 @@ int smp_startup_cpus(unsigned bsp_apic_id, phys_addr_t
> start_eip)
>
> printf("Sending IPIs from BSP APIC ID %u...\n", bsp_apic_id);
>
> - smp_send_ipi_init(bsp_apic_id);
> - err = smp_send_ipi_startup_twice(bsp_apic_id, start_eip >>
> STARTUP_VECTOR_SHIFT);
> - if (err) {
> - printf("FATAL: APs failed to start\n");
> - while(1) {
> - cpu_pause();
> + /* Target each AP from the MADT individually. The previous broadcast
> + * "all excluding self" shorthand is rejected by some hypervisors
> + * (bhyve) and is not the documented per-AP INIT/SIPI sequence. */
> + ncpus = apic_get_numcpus();
> + for (cpu = 0; cpu < ncpus; cpu++) {
> + int apic_id = apic_get_cpu_apic_id(cpu);
> + if (apic_id < 0 || apic_id == (int)bsp_apic_id)
> + continue;
> + smp_send_ipi_init(apic_id);
> + err = smp_send_ipi_startup_twice(apic_id, start_eip >>
> STARTUP_VECTOR_SHIFT);
> + if (err) {
> + printf("FATAL: AP %d failed to start\n", cpu);
> + while(1) {
> + cpu_pause();
> + }
> }
> }
> printf("done\n");
> --
> 2.47.3
>
>
--
Samuel
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://neuneu.mine.nu> : Le neueuttoyage par le vide -+-