update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@417 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									baf8ebf01a
								
							
						
					
					
						commit
						285dc330bd
					
				@ -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
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								README
									
									
									
									
									
								
							@ -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
 | 
				
			||||||
--------------------
 | 
					--------------------
 | 
				
			||||||
 | 
				
			|||||||
@ -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
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								TODO
									
									
									
									
									
								
							@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										194
									
								
								tests/testsig.c
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								tests/testsig.c
									
									
									
									
									
								
							@ -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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user