Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic allocation of mmu translation tables #7192

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

jenswi-linaro
Copy link
Contributor

No description provided.

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • For "core: allow partially unmapped MEM_AREA_TEE_RAM_RW":
    Acked-by: Jerome Forissier <[email protected]>
  • For "core: boot_mem: allow NULL pointers while relocating":
    Reviewed-by: Jerome Forissier <[email protected]>

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For commit "core: boot_mem: keep track of padding", with the minor comment below addressed:
Acked-by: Jerome Forissier <[email protected]>

@@ -39,6 +51,7 @@ struct boot_mem_desc {
vaddr_t mem_start;
vaddr_t mem_end;
struct boot_mem_reloc *reloc;
struct boot_mem_padding *padding;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @padding to the documentation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For "core: arm: add boot mem paddings to the heap":
Acked-by: Jerome Forissier <[email protected]>

Copy link
Contributor

@jforissier jforissier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For "core: mm: extend temporary dummy memory map":
Acked-by: Jerome Forissier <[email protected]>

* entry1
* entry2
* entry3
* core0: table1: entry (maps only EL0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean entry0 here? Or is it on purpose to differentiate from entry0 while entry1 etc. are the same in both tables?

Copy link
Contributor Author

@jenswi-linaro jenswi-linaro Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a typo, it should be entry0. I'll update the comment.

@jforissier
Copy link
Contributor

CFG_DYN_CONFIG=y should definitely be added to CI (both for v7 and LPAE).

@jenswi-linaro
Copy link
Contributor Author

Unless paging is enabled, CFG_DYN_CONFIG=y is defaulted on all arm platforms.

@jenswi-linaro
Copy link
Contributor Author

Ping?

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-by: Etienne Carriere <[email protected]> for commits
"core: allow partially unmapped MEM_AREA_TEE_RAM_RW",
"core: boot_mem: allow NULL pointers while relocating",
"core: boot_mem: keep track of padding" (with a minor comment to address and a free suggestion),
"core: arm: add boot mem paddings to the heap" and
"core: mm: extend temporary dummy memory map".

I'm still looking at the remaining commits.

(edited)

/*
* struct boot_mem_padding - unused memory between allocations
* @start: Start of padding
* @start: Length of padding
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/start/len/

p = boot_mem_alloc(SMALL_PAGE_SIZE, SMALL_PAGE_SIZE);
if (prtn->last_l2_page)
assert(prtn->last_l2_page + SMALL_PAGE_SIZE ==
p);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this stage prtn->last_l2_page is always NULL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I'll remove the if and assert. This was a leftover from a previous version.

assert(prtn->last_l2_page + SMALL_PAGE_SIZE ==
p);
if (!prtn->tables_used)
boot_mem_add_reloc(&prtn->last_l2_page);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this allows only a single chunk of 4 32bit MMU page table references. Isn't it an issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's OK. I'll add this comment:

                        /*
                         * L2 tables are allocated four at a time as a 4k
                         * page. The pointer prtn->last_l2_page keeps track
                         * of that page until all the l2 tables has been
                         * used. That pointer may need to be relocated when
                         * the MMU is enabled so the address of the pointer
                         * is recorded, but it must only be recorded once.
                         *
                         * The already used 4k pages are only referenced
                         * via recorded physical addresses in the l1 table
                         * so those pointers don't need to be updated for
                         * relocation.
                         */

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, crystal clear. Thanks.
s/has been/have been/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment addressed.

@@ -214,19 +217,23 @@ static l2_xlat_tbl_t main_mmu_l2_ttb[MAX_XLAT_TABLES]
/* MMU L1 table for TAs, one for each thread */
static ul1_xlat_tbl_t main_mmu_ul1_ttb[CFG_NUM_THREADS]
__aligned(UL1_ALIGNMENT) __section(".nozi.mmu.ul1");
#endif

struct mmu_partition {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be ok to add an inline description as you've added in the LPAE implementation, something like:

/*
 * struct mmu_partition - core virtual memory tables
 * @l1_table:       Level 1 translation tables base address
 * @l2_table:       Level 2 translation tables base address (CFG_DYN_CONFIG=n)
 * @last_l2_page:   Pre-allocated Level 2 table chunk (CFG_DYN_CONFIG=y)
 * @ul1_tables:     Level 1 translation tab le for EL0 mapping
 * @tables_used:    Number of level 2 tables already used
 */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment addressed.

@@ -158,6 +200,33 @@ void *boot_mem_alloc_tmp(size_t len, size_t align)
return mem_alloc_tmp(boot_mem_desc, len, align);
}

void boot_mem_foreach_padding(bool (*func)(vaddr_t va, size_t len, void *ptr),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a little helper inline description telling that this function call func() for each registered padding instance and unregisters (consumes) it when the func() return true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@jenswi-linaro
Copy link
Contributor Author

Update

@jenswi-linaro
Copy link
Contributor Author

Update.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments for commit "core: arm: mm: refactor LPAE translation table handling".

*
* TTBR is assigned a base translation table of NUM_BASE_LEVEL_ENTRIES
* entries. NUM_BASE_LEVEL_ENTRIES is determined based on
* CFG_LPAE_ADDR_SPACE_BITS. CFG_LPAE_ADDR_SPACE_BITS is by default 32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicking: 2 space chars

* EL0 where EL1 is unmapped except for a minimal trampoline needed to
* restore EL1 mappings on exception from EL0.
*
* Each CPU core is assign a unique set of base translation tables as:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/assign/assigned/

{
size_t idx = 0;

idx = ((vaddr_t)tbl - (vaddr_t)prtn->xlat_tables) / XLAT_TABLE_SIZE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previous implementation used &tbl[user_va_idx] not tbl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I think it was incorrect. user_va_idx is typically 1 so that would give the address of the second entry in the translation table. That difference is lost with the division so it doesn't harm except that it's confusing.


idx = ((vaddr_t)tbl - (vaddr_t)prtn->xlat_tables) / XLAT_TABLE_SIZE;
if (idx > MAX_XLAT_TABLES)
panic();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation tested idx index against the number of tables already consumed (prtn->xlat_table_used). It is intentional to allow up to MAX_XLAT_TABLES now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, I'll restore the assert().

I'm having my doubts about this array of indices. With a hardcoded limit, it's easy to ensure that the index type is wide enough, but with a more dynamic approach, we may be better off with pointers. It's also slightly less complicated and that should be welcome in this file. If you have a VA space larger than 39 bits, you can afford 6-7 extra bytes per CPU (in addition to the extra 4k page needed). The decision can wait until we have a dynamic configuration of the number of cores.

@jenswi-linaro
Copy link
Contributor Author

Update

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-by: Etienne Carriere <[email protected]> for commit
"core: arm: mm: dynamic allocation of LPAE translation tables".

Commit "core: arm: mm: dynamic allocation of v7 translation tables" looks good to me once comments are addressed. Feel free to squash all fixes in your next P-R update.


new_table = prtn->l2_tables[prtn->tables_used];
prtn->tables_used++;
DMSG("L2 table used: %d/%d", prtn->tables_used,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking: typo in previous implementation, let's fix it?
"L2 table used: %"PRIu32"/%d"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

assert(prtn->last_l2_page + SMALL_PAGE_SIZE ==
p);
if (!prtn->tables_used)
boot_mem_add_reloc(&prtn->last_l2_page);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment addressed.

@@ -214,19 +217,23 @@ static l2_xlat_tbl_t main_mmu_l2_ttb[MAX_XLAT_TABLES]
/* MMU L1 table for TAs, one for each thread */
static ul1_xlat_tbl_t main_mmu_ul1_ttb[CFG_NUM_THREADS]
__aligned(UL1_ALIGNMENT) __section(".nozi.mmu.ul1");
#endif

struct mmu_partition {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment addressed.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-by: Etienne Carriere <[email protected]> for commit
"core: arm: mm: refactor LPAE translation table handling".

Add special checks in phys_to_virt_tee_ram() to see that a virtual
address indeed is mapped before return the address if the memory area is
MEM_AREA_TEE_RAM_RW since the VCORE_FREE may be unmapped.

Signed-off-by: Jens Wiklander <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
In boot_mem_relocate() when relocating registered pointers, allow the
pointer to be NULL. NULL pointers are not relocated.

Signed-off-by: Jens Wiklander <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
When boot_mem_alloc() allocates memory up to alignment - 1 number of
bytes may have be skipped to satisfy the required alignment of the
returned pointer. If the skipped bytes, or padding, is large enough,
it's recorded in a list of padding. The list of paddings can be
processed and consumed with boot_mem_foreach_padding(). This allows
sufficiently large paddings to be added to for instance the heap instead
of being wasted.

Signed-off-by: Jens Wiklander <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
Add the paddings added due to requested alignment in boot mem
allocations to the heap.

Signed-off-by: Jens Wiklander <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
core_init_mmu_map() uses a temporary dummy memory map for the
virt_to_phys() and phys_to_virt() conversions to avoid asserting while
setting up translation tables before the MMU is enabled. CFG_DYN_CONFIG
will need a larger range of memory since translation tables might not be
allocated from .nozi memory only. So for CFG_DYN_CONFIG extend of end of
the unused memory range that the boot_mem_*() functions allocate memory
from.

Introduce CFG_DYN_CONFIG, enabled by default if CFG_BOOT_MEM is enabled
and CFG_WITH_PAGER disabled. CFG_DYN_CONFIG conflicts with
CFG_WITH_PAGER since the pager uses a different mechanism for memory
allocation.

Signed-off-by: Jens Wiklander <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
Refactor translation table handling to use a more flexible layout of the
translation tables in memory. Instead of relying on multidimensional
array use helper functions to calculate the address of each translation
table as needed.

Preparing for future changes, no change in behaviour.

Signed-off-by: Jens Wiklander <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
With CFG_DYN_CONFIG enabled allocate translation tables using the
boot_mem_*() functions. Static allocation from global variables is still
used with CFG_DYN_CONFIG disabled.

Signed-off-by: Jens Wiklander <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
With CFG_DYN_CONFIG enabled allocate translation tables using the
boot_mem_*() functions. Static allocation from global variables is still
used with CFG_DYN_CONFIG disabled.

Signed-off-by: Jens Wiklander <[email protected]>
Reviewed-by: Etienne Carriere <[email protected]>
@jenswi-linaro
Copy link
Contributor Author

Comments addressed, commits squashed, rebased, and tags applied.

@jenswi-linaro
Copy link
Contributor Author

The PR touches very core parts and although it's stable I don't mind if it's merged after the release to minimize the risk of last-minute problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants