Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
5c04fc78
Unverified
Commit
5c04fc78
authored
Nov 22, 2018
by
Antonio Niño Díaz
Committed by
GitHub
Nov 22, 2018
Browse files
Merge pull request #1689 from antonio-nino-diaz-arm/an/alloc-va
xlat v2: Support mapping regions with allocated VA
parents
0668e5a8
9056f108
Changes
3
Hide whitespace changes
Inline
Side-by-side
include/lib/xlat_tables/xlat_tables_v2.h
View file @
5c04fc78
...
@@ -33,6 +33,12 @@
...
@@ -33,6 +33,12 @@
#define MAP_REGION_FLAT(_adr, _sz, _attr) \
#define MAP_REGION_FLAT(_adr, _sz, _attr) \
MAP_REGION(_adr, _adr, _sz, _attr)
MAP_REGION(_adr, _adr, _sz, _attr)
/*
* Helper macro to define entries for mmap_region_t. It allows to define 'pa'
* and sets 'va' to 0 for each region. To be used with mmap_add_alloc_va().
*/
#define MAP_REGION_ALLOC_VA(pa, sz, attr) MAP_REGION(pa, 0, sz, attr)
/*
/*
* Helper macro to define an mmap_region_t to map with the desired granularity
* Helper macro to define an mmap_region_t to map with the desired granularity
* of translation tables.
* of translation tables.
...
@@ -219,6 +225,21 @@ void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);
...
@@ -219,6 +225,21 @@ void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm);
void
mmap_add
(
const
mmap_region_t
*
mm
);
void
mmap_add
(
const
mmap_region_t
*
mm
);
void
mmap_add_ctx
(
xlat_ctx_t
*
ctx
,
const
mmap_region_t
*
mm
);
void
mmap_add_ctx
(
xlat_ctx_t
*
ctx
,
const
mmap_region_t
*
mm
);
/*
* Add a region with defined base PA. Returns base VA calculated using the
* highest existing region in the mmap array even if it fails to allocate the
* region.
*/
void
mmap_add_region_alloc_va
(
unsigned
long
long
base_pa
,
uintptr_t
*
base_va
,
size_t
size
,
unsigned
int
attr
);
void
mmap_add_region_alloc_va_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
);
/*
* Add an array of static regions with defined base PA, and fill the base VA
* field on the array of structs. This function can only be used before
* initializing the translation tables. The regions cannot be removed afterwards.
*/
void
mmap_add_alloc_va
(
mmap_region_t
*
mm
);
#if PLAT_XLAT_TABLES_DYNAMIC
#if PLAT_XLAT_TABLES_DYNAMIC
/*
/*
...
@@ -236,6 +257,21 @@ int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
...
@@ -236,6 +257,21 @@ int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
size_t
size
,
unsigned
int
attr
);
size_t
size
,
unsigned
int
attr
);
int
mmap_add_dynamic_region_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
);
int
mmap_add_dynamic_region_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
);
/*
* Add a dynamic region with defined base PA. Returns base VA calculated using
* the highest existing region in the mmap array even if it fails to allocate
* the region.
*
* mmap_add_dynamic_region_alloc_va() returns the allocated VA in 'base_va'.
* mmap_add_dynamic_region_alloc_va_ctx() returns it in 'mm->base_va'.
*
* It returns the same error values as mmap_add_dynamic_region().
*/
int
mmap_add_dynamic_region_alloc_va
(
unsigned
long
long
base_pa
,
uintptr_t
*
base_va
,
size_t
size
,
unsigned
int
attr
);
int
mmap_add_dynamic_region_alloc_va_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
);
/*
/*
* Remove a region with the specified base VA and size. Only dynamic regions can
* Remove a region with the specified base VA and size. Only dynamic regions can
* be removed, and they can be removed even if the translation tables are
* be removed, and they can be removed even if the translation tables are
...
...
lib/xlat_tables_v2/xlat_tables_context.c
View file @
5c04fc78
...
@@ -38,6 +38,25 @@ void mmap_add(const mmap_region_t *mm)
...
@@ -38,6 +38,25 @@ void mmap_add(const mmap_region_t *mm)
mmap_add_ctx
(
&
tf_xlat_ctx
,
mm
);
mmap_add_ctx
(
&
tf_xlat_ctx
,
mm
);
}
}
void
mmap_add_region_alloc_va
(
unsigned
long
long
base_pa
,
uintptr_t
*
base_va
,
size_t
size
,
unsigned
int
attr
)
{
mmap_region_t
mm
=
MAP_REGION_ALLOC_VA
(
base_pa
,
size
,
attr
);
mmap_add_region_alloc_va_ctx
(
&
tf_xlat_ctx
,
&
mm
);
*
base_va
=
mm
.
base_va
;
}
void
mmap_add_alloc_va
(
mmap_region_t
*
mm
)
{
while
(
mm
->
granularity
!=
0U
)
{
assert
(
mm
->
base_va
==
0U
);
mmap_add_region_alloc_va_ctx
(
&
tf_xlat_ctx
,
mm
);
mm
++
;
}
}
#if PLAT_XLAT_TABLES_DYNAMIC
#if PLAT_XLAT_TABLES_DYNAMIC
int
mmap_add_dynamic_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
int
mmap_add_dynamic_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
...
@@ -48,6 +67,20 @@ int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
...
@@ -48,6 +67,20 @@ int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
return
mmap_add_dynamic_region_ctx
(
&
tf_xlat_ctx
,
&
mm
);
return
mmap_add_dynamic_region_ctx
(
&
tf_xlat_ctx
,
&
mm
);
}
}
int
mmap_add_dynamic_region_alloc_va
(
unsigned
long
long
base_pa
,
uintptr_t
*
base_va
,
size_t
size
,
unsigned
int
attr
)
{
mmap_region_t
mm
=
MAP_REGION_ALLOC_VA
(
base_pa
,
size
,
attr
);
int
rc
=
mmap_add_dynamic_region_alloc_va_ctx
(
&
tf_xlat_ctx
,
&
mm
);
*
base_va
=
mm
.
base_va
;
return
rc
;
}
int
mmap_remove_dynamic_region
(
uintptr_t
base_va
,
size_t
size
)
int
mmap_remove_dynamic_region
(
uintptr_t
base_va
,
size_t
size
)
{
{
return
mmap_remove_dynamic_region_ctx
(
&
tf_xlat_ctx
,
return
mmap_remove_dynamic_region_ctx
(
&
tf_xlat_ctx
,
...
...
lib/xlat_tables_v2/xlat_tables_core.c
View file @
5c04fc78
...
@@ -811,6 +811,80 @@ void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
...
@@ -811,6 +811,80 @@ void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
ctx
->
max_va
=
end_va
;
ctx
->
max_va
=
end_va
;
}
}
/*
* Determine the table level closest to the initial lookup level that
* can describe this translation. Then, align base VA to the next block
* at the determined level.
*/
static
void
mmap_alloc_va_align_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
)
{
/*
* By or'ing the size and base PA the alignment will be the one
* corresponding to the smallest boundary of the two of them.
*
* There are three different cases. For example (for 4 KiB page size):
*
* +--------------+------------------++--------------+
* | PA alignment | Size multiple of || VA alignment |
* +--------------+------------------++--------------+
* | 2 MiB | 2 MiB || 2 MiB | (1)
* | 2 MiB | 4 KiB || 4 KiB | (2)
* | 4 KiB | 2 MiB || 4 KiB | (3)
* +--------------+------------------++--------------+
*
* - In (1), it is possible to take advantage of the alignment of the PA
* and the size of the region to use a level 2 translation table
* instead of a level 3 one.
*
* - In (2), the size is smaller than a block entry of level 2, so it is
* needed to use a level 3 table to describe the region or the library
* will map more memory than the desired one.
*
* - In (3), even though the region has the size of one level 2 block
* entry, it isn't possible to describe the translation with a level 2
* block entry because of the alignment of the base PA.
*
* Only bits 47:21 of a level 2 block descriptor are used by the MMU,
* bits 20:0 of the resulting address are 0 in this case. Because of
* this, the PA generated as result of this translation is aligned to
* 2 MiB. The PA that was requested to be mapped is aligned to 4 KiB,
* though, which means that the resulting translation is incorrect.
* The only way to prevent this is by using a finer granularity.
*/
unsigned
long
long
align_check
;
align_check
=
mm
->
base_pa
|
(
unsigned
long
long
)
mm
->
size
;
/*
* Assume it is always aligned to level 3. There's no need to check that
* level because its block size is PAGE_SIZE. The checks to verify that
* the addresses and size are aligned to PAGE_SIZE are inside
* mmap_add_region.
*/
for
(
unsigned
int
level
=
ctx
->
base_level
;
level
<=
2U
;
++
level
)
{
if
((
align_check
&
XLAT_BLOCK_MASK
(
level
))
!=
0U
)
continue
;
mm
->
base_va
=
round_up
(
mm
->
base_va
,
XLAT_BLOCK_SIZE
(
level
));
return
;
}
}
void
mmap_add_region_alloc_va_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
)
{
mm
->
base_va
=
ctx
->
max_va
+
1UL
;
assert
(
mm
->
size
>
0U
);
mmap_alloc_va_align_ctx
(
ctx
,
mm
);
/* Detect overflows. More checks are done in mmap_add_region_check(). */
assert
(
mm
->
base_va
>
ctx
->
max_va
);
mmap_add_region_ctx
(
ctx
,
mm
);
}
void
mmap_add_ctx
(
xlat_ctx_t
*
ctx
,
const
mmap_region_t
*
mm
)
void
mmap_add_ctx
(
xlat_ctx_t
*
ctx
,
const
mmap_region_t
*
mm
)
{
{
const
mmap_region_t
*
mm_cursor
=
mm
;
const
mmap_region_t
*
mm_cursor
=
mm
;
...
@@ -931,6 +1005,23 @@ int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
...
@@ -931,6 +1005,23 @@ int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
return
0
;
return
0
;
}
}
int
mmap_add_dynamic_region_alloc_va_ctx
(
xlat_ctx_t
*
ctx
,
mmap_region_t
*
mm
)
{
mm
->
base_va
=
ctx
->
max_va
+
1UL
;
if
(
mm
->
size
==
0U
)
return
0
;
mmap_alloc_va_align_ctx
(
ctx
,
mm
);
/* Detect overflows. More checks are done in mmap_add_region_check(). */
if
(
mm
->
base_va
<
ctx
->
max_va
)
{
return
-
ENOMEM
;
}
return
mmap_add_dynamic_region_ctx
(
ctx
,
mm
);
}
/*
/*
* Removes the region with given base Virtual Address and size from the given
* Removes the region with given base Virtual Address and size from the given
* context.
* context.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment