mirror of https://gitee.com/openkylin/qemu.git
Merge branch 'qom-cpu' of git://repo.or.cz/qemu/afaerber
* 'qom-cpu' of git://repo.or.cz/qemu/afaerber: MAINTAINERS: Include X86CPU in CPU maintenance area cpu: Move kvm_run into CPUState cpu: Move kvm_state field into CPUState ppc_booke: Pass PowerPCCPU to ppc_booke_timers_init() ppc4xx_devs: Return PowerPCCPU from ppc4xx_init() ppc_booke: Pass PowerPCCPU to {decr,fit,wdt} timer callbacks ppc: Pass PowerPCCPU to [h]decr timer callbacks ppc: Pass PowerPCCPU to [h]decr callbacks ppc: Pass PowerPCCPU to ppc_set_irq() kvm: Pass CPUState to kvm_vcpu_ioctl() kvm: Pass CPUState to kvm_arch_* cpu: Move kvm_fd into CPUState qdev-properties.c: Separate core from the code used only by qemu-system-* qdev: Coding style fixes cpu: Introduce CPUListState struct target-alpha: Add support for -cpu ? target-alpha: Turn CPU definitions into subclasses target-alpha: Avoid leaking the alarm timer over reset alpha: Pass AlphaCPU array to Typhoon target-alpha: Let cpu_alpha_init() return AlphaCPU
This commit is contained in:
commit
4de63460ca
|
@ -600,6 +600,7 @@ M: Andreas Färber <afaerber@suse.de>
|
|||
S: Supported
|
||||
F: qom/cpu.c
|
||||
F: include/qemu/cpu.h
|
||||
F: target-i386/cpu.c
|
||||
|
||||
Device Tree
|
||||
M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
|
||||
|
|
|
@ -181,6 +181,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
|
|||
common-obj-y += bt-hci-csr.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
|
||||
common-obj-y += qdev-properties-system.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
|
||||
# xen backend driver support
|
||||
|
|
|
@ -50,7 +50,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
CPUAlphaState *cpus[4];
|
||||
AlphaCPU *cpus[4];
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
qemu_irq rtc_irq;
|
||||
|
@ -62,12 +62,12 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
/* Create up to 4 cpus. */
|
||||
memset(cpus, 0, sizeof(cpus));
|
||||
for (i = 0; i < smp_cpus; ++i) {
|
||||
cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
||||
cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
|
||||
}
|
||||
|
||||
cpus[0]->trap_arg0 = ram_size;
|
||||
cpus[0]->trap_arg1 = 0;
|
||||
cpus[0]->trap_arg2 = smp_cpus;
|
||||
cpus[0]->env.trap_arg0 = ram_size;
|
||||
cpus[0]->env.trap_arg1 = 0;
|
||||
cpus[0]->env.trap_arg2 = smp_cpus;
|
||||
|
||||
/* Init the chipset. */
|
||||
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
|
||||
|
@ -119,9 +119,9 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
|
||||
/* Start all cpus at the PALcode RESET entry point. */
|
||||
for (i = 0; i < smp_cpus; ++i) {
|
||||
cpus[i]->pal_mode = 1;
|
||||
cpus[i]->pc = palcode_entry;
|
||||
cpus[i]->palbr = palcode_entry;
|
||||
cpus[i]->env.pal_mode = 1;
|
||||
cpus[i]->env.pc = palcode_entry;
|
||||
cpus[i]->env.palbr = palcode_entry;
|
||||
}
|
||||
|
||||
/* Load a kernel. */
|
||||
|
@ -136,7 +136,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
cpus[0]->trap_arg1 = kernel_entry;
|
||||
cpus[0]->env.trap_arg1 = kernel_entry;
|
||||
|
||||
param_offset = kernel_low - 0x6000;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "irq.h"
|
||||
|
||||
|
||||
PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
|
||||
PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
|
||||
pci_map_irq_fn);
|
||||
|
||||
/* alpha_pci.c. */
|
||||
|
|
|
@ -23,7 +23,7 @@ typedef struct TyphoonCchip {
|
|||
uint64_t drir;
|
||||
uint64_t dim[4];
|
||||
uint32_t iic[4];
|
||||
CPUAlphaState *cpu[4];
|
||||
AlphaCPU *cpu[4];
|
||||
} TyphoonCchip;
|
||||
|
||||
typedef struct TyphoonWindow {
|
||||
|
@ -58,10 +58,11 @@ typedef struct TyphoonState {
|
|||
} TyphoonState;
|
||||
|
||||
/* Called when one of DRIR or DIM changes. */
|
||||
static void cpu_irq_change(CPUAlphaState *env, uint64_t req)
|
||||
static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
|
||||
{
|
||||
/* If there are any non-masked interrupts, tell the cpu. */
|
||||
if (env) {
|
||||
if (cpu != NULL) {
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
if (req) {
|
||||
cpu_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
|
@ -353,8 +354,9 @@ static void cchip_write(void *opaque, hwaddr addr,
|
|||
if ((newval ^ oldval) & 0xff0) {
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
CPUAlphaState *env = s->cchip.cpu[i];
|
||||
if (env) {
|
||||
AlphaCPU *cpu = s->cchip.cpu[i];
|
||||
if (cpu != NULL) {
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
/* IPI can be either cleared or set by the write. */
|
||||
if (newval & (1 << (i + 8))) {
|
||||
cpu_interrupt(env, CPU_INTERRUPT_SMP);
|
||||
|
@ -661,8 +663,8 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
|
|||
|
||||
/* Deliver the interrupt to each CPU, considering each CPU's IIC. */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
CPUAlphaState *env = s->cchip.cpu[i];
|
||||
if (env) {
|
||||
AlphaCPU *cpu = s->cchip.cpu[i];
|
||||
if (cpu != NULL) {
|
||||
uint32_t iic = s->cchip.iic[i];
|
||||
|
||||
/* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
|
||||
|
@ -681,7 +683,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
|
|||
/* Set the ITI bit for this cpu. */
|
||||
s->cchip.misc |= 1 << (i + 4);
|
||||
/* And signal the interrupt. */
|
||||
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
|
||||
cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -694,12 +696,12 @@ static void typhoon_alarm_timer(void *opaque)
|
|||
|
||||
/* Set the ITI bit for this cpu. */
|
||||
s->cchip.misc |= 1 << (cpu + 4);
|
||||
cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
|
||||
cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
|
||||
PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
||||
qemu_irq *p_rtc_irq,
|
||||
CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
|
||||
AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
|
||||
{
|
||||
const uint64_t MB = 1024 * 1024;
|
||||
const uint64_t GB = 1024 * MB;
|
||||
|
@ -719,10 +721,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
|||
|
||||
/* Remember the CPUs so that we can deliver interrupts to them. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
CPUAlphaState *env = cpus[i];
|
||||
s->cchip.cpu[i] = env;
|
||||
if (env) {
|
||||
env->alarm_timer = qemu_new_timer_ns(rtc_clock,
|
||||
AlphaCPU *cpu = cpus[i];
|
||||
s->cchip.cpu[i] = cpu;
|
||||
if (cpu != NULL) {
|
||||
cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
|
||||
typhoon_alarm_timer,
|
||||
(void *)((uintptr_t)s + i));
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
|
|||
.enabled = enable
|
||||
};
|
||||
|
||||
kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl);
|
||||
kvm_vcpu_ioctl(CPU(s->cpu), KVM_TPR_ACCESS_REPORTING, &ctl);
|
||||
}
|
||||
|
||||
static void kvm_apic_vapic_base_update(APICCommonState *s)
|
||||
|
@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
|
|||
};
|
||||
int ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr);
|
||||
ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_VAPIC_ADDR, &vapid_addr);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
|
||||
strerror(-ret));
|
||||
|
@ -125,15 +125,15 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
|
|||
static void do_inject_external_nmi(void *data)
|
||||
{
|
||||
APICCommonState *s = data;
|
||||
CPUX86State *env = &s->cpu->env;
|
||||
CPUState *cpu = CPU(s->cpu);
|
||||
uint32_t lvt;
|
||||
int ret;
|
||||
|
||||
cpu_synchronize_state(env);
|
||||
cpu_synchronize_state(&s->cpu->env);
|
||||
|
||||
lvt = s->lvt[APIC_LVT_LINT1];
|
||||
if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_NMI);
|
||||
ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
|
||||
strerror(-ret));
|
||||
|
|
|
@ -76,7 +76,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||
return;
|
||||
}
|
||||
for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
|
||||
ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0);
|
||||
ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL) {
|
||||
fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
|
||||
|
|
128
hw/ppc.c
128
hw/ppc.c
|
@ -50,8 +50,9 @@
|
|||
static void cpu_ppc_tb_stop (CPUPPCState *env);
|
||||
static void cpu_ppc_tb_start (CPUPPCState *env);
|
||||
|
||||
void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
|
||||
void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
unsigned int old_pending = env->pending_interrupts;
|
||||
|
||||
if (level) {
|
||||
|
@ -65,7 +66,7 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
|
|||
|
||||
if (old_pending != env->pending_interrupts) {
|
||||
#ifdef CONFIG_KVM
|
||||
kvmppc_set_interrupt(env, n_IRQ, level);
|
||||
kvmppc_set_interrupt(cpu, n_IRQ, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -100,13 +101,13 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC6xx_INPUT_SMI:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the SMI IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
|
||||
break;
|
||||
case PPC6xx_INPUT_MCP:
|
||||
/* Negative edge sensitive */
|
||||
|
@ -116,7 +117,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
if (cur_level == 1 && level == 0) {
|
||||
LOG_IRQ("%s: raise machine check state\n",
|
||||
__func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
|
||||
}
|
||||
break;
|
||||
case PPC6xx_INPUT_CKSTP_IN:
|
||||
|
@ -138,7 +139,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
case PPC6xx_INPUT_SRESET:
|
||||
LOG_IRQ("%s: set the RESET IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -178,13 +179,13 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC970_INPUT_THINT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
|
||||
level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
|
||||
break;
|
||||
case PPC970_INPUT_MCP:
|
||||
/* Negative edge sensitive */
|
||||
|
@ -194,7 +195,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
if (cur_level == 1 && level == 0) {
|
||||
LOG_IRQ("%s: raise machine check state\n",
|
||||
__func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
|
||||
}
|
||||
break;
|
||||
case PPC970_INPUT_CKSTP:
|
||||
|
@ -218,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
case PPC970_INPUT_SRESET:
|
||||
LOG_IRQ("%s: set the RESET IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
|
||||
break;
|
||||
case PPC970_INPUT_TBEN:
|
||||
LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
|
||||
|
@ -259,7 +260,7 @@ static void power7_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -319,13 +320,13 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the critical IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
|
||||
break;
|
||||
case PPC40x_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC40x_INPUT_HALT:
|
||||
/* Level sensitive - active low */
|
||||
|
@ -342,7 +343,7 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the debug pin state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -387,26 +388,26 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
|
|||
case PPCE500_INPUT_RESET_CORE:
|
||||
if (level) {
|
||||
LOG_IRQ("%s: reset the PowerPC core\n", __func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
|
||||
}
|
||||
break;
|
||||
case PPCE500_INPUT_CINT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the critical IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
|
||||
break;
|
||||
case PPCE500_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the core IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPCE500_INPUT_DEBUG:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the debug pin state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -643,26 +644,27 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env)
|
|||
/* When decrementer expires,
|
||||
* all we need to do is generate or queue a CPU exception
|
||||
*/
|
||||
static inline void cpu_ppc_decr_excp(CPUPPCState *env)
|
||||
static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
|
||||
{
|
||||
/* Raise it */
|
||||
LOG_TB("raise decrementer exception\n");
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
|
||||
}
|
||||
|
||||
static inline void cpu_ppc_hdecr_excp(CPUPPCState *env)
|
||||
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
||||
{
|
||||
/* Raise it */
|
||||
LOG_TB("raise decrementer exception\n");
|
||||
ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
|
||||
}
|
||||
|
||||
static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
|
||||
struct QEMUTimer *timer,
|
||||
void (*raise_excp)(CPUPPCState *),
|
||||
uint32_t decr, uint32_t value,
|
||||
int is_excp)
|
||||
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
||||
struct QEMUTimer *timer,
|
||||
void (*raise_excp)(PowerPCCPU *),
|
||||
uint32_t decr, uint32_t value,
|
||||
int is_excp)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
uint64_t now, next;
|
||||
|
||||
|
@ -692,53 +694,61 @@ static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
|
|||
if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
|
||||
&& (value & 0x80000000)
|
||||
&& !(decr & 0x80000000)) {
|
||||
(*raise_excp)(env);
|
||||
(*raise_excp)(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr,
|
||||
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
|
||||
uint32_t value, int is_excp)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
__cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
|
||||
&cpu_ppc_decr_excp, decr, value, is_excp);
|
||||
}
|
||||
|
||||
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
_cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
|
||||
}
|
||||
|
||||
static void cpu_ppc_decr_cb (void *opaque)
|
||||
static void cpu_ppc_decr_cb(void *opaque)
|
||||
{
|
||||
_cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr,
|
||||
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
|
||||
uint32_t value, int is_excp)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
if (tb_env->hdecr_timer != NULL) {
|
||||
__cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||
&cpu_ppc_hdecr_excp, hdecr, value, is_excp);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
_cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
|
||||
}
|
||||
|
||||
static void cpu_ppc_hdecr_cb (void *opaque)
|
||||
static void cpu_ppc_hdecr_cb(void *opaque)
|
||||
{
|
||||
_cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
|
||||
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
tb_env->purr_load = value;
|
||||
tb_env->purr_start = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -747,6 +757,7 @@ static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
|
|||
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
||||
{
|
||||
CPUPPCState *env = opaque;
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
|
||||
tb_env->tb_freq = freq;
|
||||
|
@ -755,25 +766,27 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
|||
* if a decrementer exception is pending when it enables msr_ee at startup,
|
||||
* it's not ready to handle it...
|
||||
*/
|
||||
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
cpu_ppc_store_purr(env, 0x0000000000000000ULL);
|
||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
||||
}
|
||||
|
||||
/* Set up (once) timebase frequency (in Hz) */
|
||||
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env;
|
||||
|
||||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||
env->tb_env = tb_env;
|
||||
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
|
||||
/* Create new timer */
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
|
||||
if (0) {
|
||||
/* XXX: find a suitable condition to enable the hypervisor decrementer
|
||||
*/
|
||||
tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
|
||||
tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
|
||||
cpu);
|
||||
} else {
|
||||
tb_env->hdecr_timer = NULL;
|
||||
}
|
||||
|
@ -829,12 +842,14 @@ struct ppc40x_timer_t {
|
|||
/* Fixed interval timer */
|
||||
static void cpu_4xx_fit_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
uint64_t now, next;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
now = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -860,8 +875,9 @@ static void cpu_4xx_fit_cb (void *opaque)
|
|||
next++;
|
||||
qemu_mod_timer(ppc40x_timer->fit_timer, next);
|
||||
env->spr[SPR_40x_TSR] |= 1 << 26;
|
||||
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
|
||||
ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
|
||||
}
|
||||
LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
|
||||
(int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
|
||||
env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
|
||||
|
@ -897,16 +913,19 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
|
|||
|
||||
static void cpu_4xx_pit_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
env->spr[SPR_40x_TSR] |= 1 << 27;
|
||||
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
|
||||
ppc_set_irq(env, ppc40x_timer->decr_excp, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
|
||||
ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
|
||||
}
|
||||
start_stop_pit(env, tb_env, 1);
|
||||
LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
|
||||
"%016" PRIx64 "\n", __func__,
|
||||
|
@ -919,12 +938,14 @@ static void cpu_4xx_pit_cb (void *opaque)
|
|||
/* Watchdog timer */
|
||||
static void cpu_4xx_wdt_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
uint64_t now, next;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
now = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -961,8 +982,9 @@ static void cpu_4xx_wdt_cb (void *opaque)
|
|||
qemu_mod_timer(ppc40x_timer->wdt_timer, next);
|
||||
ppc40x_timer->wdt_next = next;
|
||||
env->spr[SPR_40x_TSR] |= 1 << 30;
|
||||
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
|
||||
ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
|
||||
}
|
||||
break;
|
||||
case 0x3:
|
||||
env->spr[SPR_40x_TSR] &= ~0x30000000;
|
||||
|
|
4
hw/ppc.h
4
hw/ppc.h
|
@ -1,7 +1,7 @@
|
|||
#ifndef HW_PPC_H
|
||||
#define HW_PPC_H 1
|
||||
|
||||
void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level);
|
||||
void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
|
||||
|
||||
/* PowerPC hardware exceptions management helpers */
|
||||
typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
|
||||
|
@ -92,6 +92,6 @@ enum {
|
|||
#define PPC_SERIAL_MM_BAUDBASE 399193
|
||||
|
||||
/* ppc_booke.c */
|
||||
void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags);
|
||||
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -496,7 +496,7 @@ void ppce500_init(PPCE500Params *params)
|
|||
env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
|
||||
MPC8544_MPIC_REGS_OFFSET + 0x20000;
|
||||
|
||||
ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
|
||||
ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
|
||||
|
||||
/* Register reset handler */
|
||||
if (!i) {
|
||||
|
|
|
@ -2111,12 +2111,14 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
|
|||
{
|
||||
clk_setup_t clk_setup[PPC405CR_CLK_NB];
|
||||
qemu_irq dma_irqs[4];
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
qemu_irq *pic, *irqs;
|
||||
|
||||
memset(clk_setup, 0, sizeof(clk_setup));
|
||||
env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
|
||||
cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
|
||||
&clk_setup[PPC405CR_TMR_CLK], sysclk);
|
||||
env = &cpu->env;
|
||||
/* Memory mapped devices registers */
|
||||
/* PLB arbitrer */
|
||||
ppc4xx_plb_init(env);
|
||||
|
@ -2460,13 +2462,15 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
|||
{
|
||||
clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
|
||||
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
qemu_irq *pic, *irqs;
|
||||
|
||||
memset(clk_setup, 0, sizeof(clk_setup));
|
||||
/* init CPUs */
|
||||
env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
|
||||
cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
|
||||
&tlb_clk_setup, sysclk);
|
||||
env = &cpu->env;
|
||||
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
|
||||
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
|
||||
/* Internal devices init */
|
||||
|
@ -2478,7 +2482,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
|||
/* OBP arbitrer */
|
||||
ppc4xx_opba_init(0xef600600);
|
||||
/* Initialize timers */
|
||||
ppc_booke_timers_init(env, sysclk, 0);
|
||||
ppc_booke_timers_init(cpu, sysclk, 0);
|
||||
/* Universal interrupt controller */
|
||||
irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
|
||||
irqs[PPCUIC_OUTPUT_INT] =
|
||||
|
|
|
@ -195,7 +195,7 @@ static void bamboo_init(QEMUMachineInitArgs *args)
|
|||
env = &cpu->env;
|
||||
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
ppc_booke_timers_init(env, 400000000, 0);
|
||||
ppc_booke_timers_init(cpu, 400000000, 0);
|
||||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
/* interrupt controller */
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
#include "pci/pci.h"
|
||||
|
||||
/* PowerPC 4xx core initialization */
|
||||
CPUPPCState *ppc4xx_init (const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk);
|
||||
PowerPCCPU *ppc4xx_init(const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk);
|
||||
|
||||
/* PowerPC 4xx universal interrupt controller */
|
||||
enum {
|
||||
|
|
|
@ -47,9 +47,9 @@ static void ppc4xx_reset(void *opaque)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* Generic PowerPC 4xx processor instantiation */
|
||||
CPUPPCState *ppc4xx_init (const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk)
|
||||
PowerPCCPU *ppc4xx_init(const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
|
@ -72,7 +72,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
|
|||
/* Register qemu callbacks */
|
||||
qemu_register_reset(ppc4xx_reset, cpu);
|
||||
|
||||
return env;
|
||||
return cpu;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -71,17 +71,19 @@ struct booke_timer_t {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
static void booke_update_irq(CPUPPCState *env)
|
||||
static void booke_update_irq(PowerPCCPU *cpu)
|
||||
{
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DECR,
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_DIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_DIE));
|
||||
|
||||
ppc_set_irq(env, PPC_INTERRUPT_WDT,
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_WIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_WIE));
|
||||
|
||||
ppc_set_irq(env, PPC_INTERRUPT_FIT,
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_FIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_FIE));
|
||||
}
|
||||
|
@ -153,10 +155,11 @@ static void booke_update_fixed_timer(CPUPPCState *env,
|
|||
|
||||
static void booke_decr_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env = opaque;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
|
||||
/* Auto Reload */
|
||||
|
@ -166,16 +169,16 @@ static void booke_decr_cb(void *opaque)
|
|||
|
||||
static void booke_fit_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
||||
env = opaque;
|
||||
tb_env = env->tb_env;
|
||||
booke_timer = tb_env->opaque;
|
||||
env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_fit_target(env, tb_env),
|
||||
|
@ -185,17 +188,17 @@ static void booke_fit_cb(void *opaque)
|
|||
|
||||
static void booke_wdt_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
||||
env = opaque;
|
||||
tb_env = env->tb_env;
|
||||
booke_timer = tb_env->opaque;
|
||||
|
||||
/* TODO: There's lots of complicated stuff to do here */
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_wdt_target(env, tb_env),
|
||||
|
@ -205,19 +208,22 @@ static void booke_wdt_cb(void *opaque)
|
|||
|
||||
void store_booke_tsr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
env->spr[SPR_BOOKE_TSR] &= ~val;
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
}
|
||||
|
||||
void store_booke_tcr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
booke_timer_t *booke_timer = tb_env->opaque;
|
||||
|
||||
tb_env = env->tb_env;
|
||||
env->spr[SPR_BOOKE_TCR] = val;
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_fit_target(env, tb_env),
|
||||
|
@ -231,7 +237,7 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
|
|||
|
||||
}
|
||||
|
||||
void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags)
|
||||
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
|
||||
{
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
@ -239,16 +245,16 @@ void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags)
|
|||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||
booke_timer = g_malloc0(sizeof(booke_timer_t));
|
||||
|
||||
env->tb_env = tb_env;
|
||||
cpu->env.tb_env = tb_env;
|
||||
tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
|
||||
|
||||
tb_env->tb_freq = freq;
|
||||
tb_env->decr_freq = freq;
|
||||
tb_env->opaque = booke_timer;
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, env);
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
|
||||
|
||||
booke_timer->fit_timer =
|
||||
qemu_new_timer_ns(vm_clock, &booke_fit_cb, env);
|
||||
qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
|
||||
booke_timer->wdt_timer =
|
||||
qemu_new_timer_ns(vm_clock, &booke_wdt_cb, env);
|
||||
qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* qdev property parsing and global properties
|
||||
* (parts specific for qemu-system-*)
|
||||
*
|
||||
* This file is based on code from hw/qdev-properties.c from
|
||||
* commit 074a86fccd185616469dfcdc0e157f438aebba18,
|
||||
* Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "net/net.h"
|
||||
#include "qdev.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block-common.h"
|
||||
#include "net/hub.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "char/char.h"
|
||||
|
||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
const char *(*print)(void *ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *p;
|
||||
|
||||
p = (char *) (*ptr ? print(*ptr) : "");
|
||||
visit_type_str(v, &p, name, errp);
|
||||
}
|
||||
|
||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
int (*parse)(DeviceState *dev, const char *str,
|
||||
void **ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Error *local_err = NULL;
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, &str, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (!*str) {
|
||||
g_free(str);
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
ret = parse(dev, str, ptr);
|
||||
error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
/* --- drive --- */
|
||||
|
||||
static int parse_drive(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs = bdrv_find(str);
|
||||
if (bs == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (bdrv_attach_dev(bs, dev) < 0) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = bs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_drive(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
bdrv_detach_dev(*ptr, dev);
|
||||
blockdev_auto_del(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *print_drive(void *ptr)
|
||||
{
|
||||
return bdrv_get_device_name(ptr);
|
||||
}
|
||||
|
||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_drive, name, errp);
|
||||
}
|
||||
|
||||
static void set_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_drive, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_drive = {
|
||||
.name = "drive",
|
||||
.get = get_drive,
|
||||
.set = set_drive,
|
||||
.release = release_drive,
|
||||
};
|
||||
|
||||
/* --- character device --- */
|
||||
|
||||
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_find(str);
|
||||
if (chr == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (chr->avail_connections < 1) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = chr;
|
||||
--chr->avail_connections;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_chr(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *print_chr(void *ptr)
|
||||
{
|
||||
CharDriverState *chr = ptr;
|
||||
|
||||
return chr->label ? chr->label : "";
|
||||
}
|
||||
|
||||
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_chr, name, errp);
|
||||
}
|
||||
|
||||
static void set_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_chr, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_chr = {
|
||||
.name = "chr",
|
||||
.get = get_chr,
|
||||
.set = set_chr,
|
||||
.release = release_chr,
|
||||
};
|
||||
|
||||
/* --- netdev device --- */
|
||||
|
||||
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
NetClientState *netdev = qemu_find_netdev(str);
|
||||
|
||||
if (netdev == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (netdev->peer) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = netdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *print_netdev(void *ptr)
|
||||
{
|
||||
NetClientState *netdev = ptr;
|
||||
|
||||
return netdev->name ? netdev->name : "";
|
||||
}
|
||||
|
||||
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_netdev, name, errp);
|
||||
}
|
||||
|
||||
static void set_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_netdev, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_netdev = {
|
||||
.name = "netdev",
|
||||
.get = get_netdev,
|
||||
.set = set_netdev,
|
||||
};
|
||||
|
||||
/* --- vlan --- */
|
||||
|
||||
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
{
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
int id;
|
||||
if (!net_hub_id_for_client(*ptr, &id)) {
|
||||
return snprintf(dest, len, "%d", id);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
|
||||
static void get_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
int32_t id = -1;
|
||||
|
||||
if (*ptr) {
|
||||
int hub_id;
|
||||
if (!net_hub_id_for_client(*ptr, &hub_id)) {
|
||||
id = hub_id;
|
||||
}
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, errp);
|
||||
}
|
||||
|
||||
static void set_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
Error *local_err = NULL;
|
||||
int32_t id;
|
||||
NetClientState *hubport;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (id == -1) {
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
hubport = net_hub_port_find(id);
|
||||
if (!hubport) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
name, prop->info->name);
|
||||
return;
|
||||
}
|
||||
*ptr = hubport;
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_vlan = {
|
||||
.name = "vlan",
|
||||
.print = print_vlan,
|
||||
.get = get_vlan,
|
||||
.set = set_vlan,
|
||||
};
|
||||
|
||||
int qdev_prop_set_drive(DeviceState *dev, const char *name,
|
||||
BlockDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
|
||||
object_property_set_str(OBJECT(dev), bdrv_name,
|
||||
name, &errp);
|
||||
if (errp) {
|
||||
qerror_report_err(errp);
|
||||
error_free(errp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
|
||||
BlockDriverState *value)
|
||||
{
|
||||
if (qdev_prop_set_drive(dev, name, value) < 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name,
|
||||
CharDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->label);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->label : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name,
|
||||
NetClientState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->name);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->name : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
{
|
||||
qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
|
||||
if (nd->netdev) {
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
}
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
}
|
||||
|
||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_add_globals(void)
|
||||
{
|
||||
qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
|
||||
}
|
|
@ -14,49 +14,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
const char *(*print)(void *ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *p;
|
||||
|
||||
p = (char *) (*ptr ? print(*ptr) : "");
|
||||
visit_type_str(v, &p, name, errp);
|
||||
}
|
||||
|
||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
int (*parse)(DeviceState *dev, const char *str,
|
||||
void **ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Error *local_err = NULL;
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, &str, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (!*str) {
|
||||
g_free(str);
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
ret = parse(dev, str, ptr);
|
||||
error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void get_enum(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
|
@ -96,10 +53,11 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
|
|||
{
|
||||
uint32_t *p = qdev_get_prop_ptr(dev, props);
|
||||
uint32_t mask = qdev_get_prop_mask(props);
|
||||
if (val)
|
||||
if (val) {
|
||||
*p |= mask;
|
||||
else
|
||||
} else {
|
||||
*p &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
|
@ -421,11 +379,13 @@ static void release_string(Object *obj, const char *name, void *opaque)
|
|||
g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
|
||||
}
|
||||
|
||||
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
static int print_string(DeviceState *dev, Property *prop, char *dest,
|
||||
size_t len)
|
||||
{
|
||||
char **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
if (!*ptr)
|
||||
if (!*ptr) {
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
return snprintf(dest, len, "\"%s\"", *ptr);
|
||||
}
|
||||
|
||||
|
@ -477,227 +437,6 @@ PropertyInfo qdev_prop_string = {
|
|||
.set = set_string,
|
||||
};
|
||||
|
||||
/* --- drive --- */
|
||||
|
||||
static int parse_drive(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs = bdrv_find(str);
|
||||
if (bs == NULL)
|
||||
return -ENOENT;
|
||||
if (bdrv_attach_dev(bs, dev) < 0)
|
||||
return -EEXIST;
|
||||
*ptr = bs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_drive(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
bdrv_detach_dev(*ptr, dev);
|
||||
blockdev_auto_del(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *print_drive(void *ptr)
|
||||
{
|
||||
return bdrv_get_device_name(ptr);
|
||||
}
|
||||
|
||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_drive, name, errp);
|
||||
}
|
||||
|
||||
static void set_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_drive, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_drive = {
|
||||
.name = "drive",
|
||||
.get = get_drive,
|
||||
.set = set_drive,
|
||||
.release = release_drive,
|
||||
};
|
||||
|
||||
/* --- character device --- */
|
||||
|
||||
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_find(str);
|
||||
if (chr == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (chr->avail_connections < 1) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = chr;
|
||||
--chr->avail_connections;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_chr(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *print_chr(void *ptr)
|
||||
{
|
||||
CharDriverState *chr = ptr;
|
||||
|
||||
return chr->label ? chr->label : "";
|
||||
}
|
||||
|
||||
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_chr, name, errp);
|
||||
}
|
||||
|
||||
static void set_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_chr, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_chr = {
|
||||
.name = "chr",
|
||||
.get = get_chr,
|
||||
.set = set_chr,
|
||||
.release = release_chr,
|
||||
};
|
||||
|
||||
/* --- netdev device --- */
|
||||
|
||||
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
NetClientState *netdev = qemu_find_netdev(str);
|
||||
|
||||
if (netdev == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (netdev->peer) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = netdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *print_netdev(void *ptr)
|
||||
{
|
||||
NetClientState *netdev = ptr;
|
||||
|
||||
return netdev->name ? netdev->name : "";
|
||||
}
|
||||
|
||||
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_netdev, name, errp);
|
||||
}
|
||||
|
||||
static void set_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_netdev, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_netdev = {
|
||||
.name = "netdev",
|
||||
.get = get_netdev,
|
||||
.set = set_netdev,
|
||||
};
|
||||
|
||||
/* --- vlan --- */
|
||||
|
||||
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
{
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
int id;
|
||||
if (!net_hub_id_for_client(*ptr, &id)) {
|
||||
return snprintf(dest, len, "%d", id);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
|
||||
static void get_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
int32_t id = -1;
|
||||
|
||||
if (*ptr) {
|
||||
int hub_id;
|
||||
if (!net_hub_id_for_client(*ptr, &hub_id)) {
|
||||
id = hub_id;
|
||||
}
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, errp);
|
||||
}
|
||||
|
||||
static void set_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
Error *local_err = NULL;
|
||||
int32_t id;
|
||||
NetClientState *hubport;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (id == -1) {
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
hubport = net_hub_port_find(id);
|
||||
if (!hubport) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
name, prop->info->name);
|
||||
return;
|
||||
}
|
||||
*ptr = hubport;
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_vlan = {
|
||||
.name = "vlan",
|
||||
.print = print_vlan,
|
||||
.get = get_vlan,
|
||||
.set = set_vlan,
|
||||
};
|
||||
|
||||
/* --- pointer --- */
|
||||
|
||||
/* Not a proper property, just for dirty hacks. TODO Remove it! */
|
||||
|
@ -750,16 +489,20 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
|
|||
}
|
||||
|
||||
for (i = 0, pos = 0; i < 6; i++, pos += 3) {
|
||||
if (!qemu_isxdigit(str[pos]))
|
||||
if (!qemu_isxdigit(str[pos])) {
|
||||
goto inval;
|
||||
if (!qemu_isxdigit(str[pos+1]))
|
||||
}
|
||||
if (!qemu_isxdigit(str[pos+1])) {
|
||||
goto inval;
|
||||
}
|
||||
if (i == 5) {
|
||||
if (str[pos+2] != '\0')
|
||||
if (str[pos+2] != '\0') {
|
||||
goto inval;
|
||||
}
|
||||
} else {
|
||||
if (str[pos+2] != ':' && str[pos+2] != '-')
|
||||
if (str[pos+2] != ':' && str[pos+2] != '-') {
|
||||
goto inval;
|
||||
}
|
||||
}
|
||||
mac->a[i] = strtol(str+pos, &p, 16);
|
||||
}
|
||||
|
@ -865,7 +608,8 @@ invalid:
|
|||
g_free(str);
|
||||
}
|
||||
|
||||
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
|
||||
size_t len)
|
||||
{
|
||||
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
|
@ -1039,11 +783,13 @@ PropertyInfo qdev_prop_pci_host_devaddr = {
|
|||
|
||||
static Property *qdev_prop_walk(Property *props, const char *name)
|
||||
{
|
||||
if (!props)
|
||||
if (!props) {
|
||||
return NULL;
|
||||
}
|
||||
while (props->name) {
|
||||
if (strcmp(props->name, name) == 0)
|
||||
if (strcmp(props->name, name) == 0) {
|
||||
return props;
|
||||
}
|
||||
props++;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1159,44 +905,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
|
|||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
|
||||
object_property_set_str(OBJECT(dev), bdrv_name,
|
||||
name, &errp);
|
||||
if (errp) {
|
||||
qerror_report_err(errp);
|
||||
error_free(errp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
|
||||
{
|
||||
if (qdev_prop_set_drive(dev, name, value) < 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->label);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->label : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->name);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->name : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
|
@ -1230,9 +938,10 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
|
|||
*ptr = value;
|
||||
}
|
||||
|
||||
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
|
||||
static QTAILQ_HEAD(, GlobalProperty) global_props =
|
||||
QTAILQ_HEAD_INITIALIZER(global_props);
|
||||
|
||||
static void qdev_prop_register_global(GlobalProperty *prop)
|
||||
void qdev_prop_register_global(GlobalProperty *prop)
|
||||
{
|
||||
QTAILQ_INSERT_TAIL(&global_props, prop, next);
|
||||
}
|
||||
|
@ -1263,20 +972,3 @@ void qdev_prop_set_globals(DeviceState *dev)
|
|||
class = object_class_get_parent(class);
|
||||
} while (class);
|
||||
}
|
||||
|
||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_add_globals(void)
|
||||
{
|
||||
qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
|
|||
/* FIXME: Remove opaque pointer properties. */
|
||||
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
|
||||
|
||||
void qdev_prop_register_global(GlobalProperty *prop);
|
||||
void qdev_prop_register_global_list(GlobalProperty *props);
|
||||
void qdev_prop_set_globals(DeviceState *dev);
|
||||
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
||||
|
|
13
hw/qdev.c
13
hw/qdev.c
|
@ -25,7 +25,6 @@
|
|||
inherit from a particular bus (e.g. PCI or I2C) rather than
|
||||
this API directly. */
|
||||
|
||||
#include "net/net.h"
|
||||
#include "qdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/error.h"
|
||||
|
@ -312,18 +311,6 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
|
|||
dev->gpio_out[n] = pin;
|
||||
}
|
||||
|
||||
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
{
|
||||
qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
|
||||
if (nd->netdev)
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
}
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
{
|
||||
BusState *bus;
|
||||
|
|
|
@ -110,10 +110,12 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
|
|||
return bus;
|
||||
}
|
||||
|
||||
static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
|
||||
static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_virtio_irq(env, config_change, token);
|
||||
kvm_s390_virtio_irq(cpu, config_change, token);
|
||||
} else {
|
||||
cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token);
|
||||
}
|
||||
|
@ -142,8 +144,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
|
|||
s390_virtio_reset_idx(dev);
|
||||
if (dev->qdev.hotplugged) {
|
||||
S390CPU *cpu = s390_cpu_addr2state(0);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
||||
s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -368,9 +369,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
|
|||
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
|
||||
uint64_t token = s390_virtio_device_vq_token(dev, vector);
|
||||
S390CPU *cpu = s390_cpu_addr2state(0);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
s390_virtio_irq(env, 0, token);
|
||||
s390_virtio_irq(cpu, 0, token);
|
||||
}
|
||||
|
||||
static unsigned virtio_s390_get_features(void *opaque)
|
||||
|
|
|
@ -798,7 +798,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
|||
|
||||
/* Tell KVM that we're in PAPR mode */
|
||||
if (kvm_enabled()) {
|
||||
kvmppc_set_papr(env);
|
||||
kvmppc_set_papr(cpu);
|
||||
}
|
||||
|
||||
qemu_register_reset(spapr_cpu_reset, cpu);
|
||||
|
|
|
@ -93,7 +93,7 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
|
|||
}
|
||||
env = &cpu->env;
|
||||
|
||||
ppc_booke_timers_init(env, sysclk, 0/* no flags */);
|
||||
ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
|
||||
|
||||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
|
|
|
@ -12,6 +12,18 @@
|
|||
#include "qemu/bswap.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
/**
|
||||
* CPUListState:
|
||||
* @cpu_fprintf: Print function.
|
||||
* @file: File to print to using @cpu_fprint.
|
||||
*
|
||||
* State commonly used for iterating over CPU models.
|
||||
*/
|
||||
typedef struct CPUListState {
|
||||
fprintf_function cpu_fprintf;
|
||||
FILE *file;
|
||||
} CPUListState;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
enum device_endian {
|
||||
|
|
|
@ -134,8 +134,6 @@ typedef struct icount_decr_u16 {
|
|||
} icount_decr_u16;
|
||||
#endif
|
||||
|
||||
struct kvm_run;
|
||||
struct KVMState;
|
||||
struct qemu_work_item;
|
||||
|
||||
typedef struct CPUBreakpoint {
|
||||
|
@ -204,10 +202,6 @@ typedef struct CPUWatchpoint {
|
|||
/* user data */ \
|
||||
void *opaque; \
|
||||
\
|
||||
const char *cpu_model_str; \
|
||||
struct KVMState *kvm_state; \
|
||||
struct kvm_run *kvm_run; \
|
||||
int kvm_fd; \
|
||||
int kvm_vcpu_dirty;
|
||||
const char *cpu_model_str;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,11 +52,15 @@ typedef struct CPUClass {
|
|||
void (*reset)(CPUState *cpu);
|
||||
} CPUClass;
|
||||
|
||||
struct KVMState;
|
||||
struct kvm_run;
|
||||
|
||||
/**
|
||||
* CPUState:
|
||||
* @created: Indicates whether the CPU thread has been successfully created.
|
||||
* @stop: Indicates a pending stop request.
|
||||
* @stopped: Indicates the CPU has been artificially stopped.
|
||||
* @kvm_fd: vCPU file descriptor for KVM.
|
||||
*
|
||||
* State of one CPU core or thread.
|
||||
*/
|
||||
|
@ -77,6 +81,13 @@ struct CPUState {
|
|||
bool stop;
|
||||
bool stopped;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int kvm_fd;
|
||||
bool kvm_vcpu_dirty;
|
||||
#endif
|
||||
struct KVMState *kvm_state;
|
||||
struct kvm_run *kvm_run;
|
||||
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
};
|
||||
|
||||
|
|
|
@ -152,20 +152,20 @@ int kvm_ioctl(KVMState *s, int type, ...);
|
|||
|
||||
int kvm_vm_ioctl(KVMState *s, int type, ...);
|
||||
|
||||
int kvm_vcpu_ioctl(CPUArchState *env, int type, ...);
|
||||
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...);
|
||||
|
||||
/* Arch specific hooks */
|
||||
|
||||
extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
|
||||
|
||||
void kvm_arch_pre_run(CPUArchState *env, struct kvm_run *run);
|
||||
void kvm_arch_post_run(CPUArchState *env, struct kvm_run *run);
|
||||
void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run);
|
||||
void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run);
|
||||
|
||||
int kvm_arch_handle_exit(CPUArchState *env, struct kvm_run *run);
|
||||
int kvm_arch_handle_exit(CPUState *cpu, struct kvm_run *run);
|
||||
|
||||
int kvm_arch_process_async_events(CPUArchState *env);
|
||||
int kvm_arch_process_async_events(CPUState *cpu);
|
||||
|
||||
int kvm_arch_get_registers(CPUArchState *env);
|
||||
int kvm_arch_get_registers(CPUState *cpu);
|
||||
|
||||
/* state subset only touched by the VCPU itself during runtime */
|
||||
#define KVM_PUT_RUNTIME_STATE 1
|
||||
|
@ -174,15 +174,15 @@ int kvm_arch_get_registers(CPUArchState *env);
|
|||
/* full state set, modified during initialization or on vmload */
|
||||
#define KVM_PUT_FULL_STATE 3
|
||||
|
||||
int kvm_arch_put_registers(CPUArchState *env, int level);
|
||||
int kvm_arch_put_registers(CPUState *cpu, int level);
|
||||
|
||||
int kvm_arch_init(KVMState *s);
|
||||
|
||||
int kvm_arch_init_vcpu(CPUArchState *env);
|
||||
int kvm_arch_init_vcpu(CPUState *cpu);
|
||||
|
||||
void kvm_arch_reset_vcpu(CPUArchState *env);
|
||||
void kvm_arch_reset_vcpu(CPUState *cpu);
|
||||
|
||||
int kvm_arch_on_sigbus_vcpu(CPUArchState *env, int code, void *addr);
|
||||
int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
|
||||
int kvm_arch_on_sigbus(int code, void *addr);
|
||||
|
||||
void kvm_arch_init_irq_routing(KVMState *s);
|
||||
|
@ -207,14 +207,14 @@ struct kvm_sw_breakpoint {
|
|||
|
||||
QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint);
|
||||
|
||||
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
|
||||
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
|
||||
target_ulong pc);
|
||||
|
||||
int kvm_sw_breakpoints_active(CPUArchState *env);
|
||||
int kvm_sw_breakpoints_active(CPUState *cpu);
|
||||
|
||||
int kvm_arch_insert_sw_breakpoint(CPUArchState *current_env,
|
||||
int kvm_arch_insert_sw_breakpoint(CPUState *current_cpu,
|
||||
struct kvm_sw_breakpoint *bp);
|
||||
int kvm_arch_remove_sw_breakpoint(CPUArchState *current_env,
|
||||
int kvm_arch_remove_sw_breakpoint(CPUState *current_cpu,
|
||||
struct kvm_sw_breakpoint *bp);
|
||||
int kvm_arch_insert_hw_breakpoint(target_ulong addr,
|
||||
target_ulong len, int type);
|
||||
|
@ -222,9 +222,9 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,
|
|||
target_ulong len, int type);
|
||||
void kvm_arch_remove_all_hw_breakpoints(void);
|
||||
|
||||
void kvm_arch_update_guest_debug(CPUArchState *env, struct kvm_guest_debug *dbg);
|
||||
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg);
|
||||
|
||||
bool kvm_arch_stop_on_emulation_error(CPUArchState *env);
|
||||
bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension);
|
||||
|
||||
|
|
127
kvm-all.c
127
kvm-all.c
|
@ -209,13 +209,14 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
|
|||
|
||||
static void kvm_reset_vcpu(void *opaque)
|
||||
{
|
||||
CPUArchState *env = opaque;
|
||||
CPUState *cpu = opaque;
|
||||
|
||||
kvm_arch_reset_vcpu(env);
|
||||
kvm_arch_reset_vcpu(cpu);
|
||||
}
|
||||
|
||||
int kvm_init_vcpu(CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
KVMState *s = kvm_state;
|
||||
long mmap_size;
|
||||
int ret;
|
||||
|
@ -228,9 +229,9 @@ int kvm_init_vcpu(CPUArchState *env)
|
|||
goto err;
|
||||
}
|
||||
|
||||
env->kvm_fd = ret;
|
||||
env->kvm_state = s;
|
||||
env->kvm_vcpu_dirty = 1;
|
||||
cpu->kvm_fd = ret;
|
||||
cpu->kvm_state = s;
|
||||
cpu->kvm_vcpu_dirty = true;
|
||||
|
||||
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
|
||||
if (mmap_size < 0) {
|
||||
|
@ -239,9 +240,9 @@ int kvm_init_vcpu(CPUArchState *env)
|
|||
goto err;
|
||||
}
|
||||
|
||||
env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
env->kvm_fd, 0);
|
||||
if (env->kvm_run == MAP_FAILED) {
|
||||
cpu->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
cpu->kvm_fd, 0);
|
||||
if (cpu->kvm_run == MAP_FAILED) {
|
||||
ret = -errno;
|
||||
DPRINTF("mmap'ing vcpu state failed\n");
|
||||
goto err;
|
||||
|
@ -249,13 +250,13 @@ int kvm_init_vcpu(CPUArchState *env)
|
|||
|
||||
if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
|
||||
s->coalesced_mmio_ring =
|
||||
(void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE;
|
||||
(void *)cpu->kvm_run + s->coalesced_mmio * PAGE_SIZE;
|
||||
}
|
||||
|
||||
ret = kvm_arch_init_vcpu(env);
|
||||
ret = kvm_arch_init_vcpu(cpu);
|
||||
if (ret == 0) {
|
||||
qemu_register_reset(kvm_reset_vcpu, env);
|
||||
kvm_arch_reset_vcpu(env);
|
||||
qemu_register_reset(kvm_reset_vcpu, cpu);
|
||||
kvm_arch_reset_vcpu(cpu);
|
||||
}
|
||||
err:
|
||||
return ret;
|
||||
|
@ -1435,6 +1436,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
|
|||
|
||||
static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
|
||||
fprintf(stderr, "KVM internal error.");
|
||||
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
|
||||
int i;
|
||||
|
@ -1449,7 +1452,7 @@ static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run)
|
|||
}
|
||||
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
|
||||
fprintf(stderr, "emulation failure\n");
|
||||
if (!kvm_arch_stop_on_emulation_error(env)) {
|
||||
if (!kvm_arch_stop_on_emulation_error(cpu)) {
|
||||
cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
|
||||
return EXCP_INTERRUPT;
|
||||
}
|
||||
|
@ -1486,13 +1489,13 @@ void kvm_flush_coalesced_mmio_buffer(void)
|
|||
s->coalesced_flush_in_progress = false;
|
||||
}
|
||||
|
||||
static void do_kvm_cpu_synchronize_state(void *_env)
|
||||
static void do_kvm_cpu_synchronize_state(void *arg)
|
||||
{
|
||||
CPUArchState *env = _env;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
if (!env->kvm_vcpu_dirty) {
|
||||
kvm_arch_get_registers(env);
|
||||
env->kvm_vcpu_dirty = 1;
|
||||
if (!cpu->kvm_vcpu_dirty) {
|
||||
kvm_arch_get_registers(cpu);
|
||||
cpu->kvm_vcpu_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1500,42 +1503,47 @@ void kvm_cpu_synchronize_state(CPUArchState *env)
|
|||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
|
||||
if (!env->kvm_vcpu_dirty) {
|
||||
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, env);
|
||||
if (!cpu->kvm_vcpu_dirty) {
|
||||
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_cpu_synchronize_post_reset(CPUArchState *env)
|
||||
{
|
||||
kvm_arch_put_registers(env, KVM_PUT_RESET_STATE);
|
||||
env->kvm_vcpu_dirty = 0;
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE);
|
||||
cpu->kvm_vcpu_dirty = false;
|
||||
}
|
||||
|
||||
void kvm_cpu_synchronize_post_init(CPUArchState *env)
|
||||
{
|
||||
kvm_arch_put_registers(env, KVM_PUT_FULL_STATE);
|
||||
env->kvm_vcpu_dirty = 0;
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
cpu->kvm_vcpu_dirty = false;
|
||||
}
|
||||
|
||||
int kvm_cpu_exec(CPUArchState *env)
|
||||
{
|
||||
struct kvm_run *run = env->kvm_run;
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
struct kvm_run *run = cpu->kvm_run;
|
||||
int ret, run_ret;
|
||||
|
||||
DPRINTF("kvm_cpu_exec()\n");
|
||||
|
||||
if (kvm_arch_process_async_events(env)) {
|
||||
if (kvm_arch_process_async_events(cpu)) {
|
||||
env->exit_request = 0;
|
||||
return EXCP_HLT;
|
||||
}
|
||||
|
||||
do {
|
||||
if (env->kvm_vcpu_dirty) {
|
||||
kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE);
|
||||
env->kvm_vcpu_dirty = 0;
|
||||
if (cpu->kvm_vcpu_dirty) {
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE);
|
||||
cpu->kvm_vcpu_dirty = false;
|
||||
}
|
||||
|
||||
kvm_arch_pre_run(env, run);
|
||||
kvm_arch_pre_run(cpu, run);
|
||||
if (env->exit_request) {
|
||||
DPRINTF("interrupt exit requested\n");
|
||||
/*
|
||||
|
@ -1547,10 +1555,10 @@ int kvm_cpu_exec(CPUArchState *env)
|
|||
}
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
run_ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
|
||||
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
kvm_arch_post_run(env, run);
|
||||
kvm_arch_post_run(cpu, run);
|
||||
|
||||
if (run_ret < 0) {
|
||||
if (run_ret == -EINTR || run_ret == -EAGAIN) {
|
||||
|
@ -1600,7 +1608,7 @@ int kvm_cpu_exec(CPUArchState *env)
|
|||
break;
|
||||
default:
|
||||
DPRINTF("kvm_arch_handle_exit\n");
|
||||
ret = kvm_arch_handle_exit(env, run);
|
||||
ret = kvm_arch_handle_exit(cpu, run);
|
||||
break;
|
||||
}
|
||||
} while (ret == 0);
|
||||
|
@ -1648,7 +1656,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int kvm_vcpu_ioctl(CPUArchState *env, int type, ...)
|
||||
int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
|
||||
{
|
||||
int ret;
|
||||
void *arg;
|
||||
|
@ -1658,7 +1666,7 @@ int kvm_vcpu_ioctl(CPUArchState *env, int type, ...)
|
|||
arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
ret = ioctl(env->kvm_fd, type, arg);
|
||||
ret = ioctl(cpu->kvm_fd, type, arg);
|
||||
if (ret == -1) {
|
||||
ret = -errno;
|
||||
}
|
||||
|
@ -1753,12 +1761,12 @@ void kvm_setup_guest_memory(void *start, size_t size)
|
|||
}
|
||||
|
||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
|
||||
struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu,
|
||||
target_ulong pc)
|
||||
{
|
||||
struct kvm_sw_breakpoint *bp;
|
||||
|
||||
QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
|
||||
QTAILQ_FOREACH(bp, &cpu->kvm_state->kvm_sw_breakpoints, entry) {
|
||||
if (bp->pc == pc) {
|
||||
return bp;
|
||||
}
|
||||
|
@ -1766,23 +1774,23 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int kvm_sw_breakpoints_active(CPUArchState *env)
|
||||
int kvm_sw_breakpoints_active(CPUState *cpu)
|
||||
{
|
||||
return !QTAILQ_EMPTY(&env->kvm_state->kvm_sw_breakpoints);
|
||||
return !QTAILQ_EMPTY(&cpu->kvm_state->kvm_sw_breakpoints);
|
||||
}
|
||||
|
||||
struct kvm_set_guest_debug_data {
|
||||
struct kvm_guest_debug dbg;
|
||||
CPUArchState *env;
|
||||
CPUState *cpu;
|
||||
int err;
|
||||
};
|
||||
|
||||
static void kvm_invoke_set_guest_debug(void *data)
|
||||
{
|
||||
struct kvm_set_guest_debug_data *dbg_data = data;
|
||||
CPUArchState *env = dbg_data->env;
|
||||
|
||||
dbg_data->err = kvm_vcpu_ioctl(env, KVM_SET_GUEST_DEBUG, &dbg_data->dbg);
|
||||
dbg_data->err = kvm_vcpu_ioctl(dbg_data->cpu, KVM_SET_GUEST_DEBUG,
|
||||
&dbg_data->dbg);
|
||||
}
|
||||
|
||||
int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
|
||||
|
@ -1795,8 +1803,8 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
|
|||
if (env->singlestep_enabled) {
|
||||
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
|
||||
}
|
||||
kvm_arch_update_guest_debug(env, &data.dbg);
|
||||
data.env = env;
|
||||
kvm_arch_update_guest_debug(cpu, &data.dbg);
|
||||
data.cpu = cpu;
|
||||
|
||||
run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data);
|
||||
return data.err;
|
||||
|
@ -1805,12 +1813,13 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
|
|||
int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
CPUState *current_cpu = ENV_GET_CPU(current_env);
|
||||
struct kvm_sw_breakpoint *bp;
|
||||
CPUArchState *env;
|
||||
int err;
|
||||
|
||||
if (type == GDB_BREAKPOINT_SW) {
|
||||
bp = kvm_find_sw_breakpoint(current_env, addr);
|
||||
bp = kvm_find_sw_breakpoint(current_cpu, addr);
|
||||
if (bp) {
|
||||
bp->use_count++;
|
||||
return 0;
|
||||
|
@ -1823,13 +1832,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
|
|||
|
||||
bp->pc = addr;
|
||||
bp->use_count = 1;
|
||||
err = kvm_arch_insert_sw_breakpoint(current_env, bp);
|
||||
err = kvm_arch_insert_sw_breakpoint(current_cpu, bp);
|
||||
if (err) {
|
||||
g_free(bp);
|
||||
return err;
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_HEAD(¤t_env->kvm_state->kvm_sw_breakpoints,
|
||||
QTAILQ_INSERT_HEAD(¤t_cpu->kvm_state->kvm_sw_breakpoints,
|
||||
bp, entry);
|
||||
} else {
|
||||
err = kvm_arch_insert_hw_breakpoint(addr, len, type);
|
||||
|
@ -1850,12 +1859,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
|
|||
int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
|
||||
target_ulong len, int type)
|
||||
{
|
||||
CPUState *current_cpu = ENV_GET_CPU(current_env);
|
||||
struct kvm_sw_breakpoint *bp;
|
||||
CPUArchState *env;
|
||||
int err;
|
||||
|
||||
if (type == GDB_BREAKPOINT_SW) {
|
||||
bp = kvm_find_sw_breakpoint(current_env, addr);
|
||||
bp = kvm_find_sw_breakpoint(current_cpu, addr);
|
||||
if (!bp) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -1865,12 +1875,12 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = kvm_arch_remove_sw_breakpoint(current_env, bp);
|
||||
err = kvm_arch_remove_sw_breakpoint(current_cpu, bp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
|
||||
QTAILQ_REMOVE(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
|
||||
g_free(bp);
|
||||
} else {
|
||||
err = kvm_arch_remove_hw_breakpoint(addr, len, type);
|
||||
|
@ -1890,15 +1900,18 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
|
|||
|
||||
void kvm_remove_all_breakpoints(CPUArchState *current_env)
|
||||
{
|
||||
CPUState *current_cpu = ENV_GET_CPU(current_env);
|
||||
struct kvm_sw_breakpoint *bp, *next;
|
||||
KVMState *s = current_env->kvm_state;
|
||||
KVMState *s = current_cpu->kvm_state;
|
||||
CPUArchState *env;
|
||||
CPUState *cpu;
|
||||
|
||||
QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) {
|
||||
if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
|
||||
if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) {
|
||||
/* Try harder to find a CPU that currently sees the breakpoint. */
|
||||
for (env = first_cpu; env != NULL; env = env->next_cpu) {
|
||||
if (kvm_arch_remove_sw_breakpoint(env, bp) == 0) {
|
||||
cpu = ENV_GET_CPU(env);
|
||||
if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1939,18 +1952,19 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env)
|
|||
|
||||
int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
struct kvm_signal_mask *sigmask;
|
||||
int r;
|
||||
|
||||
if (!sigset) {
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL);
|
||||
return kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, NULL);
|
||||
}
|
||||
|
||||
sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
|
||||
|
||||
sigmask->len = 8;
|
||||
memcpy(sigmask->sigset, sigset, sizeof(*sigset));
|
||||
r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask);
|
||||
r = kvm_vcpu_ioctl(cpu, KVM_SET_SIGNAL_MASK, sigmask);
|
||||
g_free(sigmask);
|
||||
|
||||
return r;
|
||||
|
@ -2010,7 +2024,8 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
|
|||
|
||||
int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr)
|
||||
{
|
||||
return kvm_arch_on_sigbus_vcpu(env, code, addr);
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
return kvm_arch_on_sigbus_vcpu(cpu, code, addr);
|
||||
}
|
||||
|
||||
int kvm_on_sigbus(int code, void *addr)
|
||||
|
|
|
@ -58,6 +58,9 @@ typedef struct AlphaCPU {
|
|||
/*< public >*/
|
||||
|
||||
CPUAlphaState env;
|
||||
|
||||
/* This alarm doesn't exist in real hardware; we wish it did. */
|
||||
struct QEMUTimer *alarm_timer;
|
||||
} AlphaCPU;
|
||||
|
||||
static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
|
||||
|
|
|
@ -21,8 +21,211 @@
|
|||
|
||||
#include "cpu.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
|
||||
static void alpha_cpu_realize(Object *obj, Error **errp)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
|
||||
qemu_init_vcpu(&cpu->env);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sort alphabetically by type name. */
|
||||
static gint alpha_cpu_list_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
ObjectClass *class_a = (ObjectClass *)a;
|
||||
ObjectClass *class_b = (ObjectClass *)b;
|
||||
const char *name_a, *name_b;
|
||||
|
||||
name_a = object_class_get_name(class_a);
|
||||
name_b = object_class_get_name(class_b);
|
||||
return strcmp(name_a, name_b);
|
||||
}
|
||||
|
||||
static void alpha_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
CPUListState *s = user_data;
|
||||
|
||||
(*s->cpu_fprintf)(s->file, " %s\n",
|
||||
object_class_get_name(oc));
|
||||
}
|
||||
|
||||
void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
CPUListState s = {
|
||||
.file = f,
|
||||
.cpu_fprintf = cpu_fprintf,
|
||||
};
|
||||
GSList *list;
|
||||
|
||||
list = object_class_get_list(TYPE_ALPHA_CPU, false);
|
||||
list = g_slist_sort(list, alpha_cpu_list_compare);
|
||||
(*cpu_fprintf)(f, "Available CPUs:\n");
|
||||
g_slist_foreach(list, alpha_cpu_list_entry, &s);
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
/* Models */
|
||||
|
||||
#define TYPE(model) model "-" TYPE_ALPHA_CPU
|
||||
|
||||
typedef struct AlphaCPUAlias {
|
||||
const char *alias;
|
||||
const char *typename;
|
||||
} AlphaCPUAlias;
|
||||
|
||||
static const AlphaCPUAlias alpha_cpu_aliases[] = {
|
||||
{ "21064", TYPE("ev4") },
|
||||
{ "21164", TYPE("ev5") },
|
||||
{ "21164a", TYPE("ev56") },
|
||||
{ "21164pc", TYPE("pca56") },
|
||||
{ "21264", TYPE("ev6") },
|
||||
{ "21264a", TYPE("ev67") },
|
||||
};
|
||||
|
||||
static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc = NULL;
|
||||
char *typename;
|
||||
int i;
|
||||
|
||||
if (cpu_model == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
oc = object_class_by_name(cpu_model);
|
||||
if (oc != NULL) {
|
||||
return oc;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(alpha_cpu_aliases); i++) {
|
||||
if (strcmp(cpu_model, alpha_cpu_aliases[i].alias) == 0) {
|
||||
oc = object_class_by_name(alpha_cpu_aliases[i].typename);
|
||||
assert(oc != NULL);
|
||||
return oc;
|
||||
}
|
||||
}
|
||||
|
||||
typename = g_strdup_printf("%s-" TYPE_ALPHA_CPU, cpu_model);
|
||||
oc = object_class_by_name(typename);
|
||||
g_free(typename);
|
||||
return oc;
|
||||
}
|
||||
|
||||
AlphaCPU *cpu_alpha_init(const char *cpu_model)
|
||||
{
|
||||
AlphaCPU *cpu;
|
||||
CPUAlphaState *env;
|
||||
ObjectClass *cpu_class;
|
||||
|
||||
cpu_class = alpha_cpu_class_by_name(cpu_model);
|
||||
if (cpu_class == NULL) {
|
||||
/* Default to ev67; no reason not to emulate insns by default. */
|
||||
cpu_class = object_class_by_name(TYPE("ev67"));
|
||||
}
|
||||
cpu = ALPHA_CPU(object_new(object_class_get_name(cpu_class)));
|
||||
env = &cpu->env;
|
||||
|
||||
env->cpu_model_str = cpu_model;
|
||||
|
||||
alpha_cpu_realize(OBJECT(cpu), NULL);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
static void ev4_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->implver = IMPLVER_2106x;
|
||||
}
|
||||
|
||||
static const TypeInfo ev4_cpu_type_info = {
|
||||
.name = TYPE("ev4"),
|
||||
.parent = TYPE_ALPHA_CPU,
|
||||
.instance_init = ev4_cpu_initfn,
|
||||
};
|
||||
|
||||
static void ev5_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->implver = IMPLVER_21164;
|
||||
}
|
||||
|
||||
static const TypeInfo ev5_cpu_type_info = {
|
||||
.name = TYPE("ev5"),
|
||||
.parent = TYPE_ALPHA_CPU,
|
||||
.instance_init = ev5_cpu_initfn,
|
||||
};
|
||||
|
||||
static void ev56_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->amask |= AMASK_BWX;
|
||||
}
|
||||
|
||||
static const TypeInfo ev56_cpu_type_info = {
|
||||
.name = TYPE("ev56"),
|
||||
.parent = TYPE("ev5"),
|
||||
.instance_init = ev56_cpu_initfn,
|
||||
};
|
||||
|
||||
static void pca56_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->amask |= AMASK_MVI;
|
||||
}
|
||||
|
||||
static const TypeInfo pca56_cpu_type_info = {
|
||||
.name = TYPE("pca56"),
|
||||
.parent = TYPE("ev56"),
|
||||
.instance_init = pca56_cpu_initfn,
|
||||
};
|
||||
|
||||
static void ev6_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->implver = IMPLVER_21264;
|
||||
env->amask = AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP;
|
||||
}
|
||||
|
||||
static const TypeInfo ev6_cpu_type_info = {
|
||||
.name = TYPE("ev6"),
|
||||
.parent = TYPE_ALPHA_CPU,
|
||||
.instance_init = ev6_cpu_initfn,
|
||||
};
|
||||
|
||||
static void ev67_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
|
||||
env->amask |= AMASK_CIX | AMASK_PREFETCH;
|
||||
}
|
||||
|
||||
static const TypeInfo ev67_cpu_type_info = {
|
||||
.name = TYPE("ev67"),
|
||||
.parent = TYPE("ev6"),
|
||||
.instance_init = ev67_cpu_initfn,
|
||||
};
|
||||
|
||||
static const TypeInfo ev68_cpu_type_info = {
|
||||
.name = TYPE("ev68"),
|
||||
.parent = TYPE("ev67"),
|
||||
};
|
||||
|
||||
static void alpha_cpu_initfn(Object *obj)
|
||||
{
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
|
@ -31,6 +234,8 @@ static void alpha_cpu_initfn(Object *obj)
|
|||
cpu_exec_init(env);
|
||||
tlb_flush(env, 1);
|
||||
|
||||
alpha_translate_init();
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->ps = PS_USER_MODE;
|
||||
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
|
||||
|
@ -46,13 +251,20 @@ static const TypeInfo alpha_cpu_type_info = {
|
|||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(AlphaCPU),
|
||||
.instance_init = alpha_cpu_initfn,
|
||||
.abstract = false,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(AlphaCPUClass),
|
||||
};
|
||||
|
||||
static void alpha_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&alpha_cpu_type_info);
|
||||
type_register_static(&ev4_cpu_type_info);
|
||||
type_register_static(&ev5_cpu_type_info);
|
||||
type_register_static(&ev56_cpu_type_info);
|
||||
type_register_static(&pca56_cpu_type_info);
|
||||
type_register_static(&ev6_cpu_type_info);
|
||||
type_register_static(&ev67_cpu_type_info);
|
||||
type_register_static(&ev68_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(alpha_cpu_register_types)
|
||||
|
|
|
@ -277,7 +277,6 @@ struct CPUAlphaState {
|
|||
#endif
|
||||
|
||||
/* This alarm doesn't exist in real hardware; we wish it did. */
|
||||
struct QEMUTimer *alarm_timer;
|
||||
uint64_t alarm_expire;
|
||||
|
||||
/* Those resources are used only in QEMU core */
|
||||
|
@ -290,7 +289,7 @@ struct CPUAlphaState {
|
|||
int implver;
|
||||
};
|
||||
|
||||
#define cpu_init cpu_alpha_init
|
||||
#define cpu_list alpha_cpu_list
|
||||
#define cpu_exec cpu_alpha_exec
|
||||
#define cpu_gen_code cpu_alpha_gen_code
|
||||
#define cpu_signal_handler cpu_alpha_signal_handler
|
||||
|
@ -427,7 +426,20 @@ enum {
|
|||
IR_ZERO = 31,
|
||||
};
|
||||
|
||||
CPUAlphaState * cpu_alpha_init (const char *cpu_model);
|
||||
void alpha_translate_init(void);
|
||||
|
||||
AlphaCPU *cpu_alpha_init(const char *cpu_model);
|
||||
|
||||
static inline CPUAlphaState *cpu_init(const char *cpu_model)
|
||||
{
|
||||
AlphaCPU *cpu = cpu_alpha_init(cpu_model);
|
||||
if (cpu == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return &cpu->env;
|
||||
}
|
||||
|
||||
void alpha_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
||||
int cpu_alpha_exec(CPUAlphaState *s);
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
signal handlers to inform the virtual CPU of exceptions. non zero
|
||||
|
|
|
@ -77,11 +77,13 @@ uint64_t helper_get_time(void)
|
|||
|
||||
void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
|
||||
{
|
||||
AlphaCPU *cpu = alpha_env_get_cpu(env);
|
||||
|
||||
if (expire) {
|
||||
env->alarm_expire = expire;
|
||||
qemu_mod_timer(env->alarm_timer, expire);
|
||||
qemu_mod_timer(cpu->alarm_timer, expire);
|
||||
} else {
|
||||
qemu_del_timer(env->alarm_timer);
|
||||
qemu_del_timer(cpu->alarm_timer);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
|
|
@ -90,7 +90,7 @@ static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
|
|||
|
||||
#include "exec/gen-icount.h"
|
||||
|
||||
static void alpha_translate_init(void)
|
||||
void alpha_translate_init(void)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
@ -3493,62 +3493,6 @@ void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
|
|||
gen_intermediate_code_internal(env, tb, 1);
|
||||
}
|
||||
|
||||
struct cpu_def_t {
|
||||
const char *name;
|
||||
int implver, amask;
|
||||
};
|
||||
|
||||
static const struct cpu_def_t cpu_defs[] = {
|
||||
{ "ev4", IMPLVER_2106x, 0 },
|
||||
{ "ev5", IMPLVER_21164, 0 },
|
||||
{ "ev56", IMPLVER_21164, AMASK_BWX },
|
||||
{ "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
|
||||
{ "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
|
||||
{ "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
|
||||
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
|
||||
{ "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
|
||||
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
|
||||
{ "21064", IMPLVER_2106x, 0 },
|
||||
{ "21164", IMPLVER_21164, 0 },
|
||||
{ "21164a", IMPLVER_21164, AMASK_BWX },
|
||||
{ "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
|
||||
{ "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
|
||||
{ "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
|
||||
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }
|
||||
};
|
||||
|
||||
CPUAlphaState * cpu_alpha_init (const char *cpu_model)
|
||||
{
|
||||
AlphaCPU *cpu;
|
||||
CPUAlphaState *env;
|
||||
int implver, amask, i, max;
|
||||
|
||||
cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU));
|
||||
env = &cpu->env;
|
||||
|
||||
alpha_translate_init();
|
||||
|
||||
/* Default to ev67; no reason not to emulate insns by default. */
|
||||
implver = IMPLVER_21264;
|
||||
amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI
|
||||
| AMASK_TRAP | AMASK_PREFETCH);
|
||||
|
||||
max = ARRAY_SIZE(cpu_defs);
|
||||
for (i = 0; i < max; i++) {
|
||||
if (strcmp (cpu_model, cpu_defs[i].name) == 0) {
|
||||
implver = cpu_defs[i].implver;
|
||||
amask = cpu_defs[i].amask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
env->implver = implver;
|
||||
env->amask = amask;
|
||||
env->cpu_model_str = cpu_model;
|
||||
|
||||
qemu_init_vcpu(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
|
||||
{
|
||||
env->pc = tcg_ctx.gen_opc_pc[pc_pos];
|
||||
|
|
|
@ -1291,11 +1291,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model)
|
|||
return cpu;
|
||||
}
|
||||
|
||||
typedef struct ARMCPUListState {
|
||||
fprintf_function cpu_fprintf;
|
||||
FILE *file;
|
||||
} ARMCPUListState;
|
||||
|
||||
/* Sort alphabetically by type name, except for "any". */
|
||||
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
|
@ -1317,7 +1312,7 @@ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b)
|
|||
static void arm_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
ARMCPUListState *s = user_data;
|
||||
CPUListState *s = user_data;
|
||||
|
||||
(*s->cpu_fprintf)(s->file, " %s\n",
|
||||
object_class_get_name(oc));
|
||||
|
@ -1325,7 +1320,7 @@ static void arm_cpu_list_entry(gpointer data, gpointer user_data)
|
|||
|
||||
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
ARMCPUListState s = {
|
||||
CPUListState s = {
|
||||
.file = f,
|
||||
.cpu_fprintf = cpu_fprintf,
|
||||
};
|
||||
|
|
|
@ -1637,6 +1637,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||
uint32_t *eax, uint32_t *ebx,
|
||||
uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
/* test if maximum index reached */
|
||||
if (index & 0x80000000) {
|
||||
if (index > env->cpuid_xlevel) {
|
||||
|
@ -1757,7 +1760,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||
case 0xA:
|
||||
/* Architectural Performance Monitoring Leaf */
|
||||
if (kvm_enabled()) {
|
||||
KVMState *s = env->kvm_state;
|
||||
KVMState *s = cs->kvm_state;
|
||||
|
||||
*eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
|
||||
*ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
|
||||
|
@ -1780,7 +1783,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||
break;
|
||||
}
|
||||
if (kvm_enabled()) {
|
||||
KVMState *s = env->kvm_state;
|
||||
KVMState *s = cs->kvm_state;
|
||||
|
||||
*eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
|
||||
*ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
|
||||
|
|
|
@ -307,16 +307,17 @@ static void hardware_memory_error(void)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
int kvm_arch_on_sigbus_vcpu(CPUX86State *env, int code, void *addr)
|
||||
int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(c);
|
||||
CPUX86State *env = &cpu->env;
|
||||
ram_addr_t ram_addr;
|
||||
hwaddr paddr;
|
||||
|
||||
if ((env->mcg_cap & MCG_SER_P) && addr
|
||||
&& (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
|
||||
if (qemu_ram_addr_from_host(addr, &ram_addr) ||
|
||||
!kvm_physical_memory_addr_from_host(env->kvm_state, addr, &paddr)) {
|
||||
!kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
|
||||
fprintf(stderr, "Hardware memory error for memory used by "
|
||||
"QEMU itself instead of guest system!\n");
|
||||
/* Hope we are lucky for AO MCE */
|
||||
|
@ -348,8 +349,8 @@ int kvm_arch_on_sigbus(int code, void *addr)
|
|||
|
||||
/* Hope we are lucky for AO MCE */
|
||||
if (qemu_ram_addr_from_host(addr, &ram_addr) ||
|
||||
!kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr,
|
||||
&paddr)) {
|
||||
!kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state,
|
||||
addr, &paddr)) {
|
||||
fprintf(stderr, "Hardware memory error for memory used by "
|
||||
"QEMU itself instead of guest system!: %p\n", addr);
|
||||
return 0;
|
||||
|
@ -368,8 +369,10 @@ int kvm_arch_on_sigbus(int code, void *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_inject_mce_oldstyle(CPUX86State *env)
|
||||
static int kvm_inject_mce_oldstyle(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
|
||||
unsigned int bank, bank_num = env->mcg_cap & 0xff;
|
||||
struct kvm_x86_mce mce;
|
||||
|
@ -393,7 +396,7 @@ static int kvm_inject_mce_oldstyle(CPUX86State *env)
|
|||
mce.addr = env->mce_banks[bank * 4 + 2];
|
||||
mce.misc = env->mce_banks[bank * 4 + 3];
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_X86_SET_MCE, &mce);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_X86_SET_MCE, &mce);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -407,12 +410,14 @@ static void cpu_update_state(void *opaque, int running, RunState state)
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_arch_init_vcpu(CPUX86State *env)
|
||||
int kvm_arch_init_vcpu(CPUState *cs)
|
||||
{
|
||||
struct {
|
||||
struct kvm_cpuid2 cpuid;
|
||||
struct kvm_cpuid_entry2 entries[100];
|
||||
} QEMU_PACKED cpuid_data;
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
uint32_t limit, i, j, cpuid_i;
|
||||
uint32_t unused;
|
||||
struct kvm_cpuid_entry2 *c;
|
||||
|
@ -575,12 +580,12 @@ int kvm_arch_init_vcpu(CPUX86State *env)
|
|||
|
||||
if (((env->cpuid_version >> 8)&0xF) >= 6
|
||||
&& (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)
|
||||
&& kvm_check_extension(env->kvm_state, KVM_CAP_MCE) > 0) {
|
||||
&& kvm_check_extension(cs->kvm_state, KVM_CAP_MCE) > 0) {
|
||||
uint64_t mcg_cap;
|
||||
int banks;
|
||||
int ret;
|
||||
|
||||
ret = kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks);
|
||||
ret = kvm_get_mce_cap_supported(cs->kvm_state, &mcg_cap, &banks);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret));
|
||||
return ret;
|
||||
|
@ -591,7 +596,7 @@ int kvm_arch_init_vcpu(CPUX86State *env)
|
|||
}
|
||||
mcg_cap &= MCE_CAP_DEF;
|
||||
mcg_cap |= banks;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_X86_SETUP_MCE, &mcg_cap);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_X86_SETUP_MCE, &mcg_cap);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
|
||||
return ret;
|
||||
|
@ -603,14 +608,14 @@ int kvm_arch_init_vcpu(CPUX86State *env)
|
|||
qemu_add_vm_change_state_handler(cpu_update_state, env);
|
||||
|
||||
cpuid_data.cpuid.padding = 0;
|
||||
r = kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL);
|
||||
r = kvm_check_extension(cs->kvm_state, KVM_CAP_TSC_CONTROL);
|
||||
if (r && env->tsc_khz) {
|
||||
r = kvm_vcpu_ioctl(env, KVM_SET_TSC_KHZ, env->tsc_khz);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_SET_TSC_KHZ, env->tsc_khz);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "KVM_SET_TSC_KHZ failed\n");
|
||||
return r;
|
||||
|
@ -624,9 +629,10 @@ int kvm_arch_init_vcpu(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_reset_vcpu(CPUX86State *env)
|
||||
void kvm_arch_reset_vcpu(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
env->exception_injected = -1;
|
||||
env->interrupt_injected = -1;
|
||||
|
@ -817,13 +823,14 @@ static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
|
|||
}
|
||||
}
|
||||
|
||||
static int kvm_getput_regs(CPUX86State *env, int set)
|
||||
static int kvm_getput_regs(X86CPU *cpu, int set)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_regs regs;
|
||||
int ret = 0;
|
||||
|
||||
if (!set) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_REGS, ®s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -852,14 +859,15 @@ static int kvm_getput_regs(CPUX86State *env, int set)
|
|||
kvm_getput_reg(®s.rip, &env->eip, set);
|
||||
|
||||
if (set) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_REGS, ®s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_put_fpu(CPUX86State *env)
|
||||
static int kvm_put_fpu(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_fpu fpu;
|
||||
int i;
|
||||
|
||||
|
@ -877,7 +885,7 @@ static int kvm_put_fpu(CPUX86State *env)
|
|||
memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
|
||||
fpu.mxcsr = env->mxcsr;
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu);
|
||||
}
|
||||
|
||||
#define XSAVE_FCW_FSW 0
|
||||
|
@ -890,14 +898,15 @@ static int kvm_put_fpu(CPUX86State *env)
|
|||
#define XSAVE_XSTATE_BV 128
|
||||
#define XSAVE_YMMH_SPACE 144
|
||||
|
||||
static int kvm_put_xsave(CPUX86State *env)
|
||||
static int kvm_put_xsave(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_xsave* xsave = env->kvm_xsave_buf;
|
||||
uint16_t cwd, swd, twd;
|
||||
int i, r;
|
||||
|
||||
if (!kvm_has_xsave()) {
|
||||
return kvm_put_fpu(env);
|
||||
return kvm_put_fpu(cpu);
|
||||
}
|
||||
|
||||
memset(xsave, 0, sizeof(struct kvm_xsave));
|
||||
|
@ -920,12 +929,13 @@ static int kvm_put_xsave(CPUX86State *env)
|
|||
*(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv;
|
||||
memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs,
|
||||
sizeof env->ymmh_regs);
|
||||
r = kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave);
|
||||
r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kvm_put_xcrs(CPUX86State *env)
|
||||
static int kvm_put_xcrs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_xcrs xcrs;
|
||||
|
||||
if (!kvm_has_xcrs()) {
|
||||
|
@ -936,11 +946,12 @@ static int kvm_put_xcrs(CPUX86State *env)
|
|||
xcrs.flags = 0;
|
||||
xcrs.xcrs[0].xcr = 0;
|
||||
xcrs.xcrs[0].value = env->xcr0;
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XCRS, &xcrs);
|
||||
}
|
||||
|
||||
static int kvm_put_sregs(CPUX86State *env)
|
||||
static int kvm_put_sregs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_sregs sregs;
|
||||
|
||||
memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
|
||||
|
@ -985,7 +996,7 @@ static int kvm_put_sregs(CPUX86State *env)
|
|||
|
||||
sregs.efer = env->efer;
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs);
|
||||
}
|
||||
|
||||
static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
|
||||
|
@ -995,8 +1006,9 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry,
|
|||
entry->data = value;
|
||||
}
|
||||
|
||||
static int kvm_put_msrs(CPUX86State *env, int level)
|
||||
static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct {
|
||||
struct kvm_msrs info;
|
||||
struct kvm_msr_entry entries[100];
|
||||
|
@ -1077,17 +1089,18 @@ static int kvm_put_msrs(CPUX86State *env, int level)
|
|||
|
||||
msr_data.info.nmsrs = n;
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int kvm_get_fpu(CPUX86State *env)
|
||||
static int kvm_get_fpu(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_fpu fpu;
|
||||
int i, ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_FPU, &fpu);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_FPU, &fpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1108,17 +1121,18 @@ static int kvm_get_fpu(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_get_xsave(CPUX86State *env)
|
||||
static int kvm_get_xsave(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_xsave* xsave = env->kvm_xsave_buf;
|
||||
int ret, i;
|
||||
uint16_t cwd, swd, twd;
|
||||
|
||||
if (!kvm_has_xsave()) {
|
||||
return kvm_get_fpu(env);
|
||||
return kvm_get_fpu(cpu);
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XSAVE, xsave);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1146,8 +1160,9 @@ static int kvm_get_xsave(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_get_xcrs(CPUX86State *env)
|
||||
static int kvm_get_xcrs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
int i, ret;
|
||||
struct kvm_xcrs xcrs;
|
||||
|
||||
|
@ -1155,7 +1170,7 @@ static int kvm_get_xcrs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_XCRS, &xcrs);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XCRS, &xcrs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1170,13 +1185,14 @@ static int kvm_get_xcrs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_get_sregs(CPUX86State *env)
|
||||
static int kvm_get_sregs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_sregs sregs;
|
||||
uint32_t hflags;
|
||||
int bit, i, ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1254,8 +1270,9 @@ static int kvm_get_sregs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_get_msrs(CPUX86State *env)
|
||||
static int kvm_get_msrs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct {
|
||||
struct kvm_msrs info;
|
||||
struct kvm_msr_entry entries[100];
|
||||
|
@ -1312,7 +1329,7 @@ static int kvm_get_msrs(CPUX86State *env)
|
|||
}
|
||||
|
||||
msr_data.info.nmsrs = n;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1390,11 +1407,11 @@ static int kvm_get_msrs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_put_mp_state(CPUX86State *env)
|
||||
static int kvm_put_mp_state(X86CPU *cpu)
|
||||
{
|
||||
struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
|
||||
struct kvm_mp_state mp_state = { .mp_state = cpu->env.mp_state };
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_MP_STATE, &mp_state);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
|
||||
}
|
||||
|
||||
static int kvm_get_mp_state(X86CPU *cpu)
|
||||
|
@ -1403,7 +1420,7 @@ static int kvm_get_mp_state(X86CPU *cpu)
|
|||
struct kvm_mp_state mp_state;
|
||||
int ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_MP_STATE, &mp_state);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MP_STATE, &mp_state);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1414,14 +1431,15 @@ static int kvm_get_mp_state(X86CPU *cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_get_apic(CPUX86State *env)
|
||||
static int kvm_get_apic(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
DeviceState *apic = env->apic_state;
|
||||
struct kvm_lapic_state kapic;
|
||||
int ret;
|
||||
|
||||
if (apic && kvm_irqchip_in_kernel()) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_LAPIC, &kapic);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_LAPIC, &kapic);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1431,21 +1449,23 @@ static int kvm_get_apic(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_put_apic(CPUX86State *env)
|
||||
static int kvm_put_apic(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
DeviceState *apic = env->apic_state;
|
||||
struct kvm_lapic_state kapic;
|
||||
|
||||
if (apic && kvm_irqchip_in_kernel()) {
|
||||
kvm_put_apic_state(apic, &kapic);
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_LAPIC, &kapic);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_LAPIC, &kapic);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_put_vcpu_events(CPUX86State *env, int level)
|
||||
static int kvm_put_vcpu_events(X86CPU *cpu, int level)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_vcpu_events events;
|
||||
|
||||
if (!kvm_has_vcpu_events()) {
|
||||
|
@ -1475,11 +1495,12 @@ static int kvm_put_vcpu_events(CPUX86State *env, int level)
|
|||
KVM_VCPUEVENT_VALID_NMI_PENDING | KVM_VCPUEVENT_VALID_SIPI_VECTOR;
|
||||
}
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_VCPU_EVENTS, &events);
|
||||
}
|
||||
|
||||
static int kvm_get_vcpu_events(CPUX86State *env)
|
||||
static int kvm_get_vcpu_events(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_vcpu_events events;
|
||||
int ret;
|
||||
|
||||
|
@ -1487,7 +1508,7 @@ static int kvm_get_vcpu_events(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_EVENTS, &events);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_VCPU_EVENTS, &events);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1513,8 +1534,9 @@ static int kvm_get_vcpu_events(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_guest_debug_workarounds(CPUX86State *env)
|
||||
static int kvm_guest_debug_workarounds(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
int ret = 0;
|
||||
unsigned long reinject_trap = 0;
|
||||
|
||||
|
@ -1542,8 +1564,9 @@ static int kvm_guest_debug_workarounds(CPUX86State *env)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_put_debugregs(CPUX86State *env)
|
||||
static int kvm_put_debugregs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_debugregs dbgregs;
|
||||
int i;
|
||||
|
||||
|
@ -1558,11 +1581,12 @@ static int kvm_put_debugregs(CPUX86State *env)
|
|||
dbgregs.dr7 = env->dr[7];
|
||||
dbgregs.flags = 0;
|
||||
|
||||
return kvm_vcpu_ioctl(env, KVM_SET_DEBUGREGS, &dbgregs);
|
||||
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEBUGREGS, &dbgregs);
|
||||
}
|
||||
|
||||
static int kvm_get_debugregs(CPUX86State *env)
|
||||
static int kvm_get_debugregs(X86CPU *cpu)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
struct kvm_debugregs dbgregs;
|
||||
int i, ret;
|
||||
|
||||
|
@ -1570,7 +1594,7 @@ static int kvm_get_debugregs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_DEBUGREGS, &dbgregs);
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEBUGREGS, &dbgregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1583,88 +1607,88 @@ static int kvm_get_debugregs(CPUX86State *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_put_registers(CPUX86State *env, int level)
|
||||
int kvm_arch_put_registers(CPUState *cpu, int level)
|
||||
{
|
||||
CPUState *cpu = ENV_GET_CPU(env);
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
int ret;
|
||||
|
||||
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
|
||||
|
||||
ret = kvm_getput_regs(env, 1);
|
||||
ret = kvm_getput_regs(x86_cpu, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_xsave(env);
|
||||
ret = kvm_put_xsave(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_xcrs(env);
|
||||
ret = kvm_put_xcrs(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_sregs(env);
|
||||
ret = kvm_put_sregs(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
/* must be before kvm_put_msrs */
|
||||
ret = kvm_inject_mce_oldstyle(env);
|
||||
ret = kvm_inject_mce_oldstyle(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_msrs(env, level);
|
||||
ret = kvm_put_msrs(x86_cpu, level);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (level >= KVM_PUT_RESET_STATE) {
|
||||
ret = kvm_put_mp_state(env);
|
||||
ret = kvm_put_mp_state(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_apic(env);
|
||||
ret = kvm_put_apic(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = kvm_put_vcpu_events(env, level);
|
||||
ret = kvm_put_vcpu_events(x86_cpu, level);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_put_debugregs(env);
|
||||
ret = kvm_put_debugregs(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
/* must be last */
|
||||
ret = kvm_guest_debug_workarounds(env);
|
||||
ret = kvm_guest_debug_workarounds(x86_cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_get_registers(CPUX86State *env)
|
||||
int kvm_arch_get_registers(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
int ret;
|
||||
|
||||
assert(cpu_is_stopped(CPU(cpu)) || qemu_cpu_is_self(CPU(cpu)));
|
||||
assert(cpu_is_stopped(cs) || qemu_cpu_is_self(cs));
|
||||
|
||||
ret = kvm_getput_regs(env, 0);
|
||||
ret = kvm_getput_regs(cpu, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_xsave(env);
|
||||
ret = kvm_get_xsave(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_xcrs(env);
|
||||
ret = kvm_get_xcrs(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_sregs(env);
|
||||
ret = kvm_get_sregs(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_msrs(env);
|
||||
ret = kvm_get_msrs(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1672,30 +1696,32 @@ int kvm_arch_get_registers(CPUX86State *env)
|
|||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_apic(env);
|
||||
ret = kvm_get_apic(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_vcpu_events(env);
|
||||
ret = kvm_get_vcpu_events(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = kvm_get_debugregs(env);
|
||||
ret = kvm_get_debugregs(cpu);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run)
|
||||
void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
int ret;
|
||||
|
||||
/* Inject NMI */
|
||||
if (env->interrupt_request & CPU_INTERRUPT_NMI) {
|
||||
env->interrupt_request &= ~CPU_INTERRUPT_NMI;
|
||||
DPRINTF("injected NMI\n");
|
||||
ret = kvm_vcpu_ioctl(env, KVM_NMI);
|
||||
ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
|
||||
strerror(-ret));
|
||||
|
@ -1723,7 +1749,7 @@ void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run)
|
|||
|
||||
intr.irq = irq;
|
||||
DPRINTF("injected interrupt %d\n", irq);
|
||||
ret = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &intr);
|
||||
ret = kvm_vcpu_ioctl(cpu, KVM_INTERRUPT, &intr);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,
|
||||
"KVM: injection failed, interrupt lost (%s)\n",
|
||||
|
@ -1747,8 +1773,11 @@ void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run)
|
|||
}
|
||||
}
|
||||
|
||||
void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run)
|
||||
void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
|
||||
if (run->if_flag) {
|
||||
env->eflags |= IF_MASK;
|
||||
} else {
|
||||
|
@ -1758,9 +1787,10 @@ void kvm_arch_post_run(CPUX86State *env, struct kvm_run *run)
|
|||
cpu_set_apic_base(env->apic_state, run->apic_base);
|
||||
}
|
||||
|
||||
int kvm_arch_process_async_events(CPUX86State *env)
|
||||
int kvm_arch_process_async_events(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
if (env->interrupt_request & CPU_INTERRUPT_MCE) {
|
||||
/* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
|
||||
|
@ -1830,9 +1860,11 @@ static int kvm_handle_halt(X86CPU *cpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_handle_tpr_access(CPUX86State *env)
|
||||
static int kvm_handle_tpr_access(X86CPU *cpu)
|
||||
{
|
||||
struct kvm_run *run = env->kvm_run;
|
||||
CPUX86State *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_run *run = cs->kvm_run;
|
||||
|
||||
apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip,
|
||||
run->tpr_access.is_write ? TPR_ACCESS_WRITE
|
||||
|
@ -1840,8 +1872,9 @@ static int kvm_handle_tpr_access(CPUX86State *env)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp)
|
||||
int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
CPUX86State *env = &X86_CPU(cpu)->env;
|
||||
static const uint8_t int3 = 0xcc;
|
||||
|
||||
if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
|
||||
|
@ -1851,8 +1884,9 @@ int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_remove_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp)
|
||||
int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
CPUX86State *env = &X86_CPU(cpu)->env;
|
||||
uint8_t int3;
|
||||
|
||||
if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
|
||||
|
@ -1946,9 +1980,10 @@ void kvm_arch_remove_all_hw_breakpoints(void)
|
|||
|
||||
static CPUWatchpoint hw_watchpoint;
|
||||
|
||||
static int kvm_handle_debug(CPUX86State *env,
|
||||
static int kvm_handle_debug(X86CPU *cpu,
|
||||
struct kvm_debug_exit_arch *arch_info)
|
||||
{
|
||||
CPUX86State *env = &cpu->env;
|
||||
int ret = 0;
|
||||
int n;
|
||||
|
||||
|
@ -1980,7 +2015,7 @@ static int kvm_handle_debug(CPUX86State *env,
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (kvm_find_sw_breakpoint(env, arch_info->pc)) {
|
||||
} else if (kvm_find_sw_breakpoint(CPU(cpu), arch_info->pc)) {
|
||||
ret = EXCP_DEBUG;
|
||||
}
|
||||
if (ret == 0) {
|
||||
|
@ -1995,7 +2030,7 @@ static int kvm_handle_debug(CPUX86State *env,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg)
|
||||
void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
|
||||
{
|
||||
const uint8_t type_code[] = {
|
||||
[GDB_BREAKPOINT_HW] = 0x0,
|
||||
|
@ -2007,7 +2042,7 @@ void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg)
|
|||
};
|
||||
int n;
|
||||
|
||||
if (kvm_sw_breakpoints_active(env)) {
|
||||
if (kvm_sw_breakpoints_active(cpu)) {
|
||||
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
|
||||
}
|
||||
if (nb_hw_breakpoint > 0) {
|
||||
|
@ -2032,9 +2067,9 @@ static bool host_supports_vmx(void)
|
|||
|
||||
#define VMX_INVALID_GUEST_STATE 0x80000021
|
||||
|
||||
int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
|
||||
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
X86CPU *cpu = x86_env_get_cpu(env);
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
uint64_t code;
|
||||
int ret;
|
||||
|
||||
|
@ -2047,7 +2082,7 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
|
|||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_TPR_ACCESS:
|
||||
ret = kvm_handle_tpr_access(env);
|
||||
ret = kvm_handle_tpr_access(cpu);
|
||||
break;
|
||||
case KVM_EXIT_FAIL_ENTRY:
|
||||
code = run->fail_entry.hardware_entry_failure_reason;
|
||||
|
@ -2073,7 +2108,7 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
|
|||
break;
|
||||
case KVM_EXIT_DEBUG:
|
||||
DPRINTF("kvm_exit_debug\n");
|
||||
ret = kvm_handle_debug(env, &run->debug.arch);
|
||||
ret = kvm_handle_debug(cpu, &run->debug.arch);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||
|
@ -2084,8 +2119,11 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool kvm_arch_stop_on_emulation_error(CPUX86State *env)
|
||||
bool kvm_arch_stop_on_emulation_error(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
kvm_cpu_synchronize_state(env);
|
||||
return !(env->cr[0] & CR0_PE_MASK) ||
|
||||
((env->segs[R_CS].selector & 3) != 3);
|
||||
|
|
|
@ -25,11 +25,6 @@
|
|||
|
||||
#define SIGNBIT (1u << 31)
|
||||
|
||||
typedef struct M68kCPUListState {
|
||||
fprintf_function cpu_fprintf;
|
||||
FILE *file;
|
||||
} M68kCPUListState;
|
||||
|
||||
/* Sort alphabetically, except for "any". */
|
||||
static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
|
@ -51,7 +46,7 @@ static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
|
|||
static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *c = data;
|
||||
M68kCPUListState *s = user_data;
|
||||
CPUListState *s = user_data;
|
||||
|
||||
(*s->cpu_fprintf)(s->file, "%s\n",
|
||||
object_class_get_name(c));
|
||||
|
@ -59,7 +54,7 @@ static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
|
|||
|
||||
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
|
||||
{
|
||||
M68kCPUListState s = {
|
||||
CPUListState s = {
|
||||
.file = f,
|
||||
.cpu_fprintf = cpu_fprintf,
|
||||
};
|
||||
|
|
124
target-ppc/kvm.c
124
target-ppc/kvm.c
|
@ -99,8 +99,10 @@ int kvm_arch_init(KVMState *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_arch_sync_sregs(CPUPPCState *cenv)
|
||||
static int kvm_arch_sync_sregs(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *cenv = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_sregs sregs;
|
||||
int ret;
|
||||
|
||||
|
@ -117,18 +119,20 @@ static int kvm_arch_sync_sregs(CPUPPCState *cenv)
|
|||
}
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(cenv, KVM_GET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
sregs.pvr = cenv->spr[SPR_PVR];
|
||||
return kvm_vcpu_ioctl(cenv, KVM_SET_SREGS, &sregs);
|
||||
return kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||
}
|
||||
|
||||
/* Set up a shared TLB array with KVM */
|
||||
static int kvm_booke206_tlb_init(CPUPPCState *env)
|
||||
static int kvm_booke206_tlb_init(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_book3e_206_tlb_params params = {};
|
||||
struct kvm_config_tlb cfg = {};
|
||||
struct kvm_enable_cap encap = {};
|
||||
|
@ -136,7 +140,7 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
|
|||
int ret, i;
|
||||
|
||||
if (!kvm_enabled() ||
|
||||
!kvm_check_extension(env->kvm_state, KVM_CAP_SW_TLB)) {
|
||||
!kvm_check_extension(cs->kvm_state, KVM_CAP_SW_TLB)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -161,7 +165,7 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
|
|||
encap.cap = KVM_CAP_SW_TLB;
|
||||
encap.args[0] = (uintptr_t)&cfg;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &encap);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &encap);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
|
||||
__func__, strerror(-ret));
|
||||
|
@ -174,9 +178,12 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
|
|||
|
||||
|
||||
#if defined(TARGET_PPC64)
|
||||
static void kvm_get_fallback_smmu_info(CPUPPCState *env,
|
||||
static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
|
||||
struct kvm_ppc_smmu_info *info)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
/* We don't have the new KVM_PPC_GET_SMMU_INFO ioctl, so
|
||||
|
@ -202,7 +209,7 @@ static void kvm_get_fallback_smmu_info(CPUPPCState *env,
|
|||
* implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit
|
||||
* this fallback.
|
||||
*/
|
||||
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
|
||||
if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO)) {
|
||||
/* No flags */
|
||||
info->flags = 0;
|
||||
info->slb_size = 64;
|
||||
|
@ -258,18 +265,19 @@ static void kvm_get_fallback_smmu_info(CPUPPCState *env,
|
|||
}
|
||||
}
|
||||
|
||||
static void kvm_get_smmu_info(CPUPPCState *env, struct kvm_ppc_smmu_info *info)
|
||||
static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
int ret;
|
||||
|
||||
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) {
|
||||
ret = kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_SMMU_INFO, info);
|
||||
if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) {
|
||||
ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_SMMU_INFO, info);
|
||||
if (ret == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
kvm_get_fallback_smmu_info(env, info);
|
||||
kvm_get_fallback_smmu_info(cpu, info);
|
||||
}
|
||||
|
||||
static long getrampagesize(void)
|
||||
|
@ -312,10 +320,11 @@ static bool kvm_valid_page_size(uint32_t flags, long rampgsize, uint32_t shift)
|
|||
return (1ul << shift) <= rampgsize;
|
||||
}
|
||||
|
||||
static void kvm_fixup_page_sizes(CPUPPCState *env)
|
||||
static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
|
||||
{
|
||||
static struct kvm_ppc_smmu_info smmu_info;
|
||||
static bool has_smmu_info;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
long rampagesize;
|
||||
int iq, ik, jq, jk;
|
||||
|
||||
|
@ -326,7 +335,7 @@ static void kvm_fixup_page_sizes(CPUPPCState *env)
|
|||
|
||||
/* Collect MMU info from kernel if not already */
|
||||
if (!has_smmu_info) {
|
||||
kvm_get_smmu_info(env, &smmu_info);
|
||||
kvm_get_smmu_info(cpu, &smmu_info);
|
||||
has_smmu_info = true;
|
||||
}
|
||||
|
||||
|
@ -369,22 +378,23 @@ static void kvm_fixup_page_sizes(CPUPPCState *env)
|
|||
}
|
||||
#else /* defined (TARGET_PPC64) */
|
||||
|
||||
static inline void kvm_fixup_page_sizes(CPUPPCState *env)
|
||||
static inline void kvm_fixup_page_sizes(PowerPCCPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* !defined (TARGET_PPC64) */
|
||||
|
||||
int kvm_arch_init_vcpu(CPUPPCState *cenv)
|
||||
int kvm_arch_init_vcpu(CPUState *cs)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(cenv);
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *cenv = &cpu->env;
|
||||
int ret;
|
||||
|
||||
/* Gather server mmu info from KVM and update the CPU state */
|
||||
kvm_fixup_page_sizes(cenv);
|
||||
kvm_fixup_page_sizes(cpu);
|
||||
|
||||
/* Synchronize sregs with kvm */
|
||||
ret = kvm_arch_sync_sregs(cenv);
|
||||
ret = kvm_arch_sync_sregs(cpu);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -394,7 +404,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv)
|
|||
/* Some targets support access to KVM's guest TLB. */
|
||||
switch (cenv->mmu_model) {
|
||||
case POWERPC_MMU_BOOKE206:
|
||||
ret = kvm_booke206_tlb_init(cenv);
|
||||
ret = kvm_booke206_tlb_init(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -403,12 +413,14 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void kvm_arch_reset_vcpu(CPUPPCState *env)
|
||||
void kvm_arch_reset_vcpu(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static void kvm_sw_tlb_put(CPUPPCState *env)
|
||||
static void kvm_sw_tlb_put(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_dirty_tlb dirty_tlb;
|
||||
unsigned char *bitmap;
|
||||
int ret;
|
||||
|
@ -423,7 +435,7 @@ static void kvm_sw_tlb_put(CPUPPCState *env)
|
|||
dirty_tlb.bitmap = (uintptr_t)bitmap;
|
||||
dirty_tlb.num_dirty = env->nb_tlb;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_DIRTY_TLB, &dirty_tlb);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_DIRTY_TLB, &dirty_tlb);
|
||||
if (ret) {
|
||||
fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n",
|
||||
__func__, strerror(-ret));
|
||||
|
@ -432,15 +444,18 @@ static void kvm_sw_tlb_put(CPUPPCState *env)
|
|||
g_free(bitmap);
|
||||
}
|
||||
|
||||
int kvm_arch_put_registers(CPUPPCState *env, int level)
|
||||
int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
struct kvm_regs regs;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
|
||||
if (ret < 0)
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
regs.ctr = env->ctr;
|
||||
regs.lr = env->lr;
|
||||
|
@ -465,12 +480,12 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
|
|||
for (i = 0;i < 32; i++)
|
||||
regs.gpr[i] = env->gpr[i];
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (env->tlb_dirty) {
|
||||
kvm_sw_tlb_put(env);
|
||||
kvm_sw_tlb_put(cpu);
|
||||
env->tlb_dirty = false;
|
||||
}
|
||||
|
||||
|
@ -503,7 +518,7 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
|
|||
| env->IBAT[1][i];
|
||||
}
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -516,7 +531,7 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
|
|||
.addr = (uintptr_t) &hior,
|
||||
};
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, ®);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -525,14 +540,16 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int kvm_arch_get_registers(CPUPPCState *env)
|
||||
int kvm_arch_get_registers(CPUState *cs)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
struct kvm_regs regs;
|
||||
struct kvm_sregs sregs;
|
||||
uint32_t cr;
|
||||
int i, ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -566,7 +583,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
|
|||
env->gpr[i] = regs.gpr[i];
|
||||
|
||||
if (cap_booke_sregs) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -670,7 +687,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
|
|||
}
|
||||
|
||||
if (cap_segstate) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -702,7 +719,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
|
||||
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level)
|
||||
{
|
||||
unsigned virq = level ? KVM_INTERRUPT_SET_LEVEL : KVM_INTERRUPT_UNSET;
|
||||
|
||||
|
@ -714,7 +731,7 @@ int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
|
|||
return 0;
|
||||
}
|
||||
|
||||
kvm_vcpu_ioctl(env, KVM_INTERRUPT, &virq);
|
||||
kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -727,8 +744,10 @@ int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
|
|||
#define PPC_INPUT_INT PPC6xx_INPUT_INT
|
||||
#endif
|
||||
|
||||
void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
|
||||
void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int r;
|
||||
unsigned irq;
|
||||
|
||||
|
@ -746,7 +765,7 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
|
|||
irq = KVM_INTERRUPT_SET;
|
||||
|
||||
dprintf("injected interrupt %d\n", irq);
|
||||
r = kvm_vcpu_ioctl(env, KVM_INTERRUPT, &irq);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq);
|
||||
if (r < 0)
|
||||
printf("cpu %d fail inject %x\n", env->cpu_index, irq);
|
||||
|
||||
|
@ -760,13 +779,14 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
|
|||
* anyways, so we will get a chance to deliver the rest. */
|
||||
}
|
||||
|
||||
void kvm_arch_post_run(CPUPPCState *env, struct kvm_run *run)
|
||||
void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_process_async_events(CPUPPCState *env)
|
||||
int kvm_arch_process_async_events(CPUState *cs)
|
||||
{
|
||||
return env->halted;
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
return cpu->env.halted;
|
||||
}
|
||||
|
||||
static int kvmppc_handle_halt(CPUPPCState *env)
|
||||
|
@ -796,8 +816,10 @@ static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t dat
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
|
||||
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
PowerPCCPU *cpu = POWERPC_CPU(cs);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int ret;
|
||||
|
||||
switch (run->exit_reason) {
|
||||
|
@ -817,7 +839,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
|
|||
#ifdef CONFIG_PSERIES
|
||||
case KVM_EXIT_PAPR_HCALL:
|
||||
dprintf("handle PAPR hypercall\n");
|
||||
run->papr_hcall.ret = spapr_hypercall(ppc_env_get_cpu(env),
|
||||
run->papr_hcall.ret = spapr_hypercall(cpu,
|
||||
run->papr_hcall.nr,
|
||||
run->papr_hcall.args);
|
||||
ret = 0;
|
||||
|
@ -969,12 +991,14 @@ uint32_t kvmppc_get_dfp(void)
|
|||
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
uint32_t *hc = (uint32_t*)buf;
|
||||
|
||||
struct kvm_ppc_pvinfo pvinfo;
|
||||
|
||||
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
|
||||
!kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
|
||||
if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
|
||||
!kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
|
||||
memcpy(buf, pvinfo.hcall, buf_len);
|
||||
|
||||
return 0;
|
||||
|
@ -997,13 +1021,15 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kvmppc_set_papr(CPUPPCState *env)
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_enable_cap cap = {};
|
||||
int ret;
|
||||
|
||||
cap.cap = KVM_CAP_PPC_PAPR;
|
||||
ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_ENABLE_CAP, &cap);
|
||||
|
||||
if (ret) {
|
||||
cpu_abort(env, "This KVM version does not support PAPR\n");
|
||||
|
@ -1225,12 +1251,12 @@ int kvmppc_fixup_cpu(CPUPPCState *env)
|
|||
}
|
||||
|
||||
|
||||
bool kvm_arch_stop_on_emulation_error(CPUPPCState *env)
|
||||
bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int kvm_arch_on_sigbus_vcpu(CPUPPCState *env, int code, void *addr)
|
||||
int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ uint64_t kvmppc_get_clockfreq(void);
|
|||
uint32_t kvmppc_get_vmx(void);
|
||||
uint32_t kvmppc_get_dfp(void);
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
|
||||
int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level);
|
||||
void kvmppc_set_papr(CPUPPCState *env);
|
||||
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu);
|
||||
int kvmppc_smt_threads(void);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
|
||||
|
@ -65,12 +65,12 @@ static inline int kvmppc_read_segment_page_sizes(uint32_t *prop, int maxcells)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
|
||||
static inline int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void kvmppc_set_papr(CPUPPCState *env)
|
||||
static inline void kvmppc_set_papr(PowerPCCPU *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -296,21 +296,21 @@ void s390x_cpu_timer(void *opaque);
|
|||
int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall);
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code);
|
||||
void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token);
|
||||
void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
|
||||
void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code);
|
||||
void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token);
|
||||
void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm,
|
||||
uint64_t parm64, int vm);
|
||||
#else
|
||||
static inline void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code)
|
||||
static inline void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kvm_s390_virtio_irq(CPUS390XState *env, int config_change,
|
||||
static inline void kvm_s390_virtio_irq(S390CPU *cpu, int config_change,
|
||||
uint64_t token)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type,
|
||||
static inline void kvm_s390_interrupt_internal(S390CPU *cpu, int type,
|
||||
uint32_t parm, uint64_t parm64,
|
||||
int vm)
|
||||
{
|
||||
|
|
|
@ -19,7 +19,8 @@ void s390_sclp_extint(uint32_t parm)
|
|||
|
||||
if (kvm_enabled()) {
|
||||
#ifdef CONFIG_KVM
|
||||
kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE, parm, 0, 1);
|
||||
kvm_s390_interrupt_internal(dummy_cpu, KVM_S390_INT_SERVICE, parm,
|
||||
0, 1);
|
||||
#endif
|
||||
} else {
|
||||
env->psw.addr += 4;
|
||||
|
|
|
@ -72,43 +72,45 @@ int kvm_arch_init(KVMState *s)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_init_vcpu(CPUS390XState *env)
|
||||
int kvm_arch_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
|
||||
if (kvm_vcpu_ioctl(cpu, KVM_S390_INITIAL_RESET, NULL) < 0) {
|
||||
perror("cannot init reset vcpu");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void kvm_arch_reset_vcpu(CPUS390XState *env)
|
||||
void kvm_arch_reset_vcpu(CPUState *cpu)
|
||||
{
|
||||
/* FIXME: add code to reset vcpu. */
|
||||
}
|
||||
|
||||
int kvm_arch_put_registers(CPUS390XState *env, int level)
|
||||
int kvm_arch_put_registers(CPUState *cs, int level)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
struct kvm_sregs sregs;
|
||||
struct kvm_regs regs;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* always save the PSW and the GPRS*/
|
||||
env->kvm_run->psw_addr = env->psw.addr;
|
||||
env->kvm_run->psw_mask = env->psw.mask;
|
||||
cs->kvm_run->psw_addr = env->psw.addr;
|
||||
cs->kvm_run->psw_mask = env->psw.mask;
|
||||
|
||||
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) {
|
||||
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
env->kvm_run->s.regs.gprs[i] = env->regs[i];
|
||||
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS;
|
||||
cs->kvm_run->s.regs.gprs[i] = env->regs[i];
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 16; i++) {
|
||||
regs.gprs[i] = env->regs[i];
|
||||
}
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -120,53 +122,55 @@ int kvm_arch_put_registers(CPUS390XState *env, int level)
|
|||
}
|
||||
|
||||
if (cap_sync_regs &&
|
||||
env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS &&
|
||||
env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) {
|
||||
cs->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS &&
|
||||
cs->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
env->kvm_run->s.regs.acrs[i] = env->aregs[i];
|
||||
env->kvm_run->s.regs.crs[i] = env->cregs[i];
|
||||
cs->kvm_run->s.regs.acrs[i] = env->aregs[i];
|
||||
cs->kvm_run->s.regs.crs[i] = env->cregs[i];
|
||||
}
|
||||
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS;
|
||||
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS;
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS;
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS;
|
||||
} else {
|
||||
for (i = 0; i < 16; i++) {
|
||||
sregs.acrs[i] = env->aregs[i];
|
||||
sregs.crs[i] = env->cregs[i];
|
||||
}
|
||||
ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally the prefix */
|
||||
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
|
||||
env->kvm_run->s.regs.prefix = env->psa;
|
||||
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX;
|
||||
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
|
||||
cs->kvm_run->s.regs.prefix = env->psa;
|
||||
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX;
|
||||
} else {
|
||||
/* prefix is only supported via sync regs */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_get_registers(CPUS390XState *env)
|
||||
int kvm_arch_get_registers(CPUState *cs)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
struct kvm_sregs sregs;
|
||||
struct kvm_regs regs;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* get the PSW */
|
||||
env->psw.addr = env->kvm_run->psw_addr;
|
||||
env->psw.mask = env->kvm_run->psw_mask;
|
||||
env->psw.addr = cs->kvm_run->psw_addr;
|
||||
env->psw.mask = cs->kvm_run->psw_mask;
|
||||
|
||||
/* the GPRS */
|
||||
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) {
|
||||
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
env->regs[i] = env->kvm_run->s.regs.gprs[i];
|
||||
env->regs[i] = cs->kvm_run->s.regs.gprs[i];
|
||||
}
|
||||
} else {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -177,14 +181,14 @@ int kvm_arch_get_registers(CPUS390XState *env)
|
|||
|
||||
/* The ACRS and CRS */
|
||||
if (cap_sync_regs &&
|
||||
env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS &&
|
||||
env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) {
|
||||
cs->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS &&
|
||||
cs->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
env->aregs[i] = env->kvm_run->s.regs.acrs[i];
|
||||
env->cregs[i] = env->kvm_run->s.regs.crs[i];
|
||||
env->aregs[i] = cs->kvm_run->s.regs.acrs[i];
|
||||
env->cregs[i] = cs->kvm_run->s.regs.crs[i];
|
||||
}
|
||||
} else {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
|
||||
ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -195,8 +199,8 @@ int kvm_arch_get_registers(CPUS390XState *env)
|
|||
}
|
||||
|
||||
/* Finally the prefix */
|
||||
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
|
||||
env->psa = env->kvm_run->s.regs.prefix;
|
||||
if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
|
||||
env->psa = cs->kvm_run->s.regs.prefix;
|
||||
} else {
|
||||
/* no prefix without sync regs */
|
||||
}
|
||||
|
@ -239,8 +243,10 @@ void *kvm_arch_vmalloc(ram_addr_t size)
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
|
||||
int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
|
||||
|
||||
if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
|
||||
|
@ -250,8 +256,10 @@ int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_remove_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
|
||||
int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t t[4];
|
||||
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
|
||||
|
||||
|
@ -266,26 +274,28 @@ int kvm_arch_remove_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *
|
|||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_pre_run(CPUS390XState *env, struct kvm_run *run)
|
||||
void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_post_run(CPUS390XState *env, struct kvm_run *run)
|
||||
void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_process_async_events(CPUS390XState *env)
|
||||
int kvm_arch_process_async_events(CPUState *cs)
|
||||
{
|
||||
return env->halted;
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
return cpu->env.halted;
|
||||
}
|
||||
|
||||
void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
|
||||
void kvm_s390_interrupt_internal(S390CPU *cpu, int type, uint32_t parm,
|
||||
uint64_t parm64, int vm)
|
||||
{
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_s390_interrupt kvmint;
|
||||
int r;
|
||||
|
||||
if (!env->kvm_state) {
|
||||
if (!cs->kvm_state) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -294,9 +304,9 @@ void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
|
|||
kvmint.parm64 = parm64;
|
||||
|
||||
if (vm) {
|
||||
r = kvm_vm_ioctl(env->kvm_state, KVM_S390_INTERRUPT, &kvmint);
|
||||
r = kvm_vm_ioctl(cs->kvm_state, KVM_S390_INTERRUPT, &kvmint);
|
||||
} else {
|
||||
r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint);
|
||||
r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
|
@ -305,34 +315,38 @@ void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
|
|||
}
|
||||
}
|
||||
|
||||
void kvm_s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
|
||||
void kvm_s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
|
||||
{
|
||||
kvm_s390_interrupt_internal(env, KVM_S390_INT_VIRTIO, config_change,
|
||||
kvm_s390_interrupt_internal(cpu, KVM_S390_INT_VIRTIO, config_change,
|
||||
token, 1);
|
||||
}
|
||||
|
||||
void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code)
|
||||
void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code)
|
||||
{
|
||||
kvm_s390_interrupt_internal(env, type, code, 0, 0);
|
||||
kvm_s390_interrupt_internal(cpu, type, code, 0, 0);
|
||||
}
|
||||
|
||||
static void enter_pgmcheck(CPUS390XState *env, uint16_t code)
|
||||
static void enter_pgmcheck(S390CPU *cpu, uint16_t code)
|
||||
{
|
||||
kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
|
||||
kvm_s390_interrupt(cpu, KVM_S390_PROGRAM_INT, code);
|
||||
}
|
||||
|
||||
static inline void setcc(CPUS390XState *env, uint64_t cc)
|
||||
static inline void setcc(S390CPU *cpu, uint64_t cc)
|
||||
{
|
||||
env->kvm_run->psw_mask &= ~(3ull << 44);
|
||||
env->kvm_run->psw_mask |= (cc & 3) << 44;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
cs->kvm_run->psw_mask &= ~(3ull << 44);
|
||||
cs->kvm_run->psw_mask |= (cc & 3) << 44;
|
||||
|
||||
env->psw.mask &= ~(3ul << 44);
|
||||
env->psw.mask |= (cc & 3) << 44;
|
||||
}
|
||||
|
||||
static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
|
||||
static int kvm_sclp_service_call(S390CPU *cpu, struct kvm_run *run,
|
||||
uint16_t ipbh0)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint32_t sccb;
|
||||
uint64_t code;
|
||||
int r = 0;
|
||||
|
@ -343,14 +357,14 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run,
|
|||
|
||||
r = sclp_service_call(sccb, code);
|
||||
if (r < 0) {
|
||||
enter_pgmcheck(env, -r);
|
||||
enter_pgmcheck(cpu, -r);
|
||||
}
|
||||
setcc(env, r);
|
||||
setcc(cpu, r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
|
||||
static int handle_priv(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
{
|
||||
int r = 0;
|
||||
uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
|
||||
|
@ -358,7 +372,7 @@ static int handle_priv(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
|
|||
dprintf("KVM: PRIV: %d\n", ipa1);
|
||||
switch (ipa1) {
|
||||
case PRIV_SCLP_CALL:
|
||||
r = kvm_sclp_service_call(env, run, ipbh0);
|
||||
r = kvm_sclp_service_call(cpu, run, ipbh0);
|
||||
break;
|
||||
default:
|
||||
dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
|
||||
|
@ -401,7 +415,7 @@ static int s390_cpu_restart(S390CPU *cpu)
|
|||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
|
||||
kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0);
|
||||
s390_add_running_cpu(env);
|
||||
qemu_cpu_kick(CPU(cpu));
|
||||
dprintf("DONE: SIGP cpu restart: %p\n", env);
|
||||
|
@ -415,12 +429,13 @@ static int s390_store_status(CPUS390XState *env, uint32_t parameter)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int s390_cpu_initial_reset(CPUS390XState *env)
|
||||
static int s390_cpu_initial_reset(S390CPU *cpu)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
s390_del_running_cpu(env);
|
||||
if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
|
||||
if (kvm_vcpu_ioctl(CPU(cpu), KVM_S390_INITIAL_RESET, NULL) < 0) {
|
||||
perror("cannot init reset vcpu");
|
||||
}
|
||||
|
||||
|
@ -434,8 +449,9 @@ static int s390_cpu_initial_reset(CPUS390XState *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
|
||||
static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
uint8_t order_code;
|
||||
uint32_t parameter;
|
||||
uint16_t cpu_addr;
|
||||
|
@ -479,7 +495,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
|
|||
/* make the caller panic */
|
||||
return -1;
|
||||
case SIGP_INITIAL_CPU_RESET:
|
||||
r = s390_cpu_initial_reset(target_env);
|
||||
r = s390_cpu_initial_reset(target_cpu);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code);
|
||||
|
@ -487,12 +503,13 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
|
|||
}
|
||||
|
||||
out:
|
||||
setcc(env, r ? 3 : 0);
|
||||
setcc(cpu, r ? 3 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
|
||||
static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
|
||||
uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
|
||||
int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
|
||||
|
@ -501,43 +518,45 @@ static int handle_instruction(CPUS390XState *env, struct kvm_run *run)
|
|||
dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
|
||||
switch (ipa0) {
|
||||
case IPA0_PRIV:
|
||||
r = handle_priv(env, run, ipa1);
|
||||
r = handle_priv(cpu, run, ipa1);
|
||||
break;
|
||||
case IPA0_DIAG:
|
||||
r = handle_diag(env, run, ipb_code);
|
||||
break;
|
||||
case IPA0_SIGP:
|
||||
r = handle_sigp(env, run, ipa1);
|
||||
r = handle_sigp(cpu, run, ipa1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
enter_pgmcheck(env, 0x0001);
|
||||
enter_pgmcheck(cpu, 0x0001);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_special_wait_psw(CPUS390XState *env)
|
||||
static bool is_special_wait_psw(CPUState *cs)
|
||||
{
|
||||
/* signal quiesce */
|
||||
return env->kvm_run->psw_addr == 0xfffUL;
|
||||
return cs->kvm_run->psw_addr == 0xfffUL;
|
||||
}
|
||||
|
||||
static int handle_intercept(CPUS390XState *env)
|
||||
static int handle_intercept(S390CPU *cpu)
|
||||
{
|
||||
struct kvm_run *run = env->kvm_run;
|
||||
CPUS390XState *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
struct kvm_run *run = cs->kvm_run;
|
||||
int icpt_code = run->s390_sieic.icptcode;
|
||||
int r = 0;
|
||||
|
||||
dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code,
|
||||
(long)env->kvm_run->psw_addr);
|
||||
(long)cs->kvm_run->psw_addr);
|
||||
switch (icpt_code) {
|
||||
case ICPT_INSTRUCTION:
|
||||
r = handle_instruction(env, run);
|
||||
r = handle_instruction(cpu, run);
|
||||
break;
|
||||
case ICPT_WAITPSW:
|
||||
if (s390_del_running_cpu(env) == 0 &&
|
||||
is_special_wait_psw(env)) {
|
||||
is_special_wait_psw(cs)) {
|
||||
qemu_system_shutdown_request();
|
||||
}
|
||||
r = EXCP_HALTED;
|
||||
|
@ -565,13 +584,14 @@ static int handle_intercept(CPUS390XState *env)
|
|||
return r;
|
||||
}
|
||||
|
||||
int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
|
||||
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(cs);
|
||||
int ret = 0;
|
||||
|
||||
switch (run->exit_reason) {
|
||||
case KVM_EXIT_S390_SIEIC:
|
||||
ret = handle_intercept(env);
|
||||
ret = handle_intercept(cpu);
|
||||
break;
|
||||
case KVM_EXIT_S390_RESET:
|
||||
qemu_system_reset_request();
|
||||
|
@ -587,12 +607,12 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool kvm_arch_stop_on_emulation_error(CPUS390XState *env)
|
||||
bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int kvm_arch_on_sigbus_vcpu(CPUS390XState *env, int code, void *addr)
|
||||
int kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
|
|||
|
||||
if (kvm_enabled()) {
|
||||
#ifdef CONFIG_KVM
|
||||
kvm_s390_interrupt(env, KVM_S390_PROGRAM_INT, code);
|
||||
kvm_s390_interrupt(s390_env_get_cpu(env), KVM_S390_PROGRAM_INT, code);
|
||||
#endif
|
||||
} else {
|
||||
env->int_pgm_code = code;
|
||||
|
|
Loading…
Reference in New Issue