All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleksii Kurochko <oleksii.kurochko@gmail.com>
To: Baptiste Le Duc <baptiste.le-duc@vates.tech>
Cc: xen-devel@lists.xenproject.org,
	"Romain Caritey" <Romain.Caritey@microchip.com>,
	"Zheng Zhang" <zhangzheng@iscas.ac.cn>,
	"Alistair Francis" <alistair.francis@wdc.com>,
	"Connor Davis" <connojdavis@gmail.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>,
	"Anthony PERARD" <anthony.perard@vates.tech>,
	"Michal Orzel" <michal.orzel@amd.com>,
	"Jan Beulich" <jbeulich@suse.com>,
	"Julien Grall" <julien@xen.org>,
	"Roger Pau Monné" <roger@xenproject.org>,
	"Stefano Stabellini" <sstabellini@kernel.org>
Subject: Re: [PATCH v3 11/39] xen/riscv: implement vCPU context switching
Date: Wed, 14 Oct 2026 16:05:47 +0200	[thread overview]
Message-ID: <9ac3fdbe-9f3b-4abd-ab8d-7e252a7cf809@gmail.com> (raw)
In-Reply-To: <1791305420.8631fc262581453bbf619ec5b2062170.1a1121f8fef0003f66@vates.tech>

[...]

>> diff --git a/xen/arch/riscv/include/asm/csr.h b/xen/arch/riscv/include/asm/csr.h
>> index a5cb24c863..aad82c6a6d 100644
>> --- a/xen/arch/riscv/include/asm/csr.h
>> +++ b/xen/arch/riscv/include/asm/csr.h
>> @@ -40,6 +40,13 @@
>>       csr_write(csr ## H, v_ >> 32);  \
>>   })
>>   
>> +#define csr_read64(csr)                 \
>> +({                                      \
>> +    uint64_t v_ = csr_read(csr ## H);   \
> This violates Misra 20.12 rule (docs/misra/rules.rst) as we use macro
> parameter `csr` as an operand of ##, while it could be expanded as a
> macro (e.g. csr_read64(CSR_HENVCFG)).

To avoid MISRA violation, if i understand it correctly, I will do the 
following:

+#define csr_read64(name)                       \
+({                                             \
+    uint64_t v_ = csr_read(CSR_ ## name ## H); \
+                                               \
+    (v_ << 32) | csr_read(CSR_ ## name);       \

and ...

>> +                                        \
>> +    (v_ << 32) | csr_read(csr);         \
>> +})
>> +
>>   /*
>>    * The two halves are read by separate instructions, so a CSR which hardware
>>    * increments can carry from the low half into the high one in between,
>> @@ -72,6 +79,12 @@
>>       (void)csr ## H;                 \
>>       csr_read(csr);                  \
>>   })
>> +
>> +#define csr_read64(csr)             \
>> +({                                  \
>> +    (void)csr ## H;                 \
> Same as above.

... the following here:

+#define csr_read64(name) csr_read(CSR_ ## name)


>> +    csr_read(csr);                  \
>> +})
>>   #endif

[...]

>> diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c
>> index de25607247..02e7f6364f 100644
>> --- a/xen/arch/riscv/p2m.c
>> +++ b/xen/arch/riscv/p2m.c
>> @@ -243,6 +243,15 @@ static void p2m_tlb_flush(struct p2m_domain *p2m)
>>   
>>       p2m->need_flush = false;
>>   
>> +    /*
>> +     * Order the p2m updates above against the read of dirty_cpumask below,
>> +     * pairing with the barrier in p2m_vmid_switch_to(). Either that hart is
>> +     * seen here and gets an HFENCE.GVMA, or it adds itself to the mask
>> +     * afterwards, in which case it starts walking this p2m only once the
>> +     * updates are visible to it.
>> +     */
>> +    smp_mb();
>> +
>>       sbi_remote_hfence_gvma(d->dirty_cpumask, 0, 0);
>>   }
>>   
>> @@ -1504,16 +1513,110 @@ void p2m_ctxt_switch_from(struct vcpu *p)
>>        * VMID, world-switch code should zero vsatp, then swap hgatp, then
>>        * finally write the new vsatp value what will be done in
>>        * p2m_ctxt_switch_to().
>> -     * Note, that also HGATP update could happen in p2m_handle_vmenter().
>>        */
>>       p->arch.vsatp = csr_swap(CSR_VSATP, 0);
>>   
>>       /*
>> -     * Nothing to do with HGATP as it will be update in p2m_ctxt_switch_to()
>> -     * or/and in p2m_handle_vmenter().
>> +     * Nothing to do with HGATP as it will be updated in
>> +     * p2m_ctxt_switch_to().
>>        */
>>   }
>>   
>> +/*
>> + * Domain whose p2m this hart's HGATP points at. ctxt_switch_to() bails out
>> + * early for the idle vCPU, so HGATP survives a pass through idle and keeps
>> + * pointing at the domain which ran here last. That domain, rather than the
>> + * one the scheduler switched away from, is what owns this hart's G-stage
>> + * translations. The hart also keeps its place in the owner's dirty_cpumask:
>> + * p2m_tlb_flush() goes on reaching it, and a domain which idles between two
>> + * runs on the same hart keeps its VMIDs.
>> + *
>> + * TODO: nothing resets hgatp_owner when its domain is destroyed, so a hart
>> + *       which stays idle from the domain's last run until it is freed is
>> + *       left with a dangling pointer. Once domain_relinquish_resources()
>> + *       tears down the p2m, it has to reset hgatp_owner of every hart still
>> + *       pointing at the domain (cmpxchg() against d), i.e. before the RCU
>> + *       grace period of domain_destroy() and so before the domain is freed.
>> + */
>> +static DEFINE_PER_CPU(struct domain *, hgatp_owner);
>> +
>> +/*
>> + * Update this hart's place in the dirty_cpumask of the domains involved and
>> + * claim a VMID for n. Must be called before HGATP is pointed at n's p2m, as
>> + * it is written with the VMID claimed here.
>> + */
>> +static void p2m_vmid_switch_to(struct vcpu *n)
>> +{
>> +    unsigned int cpu = smp_processor_id();
>> +    struct domain *owner = this_cpu(hgatp_owner);
>> +    bool need_flush;
>> +
>> +    ASSERT(!is_idle_vcpu(n));
>> +
>> +    if ( owner != n->domain )
>> +    {
>> +        /*
>> +         * Once this hart drops out of the owner's dirty_cpumask it stops
>> +         * being a target of p2m_tlb_flush(), while its TLB may still hold
>> +         * G-stage translations of that domain: none of the vCPUs of that
>> +         * domain which ran here has had its VMID invalidated. Move the hart
>> +         * to a new VMID generation so that none of them can be reached
>> +         * again.
>> +         *
>> +         * This has to precede the VMID claim below, so that n gets a VMID of
>> +         * the new generation.
>> +         */
>> +        if ( owner )
>> +        {
>> +            vmid_flush_hart();
>> +
>> +            cpumask_clear_cpu(cpu, owner->dirty_cpumask);
>> +        }
>> +
>> +        /*
>> +         * Mark this hart in the incoming domain's dirty_cpumask before HGATP
>> +         * is pointed at its p2m: from that write on the hart may cache the
>> +         * p2m's translations, so p2m_tlb_flush() must already reach it.
>> +         */
>> +        cpumask_set_cpu(cpu, n->domain->dirty_cpumask);
>> +
>> +        /*
>> +         * Pairs with the barrier in p2m_tlb_flush(). cpumask_set_cpu() is an
>> +         * unordered AMO on RISC-V, so without this a concurrent flusher could
>> +         * read the mask without this hart in it while this hart is already
>> +         * walking the p2m it is about to be pointed at.
>> +         */
>> +        smp_mb();
>> +
>> +        this_cpu(hgatp_owner) = n->domain;
>> +    }
>> +
>> +    /*
>> +     * A VMID is meaningful only on the hart whose pool issued it: generations
>> +     * are per-hart counters which all start at 1 and advance independently,
>> +     * so the pair a vCPU brings from another hart may match this hart's
>> +     * generation by coincidence, leaving the vCPU under a VMID which is live
>> +     * here for someone else.
>> +     */
> So if I understand correctly, we are setting generation to 0 to mark the
> vCPU that it is coming from other hart right?

Yes, at least that is the case this code deals with. Strictly speaking,
generation 0 just invalidates the vCPU's VMID, so that a new one is
claimed on the next VM entry; vmid_flush_vcpu() could be used wherever
that is needed, coming from another hart being one such case.

> Nit: If it's the case I may simplify the comment to:
>        /*
>         * VMIDs and generations are per hart, so a pair issued on another hart
>         * may match this hart's generation by coincidence. Reset the generation
>         * to 0, which no hart ever uses, so that a fresh VMID is claimed from
>         * this hart's pool.
>         */
> 

Looks good to me, I'll take it.


>> +    if ( n->arch.last_cpu != cpu )
>> +        vmid_flush_vcpu(n);
>>
> Nit: I had to read this a couple of times to get why the guest entry is too
> late. "makes HGATP live" doesn't say what happens once it is: if it's
> because of speculation filling the TLB with G-stage entries tagged with
> the VMID in HGATP, like you explained in the commit message then it may

I thought that having "HGATP live" would be clear.

> worth spell out:
> 
>        /*
>         * Claim the VMID before the caller writes HGATP rather than on guest
>         * entry: from that write on, speculation may fill the TLB with this
>         * domain's G-stage entries tagged with that VMID. A stale VMID may
>         * already have been re-issued to a vCPU of another domain, which would
>         * then hit these entries.
>         */
> 

Indeed, that's clearer. I'll take your wording.

Thanks!

~ Oleksii



  parent reply	other threads:[~2026-10-14 14:06 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 16:18 [PATCH v3 00/39] [PATCH v2 00/39] [RISC-V] virtual interrupt controller (vAPLIC/vIMSIC) support Oleksii Kurochko
2026-09-30 16:18 ` [PATCH v3 01/39] xen/riscv: drop INSN_{16,32}BIT_MASK and report unknown instruction lengths Oleksii Kurochko
2026-10-05 10:01   ` Baptiste Le Duc
2026-10-08 14:35     ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 02/39] xen/riscv: set the domain type for 64-bit kernel images Oleksii Kurochko
2026-10-05 10:01   ` Baptiste Le Duc
2026-10-08 14:36     ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 03/39] xen/riscv: introduce csr_volatile_read64() Oleksii Kurochko
2026-10-05 10:01   ` Baptiste Le Duc
2026-10-09 13:29     ` Oleksii Kurochko
2026-10-08 14:46   ` Jan Beulich
2026-10-09 14:00     ` Oleksii Kurochko
2026-10-09 14:19       ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 04/39] xen/riscv: request a G-stage flush on vmenter when VMIDs are disabled Oleksii Kurochko
2026-10-05 10:01   ` Baptiste Le Duc
2026-10-08 14:53     ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 05/39] xen/riscv: use ~0 instead of ULONG_MAX to disable the VS-timer Oleksii Kurochko
2026-10-08 14:54   ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 06/39] xen/riscv: introduce device-agnostic MMIO emulation dispatch Oleksii Kurochko
2026-10-05 10:01   ` Baptiste Le Duc
2026-10-08 14:57     ` Jan Beulich
2026-10-12 13:51       ` Oleksii Kurochko
2026-10-12 13:50     ` Oleksii Kurochko
2026-10-12 15:28   ` Jan Beulich
2026-10-14 10:51     ` Oleksii Kurochko
2026-09-30 16:18 ` [PATCH v3 07/39] xen/riscv: introduce CPU_NONE Oleksii Kurochko
2026-10-05 14:53   ` Baptiste Le Duc
2026-10-12 14:27     ` Oleksii Kurochko
2026-10-12 15:40   ` Jan Beulich
2026-10-14 11:35     ` Oleksii Kurochko
2026-09-30 16:18 ` [PATCH v3 08/39] xen/riscv: implement virtual APLIC MMIO emulation Oleksii Kurochko
2026-10-05 14:53   ` Baptiste Le Duc
2026-10-13 16:06     ` Oleksii Kurochko
2026-10-14  6:16       ` Jan Beulich
2026-10-14 11:45         ` Oleksii Kurochko
2026-10-14 13:52   ` Jan Beulich
2026-09-30 16:18 ` [PATCH v3 09/39] xen/riscv: build the target hart index via aplic_hart_index() Oleksii Kurochko
2026-10-06  9:02   ` Baptiste Le Duc
2026-10-14 13:42     ` Oleksii Kurochko
2026-10-14 14:03   ` Jan Beulich
2026-09-30 16:23 ` [PATCH v3 10/39] xen/riscv: add helper to check APLIC MSI mode Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 11/39] xen/riscv: implement vCPU context switching Oleksii Kurochko
2026-10-06 16:50   ` Baptiste Le Duc
2026-10-07  8:04     ` Jan Beulich
2026-10-07  8:27       ` Baptiste Le Duc
2026-10-14 14:05     ` Oleksii Kurochko [this message]
2026-09-30 16:23 ` [PATCH v3 12/39] xen/riscv: save and restore vsiselect on vCPU context switch Oleksii Kurochko
2026-10-07  8:53   ` Baptiste Le Duc
2026-10-14 14:53     ` Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 13/39] xen/riscv: introduce vintc_ctxt_switch_{from,to}() Oleksii Kurochko
2026-10-07  9:11   ` Baptiste Le Duc
2026-09-30 16:23 ` [PATCH v3 14/39] xen/riscv: add IMSIC vCPU context switch handlers Oleksii Kurochko
2026-10-08  9:54   ` Baptiste Le Duc
2026-10-14 15:12     ` Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 15/39] xen/riscv: extend exception tables with type and data fields Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 16/39] xen/riscv: decouple INSN_PSEUDO_VS_* from the hypervisor's XLEN Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 17/39] xen/riscv: add guest page fault handling stub Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 18/39] xen/riscv: implement trap redirection to a guest Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 19/39] xen/riscv: detect Shtvala Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 20/39] xen/riscv: resolve the faulting guest physical address Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 21/39] xen/riscv: add guest memory read helper Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 22/39] xen/riscv: look up the exception table for any trap taken in Xen context Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 23/39] xen/riscv: add helpers for decoding a trapped load or store Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 24/39] xen/riscv: add guest load emulation for trapped MMIO accesses Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 25/39] xen/riscv: add guest store " Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 26/39] xen/riscv: introduce arch_move_irqs() Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 27/39] xen/riscv: handle the case when no vCPU migration is needed Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 28/39] xen/riscv: introduce vaplic_reconfigure_target() Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 29/39] xen/riscv: prepare new IMSIC VS-file Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 30/39] xen/riscv: implement APLIC-IMSIC-hart sync barrier for vCPU migration Oleksii Kurochko
2026-10-06 14:25   ` Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 31/39] xen/riscv: remap interrupts to new IMSIC VS-file Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 32/39] xen/riscv: save and clear the old IMSIC VS-file on vCPU migration Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 33/39] xen/riscv: restore register state in the new IMSIC VS-file Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 34/39] xen/riscv: add basic VGEIN management for AIA guests Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 35/39] xen/riscv: wake up a descheduled vCPU on a guest external interrupt Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 36/39] xen/riscv: map IMSIC interrupt file for vCPUs Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 37/39] xen/riscv: implement continue_new_vcpu() Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 38/39] xen/riscv: set the guest's XLEN explicitly in hstatus.VSXL Oleksii Kurochko
2026-09-30 16:23 ` [PATCH v3 39/39] xen/riscv: introduce IMSIC h/w interrupt file attaching to vcpu Oleksii Kurochko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9ac3fdbe-9f3b-4abd-ab8d-7e252a7cf809@gmail.com \
    --to=oleksii.kurochko@gmail.com \
    --cc=Romain.Caritey@microchip.com \
    --cc=alistair.francis@wdc.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=anthony.perard@vates.tech \
    --cc=baptiste.le-duc@vates.tech \
    --cc=connojdavis@gmail.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=roger@xenproject.org \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    --cc=zhangzheng@iscas.ac.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.