Commit 31b7c261 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote branch 'qemu-kvm/uq/master' into staging

parents 8b06c62a dc7a09cf
......@@ -863,10 +863,14 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
extern int phys_ram_fd;
extern ram_addr_t ram_size;
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
#define RAM_PREALLOC_MASK (1 << 0)
typedef struct RAMBlock {
uint8_t *host;
ram_addr_t offset;
ram_addr_t length;
uint32_t flags;
char idstr[256];
QLIST_ENTRY(RAMBlock) next;
#if defined(__linux__) && !defined(TARGET_S390X)
......@@ -971,8 +975,4 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
int broadcast);
#endif /* CPU_ALL_H */
......@@ -50,6 +50,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
ram_addr_t size, void *host);
ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
void qemu_ram_free(ram_addr_t addr);
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
/* This should only be used for ram local to a device. */
void *qemu_get_ram_ptr(ram_addr_t addr);
/* Same but slower, to use for migration, where the order of
......
......@@ -203,6 +203,7 @@ typedef struct CPUWatchpoint {
int nr_cores; /* number of cores within this CPU package */ \
int nr_threads;/* number of threads within this CPU */ \
int running; /* Nonzero if cpu is currently running(usermode). */ \
int thread_id; \
/* user data */ \
void *opaque; \
\
......
......@@ -196,6 +196,30 @@ static inline TranslationBlock *tb_find_fast(void)
return tb;
}
static CPUDebugExcpHandler *debug_excp_handler;
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
{
CPUDebugExcpHandler *old_handler = debug_excp_handler;
debug_excp_handler = handler;
return old_handler;
}
static void cpu_handle_debug_exception(CPUState *env)
{
CPUWatchpoint *wp;
if (!env->watchpoint_hit) {
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
wp->flags &= ~BP_WATCHPOINT_HIT;
}
}
if (debug_excp_handler) {
debug_excp_handler(env);
}
}
/* main execution loop */
volatile sig_atomic_t exit_request;
......@@ -269,6 +293,9 @@ int cpu_exec(CPUState *env1)
if (env->exception_index >= EXCP_INTERRUPT) {
/* exit request from the cpu execution loop */
ret = env->exception_index;
if (ret == EXCP_DEBUG) {
cpu_handle_debug_exception(env);
}
break;
} else {
#if defined(CONFIG_USER_ONLY)
......
......@@ -148,7 +148,8 @@ static bool cpu_thread_is_idle(CPUState *env)
if (env->stopped || !vm_running) {
return true;
}
if (!env->halted || qemu_cpu_has_work(env)) {
if (!env->halted || qemu_cpu_has_work(env) ||
(kvm_enabled() && kvm_irqchip_in_kernel())) {
return false;
}
return true;
......@@ -166,29 +167,8 @@ static bool all_cpu_threads_idle(void)
return true;
}
static CPUDebugExcpHandler *debug_excp_handler;
CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler)
static void cpu_handle_guest_debug(CPUState *env)
{
CPUDebugExcpHandler *old_handler = debug_excp_handler;
debug_excp_handler = handler;
return old_handler;
}
static void cpu_handle_debug_exception(CPUState *env)
{
CPUWatchpoint *wp;
if (!env->watchpoint_hit) {
QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
wp->flags &= ~BP_WATCHPOINT_HIT;
}
}
if (debug_excp_handler) {
debug_excp_handler(env);
}
gdb_set_stop_cpu(env);
qemu_system_debug_request();
#ifdef CONFIG_IOTHREAD
......@@ -245,11 +225,58 @@ static void qemu_init_sigbus(void)
prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
}
static void qemu_kvm_eat_signals(CPUState *env)
{
struct timespec ts = { 0, 0 };
siginfo_t siginfo;
sigset_t waitset;
sigset_t chkset;
int r;
sigemptyset(&waitset);
sigaddset(&waitset, SIG_IPI);
sigaddset(&waitset, SIGBUS);
do {
r = sigtimedwait(&waitset, &siginfo, &ts);
if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
perror("sigtimedwait");
exit(1);
}
switch (r) {
case SIGBUS:
if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
sigbus_reraise();
}
break;
default:
break;
}
r = sigpending(&chkset);
if (r == -1) {
perror("sigpending");
exit(1);
}
} while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
#ifndef CONFIG_IOTHREAD
if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
qemu_notify_event();
}
#endif
}
#else /* !CONFIG_LINUX */
static void qemu_init_sigbus(void)
{
}
static void qemu_kvm_eat_signals(CPUState *env)
{
}
#endif /* !CONFIG_LINUX */
#ifndef _WIN32
......@@ -455,49 +482,6 @@ static void qemu_tcg_init_cpu_signals(void)
#endif
}
static void qemu_kvm_eat_signals(CPUState *env)
{
struct timespec ts = { 0, 0 };
siginfo_t siginfo;
sigset_t waitset;
sigset_t chkset;
int r;
sigemptyset(&waitset);
sigaddset(&waitset, SIG_IPI);
sigaddset(&waitset, SIGBUS);
do {
r = sigtimedwait(&waitset, &siginfo, &ts);
if (r == -1 && !(errno == EAGAIN || errno == EINTR)) {
perror("sigtimedwait");
exit(1);
}
switch (r) {
case SIGBUS:
if (kvm_on_sigbus_vcpu(env, siginfo.si_code, siginfo.si_addr)) {
sigbus_reraise();
}
break;
default:
break;
}
r = sigpending(&chkset);
if (r == -1) {
perror("sigpending");
exit(1);
}
} while (sigismember(&chkset, SIG_IPI) || sigismember(&chkset, SIGBUS));
#ifndef CONFIG_IOTHREAD
if (sigismember(&chkset, SIGIO) || sigismember(&chkset, SIGALRM)) {
qemu_notify_event();
}
#endif
}
#else /* _WIN32 */
HANDLE qemu_event_handle;
......@@ -526,10 +510,6 @@ static void qemu_event_increment(void)
}
}
static void qemu_kvm_eat_signals(CPUState *env)
{
}
static int qemu_signal_init(void)
{
return 0;
......@@ -796,6 +776,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_get_self(env->thread);
env->thread_id = qemu_get_thread_id();
r = kvm_init_vcpu(env);
if (r < 0) {
......@@ -818,7 +799,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
if (cpu_can_run(env)) {
r = kvm_cpu_exec(env);
if (r == EXCP_DEBUG) {
cpu_handle_debug_exception(env);
cpu_handle_guest_debug(env);
}
}
qemu_kvm_wait_io_event(env);
......@@ -837,6 +818,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
for (env = first_cpu; env != NULL; env = env->next_cpu) {
env->thread_id = qemu_get_thread_id();
env->created = 1;
}
qemu_cond_signal(&qemu_cpu_cond);
......@@ -1110,7 +1092,7 @@ bool cpu_exec_all(void)
r = tcg_cpu_exec(env);
}
if (r == EXCP_DEBUG) {
cpu_handle_debug_exception(env);
cpu_handle_guest_debug(env);
break;
}
} else if (env->stop || env->stopped) {
......
......@@ -638,6 +638,9 @@ void cpu_exec_init(CPUState *env)
env->numa_node = 0;
QTAILQ_INIT(&env->breakpoints);
QTAILQ_INIT(&env->watchpoints);
#ifndef CONFIG_USER_ONLY
env->thread_id = qemu_get_thread_id();
#endif
*penv = env;
#if defined(CONFIG_USER_ONLY)
cpu_list_unlock();
......@@ -2867,6 +2870,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
if (host) {
new_block->host = host;
new_block->flags |= RAM_PREALLOC_MASK;
} else {
if (mem_path) {
#if defined (__linux__) && !defined(TARGET_S390X)
......@@ -2920,7 +2924,9 @@ void qemu_ram_free(ram_addr_t addr)
QLIST_FOREACH(block, &ram_list.blocks, next) {
if (addr == block->offset) {
QLIST_REMOVE(block, next);
if (mem_path) {
if (block->flags & RAM_PREALLOC_MASK) {
;
} else if (mem_path) {
#if defined (__linux__) && !defined(TARGET_S390X)
if (block->fd) {
munmap(block->host, block->length);
......@@ -2928,6 +2934,8 @@ void qemu_ram_free(ram_addr_t addr)
} else {
qemu_vfree(block->host);
}
#else
abort();
#endif
} else {
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
......@@ -2943,6 +2951,66 @@ void qemu_ram_free(ram_addr_t addr)
}
#ifndef _WIN32
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
{
RAMBlock *block;
ram_addr_t offset;
int flags;
void *area, *vaddr;
QLIST_FOREACH(block, &ram_list.blocks, next) {
offset = addr - block->offset;
if (offset < block->length) {
vaddr = block->host + offset;
if (block->flags & RAM_PREALLOC_MASK) {
;
} else {
flags = MAP_FIXED;
munmap(vaddr, length);
if (mem_path) {
#if defined(__linux__) && !defined(TARGET_S390X)
if (block->fd) {
#ifdef MAP_POPULATE
flags |= mem_prealloc ? MAP_POPULATE | MAP_SHARED :
MAP_PRIVATE;
#else
flags |= MAP_PRIVATE;
#endif
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
flags, block->fd, offset);
} else {
flags |= MAP_PRIVATE | MAP_ANONYMOUS;
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
flags, -1, 0);
}
#else
abort();
#endif
} else {
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
flags |= MAP_SHARED | MAP_ANONYMOUS;
area = mmap(vaddr, length, PROT_EXEC|PROT_READ|PROT_WRITE,
flags, -1, 0);
#else
flags |= MAP_PRIVATE | MAP_ANONYMOUS;
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
flags, -1, 0);
#endif
}
if (area != vaddr) {
fprintf(stderr, "Could not remap addr: %lx@%lx\n",
length, addr);
exit(1);
}
qemu_madvise(vaddr, length, QEMU_MADV_MERGEABLE);
}
return;
}
}
}
#endif /* !_WIN32 */
/* Return a host pointer to ram allocated with qemu_ram_alloc.
With the exception of the softmmu code in this file, this should
only be used for local memory (e.g. video ram) that the device owns,
......
......@@ -211,6 +211,7 @@ int kvm_init_vcpu(CPUState *env)
env->kvm_fd = ret;
env->kvm_state = s;
env->kvm_vcpu_dirty = 1;
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size < 0) {
......@@ -830,7 +831,7 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
fprintf(stderr, "emulation failure\n");
if (!kvm_arch_stop_on_emulation_error(env)) {
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
return 0;
return EXCP_INTERRUPT;
}
}
/* FIXME: Should trigger a qmp message to let management know
......@@ -889,11 +890,11 @@ void kvm_cpu_synchronize_post_init(CPUState *env)
int kvm_cpu_exec(CPUState *env)
{
struct kvm_run *run = env->kvm_run;
int ret;
int ret, run_ret;
DPRINTF("kvm_cpu_exec()\n");
if (kvm_arch_process_irqchip_events(env)) {
if (kvm_arch_process_async_events(env)) {
env->exit_request = 0;
return EXCP_HLT;
}
......@@ -919,7 +920,7 @@ int kvm_cpu_exec(CPUState *env)
cpu_single_env = NULL;
qemu_mutex_unlock_iothread();
ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
qemu_mutex_lock_iothread();
cpu_single_env = env;
......@@ -927,18 +928,16 @@ int kvm_cpu_exec(CPUState *env)
kvm_flush_coalesced_mmio_buffer();
if (ret == -EINTR || ret == -EAGAIN) {
DPRINTF("io window exit\n");
ret = 0;
break;
}
if (ret < 0) {
DPRINTF("kvm run failed %s\n", strerror(-ret));
if (run_ret < 0) {
if (run_ret == -EINTR || run_ret == -EAGAIN) {
DPRINTF("io window exit\n");
ret = EXCP_INTERRUPT;
break;
}
DPRINTF("kvm run failed %s\n", strerror(-run_ret));
abort();
}
ret = 0; /* exit loop */
switch (run->exit_reason) {
case KVM_EXIT_IO:
DPRINTF("handle_io\n");
......@@ -947,7 +946,7 @@ int kvm_cpu_exec(CPUState *env)
run->io.direction,
run->io.size,
run->io.count);
ret = 1;
ret = 0;
break;
case KVM_EXIT_MMIO:
DPRINTF("handle_mmio\n");
......@@ -955,14 +954,16 @@ int kvm_cpu_exec(CPUState *env)
run->mmio.data,
run->mmio.len,
run->mmio.is_write);
ret = 1;
ret = 0;
break;
case KVM_EXIT_IRQ_WINDOW_OPEN:
DPRINTF("irq_window_open\n");
ret = EXCP_INTERRUPT;
break;
case KVM_EXIT_SHUTDOWN:
DPRINTF("shutdown\n");
qemu_system_reset_request();
ret = EXCP_INTERRUPT;
break;
case KVM_EXIT_UNKNOWN:
fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
......@@ -974,31 +975,18 @@ int kvm_cpu_exec(CPUState *env)
ret = kvm_handle_internal_error(env, run);
break;
#endif
case KVM_EXIT_DEBUG:
DPRINTF("kvm_exit_debug\n");
#ifdef KVM_CAP_SET_GUEST_DEBUG
if (kvm_arch_debug(&run->debug.arch)) {
ret = EXCP_DEBUG;
goto out;
}
/* re-enter, this exception was guest-internal */
ret = 1;
#endif /* KVM_CAP_SET_GUEST_DEBUG */
break;
default:
DPRINTF("kvm_arch_handle_exit\n");
ret = kvm_arch_handle_exit(env, run);
break;
}
} while (ret > 0);
} while (ret == 0);
if (ret < 0) {
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
vm_stop(VMSTOP_PANIC);
}
ret = EXCP_INTERRUPT;
out:
env->exit_request = 0;
cpu_single_env = NULL;
return ret;
......
......@@ -102,7 +102,7 @@ void kvm_arch_post_run(CPUState *env, struct kvm_run *run);
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
int kvm_arch_process_irqchip_events(CPUState *env);
int kvm_arch_process_async_events(CPUState *env);
int kvm_arch_get_registers(CPUState *env);
......@@ -136,8 +136,6 @@ struct kvm_sw_breakpoint {
QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info);
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
target_ulong pc);
......
......@@ -897,6 +897,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
monitor_printf(mon, " (halted)");
}
monitor_printf(mon, " thread_id=%" PRId64 " ",
qdict_get_int(cpu, "thread_id"));
monitor_printf(mon, "\n");
}
......@@ -941,6 +944,7 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
#elif defined(TARGET_MIPS)
qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
#endif
qdict_put(cpu, "thread_id", qint_from_int(env->thread_id));
qlist_append(cpu_list, cpu);
}
......@@ -2709,12 +2713,15 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
uint64_t addr = qdict_get_int(qdict, "addr");
uint64_t misc = qdict_get_int(qdict, "misc");
int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
int flags = MCE_INJECT_UNCOND_AO;
if (qdict_get_try_bool(qdict, "broadcast", 0)) {
flags |= MCE_INJECT_BROADCAST;
}
for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc,
broadcast);
if (cenv->cpu_index == cpu_index) {
cpu_x86_inject_mce(mon, cenv, bank, status, mcg_status, addr, misc,
flags);
break;
}
}
......
......@@ -41,6 +41,7 @@
#ifdef CONFIG_LINUX
#include <sys/prctl.h>
#include <sys/syscall.h>
#endif
#ifdef CONFIG_EVENTFD
......@@ -382,3 +383,12 @@ int qemu_create_pidfile(const char *filename)
return 0;
}
int qemu_get_thread_id(void)
{
#if defined (__linux__)
return syscall(SYS_gettid);
#else
return getpid();
#endif
}
......@@ -266,3 +266,8 @@ int qemu_create_pidfile(const char *filename)
}
return 0;
}
int qemu_get_thread_id(void)
{
return GetCurrentThreadId();
}
......@@ -128,6 +128,7 @@ void qemu_vfree(void *ptr);
int qemu_madvise(void *addr, size_t len, int advice);
int qemu_create_pidfile(const char *filename);
int qemu_get_thread_id(void);
#ifdef _WIN32
static inline void qemu_timersub(const struct timeval *val1,
......
......@@ -18,6 +18,9 @@ typedef struct QEMUFile QEMUFile;
typedef struct QEMUBH QEMUBH;
typedef struct DeviceState DeviceState;
struct Monitor;
typedef struct Monitor Monitor;
/* we put basic includes here to avoid repeating them in device drivers */
#include <stdlib.h>
#include <stdio.h>
......@@ -327,9 +330,6 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count);
void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count,
size_t skip);
struct Monitor;
typedef struct Monitor Monitor;
/* Convert a byte between binary and BCD. */
static inline uint8_t to_bcd(uint8_t val)
{
......
......@@ -1194,6 +1194,7 @@ Return a json-array. Each CPU is represented by a json-object, which contains:
"nip": PPC (json-int)
"pc" and "npc": sparc (json-int)
"PC": mips (json-int)
- "thread_id": ID of the underlying host thread (json-int)
Example:
......@@ -1205,12 +1206,14 @@ Example:
"current":true,
"halted":false,
"pc":3227107138
"thread_id":3134
},
{
"CPU":1,
"current":false,
"halted":true,
"pc":7108165
"thread_id":3135
}