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 -+-

Reply via email to