zephyr/arch
Neil Armstrong 866840e4e8 arm64: mmu: don't use a Level block if PA is not aligned
When mapping the following:
device_map(&base0, DEVA_BASE, DEVA_SIZE, K_MEM_CACHE_NONE);
device_map(&base1, DEVB_BASE , DEVB_SIZE, K_MEM_CACHE_NONE);

with:
- DEVA_SIZE not multiple of a 4KB granule L2 block size (0x200000)
- DEVB_SIZE more than 2 x 4KB granule L2 block size

The mmu code will fill the first device_map() in a L3 table, then
on the second mapping the mmu code will complete the previous L3
table.
At the end of this table, the actual code will select an L2 block
instead of a table because the *virtual address* is multiple with
the L2 block size.

But if the physical address is not, the virtual block offset will
be ORed to the physical address, and not added.

Leading to a weird scenario where virtual memory is duplicated
resulting of the addresses ORing and not addition.

Example:
device_map(&base0, DEVA_BASE, 0x20000, K_MEM_CACHE_NONE);
device_map(&base1, 0x44000000 , 0x400000, K_MEM_CACHE_NONE);

First will result in VA 0x5ffe0000 and second in VA 0x5fbe0000.

The MMU code will use a table to map 0x5ffe0000 to 0x5fbfffff.

For 0x5fc00000 to 0x5fdfffff, since the VA is multiple of an L2
block size, the L3 table is not used.

But the L2 block description entry address is 0x44060000, meaning
that for each access in this L2 block, the following will be done:

0x44060000 | (VA & 1FFFFF)

This is working for the 0x5fc40000 to 0x5fc5ffff access, but for the
0x5fbc60000 (0x5fbe0000 + 0x80000) access the PA gets calculated as :

0x44060000 | (0x5fc60000 & 1FFFFF) = 0x44060000 | 0x60000 = 0x44060000

Instead of the expected 0x44080000.

The solution is to check if the PA descriptor is aligned with the
level block size, if not move to the next level.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
2021-10-07 10:54:28 +02:00
..
arc ARC: MWDT: get rid of MWDT startup libs 2021-09-01 17:08:32 -04:00
arm arch: arm: core: aarch32: fix regression introduced with Cortex-R 2021-09-09 19:49:37 -04:00
arm64 arm64: mmu: don't use a Level block if PA is not aligned 2021-10-07 10:54:28 +02:00
common arch: linker: specify intList section in the IDT_LIST region 2021-08-30 08:54:23 -04:00
nios2 arch: nios2: Fix 10.4 violations 2021-04-10 09:59:37 -04:00
posix cmake: Support coverage flags on all archs 2021-06-10 18:01:36 -04:00
riscv riscv: Don't reschedule on back-to-back interrupts 2021-09-03 12:20:03 -04:00
sparc SPARC: Keep interrupts disabled during kernel init 2021-07-22 10:25:53 -04:00
x86 x86: x86-64: add arch_float_en-/dis-able() functions 2021-09-03 10:00:02 -04:00
xtensa xtensa: fix implicit declaration of _xtensa_handle_one_int* 2021-09-28 20:33:56 -04:00
CMakeLists.txt cmake: fix include directories to work with out-of-tree arch 2020-08-05 08:06:07 -04:00
Kconfig kernel: demand_paging: allow reserving page frames 2021-08-26 21:16:22 -04:00