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

Re: [RFC PATCH v2 4/5] x86/hvm: Transition to needs_tlb_flush logic, use per-domain ASID


  • To: Teddy Astie <teddy.astie@xxxxxxxxxx>, Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Mon, 21 Sep 2026 15:24:37 +0200
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:From:Content-Language:References:Cc:To:Subject:User-Agent:MIME-Version:Date:Message-ID"
  • Autocrypt: addr=jbeulich@xxxxxxxx; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Jason Andryuk <jason.andryuk@xxxxxxx>, Tim Deegan <tim@xxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Mon, 21 Sep 2026 13:24:42 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 21.09.2026 14:51, Teddy Astie wrote:
> Le 18/09/2026 à 18:30, Ross Lagerwall a écrit :
>> On 7/31/26 3:46 PM, Teddy Astie wrote:
>>> --- a/xen/arch/x86/hvm/asid.c
>>> +++ b/xen/arch/x86/hvm/asid.c
>>> @@ -5,138 +5,115 @@
>>>    * Copyright (c) 2009, Citrix Systems, Inc.
>>>    */
>>> +#include <xen/errno.h>
>>>   #include <xen/init.h>
>>>   #include <xen/lib.h>
>>>   #include <xen/param.h>
>>> -#include <xen/sched.h>
>>> -#include <xen/smp.h>
>>> -#include <xen/percpu.h>
>>> +#include <xen/spinlock.h>
>>> +#include <xen/xvmalloc.h>
>>> +
>>> +#include <asm/bitops.h>
>>>   #include <asm/hvm/asid.h>
>>>   /* Xen command-line option to enable ASIDs */
>>>   static bool __read_mostly opt_asid_enabled = true;
>>>   boolean_param("asid", opt_asid_enabled);
>>> +bool __read_mostly asid_enabled = false;
>>> +static unsigned long __ro_after_init *asid_bitmap;
>>> +static unsigned long __ro_after_init asid_count;
>>> +static DEFINE_SPINLOCK(asid_lock);
>>> +
>>>   /*
>>> - * ASIDs partition the physical TLB.  In the current implementation 
>>> ASIDs are
>>> - * introduced to reduce the number of TLB flushes.  Each time the 
>>> guest's
>>> - * virtual address space changes (e.g. due to an INVLPG, MOV-TO-{CR3, 
>>> CR4}
>>> - * operation), instead of flushing the TLB, a new ASID is assigned.  
>>> This
>>> - * reduces the number of TLB flushes to at most 1/#ASIDs.  The biggest
>>> - * advantage is that hot parts of the hypervisor's code and data 
>>> retain in
>>> - * the TLB.
>>> - *
>>>    * Sketch of the Implementation:
>>> + * ASIDs are assigned uniquely per domain and doesn't change during 
>>> the lifecycle of the
>>> + * domain. Once vcpus are initialized and are up, we assign the same 
>>> ASID to all vcpus
>>> + * of that domain at the first VMRUN. In order to process a TLB flush 
>>> on a vcpu, we set
>>> + * needs_tlb_flush to schedule a TLB flush for the next VMRUN (e.g 
>>> using tlb control
>>> + * field of VMCB).
>>>    *
>>> - * ASIDs are a CPU-local resource.  As preemption of ASIDs is not 
>>> possible,
>>> - * ASIDs are assigned in a round-robin scheme.  To minimize the 
>>> overhead of
>>> - * ASID invalidation, at the time of a TLB flush,  ASIDs are tagged 
>>> with a
>>> - * 64-bit generation.  Only on a generation overflow the code needs to
>>> - * invalidate all ASID information stored at the VCPUs with are run 
>>> on the
>>> - * specific physical processor.  This overflow appears after about 2^80
>>> - * host processor cycles, so we do not optimize this case, but simply 
>>> disable
>>> - * ASID useage to retain correctness.
>>> + * We reserve ASID=1 as being the ASID used when none other is 
>>> available (or with asid
>>> + * use disabled). Multiples domains may use this ASID, thus we need 
>>> to systematically
>>> + * flush the TLB for this one when switching between vCPUs with ASID=1.
>>>    */
>>> -/* Per-CPU ASID management. */
>>> -struct hvm_asid_data {
>>> -   uint64_t core_asid_generation;
>>> -   uint32_t next_asid;
>>> -   uint32_t max_asid;
>>> -   bool disabled;
>>> -};
>>> -
>>> -static DEFINE_PER_CPU(struct hvm_asid_data, hvm_asid_data);
>>> -
>>> -void hvm_asid_init(unsigned int nasids)
>>> +int __init hvm_asid_init(unsigned long nasids)
>>>   {
>>> -    static int8_t __ro_after_init g_disabled = -1;
>>> -    struct hvm_asid_data *data = &this_cpu(hvm_asid_data);
>>> +    ASSERT(nasids);
>>> -    data->max_asid = nasids - 1;
>>> -    data->disabled = !opt_asid_enabled || (nasids <= 1);
>>> +    asid_count = nasids;
>>> +    asid_enabled = opt_asid_enabled && (nasids > 1);
>>> -    if ( g_disabled < 0 )
>>> -    {
>>> -        g_disabled = data->disabled;
>>> -        printk("HVM: ASIDs %sabled\n", data->disabled ? "dis" : "en");
>>> -    }
>>> -    else if ( g_disabled != data->disabled )
>>> -        printk("HVM: CPU%u: ASIDs %sabled\n", smp_processor_id(),
>>> -               data->disabled ? "dis" : "en");
>>> +    asid_bitmap = xvzalloc_array(unsigned long, 
>>> BITS_TO_LONGS(asid_count + 1));
>>> +    if ( !asid_bitmap )
>>> +        return -ENOMEM;
>>
>> Should there be a sanity check to avoid an excessive allocation? E.g. If
>> running under another hypervisor, it might set nasids to ~0 while with 
>> one per
>> domain we need no more than ~64k.
> 
> Indeed, I didn't consider that AMD had (and enumerates) 32-bits ASIDs. 
> Only Intel uses 16-bits VPIDs.
> 
> Limiting to 64k seems wise,

Why 64k, when there can be at most 32k domains?

> the remaining question is that I'm not sure 
> if we want to make that configurable.

Unless there are significant savings to be had, I'd say stick to the smaller
of what hardware offers and 32k.

Jan



 


Rackspace

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