diff --git a/WinQemu.vcxproj b/WinQemu.vcxproj
index 611c10f5..0a3c3646 100644
--- a/WinQemu.vcxproj
+++ b/WinQemu.vcxproj
@@ -165,6 +165,7 @@
false
+
diff --git a/WinQemu.vcxproj.filters b/WinQemu.vcxproj.filters
index cd042706..27fa6331 100644
--- a/WinQemu.vcxproj.filters
+++ b/WinQemu.vcxproj.filters
@@ -1272,6 +1272,9 @@
qemu\src
+
+ Source Files
+
diff --git a/gettimeofday.c b/gettimeofday.c
new file mode 100644
index 00000000..0b18b2a1
--- /dev/null
+++ b/gettimeofday.c
@@ -0,0 +1,32 @@
+// Source: https://stackoverflow.com/questions/10905892/equivalent-of-gettimeofday-for-windows
+
+#define WIN32_LEAN_AND_MEAN
+#include
+#include // portable: uint64_t MSVC: __int64
+
+// MSVC defines this in winsock2.h!?
+typedef struct timeval {
+ long tv_sec;
+ long tv_usec;
+} timeval;
+
+int gettimeofday(struct timeval* tp, struct timezone* tzp)
+{
+ // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
+ // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
+ // until 00:00:00 January 1, 1970
+ static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
+
+ SYSTEMTIME system_time;
+ FILETIME file_time;
+ uint64_t time;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ time = ((uint64_t)file_time.dwLowDateTime);
+ time += ((uint64_t)file_time.dwHighDateTime) << 32;
+
+ tp->tv_sec = (long)((time - EPOCH) / 10000000L);
+ tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
+ return 0;
+}
\ No newline at end of file
diff --git a/qemu/arm-dis.c b/qemu/arm-dis.c
index dedc8f75..70041e45 100644
--- a/qemu/arm-dis.c
+++ b/qemu/arm-dis.c
@@ -33,15 +33,12 @@
*/
#include "dis-asm.h"
-#define FALSE 0
-#define TRUE (!FALSE)
#ifndef _MSC_VER
#define ATTRIBUTE_UNUSED __attribute__((unused))
#else
#define ATTRIBUTE_UNUSED
#endif
-
#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
#define ARM_EXT_V1 0
@@ -1547,7 +1544,7 @@ static unsigned int regname_selected = 1;
#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
#define arm_regnames regnames[regname_selected].reg_names
-static bfd_boolean force_thumb = FALSE;
+static bfd_boolean force_thumb = false;
/* Current IT instruction state. This contains the same state as the IT
bits in the CPSR. */
@@ -1644,7 +1641,7 @@ arm_decode_shift (long given, fprintf_ftype func, void *stream,
}
/* Print one coprocessor instruction on INFO->STREAM.
- Return TRUE if the instuction matched, FALSE if this is not a
+ Return true if the instuction matched, false if this is not a
recognised coprocessor instruction. */
static bfd_boolean
@@ -2137,10 +2134,10 @@ print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given,
else
func (stream, "%c", *c);
}
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
static void
@@ -2234,7 +2231,7 @@ print_arm_address (bfd_vma pc, struct disassemble_info *info, long given)
}
/* Print one neon instruction on INFO->STREAM.
- Return TRUE if the instuction matched, FALSE if this is not a
+ Return true if the instuction matched, false if this is not a
recognised neon instruction. */
static bfd_boolean
@@ -2260,7 +2257,7 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
else if ((given & 0xff000000) == 0xf9000000)
given ^= 0xf9000000 ^ 0xf4000000;
else
- return FALSE;
+ return false;
}
for (insn = neon_opcodes; insn->assembler; insn++)
@@ -2350,34 +2347,34 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
{
int amask = (1 << size) - 1;
if ((idx_align & (1 << size)) != 0)
- return FALSE;
+ return false;
if (size > 0)
{
if ((idx_align & amask) == amask)
align = 8 << size;
else if ((idx_align & amask) != 0)
- return FALSE;
+ return false;
}
}
break;
case 2:
if (size == 2 && (idx_align & 2) != 0)
- return FALSE;
+ return false;
align = (idx_align & 1) ? 16 << size : 0;
break;
case 3:
if ((size == 2 && (idx_align & 3) != 0)
|| (idx_align & 1) != 0)
- return FALSE;
+ return false;
break;
case 4:
if (size == 2)
{
if ((idx_align & 3) == 3)
- return FALSE;
+ return false;
align = (idx_align & 3) * 64;
}
else
@@ -2686,10 +2683,10 @@ print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb)
else
func (stream, "%c", *c);
}
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/* Print one ARM instruction from PC on INFO->STREAM. */
@@ -2701,10 +2698,10 @@ print_insn_arm_internal (bfd_vma pc, struct disassemble_info *info, long given)
void *stream = info->stream;
fprintf_ftype func = info->fprintf_func;
- if (print_insn_coprocessor (pc, info, given, FALSE))
+ if (print_insn_coprocessor (pc, info, given, false))
return;
- if (print_insn_neon (info, given, FALSE))
+ if (print_insn_neon (info, given, false))
return;
for (insn = arm_opcodes; insn->assembler; insn++)
@@ -3337,10 +3334,10 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
void *stream = info->stream;
fprintf_ftype func = info->fprintf_func;
- if (print_insn_coprocessor (pc, info, given, TRUE))
+ if (print_insn_coprocessor (pc, info, given, true))
return;
- if (print_insn_neon (info, given, TRUE))
+ if (print_insn_neon (info, given, true))
return;
for (insn = thumb32_opcodes; insn->assembler; insn++)
@@ -3475,7 +3472,7 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
unsigned int op = (given & 0x00000f00) >> 8;
unsigned int i12 = (given & 0x00000fff);
unsigned int i8 = (given & 0x000000ff);
- bfd_boolean writeback = FALSE, postind = FALSE;
+ bfd_boolean writeback = false, postind = false;
int offset = 0;
func (stream, "[%s", arm_regnames[Rn]);
@@ -3505,22 +3502,22 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
case 0xF: /* 8-bit + preindex with wb */
offset = i8;
- writeback = TRUE;
+ writeback = true;
break;
case 0xD: /* 8-bit - preindex with wb */
offset = -i8;
- writeback = TRUE;
+ writeback = true;
break;
case 0xB: /* 8-bit + postindex */
offset = i8;
- postind = TRUE;
+ postind = true;
break;
case 0x9: /* 8-bit - postindex */
offset = -i8;
- postind = TRUE;
+ postind = true;
break;
default:
@@ -3893,12 +3890,12 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
unsigned char b[4];
long given;
int status;
- int is_thumb = FALSE;
- int is_data = FALSE;
+ int is_thumb = false;
+ int is_data = false;
unsigned int size = 4;
void (*printer) (bfd_vma, struct disassemble_info *, long);
#if 0
- bfd_boolean found = FALSE;
+ bfd_boolean found = false;
if (info->disassembler_options)
{
@@ -3921,7 +3918,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
if (pc <= last_mapping_addr)
last_mapping_sym = -1;
is_thumb = (last_type == MAP_THUMB);
- found = FALSE;
+ found = false;
/* Start scanning at the start of the function, or wherever
we finished last time. */
n = info->symtab_pos + 1;
@@ -3939,7 +3936,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
&& get_sym_code_type (info, n, &type))
{
last_sym = n;
- found = TRUE;
+ found = true;
}
}
@@ -3956,7 +3953,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
if (get_sym_code_type (info, n, &type))
{
last_sym = n;
- found = TRUE;
+ found = true;
break;
}
}
@@ -4028,7 +4025,7 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
#endif
if (force_thumb)
- is_thumb = TRUE;
+ is_thumb = true;
info->bytes_per_line = 4;
diff --git a/qemu/configure b/qemu/configure
index cc3cbd62..69a5502b 100644
--- a/qemu/configure
+++ b/qemu/configure
@@ -1686,6 +1686,16 @@ QEMU_CFLAGS="-U_FORTIFY_SOURCE $QEMU_CFLAGS"
QEMU_CFLAGS="-I. -I\$(SRC_PATH) -MMD -MP -MT \$@ $QEMU_CFLAGS"
LDFLAGS="-g $LDFLAGS"
+gcc_flags="-Wold-style-declaration -Wold-style-definition"
+cat > $TMPC << EOF
+int main(void) { }
+EOF
+for flag in $gcc_flags; do
+ if compile_prog "$QEMU_CFLAGS" "$flag" ; then
+ QEMU_CFLAGS="$flag $QEMU_CFLAGS"
+ fi
+done
+
# Consult white-list to determine whether to enable werror
# by default. Only enable by default for git builds
if test -z "$werror" ; then
@@ -1861,7 +1871,7 @@ if test $profiler = "yes" ; then
fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
- CFLAGS="-I\$(SRC_PATH)/slirp $CFLAGS"
+ QEMU_CFLAGS="-I\$(SRC_PATH)/slirp $QEMU_CFLAGS"
fi
if test "$vde" = "yes" ; then
echo "CONFIG_VDE=y" >> $config_host_mak
diff --git a/qemu/cris-dis.c b/qemu/cris-dis.c
index f6932a05..455ba8af 100644
--- a/qemu/cris-dis.c
+++ b/qemu/cris-dis.c
@@ -26,8 +26,6 @@
void *qemu_malloc(size_t len); /* can't include qemu-common.h here */
-#define FALSE 0
-#define TRUE 1
#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0)
/* cris-opc.c -- Table of opcodes for the CRIS processor.
@@ -1320,7 +1318,7 @@ cris_parse_disassembler_options (disassemble_info *info,
info->private_data = calloc (1, sizeof (struct cris_disasm_data));
disdata = (struct cris_disasm_data *) info->private_data;
if (disdata == NULL)
- return FALSE;
+ return false;
/* Default true. */
disdata->trace_case
@@ -1328,7 +1326,7 @@ cris_parse_disassembler_options (disassemble_info *info,
|| (strcmp (info->disassembler_options, "nocase") != 0));
disdata->distype = distype;
- return TRUE;
+ return true;
}
static const struct cris_spec_reg *
@@ -2779,7 +2777,7 @@ print_insn_cris_with_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_v0_v10))
return -1;
- return print_insn_cris_generic (vma, info, TRUE);
+ return print_insn_cris_generic (vma, info, true);
}
#endif
/* Disassemble, prefixing register names with `$'. CRIS v32. */
@@ -2791,7 +2789,7 @@ print_insn_crisv32_with_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_v32))
return -1;
- return print_insn_cris_generic (vma, info, TRUE);
+ return print_insn_cris_generic (vma, info, true);
}
#if 0
@@ -2805,7 +2803,7 @@ print_insn_crisv10_v32_with_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
return -1;
- return print_insn_cris_generic (vma, info, TRUE);
+ return print_insn_cris_generic (vma, info, true);
}
/* Disassemble, no prefixes on register names. CRIS v0..v10. */
@@ -2817,7 +2815,7 @@ print_insn_cris_without_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_v0_v10))
return -1;
- return print_insn_cris_generic (vma, info, FALSE);
+ return print_insn_cris_generic (vma, info, false);
}
/* Disassemble, no prefixes on register names. CRIS v32. */
@@ -2829,7 +2827,7 @@ print_insn_crisv32_without_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_v32))
return -1;
- return print_insn_cris_generic (vma, info, FALSE);
+ return print_insn_cris_generic (vma, info, false);
}
/* Disassemble, no prefixes on register names.
@@ -2842,7 +2840,7 @@ print_insn_crisv10_v32_without_register_prefix (bfd_vma vma,
if (info->private_data == NULL
&& !cris_parse_disassembler_options (info, cris_dis_common_v10_v32))
return -1;
- return print_insn_cris_generic (vma, info, FALSE);
+ return print_insn_cris_generic (vma, info, false);
}
#endif
diff --git a/qemu/dis-asm.h b/qemu/dis-asm.h
index 74f87335..0e0f277d 100644
--- a/qemu/dis-asm.h
+++ b/qemu/dis-asm.h
@@ -20,6 +20,7 @@
#define DIS_ASM_H
#include
+#include
#include
#include
#include
@@ -491,7 +492,6 @@ bfd_vma bfd_getl32 (const bfd_byte *addr);
bfd_vma bfd_getb32 (const bfd_byte *addr);
bfd_vma bfd_getl16 (const bfd_byte *addr);
bfd_vma bfd_getb16 (const bfd_byte *addr);
-typedef enum bfd_boolean {false, true} boolean;
-typedef boolean bfd_boolean;
+typedef bool bfd_boolean;
#endif /* ! defined (DIS_ASM_H) */
diff --git a/qemu/gdbstub.c b/qemu/gdbstub.c
index 34a67b89..4e1d9964 100644
--- a/qemu/gdbstub.c
+++ b/qemu/gdbstub.c
@@ -505,8 +505,9 @@ static const int gpr_map[16] = {
8, 9, 10, 11, 12, 13, 14, 15
};
#else
-static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+#define gpr_map gpr_map32
#endif
+static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
#define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)
@@ -520,7 +521,11 @@ static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
{
if (n < CPU_NB_REGS) {
- GET_REGL(env->regs[gpr_map[n]]);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ GET_REG64(env->regs[gpr_map[n]]);
+ } else if (n < CPU_NB_REGS32) {
+ GET_REG32(env->regs[gpr_map32[n]]);
+ }
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
@@ -531,12 +536,20 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
- stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
- stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
- return 16;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
+ stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
+ return 16;
+ }
} else {
switch (n) {
- case IDX_IP_REG: GET_REGL(env->eip);
+ case IDX_IP_REG:
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ GET_REG64(env->eip);
+ } else {
+ GET_REG32(env->eip);
+ }
case IDX_FLAGS_REG: GET_REG32(env->eflags);
case IDX_SEG_REGS: GET_REG32(env->segs[R_CS].selector);
@@ -592,8 +605,15 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
uint32_t tmp;
if (n < CPU_NB_REGS) {
- env->regs[gpr_map[n]] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->regs[gpr_map[n]] = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ } else if (n < CPU_NB_REGS32) {
+ n = gpr_map32[n];
+ env->regs[n] &= ~0xffffffffUL;
+ env->regs[n] |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
} else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
#ifdef USE_X86LDOUBLE
/* FIXME: byteswap float values - after fixing fpregs layout. */
@@ -602,14 +622,23 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
return 10;
} else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
n -= IDX_XMM_REGS;
- env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
- env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
- return 16;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
+ env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
+ return 16;
+ }
} else {
switch (n) {
case IDX_IP_REG:
- env->eip = ldtul_p(mem_buf);
- return sizeof(target_ulong);
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->eip = ldq_p(mem_buf);
+ return 8;
+ } else {
+ env->eip &= ~0xffffffffUL;
+ env->eip |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
case IDX_FLAGS_REG:
env->eflags = ldl_p(mem_buf);
return 4;
diff --git a/qemu/hw/hw.h b/qemu/hw/hw.h
index cabf6335..8c223f84 100644
--- a/qemu/hw/hw.h
+++ b/qemu/hw/hw.h
@@ -10,6 +10,7 @@
#include "cpu-common.h"
#endif
+#include
#include "ioport.h"
#include "irq.h"
@@ -299,6 +300,7 @@ typedef struct {
enum VMStateFlags flags;
const VMStateDescription *vmsd;
int version_id;
+ bool (*field_exists)(void *opaque, int version_id);
} VMStateField;
struct VMStateDescription {
@@ -345,6 +347,16 @@ extern const VMStateInfo vmstate_info_buffer;
+ type_check(_type,typeof_field(_state, _field)) \
}
+#define VMSTATE_SINGLE_TEST(_field, _state, _test, _info, _type) { \
+ .name = (stringify(_field)), \
+ .field_exists = (_test), \
+ .size = sizeof(_type), \
+ .info = &(_info), \
+ .flags = VMS_SINGLE, \
+ .offset = offsetof(_state, _field) \
+ + type_check(_type,typeof_field(_state, _field)) \
+}
+
#define VMSTATE_POINTER(_field, _state, _version, _info, _type) { \
.name = (stringify(_field)), \
.version_id = (_version), \
@@ -366,6 +378,17 @@ extern const VMStateInfo vmstate_info_buffer;
+ type_check_array(_type,typeof_field(_state, _field),_num) \
}
+#define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
+ .name = (stringify(_field)), \
+ .field_exists = (_test), \
+ .num = (_num), \
+ .info = &(_info), \
+ .size = sizeof(_type), \
+ .flags = VMS_ARRAY, \
+ .offset = offsetof(_state, _field) \
+ + type_check_array(_type,typeof_field(_state, _field),_num) \
+}
+
#define VMSTATE_VARRAY(_field, _state, _field_num, _version, _info, _type) {\
.name = (stringify(_field)), \
.version_id = (_version), \
@@ -524,6 +547,9 @@ extern const VMStateDescription vmstate_i2c_slave;
#define VMSTATE_INT32_LE(_f, _s) \
VMSTATE_SINGLE(_f, _s, 0, vmstate_info_int32_le, int32_t)
+#define VMSTATE_UINT32_TEST(_f, _s, _t) \
+ VMSTATE_SINGLE_TEST(_f, _s, _t, vmstate_info_uint32, uint32_t)
+
#define VMSTATE_TIMER_V(_f, _s, _v) \
VMSTATE_POINTER(_f, _s, _v, vmstate_info_timer, QEMUTimer *)
diff --git a/qemu/hw/marvell_88w8618_audio.c b/qemu/hw/marvell_88w8618_audio.c
index 21f8d387..d2fc7a8d 100644
--- a/qemu/hw/marvell_88w8618_audio.c
+++ b/qemu/hw/marvell_88w8618_audio.c
@@ -41,11 +41,11 @@ typedef struct mv88w8618_audio_state {
uint32_t playback_mode;
uint32_t status;
uint32_t irq_enable;
- unsigned long phys_buf;
+ uint32_t phys_buf;
uint32_t target_buffer;
- unsigned int threshold;
- unsigned int play_pos;
- unsigned int last_free;
+ uint32_t threshold;
+ uint32_t play_pos;
+ uint32_t last_free;
uint32_t clock_div;
DeviceState *wm;
} mv88w8618_audio_state;
@@ -58,22 +58,22 @@ static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
int8_t *mem_buffer;
int pos, block_size;
- if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN))
+ if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
return;
-
- if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE)
+ }
+ if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
free_out <<= 1;
-
- if (!(s->playback_mode & MP_AUDIO_MONO))
+ }
+ if (!(s->playback_mode & MP_AUDIO_MONO)) {
free_out <<= 1;
-
+ }
block_size = s->threshold / 2;
- if (free_out - s->last_free < block_size)
+ if (free_out - s->last_free < block_size) {
return;
-
- if (block_size > 4096)
+ }
+ if (block_size > 4096) {
return;
-
+ }
cpu_physical_memory_read(s->target_buffer + s->play_pos, (void *)buf,
block_size);
mem_buffer = buf;
@@ -85,9 +85,10 @@ static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
*codec_buffer++ = *(int16_t *)mem_buffer;
mem_buffer += 2;
}
- } else
+ } else {
memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
(uint32_t *)mem_buffer, block_size);
+ }
} else {
if (s->playback_mode & MP_AUDIO_MONO) {
codec_buffer = wm8750_dac_buffer(s->wm, block_size);
@@ -115,19 +116,20 @@ static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
s->play_pos = 0;
}
- if (s->status & s->irq_enable)
+ if (s->status & s->irq_enable) {
qemu_irq_raise(s->irq);
+ }
}
static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
{
int rate;
- if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ)
+ if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) {
rate = 24576000 / 64; /* 24.576MHz */
- else
+ } else {
rate = 11289600 / 64; /* 11.2896MHz */
-
+ }
rate /= ((s->clock_div >> 8) & 0xff) + 1;
wm8750_set_bclk_in(s->wm, rate);
@@ -188,8 +190,9 @@ static void mv88w8618_audio_write(void *opaque, target_phys_addr_t offset,
case MP_AUDIO_IRQ_ENABLE:
s->irq_enable = value;
- if (s->status & s->irq_enable)
+ if (s->status & s->irq_enable) {
qemu_irq_raise(s->irq);
+ }
break;
case MP_AUDIO_TX_START_LO:
@@ -212,13 +215,17 @@ static void mv88w8618_audio_write(void *opaque, target_phys_addr_t offset,
}
}
-static void mv88w8618_audio_reset(void *opaque)
+static void mv88w8618_audio_reset(DeviceState *d)
{
- mv88w8618_audio_state *s = opaque;
+ mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state,
+ sysbus_from_qdev(d));
s->playback_mode = 0;
s->status = 0;
s->irq_enable = 0;
+ s->clock_div = 0;
+ s->threshold = 0;
+ s->phys_buf = 0;
}
static CPUReadMemoryFunc * const mv88w8618_audio_readfn[] = {
@@ -246,15 +253,34 @@ static int mv88w8618_audio_init(SysBusDevice *dev)
mv88w8618_audio_writefn, s);
sysbus_init_mmio(dev, MP_AUDIO_SIZE, iomemtype);
- qemu_register_reset(mv88w8618_audio_reset, s);
-
return 0;
}
+static const VMStateDescription mv88w8618_audio_vmsd = {
+ .name = "mv88w8618_audio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
+ VMSTATE_UINT32(status, mv88w8618_audio_state),
+ VMSTATE_UINT32(irq_enable, mv88w8618_audio_state),
+ VMSTATE_UINT32(phys_buf, mv88w8618_audio_state),
+ VMSTATE_UINT32(target_buffer, mv88w8618_audio_state),
+ VMSTATE_UINT32(threshold, mv88w8618_audio_state),
+ VMSTATE_UINT32(play_pos, mv88w8618_audio_state),
+ VMSTATE_UINT32(last_free, mv88w8618_audio_state),
+ VMSTATE_UINT32(clock_div, mv88w8618_audio_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static SysBusDeviceInfo mv88w8618_audio_info = {
.init = mv88w8618_audio_init,
.qdev.name = "mv88w8618_audio",
.qdev.size = sizeof(mv88w8618_audio_state),
+ .qdev.reset = mv88w8618_audio_reset,
+ .qdev.vmsd = &mv88w8618_audio_vmsd,
.qdev.props = (Property[]) {
{
.name = "wm8750",
diff --git a/qemu/hw/mc146818rtc.c b/qemu/hw/mc146818rtc.c
index 2f8405ee..94f87b61 100644
--- a/qemu/hw/mc146818rtc.c
+++ b/qemu/hw/mc146818rtc.c
@@ -108,8 +108,8 @@ static void rtc_coalesced_timer_update(RTCState *s)
} else {
/* divide each RTC interval to 2 - 8 smaller intervals */
int c = MIN(s->irq_coalesced, 7) + 1;
- int64_t next_clock = qemu_get_clock(vm_clock) +
- muldiv64(s->period / c, get_ticks_per_sec(), 32768);
+ int64_t next_clock = qemu_get_clock(rtc_clock) +
+ muldiv64(s->period / c, get_ticks_per_sec(), 32768);
qemu_mod_timer(s->coalesced_timer, next_clock);
}
}
@@ -161,7 +161,8 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
/* compute 32 khz clock */
cur_clock = muldiv64(current_time, 32768, get_ticks_per_sec());
next_irq_clock = (cur_clock & ~(period - 1)) + period;
- s->next_periodic_time = muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
+ s->next_periodic_time =
+ muldiv64(next_irq_clock, get_ticks_per_sec(), 32768) + 1;
qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
} else {
#ifdef TARGET_I386
@@ -232,7 +233,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
- rtc_timer_update(s, qemu_get_clock(vm_clock));
+ rtc_timer_update(s, qemu_get_clock(rtc_clock));
break;
case RTC_REG_B:
if (data & REG_B_SET) {
@@ -246,7 +247,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
}
}
s->cmos_data[RTC_REG_B] = data;
- rtc_timer_update(s, qemu_get_clock(vm_clock));
+ rtc_timer_update(s, qemu_get_clock(rtc_clock));
break;
case RTC_REG_C:
case RTC_REG_D:
@@ -605,18 +606,17 @@ static int rtc_initfn(ISADevice *dev)
rtc_set_date_from_host(s);
- s->periodic_timer = qemu_new_timer(vm_clock,
- rtc_periodic_timer, s);
+ s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
#ifdef TARGET_I386
if (rtc_td_hack)
- s->coalesced_timer = qemu_new_timer(vm_clock, rtc_coalesced_timer, s);
+ s->coalesced_timer =
+ qemu_new_timer(rtc_clock, rtc_coalesced_timer, s);
#endif
- s->second_timer = qemu_new_timer(vm_clock,
- rtc_update_second, s);
- s->second_timer2 = qemu_new_timer(vm_clock,
- rtc_update_second2, s);
+ s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
+ s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
- s->next_second_time = qemu_get_clock(vm_clock) + (get_ticks_per_sec() * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
register_ioport_write(base, 2, 1, cmos_ioport_write, s);
@@ -747,14 +747,12 @@ RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
s->base_year = base_year;
rtc_set_date_from_host(s);
- s->periodic_timer = qemu_new_timer(vm_clock,
- rtc_periodic_timer, s);
- s->second_timer = qemu_new_timer(vm_clock,
- rtc_update_second, s);
- s->second_timer2 = qemu_new_timer(vm_clock,
- rtc_update_second2, s);
+ s->periodic_timer = qemu_new_timer(rtc_clock, rtc_periodic_timer, s);
+ s->second_timer = qemu_new_timer(rtc_clock, rtc_update_second, s);
+ s->second_timer2 = qemu_new_timer(rtc_clock, rtc_update_second2, s);
- s->next_second_time = qemu_get_clock(vm_clock) + (get_ticks_per_sec() * 99) / 100;
+ s->next_second_time =
+ qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
io_memory = cpu_register_io_memory(rtc_mm_read, rtc_mm_write, s);
diff --git a/qemu/hw/musicpal.c b/qemu/hw/musicpal.c
index 1c4f17cb..1fad36f2 100644
--- a/qemu/hw/musicpal.c
+++ b/qemu/hw/musicpal.c
@@ -146,7 +146,7 @@ typedef struct mv88w8618_eth_state {
uint32_t icr;
uint32_t imr;
int mmio_index;
- int vlan_header;
+ uint32_t vlan_header;
uint32_t tx_queue[2];
uint32_t rx_queue[4];
uint32_t frx_queue[4];
@@ -188,8 +188,9 @@ static ssize_t eth_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
for (i = 0; i < 4; i++) {
desc_addr = s->cur_rx[i];
- if (!desc_addr)
+ if (!desc_addr) {
continue;
+ }
do {
eth_rx_desc_get(desc_addr, &desc);
if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) {
@@ -200,8 +201,9 @@ static ssize_t eth_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
s->cur_rx[i] = desc.next;
s->icr |= MP_ETH_IRQ_RX;
- if (s->icr & s->imr)
+ if (s->icr & s->imr) {
qemu_irq_raise(s->irq);
+ }
eth_rx_desc_put(desc_addr, &desc);
return size;
}
@@ -238,7 +240,9 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index)
uint8_t buf[2048];
int len;
-
+ if (!desc_addr) {
+ return;
+ }
do {
eth_tx_desc_get(desc_addr, &desc);
if (desc.cmdstat & MP_ETH_TX_OWN) {
@@ -311,12 +315,15 @@ static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,
break;
case MP_ETH_SDCMR:
- if (value & MP_ETH_CMD_TXHI)
+ if (value & MP_ETH_CMD_TXHI) {
eth_send(s, 1);
- if (value & MP_ETH_CMD_TXLO)
+ }
+ if (value & MP_ETH_CMD_TXLO) {
eth_send(s, 0);
- if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr)
+ }
+ if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) {
qemu_irq_raise(s->irq);
+ }
break;
case MP_ETH_ICR:
@@ -325,8 +332,9 @@ static void mv88w8618_eth_write(void *opaque, target_phys_addr_t offset,
case MP_ETH_IMR:
s->imr = value;
- if (s->icr & s->imr)
+ if (s->icr & s->imr) {
qemu_irq_raise(s->irq);
+ }
break;
case MP_ETH_FRDP0 ... MP_ETH_FRDP3:
@@ -379,6 +387,31 @@ static int mv88w8618_eth_init(SysBusDevice *dev)
return 0;
}
+static const VMStateDescription mv88w8618_eth_vmsd = {
+ .name = "mv88w8618_eth",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(smir, mv88w8618_eth_state),
+ VMSTATE_UINT32(icr, mv88w8618_eth_state),
+ VMSTATE_UINT32(imr, mv88w8618_eth_state),
+ VMSTATE_UINT32(vlan_header, mv88w8618_eth_state),
+ VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2),
+ VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4),
+ VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4),
+ VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo mv88w8618_eth_info = {
+ .init = mv88w8618_eth_init,
+ .qdev.name = "mv88w8618_eth",
+ .qdev.size = sizeof(mv88w8618_eth_state),
+ .qdev.vmsd = &mv88w8618_eth_vmsd,
+};
+
/* LCD register offsets */
#define MP_LCD_IRQCTRL 0x180
#define MP_LCD_IRQSTAT 0x184
@@ -403,8 +436,8 @@ typedef struct musicpal_lcd_state {
uint32_t brightness;
uint32_t mode;
uint32_t irqctrl;
- int page;
- int page_off;
+ uint32_t page;
+ uint32_t page_off;
DisplayState *ds;
uint8_t video_ram[128*64/8];
} musicpal_lcd_state;
@@ -451,12 +484,15 @@ static void lcd_refresh(void *opaque)
col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
- for (x = 0; x < 128; x++) \
- for (y = 0; y < 64; y++) \
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) \
+ for (x = 0; x < 128; x++) { \
+ for (y = 0; y < 64; y++) { \
+ if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
glue(set_lcd_pixel, depth)(s, x, y, col); \
- else \
+ } else { \
glue(set_lcd_pixel, depth)(s, x, y, 0); \
+ } \
+ } \
+ } \
break;
LCD_REFRESH(8, rgb_to_pixel8)
LCD_REFRESH(16, rgb_to_pixel16)
@@ -476,7 +512,7 @@ static void lcd_invalidate(void *opaque)
static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
{
- musicpal_lcd_state *s = (musicpal_lcd_state *) opaque;
+ musicpal_lcd_state *s = opaque;
s->brightness &= ~(1 << irq);
s->brightness |= level << irq;
}
@@ -505,10 +541,11 @@ static void musicpal_lcd_write(void *opaque, target_phys_addr_t offset,
break;
case MP_LCD_SPICTRL:
- if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD)
+ if (value == MP_LCD_SPI_DATA || value == MP_LCD_SPI_CMD) {
s->mode = value;
- else
+ } else {
s->mode = MP_LCD_SPI_INVALID;
+ }
break;
case MP_LCD_INST:
@@ -565,6 +602,29 @@ static int musicpal_lcd_init(SysBusDevice *dev)
return 0;
}
+static const VMStateDescription musicpal_lcd_vmsd = {
+ .name = "musicpal_lcd",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(brightness, musicpal_lcd_state),
+ VMSTATE_UINT32(mode, musicpal_lcd_state),
+ VMSTATE_UINT32(irqctrl, musicpal_lcd_state),
+ VMSTATE_UINT32(page, musicpal_lcd_state),
+ VMSTATE_UINT32(page_off, musicpal_lcd_state),
+ VMSTATE_BUFFER(video_ram, musicpal_lcd_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo musicpal_lcd_info = {
+ .init = musicpal_lcd_init,
+ .qdev.name = "musicpal_lcd",
+ .qdev.size = sizeof(musicpal_lcd_state),
+ .qdev.vmsd = &musicpal_lcd_vmsd,
+};
+
/* PIC register offsets */
#define MP_PIC_STATUS 0x00
#define MP_PIC_ENABLE_SET 0x08
@@ -587,10 +647,11 @@ static void mv88w8618_pic_set_irq(void *opaque, int irq, int level)
{
mv88w8618_pic_state *s = opaque;
- if (level)
+ if (level) {
s->level |= 1 << irq;
- else
+ } else {
s->level &= ~(1 << irq);
+ }
mv88w8618_pic_update(s);
}
@@ -625,9 +686,10 @@ static void mv88w8618_pic_write(void *opaque, target_phys_addr_t offset,
mv88w8618_pic_update(s);
}
-static void mv88w8618_pic_reset(void *opaque)
+static void mv88w8618_pic_reset(DeviceState *d)
{
- mv88w8618_pic_state *s = opaque;
+ mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
+ sysbus_from_qdev(d));
s->level = 0;
s->enabled = 0;
@@ -655,11 +717,29 @@ static int mv88w8618_pic_init(SysBusDevice *dev)
iomemtype = cpu_register_io_memory(mv88w8618_pic_readfn,
mv88w8618_pic_writefn, s);
sysbus_init_mmio(dev, MP_PIC_SIZE, iomemtype);
-
- qemu_register_reset(mv88w8618_pic_reset, s);
return 0;
}
+static const VMStateDescription mv88w8618_pic_vmsd = {
+ .name = "mv88w8618_pic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(level, mv88w8618_pic_state),
+ VMSTATE_UINT32(enabled, mv88w8618_pic_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo mv88w8618_pic_info = {
+ .init = mv88w8618_pic_init,
+ .qdev.name = "mv88w8618_pic",
+ .qdev.size = sizeof(mv88w8618_pic_state),
+ .qdev.reset = mv88w8618_pic_reset,
+ .qdev.vmsd = &mv88w8618_pic_vmsd,
+};
+
/* PIT register offsets */
#define MP_PIT_TIMER1_LENGTH 0x00
/* ... */
@@ -683,7 +763,6 @@ typedef struct mv88w8618_timer_state {
typedef struct mv88w8618_pit_state {
SysBusDevice busdev;
mv88w8618_timer_state timer[4];
- uint32_t control;
} mv88w8618_pit_state;
static void mv88w8618_timer_tick(void *opaque)
@@ -731,28 +810,47 @@ static void mv88w8618_pit_write(void *opaque, target_phys_addr_t offset,
case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
t = &s->timer[offset >> 2];
t->limit = value;
- ptimer_set_limit(t->ptimer, t->limit, 1);
+ if (t->limit > 0) {
+ ptimer_set_limit(t->ptimer, t->limit, 1);
+ } else {
+ ptimer_stop(t->ptimer);
+ }
break;
case MP_PIT_CONTROL:
for (i = 0; i < 4; i++) {
- if (value & 0xf) {
- t = &s->timer[i];
+ t = &s->timer[i];
+ if (value & 0xf && t->limit > 0) {
ptimer_set_limit(t->ptimer, t->limit, 0);
ptimer_set_freq(t->ptimer, t->freq);
ptimer_run(t->ptimer, 0);
+ } else {
+ ptimer_stop(t->ptimer);
}
value >>= 4;
}
break;
case MP_BOARD_RESET:
- if (value == MP_BOARD_RESET_MAGIC)
+ if (value == MP_BOARD_RESET_MAGIC) {
qemu_system_reset_request();
+ }
break;
}
}
+static void mv88w8618_pit_reset(DeviceState *d)
+{
+ mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
+ sysbus_from_qdev(d));
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ ptimer_stop(s->timer[i].ptimer);
+ s->timer[i].limit = 0;
+ }
+}
+
static CPUReadMemoryFunc * const mv88w8618_pit_readfn[] = {
mv88w8618_pit_read,
mv88w8618_pit_read,
@@ -783,6 +881,38 @@ static int mv88w8618_pit_init(SysBusDevice *dev)
return 0;
}
+static const VMStateDescription mv88w8618_timer_vmsd = {
+ .name = "timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PTIMER(ptimer, mv88w8618_timer_state),
+ VMSTATE_UINT32(limit, mv88w8618_timer_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription mv88w8618_pit_vmsd = {
+ .name = "mv88w8618_pit",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1,
+ mv88w8618_timer_vmsd, mv88w8618_timer_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo mv88w8618_pit_info = {
+ .init = mv88w8618_pit_init,
+ .qdev.name = "mv88w8618_pit",
+ .qdev.size = sizeof(mv88w8618_pit_state),
+ .qdev.reset = mv88w8618_pit_reset,
+ .qdev.vmsd = &mv88w8618_pit_vmsd,
+};
+
/* Flash config register offsets */
#define MP_FLASHCFG_CFGR0 0x04
@@ -836,11 +966,29 @@ static int mv88w8618_flashcfg_init(SysBusDevice *dev)
s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
iomemtype = cpu_register_io_memory(mv88w8618_flashcfg_readfn,
- mv88w8618_flashcfg_writefn, s);
+ mv88w8618_flashcfg_writefn, s);
sysbus_init_mmio(dev, MP_FLASHCFG_SIZE, iomemtype);
return 0;
}
+static const VMStateDescription mv88w8618_flashcfg_vmsd = {
+ .name = "mv88w8618_flashcfg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo mv88w8618_flashcfg_info = {
+ .init = mv88w8618_flashcfg_init,
+ .qdev.name = "mv88w8618_flashcfg",
+ .qdev.size = sizeof(mv88w8618_flashcfg_state),
+ .qdev.vmsd = &mv88w8618_flashcfg_vmsd,
+};
+
/* Misc register offsets */
#define MP_MISC_BOARD_REVISION 0x18
@@ -933,16 +1081,19 @@ static int mv88w8618_wlan_init(SysBusDevice *dev)
#define MP_GPIO_OE_LO 0x008
#define MP_GPIO_OUT_LO 0x00c
#define MP_GPIO_IN_LO 0x010
+#define MP_GPIO_IER_LO 0x014
+#define MP_GPIO_IMR_LO 0x018
#define MP_GPIO_ISR_LO 0x020
#define MP_GPIO_OE_HI 0x508
#define MP_GPIO_OUT_HI 0x50c
#define MP_GPIO_IN_HI 0x510
+#define MP_GPIO_IER_HI 0x514
+#define MP_GPIO_IMR_HI 0x518
#define MP_GPIO_ISR_HI 0x520
/* GPIO bits & masks */
#define MP_GPIO_LCD_BRIGHTNESS 0x00070000
#define MP_GPIO_I2C_DATA_BIT 29
-#define MP_GPIO_I2C_DATA (1 << MP_GPIO_I2C_DATA_BIT)
#define MP_GPIO_I2C_CLOCK_BIT 30
/* LCD brightness bits in GPIO_OE_HI */
@@ -953,12 +1104,11 @@ typedef struct musicpal_gpio_state {
uint32_t lcd_brightness;
uint32_t out_state;
uint32_t in_state;
+ uint32_t ier;
+ uint32_t imr;
uint32_t isr;
- uint32_t i2c_read_data;
- uint32_t key_released;
- uint32_t keys_event; /* store the received key event */
qemu_irq irq;
- qemu_irq out[5];
+ qemu_irq out[5]; /* 3 brightness out + 2 lcd (data and clock ) */
} musicpal_gpio_state;
static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
@@ -1001,57 +1151,31 @@ static void musicpal_gpio_brightness_update(musicpal_gpio_state *s) {
}
/* set lcd brightness GPIOs */
- for (i = 0; i <= 2; i++)
+ for (i = 0; i <= 2; i++) {
qemu_set_irq(s->out[i], (brightness >> i) & 1);
+ }
}
-static void musicpal_gpio_keys_update(musicpal_gpio_state *s)
-{
- int gpio_mask = 0;
-
- /* transform the key state for GPIO usage */
- gpio_mask |= (s->keys_event & 15) << 8;
- gpio_mask |= ((s->keys_event >> 4) & 15) << 19;
-
- /* update GPIO state */
- if (s->key_released) {
- s->in_state |= gpio_mask;
- } else {
- s->in_state &= ~gpio_mask;
- s->isr = gpio_mask;
- qemu_irq_raise(s->irq);
- }
-}
-
-static void musicpal_gpio_irq(void *opaque, int irq, int level)
+static void musicpal_gpio_pin_event(void *opaque, int pin, int level)
{
- musicpal_gpio_state *s = (musicpal_gpio_state *) opaque;
-
- if (irq == 10) {
- s->i2c_read_data = level;
+ musicpal_gpio_state *s = opaque;
+ uint32_t mask = 1 << pin;
+ uint32_t delta = level << pin;
+ uint32_t old = s->in_state & mask;
+
+ s->in_state &= ~mask;
+ s->in_state |= delta;
+
+ if ((old ^ delta) &&
+ ((level && (s->imr & mask)) || (!level && (s->ier & mask)))) {
+ s->isr = mask;
+ qemu_irq_raise(s->irq);
}
-
- /* receives keys bits */
- if (irq <= 7) {
- s->keys_event &= ~(1 << irq);
- s->keys_event |= level << irq;
- return;
- }
-
- /* receives key press/release */
- if (irq == 8) {
- s->key_released = level;
- return;
- }
-
- /* a key has been transmited */
- if (irq == 9 && level == 1)
- musicpal_gpio_keys_update(s);
}
static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset)
{
- musicpal_gpio_state *s = (musicpal_gpio_state *) opaque;
+ musicpal_gpio_state *s = opaque;
switch (offset) {
case MP_GPIO_OE_HI: /* used for LCD brightness control */
@@ -1065,11 +1189,18 @@ static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset)
case MP_GPIO_IN_LO:
return s->in_state & 0xFFFF;
case MP_GPIO_IN_HI:
- /* Update received I2C data */
- s->in_state = (s->in_state & ~MP_GPIO_I2C_DATA) |
- (s->i2c_read_data << MP_GPIO_I2C_DATA_BIT);
return s->in_state >> 16;
+ case MP_GPIO_IER_LO:
+ return s->ier & 0xFFFF;
+ case MP_GPIO_IER_HI:
+ return s->ier >> 16;
+
+ case MP_GPIO_IMR_LO:
+ return s->imr & 0xFFFF;
+ case MP_GPIO_IMR_HI:
+ return s->imr >> 16;
+
case MP_GPIO_ISR_LO:
return s->isr & 0xFFFF;
case MP_GPIO_ISR_HI:
@@ -1083,7 +1214,7 @@ static uint32_t musicpal_gpio_read(void *opaque, target_phys_addr_t offset)
static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
- musicpal_gpio_state *s = (musicpal_gpio_state *) opaque;
+ musicpal_gpio_state *s = opaque;
switch (offset) {
case MP_GPIO_OE_HI: /* used for LCD brightness control */
s->lcd_brightness = (s->lcd_brightness & MP_GPIO_LCD_BRIGHTNESS) |
@@ -1103,6 +1234,19 @@ static void musicpal_gpio_write(void *opaque, target_phys_addr_t offset,
qemu_set_irq(s->out[4], (s->out_state >> MP_GPIO_I2C_CLOCK_BIT) & 1);
break;
+ case MP_GPIO_IER_LO:
+ s->ier = (s->ier & 0xFFFF0000) | (value & 0xFFFF);
+ break;
+ case MP_GPIO_IER_HI:
+ s->ier = (s->ier & 0xFFFF) | (value << 16);
+ break;
+
+ case MP_GPIO_IMR_LO:
+ s->imr = (s->imr & 0xFFFF0000) | (value & 0xFFFF);
+ break;
+ case MP_GPIO_IMR_HI:
+ s->imr = (s->imr & 0xFFFF) | (value << 16);
+ break;
}
}
@@ -1118,12 +1262,16 @@ static CPUWriteMemoryFunc * const musicpal_gpio_writefn[] = {
musicpal_gpio_write,
};
-static void musicpal_gpio_reset(musicpal_gpio_state *s)
+static void musicpal_gpio_reset(DeviceState *d)
{
+ musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
+ sysbus_from_qdev(d));
+
+ s->lcd_brightness = 0;
+ s->out_state = 0;
s->in_state = 0xffffffff;
- s->i2c_read_data = 1;
- s->key_released = 0;
- s->keys_event = 0;
+ s->ier = 0;
+ s->imr = 0;
s->isr = 0;
}
@@ -1138,16 +1286,39 @@ static int musicpal_gpio_init(SysBusDevice *dev)
musicpal_gpio_writefn, s);
sysbus_init_mmio(dev, MP_GPIO_SIZE, iomemtype);
- musicpal_gpio_reset(s);
+ musicpal_gpio_reset(&dev->qdev);
+
+ qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
- /* 3 brightness out + 2 lcd (data and clock ) */
- qdev_init_gpio_out(&dev->qdev, s->out, 5);
- /* 10 gpio button input + 1 I2C data input */
- qdev_init_gpio_in(&dev->qdev, musicpal_gpio_irq, 11);
+ qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
return 0;
}
+static const VMStateDescription musicpal_gpio_vmsd = {
+ .name = "musicpal_gpio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state),
+ VMSTATE_UINT32(out_state, musicpal_gpio_state),
+ VMSTATE_UINT32(in_state, musicpal_gpio_state),
+ VMSTATE_UINT32(ier, musicpal_gpio_state),
+ VMSTATE_UINT32(imr, musicpal_gpio_state),
+ VMSTATE_UINT32(isr, musicpal_gpio_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo musicpal_gpio_info = {
+ .init = musicpal_gpio_init,
+ .qdev.name = "musicpal_gpio",
+ .qdev.size = sizeof(musicpal_gpio_state),
+ .qdev.reset = musicpal_gpio_reset,
+ .qdev.vmsd = &musicpal_gpio_vmsd,
+};
+
/* Keyboard codes & masks */
#define KEY_RELEASED 0x80
#define KEY_CODE 0x7f
@@ -1163,7 +1334,7 @@ static int musicpal_gpio_init(SysBusDevice *dev)
#define KEYCODE_LEFT 0x4b
#define KEYCODE_RIGHT 0x4d
-#define MP_KEY_WHEEL_VOL (1)
+#define MP_KEY_WHEEL_VOL (1 << 0)
#define MP_KEY_WHEEL_VOL_INV (1 << 1)
#define MP_KEY_WHEEL_NAV (1 << 2)
#define MP_KEY_WHEEL_NAV_INV (1 << 3)
@@ -1175,13 +1346,13 @@ static int musicpal_gpio_init(SysBusDevice *dev)
typedef struct musicpal_key_state {
SysBusDevice busdev;
uint32_t kbd_extended;
- uint32_t keys_state;
- qemu_irq out[10];
+ uint32_t pressed_keys;
+ qemu_irq out[8];
} musicpal_key_state;
static void musicpal_key_event(void *opaque, int keycode)
{
- musicpal_key_state *s = (musicpal_key_state *) opaque;
+ musicpal_key_state *s = opaque;
uint32_t event = 0;
int i;
@@ -1190,7 +1361,7 @@ static void musicpal_key_event(void *opaque, int keycode)
return;
}
- if (s->kbd_extended)
+ if (s->kbd_extended) {
switch (keycode & KEY_CODE) {
case KEYCODE_UP:
event = MP_KEY_WHEEL_NAV | MP_KEY_WHEEL_NAV_INV;
@@ -1208,7 +1379,7 @@ static void musicpal_key_event(void *opaque, int keycode)
event = MP_KEY_WHEEL_VOL;
break;
}
- else {
+ } else {
switch (keycode & KEY_CODE) {
case KEYCODE_F:
event = MP_KEY_BTN_FAVORITS;
@@ -1227,27 +1398,30 @@ static void musicpal_key_event(void *opaque, int keycode)
break;
}
/* Do not repeat already pressed buttons */
- if (!(keycode & KEY_RELEASED) && !(s->keys_state & event))
+ if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
event = 0;
+ }
}
if (event) {
-
- /* transmit key event on GPIOS */
- for (i = 0; i <= 7; i++)
- qemu_set_irq(s->out[i], (event >> i) & 1);
-
- /* handle key press/release */
+ /* Raise GPIO pin first if repeating a key */
+ if (!(keycode & KEY_RELEASED) && (s->pressed_keys & event)) {
+ for (i = 0; i <= 7; i++) {
+ if (event & (1 << i)) {
+ qemu_set_irq(s->out[i], 1);
+ }
+ }
+ }
+ for (i = 0; i <= 7; i++) {
+ if (event & (1 << i)) {
+ qemu_set_irq(s->out[i], !!(keycode & KEY_RELEASED));
+ }
+ }
if (keycode & KEY_RELEASED) {
- s->keys_state |= event;
- qemu_irq_raise(s->out[8]);
+ s->pressed_keys &= ~event;
} else {
- s->keys_state &= ~event;
- qemu_irq_lower(s->out[8]);
+ s->pressed_keys |= event;
}
-
- /* signal that a key event occured */
- qemu_irq_pulse(s->out[9]);
}
s->kbd_extended = 0;
@@ -1260,16 +1434,34 @@ static int musicpal_key_init(SysBusDevice *dev)
sysbus_init_mmio(dev, 0x0, 0);
s->kbd_extended = 0;
- s->keys_state = 0;
+ s->pressed_keys = 0;
- /* 8 key event GPIO + 1 key press/release + 1 strobe */
- qdev_init_gpio_out(&dev->qdev, s->out, 10);
+ qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
qemu_add_kbd_event_handler(musicpal_key_event, s);
return 0;
}
+static const VMStateDescription musicpal_key_vmsd = {
+ .name = "musicpal_key",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(kbd_extended, musicpal_key_state),
+ VMSTATE_UINT32(pressed_keys, musicpal_key_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo musicpal_key_info = {
+ .init = musicpal_key_init,
+ .qdev.name = "musicpal_key",
+ .qdev.size = sizeof(musicpal_key_state),
+ .qdev.vmsd = &musicpal_key_vmsd,
+};
+
static struct arm_boot_info musicpal_binfo = {
.loader_start = 0x0,
.board_id = 0x20e,
@@ -1297,9 +1489,9 @@ static void musicpal_init(ram_addr_t ram_size,
DriveInfo *dinfo;
ram_addr_t sram_off;
- if (!cpu_model)
+ if (!cpu_model) {
cpu_model = "arm926";
-
+ }
env = cpu_init(cpu_model);
if (!env) {
fprintf(stderr, "Unable to find CPU definition\n");
@@ -1323,12 +1515,14 @@ static void musicpal_init(ram_addr_t ram_size,
pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
pic[MP_TIMER4_IRQ], NULL);
- if (serial_hds[0])
+ if (serial_hds[0]) {
serial_mm_init(MP_UART1_BASE, 2, pic[MP_UART1_IRQ], 1825000,
serial_hds[0], 1);
- if (serial_hds[1])
+ }
+ if (serial_hds[1]) {
serial_mm_init(MP_UART2_BASE, 2, pic[MP_UART2_IRQ], 1825000,
serial_hds[1], 1);
+ }
/* Register flash */
dinfo = drive_get(IF_PFLASH, 0, 0);
@@ -1373,17 +1567,22 @@ static void musicpal_init(ram_addr_t ram_size,
key_dev = sysbus_create_simple("musicpal_key", 0, NULL);
/* I2C read data */
- qdev_connect_gpio_out(i2c_dev, 0, qdev_get_gpio_in(dev, 10));
+ qdev_connect_gpio_out(i2c_dev, 0,
+ qdev_get_gpio_in(dev, MP_GPIO_I2C_DATA_BIT));
/* I2C data */
qdev_connect_gpio_out(dev, 3, qdev_get_gpio_in(i2c_dev, 0));
/* I2C clock */
qdev_connect_gpio_out(dev, 4, qdev_get_gpio_in(i2c_dev, 1));
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++) {
qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(lcd_dev, i));
-
- for (i = 0; i < 10; i++)
- qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i));
+ }
+ for (i = 0; i < 4; i++) {
+ qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 8));
+ }
+ for (i = 4; i < 8; i++) {
+ qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
+ }
#ifdef HAS_AUDIO
wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
@@ -1417,22 +1616,15 @@ machine_init(musicpal_machine_init);
static void musicpal_register_devices(void)
{
- sysbus_register_dev("mv88w8618_pic", sizeof(mv88w8618_pic_state),
- mv88w8618_pic_init);
- sysbus_register_dev("mv88w8618_pit", sizeof(mv88w8618_pit_state),
- mv88w8618_pit_init);
- sysbus_register_dev("mv88w8618_flashcfg", sizeof(mv88w8618_flashcfg_state),
- mv88w8618_flashcfg_init);
- sysbus_register_dev("mv88w8618_eth", sizeof(mv88w8618_eth_state),
- mv88w8618_eth_init);
+ sysbus_register_withprop(&mv88w8618_pic_info);
+ sysbus_register_withprop(&mv88w8618_pit_info);
+ sysbus_register_withprop(&mv88w8618_flashcfg_info);
+ sysbus_register_withprop(&mv88w8618_eth_info);
sysbus_register_dev("mv88w8618_wlan", sizeof(SysBusDevice),
mv88w8618_wlan_init);
- sysbus_register_dev("musicpal_lcd", sizeof(musicpal_lcd_state),
- musicpal_lcd_init);
- sysbus_register_dev("musicpal_gpio", sizeof(musicpal_gpio_state),
- musicpal_gpio_init);
- sysbus_register_dev("musicpal_key", sizeof(musicpal_key_state),
- musicpal_key_init);
+ sysbus_register_withprop(&musicpal_lcd_info);
+ sysbus_register_withprop(&musicpal_gpio_info);
+ sysbus_register_withprop(&musicpal_key_info);
}
device_init(musicpal_register_devices)
diff --git a/qemu/hw/pci-hotplug.c b/qemu/hw/pci-hotplug.c
index f3dc4210..89974a06 100644
--- a/qemu/hw/pci-hotplug.c
+++ b/qemu/hw/pci-hotplug.c
@@ -46,6 +46,10 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
monitor_printf(mon, "Parameter addr not supported\n");
return NULL;
}
+
+ if (nd_table[ret].model && !pci_nic_supported(nd_table[ret].model))
+ return NULL;
+
return pci_nic_init(&nd_table[ret], "rtl8139", devaddr);
}
diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c
index 314c2d0f..46429634 100644
--- a/qemu/hw/pci.c
+++ b/qemu/hw/pci.c
@@ -806,6 +806,17 @@ static const char * const pci_nic_names[] = {
NULL
};
+int pci_nic_supported(const char *model)
+{
+ int i;
+
+ for (i = 0; pci_nic_names[i]; i++)
+ if (strcmp(model, pci_nic_names[i]) == 0)
+ return 1;
+
+ return 0;
+}
+
/* Initialize a PCI NIC. */
PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
const char *default_devaddr)
diff --git a/qemu/hw/pci.h b/qemu/hw/pci.h
index caba5c85..ba748ff9 100644
--- a/qemu/hw/pci.h
+++ b/qemu/hw/pci.h
@@ -252,6 +252,7 @@ PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int devfn_min, int nirq);
+int pci_nic_supported(const char *model);
PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
const char *default_devaddr);
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
diff --git a/qemu/kvm-all.c b/qemu/kvm-all.c
index 7dcc5531..5ea0dd8b 100644
--- a/qemu/kvm-all.c
+++ b/qemu/kvm-all.c
@@ -905,11 +905,15 @@ void kvm_setup_guest_memory(void *start, size_t size)
#ifdef KVM_CAP_SET_GUEST_DEBUG
static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
{
+#ifdef CONFIG_IOTHREAD
if (env == cpu_single_env) {
func(data);
return;
}
abort();
+#else
+ func(data);
+#endif
}
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
@@ -938,7 +942,13 @@ struct kvm_set_guest_debug_data {
static void kvm_invoke_set_guest_debug(void *data)
{
struct kvm_set_guest_debug_data *dbg_data = data;
- dbg_data->err = kvm_vcpu_ioctl(dbg_data->env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
+ CPUState *env = dbg_data->env;
+
+ if (env->kvm_state->regs_modified) {
+ kvm_arch_put_registers(env);
+ env->kvm_state->regs_modified = 0;
+ }
+ dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
}
int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
diff --git a/qemu/microblaze-dis.c b/qemu/microblaze-dis.c
index 6144334e..016b25e8 100644
--- a/qemu/microblaze-dis.c
+++ b/qemu/microblaze-dis.c
@@ -543,7 +543,7 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
unsigned long inst, prev_inst;
struct op_code_struct * op, *pop;
int immval = 0;
- boolean immfound = false;
+ bfd_boolean immfound = false;
static bfd_vma prev_insn_addr = -1; /*init the prev insn addr */
static int prev_insn_vma = -1; /*init the prev insn vma */
int curr_insn_vma = info->buffer_vma;
diff --git a/qemu/net.c b/qemu/net.c
index 2686f78b..bcc51763 100644
--- a/qemu/net.c
+++ b/qemu/net.c
@@ -2803,8 +2803,13 @@ void net_client_uninit(NICInfo *nd)
{
nd->vlan->nb_guest_devs--;
nb_nics--;
- nd->used = 0;
- free((void *)nd->model);
+
+ qemu_free((void *)nd->model);
+ qemu_free((void *)nd->name);
+ qemu_free((void *)nd->devaddr);
+ qemu_free((void *)nd->id);
+
+ memset(nd, 0, sizeof(*nd));
}
static int net_host_check_device(const char *device)
diff --git a/qemu/qemu-common.h b/qemu/qemu-common.h
index e407cac4..eda4fea4 100644
--- a/qemu/qemu-common.h
+++ b/qemu/qemu-common.h
@@ -121,6 +121,8 @@ typedef signed int ssize_t;
// more posixyness
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
+
+int gettimeofday(struct timeval* tp, struct timezone* tzp);
#endif
#endif // end MSVC sections
diff --git a/qemu/qemu-config.c b/qemu/qemu-config.c
index 555c7ba0..785b1468 100644
--- a/qemu/qemu-config.c
+++ b/qemu/qemu-config.c
@@ -151,6 +151,26 @@ QemuOptsList qemu_device_opts = {
},
};
+QemuOptsList qemu_rtc_opts = {
+ .name = "rtc",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
+ .desc = {
+ {
+ .name = "base",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "clock",
+ .type = QEMU_OPT_STRING,
+#ifdef TARGET_I386
+ },{
+ .name = "driftfix",
+ .type = QEMU_OPT_STRING,
+#endif
+ },
+ { /* end if list */ }
+ },
+};
+
static QemuOptsList *lists[] = {
&qemu_drive_opts,
&qemu_chardev_opts,
diff --git a/qemu/qemu-config.h b/qemu/qemu-config.h
index 13b0f193..4ae7b74f 100644
--- a/qemu/qemu-config.h
+++ b/qemu/qemu-config.h
@@ -4,6 +4,7 @@
extern QemuOptsList qemu_drive_opts;
extern QemuOptsList qemu_chardev_opts;
extern QemuOptsList qemu_device_opts;
+extern QemuOptsList qemu_rtc_opts;
int qemu_set_option(const char *str);
diff --git a/qemu/qemu-monitor.h b/qemu/qemu-monitor.h
index 36792961..3152caa2 100644
--- a/qemu/qemu-monitor.h
+++ b/qemu/qemu-monitor.h
@@ -2,7 +2,7 @@
{ "help|?", "name:s?", do_help_cmd, "[cmd]", "show the help" },
-{ "commit", "device:s", do_commit,
+{ "commit", "device:B", do_commit,
"device|all", "commit changes to the disk images (if -snapshot is used) or backing files" },
{ "info", "item:s?", do_info,
@@ -93,7 +93,7 @@
"index", "set which mouse device receives events" },
#ifdef HAS_AUDIO
-{ "wavcapture", "path:s,freq:i?,bits:i?,nchannels:i?", do_wav_capture,
+{ "wavcapture", "path:F,freq:i?,bits:i?,nchannels:i?", do_wav_capture,
"path [frequency [bits [channels]]]",
"capture audio to a wave file (default frequency=44100 bits=16 channels=2)" },
#endif
diff --git a/qemu/qemu-options.h b/qemu/qemu-options.h
index 00f940b4..6a7bbc28 100644
--- a/qemu/qemu-options.h
+++ b/qemu/qemu-options.h
@@ -168,8 +168,7 @@ DEF("win2k-hack", 0, QEMU_OPTION_win2k_hack,
#endif
#ifdef TARGET_I386
-DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack,
-"-rtc-td-hack use it to fix time drift in Windows ACPI HAL\n")
+DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "")
#endif
#ifdef TARGET_I386
@@ -307,6 +306,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
// END HEAVILY MODIFIED SECTION
+
DEF("bt", HAS_ARG, QEMU_OPTION_bt, \
"\n" \
"-bt hci,null dumb bluetooth HCI - doesn't respond to commands\n" \
@@ -416,11 +416,19 @@ DEF("clock", HAS_ARG, QEMU_OPTION_clock, \
"-clock force the use of the given methods for timer alarm.\n" \
" To see what timers are available use -clock ?\n")
-DEF("localtime", 0, QEMU_OPTION_localtime, \
-"-localtime set the real time clock to local time [default=utc]\n")
+DEF("localtime", 0, QEMU_OPTION_localtime, "")
+DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "")
+
+#ifdef TARGET_I386
+DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
+"-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]\n" \
+" set the RTC base and clock, enable drift fix for clock ticks\n")
+#else
+DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
+"-rtc [base=utc|localtime|date][,clock=host|vm]\n" \
+" set the RTC base and clock\n")
+#endif
-DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, \
-"-startdate select initial date of the clock\n")
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
"-icount [N|auto]\n" \
diff --git a/qemu/qemu-options.hx b/qemu/qemu-options.hx
index d3aa55b6..f21e9f9d 100644
--- a/qemu/qemu-options.hx
+++ b/qemu/qemu-options.hx
@@ -681,15 +681,9 @@ slows down the IDE transfers).
ETEXI
#ifdef TARGET_I386
-DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack,
- "-rtc-td-hack use it to fix time drift in Windows ACPI HAL\n")
+HXCOMM Deprecated by -rtc
+DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "")
#endif
-STEXI
-@item -rtc-td-hack
-Use it if you experience time drift problem in Windows with ACPI HAL.
-This option will try to figure out how many timer interrupts were not
-processed by the Windows guest and will re-inject them.
-ETEXI
#ifdef TARGET_I386
DEF("no-fd-bootchk", 0, QEMU_OPTION_no_fd_bootchk,
@@ -1500,23 +1494,38 @@ Force the use of the given methods for timer alarm. To see what timers
are available use -clock ?.
ETEXI
-DEF("localtime", 0, QEMU_OPTION_localtime, \
- "-localtime set the real time clock to local time [default=utc]\n")
-STEXI
-@item -localtime
-Set the real time clock to local time (the default is to UTC
-time). This option is needed to have correct date in MS-DOS or
-Windows.
-ETEXI
+HXCOMM Options deprecated by -rtc
+DEF("localtime", 0, QEMU_OPTION_localtime, "")
+DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, "")
+
+#ifdef TARGET_I386
+DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
+ "-rtc [base=utc|localtime|date][,clock=host|vm][,driftfix=none|slew]\n" \
+ " set the RTC base and clock, enable drift fix for clock ticks\n")
+#else
+DEF("rtc", HAS_ARG, QEMU_OPTION_rtc, \
+ "-rtc [base=utc|localtime|date][,clock=host|vm]\n" \
+ " set the RTC base and clock\n")
+#endif
-DEF("startdate", HAS_ARG, QEMU_OPTION_startdate, \
- "-startdate select initial date of the clock\n")
STEXI
-@item -startdate @var{date}
-Set the initial date of the real time clock. Valid formats for
-@var{date} are: @code{now} or @code{2006-06-17T16:01:21} or
-@code{2006-06-17}. The default value is @code{now}.
+@item -rtc [base=utc|localtime|@var{date}][,clock=host|vm][,driftfix=none|slew]
+Specify @option{base} as @code{utc} or @code{localtime} to let the RTC start at the current
+UTC or local time, respectively. @code{localtime} is required for correct date in
+MS-DOS or Windows. To start at a specific point in time, provide @var{date} in the
+format @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default base is UTC.
+
+By default the RTC is driven by the host system time. This allows to use the
+RTC as accurate reference clock inside the guest, specifically if the host
+time is smoothly following an accurate external reference clock, e.g. via NTP.
+If you want to isolate the guest time from the host, even prevent it from
+progressing during suspension, you can set @option{clock} to @code{vm} instead.
+
+Enable @option{driftfix} (i386 targets only) if you experience time drift problems,
+specifically with Windows' ACPI HAL. This option will try to figure out how
+many timer interrupts were not processed by the Windows guest and will
+re-inject them.
ETEXI
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
diff --git a/qemu/qemu-timer.h b/qemu/qemu-timer.h
index e44c3342..e7eaa043 100644
--- a/qemu/qemu-timer.h
+++ b/qemu/qemu-timer.h
@@ -17,6 +17,13 @@ extern QEMUClock *rt_clock;
precision clock, usually cpu cycles (use ticks_per_sec). */
extern QEMUClock *vm_clock;
+/* The host clock should be use for device models that emulate accurate
+ real time sources. It will continue to run when the virtual machine
+ is suspended, and it will reflect system time changes the host may
+ undergo (e.g. due to NTP). The host clock has the same precision as
+ the virtual clock. */
+extern QEMUClock *host_clock;
+
int64_t qemu_get_clock(QEMUClock *clock);
QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque);
diff --git a/qemu/savevm.c b/qemu/savevm.c
index da6bd24c..d817de58 100644
--- a/qemu/savevm.c
+++ b/qemu/savevm.c
@@ -1056,7 +1056,10 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
return ret;
}
while(field->name) {
- if (field->version_id <= version_id) {
+ if ((field->field_exists &&
+ field->field_exists(opaque, version_id)) ||
+ (!field->field_exists &&
+ field->version_id <= version_id)) {
void *base_addr = (char *)opaque + field->offset;
int ret, i, n_elems = 1;
@@ -1072,7 +1075,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *addr = (char *)base_addr + field->size * i;
if (field->flags & VMS_ARRAY_OF_POINTER) {
- addr = *(void**)addr;
+ addr = *(void **)addr;
}
if (field->flags & VMS_STRUCT) {
ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id);
@@ -1101,25 +1104,28 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
if (vmsd->pre_save) {
vmsd->pre_save(opaque);
}
- while(field->name) {
- void *base_addr = (char *)opaque + field->offset;
- int i, n_elems = 1;
+ while (field->name) {
+ if (!field->field_exists ||
+ field->field_exists(opaque, vmsd->version_id)) {
+ void* base_addr = (char *)opaque + field->offset;
+ int i, n_elems = 1;
- if (field->flags & VMS_ARRAY) {
- n_elems = field->num;
- } else if (field->flags & VMS_VARRAY) {
+ if (field->flags & VMS_ARRAY) {
+ n_elems = field->num;
+ } else if (field->flags & VMS_VARRAY) {
n_elems = *(size_t *)((char *)opaque+field->num_offset);
- }
- if (field->flags & VMS_POINTER) {
- base_addr = *(void **)base_addr;
- }
- for (i = 0; i < n_elems; i++) {
+ }
+ if (field->flags & VMS_POINTER) {
+ base_addr = *(void **)base_addr;
+ }
+ for (i = 0; i < n_elems; i++) {
void *addr = (char *)base_addr + field->size * i;
- if (field->flags & VMS_STRUCT) {
- vmstate_save_state(f, field->vmsd, addr);
- } else {
- field->info->put(f, addr, field->size);
+ if (field->flags & VMS_STRUCT) {
+ vmstate_save_state(f, field->vmsd, addr);
+ } else {
+ field->info->put(f, addr, field->size);
+ }
}
}
field++;
diff --git a/qemu/sysemu.h b/qemu/sysemu.h
index 9d99e413..da087baf 100644
--- a/qemu/sysemu.h
+++ b/qemu/sysemu.h
@@ -5,6 +5,7 @@
#include "qemu-common.h"
#include "qemu-option.h"
#include "qemu-queue.h"
+#include "qemu-timer.h"
#include "qdict.h"
#ifdef _WIN32
@@ -137,6 +138,7 @@ extern int no_quit;
extern int semihosting_enabled;
extern int old_param;
extern int boot_menu;
+extern QEMUClock *rtc_clock;
#define MAX_NODES 64
extern int nb_numa_nodes;
diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h
index a9c0e0b9..d35ca925 100644
--- a/qemu/target-i386/cpu.h
+++ b/qemu/target-i386/cpu.h
@@ -583,10 +583,13 @@ typedef struct {
uint64_t mask;
} MTRRVar;
+#define CPU_NB_REGS64 16
+#define CPU_NB_REGS32 8
+
#ifdef TARGET_X86_64
-#define CPU_NB_REGS 16
+#define CPU_NB_REGS CPU_NB_REGS64
#else
-#define CPU_NB_REGS 8
+#define CPU_NB_REGS CPU_NB_REGS32
#endif
#define NB_MMU_MODES 2
diff --git a/qemu/target-i386/machine.c b/qemu/target-i386/machine.c
index e59b4ebe..c0082098 100644
--- a/qemu/target-i386/machine.c
+++ b/qemu/target-i386/machine.c
@@ -21,16 +21,302 @@ static const VMStateDescription vmstate_segment = {
}
};
-static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
+#define VMSTATE_SEGMENT(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(SegmentCache), \
+ .vmsd = &vmstate_segment, \
+ .flags = VMS_STRUCT, \
+ .offset = offsetof(_state, _field) \
+ + type_check(SegmentCache,typeof_field(_state, _field)) \
+}
+
+#define VMSTATE_SEGMENT_ARRAY(_field, _state, _n) \
+ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_segment, SegmentCache)
+
+static const VMStateDescription vmstate_xmm_reg = {
+ .name = "xmm_reg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64(XMM_Q(0), XMMReg),
+ VMSTATE_UINT64(XMM_Q(1), XMMReg),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+#define VMSTATE_XMM_REGS(_field, _state, _n) \
+ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_xmm_reg, XMMReg)
+
+static const VMStateDescription vmstate_mtrr_var = {
+ .name = "mtrr_var",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64(base, MTRRVar),
+ VMSTATE_UINT64(mask, MTRRVar),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+#define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \
+ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
+
+static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
+{
+ fprintf(stderr, "call put_fpreg() with invalid arguments\n");
+ exit(0);
+}
+
+#ifdef USE_X86LDOUBLE
+/* XXX: add that in a FPU generic layer */
+union x86_longdouble {
+ uint64_t mant;
+ uint16_t exp;
+};
+
+#define MANTD1(fp) (fp & ((1LL << 52) - 1))
+#define EXPBIAS1 1023
+#define EXPD1(fp) ((fp >> 52) & 0x7FF)
+#define SIGND1(fp) ((fp >> 32) & 0x80000000)
+
+static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
+{
+ int e;
+ /* mantissa */
+ p->mant = (MANTD1(temp) << 11) | (1LL << 63);
+ /* exponent + sign */
+ e = EXPD1(temp) - EXPBIAS1 + 16383;
+ e |= SIGND1(temp) >> 16;
+ p->exp = e;
+}
+
+static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+ uint64_t mant;
+ uint16_t exp;
+
+ qemu_get_be64s(f, &mant);
+ qemu_get_be16s(f, &exp);
+ fp_reg->d = cpu_set_fp80(mant, exp);
+ return 0;
+}
+
+static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+ uint64_t mant;
+ uint16_t exp;
+ /* we save the real CPU data (in case of MMX usage only 'mant'
+ contains the MMX register */
+ cpu_get_fp80(&mant, &exp, fp_reg->d);
+ qemu_put_be64s(f, &mant);
+ qemu_put_be16s(f, &exp);
+}
+
+const VMStateInfo vmstate_fpreg = {
+ .name = "fpreg",
+ .get = get_fpreg,
+ .put = put_fpreg,
+};
+
+static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+ union x86_longdouble *p = opaque;
+ uint64_t mant;
+
+ qemu_get_be64s(f, &mant);
+ p->mant = mant;
+ p->exp = 0xffff;
+ return 0;
+}
+
+const VMStateInfo vmstate_fpreg_1_mmx = {
+ .name = "fpreg_1_mmx",
+ .get = get_fpreg_1_mmx,
+ .put = put_fpreg_error,
+};
+
+static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+ union x86_longdouble *p = opaque;
+ uint64_t mant;
+
+ qemu_get_be64s(f, &mant);
+ fp64_to_fp80(p, mant);
+ return 0;
+}
+
+const VMStateInfo vmstate_fpreg_1_no_mmx = {
+ .name = "fpreg_1_no_mmx",
+ .get = get_fpreg_1_no_mmx,
+ .put = put_fpreg_error,
+};
+
+static bool fpregs_is_0(void *opaque, int version_id)
+{
+ CPUState *env = opaque;
+
+ return (env->fpregs_format_vmstate == 0);
+}
+
+static bool fpregs_is_1_mmx(void *opaque, int version_id)
+{
+ CPUState *env = opaque;
+ int guess_mmx;
+
+ guess_mmx = ((env->fptag_vmstate == 0xff) &&
+ (env->fpus_vmstate & 0x3800) == 0);
+ return (guess_mmx && (env->fpregs_format_vmstate == 1));
+}
+
+static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
+{
+ CPUState *env = opaque;
+ int guess_mmx;
+
+ guess_mmx = ((env->fptag_vmstate == 0xff) &&
+ (env->fpus_vmstate & 0x3800) == 0);
+ return (!guess_mmx && (env->fpregs_format_vmstate == 1));
+}
+
+#define VMSTATE_FP_REGS(_field, _state, _n) \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0, vmstate_fpreg, FPReg), \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_mmx, vmstate_fpreg_1_mmx, FPReg), \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_no_mmx, vmstate_fpreg_1_no_mmx, FPReg)
+
+#else
+static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+
+ qemu_get_be64s(f, &fp_reg->mmx.MMX_Q(0));
+ return 0;
+}
+
+static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+ /* if we use doubles for float emulation, we save the doubles to
+ avoid losing information in case of MMX usage. It can give
+ problems if the image is restored on a CPU where long
+ doubles are used instead. */
+ qemu_put_be64s(f, &fp_reg->mmx.MMX_Q(0));
+}
+
+const VMStateInfo vmstate_fpreg = {
+ .name = "fpreg",
+ .get = get_fpreg,
+ .put = put_fpreg,
+};
+
+static int get_fpreg_0_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+ uint64_t mant;
+ uint16_t exp;
+
+ qemu_get_be64s(f, &mant);
+ qemu_get_be16s(f, &exp);
+ fp_reg->mmx.MMX_Q(0) = mant;
+ return 0;
+}
+
+const VMStateInfo vmstate_fpreg_0_mmx = {
+ .name = "fpreg_0_mmx",
+ .get = get_fpreg_0_mmx,
+ .put = put_fpreg_error,
+};
+
+static int get_fpreg_0_no_mmx(QEMUFile *f, void *opaque, size_t size)
+{
+ FPReg *fp_reg = opaque;
+ uint64_t mant;
+ uint16_t exp;
+
+ qemu_get_be64s(f, &mant);
+ qemu_get_be16s(f, &exp);
+
+ fp_reg->d = cpu_set_fp80(mant, exp);
+ return 0;
+}
+
+const VMStateInfo vmstate_fpreg_0_no_mmx = {
+ .name = "fpreg_0_no_mmx",
+ .get = get_fpreg_0_no_mmx,
+ .put = put_fpreg_error,
+};
+
+static bool fpregs_is_1(void *opaque, int version_id)
+{
+ CPUState *env = opaque;
+
+ return env->fpregs_format_vmstate == 1;
+}
+
+static bool fpregs_is_0_mmx(void *opaque, int version_id)
+{
+ CPUState *env = opaque;
+ int guess_mmx;
+
+ guess_mmx = ((env->fptag_vmstate == 0xff) &&
+ (env->fpus_vmstate & 0x3800) == 0);
+ return guess_mmx && env->fpregs_format_vmstate == 0;
+}
+
+static bool fpregs_is_0_no_mmx(void *opaque, int version_id)
{
- vmstate_save_state(f, &vmstate_segment, dt);
+ CPUState *env = opaque;
+ int guess_mmx;
+
+ guess_mmx = ((env->fptag_vmstate == 0xff) &&
+ (env->fpus_vmstate & 0x3800) == 0);
+ return !guess_mmx && env->fpregs_format_vmstate == 0;
}
-static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
+#define VMSTATE_FP_REGS(_field, _state, _n) \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1, vmstate_fpreg, FPReg), \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0_mmx, vmstate_fpreg_0_mmx, FPReg), \
+ VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0_no_mmx, vmstate_fpreg_0_no_mmx, FPReg)
+
+#endif /* USE_X86LDOUBLE */
+
+static bool version_is_5(void *opaque, int version_id)
{
- vmstate_load_state(f, &vmstate_segment, dt, vmstate_segment.version_id);
+ return version_id == 5;
}
+#ifdef TARGET_X86_64
+static bool less_than_7(void *opaque, int version_id)
+{
+ return version_id < 7;
+}
+
+static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
+{
+ uint64_t *v = pv;
+ *v = qemu_get_be32(f);
+ return 0;
+}
+
+static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
+{
+ uint64_t *v = pv;
+ qemu_put_be32(f, *v);
+}
+
+const VMStateInfo vmstate_hack_uint64_as_uint32 = {
+ .name = "uint64_as_uint32",
+ .get = get_uint64_as_uint32,
+ .put = put_uint64_as_uint32,
+};
+
+#define VMSTATE_HACK_UINT32(_f, _s, _t) \
+ VMSTATE_SINGLE_TEST(_f, _s, _t, vmstate_hack_uint64_as_uint32, uint64_t)
+#endif
+
static void cpu_pre_save(void *opaque)
{
CPUState *env = opaque;
@@ -63,148 +349,6 @@ static void cpu_pre_save(void *opaque)
}
}
-void cpu_save(QEMUFile *f, void *opaque)
-{
- CPUState *env = opaque;
- int i;
-
- cpu_pre_save(opaque);
-
- for(i = 0; i < CPU_NB_REGS; i++)
- qemu_put_betls(f, &env->regs[i]);
- qemu_put_betls(f, &env->eip);
- qemu_put_betls(f, &env->eflags);
- qemu_put_be32s(f, &env->hflags);
-
- /* FPU */
- qemu_put_be16s(f, &env->fpuc);
- qemu_put_be16s(f, &env->fpus_vmstate);
- qemu_put_be16s(f, &env->fptag_vmstate);
-
- qemu_put_be16s(f, &env->fpregs_format_vmstate);
-
- for(i = 0; i < 8; i++) {
-#ifdef USE_X86LDOUBLE
- {
- uint64_t mant;
- uint16_t exp;
- /* we save the real CPU data (in case of MMX usage only 'mant'
- contains the MMX register */
- cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
- qemu_put_be64(f, mant);
- qemu_put_be16(f, exp);
- }
-#else
- /* if we use doubles for float emulation, we save the doubles to
- avoid losing information in case of MMX usage. It can give
- problems if the image is restored on a CPU where long
- doubles are used instead. */
- qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
-#endif
- }
-
- for(i = 0; i < 6; i++)
- cpu_put_seg(f, &env->segs[i]);
- cpu_put_seg(f, &env->ldt);
- cpu_put_seg(f, &env->tr);
- cpu_put_seg(f, &env->gdt);
- cpu_put_seg(f, &env->idt);
-
- qemu_put_be32s(f, &env->sysenter_cs);
- qemu_put_betls(f, &env->sysenter_esp);
- qemu_put_betls(f, &env->sysenter_eip);
-
- qemu_put_betls(f, &env->cr[0]);
- qemu_put_betls(f, &env->cr[2]);
- qemu_put_betls(f, &env->cr[3]);
- qemu_put_betls(f, &env->cr[4]);
-
- for(i = 0; i < 8; i++)
- qemu_put_betls(f, &env->dr[i]);
-
- /* MMU */
- qemu_put_sbe32s(f, &env->a20_mask);
-
- /* XMM */
- qemu_put_be32s(f, &env->mxcsr);
- for(i = 0; i < CPU_NB_REGS; i++) {
- qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
- qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
- }
-
-#ifdef TARGET_X86_64
- qemu_put_be64s(f, &env->efer);
- qemu_put_be64s(f, &env->star);
- qemu_put_be64s(f, &env->lstar);
- qemu_put_be64s(f, &env->cstar);
- qemu_put_be64s(f, &env->fmask);
- qemu_put_be64s(f, &env->kernelgsbase);
-#endif
- qemu_put_be32s(f, &env->smbase);
-
- qemu_put_be64s(f, &env->pat);
- qemu_put_be32s(f, &env->hflags2);
-
- qemu_put_be64s(f, &env->vm_hsave);
- qemu_put_be64s(f, &env->vm_vmcb);
- qemu_put_be64s(f, &env->tsc_offset);
- qemu_put_be64s(f, &env->intercept);
- qemu_put_be16s(f, &env->intercept_cr_read);
- qemu_put_be16s(f, &env->intercept_cr_write);
- qemu_put_be16s(f, &env->intercept_dr_read);
- qemu_put_be16s(f, &env->intercept_dr_write);
- qemu_put_be32s(f, &env->intercept_exceptions);
- qemu_put_8s(f, &env->v_tpr);
-
- /* MTRRs */
- for(i = 0; i < 11; i++)
- qemu_put_be64s(f, &env->mtrr_fixed[i]);
- qemu_put_be64s(f, &env->mtrr_deftype);
- for(i = 0; i < 8; i++) {
- qemu_put_be64s(f, &env->mtrr_var[i].base);
- qemu_put_be64s(f, &env->mtrr_var[i].mask);
- }
-
- /* KVM-related states */
-
- qemu_put_sbe32s(f, &env->pending_irq_vmstate);
- qemu_put_be32s(f, &env->mp_state);
- qemu_put_be64s(f, &env->tsc);
-
- /* MCE */
- qemu_put_be64s(f, &env->mcg_cap);
- qemu_put_be64s(f, &env->mcg_status);
- qemu_put_be64s(f, &env->mcg_ctl);
- for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
- qemu_put_be64s(f, &env->mce_banks[i]);
- }
- qemu_put_be64s(f, &env->tsc_aux);
- }
-
-#ifdef USE_X86LDOUBLE
-/* XXX: add that in a FPU generic layer */
-union x86_longdouble {
- uint64_t mant;
- uint16_t exp;
-};
-
-#define MANTD1(fp) (fp & ((1LL << 52) - 1))
-#define EXPBIAS1 1023
-#define EXPD1(fp) ((fp >> 52) & 0x7FF)
-#define SIGND1(fp) ((fp >> 32) & 0x80000000)
-
-static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
-{
- int e;
- /* mantissa */
- p->mant = (MANTD1(temp) << 11) | (1LL << 63);
- /* exponent + sign */
- e = EXPD1(temp) - EXPBIAS1 + 16383;
- e |= SIGND1(temp) >> 16;
- p->exp = e;
-}
-#endif
-
static int cpu_pre_load(void *opaque)
{
CPUState *env = opaque;
@@ -242,162 +386,104 @@ static int cpu_post_load(void *opaque, int version_id)
return cpu_post_load(env, version_id);
}
-int cpu_load(QEMUFile *f, void *opaque, int version_id)
-{
- CPUState *env = opaque;
- int i, guess_mmx;
-
- cpu_pre_load(env);
-
- if (version_id < 3 || version_id > CPU_SAVE_VERSION)
- return -EINVAL;
- for(i = 0; i < CPU_NB_REGS; i++)
- qemu_get_betls(f, &env->regs[i]);
- qemu_get_betls(f, &env->eip);
- qemu_get_betls(f, &env->eflags);
- qemu_get_be32s(f, &env->hflags);
-
- qemu_get_be16s(f, &env->fpuc);
- qemu_get_be16s(f, &env->fpus_vmstate);
- qemu_get_be16s(f, &env->fptag_vmstate);
- qemu_get_be16s(f, &env->fpregs_format_vmstate);
-
- /* NOTE: we cannot always restore the FPU state if the image come
- from a host with a different 'USE_X86LDOUBLE' define. We guess
- if we are in an MMX state to restore correctly in that case. */
- guess_mmx = ((env->fptag_vmstate == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
- for(i = 0; i < 8; i++) {
- uint64_t mant;
- uint16_t exp;
-
- switch(env->fpregs_format_vmstate) {
- case 0:
- mant = qemu_get_be64(f);
- exp = qemu_get_be16(f);
-#ifdef USE_X86LDOUBLE
- env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#else
- /* difficult case */
- if (guess_mmx)
- env->fpregs[i].mmx.MMX_Q(0) = mant;
- else
- env->fpregs[i].d = cpu_set_fp80(mant, exp);
-#endif
- break;
- case 1:
- mant = qemu_get_be64(f);
-#ifdef USE_X86LDOUBLE
- {
- union x86_longdouble *p;
- /* difficult case */
- p = (void *)&env->fpregs[i];
- if (guess_mmx) {
- p->mant = mant;
- p->exp = 0xffff;
- } else {
- fp64_to_fp80(p, mant);
- }
- }
+const VMStateDescription vmstate_cpu = {
+ .name = "cpu",
+ .version_id = CPU_SAVE_VERSION,
+ .minimum_version_id = 3,
+ .minimum_version_id_old = 3,
+ .pre_save = cpu_pre_save,
+ .pre_load = cpu_pre_load,
+ .post_load = cpu_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINTTL_ARRAY(regs, CPUState, CPU_NB_REGS),
+ VMSTATE_UINTTL(eip, CPUState),
+ VMSTATE_UINTTL(eflags, CPUState),
+ VMSTATE_UINT32(hflags, CPUState),
+ /* FPU */
+ VMSTATE_UINT16(fpuc, CPUState),
+ VMSTATE_UINT16(fpus_vmstate, CPUState),
+ VMSTATE_UINT16(fptag_vmstate, CPUState),
+ VMSTATE_UINT16(fpregs_format_vmstate, CPUState),
+ VMSTATE_FP_REGS(fpregs, CPUState, 8),
+
+ VMSTATE_SEGMENT_ARRAY(segs, CPUState, 6),
+ VMSTATE_SEGMENT(ldt, CPUState),
+ VMSTATE_SEGMENT(tr, CPUState),
+ VMSTATE_SEGMENT(gdt, CPUState),
+ VMSTATE_SEGMENT(idt, CPUState),
+
+ VMSTATE_UINT32(sysenter_cs, CPUState),
+#ifdef TARGET_X86_64
+ /* Hack: In v7 size changed from 32 to 64 bits on x86_64 */
+ VMSTATE_HACK_UINT32(sysenter_esp, CPUState, less_than_7),
+ VMSTATE_HACK_UINT32(sysenter_eip, CPUState, less_than_7),
+ VMSTATE_UINTTL_V(sysenter_esp, CPUState, 7),
+ VMSTATE_UINTTL_V(sysenter_eip, CPUState, 7),
#else
- env->fpregs[i].mmx.MMX_Q(0) = mant;
+ VMSTATE_UINTTL(sysenter_esp, CPUState),
+ VMSTATE_UINTTL(sysenter_eip, CPUState),
#endif
- break;
- default:
- return -EINVAL;
- }
- }
-
- for(i = 0; i < 6; i++)
- cpu_get_seg(f, &env->segs[i]);
- cpu_get_seg(f, &env->ldt);
- cpu_get_seg(f, &env->tr);
- cpu_get_seg(f, &env->gdt);
- cpu_get_seg(f, &env->idt);
-
- qemu_get_be32s(f, &env->sysenter_cs);
- if (version_id >= 7) {
- qemu_get_betls(f, &env->sysenter_esp);
- qemu_get_betls(f, &env->sysenter_eip);
- } else {
- env->sysenter_esp = qemu_get_be32(f);
- env->sysenter_eip = qemu_get_be32(f);
- }
-
- qemu_get_betls(f, &env->cr[0]);
- qemu_get_betls(f, &env->cr[2]);
- qemu_get_betls(f, &env->cr[3]);
- qemu_get_betls(f, &env->cr[4]);
- for(i = 0; i < 8; i++)
- qemu_get_betls(f, &env->dr[i]);
-
- qemu_get_sbe32s(f, &env->a20_mask);
-
- qemu_get_be32s(f, &env->mxcsr);
- for(i = 0; i < CPU_NB_REGS; i++) {
- qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
- qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
- }
+ VMSTATE_UINTTL(cr[0], CPUState),
+ VMSTATE_UINTTL(cr[2], CPUState),
+ VMSTATE_UINTTL(cr[3], CPUState),
+ VMSTATE_UINTTL(cr[4], CPUState),
+ VMSTATE_UINTTL_ARRAY(dr, CPUState, 8),
+ /* MMU */
+ VMSTATE_INT32(a20_mask, CPUState),
+ /* XMM */
+ VMSTATE_UINT32(mxcsr, CPUState),
+ VMSTATE_XMM_REGS(xmm_regs, CPUState, CPU_NB_REGS),
#ifdef TARGET_X86_64
- qemu_get_be64s(f, &env->efer);
- qemu_get_be64s(f, &env->star);
- qemu_get_be64s(f, &env->lstar);
- qemu_get_be64s(f, &env->cstar);
- qemu_get_be64s(f, &env->fmask);
- qemu_get_be64s(f, &env->kernelgsbase);
+ VMSTATE_UINT64(efer, CPUState),
+ VMSTATE_UINT64(star, CPUState),
+ VMSTATE_UINT64(lstar, CPUState),
+ VMSTATE_UINT64(cstar, CPUState),
+ VMSTATE_UINT64(fmask, CPUState),
+ VMSTATE_UINT64(kernelgsbase, CPUState),
#endif
- if (version_id >= 4) {
- qemu_get_be32s(f, &env->smbase);
- }
- if (version_id >= 5) {
- qemu_get_be64s(f, &env->pat);
- qemu_get_be32s(f, &env->hflags2);
- if (version_id < 6)
- qemu_get_be32s(f, &env->halted);
-
- qemu_get_be64s(f, &env->vm_hsave);
- qemu_get_be64s(f, &env->vm_vmcb);
- qemu_get_be64s(f, &env->tsc_offset);
- qemu_get_be64s(f, &env->intercept);
- qemu_get_be16s(f, &env->intercept_cr_read);
- qemu_get_be16s(f, &env->intercept_cr_write);
- qemu_get_be16s(f, &env->intercept_dr_read);
- qemu_get_be16s(f, &env->intercept_dr_write);
- qemu_get_be32s(f, &env->intercept_exceptions);
- qemu_get_8s(f, &env->v_tpr);
- }
-
- if (version_id >= 8) {
+ VMSTATE_UINT32_V(smbase, CPUState, 4),
+
+ VMSTATE_UINT64_V(pat, CPUState, 5),
+ VMSTATE_UINT32_V(hflags2, CPUState, 5),
+
+ VMSTATE_UINT32_TEST(halted, CPUState, version_is_5),
+ VMSTATE_UINT64_V(vm_hsave, CPUState, 5),
+ VMSTATE_UINT64_V(vm_vmcb, CPUState, 5),
+ VMSTATE_UINT64_V(tsc_offset, CPUState, 5),
+ VMSTATE_UINT64_V(intercept, CPUState, 5),
+ VMSTATE_UINT16_V(intercept_cr_read, CPUState, 5),
+ VMSTATE_UINT16_V(intercept_cr_write, CPUState, 5),
+ VMSTATE_UINT16_V(intercept_dr_read, CPUState, 5),
+ VMSTATE_UINT16_V(intercept_dr_write, CPUState, 5),
+ VMSTATE_UINT32_V(intercept_exceptions, CPUState, 5),
+ VMSTATE_UINT8_V(v_tpr, CPUState, 5),
/* MTRRs */
- for(i = 0; i < 11; i++)
- qemu_get_be64s(f, &env->mtrr_fixed[i]);
- qemu_get_be64s(f, &env->mtrr_deftype);
- for(i = 0; i < 8; i++) {
- qemu_get_be64s(f, &env->mtrr_var[i].base);
- qemu_get_be64s(f, &env->mtrr_var[i].mask);
- }
- }
-
- if (version_id >= 9) {
- qemu_get_sbe32s(f, &env->pending_irq_vmstate);
- qemu_get_be32s(f, &env->mp_state);
- qemu_get_be64s(f, &env->tsc);
- }
-
- if (version_id >= 10) {
- qemu_get_be64s(f, &env->mcg_cap);
- qemu_get_be64s(f, &env->mcg_status);
- qemu_get_be64s(f, &env->mcg_ctl);
- for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
- qemu_get_be64s(f, &env->mce_banks[i]);
- }
+ VMSTATE_UINT64_ARRAY_V(mtrr_fixed, CPUState, 11, 8),
+ VMSTATE_UINT64_V(mtrr_deftype, CPUState, 8),
+ VMSTATE_MTRR_VARS(mtrr_var, CPUState, 8, 8),
+ /* KVM-related states */
+ VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9),
+ VMSTATE_UINT32_V(mp_state, CPUState, 9),
+ VMSTATE_UINT64_V(tsc, CPUState, 9),
+ /* MCE */
+ VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
+ VMSTATE_UINT64_V(mcg_status, CPUState, 10),
+ VMSTATE_UINT64_V(mcg_ctl, CPUState, 10),
+ VMSTATE_UINT64_ARRAY_V(mce_banks, CPUState, MCE_BANKS_DEF *4, 10),
+ /* rdtscp */
+ VMSTATE_UINT64_V(tsc_aux, CPUState, 11),
+ VMSTATE_END_OF_LIST()
}
+};
- if (version_id >= 11) {
- qemu_get_be64s(f, &env->tsc_aux);
- }
+void cpu_save(QEMUFile *f, void *opaque)
+{
+ vmstate_save_state(f, &vmstate_cpu, opaque);
+}
- tlb_flush(env, 1);
- return 0;
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
}
diff --git a/qemu/vl.c b/qemu/vl.c
index 1907dea3..e74e6951 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -207,6 +207,7 @@ int vm_running;
int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
+QEMUClock *rtc_clock;
int vga_interface_type = VGA_CIRRUS;
#ifdef TARGET_SPARC
int graphic_width = 1024;
@@ -542,6 +543,14 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
/***********************************************************/
/* 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;
@@ -596,9 +605,7 @@ static int64_t get_clock(void)
{
/* XXX: using gettimeofday leads to problems if the date
changes, so it should be avoided. */
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
+ return get_clock_realtime();
}
}
#endif
@@ -687,8 +694,9 @@ void cpu_disable_ticks(void)
/***********************************************************/
/* timers */
-#define QEMU_TIMER_REALTIME 0
-#define QEMU_TIMER_VIRTUAL 1
+#define QEMU_CLOCK_REALTIME 0
+#define QEMU_CLOCK_VIRTUAL 1
+#define QEMU_CLOCK_HOST 2
struct QEMUClock {
int type;
@@ -915,10 +923,13 @@ static void configure_alarms(char const *opt)
}
}
+#define QEMU_NUM_CLOCKS 3
+
QEMUClock *rt_clock;
QEMUClock *vm_clock;
+QEMUClock *host_clock;
-static QEMUTimer *active_timers[2];
+static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
static QEMUClock *qemu_new_clock(int type)
{
@@ -1036,23 +1047,28 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
int64_t qemu_get_clock(QEMUClock *clock)
{
switch(clock->type) {
- case QEMU_TIMER_REALTIME:
+ case QEMU_CLOCK_REALTIME:
return get_clock() / 1000000;
default:
- case QEMU_TIMER_VIRTUAL:
+ case QEMU_CLOCK_VIRTUAL:
if (use_icount) {
return cpu_get_icount();
} else {
return cpu_get_clock();
}
+ case QEMU_CLOCK_HOST:
+ return get_clock_realtime();
}
}
-static void init_timers(void)
+static void init_clocks(void)
{
init_get_clock();
- rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
- vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
+ rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
+ vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
+ host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+
+ rtc_clock = host_clock;
}
/* save a timer */
@@ -1134,10 +1150,12 @@ static void host_alarm_handler(int host_signum)
#endif
if (alarm_has_dynticks(alarm_timer) ||
(!use_icount &&
- qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL],
+ qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
qemu_get_clock(vm_clock))) ||
- qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME],
- qemu_get_clock(rt_clock))) {
+ qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME],
+ qemu_get_clock(rt_clock)) ||
+ qemu_timer_expired(active_timers[QEMU_CLOCK_HOST],
+ qemu_get_clock(host_clock))) {
qemu_event_increment();
if (alarm_timer) alarm_timer->flags |= ALARM_FLAG_EXPIRED;
@@ -1154,14 +1172,18 @@ static void host_alarm_handler(int host_signum)
static int64_t qemu_next_deadline(void)
{
- int64_t delta;
+ /* To avoid problems with overflow limit this to 2^32. */
+ int64_t delta = INT32_MAX;
- if (active_timers[QEMU_TIMER_VIRTUAL]) {
- delta = active_timers[QEMU_TIMER_VIRTUAL]->expire_time -
+ if (active_timers[QEMU_CLOCK_VIRTUAL]) {
+ delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
qemu_get_clock(vm_clock);
- } else {
- /* To avoid problems with overflow limit this to 2^32. */
- delta = INT32_MAX;
+ }
+ if (active_timers[QEMU_CLOCK_HOST]) {
+ int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+ qemu_get_clock(host_clock);
+ if (hdelta < delta)
+ delta = hdelta;
}
if (delta < 0)
@@ -1170,7 +1192,7 @@ static int64_t qemu_next_deadline(void)
return delta;
}
-#if defined(__linux__) || defined(_WIN32)
+#if defined(__linux__)
static uint64_t qemu_next_deadline_dyntick(void)
{
int64_t delta;
@@ -1181,8 +1203,8 @@ static uint64_t qemu_next_deadline_dyntick(void)
else
delta = (qemu_next_deadline() + 999) / 1000;
- if (active_timers[QEMU_TIMER_REALTIME]) {
- rtdelta = (active_timers[QEMU_TIMER_REALTIME]->expire_time -
+ if (active_timers[QEMU_CLOCK_REALTIME]) {
+ rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
qemu_get_clock(rt_clock))*1000;
if (rtdelta < delta)
delta = rtdelta;
@@ -1364,8 +1386,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
int64_t nearest_delta_us = INT64_MAX;
int64_t current_us;
- if (!active_timers[QEMU_TIMER_REALTIME] &&
- !active_timers[QEMU_TIMER_VIRTUAL])
+ if (!active_timers[QEMU_CLOCK_REALTIME] &&
+ !active_timers[QEMU_CLOCK_VIRTUAL] &&
+ !active_timers[QEMU_CLOCK_HOST])
return;
nearest_delta_us = qemu_next_deadline_dyntick();
@@ -1479,15 +1502,12 @@ static void win32_stop_timer(struct qemu_alarm_timer *t)
static void win32_rearm_timer(struct qemu_alarm_timer *t)
{
struct qemu_alarm_win32 *data = t->priv;
- uint64_t nearest_delta_us;
- if (!active_timers[QEMU_TIMER_REALTIME] &&
- !active_timers[QEMU_TIMER_VIRTUAL])
+ if (!active_timers[QEMU_CLOCK_REALTIME] &&
+ !active_timers[QEMU_CLOCK_VIRTUAL] &&
+ !active_timers[QEMU_CLOCK_HOST])
return;
- nearest_delta_us = qemu_next_deadline_dyntick();
- nearest_delta_us /= 1000;
-
timeKillEvent(data->timerId);
data->timerId = timeSetEvent(1,
@@ -1576,6 +1596,85 @@ int qemu_timedate_diff(struct tm *tm)
return seconds - time(NULL);
}
+static void configure_rtc_date_offset(const char *startdate, int legacy)
+{
+ time_t rtc_start_date;
+ struct tm tm;
+
+ if (!strcmp(startdate, "now") && legacy) {
+ rtc_date_offset = -1;
+ } else {
+ if (sscanf(startdate, "%d-%d-%dT%d:%d:%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec) == 6) {
+ /* OK */
+ } else if (sscanf(startdate, "%d-%d-%d",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday) == 3) {
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ } else {
+ goto date_fail;
+ }
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ rtc_start_date = mktimegm(&tm);
+ if (rtc_start_date == -1) {
+ date_fail:
+ fprintf(stderr, "Invalid date format. Valid formats are:\n"
+ "'2006-06-17T16:01:21' or '2006-06-17'\n");
+ exit(1);
+ }
+ rtc_date_offset = time(NULL) - rtc_start_date;
+ }
+}
+
+static void configure_rtc(QemuOpts *opts)
+{
+ const char *value;
+
+ value = qemu_opt_get(opts, "base");
+ if (value) {
+ if (!strcmp(value, "utc")) {
+ rtc_utc = 1;
+ } else if (!strcmp(value, "localtime")) {
+ rtc_utc = 0;
+ } else {
+ configure_rtc_date_offset(value, 0);
+ }
+ }
+ value = qemu_opt_get(opts, "clock");
+ if (value) {
+ if (!strcmp(value, "host")) {
+ rtc_clock = host_clock;
+ } else if (!strcmp(value, "vm")) {
+ rtc_clock = vm_clock;
+ } else {
+ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ exit(1);
+ }
+ }
+#ifdef CONFIG_TARGET_I386
+ value = qemu_opt_get(opts, "driftfix");
+ if (value) {
+ if (!strcmp(buf, "slew")) {
+ rtc_td_hack = 1;
+ } else if (!strcmp(buf, "none")) {
+ rtc_td_hack = 0;
+ } else {
+ fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+ exit(1);
+ }
+ }
+#endif
+}
+
#ifdef _WIN32
static void socket_cleanup(void)
{
@@ -3603,9 +3702,14 @@ void qemu_cpu_kick(void *_env)
qemu_thread_signal(env->thread, SIGUSR1);
}
-int qemu_cpu_self(void *env)
+int qemu_cpu_self(void *_env)
{
- return (cpu_single_env != NULL);
+ CPUState *env = _env;
+ QemuThread this;
+
+ qemu_thread_self(&this);
+
+ return qemu_thread_equal(&this, env->thread);
}
static void cpu_signal(int sig)
@@ -3919,14 +4023,17 @@ void main_loop_wait(int timeout)
/* vm time timers */
if (vm_running) {
if (!cur_cpu || likely(!(cur_cpu->singlestep_enabled & SSTEP_NOTIMER)))
- qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
- qemu_get_clock(vm_clock));
+ qemu_run_timers(&active_timers[QEMU_CLOCK_VIRTUAL],
+ qemu_get_clock(vm_clock));
}
/* real time timers */
- qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
+ qemu_run_timers(&active_timers[QEMU_CLOCK_REALTIME],
qemu_get_clock(rt_clock));
+ qemu_run_timers(&active_timers[QEMU_CLOCK_HOST],
+ qemu_get_clock(host_clock));
+
/* Check bottom-halves last in case any of the earlier events triggered
them. */
qemu_bh_poll();
@@ -4678,6 +4785,8 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp)
CPUState *env;
int show_vnc_port = 0;
+ init_clocks();
+
qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp);
@@ -5374,42 +5483,15 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp)
configure_alarms(optarg);
break;
case QEMU_OPTION_startdate:
- {
- struct tm tm;
- time_t rtc_start_date;
- if (!strcmp(optarg, "now")) {
- rtc_date_offset = -1;
- } else {
- if (sscanf(optarg, "%d-%d-%dT%d:%d:%d",
- &tm.tm_year,
- &tm.tm_mon,
- &tm.tm_mday,
- &tm.tm_hour,
- &tm.tm_min,
- &tm.tm_sec) == 6) {
- /* OK */
- } else if (sscanf(optarg, "%d-%d-%d",
- &tm.tm_year,
- &tm.tm_mon,
- &tm.tm_mday) == 3) {
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- } else {
- goto date_fail;
- }
- tm.tm_year -= 1900;
- tm.tm_mon--;
- rtc_start_date = mktimegm(&tm);
- if (rtc_start_date == -1) {
- date_fail:
- fprintf(stderr, "Invalid date format. Valid format are:\n"
- "'now' or '2006-06-17T16:01:21' or '2006-06-17'\n");
- exit(1);
- }
- rtc_date_offset = time(NULL) - rtc_start_date;
- }
+ configure_rtc_date_offset(optarg, 1);
+ break;
+ case QEMU_OPTION_rtc:
+ opts = qemu_opts_parse(&qemu_rtc_opts, optarg, NULL);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
}
+ configure_rtc(opts);
break;
case QEMU_OPTION_tb_size:
tb_size = strtol(optarg, NULL, 0);
@@ -5570,7 +5652,6 @@ int __declspec(dllexport) qemu_main(int argc, char** argv, char** envp)
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
- init_timers();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
exit(1);