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
4ca473db
Commit
4ca473db
authored
Dec 09, 2015
by
danh-arm
Browse files
Merge pull request #456 from soby-mathew/sm/gicv3-tsp-plat-changes-v2
Modify TSP and ARM standard platforms for new GIC drivers v2
parents
8d297cc9
63b8440f
Changes
44
Show whitespace changes
Inline
Side-by-side
bl31/interrupt_mgmt.c
View file @
4ca473db
...
@@ -67,18 +67,15 @@ typedef struct intr_type_desc {
...
@@ -67,18 +67,15 @@ typedef struct intr_type_desc {
static
intr_type_desc_t
intr_type_descs
[
MAX_INTR_TYPES
];
static
intr_type_desc_t
intr_type_descs
[
MAX_INTR_TYPES
];
/*******************************************************************************
/*******************************************************************************
* This function validates the interrupt type. EL3 interrupts are currently not
* This function validates the interrupt type.
* supported.
******************************************************************************/
******************************************************************************/
static
int32_t
validate_interrupt_type
(
uint32_t
type
)
static
int32_t
validate_interrupt_type
(
uint32_t
type
)
{
{
if
(
type
==
INTR_TYPE_EL3
)
if
(
type
==
INTR_TYPE_S_EL1
||
type
==
INTR_TYPE_NS
||
return
-
ENOTSUP
;
type
==
INTR_TYPE_EL3
)
return
0
;
if
(
type
!=
INTR_TYPE_S_EL1
&&
type
!=
INTR_TYPE_NS
)
return
-
EINVAL
;
return
-
EINVAL
;
return
0
;
}
}
/*******************************************************************************
/*******************************************************************************
...
@@ -95,6 +92,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags)
...
@@ -95,6 +92,9 @@ static int32_t validate_routing_model(uint32_t type, uint32_t flags)
if
(
type
==
INTR_TYPE_NS
)
if
(
type
==
INTR_TYPE_NS
)
return
validate_ns_interrupt_rm
(
flags
);
return
validate_ns_interrupt_rm
(
flags
);
if
(
type
==
INTR_TYPE_EL3
)
return
validate_el3_interrupt_rm
(
flags
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
...
bl32/tsp/aarch64/tsp_entrypoint.S
View file @
4ca473db
...
@@ -177,7 +177,7 @@ func tsp_vector_table
...
@@ -177,7 +177,7 @@ func tsp_vector_table
b
tsp_cpu_off_entry
b
tsp_cpu_off_entry
b
tsp_cpu_resume_entry
b
tsp_cpu_resume_entry
b
tsp_cpu_suspend_entry
b
tsp_cpu_suspend_entry
b
tsp_
fiq
_entry
b
tsp_
sel1_intr
_entry
b
tsp_system_off_entry
b
tsp_system_off_entry
b
tsp_system_reset_entry
b
tsp_system_reset_entry
endfunc
tsp_vector_table
endfunc
tsp_vector_table
...
@@ -325,13 +325,15 @@ func tsp_cpu_suspend_entry
...
@@ -325,13 +325,15 @@ func tsp_cpu_suspend_entry
restore_args_call_smc
restore_args_call_smc
endfunc
tsp_cpu_suspend_entry
endfunc
tsp_cpu_suspend_entry
/*---------------------------------------------
/*---------------------------------------------
----
*
This
entrypoint
is
used
by
the
TSPD
to
pass
*
This
entrypoint
is
used
by
the
TSPD
to
pass
*
control
for
handling
a
pending
S
-
EL1
FIQ
.
*
control
for
`
synchronously
`
handling
a
S
-
EL1
*
'x0'
contains
a
magic
number
which
indicates
*
Interrupt
which
was
triggered
while
executing
*
this
.
TSPD
expects
control
to
be
handed
back
*
in
normal
world
.
'x0'
contains
a
magic
number
*
at
the
end
of
FIQ
processing
.
This
is
done
*
which
indicates
this
.
TSPD
expects
control
to
*
through
an
SMC
.
The
handover
agreement
is
:
*
be
handed
back
at
the
end
of
interrupt
*
processing
.
This
is
done
through
an
SMC
.
*
The
handover
agreement
is
:
*
*
*
1
.
PSTATE
.
DAIF
are
set
upon
entry
.
'x1'
has
*
1
.
PSTATE
.
DAIF
are
set
upon
entry
.
'x1'
has
*
the
ELR_EL3
from
the
non
-
secure
state
.
*
the
ELR_EL3
from
the
non
-
secure
state
.
...
@@ -343,40 +345,54 @@ endfunc tsp_cpu_suspend_entry
...
@@ -343,40 +345,54 @@ endfunc tsp_cpu_suspend_entry
*
4
.
TSP
can
use
'x0-x18'
to
enable
its
C
*
4
.
TSP
can
use
'x0-x18'
to
enable
its
C
*
runtime
.
*
runtime
.
*
5
.
TSP
returns
to
TSPD
using
an
SMC
with
*
5
.
TSP
returns
to
TSPD
using
an
SMC
with
*
'x0'
=
TSP_HANDLED_S_EL1_
FIQ
*
'x0'
=
TSP_HANDLED_S_EL1_
INTR
*
---------------------------------------------
*
---------------------------------------------
---
*/
*/
func
tsp_
fiq
_entry
func
tsp_
sel1_intr
_entry
#if DEBUG
#if DEBUG
mov
x2
,
#(
TSP_HANDLE_FIQ_AND_RETURN
&
~
0xffff
)
mov_imm
x2
,
TSP_HANDLE_SEL1_INTR_AND_RETURN
movk
x2
,
#(
TSP_HANDLE_FIQ_AND_RETURN
&
0xffff
)
cmp
x0
,
x2
cmp
x0
,
x2
b.ne
tsp_
fiq
_entry_panic
b.ne
tsp_
sel1_int
_entry_panic
#endif
#endif
/*---------------------------------------------
/*---------------------------------------------
----
*
Save
any
previous
context
needed
to
perform
*
Save
any
previous
context
needed
to
perform
*
an
exception
return
from
S
-
EL1
e
.
g
.
context
*
an
exception
return
from
S
-
EL1
e
.
g
.
context
*
from
a
previous
IRQ
.
Update
statistics
and
*
from
a
previous
Non
secure
Interrupt
.
*
handle
the
FIQ
before
returning
to
the
TSPD
.
*
Update
statistics
and
handle
the
S
-
EL1
*
interrupt
before
returning
to
the
TSPD
.
*
IRQ
/
FIQs
are
not
enabled
since
that
will
*
IRQ
/
FIQs
are
not
enabled
since
that
will
*
complicate
the
implementation
.
Execution
*
complicate
the
implementation
.
Execution
*
will
be
transferred
back
to
the
normal
world
*
will
be
transferred
back
to
the
normal
world
*
in
any
case
.
A
non
-
zero
return
value
from
the
*
in
any
case
.
The
handler
can
return
0
*
fiq
handler
is
an
error
.
*
if
the
interrupt
was
handled
or
TSP_PREEMPTED
*
---------------------------------------------
*
if
the
expected
interrupt
was
preempted
*
by
an
interrupt
that
should
be
handled
in
EL3
*
e
.
g
.
Group
0
interrupt
in
GICv3
.
In
both
*
the
cases
switch
to
EL3
using
SMC
with
id
*
TSP_HANDLED_S_EL1_INTR
.
Any
other
return
value
*
from
the
handler
will
result
in
panic
.
*
------------------------------------------------
*/
*/
save_eret_context
x2
x3
save_eret_context
x2
x3
bl
tsp_update_sync_fiq_stats
bl
tsp_update_sync_sel1_intr_stats
bl
tsp_fiq_handler
bl
tsp_common_int_handler
cbnz
x0
,
tsp_fiq_entry_panic
/
*
Check
if
the
S
-
EL1
interrupt
has
been
handled
*/
cbnz
x0
,
tsp_sel1_intr_check_preemption
b
tsp_sel1_intr_return
tsp_sel1_intr_check_preemption
:
/
*
Check
if
the
S
-
EL1
interrupt
has
been
preempted
*/
mov_imm
x1
,
TSP_PREEMPTED
cmp
x0
,
x1
b.ne
tsp_sel1_int_entry_panic
tsp_sel1_intr_return
:
mov_imm
x0
,
TSP_HANDLED_S_EL1_INTR
restore_eret_context
x2
x3
restore_eret_context
x2
x3
mov
x0
,
#(
TSP_HANDLED_S_EL1_FIQ
&
~
0xffff
)
movk
x0
,
#(
TSP_HANDLED_S_EL1_FIQ
&
0xffff
)
smc
#
0
smc
#
0
tsp_fiq_entry_panic
:
/
*
Should
never
reach
here
*/
b
tsp_fiq_entry_panic
tsp_sel1_int_entry_panic
:
endfunc
tsp_fiq_entry
b
tsp_sel1_int_entry_panic
endfunc
tsp_sel1_intr_entry
/*---------------------------------------------
/*---------------------------------------------
*
This
entrypoint
is
used
by
the
TSPD
when
this
*
This
entrypoint
is
used
by
the
TSPD
when
this
...
...
bl32/tsp/aarch64/tsp_exceptions.S
View file @
4ca473db
...
@@ -70,6 +70,28 @@
...
@@ -70,6 +70,28 @@
add
sp
,
sp
,
SCRATCH_REG_SIZE
add
sp
,
sp
,
SCRATCH_REG_SIZE
.
endm
.
endm
/
*
----------------------------------------------------
*
Common
TSP
interrupt
handling
routine
*
----------------------------------------------------
*/
.
macro
handle_tsp_interrupt
label
/
*
Enable
the
SError
interrupt
*/
msr
daifclr
,
#
DAIF_ABT_BIT
save_caller_regs_and_lr
bl
tsp_common_int_handler
cbz
x0
,
interrupt_exit_
\
label
/
*
*
This
interrupt
was
not
targetted
to
S
-
EL1
so
send
it
to
*
the
monitor
and
wait
for
execution
to
resume
.
*/
smc
#
0
interrupt_exit_
\
label
:
restore_caller_regs_and_lr
eret
.
endm
.
globl
tsp_exceptions
.
globl
tsp_exceptions
/
*
-----------------------------------------------------
/
*
-----------------------------------------------------
...
@@ -120,36 +142,12 @@ sync_exception_sp_elx:
...
@@ -120,36 +142,12 @@ sync_exception_sp_elx:
.
align
7
.
align
7
irq_sp_elx
:
irq_sp_elx
:
/
*
Enable
the
SError
interrupt
*/
handle_tsp_interrupt
irq_sp_elx
msr
daifclr
,
#
DAIF_ABT_BIT
save_caller_regs_and_lr
/
*
We
just
update
some
statistics
in
the
handler
*/
bl
tsp_irq_received
/
*
Hand
over
control
to
the
normal
world
to
handle
the
IRQ
*/
smc
#
0
/
*
The
resume
std
smc
starts
from
here
*/
restore_caller_regs_and_lr
eret
check_vector_size
irq_sp_elx
check_vector_size
irq_sp_elx
.
align
7
.
align
7
fiq_sp_elx
:
fiq_sp_elx
:
/
*
Enable
the
SError
interrupt
*/
handle_tsp_interrupt
fiq_sp_elx
msr
daifclr
,
#
DAIF_ABT_BIT
save_caller_regs_and_lr
bl
tsp_fiq_handler
cbz
x0
,
fiq_sp_elx_done
/
*
*
This
FIQ
was
not
targetted
to
S
-
EL1
so
send
it
to
*
the
monitor
and
wait
for
execution
to
resume
.
*/
smc
#
0
fiq_sp_elx_done
:
restore_caller_regs_and_lr
eret
check_vector_size
fiq_sp_elx
check_vector_size
fiq_sp_elx
.
align
7
.
align
7
...
...
bl32/tsp/tsp_interrupt.c
View file @
4ca473db
...
@@ -31,50 +31,70 @@
...
@@ -31,50 +31,70 @@
#include <arch_helpers.h>
#include <arch_helpers.h>
#include <assert.h>
#include <assert.h>
#include <debug.h>
#include <debug.h>
#include <gic_v2.h>
#include <platform.h>
#include <platform.h>
#include <platform_def.h>
#include <platform_def.h>
#include <tsp.h>
#include <tsp.h>
#include "tsp_private.h"
#include "tsp_private.h"
/*******************************************************************************
/*******************************************************************************
* This function updates the TSP statistics for FIQs handled synchronously i.e
* This function updates the TSP statistics for S-EL1 interrupts handled
* the ones that have been handed over by the TSPD. It also keeps count of the
* synchronously i.e the ones that have been handed over by the TSPD. It also
* number of times control was passed back to the TSPD after handling an FIQ.
* keeps count of the number of times control was passed back to the TSPD
* In the future it will be possible that the TSPD hands over an FIQ to the TSP
* after handling the interrupt. In the future it will be possible that the
* but does not expect it to return execution. This statistic will be useful to
* TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to
* distinguish between these two models of synchronous FIQ handling.
* return execution. This statistic will be useful to distinguish between these
* The 'elr_el3' parameter contains the address of the instruction in normal
* two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter
* world where this FIQ was generated.
* contains the address of the instruction in normal world where this S-EL1
* interrupt was generated.
******************************************************************************/
******************************************************************************/
void
tsp_update_sync_
fiq
_stats
(
uint32_t
type
,
uint64_t
elr_el3
)
void
tsp_update_sync_
sel1_intr
_stats
(
uint32_t
type
,
uint64_t
elr_el3
)
{
{
uint32_t
linear_id
=
plat_my_core_pos
();
uint32_t
linear_id
=
plat_my_core_pos
();
tsp_stats
[
linear_id
].
sync_
fiq
_count
++
;
tsp_stats
[
linear_id
].
sync_
sel1_intr
_count
++
;
if
(
type
==
TSP_HANDLE_
FIQ
_AND_RETURN
)
if
(
type
==
TSP_HANDLE_
SEL1_INTR
_AND_RETURN
)
tsp_stats
[
linear_id
].
sync_
fiq
_ret_count
++
;
tsp_stats
[
linear_id
].
sync_
sel1_intr
_ret_count
++
;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock
(
&
console_lock
);
spin_lock
(
&
console_lock
);
VERBOSE
(
"TSP: cpu 0x%lx sync
fiq
request from 0x%lx
\n
"
,
VERBOSE
(
"TSP: cpu 0x%lx sync
s-el1 interrupt
request from 0x%lx
\n
"
,
read_mpidr
(),
elr_el3
);
read_mpidr
(),
elr_el3
);
VERBOSE
(
"TSP: cpu 0x%lx: %d sync fiq requests, %d sync fiq returns
\n
"
,
VERBOSE
(
"TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
" %d sync s-el1 interrupt returns
\n
"
,
read_mpidr
(),
read_mpidr
(),
tsp_stats
[
linear_id
].
sync_
fiq
_count
,
tsp_stats
[
linear_id
].
sync_
sel1_intr
_count
,
tsp_stats
[
linear_id
].
sync_
fiq
_ret_count
);
tsp_stats
[
linear_id
].
sync_
sel1_intr
_ret_count
);
spin_unlock
(
&
console_lock
);
spin_unlock
(
&
console_lock
);
#endif
#endif
}
}
/******************************************************************************
* This function is invoked when a non S-EL1 interrupt is received and causes
* the preemption of TSP. This function returns TSP_PREEMPTED and results
* in the control being handed over to EL3 for handling the interrupt.
*****************************************************************************/
int32_t
tsp_handle_preemption
(
void
)
{
uint32_t
linear_id
=
plat_my_core_pos
();
tsp_stats
[
linear_id
].
preempt_intr_count
++
;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock
(
&
console_lock
);
VERBOSE
(
"TSP: cpu 0x%lx: %d preempt interrupt requests
\n
"
,
read_mpidr
(),
tsp_stats
[
linear_id
].
preempt_intr_count
);
spin_unlock
(
&
console_lock
);
#endif
return
TSP_PREEMPTED
;
}
/*******************************************************************************
/*******************************************************************************
* TSP
FIQ
handler called as a part of both synchronous and
asynchronous
* TSP
interrupt
handler
is
called as a part of both synchronous and
* handling of
FIQ
interrupts.
It returns 0 upon successfully handling a S-EL1
*
asynchronous
handling of
TSP
interrupts.
Currently the physical timer
*
FIQ and treats all other FIQs as
EL
3
interrupt
s. It assume
s
t
ha
t the GIC
*
interrupt is the only S-
EL
1
interrupt
that thi
s ha
ndler expects. It returns
*
architecture version in v2.0 and the secure physical timer
interrupt
is
the
*
0 upon successfully handling the expected
interrupt
and all o
the
r
*
only S-EL1 interrupt that it needs to handle
.
*
interrupts are treated as normal world or EL3 interrupts
.
******************************************************************************/
******************************************************************************/
int32_t
tsp_
fiq
_handler
(
void
)
int32_t
tsp_
common_int
_handler
(
void
)
{
{
uint32_t
linear_id
=
plat_my_core_pos
(),
id
;
uint32_t
linear_id
=
plat_my_core_pos
(),
id
;
...
@@ -82,16 +102,21 @@ int32_t tsp_fiq_handler(void)
...
@@ -82,16 +102,21 @@ int32_t tsp_fiq_handler(void)
* Get the highest priority pending interrupt id and see if it is the
* Get the highest priority pending interrupt id and see if it is the
* secure physical generic timer interrupt in which case, handle it.
* secure physical generic timer interrupt in which case, handle it.
* Otherwise throw this interrupt at the EL3 firmware.
* Otherwise throw this interrupt at the EL3 firmware.
*
* There is a small time window between reading the highest priority
* pending interrupt and acknowledging it during which another
* interrupt of higher priority could become the highest pending
* interrupt. This is not expected to happen currently for TSP.
*/
*/
id
=
plat_ic_get_pending_interrupt_id
();
id
=
plat_ic_get_pending_interrupt_id
();
/* TSP can only handle the secure physical timer interrupt */
/* TSP can only handle the secure physical timer interrupt */
if
(
id
!=
TSP_IRQ_SEC_PHY_TIMER
)
if
(
id
!=
TSP_IRQ_SEC_PHY_TIMER
)
return
TSP_EL3_FIQ
;
return
tsp_handle_preemption
()
;
/*
/*
*
Handle the interrupt. Also sanity check if it has been preempted by
*
Acknowledge and handle the secure timer interrupt. Also sanity check
* another
secure
interrupt through an assertion.
*
if it has been preempted by
another interrupt through an assertion.
*/
*/
id
=
plat_ic_acknowledge_interrupt
();
id
=
plat_ic_acknowledge_interrupt
();
assert
(
id
==
TSP_IRQ_SEC_PHY_TIMER
);
assert
(
id
==
TSP_IRQ_SEC_PHY_TIMER
);
...
@@ -99,29 +124,14 @@ int32_t tsp_fiq_handler(void)
...
@@ -99,29 +124,14 @@ int32_t tsp_fiq_handler(void)
plat_ic_end_of_interrupt
(
id
);
plat_ic_end_of_interrupt
(
id
);
/* Update the statistics and print some messages */
/* Update the statistics and print some messages */
tsp_stats
[
linear_id
].
fiq
_count
++
;
tsp_stats
[
linear_id
].
sel1_intr
_count
++
;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock
(
&
console_lock
);
spin_lock
(
&
console_lock
);
VERBOSE
(
"TSP: cpu 0x%lx handled
fiq
%d
\n
"
,
VERBOSE
(
"TSP: cpu 0x%lx handled
S-EL1 interrupt
%d
\n
"
,
read_mpidr
(),
id
);
read_mpidr
(),
id
);
VERBOSE
(
"TSP: cpu 0x%lx: %d
fiq
requests
\n
"
,
VERBOSE
(
"TSP: cpu 0x%lx: %d
S-EL1
requests
\n
"
,
read_mpidr
(),
tsp_stats
[
linear_id
].
fiq
_count
);
read_mpidr
(),
tsp_stats
[
linear_id
].
sel1_intr
_count
);
spin_unlock
(
&
console_lock
);
spin_unlock
(
&
console_lock
);
#endif
#endif
return
0
;
return
0
;
}
}
int32_t
tsp_irq_received
(
void
)
{
uint32_t
linear_id
=
plat_my_core_pos
();
tsp_stats
[
linear_id
].
irq_count
++
;
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
spin_lock
(
&
console_lock
);
VERBOSE
(
"TSP: cpu 0x%lx received irq
\n
"
,
read_mpidr
());
VERBOSE
(
"TSP: cpu 0x%lx: %d irq requests
\n
"
,
read_mpidr
(),
tsp_stats
[
linear_id
].
irq_count
);
spin_unlock
(
&
console_lock
);
#endif
return
TSP_PREEMPTED
;
}
bl32/tsp/tsp_private.h
View file @
4ca473db
...
@@ -54,10 +54,14 @@
...
@@ -54,10 +54,14 @@
typedef
struct
work_statistics
{
typedef
struct
work_statistics
{
uint32_t
fiq_count
;
/* Number of FIQs on this cpu */
/* Number of s-el1 interrupts on this cpu */
uint32_t
irq_count
;
/* Number of IRQs on this cpu */
uint32_t
sel1_intr_count
;
uint32_t
sync_fiq_count
;
/* Number of sync. fiqs on this cpu */
/* Number of non s-el1 interrupts on this cpu which preempted TSP */
uint32_t
sync_fiq_ret_count
;
/* Number of fiq returns on this cpu */
uint32_t
preempt_intr_count
;
/* Number of sync s-el1 interrupts on this cpu */
uint32_t
sync_sel1_intr_count
;
/* Number of s-el1 interrupts returns on this cpu */
uint32_t
sync_sel1_intr_ret_count
;
uint32_t
smc_count
;
/* Number of returns on this cpu */
uint32_t
smc_count
;
/* Number of returns on this cpu */
uint32_t
eret_count
;
/* Number of entries on this cpu */
uint32_t
eret_count
;
/* Number of entries on this cpu */
uint32_t
cpu_on_count
;
/* Number of cpu on requests */
uint32_t
cpu_on_count
;
/* Number of cpu on requests */
...
@@ -115,8 +119,8 @@ void tsp_generic_timer_stop(void);
...
@@ -115,8 +119,8 @@ void tsp_generic_timer_stop(void);
void
tsp_generic_timer_save
(
void
);
void
tsp_generic_timer_save
(
void
);
void
tsp_generic_timer_restore
(
void
);
void
tsp_generic_timer_restore
(
void
);
/*
FIQ
management functions */
/*
S-EL1 interrupt
management functions */
void
tsp_update_sync_
fiq
_stats
(
uint32_t
type
,
uint64_t
elr_el3
);
void
tsp_update_sync_
sel1_intr
_stats
(
uint32_t
type
,
uint64_t
elr_el3
);
/* Data structure to keep track of TSP statistics */
/* Data structure to keep track of TSP statistics */
...
...
docs/interrupt-framework-design.md
View file @
4ca473db
...
@@ -399,12 +399,12 @@ requirements mentioned earlier.
...
@@ -399,12 +399,12 @@ requirements mentioned earlier.
1.
It passes control to the Test Secure Payload to perform its
1.
It passes control to the Test Secure Payload to perform its
initialisation. The TSP provides the address of the vector table
initialisation. The TSP provides the address of the vector table
`tsp_vectors`
in the SP which also includes the handler for Secure-EL1
`tsp_vectors`
in the SP which also includes the handler for Secure-EL1
interrupts in the
`
fiq
_entry`
field. The TSPD passes control to the TSP at
interrupts in the
`
sel1_intr
_entry`
field. The TSPD passes control to the TSP at
this address when it receives a Secure-EL1 interrupt.
this address when it receives a Secure-EL1 interrupt.
The handover agreement between the TSP and the TSPD requires that the TSPD
The handover agreement between the TSP and the TSPD requires that the TSPD
masks all interrupts (`PSTATE.DAIF` bits) when it calls
masks all interrupts (`PSTATE.DAIF` bits) when it calls
`tsp_
fiq
_entry()`. The TSP has to preserve the callee saved general
`tsp_
sel1_intr
_entry()`. The TSP has to preserve the callee saved general
purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use
`x0-x18` to enable its C runtime.
`x0-x18` to enable its C runtime.
...
@@ -514,7 +514,7 @@ runtime firmware is not aware of through its platform port.
...
@@ -514,7 +514,7 @@ runtime firmware is not aware of through its platform port.
The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is
described in Section 2.2.2. It is known to the TSPD service at build time.
described in Section 2.2.2. It is known to the TSPD service at build time.
The TSP implements an entrypoint (
`tsp_
fiq
_entry()`
) for handling Secure-EL1
The TSP implements an entrypoint (
`tsp_
sel1_intr
_entry()`
) for handling Secure-EL1
interrupts taken in non-secure state and routed through the TSPD service
interrupts taken in non-secure state and routed through the TSPD service
(synchronous handling model). It passes the reference to this entrypoint via
(synchronous handling model). It passes the reference to this entrypoint via
`tsp_vectors`
to the TSPD service.
`tsp_vectors`
to the TSPD service.
...
@@ -700,9 +700,9 @@ takes the following actions upon being invoked.
...
@@ -700,9 +700,9 @@ takes the following actions upon being invoked.
3.
It saves the system register context for the non-secure state by calling
3.
It saves the system register context for the non-secure state by calling
`cm_el1_sysregs_context_save(NON_SECURE);`
.
`cm_el1_sysregs_context_save(NON_SECURE);`
.
4.
It sets the
`ELR_EL3`
system register to
`tsp_
fiq
_entry`
and sets the
4.
It sets the
`ELR_EL3`
system register to
`tsp_
sel1_intr
_entry`
and sets the
`SPSR_EL3.DAIF`
bits in the secure CPU context. It sets
`x0`
to
`SPSR_EL3.DAIF`
bits in the secure CPU context. It sets
`x0`
to
`TSP_HANDLE_
FIQ
_AND_RETURN`
. If the TSP was in the middle of handling a
`TSP_HANDLE_
SEL1_INTR
_AND_RETURN`
. If the TSP was in the middle of handling a
standard SMC, then the
`ELR_EL3`
and
`SPSR_EL3`
registers in the secure CPU
standard SMC, then the
`ELR_EL3`
and
`SPSR_EL3`
registers in the secure CPU
context are saved first.
context are saved first.
...
@@ -723,20 +723,20 @@ state.
...
@@ -723,20 +723,20 @@ state.
![
Image 1
](
diagrams/sec-int-handling.png?raw=true
)
![
Image 1
](
diagrams/sec-int-handling.png?raw=true
)
The TSP issues an SMC with
`TSP_HANDLED_S_EL1_
FIQ
`
as the function identifier to
The TSP issues an SMC with
`TSP_HANDLED_S_EL1_
INTR
`
as the function identifier to
signal completion of interrupt handling.
signal completion of interrupt handling.
The TSP issues an SMC with
`TSP_PREEMPTED`
as the function identifier to signal
The TSP issues an SMC with
`TSP_PREEMPTED`
as the function identifier to signal
generation of a non-secure interrupt in Secure-EL1.
generation of a non-secure interrupt in Secure-EL1.
The TSPD service takes the following actions in
`tspd_smc_handler()`
function
The TSPD service takes the following actions in
`tspd_smc_handler()`
function
upon receiving an SMC with
`TSP_HANDLED_S_EL1_
FIQ
`
and
`TSP_PREEMPTED`
as the
upon receiving an SMC with
`TSP_HANDLED_S_EL1_
INTR
`
and
`TSP_PREEMPTED`
as the
function identifiers:
function identifiers:
1.
It ensures that the call originated from the secure state otherwise
1.
It ensures that the call originated from the secure state otherwise
execution returns to the non-secure state with
`SMC_UNK`
in
`x0`
.
execution returns to the non-secure state with
`SMC_UNK`
in
`x0`
.
2.
If the function identifier is
`TSP_HANDLED_S_EL1_
FIQ
`
, it restores the
2.
If the function identifier is
`TSP_HANDLED_S_EL1_
INTR
`
, it restores the
saved
`ELR_EL3`
and
`SPSR_EL3`
system registers back to the secure CPU
saved
`ELR_EL3`
and
`SPSR_EL3`
system registers back to the secure CPU
context (see step 4 above) in case the TSP had been preempted by a non
context (see step 4 above) in case the TSP had been preempted by a non
secure interrupt earlier. It does not save the secure context since the
secure interrupt earlier. It does not save the secure context since the
...
@@ -811,7 +811,7 @@ state.
...
@@ -811,7 +811,7 @@ state.
##### 2.3.3.1 Test secure payload behavior
##### 2.3.3.1 Test secure payload behavior
The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
The TSPD hands control of a Secure-EL1 interrupt to the TSP at the
`
tsp_
fiq
_entry()
`. The TSP handles the interrupt while ensuring that the
`
tsp_
sel1_intr
_entry()
`. The TSP handles the interrupt while ensuring that the
handover agreement described in Section 2.2.2.1 is maintained. It updates some
handover agreement described in Section 2.2.2.1 is maintained. It updates some
statistics by calling `
tsp_update_sync_fiq_stats()
`. It then calls
statistics by calling `
tsp_update_sync_fiq_stats()
`. It then calls
`
tsp_fiq_handler()
` which.
`
tsp_fiq_handler()
` which.
...
@@ -827,7 +827,7 @@ statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
...
@@ -827,7 +827,7 @@ statistics by calling `tsp_update_sync_fiq_stats()`. It then calls
end of interrupt processing.
end of interrupt processing.
The TSP passes control back to the TSPD by issuing an SMC64 with
The TSP passes control back to the TSPD by issuing an SMC64 with
`
TSP_HANDLED_S_EL1_
FIQ
` as the function identifier.
`
TSP_HANDLED_S_EL1_
INTR
` as the function identifier.
The TSP handles interrupts under the asynchronous model as follows.
The TSP handles interrupts under the asynchronous model as follows.
...
...
docs/user-guide.md
View file @
4ca473db
...
@@ -278,10 +278,13 @@ performed.
...
@@ -278,10 +278,13 @@ performed.
(Coherent memory region is included) or 0 (Coherent memory region is
(Coherent memory region is included) or 0 (Coherent memory region is
excluded). Default is 1.
excluded). Default is 1.
*
`TSPD_ROUTE_IRQ_TO_EL3`
: A non zero value enables the routing model
*
`TSP_NS_INTR_ASYNC_PREEMPT`
: A non zero value enables the interrupt
for non-secure interrupts in which they are routed to EL3 (TSPD). The
routing model which routes non-secure interrupts asynchronously from TSP
default model (when the value is 0) is to route non-secure interrupts
to EL3 causing immediate preemption of TSP. The EL3 is responsible
to S-EL1 (TSP).
for saving and restoring the TSP context in this routing model. The
default routing model (when the value is 0) is to route non-secure
interrupts to TSP allowing it to save its context and hand over
synchronously to EL3 via an SMC.
*
`TRUSTED_BOARD_BOOT`
: Boolean flag to include support for the Trusted Board
*
`TRUSTED_BOARD_BOOT`
: Boolean flag to include support for the Trusted Board
Boot feature. When set to '1', BL1 and BL2 images include support to load
Boot feature. When set to '1', BL1 and BL2 images include support to load
...
...
drivers/arm/gic/v3/gicv3_helpers.c
View file @
4ca473db
...
@@ -312,7 +312,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
...
@@ -312,7 +312,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
unsigned
int
index
,
irq_num
;
unsigned
int
index
,
irq_num
;
uint64_t
gic_affinity_val
;
uint64_t
gic_affinity_val
;
assert
((
int_grp
==
INT
_TYPE_G
1S
)
||
(
int_grp
==
INT
_TYPE_G
0
));
assert
((
int_grp
==
INT
R_GROUP
1S
)
||
(
int_grp
==
INT
R_GROUP
0
));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert
(
num_ints
?
(
uintptr_t
)
sec_intr_list
:
1
);
assert
(
num_ints
?
(
uintptr_t
)
sec_intr_list
:
1
);
...
@@ -324,7 +324,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
...
@@ -324,7 +324,7 @@ void gicv3_secure_spis_configure(uintptr_t gicd_base,
gicd_clr_igroupr
(
gicd_base
,
irq_num
);
gicd_clr_igroupr
(
gicd_base
,
irq_num
);
/* Configure this interrupt as G0 or a G1S interrupt */
/* Configure this interrupt as G0 or a G1S interrupt */
if
(
int_grp
==
INT
_TYPE_G
1S
)
if
(
int_grp
==
INT
R_GROUP
1S
)
gicd_set_igrpmodr
(
gicd_base
,
irq_num
);
gicd_set_igrpmodr
(
gicd_base
,
irq_num
);
else
else
gicd_clr_igrpmodr
(
gicd_base
,
irq_num
);
gicd_clr_igrpmodr
(
gicd_base
,
irq_num
);
...
@@ -386,7 +386,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
...
@@ -386,7 +386,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
{
{
unsigned
int
index
,
irq_num
;
unsigned
int
index
,
irq_num
;
assert
((
int_grp
==
INT
_TYPE_G
1S
)
||
(
int_grp
==
INT
_TYPE_G
0
));
assert
((
int_grp
==
INT
R_GROUP
1S
)
||
(
int_grp
==
INT
R_GROUP
0
));
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
/* If `num_ints` is not 0, ensure that `sec_intr_list` is not NULL */
assert
(
num_ints
?
(
uintptr_t
)
sec_intr_list
:
1
);
assert
(
num_ints
?
(
uintptr_t
)
sec_intr_list
:
1
);
...
@@ -398,7 +398,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
...
@@ -398,7 +398,7 @@ void gicv3_secure_ppi_sgi_configure(uintptr_t gicr_base,
gicr_clr_igroupr0
(
gicr_base
,
irq_num
);
gicr_clr_igroupr0
(
gicr_base
,
irq_num
);
/* Configure this interrupt as G0 or a G1S interrupt */
/* Configure this interrupt as G0 or a G1S interrupt */
if
(
int_grp
==
INT
_TYPE_G
1S
)
if
(
int_grp
==
INT
R_GROUP
1S
)
gicr_set_igrpmodr0
(
gicr_base
,
irq_num
);
gicr_set_igrpmodr0
(
gicr_base
,
irq_num
);
else
else
gicr_clr_igrpmodr0
(
gicr_base
,
irq_num
);
gicr_clr_igrpmodr0
(
gicr_base
,
irq_num
);
...
...
drivers/arm/gic/v3/gicv3_main.c
View file @
4ca473db
...
@@ -144,13 +144,13 @@ void gicv3_distif_init(void)
...
@@ -144,13 +144,13 @@ void gicv3_distif_init(void)
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_array
,
driver_data
->
g1s_interrupt_array
,
INT
_TYPE_G
1S
);
INT
R_GROUP
1S
);
/* Configure the G0 SPIs */
/* Configure the G0 SPIs */
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
gicv3_secure_spis_configure
(
driver_data
->
gicd_base
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_array
,
driver_data
->
g0_interrupt_array
,
INT
_TYPE_G
0
);
INT
R_GROUP
0
);
/* Enable the secure SPIs now that they have been configured */
/* Enable the secure SPIs now that they have been configured */
gicd_set_ctlr
(
driver_data
->
gicd_base
,
gicd_set_ctlr
(
driver_data
->
gicd_base
,
...
@@ -186,13 +186,13 @@ void gicv3_rdistif_init(unsigned int proc_num)
...
@@ -186,13 +186,13 @@ void gicv3_rdistif_init(unsigned int proc_num)
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_num
,
driver_data
->
g1s_interrupt_array
,
driver_data
->
g1s_interrupt_array
,
INT
_TYPE_G
1S
);
INT
R_GROUP
1S
);
/* Configure the G0 SGIs/PPIs */
/* Configure the G0 SGIs/PPIs */
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
gicv3_secure_ppi_sgi_configure
(
gicr_base
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_num
,
driver_data
->
g0_interrupt_array
,
driver_data
->
g0_interrupt_array
,
INT
_TYPE_G
0
);
INT
R_GROUP
0
);
}
}
/*******************************************************************************
/*******************************************************************************
...
@@ -332,9 +332,9 @@ unsigned int gicv3_get_pending_interrupt_type(void)
...
@@ -332,9 +332,9 @@ unsigned int gicv3_get_pending_interrupt_type(void)
* this interrupt has been configured under by the interrupt controller i.e.
* this interrupt has been configured under by the interrupt controller i.e.
* group0 or group1 Secure / Non Secure. The return value can be one of the
* group0 or group1 Secure / Non Secure. The return value can be one of the
* following :
* following :
* INT
_TYPE_G
0 : The interrupt type is a Secure Group 0 interrupt
* INT
R_GROUP
0 : The interrupt type is a Secure Group 0 interrupt
* INT
_TYPE_G
1S : The interrupt type is a Secure Group 1 secure interrupt
* INT
R_GROUP
1S : The interrupt type is a Secure Group 1 secure interrupt
* INT
_TYPE_G
1NS: The interrupt type is a Secure Group 1 non secure
* INT
R_GROUP
1NS: The interrupt type is a Secure Group 1 non secure
* interrupt.
* interrupt.
******************************************************************************/
******************************************************************************/
unsigned
int
gicv3_get_interrupt_type
(
unsigned
int
id
,
unsigned
int
gicv3_get_interrupt_type
(
unsigned
int
id
,
...
@@ -352,7 +352,7 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
...
@@ -352,7 +352,7 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
/* All LPI interrupts are Group 1 non secure */
/* All LPI interrupts are Group 1 non secure */
if
(
id
>=
MIN_LPI_ID
)
if
(
id
>=
MIN_LPI_ID
)
return
INT
_TYPE_G
1NS
;
return
INT
R_GROUP
1NS
;
if
(
id
<
MIN_SPI_ID
)
{
if
(
id
<
MIN_SPI_ID
)
{
assert
(
driver_data
->
rdistif_base_addrs
);
assert
(
driver_data
->
rdistif_base_addrs
);
...
@@ -370,12 +370,12 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
...
@@ -370,12 +370,12 @@ unsigned int gicv3_get_interrupt_type(unsigned int id,
* interrupt
* interrupt
*/
*/
if
(
igroup
)
if
(
igroup
)
return
INT
_TYPE_G
1NS
;
return
INT
R_GROUP
1NS
;
/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
/* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */
if
(
grpmodr
)
if
(
grpmodr
)
return
INT
_TYPE_G
1S
;
return
INT
R_GROUP
1S
;
/* Else it is a Group 0 Secure interrupt */
/* Else it is a Group 0 Secure interrupt */
return
INT
_TYPE_G
0
;
return
INT
R_GROUP
0
;
}
}
include/bl31/interrupt_mgmt.h
View file @
4ca473db
...
@@ -63,6 +63,10 @@
...
@@ -63,6 +63,10 @@
#define INTR_NS_VALID_RM0 0x0
#define INTR_NS_VALID_RM0 0x0
/* Routed to EL1/EL2 from NS and to EL3 from Secure */
/* Routed to EL1/EL2 from NS and to EL3 from Secure */
#define INTR_NS_VALID_RM1 0x1
#define INTR_NS_VALID_RM1 0x1
/* Routed to EL3 from NS. Taken to S-EL1 from Secure and handed over to EL3 */
#define INTR_EL3_VALID_RM0 0x2
/* Routed to EL3 from NS and Secure */
#define INTR_EL3_VALID_RM1 0x3
/* This is the default routing model */
/* This is the default routing model */
#define INTR_DEFAULT_RM 0x0
#define INTR_DEFAULT_RM 0x0
...
@@ -87,12 +91,16 @@
...
@@ -87,12 +91,16 @@
* of interrupt. If the model does not match one of the valid masks
* of interrupt. If the model does not match one of the valid masks
* -EINVAL is returned.
* -EINVAL is returned.
******************************************************************************/
******************************************************************************/
#define validate_sel1_interrupt_rm(x) (x == INTR_SEL1_VALID_RM0 ? 0 : \
#define validate_sel1_interrupt_rm(x) ((x) == INTR_SEL1_VALID_RM0 ? 0 : \
(x == INTR_SEL1_VALID_RM1 ? 0 :\
((x) == INTR_SEL1_VALID_RM1 ? 0 :\
-EINVAL))
#define validate_ns_interrupt_rm(x) ((x) == INTR_NS_VALID_RM0 ? 0 : \
((x) == INTR_NS_VALID_RM1 ? 0 :\
-EINVAL))
-EINVAL))
#define validate_
ns
_interrupt_rm(x) (
x
== INTR_
NS
_VALID_RM0 ? 0 : \
#define validate_
el3
_interrupt_rm(x) (
(x)
== INTR_
EL3
_VALID_RM0 ? 0 : \
(
x
== INTR_
NS
_VALID_RM1 ? 0 :\
(
(x)
== INTR_
EL3
_VALID_RM1 ? 0 :\
-EINVAL))
-EINVAL))
/*******************************************************************************
/*******************************************************************************
...
...
include/bl32/tsp/tsp.h
View file @
4ca473db
...
@@ -45,12 +45,12 @@
...
@@ -45,12 +45,12 @@
#define TSP_SYSTEM_RESET_DONE 0xf2000009
#define TSP_SYSTEM_RESET_DONE 0xf2000009
/*
/*
* Function identifiers to handle FIQs through the synchronous handling model.
* Function identifiers to handle S-El1 interrupt through the synchronous
* If the TSP was previously interrupted then control has to be returned to
* handling model. If the TSP was previously interrupted then control has to
* the TSPD after handling the interrupt else execution can remain in the TSP.
* be returned to the TSPD after handling the interrupt else execution can
* remain in the TSP.
*/
*/
#define TSP_HANDLED_S_EL1_FIQ 0xf2000006
#define TSP_HANDLED_S_EL1_INTR 0xf2000006
#define TSP_EL3_FIQ 0xf2000007
/* SMC function ID that TSP uses to request service from secure monitor */
/* SMC function ID that TSP uses to request service from secure monitor */
#define TSP_GET_ARGS 0xf2001000
#define TSP_GET_ARGS 0xf2001000
...
@@ -63,7 +63,7 @@
...
@@ -63,7 +63,7 @@
#define TSP_SUB 0x2001
#define TSP_SUB 0x2001
#define TSP_MUL 0x2002
#define TSP_MUL 0x2002
#define TSP_DIV 0x2003
#define TSP_DIV 0x2003
#define TSP_HANDLE_
FIQ
_AND_RETURN 0x2004
#define TSP_HANDLE_
SEL1_INTR
_AND_RETURN 0x2004
/*
/*
* Generate function IDs for TSP services to be used in SMC calls, by
* Generate function IDs for TSP services to be used in SMC calls, by
...
@@ -115,7 +115,7 @@ typedef struct tsp_vectors {
...
@@ -115,7 +115,7 @@ typedef struct tsp_vectors {
tsp_vector_isn_t
cpu_off_entry
;
tsp_vector_isn_t
cpu_off_entry
;
tsp_vector_isn_t
cpu_resume_entry
;
tsp_vector_isn_t
cpu_resume_entry
;
tsp_vector_isn_t
cpu_suspend_entry
;
tsp_vector_isn_t
cpu_suspend_entry
;
tsp_vector_isn_t
fiq
_entry
;
tsp_vector_isn_t
sel1_intr
_entry
;
tsp_vector_isn_t
system_off_entry
;
tsp_vector_isn_t
system_off_entry
;
tsp_vector_isn_t
system_reset_entry
;
tsp_vector_isn_t
system_reset_entry
;
}
tsp_vectors_t
;
}
tsp_vectors_t
;
...
...
include/drivers/arm/gicv3.h
View file @
4ca473db
...
@@ -35,9 +35,9 @@
...
@@ -35,9 +35,9 @@
* GICv3 miscellaneous definitions
* GICv3 miscellaneous definitions
******************************************************************************/
******************************************************************************/
/* Interrupt group definitions */
/* Interrupt group definitions */
#define INT
_TYPE_G
1S 0
#define INT
R_GROUP
1S 0
#define INT
_TYPE_G
0 1
#define INT
R_GROUP
0 1
#define INT
_TYPE_G
1NS 2
#define INT
R_GROUP
1NS 2
/* Interrupt IDs reported by the HPPIR and IAR registers */
/* Interrupt IDs reported by the HPPIR and IAR registers */
#define PENDING_G1S_INTID 1020
#define PENDING_G1S_INTID 1020
...
...
include/plat/arm/common/aarch64/arm_macros.S
View file @
4ca473db
...
@@ -31,12 +31,21 @@
...
@@ -31,12 +31,21 @@
#define __ARM_MACROS_S__
#define __ARM_MACROS_S__
#include <cci.h>
#include <cci.h>
#include <gic_v2.h>
#include <gic_common.h>
#include <gicv2.h>
#include <gicv3.h>
#include <platform_def.h>
#include <platform_def.h>
.
section
.
rodata.
gic_reg_name
,
"aS"
.
section
.
rodata.
gic_reg_name
,
"aS"
/*
Applicable
only
to
GICv2
and
GICv3
with
SRE
disabled
(
legacy
mode
)
*/
gicc_regs
:
gicc_regs
:
.
asciz
"gicc_hppir"
,
"gicc_ahppir"
,
"gicc_ctlr"
,
""
.
asciz
"gicc_hppir"
,
"gicc_ahppir"
,
"gicc_ctlr"
,
""
/*
Applicable
only
to
GICv3
with
SRE
enabled
*/
icc_regs
:
.
asciz
"icc_hppir0_el1"
,
"icc_hppir1_el1"
,
"icc_ctlr_el3"
,
""
/*
Registers
common
to
both
GICv2
and
GICv3
*/
gicd_pend_reg
:
gicd_pend_reg
:
.
asciz
"gicd_ispendr regs (Offsets 0x200 - 0x278)\n"
\
.
asciz
"gicd_ispendr regs (Offsets 0x200 - 0x278)\n"
\
"
Offset
:\
t
\
t
\
tvalue
\
n
"
"
Offset
:\
t
\
t
\
tvalue
\
n
"
...
@@ -54,6 +63,28 @@ spacer:
...
@@ -54,6 +63,28 @@ spacer:
*
---------------------------------------------
*
---------------------------------------------
*/
*/
.
macro
arm_print_gic_regs
.
macro
arm_print_gic_regs
/
*
Check
for
GICv3
system
register
access
*/
mrs
x7
,
id_aa64pfr0_el1
ubfx
x7
,
x7
,
#
ID_AA64PFR0_GIC_SHIFT
,
#
ID_AA64PFR0_GIC_WIDTH
cmp
x7
,
#
1
b.ne
print_gicv2
/
*
Check
for
SRE
enable
*/
mrs
x8
,
ICC_SRE_EL3
tst
x8
,
#
ICC_SRE_SRE_BIT
b.eq
print_gicv2
/
*
Load
the
icc
reg
list
to
x6
*/
adr
x6
,
icc_regs
/
*
Load
the
icc
regs
to
gp
regs
used
by
str_in_crash_buf_print
*/
mrs
x8
,
ICC_HPPIR0_EL1
mrs
x9
,
ICC_HPPIR1_EL1
mrs
x10
,
ICC_CTLR_EL3
/
*
Store
to
the
crash
buf
and
print
to
console
*/
bl
str_in_crash_buf_print
b
print_gic_common
print_gicv2
:
/
*
Load
the
gicc
reg
list
to
x6
*/
/
*
Load
the
gicc
reg
list
to
x6
*/
adr
x6
,
gicc_regs
adr
x6
,
gicc_regs
/
*
Load
the
gicc
regs
to
gp
regs
used
by
str_in_crash_buf_print
*/
/
*
Load
the
gicc
regs
to
gp
regs
used
by
str_in_crash_buf_print
*/
...
@@ -63,6 +94,7 @@ spacer:
...
@@ -63,6 +94,7 @@ spacer:
/
*
Store
to
the
crash
buf
and
print
to
console
*/
/
*
Store
to
the
crash
buf
and
print
to
console
*/
bl
str_in_crash_buf_print
bl
str_in_crash_buf_print
print_gic_common
:
/
*
Print
the
GICD_ISPENDR
regs
*/
/
*
Print
the
GICD_ISPENDR
regs
*/
add
x7
,
x16
,
#
GICD_ISPENDR
add
x7
,
x16
,
#
GICD_ISPENDR
adr
x4
,
gicd_pend_reg
adr
x4
,
gicd_pend_reg
...
...
include/plat/arm/common/arm_config.h
View file @
4ca473db
...
@@ -42,12 +42,6 @@ enum arm_config_flags {
...
@@ -42,12 +42,6 @@ enum arm_config_flags {
};
};
typedef
struct
arm_config
{
typedef
struct
arm_config
{
uintptr_t
gicd_base
;
uintptr_t
gicc_base
;
uintptr_t
gich_base
;
uintptr_t
gicv_base
;
unsigned
int
max_aff0
;
unsigned
int
max_aff1
;
unsigned
long
flags
;
unsigned
long
flags
;
}
arm_config_t
;
}
arm_config_t
;
...
...
include/plat/arm/common/arm_def.h
View file @
4ca473db
...
@@ -135,6 +135,22 @@
...
@@ -135,6 +135,22 @@
#define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_6 14
#define ARM_IRQ_SEC_SGI_7 15
#define ARM_IRQ_SEC_SGI_7 15
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
* terminology. On a GICv2 system or mode, the lists will be merged and treated
* as Group 0 interrupts.
*/
#define ARM_G1S_IRQS ARM_IRQ_SEC_PHY_TIMER, \
ARM_IRQ_SEC_SGI_1, \
ARM_IRQ_SEC_SGI_2, \
ARM_IRQ_SEC_SGI_3, \
ARM_IRQ_SEC_SGI_4, \
ARM_IRQ_SEC_SGI_5, \
ARM_IRQ_SEC_SGI_7
#define ARM_G0_IRQS ARM_IRQ_SEC_SGI_0, \
ARM_IRQ_SEC_SGI_6
#define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \
#define ARM_SHARED_RAM_ATTR ((PLAT_ARM_SHARED_RAM_CACHED ? \
MT_MEMORY : MT_DEVICE) \
MT_MEMORY : MT_DEVICE) \
| MT_RW | MT_SECURE)
| MT_RW | MT_SECURE)
...
...
include/plat/arm/common/plat_arm.h
View file @
4ca473db
...
@@ -37,7 +37,6 @@
...
@@ -37,7 +37,6 @@
#include <stdint.h>
#include <stdint.h>
#include <xlat_tables.h>
#include <xlat_tables.h>
/*
/*
* Extern declarations common to ARM standard platforms
* Extern declarations common to ARM standard platforms
*/
*/
...
@@ -179,7 +178,11 @@ void arm_tsp_early_platform_setup(void);
...
@@ -179,7 +178,11 @@ void arm_tsp_early_platform_setup(void);
/*
/*
* Mandatory functions required in ARM standard platforms
* Mandatory functions required in ARM standard platforms
*/
*/
void
plat_arm_gic_driver_init
(
void
);
void
plat_arm_gic_init
(
void
);
void
plat_arm_gic_init
(
void
);
void
plat_arm_gic_cpuif_enable
(
void
);
void
plat_arm_gic_cpuif_disable
(
void
);
void
plat_arm_gic_pcpu_init
(
void
);
void
plat_arm_security_setup
(
void
);
void
plat_arm_security_setup
(
void
);
void
plat_arm_pwrc_setup
(
void
);
void
plat_arm_pwrc_setup
(
void
);
...
...
include/plat/arm/css/common/aarch64/css_macros.S
View file @
4ca473db
...
@@ -41,8 +41,8 @@
...
@@ -41,8 +41,8 @@
*
---------------------------------------------
*
---------------------------------------------
*/
*/
.
macro
plat_print_gic_regs
.
macro
plat_print_gic_regs
mov_imm
x16
,
PLAT_
CSS
_GICD_BASE
mov_imm
x16
,
PLAT_
ARM
_GICD_BASE
mov_imm
x17
,
PLAT_
CSS
_GICC_BASE
mov_imm
x17
,
PLAT_
ARM
_GICC_BASE
arm_print_gic_regs
arm_print_gic_regs
.
endm
.
endm
...
...
include/plat/arm/css/common/css_def.h
View file @
4ca473db
...
@@ -60,6 +60,16 @@
...
@@ -60,6 +60,16 @@
#define CSS_IRQ_TZ_WDOG 86
#define CSS_IRQ_TZ_WDOG 86
#define CSS_IRQ_SEC_SYS_TIMER 91
#define CSS_IRQ_SEC_SYS_TIMER 91
/*
* Define a list of Group 1 Secure interrupts as per GICv3 terminology. On a
* GICv2 system or mode, the interrupts will be treated as Group 0 interrupts.
*/
#define CSS_G1S_IRQS CSS_IRQ_MHU, \
CSS_IRQ_GPU_SMMU_0, \
CSS_IRQ_TZC, \
CSS_IRQ_TZ_WDOG, \
CSS_IRQ_SEC_SYS_TIMER
/*
/*
* SCP <=> AP boot configuration
* SCP <=> AP boot configuration
*
*
...
...
plat/arm/board/fvp/aarch64/fvp_common.c
View file @
4ca473db
...
@@ -30,14 +30,23 @@
...
@@ -30,14 +30,23 @@
#include <arm_config.h>
#include <arm_config.h>
#include <arm_def.h>
#include <arm_def.h>
#include <arm_gic.h>
#include <cci.h>
#include <cci.h>
#include <debug.h>
#include <debug.h>
#include <gicv2.h>
#include <mmio.h>
#include <mmio.h>
#include <plat_arm.h>
#include <plat_arm.h>
#include <v2m_def.h>
#include <v2m_def.h>
#include "../fvp_def.h"
#include "../fvp_def.h"
#if (FVP_USE_GIC_DRIVER == FVP_GICV2)
extern
gicv2_driver_data_t
arm_gic_data
;
#endif
/* Defines for GIC Driver build time selection */
#define FVP_GICV2 1
#define FVP_GICV3 2
#define FVP_GICV3_LEGACY 3
/*******************************************************************************
/*******************************************************************************
* arm_config holds the characteristics of the differences between the three FVP
* arm_config holds the characteristics of the differences between the three FVP
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
* platforms (Base, A53_A57 & Foundation). It will be populated during cold boot
...
@@ -110,33 +119,6 @@ const mmap_region_t plat_arm_mmap[] = {
...
@@ -110,33 +119,6 @@ const mmap_region_t plat_arm_mmap[] = {
ARM_CASSERT_MMAP
ARM_CASSERT_MMAP
#if IMAGE_BL31 || IMAGE_BL32
/* Array of secure interrupts to be configured by the gic driver */
const
unsigned
int
irq_sec_array
[]
=
{
ARM_IRQ_SEC_PHY_TIMER
,
ARM_IRQ_SEC_SGI_0
,
ARM_IRQ_SEC_SGI_1
,
ARM_IRQ_SEC_SGI_2
,
ARM_IRQ_SEC_SGI_3
,
ARM_IRQ_SEC_SGI_4
,
ARM_IRQ_SEC_SGI_5
,
ARM_IRQ_SEC_SGI_6
,
ARM_IRQ_SEC_SGI_7
,
FVP_IRQ_TZ_WDOG
,
FVP_IRQ_SEC_SYS_TIMER
};
void
plat_arm_gic_init
(
void
)
{
arm_gic_init
(
arm_config
.
gicc_base
,
arm_config
.
gicd_base
,
BASE_GICR_BASE
,
irq_sec_array
,
ARRAY_SIZE
(
irq_sec_array
));
}
#endif
/*******************************************************************************
/*******************************************************************************
* A single boot loader stack is expected to work on both the Foundation FVP
* A single boot loader stack is expected to work on both the Foundation FVP
* models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
* models and the two flavours of the Base FVP models (AEMv8 & Cortex). The
...
@@ -165,16 +147,28 @@ void fvp_config_setup(void)
...
@@ -165,16 +147,28 @@ void fvp_config_setup(void)
*/
*/
switch
(
bld
)
{
switch
(
bld
)
{
case
BLD_GIC_VE_MMAP
:
case
BLD_GIC_VE_MMAP
:
arm_config
.
gicd_base
=
VE_GICD_BASE
;
#if IMAGE_BL31 || IMAGE_BL32
arm_config
.
gicc_base
=
VE_GICC_BASE
;
#if FVP_USE_GIC_DRIVER == FVP_GICV2
arm_config
.
gich_base
=
VE_GICH_BASE
;
/*
arm_config
.
gicv_base
=
VE_GICV_BASE
;
* If the FVP implements the VE compatible memory map, then the
* GICv2 driver must be included in the build. Update the platform
* data with the correct GICv2 base addresses before it is used
* to initialise the driver.
*
* This update of platform data is temporary and will be removed
* once VE memory map for FVP is no longer supported by Trusted
* Firmware.
*/
arm_gic_data
.
gicd_base
=
VE_GICD_BASE
;
arm_gic_data
.
gicc_base
=
VE_GICC_BASE
;
#else
ERROR
(
"Only GICv2 driver supported for VE memory map
\n
"
);
panic
();
#endif
/* __FVP_USE_GIC_DRIVER == FVP_GICV2__ */
#endif
/* __IMAGE_BL31 || IMAGE_BL32__ */
break
;
break
;
case
BLD_GIC_A53A57_MMAP
:
case
BLD_GIC_A53A57_MMAP
:
arm_config
.
gicd_base
=
BASE_GICD_BASE
;
arm_config
.
gicc_base
=
BASE_GICC_BASE
;
arm_config
.
gich_base
=
BASE_GICH_BASE
;
arm_config
.
gicv_base
=
BASE_GICV_BASE
;
break
;
break
;
default:
default:
ERROR
(
"Unsupported board build %x
\n
"
,
bld
);
ERROR
(
"Unsupported board build %x
\n
"
,
bld
);
...
@@ -187,8 +181,6 @@ void fvp_config_setup(void)
...
@@ -187,8 +181,6 @@ void fvp_config_setup(void)
*/
*/
switch
(
hbi
)
{
switch
(
hbi
)
{
case
HBI_FOUNDATION_FVP
:
case
HBI_FOUNDATION_FVP
:
arm_config
.
max_aff0
=
4
;
arm_config
.
max_aff1
=
1
;
arm_config
.
flags
=
0
;
arm_config
.
flags
=
0
;
/*
/*
...
@@ -206,8 +198,6 @@ void fvp_config_setup(void)
...
@@ -206,8 +198,6 @@ void fvp_config_setup(void)
}
}
break
;
break
;
case
HBI_BASE_FVP
:
case
HBI_BASE_FVP
:
arm_config
.
max_aff0
=
4
;
arm_config
.
max_aff1
=
2
;
arm_config
.
flags
|=
ARM_CONFIG_BASE_MMAP
|
arm_config
.
flags
|=
ARM_CONFIG_BASE_MMAP
|
ARM_CONFIG_HAS_CCI
|
ARM_CONFIG_HAS_TZC
;
ARM_CONFIG_HAS_CCI
|
ARM_CONFIG_HAS_TZC
;
...
...
plat/arm/board/fvp/aarch64/fvp_helpers.S
View file @
4ca473db
...
@@ -30,7 +30,8 @@
...
@@ -30,7 +30,8 @@
#include <arch.h>
#include <arch.h>
#include <asm_macros.S>
#include <asm_macros.S>
#include <gic_v2.h>
#include <gicv2.h>
#include <gicv3.h>
#include <platform_def.h>
#include <platform_def.h>
#include <v2m_def.h>
#include <v2m_def.h>
#include "../drivers/pwrc/fvp_pwrc.h"
#include "../drivers/pwrc/fvp_pwrc.h"
...
@@ -74,9 +75,26 @@ func plat_secondary_cold_boot_setup
...
@@ -74,9 +75,26 @@ func plat_secondary_cold_boot_setup
str
w0
,
[
x1
,
#
PPOFFR_OFF
]
str
w0
,
[
x1
,
#
PPOFFR_OFF
]
/
*
---------------------------------------------
/
*
---------------------------------------------
*
D
eactivate
the
gic
cpu
interface
as
well
*
D
isable
GIC
bypass
as
well
*
---------------------------------------------
*
---------------------------------------------
*/
*/
/
*
Check
for
GICv3
system
register
access
*/
mrs
x0
,
id_aa64pfr0_el1
ubfx
x0
,
x0
,
#
ID_AA64PFR0_GIC_SHIFT
,
#
ID_AA64PFR0_GIC_WIDTH
cmp
x0
,
#
1
b.ne
gicv2_bypass_disable
/
*
Check
for
SRE
enable
*/
mrs
x1
,
ICC_SRE_EL3
tst
x1
,
#
ICC_SRE_SRE_BIT
b.eq
gicv2_bypass_disable
mrs
x2
,
ICC_SRE_EL3
orr
x2
,
x2
,
#(
ICC_SRE_DIB_BIT
|
ICC_SRE_DFB_BIT
)
msr
ICC_SRE_EL3
,
x2
b
secondary_cold_boot_wait
gicv2_bypass_disable
:
ldr
x0
,
=
VE_GICC_BASE
ldr
x0
,
=
VE_GICC_BASE
ldr
x1
,
=
BASE_GICC_BASE
ldr
x1
,
=
BASE_GICC_BASE
fvp_choose_gicmmap
x0
,
x1
,
x2
,
w2
,
x1
fvp_choose_gicmmap
x0
,
x1
,
x2
,
w2
,
x1
...
@@ -84,6 +102,7 @@ func plat_secondary_cold_boot_setup
...
@@ -84,6 +102,7 @@ func plat_secondary_cold_boot_setup
orr
w0
,
w0
,
#(
IRQ_BYP_DIS_GRP0
|
FIQ_BYP_DIS_GRP0
)
orr
w0
,
w0
,
#(
IRQ_BYP_DIS_GRP0
|
FIQ_BYP_DIS_GRP0
)
str
w0
,
[
x1
,
#
GICC_CTLR
]
str
w0
,
[
x1
,
#
GICC_CTLR
]
secondary_cold_boot_wait
:
/
*
---------------------------------------------
/
*
---------------------------------------------
*
There
is
no
sane
reason
to
come
out
of
this
*
There
is
no
sane
reason
to
come
out
of
this
*
wfi
so
panic
if
we
do
.
This
cpu
will
be
pow
-
*
wfi
so
panic
if
we
do
.
This
cpu
will
be
pow
-
...
...
Prev
1
2
3
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