diff mbox series

[v5,05/27] arm64: Use daifflag_restore after bp_hardening

Message ID 1535471497-38854-6-git-send-email-julien.thierry@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: provide pseudo NMI with GICv3 | expand

Commit Message

Julien Thierry Aug. 28, 2018, 3:51 p.m. UTC
For EL0 entries requiring bp_hardening, daif status is kept at
DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
are enabled through local_irq_enable().

Before using local_irq_* functions, daifflags should be properly restored
to a state where IRQs are enabled.

Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: James Morse <james.morse@arm.com>
---
 arch/arm64/mm/fault.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

James Morse Sept. 12, 2018, 10:32 a.m. UTC | #1
Hi Julien,

On 28/08/18 16:51, Julien Thierry wrote:
> For EL0 entries requiring bp_hardening, daif status is kept at
> DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
> are enabled through local_irq_enable().
> 
> Before using local_irq_* functions, daifflags should be properly restored
> to a state where IRQs are enabled.

> Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.

Is this just for symmetry, or are you going on to add something to the daifflags
state that local_irq_* functions won't change? (if so, could you allude to that
in the commit message)


Either way,

Acked-by: James Morse <james.morse@arm.com>
Julien Thierry Sept. 12, 2018, 11:11 a.m. UTC | #2
Hi James,

On 12/09/18 11:32, James Morse wrote:
> Hi Julien,
> 
> On 28/08/18 16:51, Julien Thierry wrote:
>> For EL0 entries requiring bp_hardening, daif status is kept at
>> DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
>> are enabled through local_irq_enable().
>>
>> Before using local_irq_* functions, daifflags should be properly restored
>> to a state where IRQs are enabled.
> 
>> Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.
> 
> Is this just for symmetry, or are you going on to add something to the daifflags
> state that local_irq_* functions won't change? (if so, could you allude to that
> in the commit message)
> 

What happens is that once we use ICC_PMR_EL1, local_irq_enable will not 
touch PSR.I. And we are coming back from an entry where PSR.I was kept 
to 1 so local_irq_enable was not actually enabling the interrupts. On 
the otherhand, restore will affect both.

Another option is to have the asm macro "enable_da_f" also switch to PMR 
usage (i.e. "just keep normal interrupts disabled"). Overall it would 
probably be easier to reason with, but I'm just unsure whether it is 
acceptable to receive a Pseudo NMI before having applied the bp_hardening.

If it is possible, I'm happy to solve this with enable_da_f.

Thanks,

> 
> Either way,
> 
> Acked-by: James Morse <james.morse@arm.com>
>
James Morse Sept. 12, 2018, 12:28 p.m. UTC | #3
Hi Julien,

On 12/09/18 12:11, Julien Thierry wrote:
> On 12/09/18 11:32, James Morse wrote:
>> On 28/08/18 16:51, Julien Thierry wrote:
>>> For EL0 entries requiring bp_hardening, daif status is kept at
>>> DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
>>> are enabled through local_irq_enable().
>>>
>>> Before using local_irq_* functions, daifflags should be properly restored
>>> to a state where IRQs are enabled.
>>
>>> Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.
>>
>> Is this just for symmetry, or are you going on to add something to the daifflags
>> state that local_irq_* functions won't change? (if so, could you allude to that
>> in the commit message)

> What happens is that once we use ICC_PMR_EL1, local_irq_enable will not touch
> PSR.I. And we are coming back from an entry where PSR.I was kept to 1 so
> local_irq_enable was not actually enabling the interrupts. On the otherhand,
> restore will affect both.

Got it. Thanks!

Does this mean stop_machine()s local_save_flags()/local_irq_restore() will not
be symmetric around __apply_alternatives_multi_stop()?
I see you add alternatives in these in patch 15, but I haven't got that far yet)


> Another option is to have the asm macro "enable_da_f" also switch to PMR usage
> (i.e. "just keep normal interrupts disabled"). Overall it would probably be
> easier to reason with, but I'm just unsure whether it is acceptable to receive a
> Pseudo NMI before having applied the bp_hardening.

Wouldn't this give the interrupt controller a headache? I assume IRQs really are
masked when handle_arch_irq is called. (I know nothing about the gic)


Thanks,

James
Julien Thierry Sept. 12, 2018, 1:03 p.m. UTC | #4
On 12/09/18 13:28, James Morse wrote:
> On 12/09/18 12:11, Julien Thierry wrote:
>> On 12/09/18 11:32, James Morse wrote:
>>> On 28/08/18 16:51, Julien Thierry wrote:
>>>> For EL0 entries requiring bp_hardening, daif status is kept at
>>>> DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
>>>> are enabled through local_irq_enable().
>>>>
>>>> Before using local_irq_* functions, daifflags should be properly restored
>>>> to a state where IRQs are enabled.
>>>
>>>> Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.
>>>
>>> Is this just for symmetry, or are you going on to add something to the daifflags
>>> state that local_irq_* functions won't change? (if so, could you allude to that
>>> in the commit message)
> 
>> What happens is that once we use ICC_PMR_EL1, local_irq_enable will not touch
>> PSR.I. And we are coming back from an entry where PSR.I was kept to 1 so
>> local_irq_enable was not actually enabling the interrupts. On the otherhand,
>> restore will affect both.
> 
> Got it. Thanks!
> 
> Does this mean stop_machine()s local_save_flags()/local_irq_restore() will not
> be symmetric around __apply_alternatives_multi_stop()?
> I see you add alternatives in these in patch 15, but I haven't got that far yet)
> 

It's a good point but it should be fine.
The changes to the irqflags make save/restore takes everything into 
consideration (PMR + PSR.I) because of situtations like this, 
enable/disable only toggle the PMR (so the goal is to not have PSR.I set 
before reaching path calling enable/disable).
Maybe I should add a comment for this in asm/irqflags.f when I add the 
alternatives, so that at least arch code can be wary of this.

> 
>> Another option is to have the asm macro "enable_da_f" also switch to PMR usage
>> (i.e. "just keep normal interrupts disabled"). Overall it would probably be
>> easier to reason with, but I'm just unsure whether it is acceptable to receive a
>> Pseudo NMI before having applied the bp_hardening.
> 
> Wouldn't this give the interrupt controller a headache? I assume IRQs really are
> masked when handle_arch_irq is called. (I know nothing about the gic)
> 

Yes, you're right, I missed that da_f gets unmasked right before the 
irq_handler... So unless I do some special case for irqs, enable_da_f is 
not the way to go.

Thanks,
Catalin Marinas Oct. 3, 2018, 3:12 p.m. UTC | #5
On Tue, Aug 28, 2018 at 04:51:15PM +0100, Julien Thierry wrote:
> For EL0 entries requiring bp_hardening, daif status is kept at
> DAIF_PROCCTX_NOIRQ until after hardening has been done. Then interrupts
> are enabled through local_irq_enable().
> 
> Before using local_irq_* functions, daifflags should be properly restored
> to a state where IRQs are enabled.
> 
> Enable IRQs by restoring DAIF_PROCCTX state after bp hardening.
> 
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: James Morse <james.morse@arm.com>

Queued for 4.20. Thanks.
diff mbox series

Patch

diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 50b30ff..dfa2c43 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -37,6 +37,7 @@ 
 #include <asm/cmpxchg.h>
 #include <asm/cpufeature.h>
 #include <asm/exception.h>
+#include <asm/daifflags.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
 #include <asm/sysreg.h>
@@ -771,7 +772,7 @@  asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr,
 	if (addr > TASK_SIZE)
 		arm64_apply_bp_hardening();
 
-	local_irq_enable();
+	local_daif_restore(DAIF_PROCCTX);
 	do_mem_abort(addr, esr, regs);
 }
 
@@ -785,7 +786,7 @@  asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
 	if (user_mode(regs)) {
 		if (instruction_pointer(regs) > TASK_SIZE)
 			arm64_apply_bp_hardening();
-		local_irq_enable();
+		local_daif_restore(DAIF_PROCCTX);
 	}
 
 	clear_siginfo(&info);