svn commit: r334329 - head/sys/arm64/arm64

Patryk Duda pdk at semihalf.com
Thu Jun 21 12:41:32 UTC 2018


Hi,

I'm trying to boot kernel on ThunderX2 but I've got following error:

panic: efi_init: PA out of range, PA: 0xfafd0018

This error comes from PHYS_TO_DMAP macro.
I can workaround this issue by disabling EFI Runtime Services in
kernel config but it seems to be
a problem with discontignous DMAP mapping.


2018-05-29 15:52 GMT+02:00 Andrew Turner <andrew at freebsd.org>:
> Author: andrew
> Date: Tue May 29 13:52:25 2018
> New Revision: 334329
> URL: https://svnweb.freebsd.org/changeset/base/334329
>
> Log:
>   On ThunderX2 we need to be careful to only map the memory the firmware
>   lists in the EFI memory map. As such we need to reduce the mappings to
>   restrict them to not be the full 1G block. For now reduce this to a 2M
>   block, however this may be further restricted to be 4k page aligned as
>   other SoCs may require.
>
>   This allows ThunderX2 to boot reliably to userspace without performing
>   any speculative memory accesses to invalid physical memory.
>
>   This is a recommit of r334035 now that we can access the EFI Runtime data
>   through the DMAP region.
>
>   Tested by:    tuexen
>   Sponsored by: DARPA, AFRL
>
> Modified:
>   head/sys/arm64/arm64/pmap.c
>
> Modified: head/sys/arm64/arm64/pmap.c
> ==============================================================================
> --- head/sys/arm64/arm64/pmap.c Tue May 29 13:43:16 2018        (r334328)
> +++ head/sys/arm64/arm64/pmap.c Tue May 29 13:52:25 2018        (r334329)
> @@ -590,33 +590,100 @@ pmap_early_vtophys(vm_offset_t l1pt, vm_offset_t va)
>         return ((l2[l2_slot] & ~ATTR_MASK) + (va & L2_OFFSET));
>  }
>
> -static void
> -pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa, vm_paddr_t max_pa)
> +static vm_offset_t
> +pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t min_pa,
> +    vm_offset_t freemempos)
>  {
> +       pt_entry_t *l2;
>         vm_offset_t va;
> -       vm_paddr_t pa;
> -       u_int l1_slot;
> +       vm_paddr_t l2_pa, pa;
> +       u_int l1_slot, l2_slot, prev_l1_slot;
>         int i;
>
>         dmap_phys_base = min_pa & ~L1_OFFSET;
>         dmap_phys_max = 0;
>         dmap_max_addr = 0;
> +       l2 = NULL;
> +       prev_l1_slot = -1;
>
> +#define        DMAP_TABLES     ((DMAP_MAX_ADDRESS - DMAP_MIN_ADDRESS) >> L0_SHIFT)
> +       memset(pagetable_dmap, 0, PAGE_SIZE * DMAP_TABLES);
> +
>         for (i = 0; i < (physmap_idx * 2); i += 2) {
> -               pa = physmap[i] & ~L1_OFFSET;
> +               pa = physmap[i] & ~L2_OFFSET;
>                 va = pa - dmap_phys_base + DMAP_MIN_ADDRESS;
>
> -               for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1];
> +               /* Create L2 mappings at the start of the region */
> +               if ((pa & L1_OFFSET) != 0) {
> +                       l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
> +                       if (l1_slot != prev_l1_slot) {
> +                               prev_l1_slot = l1_slot;
> +                               l2 = (pt_entry_t *)freemempos;
> +                               l2_pa = pmap_early_vtophys(kern_l1,
> +                                   (vm_offset_t)l2);
> +                               freemempos += PAGE_SIZE;
> +
> +                               pmap_load_store(&pagetable_dmap[l1_slot],
> +                                   (l2_pa & ~Ln_TABLE_MASK) | L1_TABLE);
> +
> +                               memset(l2, 0, PAGE_SIZE);
> +                       }
> +                       KASSERT(l2 != NULL,
> +                           ("pmap_bootstrap_dmap: NULL l2 map"));
> +                       for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1];
> +                           pa += L2_SIZE, va += L2_SIZE) {
> +                               /*
> +                                * We are on a boundary, stop to
> +                                * create a level 1 block
> +                                */
> +                               if ((pa & L1_OFFSET) == 0)
> +                                       break;
> +
> +                               l2_slot = pmap_l2_index(va);
> +                               KASSERT(l2_slot != 0, ("..."));
> +                               pmap_load_store(&l2[l2_slot],
> +                                   (pa & ~L2_OFFSET) | ATTR_DEFAULT | ATTR_XN |
> +                                   ATTR_IDX(CACHED_MEMORY) | L2_BLOCK);
> +                       }
> +                       KASSERT(va == (pa - dmap_phys_base + DMAP_MIN_ADDRESS),
> +                           ("..."));
> +               }
> +
> +               for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1] &&
> +                   (physmap[i + 1] - pa) >= L1_SIZE;
>                     pa += L1_SIZE, va += L1_SIZE) {
>                         l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
> -                       /* We already have an entry */
> -                       if (pagetable_dmap[l1_slot] != 0)
> -                               continue;
>                         pmap_load_store(&pagetable_dmap[l1_slot],
>                             (pa & ~L1_OFFSET) | ATTR_DEFAULT | ATTR_XN |
>                             ATTR_IDX(CACHED_MEMORY) | L1_BLOCK);
>                 }
>
> +               /* Create L2 mappings at the end of the region */
> +               if (pa < physmap[i + 1]) {
> +                       l1_slot = ((va - DMAP_MIN_ADDRESS) >> L1_SHIFT);
> +                       if (l1_slot != prev_l1_slot) {
> +                               prev_l1_slot = l1_slot;
> +                               l2 = (pt_entry_t *)freemempos;
> +                               l2_pa = pmap_early_vtophys(kern_l1,
> +                                   (vm_offset_t)l2);
> +                               freemempos += PAGE_SIZE;
> +
> +                               pmap_load_store(&pagetable_dmap[l1_slot],
> +                                   (l2_pa & ~Ln_TABLE_MASK) | L1_TABLE);
> +
> +                               memset(l2, 0, PAGE_SIZE);
> +                       }
> +                       KASSERT(l2 != NULL,
> +                           ("pmap_bootstrap_dmap: NULL l2 map"));
> +                       for (; va < DMAP_MAX_ADDRESS && pa < physmap[i + 1];
> +                           pa += L2_SIZE, va += L2_SIZE) {
> +                               l2_slot = pmap_l2_index(va);
> +                               pmap_load_store(&l2[l2_slot],
> +                                   (pa & ~L2_OFFSET) | ATTR_DEFAULT | ATTR_XN |
> +                                   ATTR_IDX(CACHED_MEMORY) | L2_BLOCK);
> +                       }
> +               }
> +
>                 if (pa > dmap_phys_max) {
>                         dmap_phys_max = pa;
>                         dmap_max_addr = va;
> @@ -624,6 +691,8 @@ pmap_bootstrap_dmap(vm_offset_t kern_l1, vm_paddr_t mi
>         }
>
>         cpu_tlb_flushID();
> +
> +       return (freemempos);
>  }
>
>  static vm_offset_t
> @@ -729,8 +798,11 @@ pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_
>                         max_pa = physmap[i + 1];
>         }
>
> +       freemempos = KERNBASE + kernlen;
> +       freemempos = roundup2(freemempos, PAGE_SIZE);
> +
>         /* Create a direct map region early so we can use it for pa -> va */
> -       pmap_bootstrap_dmap(l1pt, min_pa, max_pa);
> +       freemempos = pmap_bootstrap_dmap(l1pt, min_pa, freemempos);
>
>         va = KERNBASE;
>         start_pa = pa = KERNBASE - kern_delta;
> @@ -762,8 +834,6 @@ pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_
>
>         va = roundup2(va, L1_SIZE);
>
> -       freemempos = KERNBASE + kernlen;
> -       freemempos = roundup2(freemempos, PAGE_SIZE);
>         /* Create the l2 tables up to VM_MAX_KERNEL_ADDRESS */
>         freemempos = pmap_bootstrap_l2(l1pt, va, freemempos);
>         /* And the l3 tables for the early devmap */
> _______________________________________________
> svn-src-all at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"


More information about the svn-src-all mailing list