[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Incorrect x86[_64] RMW emulation
From: |
malc |
Subject: |
[Qemu-devel] Incorrect x86[_64] RMW emulation |
Date: |
Thu, 19 Aug 2010 08:20:51 +0400 (MSD) |
User-agent: |
Alpine 2.00 (LNX 1167 2008-08-23) |
Alexander Graf kindly shared with the wolrd the link[1] to an
informative article which among other things the article highlights
the fact that QEMU's emulation of exception handling on x86[_64] is
incorrect when the faulting instruction is RMW.
Here's small test case (__i386__ case is untested):
#define _GNU_SOURCE
#include <err.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ucontext.h>
#include <unistd.h>
#define UNUSED __attribute ((unused))
/* http://fixunix.com/linux/7635-sigsegv-signal-handler.html */
static void handler (int signo, siginfo_t *info, void *context)
{
int iswrite;
#ifdef __i386__
(void) context;
iswrite = info.err & 2;
#elif __x86_64__
struct ucontext *uc = context;
(void) info;
mcontext_t *mc = &uc->uc_mcontext;
iswrite = mc->gregs[REG_ERR] & 2;
#else
#error shrug
#endif
if (iswrite) write (2, "write\n", 6);
else write (2, "read\n", 5);
_Exit (EXIT_FAILURE);
}
int main (int argc, char **argv)
{
int ret;
enum {R,W,RMW} n = R;
struct sigaction act;
if (argc == 2) {
if (!strcmp (argv[1], "read")) n = R;
else if (!strcmp (argv[1], "write")) n = W;
else if (!strcmp (argv[1], "rmw")) n = RMW;
else errx (EXIT_FAILURE, "argument should be one of [read|write|rmw]");
}
else {
if (argc > 2) errx (EXIT_FAILURE, "need only one argument");
}
act.sa_sigaction = handler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_SIGINFO;
ret = sigaction (SIGSEGV, &act, NULL);
if (ret) err (EXIT_FAILURE, "sigaction");
switch (n) {
case W: asm ("mov %eax, 0"); break;
case R: asm ("mov 0, %eax"); break;
case RMW: asm ("incl 0"); break;
}
abort ();
}
Here's the output obtained on an x86_64 machine:
rmw$ gcc rmw.c
rmw$ ./a.out read
read
rmw$ ./a.out write
write
rmw$ ./a.out rmw
write
Since the last one is translated to more or less following TCG:
movi rN, $0
ld32 rM, rN
movi rL, $1
add rO, rM, rL
st32 rO, rN
and will incorrectly produce a read trap for both user and softmmu.
[1] http://emulators.com/docs/nx33_qemu_0125.htm
--
mailto:address@hidden
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] Incorrect x86[_64] RMW emulation,
malc <=