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
f69a5828
Commit
f69a5828
authored
Jan 30, 2020
by
Alexei Fedorov
Committed by
TrustedFirmware Code Review
Jan 30, 2020
Browse files
Merge "Use correct type when reading SCR register" into integration
parents
b7e0ed2c
f1be00da
Changes
12
Show whitespace changes
Inline
Side-by-side
bl31/interrupt_mgmt.c
View file @
f69a5828
/*
/*
* Copyright (c) 2014-20
18
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -17,6 +17,11 @@
...
@@ -17,6 +17,11 @@
* registered interrupt handlers for each interrupt type.
* registered interrupt handlers for each interrupt type.
* The field descriptions are:
* The field descriptions are:
*
*
* 'scr_el3[2]' : Mapping of the routing model in the 'flags' field to the
* value of the SCR_EL3.IRQ or FIQ bit for each security state.
* There are two instances of this field corresponding to the
* two security states.
*
* 'flags' : Bit[0], Routing model for this interrupt type when execution is
* 'flags' : Bit[0], Routing model for this interrupt type when execution is
* not in EL3 in the secure state. '1' implies that this
* not in EL3 in the secure state. '1' implies that this
* interrupt will be routed to EL3. '0' implies that this
* interrupt will be routed to EL3. '0' implies that this
...
@@ -28,16 +33,11 @@
...
@@ -28,16 +33,11 @@
* interrupt will be routed to the current exception level.
* interrupt will be routed to the current exception level.
*
*
* All other bits are reserved and SBZ.
* All other bits are reserved and SBZ.
*
* 'scr_el3[2]' : Mapping of the routing model in the 'flags' field to the
* value of the SCR_EL3.IRQ or FIQ bit for each security state.
* There are two instances of this field corresponding to the
* two security states.
******************************************************************************/
******************************************************************************/
typedef
struct
intr_type_desc
{
typedef
struct
intr_type_desc
{
interrupt_type_handler_t
handler
;
interrupt_type_handler_t
handler
;
u_register_t
scr_el3
[
2
];
uint32_t
flags
;
uint32_t
flags
;
uint32_t
scr_el3
[
2
];
}
intr_type_desc_t
;
}
intr_type_desc_t
;
static
intr_type_desc_t
intr_type_descs
[
MAX_INTR_TYPES
];
static
intr_type_desc_t
intr_type_descs
[
MAX_INTR_TYPES
];
...
@@ -78,9 +78,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags)
...
@@ -78,9 +78,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags)
* routing model (expressed through the IRQ and FIQ bits) for a security state
* routing model (expressed through the IRQ and FIQ bits) for a security state
* which was stored through a call to 'set_routing_model()' earlier.
* which was stored through a call to 'set_routing_model()' earlier.
******************************************************************************/
******************************************************************************/
u
int32
_t
get_scr_el3_from_routing_model
(
uint32_t
security_state
)
u
_register
_t
get_scr_el3_from_routing_model
(
uint32_t
security_state
)
{
{
u
int32
_t
scr_el3
;
u
_register
_t
scr_el3
;
assert
(
sec_state_is_valid
(
security_state
));
assert
(
sec_state_is_valid
(
security_state
));
scr_el3
=
intr_type_descs
[
INTR_TYPE_NS
].
scr_el3
[
security_state
];
scr_el3
=
intr_type_descs
[
INTR_TYPE_NS
].
scr_el3
[
security_state
];
...
@@ -103,7 +103,7 @@ static void set_scr_el3_from_rm(uint32_t type,
...
@@ -103,7 +103,7 @@ static void set_scr_el3_from_rm(uint32_t type,
flag
=
get_interrupt_rm_flag
(
interrupt_type_flags
,
security_state
);
flag
=
get_interrupt_rm_flag
(
interrupt_type_flags
,
security_state
);
bit_pos
=
plat_interrupt_type_to_line
(
type
,
security_state
);
bit_pos
=
plat_interrupt_type_to_line
(
type
,
security_state
);
intr_type_descs
[
type
].
scr_el3
[
security_state
]
=
flag
<<
bit_pos
;
intr_type_descs
[
type
].
scr_el3
[
security_state
]
=
(
u_register_t
)
flag
<<
bit_pos
;
/*
/*
* Update scr_el3 only if there is a context available. If not, it
* Update scr_el3 only if there is a context available. If not, it
...
...
drivers/arm/gic/v3/gicv3_main.c
View file @
f69a5828
/*
/*
* Copyright (c) 2015-20
19
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -235,7 +235,7 @@ void gicv3_rdistif_on(unsigned int proc_num)
...
@@ -235,7 +235,7 @@ void gicv3_rdistif_on(unsigned int proc_num)
void
gicv3_cpuif_enable
(
unsigned
int
proc_num
)
void
gicv3_cpuif_enable
(
unsigned
int
proc_num
)
{
{
uintptr_t
gicr_base
;
uintptr_t
gicr_base
;
u
nsigned
in
t
scr_el3
;
u
_register_
t
scr_el3
;
unsigned
int
icc_sre_el3
;
unsigned
int
icc_sre_el3
;
assert
(
gicv3_driver_data
!=
NULL
);
assert
(
gicv3_driver_data
!=
NULL
);
...
@@ -258,7 +258,7 @@ void gicv3_cpuif_enable(unsigned int proc_num)
...
@@ -258,7 +258,7 @@ void gicv3_cpuif_enable(unsigned int proc_num)
icc_sre_el3
|=
(
ICC_SRE_EN_BIT
|
ICC_SRE_SRE_BIT
);
icc_sre_el3
|=
(
ICC_SRE_EN_BIT
|
ICC_SRE_SRE_BIT
);
write_icc_sre_el3
(
read_icc_sre_el3
()
|
icc_sre_el3
);
write_icc_sre_el3
(
read_icc_sre_el3
()
|
icc_sre_el3
);
scr_el3
=
(
uint32_t
)
read_scr_el3
();
scr_el3
=
read_scr_el3
();
/*
/*
* Switch to NS state to write Non secure ICC_SRE_EL1 and
* Switch to NS state to write Non secure ICC_SRE_EL1 and
...
...
include/bl31/interrupt_mgmt.h
View file @
f69a5828
/*
/*
* Copyright (c) 2014-20
18
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -134,7 +134,7 @@ typedef uint64_t (*interrupt_type_handler_t)(uint32_t id,
...
@@ -134,7 +134,7 @@ typedef uint64_t (*interrupt_type_handler_t)(uint32_t id,
/*******************************************************************************
/*******************************************************************************
* Function & variable prototypes
* Function & variable prototypes
******************************************************************************/
******************************************************************************/
u
int32
_t
get_scr_el3_from_routing_model
(
uint32_t
security_state
);
u
_register
_t
get_scr_el3_from_routing_model
(
uint32_t
security_state
);
int32_t
set_routing_model
(
uint32_t
type
,
uint32_t
flags
);
int32_t
set_routing_model
(
uint32_t
type
,
uint32_t
flags
);
int32_t
register_interrupt_type_handler
(
uint32_t
type
,
int32_t
register_interrupt_type_handler
(
uint32_t
type
,
interrupt_type_handler_t
handler
,
interrupt_type_handler_t
handler
,
...
...
include/lib/el3_runtime/context_mgmt.h
View file @
f69a5828
/*
/*
* Copyright (c) 2013-20
18
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -45,7 +45,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
...
@@ -45,7 +45,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
uint32_t
bit_pos
,
uint32_t
bit_pos
,
uint32_t
value
);
uint32_t
value
);
void
cm_set_next_eret_context
(
uint32_t
security_state
);
void
cm_set_next_eret_context
(
uint32_t
security_state
);
u
int32
_t
cm_get_scr_el3
(
uint32_t
security_state
);
u
_register
_t
cm_get_scr_el3
(
uint32_t
security_state
);
/* Inline definitions */
/* Inline definitions */
...
...
lib/el3_runtime/aarch64/context_mgmt.c
View file @
f69a5828
/*
/*
* Copyright (c) 2013-20
19
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -66,7 +66,7 @@ void __init cm_init(void)
...
@@ -66,7 +66,7 @@ void __init cm_init(void)
void
cm_setup_context
(
cpu_context_t
*
ctx
,
const
entry_point_info_t
*
ep
)
void
cm_setup_context
(
cpu_context_t
*
ctx
,
const
entry_point_info_t
*
ep
)
{
{
unsigned
int
security_state
;
unsigned
int
security_state
;
u
int32
_t
scr_el3
;
u
_register
_t
scr_el3
;
el3_state_t
*
state
;
el3_state_t
*
state
;
gp_regs_t
*
gp_regs
;
gp_regs_t
*
gp_regs
;
u_register_t
sctlr_elx
,
actlr_elx
;
u_register_t
sctlr_elx
,
actlr_elx
;
...
@@ -87,7 +87,7 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep)
...
@@ -87,7 +87,7 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep)
* the required value depending on the state of the SPSR_EL3 and the
* the required value depending on the state of the SPSR_EL3 and the
* Security state and entrypoint attributes of the next EL.
* Security state and entrypoint attributes of the next EL.
*/
*/
scr_el3
=
(
uint32_t
)
read_scr
();
scr_el3
=
read_scr
();
scr_el3
&=
~
(
SCR_NS_BIT
|
SCR_RW_BIT
|
SCR_FIQ_BIT
|
SCR_IRQ_BIT
|
scr_el3
&=
~
(
SCR_NS_BIT
|
SCR_RW_BIT
|
SCR_FIQ_BIT
|
SCR_IRQ_BIT
|
SCR_ST_BIT
|
SCR_HCE_BIT
);
SCR_ST_BIT
|
SCR_HCE_BIT
);
/*
/*
...
@@ -326,7 +326,7 @@ void cm_init_my_context(const entry_point_info_t *ep)
...
@@ -326,7 +326,7 @@ void cm_init_my_context(const entry_point_info_t *ep)
******************************************************************************/
******************************************************************************/
void
cm_prepare_el3_exit
(
uint32_t
security_state
)
void
cm_prepare_el3_exit
(
uint32_t
security_state
)
{
{
u
int32
_t
sctlr_elx
,
scr_el3
,
mdcr_el2
;
u
_register
_t
sctlr_elx
,
scr_el3
,
mdcr_el2
;
cpu_context_t
*
ctx
=
cm_get_context
(
security_state
);
cpu_context_t
*
ctx
=
cm_get_context
(
security_state
);
bool
el2_unused
=
false
;
bool
el2_unused
=
false
;
uint64_t
hcr_el2
=
0U
;
uint64_t
hcr_el2
=
0U
;
...
@@ -334,11 +334,11 @@ void cm_prepare_el3_exit(uint32_t security_state)
...
@@ -334,11 +334,11 @@ void cm_prepare_el3_exit(uint32_t security_state)
assert
(
ctx
!=
NULL
);
assert
(
ctx
!=
NULL
);
if
(
security_state
==
NON_SECURE
)
{
if
(
security_state
==
NON_SECURE
)
{
scr_el3
=
(
uint32_t
)
read_ctx_reg
(
get_el3state_ctx
(
ctx
),
scr_el3
=
read_ctx_reg
(
get_el3state_ctx
(
ctx
),
CTX_SCR_EL3
);
CTX_SCR_EL3
);
if
((
scr_el3
&
SCR_HCE_BIT
)
!=
0U
)
{
if
((
scr_el3
&
SCR_HCE_BIT
)
!=
0U
)
{
/* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
/* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
sctlr_elx
=
(
uint32_t
)
read_ctx_reg
(
get_sysregs_ctx
(
ctx
),
sctlr_elx
=
read_ctx_reg
(
get_sysregs_ctx
(
ctx
),
CTX_SCTLR_EL1
);
CTX_SCTLR_EL1
);
sctlr_elx
&=
SCTLR_EE_BIT
;
sctlr_elx
&=
SCTLR_EE_BIT
;
sctlr_elx
|=
SCTLR_EL2_RES1
;
sctlr_elx
|=
SCTLR_EL2_RES1
;
...
@@ -618,7 +618,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
...
@@ -618,7 +618,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
{
{
cpu_context_t
*
ctx
;
cpu_context_t
*
ctx
;
el3_state_t
*
state
;
el3_state_t
*
state
;
u
int32
_t
scr_el3
;
u
_register
_t
scr_el3
;
ctx
=
cm_get_context
(
security_state
);
ctx
=
cm_get_context
(
security_state
);
assert
(
ctx
!=
NULL
);
assert
(
ctx
!=
NULL
);
...
@@ -634,9 +634,9 @@ void cm_write_scr_el3_bit(uint32_t security_state,
...
@@ -634,9 +634,9 @@ void cm_write_scr_el3_bit(uint32_t security_state,
* and set it to its new value.
* and set it to its new value.
*/
*/
state
=
get_el3state_ctx
(
ctx
);
state
=
get_el3state_ctx
(
ctx
);
scr_el3
=
(
uint32_t
)
read_ctx_reg
(
state
,
CTX_SCR_EL3
);
scr_el3
=
read_ctx_reg
(
state
,
CTX_SCR_EL3
);
scr_el3
&=
~
(
1U
<<
bit_pos
);
scr_el3
&=
~
(
1U
<<
bit_pos
);
scr_el3
|=
value
<<
bit_pos
;
scr_el3
|=
(
u_register_t
)
value
<<
bit_pos
;
write_ctx_reg
(
state
,
CTX_SCR_EL3
,
scr_el3
);
write_ctx_reg
(
state
,
CTX_SCR_EL3
,
scr_el3
);
}
}
...
@@ -644,7 +644,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
...
@@ -644,7 +644,7 @@ void cm_write_scr_el3_bit(uint32_t security_state,
* This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the
* This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the
* given security state.
* given security state.
******************************************************************************/
******************************************************************************/
u
int32
_t
cm_get_scr_el3
(
uint32_t
security_state
)
u
_register
_t
cm_get_scr_el3
(
uint32_t
security_state
)
{
{
cpu_context_t
*
ctx
;
cpu_context_t
*
ctx
;
el3_state_t
*
state
;
el3_state_t
*
state
;
...
@@ -654,7 +654,7 @@ uint32_t cm_get_scr_el3(uint32_t security_state)
...
@@ -654,7 +654,7 @@ uint32_t cm_get_scr_el3(uint32_t security_state)
/* Populate EL3 state so that ERET jumps to the correct entry */
/* Populate EL3 state so that ERET jumps to the correct entry */
state
=
get_el3state_ctx
(
ctx
);
state
=
get_el3state_ctx
(
ctx
);
return
(
uint32_t
)
read_ctx_reg
(
state
,
CTX_SCR_EL3
);
return
read_ctx_reg
(
state
,
CTX_SCR_EL3
);
}
}
/*******************************************************************************
/*******************************************************************************
...
...
plat/arm/common/arm_common.c
View file @
f69a5828
/*
/*
* Copyright (c) 2015-20
19
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -173,7 +173,7 @@ unsigned int plat_get_syscnt_freq2(void)
...
@@ -173,7 +173,7 @@ unsigned int plat_get_syscnt_freq2(void)
int
plat_sdei_validate_entry_point
(
uintptr_t
ep
,
unsigned
int
client_mode
)
int
plat_sdei_validate_entry_point
(
uintptr_t
ep
,
unsigned
int
client_mode
)
{
{
uint64_t
par
,
pa
;
uint64_t
par
,
pa
;
u
int32
_t
scr_el3
;
u
_register
_t
scr_el3
;
/* Doing Non-secure address translation requires SCR_EL3.NS set */
/* Doing Non-secure address translation requires SCR_EL3.NS set */
scr_el3
=
read_scr_el3
();
scr_el3
=
read_scr_el3
();
...
...
plat/mediatek/mt8173/plat_pm.c
View file @
f69a5828
/*
/*
* Copyright (c) 2013-20
15
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -236,7 +236,7 @@ static void mt_platform_restore_context(unsigned long mpidr)
...
@@ -236,7 +236,7 @@ static void mt_platform_restore_context(unsigned long mpidr)
static
void
plat_cpu_standby
(
plat_local_state_t
cpu_state
)
static
void
plat_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
nsigned
in
t
scr
;
u
_register_
t
scr
;
scr
=
read_scr_el3
();
scr
=
read_scr_el3
();
write_scr_el3
(
scr
|
SCR_IRQ_BIT
);
write_scr_el3
(
scr
|
SCR_IRQ_BIT
);
...
...
plat/mediatek/mt8183/plat_pm.c
View file @
f69a5828
/*
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
* Copyright (c) 2019
-2020
, MediaTek Inc. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -197,7 +197,7 @@ static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
...
@@ -197,7 +197,7 @@ static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
static
void
plat_cpu_standby
(
plat_local_state_t
cpu_state
)
static
void
plat_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
nsigned
in
t
scr
;
u
_register_
t
scr
;
scr
=
read_scr_el3
();
scr
=
read_scr_el3
();
write_scr_el3
(
scr
|
SCR_IRQ_BIT
|
SCR_FIQ_BIT
);
write_scr_el3
(
scr
|
SCR_IRQ_BIT
|
SCR_FIQ_BIT
);
...
...
plat/renesas/rcar/plat_pm.c
View file @
f69a5828
/*
/*
* Copyright (c) 2015-20
19
, Renesas Electronics Corporation. All rights reserved.
* Copyright (c) 2015-20
20
, Renesas Electronics Corporation. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -56,7 +56,7 @@ static void rcar_program_mailbox(uint64_t mpidr, uint64_t address)
...
@@ -56,7 +56,7 @@ static void rcar_program_mailbox(uint64_t mpidr, uint64_t address)
static
void
rcar_cpu_standby
(
plat_local_state_t
cpu_state
)
static
void
rcar_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
int32
_t
scr_el3
=
read_scr_el3
();
u
_register
_t
scr_el3
=
read_scr_el3
();
write_scr_el3
(
scr_el3
|
SCR_IRQ_BIT
);
write_scr_el3
(
scr_el3
|
SCR_IRQ_BIT
);
dsb
();
dsb
();
...
...
plat/rockchip/common/plat_pm.c
View file @
f69a5828
/*
/*
* Copyright (c) 2013-20
16
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -182,7 +182,7 @@ void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
...
@@ -182,7 +182,7 @@ void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
******************************************************************************/
******************************************************************************/
void
rockchip_cpu_standby
(
plat_local_state_t
cpu_state
)
void
rockchip_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
nsigned
in
t
scr
;
u
_register_
t
scr
;
assert
(
cpu_state
==
PLAT_MAX_RET_STATE
);
assert
(
cpu_state
==
PLAT_MAX_RET_STATE
);
...
...
plat/socionext/synquacer/sq_psci.c
View file @
f69a5828
/*
/*
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018
-2020
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -155,7 +155,7 @@ void __dead2 sq_system_reset(void)
...
@@ -155,7 +155,7 @@ void __dead2 sq_system_reset(void)
void
sq_cpu_standby
(
plat_local_state_t
cpu_state
)
void
sq_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
nsigned
in
t
scr
;
u
_register_
t
scr
;
assert
(
cpu_state
==
SQ_LOCAL_STATE_RET
);
assert
(
cpu_state
==
SQ_LOCAL_STATE_RET
);
...
...
plat/ti/k3/common/k3_psci.c
View file @
f69a5828
/*
/*
* Copyright (c) 2017-20
18
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-20
20
, ARM Limited and Contributors. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-License-Identifier: BSD-3-Clause
*/
*/
...
@@ -25,7 +25,7 @@ uintptr_t k3_sec_entrypoint;
...
@@ -25,7 +25,7 @@ uintptr_t k3_sec_entrypoint;
static
void
k3_cpu_standby
(
plat_local_state_t
cpu_state
)
static
void
k3_cpu_standby
(
plat_local_state_t
cpu_state
)
{
{
u
nsigned
in
t
scr
;
u
_register_
t
scr
;
scr
=
read_scr_el3
();
scr
=
read_scr_el3
();
/* Enable the Non secure interrupt to wake the CPU */
/* Enable the Non secure interrupt to wake the CPU */
...
...
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