diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | Makefile.objs | 3 | ||||
-rw-r--r-- | block/raw-posix.c | 12 | ||||
-rwxr-xr-x | configure | 5 | ||||
-rw-r--r-- | cpu-all.h | 2 | ||||
-rw-r--r-- | cris-dis.c | 4 | ||||
-rw-r--r-- | disas.h | 3 | ||||
-rw-r--r-- | dyngen-exec.h | 23 | ||||
-rw-r--r-- | hw/mips_fulong2e.c | 2 | ||||
-rw-r--r-- | hw/omap_clk.c | 1 | ||||
-rw-r--r-- | pc-bios/bios.bin | bin | 131072 -> 131072 bytes | |||
-rw-r--r-- | qemu-common.h | 9 | ||||
-rw-r--r-- | qemu-timer-common.c | 62 | ||||
-rw-r--r-- | qemu-timer.c | 73 | ||||
-rw-r--r-- | qemu-timer.h | 74 | ||||
-rw-r--r-- | qemu-tool.c | 7 | ||||
m--------- | roms/seabios | 0 | ||||
-rw-r--r-- | rules.mak | 9 | ||||
-rw-r--r-- | simpletrace.c | 10 | ||||
-rw-r--r-- | target-i386/kvm.c | 132 | ||||
-rw-r--r-- | tests/Makefile | 123 | ||||
-rw-r--r-- | tests/runcom.c | 11 | ||||
-rw-r--r-- | tests/test-i386.c | 5 | ||||
-rw-r--r-- | tests/test_path.c | 13 | ||||
-rw-r--r-- | ui/spice-display.c | 3 | ||||
-rw-r--r-- | vl.c | 24 |
26 files changed, 368 insertions, 248 deletions
@@ -129,11 +129,11 @@ version-obj-$(CONFIG_WIN32) += version.o qemu-img.o: qemu-img-cmds.h qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS) -qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o -qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o -qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) +qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@") diff --git a/Makefile.objs b/Makefile.objs index 6e6f60a3af..f07fb01bc3 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -127,7 +127,7 @@ common-obj-y += iov.o acl.o common-obj-$(CONFIG_THREAD) += qemu-thread.o common-obj-$(CONFIG_IOTHREAD) += compatfd.o common-obj-y += notify.o event_notifier.o -common-obj-y += qemu-timer.o +common-obj-y += qemu-timer.o qemu-timer-common.o slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o @@ -278,6 +278,7 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o trace-obj-y = trace.o ifeq ($(TRACE_BACKEND),simple) trace-obj-y += simpletrace.o +user-obj-y += qemu-timer-common.o endif vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/block/raw-posix.c b/block/raw-posix.c index a5cbb7e929..d0393e0c44 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -97,9 +97,9 @@ #define FTYPE_CD 1 #define FTYPE_FD 2 -/* if the FD is not accessed during that time (in ms), we try to +/* if the FD is not accessed during that time (in ns), we try to reopen it to see if the disk has been changed */ -#define FD_OPEN_TIMEOUT 1000 +#define FD_OPEN_TIMEOUT (1000000000) #define MAX_BLOCKSIZE 4096 @@ -908,7 +908,7 @@ static int fd_open(BlockDriverState *bs) return 0; last_media_present = (s->fd >= 0); if (s->fd >= 0 && - (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { + (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) { close(s->fd); s->fd = -1; #ifdef DEBUG_FLOPPY @@ -917,7 +917,7 @@ static int fd_open(BlockDriverState *bs) } if (s->fd < 0) { if (s->fd_got_error && - (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) { + (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) { #ifdef DEBUG_FLOPPY printf("No floppy (open delayed)\n"); #endif @@ -925,7 +925,7 @@ static int fd_open(BlockDriverState *bs) } s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK); if (s->fd < 0) { - s->fd_error_time = qemu_get_clock(rt_clock); + s->fd_error_time = get_clock(); s->fd_got_error = 1; if (last_media_present) s->fd_media_changed = 1; @@ -940,7 +940,7 @@ static int fd_open(BlockDriverState *bs) } if (!last_media_present) s->fd_media_changed = 1; - s->fd_open_time = qemu_get_clock(rt_clock); + s->fd_open_time = get_clock(); s->fd_got_error = 0; return 0; } @@ -92,6 +92,7 @@ libs_softmmu="" libs_tools="" audio_pt_int="" audio_win_int="" +cc_i386=i386-pc-linux-gnu-gcc # parse CC options first for opt do @@ -789,12 +790,14 @@ case "$cpu" in i386) QEMU_CFLAGS="-m32 $QEMU_CFLAGS" LDFLAGS="-m32 $LDFLAGS" + cc_i386='$(CC) -m32' helper_cflags="-fomit-frame-pointer" host_guest_base="yes" ;; x86_64) QEMU_CFLAGS="-m64 $QEMU_CFLAGS" LDFLAGS="-m64 $LDFLAGS" + cc_i386='$(CC) -m32' host_guest_base="yes" ;; arm*) @@ -2348,6 +2351,7 @@ printf "# Configured with:" >> $config_host_mak printf " '%s'" "$0" "$@" >> $config_host_mak echo >> $config_host_mak +echo all: >> $config_host_mak echo "prefix=$prefix" >> $config_host_mak echo "bindir=$bindir" >> $config_host_mak echo "mandir=$mandir" >> $config_host_mak @@ -2639,6 +2643,7 @@ echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak echo "INSTALL_DATA=$install -m0644 -p" >> $config_host_mak echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak echo "CC=$cc" >> $config_host_mak +echo "CC_I386=$cc_i386" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak if test "$sparse" = "yes" ; then echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak @@ -773,7 +773,7 @@ void cpu_dump_statistics (CPUState *env, FILE *f, int flags); void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); + GCC_FMT_ATTR(2, 3); extern CPUState *first_cpu; extern CPUState *cpu_single_env; diff --git a/cris-dis.c b/cris-dis.c index 455ba8af3f..afd775c29b 100644 --- a/cris-dis.c +++ b/cris-dis.c @@ -18,13 +18,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "qemu-common.h" #include "dis-asm.h" //#include "sysdep.h" #include "target-cris/opcode-cris.h" //#include "libiberty.h" - - -void *qemu_malloc(size_t len); /* can't include qemu-common.h here */ #define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0) @@ -8,11 +8,8 @@ void disas(FILE *out, void *code, unsigned long size); void target_disas(FILE *out, target_ulong code, target_ulong size, int flags); -/* The usual mess... FIXME: Remove this condition once dyngen-exec.h is gone */ -#ifndef __DYNGEN_EXEC_H__ void monitor_disas(Monitor *mon, CPUState *env, target_ulong pc, int nb_insn, int is_physical, int flags); -#endif /* Look up symbol for debugging purpose. Returns "" if unknown. */ const char *lookup_symbol(target_ulong orig_addr); diff --git a/dyngen-exec.h b/dyngen-exec.h index 5bfef3f6fe..db00fbae04 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -19,19 +19,7 @@ #if !defined(__DYNGEN_EXEC_H__) #define __DYNGEN_EXEC_H__ -/* prevent Solaris from trying to typedef FILE in gcc's - include/floatingpoint.h which will conflict with the - definition down below */ -#ifdef __sun__ -#define _FILEDEFED -#endif - -/* NOTE: standard headers should be used with special care at this - point because host CPU registers are used as global variables. Some - host headers do not allow that. */ -#include <stddef.h> -#include <stdint.h> -#include <stdbool.h> +#include "qemu-common.h" #ifdef __OpenBSD__ #include <sys/types.h> @@ -40,15 +28,6 @@ /* XXX: This may be wrong for 64-bit ILP32 hosts. */ typedef void * host_reg_t; -#ifdef CONFIG_BSD -typedef struct __sFILE FILE; -#else -typedef struct FILE FILE; -#endif -extern int fprintf(FILE *, const char *, ...); -extern int fputs(const char *, FILE *); -extern int printf(const char *, ...); - #if defined(__i386__) #define AREG0 "ebp" #elif defined(__x86_64__) diff --git a/hw/mips_fulong2e.c b/hw/mips_fulong2e.c index f9723f559e..07eb9eeba1 100644 --- a/hw/mips_fulong2e.c +++ b/hw/mips_fulong2e.c @@ -295,7 +295,7 @@ static void mips_fulong2e_init(ram_addr_t ram_size, const char *boot_device, ram_offset = qemu_ram_alloc(NULL, "fulong2e.ram", ram_size); bios_offset = qemu_ram_alloc(NULL, "fulong2e.bios", bios_size); - cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); + cpu_register_physical_memory(0, ram_size, ram_offset); cpu_register_physical_memory(0x1fc00000LL, bios_size, bios_offset | IO_MEM_ROM); diff --git a/hw/omap_clk.c b/hw/omap_clk.c index 6bcabef8ac..10c9c4308c 100644 --- a/hw/omap_clk.c +++ b/hw/omap_clk.c @@ -20,6 +20,7 @@ */ #include "hw.h" #include "omap.h" +#include "qemu-timer.h" /* for muldiv64() */ struct clk { const char *name; diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin Binary files differindex d0d4b6aa43..f79c342264 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin diff --git a/qemu-common.h b/qemu-common.h index 81aafa0a49..2fbc27f9f0 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -18,11 +18,6 @@ typedef struct QEMUFile QEMUFile; typedef struct QEMUBH QEMUBH; typedef struct DeviceState DeviceState; -/* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that - cannot include the following headers without conflicts. This condition has - to be removed once dyngen is gone. */ -#ifndef __DYNGEN_EXEC_H__ - /* we put basic includes here to avoid repeating them in device drivers */ #include <stdlib.h> #include <stdio.h> @@ -138,8 +133,6 @@ void qemu_bh_delete(QEMUBH *bh); int qemu_bh_poll(void); void qemu_bh_update_timeout(int *timeout); -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c); - void qemu_get_timedate(struct tm *tm, int offset); int qemu_timedate_diff(struct tm *tm); @@ -318,6 +311,4 @@ static inline uint8_t from_bcd(uint8_t val) #include "module.h" -#endif /* dyngen-exec.h hack */ - #endif diff --git a/qemu-timer-common.c b/qemu-timer-common.c new file mode 100644 index 0000000000..fff43996d8 --- /dev/null +++ b/qemu-timer-common.c @@ -0,0 +1,62 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu-timer.h" + +/***********************************************************/ +/* real time host monotonic timer */ + +#ifdef _WIN32 + +int64_t clock_freq; + +static void __attribute__((constructor)) init_get_clock(void) +{ + LARGE_INTEGER freq; + int ret; + ret = QueryPerformanceFrequency(&freq); + if (ret == 0) { + fprintf(stderr, "Could not calibrate ticks\n"); + exit(1); + } + clock_freq = freq.QuadPart; +} + +#else + +int use_rt_clock; + +static void __attribute__((constructor)) init_get_clock(void) +{ + use_rt_clock = 0; +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + { + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + use_rt_clock = 1; + } + } +#endif +} +#endif diff --git a/qemu-timer.c b/qemu-timer.c index bc5f207bb6..95814af798 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -64,78 +64,6 @@ int64_t qemu_icount_bias; static QEMUTimer *icount_rt_timer; static QEMUTimer *icount_vm_timer; - -/***********************************************************/ -/* real time host monotonic timer */ - - -static int64_t get_clock_realtime(void) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); -} - -#ifdef WIN32 - -static int64_t clock_freq; - -static void init_get_clock(void) -{ - LARGE_INTEGER freq; - int ret; - ret = QueryPerformanceFrequency(&freq); - if (ret == 0) { - fprintf(stderr, "Could not calibrate ticks\n"); - exit(1); - } - clock_freq = freq.QuadPart; -} - -static int64_t get_clock(void) -{ - LARGE_INTEGER ti; - QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); -} - -#else - -static int use_rt_clock; - -static void init_get_clock(void) -{ - use_rt_clock = 0; -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) || defined(__FreeBSD_kernel__) - { - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - use_rt_clock = 1; - } - } -#endif -} - -static int64_t get_clock(void) -{ -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ - || defined(__DragonFly__) || defined(__FreeBSD_kernel__) - if (use_rt_clock) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000LL + ts.tv_nsec; - } else -#endif - { - /* XXX: using gettimeofday leads to problems if the date - changes, so it should be avoided. */ - return get_clock_realtime(); - } -} -#endif - /***********************************************************/ /* guest cycle counter */ @@ -614,7 +542,6 @@ int64_t qemu_get_clock_ns(QEMUClock *clock) void init_clocks(void) { - init_get_clock(); rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME); vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL); host_clock = qemu_new_clock(QEMU_CLOCK_HOST); diff --git a/qemu-timer.h b/qemu-timer.h index 1494f79406..299e387768 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -2,6 +2,13 @@ #define QEMU_TIMER_H #include "qemu-common.h" +#include <time.h> +#include <sys/time.h> + +#ifdef _WIN32 +#include <windows.h> +#include <mmsystem.h> +#endif /* timers */ @@ -52,6 +59,73 @@ static inline int64_t get_ticks_per_sec(void) return 1000000000LL; } +/* compute with 96 bit intermediate result: (a*b)/c */ +static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ + union { + uint64_t ll; + struct { +#ifdef HOST_WORDS_BIGENDIAN + uint32_t high, low; +#else + uint32_t low, high; +#endif + } l; + } u, res; + uint64_t rl, rh; + + u.ll = a; + rl = (uint64_t)u.l.low * (uint64_t)b; + rh = (uint64_t)u.l.high * (uint64_t)b; + rh += (rl >> 32); + res.l.high = rh / c; + res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; + return res.ll; +} + +/* real time host monotonic timer */ +static inline int64_t get_clock_realtime(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} + +/* Warning: don't insert tracepoints into these functions, they are + also used by simpletrace backend and tracepoints would cause + an infinite recursion! */ +#ifdef _WIN32 +extern int64_t clock_freq; + +static inline int64_t get_clock(void) +{ + LARGE_INTEGER ti; + QueryPerformanceCounter(&ti); + return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); +} + +#else + +extern int use_rt_clock; + +static inline int64_t get_clock(void) +{ +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \ + || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + if (use_rt_clock) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000000000LL + ts.tv_nsec; + } else +#endif + { + /* XXX: using gettimeofday leads to problems if the date + changes, so it should be avoided. */ + return get_clock_realtime(); + } +} +#endif void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); diff --git a/qemu-tool.c b/qemu-tool.c index b39af86e01..9ccca655ef 100644 --- a/qemu-tool.c +++ b/qemu-tool.c @@ -110,10 +110,3 @@ int qemu_set_fd_handler2(int fd, { return 0; } - -int64_t qemu_get_clock(QEMUClock *clock) -{ - qemu_timeval tv; - qemu_gettimeofday(&tv); - return (tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000)) / 1000000; -} diff --git a/roms/seabios b/roms/seabios -Subproject 17d3e46511aeedc9f09a8216d194d749187b80a +Subproject 0ff9051f756ba739bc2edca77925191c3c6cbc2 @@ -42,6 +42,15 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) +# find-in-path +# Usage: $(call find-in-path, prog) +# Looks in the PATH if the argument contains no slash, else only considers one +# specific directory. Returns an # empty string if the program doesn't exist +# there. +find-in-path = $(if $(find-string /, $1), \ + $(wildcard $1), \ + $(wildcard $(patsubst %, %/$1, $(subst :, ,$(PATH))))) + # Generate timestamp files for .h include files %.h: %.h-timestamp diff --git a/simpletrace.c b/simpletrace.c index b488d51766..9ea0d1f984 100644 --- a/simpletrace.c +++ b/simpletrace.c @@ -12,6 +12,7 @@ #include <stdint.h> #include <stdio.h> #include <time.h> +#include "qemu-timer.h" #include "trace.h" /** Trace file header event ID */ @@ -140,20 +141,13 @@ static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6) { TraceRecord *rec = &trace_buf[trace_idx]; - struct timespec ts; - - /* TODO Windows? It would be good to use qemu-timer here but that isn't - * linked into qemu-tools. Also we should avoid recursion in the tracing - * code, therefore it is useful to be self-contained. - */ - clock_gettime(CLOCK_MONOTONIC, &ts); if (!trace_list[event].state) { return; } rec->event = event; - rec->timestamp_ns = ts.tv_sec * 1000000000LL + ts.tv_nsec; + rec->timestamp_ns = get_clock(); rec->x1 = x1; rec->x2 = x2; rec->x3 = x3; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 512d533970..ae0a034ab0 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -15,6 +15,7 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/mman.h> +#include <sys/utsname.h> #include <linux/kvm.h> @@ -53,6 +54,8 @@ #define BUS_MCEERR_AO 5 #endif +static int lm_capable_kernel; + #ifdef KVM_CAP_EXT_CPUID static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) @@ -239,12 +242,16 @@ static void kvm_do_inject_x86_mce(void *_data) struct kvm_x86_mce_data *data = _data; int r; - /* If there is an MCE excpetion being processed, ignore this SRAO MCE */ - r = kvm_mce_in_exception(data->env); - if (r == -1) - fprintf(stderr, "Failed to get MCE status\n"); - else if (r && !(data->mce->status & MCI_STATUS_AR)) - return; + /* If there is an MCE exception being processed, ignore this SRAO MCE */ + if ((data->env->mcg_cap & MCG_SER_P) && + !(data->mce->status & MCI_STATUS_AR)) { + r = kvm_mce_in_exception(data->env); + if (r == -1) { + fprintf(stderr, "Failed to get MCE status\n"); + } else if (r) { + return; + } + } r = kvm_set_mce(data->env, data->mce); if (r < 0) { @@ -434,23 +441,26 @@ void kvm_arch_reset_vcpu(CPUState *env) } } -static int kvm_has_msr_star(CPUState *env) +int has_msr_star; +int has_msr_hsave_pa; + +static void kvm_supported_msrs(CPUState *env) { - static int has_msr_star; + static int kvm_supported_msrs; int ret; /* first time */ - if (has_msr_star == 0) { + if (kvm_supported_msrs == 0) { struct kvm_msr_list msr_list, *kvm_msr_list; - has_msr_star = -1; + kvm_supported_msrs = -1; /* Obtain MSR list from KVM. These are the MSRs that we must * save/restore */ msr_list.nmsrs = 0; ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list); if (ret < 0 && ret != -E2BIG) { - return 0; + return; } /* Old kernel modules had a bug and could write beyond the provided memory. Allocate at least a safe amount of 1K. */ @@ -466,7 +476,11 @@ static int kvm_has_msr_star(CPUState *env) for (i = 0; i < kvm_msr_list->nmsrs; i++) { if (kvm_msr_list->indices[i] == MSR_STAR) { has_msr_star = 1; - break; + continue; + } + if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) { + has_msr_hsave_pa = 1; + continue; } } } @@ -474,9 +488,19 @@ static int kvm_has_msr_star(CPUState *env) free(kvm_msr_list); } - if (has_msr_star == 1) - return 1; - return 0; + return; +} + +static int kvm_has_msr_hsave_pa(CPUState *env) +{ + kvm_supported_msrs(env); + return has_msr_hsave_pa; +} + +static int kvm_has_msr_star(CPUState *env) +{ + kvm_supported_msrs(env); + return has_msr_star; } static int kvm_init_identity_map_page(KVMState *s) @@ -502,6 +526,11 @@ int kvm_arch_init(KVMState *s, int smp_cpus) { int ret; + struct utsname utsname; + + uname(&utsname); + lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0; + /* create vm86 tss. KVM uses vm86 mode to emulate 16-bit code * directly. In order to use vm86 mode, a TSS is needed. Since this * must be part of guest physical memory, we need to allocate it. Older @@ -779,28 +808,40 @@ static int kvm_put_msrs(CPUState *env, int level) struct kvm_msr_entry entries[100]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; - int i, n = 0; + int n = 0; kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); if (kvm_has_msr_star(env)) kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star); + if (kvm_has_msr_hsave_pa(env)) + kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave); #ifdef TARGET_X86_64 - /* FIXME if lm capable */ - kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); - kvm_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); - kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask); - kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); + if (lm_capable_kernel) { + kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); + kvm_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); + kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask); + kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); + } #endif if (level == KVM_PUT_FULL_STATE) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc); + /* + * KVM is yet unable to synchronize TSC values of multiple VCPUs on + * writeback. Until this is fixed, we only write the offset to SMP + * guests after migration, desynchronizing the VCPUs, but avoiding + * huge jump-backs that would occur without any writeback at all. + */ + if (smp_cpus == 1 || env->tsc != 0) { + kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc); + } kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, env->system_time_msr); kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr); } #ifdef KVM_CAP_MCE if (env->mcg_cap) { + int i; if (level == KVM_PUT_RESET_STATE) kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status); else if (level == KVM_PUT_FULL_STATE) { @@ -1010,13 +1051,16 @@ static int kvm_get_msrs(CPUState *env) msrs[n++].index = MSR_IA32_SYSENTER_EIP; if (kvm_has_msr_star(env)) msrs[n++].index = MSR_STAR; + if (kvm_has_msr_hsave_pa(env)) + msrs[n++].index = MSR_VM_HSAVE_PA; msrs[n++].index = MSR_IA32_TSC; #ifdef TARGET_X86_64 - /* FIXME lm_capable_kernel */ - msrs[n++].index = MSR_CSTAR; - msrs[n++].index = MSR_KERNELGSBASE; - msrs[n++].index = MSR_FMASK; - msrs[n++].index = MSR_LSTAR; + if (lm_capable_kernel) { + msrs[n++].index = MSR_CSTAR; + msrs[n++].index = MSR_KERNELGSBASE; + msrs[n++].index = MSR_FMASK; + msrs[n++].index = MSR_LSTAR; + } #endif msrs[n++].index = MSR_KVM_SYSTEM_TIME; msrs[n++].index = MSR_KVM_WALL_CLOCK; @@ -1066,6 +1110,9 @@ static int kvm_get_msrs(CPUState *env) case MSR_IA32_TSC: env->tsc = msrs[i].data; break; + case MSR_VM_HSAVE_PA: + env->vm_hsave = msrs[i].data; + break; case MSR_KVM_SYSTEM_TIME: env->system_time_msr = msrs[i].data; break; @@ -1085,9 +1132,9 @@ static int kvm_get_msrs(CPUState *env) if (msrs[i].index >= MSR_MC0_CTL && msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { env->mce_banks[msrs[i].index - MSR_MC0_CTL] = msrs[i].data; - break; } #endif + break; } } @@ -1632,6 +1679,28 @@ static void hardware_memory_error(void) exit(1); } +#ifdef KVM_CAP_MCE +static void kvm_mce_broadcast_rest(CPUState *env) +{ + CPUState *cenv; + int family, model, cpuver = env->cpuid_version; + + family = (cpuver >> 8) & 0xf; + model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0xf); + + /* Broadcast MCA signal for processor version 06H_EH and above */ + if ((family == 6 && model >= 14) || family > 6) { + for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + if (cenv == env) { + continue; + } + kvm_inject_x86_mce(cenv, 1, MCI_STATUS_VAL | MCI_STATUS_UC, + MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, 1); + } + } +} +#endif + int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr) { #if defined(KVM_CAP_MCE) @@ -1689,6 +1758,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr) fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno)); abort(); } + kvm_mce_broadcast_rest(env); } else #endif { @@ -1711,7 +1781,6 @@ int kvm_on_sigbus(int code, void *addr) void *vaddr; ram_addr_t ram_addr; target_phys_addr_t paddr; - CPUState *cenv; /* Hope we are lucky for AO MCE */ vaddr = addr; @@ -1727,10 +1796,7 @@ int kvm_on_sigbus(int code, void *addr) kvm_inject_x86_mce(first_cpu, 9, status, MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr, (MCM_ADDR_PHYS << 6) | 0xc, 1); - for (cenv = first_cpu->next_cpu; cenv != NULL; cenv = cenv->next_cpu) { - kvm_inject_x86_mce(cenv, 1, MCI_STATUS_VAL | MCI_STATUS_UC, - MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, 1); - } + kvm_mce_broadcast_rest(first_cpu); } else #endif { diff --git a/tests/Makefile b/tests/Makefile index ff7f787a9a..e43ec70b6d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,83 +1,120 @@ -include ../config-host.mak +-include $(SRC_PATH)/rules.mak $(call set-vpath, $(SRC_PATH)/tests) -CFLAGS=-Wall -O2 -g -fno-strict-aliasing +QEMU=../i386-linux-user/qemu-i386 +QEMU_X86_64=../x86_64-linux-user/qemu-x86_64 +CC_X86_64=$(CC_I386) -m64 + +CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I.. #CFLAGS+=-msse2 LDFLAGS= -ifeq ($(ARCH),i386) -TESTS=linux-test testthread sha1-i386 test-i386 +# TODO: automatically detect ARM and MIPS compilers, and run those too + +# runcom maps page 0, so it requires root privileges +# also, pi_10.com runs indefinitely + +I386_TESTS=hello-i386 \ + linux-test \ + testthread \ + sha1-i386 \ + test-i386 \ + test-mmap \ + # runcom + +# native i386 compilers sometimes are not biarch. assume cross-compilers are +ifneq ($(ARCH),i386) +I386_TESTS+=run-test-x86_64 endif -ifeq ($(ARCH),x86_64) -TESTS=test-x86_64 + +TESTS = test_path +ifneq ($(call find-in-path, $(CC_I386)),) +TESTS += $(I386_TESTS) endif -TESTS+=sha1# test_path -#TESTS+=test_path -#TESTS+=runcom -QEMU=../i386-linux-user/qemu-i386 +all: $(patsubst %,run-%,$(TESTS)) + +# rules to run tests + +.PHONY: $(patsubst %,run-%,$(TESTS)) + +run-%: % + -$(QEMU) ./$* + +run-hello-i386: hello-i386 +run-linux-test: linux-test +run-testthread: testthread +run-sha1-i386: sha1-i386 + +run-test-i386: test-i386 + ./test-i386 > test-i386.ref + -$(QEMU) test-i386 > test-i386.out + @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi + +run-test-x86_64: test-x86_64 + ./test-x86_64 > test-x86_64.ref + -$(QEMU_X86_64) test-x86_64 > test-x86_64.out + @if diff -u test-x86_64.ref test-x86_64.out ; then echo "Auto Test OK"; fi + +run-test-mmap: test-mmap + -$(QEMU) ./test-mmap + -$(QEMU) -p 8192 ./test-mmap 8192 + -$(QEMU) -p 16384 ./test-mmap 16384 + -$(QEMU) -p 32768 ./test-mmap 32768 + +run-runcom: runcom + -$(QEMU) ./runcom $(SRC_PATH)/tests/pi_10.com + +run-test_path: test_path + ./test_path + +# rules to compile tests -all: $(TESTS) +test_path: test_path.o +test_path.o: test_path.c hello-i386: hello-i386.c - $(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $< + $(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $< strip $@ testthread: testthread.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread - -test_path: test_path.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< - ./$@ || { rm $@; exit 1; } + $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread # i386/x86_64 emulation test (test various opcodes) */ test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \ test-i386.h test-i386-shift.h test-i386-muldiv.h - $(CC) -m32 $(CFLAGS) $(LDFLAGS) -static -o $@ \ + $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ \ $(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm test-x86_64: test-i386.c \ test-i386.h test-i386-shift.h test-i386-muldiv.h - $(CC) -m64 $(CFLAGS) $(LDFLAGS) -static -o $@ $(<D)/test-i386.c -lm - -ifeq ($(ARCH),i386) -test: test-i386 - ./test-i386 > test-i386.ref -else -test: -endif - $(QEMU) test-i386 > test-i386.out - @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi - -.PHONY: test-mmap -test-mmap: test-mmap.c - $(CC) $(CFLAGS) -Wall -static -O2 $(LDFLAGS) -o $@ $< - -./test-mmap - -$(QEMU) ./test-mmap - -$(QEMU) -p 8192 ./test-mmap 8192 - -$(QEMU) -p 16384 ./test-mmap 16384 - -$(QEMU) -p 32768 ./test-mmap 32768 + $(CC_X86_64) $(CFLAGS) $(LDFLAGS) -o $@ $(<D)/test-i386.c -lm # generic Linux and CPU test linux-test: linux-test.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm + $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm + +# vm86 test +runcom: runcom.c + $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< + +test-mmap: test-mmap.c + $(CC_I386) -m32 $(CFLAGS) -Wall -O2 $(LDFLAGS) -o $@ $< # speed test sha1-i386: sha1.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + $(CC_I386) $(CFLAGS) $(LDFLAGS) -o $@ $< sha1: sha1.c - $(HOST_CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< speed: sha1 sha1-i386 time ./sha1 time $(QEMU) ./sha1-i386 -# vm86 test -runcom: runcom.c - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< - +# broken test # NOTE: -fomit-frame-pointer is currently needed : this is a bug in libqemu qruncom: qruncom.c ../ioport-user.c ../i386-user/libqemu.a $(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -I../target-i386 -I.. -I../i386-user -I../fpu \ diff --git a/tests/runcom.c b/tests/runcom.c index 6380566635..d60342bfc6 100644 --- a/tests/runcom.c +++ b/tests/runcom.c @@ -13,15 +13,12 @@ #include <linux/unistd.h> #include <asm/vm86.h> -//#define SIGTEST +extern int vm86 (unsigned long int subfunction, + struct vm86plus_struct *info); -#undef __syscall_return -#define __syscall_return(type, res) \ -do { \ - return (type) (res); \ -} while (0) +#define VIF_MASK 0x00080000 -_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86) +//#define SIGTEST #define COM_BASE_ADDR 0x10100 diff --git a/tests/test-i386.c b/tests/test-i386.c index b28b257f81..8f481c7f7a 100644 --- a/tests/test-i386.c +++ b/tests/test-i386.c @@ -2047,6 +2047,10 @@ long enter_stack[4096]; #define RBP "%%ebp" #endif +#if !defined(__x86_64__) +/* causes an infinite loop, disable it for now. */ +#define TEST_ENTER(size, stack_type, level) +#else #define TEST_ENTER(size, stack_type, level)\ {\ long esp_save, esp_val, ebp_val, ebp_save, i;\ @@ -2078,6 +2082,7 @@ long enter_stack[4096]; for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\ printf(FMTLX "\n", (long)ptr[0]);\ } +#endif static void test_enter(void) { diff --git a/tests/test_path.c b/tests/test_path.c index def7441c8c..234ed97088 100644 --- a/tests/test_path.c +++ b/tests/test_path.c @@ -1,12 +1,21 @@ /* Test path override code */ -#define _GNU_SOURCE +#include "../config-host.h" +#include "../qemu-malloc.c" +#include "../cutils.c" #include "../path.c" +#include "../trace.c" +#ifdef CONFIG_SIMPLE_TRACE +#include "../simpletrace.c" +#endif + #include <stdarg.h> #include <sys/stat.h> #include <fcntl.h> +void qemu_log(const char *fmt, ...); + /* Any log message kills the test. */ -void gemu_log(const char *fmt, ...) +void qemu_log(const char *fmt, ...) { va_list ap; diff --git a/ui/spice-display.c b/ui/spice-display.c index 6702dfd7ea..7b4f5c1bc9 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -29,8 +29,7 @@ static int debug = 0; -static void __attribute__((format(printf,2,3))) -dprint(int level, const char *fmt, ...) +static void GCC_FMT_ATTR(2, 3) dprint(int level, const char *fmt, ...) { va_list args; @@ -289,30 +289,6 @@ static int default_driver_check(QemuOpts *opts, void *opaque) /***********************************************************/ /* real time host monotonic timer */ -/* compute with 96 bit intermediate result: (a*b)/c */ -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) -{ - union { - uint64_t ll; - struct { -#ifdef HOST_WORDS_BIGENDIAN - uint32_t high, low; -#else - uint32_t low, high; -#endif - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} - /***********************************************************/ /* host time/date access */ void qemu_get_timedate(struct tm *tm, int offset) |