* GUEST_PANICKED improvements (Anton)

* vCont gdbstub rewrite (Claudio)
 * Fix CPU creation with -device (Liyang)
 * Logging fixes for pty chardevs (Ed)
 * Makefile "move if changed" fix (Lin)
 * First part of cpu_exec refactoring (me)
 * SVM emulation fix (me)
 * apic_delivered fix (Pavel)
 * "info ioapic" fix (Peter)
 * qemu-nbd socket activation (Richard)
 * QOMification of mcf_uart (Thomas)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJYpeNbAAoJEL/70l94x66DIC4H/0I1WChmdOKqMBOuHe5yGIqy
 YZUpEmbUMG9A8Idh6uuVaQni6mYcMpJwq3zNYkNFEAodNzoKsh475gyV3ay5SnY/
 s8x6KeCfsVD5UgpQQH9Q3kVr+4QfdtPCqbkoXq4rMeA0293J6sq/+cTqwACJuY9T
 yCdrFhFoRO6B/dv/c/vMx7XqOwTNwOhJZUPc/ZvgZM4llB+wNaR1G/eRjcAVnLG8
 JZp3bDqHkqoe2aIauYfW59LVQ/Vjejxn3yCXyvj8gk3OG81SEziKX6jM/ls29C2V
 2eu6+f8wvOW0plj+zE9UcXe/7ThMYvv7TwhnhIaPOsLDBrVFtT8VAOW7KpuLN54=
 =3ucZ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* GUEST_PANICKED improvements (Anton)
* vCont gdbstub rewrite (Claudio)
* Fix CPU creation with -device (Liyang)
* Logging fixes for pty chardevs (Ed)
* Makefile "move if changed" fix (Lin)
* First part of cpu_exec refactoring (me)
* SVM emulation fix (me)
* apic_delivered fix (Pavel)
* "info ioapic" fix (Peter)
* qemu-nbd socket activation (Richard)
* QOMification of mcf_uart (Thomas)

# gpg: Signature made Thu 16 Feb 2017 17:37:31 GMT
# gpg:                using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream: (23 commits)
  target-i386: correctly propagate retaddr into SVM helpers
  vl: log available guest crash information
  report guest crash information in GUEST_PANICKED event
  i386/cpu: add crash-information QOM property
  Makefile: avoid leaving the temporary QEMU_PKGVERSION header file
  vl: Move the cpu_synchronize_all_post_init() after generic devices initialization
  qemu-nbd: Implement socket activation.
  qemu-doc: Clarify that -vga std is now the default
  cpu-exec: remove outermost infinite loop
  cpu-exec: avoid repeated sigsetjmp on interrupts
  cpu-exec: avoid cpu_loop_exit in cpu_handle_interrupt
  cpu-exec: tighten barrier on TCG_EXIT_REQUESTED
  cpu-exec: fix icount out-of-bounds access
  hw/char/mcf_uart: QOMify the ColdFire UART
  gdbstub: Fix vCont behaviour
  move vm_start to cpus.c
  char: drop data written to a disconnected pty
  apic: reset apic_delivered global variable on machine reset
  qemu-char: socket backend: disconnect on write error
  test-vmstate: remove yield_until_fd_readable
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2017-02-16 17:46:52 +00:00
commit ad584d37f2
33 changed files with 710 additions and 252 deletions

View File

@ -299,7 +299,11 @@ qemu-version.h: FORCE
printf '""\n'; \
fi; \
fi) > $@.tmp)
$(call quiet-command, cmp -s $@ $@.tmp || mv $@.tmp $@)
$(call quiet-command, if ! cmp -s $@ $@.tmp; then \
mv $@.tmp $@; \
else \
rm $@.tmp; \
fi)
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak

View File

@ -129,7 +129,7 @@ static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
/* guest sends data, check for (re-)connect */
pty_chr_update_read_handler_locked(chr);
if (!s->connected) {
return 0;
return len;
}
}
return io_channel_send(s->ioc, buf, len);

View File

@ -97,6 +97,9 @@ static gboolean tcp_chr_accept(QIOChannel *chan,
GIOCondition cond,
void *opaque);
static int tcp_chr_read_poll(void *opaque);
static void tcp_chr_disconnect(Chardev *chr);
/* Called with chr_write_lock held. */
static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
@ -114,6 +117,13 @@ static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
s->write_msgfds_num = 0;
}
if (ret < 0 && errno != EAGAIN) {
if (tcp_chr_read_poll(chr) <= 0) {
tcp_chr_disconnect(chr);
return len;
} /* else let the read handler finish it properly */
}
return ret;
} else {
/* XXX: indicate an error ? */

View File

@ -461,7 +461,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
return false;
}
static inline void cpu_handle_interrupt(CPUState *cpu,
static inline bool cpu_handle_interrupt(CPUState *cpu,
TranslationBlock **last_tb)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
@ -475,7 +475,7 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
if (interrupt_request & CPU_INTERRUPT_DEBUG) {
cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
cpu->exception_index = EXCP_DEBUG;
cpu_loop_exit(cpu);
return true;
}
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
/* Do nothing */
@ -484,23 +484,23 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
cpu->halted = 1;
cpu->exception_index = EXCP_HLT;
cpu_loop_exit(cpu);
return true;
}
#if defined(TARGET_I386)
else if (interrupt_request & CPU_INTERRUPT_INIT) {
X86CPU *x86_cpu = X86_CPU(cpu);
CPUArchState *env = &x86_cpu->env;
replay_interrupt();
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_INIT, 0, 0);
do_cpu_init(x86_cpu);
cpu->exception_index = EXCP_HALTED;
cpu_loop_exit(cpu);
return true;
}
#else
else if (interrupt_request & CPU_INTERRUPT_RESET) {
replay_interrupt();
cpu_reset(cpu);
cpu_loop_exit(cpu);
return true;
}
#endif
/* The target hook has 3 exit conditions:
@ -526,8 +526,10 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
if (unlikely(atomic_read(&cpu->exit_request) || replay_has_interrupt())) {
atomic_set(&cpu->exit_request, 0);
cpu->exception_index = EXCP_INTERRUPT;
cpu_loop_exit(cpu);
return true;
}
return false;
}
static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
@ -542,7 +544,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
trace_exec_tb(tb, tb->pc);
ret = cpu_tb_exec(cpu, tb);
*last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
*tb_exit = ret & TB_EXIT_MASK;
switch (*tb_exit) {
case TB_EXIT_REQUESTED:
@ -552,11 +554,11 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
* have set something else (eg exit_request or
* interrupt_request) which we will handle
* next time around the loop. But we need to
* ensure the tcg_exit_req read in generated code
* ensure the zeroing of tcg_exit_req (see cpu_tb_exec)
* comes before the next read of cpu->exit_request
* or cpu->interrupt_request.
*/
smp_rmb();
smp_mb();
*last_tb = NULL;
break;
case TB_EXIT_ICOUNT_EXPIRED:
@ -566,6 +568,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
abort();
#else
int insns_left = cpu->icount_decr.u32;
*last_tb = NULL;
if (cpu->icount_extra && insns_left >= 0) {
/* Refill decrementer and continue execution. */
cpu->icount_extra += insns_left;
@ -575,17 +578,17 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
} else {
if (insns_left > 0) {
/* Execute remaining instructions. */
cpu_exec_nocache(cpu, insns_left, *last_tb, false);
cpu_exec_nocache(cpu, insns_left, tb, false);
align_clocks(sc, cpu);
}
cpu->exception_index = EXCP_INTERRUPT;
*last_tb = NULL;
cpu_loop_exit(cpu);
}
break;
#endif
}
default:
*last_tb = tb;
break;
}
}
@ -621,42 +624,37 @@ int cpu_exec(CPUState *cpu)
*/
init_delay_params(&sc, cpu);
for(;;) {
/* prepare setjmp context for exception handling */
if (sigsetjmp(cpu->jmp_env, 0) == 0) {
TranslationBlock *tb, *last_tb = NULL;
int tb_exit = 0;
/* if an exception is pending, we execute it here */
if (cpu_handle_exception(cpu, &ret)) {
break;
}
for(;;) {
cpu_handle_interrupt(cpu, &last_tb);
tb = tb_find(cpu, last_tb, tb_exit);
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc);
/* Try to align the host and virtual clocks
if the guest is in advance */
align_clocks(&sc, cpu);
} /* for(;;) */
} else {
/* prepare setjmp context for exception handling */
if (sigsetjmp(cpu->jmp_env, 0) != 0) {
#if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6)
/* Some compilers wrongly smash all local variables after
* siglongjmp. There were bug reports for gcc 4.5.0 and clang.
* Reload essential local variables here for those compilers.
* Newer versions of gcc would complain about this code (-Wclobbered). */
cpu = current_cpu;
cc = CPU_GET_CLASS(cpu);
/* Some compilers wrongly smash all local variables after
* siglongjmp. There were bug reports for gcc 4.5.0 and clang.
* Reload essential local variables here for those compilers.
* Newer versions of gcc would complain about this code (-Wclobbered). */
cpu = current_cpu;
cc = CPU_GET_CLASS(cpu);
#else /* buggy compiler */
/* Assert that the compiler does not smash local variables. */
g_assert(cpu == current_cpu);
g_assert(cc == CPU_GET_CLASS(cpu));
/* Assert that the compiler does not smash local variables. */
g_assert(cpu == current_cpu);
g_assert(cc == CPU_GET_CLASS(cpu));
#endif /* buggy compiler */
cpu->can_do_io = 1;
tb_lock_reset();
cpu->can_do_io = 1;
tb_lock_reset();
}
/* if an exception is pending, we execute it here */
while (!cpu_handle_exception(cpu, &ret)) {
TranslationBlock *last_tb = NULL;
int tb_exit = 0;
while (!cpu_handle_interrupt(cpu, &last_tb)) {
TranslationBlock *tb = tb_find(cpu, last_tb, tb_exit);
cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit, &sc);
/* Try to align the host and virtual clocks
if the guest is in advance */
align_clocks(&sc, cpu);
}
} /* for(;;) */
}
cc->cpu_exec_exit(cpu);
rcu_read_unlock();

42
cpus.c
View File

@ -1578,6 +1578,48 @@ int vm_stop(RunState state)
return do_vm_stop(state);
}
/**
* Prepare for (re)starting the VM.
* Returns -1 if the vCPUs are not to be restarted (e.g. if they are already
* running or in case of an error condition), 0 otherwise.
*/
int vm_prepare_start(void)
{
RunState requested;
int res = 0;
qemu_vmstop_requested(&requested);
if (runstate_is_running() && requested == RUN_STATE__MAX) {
return -1;
}
/* Ensure that a STOP/RESUME pair of events is emitted if a
* vmstop request was pending. The BLOCK_IO_ERROR event, for
* example, according to documentation is always followed by
* the STOP event.
*/
if (runstate_is_running()) {
qapi_event_send_stop(&error_abort);
res = -1;
} else {
replay_enable_events();
cpu_enable_ticks();
runstate_set(RUN_STATE_RUNNING);
vm_state_notify(1, RUN_STATE_RUNNING);
}
/* We are sending this now, but the CPUs will be resumed shortly later */
qapi_event_send_resume(&error_abort);
return res;
}
void vm_start(void)
{
if (!vm_prepare_start()) {
resume_all_vcpus();
}
}
/* does a state transition even if the VM is already stopped,
current state is forgotten forever */
int vm_stop_force_state(RunState state)

207
gdbstub.c
View File

@ -387,6 +387,60 @@ static inline void gdb_continue(GDBState *s)
#endif
}
/*
* Resume execution, per CPU actions. For user-mode emulation it's
* equivalent to gdb_continue.
*/
static int gdb_continue_partial(GDBState *s, char *newstates)
{
CPUState *cpu;
int res = 0;
#ifdef CONFIG_USER_ONLY
/*
* This is not exactly accurate, but it's an improvement compared to the
* previous situation, where only one CPU would be single-stepped.
*/
CPU_FOREACH(cpu) {
if (newstates[cpu->cpu_index] == 's') {
cpu_single_step(cpu, sstep_flags);
}
}
s->running_state = 1;
#else
int flag = 0;
if (!runstate_needs_reset()) {
if (vm_prepare_start()) {
return 0;
}
CPU_FOREACH(cpu) {
switch (newstates[cpu->cpu_index]) {
case 0:
case 1:
break; /* nothing to do here */
case 's':
cpu_single_step(cpu, sstep_flags);
cpu_resume(cpu);
flag = 1;
break;
case 'c':
cpu_resume(cpu);
flag = 1;
break;
default:
res = -1;
break;
}
}
}
if (flag) {
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
}
#endif
return res;
}
static void put_buffer(GDBState *s, const uint8_t *buf, int len)
{
#ifdef CONFIG_USER_ONLY
@ -785,6 +839,107 @@ static int is_query_packet(const char *p, const char *query, char separator)
(p[query_len] == '\0' || p[query_len] == separator);
}
/**
* gdb_handle_vcont - Parses and handles a vCont packet.
* returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is
* a format error, 0 on success.
*/
static int gdb_handle_vcont(GDBState *s, const char *p)
{
int res, idx, signal = 0;
char cur_action;
char *newstates;
unsigned long tmp;
CPUState *cpu;
#ifdef CONFIG_USER_ONLY
int max_cpus = 1; /* global variable max_cpus exists only in system mode */
CPU_FOREACH(cpu) {
max_cpus = max_cpus <= cpu->cpu_index ? cpu->cpu_index + 1 : max_cpus;
}
#endif
/* uninitialised CPUs stay 0 */
newstates = g_new0(char, max_cpus);
/* mark valid CPUs with 1 */
CPU_FOREACH(cpu) {
newstates[cpu->cpu_index] = 1;
}
/*
* res keeps track of what error we are returning, with -ENOTSUP meaning
* that the command is unknown or unsupported, thus returning an empty
* packet, while -EINVAL and -ERANGE cause an E22 packet, due to invalid,
* or incorrect parameters passed.
*/
res = 0;
while (*p) {
if (*p++ != ';') {
res = -ENOTSUP;
goto out;
}
cur_action = *p++;
if (cur_action == 'C' || cur_action == 'S') {
cur_action = tolower(cur_action);
res = qemu_strtoul(p + 1, &p, 16, &tmp);
if (res) {
goto out;
}
signal = gdb_signal_to_target(tmp);
} else if (cur_action != 'c' && cur_action != 's') {
/* unknown/invalid/unsupported command */
res = -ENOTSUP;
goto out;
}
/* thread specification. special values: (none), -1 = all; 0 = any */
if ((p[0] == ':' && p[1] == '-' && p[2] == '1') || (p[0] != ':')) {
if (*p == ':') {
p += 3;
}
for (idx = 0; idx < max_cpus; idx++) {
if (newstates[idx] == 1) {
newstates[idx] = cur_action;
}
}
} else if (*p == ':') {
p++;
res = qemu_strtoul(p, &p, 16, &tmp);
if (res) {
goto out;
}
idx = tmp;
/* 0 means any thread, so we pick the first valid CPU */
if (!idx) {
idx = cpu_index(first_cpu);
}
/*
* If we are in user mode, the thread specified is actually a
* thread id, and not an index. We need to find the actual
* CPU first, and only then we can use its index.
*/
cpu = find_cpu(idx);
/* invalid CPU/thread specified */
if (!idx || !cpu) {
res = -EINVAL;
goto out;
}
/* only use if no previous match occourred */
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
}
}
}
s->signal = signal;
gdb_continue_partial(s, newstates);
out:
g_free(newstates);
return res;
}
static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
CPUState *cpu;
@ -830,60 +985,20 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
return RS_IDLE;
case 'v':
if (strncmp(p, "Cont", 4) == 0) {
int res_signal, res_thread;
p += 4;
if (*p == '?') {
put_packet(s, "vCont;c;C;s;S");
break;
}
res = 0;
res_signal = 0;
res_thread = 0;
while (*p) {
int action, signal;
if (*p++ != ';') {
res = 0;
break;
}
action = *p++;
signal = 0;
if (action == 'C' || action == 'S') {
signal = gdb_signal_to_target(strtoul(p, (char **)&p, 16));
if (signal == -1) {
signal = 0;
}
} else if (action != 'c' && action != 's') {
res = 0;
break;
}
thread = 0;
if (*p == ':') {
thread = strtoull(p+1, (char **)&p, 16);
}
action = tolower(action);
if (res == 0 || (res == 'c' && action == 's')) {
res = action;
res_signal = signal;
res_thread = thread;
}
}
res = gdb_handle_vcont(s, p);
if (res) {
if (res_thread != -1 && res_thread != 0) {
cpu = find_cpu(res_thread);
if (cpu == NULL) {
put_packet(s, "E22");
break;
}
s->c_cpu = cpu;
if ((res == -EINVAL) || (res == -ERANGE)) {
put_packet(s, "E22");
break;
}
if (res == 's') {
cpu_single_step(s->c_cpu, sstep_flags);
}
s->signal = res_signal;
gdb_continue(s);
return RS_IDLE;
goto unknown_command;
}
break;
} else {

View File

@ -7,12 +7,15 @@
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/m68k/mcf.h"
#include "sysemu/char.h"
#include "exec/address-spaces.h"
#include "qapi/error.h"
typedef struct {
SysBusDevice parent_obj;
MemoryRegion iomem;
uint8_t mr[2];
uint8_t sr;
@ -30,6 +33,9 @@ typedef struct {
CharBackend chr;
} mcf_uart_state;
#define TYPE_MCF_UART "mcf-uart"
#define MCF_UART(obj) OBJECT_CHECK(mcf_uart_state, (obj), TYPE_MCF_UART)
/* UART Status Register bits. */
#define MCF_UART_RxRDY 0x01
#define MCF_UART_FFULL 0x02
@ -220,8 +226,10 @@ void mcf_uart_write(void *opaque, hwaddr addr,
mcf_uart_update(s);
}
static void mcf_uart_reset(mcf_uart_state *s)
static void mcf_uart_reset(DeviceState *dev)
{
mcf_uart_state *s = MCF_UART(dev);
s->fifo_len = 0;
s->mr[0] = 0;
s->mr[1] = 0;
@ -275,36 +283,80 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
mcf_uart_push_byte(s, buf[0]);
}
void *mcf_uart_init(qemu_irq irq, Chardev *chr)
{
mcf_uart_state *s;
s = g_malloc0(sizeof(mcf_uart_state));
s->irq = irq;
if (chr) {
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive,
mcf_uart_receive, mcf_uart_event,
s, NULL, true);
}
mcf_uart_reset(s);
return s;
}
static const MemoryRegionOps mcf_uart_ops = {
.read = mcf_uart_read,
.write = mcf_uart_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
void mcf_uart_mm_init(MemoryRegion *sysmem,
hwaddr base,
qemu_irq irq,
Chardev *chr)
static void mcf_uart_instance_init(Object *obj)
{
mcf_uart_state *s;
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
mcf_uart_state *s = MCF_UART(dev);
s = mcf_uart_init(irq, chr);
memory_region_init_io(&s->iomem, NULL, &mcf_uart_ops, s, "uart", 0x40);
memory_region_add_subregion(sysmem, base, &s->iomem);
memory_region_init_io(&s->iomem, obj, &mcf_uart_ops, s, "uart", 0x40);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
}
static void mcf_uart_realize(DeviceState *dev, Error **errp)
{
mcf_uart_state *s = MCF_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s, NULL, true);
}
static Property mcf_uart_properties[] = {
DEFINE_PROP_CHR("chardev", mcf_uart_state, chr),
DEFINE_PROP_END_OF_LIST(),
};
static void mcf_uart_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = mcf_uart_realize;
dc->reset = mcf_uart_reset;
dc->props = mcf_uart_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo mcf_uart_info = {
.name = TYPE_MCF_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mcf_uart_state),
.instance_init = mcf_uart_instance_init,
.class_init = mcf_uart_class_init,
};
static void mcf_uart_register(void)
{
type_register_static(&mcf_uart_info);
}
type_init(mcf_uart_register)
void *mcf_uart_init(qemu_irq irq, Chardev *chrdrv)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_MCF_UART);
if (chrdrv) {
qdev_prop_set_chr(dev, "chardev", chrdrv);
}
qdev_init_nofail(dev);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
return dev;
}
void mcf_uart_mm_init(hwaddr base, qemu_irq irq, Chardev *chrdrv)
{
DeviceState *dev;
dev = mcf_uart_init(irq, chrdrv);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
}

View File

@ -114,11 +114,11 @@ static void kvm_ioapic_put(IOAPICCommonState *s)
void kvm_ioapic_dump_state(Monitor *mon, const QDict *qdict)
{
IOAPICCommonState s;
IOAPICCommonState *s = IOAPIC_COMMON(object_resolve_path("ioapic", NULL));
kvm_ioapic_get(&s);
ioapic_print_redtbl(mon, &s);
assert(s);
kvm_ioapic_get(s);
ioapic_print_redtbl(mon, s);
}
static void kvm_ioapic_reset(DeviceState *dev)
@ -143,6 +143,11 @@ static void kvm_ioapic_realize(DeviceState *dev, Error **errp)
IOAPICCommonState *s = IOAPIC_COMMON(dev);
memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000);
/*
* KVM ioapic only supports 0x11 now. This will only be used when
* we want to dump ioapic version.
*/
s->version = 0x11;
qdev_init_gpio_in(dev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
}

View File

@ -251,6 +251,8 @@ static void apic_reset_common(DeviceState *dev)
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
s->id = s->initial_apic_id;
apic_reset_irq_delivered();
s->vapic_paddr = 0;
info->vapic_base_update(s);

View File

@ -408,13 +408,15 @@ static void ioapic_machine_done_notify(Notifier *notifier, void *data)
#endif
}
#define IOAPIC_VER_DEF 0x20
static void ioapic_realize(DeviceState *dev, Error **errp)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
if (s->version != 0x11 && s->version != 0x20) {
error_report("IOAPIC only supports version 0x11 or 0x20 "
"(default: 0x11).");
"(default: 0x%x).", IOAPIC_VER_DEF);
exit(1);
}
@ -429,7 +431,7 @@ static void ioapic_realize(DeviceState *dev, Error **errp)
}
static Property ioapic_properties[] = {
DEFINE_PROP_UINT8("version", IOAPICCommonState, version, 0x20),
DEFINE_PROP_UINT8("version", IOAPICCommonState, version, IOAPIC_VER_DEF),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -255,9 +255,9 @@ static void mcf5208evb_init(MachineState *machine)
/* Internal peripherals. */
pic = mcf_intc_init(address_space_mem, 0xfc048000, cpu);
mcf_uart_mm_init(address_space_mem, 0xfc060000, pic[26], serial_hds[0]);
mcf_uart_mm_init(address_space_mem, 0xfc064000, pic[27], serial_hds[1]);
mcf_uart_mm_init(address_space_mem, 0xfc068000, pic[28], serial_hds[2]);
mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
mcf5208_sys_init(address_space_mem, pic);

View File

@ -42,7 +42,7 @@ static void handle_event(int event)
}
if (event & PVPANIC_PANICKED) {
qemu_system_guest_panicked();
qemu_system_guest_panicked(NULL);
return;
}
}

View File

@ -334,7 +334,8 @@ static void rtas_ibm_os_term(PowerPCCPU *cpu,
{
target_ulong ret = 0;
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, false, NULL,
&error_abort);
rtas_st(rets, 0, ret);
}

View File

@ -318,6 +318,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
assert(n < ARRAY_SIZE(tb->jmp_list_next));
if (tb->jmp_list_next[n]) {
/* Another thread has already done this while we were
* outside of the lock; nothing to do in this case */

View File

@ -4,17 +4,13 @@
#include "target/m68k/cpu-qom.h"
struct MemoryRegion;
/* mcf_uart.c */
uint64_t mcf_uart_read(void *opaque, hwaddr addr,
unsigned size);
void mcf_uart_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size);
void *mcf_uart_init(qemu_irq irq, Chardev *chr);
void mcf_uart_mm_init(struct MemoryRegion *sysmem,
hwaddr base,
qemu_irq irq, Chardev *chr);
void mcf_uart_mm_init(hwaddr base, qemu_irq irq, Chardev *chr);
/* mcf_intc.c */
qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,

View File

@ -158,6 +158,7 @@ typedef struct CPUClass {
uint8_t *buf, int len, bool is_write);
void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
void (*dump_statistics)(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
int64_t (*get_arch_id)(CPUState *cpu);
@ -471,6 +472,15 @@ int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
void *opaque);
/**
* cpu_get_crash_info:
* @cpu: The CPU to get crash information for
*
* Gets the previously saved crash information.
* Caller is responsible for freeing the data.
*/
GuestPanicInformation *cpu_get_crash_info(CPUState *cpu);
/**
* CPUDumpFlags:
* @CPU_DUMP_CODE:

View File

@ -37,6 +37,7 @@ void vm_state_notify(int running, RunState state);
#define VMRESET_REPORT true
void vm_start(void);
int vm_prepare_start(void);
int vm_stop(RunState state);
int vm_stop_force_state(RunState state);
@ -60,11 +61,12 @@ void qemu_register_powerdown_notifier(Notifier *notifier);
void qemu_system_debug_request(void);
void qemu_system_vmstop_request(RunState reason);
void qemu_system_vmstop_request_prepare(void);
bool qemu_vmstop_requested(RunState *r);
int qemu_shutdown_requested_get(void);
int qemu_reset_requested_get(void);
void qemu_system_killed(int signal, pid_t pid);
void qemu_system_reset(bool report);
void qemu_system_guest_panicked(void);
void qemu_system_guest_panicked(GuestPanicInformation *info);
size_t qemu_target_page_bits(void);
void qemu_add_exit_notifier(Notifier *notify);

View File

@ -2000,8 +2000,9 @@ int kvm_cpu_exec(CPUState *cpu)
ret = EXCP_INTERRUPT;
break;
case KVM_SYSTEM_EVENT_CRASH:
kvm_cpu_synchronize_state(cpu);
qemu_mutex_lock_iothread();
qemu_system_guest_panicked();
qemu_system_guest_panicked(cpu_get_crash_info(cpu));
qemu_mutex_unlock_iothread();
ret = 0;
break;

View File

@ -5870,6 +5870,30 @@
{ 'enum': 'GuestPanicAction',
'data': [ 'pause', 'poweroff' ] }
##
# @GuestPanicInformation:
#
# Information about a guest panic
#
# Since: 2.9
##
{'union': 'GuestPanicInformation',
'data': { 'hyper-v': 'GuestPanicInformationHyperV' } }
##
# @GuestPanicInformationHyperV:
#
# Hyper-V specific guest panic information (HV crash MSRs)
#
# Since: 2.9
##
{'struct': 'GuestPanicInformationHyperV',
'data': { 'arg1': 'uint64',
'arg2': 'uint64',
'arg3': 'uint64',
'arg4': 'uint64',
'arg5': 'uint64' } }
##
# @rtc-reset-reinjection:
#

View File

@ -488,7 +488,9 @@
#
# @action: action that has been taken, currently always "pause"
#
# Since: 1.5
# @info: optional information about a panic
#
# Since: 1.5 (@info since 2.9)
#
# Example:
#
@ -497,7 +499,7 @@
#
##
{ 'event': 'GUEST_PANICKED',
'data': { 'action': 'GuestPanicAction' } }
'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } }
##
# @QUORUM_FAILURE:

View File

@ -463,6 +463,135 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
return creds;
}
static void setup_address_and_port(const char **address, const char **port)
{
if (*address == NULL) {
*address = "0.0.0.0";
}
if (*port == NULL) {
*port = stringify(NBD_DEFAULT_PORT);
}
}
#define FIRST_SOCKET_ACTIVATION_FD 3 /* defined by systemd ABI */
#ifndef _WIN32
/*
* Check if socket activation was requested via use of the
* LISTEN_FDS and LISTEN_PID environment variables.
*
* Returns 0 if no socket activation, or the number of FDs.
*/
static unsigned int check_socket_activation(void)
{
const char *s;
unsigned long pid;
unsigned long nr_fds;
unsigned int i;
int fd;
int err;
s = getenv("LISTEN_PID");
if (s == NULL) {
return 0;
}
err = qemu_strtoul(s, NULL, 10, &pid);
if (err) {
if (verbose) {
fprintf(stderr, "malformed %s environment variable (ignored)\n",
"LISTEN_PID");
}
return 0;
}
if (pid != getpid()) {
if (verbose) {
fprintf(stderr, "%s was not for us (ignored)\n",
"LISTEN_PID");
}
return 0;
}
s = getenv("LISTEN_FDS");
if (s == NULL) {
return 0;
}
err = qemu_strtoul(s, NULL, 10, &nr_fds);
if (err) {
if (verbose) {
fprintf(stderr, "malformed %s environment variable (ignored)\n",
"LISTEN_FDS");
}
return 0;
}
assert(nr_fds <= UINT_MAX);
/* A limitation of current qemu-nbd is that it can only listen on
* a single socket. When that limitation is lifted, we can change
* this function to allow LISTEN_FDS > 1, and remove the assertion
* in the main function below.
*/
if (nr_fds > 1) {
error_report("qemu-nbd does not support socket activation with %s > 1",
"LISTEN_FDS");
exit(EXIT_FAILURE);
}
/* So these are not passed to any child processes we might start. */
unsetenv("LISTEN_FDS");
unsetenv("LISTEN_PID");
/* So the file descriptors don't leak into child processes. */
for (i = 0; i < nr_fds; ++i) {
fd = FIRST_SOCKET_ACTIVATION_FD + i;
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
/* If we cannot set FD_CLOEXEC then it probably means the file
* descriptor is invalid, so socket activation has gone wrong
* and we should exit.
*/
error_report("Socket activation failed: "
"invalid file descriptor fd = %d: %m",
fd);
exit(EXIT_FAILURE);
}
}
return (unsigned int) nr_fds;
}
#else /* !_WIN32 */
static unsigned int check_socket_activation(void)
{
return 0;
}
#endif
/*
* Check socket parameters compatibility when socket activation is used.
*/
static const char *socket_activation_validate_opts(const char *device,
const char *sockpath,
const char *address,
const char *port)
{
if (device != NULL) {
return "NBD device can't be set when using socket activation";
}
if (sockpath != NULL) {
return "Unix socket can't be set when using socket activation";
}
if (address != NULL) {
return "The interface can't be set when using socket activation";
}
if (port != NULL) {
return "TCP port number can't be set when using socket activation";
}
return NULL;
}
int main(int argc, char **argv)
{
@ -471,7 +600,7 @@ int main(int argc, char **argv)
off_t dev_offset = 0;
uint16_t nbdflags = 0;
bool disconnect = false;
const char *bindto = "0.0.0.0";
const char *bindto = NULL;
const char *port = NULL;
char *sockpath = NULL;
char *device = NULL;
@ -533,6 +662,7 @@ int main(int argc, char **argv)
char *trace_file = NULL;
bool fork_process = false;
int old_stderr = -1;
unsigned socket_activation;
/* The client thread uses SIGTERM to interrupt the server. A signal
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
@ -751,6 +881,19 @@ int main(int argc, char **argv)
trace_init_file(trace_file);
qemu_set_log(LOG_TRACE);
socket_activation = check_socket_activation();
if (socket_activation == 0) {
setup_address_and_port(&bindto, &port);
} else {
/* Using socket activation - check user didn't use -p etc. */
const char *err_msg = socket_activation_validate_opts(device, sockpath,
bindto, port);
if (err_msg != NULL) {
error_report("%s", err_msg);
exit(EXIT_FAILURE);
}
}
if (tlscredsid) {
if (sockpath) {
error_report("TLS is only supported with IPv4/IPv6");
@ -855,7 +998,25 @@ int main(int argc, char **argv)
snprintf(sockpath, 128, SOCKET_PATH, basename(device));
}
saddr = nbd_build_socket_address(sockpath, bindto, port);
if (socket_activation == 0) {
server_ioc = qio_channel_socket_new();
saddr = nbd_build_socket_address(sockpath, bindto, port);
if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) {
object_unref(OBJECT(server_ioc));
error_report_err(local_err);
return 1;
}
} else {
/* See comment in check_socket_activation above. */
assert(socket_activation == 1);
server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD,
&local_err);
if (server_ioc == NULL) {
error_report("Failed to use socket activation: %s",
error_get_pretty(local_err));
exit(EXIT_FAILURE);
}
}
if (qemu_init_main_loop(&local_err)) {
error_report_err(local_err);
@ -950,13 +1111,6 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
server_ioc = qio_channel_socket_new();
if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) {
object_unref(OBJECT(server_ioc));
error_report_err(local_err);
return 1;
}
if (device) {
int ret;

View File

@ -1194,12 +1194,12 @@ Select type of VGA card to emulate. Valid values for @var{type} are
Cirrus Logic GD5446 Video card. All Windows versions starting from
Windows 95 should recognize and use this graphic card. For optimal
performances, use 16 bit color depth in the guest and the host OS.
(This one is the default)
(This card was the default before QEMU 2.2)
@item std
Standard VGA card with Bochs VBE extensions. If your guest OS
supports the VESA 2.0 VBE extensions (e.g. Windows XP) and if you want
to use high resolution modes (>= 1280x1024x16) then you should use
this option.
this option. (This card is the default since QEMU 2.2)
@item vmware
VMWare SVGA-II compatible adapter. Use it if you have sufficiently
recent XFree86/XOrg server or Windows guest with a driver for this

View File

@ -218,6 +218,17 @@ static bool cpu_common_exec_interrupt(CPUState *cpu, int int_req)
return false;
}
GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
GuestPanicInformation *res = NULL;
if (cc->get_crash_info) {
res = cc->get_crash_info(cpu);
}
return res;
}
void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags)
{

View File

@ -3495,6 +3495,53 @@ static void x86_cpu_register_feature_bit_props(X86CPU *cpu,
x86_cpu_register_bit_prop(cpu, name, &cpu->env.features[w], bitnr);
}
static GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
GuestPanicInformation *panic_info = NULL;
if (env->features[FEAT_HYPERV_EDX] & HV_X64_GUEST_CRASH_MSR_AVAILABLE) {
GuestPanicInformationHyperV *panic_info_hv =
g_malloc0(sizeof(GuestPanicInformationHyperV));
panic_info = g_malloc0(sizeof(GuestPanicInformation));
panic_info->type = GUEST_PANIC_INFORMATION_KIND_HYPER_V;
panic_info->u.hyper_v.data = panic_info_hv;
assert(HV_X64_MSR_CRASH_PARAMS >= 5);
panic_info_hv->arg1 = env->msr_hv_crash_params[0];
panic_info_hv->arg2 = env->msr_hv_crash_params[1];
panic_info_hv->arg3 = env->msr_hv_crash_params[2];
panic_info_hv->arg4 = env->msr_hv_crash_params[3];
panic_info_hv->arg5 = env->msr_hv_crash_params[4];
}
return panic_info;
}
static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v,
const char *name, void *opaque,
Error **errp)
{
CPUState *cs = CPU(obj);
GuestPanicInformation *panic_info;
if (!cs->crash_occurred) {
error_setg(errp, "No crash occured");
return;
}
panic_info = x86_cpu_get_crash_info(cs);
if (panic_info == NULL) {
error_setg(errp, "No crash information");
return;
}
visit_type_GuestPanicInformation(v, "crash-information", &panic_info,
errp);
qapi_free_GuestPanicInformation(panic_info);
}
static void x86_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
@ -3530,6 +3577,9 @@ static void x86_cpu_initfn(Object *obj)
x86_cpu_get_feature_words,
NULL, NULL, (void *)cpu->filtered_features, NULL);
object_property_add(obj, "crash-information", "GuestPanicInformation",
x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
for (w = 0; w < FEATURE_WORDS; w++) {
@ -3684,6 +3734,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->do_interrupt = x86_cpu_do_interrupt;
cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
cc->dump_state = x86_cpu_dump_state;
cc->get_crash_info = x86_cpu_get_crash_info;
cc->set_pc = x86_cpu_set_pc;
cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
cc->gdb_read_register = x86_cpu_gdb_read_register;

View File

@ -1621,8 +1621,9 @@ void helper_lock_init(void);
/* svm_helper.c */
void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type,
uint64_t param);
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1);
uint64_t param, uintptr_t retaddr);
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1,
uintptr_t retaddr);
/* seg_helper.c */
void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw);

View File

@ -39,7 +39,8 @@ void helper_raise_exception(CPUX86State *env, int exception_index)
* needed. It should only be called, if this is not an interrupt.
* Returns the new exception number.
*/
static int check_exception(CPUX86State *env, int intno, int *error_code)
static int check_exception(CPUX86State *env, int intno, int *error_code,
uintptr_t retaddr)
{
int first_contributory = env->old_exception == 0 ||
(env->old_exception >= 10 &&
@ -53,7 +54,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code)
#if !defined(CONFIG_USER_ONLY)
if (env->old_exception == EXCP08_DBLE) {
if (env->hflags & HF_SVMI_MASK) {
cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0); /* does not return */
cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */
}
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
@ -93,10 +94,10 @@ static void QEMU_NORETURN raise_interrupt2(CPUX86State *env, int intno,
if (!is_int) {
cpu_svm_check_intercept_param(env, SVM_EXIT_EXCP_BASE + intno,
error_code);
intno = check_exception(env, intno, &error_code);
error_code, retaddr);
intno = check_exception(env, intno, &error_code, retaddr);
} else {
cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_SWINT, 0, retaddr);
}
cs->exception_index = intno;

View File

@ -99,7 +99,6 @@ DEF_HELPER_2(inl, tl, env, i32)
DEF_HELPER_FLAGS_4(bpt_io, TCG_CALL_NO_WG, void, env, i32, i32, tl)
DEF_HELPER_3(svm_check_intercept_param, void, env, i32, i64)
DEF_HELPER_3(vmexit, void, env, i32, i64)
DEF_HELPER_4(svm_check_io, void, env, i32, i32, i32)
DEF_HELPER_3(vmrun, void, env, int, int)
DEF_HELPER_1(vmmcall, void, env)

View File

@ -101,7 +101,7 @@ void helper_cpuid(CPUX86State *env)
{
uint32_t eax, ebx, ecx, edx;
cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_CPUID, 0, GETPC());
cpu_x86_cpuid(env, (uint32_t)env->regs[R_EAX], (uint32_t)env->regs[R_ECX],
&eax, &ebx, &ecx, &edx);
@ -125,7 +125,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
{
target_ulong val;
cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_READ_CR0 + reg, 0, GETPC());
switch (reg) {
default:
val = env->cr[reg];
@ -143,7 +143,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_WRITE_CR0 + reg, 0, GETPC());
switch (reg) {
case 0:
cpu_x86_update_cr0(env, t0);
@ -179,7 +179,7 @@ void helper_invlpg(CPUX86State *env, target_ulong addr)
{
X86CPU *cpu = x86_env_get_cpu(env);
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0, GETPC());
tlb_flush_page(CPU(cpu), addr);
}
@ -190,7 +190,7 @@ void helper_rdtsc(CPUX86State *env)
if ((env->cr[4] & CR4_TSD_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_RDTSC, 0, GETPC());
val = cpu_get_tsc(env) + env->tsc_offset;
env->regs[R_EAX] = (uint32_t)(val);
@ -208,7 +208,7 @@ void helper_rdpmc(CPUX86State *env)
if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) {
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_RDPMC, 0, GETPC());
/* currently unimplemented */
qemu_log_mask(LOG_UNIMP, "x86: unimplemented rdpmc\n");
@ -228,7 +228,7 @@ void helper_wrmsr(CPUX86State *env)
{
uint64_t val;
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1);
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
val = ((uint32_t)env->regs[R_EAX]) |
((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
@ -388,7 +388,7 @@ void helper_rdmsr(CPUX86State *env)
{
uint64_t val;
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
switch ((uint32_t)env->regs[R_ECX]) {
case MSR_IA32_SYSENTER_CS:
@ -557,7 +557,7 @@ void helper_hlt(CPUX86State *env, int next_eip_addend)
{
X86CPU *cpu = x86_env_get_cpu(env);
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_HLT, 0, GETPC());
env->eip += next_eip_addend;
do_hlt(cpu);
@ -569,7 +569,7 @@ void helper_monitor(CPUX86State *env, target_ulong ptr)
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
/* XXX: store address? */
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_MONITOR, 0, GETPC());
}
void helper_mwait(CPUX86State *env, int next_eip_addend)
@ -580,7 +580,7 @@ void helper_mwait(CPUX86State *env, int next_eip_addend)
if ((uint32_t)env->regs[R_ECX] != 0) {
raise_exception_ra(env, EXCP0D_GPF, GETPC());
}
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_MWAIT, 0, GETPC());
env->eip += next_eip_addend;
cpu = x86_env_get_cpu(env);
@ -597,7 +597,7 @@ void helper_pause(CPUX86State *env, int next_eip_addend)
{
X86CPU *cpu = x86_env_get_cpu(env);
cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_PAUSE, 0, GETPC());
env->eip += next_eip_addend;
do_pause(cpu);

View File

@ -1335,7 +1335,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
} else if (env->hflags2 & HF2_GIF_MASK) {
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0, 0);
cs->interrupt_request &= ~CPU_INTERRUPT_SMI;
do_smm_enter(cpu);
ret = true;
@ -1356,7 +1356,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
(env->eflags & IF_MASK &&
!(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
int intno;
cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_INTR, 0, 0);
cs->interrupt_request &= ~(CPU_INTERRUPT_HARD |
CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
@ -1372,7 +1372,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
/* FIXME: this should respect TPR */
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_VINTR, 0, 0);
intno = x86_ldl_phys(cs, env->vm_vmcb
+ offsetof(struct vmcb, control.int_vector));
qemu_log_mask(CPU_LOG_TB_IN_ASM,

View File

@ -60,11 +60,8 @@ void helper_invlpga(CPUX86State *env, int aflag)
{
}
void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
{
}
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1)
void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1,
uintptr_t retaddr)
{
}
@ -74,7 +71,7 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
}
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
uint64_t param, uintptr_t retaddr)
{
}
@ -130,7 +127,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
uint32_t event_inj;
uint32_t int_ctl;
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_VMRUN, 0, GETPC());
if (aflag == 2) {
addr = env->regs[R_EAX];
@ -355,7 +352,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
void helper_vmmcall(CPUX86State *env)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_VMMCALL, 0, GETPC());
raise_exception(env, EXCP06_ILLOP);
}
@ -364,7 +361,7 @@ void helper_vmload(CPUX86State *env, int aflag)
CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_VMLOAD, 0, GETPC());
if (aflag == 2) {
addr = env->regs[R_EAX];
@ -404,7 +401,7 @@ void helper_vmsave(CPUX86State *env, int aflag)
CPUState *cs = CPU(x86_env_get_cpu(env));
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_VMSAVE, 0, GETPC());
if (aflag == 2) {
addr = env->regs[R_EAX];
@ -445,19 +442,19 @@ void helper_vmsave(CPUX86State *env, int aflag)
void helper_stgi(CPUX86State *env)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_STGI, 0, GETPC());
env->hflags2 |= HF2_GIF_MASK;
}
void helper_clgi(CPUX86State *env)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_CLGI, 0, GETPC());
env->hflags2 &= ~HF2_GIF_MASK;
}
void helper_skinit(CPUX86State *env)
{
cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_SKINIT, 0, GETPC());
/* XXX: not implemented */
raise_exception(env, EXCP06_ILLOP);
}
@ -467,7 +464,7 @@ void helper_invlpga(CPUX86State *env, int aflag)
X86CPU *cpu = x86_env_get_cpu(env);
target_ulong addr;
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0);
cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPGA, 0, GETPC());
if (aflag == 2) {
addr = env->regs[R_EAX];
@ -480,8 +477,8 @@ void helper_invlpga(CPUX86State *env, int aflag)
tlb_flush_page(CPU(cpu), addr);
}
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param, uintptr_t retaddr)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
@ -491,27 +488,27 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
switch (type) {
case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8:
if (env->intercept_cr_read & (1 << (type - SVM_EXIT_READ_CR0))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8:
if (env->intercept_cr_write & (1 << (type - SVM_EXIT_WRITE_CR0))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 7:
if (env->intercept_dr_read & (1 << (type - SVM_EXIT_READ_DR0))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 7:
if (env->intercept_dr_write & (1 << (type - SVM_EXIT_WRITE_DR0))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 31:
if (env->intercept_exceptions & (1 << (type - SVM_EXIT_EXCP_BASE))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
case SVM_EXIT_MSR:
@ -538,28 +535,28 @@ void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
t0 %= 8;
break;
default:
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
t0 = 0;
t1 = 0;
break;
}
if (x86_ldub_phys(cs, addr + t1) & ((1 << param) << t0)) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
}
break;
default:
if (env->intercept & (1ULL << (type - SVM_EXIT_INTR))) {
helper_vmexit(env, type, param);
cpu_vmexit(env, type, param, retaddr);
}
break;
}
}
void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type,
uint64_t param)
{
helper_svm_check_intercept_param(env, type, param);
cpu_svm_check_intercept_param(env, type, param, GETPC());
}
void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
@ -578,17 +575,22 @@ void helper_svm_check_io(CPUX86State *env, uint32_t port, uint32_t param,
x86_stq_phys(cs,
env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2),
env->eip + next_eip_addend);
helper_vmexit(env, SVM_EXIT_IOIO, param | (port << 16));
cpu_vmexit(env, SVM_EXIT_IOIO, param | (port << 16), GETPC());
}
}
}
/* Note: currently only 32 bits of exit_code are used */
void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1,
uintptr_t retaddr)
{
CPUState *cs = CPU(x86_env_get_cpu(env));
uint32_t int_ctl;
if (retaddr) {
cpu_restore_state(cs, retaddr);
}
qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016"
PRIx64 ", " TARGET_FMT_lx ")!\n",
exit_code, exit_info_1,
@ -766,9 +768,4 @@ void helper_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
cpu_loop_exit(cs);
}
void cpu_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1)
{
helper_vmexit(env, exit_code, exit_info_1);
}
#endif

View File

@ -1864,7 +1864,7 @@ static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
s390_cpu_halt(cpu);
qemu_system_guest_panicked();
qemu_system_guest_panicked(NULL);
}
static int handle_intercept(S390CPU *cpu)
@ -1897,7 +1897,7 @@ static int handle_intercept(S390CPU *cpu)
if (is_special_wait_psw(cs)) {
qemu_system_shutdown_request();
} else {
qemu_system_guest_panicked();
qemu_system_guest_panicked(NULL);
}
}
r = EXCP_HALTED;

View File

@ -33,17 +33,6 @@
static char temp_file[] = "/tmp/vmst.test.XXXXXX";
static int temp_fd;
/* Fake yield_until_fd_readable() implementation so we don't have to pull the
* coroutine code as dependency.
*/
void yield_until_fd_readable(int fd)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
select(fd + 1, &fds, NULL, NULL, NULL);
}
/* Duplicate temp_fd and seek to the beginning of the file */
static QEMUFile *open_test_file(bool write)

56
vl.c
View File

@ -724,7 +724,7 @@ StatusInfo *qmp_query_status(Error **errp)
return info;
}
static bool qemu_vmstop_requested(RunState *r)
bool qemu_vmstop_requested(RunState *r)
{
qemu_mutex_lock(&vmstop_lock);
*r = vmstop_requested;
@ -745,34 +745,6 @@ void qemu_system_vmstop_request(RunState state)
qemu_notify_event();
}
void vm_start(void)
{
RunState requested;
qemu_vmstop_requested(&requested);
if (runstate_is_running() && requested == RUN_STATE__MAX) {
return;
}
/* Ensure that a STOP/RESUME pair of events is emitted if a
* vmstop request was pending. The BLOCK_IO_ERROR event, for
* example, according to documentation is always followed by
* the STOP event.
*/
if (runstate_is_running()) {
qapi_event_send_stop(&error_abort);
} else {
replay_enable_events();
cpu_enable_ticks();
runstate_set(RUN_STATE_RUNNING);
vm_state_notify(1, RUN_STATE_RUNNING);
resume_all_vcpus();
}
qapi_event_send_resume(&error_abort);
}
/***********************************************************/
/* real time host monotonic timer */
@ -1707,18 +1679,34 @@ void qemu_system_reset(bool report)
cpu_synchronize_all_post_reset();
}
void qemu_system_guest_panicked(void)
void qemu_system_guest_panicked(GuestPanicInformation *info)
{
qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed\n");
if (current_cpu) {
current_cpu->crash_occurred = true;
}
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
!!info, info, &error_abort);
vm_stop(RUN_STATE_GUEST_PANICKED);
if (!no_shutdown) {
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
&error_abort);
!!info, info, &error_abort);
qemu_system_shutdown_request();
}
if (info) {
if (info->type == GUEST_PANIC_INFORMATION_KIND_HYPER_V) {
qemu_log_mask(LOG_GUEST_ERROR, "HV crash parameters: (%#"PRIx64
" %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
info->u.hyper_v.data->arg1,
info->u.hyper_v.data->arg2,
info->u.hyper_v.data->arg3,
info->u.hyper_v.data->arg4,
info->u.hyper_v.data->arg5);
}
qapi_free_GuestPanicInformation(info);
}
}
void qemu_system_reset_request(void)
@ -4490,8 +4478,6 @@ int main(int argc, char **argv, char **envp)
audio_init();
cpu_synchronize_all_post_init();
if (hax_enabled()) {
hax_sync_vcpus();
}
@ -4517,6 +4503,8 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
cpu_synchronize_all_post_init();
numa_post_machine_init();
rom_reset_order_override();