[PATCH v2] xen/arm64: Add support Clang build on arm64

Saman Dehghan posted 1 patch 1 month, 4 weeks ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/bb575726fe0ac783121e563b1c92f81f51e41f75.1765420376.git.samaan.dehghan@gmail.com
There is a newer version of this series
README                   | 2 ++
xen/arch/arm/arch.mk     | 1 +
xen/arch/arm/arm64/vfp.c | 6 ++++++
3 files changed, 9 insertions(+)
[PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
This patch enables building Xen on arm64 architecture using the Clang compiler.
Changes include:
- Add explicit -march=armv8 flag for arm64 builds.
- Add `__attribute__((target("fp-armv8")))` to `vfp_save_state` and
  `vfp_restore_state` functions when building with Clang to allow
  FP instructions despite `-mgeneral-regs-only`.

Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
---
 README                   | 2 ++
 xen/arch/arm/arch.mk     | 1 +
 xen/arch/arm/arm64/vfp.c | 6 ++++++
 3 files changed, 9 insertions(+)

diff --git a/README b/README
index 889a4ea906..67c1aa7fe6 100644
--- a/README
+++ b/README
@@ -45,6 +45,8 @@ provided by your OS distributor:
       - For ARM:
         - GCC 5.1 or later
         - GNU Binutils 2.25 or later
+        or
+        - Clang/LLVM 11 or later
       - For RISC-V 64-bit:
         - GCC 12.2 or later
         - GNU Binutils 2.39 or later
diff --git a/xen/arch/arm/arch.mk b/xen/arch/arm/arch.mk
index 9c4bedfb3b..bcf548069b 100644
--- a/xen/arch/arm/arch.mk
+++ b/xen/arch/arm/arch.mk
@@ -13,6 +13,7 @@ ifeq ($(CONFIG_MPU),y)
 CFLAGS-$(CONFIG_ARM_64) += -march=armv8-r
 else
 CFLAGS-$(CONFIG_ARM_64) += -mcpu=generic
+CFLAGS-$(CONFIG_ARM_64) += -march=armv8
 endif
 CFLAGS-$(CONFIG_ARM_64) += -mgeneral-regs-only # No fp registers etc
 $(call cc-option-add,CFLAGS-$(CONFIG_ARM_64),CC,-mno-outline-atomics)
diff --git a/xen/arch/arm/arm64/vfp.c b/xen/arch/arm/arm64/vfp.c
index c4f89c7b0e..51fd2ddc54 100644
--- a/xen/arch/arm/arm64/vfp.c
+++ b/xen/arch/arm/arm64/vfp.c
@@ -46,6 +46,9 @@ static inline void restore_state(const uint64_t *fpregs)
                  : : "Q" (*fpregs), "r" (fpregs));
 }
 
+#if defined(CONFIG_CC_IS_CLANG)
+__attribute__((target("fp-armv8")))
+#endif
 void vfp_save_state(struct vcpu *v)
 {
     if ( !cpu_has_fp )
@@ -62,6 +65,9 @@ void vfp_save_state(struct vcpu *v)
         v->arch.vfp.fpexc32_el2 = READ_SYSREG(FPEXC32_EL2);
 }
 
+#if defined(CONFIG_CC_IS_CLANG)
+__attribute__((target("fp-armv8")))
+#endif
 void vfp_restore_state(struct vcpu *v)
 {
     if ( !cpu_has_fp )
-- 
2.49.0
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Julien Grall 1 month, 4 weeks ago

On 11/12/2025 02:39, Saman Dehghan wrote:
> This patch enables building Xen on arm64 architecture using the Clang compiler.
> Changes include:
> - Add explicit -march=armv8 flag for arm64 builds.
> - Add `__attribute__((target("fp-armv8")))` to `vfp_save_state` and
>    `vfp_restore_state` functions when building with Clang to allow
>    FP instructions despite `-mgeneral-regs-only`.
> 
> Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
> ---
>   README                   | 2 ++
>   xen/arch/arm/arch.mk     | 1 +
>   xen/arch/arm/arm64/vfp.c | 6 ++++++
>   3 files changed, 9 insertions(+)
> 
> diff --git a/README b/README
> index 889a4ea906..67c1aa7fe6 100644
> --- a/README
> +++ b/README
> @@ -45,6 +45,8 @@ provided by your OS distributor:
>         - For ARM:
>           - GCC 5.1 or later
>           - GNU Binutils 2.25 or later
> +        or
> +        - Clang/LLVM 11 or later

I forgot to ask. Is this cross-compiling or native? Or both?

And OOI, how did you chose Clang 11?

Cheers,

-- 
Julien Grall
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
On Thu, Dec 11, 2025 at 3:35 AM Julien Grall <julien@xen.org> wrote:
>
>
>
> On 11/12/2025 02:39, Saman Dehghan wrote:
> > This patch enables building Xen on arm64 architecture using the Clang compiler.
> > Changes include:
> > - Add explicit -march=armv8 flag for arm64 builds.
> > - Add `__attribute__((target("fp-armv8")))` to `vfp_save_state` and
> >    `vfp_restore_state` functions when building with Clang to allow
> >    FP instructions despite `-mgeneral-regs-only`.
> >
> > Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
> > ---
> >   README                   | 2 ++
> >   xen/arch/arm/arch.mk     | 1 +
> >   xen/arch/arm/arm64/vfp.c | 6 ++++++
> >   3 files changed, 9 insertions(+)
> >
> > diff --git a/README b/README
> > index 889a4ea906..67c1aa7fe6 100644
> > --- a/README
> > +++ b/README
> > @@ -45,6 +45,8 @@ provided by your OS distributor:
> >         - For ARM:
> >           - GCC 5.1 or later
> >           - GNU Binutils 2.25 or later
> > +        or
> > +        - Clang/LLVM 11 or later
>
> I forgot to ask. Is this cross-compiling or native? Or both?
>
> And OOI, how did you chose Clang 11?

Hi Julien,

To be consistent with minimum requirements for Clang/LLVM on x86.

~Saman

>
> Cheers,
>
> --
> Julien Grall
>
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Julien Grall 1 month, 4 weeks ago
Hi,

On 11/12/2025 12:49, Saman Dehghan wrote:
>> And OOI, how did you chose Clang 11?
> 
> Hi Julien,
> 
> To be consistent with minimum requirements for Clang/LLVM on x86.

To double check did you try the version and confirm every works?

Cheers,

-- 
Julien Grall
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
On Thu, Dec 11, 2025 at 9:06 AM Julien Grall <julien@xen.org> wrote:
>
> Hi,
>
> On 11/12/2025 12:49, Saman Dehghan wrote:
> >> And OOI, how did you chose Clang 11?
> >
> > Hi Julien,
> >
> > To be consistent with minimum requirements for Clang/LLVM on x86.
>
> To double check did you try the version and confirm every works?

Hi Julien,

I compiled and booted Xen with Clang-{11 - 20} on both native and
CROSS_COMPILE=aarch64-linux-gnu-.

~Saman

>
> Cheers,
>
> --
> Julien Grall
>
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Julien Grall 1 month, 4 weeks ago
Hi Saman,

A bit of process first. Usually, when sending a v2, a new thread is 
started (IOW, this is not sent in reply to v1).

On 11/12/2025 02:39, Saman Dehghan wrote:
> This patch enables building Xen on arm64 architecture using the Clang compiler.
> Changes include:
> - Add explicit -march=armv8 flag for arm64 builds.
> - Add `__attribute__((target("fp-armv8")))` to `vfp_save_state` and
>    `vfp_restore_state` functions when building with Clang to allow
>    FP instructions despite `-mgeneral-regs-only`.
> 
> Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
> ---
>   README                   | 2 ++
>   xen/arch/arm/arch.mk     | 1 +
>   xen/arch/arm/arm64/vfp.c | 6 ++++++
>   3 files changed, 9 insertions(+)
> 
> diff --git a/README b/README
> index 889a4ea906..67c1aa7fe6 100644
> --- a/README
> +++ b/README
> @@ -45,6 +45,8 @@ provided by your OS distributor:
>         - For ARM:
>           - GCC 5.1 or later
>           - GNU Binutils 2.25 or later
> +        or
> +        - Clang/LLVM 11 or later
>         - For RISC-V 64-bit:
>           - GCC 12.2 or later
>           - GNU Binutils 2.39 or later
> diff --git a/xen/arch/arm/arch.mk b/xen/arch/arm/arch.mk
> index 9c4bedfb3b..bcf548069b 100644
> --- a/xen/arch/arm/arch.mk
> +++ b/xen/arch/arm/arch.mk
> @@ -13,6 +13,7 @@ ifeq ($(CONFIG_MPU),y)
>   CFLAGS-$(CONFIG_ARM_64) += -march=armv8-r
>   else
>   CFLAGS-$(CONFIG_ARM_64) += -mcpu=generic
> +CFLAGS-$(CONFIG_ARM_64) += -march=armv8
>   endif
>   CFLAGS-$(CONFIG_ARM_64) += -mgeneral-regs-only # No fp registers etc
>   $(call cc-option-add,CFLAGS-$(CONFIG_ARM_64),CC,-mno-outline-atomics)
> diff --git a/xen/arch/arm/arm64/vfp.c b/xen/arch/arm/arm64/vfp.c
> index c4f89c7b0e..51fd2ddc54 100644
> --- a/xen/arch/arm/arm64/vfp.c
> +++ b/xen/arch/arm/arm64/vfp.c
> @@ -46,6 +46,9 @@ static inline void restore_state(const uint64_t *fpregs)
>                    : : "Q" (*fpregs), "r" (fpregs));
>   }
>   
> +#if defined(CONFIG_CC_IS_CLANG)
> +__attribute__((target("fp-armv8")))
> +#endif

Based on Jan's comment, I am a bit puzzled why adding #ifdef is 
sufficient. In fact, I do agree with Jan, my understanding of 
target(...) is this will impact the ABI.

I haven't experienced any issue with the C side yet. But I know in the 
Rust world (they also have an LLVM backend), they decided to prevent 
enabling fp/neon [1] at the function level.

Did you find any documentation that would suggest this is safe?

Now regarding the issue you mentioned in v1:

 > On top of those, `READ_SYSREG(FPSR)`, `READ_SYSREG(FPCR)`,
 > `WRITE_SYSREG(v->arch.vfp.fpsr, FPSR)`and
 > `WRITE_SYSREG(v->arch.vfp.fpcr, FPCR)` using FP.
 > I think I cannot apply __attribute__ on statements.

Do you mean the compiler will complain that you are trying to access 
FPCR/FPSR if you don't add the __atribute__ at the function level?

If so, what you could possibly do is either rewriting the functions in 
assembly or open-code the "{WRITE, READ}_SYSREG()" and add a line 
".arch_extension fp".

Cheers,

[1] https://github.com/llvm/llvm-project/issues/110632

-- 
Julien Grall
Re: [PATCH v2] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
On Thu, Dec 11, 2025 at 3:33 AM Julien Grall <julien@xen.org> wrote:
>
> Hi Saman,
>
> A bit of process first. Usually, when sending a v2, a new thread is
> started (IOW, this is not sent in reply to v1).

Hi Julien,

Thanks :)

>
> On 11/12/2025 02:39, Saman Dehghan wrote:
> > This patch enables building Xen on arm64 architecture using the Clang compiler.
> > Changes include:
> > - Add explicit -march=armv8 flag for arm64 builds.
> > - Add `__attribute__((target("fp-armv8")))` to `vfp_save_state` and
> >    `vfp_restore_state` functions when building with Clang to allow
> >    FP instructions despite `-mgeneral-regs-only`.
> >
> > Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
> > ---
> >   README                   | 2 ++
> >   xen/arch/arm/arch.mk     | 1 +
> >   xen/arch/arm/arm64/vfp.c | 6 ++++++
> >   3 files changed, 9 insertions(+)
> >
> > diff --git a/README b/README
> > index 889a4ea906..67c1aa7fe6 100644
> > --- a/README
> > +++ b/README
> > @@ -45,6 +45,8 @@ provided by your OS distributor:
> >         - For ARM:
> >           - GCC 5.1 or later
> >           - GNU Binutils 2.25 or later
> > +        or
> > +        - Clang/LLVM 11 or later
> >         - For RISC-V 64-bit:
> >           - GCC 12.2 or later
> >           - GNU Binutils 2.39 or later
> > diff --git a/xen/arch/arm/arch.mk b/xen/arch/arm/arch.mk
> > index 9c4bedfb3b..bcf548069b 100644
> > --- a/xen/arch/arm/arch.mk
> > +++ b/xen/arch/arm/arch.mk
> > @@ -13,6 +13,7 @@ ifeq ($(CONFIG_MPU),y)
> >   CFLAGS-$(CONFIG_ARM_64) += -march=armv8-r
> >   else
> >   CFLAGS-$(CONFIG_ARM_64) += -mcpu=generic
> > +CFLAGS-$(CONFIG_ARM_64) += -march=armv8
> >   endif
> >   CFLAGS-$(CONFIG_ARM_64) += -mgeneral-regs-only # No fp registers etc
> >   $(call cc-option-add,CFLAGS-$(CONFIG_ARM_64),CC,-mno-outline-atomics)
> > diff --git a/xen/arch/arm/arm64/vfp.c b/xen/arch/arm/arm64/vfp.c
> > index c4f89c7b0e..51fd2ddc54 100644
> > --- a/xen/arch/arm/arm64/vfp.c
> > +++ b/xen/arch/arm/arm64/vfp.c
> > @@ -46,6 +46,9 @@ static inline void restore_state(const uint64_t *fpregs)
> >                    : : "Q" (*fpregs), "r" (fpregs));
> >   }
> >
> > +#if defined(CONFIG_CC_IS_CLANG)
> > +__attribute__((target("fp-armv8")))
> > +#endif
>
> Based on Jan's comment, I am a bit puzzled why adding #ifdef is
> sufficient. In fact, I do agree with Jan, my understanding of
> target(...) is this will impact the ABI.
>
> I haven't experienced any issue with the C side yet. But I know in the
> Rust world (they also have an LLVM backend), they decided to prevent
> enabling fp/neon [1] at the function level.
>
> Did you find any documentation that would suggest this is safe?
>
> Now regarding the issue you mentioned in v1:
>
>  > On top of those, `READ_SYSREG(FPSR)`, `READ_SYSREG(FPCR)`,
>  > `WRITE_SYSREG(v->arch.vfp.fpsr, FPSR)`and
>  > `WRITE_SYSREG(v->arch.vfp.fpcr, FPCR)` using FP.
>  > I think I cannot apply __attribute__ on statements.
>
> Do you mean the compiler will complain that you are trying to access
> FPCR/FPSR if you don't add the __atribute__ at the function level?
>
> If so, what you could possibly do is either rewriting the functions in
> assembly or open-code the "{WRITE, READ}_SYSREG()" and add a line
> ".arch_extension fp".

I couldn't find any documentation to suggest that it is safe. I will
do what you and Jan suggested and use ".arch_extension fp".

~Saman

>
> Cheers,
>
> [1] https://github.com/llvm/llvm-project/issues/110632
>
> --
> Julien Grall
>
[PATCH v3] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
This patch enables building Xen for the arm64 using the Clang/LLVM compiler.
Changes include:
- Add explicit -march=armv8 flag for arm64 builds.
- Introduce `READ_FP_SYSREG` and `WRITE_FP_SYSREG` to encapsulate the required
  `.arch_extension fp` directive for system fp register access.
- Add ".arch_extension fp" to the inline assembly for `save_state` and
  `restore_state`.

Signed-off-by: Saman Dehghan <samaan.dehghan@gmail.com>
---
 README                   |  2 ++
 xen/arch/arm/arch.mk     |  1 +
 xen/arch/arm/arm64/vfp.c | 30 ++++++++++++++++++++++--------
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/README b/README
index 889a4ea906..67c1aa7fe6 100644
--- a/README
+++ b/README
@@ -45,6 +45,8 @@ provided by your OS distributor:
       - For ARM:
         - GCC 5.1 or later
         - GNU Binutils 2.25 or later
+        or
+        - Clang/LLVM 11 or later
       - For RISC-V 64-bit:
         - GCC 12.2 or later
         - GNU Binutils 2.39 or later
diff --git a/xen/arch/arm/arch.mk b/xen/arch/arm/arch.mk
index 9c4bedfb3b..bcf548069b 100644
--- a/xen/arch/arm/arch.mk
+++ b/xen/arch/arm/arch.mk
@@ -13,6 +13,7 @@ ifeq ($(CONFIG_MPU),y)
 CFLAGS-$(CONFIG_ARM_64) += -march=armv8-r
 else
 CFLAGS-$(CONFIG_ARM_64) += -mcpu=generic
+CFLAGS-$(CONFIG_ARM_64) += -march=armv8
 endif
 CFLAGS-$(CONFIG_ARM_64) += -mgeneral-regs-only # No fp registers etc
 $(call cc-option-add,CFLAGS-$(CONFIG_ARM_64),CC,-mno-outline-atomics)
diff --git a/xen/arch/arm/arm64/vfp.c b/xen/arch/arm/arm64/vfp.c
index c4f89c7b0e..ea75c7a2b2 100644
--- a/xen/arch/arm/arm64/vfp.c
+++ b/xen/arch/arm/arm64/vfp.c
@@ -6,7 +6,8 @@
 
 static inline void save_state(uint64_t *fpregs)
 {
-    asm volatile("stp q0, q1, [%1, #16 * 0]\n\t"
+    asm volatile(".arch_extension fp\n\t"
+                 "stp q0, q1, [%1, #16 * 0]\n\t"
                  "stp q2, q3, [%1, #16 * 2]\n\t"
                  "stp q4, q5, [%1, #16 * 4]\n\t"
                  "stp q6, q7, [%1, #16 * 6]\n\t"
@@ -27,7 +28,8 @@ static inline void save_state(uint64_t *fpregs)
 
 static inline void restore_state(const uint64_t *fpregs)
 {
-    asm volatile("ldp q0, q1, [%1, #16 * 0]\n\t"
+    asm volatile(".arch_extension fp\n\t"
+                 "ldp q0, q1, [%1, #16 * 0]\n\t"
                  "ldp q2, q3, [%1, #16 * 2]\n\t"
                  "ldp q4, q5, [%1, #16 * 4]\n\t"
                  "ldp q6, q7, [%1, #16 * 6]\n\t"
@@ -46,6 +48,18 @@ static inline void restore_state(const uint64_t *fpregs)
                  : : "Q" (*fpregs), "r" (fpregs));
 }
 
+#define WRITE_FP_SYSREG(v, name) do {                               \
+    uint64_t _r = (v);                                              \
+    asm volatile(".arch_extension fp\n\t"                           \
+                 "msr "__stringify(name)", %0" : : "r" (_r));       \
+} while (0)
+
+#define READ_FP_SYSREG(name) ({                                     \
+    uint64_t _r;                                                    \
+    asm volatile(".arch_extension fp\n\t"                           \
+                 "mrs  %0, "__stringify(name) : "=r" (_r));         \
+    _r; })
+
 void vfp_save_state(struct vcpu *v)
 {
     if ( !cpu_has_fp )
@@ -56,10 +70,10 @@ void vfp_save_state(struct vcpu *v)
     else
         save_state(v->arch.vfp.fpregs);
 
-    v->arch.vfp.fpsr = READ_SYSREG(FPSR);
-    v->arch.vfp.fpcr = READ_SYSREG(FPCR);
+    v->arch.vfp.fpsr = READ_FP_SYSREG(FPSR);
+    v->arch.vfp.fpcr = READ_FP_SYSREG(FPCR);
     if ( is_32bit_domain(v->domain) )
-        v->arch.vfp.fpexc32_el2 = READ_SYSREG(FPEXC32_EL2);
+        v->arch.vfp.fpexc32_el2 = READ_FP_SYSREG(FPEXC32_EL2);
 }
 
 void vfp_restore_state(struct vcpu *v)
@@ -72,8 +86,8 @@ void vfp_restore_state(struct vcpu *v)
     else
         restore_state(v->arch.vfp.fpregs);
 
-    WRITE_SYSREG(v->arch.vfp.fpsr, FPSR);
-    WRITE_SYSREG(v->arch.vfp.fpcr, FPCR);
+    WRITE_FP_SYSREG(v->arch.vfp.fpsr, FPSR);
+    WRITE_FP_SYSREG(v->arch.vfp.fpcr, FPCR);
     if ( is_32bit_domain(v->domain) )
-        WRITE_SYSREG(v->arch.vfp.fpexc32_el2, FPEXC32_EL2);
+        WRITE_FP_SYSREG(v->arch.vfp.fpexc32_el2, FPEXC32_EL2);
 }
-- 
2.49.0
Re: [PATCH v3] xen/arm64: Add support Clang build on arm64
Posted by Jan Beulich 1 month, 4 weeks ago
On 11.12.2025 13:57, Saman Dehghan wrote:
> --- a/xen/arch/arm/arm64/vfp.c
> +++ b/xen/arch/arm/arm64/vfp.c
> @@ -6,7 +6,8 @@
>  
>  static inline void save_state(uint64_t *fpregs)
>  {
> -    asm volatile("stp q0, q1, [%1, #16 * 0]\n\t"
> +    asm volatile(".arch_extension fp\n\t"

This will take effect for the rest of the (generated) assembler file, which aiui
isn't what you want.

Jan
Re: [PATCH v3] xen/arm64: Add support Clang build on arm64
Posted by Saman Dehghan 1 month, 4 weeks ago
On Thu, Dec 11, 2025 at 7:50 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 11.12.2025 13:57, Saman Dehghan wrote:
> > --- a/xen/arch/arm/arm64/vfp.c
> > +++ b/xen/arch/arm/arm64/vfp.c
> > @@ -6,7 +6,8 @@
> >
> >  static inline void save_state(uint64_t *fpregs)
> >  {
> > -    asm volatile("stp q0, q1, [%1, #16 * 0]\n\t"
> > +    asm volatile(".arch_extension fp\n\t"
>
> This will take effect for the rest of the (generated) assembler file, which aiui
> isn't what you want.

Thanks Jan, I also noticed I forgot ".arch_extension nofp" just after
sending the patch. Sorry about that.

~Saman

>
> Jan