Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
696966ec
Commit
696966ec
authored
Sep 17, 2020
by
Marc Zyngier
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/irq/gic-v3-nmi-ns' into irq/irqchip-next
Signed-off-by:
Marc Zyngier
<
maz@kernel.org
>
parents
bf476c60
33678059
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
16 deletions
+68
-16
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/arch_gicv3.h
+7
-1
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/ptrace.h
+13
-1
arch/arm64/kernel/image-vars.h
arch/arm64/kernel/image-vars.h
+2
-0
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic-v3.c
+46
-14
No files found.
arch/arm64/include/asm/arch_gicv3.h
View file @
696966ec
...
@@ -153,7 +153,7 @@ static inline bool gic_prio_masking_enabled(void)
...
@@ -153,7 +153,7 @@ static inline bool gic_prio_masking_enabled(void)
static
inline
void
gic_pmr_mask_irqs
(
void
)
static
inline
void
gic_pmr_mask_irqs
(
void
)
{
{
BUILD_BUG_ON
(
GICD_INT_DEF_PRI
<
(
GIC_PRIO_IRQOFF
|
BUILD_BUG_ON
(
GICD_INT_DEF_PRI
<
(
__
GIC_PRIO_IRQOFF
|
GIC_PRIO_PSR_I_SET
));
GIC_PRIO_PSR_I_SET
));
BUILD_BUG_ON
(
GICD_INT_DEF_PRI
>=
GIC_PRIO_IRQON
);
BUILD_BUG_ON
(
GICD_INT_DEF_PRI
>=
GIC_PRIO_IRQON
);
/*
/*
...
@@ -162,6 +162,12 @@ static inline void gic_pmr_mask_irqs(void)
...
@@ -162,6 +162,12 @@ static inline void gic_pmr_mask_irqs(void)
* are applied to IRQ priorities
* are applied to IRQ priorities
*/
*/
BUILD_BUG_ON
((
0x80
|
(
GICD_INT_DEF_PRI
>>
1
))
>=
GIC_PRIO_IRQON
);
BUILD_BUG_ON
((
0x80
|
(
GICD_INT_DEF_PRI
>>
1
))
>=
GIC_PRIO_IRQON
);
/*
* Same situation as above, but now we make sure that we can mask
* regular interrupts.
*/
BUILD_BUG_ON
((
0x80
|
(
GICD_INT_DEF_PRI
>>
1
))
<
(
__GIC_PRIO_IRQOFF_NS
|
GIC_PRIO_PSR_I_SET
));
gic_write_pmr
(
GIC_PRIO_IRQOFF
);
gic_write_pmr
(
GIC_PRIO_IRQOFF
);
}
}
...
...
arch/arm64/include/asm/ptrace.h
View file @
696966ec
...
@@ -31,9 +31,21 @@
...
@@ -31,9 +31,21 @@
* interrupt disabling temporarily does not rely on IRQ priorities.
* interrupt disabling temporarily does not rely on IRQ priorities.
*/
*/
#define GIC_PRIO_IRQON 0xe0
#define GIC_PRIO_IRQON 0xe0
#define GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80)
#define __GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80)
#define __GIC_PRIO_IRQOFF_NS 0xa0
#define GIC_PRIO_PSR_I_SET (1 << 4)
#define GIC_PRIO_PSR_I_SET (1 << 4)
#define GIC_PRIO_IRQOFF \
({ \
extern struct static_key_false gic_nonsecure_priorities;\
u8 __prio = __GIC_PRIO_IRQOFF; \
\
if (static_branch_unlikely(&gic_nonsecure_priorities)) \
__prio = __GIC_PRIO_IRQOFF_NS; \
\
__prio; \
})
/* Additional SPSR bits not exposed in the UABI */
/* Additional SPSR bits not exposed in the UABI */
#define PSR_MODE_THREAD_BIT (1 << 0)
#define PSR_MODE_THREAD_BIT (1 << 0)
#define PSR_IL_BIT (1 << 20)
#define PSR_IL_BIT (1 << 20)
...
...
arch/arm64/kernel/image-vars.h
View file @
696966ec
...
@@ -101,6 +101,8 @@ KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
...
@@ -101,6 +101,8 @@ KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
/* Static key checked in pmr_sync(). */
/* Static key checked in pmr_sync(). */
#ifdef CONFIG_ARM64_PSEUDO_NMI
#ifdef CONFIG_ARM64_PSEUDO_NMI
KVM_NVHE_ALIAS
(
gic_pmr_sync
);
KVM_NVHE_ALIAS
(
gic_pmr_sync
);
/* Static key checked in GIC_PRIO_IRQOFF. */
KVM_NVHE_ALIAS
(
gic_nonsecure_priorities
);
#endif
#endif
/* EL2 exception handling */
/* EL2 exception handling */
...
...
drivers/irqchip/irq-gic-v3.c
View file @
696966ec
...
@@ -75,16 +75,14 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
...
@@ -75,16 +75,14 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
*
*
* If SCR_EL3.FIQ == 1, the values writen to/read from PMR and RPR at non-secure
* If SCR_EL3.FIQ == 1, the values writen to/read from PMR and RPR at non-secure
* EL1 are subject to a similar operation thus matching the priorities presented
* EL1 are subject to a similar operation thus matching the priorities presented
* from the (re)distributor when security is enabled.
* from the (re)distributor when security is enabled. When SCR_EL3.FIQ == 0,
* these values are unchanched by the GIC.
*
*
* see GICv3/GICv4 Architecture Specification (IHI0069D):
* see GICv3/GICv4 Architecture Specification (IHI0069D):
* - section 4.8.1 Non-secure accesses to register fields for Secure interrupt
* - section 4.8.1 Non-secure accesses to register fields for Secure interrupt
* priorities.
* priorities.
* - Figure 4-7 Secure read of the priority field for a Non-secure Group 1
* - Figure 4-7 Secure read of the priority field for a Non-secure Group 1
* interrupt.
* interrupt.
*
* For now, we only support pseudo-NMIs if we have non-secure view of
* priorities.
*/
*/
static
DEFINE_STATIC_KEY_FALSE
(
supports_pseudo_nmis
);
static
DEFINE_STATIC_KEY_FALSE
(
supports_pseudo_nmis
);
...
@@ -97,6 +95,9 @@ static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
...
@@ -97,6 +95,9 @@ static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
DEFINE_STATIC_KEY_FALSE
(
gic_pmr_sync
);
DEFINE_STATIC_KEY_FALSE
(
gic_pmr_sync
);
EXPORT_SYMBOL
(
gic_pmr_sync
);
EXPORT_SYMBOL
(
gic_pmr_sync
);
DEFINE_STATIC_KEY_FALSE
(
gic_nonsecure_priorities
);
EXPORT_SYMBOL
(
gic_nonsecure_priorities
);
/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
static
refcount_t
*
ppi_nmi_refs
;
static
refcount_t
*
ppi_nmi_refs
;
...
@@ -932,14 +933,20 @@ static void gic_cpu_sys_reg_init(void)
...
@@ -932,14 +933,20 @@ static void gic_cpu_sys_reg_init(void)
/* Set priority mask register */
/* Set priority mask register */
if
(
!
gic_prio_masking_enabled
())
{
if
(
!
gic_prio_masking_enabled
())
{
write_gicreg
(
DEFAULT_PMR_VALUE
,
ICC_PMR_EL1
);
write_gicreg
(
DEFAULT_PMR_VALUE
,
ICC_PMR_EL1
);
}
else
{
}
else
if
(
gic_supports_nmi
())
{
/*
/*
* Mismatch configuration with boot CPU, the system is likely
* Mismatch configuration with boot CPU, the system is likely
* to die as interrupt masking will not work properly on all
* to die as interrupt masking will not work properly on all
* CPUs
* CPUs
*
* The boot CPU calls this function before enabling NMI support,
* and as a result we'll never see this warning in the boot path
* for that CPU.
*/
*/
WARN_ON
(
gic_supports_nmi
()
&&
group0
&&
if
(
static_branch_unlikely
(
&
gic_nonsecure_priorities
))
!
gic_dist_security_disabled
());
WARN_ON
(
!
group0
||
gic_dist_security_disabled
());
else
WARN_ON
(
group0
&&
!
gic_dist_security_disabled
());
}
}
/*
/*
...
@@ -1544,11 +1551,6 @@ static void gic_enable_nmi_support(void)
...
@@ -1544,11 +1551,6 @@ static void gic_enable_nmi_support(void)
if
(
!
gic_prio_masking_enabled
())
if
(
!
gic_prio_masking_enabled
())
return
;
return
;
if
(
gic_has_group0
()
&&
!
gic_dist_security_disabled
())
{
pr_warn
(
"SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs
\n
"
);
return
;
}
ppi_nmi_refs
=
kcalloc
(
gic_data
.
ppi_nr
,
sizeof
(
*
ppi_nmi_refs
),
GFP_KERNEL
);
ppi_nmi_refs
=
kcalloc
(
gic_data
.
ppi_nr
,
sizeof
(
*
ppi_nmi_refs
),
GFP_KERNEL
);
if
(
!
ppi_nmi_refs
)
if
(
!
ppi_nmi_refs
)
return
;
return
;
...
@@ -1564,8 +1566,38 @@ static void gic_enable_nmi_support(void)
...
@@ -1564,8 +1566,38 @@ static void gic_enable_nmi_support(void)
if
(
gic_read_ctlr
()
&
ICC_CTLR_EL1_PMHE_MASK
)
if
(
gic_read_ctlr
()
&
ICC_CTLR_EL1_PMHE_MASK
)
static_branch_enable
(
&
gic_pmr_sync
);
static_branch_enable
(
&
gic_pmr_sync
);
pr_info
(
"%s ICC_PMR_EL1 synchronisation
\n
"
,
pr_info
(
"Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation
\n
"
,
static_branch_unlikely
(
&
gic_pmr_sync
)
?
"Forcing"
:
"Relaxing"
);
static_branch_unlikely
(
&
gic_pmr_sync
)
?
"forced"
:
"relaxed"
);
/*
* How priority values are used by the GIC depends on two things:
* the security state of the GIC (controlled by the GICD_CTRL.DS bit)
* and if Group 0 interrupts can be delivered to Linux in the non-secure
* world as FIQs (controlled by the SCR_EL3.FIQ bit). These affect the
* the ICC_PMR_EL1 register and the priority that software assigns to
* interrupts:
*
* GICD_CTRL.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Group 1 priority
* -----------------------------------------------------------
* 1 | - | unchanged | unchanged
* -----------------------------------------------------------
* 0 | 1 | non-secure | non-secure
* -----------------------------------------------------------
* 0 | 0 | unchanged | non-secure
*
* where non-secure means that the value is right-shifted by one and the
* MSB bit set, to make it fit in the non-secure priority range.
*
* In the first two cases, where ICC_PMR_EL1 and the interrupt priority
* are both either modified or unchanged, we can use the same set of
* priorities.
*
* In the last case, where only the interrupt priorities are modified to
* be in the non-secure range, we use a different PMR value to mask IRQs
* and the rest of the values that we use remain unchanged.
*/
if
(
gic_has_group0
()
&&
!
gic_dist_security_disabled
())
static_branch_enable
(
&
gic_nonsecure_priorities
);
static_branch_enable
(
&
supports_pseudo_nmis
);
static_branch_enable
(
&
supports_pseudo_nmis
);
...
...
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