NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-xen/58561 (panic: kernel diagnostic assertion, "x86_read_psl() == 0" failed: file, "/home/netbsd/10/src/sys/arch/x86/x86/pmap.c", line 3581)
On Wed, Jan 14, 2026 at 11:00:10PM +0000, Taylor R Campbell wrote:
> > Date: Tue, 13 Jan 2026 15:50:10 +0100
> > From: Manuel Bouyer <bouyer%antioche.eu.org@localhost>
> >
> > Here's the updated patch
>
> Thanks for working on this! Some small issues:
thanks for the review,
>
> > --- amd64/amd64/cpufunc.S 6 Sep 2025 02:53:22 -0000 1.70
> > +++ amd64/amd64/cpufunc.S 13 Jan 2026 14:48:25 -0000
> > @@ -184,7 +184,7 @@ ENTRY(wbinvd)
> > END(wbinvd)
> >
> > ENTRY(setusergs)
> > - CLI(ax)
> > + CLI2(ax, rdi)
> > swapgs
> > movw %di, %gs
> > swapgs
>
> I think this can't be right. %rdi is obviously not a free scratch
> register: it's the first argument register. But also, this code isn't
> even used in Xen builds, is it? Xen has its own setusergs in
> xenfunc.c, doesn't it?
Right, I changed it to use %rsi. Also as you noted this is not used for
Xen at this time (which is why I didn't notice I guess), but I think it's
better to be correct and use the appropriate macro here (even if it always
end up being a single cli instruction at this time)
>
> https://nxr.netbsd.org/xref/src/sys/arch/xen/x86/xenfunc.c?r=1.29#270
>
> > --- amd64/amd64/spl.S 1 Mar 2023 08:38:50 -0000 1.49
> > +++ amd64/amd64/spl.S 13 Jan 2026 14:48:25 -0000
> > ...
> > @@ -355,7 +356,7 @@ IDTVEC(doreti)
> > 1:
> > movl %ebx,%eax
> > movq CPUVAR(IUNMASK)(,%rax,8),%rax
> > - CLI(si)
> > + CLI2(si, r14)
> > andq CPUVAR(IPENDING),%rax
> > jz 2f
> > bsrq %rax,%rax /* slow, but not worth optimizing */
> > @@ -378,7 +379,7 @@ IDTVEC(doreti)
> > movq %rsp,%rdi
> > KMSAN_INIT_ARG(8)
> > call _C_LABEL(trap)
> > - CLI(si)
> > + CLI2(si, rdi)
> > jmp .Ldoreti_checkast
> > 3:
> > CHECK_DEFERRED_SWITCH
> > @@ -389,6 +390,6 @@ IDTVEC(doreti)
> > 9:
> > STI(si)
> > call _C_LABEL(do_pmap_load)
> > - CLI(si)
> > + CLI2(si, rdi)
> > jmp .Ldoreti_checkast /* recheck ASTs */
> > IDTVEC_END(doreti)
>
> Not immediately clear these registers are free here, can we
> double-check and document in a comment exactly what registers are
> involved on entry and exit to doreti?
I added "rsi, rdi and r14 - free for local use". rsi was already used here,
r14 is also used by CHECK_ASTPENDING()/CLEAR_ASTPENDING() and rdi for the
call to trap().
>
> > --- amd64/include/frameasm.h 30 Jul 2022 14:11:00 -0000 1.55
> > +++ amd64/include/frameasm.h 13 Jan 2026 14:48:25 -0000
> > ...
> > + * ci_ilevel is nit 0, or
>
> Nit: not `nit', `not'!
>
> > + cmpl $0, L_NOPREEMPT(%r ## temp_reg); \
> > + jne 199f; \
> > ...
> > +199: movq CPUVAR(VCPU),%r ## temp_reg ; \
> > movb $1,EVTCHN_UPCALL_MASK(%r ## temp_reg);
>
> Would be nice if we could make this work so the static branch
> prediction (forward jump not taken) takes the right path here, but I
> guess it's a pain because this is really doing
>
> KASSERT(l->l_nopreempt != 0 || curcpu()->ci_ilevel != 0 || ...)
yes, that's the problem. Also it's DIAGNOSTIC code so I prefer to
keep it easy to read.
>
> > + movq $panicstr,%r ## temp_reg ; \
>
> Should this use _C_LABEL for consistency?
Fixed
>
> > + cmpq $0, 0(%r ## temp_reg); \
>
> I always get confused about C symbols in MOV assembly directives.
> Does temp_reg at this point hold a (possibly null) pointer to the
> first character of the panic string, or a (possibly null) pointer to
> the _pointer to_ first character of the panic string?
temp_reg holds the address of the pointer (that is, &panicstr), and this
cannot be NULL. So the cmpq checks the pointer itself.
I know this code works because I went there multiple times while debugging :)
>
> Shouldn't this be one of the two options?
>
> leaq $panicstr,%rtmp
> cmpq $0, 0(%rtmp)
I guess this would check *panicstr, that is, the 8 first character of the
panicstr string
>
> or
>
> movq $panicstr,%rtmp
> cmpq $0,%rtmp
that would check &panicstr, which cannot be NULL
>
> > + movq _C_LABEL(cli_panic), %rdi; \
> > + call _C_LABEL(panic); \
>
> Have you tested provoking this path to make sure it leads to a
> sensible-looking panic?
Ho yes, multiple times :)
>
> > +/* CLI() with preemtion disabled */
> > +#define CLI2(temp_reg, temp_reg2) \
> > + movq CPUVAR(CURLWP),% ## temp_reg2 ; \
> > + incl L_NOPREEMPT(% ## temp_reg2); \
> > + movq CPUVAR(VCPU),%r ## temp_reg ; \
> > + movb $1,EVTCHN_UPCALL_MASK(%r ## temp_reg); \
> > + decl L_NOPREEMPT(% ## temp_reg2);
>
> Or, as an alternative to all the above issues... What if we just make
> CLI work using a single temporary register? Requires one extra load
> to reuse the register but I bet modern x86 CPUs will do enough fancy
> register renaming and caching internally that it makes essentially no
> difference except perhaps for a few bytes of code size:
Yes, you're probably right it wouldn't make much difference.
But we always have an extra free register, except in syscall entries.
I choose to save an instruction most of the time.
>
> movq CPUVAR(curlwp),%r ## temp_reg;
> incl L_NOPREEMPT(%r ## temp_reg);
> movq CPUVAR(VCPU),%r ## temp_reg2;
> movb $1,EVTCHN_UPCALL_MASK(%r ## temp_reg);
> movq CPUVAR(curlwp),%r ## temp_reg;
> decl L_NOPREEMPT(%r ## temp_reg);
>
> > --- xen/x86/xen_intr.c 25 Feb 2023 00:32:13 -0000 1.31
> > +++ xen/x86/xen_intr.c 13 Jan 2026 14:48:26 -0000
> > @@ -540,3 +547,9 @@ __strong_alias(cpu_intr_init, xen_cpu_in
> > __strong_alias(intr_allocate_io_intrsource, xen_intr_allocate_io_intrsource);
> > __strong_alias(intr_free_io_intrsource, xen_intr_free_io_intrsource);
> > #endif /* XENPV */
> > +
> > +
> > +#if defined(DIAGNOSTIC) && defined(XENPV)
> > +const char *cli_panic = "cli with preemtion";
> > +const char *sti_panic = "sti with interrupts enabled";
> > +#endif
>
> const char cli_panic[] = "cli with preemtion";
> const char sti_panic[] = "sti with interrupts enabled";
>
> Don't need a mutable pointer to the immutable string in memory -- just
> a symbol for the string is enough.
Yes, but how do we do this in C ?
--
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
NetBSD: 26 ans d'experience feront toujours la difference
--
Home |
Main Index |
Thread Index |
Old Index