Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into…
Browse files Browse the repository at this point in the history
… staging

Usual mix of patches, the most important being Alex and Marcelo's
kvmclock fix.  This was reverted last minute for 2.1, but it is now back
with the problematic case fixed.

Note: I will soon switch to a subkey for signing purposes.  To verify
future signed pull requests from me, please update my key with
"gpg --recv-keys 9B4D86F2".  You should see 3 new subkeys---the
one for signing will be a 2048-bit RSA key, 4E6B09D7.

# gpg: Signature made Fri 26 Sep 2014 15:34:44 BST using RSA key ID 9B4D86F2
# gpg: Good signature from "Paolo Bonzini <pbonzini@redhat.com>"
# gpg:                 aka "Paolo Bonzini <bonzini@gnu.org>"

* remotes/bonzini/tags/for-upstream:
  kvm/valgrind: don't mark memory as initialized
  po: fix conflict with %.mo rule in rules.mak
  kvmvapic: fix migration when VM paused and when not running Windows
  serial: check if backed by a physical serial port at realize time
  serial: reset state at startup
  target-i386: update fp status fix
  hw/dma/i8257: Silence phony error message
  kvmclock: Ensure time in migration never goes backward
  kvmclock: Ensure proper env->tsc value for kvmclock_current_nsec calculation
  Introduce cpu_clean_all_dirty
  pit: fix pit interrupt can't inject into vm after migration

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Sep 26, 2014
2 parents da1c4ec + 541be92 commit 81ab11a
Show file tree
Hide file tree
Showing 17 changed files with 117 additions and 31 deletions.
3 changes: 1 addition & 2 deletions configure
Expand Up @@ -3956,12 +3956,11 @@ else
fi

########################################
# check if we have valgrind/valgrind.h and valgrind/memcheck.h
# check if we have valgrind/valgrind.h

valgrind_h=no
cat > $TMPC << EOF
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
int main(void) {
return 0;
}
Expand Down
9 changes: 9 additions & 0 deletions cpus.c
Expand Up @@ -593,6 +593,15 @@ void cpu_synchronize_all_post_init(void)
}
}

void cpu_clean_all_dirty(void)
{
CPUState *cpu;

CPU_FOREACH(cpu) {
cpu_clean_state(cpu);
}
}

static int do_vm_stop(RunState state)
{
int ret = 0;
Expand Down
6 changes: 4 additions & 2 deletions hw/char/serial.c
Expand Up @@ -815,6 +815,9 @@ static void serial_reset(void *opaque)
s->thr_ipending = 0;
s->last_break_enable = 0;
qemu_irq_lower(s->irq);

serial_update_msl(s);
s->msr &= ~UART_MSR_ANY_DELTA;
}

void serial_realize_core(SerialState *s, Error **errp)
Expand All @@ -833,6 +836,7 @@ void serial_realize_core(SerialState *s, Error **errp)
serial_event, s);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
}

void serial_exit_core(SerialState *s)
Expand Down Expand Up @@ -944,7 +948,5 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s,
"serial", 8 << it_shift);
memory_region_add_subregion(address_space, base, &s->io);

serial_update_msl(s);
return s;
}
4 changes: 2 additions & 2 deletions hw/dma/i8257.c
Expand Up @@ -24,6 +24,7 @@
#include "hw/hw.h"
#include "hw/isa/isa.h"
#include "qemu/main-loop.h"
#include "trace.h"

/* #define DEBUG_DMA */

Expand Down Expand Up @@ -473,8 +474,7 @@ static void dma_reset(void *opaque)

static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
{
dolog ("unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d\n",
nchan, dma_pos, dma_len);
trace_i8257_unregistered_dma(nchan, dma_pos, dma_len);
return dma_pos;
}

Expand Down
53 changes: 53 additions & 0 deletions hw/i386/kvm/clock.c
Expand Up @@ -14,8 +14,10 @@
*/

#include "qemu-common.h"
#include "qemu/host-utils.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "sysemu/cpus.h"
#include "hw/sysbus.h"
#include "hw/kvm/clock.h"

Expand All @@ -34,6 +36,48 @@ typedef struct KVMClockState {
bool clock_valid;
} KVMClockState;

struct pvclock_vcpu_time_info {
uint32_t version;
uint32_t pad0;
uint64_t tsc_timestamp;
uint64_t system_time;
uint32_t tsc_to_system_mul;
int8_t tsc_shift;
uint8_t flags;
uint8_t pad[2];
} __attribute__((__packed__)); /* 32 bytes */

static uint64_t kvmclock_current_nsec(KVMClockState *s)
{
CPUState *cpu = first_cpu;
CPUX86State *env = cpu->env_ptr;
hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
uint64_t migration_tsc = env->tsc;
struct pvclock_vcpu_time_info time;
uint64_t delta;
uint64_t nsec_lo;
uint64_t nsec_hi;
uint64_t nsec;

if (!(env->system_time_msr & 1ULL)) {
/* KVM clock not active */
return 0;
}

cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));

assert(time.tsc_timestamp <= migration_tsc);
delta = migration_tsc - time.tsc_timestamp;
if (time.tsc_shift < 0) {
delta >>= -time.tsc_shift;
} else {
delta <<= time.tsc_shift;
}

mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
nsec = (nsec_lo >> 32) | (nsec_hi << 32);
return nsec + time.system_time;
}

static void kvmclock_vm_state_change(void *opaque, int running,
RunState state)
Expand All @@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,

if (running) {
struct kvm_clock_data data;
uint64_t time_at_migration = kvmclock_current_nsec(s);

s->clock_valid = false;

/* We can't rely on the migrated clock value, just discard it */
if (time_at_migration) {
s->clock = time_at_migration;
}

data.clock = s->clock;
data.flags = 0;
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
Expand Down Expand Up @@ -75,6 +125,9 @@ static void kvmclock_vm_state_change(void *opaque, int running,
if (s->clock_valid) {
return;
}

cpu_synchronize_all_states();
cpu_clean_all_dirty();
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
if (ret < 0) {
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));
Expand Down
3 changes: 1 addition & 2 deletions hw/i386/kvm/i8254.c
Expand Up @@ -239,6 +239,7 @@ static void kvm_pit_vm_state_change(void *opaque, int running,

if (running) {
kvm_pit_update_clock_offset(s);
kvm_pit_put(PIT_COMMON(s));
s->vm_stopped = false;
} else {
kvm_pit_update_clock_offset(s);
Expand Down Expand Up @@ -314,8 +315,6 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
dc->realize = kvm_pit_realizefn;
k->set_channel_gate = kvm_pit_set_gate;
k->get_channel_info = kvm_pit_get_channel_info;
k->pre_save = kvm_pit_get;
k->post_load = kvm_pit_put;
dc->reset = kvm_pit_reset;
dc->props = kvm_pit_properties;
}
Expand Down
11 changes: 9 additions & 2 deletions hw/i386/kvmvapic.c
Expand Up @@ -732,7 +732,11 @@ static void do_vapic_enable(void *data)
VAPICROMState *s = data;
X86CPU *cpu = X86_CPU(first_cpu);

vapic_enable(s, cpu);
static const uint8_t enabled = 1;
cpu_physical_memory_write(s->vapic_paddr + offsetof(VAPICState, enabled),
&enabled, sizeof(enabled));
apic_enable_vapic(cpu->apic_state, s->vapic_paddr);
s->state = VAPIC_ACTIVE;
}

static void kvmvapic_vm_state_change(void *opaque, int running,
Expand Down Expand Up @@ -777,7 +781,10 @@ static int vapic_post_load(void *opaque, int version_id)
}
}

s->vmsentry = qemu_add_vm_change_state_handler(kvmvapic_vm_state_change, s);
if (!s->vmsentry) {
s->vmsentry =
qemu_add_vm_change_state_handler(kvmvapic_vm_state_change, s);
}
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/sysemu/cpus.h
Expand Up @@ -10,6 +10,7 @@ void cpu_stop_current(void);
void cpu_synchronize_all_states(void);
void cpu_synchronize_all_post_reset(void);
void cpu_synchronize_all_post_init(void);
void cpu_clean_all_dirty(void);

void qtest_clock_warp(int64_t dest);

Expand Down
8 changes: 8 additions & 0 deletions include/sysemu/kvm.h
Expand Up @@ -350,6 +350,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
void kvm_cpu_synchronize_state(CPUState *cpu);
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
void kvm_cpu_synchronize_post_init(CPUState *cpu);
void kvm_cpu_clean_state(CPUState *cpu);

/* generic hooks - to be moved/refactored once there are more users */

Expand All @@ -374,6 +375,13 @@ static inline void cpu_synchronize_post_init(CPUState *cpu)
}
}

static inline void cpu_clean_state(CPUState *cpu)
{
if (kvm_enabled()) {
kvm_cpu_clean_state(cpu);
}
}

int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
void kvm_irqchip_release_virq(KVMState *s, int virq);
Expand Down
12 changes: 5 additions & 7 deletions kvm-all.c
Expand Up @@ -44,10 +44,6 @@
#include <sys/eventfd.h>
#endif

#ifdef CONFIG_VALGRIND_H
#include <valgrind/memcheck.h>
#endif

/* KVM uses PAGE_SIZE in its definition of COALESCED_MMIO_MAX */
#define PAGE_SIZE TARGET_PAGE_SIZE

Expand Down Expand Up @@ -1708,6 +1704,11 @@ void kvm_cpu_synchronize_post_init(CPUState *cpu)
run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, cpu);
}

void kvm_cpu_clean_state(CPUState *cpu)
{
cpu->kvm_vcpu_dirty = false;
}

int kvm_cpu_exec(CPUState *cpu)
{
struct kvm_run *run = cpu->kvm_run;
Expand Down Expand Up @@ -1954,9 +1955,6 @@ int kvm_has_intx_set_mask(void)

void kvm_setup_guest_memory(void *start, size_t size)
{
#ifdef CONFIG_VALGRIND_H
VALGRIND_MAKE_MEM_DEFINED(start, size);
#endif
if (!kvm_has_sync_mmu()) {
int ret = qemu_madvise(start, size, QEMU_MADV_DONTFORK);

Expand Down
6 changes: 3 additions & 3 deletions po/Makefile
Expand Up @@ -9,6 +9,9 @@ all:

.PHONY: all build clean install update

%.mo: %.po
$(call quiet-command, msgfmt -o $@ $<, " GEN $@")

-include ../config-host.mak
include $(SRC_PATH)/rules.mak

Expand Down Expand Up @@ -38,9 +41,6 @@ install: $(OBJS)
$(INSTALL) -m644 $$obj $(DESTDIR)$(prefix)/share/locale/$$base/LC_MESSAGES/qemu.mo; \
done

%.mo: %.po
$(call quiet-command, msgfmt -o $@ $<, " GEN $@")

$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
$(call quiet-command, ( cd $(SRC_PATH) && \
xgettext -o - --from-code=UTF-8 --foreign-user \
Expand Down
2 changes: 1 addition & 1 deletion target-i386/cpu.c
Expand Up @@ -2580,7 +2580,7 @@ static void x86_cpu_reset(CPUState *s)
for (i = 0; i < 8; i++) {
env->fptags[i] = 1;
}
env->fpuc = 0x37f;
cpu_set_fpuc(env, 0x37f);

env->mxcsr = 0x1f80;
env->xstate_bv = XSTATE_FP | XSTATE_SSE;
Expand Down
2 changes: 2 additions & 0 deletions target-i386/cpu.h
Expand Up @@ -1251,6 +1251,7 @@ void QEMU_NORETURN raise_interrupt(CPUX86State *nenv, int intno, int is_int,
/* cc_helper.c */
extern const uint8_t parity_table[256];
uint32_t cpu_cc_compute_all(CPUX86State *env1, int op);
void update_fp_status(CPUX86State *env);

static inline uint32_t cpu_compute_eflags(CPUX86State *env)
{
Expand Down Expand Up @@ -1286,6 +1287,7 @@ static inline void cpu_load_efer(CPUX86State *env, uint64_t val)

/* fpu_helper.c */
void cpu_set_mxcsr(CPUX86State *env, uint32_t val);
void cpu_set_fpuc(CPUX86State *env, uint16_t val);

/* svm_helper.c */
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
Expand Down
21 changes: 13 additions & 8 deletions target-i386/fpu_helper.c
Expand Up @@ -537,7 +537,7 @@ uint32_t helper_fnstcw(CPUX86State *env)
return env->fpuc;
}

static void update_fp_status(CPUX86State *env)
void update_fp_status(CPUX86State *env)
{
int rnd_type;

Expand Down Expand Up @@ -575,8 +575,7 @@ static void update_fp_status(CPUX86State *env)

void helper_fldcw(CPUX86State *env, uint32_t val)
{
env->fpuc = val;
update_fp_status(env);
cpu_set_fpuc(env, val);
}

void helper_fclex(CPUX86State *env)
Expand All @@ -595,7 +594,7 @@ void helper_fninit(CPUX86State *env)
{
env->fpus = 0;
env->fpstt = 0;
env->fpuc = 0x37f;
cpu_set_fpuc(env, 0x37f);
env->fptags[0] = 1;
env->fptags[1] = 1;
env->fptags[2] = 1;
Expand Down Expand Up @@ -1013,11 +1012,11 @@ void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
int i, fpus, fptag;

if (data32) {
env->fpuc = cpu_lduw_data(env, ptr);
cpu_set_fpuc(env, cpu_lduw_data(env, ptr));
fpus = cpu_lduw_data(env, ptr + 4);
fptag = cpu_lduw_data(env, ptr + 8);
} else {
env->fpuc = cpu_lduw_data(env, ptr);
cpu_set_fpuc(env, cpu_lduw_data(env, ptr));
fpus = cpu_lduw_data(env, ptr + 2);
fptag = cpu_lduw_data(env, ptr + 4);
}
Expand Down Expand Up @@ -1046,7 +1045,7 @@ void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
/* fninit */
env->fpus = 0;
env->fpstt = 0;
env->fpuc = 0x37f;
cpu_set_fpuc(env, 0x37f);
env->fptags[0] = 1;
env->fptags[1] = 1;
env->fptags[2] = 1;
Expand Down Expand Up @@ -1157,7 +1156,7 @@ void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
raise_exception(env, EXCP0D_GPF);
}

env->fpuc = cpu_lduw_data(env, ptr);
cpu_set_fpuc(env, cpu_lduw_data(env, ptr));
fpus = cpu_lduw_data(env, ptr + 2);
fptag = cpu_lduw_data(env, ptr + 4);
env->fpstt = (fpus >> 11) & 7;
Expand Down Expand Up @@ -1257,6 +1256,12 @@ void cpu_set_mxcsr(CPUX86State *env, uint32_t mxcsr)
set_flush_to_zero((mxcsr & SSE_FZ) ? 1 : 0, &env->fp_status);
}

void cpu_set_fpuc(CPUX86State *env, uint16_t val)
{
env->fpuc = val;
update_fp_status(env);
}

void helper_ldmxcsr(CPUX86State *env, uint32_t val)
{
cpu_set_mxcsr(env, val);
Expand Down
2 changes: 1 addition & 1 deletion target-i386/gdbstub.c
Expand Up @@ -203,7 +203,7 @@ int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);

case IDX_FP_REGS + 8:
env->fpuc = ldl_p(mem_buf);
cpu_set_fpuc(env, ldl_p(mem_buf));
return 4;
case IDX_FP_REGS + 9:
tmp = ldl_p(mem_buf);
Expand Down

0 comments on commit 81ab11a

Please sign in to comment.