-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
target/i386: introduce flags writeback mechanism
ALU instructions can write to both memory and flags. If the CC_SRC* and CC_DST locations have been written already when a memory access causes a fault, the value in CC_SRC* and CC_DST might be interpreted with the wrong CC_OP (the one that is in effect before the instruction. Besides just using the wrong result for the flags, something like subtracting -1 can have disastrous effects if the current CC_OP is CC_OP_EFLAGS: this is because QEMU does not expect bits outside the ALU flags to be set in CC_SRC, and env->eflags can end up set to all-ones. In the case of the attached testcase, this sets IOPL to 3 and would cause an assertion failure if SUB is moved to the new decoder. This mechanism is not really needed for BMI instructions, which can only write to a register, but put it to use anyway for cleanliness. In the case of BZHI, the code has to be modified slightly to ensure that decode->cc_src is written, otherwise the new assertions trigger. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
- Loading branch information
Showing
6 changed files
with
101 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#define _GNU_SOURCE | ||
#include <sys/mman.h> | ||
#include <signal.h> | ||
#include <stdio.h> | ||
#include <assert.h> | ||
|
||
volatile unsigned long flags; | ||
volatile unsigned long flags_after; | ||
int *addr; | ||
|
||
void sigsegv(int sig, siginfo_t *info, ucontext_t *uc) | ||
{ | ||
flags = uc->uc_mcontext.gregs[REG_EFL]; | ||
mprotect(addr, 4096, PROT_READ|PROT_WRITE); | ||
} | ||
|
||
int main() | ||
{ | ||
struct sigaction sa = { .sa_handler = (void *)sigsegv, .sa_flags = SA_SIGINFO }; | ||
sigaction(SIGSEGV, &sa, NULL); | ||
|
||
/* fault in the page then protect it */ | ||
addr = mmap (NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); | ||
*addr = 0x1234; | ||
mprotect(addr, 4096, PROT_READ); | ||
|
||
asm("# set flags to all ones \n" | ||
"mov $-1, %%eax \n" | ||
"movq addr, %%rdi \n" | ||
"sahf \n" | ||
"sub %%eax, (%%rdi) \n" | ||
"pushf \n" | ||
"pop flags_after(%%rip) \n" : : : "eax", "edi", "memory"); | ||
|
||
/* OF can have any value before the SUB instruction. */ | ||
assert((flags & 0xff) == 0xd7 && (flags_after & 0x8ff) == 0x17); | ||
} |