diff mbox series

KVM: arm64: nv: Work around lack of pauth support in old toolchains

Message ID 20240422224849.2238222-1-maz@kernel.org (mailing list archive)
State New, archived
Headers show
Series KVM: arm64: nv: Work around lack of pauth support in old toolchains | expand

Commit Message

Marc Zyngier April 22, 2024, 10:48 p.m. UTC
We still support GCC 8.x, and it appears that this toolchain
does not understand "pauth" as a valid architectural extension.
After all, it's only been 8 years since ARMv8.3 was released...

This results in the NV ERETAx code breaking the build, as it relies
on this extention to make use of the PACGA instruction.

Work around it by hand-assembling the instruction using a mind-bending
trick lifted from an old patch by Will. Magic.

Fixes: e09faab353a6 ("KVM: arm64: nv: Add emulation for ERETAx instructions")
Reported-by: Linaro Kernel Functional Testing <lkft@linaro.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/pauth.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

Comments

Arnd Bergmann April 23, 2024, 8:24 a.m. UTC | #1
On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
> We still support GCC 8.x, and it appears that this toolchain
> does not understand "pauth" as a valid architectural extension.
> After all, it's only been 8 years since ARMv8.3 was released...

Just to clarify: I'm fairly sure that all supported toolchains
support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
seems to be that it was retroactively made an optional
feature for earlier architecture versions a few years after
ARMv8.3, so most binutils versions we support understand
pacga as an armv8.3 feature but reject the pauth name for the
extension.

> This results in the NV ERETAx code breaking the build, as it relies
> on this extention to make use of the PACGA instruction.
>
> Work around it by hand-assembling the instruction using a mind-bending
> trick lifted from an old patch by Will. Magic.
>
> Fixes: e09faab353a6 ("KVM: arm64: nv: Add emulation for ERETAx instructions")
> Reported-by: Linaro Kernel Functional Testing <lkft@linaro.org>
> Signed-off-by: Marc Zyngier <maz@kernel.org>

I usually try to enclose these in a version check like
"#if CONFIG_AS_VERSION >= 22800" so we can be sure we clean them up
whenever the minimum version changes, but I assume you'll remember
this one.

Acked-by: Arnd Bergmann <arnd@arndb.de>
Mark Rutland April 23, 2024, 8:37 a.m. UTC | #2
On Mon, Apr 22, 2024 at 11:48:49PM +0100, Marc Zyngier wrote:
> We still support GCC 8.x, and it appears that this toolchain
> does not understand "pauth" as a valid architectural extension.
> After all, it's only been 8 years since ARMv8.3 was released...
> 
> This results in the NV ERETAx code breaking the build, as it relies
> on this extention to make use of the PACGA instruction.
> 
> Work around it by hand-assembling the instruction using a mind-bending
> trick lifted from an old patch by Will. Magic.
> 
> Fixes: e09faab353a6 ("KVM: arm64: nv: Add emulation for ERETAx instructions")
> Reported-by: Linaro Kernel Functional Testing <lkft@linaro.org>
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  arch/arm64/kvm/pauth.c | 19 +++++++++++++++++--
>  1 file changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/pauth.c b/arch/arm64/kvm/pauth.c
> index a3a5c404375b..8baf2a2cbdd3 100644
> --- a/arch/arm64/kvm/pauth.c
> +++ b/arch/arm64/kvm/pauth.c
> @@ -17,6 +17,22 @@
>  #include <asm/kvm_emulate.h>
>  #include <asm/pointer_auth.h>
>  
> +/*
> + * "// This is some of my finest work" (Will Deacon, 2019-02-12)
> + *
> + * The jury is still out on that one.
> + */
> +#define REG(r)	"(0%x[" #r "] - ((0%x[" #r "] >> 4) * 6))"
> +
> +/* PACGA Xd, Xn, Xm */
> +#define PACGA(d,n,m)						\
> +	asm volatile(".inst 0x9AC03000   |"			\
> +		     "(" REG(Rd) "<< 0)  |"			\
> +		     "(" REG(Rn) "<< 5)  |"			\
> +		     "(" REG(Rm) "<< 16)\n"			\
> +		     : [Rd] "=r" ((d))				\
> +		     : [Rn] "r" ((n)), [Rm] "r" ((m)))

Can you please use <asm/gpr-num.h> rather than open-coding this new REG()
helper? That way this'll be consistent with the way we assemble MRS/MSR in
<asm/sysreg.h>, and it avoids the few seconds of confusion trying to figure out
the maths in the REG() helper (neat trick though!).

Fixlet for that below; I've build tested this and the resulting object file is
the same before and after (diff shows that only the name of the file changed):

| [mark@lakrids:~/src/linux]% usekorg 13.2.0 aarch64-linux-objdump -d pauth-maz.o | grep pacga
|  204:   9ac03335        pacga   x21, x25, x0
| [mark@lakrids:~/src/linux]% usekorg 13.2.0 aarch64-linux-objdump -d pauth-rutland.o | grep pacga
|  204:   9ac03335        pacga   x21, x25, x0
| [mark@lakrids:~/src/linux]% diff <(usekorg 13.2.0 aarch64-linux-objdump -d pauth-maz.o) <(usekorg 13.2.0 aarch64-linux-objdump -d pauth-rutland.o)
| 2c2
| < pauth-maz.o:     file format elf64-littleaarch64
| ---
| > pauth-rutland.o:     file format elf64-littleaarch64

If you'd prefer I can send this as a patch.

Otherwise, this looks good to me; thanks for the fix!

Mark.

---->8----
diff --git a/arch/arm64/kvm/pauth.c b/arch/arm64/kvm/pauth.c
index 8baf2a2cbdd32..e518baf570c86 100644
--- a/arch/arm64/kvm/pauth.c
+++ b/arch/arm64/kvm/pauth.c
@@ -14,24 +14,20 @@
 
 #include <linux/kvm_host.h>
 
+#include <asm/gpr-num.h>
 #include <asm/kvm_emulate.h>
 #include <asm/pointer_auth.h>
 
-/*
- * "// This is some of my finest work" (Will Deacon, 2019-02-12)
- *
- * The jury is still out on that one.
- */
-#define REG(r)	"(0%x[" #r "] - ((0%x[" #r "] >> 4) * 6))"
-
 /* PACGA Xd, Xn, Xm */
-#define PACGA(d,n,m)						\
-	asm volatile(".inst 0x9AC03000   |"			\
-		     "(" REG(Rd) "<< 0)  |"			\
-		     "(" REG(Rn) "<< 5)  |"			\
-		     "(" REG(Rm) "<< 16)\n"			\
-		     : [Rd] "=r" ((d))				\
-		     : [Rn] "r" ((n)), [Rm] "r" ((m)))
+#define PACGA(d,n,m)				\
+	asm volatile(				\
+	__DEFINE_ASM_GPR_NUMS			\
+	"	.inst 0x9AC03000          |"	\
+	"	(.L__gpr_num_%[Rd] << 0)  |"	\
+	"	(.L__gpr_num_%[Rn] << 5)  |"	\
+	"	(.L__gpr_num_%[Rm] << 16)\n"	\
+	: [Rd] "=r" ((d))			\
+	: [Rn] "r" ((n)), [Rm] "r" ((m)))
 
 static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
 		       struct ptrauth_key ikey)
Marc Zyngier April 23, 2024, 11:33 a.m. UTC | #3
On Tue, 23 Apr 2024 09:37:04 +0100,
Mark Rutland <mark.rutland@arm.com> wrote:
> 
> On Mon, Apr 22, 2024 at 11:48:49PM +0100, Marc Zyngier wrote:
> > We still support GCC 8.x, and it appears that this toolchain
> > does not understand "pauth" as a valid architectural extension.
> > After all, it's only been 8 years since ARMv8.3 was released...
> > 
> > This results in the NV ERETAx code breaking the build, as it relies
> > on this extention to make use of the PACGA instruction.
> > 
> > Work around it by hand-assembling the instruction using a mind-bending
> > trick lifted from an old patch by Will. Magic.
> > 
> > Fixes: e09faab353a6 ("KVM: arm64: nv: Add emulation for ERETAx instructions")
> > Reported-by: Linaro Kernel Functional Testing <lkft@linaro.org>
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> >  arch/arm64/kvm/pauth.c | 19 +++++++++++++++++--
> >  1 file changed, 17 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/pauth.c b/arch/arm64/kvm/pauth.c
> > index a3a5c404375b..8baf2a2cbdd3 100644
> > --- a/arch/arm64/kvm/pauth.c
> > +++ b/arch/arm64/kvm/pauth.c
> > @@ -17,6 +17,22 @@
> >  #include <asm/kvm_emulate.h>
> >  #include <asm/pointer_auth.h>
> >  
> > +/*
> > + * "// This is some of my finest work" (Will Deacon, 2019-02-12)
> > + *
> > + * The jury is still out on that one.
> > + */
> > +#define REG(r)	"(0%x[" #r "] - ((0%x[" #r "] >> 4) * 6))"
> > +
> > +/* PACGA Xd, Xn, Xm */
> > +#define PACGA(d,n,m)						\
> > +	asm volatile(".inst 0x9AC03000   |"			\
> > +		     "(" REG(Rd) "<< 0)  |"			\
> > +		     "(" REG(Rn) "<< 5)  |"			\
> > +		     "(" REG(Rm) "<< 16)\n"			\
> > +		     : [Rd] "=r" ((d))				\
> > +		     : [Rn] "r" ((n)), [Rm] "r" ((m)))
> 
> Can you please use <asm/gpr-num.h> rather than open-coding this new REG()
> helper? That way this'll be consistent with the way we assemble MRS/MSR in
> <asm/sysreg.h>, and it avoids the few seconds of confusion trying to figure out
> the maths in the REG() helper (neat trick though!).

Ah, I had completely forgot about this guy. Good call. I'll fold that
patchlet in and re-push the result.

Thanks,

	M.
Aiqun Yu (Maria) April 23, 2024, noon UTC | #4
On 4/23/2024 4:24 PM, Arnd Bergmann wrote:
> On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
>> We still support GCC 8.x, and it appears that this toolchain
>> does not understand "pauth" as a valid architectural extension.
>> After all, it's only been 8 years since ARMv8.3 was released...
> 
> Just to clarify: I'm fairly sure that all supported toolchains
> support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
> seems to be that it was retroactively made an optional
> feature for earlier architecture versions a few years after
> ARMv8.3, so most binutils versions we support understand
> pacga as an armv8.3 feature but reject the pauth name for the
> extension.
Kind of agree with Arnd here.
Shall the fix just remove the ".arch_extension pauth"?

I've tried gcc 7 failed with the pauth name for the extension.
After I remove the ".arch_extension pauth" and use "pacga" instruction
directly pass the gcc 7 compilation.

By the way, have a glance for gcc7/8/9/10 manual, from the gcc 10 manual
[1], seems gcc 10 was the first introduced the pauth as the extension
name support.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/AArch64-Options.html#g_t-march-and--mcpu-Feature-Modifiers
> 
>> This results in the NV ERETAx code breaking the build, as it relies
>> on this extention to make use of the PACGA instruction.
>>
>> Work around it by hand-assembling the instruction using a mind-bending
>> trick lifted from an old patch by Will. Magic.
>>
>> Fixes: e09faab353a6 ("KVM: arm64: nv: Add emulation for ERETAx instructions")
>> Reported-by: Linaro Kernel Functional Testing <lkft@linaro.org>
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
> 
> I usually try to enclose these in a version check like
> "#if CONFIG_AS_VERSION >= 22800" so we can be sure we clean them up
> whenever the minimum version changes, but I assume you'll remember
> this one.
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Marc Zyngier April 23, 2024, 12:06 p.m. UTC | #5
On Tue, 23 Apr 2024 13:00:55 +0100,
"Aiqun Yu (Maria)" <quic_aiquny@quicinc.com> wrote:
> 
> 
> 
> On 4/23/2024 4:24 PM, Arnd Bergmann wrote:
> > On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
> >> We still support GCC 8.x, and it appears that this toolchain
> >> does not understand "pauth" as a valid architectural extension.
> >> After all, it's only been 8 years since ARMv8.3 was released...
> > 
> > Just to clarify: I'm fairly sure that all supported toolchains
> > support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
> > seems to be that it was retroactively made an optional
> > feature for earlier architecture versions a few years after
> > ARMv8.3, so most binutils versions we support understand
> > pacga as an armv8.3 feature but reject the pauth name for the
> > extension.
> Kind of agree with Arnd here.
> Shall the fix just remove the ".arch_extension pauth"?
> 
> I've tried gcc 7 failed with the pauth name for the extension.
> After I remove the ".arch_extension pauth" and use "pacga" instruction
> directly pass the gcc 7 compilation.

And breaks with LLVM:

  CC      arch/arm64/kvm/pauth.o
arch/arm64/kvm/pauth.c:40:9: error: instruction requires: pauth
                     "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
                      ^
<inline asm>:2:1: note: instantiated into assembly here
pacga x19, x1, x9
^
1 error generated.


	M.
Arnd Bergmann April 23, 2024, 12:37 p.m. UTC | #6
On Tue, Apr 23, 2024, at 14:06, Marc Zyngier wrote:
> On Tue, 23 Apr 2024 13:00:55 +0100,
> "Aiqun Yu (Maria)" <quic_aiquny@quicinc.com> wrote:
>> On 4/23/2024 4:24 PM, Arnd Bergmann wrote:
>> > On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
>> >> We still support GCC 8.x, and it appears that this toolchain
>> >> does not understand "pauth" as a valid architectural extension.
>> >> After all, it's only been 8 years since ARMv8.3 was released...
>> > 
>> > Just to clarify: I'm fairly sure that all supported toolchains
>> > support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
>> > seems to be that it was retroactively made an optional
>> > feature for earlier architecture versions a few years after
>> > ARMv8.3, so most binutils versions we support understand
>> > pacga as an armv8.3 feature but reject the pauth name for the
>> > extension.
>> Kind of agree with Arnd here.
>> Shall the fix just remove the ".arch_extension pauth"?
>> 
>> I've tried gcc 7 failed with the pauth name for the extension.
>> After I remove the ".arch_extension pauth" and use "pacga" instruction
>> directly pass the gcc 7 compilation.

It really depends on the binutils version, not gcc of course.

> And breaks with LLVM:
>
>   CC      arch/arm64/kvm/pauth.o
> arch/arm64/kvm/pauth.c:40:9: error: instruction requires: pauth
>                      "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
>                       ^
> <inline asm>:2:1: note: instantiated into assembly here
> pacga x19, x1, x9
> ^

It works when building with LLVM_IAS=0, which we obviously don't
want to mandate here. The variant below works for both clang+ias
(including all still supported versions) and gcc+binutils, but at
that point it gets obscure enough that your .inst version is easier
to understand.

    Arnd

--- a/arch/arm64/kvm/pauth.c
+++ b/arch/arm64/kvm/pauth.c
@@ -36,7 +36,12 @@ static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
        __ptrauth_key_install_nosync(APGA, ikey);
        isb();
 
-       asm volatile(ARM64_ASM_PREAMBLE ".arch_extension pauth\n"
+       asm volatile(ARM64_ASM_PREAMBLE
+#ifdef CONFIG_AS_IS_LLVM
+                    ".arch_extension pauth\n"
+#else
+                    ".arch armv8.3-a\n"
+#endif
                     "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
        isb();
Marc Zyngier April 23, 2024, 4:15 p.m. UTC | #7
On Tue, 23 Apr 2024 13:37:09 +0100,
"Arnd Bergmann" <arnd@arndb.de> wrote:
> 
> On Tue, Apr 23, 2024, at 14:06, Marc Zyngier wrote:
> > On Tue, 23 Apr 2024 13:00:55 +0100,
> > "Aiqun Yu (Maria)" <quic_aiquny@quicinc.com> wrote:
> >> On 4/23/2024 4:24 PM, Arnd Bergmann wrote:
> >> > On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
> >> >> We still support GCC 8.x, and it appears that this toolchain
> >> >> does not understand "pauth" as a valid architectural extension.
> >> >> After all, it's only been 8 years since ARMv8.3 was released...
> >> > 
> >> > Just to clarify: I'm fairly sure that all supported toolchains
> >> > support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
> >> > seems to be that it was retroactively made an optional
> >> > feature for earlier architecture versions a few years after
> >> > ARMv8.3, so most binutils versions we support understand
> >> > pacga as an armv8.3 feature but reject the pauth name for the
> >> > extension.
> >> Kind of agree with Arnd here.
> >> Shall the fix just remove the ".arch_extension pauth"?
> >> 
> >> I've tried gcc 7 failed with the pauth name for the extension.
> >> After I remove the ".arch_extension pauth" and use "pacga" instruction
> >> directly pass the gcc 7 compilation.
> 
> It really depends on the binutils version, not gcc of course.

Right. I'll amend the commit message to reflect that.

> 
> > And breaks with LLVM:
> >
> >   CC      arch/arm64/kvm/pauth.o
> > arch/arm64/kvm/pauth.c:40:9: error: instruction requires: pauth
> >                      "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
> >                       ^
> > <inline asm>:2:1: note: instantiated into assembly here
> > pacga x19, x1, x9
> > ^
> 
> It works when building with LLVM_IAS=0, which we obviously don't
> want to mandate here. The variant below works for both clang+ias
> (including all still supported versions) and gcc+binutils, but at
> that point it gets obscure enough that your .inst version is easier
> to understand.

Exactly. Either we have a good way to abstract this behind the scenes
(which I don't see right now), or we just assume control of the
instruction generation, which is what my patch does.

In general, I question the value of the ".arch_extension" requirement
for something like Linux, where we already have a pretty fine grained
control of what we want to see being output by the compiler. but that
ship has sailed long ago.

Thanks,

	M.

> 
>     arnd
> 
> --- a/arch/arm64/kvm/pauth.c
> +++ b/arch/arm64/kvm/pauth.c
> @@ -36,7 +36,12 @@ static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
>         __ptrauth_key_install_nosync(APGA, ikey);
>         isb();
>  
> -       asm volatile(ARM64_ASM_PREAMBLE ".arch_extension pauth\n"
> +       asm volatile(ARM64_ASM_PREAMBLE
> +#ifdef CONFIG_AS_IS_LLVM
> +                    ".arch_extension pauth\n"
> +#else
> +                    ".arch armv8.3-a\n"
> +#endif
>                      "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
>         isb();
>  
>
Aiqun Yu (Maria) April 24, 2024, 1:54 a.m. UTC | #8
On 4/24/2024 12:15 AM, Marc Zyngier wrote:
> On Tue, 23 Apr 2024 13:37:09 +0100,
> "Arnd Bergmann" <arnd@arndb.de> wrote:
>>
>> On Tue, Apr 23, 2024, at 14:06, Marc Zyngier wrote:
>>> On Tue, 23 Apr 2024 13:00:55 +0100,
>>> "Aiqun Yu (Maria)" <quic_aiquny@quicinc.com> wrote:
>>>> On 4/23/2024 4:24 PM, Arnd Bergmann wrote:
>>>>> On Tue, Apr 23, 2024, at 00:48, Marc Zyngier wrote:
>>>>>> We still support GCC 8.x, and it appears that this toolchain
>>>>>> does not understand "pauth" as a valid architectural extension.
>>>>>> After all, it's only been 8 years since ARMv8.3 was released...
>>>>>
>>>>> Just to clarify: I'm fairly sure that all supported toolchains
>>>>> support ARMv8.3 and PACGA, the problem with ".arch_extension pauth\n"
>>>>> seems to be that it was retroactively made an optional
>>>>> feature for earlier architecture versions a few years after
>>>>> ARMv8.3, so most binutils versions we support understand
>>>>> pacga as an armv8.3 feature but reject the pauth name for the
>>>>> extension.
>>>> Kind of agree with Arnd here.
>>>> Shall the fix just remove the ".arch_extension pauth"?
>>>>
>>>> I've tried gcc 7 failed with the pauth name for the extension.
>>>> After I remove the ".arch_extension pauth" and use "pacga" instruction
>>>> directly pass the gcc 7 compilation.
>>
>> It really depends on the binutils version, not gcc of course.
> 
> Right. I'll amend the commit message to reflect that.
> 
>>
>>> And breaks with LLVM:
>>>
>>>   CC      arch/arm64/kvm/pauth.o
>>> arch/arm64/kvm/pauth.c:40:9: error: instruction requires: pauth
>>>                      "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
>>>                       ^
>>> <inline asm>:2:1: note: instantiated into assembly here
>>> pacga x19, x1, x9
>>> ^
>>
>> It works when building with LLVM_IAS=0, which we obviously don't
>> want to mandate here. The variant below works for both clang+ias
>> (including all still supported versions) and gcc+binutils, but at
>> that point it gets obscure enough that your .inst version is easier
>> to understand.
> 
> Exactly. Either we have a good way to abstract this behind the scenes
> (which I don't see right now), or we just assume control of the
> instruction generation, which is what my patch does.
Ack.
> 
> In general, I question the value of the ".arch_extension" requirement
> for something like Linux, where we already have a pretty fine grained
> control of what we want to see being output by the compiler. but that
> ship has sailed long ago.
> 
> Thanks,
> 
> 	M.
> 
>>
>>     arnd
>>
>> --- a/arch/arm64/kvm/pauth.c
>> +++ b/arch/arm64/kvm/pauth.c
>> @@ -36,7 +36,12 @@ static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
>>         __ptrauth_key_install_nosync(APGA, ikey);
>>         isb();
>>  
>> -       asm volatile(ARM64_ASM_PREAMBLE ".arch_extension pauth\n"
>> +       asm volatile(ARM64_ASM_PREAMBLE
>> +#ifdef CONFIG_AS_IS_LLVM
>> +                    ".arch_extension pauth\n"
>> +#else
>> +                    ".arch armv8.3-a\n"
>> +#endif
>>                      "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
>>         isb();
>>  
>>
>
diff mbox series

Patch

diff --git a/arch/arm64/kvm/pauth.c b/arch/arm64/kvm/pauth.c
index a3a5c404375b..8baf2a2cbdd3 100644
--- a/arch/arm64/kvm/pauth.c
+++ b/arch/arm64/kvm/pauth.c
@@ -17,6 +17,22 @@ 
 #include <asm/kvm_emulate.h>
 #include <asm/pointer_auth.h>
 
+/*
+ * "// This is some of my finest work" (Will Deacon, 2019-02-12)
+ *
+ * The jury is still out on that one.
+ */
+#define REG(r)	"(0%x[" #r "] - ((0%x[" #r "] >> 4) * 6))"
+
+/* PACGA Xd, Xn, Xm */
+#define PACGA(d,n,m)						\
+	asm volatile(".inst 0x9AC03000   |"			\
+		     "(" REG(Rd) "<< 0)  |"			\
+		     "(" REG(Rn) "<< 5)  |"			\
+		     "(" REG(Rm) "<< 16)\n"			\
+		     : [Rd] "=r" ((d))				\
+		     : [Rn] "r" ((n)), [Rm] "r" ((m)))
+
 static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
 		       struct ptrauth_key ikey)
 {
@@ -36,8 +52,7 @@  static u64 compute_pac(struct kvm_vcpu *vcpu, u64 ptr,
 	__ptrauth_key_install_nosync(APGA, ikey);
 	isb();
 
-	asm volatile(ARM64_ASM_PREAMBLE ".arch_extension pauth\n"
-		     "pacga %0, %1, %2" : "=r" (pac) : "r" (ptr), "r" (mod));
+	PACGA(pac, ptr, mod);
 	isb();
 
 	__ptrauth_key_install_nosync(APGA, gkey);