Re: SIGSEGV in LuaJIT 2.1 VM

  • From: Peter Cawley <corsix@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Wed, 23 Nov 2016 22:48:01 +0000

On Wed, Nov 23, 2016 at 4:22 PM, Demi Obenour <demiobenour@xxxxxxxxx> wrote:

I just had a theory for what the problem could be: the memory protection
change happens just around the kernel moving the process from one CPU core
to another.  So the data is in the cache of one core, but hasn't been
flushed from the I-cache of the migrated-to core.

I mean, sure, a memory protection change has to happen, and a thread
CPU core migration has to happen, and various things have to be or not
be in various caches.

Given Tomas' remarks on lvmst being "wrong", I posit that the following happens:

1. a trace exit becomes hot enough to trigger creation of a new side trace
2. change protection of new side trace mcode area to RW
3. write new side trace machine code
4. cpuid instruction (with my patch)
5. change protection of parent trace mcode area to RW (unless same
mcode area as new side trace)
6. change jump-to-exit-stub in parent trace to jump-to-side-trace
7. cpuid instruction (with my patch)
8. change protection of parent trace mcode area to RX (unless same
mcode area as new side trace)
9. change protection of new side trace mcode area to RX
10. resume interpreter
11. execute in the interpreter for a while
12. enter parent trace
13. execute some of parent trace
14. jump to side trace
15. segfault (maybe not with my patch)

At least one CPU core migration needs to happen somewhere in there
too. Presumably, at the time of the segfault, the migrated-to core
has:

a. A cached TLB entry for the parent trace's mcode, which is correct [1].
b. The head of the parent trace's mcode in its I-cache, which is correct [1].
c. A cached TLB entry for the side trace's mcode, which is somehow
incorrect (i.e. still specifying RW rather than RX).

Perhaps the migrated-to core has the side trace's mcode in its I-cache
at step 14; perhaps instead the core has to suffer a page fault
between steps 14 and 15. Inspection of core dumps should determine
whether steps 5 and 8 happen. If we were observing this on Broadwell
chips, then Intel PT might be useful for shedding more light on what
happens when.

[1] Though perhaps if an interrupt (like a page fault) happens between
steps 14 and 15, then the migration might happen between steps 14 and
15, and the migrated-to core might not have anything related to the
parent trace in its caches.

Other related posts: