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…
Reference in New Issue
Block a user