mirror of
https://github.com/qemu/qemu.git
synced 2024-11-29 14:53:35 +08:00
Merge remote branch 'qemu-kvm/uq/master' into pulls
This commit is contained in:
commit
f374e826e3
@ -847,6 +847,9 @@ extern uint8_t *phys_ram_dirty;
|
|||||||
extern ram_addr_t ram_size;
|
extern ram_addr_t ram_size;
|
||||||
extern ram_addr_t last_ram_offset;
|
extern ram_addr_t last_ram_offset;
|
||||||
|
|
||||||
|
extern const char *mem_path;
|
||||||
|
extern int mem_prealloc;
|
||||||
|
|
||||||
/* physical memory access */
|
/* physical memory access */
|
||||||
|
|
||||||
/* MMIO pages are identified by a combination of an IO device index and
|
/* MMIO pages are identified by a combination of an IO device index and
|
||||||
|
134
exec.c
134
exec.c
@ -512,21 +512,6 @@ void cpu_exec_init_all(unsigned long tb_size)
|
|||||||
|
|
||||||
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
|
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
static void cpu_common_pre_save(void *opaque)
|
|
||||||
{
|
|
||||||
CPUState *env = opaque;
|
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu_common_pre_load(void *opaque)
|
|
||||||
{
|
|
||||||
CPUState *env = opaque;
|
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu_common_post_load(void *opaque, int version_id)
|
static int cpu_common_post_load(void *opaque, int version_id)
|
||||||
{
|
{
|
||||||
CPUState *env = opaque;
|
CPUState *env = opaque;
|
||||||
@ -544,8 +529,6 @@ static const VMStateDescription vmstate_cpu_common = {
|
|||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.minimum_version_id_old = 1,
|
.minimum_version_id_old = 1,
|
||||||
.pre_save = cpu_common_pre_save,
|
|
||||||
.pre_load = cpu_common_pre_load,
|
|
||||||
.post_load = cpu_common_post_load,
|
.post_load = cpu_common_post_load,
|
||||||
.fields = (VMStateField []) {
|
.fields = (VMStateField []) {
|
||||||
VMSTATE_UINT32(halted, CPUState),
|
VMSTATE_UINT32(halted, CPUState),
|
||||||
@ -2529,6 +2512,99 @@ void qemu_flush_coalesced_mmio_buffer(void)
|
|||||||
kvm_flush_coalesced_mmio_buffer();
|
kvm_flush_coalesced_mmio_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(TARGET_S390X)
|
||||||
|
|
||||||
|
#include <sys/vfs.h>
|
||||||
|
|
||||||
|
#define HUGETLBFS_MAGIC 0x958458f6
|
||||||
|
|
||||||
|
static long gethugepagesize(const char *path)
|
||||||
|
{
|
||||||
|
struct statfs fs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = statfs(path, &fs);
|
||||||
|
} while (ret != 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
perror("statfs");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.f_type != HUGETLBFS_MAGIC)
|
||||||
|
fprintf(stderr, "Warning: path not on HugeTLBFS: %s\n", path);
|
||||||
|
|
||||||
|
return fs.f_bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *file_ram_alloc(ram_addr_t memory, const char *path)
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
void *area;
|
||||||
|
int fd;
|
||||||
|
#ifdef MAP_POPULATE
|
||||||
|
int flags;
|
||||||
|
#endif
|
||||||
|
unsigned long hpagesize;
|
||||||
|
|
||||||
|
hpagesize = gethugepagesize(path);
|
||||||
|
if (!hpagesize) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory < hpagesize) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
||||||
|
fprintf(stderr, "host lacks kvm mmu notifiers, -mem-path unsupported\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asprintf(&filename, "%s/qemu_back_mem.XXXXXX", path) == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = mkstemp(filename);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("mkstemp");
|
||||||
|
free(filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unlink(filename);
|
||||||
|
free(filename);
|
||||||
|
|
||||||
|
memory = (memory+hpagesize-1) & ~(hpagesize-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ftruncate is not supported by hugetlbfs in older
|
||||||
|
* hosts, so don't bother bailing out on errors.
|
||||||
|
* If anything goes wrong with it under other filesystems,
|
||||||
|
* mmap will fail.
|
||||||
|
*/
|
||||||
|
if (ftruncate(fd, memory))
|
||||||
|
perror("ftruncate");
|
||||||
|
|
||||||
|
#ifdef MAP_POPULATE
|
||||||
|
/* NB: MAP_POPULATE won't exhaustively alloc all phys pages in the case
|
||||||
|
* MAP_PRIVATE is requested. For mem_prealloc we mmap as MAP_SHARED
|
||||||
|
* to sidestep this quirk.
|
||||||
|
*/
|
||||||
|
flags = mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_PRIVATE;
|
||||||
|
area = mmap(0, memory, PROT_READ | PROT_WRITE, flags, fd, 0);
|
||||||
|
#else
|
||||||
|
area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||||
|
#endif
|
||||||
|
if (area == MAP_FAILED) {
|
||||||
|
perror("file_ram_alloc: can't mmap RAM pages");
|
||||||
|
close(fd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ram_addr_t qemu_ram_alloc(ram_addr_t size)
|
ram_addr_t qemu_ram_alloc(ram_addr_t size)
|
||||||
{
|
{
|
||||||
RAMBlock *new_block;
|
RAMBlock *new_block;
|
||||||
@ -2536,16 +2612,28 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
|
|||||||
size = TARGET_PAGE_ALIGN(size);
|
size = TARGET_PAGE_ALIGN(size);
|
||||||
new_block = qemu_malloc(sizeof(*new_block));
|
new_block = qemu_malloc(sizeof(*new_block));
|
||||||
|
|
||||||
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
|
if (mem_path) {
|
||||||
/* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
|
#if defined (__linux__) && !defined(TARGET_S390X)
|
||||||
new_block->host = mmap((void*)0x1000000, size, PROT_EXEC|PROT_READ|PROT_WRITE,
|
new_block->host = file_ram_alloc(size, mem_path);
|
||||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
if (!new_block->host)
|
||||||
|
exit(1);
|
||||||
#else
|
#else
|
||||||
new_block->host = qemu_vmalloc(size);
|
fprintf(stderr, "-mem-path option unsupported\n");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if defined(TARGET_S390X) && defined(CONFIG_KVM)
|
||||||
|
/* XXX S390 KVM requires the topmost vma of the RAM to be < 256GB */
|
||||||
|
new_block->host = mmap((void*)0x1000000, size,
|
||||||
|
PROT_EXEC|PROT_READ|PROT_WRITE,
|
||||||
|
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||||
|
#else
|
||||||
|
new_block->host = qemu_vmalloc(size);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MADV_MERGEABLE
|
#ifdef MADV_MERGEABLE
|
||||||
madvise(new_block->host, size, MADV_MERGEABLE);
|
madvise(new_block->host, size, MADV_MERGEABLE);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
new_block->offset = last_ram_offset;
|
new_block->offset = last_ram_offset;
|
||||||
new_block->length = size;
|
new_block->length = size;
|
||||||
|
|
||||||
|
@ -938,8 +938,6 @@ static void apic_reset(void *opaque)
|
|||||||
APICState *s = opaque;
|
APICState *s = opaque;
|
||||||
int bsp;
|
int bsp;
|
||||||
|
|
||||||
cpu_synchronize_state(s->cpu_env);
|
|
||||||
|
|
||||||
bsp = cpu_is_bsp(s->cpu_env);
|
bsp = cpu_is_bsp(s->cpu_env);
|
||||||
s->apicbase = 0xfee00000 |
|
s->apicbase = 0xfee00000 |
|
||||||
(bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
|
(bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
|
||||||
|
14
hw/pc.c
14
hw/pc.c
@ -760,7 +760,8 @@ static void pc_init_ne2k_isa(NICInfo *nd)
|
|||||||
|
|
||||||
int cpu_is_bsp(CPUState *env)
|
int cpu_is_bsp(CPUState *env)
|
||||||
{
|
{
|
||||||
return env->cpuid_apic_id == 0;
|
/* We hard-wire the BSP to the first CPU. */
|
||||||
|
return env->cpu_index == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CPUState *pc_new_cpu(const char *cpu_model)
|
static CPUState *pc_new_cpu(const char *cpu_model)
|
||||||
@ -833,18 +834,11 @@ static void pc_init1(ram_addr_t ram_size,
|
|||||||
vmport_init();
|
vmport_init();
|
||||||
|
|
||||||
/* allocate RAM */
|
/* allocate RAM */
|
||||||
ram_addr = qemu_ram_alloc(0xa0000);
|
ram_addr = qemu_ram_alloc(below_4g_mem_size);
|
||||||
cpu_register_physical_memory(0, 0xa0000, ram_addr);
|
cpu_register_physical_memory(0, 0xa0000, ram_addr);
|
||||||
|
|
||||||
/* Allocate, even though we won't register, so we don't break the
|
|
||||||
* phys_ram_base + PA assumption. This range includes vga (0xa0000 - 0xc0000),
|
|
||||||
* and some bios areas, which will be registered later
|
|
||||||
*/
|
|
||||||
ram_addr = qemu_ram_alloc(0x100000 - 0xa0000);
|
|
||||||
ram_addr = qemu_ram_alloc(below_4g_mem_size - 0x100000);
|
|
||||||
cpu_register_physical_memory(0x100000,
|
cpu_register_physical_memory(0x100000,
|
||||||
below_4g_mem_size - 0x100000,
|
below_4g_mem_size - 0x100000,
|
||||||
ram_addr);
|
ram_addr + 0x100000);
|
||||||
|
|
||||||
/* above 4giga memory allocation */
|
/* above 4giga memory allocation */
|
||||||
if (above_4g_mem_size > 0) {
|
if (above_4g_mem_size > 0) {
|
||||||
|
@ -167,9 +167,6 @@ static void ppc_core99_init (ram_addr_t ram_size,
|
|||||||
envs[i] = env;
|
envs[i] = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure all register sets take effect */
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
|
|
||||||
/* allocate RAM */
|
/* allocate RAM */
|
||||||
ram_offset = qemu_ram_alloc(ram_size);
|
ram_offset = qemu_ram_alloc(ram_size);
|
||||||
cpu_register_physical_memory(0, ram_size, ram_offset);
|
cpu_register_physical_memory(0, ram_size, ram_offset);
|
||||||
|
@ -165,9 +165,6 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
|
|||||||
envs[i] = env;
|
envs[i] = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure all register sets take effect */
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
|
|
||||||
/* allocate RAM */
|
/* allocate RAM */
|
||||||
if (ram_size > (2047 << 20)) {
|
if (ram_size > (2047 << 20)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -185,7 +185,6 @@ static void s390_init(ram_addr_t ram_size,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
env->psw.addr = KERN_IMAGE_START;
|
env->psw.addr = KERN_IMAGE_START;
|
||||||
env->psw.mask = 0x0000000180000000ULL;
|
env->psw.mask = 0x0000000180000000ULL;
|
||||||
}
|
}
|
||||||
|
43
kvm-all.c
43
kvm-all.c
@ -65,6 +65,7 @@ struct KVMState
|
|||||||
int broken_set_mem_region;
|
int broken_set_mem_region;
|
||||||
int migration_log;
|
int migration_log;
|
||||||
int vcpu_events;
|
int vcpu_events;
|
||||||
|
int robust_singlestep;
|
||||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
|
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
|
||||||
#endif
|
#endif
|
||||||
@ -155,10 +156,6 @@ static void kvm_reset_vcpu(void *opaque)
|
|||||||
CPUState *env = opaque;
|
CPUState *env = opaque;
|
||||||
|
|
||||||
kvm_arch_reset_vcpu(env);
|
kvm_arch_reset_vcpu(env);
|
||||||
if (kvm_arch_put_registers(env)) {
|
|
||||||
fprintf(stderr, "Fatal: kvm vcpu reset failed\n");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_irqchip_in_kernel(void)
|
int kvm_irqchip_in_kernel(void)
|
||||||
@ -213,7 +210,6 @@ int kvm_init_vcpu(CPUState *env)
|
|||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
qemu_register_reset(kvm_reset_vcpu, env);
|
qemu_register_reset(kvm_reset_vcpu, env);
|
||||||
kvm_arch_reset_vcpu(env);
|
kvm_arch_reset_vcpu(env);
|
||||||
ret = kvm_arch_put_registers(env);
|
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
@ -659,6 +655,12 @@ int kvm_init(int smp_cpus)
|
|||||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
s->robust_singlestep = 0;
|
||||||
|
#ifdef KVM_CAP_X86_ROBUST_SINGLESTEP
|
||||||
|
s->robust_singlestep =
|
||||||
|
kvm_check_extension(s, KVM_CAP_X86_ROBUST_SINGLESTEP);
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = kvm_arch_init(s, smp_cpus);
|
ret = kvm_arch_init(s, smp_cpus);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -746,6 +748,18 @@ void kvm_cpu_synchronize_state(CPUState *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_post_reset(CPUState *env)
|
||||||
|
{
|
||||||
|
kvm_arch_put_registers(env, KVM_PUT_RESET_STATE);
|
||||||
|
env->kvm_vcpu_dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_post_init(CPUState *env)
|
||||||
|
{
|
||||||
|
kvm_arch_put_registers(env, KVM_PUT_FULL_STATE);
|
||||||
|
env->kvm_vcpu_dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int kvm_cpu_exec(CPUState *env)
|
int kvm_cpu_exec(CPUState *env)
|
||||||
{
|
{
|
||||||
struct kvm_run *run = env->kvm_run;
|
struct kvm_run *run = env->kvm_run;
|
||||||
@ -763,7 +777,7 @@ int kvm_cpu_exec(CPUState *env)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (env->kvm_vcpu_dirty) {
|
if (env->kvm_vcpu_dirty) {
|
||||||
kvm_arch_put_registers(env);
|
kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
|
||||||
env->kvm_vcpu_dirty = 0;
|
env->kvm_vcpu_dirty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -917,6 +931,11 @@ int kvm_has_vcpu_events(void)
|
|||||||
return kvm_state->vcpu_events;
|
return kvm_state->vcpu_events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kvm_has_robust_singlestep(void)
|
||||||
|
{
|
||||||
|
return kvm_state->robust_singlestep;
|
||||||
|
}
|
||||||
|
|
||||||
void kvm_setup_guest_memory(void *start, size_t size)
|
void kvm_setup_guest_memory(void *start, size_t size)
|
||||||
{
|
{
|
||||||
if (!kvm_has_sync_mmu()) {
|
if (!kvm_has_sync_mmu()) {
|
||||||
@ -974,10 +993,6 @@ static void kvm_invoke_set_guest_debug(void *data)
|
|||||||
struct kvm_set_guest_debug_data *dbg_data = data;
|
struct kvm_set_guest_debug_data *dbg_data = data;
|
||||||
CPUState *env = dbg_data->env;
|
CPUState *env = dbg_data->env;
|
||||||
|
|
||||||
if (env->kvm_vcpu_dirty) {
|
|
||||||
kvm_arch_put_registers(env);
|
|
||||||
env->kvm_vcpu_dirty = 0;
|
|
||||||
}
|
|
||||||
dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
|
dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,12 +1000,12 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
|
|||||||
{
|
{
|
||||||
struct kvm_set_guest_debug_data data;
|
struct kvm_set_guest_debug_data data;
|
||||||
|
|
||||||
data.dbg.control = 0;
|
data.dbg.control = reinject_trap;
|
||||||
if (env->singlestep_enabled)
|
|
||||||
data.dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
|
||||||
|
|
||||||
|
if (env->singlestep_enabled) {
|
||||||
|
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
||||||
|
}
|
||||||
kvm_arch_update_guest_debug(env, &data.dbg);
|
kvm_arch_update_guest_debug(env, &data.dbg);
|
||||||
data.dbg.control |= reinject_trap;
|
|
||||||
data.env = env;
|
data.env = env;
|
||||||
|
|
||||||
on_vcpu(env, kvm_invoke_set_guest_debug, &data);
|
on_vcpu(env, kvm_invoke_set_guest_debug, &data);
|
||||||
|
26
kvm.h
26
kvm.h
@ -40,6 +40,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
|
|||||||
|
|
||||||
int kvm_has_sync_mmu(void);
|
int kvm_has_sync_mmu(void);
|
||||||
int kvm_has_vcpu_events(void);
|
int kvm_has_vcpu_events(void);
|
||||||
|
int kvm_has_robust_singlestep(void);
|
||||||
|
|
||||||
void kvm_setup_guest_memory(void *start, size_t size);
|
void kvm_setup_guest_memory(void *start, size_t size);
|
||||||
|
|
||||||
@ -81,7 +82,14 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run);
|
|||||||
|
|
||||||
int kvm_arch_get_registers(CPUState *env);
|
int kvm_arch_get_registers(CPUState *env);
|
||||||
|
|
||||||
int kvm_arch_put_registers(CPUState *env);
|
/* state subset only touched by the VCPU itself during runtime */
|
||||||
|
#define KVM_PUT_RUNTIME_STATE 1
|
||||||
|
/* state subset modified during VCPU reset */
|
||||||
|
#define KVM_PUT_RESET_STATE 2
|
||||||
|
/* full state set, modified during initialization or on vmload */
|
||||||
|
#define KVM_PUT_FULL_STATE 3
|
||||||
|
|
||||||
|
int kvm_arch_put_registers(CPUState *env, int level);
|
||||||
|
|
||||||
int kvm_arch_init(KVMState *s, int smp_cpus);
|
int kvm_arch_init(KVMState *s, int smp_cpus);
|
||||||
|
|
||||||
@ -125,6 +133,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
|
|||||||
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
|
uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
|
||||||
int reg);
|
int reg);
|
||||||
void kvm_cpu_synchronize_state(CPUState *env);
|
void kvm_cpu_synchronize_state(CPUState *env);
|
||||||
|
void kvm_cpu_synchronize_post_reset(CPUState *env);
|
||||||
|
void kvm_cpu_synchronize_post_init(CPUState *env);
|
||||||
|
|
||||||
/* generic hooks - to be moved/refactored once there are more users */
|
/* generic hooks - to be moved/refactored once there are more users */
|
||||||
|
|
||||||
@ -135,4 +145,18 @@ static inline void cpu_synchronize_state(CPUState *env)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpu_synchronize_post_reset(CPUState *env)
|
||||||
|
{
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
kvm_cpu_synchronize_post_reset(env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cpu_synchronize_post_init(CPUState *env)
|
||||||
|
{
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
kvm_cpu_synchronize_post_init(env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -314,6 +314,22 @@ a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or
|
|||||||
gigabytes respectively.
|
gigabytes respectively.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
DEF("mem-path", HAS_ARG, QEMU_OPTION_mempath,
|
||||||
|
"-mem-path FILE provide backing storage for guest RAM\n")
|
||||||
|
STEXI
|
||||||
|
@item -mem-path @var{path}
|
||||||
|
Allocate guest RAM from a temporarily created file in @var{path}.
|
||||||
|
ETEXI
|
||||||
|
|
||||||
|
#ifdef MAP_POPULATE
|
||||||
|
DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
|
||||||
|
"-mem-prealloc preallocate guest memory (use with -mem-path)\n")
|
||||||
|
STEXI
|
||||||
|
@item -mem-prealloc
|
||||||
|
Preallocate memory when using -mem-path.
|
||||||
|
ETEXI
|
||||||
|
#endif
|
||||||
|
|
||||||
DEF("k", HAS_ARG, QEMU_OPTION_k,
|
DEF("k", HAS_ARG, QEMU_OPTION_k,
|
||||||
"-k language use keyboard layout (for example 'fr' for French)\n")
|
"-k language use keyboard layout (for example 'fr' for French)\n")
|
||||||
STEXI
|
STEXI
|
||||||
|
4
savevm.c
4
savevm.c
@ -1345,6 +1345,8 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
|
|||||||
{
|
{
|
||||||
SaveStateEntry *se;
|
SaveStateEntry *se;
|
||||||
|
|
||||||
|
cpu_synchronize_all_states();
|
||||||
|
|
||||||
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||||
if (se->save_live_state == NULL)
|
if (se->save_live_state == NULL)
|
||||||
continue;
|
continue;
|
||||||
@ -1545,6 +1547,8 @@ int qemu_loadvm_state(QEMUFile *f)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_synchronize_all_post_init();
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
4
sysemu.h
4
sysemu.h
@ -58,6 +58,10 @@ int load_vmstate(Monitor *mon, const char *name);
|
|||||||
void do_delvm(Monitor *mon, const QDict *qdict);
|
void do_delvm(Monitor *mon, const QDict *qdict);
|
||||||
void do_info_snapshots(Monitor *mon);
|
void do_info_snapshots(Monitor *mon);
|
||||||
|
|
||||||
|
void cpu_synchronize_all_states(void);
|
||||||
|
void cpu_synchronize_all_post_reset(void);
|
||||||
|
void cpu_synchronize_all_post_init(void);
|
||||||
|
|
||||||
void qemu_announce_self(void);
|
void qemu_announce_self(void);
|
||||||
|
|
||||||
void main_loop_wait(int timeout);
|
void main_loop_wait(int timeout);
|
||||||
|
@ -546,7 +546,7 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
|
|||||||
entry->data = value;
|
entry->data = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvm_put_msrs(CPUState *env)
|
static int kvm_put_msrs(CPUState *env, int level)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
struct kvm_msrs info;
|
struct kvm_msrs info;
|
||||||
@ -560,7 +560,6 @@ static int kvm_put_msrs(CPUState *env)
|
|||||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
|
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
|
||||||
if (kvm_has_msr_star(env))
|
if (kvm_has_msr_star(env))
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
|
kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
|
|
||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
/* FIXME if lm capable */
|
/* FIXME if lm capable */
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
|
kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
|
||||||
@ -568,8 +567,12 @@ static int kvm_put_msrs(CPUState *env)
|
|||||||
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
|
kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask);
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
|
kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar);
|
||||||
#endif
|
#endif
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, env->system_time_msr);
|
if (level == KVM_PUT_FULL_STATE) {
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
|
kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
|
||||||
|
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
|
||||||
|
env->system_time_msr);
|
||||||
|
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
|
||||||
|
}
|
||||||
|
|
||||||
msr_data.info.nmsrs = n;
|
msr_data.info.nmsrs = n;
|
||||||
|
|
||||||
@ -782,7 +785,7 @@ static int kvm_get_mp_state(CPUState *env)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kvm_put_vcpu_events(CPUState *env)
|
static int kvm_put_vcpu_events(CPUState *env, int level)
|
||||||
{
|
{
|
||||||
#ifdef KVM_CAP_VCPU_EVENTS
|
#ifdef KVM_CAP_VCPU_EVENTS
|
||||||
struct kvm_vcpu_events events;
|
struct kvm_vcpu_events events;
|
||||||
@ -806,8 +809,11 @@ static int kvm_put_vcpu_events(CPUState *env)
|
|||||||
|
|
||||||
events.sipi_vector = env->sipi_vector;
|
events.sipi_vector = env->sipi_vector;
|
||||||
|
|
||||||
events.flags =
|
events.flags = 0;
|
||||||
KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR;
|
if (level >= KVM_PUT_RESET_STATE) {
|
||||||
|
events.flags |=
|
||||||
|
KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
|
return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
|
||||||
#else
|
#else
|
||||||
@ -852,7 +858,38 @@ static int kvm_get_vcpu_events(CPUState *env)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_put_registers(CPUState *env)
|
static int kvm_guest_debug_workarounds(CPUState *env)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
|
unsigned long reinject_trap = 0;
|
||||||
|
|
||||||
|
if (!kvm_has_vcpu_events()) {
|
||||||
|
if (env->exception_injected == 1) {
|
||||||
|
reinject_trap = KVM_GUESTDBG_INJECT_DB;
|
||||||
|
} else if (env->exception_injected == 3) {
|
||||||
|
reinject_trap = KVM_GUESTDBG_INJECT_BP;
|
||||||
|
}
|
||||||
|
env->exception_injected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kernels before KVM_CAP_X86_ROBUST_SINGLESTEP overwrote flags.TF
|
||||||
|
* injected via SET_GUEST_DEBUG while updating GP regs. Work around this
|
||||||
|
* by updating the debug state once again if single-stepping is on.
|
||||||
|
* Another reason to call kvm_update_guest_debug here is a pending debug
|
||||||
|
* trap raise by the guest. On kernels without SET_VCPU_EVENTS we have to
|
||||||
|
* reinject them via SET_GUEST_DEBUG.
|
||||||
|
*/
|
||||||
|
if (reinject_trap ||
|
||||||
|
(!kvm_has_robust_singlestep() && env->singlestep_enabled)) {
|
||||||
|
ret = kvm_update_guest_debug(env, reinject_trap);
|
||||||
|
}
|
||||||
|
#endif /* KVM_CAP_SET_GUEST_DEBUG */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvm_arch_put_registers(CPUState *env, int level)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -868,15 +905,22 @@ int kvm_arch_put_registers(CPUState *env)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = kvm_put_msrs(env);
|
ret = kvm_put_msrs(env, level);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = kvm_put_mp_state(env);
|
if (level >= KVM_PUT_RESET_STATE) {
|
||||||
|
ret = kvm_put_mp_state(env);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = kvm_put_vcpu_events(env, level);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = kvm_put_vcpu_events(env);
|
/* must be last */
|
||||||
|
ret = kvm_guest_debug_workarounds(env);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1123,10 +1167,13 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
|
|||||||
} else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
|
} else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
|
||||||
handle = 1;
|
handle = 1;
|
||||||
|
|
||||||
if (!handle)
|
if (!handle) {
|
||||||
kvm_update_guest_debug(cpu_single_env,
|
cpu_synchronize_state(cpu_single_env);
|
||||||
(arch_info->exception == 1) ?
|
assert(cpu_single_env->exception_injected == -1);
|
||||||
KVM_GUESTDBG_INJECT_DB : KVM_GUESTDBG_INJECT_BP);
|
|
||||||
|
cpu_single_env->exception_injected = arch_info->exception;
|
||||||
|
cpu_single_env->has_error_code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -321,8 +321,6 @@ static void cpu_pre_save(void *opaque)
|
|||||||
CPUState *env = opaque;
|
CPUState *env = opaque;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
|
|
||||||
/* FPU */
|
/* FPU */
|
||||||
env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
|
env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
|
||||||
env->fptag_vmstate = 0;
|
env->fptag_vmstate = 0;
|
||||||
@ -337,14 +335,6 @@ static void cpu_pre_save(void *opaque)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cpu_pre_load(void *opaque)
|
|
||||||
{
|
|
||||||
CPUState *env = opaque;
|
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cpu_post_load(void *opaque, int version_id)
|
static int cpu_post_load(void *opaque, int version_id)
|
||||||
{
|
{
|
||||||
CPUState *env = opaque;
|
CPUState *env = opaque;
|
||||||
@ -373,7 +363,6 @@ static const VMStateDescription vmstate_cpu = {
|
|||||||
.minimum_version_id = 3,
|
.minimum_version_id = 3,
|
||||||
.minimum_version_id_old = 3,
|
.minimum_version_id_old = 3,
|
||||||
.pre_save = cpu_pre_save,
|
.pre_save = cpu_pre_save,
|
||||||
.pre_load = cpu_pre_load,
|
|
||||||
.post_load = cpu_post_load,
|
.post_load = cpu_post_load,
|
||||||
.fields = (VMStateField []) {
|
.fields = (VMStateField []) {
|
||||||
VMSTATE_UINTTL_ARRAY(regs, CPUState, CPU_NB_REGS),
|
VMSTATE_UINTTL_ARRAY(regs, CPUState, CPU_NB_REGS),
|
||||||
|
@ -73,7 +73,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_put_registers(CPUState *env)
|
int kvm_arch_put_registers(CPUState *env, int level)
|
||||||
{
|
{
|
||||||
struct kvm_regs regs;
|
struct kvm_regs regs;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -7,8 +7,6 @@ void cpu_save(QEMUFile *f, void *opaque)
|
|||||||
CPUState *env = (CPUState *)opaque;
|
CPUState *env = (CPUState *)opaque;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
qemu_put_betls(f, &env->gpr[i]);
|
qemu_put_betls(f, &env->gpr[i]);
|
||||||
#if !defined(TARGET_PPC64)
|
#if !defined(TARGET_PPC64)
|
||||||
@ -96,8 +94,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
CPUState *env = (CPUState *)opaque;
|
CPUState *env = (CPUState *)opaque;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
cpu_synchronize_state(env);
|
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
||||||
qemu_get_betls(f, &env->gpr[i]);
|
qemu_get_betls(f, &env->gpr[i]);
|
||||||
#if !defined(TARGET_PPC64)
|
#if !defined(TARGET_PPC64)
|
||||||
|
@ -91,7 +91,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
|
|||||||
/* FIXME: add code to reset vcpu. */
|
/* FIXME: add code to reset vcpu. */
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_put_registers(CPUState *env)
|
int kvm_arch_put_registers(CPUState *env, int level)
|
||||||
{
|
{
|
||||||
struct kvm_regs regs;
|
struct kvm_regs regs;
|
||||||
int ret;
|
int ret;
|
||||||
@ -296,7 +296,6 @@ static int handle_hypercall(CPUState *env, struct kvm_run *run)
|
|||||||
|
|
||||||
cpu_synchronize_state(env);
|
cpu_synchronize_state(env);
|
||||||
r = s390_virtio_hypercall(env);
|
r = s390_virtio_hypercall(env);
|
||||||
kvm_arch_put_registers(env);
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
41
vl.c
41
vl.c
@ -185,6 +185,10 @@ enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
|
|||||||
DisplayType display_type = DT_DEFAULT;
|
DisplayType display_type = DT_DEFAULT;
|
||||||
const char* keyboard_layout = NULL;
|
const char* keyboard_layout = NULL;
|
||||||
ram_addr_t ram_size;
|
ram_addr_t ram_size;
|
||||||
|
const char *mem_path = NULL;
|
||||||
|
#ifdef MAP_POPULATE
|
||||||
|
int mem_prealloc = 0; /* force preallocation of physical target memory */
|
||||||
|
#endif
|
||||||
int nb_nics;
|
int nb_nics;
|
||||||
NICInfo nd_table[MAX_NICS];
|
NICInfo nd_table[MAX_NICS];
|
||||||
int vm_running;
|
int vm_running;
|
||||||
@ -2998,6 +3002,33 @@ static void nographic_update(void *opaque)
|
|||||||
qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
|
qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cpu_synchronize_all_states(void)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
|
||||||
|
cpu_synchronize_state(cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_synchronize_all_post_reset(void)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
|
||||||
|
cpu_synchronize_post_reset(cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpu_synchronize_all_post_init(void)
|
||||||
|
{
|
||||||
|
CPUState *cpu;
|
||||||
|
|
||||||
|
for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
|
||||||
|
cpu_synchronize_post_init(cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct vm_change_state_entry {
|
struct vm_change_state_entry {
|
||||||
VMChangeStateHandler *cb;
|
VMChangeStateHandler *cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
@ -3139,6 +3170,7 @@ void qemu_system_reset(void)
|
|||||||
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
|
QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
|
||||||
re->func(re->opaque);
|
re->func(re->opaque);
|
||||||
}
|
}
|
||||||
|
cpu_synchronize_all_post_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_system_reset_request(void)
|
void qemu_system_reset_request(void)
|
||||||
@ -5216,6 +5248,14 @@ int main(int argc, char **argv, char **envp)
|
|||||||
ram_size = value;
|
ram_size = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case QEMU_OPTION_mempath:
|
||||||
|
mem_path = optarg;
|
||||||
|
break;
|
||||||
|
#ifdef MAP_POPULATE
|
||||||
|
case QEMU_OPTION_mem_prealloc:
|
||||||
|
mem_prealloc = 1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case QEMU_OPTION_d:
|
case QEMU_OPTION_d:
|
||||||
{
|
{
|
||||||
int mask;
|
int mask;
|
||||||
@ -5916,6 +5956,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
machine->init(ram_size, boot_devices,
|
machine->init(ram_size, boot_devices,
|
||||||
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
|
||||||
|
|
||||||
|
cpu_synchronize_all_post_init();
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/* must be after terminal init, SDL library changes signal handlers */
|
/* must be after terminal init, SDL library changes signal handlers */
|
||||||
|
Loading…
Reference in New Issue
Block a user