Re: [PATCH 2/2] tools/ocaml: Fill arch_config for ARM in domain_getinfo{,list}()

Andrew Cooper <[email protected]> Thu, 30 Jul 2026 10:35:46 +0100
Newsgroups gmane.comp.emulators.xen.devel
Message-ID <[email protected]>
On 30/07/2026 9:43 am, Julian Vetter wrote:
>
> On 7/28/26 17:48, Andrew Cooper wrote:
>> From: Julian Vetter <[email protected]>
>>
>> Add the missing ARM logic, populating xen_arm_arch_domainconfig
>> from the raw xc_domaininfo_t the same way the x86 branch does for
>> xen_x86_arch_domainconfig.
>>
>> Signed-off-by: Julian Vetter <[email protected]>
>> Signed-off-by: Andrew Cooper <[email protected]>
>> ---
>> CC: Andrew Cooper <[email protected]>
>> CC: Andrii Sultanov <[email protected]>
>> CC: Guillaume Thouvenin <[email protected]>
>> CC: Julian Vetter <[email protected]>
>> CC: Oleksii Kurochko <[email protected]>
>> ---
>>   tools/ocaml/libs/xc/xenctrl_stubs.c | 16 ++++++++++++++--
>>   1 file changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c b/tools/ocaml/libs/xc/xenctrl_stubs.c
>> index 441e1d83cfec..fb983709066f 100644
>> --- a/tools/ocaml/libs/xc/xenctrl_stubs.c
>> +++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
>> @@ -444,9 +444,21 @@ static value alloc_domaininfo(xc_domaininfo_t * info)
>>   
>>   	Store_field(result, 15, tmp);
>>   
>> -#if defined(__i386__) || defined(__x86_64__)
>> +#if defined(__arm__) || defined(__aarch64__)
>>   
>> -	tag = 1; /* tag x86 */
>> +	tag = 0; /* tag ARM */
>> +
>> +        /* xen_arm_arch_domainconfig */
>> +        arch_config = caml_alloc_tuple(3);
>> +        Field(arch_config, 0) = Val_int(info->arch_config.gic_version);
>> +        Field(arch_config, 1) = Val_int(info->arch_config.nr_spis);
>> +
>> +	tmp = caml_copy_int32(info->arch_config.clock_frequency);
>> +        Field(arch_config, 2) = tmp;
> Shouldn't the Field() be a `Store_field(arch_config, 2, tmp);`, because 
> the `caml_copy_int32` makes an allocation on the minor heap to allow 
> OCAML's GC to keep track of this pointer if ever the arch_config is 
> promoted?

No (ish).  The Ocaml/C manual is subtly wrong in it's advice about this.

Using Store_field() would be safe, but it has an obscene overhead for a
scalar store, and caml_modify() does a whole bunch of barriers/atomics
which are not necessary on anything which isn't allocated from
caml_alloc_shr() (which we don't use at all).

The buggy construct is:

    Field(foo, bar) = caml_{copy,alloc,etc}(baz);

because C does not provide an ordering between evaluation of the Rvalue
vs the Lvalue.  Specifically, if the Lvalue were evaluated prior to the
function call, then indeed we could store into a stale pointer.

But, using tmp in the way we do:

    tmp = caml_copy_*(baz);
    Field(foo, bar) = tmp;

puts a sequence point after calling caml_copy_*(), and prior to
evaluating Field(), so guarantees to do them in the correct order.

In the Store_field() macro, this occurs by taking (val) into a local
variable, and not because of how it calls caml_modify().


In a perfect world we'd have a Store_field() that arranged for the
intermediate safety without calling caml_modify().

It is also telling that the Ocaml runtime has a total of 15 uses of
Store_field, and we've got more than that in this function alone, let
alone the rest of our bindings.

I do have a cleanup patch for those as well, once we got this bug sorted.

~Andrew