git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@417 c046a42c-6fe2-441c-8c8c-71466251a162
master
bellard 2003-10-27 23:58:04 +00:00
parent baf8ebf01a
commit 285dc330bd
9 changed files with 47 additions and 320 deletions

View File

@ -1,4 +1,4 @@
version 0.4.4: version 0.5.0:
- full hardware level VGA emulation - full hardware level VGA emulation
- graphical display with SDL - graphical display with SDL
@ -16,8 +16,9 @@ version 0.4.4:
- preliminary SPARC target support (Thomas M. Ogrisegg) - preliminary SPARC target support (Thomas M. Ogrisegg)
- tun-fd option (Rusty Russell) - tun-fd option (Rusty Russell)
- automatic IDE geometry detection - automatic IDE geometry detection
- renamed 'vl' to qemu and user qemu to qemu-{cpu}. - renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}.
- added man page - added man page
- added full soft mmy mode to launch unpatched OSes.
version 0.4.3: version 0.4.3:

26
README
View File

@ -6,35 +6,17 @@ INSTALLATION
Type Type
./configure --interp-prefix=/usr/local/qemu-i386 ./configure
make make
to build qemu and libqemu.a. to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
supported target CPUs).
Type Type
make install make install
to install QEMU in /usr/local/bin to install QEMU in /usr/local
* On x86 you should be able to launch any program by using the
libraries installed on your PC. For example:
./qemu -L / /bin/ls
* On non x86 CPUs, you need first to download at least an x86 glibc
(qemu-XXX-i386-glibc21.tar.gz on the qemu web page). Ensure that
LD_LIBRARY_PATH is not set:
unset LD_LIBRARY_PATH
Then you can launch the precompiled 'ls' x86 executable:
./qemu /usr/local/qemu-i386/bin/ls-i386
You can look at /usr/local/qemu-i386/bin/qemu-conf.sh so that QEMU is
automatically launched by the Linux kernel when you try to launch x86
executables.
Tested tool versions Tested tool versions
-------------------- --------------------

View File

@ -6,11 +6,11 @@ x86 binary distribution:
* wine-20020411 tarball * wine-20020411 tarball
./configure --prefix=/usr/local/qemu-i386/wine ./configure --prefix=/usr/local/wine-i386
All exe and libs were stripped. Some compile time tools and the All exe and libs were stripped. Some compile time tools and the
includes were deleted. includes were deleted.
* ldconfig was launched to build the library links: * ldconfig was launched to build the library links:
./qemu /usr/local/qemu-i386/bin/ldconfig-i386 -C /usr/local/qemu-i386/etc/ld.so.cache qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache

9
TODO
View File

@ -1,17 +1,20 @@
- tests for each target CPU
- ppc qemu test
- optimize FPU operations (evaluate x87 stack pointer statically) and - optimize FPU operations (evaluate x87 stack pointer statically) and
fix cr0.TS emulation fix cr0.TS emulation
- fix some 16 bit sp push/pop overflow
- sysenter/sysexit emulation
- finish segment ops (call far, ret far, load_seg suppressed)
- fix CCOP optimisation - fix CCOP optimisation
- fix all remaining thread lock issues (must put TBs in a specific invalid - fix all remaining thread lock issues (must put TBs in a specific invalid
state, find a solution for tb_flush()). state, find a solution for tb_flush()).
- cpu loop optimisation (optimise ret case as the cpu state does not change) - cpu loop optimisation (optimise ret case as the cpu state does not change)
- fix arm fpu rounding (at least for float->integer conversions) - fix arm fpu rounding (at least for float->integer conversions)
- add IPC syscalls
lower priority: lower priority:
-------------- --------------
- sysenter/sysexit emulation - add IPC syscalls
- SMP support - SMP support
- finish segment ops (call far, ret far, load_seg suppressed)
- use -msoft-float on ARM - use -msoft-float on ARM
- use kernel traps for unaligned accesses on ARM ? - use kernel traps for unaligned accesses on ARM ?
- handle rare page fault cases (in particular if page fault in heplers or - handle rare page fault cases (in particular if page fault in heplers or

View File

@ -1 +1 @@
0.4.4 0.5.0

View File

@ -72,7 +72,7 @@ QEMU user mode emulation features:
QEMU full system emulation features: QEMU full system emulation features:
@itemize @itemize
@item Using mmap() system calls to simulate the MMU @item QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU.
@end itemize @end itemize
@section x86 emulation @section x86 emulation
@ -110,14 +110,7 @@ memory access.
10 byte @code{long double}s of x86 for floating point emulation to get 10 byte @code{long double}s of x86 for floating point emulation to get
maximum performances. maximum performances.
@item Full system emulation only works if no data are mapped above the virtual address @item Some priviledged instructions or behaviors are missing, especially for segment protection testing (yet).
0xc0000000 (yet).
@item Some priviledged instructions or behaviors are missing. Only the ones
needed for proper Linux kernel operation are emulated.
@item No memory separation between the kernel and the user processes is done.
It will be implemented very soon.
@end itemize @end itemize
@ -177,9 +170,9 @@ unset LD_LIBRARY_PATH
Then you can launch the precompiled @file{ls} x86 executable: Then you can launch the precompiled @file{ls} x86 executable:
@example @example
qemu-i386 /usr/local/qemu-i386/bin/ls-i386 qemu-i386 tests/i386/ls
@end example @end example
You can look at @file{/usr/local/qemu-i386/bin/qemu-conf.sh} so that You can look at @file{qemu-binfmt-conf.sh} so that
QEMU is automatically launched by the Linux kernel when you try to QEMU is automatically launched by the Linux kernel when you try to
launch x86 executables. It requires the @code{binfmt_misc} module in the launch x86 executables. It requires the @code{binfmt_misc} module in the
Linux kernel. Linux kernel.
@ -258,16 +251,15 @@ available:
@enumerate @enumerate
@item @item
@code{qemu} uses the host Memory Management Unit (MMU) to simulate @code{qemu-fast} uses the host Memory Management Unit (MMU) to simulate
the x86 MMU. It is @emph{fast} but has limitations because the whole 4 GB the x86 MMU. It is @emph{fast} but has limitations because the whole 4 GB
address space cannot be used and some memory mapped peripherials address space cannot be used and some memory mapped peripherials
cannot be emulated accurately yet. Therefore, a specific Linux kernel cannot be emulated accurately yet. Therefore, a specific Linux kernel
must be used (@xref{linux_compile}). must be used (@xref{linux_compile}).
@item @item
@code{qemu-softmmu} uses a software MMU. It is about @emph{two times @code{qemu} uses a software MMU. It is about @emph{two times
slower} but gives a more accurate emulation. (XXX: Linux cannot be ran slower} but gives a more accurate emulation.
unpatched yet).
@end enumerate @end enumerate
@ -296,10 +288,10 @@ CMOS memory
@section Quick Start @section Quick Start
Download the linux image (@file{linux.img}) and type: Download and uncompress the linux image (@file{linux.img}) and type:
@example @example
qemu-softmmu linux.img qemu linux.img
@end example @end example
Linux should boot and give you a prompt. Linux should boot and give you a prompt.
@ -627,8 +619,10 @@ the real one. To know it, use the @code{ls -ls} command.
@node linux_compile @node linux_compile
@section Linux Kernel Compilation @section Linux Kernel Compilation
You should be able to use any kernel with QEMU provided you make the You can use any linux kernel with QEMU. However, if you want to use
following changes (only 2.4.x and 2.5.x were tested): @code{qemu-fast} to get maximum performances, you should make the
following changes to the Linux kernel (only 2.4.x and 2.5.x were
tested):
@enumerate @enumerate
@item @item
@ -723,8 +717,6 @@ Then you can use gdb normally. For example, type 'c' to launch the kernel:
(gdb) c (gdb) c
@end example @end example
WARNING: breakpoints and single stepping are not yet supported.
Here are some useful tips in order to use gdb on system code: Here are some useful tips in order to use gdb on system code:
@enumerate @enumerate
@ -1019,16 +1011,6 @@ The new Plex86 project.
In the directory @file{tests/}, various interesting testing programs In the directory @file{tests/}, various interesting testing programs
are available. There are used for regression testing. are available. There are used for regression testing.
@section @file{hello-i386}
Very simple statically linked x86 program, just to test QEMU during a
port to a new host CPU.
@section @file{hello-arm}
Very simple statically linked ARM program, just to test QEMU during a
port to a new host CPU.
@section @file{test-i386} @section @file{test-i386}
This program executes most of the 16 bit and 32 bit x86 instructions and This program executes most of the 16 bit and 32 bit x86 instructions and
@ -1044,6 +1026,22 @@ The Linux system call @code{vm86()} is used to test vm86 emulation.
Various exceptions are raised to test most of the x86 user space Various exceptions are raised to test most of the x86 user space
exception reporting. exception reporting.
@section @file{linux-test}
This program tests various Linux system calls. It is used to verify
that the system call parameters are correctly converted between target
and host CPUs.
@section @file{hello-i386}
Very simple statically linked x86 program, just to test QEMU during a
port to a new host CPU.
@section @file{hello-arm}
Very simple statically linked ARM program, just to test QEMU during a
port to a new host CPU.
@section @file{sha1} @section @file{sha1}
It is a simple benchmark. Care must be taken to interpret the results It is a simple benchmark. Care must be taken to interpret the results

View File

@ -71,7 +71,7 @@ int __chk_error(const char *filename, int line, int ret)
#define FILE_BUF_SIZE 300 #define FILE_BUF_SIZE 300
void file_test(void) void test_file(void)
{ {
int fd, i, len, ret; int fd, i, len, ret;
uint8_t buf[FILE_BUF_SIZE]; uint8_t buf[FILE_BUF_SIZE];
@ -499,7 +499,7 @@ void test_signal(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
file_test(); test_file();
test_fork(); test_fork();
test_time(); test_time();
test_socket(); test_socket();
@ -507,4 +507,3 @@ int main(int argc, char **argv)
test_signal(); test_signal();
return 0; return 0;
} }

View File

@ -1,62 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <inttypes.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sched.h>
int thread1_func(void *arg)
{
int i;
char buf[512];
for(i=0;i<10;i++) {
snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
write(1, buf, strlen(buf));
usleep(100 * 1000);
}
return 0;
}
int thread2_func(void *arg)
{
int i;
char buf[512];
for(i=0;i<20;i++) {
snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
write(1, buf, strlen(buf));
usleep(120 * 1000);
}
return 0;
}
#define STACK_SIZE 16384
void test_clone(void)
{
uint8_t *stack1, *stack2;
int pid1, pid2, status1, status2;
stack1 = malloc(STACK_SIZE);
pid1 = clone(thread1_func, stack1 + STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1");
stack2 = malloc(STACK_SIZE);
pid2 = clone(thread2_func, stack2 + STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2");
while (waitpid(pid1, &status1, 0) != pid1);
while (waitpid(pid2, &status2, 0) != pid2);
printf("status1=0x%x\n", status1);
printf("status2=0x%x\n", status2);
printf("End of clone test.\n");
}
int main(int argc, char **argv)
{
test_clone();
return 0;
}

View File

@ -1,194 +0,0 @@
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <sys/ucontext.h>
jmp_buf jmp_env;
void alarm_handler(int sig)
{
printf("alarm signal=%d\n", sig);
alarm(1);
}
#ifndef REG_EAX
#define REG_EAX EAX
#define REG_EBX EBX
#define REG_ECX ECX
#define REG_EDX EDX
#define REG_ESI ESI
#define REG_EDI EDI
#define REG_EBP EBP
#define REG_ESP ESP
#define REG_EIP EIP
#define REG_EFL EFL
#define REG_TRAPNO TRAPNO
#define REG_ERR ERR
#endif
void dump_regs(struct ucontext *uc)
{
printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
"EFL=%08x EIP=%08x trapno=%02x err=%08x\n",
uc->uc_mcontext.gregs[REG_EAX],
uc->uc_mcontext.gregs[REG_EBX],
uc->uc_mcontext.gregs[REG_ECX],
uc->uc_mcontext.gregs[REG_EDX],
uc->uc_mcontext.gregs[REG_ESI],
uc->uc_mcontext.gregs[REG_EDI],
uc->uc_mcontext.gregs[REG_EBP],
uc->uc_mcontext.gregs[REG_ESP],
uc->uc_mcontext.gregs[REG_EFL],
uc->uc_mcontext.gregs[REG_EIP],
uc->uc_mcontext.gregs[REG_TRAPNO],
uc->uc_mcontext.gregs[REG_ERR]);
}
void sig_handler(int sig, siginfo_t *info, void *puc)
{
struct ucontext *uc = puc;
printf("%s: si_signo=%d si_errno=%d si_code=%d si_addr=0x%08lx\n",
strsignal(info->si_signo),
info->si_signo, info->si_errno, info->si_code,
(unsigned long)info->si_addr);
dump_regs(uc);
longjmp(jmp_env, 1);
}
int v1;
int tab[2];
int main(int argc, char **argv)
{
struct sigaction act;
volatile int val;
act.sa_sigaction = sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGFPE, &act, NULL);
sigaction(SIGILL, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGTRAP, &act, NULL);
/* test division by zero reporting */
if (setjmp(jmp_env) == 0) {
/* now divide by zero */
v1 = 0;
v1 = 2 / v1;
}
/* test illegal instruction reporting */
if (setjmp(jmp_env) == 0) {
/* now execute an invalid instruction */
asm volatile("ud2");
}
/* test SEGV reporting */
if (setjmp(jmp_env) == 0) {
/* now store in an invalid address */
*(char *)0x1234 = 1;
}
/* test SEGV reporting */
if (setjmp(jmp_env) == 0) {
/* read from an invalid address */
v1 = *(char *)0x1234;
}
printf("segment GPF exception:\n");
if (setjmp(jmp_env) == 0) {
/* load an invalid segment */
asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 0));
}
printf("INT exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("int $0xfd");
}
printf("INT3 exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("int3");
}
printf("CLI exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("cli");
}
printf("STI exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("cli");
}
printf("INTO exception:\n");
if (setjmp(jmp_env) == 0) {
/* overflow exception */
asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
}
printf("BOUND exception:\n");
if (setjmp(jmp_env) == 0) {
/* bound exception */
tab[0] = 1;
tab[1] = 10;
asm volatile ("bound %0, %1" : : "r" (11), "m" (tab));
}
printf("OUTB exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
}
printf("INB exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
}
printf("REP OUTSB exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
}
printf("REP INSB exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
}
printf("HLT exception:\n");
if (setjmp(jmp_env) == 0) {
asm volatile ("hlt");
}
printf("single step exception:\n");
val = 0;
if (setjmp(jmp_env) == 0) {
asm volatile ("pushf\n"
"orl $0x00100, (%%esp)\n"
"popf\n"
"movl $0xabcd, %0\n" : "=m" (val) : : "cc", "memory");
}
printf("val=0x%x\n", val);
#if 1
{
int i;
act.sa_handler = alarm_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
alarm(1);
for(i = 0;i < 2; i++) {
sleep(1);
}
}
#endif
return 0;
}