diff mbox series

[v4,10/12] xen/tools: add sve parameter in XL configuration

Message ID 20230327105944.1360856-11-luca.fancellu@arm.com (mailing list archive)
State Superseded
Headers show
Series SVE feature for arm guests | expand

Commit Message

Luca Fancellu March 27, 2023, 10:59 a.m. UTC
Add sve parameter in XL configuration to allow guests to use
SVE feature.

Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Acked-by: George Dunlap <george.dunlap@cloud.com>
---
Changes from v3:
 - no changes
Changes from v2:
 - domain configuration field name has changed to sve_vl,
   also its value now is VL/128.
 - Add Ack-by George for the Golang bits
Changes from v1:
 - updated to use arch_capabilities field for vector length
Changes from RFC:
 - changed libxl_types.idl sve field to uint16
 - now toolstack uses info from physinfo to check against the
   sve XL value
 - Changed documentation
---
 docs/man/xl.cfg.5.pod.in             | 11 +++++++++++
 tools/golang/xenlight/helpers.gen.go |  2 ++
 tools/golang/xenlight/types.gen.go   |  1 +
 tools/include/libxl.h                |  5 +++++
 tools/libs/light/libxl_arm.c         |  2 ++
 tools/libs/light/libxl_types.idl     |  1 +
 tools/xl/xl_parse.c                  | 26 ++++++++++++++++++++++++--
 7 files changed, 46 insertions(+), 2 deletions(-)

Comments

Anthony PERARD March 31, 2023, 2:23 p.m. UTC | #1
On Mon, Mar 27, 2023 at 11:59:42AM +0100, Luca Fancellu wrote:
> diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
> index 10f37990be57..adf48fe8ac1d 100644
> --- a/docs/man/xl.cfg.5.pod.in
> +++ b/docs/man/xl.cfg.5.pod.in
> @@ -2952,6 +2952,17 @@ Currently, only the "sbsa_uart" model is supported for ARM.
>  
>  =back
>  
> +=item B<sve="NUMBER">
> +
> +To enable SVE, user must specify a number different from zero, maximum 2048 and
> +multiple of 128. That value will be the maximum number of SVE registers bits
> +that the hypervisor will impose to this guest. If the platform has a lower

Maybe start by describing what the "sve" value is before imposing
limits. Maybe something like:

    Set the maximum vector length that a guest's Scalable Vector
    Extension (SVE) can use. Or disable it by specifying 0, the default.

    Value needs to be a multiple of 128, with a maximum of 2048 or the
    maximum supported by the platform.

Would this, or something like that be a good explanation of the "sve"
configuration option?

> +supported bits value, then the domain creation will fail.
> +A value equal to zero is the default and it means this guest is not allowed to
> +use SVE.
> +
> +=back
> +
>  =head3 x86
>  
>  =over 4
> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
> index ddc7b2a15975..16a49031fd51 100644
> --- a/tools/libs/light/libxl_arm.c
> +++ b/tools/libs/light/libxl_arm.c
> @@ -211,6 +211,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>          return ERROR_FAIL;
>      }
>  
> +    config->arch.sve_vl = d_config->b_info.arch_arm.sve;

This truncate a 16bit value into an 8bit value, I think you should check
that the value can actually fit.

And maybe check `d_config->b_info.arch_arm.sve` value here instead of
`xl` as commented later.

> +
>      return 0;
>  }
>  
> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
> index fd31dacf7d5a..ef4a8358e54e 100644
> --- a/tools/libs/light/libxl_types.idl
> +++ b/tools/libs/light/libxl_types.idl
> @@ -690,6 +690,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>  
>      ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
>                                 ("vuart", libxl_vuart_type),
> +                               ("sve", uint16),

I wonder if renaming "sve" to "sve_vl" here would make sense, seeing
that "sve_vl" is actually used in other places.

>                                ])),
>      ("arch_x86", Struct(None, [("msr_relaxed", libxl_defbool),
>                                ])),
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 1f6f47daf4e1..3cbc23b36952 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -12,6 +12,7 @@
>   * GNU Lesser General Public License for more details.
>   */
>  
> +#include <arm-arch-capabilities.h>

Could you add this headers after public ones?

>  #include <ctype.h>
>  #include <inttypes.h>
>  #include <limits.h>
> @@ -1312,8 +1313,6 @@ void parse_config_data(const char *config_source,
>          exit(EXIT_FAILURE);
>      }
>  
> -    libxl_physinfo_dispose(&physinfo);
> -
>      config= xlu_cfg_init(stderr, config_source);
>      if (!config) {
>          fprintf(stderr, "Failed to allocate for configuration\n");
> @@ -2887,6 +2886,29 @@ skip_usbdev:
>          }
>      }
>  
> +    if (!xlu_cfg_get_long (config, "sve", &l, 0)) {
> +        unsigned int arm_sve_vl =
> +            arch_capabilities_arm_sve(physinfo.arch_capabilities);
> +        if (!arm_sve_vl) {
> +            fprintf(stderr, "SVE is not supported by the platform\n");
> +            exit(-ERROR_FAIL);

"ERROR_FAIL" is a "libxl_error", instead exit with "EXIT_FAILURE".

> +        } else if (((l % 128) != 0) || (l > 2048)) {
> +            fprintf(stderr,
> +                    "Invalid sve value: %ld. Needs to be <= 2048 and multiple"
> +                    " of 128\n", l);
> +            exit(-ERROR_FAIL);
> +        } else if (l > arm_sve_vl) {
> +            fprintf(stderr,
> +                    "Invalid sve value: %ld. Platform supports up to %u bits\n",
> +                    l, arm_sve_vl);
> +            exit(-ERROR_FAIL);
> +        }
> +        /* Vector length is divided by 128 in domain configuration struct */

That's wrong, beside this comment there's nothing that say that
`b_info->arch_arm.sve` needs to have a value divided by 128.
`b_info->arch_arm.sve` is just of type uint16_t (libxl_type.idl).

BTW, "tools/xl" (xl) use just one user of "tools/libs/light" (libxl), so
it's possible that other users would set `sve` to a value that haven't
been checked. So I think all the check that the `sve` value is correct
could be done in libxl instead.


> +        b_info->arch_arm.sve = l / 128U;
> +    }
> +
> +    libxl_physinfo_dispose(&physinfo);
> +
>      parse_vkb_list(config, d_config);
>  
>      d_config->virtios = NULL;

Thanks,
Luca Fancellu April 4, 2023, 1:48 p.m. UTC | #2
Hi Anthony,

Thanks for your review

> On 31 Mar 2023, at 15:23, Anthony PERARD <anthony.perard@citrix.com> wrote:
> 
> On Mon, Mar 27, 2023 at 11:59:42AM +0100, Luca Fancellu wrote:
>> diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
>> index 10f37990be57..adf48fe8ac1d 100644
>> --- a/docs/man/xl.cfg.5.pod.in
>> +++ b/docs/man/xl.cfg.5.pod.in
>> @@ -2952,6 +2952,17 @@ Currently, only the "sbsa_uart" model is supported for ARM.
>> 
>> =back
>> 
>> +=item B<sve="NUMBER">
>> +
>> +To enable SVE, user must specify a number different from zero, maximum 2048 and
>> +multiple of 128. That value will be the maximum number of SVE registers bits
>> +that the hypervisor will impose to this guest. If the platform has a lower
> 
> Maybe start by describing what the "sve" value is before imposing
> limits. Maybe something like:
> 
>    Set the maximum vector length that a guest's Scalable Vector
>    Extension (SVE) can use. Or disable it by specifying 0, the default.
> 
>    Value needs to be a multiple of 128, with a maximum of 2048 or the
>    maximum supported by the platform.
> 
> Would this, or something like that be a good explanation of the "sve"
> configuration option?

Yes I can change it, a need to do it anyway because I think also here, the suggestion
From Jan can apply and we could pass a negative value that means “max VL supported
by the platform"

> 
>> +supported bits value, then the domain creation will fail.
>> +A value equal to zero is the default and it means this guest is not allowed to
>> +use SVE.
>> +
>> +=back
>> +
>> =head3 x86
>> 
>> =over 4
>> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
>> index ddc7b2a15975..16a49031fd51 100644
>> --- a/tools/libs/light/libxl_arm.c
>> +++ b/tools/libs/light/libxl_arm.c
>> @@ -211,6 +211,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>>         return ERROR_FAIL;
>>     }
>> 
>> +    config->arch.sve_vl = d_config->b_info.arch_arm.sve;
> 
> This truncate a 16bit value into an 8bit value, I think you should check
> that the value can actually fit.
> 
> And maybe check `d_config->b_info.arch_arm.sve` value here instead of
> `xl` as commented later.

Yes I can do it, one question, can I use here xc_physinfo to retrieve the maximum
Vector length from arch_capabilities?
I mean, is there a better way or I can go for that?

> 
>> +
>>     return 0;
>> }
>> 
>> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
>> index fd31dacf7d5a..ef4a8358e54e 100644
>> --- a/tools/libs/light/libxl_types.idl
>> +++ b/tools/libs/light/libxl_types.idl
>> @@ -690,6 +690,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>> 
>>     ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
>>                                ("vuart", libxl_vuart_type),
>> +                               ("sve", uint16),
> 
> I wonder if renaming "sve" to "sve_vl" here would make sense, seeing
> that "sve_vl" is actually used in other places.

Yes I can rename it as sve_vl, I will also change the type to “integer"

> 
>>                               ])),
>>     ("arch_x86", Struct(None, [("msr_relaxed", libxl_defbool),
>>                               ])),
>> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
>> index 1f6f47daf4e1..3cbc23b36952 100644
>> --- a/tools/xl/xl_parse.c
>> +++ b/tools/xl/xl_parse.c
>> @@ -12,6 +12,7 @@
>>  * GNU Lesser General Public License for more details.
>>  */
>> 
>> +#include <arm-arch-capabilities.h>
> 
> Could you add this headers after public ones?

Yes

> 
>> #include <ctype.h>
>> #include <inttypes.h>
>> #include <limits.h>
>> @@ -1312,8 +1313,6 @@ void parse_config_data(const char *config_source,
>>         exit(EXIT_FAILURE);
>>     }
>> 
>> -    libxl_physinfo_dispose(&physinfo);
>> -
>>     config= xlu_cfg_init(stderr, config_source);
>>     if (!config) {
>>         fprintf(stderr, "Failed to allocate for configuration\n");
>> @@ -2887,6 +2886,29 @@ skip_usbdev:
>>         }
>>     }
>> 
>> +    if (!xlu_cfg_get_long (config, "sve", &l, 0)) {
>> +        unsigned int arm_sve_vl =
>> +            arch_capabilities_arm_sve(physinfo.arch_capabilities);
>> +        if (!arm_sve_vl) {
>> +            fprintf(stderr, "SVE is not supported by the platform\n");
>> +            exit(-ERROR_FAIL);
> 
> "ERROR_FAIL" is a "libxl_error", instead exit with "EXIT_FAILURE".

Ok I will use the right type

> 
>> +        } else if (((l % 128) != 0) || (l > 2048)) {
>> +            fprintf(stderr,
>> +                    "Invalid sve value: %ld. Needs to be <= 2048 and multiple"
>> +                    " of 128\n", l);
>> +            exit(-ERROR_FAIL);
>> +        } else if (l > arm_sve_vl) {
>> +            fprintf(stderr,
>> +                    "Invalid sve value: %ld. Platform supports up to %u bits\n",
>> +                    l, arm_sve_vl);
>> +            exit(-ERROR_FAIL);
>> +        }
>> +        /* Vector length is divided by 128 in domain configuration struct */
> 
> That's wrong, beside this comment there's nothing that say that
> `b_info->arch_arm.sve` needs to have a value divided by 128.
> `b_info->arch_arm.sve` is just of type uint16_t (libxl_type.idl).
> 
> BTW, "tools/xl" (xl) use just one user of "tools/libs/light" (libxl), so
> it's possible that other users would set `sve` to a value that haven't
> been checked. So I think all the check that the `sve` value is correct
> could be done in libxl instead.

Sure I will do that

> 
> 
>> +        b_info->arch_arm.sve = l / 128U;
>> +    }
>> +
>> +    libxl_physinfo_dispose(&physinfo);
>> +
>>     parse_vkb_list(config, d_config);
>> 
>>     d_config->virtios = NULL;
> 
> Thanks,
> 
> -- 
> Anthony PERARD
Anthony PERARD April 5, 2023, 3:14 p.m. UTC | #3
On Tue, Apr 04, 2023 at 01:48:34PM +0000, Luca Fancellu wrote:
> > On 31 Mar 2023, at 15:23, Anthony PERARD <anthony.perard@citrix.com> wrote:
> > 
> > On Mon, Mar 27, 2023 at 11:59:42AM +0100, Luca Fancellu wrote:
> >> diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
> >> index 10f37990be57..adf48fe8ac1d 100644
> >> --- a/docs/man/xl.cfg.5.pod.in
> >> +++ b/docs/man/xl.cfg.5.pod.in
> >> @@ -2952,6 +2952,17 @@ Currently, only the "sbsa_uart" model is supported for ARM.
> >> 
> >> =back
> >> 
> >> +=item B<sve="NUMBER">
> >> +
> >> +To enable SVE, user must specify a number different from zero, maximum 2048 and
> >> +multiple of 128. That value will be the maximum number of SVE registers bits
> >> +that the hypervisor will impose to this guest. If the platform has a lower
> > 
> > Maybe start by describing what the "sve" value is before imposing
> > limits. Maybe something like:
> > 
> >    Set the maximum vector length that a guest's Scalable Vector
> >    Extension (SVE) can use. Or disable it by specifying 0, the default.
> > 
> >    Value needs to be a multiple of 128, with a maximum of 2048 or the
> >    maximum supported by the platform.
> > 
> > Would this, or something like that be a good explanation of the "sve"
> > configuration option?
> 
> Yes I can change it, a need to do it anyway because I think also here, the suggestion
> From Jan can apply and we could pass a negative value that means “max VL supported
> by the platform"

Well, it's a config file, not a C ABI, so max allowed here doesn't have to be
spelled "-1", it could also be "max", "max-allowed",
"max-size-supported", ... So fill free deviate from the restricted C
ABI. But "-1" works as long as it's the only allowed negative number.

> > 
> >> +supported bits value, then the domain creation will fail.
> >> +A value equal to zero is the default and it means this guest is not allowed to
> >> +use SVE.
> >> +
> >> +=back
> >> +
> >> =head3 x86
> >> 
> >> =over 4
> >> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
> >> index ddc7b2a15975..16a49031fd51 100644
> >> --- a/tools/libs/light/libxl_arm.c
> >> +++ b/tools/libs/light/libxl_arm.c
> >> @@ -211,6 +211,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
> >>         return ERROR_FAIL;
> >>     }
> >> 
> >> +    config->arch.sve_vl = d_config->b_info.arch_arm.sve;
> > 
> > This truncate a 16bit value into an 8bit value, I think you should check
> > that the value can actually fit.
> > 
> > And maybe check `d_config->b_info.arch_arm.sve` value here instead of
> > `xl` as commented later.
> 
> Yes I can do it, one question, can I use here xc_physinfo to retrieve the maximum
> Vector length from arch_capabilities?
> I mean, is there a better way or I can go for that?

Yeah, there might be a "better" way. I think me suggestion to check the
sve value here was wrong. I still want to have it checked in libxl, but
it might be better to do that in the previous step, that is
"libxl__domain_config_setdefault". libxl__arch_domain_build_info_setdefault()
will have `physinfo` so you won't have to call xc_physinfo().


Regarding the default, libxl is capable of selecting a good set of
option, depending on the underling hardware. So is it possible that in
the future we would want to enable SVE by default? If that's even a
remote possibility, the current API wouldn't allow it because we have
"default" and "disable" been the same.

Since we want to add a max VL supported option, maybe we want to
separate the default and disable options. So we could keep the
single field `libxl_domain_build_info.arch_arm.sve` and have for example
"-1" for max-supported and "-2" for disabled, while "0" mean default.
Or alternatively, add an extra field libxl_defbool (can be
default/true/false) and keep the second one for VL. (That extra
"disabled" option would only be for libxl, for xl we can keep "sve=0"
mean disable, and the missing option just mean default.)

In any case, libxl__arch_domain_build_info_setdefault() will check
`b_info.arch_arm.sve` and set it to the value that can given to Xen. And
as of now, libxl__arch_domain_prepare_config() will just copy the value
from `b_info` to `config`. (I guess that last step _prepare_config()
could still do the division by 128.)


Thanks,
Luca Fancellu April 6, 2023, 5:53 a.m. UTC | #4
Hi Anthony,

>> 
>> Yes I can change it, a need to do it anyway because I think also here, the suggestion
>> From Jan can apply and we could pass a negative value that means “max VL supported
>> by the platform"
> 
> Well, it's a config file, not a C ABI, so max allowed here doesn't have to be
> spelled "-1", it could also be "max", "max-allowed",
> "max-size-supported", ... So fill free deviate from the restricted C
> ABI. But "-1" works as long as it's the only allowed negative number.

Yes while working on the patch I’ve found that I could declare this type in Libxl:

libxl_sve_type = Enumeration("sve_type", [
    (0, "disabled"),
    (128, "128"),
    (256, "256"),
    (384, "384"),
    (512, "512"),
    (640, "640"),
    (768, "768"),
    (896, "896"),
    (1024, "1024"),
    (1152, "1152"),
    (1280, "1280"),
    (1408, "1408"),
    (1536, "1536"),
    (1664, "1664"),
    (1792, "1792"),
    (1920, "1920"),
    (2048, "2048"),
    (-1, "hw")
    ], init_val = "LIBXL_SVE_TYPE_DISABLED”)

So that in xl I can just use libxl_sve_type_from_string

> 
>>> 
>>>> +supported bits value, then the domain creation will fail.
>>>> +A value equal to zero is the default and it means this guest is not allowed to
>>>> +use SVE.
>>>> +
>>>> +=back
>>>> +
>>>> =head3 x86
>>>> 
>>>> =over 4
>>>> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
>>>> index ddc7b2a15975..16a49031fd51 100644
>>>> --- a/tools/libs/light/libxl_arm.c
>>>> +++ b/tools/libs/light/libxl_arm.c
>>>> @@ -211,6 +211,8 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>>>>        return ERROR_FAIL;
>>>>    }
>>>> 
>>>> +    config->arch.sve_vl = d_config->b_info.arch_arm.sve;
>>> 
>>> This truncate a 16bit value into an 8bit value, I think you should check
>>> that the value can actually fit.
>>> 
>>> And maybe check `d_config->b_info.arch_arm.sve` value here instead of
>>> `xl` as commented later.
>> 
>> Yes I can do it, one question, can I use here xc_physinfo to retrieve the maximum
>> Vector length from arch_capabilities?
>> I mean, is there a better way or I can go for that?
> 
> Yeah, there might be a "better" way. I think me suggestion to check the
> sve value here was wrong. I still want to have it checked in libxl, but
> it might be better to do that in the previous step, that is
> "libxl__domain_config_setdefault". libxl__arch_domain_build_info_setdefault()
> will have `physinfo` so you won't have to call xc_physinfo().

Right, I’ve seen it before but I was unsure if it was the right way, now that you
suggested it, I will go for that.

Thank you.

Cheers,
Luca
diff mbox series

Patch

diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 10f37990be57..adf48fe8ac1d 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -2952,6 +2952,17 @@  Currently, only the "sbsa_uart" model is supported for ARM.
 
 =back
 
+=item B<sve="NUMBER">
+
+To enable SVE, user must specify a number different from zero, maximum 2048 and
+multiple of 128. That value will be the maximum number of SVE registers bits
+that the hypervisor will impose to this guest. If the platform has a lower
+supported bits value, then the domain creation will fail.
+A value equal to zero is the default and it means this guest is not allowed to
+use SVE.
+
+=back
+
 =head3 x86
 
 =over 4
diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
index 35397be2f9e2..72a3a12a6065 100644
--- a/tools/golang/xenlight/helpers.gen.go
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -1149,6 +1149,7 @@  default:
 return fmt.Errorf("invalid union key '%v'", x.Type)}
 x.ArchArm.GicVersion = GicVersion(xc.arch_arm.gic_version)
 x.ArchArm.Vuart = VuartType(xc.arch_arm.vuart)
+x.ArchArm.Sve = uint16(xc.arch_arm.sve)
 if err := x.ArchX86.MsrRelaxed.fromC(&xc.arch_x86.msr_relaxed);err != nil {
 return fmt.Errorf("converting field ArchX86.MsrRelaxed: %v", err)
 }
@@ -1653,6 +1654,7 @@  default:
 return fmt.Errorf("invalid union key '%v'", x.Type)}
 xc.arch_arm.gic_version = C.libxl_gic_version(x.ArchArm.GicVersion)
 xc.arch_arm.vuart = C.libxl_vuart_type(x.ArchArm.Vuart)
+xc.arch_arm.sve = C.uint16_t(x.ArchArm.Sve)
 if err := x.ArchX86.MsrRelaxed.toC(&xc.arch_x86.msr_relaxed); err != nil {
 return fmt.Errorf("converting field ArchX86.MsrRelaxed: %v", err)
 }
diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go
index 3d968a496744..3dc292b5f1be 100644
--- a/tools/golang/xenlight/types.gen.go
+++ b/tools/golang/xenlight/types.gen.go
@@ -564,6 +564,7 @@  TypeUnion DomainBuildInfoTypeUnion
 ArchArm struct {
 GicVersion GicVersion
 Vuart VuartType
+Sve uint16
 }
 ArchX86 struct {
 MsrRelaxed Defbool
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index cfa1a191318c..9f040316ad80 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -283,6 +283,11 @@ 
  */
 #define LIBXL_HAVE_BUILDINFO_ARCH_ARM_TEE 1
 
+/*
+ * libxl_domain_build_info has the arch_arm.sve field.
+ */
+#define LIBXL_HAVE_BUILDINFO_ARCH_ARM_SVE 1
+
 /*
  * LIBXL_HAVE_SOFT_RESET indicates that libxl supports performing
  * 'soft reset' for domains and there is 'soft_reset' shutdown reason
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index ddc7b2a15975..16a49031fd51 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -211,6 +211,8 @@  int libxl__arch_domain_prepare_config(libxl__gc *gc,
         return ERROR_FAIL;
     }
 
+    config->arch.sve_vl = d_config->b_info.arch_arm.sve;
+
     return 0;
 }
 
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index fd31dacf7d5a..ef4a8358e54e 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -690,6 +690,7 @@  libxl_domain_build_info = Struct("domain_build_info",[
 
     ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
                                ("vuart", libxl_vuart_type),
+                               ("sve", uint16),
                               ])),
     ("arch_x86", Struct(None, [("msr_relaxed", libxl_defbool),
                               ])),
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 1f6f47daf4e1..3cbc23b36952 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -12,6 +12,7 @@ 
  * GNU Lesser General Public License for more details.
  */
 
+#include <arm-arch-capabilities.h>
 #include <ctype.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -1312,8 +1313,6 @@  void parse_config_data(const char *config_source,
         exit(EXIT_FAILURE);
     }
 
-    libxl_physinfo_dispose(&physinfo);
-
     config= xlu_cfg_init(stderr, config_source);
     if (!config) {
         fprintf(stderr, "Failed to allocate for configuration\n");
@@ -2887,6 +2886,29 @@  skip_usbdev:
         }
     }
 
+    if (!xlu_cfg_get_long (config, "sve", &l, 0)) {
+        unsigned int arm_sve_vl =
+            arch_capabilities_arm_sve(physinfo.arch_capabilities);
+        if (!arm_sve_vl) {
+            fprintf(stderr, "SVE is not supported by the platform\n");
+            exit(-ERROR_FAIL);
+        } else if (((l % 128) != 0) || (l > 2048)) {
+            fprintf(stderr,
+                    "Invalid sve value: %ld. Needs to be <= 2048 and multiple"
+                    " of 128\n", l);
+            exit(-ERROR_FAIL);
+        } else if (l > arm_sve_vl) {
+            fprintf(stderr,
+                    "Invalid sve value: %ld. Platform supports up to %u bits\n",
+                    l, arm_sve_vl);
+            exit(-ERROR_FAIL);
+        }
+        /* Vector length is divided by 128 in domain configuration struct */
+        b_info->arch_arm.sve = l / 128U;
+    }
+
+    libxl_physinfo_dispose(&physinfo);
+
     parse_vkb_list(config, d_config);
 
     d_config->virtios = NULL;