lib/xlat_tables_v2/xlat_tables_core.c
/*
 * Recursive function that writes to the translation tables and maps the
 * specified region. On success, it returns the VA of the last byte that was
 * successfully mapped. On error, it returns the VA of the next entry that
 * should have been mapped.
 */
Recursive function that writes to the translation tables and maps the
specified region. On success, it returns the VA of the last byte that was
successfully mapped. On error, it returns the VA of the next entry that
should have been mapped.
Recursive function that writes to the translation tables and maps the specified region . On success it returns the VA of the last byte that was successfully mapped . On error it returns the VA of the next entry that should have been mapped .
static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
				   uintptr_t table_base_va,
				   uint64_t *const table_base,
				   unsigned int table_entries,
				   unsigned int level)
{
	assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
	uintptr_t mm_end_va = mm->base_va + mm->size - 1U;
	uintptr_t table_idx_va;
	unsigned long long table_idx_pa;
	uint64_t *subtable;
	uint64_t desc;
	unsigned int table_idx;
	if (mm->base_va > table_base_va) {
		table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
		table_idx = (unsigned int)((table_idx_va - table_base_va) >>
			    XLAT_ADDR_SHIFT(level));
		assert(table_idx < table_entries);
	} else {
		table_idx_va = table_base_va;
		table_idx = 0U;
	}
#if PLAT_XLAT_TABLES_DYNAMIC
	if (level > ctx->base_level)
		xlat_table_inc_regions_count(ctx, table_base);
#endif
	while (table_idx < table_entries) {
		desc = table_base[table_idx];
		table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
		action_t action = xlat_tables_map_region_action(mm,
			(uint32_t)(desc & DESC_MASK), table_idx_pa,
			table_idx_va, level);
		if (action == ACTION_WRITE_BLOCK_ENTRY) {
			table_base[table_idx] =
				xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
					  level);
		} else if (action == ACTION_CREATE_NEW_TABLE) {
			uintptr_t end_va;
			subtable = xlat_table_get_empty(ctx);
			if (subtable == NULL) {
				return table_idx_va;
			}
			table_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
			end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
					       subtable, XLAT_TABLE_ENTRIES,
					       level + 1U);
			if (end_va !=
				(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
				return end_va;
		} else if (action == ACTION_RECURSE_INTO_TABLE) {
			uintptr_t end_va;
			subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
			end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
					       subtable, XLAT_TABLE_ENTRIES,
					       level + 1U);
			if (end_va !=
				(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
				return end_va;
		} else {
			assert(action == ACTION_NONE);
		}
		table_idx++;
		table_idx_va += XLAT_BLOCK_SIZE(level);
		if (mm_end_va <= table_idx_va)
			break;
	}
	return table_idx_va - 1U;
}
static uintptr_t xlat_tables_map_region ( xlat_ctx_t * ctx , mmap_region_t * mm , uintptr_t table_base_va , uint64_t * const table_base , unsigned int table_entries , unsigned int level ) { assert ( ( level >= ctx -> base_level ) && ( level <= XLAT_TABLE_LEVEL_MAX ) ) ; uintptr_t mm_end_va = mm -> base_va + mm -> size - 1U ; uintptr_t table_idx_va ; unsigned long long table_idx_pa ; uint64_t * subtable ; uint64_t desc ; unsigned int table_idx ; if ( mm -> base_va > table_base_va ) { table_idx_va = mm -> base_va & ~ XLAT_BLOCK_MASK ( level ) ; table_idx = ( unsigned int ) ( ( table_idx_va - table_base_va ) >> XLAT_ADDR_SHIFT ( level ) ) ; assert ( table_idx < table_entries ) ; } else { table_idx_va = table_base_va ; table_idx = 0U ; } #if PLAT_XLAT_TABLES_DYNAMIC if ( level > ctx -> base_level ) xlat_table_inc_regions_count ( ctx , table_base ) ; #endif while ( table_idx < table_entries ) { desc = table_base [ table_idx ] ; table_idx_pa = mm -> base_pa + table_idx_va - mm -> base_va ; action_t action = xlat_tables_map_region_action ( mm , ( uint32_t ) ( desc & DESC_MASK ) , table_idx_pa , table_idx_va , level ) ; if ( action == ACTION_WRITE_BLOCK_ENTRY ) { table_base [ table_idx ] = xlat_desc ( ctx , ( uint32_t ) mm -> attr , table_idx_pa , level ) ; } else if ( action == ACTION_CREATE_NEW_TABLE ) { uintptr_t end_va ; subtable = xlat_table_get_empty ( ctx ) ; if ( subtable == NULL ) { return table_idx_va ; } table_base [ table_idx ] = TABLE_DESC | ( unsigned long ) subtable ; end_va = xlat_tables_map_region ( ctx , mm , table_idx_va , subtable , XLAT_TABLE_ENTRIES , level + 1U ) ; if ( end_va != ( table_idx_va + XLAT_BLOCK_SIZE ( level ) - 1U ) ) return end_va ; } else if ( action == ACTION_RECURSE_INTO_TABLE ) { uintptr_t end_va ; subtable = ( uint64_t * ) ( uintptr_t ) ( desc & TABLE_ADDR_MASK ) ; end_va = xlat_tables_map_region ( ctx , mm , table_idx_va , subtable , XLAT_TABLE_ENTRIES , level + 1U ) ; if ( end_va != ( table_idx_va + XLAT_BLOCK_SIZE ( level ) - 1U ) ) return end_va ; } else { assert ( action == ACTION_NONE ) ; } table_idx ++ ; table_idx_va += XLAT_BLOCK_SIZE ( level ) ; if ( mm_end_va <= table_idx_va ) break ; } return table_idx_va - 1U ; }
Recursive function that writes to the translation tables and maps the
 specified region.
Recursive function that writes to the translation tables and maps the specified region .
/* Find the first index of the table affected by the region. */ /* Start from the beginning of the table. */ /* Not enough free tables to map this region */ /* Point to new subtable from this one. */ /* Recurse to write into subtable */ /* Recurse to write into subtable */ /* If reached the end of the region, exit */