* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpus.h"
#include "sysemu/kvm.h"
GuestROMState rom_state;
size_t rom_size;
bool rom_mapped_writable;
+ VMChangeStateEntry *vmsentry;
} VAPICROMState;
#define TYPE_VAPIC "kvmvapic"
static void read_guest_rom_state(VAPICROMState *s)
{
- cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
- sizeof(GuestROMState), 0);
+ cpu_physical_memory_read(s->rom_state_paddr, &s->rom_state,
+ sizeof(GuestROMState));
}
static void write_guest_rom_state(VAPICROMState *s)
{
- cpu_physical_memory_rw(s->rom_state_paddr, (void *)&s->rom_state,
- sizeof(GuestROMState), 1);
+ cpu_physical_memory_write(s->rom_state_paddr, &s->rom_state,
+ sizeof(GuestROMState));
}
static void update_guest_rom_state(VAPICROMState *s)
for (pos = le32_to_cpu(s->rom_state.fixup_start);
pos < le32_to_cpu(s->rom_state.fixup_end);
pos += 4) {
- cpu_physical_memory_rw(paddr + pos - s->rom_state.vaddr,
- (void *)&offset, sizeof(offset), 0);
+ cpu_physical_memory_read(paddr + pos - s->rom_state.vaddr,
+ &offset, sizeof(offset));
offset = le32_to_cpu(offset);
- cpu_physical_memory_rw(paddr + offset, (void *)&patch,
- sizeof(patch), 0);
+ cpu_physical_memory_read(paddr + offset, &patch, sizeof(patch));
patch = le32_to_cpu(patch);
patch += rom_state_vaddr - le32_to_cpu(s->rom_state.vaddr);
patch = cpu_to_le32(patch);
- cpu_physical_memory_rw(paddr + offset, (void *)&patch,
- sizeof(patch), 1);
+ cpu_physical_memory_write(paddr + offset, &patch, sizeof(patch));
}
read_guest_rom_state(s);
s->vapic_paddr = paddr + le32_to_cpu(s->rom_state.vapic_vaddr) -
}
vapic_paddr = s->vapic_paddr +
(((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
- cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
- (void *)&enabled, sizeof(enabled), 1);
+ cpu_physical_memory_write(vapic_paddr + offsetof(VAPICState, enabled),
+ &enabled, sizeof(enabled));
apic_enable_vapic(cpu->apic_state, vapic_paddr);
s->state = VAPIC_ACTIVE;
CPUX86State *env = &cpu->env;
VAPICHandlers *handlers;
uint8_t opcode[2];
- uint32_t imm32;
+ uint32_t imm32 = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
- int current_flags = 0;
+ uint32_t current_flags = 0;
if (smp_cpus == 1) {
handlers = &s->rom_state.up;
}
if (!kvm_enabled()) {
- cpu_restore_state(cs, cs->mem_io_pc);
cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
¤t_flags);
}
resume_all_vcpus();
if (!kvm_enabled()) {
- cs->current_tb = NULL;
- tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
- cpu_resume_from_signal(env, NULL);
+ tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
+ cpu_loop_exit_noexc(cs);
}
}
bool enable;
} VAPICEnableTPRReporting;
-static void vapic_do_enable_tpr_reporting(void *data)
+static void vapic_do_enable_tpr_reporting(CPUState *cpu, void *data)
{
VAPICEnableTPRReporting *info = data;
uint8_t *rom;
rom = g_malloc(s->rom_size);
- cpu_physical_memory_rw(rom_paddr, rom, s->rom_size, 0);
+ cpu_physical_memory_read(rom_paddr, rom, s->rom_size);
for (pos = 0; pos < s->rom_size - sizeof(vmcall_pattern); pos++) {
if (kvm_irqchip_in_kernel()) {
}
if (memcmp(rom + pos, pattern, 7) == 0 &&
(rom[pos + 7] == alternates[0] || rom[pos + 7] == alternates[1])) {
- cpu_physical_memory_rw(rom_paddr + pos + 5, (uint8_t *)patch,
- 3, 1);
+ cpu_physical_memory_write(rom_paddr + pos + 5, patch, 3);
/*
* Don't flush the tb here. Under ordinary conditions, the patched
* calls are miles away from the current IP. Under malicious
if (s->rom_mapped_writable) {
memory_region_del_subregion(as, &s->rom);
- memory_region_destroy(&s->rom);
+ object_unparent(OBJECT(&s->rom));
}
/* grab RAM memory region (region @rom_paddr may still be pc.rom) */
static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
- CPUState *cs = current_cpu;
- X86CPU *cpu = X86_CPU(cs);
- CPUX86State *env = &cpu->env;
- hwaddr rom_paddr;
VAPICROMState *s = opaque;
+ X86CPU *cpu;
+ CPUX86State *env;
+ hwaddr rom_paddr;
- cpu_synchronize_state(cs);
+ if (!current_cpu) {
+ return;
+ }
+
+ cpu_synchronize_state(current_cpu);
+ cpu = X86_CPU(current_cpu);
+ env = &cpu->env;
/*
* The VAPIC supports two PIO-based hypercalls, both via port 0x7E.
nb_option_roms++;
}
-static void do_vapic_enable(void *data)
+static void do_vapic_enable(CPUState *cs, void *data)
{
VAPICROMState *s = data;
- X86CPU *cpu = X86_CPU(first_cpu);
+ X86CPU *cpu = X86_CPU(cs);
- vapic_enable(s, cpu);
+ static const uint8_t enabled = 1;
+ cpu_physical_memory_write(s->vapic_paddr + offsetof(VAPICState, enabled),
+ &enabled, sizeof(enabled));
+ apic_enable_vapic(cpu->apic_state, s->vapic_paddr);
+ s->state = VAPIC_ACTIVE;
}
-static int vapic_post_load(void *opaque, int version_id)
+static void kvmvapic_vm_state_change(void *opaque, int running,
+ RunState state)
{
VAPICROMState *s = opaque;
uint8_t *zero;
+ if (!running) {
+ return;
+ }
+
+ if (s->state == VAPIC_ACTIVE) {
+ if (smp_cpus == 1) {
+ run_on_cpu(first_cpu, do_vapic_enable, s);
+ } else {
+ zero = g_malloc0(s->rom_state.vapic_size);
+ cpu_physical_memory_write(s->vapic_paddr, zero,
+ s->rom_state.vapic_size);
+ g_free(zero);
+ }
+ }
+
+ qemu_del_vm_change_state_handler(s->vmsentry);
+ s->vmsentry = NULL;
+}
+
+static int vapic_post_load(void *opaque, int version_id)
+{
+ VAPICROMState *s = opaque;
+
/*
* The old implementation of qemu-kvm did not provide the state
* VAPIC_STANDBY. Reconstruct it.
return -1;
}
}
- if (s->state == VAPIC_ACTIVE) {
- if (smp_cpus == 1) {
- run_on_cpu(first_cpu, do_vapic_enable, s);
- } else {
- zero = g_malloc0(s->rom_state.vapic_size);
- cpu_physical_memory_rw(s->vapic_paddr, zero,
- s->rom_state.vapic_size, 1);
- g_free(zero);
- }
- }
+ if (!s->vmsentry) {
+ s->vmsentry =
+ qemu_add_vm_change_state_handler(kvmvapic_vm_state_change, s);
+ }
return 0;
}
.name = "kvmvapic-handlers",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(set_tpr, VAPICHandlers),
VMSTATE_UINT32(set_tpr_eax, VAPICHandlers),
.name = "kvmvapic-guest-rom",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UNUSED(8), /* signature */
VMSTATE_UINT32(vaddr, GuestROMState),
.name = "kvm-tpr-opt", /* compatible with qemu-kvm VAPIC */
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.post_load = vapic_post_load,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(rom_state, VAPICROMState, 0, vmstate_guest_rom,