[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v3 05/10] xen/arm: Setup virtual paging for non-boot CPUs on hotplug/resume



Hi Julien,


On Mon, Apr 30, 2018 at 4:47 PM, Julien Grall <julien.grall@xxxxxxx> wrote:
> Hi Mirela,
>
>
> On 27/04/18 18:12, Mirela Simonovic wrote:
>>
>> In existing code the virtual paging for non-boot CPUs is setup only on
>> boot.
>> The setup is triggered from start_xen() after all CPUs are brought online.
>> In other words, the initialization of VTCR_EL2 register is done out of the
>> cpu_up/start_secondary() control flow. However, the cpu_up flow is also
>> used
>> to hotplug non-boot CPUs on resume from suspend to RAM state, in which
>> case
>> the virtual paging will not be configured.
>>
>> With this patch the setting of paging is triggered from start_secondary()
>> function using cpu starting notifier (notify_cpu_starting() call). The
>> notifier is registered in p2m.c using init call. This has to be done with
>> init call rather than presmp_init because the registered callback depends
>> on vtcr configuration value which is setup after the presmp init calls
>> are executed (do_presmp_initcalls() called from start_xen()). Init calls
>> are executed after initial virtual paging is set up for all CPUs on boot.
>> This ensures that no callback can fire until the vtcr value is calculated
>> by Xen and virtual paging is set up initially for all CPUs. Also, this way
>> the virtual paging setup in boot scenario remains unchanged.
>>
>> It is assumed here that after the system completed the boot, CPUs that
>> execute start_secondary() were booted as well when the Xen itself was
>> booted. According to this assumption non-boot CPUs will always be
>> compliant
>> with the VTCR_EL2 value that was selected by Xen on boot.
>> Currently, there is no mechanism to trigger hotplugging of a CPU. This
>> will be added with the suspend to RAM support for ARM, where the hotplug
>> of non-boot CPUs will be triggered via enable_nonboot_cpus() call.
>>
>> Signed-off-by: Mirela Simonovic <mirela.simonovic@xxxxxxxxxx>
>>
>> ---
>> CC: Stefano Stabellini <sstabellini@xxxxxxxxxx>
>> CC: Julien Grall <julien.grall@xxxxxxx>
>> ---
>> Changes in v2:
>> -Fix commit message
>> -Save configured VTCR_EL2 value into static variable that will be used
>>   by non-boot CPUs on hotplug
>> -Add setup_virt_paging_secondary() and invoke it from start_secondary()
>>   if that CPU has to setup virtual paging (if the system state is not
>> boot)
>>
>> Changes in v3:
>> -Fix commit message
>> -Remove setup_virt_paging_secondary() and use notifier to setup virtual
>>   paging for non-boot CPU on hotplug.
>> -In setup_virt_paging() use vtcr static variable instead of local val
>> -In setup_virt_paging_one() use vtcr static variable instead of provided
>>   argument
>> ---
>>   xen/arch/arm/p2m.c | 82
>> +++++++++++++++++++++++++++++++++++++++++-------------
>>   1 file changed, 62 insertions(+), 20 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index d43c3aa896..98a1fe6de9 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -8,6 +8,8 @@
>>   #include <xen/iocap.h>
>>   #include <xen/mem_access.h>
>>   #include <xen/xmalloc.h>
>> +#include <xen/notifier.h>
>> +#include <xen/cpu.h>
>
>
> Please add them alphabetically.
>
>
>>   #include <public/vm_event.h>
>>   #include <asm/flushtlb.h>
>>   #include <asm/event.h>
>> @@ -1451,24 +1453,17 @@ err:
>>       return page;
>>   }
>>   -static void __init setup_virt_paging_one(void *data)
>> +/* VTCR value to be configured by all CPUs. Set only once by the boot CPU
>> */
>> +static uint64_t __read_mostly vtcr;
>> +
>> +static void setup_virt_paging_one(void *data)
>>   {
>> -    unsigned long val = (unsigned long)data;
>> -    WRITE_SYSREG32(val, VTCR_EL2);
>> +    WRITE_SYSREG32(vtcr, VTCR_EL2);
>>       isb();
>>   }
>>     void __init setup_virt_paging(void)
>>   {
>> -    /* Setup Stage 2 address translation */
>> -    unsigned long val =
>> VTCR_RES1|VTCR_SH0_IS|VTCR_ORGN0_WBWA|VTCR_IRGN0_WBWA;
>> -
>> -#ifdef CONFIG_ARM_32
>> -    printk("P2M: 40-bit IPA\n");
>> -    p2m_ipa_bits = 40;
>> -    val |= VTCR_T0SZ(0x18); /* 40 bit IPA */
>> -    val |= VTCR_SL0(0x1); /* P2M starts at first level */
>> -#else /* CONFIG_ARM_64 */
>>       const struct {
>>           unsigned int pabits; /* Physical Address Size */
>>           unsigned int t0sz;   /* Desired T0SZ, minimum in comment */
>> @@ -1491,6 +1486,16 @@ void __init setup_virt_paging(void)
>>       unsigned int pa_range = 0x10; /* Larger than any possible value */
>>       bool vmid_8_bit = false;
>
>
> That's not going to build on arm32 because vmid_8_bit & co are not used.
> While I will not ask you to test the changes on 32-bit board, I would at
> least want each change to be build test it on impacted architecture.
>
> In that particular case, you can just move the initialization of vtcr at
> after the endif because there is nothing that required that to be setup very
> early.
>
>
>>   +    /* Setup Stage 2 address translation */
>> +    vtcr = VTCR_RES1|VTCR_SH0_IS|VTCR_ORGN0_WBWA|VTCR_IRGN0_WBWA;
>> +
>> +#ifdef CONFIG_ARM_32
>> +    printk("P2M: 40-bit IPA\n");
>> +    p2m_ipa_bits = 40;
>> +    vtcr |= VTCR_T0SZ(0x18); /* 40 bit IPA */
>> +    vtcr |= VTCR_SL0(0x1); /* P2M starts at first level */
>> +#else /* CONFIG_ARM_64 */
>> +
>>       for_each_online_cpu ( cpu )
>>       {
>>           const struct cpuinfo_arm *info = &cpu_data[cpu];
>> @@ -1513,14 +1518,14 @@ void __init setup_virt_paging(void)
>>       if ( pa_range >= ARRAY_SIZE(pa_range_info) ||
>> !pa_range_info[pa_range].pabits )
>>           panic("Unknown encoding of ID_AA64MMFR0_EL1.PARange %x\n",
>> pa_range);
>>   -    val |= VTCR_PS(pa_range);
>> -    val |= VTCR_TG0_4K;
>> +    vtcr |= VTCR_PS(pa_range);
>> +    vtcr |= VTCR_TG0_4K;
>>         /* Set the VS bit only if 16 bit VMID is supported. */
>>       if ( MAX_VMID == MAX_VMID_16_BIT )
>> -        val |= VTCR_VS;
>> -    val |= VTCR_SL0(pa_range_info[pa_range].sl0);
>> -    val |= VTCR_T0SZ(pa_range_info[pa_range].t0sz);
>> +        vtcr |= VTCR_VS;
>> +    vtcr |= VTCR_SL0(pa_range_info[pa_range].sl0);
>> +    vtcr |= VTCR_T0SZ(pa_range_info[pa_range].t0sz);
>>         p2m_root_order = pa_range_info[pa_range].root_order;
>>       p2m_root_level = 2 - pa_range_info[pa_range].sl0;
>> @@ -1532,16 +1537,53 @@ void __init setup_virt_paging(void)
>>              ( MAX_VMID == MAX_VMID_16_BIT ) ? 16 : 8);
>>   #endif
>>       printk("P2M: %d levels with order-%d root, VTCR 0x%lx\n",
>> -           4 - P2M_ROOT_LEVEL, P2M_ROOT_ORDER, val);
>> +           4 - P2M_ROOT_LEVEL, P2M_ROOT_ORDER, vtcr);
>>         p2m_vmid_allocator_init();
>>         /* It is not allowed to concatenate a level zero root */
>>       BUG_ON( P2M_ROOT_LEVEL == 0 && P2M_ROOT_ORDER > 0 );
>> -    setup_virt_paging_one((void *)val);
>> -    smp_call_function(setup_virt_paging_one, (void *)val, 1);
>> +    setup_virt_paging_one(NULL);
>> +    smp_call_function(setup_virt_paging_one, NULL, 1);
>> +}
>> +
>> +static int cpu_virt_paging_callback(
>> +    struct notifier_block *nfb, unsigned long action, void *hcpu)
>
>
> The indentation looks wrong.
>

Editor indented this for me and it looks the same as in other places
where a notifier is defined. I did
grep -r "struct notifier_block \*nfb,"
to check. It looks weird but seems correct

>> +{
>> +    switch ( action )
>> +    {
>> +    case CPU_STARTING:
>> +        ASSERT(system_state != SYS_STATE_boot);
>
>
> I was about to complain about this but then saw you add the notifiers after.
> That's quite clever and the comment is really helpful :).
>
>> +        setup_virt_paging_one(NULL);
>> +        break;
>> +    default:
>> +        break;
>> +    }
>> +
>> +    return NOTIFY_DONE;
>>   }
>>   +static struct notifier_block cpu_virt_paging_nfb = {
>> +    .notifier_call = cpu_virt_paging_callback,
>> +    .priority = 100 /* highest priority */
>> +};
>> +
>> +static int __init cpu_virt_paging_init(void)
>> +{
>> +    register_cpu_notifier(&cpu_virt_paging_nfb);
>> +    return 0;
>> +}
>
>
> NIT: Missing newline.
>
>> +/*
>> + * Initialization of the notifier has to be done at init rather than
>> presmp_init
>> + * phase because: the registered notifier is used to setup virtual paging
>> for
>> + * non-boot CPUs after the initial virtual paging for all CPUs is already
>> setup,
>> + * i.e. when a non-boot CPU is hotplugged after the system has booted. In
>> other
>> + * words, the notifier should be registered after the virtual paging is
>> + * initially setup (setup_virt_paging() is called from start_xen()). This
>> is
>> + * required because vtcr config value has to be set before a notifier can
>> fire.
>> + */
>> +__initcall(cpu_virt_paging_init);
>> +
>>   /*
>>    * Local variables:
>>    * mode: C
>>
>
> Cheers,
>
> --
> Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.