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

2018-06-26 Thread Patryk Duda
Could you provide some details about firmware? I would like to
reproduce it on our ThunderX2.

2018-06-25 17:28 GMT+02:00 Andrew Turner :
> I’ve not seen this on the ThunderX2 I have access to with the latest 
> firmware. You’ll need to find out why the kernel is trying to access the 
> memory, and where it is in the EFI memory map.
>
> Andrew
>
>> On 21 Jun 2018, at 13:41, Patryk Duda  wrote:
>>
>> 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 :
>>> 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;
>>>
>>> +#defineDMAP_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(_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_slot],
>>> +   (pa & ~L2_OFFSET) | ATTR_DEFAULT | 
>>> ATTR_XN |
>>> +   ATTR_IDX(CACHED_MEMORY) | L2_BLOCK);
>>> +   }
>>> +   

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

2018-06-25 Thread Andrew Turner
I’ve not seen this on the ThunderX2 I have access to with the latest firmware. 
You’ll need to find out why the kernel is trying to access the memory, and 
where it is in the EFI memory map.

Andrew

> On 21 Jun 2018, at 13:41, Patryk Duda  wrote:
> 
> 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 :
>> 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;
>> 
>> +#defineDMAP_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(_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_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] - 

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

2018-06-25 Thread Patryk Duda
Any updates?

2018-06-21 14:41 GMT+02:00 Patryk Duda :
> 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 :
>> 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;
>>
>> +#defineDMAP_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(_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_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 

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

2018-06-21 Thread Patryk Duda
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 :
> 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;
>
> +#defineDMAP_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(_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_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(_dmap[l1_slot],
>  

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

2018-05-29 Thread Andrew Turner
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;
 
+#defineDMAP_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(_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_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(_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 =