Re: [PATCH 2/2] irqchip/gic-v3: Support pseudo-NMIs when SCR_EL3.FIQ == 0

2020-06-26 Thread Alexandru Elisei
Hi,

On 6/26/20 2:51 AM, kernel test robot wrote:
> Hi Alexandru,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on arm64/for-next/core]
> [also build test WARNING on tip/irq/core v5.8-rc2 next-20200625]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use  as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url:
> https://github.com/0day-ci/linux/commits/Alexandru-Elisei/irqchip-gic-v3-Support-pseudo-NMIs-when-SCR_EL3-FIQ-0/20200625-230144
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git 
> for-next/core
> config: arm64-randconfig-r025-20200624 (attached as .config)
> compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 
> 8911a35180c6777188fefe0954a2451a2b91deaf)
> reproduce (this is a W=1 build):
> wget 
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
> ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # install arm64 cross compiling tool for clang build
> # apt-get install binutils-aarch64-linux-gnu
> # save the attached .config to linux build tree
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm64 

My mistake, I'll start compiling the kernel with clang too.

The register width for ICC_PMR_EL1 in the kernel is rather inconsistent: in
arch_gicv3.h, the accessors use 32 bits for the PMR value which gets casted to 
64
bit by the {read,write}_sysreg_s macros anyway, in struct pt_regs the register 
is
64-bit, in __cpu_do_idle_irqprio it's declared as an unsigned long,
arch_local_irqs_{disable,enable} declares it as u32 and casts it to an unsigned
long when used by the inline assembly, the gicv3 irqchip driver uses it as a 32
bit variable.

I think the confusion stems from the fact that originally it was a 32 bit
register, but was changed to 64 bits in Arm IHI 0069E (January 2019).

I could cast it to an unsigned long in the inline assembly, but IMO that looks a
bit awkward. Before sending the patches I was considering changing it everywhere
to 64 bits, but Mark Rutland had a different idea. Mark, would you mind 
explaining
why keeping it 32 bit wide makes more sense?

Thanks,
Alex
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot 
>
> All warnings (new ones prefixed by >>):
>
>In file included from arch/arm64/kernel/asm-offsets.c:10:
>In file included from include/linux/arm_sdei.h:8:
>In file included from include/acpi/ghes.h:5:
>In file included from include/acpi/apei.h:9:
>In file included from include/linux/acpi.h:13:
>In file included from include/linux/irqdomain.h:35:
>In file included from include/linux/of.h:17:
>In file included from include/linux/kobject.h:20:
>In file included from include/linux/sysfs.h:16:
>In file included from include/linux/kernfs.h:13:
>In file included from include/linux/idr.h:15:
>In file included from include/linux/radix-tree.h:15:
>In file included from include/linux/rcupdate.h:26:
>In file included from include/linux/irqflags.h:16:
>>> arch/arm64/include/asm/irqflags.h:45:10: warning: value size does not match 
>>> register size specified by the constraint and modifier 
>>> [-Wasm-operand-widths]
>: "r" (pmr_irqon)
>   ^
>arch/arm64/include/asm/irqflags.h:42:29: note: use constraint modifier "w"
>__msr_s(SYS_ICC_PMR_EL1, "%0"),
>  ^
>arch/arm64/include/asm/irqflags.h:67:10: warning: value size does not 
> match register size specified by the constraint and modifier 
> [-Wasm-operand-widths]
>: "r" (pmr_irqoff)
>   ^
>arch/arm64/include/asm/irqflags.h:64:29: note: use constraint modifier "w"
>__msr_s(SYS_ICC_PMR_EL1, "%0"),
>  ^
>2 warnings generated.
> --
>In file included from drivers/power/supply/ltc2941-battery-gauge.c:12:
>In file included from include/linux/module.h:13:
>In file included from include/linux/stat.h:6:
>In file included from arch/arm64/include/asm/stat.h:12:
>In file included from include/linux/time.h:6:
>In file included from include/linux/seqlock.h:36:
>In file included from include/linux/spinlock.h:54:
>In file included from include/linux/irqflags.h:16:
>>> arch/arm64/include/asm/irqflags.h:45:10: warning: value size does not match 
>>> register size specified by the constraint and modifier 
>>> [-Wasm-operand-widths]
>: "r" (pmr_irqon)
>   ^
>arch/arm64/include/asm/irqflags.h:42:29: note: use constraint modifier "w"
>__msr_s(SYS_ICC_PMR_EL1, "%0"),
>  ^
>arch/arm64/include/asm/irqflags.h:67:10: warning: value size d

Re: [PATCH 2/2] irqchip/gic-v3: Support pseudo-NMIs when SCR_EL3.FIQ == 0

2020-06-25 Thread kernel test robot
Hi Alexandru,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on tip/irq/core v5.8-rc2 next-20200625]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use  as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Alexandru-Elisei/irqchip-gic-v3-Support-pseudo-NMIs-when-SCR_EL3-FIQ-0/20200625-230144
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git 
for-next/core
config: arm64-randconfig-r025-20200624 (attached as .config)
compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 
8911a35180c6777188fefe0954a2451a2b91deaf)
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm64 cross compiling tool for clang build
# apt-get install binutils-aarch64-linux-gnu
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All warnings (new ones prefixed by >>):

   In file included from arch/arm64/kernel/asm-offsets.c:10:
   In file included from include/linux/arm_sdei.h:8:
   In file included from include/acpi/ghes.h:5:
   In file included from include/acpi/apei.h:9:
   In file included from include/linux/acpi.h:13:
   In file included from include/linux/irqdomain.h:35:
   In file included from include/linux/of.h:17:
   In file included from include/linux/kobject.h:20:
   In file included from include/linux/sysfs.h:16:
   In file included from include/linux/kernfs.h:13:
   In file included from include/linux/idr.h:15:
   In file included from include/linux/radix-tree.h:15:
   In file included from include/linux/rcupdate.h:26:
   In file included from include/linux/irqflags.h:16:
>> arch/arm64/include/asm/irqflags.h:45:10: warning: value size does not match 
>> register size specified by the constraint and modifier [-Wasm-operand-widths]
   : "r" (pmr_irqon)
  ^
   arch/arm64/include/asm/irqflags.h:42:29: note: use constraint modifier "w"
   __msr_s(SYS_ICC_PMR_EL1, "%0"),
 ^
   arch/arm64/include/asm/irqflags.h:67:10: warning: value size does not match 
register size specified by the constraint and modifier [-Wasm-operand-widths]
   : "r" (pmr_irqoff)
  ^
   arch/arm64/include/asm/irqflags.h:64:29: note: use constraint modifier "w"
   __msr_s(SYS_ICC_PMR_EL1, "%0"),
 ^
   2 warnings generated.
--
   In file included from drivers/power/supply/ltc2941-battery-gauge.c:12:
   In file included from include/linux/module.h:13:
   In file included from include/linux/stat.h:6:
   In file included from arch/arm64/include/asm/stat.h:12:
   In file included from include/linux/time.h:6:
   In file included from include/linux/seqlock.h:36:
   In file included from include/linux/spinlock.h:54:
   In file included from include/linux/irqflags.h:16:
>> arch/arm64/include/asm/irqflags.h:45:10: warning: value size does not match 
>> register size specified by the constraint and modifier [-Wasm-operand-widths]
   : "r" (pmr_irqon)
  ^
   arch/arm64/include/asm/irqflags.h:42:29: note: use constraint modifier "w"
   __msr_s(SYS_ICC_PMR_EL1, "%0"),
 ^
   arch/arm64/include/asm/irqflags.h:67:10: warning: value size does not match 
register size specified by the constraint and modifier [-Wasm-operand-widths]
   : "r" (pmr_irqoff)
  ^
   arch/arm64/include/asm/irqflags.h:64:29: note: use constraint modifier "w"
   __msr_s(SYS_ICC_PMR_EL1, "%0"),
 ^
   drivers/power/supply/ltc2941-battery-gauge.c:476:13: warning: cast to 
smaller integer type 'enum ltc294x_id' from 'const void *' 
[-Wvoid-pointer-to-enum-cast]
   info->id = (enum ltc294x_id)of_device_get_match_data(&client->dev);
  ^~~
   3 warnings generated.
--
   In file included from drivers/power/supply/goldfish_battery.c:11:
   In file included from include/linux/module.h:13:
   In file included from include/linux/stat.h:6:
   In file included from arch/arm64/include/asm/stat.h:12:
   In file included from include/linux/time.h:6:
   In file included from include/linux/seqlock.h:36:
   In file included from include/linux/spinlock.h:54:
   In file included from include/linux/irqflags.h:16:
>> arch/arm64/include/asm/irqflags.h:45:10: warning: value size does not match 
>

[PATCH 2/2] irqchip/gic-v3: Support pseudo-NMIs when SCR_EL3.FIQ == 0

2020-06-25 Thread Alexandru Elisei
The GIC's internal view of the priority mask register and the assigned
interrupt priorities are based on whether GIC security is enabled and
whether firmware routes Group 0 interrupts to EL3. At the moment, we
support priority masking when ICC_PMR_EL1 and interrupt priorities are
either both modified by the GIC, or both left unchanged.

Trusted Firmware-A's default interrupt routing model allows Group 0
interrupts to be delivered to the non-secure world (SCR_EL3.FIQ == 0).
Unfortunately, this is precisely the case that the GIC driver doesn't
support: ICC_PMR_EL1 remains unchanged, but the GIC's view of interrupt
priorities is different from the software programmed values.

Support pseudo-NMIs when SCR_EL3.FIQ == 0 by using a different value to
mask regular interrupts. All the other values remain the same.

Signed-off-by: Alexandru Elisei 
---
 arch/arm64/include/asm/arch_gicv3.h |  8 -
 arch/arm64/include/asm/daifflags.h  |  4 +--
 arch/arm64/include/asm/irqflags.h   | 14 +---
 arch/arm64/include/asm/ptrace.h | 12 +++
 arch/arm64/kernel/entry.S   |  2 +-
 arch/arm64/kvm/hyp/switch.c |  2 +-
 drivers/irqchip/irq-gic-v3.c| 52 ++---
 7 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/include/asm/arch_gicv3.h 
b/arch/arm64/include/asm/arch_gicv3.h
index a358e97572c1..c2a67a81e39d 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -162,7 +162,13 @@ static inline void gic_pmr_mask_irqs(void)
 * are applied to IRQ priorities
 */
BUILD_BUG_ON((0x80 | (GICD_INT_DEF_PRI >> 1)) >= GIC_PRIO_IRQON);
-   gic_write_pmr(GIC_PRIO_IRQOFF);
+   /*
+* 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());
 }
 
 static inline void gic_arch_enable_irqs(void)
diff --git a/arch/arm64/include/asm/daifflags.h 
b/arch/arm64/include/asm/daifflags.h
index ec213b4a1650..3efa240a6c48 100644
--- a/arch/arm64/include/asm/daifflags.h
+++ b/arch/arm64/include/asm/daifflags.h
@@ -22,7 +22,7 @@
 static inline void local_daif_mask(void)
 {
WARN_ON(system_has_prio_mask_debugging() &&
-   (read_sysreg_s(SYS_ICC_PMR_EL1) == (GIC_PRIO_IRQOFF |
+   (read_sysreg_s(SYS_ICC_PMR_EL1) == (gic_prio_irqoff() |
GIC_PRIO_PSR_I_SET)));
 
asm volatile(
@@ -87,7 +87,7 @@ static inline void local_daif_restore(unsigned long flags)
 * asynchronous errors, we can take NMIs
 */
flags &= ~PSR_I_BIT;
-   pmr = GIC_PRIO_IRQOFF;
+   pmr = gic_prio_irqoff();
} else {
pmr = GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET;
}
diff --git a/arch/arm64/include/asm/irqflags.h 
b/arch/arm64/include/asm/irqflags.h
index aa4b6521ef14..dc68e11c63a1 100644
--- a/arch/arm64/include/asm/irqflags.h
+++ b/arch/arm64/include/asm/irqflags.h
@@ -28,10 +28,13 @@
  */
 static inline void arch_local_irq_enable(void)
 {
+   u32 pmr_irqon = GIC_PRIO_IRQON;
+
if (system_has_prio_mask_debugging()) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
+   u32 pmr_irqoff = gic_prio_irqoff();
 
-   WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
+   WARN_ON_ONCE(pmr != pmr_irqon && pmr != pmr_irqoff);
}
 
asm volatile(ALTERNATIVE(
@@ -39,7 +42,7 @@ static inline void arch_local_irq_enable(void)
__msr_s(SYS_ICC_PMR_EL1, "%0"),
ARM64_HAS_IRQ_PRIO_MASKING)
:
-   : "r" ((unsigned long) GIC_PRIO_IRQON)
+   : "r" (pmr_irqon)
: "memory");
 
pmr_sync();
@@ -47,10 +50,13 @@ static inline void arch_local_irq_enable(void)
 
 static inline void arch_local_irq_disable(void)
 {
+   u32 pmr_irqoff = gic_prio_irqoff();
+
if (system_has_prio_mask_debugging()) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
+   u32 pmr_irqon = GIC_PRIO_IRQON;
 
-   WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
+   WARN_ON_ONCE(pmr != pmr_irqon && pmr != pmr_irqoff);
}
 
asm volatile(ALTERNATIVE(
@@ -58,7 +64,7 @@ static inline void arch_local_irq_disable(void)
__msr_s(SYS_ICC_PMR_EL1, "%0"),
ARM64_HAS_IRQ_PRIO_MASKING)
:
-   : "r" ((unsigned long) GIC_PRIO_IRQOFF)
+   : "r" (pmr_irqoff)
: "memory");
 }
 
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 953b6a1ce549..ad58f05544a1 100644