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
28ee754d
Commit
28ee754d
authored
Mar 16, 2017
by
davidcunado-arm
Committed by
GitHub
Mar 16, 2017
Browse files
Merge pull request #856 from antonio-nino-diaz-arm/an/dynamic-xlat
Introduce version 2 of the translation tables library
parents
fa971fca
bf75a371
Changes
37
Show whitespace changes
Inline
Side-by-side
Makefile
View file @
28ee754d
...
@@ -191,6 +191,7 @@ INCLUDES += -Iinclude/bl1 \
...
@@ -191,6 +191,7 @@ INCLUDES += -Iinclude/bl1 \
-Iinclude
/lib/el3_runtime/
${ARCH}
\
-Iinclude
/lib/el3_runtime/
${ARCH}
\
-Iinclude
/lib/pmf
\
-Iinclude
/lib/pmf
\
-Iinclude
/lib/psci
\
-Iinclude
/lib/psci
\
-Iinclude
/lib/xlat_tables
\
-Iinclude
/plat/common
\
-Iinclude
/plat/common
\
-Iinclude
/services
\
-Iinclude
/services
\
${PLAT_INCLUDES}
\
${PLAT_INCLUDES}
\
...
...
bl31/aarch64/bl31_entrypoint.S
View file @
28ee754d
/*
/*
*
Copyright
(
c
)
2013
-
201
6
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
Copyright
(
c
)
2013
-
201
7
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
#include <el3_common_macros.S>
#include <el3_common_macros.S>
#include <pmf_asm_macros.S>
#include <pmf_asm_macros.S>
#include <runtime_instr.h>
#include <runtime_instr.h>
#include <xlat_tables.h>
#include <xlat_tables
_defs
.h>
.
globl
bl31_entrypoint
.
globl
bl31_entrypoint
.
globl
bl31_warm_entrypoint
.
globl
bl31_warm_entrypoint
...
...
bl32/sp_min/aarch32/entrypoint.S
View file @
28ee754d
/*
/*
*
Copyright
(
c
)
2016
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
Copyright
(
c
)
2016
-
2017
,
ARM
Limited
and
Contributors
.
All
rights
reserved
.
*
*
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
Redistribution
and
use
in
source
and
binary
forms
,
with
or
without
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
*
modification
,
are
permitted
provided
that
the
following
conditions
are
met
:
...
@@ -36,7 +36,7 @@
...
@@ -36,7 +36,7 @@
#include <runtime_svc.h>
#include <runtime_svc.h>
#include <smcc_helpers.h>
#include <smcc_helpers.h>
#include <smcc_macros.S>
#include <smcc_macros.S>
#include <xlat_tables.h>
#include <xlat_tables
_defs
.h>
.
globl
sp_min_vector_table
.
globl
sp_min_vector_table
.
globl
sp_min_entrypoint
.
globl
sp_min_entrypoint
...
...
bl32/tsp/aarch64/tsp_entrypoint.S
View file @
28ee754d
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
#include <arch.h>
#include <arch.h>
#include <asm_macros.S>
#include <asm_macros.S>
#include <tsp.h>
#include <tsp.h>
#include <xlat_tables.h>
#include <xlat_tables
_defs
.h>
#include "../tsp_private.h"
#include "../tsp_private.h"
...
...
common/bl_common.c
View file @
28ee754d
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
#include <platform.h>
#include <platform.h>
#include <string.h>
#include <string.h>
#include <utils.h>
#include <utils.h>
#include <xlat_tables.h>
#include <xlat_tables
_defs
.h>
uintptr_t
page_align
(
uintptr_t
value
,
unsigned
dir
)
uintptr_t
page_align
(
uintptr_t
value
,
unsigned
dir
)
{
{
...
...
docs/cpu-specific-build-macros.md
View file @
28ee754d
...
@@ -65,6 +65,9 @@ For Cortex-A57, following errata build flags are defined :
...
@@ -65,6 +65,9 @@ For Cortex-A57, following errata build flags are defined :
*
`ERRATA_A57_806969`
: This applies errata 806969 workaround to Cortex-A57
*
`ERRATA_A57_806969`
: This applies errata 806969 workaround to Cortex-A57
CPU. This needs to be enabled only for revision r0p0 of the CPU.
CPU. This needs to be enabled only for revision r0p0 of the CPU.
*
`ERRATA_A57_813419`
: This applies errata 813419 workaround to Cortex-A57
CPU. This needs to be enabled only for revision r0p0 of the CPU.
*
`ERRATA_A57_813420`
: This applies errata 813420 workaround to Cortex-A57
*
`ERRATA_A57_813420`
: This applies errata 813420 workaround to Cortex-A57
CPU. This needs to be enabled only for revision r0p0 of the CPU.
CPU. This needs to be enabled only for revision r0p0 of the CPU.
...
...
docs/porting-guide.md
View file @
28ee754d
...
@@ -420,14 +420,23 @@ platform, the following constants must also be defined:
...
@@ -420,14 +420,23 @@ platform, the following constants must also be defined:
TSP's interrupt handling code.
TSP's interrupt handling code.
If the platform port uses the translation table library code, the following
If the platform port uses the translation table library code, the following
constant must also be defined:
constants must also be defined:
*
**#define : PLAT_XLAT_TABLES_DYNAMIC**
Optional flag that can be set per-image to enable the dynamic allocation of
regions even when the MMU is enabled. If not defined, only static
functionality will be available, if defined and set to 1 it will also
include the dynamic functionality.
*
**#define : MAX_XLAT_TABLES**
*
**#define : MAX_XLAT_TABLES**
Defines the maximum number of translation tables that are allocated by the
Defines the maximum number of translation tables that are allocated by the
translation table library code. To minimize the amount of runtime memory
translation table library code. To minimize the amount of runtime memory
used, choose the smallest value needed to map the required virtual addresses
used, choose the smallest value needed to map the required virtual addresses
for each BL stage.
for each BL stage. If `PLAT_XLAT_TABLES_DYNAMIC` flag is enabled for a BL
image, `MAX_XLAT_TABLES` must be defined to accommodate the dynamic regions
as well.
*
**#define : MAX_MMAP_REGIONS**
*
**#define : MAX_MMAP_REGIONS**
...
@@ -438,7 +447,9 @@ constant must also be defined:
...
@@ -438,7 +447,9 @@ constant must also be defined:
that should be mapped. Then, the translation table library will create the
that should be mapped. Then, the translation table library will create the
corresponding tables and descriptors at runtime. To minimize the amount of
corresponding tables and descriptors at runtime. To minimize the amount of
runtime memory used, choose the smallest value needed to register the
runtime memory used, choose the smallest value needed to register the
required regions for each BL stage.
required regions for each BL stage. If `PLAT_XLAT_TABLES_DYNAMIC` flag is
enabled for a BL image, `MAX_MMAP_REGIONS` must be defined to accommodate
the dynamic regions as well.
*
**#define : ADDR_SPACE_SIZE**
*
**#define : ADDR_SPACE_SIZE**
...
...
include/lib/aarch32/arch.h
View file @
28ee754d
/*
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016
-2017
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -331,6 +331,15 @@
...
@@ -331,6 +331,15 @@
#define PMCR_N_MASK 0x1f
#define PMCR_N_MASK 0x1f
#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT)
#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT)
/*******************************************************************************
* Definitions of register offsets, fields and macros for CPU system
* instructions.
******************************************************************************/
#define TLBI_ADDR_SHIFT 0
#define TLBI_ADDR_MASK 0xFFFFF000
#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK)
/*******************************************************************************
/*******************************************************************************
* Definitions of register offsets and fields in the CNTCTLBase Frame of the
* Definitions of register offsets and fields in the CNTCTLBase Frame of the
* system level implementation of the Generic Timer.
* system level implementation of the Generic Timer.
...
@@ -378,6 +387,8 @@
...
@@ -378,6 +387,8 @@
#define TLBIALLIS p15, 0, c8, c3, 0
#define TLBIALLIS p15, 0, c8, c3, 0
#define TLBIMVA p15, 0, c8, c7, 1
#define TLBIMVA p15, 0, c8, c7, 1
#define TLBIMVAA p15, 0, c8, c7, 3
#define TLBIMVAA p15, 0, c8, c7, 3
#define TLBIMVAAIS p15, 0, c8, c3, 3
#define BPIALLIS p15, 0, c7, c1, 6
#define HSCTLR p15, 4, c1, c0, 0
#define HSCTLR p15, 4, c1, c0, 0
#define HCR p15, 4, c1, c1, 0
#define HCR p15, 4, c1, c1, 0
#define HCPTR p15, 4, c1, c1, 2
#define HCPTR p15, 4, c1, c1, 2
...
...
include/lib/aarch32/arch_helpers.h
View file @
28ee754d
...
@@ -131,6 +131,13 @@ static inline void tlbi##_op(void) \
...
@@ -131,6 +131,13 @@ static inline void tlbi##_op(void) \
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
}
}
#define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
static inline void bpi##_op(void) \
{ \
u_register_t v = 0; \
__asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\
}
#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \
static inline void tlbi##_op(u_register_t v) \
static inline void tlbi##_op(u_register_t v) \
{ \
{ \
...
@@ -145,6 +152,10 @@ static inline void tlbi##_op(u_register_t v) \
...
@@ -145,6 +152,10 @@ static inline void tlbi##_op(u_register_t v) \
#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \
#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \
_DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__)
_DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__)
/* Define function for simple BPI operation */
#define DEFINE_BPIOP_FUNC(_op, ...) \
_DEFINE_BPIOP_FUNC(_op, __VA_ARGS__)
/**********************************************************************
/**********************************************************************
* Macros to create inline functions for DC operations
* Macros to create inline functions for DC operations
*********************************************************************/
*********************************************************************/
...
@@ -199,6 +210,7 @@ DEFINE_SYSOP_FUNC(sev)
...
@@ -199,6 +210,7 @@ DEFINE_SYSOP_FUNC(sev)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
sy
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
sy
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
sy
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
sy
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ishst
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ish
)
DEFINE_SYSOP_FUNC
(
isb
)
DEFINE_SYSOP_FUNC
(
isb
)
...
@@ -263,6 +275,12 @@ DEFINE_TLBIOP_FUNC(all, TLBIALL)
...
@@ -263,6 +275,12 @@ DEFINE_TLBIOP_FUNC(all, TLBIALL)
DEFINE_TLBIOP_FUNC
(
allis
,
TLBIALLIS
)
DEFINE_TLBIOP_FUNC
(
allis
,
TLBIALLIS
)
DEFINE_TLBIOP_PARAM_FUNC
(
mva
,
TLBIMVA
)
DEFINE_TLBIOP_PARAM_FUNC
(
mva
,
TLBIMVA
)
DEFINE_TLBIOP_PARAM_FUNC
(
mvaa
,
TLBIMVAA
)
DEFINE_TLBIOP_PARAM_FUNC
(
mvaa
,
TLBIMVAA
)
DEFINE_TLBIOP_PARAM_FUNC
(
mvaais
,
TLBIMVAAIS
)
/*
* BPI operation prototypes.
*/
DEFINE_BPIOP_FUNC
(
allis
,
BPIALLIS
)
/*
/*
* DC operation prototypes
* DC operation prototypes
...
...
include/lib/aarch64/arch.h
View file @
28ee754d
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
#ifndef __ARCH_H__
#ifndef __ARCH_H__
#define __ARCH_H__
#define __ARCH_H__
#include <utils.h>
/*******************************************************************************
/*******************************************************************************
* MIDR bit definitions
* MIDR bit definitions
...
@@ -417,6 +418,15 @@
...
@@ -417,6 +418,15 @@
#define EC_BITS(x) (x >> ESR_EC_SHIFT) & ESR_EC_MASK
#define EC_BITS(x) (x >> ESR_EC_SHIFT) & ESR_EC_MASK
/*******************************************************************************
* Definitions of register offsets, fields and macros for CPU system
* instructions.
******************************************************************************/
#define TLBI_ADDR_SHIFT 12
#define TLBI_ADDR_MASK ULL(0x00000FFFFFFFFFFF)
#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK)
/*******************************************************************************
/*******************************************************************************
* Definitions of register offsets and fields in the CNTCTLBase Frame of the
* Definitions of register offsets and fields in the CNTCTLBase Frame of the
* system level implementation of the Generic Timer.
* system level implementation of the Generic Timer.
...
...
include/lib/aarch64/arch_helpers.h
View file @
28ee754d
...
@@ -116,14 +116,58 @@ static inline void _op ## _type(uint64_t v) \
...
@@ -116,14 +116,58 @@ static inline void _op ## _type(uint64_t v) \
/*******************************************************************************
/*******************************************************************************
* TLB maintenance accessor prototypes
* TLB maintenance accessor prototypes
******************************************************************************/
******************************************************************************/
#if ERRATA_A57_813419
/*
* Define function for TLBI instruction with type specifier that implements
* the workaround for errata 813419 of Cortex-A57.
*/
#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC(_type)\
static inline void tlbi ## _type(void) \
{ \
__asm__("tlbi " #_type "\n" \
"dsb ish\n" \
"tlbi " #_type); \
}
/*
* Define function for TLBI instruction with register parameter that implements
* the workaround for errata 813419 of Cortex-A57.
*/
#define DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC(_type) \
static inline void tlbi ## _type(uint64_t v) \
{ \
__asm__("tlbi " #_type ", %0\n" \
"dsb ish\n" \
"tlbi " #_type ", %0" : : "r" (v)); \
}
#endif
/* ERRATA_A57_813419 */
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle1
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle1
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle1is
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle1is
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle2
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle2
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle2is
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle2is
)
#if ERRATA_A57_813419
DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC
(
alle3
)
DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_FUNC
(
alle3is
)
#else
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle3
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle3
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle3is
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
alle3is
)
#endif
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
vmalle1
)
DEFINE_SYSOP_TYPE_FUNC
(
tlbi
,
vmalle1
)
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vaae1is
)
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vaale1is
)
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vae2is
)
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vale2is
)
#if ERRATA_A57_813419
DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC
(
vae3is
)
DEFINE_TLBIOP_ERRATA_A57_813419_TYPE_PARAM_FUNC
(
vale3is
)
#else
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vae3is
)
DEFINE_SYSOP_TYPE_PARAM_FUNC
(
tlbi
,
vale3is
)
#endif
/*******************************************************************************
/*******************************************************************************
* Cache maintenance accessor prototypes
* Cache maintenance accessor prototypes
******************************************************************************/
******************************************************************************/
...
@@ -181,6 +225,7 @@ DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
...
@@ -181,6 +225,7 @@ DEFINE_SYSOP_TYPE_FUNC(dmb, sy)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
st
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
st
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ld
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ld
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dsb
,
ishst
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ish
)
DEFINE_SYSOP_TYPE_FUNC
(
dmb
,
ish
)
DEFINE_SYSOP_FUNC
(
isb
)
DEFINE_SYSOP_FUNC
(
isb
)
...
...
include/lib/xlat_tables/xlat_mmu_helpers.h
0 → 100644
View file @
28ee754d
/*
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __XLAT_MMU_HELPERS_H__
#define __XLAT_MMU_HELPERS_H__
#ifdef AARCH32
/* AArch32 specific translation table API */
void
enable_mmu_secure
(
uint32_t
flags
);
#else
/* AArch64 specific translation table APIs */
void
enable_mmu_el1
(
unsigned
int
flags
);
void
enable_mmu_el3
(
unsigned
int
flags
);
#endif
/* AARCH32 */
#endif
/* __XLAT_MMU_HELPERS_H__ */
include/lib/xlat_tables/xlat_tables.h
0 → 100644
View file @
28ee754d
/*
* Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __XLAT_TABLES_H__
#define __XLAT_TABLES_H__
#include <xlat_tables_defs.h>
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
#include <xlat_mmu_helpers.h>
/* Helper macro to define entries for mmap_region_t. It creates
* identity mappings for each region.
*/
#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr)
/* Helper macro to define entries for mmap_region_t. It allows to
* re-map address mappings from 'pa' to 'va' for each region.
*/
#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
/*
* Shifts and masks to access fields of an mmap_attr_t
*/
#define MT_TYPE_MASK 0x7
#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
/* Access permissions (RO/RW) */
#define MT_PERM_SHIFT 3
/* Security state (SECURE/NS) */
#define MT_SEC_SHIFT 4
/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
#define MT_EXECUTE_SHIFT 5
/*
* Memory mapping attributes
*/
typedef
enum
{
/*
* Memory types supported.
* These are organised so that, going down the list, the memory types
* are getting weaker; conversely going up the list the memory types are
* getting stronger.
*/
MT_DEVICE
,
MT_NON_CACHEABLE
,
MT_MEMORY
,
/* Values up to 7 are reserved to add new memory types in the future */
MT_RO
=
0
<<
MT_PERM_SHIFT
,
MT_RW
=
1
<<
MT_PERM_SHIFT
,
MT_SECURE
=
0
<<
MT_SEC_SHIFT
,
MT_NS
=
1
<<
MT_SEC_SHIFT
,
/*
* Access permissions for instruction execution are only relevant for
* normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
* (and potentially overridden) otherwise:
* - Device memory is always marked as execute-never.
* - Read-write normal memory is always marked as execute-never.
*/
MT_EXECUTE
=
0
<<
MT_EXECUTE_SHIFT
,
MT_EXECUTE_NEVER
=
1
<<
MT_EXECUTE_SHIFT
,
}
mmap_attr_t
;
#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE)
#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
/*
* Structure for specifying a single region of memory.
*/
typedef
struct
mmap_region
{
unsigned
long
long
base_pa
;
uintptr_t
base_va
;
size_t
size
;
mmap_attr_t
attr
;
}
mmap_region_t
;
/* Generic translation table APIs */
void
init_xlat_tables
(
void
);
void
mmap_add_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
size_t
size
,
unsigned
int
attr
);
void
mmap_add
(
const
mmap_region_t
*
mm
);
#endif
/*__ASSEMBLY__*/
#endif
/* __XLAT_TABLES_H__ */
include/lib/xlat_tables.h
→
include/lib/xlat_tables
/xlat_tables_defs
.h
View file @
28ee754d
/*
/*
* Copyright (c) 201
4-2016
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 201
7
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -28,8 +28,10 @@
...
@@ -28,8 +28,10 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef __XLAT_TABLES_H__
#ifndef __XLAT_TABLES_DEFS_H__
#define __XLAT_TABLES_H__
#define __XLAT_TABLES_DEFS_H__
#include <utils.h>
/* Miscellaneous MMU related constants */
/* Miscellaneous MMU related constants */
#define NUM_2MB_IN_GB (1 << 9)
#define NUM_2MB_IN_GB (1 << 9)
...
@@ -48,23 +50,26 @@
...
@@ -48,23 +50,26 @@
#define BLOCK_DESC 0x1
/* Table levels 0-2 */
#define BLOCK_DESC 0x1
/* Table levels 0-2 */
#define TABLE_DESC 0x3
/* Table levels 0-2 */
#define TABLE_DESC 0x3
/* Table levels 0-2 */
#define PAGE_DESC 0x3
/* Table level 3 */
#define PAGE_DESC 0x3
/* Table level 3 */
#define DESC_MASK 0x3
#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT
#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT
#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT
#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT
#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT
#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT
#define XN (1ull << 2)
#define XN (ULL(1) << 2)
#define PXN (1ull << 1)
#define PXN (ULL(1) << 1)
#define CONT_HINT (1ull << 0)
#define CONT_HINT (ULL(1) << 0)
#define UPPER_ATTRS(x) (((x) & ULL(0x7)) << 52)
#define UPPER_ATTRS(x) (x & 0x7) << 52
#define NON_GLOBAL (1 << 9)
#define NON_GLOBAL (1 << 9)
#define ACCESS_FLAG (1 << 8)
#define ACCESS_FLAG (1 << 8)
#define NSH (0x0 << 6)
#define NSH (0x0 << 6)
#define OSH (0x2 << 6)
#define OSH (0x2 << 6)
#define ISH (0x3 << 6)
#define ISH (0x3 << 6)
#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT
#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000)
#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT
/* 4, 16 or 64 KB */
#define PAGE_SIZE (1 << PAGE_SIZE_SHIFT)
#define PAGE_SIZE (1 << PAGE_SIZE_SHIFT)
#define PAGE_SIZE_MASK (PAGE_SIZE - 1)
#define PAGE_SIZE_MASK (PAGE_SIZE - 1)
#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == 0)
#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == 0)
...
@@ -72,7 +77,7 @@
...
@@ -72,7 +77,7 @@
#define XLAT_ENTRY_SIZE_SHIFT 3
/* Each MMU table entry is 8 bytes (1 << 3) */
#define XLAT_ENTRY_SIZE_SHIFT 3
/* Each MMU table entry is 8 bytes (1 << 3) */
#define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SIZE_SHIFT)
#define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SIZE_SHIFT)
#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT
#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT
/* Size of one complete table */
#define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SIZE_SHIFT)
#define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SIZE_SHIFT)
#ifdef AARCH32
#ifdef AARCH32
...
@@ -97,7 +102,10 @@
...
@@ -97,7 +102,10 @@
((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT))
((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT))
#define XLAT_BLOCK_SIZE(level) ((u_register_t)1 << XLAT_ADDR_SHIFT(level))
#define XLAT_BLOCK_SIZE(level) ((u_register_t)1 << XLAT_ADDR_SHIFT(level))
/* Mask to get the bits used to index inside a block of a certain level */
#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - 1)
#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - 1)
/* Mask to get the address bits common to a block of a certain table level*/
#define XLAT_ADDR_MASK(level) (~XLAT_BLOCK_MASK(level))
/*
/*
* AP[1] bit is ignored by hardware and is
* AP[1] bit is ignored by hardware and is
...
@@ -111,10 +119,15 @@
...
@@ -111,10 +119,15 @@
#define ATTR_DEVICE_INDEX 0x1
#define ATTR_DEVICE_INDEX 0x1
#define ATTR_IWBWA_OWBWA_NTR_INDEX 0x0
#define ATTR_IWBWA_OWBWA_NTR_INDEX 0x0
#define LOWER_ATTRS(x) (((x) & 0xfff) << 2)
#define LOWER_ATTRS(x) (((x) & 0xfff) << 2)
/* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */
#define ATTR_NON_CACHEABLE (0x44)
#define ATTR_NON_CACHEABLE (0x44)
/* Device-nGnRE */
#define ATTR_DEVICE (0x4)
#define ATTR_DEVICE (0x4)
/* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */
#define ATTR_IWBWA_OWBWA_NTR (0xff)
#define ATTR_IWBWA_OWBWA_NTR (0xff)
#define MAIR_ATTR_SET(attr, index) (attr << (index << 3))
#define MAIR_ATTR_SET(attr, index) ((attr) << ((index) << 3))
#define ATTR_INDEX_MASK 0x3
#define ATTR_INDEX_GET(attr) (((attr) >> 2) & ATTR_INDEX_MASK)
/*
/*
* Flags to override default values used to program system registers while
* Flags to override default values used to program system registers while
...
@@ -122,91 +135,4 @@
...
@@ -122,91 +135,4 @@
*/
*/
#define DISABLE_DCACHE (1 << 0)
#define DISABLE_DCACHE (1 << 0)
#ifndef __ASSEMBLY__
#endif
/* __XLAT_TABLES_DEFS_H__ */
#include <stddef.h>
#include <stdint.h>
/* Helper macro to define entries for mmap_region_t. It creates
* identity mappings for each region.
*/
#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr)
/* Helper macro to define entries for mmap_region_t. It allows to
* re-map address mappings from 'pa' to 'va' for each region.
*/
#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
/*
* Shifts and masks to access fields of an mmap_attr_t
*/
#define MT_TYPE_MASK 0x7
#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
/* Access permissions (RO/RW) */
#define MT_PERM_SHIFT 3
/* Security state (SECURE/NS) */
#define MT_SEC_SHIFT 4
/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
#define MT_EXECUTE_SHIFT 5
/*
* Memory mapping attributes
*/
typedef
enum
{
/*
* Memory types supported.
* These are organised so that, going down the list, the memory types
* are getting weaker; conversely going up the list the memory types are
* getting stronger.
*/
MT_DEVICE
,
MT_NON_CACHEABLE
,
MT_MEMORY
,
/* Values up to 7 are reserved to add new memory types in the future */
MT_RO
=
0
<<
MT_PERM_SHIFT
,
MT_RW
=
1
<<
MT_PERM_SHIFT
,
MT_SECURE
=
0
<<
MT_SEC_SHIFT
,
MT_NS
=
1
<<
MT_SEC_SHIFT
,
/*
* Access permissions for instruction execution are only relevant for
* normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
* (and potentially overridden) otherwise:
* - Device memory is always marked as execute-never.
* - Read-write normal memory is always marked as execute-never.
*/
MT_EXECUTE
=
0
<<
MT_EXECUTE_SHIFT
,
MT_EXECUTE_NEVER
=
1
<<
MT_EXECUTE_SHIFT
,
}
mmap_attr_t
;
#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE)
#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
/*
* Structure for specifying a single region of memory.
*/
typedef
struct
mmap_region
{
unsigned
long
long
base_pa
;
uintptr_t
base_va
;
size_t
size
;
mmap_attr_t
attr
;
}
mmap_region_t
;
/* Generic translation table APIs */
void
init_xlat_tables
(
void
);
void
mmap_add_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
size_t
size
,
unsigned
int
attr
);
void
mmap_add
(
const
mmap_region_t
*
mm
);
#ifdef AARCH32
/* AArch32 specific translation table API */
void
enable_mmu_secure
(
uint32_t
flags
);
#else
/* AArch64 specific translation table APIs */
void
enable_mmu_el1
(
unsigned
int
flags
);
void
enable_mmu_el3
(
unsigned
int
flags
);
#endif
/* AARCH32 */
#endif
/*__ASSEMBLY__*/
#endif
/* __XLAT_TABLES_H__ */
include/lib/xlat_tables/xlat_tables_v2.h
0 → 100644
View file @
28ee754d
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __XLAT_TABLES_V2_H__
#define __XLAT_TABLES_V2_H__
#include <xlat_tables_defs.h>
#ifndef __ASSEMBLY__
#include <stddef.h>
#include <stdint.h>
#include <xlat_mmu_helpers.h>
/* Helper macro to define entries for mmap_region_t. It creates
* identity mappings for each region.
*/
#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr)
/* Helper macro to define entries for mmap_region_t. It allows to
* re-map address mappings from 'pa' to 'va' for each region.
*/
#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)}
/*
* Shifts and masks to access fields of an mmap_attr_t
*/
#define MT_TYPE_MASK 0x7
#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK)
/* Access permissions (RO/RW) */
#define MT_PERM_SHIFT 3
/* Security state (SECURE/NS) */
#define MT_SEC_SHIFT 4
/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
#define MT_EXECUTE_SHIFT 5
/* All other bits are reserved */
/*
* Memory mapping attributes
*/
typedef
enum
{
/*
* Memory types supported.
* These are organised so that, going down the list, the memory types
* are getting weaker; conversely going up the list the memory types are
* getting stronger.
*/
MT_DEVICE
,
MT_NON_CACHEABLE
,
MT_MEMORY
,
/* Values up to 7 are reserved to add new memory types in the future */
MT_RO
=
0
<<
MT_PERM_SHIFT
,
MT_RW
=
1
<<
MT_PERM_SHIFT
,
MT_SECURE
=
0
<<
MT_SEC_SHIFT
,
MT_NS
=
1
<<
MT_SEC_SHIFT
,
/*
* Access permissions for instruction execution are only relevant for
* normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored
* (and potentially overridden) otherwise:
* - Device memory is always marked as execute-never.
* - Read-write normal memory is always marked as execute-never.
*/
MT_EXECUTE
=
0
<<
MT_EXECUTE_SHIFT
,
MT_EXECUTE_NEVER
=
1
<<
MT_EXECUTE_SHIFT
,
}
mmap_attr_t
;
#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE)
#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
/*
* Structure for specifying a single region of memory.
*/
typedef
struct
mmap_region
{
unsigned
long
long
base_pa
;
uintptr_t
base_va
;
size_t
size
;
mmap_attr_t
attr
;
}
mmap_region_t
;
/* Generic translation table APIs */
void
init_xlat_tables
(
void
);
/*
* Add a region with defined base PA and base VA. This type of region can only
* be added before initializing the MMU and cannot be removed later.
*/
void
mmap_add_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
size_t
size
,
unsigned
int
attr
);
/*
* Add a region with defined base PA and base VA. This type of region can be
* added and removed even if the MMU is enabled.
*
* Returns:
* 0: Success.
* EINVAL: Invalid values were used as arguments.
* ERANGE: Memory limits were surpassed.
* ENOMEM: Not enough space in the mmap array or not enough free xlat tables.
* EPERM: It overlaps another region in an invalid way.
*/
int
mmap_add_dynamic_region
(
unsigned
long
long
base_pa
,
uintptr_t
base_va
,
size_t
size
,
unsigned
int
attr
);
/*
* Add an array of static regions with defined base PA and base VA. This type
* of region can only be added before initializing the MMU and cannot be
* removed later.
*/
void
mmap_add
(
const
mmap_region_t
*
mm
);
/*
* Remove a region with the specified base VA and size. Only dynamic regions can
* be removed, and they can be removed even if the MMU is enabled.
*
* Returns:
* 0: Success.
* EINVAL: The specified region wasn't found.
* EPERM: Trying to remove a static region.
*/
int
mmap_remove_dynamic_region
(
uintptr_t
base_va
,
size_t
size
);
#endif
/*__ASSEMBLY__*/
#endif
/* __XLAT_TABLES_V2_H__ */
include/plat/arm/board/common/board_arm_def.h
View file @
28ee754d
/*
/*
* Copyright (c) 2015-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -72,6 +72,9 @@
...
@@ -72,6 +72,9 @@
* Provide relatively optimised values for the runtime images (BL31 and BL32).
* Provide relatively optimised values for the runtime images (BL31 and BL32).
* Optimisation is less important for the other, transient boot images so a
* Optimisation is less important for the other, transient boot images so a
* common, maximum value is used across these images.
* common, maximum value is used across these images.
*
* They are also used for the dynamically mapped regions in the images that
* enable dynamic memory mapping.
*/
*/
#if defined(IMAGE_BL31) || defined(IMAGE_BL32)
#if defined(IMAGE_BL31) || defined(IMAGE_BL32)
# define PLAT_ARM_MMAP_ENTRIES 6
# define PLAT_ARM_MMAP_ENTRIES 6
...
...
include/plat/arm/board/common/v2m_def.h
View file @
28ee754d
/*
/*
* Copyright (c) 2015-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
#ifndef __V2M_DEF_H__
#ifndef __V2M_DEF_H__
#define __V2M_DEF_H__
#define __V2M_DEF_H__
#include <xlat_tables.h>
#include <xlat_tables
_v2
.h>
/* V2M motherboard system registers & offsets */
/* V2M motherboard system registers & offsets */
...
...
include/plat/arm/common/arm_def.h
View file @
28ee754d
...
@@ -34,7 +34,7 @@
...
@@ -34,7 +34,7 @@
#include <common_def.h>
#include <common_def.h>
#include <platform_def.h>
#include <platform_def.h>
#include <tbbr_img_def.h>
#include <tbbr_img_def.h>
#include <xlat_tables.h>
#include <xlat_tables
_defs
.h>
/******************************************************************************
/******************************************************************************
...
...
include/plat/arm/common/plat_arm.h
View file @
28ee754d
/*
/*
* Copyright (c) 2015-201
6
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-201
7
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include <cpu_data.h>
#include <cpu_data.h>
#include <stdint.h>
#include <stdint.h>
#include <utils.h>
#include <utils.h>
#include <xlat_tables.h>
#include <xlat_tables
_v2
.h>
/*******************************************************************************
/*******************************************************************************
* Forward declarations
* Forward declarations
...
...
include/plat/arm/soc/common/soc_css_def.h
View file @
28ee754d
...
@@ -32,7 +32,6 @@
...
@@ -32,7 +32,6 @@
#define __SOC_CSS_DEF_H__
#define __SOC_CSS_DEF_H__
#include <common_def.h>
#include <common_def.h>
#include <xlat_tables.h>
/*
/*
...
...
Prev
1
2
Next
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