Why it is not preempt-unsafe, I beleive, is because1. I am not allocating the ring1 stack separately,I think that it is problem. And do not forget that NMI can occur at any
I am allocating it on a ring0 stack. Much simpler
code, although non-reentrant/preempt-unsafe.
place, so I'm not quite sure how your code works.
What if exception occurs in CPL1 code? Processor reloads SS/ESP fromBut for that I reserve the room on stack, so that
TSS, pointing at top of CPL0 stack - where it overwrites CPL1 stack -
- and it pushes on top of CPL0 stack address of CPL1 - and real return
address for CPL3 was lost :-( Boom.
You change base address for SS segment - in that case you need per-CPUBut I beleive it *is* per-CPU, no? I am taking the
SS segment, it wont' work with global SS segment.
Did you tried setting SS/ESP on stack to invalid values, so IRET on CPL1Yes, I did that - that seem to work (i.e. no Oops
triggers fault? You should be able to do that by modifying SS/ESP from
signal handler.
Adjusting NMI_STACK_RESERVE? I need only a few+#define NMI_STACK_RESERVE 0x400This is ugly. What if NMI handler uses more than 1KB?
+#define MAKE_ESPFIX \
+ cli; \
+ subl $NMI_STACK_RESERVE, %esp; \
What about referencing 14+NMI_STACK_RESERVE() ?Will work either, but for what? Just looks a bit
And ESP is notBut I have to store the value of ((ESP & 0xffff) | 4) on
multiple of 4 here - it may slow down processor a bit.
I think that you should prepare stack by using moves toI can do that of course, do you think it is faster?
-NMI_STACK_RESERVE-xx(%esp) instead of adjusting stack and using pushes.
Or you can (if you want per-thread and not per-CPU stack) prepare CPL1Ughh, I really need the motivation to fiddle with
stack above CPL0 stack - this way you steal 24 bytes from CPL0 stack,
but CPL0 can use full 4KB (8KB), without NMI being limited by 1KB.
Yes, that should work I think.+ pushl 20(%esp); \Does this work if userspace runs with iopl 3,2 or 1? Does iret on CPL1
+ andl $~(IF_MASK | TF_MASK | RF_MASK | NT_MASK | AC_MASK), (%esp); \
+ orl $IOPL1_MASK, (%esp); \
set iopl level properly (i.e. is iopl set if IOPL <= CPL, or only if CPL=0?).Ring-1 code can't alter the IOPL, but then I set
I'm not sure about lea speed. And fast path should NOT jump,No problems.
forward jumps are initialy predicted as not taken... Maybe:
And then you can move MAKE_ESPFIX out of macro.Good idea! :)
And it seems to me that it adds too many operations to fast path.Ughh, 8 insns only! Is this really too much? :(
Maybe you want to introduce some per-thread flag,I don't know. Probably not. I'll think about that.
or leave syscall pathYes. I'll see how that can be done.
to corrupt ESP (dosemu apps should not call Linux INT syscall, yes?).
Very probably, I was not sure about all that- if (regs->xcs & 3)I think you should leave this as is, regs->xss/regs->esp should be valid
+ if (regs->xcs & 2)
printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
for CPL1 exceptions.