bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Ivan Zakharyaschev <imz@altlinux.org>
To: Bruno Haible <bruno@clisp.org>
Cc: bircoph@altlinux.org, bug-gnulib@gnu.org
Subject: Re: [RFC PATCH] test-c-stack2.sh: skip if the platform sent SIGILL on an invalid address.
Date: Sat, 29 Dec 2018 23:13:00 +0300 (MSK)	[thread overview]
Message-ID: <alpine.LFD.2.20.1812292301020.6081@imap.altlinux.org> (raw)
In-Reply-To: <alpine.LFD.2.20.1812291505000.6081@imap.altlinux.org>

Here is a follow-up to the story, for those curious what happens in a 
similar IA64 architecture. And this should be it.

As for the problem on E2K itself, we should discuss it with MCST and/or 
investigate whether the missing information about the faults can be 
recovered to better satisfy POSIX.

On Sat, 29 Dec 2018, Ivan Zakharyaschev wrote:

> > > As for the SIGILL peculiarity, it has a reason in the Elbrus architecture. 

> I've studied the assembler code and found the other true 
> reason in this specific case: these are faults "hidden" in an explicitly 
> "speculative" computation which utltimately result in SIGILL. (The E2K ISA 
> is reminiscent of IA64; this can help get the idea.) The specific kind of 
> the fault is "forgotten", unfortunately.

> Besides, in many aspects including the newly mentioned by me explicitly 
> speculative instructions, E2K reminds IA64.
> 
> And it'd be interesting to have a look how they treat faults coming from 
> speculative computations in Linux/ia64 to get an idea whether it can be 
> done in a manner with better conformance to POSIX.

> * * *
> 
> BTW, saving and forgetting the type of the original fault doesn't seem

I meant "not forgetting".

> to be something expensive to implement (after some thought): when a
> register is marked as invalid, it shouldn't matter anymore what value
> it holds. So, the same register can be used to save the information
> about the type of the fault.

As Dmitry Levin pointed out, probably not, because there can be too much 
information (the fault, and the associated addres) for a single register.

> * * *
> 
> I wanted to see how Linux/ia64 handles these complications arising
> from speculative computations possibly causing a fault; and powered on
> such a machine, and had a look at the above examples with SIGILL on
> E2K: the third one, and the fifth one (speculative division by zero).
> 
> The third example from above:
> 
> imz@rx2620:~/test-speculative-SIGSEGV$ cc -Wall -O3 -xc - -S -o c.s && cat c.s
> int main(int argc, char ** argv) {
>   if (0 < argc)
>     ++*(char*)0xbad;
>   return 0xbeef;
> }
> 	.file	""
> 	.pred.safe_across_calls p1-p5,p16-p63
> 	.section	.text.startup,"ax",@progbits
> 	.align 16
> 	.align 64
> 	.global main#
> 	.type	main#, @function
> 	.proc main#
> main:
> 	.prologue
> 	.body
> 	.mmi
> 	cmp4.ge p6, p7 = 0, r32
> 	addl r14 = 2989, r0
> 	addl r8 = 48879, r0
> 	;;
> 	.mmi
> 	(p7) ld1 r15 = [r14]
> 	;;
> 	(p7) adds r15 = 1, r15
> 	nop 0
> 	;;
> 	.mib
> 	(p7) st1 [r14] = r15
> 	nop 0
> 	br.ret.sptk.many b0
> 	.endp main#
> 	.ident	"GCC: (Debian 4.6.3-14) 4.6.3"
> 	.section	.note.GNU-stack,"",@progbits
> imz@rx2620:~/test-speculative-SIGSEGV$ cc -Wall -O3 c.s && ./a.out; echo $?
> Segmentation fault
> 139

> Notes on the assembler: the possible groupings into VLIWs are
> separated by double semicolons (";;"). Predicative execution of
> instructions is marked by a prefix with the corresponding predicate
> register in parentheses, like "(p7)" in the code above:
> 
> 	.mmi
> 	(p7) ld1 r15 = [r14]
> 	;;
> 	(p7) adds r15 = 1, r15
> 	nop 0
> 	;;
> 	.mib
> 	(p7) st1 [r14] = r15
> 
> These are the "load", "add", and "store" instructions corresponding to: ++*(char*)0xbad
> 
> All this shows that gcc-4.6 on IA-64 doesn't generate speculative
> computations for the same examples that had speculative computations
> on E2K. Unfortunately, this means that we couldn't compare the
> interesting bits of the behavior between Linux/e2k and Linux/ia64
> quickly. Perhaps, editing the IA64 assembler code can give a desired
> example.

Cool! Linux/ia64 also produces SIGILL in the same situation; it seems
to have no magic. (But there is a second part of the story!)

imz@rx2620:~/test-speculative-SIGSEGV$ diff c.s c_s.s
18c18
< 	(p7) ld1 r15 = [r14]
---
> 	(p7) ld1.s r15 = [r14]
imz@rx2620:~/test-speculative-SIGSEGV$ cc c_s.s && ./a.out; echo $?
Illegal instruction
132

"ld1.s" is the "load 1 byte" instruction with the "speculative" flag.

If we do not use the "invalid" register in a "store" instruction, then
there is no fault:

imz@rx2620:~/test-speculative-SIGSEGV$ diff c_s.s c_nost.s
24,25d23
< 	(p7) st1 [r14] = r15
< 	nop 0
imz@rx2620:~/test-speculative-SIGSEGV$ cc c_nost.s && ./a.out; echo $?
239


And the second part:

The problem has a solution on IA64. The compiler would know how to
replay the faulty speculative computation, so it would be able
generate code to do this non-speculatively and trigger the real fault.
And there is an instruction that checks whether a register is
"valid"[1] and helps to jump to the recovery code[2]: "chk.s".

I've implemented this approach manually in c_chk.s like this (but I
have not seen what a compiler would do actually; IA64 has other
flavors of speculative instructions, like "ld.a" etc., so there are
rich possiblities):

	.file	""
	.pred.safe_across_calls p1-p5,p16-p63
	.section	.text.startup,"ax",@progbits
	.align 16
	.align 64
	.global main#
	.type	main#, @function
	.proc main#
main:
	.prologue
	.body
	.mmi
	addl r14 = 2989, r0
	addl r8 = 48879, r0
	;;
	.mmi
	ld1.s r15 = [r14]
	;;
	.mmi
	cmp4.ge p6, p7 = 0, r32
	;;
	(p7) adds r15 = 1, r15
	nop 0
	;;
	(p7) chk.s r15, .recovery
	;;
.back:
	.mib
	(p7) st1 [r14] = r15
	nop 0
	br.ret.sptk.many b0
.recovery:
	ld1 r15 = [r14]
	//adds r15 = 1, r15
        br.cond.sptk .back
	.endp main#
	.ident	"GCC: (Debian 4.6.3-14) 4.6.3"
	.section	.note.GNU-stack,"",@progbits

imz@rx2620:~/test-speculative-SIGSEGV$ cc c_chk.s && ./a.out; echo $?
Segmentation fault
139

It produced a normal behavior, better satisfying POSIX.

[1]: https://blogs.msdn.microsoft.com/oldnewthing/20040119-00/?p=41003
[2]: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ia64/strchr.S;h=3a29e80b52c350a76e880cbb8daa66c91fa98964;hb=HEAD#l87

[1] seems to be outdated because it shows a wrong variant of "chk.s",
but has a story about the registers being 65-bit having an additional
bit for their "validity".

[2] is a manually written example of this approach which I googled up
quickly searching for "chk.s" "ia64".

-- 
Best regards,
Ivan



  parent reply	other threads:[~2018-12-29 20:31 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-15 12:50 [RFC PATCH] test-c-stack2.sh: skip if the platform sent SIGILL on an invalid address Ivan Zakharyaschev
2018-12-20  2:24 ` Bruno Haible
2018-12-28 14:23   ` Ivan Zakharyaschev
2018-12-29 11:17     ` Bruno Haible
2018-12-29 11:31       ` Andrey Savchenko
2018-12-29 14:03         ` Bruno Haible
2018-12-29 14:31         ` Dmitry V. Levin
2018-12-29 14:54       ` Bruno Haible
2018-12-29 15:03       ` Ivan Zakharyaschev
2018-12-29 16:30         ` Dmitry V. Levin
2018-12-29 20:13         ` Ivan Zakharyaschev [this message]
2018-12-30  4:49           ` Bruno Haible
2018-12-29 13:54     ` Dmitry V. Levin
2018-12-29 15:15       ` Ivan Zakharyaschev

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

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

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

  git send-email \
    --in-reply-to=alpine.LFD.2.20.1812292301020.6081@imap.altlinux.org \
    --to=imz@altlinux.org \
    --cc=bircoph@altlinux.org \
    --cc=bruno@clisp.org \
    --cc=bug-gnulib@gnu.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).