Applied, thanks!
David Bidner, le ven. 06 nov. 2026 12:36:08 +0100, a ecrit:
> Each AP called mp_desc_init() from cpu_setup(), which took the AP's
> descriptor table (GDT, LDT, IDT and TSS) from init_alloc_aligned().
> That is the boot allocator; once the VM system is up it no longer owns
> any memory, so the AP wrote its table into pages the kernel had
> already handed out.
>
> Allocate the tables with kmem_alloc_wired() in start_other_cpus(),
> before any AP is started, and let the APs only pick up their table.
>
> mp_desc_init() uses its argument only as the index of the CPU whose
> tables it sets up and reads no per-CPU state, so it can run on the BSP
> before the AP reaches init_percpu().
>
> When the APs start, the old code corrupted pv_head_table in a guest
> with 2 GiB of RAM (38 bad entries at -smp 2, 114 at -smp 4, in a
> QEMU/NVMM i386 PAE guest) and ended in a pmap fault or hang under
> memory pressure within a minute at -smp 4. With this change the
> table is intact and 300 s runs of the same load (apt-get update plus
> three parallel 200 MB downloads) are clean.
> ---
> Changes in v2:
> - Commit message only: state that mp_desc_init() uses its argument only
> as the index of the CPU whose tables it sets up, so it can run on the
> BSP before the AP reaches init_percpu() (asked by Alperen Erkan).
> The code is unchanged from v1.
>
> i386/i386/mp_desc.c | 17 ++++++++++++-----
> i386/i386/mp_desc.h | 2 +-
> 2 files changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
> index 1343861c..8f2589b3 100644
> --- a/i386/i386/mp_desc.c
> +++ b/i386/i386/mp_desc.c
> @@ -151,11 +151,15 @@ mp_desc_init(int mycpu)
> }
> else {
> /*
> - * Allocate tables for other CPUs
> + * The BSP allocates AP tables after VM initialization, before
> + * starting the APs. The boot allocator no longer owns these
> + * pages and must not be used here.
> */
> - if (!init_alloc_aligned(sizeof(struct mp_desc_table), &mem))
> + if (kmem_alloc_wired(kernel_map, &mem,
> + round_page(sizeof(struct mp_desc_table)))
> + != KERN_SUCCESS)
> panic("not enough memory for descriptor tables");
> - mpt = (struct mp_desc_table *)phystokv(mem);
> + mpt = (struct mp_desc_table *)mem;
>
> mp_desc_table[mycpu] = mpt;
> mp_ktss[mycpu] = &mpt->ktss;
> @@ -236,8 +240,7 @@ cpu_setup(int cpu)
> printf("AP=(%u) paging done\n", cpu);
>
> init_percpu(cpu);
> - mp_desc_init(cpu);
> - printf("AP=(%u) mpdesc done\n", cpu);
> + assert(mp_desc_table[cpu] != NULL);
>
> ap_gdt_init(cpu);
> printf("AP=(%u) gdt done\n", cpu);
> @@ -283,6 +286,10 @@ start_other_cpus(void)
> if (ncpus == 1)
> return;
>
> + /* Allocate while the BSP can use the VM allocator and before APs run.
> */
> + for (int cpu = 1; cpu < ncpus; cpu++)
> + mp_desc_init(cpu);
> +
> //Copy cpu initialization assembly routine
> #ifdef __i386__
> memcpy((void*) phystokv(apboot_addr), (void*) &apboot,
> diff --git a/i386/i386/mp_desc.h b/i386/i386/mp_desc.h
> index 92790171..2adce2b0 100644
> --- a/i386/i386/mp_desc.h
> +++ b/i386/i386/mp_desc.h
> @@ -75,7 +75,7 @@ extern struct real_descriptor *mp_gdt[NCPUS];
> extern uint8_t solid_intstack[];
>
> /*
> - * Each CPU calls this routine to set up its descriptor tables.
> + * The BSP calls this routine to set up each CPU's descriptor tables.
> */
> extern int mp_desc_init(int);
>
> --
> 2.49.0
>
>
--
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 -+-