From: Oleksii Kurochko <oleksii.kurochko@gmail.com>
To: Jan Beulich <jbeulich@suse.com>
Cc: Romain Caritey <Romain.Caritey@microchip.com>,
Doug Goldstein <cardoe@cardoe.com>,
Stefano Stabellini <sstabellini@kernel.org>,
Alistair Francis <alistair.francis@wdc.com>,
Connor Davis <connojdavis@gmail.com>,
xen-devel@lists.xenproject.org
Subject: Re: [PATCH v7 14/14] xen/riscv: Disable SSTC extension and add trap-based CSR probing
Date: Wed, 11 Mar 2026 12:38:34 +0100 [thread overview]
Message-ID: <87eb8fb1-aa50-436c-8e2e-050981af4d1b@gmail.com> (raw)
In-Reply-To: <2e471f54-1885-4615-8a23-c33ce683158f@suse.com>
On 3/11/26 11:58 AM, Jan Beulich wrote:
> On 11.03.2026 10:54, Oleksii Kurochko wrote:
>> On 3/10/26 10:15 AM, Jan Beulich wrote:
>>> On 06.03.2026 17:33, Oleksii Kurochko wrote:
>>>> --- a/automation/scripts/qemu-smoke-riscv64.sh
>>>> +++ b/automation/scripts/qemu-smoke-riscv64.sh
>>>> @@ -7,7 +7,7 @@ rm -f smoke.serial
>>>>
>>>> export TEST_CMD="qemu-system-riscv64 \
>>>> -M virt,aia=aplic-imsic \
>>>> - -cpu rv64,svpbmt=on \
>>>> + -cpu rv64,svpbmt=on,sstc=off \
>>>> -smp 1 \
>>>> -nographic \
>>>> -m 2g \
>>> How does this fit with you panic()ing when SSTC isn't available (i.e. the
>>> register cannot be read)? I must be missing something, likely a result of
>>> me not being able to really understand the description.
>> When SSTC isn't available my panic() won't occur and then will continue to
>> be executed. Otherwise, when SSTC is enabled (it is enabled by QEMU by default)
>> my panic will occur.
> Oh, I notice I misread the condition around the panic(), mainly because of
> the misleading / ambiguous message passed to it: "SSTC isn't supported\n"
> can mean unsupported by Xen or unsupported by the platform.
>
> Anyway, to me this is entirely bogus: Why would we panic() because there is
> a certain extension available?
It is bogus because then we need also add support of SSTC for a guest what isn't
done now thereby if it is detected that SSTC is available that it is dangerous
to continue about full support (guest part) of it.
I thought about the case to let Xen use SSTC and just don't tell Linux that SSTC
is available by dropping from riscv,isa property the mentioning of SSTC, so then
Linux will still continue to use SBI set timer call to Xen and the will just
safely reprogram (if it is needed) a timer using SSTC instructions. But if to do
in this way still nothing will prevent a guest to test if SSTC is available by
reading CSR_STIMECMP and nothing will prevent to access CSR_VSTIMECMP by guest
what could also lead to some misleading behavior.
Likely we could set henvcfg.STCE to zero and it will forbid guest to access SSTC
registers but I am not sure that we really want such behavior when Xen is using
SSTC to setup a timer, but guest isn't allowed. It seems it will be better just
support SSTC extension fully and not to support it only for now.
>
>>>> --- a/xen/arch/riscv/include/asm/csr.h
>>>> +++ b/xen/arch/riscv/include/asm/csr.h
>>>> @@ -9,6 +9,7 @@
>>>> #include <asm/asm.h>
>>>> #include <xen/const.h>
>>>> #include <asm/riscv_encoding.h>
>>>> +#include <asm/traps.h>
>>>>
>>>> #ifndef __ASSEMBLER__
>>>>
>>>> @@ -78,6 +79,37 @@
>>>> : "memory" ); \
>>>> })
>>>>
>>>> +/*
>>>> + * Some functions inside asm/system.h requires some of the macros above,
>>>> + * so this header should be included after the macros above are introduced.
>>>> + */
>>>> +#include <asm/system.h>
>>>> +
>>>> +#define csr_read_allowed(csr_num, trap) \
>>>> +({ \
>>>> + register unsigned long tinfo asm("a3") = (unsigned long)trap; \
>>> Why can't this variable be of the correct (pointer) type? This would then
>>> at the same time serve as a compile-time check for the caller to have
>>> passed an argument of the correct type.
>> Good point it could be an option.
>>
>>>> + register unsigned long ttmp asm("a4"); \
>>>> + register unsigned long stvec = (unsigned long)&do_expected_trap; \
>>> Fiddling with stvec may be okay-ish very early during boot. NMIs, for
>>> example, do exist in principle on RISC-V, aiui. There must be a way for them
>>> to be dealt with by other than just M-mode.
>> Do I understand correct that your concern is about that if NMIs will be handled
>> in HS-mode that switching stvec in this way could be dangerous as do_expected_trap()
>> doesn't know how to handle NMIs?
> Yes.
>
>> If yes, then NMIs should be handled by M-mode as:
>> Non-maskable interrupts (NMIs) are only used for hardware error conditions, and
>> cause an immediate jump to an implementation-defined NMI vector running in M-mode
>> regardless of the state of a hart’s interrupt enable bits
>> and:
>> The non-maskable interrupt is not made visible via the mip register as its
>> presence is implicitly known when executing the NMI trap handler.
>>
>> So standard delegation registers like mideleg do not apply to NMIs because NMIs
>> are not visible in the mip register.
>>
>> I haven't found in OpenSBI how they are explicitly handling NMIs, but it looks
>> like if they happen in (H)S-mode or (V)U-mode then they will be just redirected
>> to (H)S-mode or V(U)-mode:
>> https://github.com/riscv-software-src/opensbi/blob/master/lib/sbi/sbi_trap.c#L361
>> And then do_expected_trap() will fail to handle them...
>>
>> Interesting that other hypervisors are using the similar approarch (with temporary
>> updating of stvec) and they haven't faced such issue with NMIs yet...
> Well, NMIs may be rare to occur? And hence very unlikely to occur in this small
> a window?
It is still sound risky and ASM_EXTABLE approach sounds more safe particular in this
case.
>
>>>> + register unsigned long ret = 0; \
>>>> + unsigned long flags; \
>>>> + ((struct trap_info *)(trap))->scause = 0; \
>>> "trap" would better be of the correct type. Don't use casts like this, please.
>>>
>>> Further, wouldn't you better set the field to a guaranteed invalid value? 0 is
>>> CAUSE_MISALIGNED_FETCH, after all.
>> I don't see that such an invalid value exist for scause. I think we have to reserved
>> a value from region 24-31 or 48-63 as they are designated for custom use.
> Not sure that's possible. "Custom use" may mean "custom" from hw perspective.
> I was rather thinking of picking something pretty high in the reserved range,
> like (1 << (MXLEN-1)) - 1 or 1 << (MXLEN-2).
Agree, it could be an option.
>
>>>> + local_irq_save(flags); \
>>>> + asm volatile ( \
>>>> + ".option push\n" \
>>>> + ".option norvc\n" \
>>> Shouldn't this come later?
>> Do you mean before where SSTC csr is really tried to be read ("csrr %[ret], %[csr]\n")?
> Yes.
>
>> Does it really matter in such small inline assembler?
> Yes, if nothing else then to not raise questions. Plus (depending on the
> specific operands used), the ADD (MV) could e.g. be representable by a C insn.
>
>>> And why set ttmp in the first place, when
>>> that's what do_expected_trap() writes to?
>> To force the compiler to materialize tinfo in register a4 (ttmp) before the
>> trap handler runs as handler will use a4 as temporary register.
> ??? I don't understand what you mean with "materialize".
Mean forcing the compiler to load the variable into the specific hardware
register (a4) before the potentially trapping instruction executes, so the
trap handler can safely use that register.
>
>>>> + "csrr %[ret], %[csr]\n" \
>>>> + "csrw " STR(CSR_STVEC) ", %[stvec]\n" \
>>>> + ".option pop" \
>>>> + : [stvec] "+&r" (stvec), [tinfo] "+&r" (tinfo), \
>>> tinfo isn't modified, is it?
>> It is modified by handler.
> Where? It's only used as the address of the two stores.
There are to updates of tinfo in the do_expected_trap():
FUNC(do_expected_trap)
...
REG_S a4, RISCV_TRAP_SEPC(a3)
...
REG_S a4, RISCV_TRAP_SCAUSE(a3)
...
END(do_expected_trap)
>
>>>> + [ttmp] "+&r" (ttmp), [ret] "=&r" (ret) \
>>> ttmp isn't initialized (in C), so the compiler could legitimately complain
>>> about the use of an uninitialized variable here (due to the use of + where
>>> = is meant).
>> ttmp is modified by handler too.
> Of course, but just to repeat - you mean "=&r" there.
>
>>> Whereas for ret the situation is the other way around - you initialize the
>>> variable, just to then tell the compiler that it can drop this
>>> initialization, as - supposedly - the asm() always sets it (which it doesn't
>>> when the csrr faults).
>> It was done in that way as when csrr will lead to a fault, handler will jump
>> over the csrr instruction and so ret won't be set at all. For that case it was
>> set to 0.
> And again - this is meaningless if the constraint is "=&r".
Make sense...
>
>>>> + : [csr] "i" (csr_num) \
>>>> + : "memory" ); \
>>>> + local_irq_restore(flags); \
>>>> + ret; \
>>>> +})
>>> A macro of this name would better return an indicator of what it is checking,
>>> rather than the CSR value (which the sole user of this macro doesn't even
>>> care about).
>> With the current one use case it doesn't care but generally I think that someone
>> will want to use this macro just to get CSR value. I don't have a speicifc example
>> but still it could be used in this way.
> Well, if you want to keep it doing so, make the name match what it does (and
> in particular what it returns).
>
>>> Ideally such would also be an inline function.
>> I thought about that but I had difficulties with csr* instruction and their second
>> operand which expects to have immediate. But if I will have inline function that
>> csr_num will be in register.
> Only if the function wouldn't be inlined, I expect? Which hence you may need
> to force, by using always_inline.
It could work.
Thanks.
~ Oleksii
next prev parent reply other threads:[~2026-03-11 11:39 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-06 16:33 [PATCH v7 00/14] xen/riscv: introduce vtimer related things Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 01/14] xen/riscv: detect and store supported hypervisor CSR bits at boot Oleksii Kurochko
2026-03-10 8:11 ` Jan Beulich
2026-03-10 8:17 ` Jan Beulich
2026-03-10 16:00 ` Oleksii Kurochko
2026-03-10 16:14 ` Jan Beulich
2026-03-06 16:33 ` [PATCH v7 02/14] xen/riscv: implement vcpu_csr_init() Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 03/14] xen/riscv: introduce tracking of pending vCPU interrupts, part 1 Oleksii Kurochko
2026-03-10 8:13 ` Jan Beulich
2026-03-06 16:33 ` [PATCH v7 04/14] xen/riscv: introduce tracking of pending vCPU interrupts, part 2 Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 05/14] xen/riscv: introduce basic vtimer infrastructure for guests Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 06/14] xen/riscv: introduce vcpu_kick() implementation Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 07/14] xen/riscv: add vtimer context switch helpers Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 08/14] xen/riscv: implement SBI legacy SET_TIMER support for guests Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 09/14] xen/riscv: introduce sbi_set_timer() Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 10/14] xen/riscv: implement reprogram_timer() via SBI Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 11/14] xen/riscv: handle hypervisor timer interrupts Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 12/14] xen/riscv: init tasklet subsystem Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 13/14] xen/riscv: implement sync_vcpu_execstate() Oleksii Kurochko
2026-03-06 16:33 ` [PATCH v7 14/14] xen/riscv: Disable SSTC extension and add trap-based CSR probing Oleksii Kurochko
2026-03-10 9:15 ` Jan Beulich
2026-03-11 9:54 ` Oleksii Kurochko
2026-03-11 10:54 ` Oleksii Kurochko
2026-03-11 10:58 ` Jan Beulich
2026-03-11 11:38 ` Oleksii Kurochko [this message]
2026-03-11 12:54 ` Jan Beulich
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=87eb8fb1-aa50-436c-8e2e-050981af4d1b@gmail.com \
--to=oleksii.kurochko@gmail.com \
--cc=Romain.Caritey@microchip.com \
--cc=alistair.francis@wdc.com \
--cc=cardoe@cardoe.com \
--cc=connojdavis@gmail.com \
--cc=jbeulich@suse.com \
--cc=sstabellini@kernel.org \
--cc=xen-devel@lists.xenproject.org \
/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.