Applied, thanks!

Mike Kelly, le dim. 25 oct. 2026 08:03:14 +0000, a ecrit:
> Some machines have a memory map showing 'reserved' memory regions
> spanning an entire memory segment. Currently this condition terminates
> memory mapping early which prevents higher segments from being
> considered during biosmem startup. This results in a failed assertion
> later on whilst booting the vm_page tables.
> ---
>  i386/i386at/biosmem.c |  24 +++------
>  vm/vm_page.c          | 116 +++++++++++++++++++++++-------------------
>  2 files changed, 72 insertions(+), 68 deletions(-)
> 
> diff --git a/i386/i386at/biosmem.c b/i386/i386at/biosmem.c
> index ce1fe9c7..b6887eff 100644
> --- a/i386/i386at/biosmem.c
> +++ b/i386/i386at/biosmem.c
> @@ -713,10 +713,8 @@ biosmem_bootstrap_common(void)
>      phys_end = VM_PAGE_DMA32_LIMIT;
>      error = biosmem_map_find_avail(&phys_start, &phys_end);
>  
> -    if (error)
> -        return;
> -
> -    biosmem_set_segment(VM_PAGE_SEG_DMA32, phys_start, phys_end);
> +    if (!error)
> +      biosmem_set_segment(VM_PAGE_SEG_DMA32, phys_start, phys_end);
>  
>      phys_start = VM_PAGE_DMA32_LIMIT;
>  #endif
> @@ -725,10 +723,8 @@ biosmem_bootstrap_common(void)
>      phys_end = VM_PAGE_DIRECTMAP_LIMIT;
>      error = biosmem_map_find_avail(&phys_start, &phys_end);
>  
> -    if (error)
> -        return;
> -
> -    biosmem_set_segment(VM_PAGE_SEG_DIRECTMAP, phys_start, phys_end);
> +    if (!error)
> +      biosmem_set_segment(VM_PAGE_SEG_DIRECTMAP, phys_start, phys_end);
>  
>      phys_start = VM_PAGE_DIRECTMAP_LIMIT;
>  
> @@ -737,10 +733,8 @@ biosmem_bootstrap_common(void)
>      phys_end = VM_PAGE_DMA32_LIMIT;
>      error = biosmem_map_find_avail(&phys_start, &phys_end);
>  
> -    if (error)
> -        return;
> -
> -    biosmem_set_segment(VM_PAGE_SEG_DMA32, phys_start, phys_end);
> +    if (!error)
> +      biosmem_set_segment(VM_PAGE_SEG_DMA32, phys_start, phys_end);
>  
>      phys_start = VM_PAGE_DMA32_LIMIT;
>  #endif
> @@ -749,10 +743,8 @@ biosmem_bootstrap_common(void)
>      phys_end = VM_PAGE_HIGHMEM_LIMIT;
>      error = biosmem_map_find_avail(&phys_start, &phys_end);
>  
> -    if (error)
> -        return;
> -
> -    biosmem_set_segment(VM_PAGE_SEG_HIGHMEM, phys_start, phys_end);
> +    if (!error)
> +      biosmem_set_segment(VM_PAGE_SEG_HIGHMEM, phys_start, phys_end);
>  }
>  
>  #ifdef MACH_HYP
> diff --git a/vm/vm_page.c b/vm/vm_page.c
> index f6f3981d..5d733120 100644
> --- a/vm/vm_page.c
> +++ b/vm/vm_page.c
> @@ -225,6 +225,7 @@ struct vm_page_seg {
>      phys_addr_t end;
>      struct vm_page *pages;
>      struct vm_page *pages_end;
> +    unsigned int type;
>      simple_lock_data_t lock;
>      struct vm_page_free_list free_lists[VM_PAGE_NR_FREE_LISTS];
>      unsigned long nr_free_pages;
> @@ -271,8 +272,31 @@ static int vm_page_is_ready __read_mostly;
>   * possible from the direct physical mapping, DMA and DMA32 are aliases for
>   * DIRECTMAP, in which case the segment table contains DIRECTMAP and HIGHMEM
>   * only.
> + *
> + * All elements of 'vm_page_boot_segs' are always valid. This is the
> + * case even if the machine's physical memory address range does not
> + * cover all segment types. Moreover, some machines have a memory map
> + * in which an intermediate segment has either no memory or no
> + * 'available' memory. vm_page_boot_seg_size() can be used to assess
> + * whether a given element has 'available' memory.
> + *
> + * 'vm_page_segs' only contains elements that have 'available'
> + * memory. 'vm_page_segs_size' can therefore be lower than
> + * VM_PAGE_MAX_SEGS even if the VM_PAGE_SEG_HIGHMEM segment is
> + * present. The index position in vm_page_segs therefore has no
> + * particular significance unlike vm_page_boot_segs.
> + *
> + * It is sometimes important to select free memory with a certain
> + * 'type'. The vm_page_segs_type_to_index array defines the
> + * appropriate mapping between segment type and index into
> + * 'vm_page_segs'. There are always VM_PAGE_MAX_SEGS defined by this
> + * array.
> + *
> + * Note that vm_page.seg_index is the index into vm_page_segs which is
> + * not necessarily the same as the segment 'type'.
>   */
>  static struct vm_page_seg vm_page_segs[VM_PAGE_MAX_SEGS];
> +static unsigned int vm_page_segs_type_to_index[VM_PAGE_MAX_SEGS];
>  
>  /*
>   * Bootstrap segment table.
> @@ -671,6 +695,7 @@ vm_page_seg_compute_pageout_thresholds(struct vm_page_seg 
> *seg)
>  
>  static void __init
>  vm_page_seg_init(struct vm_page_seg *seg, phys_addr_t start, phys_addr_t end,
> +              unsigned int seg_index,
>                   struct vm_page *pages)
>  {
>      phys_addr_t pa;
> @@ -679,6 +704,7 @@ vm_page_seg_init(struct vm_page_seg *seg, phys_addr_t 
> start, phys_addr_t end,
>  
>      seg->start = start;
>      seg->end = end;
> +    seg->type = seg_index;
>      pool_size = vm_page_seg_compute_pool_size(seg);
>  
>      for (i = 0; i < ARRAY_SIZE(seg->cpu_pools); i++)
> @@ -1460,7 +1486,6 @@ vm_page_load(unsigned int seg_index, phys_addr_t start, 
> phys_addr_t end)
>      assert(vm_page_aligned(start));
>      assert(vm_page_aligned(end));
>      assert(start < end);
> -    assert(vm_page_segs_size < ARRAY_SIZE(vm_page_boot_segs));
>  
>      seg = &vm_page_boot_segs[seg_index];
>      seg->start = start;
> @@ -1472,8 +1497,6 @@ vm_page_load(unsigned int seg_index, phys_addr_t start, 
> phys_addr_t end)
>             vm_page_seg_name(seg_index),
>             (unsigned long long)start, (unsigned long long)end);
>  #endif
> -
> -    vm_page_segs_size++;
>  }
>  
>  void
> @@ -1529,32 +1552,7 @@ vm_page_select_alloc_seg(unsigned int selector)
>          panic("vm_page: invalid selector");
>      }
>  
> -    return MIN(vm_page_segs_size - 1, seg_index);
> -}
> -
> -static int __init
> -vm_page_boot_seg_loaded(const struct vm_page_boot_seg *seg)
> -{
> -    return (seg->end != 0);
> -}
> -
> -static void __init
> -vm_page_check_boot_segs(void)
> -{
> -    unsigned int i;
> -    int expect_loaded;
> -
> -    if (vm_page_segs_size == 0)
> -        panic("vm_page: no physical memory loaded");
> -
> -    for (i = 0; i < ARRAY_SIZE(vm_page_boot_segs); i++) {
> -        expect_loaded = (i < vm_page_segs_size);
> -
> -        if (vm_page_boot_seg_loaded(&vm_page_boot_segs[i]) == expect_loaded)
> -            continue;
> -
> -        panic("vm_page: invalid boot segment table");
> -    }
> +    return vm_page_segs_type_to_index[seg_index];
>  }
>  
>  static phys_addr_t __init
> @@ -1576,8 +1574,8 @@ vm_page_bootalloc(size_t size)
>      phys_addr_t pa;
>      unsigned int i;
>  
> -    for (i = vm_page_select_alloc_seg(VM_PAGE_SEL_DIRECTMAP);
> -         i < vm_page_segs_size;
> +    for (i = VM_PAGE_SEG_DIRECTMAP;
> +         i < ARRAY_SIZE(vm_page_boot_segs);
>           i--) {
>          seg = &vm_page_boot_segs[i];
>  
> @@ -1602,8 +1600,6 @@ vm_page_setup(void)
>      unsigned int i;
>      phys_addr_t pa;
>  
> -    vm_page_check_boot_segs();
> -
>      list_init(&vm_page_active_lru_list.internal);
>      list_init(&vm_page_active_lru_list.external);
>      list_init(&vm_page_inactive_lru_list.internal);
> @@ -1614,9 +1610,12 @@ vm_page_setup(void)
>       */
>      nr_pages = 0;
>  
> -    for (i = 0; i < vm_page_segs_size; i++)
> +    for (i = 0; i < ARRAY_SIZE(vm_page_boot_segs); i++)
>          nr_pages += 
> vm_page_atop(vm_page_boot_seg_size(&vm_page_boot_segs[i]));
>  
> +    if (nr_pages == 0)
> +        panic("vm_page: no physical memory loaded");
> +
>      table_size = vm_page_round(nr_pages * sizeof(struct vm_page));
>      printf("vm_page: page table size: %lu entries (%luk)\n",
>          (unsigned long) nr_pages,
> @@ -1629,22 +1628,34 @@ vm_page_setup(void)
>       * the segments are initialized, all their pages are set allocated.
>       * Pages are then released, which populates the free lists.
>       */
> -    for (i = 0; i < vm_page_segs_size; i++) {
> -        seg = &vm_page_segs[i];
> +    for (i = 0; i < ARRAY_SIZE(vm_page_boot_segs); i++) {
>          boot_seg = &vm_page_boot_segs[i];
> -        vm_page_seg_init(seg, boot_seg->start, boot_seg->end, table);
> -        page = seg->pages + vm_page_atop(boot_seg->avail_start
> -                                         - boot_seg->start);
> -        end = seg->pages + vm_page_atop(boot_seg->avail_end
> -                                        - boot_seg->start);
> -
> -        while (page < end) {
> -            page->type = VM_PT_FREE;
> -            vm_page_seg_free_to_buddy(seg, page, 0);
> -            page++;
> -        }
>  
> -        table += vm_page_atop(vm_page_seg_size(seg));
> +        if (vm_page_boot_seg_size(boot_seg))
> +       {
> +         vm_page_segs_type_to_index[i] = vm_page_segs_size;
> +         seg = &vm_page_segs[vm_page_segs_size++];
> +         vm_page_seg_init(seg, boot_seg->start, boot_seg->end, i, table);
> +         page = seg->pages + vm_page_atop(boot_seg->avail_start
> +                                          - boot_seg->start);
> +         end = seg->pages + vm_page_atop(boot_seg->avail_end
> +                                         - boot_seg->start);
> +
> +         while (page < end) {
> +           page->type = VM_PT_FREE;
> +           vm_page_seg_free_to_buddy(seg, page, 0);
> +           page++;
> +         }
> +
> +         table += vm_page_atop(vm_page_seg_size(seg));
> +       }
> +     else
> +       {
> +         vm_page_segs_type_to_index[i] =
> +           (vm_page_segs_size != 0
> +            ? vm_page_segs_type_to_index[vm_page_segs_size - 1]
> +            : 0);
> +       }
>      }
>  
>      while (va < (unsigned long)table) {
> @@ -1827,10 +1838,10 @@ vm_page_info_all(void)
>          seg = &vm_page_segs[i];
>          pages = (unsigned long)(seg->pages_end - seg->pages);
>          printf("vm_page: %s: pages: %lu (%luM), free: %lu (%luM)\n",
> -               vm_page_seg_name(i), pages, pages >> (20 - PAGE_SHIFT),
> +               vm_page_seg_name(seg->type), pages, pages >> (20 - 
> PAGE_SHIFT),
>                 seg->nr_free_pages, seg->nr_free_pages >> (20 - PAGE_SHIFT));
>          printf("vm_page: %s: min:%lu low:%lu high:%lu\n",
> -               vm_page_seg_name(vm_page_seg_index(seg)),
> +               vm_page_seg_name(seg->type),
>                 seg->min_free_pages, seg->low_free_pages, 
> seg->high_free_pages);
>      }
>  }
> @@ -1849,7 +1860,7 @@ vm_page_boot_table_size(void)
>  
>      nr_pages = 0;
>  
> -    for (i = 0; i < vm_page_segs_size; i++) {
> +    for (i = 0; i < ARRAY_SIZE(vm_page_boot_segs); i++) {
>          nr_pages += 
> vm_page_atop(vm_page_boot_seg_size(&vm_page_boot_segs[i]));
>      }
>  
> @@ -2359,7 +2370,8 @@ void db_show_vmstat(void)
>                 (vm_page_segs[i].inactive_pages.internal.nr_pages +
>                  vm_page_segs[i].inactive_pages.external.nr_pages);
>  
> -             db_printf("\nSegment %s:\n", vm_page_seg_name(i));
> +             db_printf("\nSegment %s:\n",
> +                       vm_page_seg_name(vm_page_segs[i].type));
>               db_printf("%-20s %10uM\n", "size:",
>                       vm_page_seg_size(&vm_page_segs[i]) >> 20);
>               db_printf("%-20s %10uM\n", "free:",
> -- 
> 2.47.3
> 
> 

-- 
Samuel
> Allez, soyez sympa ... traduisez-lui "linux"
Linux, c'est comme le miel : c'est vachement bon mais ça attire les
mouches. En plus, ça colle aux doigts et on a du mal à s'en défaire.
-+- TP in: Guide du linuxien pervers - "Barrez vous les mouches !"

Reply via email to