On 02/03/2022 13:39, Andrew Cooper wrote:
> On 02/03/2022 10:34, Jan Beulich wrote:
>> On 02.03.2022 11:12, Andrew Cooper wrote:
>>> On 02/03/2022 08:10, Jan Beulich wrote:
>>>> On 01.03.2022 15:58, Andrew Cooper wrote:
>>>>> On 25/02/2022 08:24, Jan Beulich wrote:
>>>>>> On 22.02.2022 12:47, Andrew Cooper wrote:
>>>>>>> --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
>>>>>>> +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
>>>>>>> @@ -628,7 +628,7 @@ static void cf_check amd_dump_page_tables(struct 
>>>>>>> domain *d)
>>>>>>>                                hd->arch.amd.paging_mode, 0, 0);
>>>>>>>  }
>>>>>>>  
>>>>>>> -static const struct iommu_ops __initconstrel _iommu_ops = {
>>>>>>> +static const struct iommu_ops __initconst_cf_clobber _iommu_ops = {
>>>>>> Following my initcall related remark on x86'es time.c I'm afraid I don't
>>>>>> see how this and ...
>>>>>>
>>>>>>> @@ -2794,7 +2793,7 @@ static int __init cf_check 
>>>>>>> intel_iommu_quarantine_init(struct domain *d)
>>>>>>>      return rc;
>>>>>>>  }
>>>>>>>  
>>>>>>> -static struct iommu_ops __initdata vtd_ops = {
>>>>>>> +static const struct iommu_ops __initconst_cf_clobber vtd_ops = {
>>>>>> ... this actually works. But I guess I must be overlooking something, as
>>>>>> I'm sure that you did test the change.
>>>>>>
>>>>>> Both ops structures reference a function, through .adjust_irq_affinities,
>>>>>> which isn't __init but which is used (besides here) for an initcall. With
>>>>>> the ENDBR removed by the time initcalls are run, these should cause #CP.
>>>>> This doesn't explode because the indirect calls are resolved to direct
>>>>> calls before the ENDBR's are clobbered to NOP4.
>>>> I'm afraid I don't understand: The problematic call is in do_initcalls():
>>>>
>>>>     for ( call = __presmp_initcall_end; call < __initcall_end; call++ )
>>>>         (*call)();
>>>>
>>>> I don't see how this could be converted to a direct call.
>>> Oh.  iov_adjust_irq_affinities()'s double use is hiding here.
>>>
>>> The safety rule for cf_clobber is that there must not be any
>>> non-alt-called callers.  We need to fix it:
>>>
>>> diff --git a/xen/drivers/passthrough/amd/iommu_init.c
>>> b/xen/drivers/passthrough/amd/iommu_init.c
>>> index 657c7f619a51..b1af5085efda 100644
>>> --- a/xen/drivers/passthrough/amd/iommu_init.c
>>> +++ b/xen/drivers/passthrough/amd/iommu_init.c
>>> @@ -831,7 +831,12 @@ int cf_check iov_adjust_irq_affinities(void)
>>>  
>>>      return 0;
>>>  }
>>> -__initcall(iov_adjust_irq_affinities);
>>> +
>>> +int cf_check __init initcall_iov_adjust_irq_affinities(void)
>>> +{
>>> +    return iommu_call(&iommu_ops, adjust_irq_affinities);
>>> +}
>>> +__initcall(initcall_iov_adjust_irq_affinities);
>>>  
>>>  /*
>>>   * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall
>>> Translations)
>>>
>>>
>>>> Afaics only pre-SMP initcalls are safe in this regard: 
>>>> do_presmp_initcalls()
>>>> is called immediately ahead of alternative_branches().
>>>>
>>>> Isn't this (previously?) working related to your "x86/spec-ctrl: Disable
>>>> retpolines with CET-IBT"?
>>> No.  It's because AMD CPUs don't have CET-IBT at this juncture, and will
>>> never encounter a faulting situation.
>> I'm still lost. An exactly matching construct exists in VT-d code (and
>> my initial comment also was on VT-d). The AMD one is actually a clone
>> of that much older one. The initcall really wants to move to vendor
>> independent code, but I'd still like to understand why no fault was
>> ever observed.
> Lovely.  It's got a vtd infix which is why it escaped my grep.
>
> And yes, I really would expect that to explode on my test system...

And the answer is that the linker script collects .init.rodata.* ahead
of the dedicated .init.rodata.cf_clobber section.

Meaning that __initdata_cf_clobber works as expected but
__initconst_cf_clobber is a no-op.

~Andrew

Reply via email to