* [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
@ 2026-07-08 7:49 Michal Orzel
2026-07-08 9:06 ` Halder, Ayan Kumar
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Michal Orzel @ 2026-07-08 7:49 UTC (permalink / raw)
To: xen-devel
Cc: Michal Orzel, Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
construct_domain() creates the secondary vCPUs in a loop, but on a
vcpu_create() failure it only prints a message and breaks out of the
loop returning success. As a result the domain can be constructed
with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
below max_vcpus.
When the guest probes the redistributor of a vCPU that was never created,
get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
Return an error instead of breaking out of the loop. Both callers
(construct_domU() and construct_hwdom()) already propagate a negative
return value and fail domain construction, which is the correct
behaviour: a domain that cannot provide the requested number of vCPUs
should not be brought up.
Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
Signed-off-by: Michal Orzel <michal.orzel@amd.com>
---
xen/arch/arm/domain_build.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 550617f152bb..b46574fd32aa 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
if ( vcpu_create(d, i) == NULL )
{
printk("Failed to allocate d%dv%d\n", d->domain_id, i);
- break;
+ return -EINVAL;
}
if ( is_64bit_domain(d) )
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 7:49 [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created Michal Orzel
@ 2026-07-08 9:06 ` Halder, Ayan Kumar
2026-07-08 11:20 ` Orzel, Michal
2026-07-08 9:18 ` Dmytro Prokopchuk1
2026-07-08 11:30 ` Andrew Cooper
2 siblings, 1 reply; 9+ messages in thread
From: Halder, Ayan Kumar @ 2026-07-08 9:06 UTC (permalink / raw)
To: Michal Orzel, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
Hi MIchal,
Nice catch. Few questions.
On 08/07/2026 08:49, Michal Orzel wrote:
> construct_domain() creates the secondary vCPUs in a loop, but on a
> vcpu_create() failure it only prints a message and breaks out of the
> loop returning success. As a result the domain can be constructed
> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
> below max_vcpus.
>
> When the guest probes the redistributor of a vCPU that was never created,
Shouldn't the guest check how many vCPUs were created and probe the ones
that were created ?
> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>
> Return an error instead of breaking out of the loop. Both callers
> (construct_domU() and construct_hwdom()) already propagate a negative
> return value and fail domain construction, which is the correct
> behaviour: a domain that cannot provide the requested number of vCPUs
> should not be brought up.
I see your reasoning.
Alternatively it can be a design choice. Xen does not commit to create
the max_vcpus that was requested.
If Xen is unable to create any vCPU, it should abort domain creation.
If Xen creates lesser number of vCPUs than requested by max_vcpus, it
can just print a warning and carry on.
In that case it should be the guest's responsibility to check the number
of CPUs that it has.
- Ayan
>
> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
> ---
> xen/arch/arm/domain_build.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 550617f152bb..b46574fd32aa 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
> if ( vcpu_create(d, i) == NULL )
> {
> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
> - break;
> + return -EINVAL;
> }
>
> if ( is_64bit_domain(d) )
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 7:49 [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created Michal Orzel
2026-07-08 9:06 ` Halder, Ayan Kumar
@ 2026-07-08 9:18 ` Dmytro Prokopchuk1
2026-07-08 11:56 ` Orzel, Michal
2026-07-08 11:30 ` Andrew Cooper
2 siblings, 1 reply; 9+ messages in thread
From: Dmytro Prokopchuk1 @ 2026-07-08 9:18 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Hi Michal,
On 7/8/26 10:49, Michal Orzel wrote:
> construct_domain() creates the secondary vCPUs in a loop, but on a
> vcpu_create() failure it only prints a message and breaks out of the
> loop returning success. As a result the domain can be constructed
> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
> below max_vcpus.
>
> When the guest probes the redistributor of a vCPU that was never created,
> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>
> Return an error instead of breaking out of the loop. Both callers
> (construct_domU() and construct_hwdom()) already propagate a negative
> return value and fail domain construction, which is the correct
> behaviour: a domain that cannot provide the requested number of vCPUs
> should not be brought up.
>
> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
> ---
> xen/arch/arm/domain_build.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 550617f152bb..b46574fd32aa 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
> if ( vcpu_create(d, i) == NULL )
> {
> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
> - break;
> + return -EINVAL;
I would say returning "-ENOMEM" is more actual here, because
vcpu_create() fails in most cases due to unable to allocate memory.
> }
>
> if ( is_64bit_domain(d) )
BR, Dmytro.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 9:06 ` Halder, Ayan Kumar
@ 2026-07-08 11:20 ` Orzel, Michal
2026-07-08 11:27 ` Halder, Ayan Kumar
0 siblings, 1 reply; 9+ messages in thread
From: Orzel, Michal @ 2026-07-08 11:20 UTC (permalink / raw)
To: Halder, Ayan Kumar, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
On 08-Jul-26 11:06, Halder, Ayan Kumar wrote:
> Hi MIchal,
>
> Nice catch. Few questions.
>
> On 08/07/2026 08:49, Michal Orzel wrote:
>> construct_domain() creates the secondary vCPUs in a loop, but on a
>> vcpu_create() failure it only prints a message and breaks out of the
>> loop returning success. As a result the domain can be constructed
>> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
>> below max_vcpus.
>>
>> When the guest probes the redistributor of a vCPU that was never created,
> Shouldn't the guest check how many vCPUs were created and probe the ones
> that were created ?
See below about DTB.
>> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
>> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>>
>> Return an error instead of breaking out of the loop. Both callers
>> (construct_domU() and construct_hwdom()) already propagate a negative
>> return value and fail domain construction, which is the correct
>> behaviour: a domain that cannot provide the requested number of vCPUs
>> should not be brought up.
>
> I see your reasoning.
>
> Alternatively it can be a design choice. Xen does not commit to create
> the max_vcpus that was requested.
Everything can be a design choice but this one wouldn't be wise, would it?
All in all, we (Arm maintainers) aim at following the contract to fail as soon
as possible if the user request cannot be satisfied.
>
> If Xen is unable to create any vCPU, it should abort domain creation.
>
> If Xen creates lesser number of vCPUs than requested by max_vcpus, it
> can just print a warning and carry on.
No. Xen creates domain DTB before creating vCPUs, so Xen advertises something
that is not true. Here, Xen would create a DTB with e.g. 2 vCPUs while only 1
was created.
~Michal
>
> In that case it should be the guest's responsibility to check the number
> of CPUs that it has.
>
> - Ayan
>
>>
>> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
>> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
>> ---
>> xen/arch/arm/domain_build.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 550617f152bb..b46574fd32aa 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>> if ( vcpu_create(d, i) == NULL )
>> {
>> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
>> - break;
>> + return -EINVAL;
>> }
>>
>> if ( is_64bit_domain(d) )
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 11:20 ` Orzel, Michal
@ 2026-07-08 11:27 ` Halder, Ayan Kumar
2026-07-08 11:31 ` Orzel, Michal
0 siblings, 1 reply; 9+ messages in thread
From: Halder, Ayan Kumar @ 2026-07-08 11:27 UTC (permalink / raw)
To: Orzel, Michal, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
On 08/07/2026 12:20, Orzel, Michal wrote:
>
> On 08-Jul-26 11:06, Halder, Ayan Kumar wrote:
>> Hi MIchal,
>>
>> Nice catch. Few questions.
>>
>> On 08/07/2026 08:49, Michal Orzel wrote:
>>> construct_domain() creates the secondary vCPUs in a loop, but on a
>>> vcpu_create() failure it only prints a message and breaks out of the
>>> loop returning success. As a result the domain can be constructed
>>> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
>>> below max_vcpus.
>>>
>>> When the guest probes the redistributor of a vCPU that was never created,
>> Shouldn't the guest check how many vCPUs were created and probe the ones
>> that were created ?
> See below about DTB.
>
>>> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
>>> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>>>
>>> Return an error instead of breaking out of the loop. Both callers
>>> (construct_domU() and construct_hwdom()) already propagate a negative
>>> return value and fail domain construction, which is the correct
>>> behaviour: a domain that cannot provide the requested number of vCPUs
>>> should not be brought up.
>> I see your reasoning.
>>
>> Alternatively it can be a design choice. Xen does not commit to create
>> the max_vcpus that was requested.
> Everything can be a design choice but this one wouldn't be wise, would it?
> All in all, we (Arm maintainers) aim at following the contract to fail as soon
> as possible if the user request cannot be satisfied.
Can we remove the redundant DTB node so that the contract is maintained
? IMHO , stopping a domain creation seems severe if the other vCPUs were
created.
>
>> If Xen is unable to create any vCPU, it should abort domain creation.
>>
>> If Xen creates lesser number of vCPUs than requested by max_vcpus, it
>> can just print a warning and carry on.
> No. Xen creates domain DTB before creating vCPUs, so Xen advertises something
> that is not true. Here, Xen would create a DTB with e.g. 2 vCPUs while only 1
> was created.
I agree that this is a problem.
- Ayan
>
> ~Michal
>
>> In that case it should be the guest's responsibility to check the number
>> of CPUs that it has.
>>
>> - Ayan
>>
>>> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
>>> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
>>> ---
>>> xen/arch/arm/domain_build.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>> index 550617f152bb..b46574fd32aa 100644
>>> --- a/xen/arch/arm/domain_build.c
>>> +++ b/xen/arch/arm/domain_build.c
>>> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>>> if ( vcpu_create(d, i) == NULL )
>>> {
>>> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
>>> - break;
>>> + return -EINVAL;
>>> }
>>>
>>> if ( is_64bit_domain(d) )
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 7:49 [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created Michal Orzel
2026-07-08 9:06 ` Halder, Ayan Kumar
2026-07-08 9:18 ` Dmytro Prokopchuk1
@ 2026-07-08 11:30 ` Andrew Cooper
2026-07-08 11:40 ` Orzel, Michal
2 siblings, 1 reply; 9+ messages in thread
From: Andrew Cooper @ 2026-07-08 11:30 UTC (permalink / raw)
To: Michal Orzel, xen-devel
Cc: Andrew Cooper, Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
On 08/07/2026 8:49 am, Michal Orzel wrote:
> construct_domain() creates the secondary vCPUs in a loop, but on a
> vcpu_create() failure it only prints a message and breaks out of the
> loop returning success. As a result the domain can be constructed
> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
> below max_vcpus.
I'd suggest phrasing this as "partially constructed". "holes" isn't
really what's going on, given the linear nature of allocation.
Because of the object visibility, and because constructing vCPUs isn't
atomic, all code needs to cope with d->vcpu[] having no, some or all of
d->max_vcpus constructed.
>
> When the guest probes the redistributor of a vCPU that was never created,
> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
That's unsafe, especially as vcpu_id is calculated from an MMIO access.
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index c1c4d6f71ea8..c01cc596d593 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1111,10 +1111,10 @@ static struct vcpu *get_vcpu_from_rdist(struct
domain *d,
unsigned int vcpu_id;
vcpu_id = region->first_cpu + ((gpa - region->base) / GICV3_GICR_SIZE);
- if ( unlikely(vcpu_id >= d->max_vcpus) )
- return NULL;
- v = d->vcpu[vcpu_id];
+ v = domain_vcpu(d, vcpu_id);
+ if ( !v )
+ return NULL;
*offset = gpa - v->arch.vgic.rdist_base;
Do you want me to submit this separately?
>
> Return an error instead of breaking out of the loop. Both callers
> (construct_domU() and construct_hwdom()) already propagate a negative
> return value and fail domain construction, which is the correct
> behaviour: a domain that cannot provide the requested number of vCPUs
> should not be brought up.
>
> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
> ---
> xen/arch/arm/domain_build.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 550617f152bb..b46574fd32aa 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
> if ( vcpu_create(d, i) == NULL )
> {
> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
> - break;
> + return -EINVAL;
> }
>
> if ( is_64bit_domain(d) )
On x86, we explicitly tolerate a failure to build all of dom0's CPUs, if
at least one did get constructed. This is to increase the chances that
the server can boot and at least let an admin in to look at things.
However, I can see why such a behaviour is not wanted in a "single
pre-packaged system" as used by automotive.
~Andrew
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 11:27 ` Halder, Ayan Kumar
@ 2026-07-08 11:31 ` Orzel, Michal
0 siblings, 0 replies; 9+ messages in thread
From: Orzel, Michal @ 2026-07-08 11:31 UTC (permalink / raw)
To: Halder, Ayan Kumar, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
On 08-Jul-26 13:27, Halder, Ayan Kumar wrote:
>
> On 08/07/2026 12:20, Orzel, Michal wrote:
>>
>> On 08-Jul-26 11:06, Halder, Ayan Kumar wrote:
>>> Hi MIchal,
>>>
>>> Nice catch. Few questions.
>>>
>>> On 08/07/2026 08:49, Michal Orzel wrote:
>>>> construct_domain() creates the secondary vCPUs in a loop, but on a
>>>> vcpu_create() failure it only prints a message and breaks out of the
>>>> loop returning success. As a result the domain can be constructed
>>>> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
>>>> below max_vcpus.
>>>>
>>>> When the guest probes the redistributor of a vCPU that was never created,
>>> Shouldn't the guest check how many vCPUs were created and probe the ones
>>> that were created ?
>> See below about DTB.
>>
>>>> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
>>>> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>>>>
>>>> Return an error instead of breaking out of the loop. Both callers
>>>> (construct_domU() and construct_hwdom()) already propagate a negative
>>>> return value and fail domain construction, which is the correct
>>>> behaviour: a domain that cannot provide the requested number of vCPUs
>>>> should not be brought up.
>>> I see your reasoning.
>>>
>>> Alternatively it can be a design choice. Xen does not commit to create
>>> the max_vcpus that was requested.
>> Everything can be a design choice but this one wouldn't be wise, would it?
>> All in all, we (Arm maintainers) aim at following the contract to fail as soon
>> as possible if the user request cannot be satisfied.
> Can we remove the redundant DTB node so that the contract is maintained
> ? IMHO , stopping a domain creation seems severe if the other vCPUs were
> created.
No, we can't. First of all, the contract is to fail on unsatisifed user
requests. User requested e.g. 5 vCPUS, we created only 2 - we should bail out.
Please see all the dom0/dom0less code on Arm. Next, DTB generation and vCPU
creation happens *before* starting domains, so this is definitely not something
severe.
~Michal
>>
>>> If Xen is unable to create any vCPU, it should abort domain creation.
>>>
>>> If Xen creates lesser number of vCPUs than requested by max_vcpus, it
>>> can just print a warning and carry on.
>> No. Xen creates domain DTB before creating vCPUs, so Xen advertises something
>> that is not true. Here, Xen would create a DTB with e.g. 2 vCPUs while only 1
>> was created.
>
> I agree that this is a problem.
>
> - Ayan
>
>>
>> ~Michal
>>
>>> In that case it should be the guest's responsibility to check the number
>>> of CPUs that it has.
>>>
>>> - Ayan
>>>
>>>> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
>>>> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
>>>> ---
>>>> xen/arch/arm/domain_build.c | 2 +-
>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>
>>>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>>>> index 550617f152bb..b46574fd32aa 100644
>>>> --- a/xen/arch/arm/domain_build.c
>>>> +++ b/xen/arch/arm/domain_build.c
>>>> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>>>> if ( vcpu_create(d, i) == NULL )
>>>> {
>>>> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
>>>> - break;
>>>> + return -EINVAL;
>>>> }
>>>>
>>>> if ( is_64bit_domain(d) )
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 11:30 ` Andrew Cooper
@ 2026-07-08 11:40 ` Orzel, Michal
0 siblings, 0 replies; 9+ messages in thread
From: Orzel, Michal @ 2026-07-08 11:40 UTC (permalink / raw)
To: Andrew Cooper, xen-devel
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis,
Volodymyr Babchuk, ayan.kumar.halder
On 08-Jul-26 13:30, Andrew Cooper wrote:
> On 08/07/2026 8:49 am, Michal Orzel wrote:
>> construct_domain() creates the secondary vCPUs in a loop, but on a
>> vcpu_create() failure it only prints a message and breaks out of the
>> loop returning success. As a result the domain can be constructed
>> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
>> below max_vcpus.
>
> I'd suggest phrasing this as "partially constructed". "holes" isn't
> really what's going on, given the linear nature of allocation.
>
> Because of the object visibility, and because constructing vCPUs isn't
> atomic, all code needs to cope with d->vcpu[] having no, some or all of
> d->max_vcpus constructed.
>
>>
>> When the guest probes the redistributor of a vCPU that was never created,
>> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
>> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>
> That's unsafe, especially as vcpu_id is calculated from an MMIO access.
>
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index c1c4d6f71ea8..c01cc596d593 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -1111,10 +1111,10 @@ static struct vcpu *get_vcpu_from_rdist(struct
> domain *d,
> unsigned int vcpu_id;
>
> vcpu_id = region->first_cpu + ((gpa - region->base) / GICV3_GICR_SIZE);
> - if ( unlikely(vcpu_id >= d->max_vcpus) )
> - return NULL;
>
> - v = d->vcpu[vcpu_id];
> + v = domain_vcpu(d, vcpu_id);
> + if ( !v )
> + return NULL;
>
> *offset = gpa - v->arch.vgic.rdist_base;
>
>
> Do you want me to submit this separately?
If you have time, yes. Otherwise I can do that too tomorrow.
>
>
>>
>> Return an error instead of breaking out of the loop. Both callers
>> (construct_domU() and construct_hwdom()) already propagate a negative
>> return value and fail domain construction, which is the correct
>> behaviour: a domain that cannot provide the requested number of vCPUs
>> should not be brought up.
>>
>> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
>> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
>> ---
>> xen/arch/arm/domain_build.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 550617f152bb..b46574fd32aa 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>> if ( vcpu_create(d, i) == NULL )
>> {
>> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
>> - break;
>> + return -EINVAL;
>> }
>>
>> if ( is_64bit_domain(d) )
>
> On x86, we explicitly tolerate a failure to build all of dom0's CPUs, if
> at least one did get constructed. This is to increase the chances that
> the server can boot and at least let an admin in to look at things.
>
> However, I can see why such a behaviour is not wanted in a "single
> pre-packaged system" as used by automotive.
Yes, that is a known difference in behavior between x86 and Arm. We decided to
bail out asap.
~Michal
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created
2026-07-08 9:18 ` Dmytro Prokopchuk1
@ 2026-07-08 11:56 ` Orzel, Michal
0 siblings, 0 replies; 9+ messages in thread
From: Orzel, Michal @ 2026-07-08 11:56 UTC (permalink / raw)
To: Dmytro Prokopchuk1, xen-devel@lists.xenproject.org
On 08-Jul-26 11:18, Dmytro Prokopchuk1 wrote:
> Hi Michal,
>
> On 7/8/26 10:49, Michal Orzel wrote:
>> construct_domain() creates the secondary vCPUs in a loop, but on a
>> vcpu_create() failure it only prints a message and breaks out of the
>> loop returning success. As a result the domain can be constructed
>> with fewer vCPUs than d->max_vcpus, leaving NULL holes in d->vcpu[]
>> below max_vcpus.
>>
>> When the guest probes the redistributor of a vCPU that was never created,
>> get_vcpu_from_rdist() only checks vcpu_id against d->max_vcpus and then
>> dereferences the NULL d->vcpu[vcpu_id], resulting in a data abort.
>>
>> Return an error instead of breaking out of the loop. Both callers
>> (construct_domU() and construct_hwdom()) already propagate a negative
>> return value and fail domain construction, which is the correct
>> behaviour: a domain that cannot provide the requested number of vCPUs
>> should not be brought up.
>>
>> Fixes: 6b0e8e43348a ("xen/arm: allocate secondaries dom0 vcpus")
>> Signed-off-by: Michal Orzel <michal.orzel@amd.com>
>> ---
>> xen/arch/arm/domain_build.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index 550617f152bb..b46574fd32aa 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -1847,7 +1847,7 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
>> if ( vcpu_create(d, i) == NULL )
>> {
>> printk("Failed to allocate d%dv%d\n", d->domain_id, i);
>> - break;
>> + return -EINVAL;
>
> I would say returning "-ENOMEM" is more actual here, because
> vcpu_create() fails in most cases due to unable to allocate memory.
I think you're right. Not all, but most of them yes. Will change on commit.
~Michal
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-08 11:56 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 7:49 [for-4.22][PATCH] xen/arm: Fail domain construction if a secondary vCPU cannot be created Michal Orzel
2026-07-08 9:06 ` Halder, Ayan Kumar
2026-07-08 11:20 ` Orzel, Michal
2026-07-08 11:27 ` Halder, Ayan Kumar
2026-07-08 11:31 ` Orzel, Michal
2026-07-08 9:18 ` Dmytro Prokopchuk1
2026-07-08 11:56 ` Orzel, Michal
2026-07-08 11:30 ` Andrew Cooper
2026-07-08 11:40 ` Orzel, Michal
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.