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:
Blue Swirl 2012-12-28 16:08:23 +00:00
commit 4de63460ca
42 changed files with 1224 additions and 867 deletions

View file

@ -600,6 +600,7 @@ M: Andreas Färber <afaerber@suse.de>
S: Supported S: Supported
F: qom/cpu.c F: qom/cpu.c
F: include/qemu/cpu.h F: include/qemu/cpu.h
F: target-i386/cpu.c
Device Tree Device Tree
M: Peter Crosthwaite <peter.crosthwaite@petalogix.com> M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>

View file

@ -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 += bt-hci-csr.o
common-obj-y += msmouse.o ps2.o common-obj-y += msmouse.o ps2.o
common-obj-y += qdev.o qdev-properties.o qdev-monitor.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 common-obj-$(CONFIG_BRLAPI) += baum.o
# xen backend driver support # xen backend driver support

View file

@ -50,7 +50,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
const char *kernel_filename = args->kernel_filename; const char *kernel_filename = args->kernel_filename;
const char *kernel_cmdline = args->kernel_cmdline; const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename; const char *initrd_filename = args->initrd_filename;
CPUAlphaState *cpus[4]; AlphaCPU *cpus[4];
PCIBus *pci_bus; PCIBus *pci_bus;
ISABus *isa_bus; ISABus *isa_bus;
qemu_irq rtc_irq; qemu_irq rtc_irq;
@ -62,12 +62,12 @@ static void clipper_init(QEMUMachineInitArgs *args)
/* Create up to 4 cpus. */ /* Create up to 4 cpus. */
memset(cpus, 0, sizeof(cpus)); memset(cpus, 0, sizeof(cpus));
for (i = 0; i < smp_cpus; ++i) { 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]->env.trap_arg0 = ram_size;
cpus[0]->trap_arg1 = 0; cpus[0]->env.trap_arg1 = 0;
cpus[0]->trap_arg2 = smp_cpus; cpus[0]->env.trap_arg2 = smp_cpus;
/* Init the chipset. */ /* Init the chipset. */
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, 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. */ /* Start all cpus at the PALcode RESET entry point. */
for (i = 0; i < smp_cpus; ++i) { for (i = 0; i < smp_cpus; ++i) {
cpus[i]->pal_mode = 1; cpus[i]->env.pal_mode = 1;
cpus[i]->pc = palcode_entry; cpus[i]->env.pc = palcode_entry;
cpus[i]->palbr = palcode_entry; cpus[i]->env.palbr = palcode_entry;
} }
/* Load a kernel. */ /* Load a kernel. */
@ -136,7 +136,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
exit(1); exit(1);
} }
cpus[0]->trap_arg1 = kernel_entry; cpus[0]->env.trap_arg1 = kernel_entry;
param_offset = kernel_low - 0x6000; param_offset = kernel_low - 0x6000;

View file

@ -10,7 +10,7 @@
#include "irq.h" #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); pci_map_irq_fn);
/* alpha_pci.c. */ /* alpha_pci.c. */

View file

@ -23,7 +23,7 @@ typedef struct TyphoonCchip {
uint64_t drir; uint64_t drir;
uint64_t dim[4]; uint64_t dim[4];
uint32_t iic[4]; uint32_t iic[4];
CPUAlphaState *cpu[4]; AlphaCPU *cpu[4];
} TyphoonCchip; } TyphoonCchip;
typedef struct TyphoonWindow { typedef struct TyphoonWindow {
@ -58,10 +58,11 @@ typedef struct TyphoonState {
} TyphoonState; } TyphoonState;
/* Called when one of DRIR or DIM changes. */ /* 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 there are any non-masked interrupts, tell the cpu. */
if (env) { if (cpu != NULL) {
CPUAlphaState *env = &cpu->env;
if (req) { if (req) {
cpu_interrupt(env, CPU_INTERRUPT_HARD); cpu_interrupt(env, CPU_INTERRUPT_HARD);
} else { } else {
@ -353,8 +354,9 @@ static void cchip_write(void *opaque, hwaddr addr,
if ((newval ^ oldval) & 0xff0) { if ((newval ^ oldval) & 0xff0) {
int i; int i;
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
CPUAlphaState *env = s->cchip.cpu[i]; AlphaCPU *cpu = s->cchip.cpu[i];
if (env) { if (cpu != NULL) {
CPUAlphaState *env = &cpu->env;
/* IPI can be either cleared or set by the write. */ /* IPI can be either cleared or set by the write. */
if (newval & (1 << (i + 8))) { if (newval & (1 << (i + 8))) {
cpu_interrupt(env, CPU_INTERRUPT_SMP); 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. */ /* Deliver the interrupt to each CPU, considering each CPU's IIC. */
for (i = 0; i < 4; ++i) { for (i = 0; i < 4; ++i) {
CPUAlphaState *env = s->cchip.cpu[i]; AlphaCPU *cpu = s->cchip.cpu[i];
if (env) { if (cpu != NULL) {
uint32_t iic = s->cchip.iic[i]; uint32_t iic = s->cchip.iic[i];
/* ??? The verbage in Section 10.2.2.10 isn't 100% clear. /* ??? 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. */ /* Set the ITI bit for this cpu. */
s->cchip.misc |= 1 << (i + 4); s->cchip.misc |= 1 << (i + 4);
/* And signal the interrupt. */ /* 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. */ /* Set the ITI bit for this cpu. */
s->cchip.misc |= 1 << (cpu + 4); 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, PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
qemu_irq *p_rtc_irq, 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 MB = 1024 * 1024;
const uint64_t GB = 1024 * MB; 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. */ /* Remember the CPUs so that we can deliver interrupts to them. */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
CPUAlphaState *env = cpus[i]; AlphaCPU *cpu = cpus[i];
s->cchip.cpu[i] = env; s->cchip.cpu[i] = cpu;
if (env) { if (cpu != NULL) {
env->alarm_timer = qemu_new_timer_ns(rtc_clock, cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
typhoon_alarm_timer, typhoon_alarm_timer,
(void *)((uintptr_t)s + i)); (void *)((uintptr_t)s + i));
} }

View file

@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
.enabled = 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) static void kvm_apic_vapic_base_update(APICCommonState *s)
@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
}; };
int ret; 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) { if (ret < 0) {
fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n", fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
strerror(-ret)); strerror(-ret));
@ -125,15 +125,15 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
static void do_inject_external_nmi(void *data) static void do_inject_external_nmi(void *data)
{ {
APICCommonState *s = data; APICCommonState *s = data;
CPUX86State *env = &s->cpu->env; CPUState *cpu = CPU(s->cpu);
uint32_t lvt; uint32_t lvt;
int ret; int ret;
cpu_synchronize_state(env); cpu_synchronize_state(&s->cpu->env);
lvt = s->lvt[APIC_LVT_LINT1]; lvt = s->lvt[APIC_LVT_LINT1];
if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) { 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) { if (ret < 0) {
fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n", fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
strerror(-ret)); strerror(-ret));

View file

@ -76,7 +76,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
return; return;
} }
for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) { 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) {
if (ret != -EINVAL) { if (ret != -EINVAL) {
fprintf(stderr, "%s: %s\n", __func__, strerror(-ret)); fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));

128
hw/ppc.c
View file

@ -50,8 +50,9 @@
static void cpu_ppc_tb_stop (CPUPPCState *env); static void cpu_ppc_tb_stop (CPUPPCState *env);
static void cpu_ppc_tb_start (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; unsigned int old_pending = env->pending_interrupts;
if (level) { if (level) {
@ -65,7 +66,7 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
if (old_pending != env->pending_interrupts) { if (old_pending != env->pending_interrupts) {
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
kvmppc_set_interrupt(env, n_IRQ, level); kvmppc_set_interrupt(cpu, n_IRQ, level);
#endif #endif
} }
@ -100,13 +101,13 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the external IRQ state to %d\n", LOG_IRQ("%s: set the external IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_EXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
break; break;
case PPC6xx_INPUT_SMI: case PPC6xx_INPUT_SMI:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the SMI IRQ state to %d\n", LOG_IRQ("%s: set the SMI IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_SMI, level); ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
break; break;
case PPC6xx_INPUT_MCP: case PPC6xx_INPUT_MCP:
/* Negative edge sensitive */ /* Negative edge sensitive */
@ -116,7 +117,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
if (cur_level == 1 && level == 0) { if (cur_level == 1 && level == 0) {
LOG_IRQ("%s: raise machine check state\n", LOG_IRQ("%s: raise machine check state\n",
__func__); __func__);
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
} }
break; break;
case PPC6xx_INPUT_CKSTP_IN: case PPC6xx_INPUT_CKSTP_IN:
@ -138,7 +139,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
case PPC6xx_INPUT_SRESET: case PPC6xx_INPUT_SRESET:
LOG_IRQ("%s: set the RESET IRQ state to %d\n", LOG_IRQ("%s: set the RESET IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_RESET, level); ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
break; break;
default: default:
/* Unknown pin - do nothing */ /* Unknown pin - do nothing */
@ -178,13 +179,13 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the external IRQ state to %d\n", LOG_IRQ("%s: set the external IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_EXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
break; break;
case PPC970_INPUT_THINT: case PPC970_INPUT_THINT:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__, LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
level); level);
ppc_set_irq(env, PPC_INTERRUPT_THERM, level); ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
break; break;
case PPC970_INPUT_MCP: case PPC970_INPUT_MCP:
/* Negative edge sensitive */ /* Negative edge sensitive */
@ -194,7 +195,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
if (cur_level == 1 && level == 0) { if (cur_level == 1 && level == 0) {
LOG_IRQ("%s: raise machine check state\n", LOG_IRQ("%s: raise machine check state\n",
__func__); __func__);
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1); ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
} }
break; break;
case PPC970_INPUT_CKSTP: case PPC970_INPUT_CKSTP:
@ -218,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
case PPC970_INPUT_SRESET: case PPC970_INPUT_SRESET:
LOG_IRQ("%s: set the RESET IRQ state to %d\n", LOG_IRQ("%s: set the RESET IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_RESET, level); ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
break; break;
case PPC970_INPUT_TBEN: case PPC970_INPUT_TBEN:
LOG_IRQ("%s: set the TBEN state to %d\n", __func__, 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 */ /* Level sensitive - active high */
LOG_IRQ("%s: set the external IRQ state to %d\n", LOG_IRQ("%s: set the external IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_EXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
break; break;
default: default:
/* Unknown pin - do nothing */ /* Unknown pin - do nothing */
@ -319,13 +320,13 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the critical IRQ state to %d\n", LOG_IRQ("%s: set the critical IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
break; break;
case PPC40x_INPUT_INT: case PPC40x_INPUT_INT:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the external IRQ state to %d\n", LOG_IRQ("%s: set the external IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_EXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
break; break;
case PPC40x_INPUT_HALT: case PPC40x_INPUT_HALT:
/* Level sensitive - active low */ /* Level sensitive - active low */
@ -342,7 +343,7 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the debug pin state to %d\n", LOG_IRQ("%s: set the debug pin state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level); ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
break; break;
default: default:
/* Unknown pin - do nothing */ /* Unknown pin - do nothing */
@ -387,26 +388,26 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
case PPCE500_INPUT_RESET_CORE: case PPCE500_INPUT_RESET_CORE:
if (level) { if (level) {
LOG_IRQ("%s: reset the PowerPC core\n", __func__); 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; break;
case PPCE500_INPUT_CINT: case PPCE500_INPUT_CINT:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the critical IRQ state to %d\n", LOG_IRQ("%s: set the critical IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
break; break;
case PPCE500_INPUT_INT: case PPCE500_INPUT_INT:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the core IRQ state to %d\n", LOG_IRQ("%s: set the core IRQ state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_EXT, level); ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
break; break;
case PPCE500_INPUT_DEBUG: case PPCE500_INPUT_DEBUG:
/* Level sensitive - active high */ /* Level sensitive - active high */
LOG_IRQ("%s: set the debug pin state to %d\n", LOG_IRQ("%s: set the debug pin state to %d\n",
__func__, level); __func__, level);
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level); ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
break; break;
default: default:
/* Unknown pin - do nothing */ /* Unknown pin - do nothing */
@ -643,26 +644,27 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env)
/* When decrementer expires, /* When decrementer expires,
* all we need to do is generate or queue a CPU exception * 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 */ /* Raise it */
LOG_TB("raise decrementer exception\n"); 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 */ /* Raise it */
LOG_TB("raise decrementer exception\n"); 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, static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
struct QEMUTimer *timer, struct QEMUTimer *timer,
void (*raise_excp)(CPUPPCState *), void (*raise_excp)(PowerPCCPU *),
uint32_t decr, uint32_t value, uint32_t decr, uint32_t value,
int is_excp) int is_excp)
{ {
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env = env->tb_env; ppc_tb_t *tb_env = env->tb_env;
uint64_t now, next; 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) if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
&& (value & 0x80000000) && (value & 0x80000000)
&& !(decr & 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) 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); &cpu_ppc_decr_excp, decr, value, is_excp);
} }
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value) 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) 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) { 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); &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
} }
} }
void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value) 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_load = value;
tb_env->purr_start = qemu_get_clock_ns(vm_clock); 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) static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
{ {
CPUPPCState *env = opaque; CPUPPCState *env = opaque;
PowerPCCPU *cpu = ppc_env_get_cpu(env);
ppc_tb_t *tb_env = env->tb_env; ppc_tb_t *tb_env = env->tb_env;
tb_env->tb_freq = freq; 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, * if a decrementer exception is pending when it enables msr_ee at startup,
* it's not ready to handle it... * it's not ready to handle it...
*/ */
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); _cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
_cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); _cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
cpu_ppc_store_purr(env, 0x0000000000000000ULL); cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
} }
/* Set up (once) timebase frequency (in Hz) */ /* Set up (once) timebase frequency (in Hz) */
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
tb_env = g_malloc0(sizeof(ppc_tb_t)); tb_env = g_malloc0(sizeof(ppc_tb_t));
env->tb_env = tb_env; env->tb_env = tb_env;
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
/* Create new timer */ /* 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) { if (0) {
/* XXX: find a suitable condition to enable the hypervisor decrementer /* 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 { } else {
tb_env->hdecr_timer = NULL; tb_env->hdecr_timer = NULL;
} }
@ -829,12 +842,14 @@ struct ppc40x_timer_t {
/* Fixed interval timer */ /* Fixed interval timer */
static void cpu_4xx_fit_cb (void *opaque) static void cpu_4xx_fit_cb (void *opaque)
{ {
PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer; ppc40x_timer_t *ppc40x_timer;
uint64_t now, next; uint64_t now, next;
env = opaque; env = opaque;
cpu = ppc_env_get_cpu(env);
tb_env = env->tb_env; tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque; ppc40x_timer = tb_env->opaque;
now = qemu_get_clock_ns(vm_clock); now = qemu_get_clock_ns(vm_clock);
@ -860,8 +875,9 @@ static void cpu_4xx_fit_cb (void *opaque)
next++; next++;
qemu_mod_timer(ppc40x_timer->fit_timer, next); qemu_mod_timer(ppc40x_timer->fit_timer, next);
env->spr[SPR_40x_TSR] |= 1 << 26; env->spr[SPR_40x_TSR] |= 1 << 26;
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
ppc_set_irq(env, PPC_INTERRUPT_FIT, 1); ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
}
LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__, LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
(int)((env->spr[SPR_40x_TCR] >> 23) & 0x1), (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]); 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) static void cpu_4xx_pit_cb (void *opaque)
{ {
PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer; ppc40x_timer_t *ppc40x_timer;
env = opaque; env = opaque;
cpu = ppc_env_get_cpu(env);
tb_env = env->tb_env; tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque; ppc40x_timer = tb_env->opaque;
env->spr[SPR_40x_TSR] |= 1 << 27; env->spr[SPR_40x_TSR] |= 1 << 27;
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
ppc_set_irq(env, ppc40x_timer->decr_excp, 1); ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
}
start_stop_pit(env, tb_env, 1); start_stop_pit(env, tb_env, 1);
LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " " LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
"%016" PRIx64 "\n", __func__, "%016" PRIx64 "\n", __func__,
@ -919,12 +938,14 @@ static void cpu_4xx_pit_cb (void *opaque)
/* Watchdog timer */ /* Watchdog timer */
static void cpu_4xx_wdt_cb (void *opaque) static void cpu_4xx_wdt_cb (void *opaque)
{ {
PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
ppc40x_timer_t *ppc40x_timer; ppc40x_timer_t *ppc40x_timer;
uint64_t now, next; uint64_t now, next;
env = opaque; env = opaque;
cpu = ppc_env_get_cpu(env);
tb_env = env->tb_env; tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque; ppc40x_timer = tb_env->opaque;
now = qemu_get_clock_ns(vm_clock); 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); qemu_mod_timer(ppc40x_timer->wdt_timer, next);
ppc40x_timer->wdt_next = next; ppc40x_timer->wdt_next = next;
env->spr[SPR_40x_TSR] |= 1 << 30; env->spr[SPR_40x_TSR] |= 1 << 30;
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
ppc_set_irq(env, PPC_INTERRUPT_WDT, 1); ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
}
break; break;
case 0x3: case 0x3:
env->spr[SPR_40x_TSR] &= ~0x30000000; env->spr[SPR_40x_TSR] &= ~0x30000000;

View file

@ -1,7 +1,7 @@
#ifndef HW_PPC_H #ifndef HW_PPC_H
#define HW_PPC_H 1 #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 */ /* PowerPC hardware exceptions management helpers */
typedef void (*clk_setup_cb)(void *opaque, uint32_t freq); typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
@ -92,6 +92,6 @@ enum {
#define PPC_SERIAL_MM_BAUDBASE 399193 #define PPC_SERIAL_MM_BAUDBASE 399193
/* ppc_booke.c */ /* 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 #endif

View file

@ -496,7 +496,7 @@ void ppce500_init(PPCE500Params *params)
env->mpic_cpu_base = MPC8544_CCSRBAR_BASE + env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
MPC8544_MPIC_REGS_OFFSET + 0x20000; 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 */ /* Register reset handler */
if (!i) { if (!i) {

View file

@ -2111,12 +2111,14 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
{ {
clk_setup_t clk_setup[PPC405CR_CLK_NB]; clk_setup_t clk_setup[PPC405CR_CLK_NB];
qemu_irq dma_irqs[4]; qemu_irq dma_irqs[4];
PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
qemu_irq *pic, *irqs; qemu_irq *pic, *irqs;
memset(clk_setup, 0, sizeof(clk_setup)); 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); &clk_setup[PPC405CR_TMR_CLK], sysclk);
env = &cpu->env;
/* Memory mapped devices registers */ /* Memory mapped devices registers */
/* PLB arbitrer */ /* PLB arbitrer */
ppc4xx_plb_init(env); 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; clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
qemu_irq *pic, *irqs; qemu_irq *pic, *irqs;
memset(clk_setup, 0, sizeof(clk_setup)); memset(clk_setup, 0, sizeof(clk_setup));
/* init CPUs */ /* init CPUs */
env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK], cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
&tlb_clk_setup, sysclk); &tlb_clk_setup, sysclk);
env = &cpu->env;
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
/* Internal devices init */ /* Internal devices init */
@ -2478,7 +2482,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
/* OBP arbitrer */ /* OBP arbitrer */
ppc4xx_opba_init(0xef600600); ppc4xx_opba_init(0xef600600);
/* Initialize timers */ /* Initialize timers */
ppc_booke_timers_init(env, sysclk, 0); ppc_booke_timers_init(cpu, sysclk, 0);
/* Universal interrupt controller */ /* Universal interrupt controller */
irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] = irqs[PPCUIC_OUTPUT_INT] =

View file

@ -195,7 +195,7 @@ static void bamboo_init(QEMUMachineInitArgs *args)
env = &cpu->env; env = &cpu->env;
qemu_register_reset(main_cpu_reset, cpu); 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); ppc_dcr_init(env, NULL, NULL);
/* interrupt controller */ /* interrupt controller */

View file

@ -28,9 +28,9 @@
#include "pci/pci.h" #include "pci/pci.h"
/* PowerPC 4xx core initialization */ /* PowerPC 4xx core initialization */
CPUPPCState *ppc4xx_init (const char *cpu_model, PowerPCCPU *ppc4xx_init(const char *cpu_model,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk, clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk); uint32_t sysclk);
/* PowerPC 4xx universal interrupt controller */ /* PowerPC 4xx universal interrupt controller */
enum { enum {

View file

@ -47,9 +47,9 @@ static void ppc4xx_reset(void *opaque)
/*****************************************************************************/ /*****************************************************************************/
/* Generic PowerPC 4xx processor instantiation */ /* Generic PowerPC 4xx processor instantiation */
CPUPPCState *ppc4xx_init (const char *cpu_model, PowerPCCPU *ppc4xx_init(const char *cpu_model,
clk_setup_t *cpu_clk, clk_setup_t *tb_clk, clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
uint32_t sysclk) uint32_t sysclk)
{ {
PowerPCCPU *cpu; PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
@ -72,7 +72,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
/* Register qemu callbacks */ /* Register qemu callbacks */
qemu_register_reset(ppc4xx_reset, cpu); qemu_register_reset(ppc4xx_reset, cpu);
return env; return cpu;
} }
/*****************************************************************************/ /*****************************************************************************/

View file

@ -71,17 +71,19 @@ struct booke_timer_t {
uint32_t flags; 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_TSR] & TSR_DIS
&& env->spr[SPR_BOOKE_TCR] & TCR_DIE)); && 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_TSR] & TSR_WIS
&& env->spr[SPR_BOOKE_TCR] & TCR_WIE)); && 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_TSR] & TSR_FIS
&& env->spr[SPR_BOOKE_TCR] & TCR_FIE)); && 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) static void booke_decr_cb(void *opaque)
{ {
CPUPPCState *env = opaque; PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
env->spr[SPR_BOOKE_TSR] |= TSR_DIS; env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
booke_update_irq(env); booke_update_irq(cpu);
if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) { if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
/* Auto Reload */ /* Auto Reload */
@ -166,16 +169,16 @@ static void booke_decr_cb(void *opaque)
static void booke_fit_cb(void *opaque) static void booke_fit_cb(void *opaque)
{ {
CPUPPCState *env; PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
booke_timer_t *booke_timer; booke_timer_t *booke_timer;
env = opaque;
tb_env = env->tb_env; tb_env = env->tb_env;
booke_timer = tb_env->opaque; booke_timer = tb_env->opaque;
env->spr[SPR_BOOKE_TSR] |= TSR_FIS; env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
booke_update_irq(env); booke_update_irq(cpu);
booke_update_fixed_timer(env, booke_update_fixed_timer(env,
booke_get_fit_target(env, tb_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) static void booke_wdt_cb(void *opaque)
{ {
CPUPPCState *env; PowerPCCPU *cpu = opaque;
CPUPPCState *env = &cpu->env;
ppc_tb_t *tb_env; ppc_tb_t *tb_env;
booke_timer_t *booke_timer; booke_timer_t *booke_timer;
env = opaque;
tb_env = env->tb_env; tb_env = env->tb_env;
booke_timer = tb_env->opaque; booke_timer = tb_env->opaque;
/* TODO: There's lots of complicated stuff to do here */ /* TODO: There's lots of complicated stuff to do here */
booke_update_irq(env); booke_update_irq(cpu);
booke_update_fixed_timer(env, booke_update_fixed_timer(env,
booke_get_wdt_target(env, tb_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) void store_booke_tsr(CPUPPCState *env, target_ulong val)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
env->spr[SPR_BOOKE_TSR] &= ~val; env->spr[SPR_BOOKE_TSR] &= ~val;
booke_update_irq(env); booke_update_irq(cpu);
} }
void store_booke_tcr(CPUPPCState *env, target_ulong val) void store_booke_tcr(CPUPPCState *env, target_ulong val)
{ {
PowerPCCPU *cpu = ppc_env_get_cpu(env);
ppc_tb_t *tb_env = env->tb_env; ppc_tb_t *tb_env = env->tb_env;
booke_timer_t *booke_timer = tb_env->opaque; booke_timer_t *booke_timer = tb_env->opaque;
tb_env = env->tb_env; tb_env = env->tb_env;
env->spr[SPR_BOOKE_TCR] = val; env->spr[SPR_BOOKE_TCR] = val;
booke_update_irq(env); booke_update_irq(cpu);
booke_update_fixed_timer(env, booke_update_fixed_timer(env,
booke_get_fit_target(env, tb_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; ppc_tb_t *tb_env;
booke_timer_t *booke_timer; 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)); tb_env = g_malloc0(sizeof(ppc_tb_t));
booke_timer = g_malloc0(sizeof(booke_timer_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->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
tb_env->tb_freq = freq; tb_env->tb_freq = freq;
tb_env->decr_freq = freq; tb_env->decr_freq = freq;
tb_env->opaque = booke_timer; 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 = 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 = booke_timer->wdt_timer =
qemu_new_timer_ns(vm_clock, &booke_wdt_cb, env); qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
} }

358
hw/qdev-properties-system.c Normal file
View file

@ -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);
}

View file

@ -14,49 +14,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
return ptr; 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, static void get_enum(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp) 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 *p = qdev_get_prop_ptr(dev, props);
uint32_t mask = qdev_get_prop_mask(props); uint32_t mask = qdev_get_prop_mask(props);
if (val) if (val) {
*p |= mask; *p |= mask;
else } else {
*p &= ~mask; *p &= ~mask;
}
} }
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) 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)); 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); char **ptr = qdev_get_prop_ptr(dev, prop);
if (!*ptr) if (!*ptr) {
return snprintf(dest, len, "<null>"); return snprintf(dest, len, "<null>");
}
return snprintf(dest, len, "\"%s\"", *ptr); return snprintf(dest, len, "\"%s\"", *ptr);
} }
@ -477,227 +437,6 @@ PropertyInfo qdev_prop_string = {
.set = set_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 --- */ /* --- pointer --- */
/* Not a proper property, just for dirty hacks. TODO Remove it! */ /* 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) { for (i = 0, pos = 0; i < 6; i++, pos += 3) {
if (!qemu_isxdigit(str[pos])) if (!qemu_isxdigit(str[pos])) {
goto inval; goto inval;
if (!qemu_isxdigit(str[pos+1])) }
if (!qemu_isxdigit(str[pos+1])) {
goto inval; goto inval;
}
if (i == 5) { if (i == 5) {
if (str[pos+2] != '\0') if (str[pos+2] != '\0') {
goto inval; goto inval;
}
} else { } else {
if (str[pos+2] != ':' && str[pos+2] != '-') if (str[pos+2] != ':' && str[pos+2] != '-') {
goto inval; goto inval;
}
} }
mac->a[i] = strtol(str+pos, &p, 16); mac->a[i] = strtol(str+pos, &p, 16);
} }
@ -865,7 +608,8 @@ invalid:
g_free(str); 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); 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) static Property *qdev_prop_walk(Property *props, const char *name)
{ {
if (!props) if (!props) {
return NULL; return NULL;
}
while (props->name) { while (props->name) {
if (strcmp(props->name, name) == 0) if (strcmp(props->name, name) == 0) {
return props; return props;
}
props++; props++;
} }
return NULL; return NULL;
@ -1159,44 +905,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
assert_no_error(errp); 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) void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
{ {
Error *errp = NULL; Error *errp = NULL;
@ -1230,9 +938,10 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
*ptr = 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); QTAILQ_INSERT_TAIL(&global_props, prop, next);
} }
@ -1263,20 +972,3 @@ void qdev_prop_set_globals(DeviceState *dev)
class = object_class_get_parent(class); class = object_class_get_parent(class);
} while (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);
}

View file

@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
/* FIXME: Remove opaque pointer properties. */ /* FIXME: Remove opaque pointer properties. */
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); 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_register_global_list(GlobalProperty *props);
void qdev_prop_set_globals(DeviceState *dev); void qdev_prop_set_globals(DeviceState *dev);
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,

View file

@ -25,7 +25,6 @@
inherit from a particular bus (e.g. PCI or I2C) rather than inherit from a particular bus (e.g. PCI or I2C) rather than
this API directly. */ this API directly. */
#include "net/net.h"
#include "qdev.h" #include "qdev.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "qapi/error.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; 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 *qdev_get_child_bus(DeviceState *dev, const char *name)
{ {
BusState *bus; BusState *bus;

View file

@ -110,10 +110,12 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
return bus; 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()) { if (kvm_enabled()) {
kvm_s390_virtio_irq(env, config_change, token); kvm_s390_virtio_irq(cpu, config_change, token);
} else { } else {
cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token); 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); s390_virtio_reset_idx(dev);
if (dev->qdev.hotplugged) { if (dev->qdev.hotplugged) {
S390CPU *cpu = s390_cpu_addr2state(0); S390CPU *cpu = s390_cpu_addr2state(0);
CPUS390XState *env = &cpu->env; s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
} }
return 0; return 0;
@ -368,9 +369,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
VirtIOS390Device *dev = (VirtIOS390Device*)opaque; VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
uint64_t token = s390_virtio_device_vq_token(dev, vector); uint64_t token = s390_virtio_device_vq_token(dev, vector);
S390CPU *cpu = s390_cpu_addr2state(0); 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) static unsigned virtio_s390_get_features(void *opaque)

View file

@ -798,7 +798,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
/* Tell KVM that we're in PAPR mode */ /* Tell KVM that we're in PAPR mode */
if (kvm_enabled()) { if (kvm_enabled()) {
kvmppc_set_papr(env); kvmppc_set_papr(cpu);
} }
qemu_register_reset(spapr_cpu_reset, cpu); qemu_register_reset(spapr_cpu_reset, cpu);

View file

@ -93,7 +93,7 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
} }
env = &cpu->env; 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); ppc_dcr_init(env, NULL, NULL);

View file

@ -12,6 +12,18 @@
#include "qemu/bswap.h" #include "qemu/bswap.h"
#include "qemu/queue.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) #if !defined(CONFIG_USER_ONLY)
enum device_endian { enum device_endian {

View file

@ -134,8 +134,6 @@ typedef struct icount_decr_u16 {
} icount_decr_u16; } icount_decr_u16;
#endif #endif
struct kvm_run;
struct KVMState;
struct qemu_work_item; struct qemu_work_item;
typedef struct CPUBreakpoint { typedef struct CPUBreakpoint {
@ -204,10 +202,6 @@ typedef struct CPUWatchpoint {
/* user data */ \ /* user data */ \
void *opaque; \ void *opaque; \
\ \
const char *cpu_model_str; \ const char *cpu_model_str;
struct KVMState *kvm_state; \
struct kvm_run *kvm_run; \
int kvm_fd; \
int kvm_vcpu_dirty;
#endif #endif

View file

@ -52,11 +52,15 @@ typedef struct CPUClass {
void (*reset)(CPUState *cpu); void (*reset)(CPUState *cpu);
} CPUClass; } CPUClass;
struct KVMState;
struct kvm_run;
/** /**
* CPUState: * CPUState:
* @created: Indicates whether the CPU thread has been successfully created. * @created: Indicates whether the CPU thread has been successfully created.
* @stop: Indicates a pending stop request. * @stop: Indicates a pending stop request.
* @stopped: Indicates the CPU has been artificially stopped. * @stopped: Indicates the CPU has been artificially stopped.
* @kvm_fd: vCPU file descriptor for KVM.
* *
* State of one CPU core or thread. * State of one CPU core or thread.
*/ */
@ -77,6 +81,13 @@ struct CPUState {
bool stop; bool stop;
bool stopped; 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. */ /* TODO Move common fields from CPUArchState here. */
}; };

View file

@ -152,20 +152,20 @@ int kvm_ioctl(KVMState *s, int type, ...);
int kvm_vm_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 */ /* Arch specific hooks */
extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
void kvm_arch_pre_run(CPUArchState *env, struct kvm_run *run); void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run);
void kvm_arch_post_run(CPUArchState *env, 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 */ /* state subset only touched by the VCPU itself during runtime */
#define KVM_PUT_RUNTIME_STATE 1 #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 */ /* full state set, modified during initialization or on vmload */
#define KVM_PUT_FULL_STATE 3 #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(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); int kvm_arch_on_sigbus(int code, void *addr);
void kvm_arch_init_irq_routing(KVMState *s); 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); 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); 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); 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); struct kvm_sw_breakpoint *bp);
int kvm_arch_insert_hw_breakpoint(target_ulong addr, int kvm_arch_insert_hw_breakpoint(target_ulong addr,
target_ulong len, int type); target_ulong len, int type);
@ -222,9 +222,9 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,
target_ulong len, int type); target_ulong len, int type);
void kvm_arch_remove_all_hw_breakpoints(void); 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); int kvm_check_extension(KVMState *s, unsigned int extension);

127
kvm-all.c
View file

@ -209,13 +209,14 @@ static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
static void kvm_reset_vcpu(void *opaque) 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) int kvm_init_vcpu(CPUArchState *env)
{ {
CPUState *cpu = ENV_GET_CPU(env);
KVMState *s = kvm_state; KVMState *s = kvm_state;
long mmap_size; long mmap_size;
int ret; int ret;
@ -228,9 +229,9 @@ int kvm_init_vcpu(CPUArchState *env)
goto err; goto err;
} }
env->kvm_fd = ret; cpu->kvm_fd = ret;
env->kvm_state = s; cpu->kvm_state = s;
env->kvm_vcpu_dirty = 1; cpu->kvm_vcpu_dirty = true;
mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
if (mmap_size < 0) { if (mmap_size < 0) {
@ -239,9 +240,9 @@ int kvm_init_vcpu(CPUArchState *env)
goto err; goto err;
} }
env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, cpu->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
env->kvm_fd, 0); cpu->kvm_fd, 0);
if (env->kvm_run == MAP_FAILED) { if (cpu->kvm_run == MAP_FAILED) {
ret = -errno; ret = -errno;
DPRINTF("mmap'ing vcpu state failed\n"); DPRINTF("mmap'ing vcpu state failed\n");
goto err; goto err;
@ -249,13 +250,13 @@ int kvm_init_vcpu(CPUArchState *env)
if (s->coalesced_mmio && !s->coalesced_mmio_ring) { if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
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) { if (ret == 0) {
qemu_register_reset(kvm_reset_vcpu, env); qemu_register_reset(kvm_reset_vcpu, cpu);
kvm_arch_reset_vcpu(env); kvm_arch_reset_vcpu(cpu);
} }
err: err:
return ret; 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) static int kvm_handle_internal_error(CPUArchState *env, struct kvm_run *run)
{ {
CPUState *cpu = ENV_GET_CPU(env);
fprintf(stderr, "KVM internal error."); fprintf(stderr, "KVM internal error.");
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) { if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
int i; 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) { if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n"); 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); cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
return EXCP_INTERRUPT; return EXCP_INTERRUPT;
} }
@ -1486,13 +1489,13 @@ void kvm_flush_coalesced_mmio_buffer(void)
s->coalesced_flush_in_progress = false; 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) { if (!cpu->kvm_vcpu_dirty) {
kvm_arch_get_registers(env); kvm_arch_get_registers(cpu);
env->kvm_vcpu_dirty = 1; cpu->kvm_vcpu_dirty = true;
} }
} }
@ -1500,42 +1503,47 @@ void kvm_cpu_synchronize_state(CPUArchState *env)
{ {
CPUState *cpu = ENV_GET_CPU(env); CPUState *cpu = ENV_GET_CPU(env);
if (!env->kvm_vcpu_dirty) { if (!cpu->kvm_vcpu_dirty) {
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, env); run_on_cpu(cpu, do_kvm_cpu_synchronize_state, cpu);
} }
} }
void kvm_cpu_synchronize_post_reset(CPUArchState *env) void kvm_cpu_synchronize_post_reset(CPUArchState *env)
{ {
kvm_arch_put_registers(env, KVM_PUT_RESET_STATE); CPUState *cpu = ENV_GET_CPU(env);
env->kvm_vcpu_dirty = 0;
kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE);
cpu->kvm_vcpu_dirty = false;
} }
void kvm_cpu_synchronize_post_init(CPUArchState *env) void kvm_cpu_synchronize_post_init(CPUArchState *env)
{ {
kvm_arch_put_registers(env, KVM_PUT_FULL_STATE); CPUState *cpu = ENV_GET_CPU(env);
env->kvm_vcpu_dirty = 0;
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
cpu->kvm_vcpu_dirty = false;
} }
int kvm_cpu_exec(CPUArchState *env) 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; int ret, run_ret;
DPRINTF("kvm_cpu_exec()\n"); DPRINTF("kvm_cpu_exec()\n");
if (kvm_arch_process_async_events(env)) { if (kvm_arch_process_async_events(cpu)) {
env->exit_request = 0; env->exit_request = 0;
return EXCP_HLT; return EXCP_HLT;
} }
do { do {
if (env->kvm_vcpu_dirty) { if (cpu->kvm_vcpu_dirty) {
kvm_arch_put_registers(env, KVM_PUT_RUNTIME_STATE); kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE);
env->kvm_vcpu_dirty = 0; cpu->kvm_vcpu_dirty = false;
} }
kvm_arch_pre_run(env, run); kvm_arch_pre_run(cpu, run);
if (env->exit_request) { if (env->exit_request) {
DPRINTF("interrupt exit requested\n"); DPRINTF("interrupt exit requested\n");
/* /*
@ -1547,10 +1555,10 @@ int kvm_cpu_exec(CPUArchState *env)
} }
qemu_mutex_unlock_iothread(); 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(); qemu_mutex_lock_iothread();
kvm_arch_post_run(env, run); kvm_arch_post_run(cpu, run);
if (run_ret < 0) { if (run_ret < 0) {
if (run_ret == -EINTR || run_ret == -EAGAIN) { if (run_ret == -EINTR || run_ret == -EAGAIN) {
@ -1600,7 +1608,7 @@ int kvm_cpu_exec(CPUArchState *env)
break; break;
default: default:
DPRINTF("kvm_arch_handle_exit\n"); DPRINTF("kvm_arch_handle_exit\n");
ret = kvm_arch_handle_exit(env, run); ret = kvm_arch_handle_exit(cpu, run);
break; break;
} }
} while (ret == 0); } while (ret == 0);
@ -1648,7 +1656,7 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
return ret; return ret;
} }
int kvm_vcpu_ioctl(CPUArchState *env, int type, ...) int kvm_vcpu_ioctl(CPUState *cpu, int type, ...)
{ {
int ret; int ret;
void *arg; void *arg;
@ -1658,7 +1666,7 @@ int kvm_vcpu_ioctl(CPUArchState *env, int type, ...)
arg = va_arg(ap, void *); arg = va_arg(ap, void *);
va_end(ap); va_end(ap);
ret = ioctl(env->kvm_fd, type, arg); ret = ioctl(cpu->kvm_fd, type, arg);
if (ret == -1) { if (ret == -1) {
ret = -errno; ret = -errno;
} }
@ -1753,12 +1761,12 @@ void kvm_setup_guest_memory(void *start, size_t size)
} }
#ifdef KVM_CAP_SET_GUEST_DEBUG #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) target_ulong pc)
{ {
struct kvm_sw_breakpoint *bp; 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) { if (bp->pc == pc) {
return bp; return bp;
} }
@ -1766,23 +1774,23 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env,
return NULL; 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_set_guest_debug_data {
struct kvm_guest_debug dbg; struct kvm_guest_debug dbg;
CPUArchState *env; CPUState *cpu;
int err; int err;
}; };
static void kvm_invoke_set_guest_debug(void *data) static void kvm_invoke_set_guest_debug(void *data)
{ {
struct kvm_set_guest_debug_data *dbg_data = data; struct kvm_set_guest_debug_data *dbg_data = data;
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) 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) { if (env->singlestep_enabled) {
data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP; data.dbg.control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP;
} }
kvm_arch_update_guest_debug(env, &data.dbg); kvm_arch_update_guest_debug(cpu, &data.dbg);
data.env = env; data.cpu = cpu;
run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data); run_on_cpu(cpu, kvm_invoke_set_guest_debug, &data);
return data.err; 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, int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
target_ulong len, int type) target_ulong len, int type)
{ {
CPUState *current_cpu = ENV_GET_CPU(current_env);
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;
CPUArchState *env; CPUArchState *env;
int err; int err;
if (type == GDB_BREAKPOINT_SW) { if (type == GDB_BREAKPOINT_SW) {
bp = kvm_find_sw_breakpoint(current_env, addr); bp = kvm_find_sw_breakpoint(current_cpu, addr);
if (bp) { if (bp) {
bp->use_count++; bp->use_count++;
return 0; return 0;
@ -1823,13 +1832,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr,
bp->pc = addr; bp->pc = addr;
bp->use_count = 1; bp->use_count = 1;
err = kvm_arch_insert_sw_breakpoint(current_env, bp); err = kvm_arch_insert_sw_breakpoint(current_cpu, bp);
if (err) { if (err) {
g_free(bp); g_free(bp);
return err; return err;
} }
QTAILQ_INSERT_HEAD(&current_env->kvm_state->kvm_sw_breakpoints, QTAILQ_INSERT_HEAD(&current_cpu->kvm_state->kvm_sw_breakpoints,
bp, entry); bp, entry);
} else { } else {
err = kvm_arch_insert_hw_breakpoint(addr, len, type); 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, int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
target_ulong len, int type) target_ulong len, int type)
{ {
CPUState *current_cpu = ENV_GET_CPU(current_env);
struct kvm_sw_breakpoint *bp; struct kvm_sw_breakpoint *bp;
CPUArchState *env; CPUArchState *env;
int err; int err;
if (type == GDB_BREAKPOINT_SW) { if (type == GDB_BREAKPOINT_SW) {
bp = kvm_find_sw_breakpoint(current_env, addr); bp = kvm_find_sw_breakpoint(current_cpu, addr);
if (!bp) { if (!bp) {
return -ENOENT; return -ENOENT;
} }
@ -1865,12 +1875,12 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr,
return 0; return 0;
} }
err = kvm_arch_remove_sw_breakpoint(current_env, bp); err = kvm_arch_remove_sw_breakpoint(current_cpu, bp);
if (err) { if (err) {
return err; return err;
} }
QTAILQ_REMOVE(&current_env->kvm_state->kvm_sw_breakpoints, bp, entry); QTAILQ_REMOVE(&current_cpu->kvm_state->kvm_sw_breakpoints, bp, entry);
g_free(bp); g_free(bp);
} else { } else {
err = kvm_arch_remove_hw_breakpoint(addr, len, type); 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) void kvm_remove_all_breakpoints(CPUArchState *current_env)
{ {
CPUState *current_cpu = ENV_GET_CPU(current_env);
struct kvm_sw_breakpoint *bp, *next; struct kvm_sw_breakpoint *bp, *next;
KVMState *s = current_env->kvm_state; KVMState *s = current_cpu->kvm_state;
CPUArchState *env; CPUArchState *env;
CPUState *cpu;
QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { 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. */ /* Try harder to find a CPU that currently sees the breakpoint. */
for (env = first_cpu; env != NULL; env = env->next_cpu) { 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; break;
} }
} }
@ -1939,18 +1952,19 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env)
int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset) int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
{ {
CPUState *cpu = ENV_GET_CPU(env);
struct kvm_signal_mask *sigmask; struct kvm_signal_mask *sigmask;
int r; int r;
if (!sigset) { 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 = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
sigmask->len = 8; sigmask->len = 8;
memcpy(sigmask->sigset, sigset, sizeof(*sigset)); 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); g_free(sigmask);
return r; 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) 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) int kvm_on_sigbus(int code, void *addr)

View file

@ -58,6 +58,9 @@ typedef struct AlphaCPU {
/*< public >*/ /*< public >*/
CPUAlphaState env; CPUAlphaState env;
/* This alarm doesn't exist in real hardware; we wish it did. */
struct QEMUTimer *alarm_timer;
} AlphaCPU; } AlphaCPU;
static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env) static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)

View file

@ -21,8 +21,211 @@
#include "cpu.h" #include "cpu.h"
#include "qemu-common.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) static void alpha_cpu_initfn(Object *obj)
{ {
AlphaCPU *cpu = ALPHA_CPU(obj); AlphaCPU *cpu = ALPHA_CPU(obj);
@ -31,6 +234,8 @@ static void alpha_cpu_initfn(Object *obj)
cpu_exec_init(env); cpu_exec_init(env);
tlb_flush(env, 1); tlb_flush(env, 1);
alpha_translate_init();
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
env->ps = PS_USER_MODE; env->ps = PS_USER_MODE;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD 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, .parent = TYPE_CPU,
.instance_size = sizeof(AlphaCPU), .instance_size = sizeof(AlphaCPU),
.instance_init = alpha_cpu_initfn, .instance_init = alpha_cpu_initfn,
.abstract = false, .abstract = true,
.class_size = sizeof(AlphaCPUClass), .class_size = sizeof(AlphaCPUClass),
}; };
static void alpha_cpu_register_types(void) static void alpha_cpu_register_types(void)
{ {
type_register_static(&alpha_cpu_type_info); 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) type_init(alpha_cpu_register_types)

View file

@ -277,7 +277,6 @@ struct CPUAlphaState {
#endif #endif
/* This alarm doesn't exist in real hardware; we wish it did. */ /* This alarm doesn't exist in real hardware; we wish it did. */
struct QEMUTimer *alarm_timer;
uint64_t alarm_expire; uint64_t alarm_expire;
/* Those resources are used only in QEMU core */ /* Those resources are used only in QEMU core */
@ -290,7 +289,7 @@ struct CPUAlphaState {
int implver; int implver;
}; };
#define cpu_init cpu_alpha_init #define cpu_list alpha_cpu_list
#define cpu_exec cpu_alpha_exec #define cpu_exec cpu_alpha_exec
#define cpu_gen_code cpu_alpha_gen_code #define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler #define cpu_signal_handler cpu_alpha_signal_handler
@ -427,7 +426,20 @@ enum {
IR_ZERO = 31, 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); int cpu_alpha_exec(CPUAlphaState *s);
/* you can call this signal handler from your SIGBUS and SIGSEGV /* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero signal handlers to inform the virtual CPU of exceptions. non zero

View file

@ -77,11 +77,13 @@ uint64_t helper_get_time(void)
void helper_set_alarm(CPUAlphaState *env, uint64_t expire) void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
{ {
AlphaCPU *cpu = alpha_env_get_cpu(env);
if (expire) { if (expire) {
env->alarm_expire = expire; env->alarm_expire = expire;
qemu_mod_timer(env->alarm_timer, expire); qemu_mod_timer(cpu->alarm_timer, expire);
} else { } else {
qemu_del_timer(env->alarm_timer); qemu_del_timer(cpu->alarm_timer);
} }
} }
#endif /* CONFIG_USER_ONLY */ #endif /* CONFIG_USER_ONLY */

View file

@ -90,7 +90,7 @@ static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
#include "exec/gen-icount.h" #include "exec/gen-icount.h"
static void alpha_translate_init(void) void alpha_translate_init(void)
{ {
int i; int i;
char *p; char *p;
@ -3493,62 +3493,6 @@ void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1); 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) void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
{ {
env->pc = tcg_ctx.gen_opc_pc[pc_pos]; env->pc = tcg_ctx.gen_opc_pc[pc_pos];

View file

@ -1291,11 +1291,6 @@ ARMCPU *cpu_arm_init(const char *cpu_model)
return cpu; return cpu;
} }
typedef struct ARMCPUListState {
fprintf_function cpu_fprintf;
FILE *file;
} ARMCPUListState;
/* Sort alphabetically by type name, except for "any". */ /* Sort alphabetically by type name, except for "any". */
static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) 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) static void arm_cpu_list_entry(gpointer data, gpointer user_data)
{ {
ObjectClass *oc = data; ObjectClass *oc = data;
ARMCPUListState *s = user_data; CPUListState *s = user_data;
(*s->cpu_fprintf)(s->file, " %s\n", (*s->cpu_fprintf)(s->file, " %s\n",
object_class_get_name(oc)); 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) void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{ {
ARMCPUListState s = { CPUListState s = {
.file = f, .file = f,
.cpu_fprintf = cpu_fprintf, .cpu_fprintf = cpu_fprintf,
}; };

View file

@ -1637,6 +1637,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *eax, uint32_t *ebx, uint32_t *eax, uint32_t *ebx,
uint32_t *ecx, uint32_t *edx) uint32_t *ecx, uint32_t *edx)
{ {
X86CPU *cpu = x86_env_get_cpu(env);
CPUState *cs = CPU(cpu);
/* test if maximum index reached */ /* test if maximum index reached */
if (index & 0x80000000) { if (index & 0x80000000) {
if (index > env->cpuid_xlevel) { if (index > env->cpuid_xlevel) {
@ -1757,7 +1760,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
case 0xA: case 0xA:
/* Architectural Performance Monitoring Leaf */ /* Architectural Performance Monitoring Leaf */
if (kvm_enabled()) { if (kvm_enabled()) {
KVMState *s = env->kvm_state; KVMState *s = cs->kvm_state;
*eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
*ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); *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; break;
} }
if (kvm_enabled()) { if (kvm_enabled()) {
KVMState *s = env->kvm_state; KVMState *s = cs->kvm_state;
*eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
*ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);

View file

@ -307,16 +307,17 @@ static void hardware_memory_error(void)
exit(1); 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; ram_addr_t ram_addr;
hwaddr paddr; hwaddr paddr;
if ((env->mcg_cap & MCG_SER_P) && addr if ((env->mcg_cap & MCG_SER_P) && addr
&& (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) { && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) {
if (qemu_ram_addr_from_host(addr, &ram_addr) || 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 " fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!\n"); "QEMU itself instead of guest system!\n");
/* Hope we are lucky for AO MCE */ /* 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 */ /* Hope we are lucky for AO MCE */
if (qemu_ram_addr_from_host(addr, &ram_addr) || if (qemu_ram_addr_from_host(addr, &ram_addr) ||
!kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr, !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state,
&paddr)) { addr, &paddr)) {
fprintf(stderr, "Hardware memory error for memory used by " fprintf(stderr, "Hardware memory error for memory used by "
"QEMU itself instead of guest system!: %p\n", addr); "QEMU itself instead of guest system!: %p\n", addr);
return 0; return 0;
@ -368,8 +369,10 @@ int kvm_arch_on_sigbus(int code, void *addr)
return 0; 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) { if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) {
unsigned int bank, bank_num = env->mcg_cap & 0xff; unsigned int bank, bank_num = env->mcg_cap & 0xff;
struct kvm_x86_mce mce; 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.addr = env->mce_banks[bank * 4 + 2];
mce.misc = env->mce_banks[bank * 4 + 3]; 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; 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 {
struct kvm_cpuid2 cpuid; struct kvm_cpuid2 cpuid;
struct kvm_cpuid_entry2 entries[100]; struct kvm_cpuid_entry2 entries[100];
} QEMU_PACKED cpuid_data; } QEMU_PACKED cpuid_data;
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
uint32_t limit, i, j, cpuid_i; uint32_t limit, i, j, cpuid_i;
uint32_t unused; uint32_t unused;
struct kvm_cpuid_entry2 *c; struct kvm_cpuid_entry2 *c;
@ -575,12 +580,12 @@ int kvm_arch_init_vcpu(CPUX86State *env)
if (((env->cpuid_version >> 8)&0xF) >= 6 if (((env->cpuid_version >> 8)&0xF) >= 6
&& (env->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA) && (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; uint64_t mcg_cap;
int banks; int banks;
int ret; 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) { if (ret < 0) {
fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret)); fprintf(stderr, "kvm_get_mce_cap_supported: %s", strerror(-ret));
return ret; return ret;
@ -591,7 +596,7 @@ int kvm_arch_init_vcpu(CPUX86State *env)
} }
mcg_cap &= MCE_CAP_DEF; mcg_cap &= MCE_CAP_DEF;
mcg_cap |= banks; 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) { if (ret < 0) {
fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret)); fprintf(stderr, "KVM_X86_SETUP_MCE: %s", strerror(-ret));
return ret; return ret;
@ -603,14 +608,14 @@ int kvm_arch_init_vcpu(CPUX86State *env)
qemu_add_vm_change_state_handler(cpu_update_state, env); qemu_add_vm_change_state_handler(cpu_update_state, env);
cpuid_data.cpuid.padding = 0; 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) { if (r) {
return 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) { 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) { if (r < 0) {
fprintf(stderr, "KVM_SET_TSC_KHZ failed\n"); fprintf(stderr, "KVM_SET_TSC_KHZ failed\n");
return r; return r;
@ -624,9 +629,10 @@ int kvm_arch_init_vcpu(CPUX86State *env)
return 0; 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->exception_injected = -1;
env->interrupt_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; struct kvm_regs regs;
int ret = 0; int ret = 0;
if (!set) { if (!set) {
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_REGS, &regs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -852,14 +859,15 @@ static int kvm_getput_regs(CPUX86State *env, int set)
kvm_getput_reg(&regs.rip, &env->eip, set); kvm_getput_reg(&regs.rip, &env->eip, set);
if (set) { if (set) {
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_REGS, &regs);
} }
return ret; return ret;
} }
static int kvm_put_fpu(CPUX86State *env) static int kvm_put_fpu(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
struct kvm_fpu fpu; struct kvm_fpu fpu;
int i; int i;
@ -877,7 +885,7 @@ static int kvm_put_fpu(CPUX86State *env)
memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs); memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
fpu.mxcsr = env->mxcsr; 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 #define XSAVE_FCW_FSW 0
@ -890,14 +898,15 @@ static int kvm_put_fpu(CPUX86State *env)
#define XSAVE_XSTATE_BV 128 #define XSAVE_XSTATE_BV 128
#define XSAVE_YMMH_SPACE 144 #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; struct kvm_xsave* xsave = env->kvm_xsave_buf;
uint16_t cwd, swd, twd; uint16_t cwd, swd, twd;
int i, r; int i, r;
if (!kvm_has_xsave()) { if (!kvm_has_xsave()) {
return kvm_put_fpu(env); return kvm_put_fpu(cpu);
} }
memset(xsave, 0, sizeof(struct kvm_xsave)); 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; *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv;
memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs,
sizeof 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; return r;
} }
static int kvm_put_xcrs(CPUX86State *env) static int kvm_put_xcrs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
struct kvm_xcrs xcrs; struct kvm_xcrs xcrs;
if (!kvm_has_xcrs()) { if (!kvm_has_xcrs()) {
@ -936,11 +946,12 @@ static int kvm_put_xcrs(CPUX86State *env)
xcrs.flags = 0; xcrs.flags = 0;
xcrs.xcrs[0].xcr = 0; xcrs.xcrs[0].xcr = 0;
xcrs.xcrs[0].value = env->xcr0; 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; struct kvm_sregs sregs;
memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap)); memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
@ -985,7 +996,7 @@ static int kvm_put_sregs(CPUX86State *env)
sregs.efer = env->efer; 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, 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; 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 {
struct kvm_msrs info; struct kvm_msrs info;
struct kvm_msr_entry entries[100]; struct kvm_msr_entry entries[100];
@ -1077,17 +1089,18 @@ static int kvm_put_msrs(CPUX86State *env, int level)
msr_data.info.nmsrs = n; 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; struct kvm_fpu fpu;
int i, ret; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1108,17 +1121,18 @@ static int kvm_get_fpu(CPUX86State *env)
return 0; 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; struct kvm_xsave* xsave = env->kvm_xsave_buf;
int ret, i; int ret, i;
uint16_t cwd, swd, twd; uint16_t cwd, swd, twd;
if (!kvm_has_xsave()) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1146,8 +1160,9 @@ static int kvm_get_xsave(CPUX86State *env)
return 0; return 0;
} }
static int kvm_get_xcrs(CPUX86State *env) static int kvm_get_xcrs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
int i, ret; int i, ret;
struct kvm_xcrs xcrs; struct kvm_xcrs xcrs;
@ -1155,7 +1170,7 @@ static int kvm_get_xcrs(CPUX86State *env)
return 0; return 0;
} }
ret = kvm_vcpu_ioctl(env, KVM_GET_XCRS, &xcrs); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_XCRS, &xcrs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -1170,13 +1185,14 @@ static int kvm_get_xcrs(CPUX86State *env)
return 0; return 0;
} }
static int kvm_get_sregs(CPUX86State *env) static int kvm_get_sregs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
struct kvm_sregs sregs; struct kvm_sregs sregs;
uint32_t hflags; uint32_t hflags;
int bit, i, ret; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1254,8 +1270,9 @@ static int kvm_get_sregs(CPUX86State *env)
return 0; return 0;
} }
static int kvm_get_msrs(CPUX86State *env) static int kvm_get_msrs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
struct { struct {
struct kvm_msrs info; struct kvm_msrs info;
struct kvm_msr_entry entries[100]; struct kvm_msr_entry entries[100];
@ -1312,7 +1329,7 @@ static int kvm_get_msrs(CPUX86State *env)
} }
msr_data.info.nmsrs = n; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1390,11 +1407,11 @@ static int kvm_get_msrs(CPUX86State *env)
return 0; 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) 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; struct kvm_mp_state mp_state;
int ret; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1414,14 +1431,15 @@ static int kvm_get_mp_state(X86CPU *cpu)
return 0; 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; DeviceState *apic = env->apic_state;
struct kvm_lapic_state kapic; struct kvm_lapic_state kapic;
int ret; int ret;
if (apic && kvm_irqchip_in_kernel()) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1431,21 +1449,23 @@ static int kvm_get_apic(CPUX86State *env)
return 0; 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; DeviceState *apic = env->apic_state;
struct kvm_lapic_state kapic; struct kvm_lapic_state kapic;
if (apic && kvm_irqchip_in_kernel()) { if (apic && kvm_irqchip_in_kernel()) {
kvm_put_apic_state(apic, &kapic); 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; 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; struct kvm_vcpu_events events;
if (!kvm_has_vcpu_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; 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; struct kvm_vcpu_events events;
int ret; int ret;
@ -1487,7 +1508,7 @@ static int kvm_get_vcpu_events(CPUX86State *env)
return 0; 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) { if (ret < 0) {
return ret; return ret;
} }
@ -1513,8 +1534,9 @@ static int kvm_get_vcpu_events(CPUX86State *env)
return 0; 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; int ret = 0;
unsigned long reinject_trap = 0; unsigned long reinject_trap = 0;
@ -1542,8 +1564,9 @@ static int kvm_guest_debug_workarounds(CPUX86State *env)
return ret; return ret;
} }
static int kvm_put_debugregs(CPUX86State *env) static int kvm_put_debugregs(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env;
struct kvm_debugregs dbgregs; struct kvm_debugregs dbgregs;
int i; int i;
@ -1558,11 +1581,12 @@ static int kvm_put_debugregs(CPUX86State *env)
dbgregs.dr7 = env->dr[7]; dbgregs.dr7 = env->dr[7];
dbgregs.flags = 0; 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; struct kvm_debugregs dbgregs;
int i, ret; int i, ret;
@ -1570,7 +1594,7 @@ static int kvm_get_debugregs(CPUX86State *env)
return 0; return 0;
} }
ret = kvm_vcpu_ioctl(env, KVM_GET_DEBUGREGS, &dbgregs); ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEBUGREGS, &dbgregs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -1583,88 +1607,88 @@ static int kvm_get_debugregs(CPUX86State *env)
return 0; 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; int ret;
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); 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) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_xsave(env); ret = kvm_put_xsave(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_xcrs(env); ret = kvm_put_xcrs(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_sregs(env); ret = kvm_put_sregs(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
/* must be before kvm_put_msrs */ /* must be before kvm_put_msrs */
ret = kvm_inject_mce_oldstyle(env); ret = kvm_inject_mce_oldstyle(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_msrs(env, level); ret = kvm_put_msrs(x86_cpu, level);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
if (level >= KVM_PUT_RESET_STATE) { if (level >= KVM_PUT_RESET_STATE) {
ret = kvm_put_mp_state(env); ret = kvm_put_mp_state(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_apic(env); ret = kvm_put_apic(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
} }
ret = kvm_put_vcpu_events(env, level); ret = kvm_put_vcpu_events(x86_cpu, level);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_put_debugregs(env); ret = kvm_put_debugregs(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
/* must be last */ /* must be last */
ret = kvm_guest_debug_workarounds(env); ret = kvm_guest_debug_workarounds(x86_cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
return 0; 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; 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) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_xsave(env); ret = kvm_get_xsave(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_xcrs(env); ret = kvm_get_xcrs(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_sregs(env); ret = kvm_get_sregs(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_msrs(env); ret = kvm_get_msrs(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -1672,30 +1696,32 @@ int kvm_arch_get_registers(CPUX86State *env)
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_apic(env); ret = kvm_get_apic(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_vcpu_events(env); ret = kvm_get_vcpu_events(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
ret = kvm_get_debugregs(env); ret = kvm_get_debugregs(cpu);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
return 0; 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; int ret;
/* Inject NMI */ /* Inject NMI */
if (env->interrupt_request & CPU_INTERRUPT_NMI) { if (env->interrupt_request & CPU_INTERRUPT_NMI) {
env->interrupt_request &= ~CPU_INTERRUPT_NMI; env->interrupt_request &= ~CPU_INTERRUPT_NMI;
DPRINTF("injected NMI\n"); DPRINTF("injected NMI\n");
ret = kvm_vcpu_ioctl(env, KVM_NMI); ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n", fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
strerror(-ret)); strerror(-ret));
@ -1723,7 +1749,7 @@ void kvm_arch_pre_run(CPUX86State *env, struct kvm_run *run)
intr.irq = irq; intr.irq = irq;
DPRINTF("injected interrupt %d\n", 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) { if (ret < 0) {
fprintf(stderr, fprintf(stderr,
"KVM: injection failed, interrupt lost (%s)\n", "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) { if (run->if_flag) {
env->eflags |= IF_MASK; env->eflags |= IF_MASK;
} else { } 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); 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) { if (env->interrupt_request & CPU_INTERRUPT_MCE) {
/* We must not raise CPU_INTERRUPT_MCE if it's not supported. */ /* 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; 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, apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip,
run->tpr_access.is_write ? TPR_ACCESS_WRITE run->tpr_access.is_write ? TPR_ACCESS_WRITE
@ -1840,8 +1872,9 @@ static int kvm_handle_tpr_access(CPUX86State *env)
return 1; 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; static const uint8_t int3 = 0xcc;
if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) || 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; 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; uint8_t int3;
if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc || 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 CPUWatchpoint hw_watchpoint;
static int kvm_handle_debug(CPUX86State *env, static int kvm_handle_debug(X86CPU *cpu,
struct kvm_debug_exit_arch *arch_info) struct kvm_debug_exit_arch *arch_info)
{ {
CPUX86State *env = &cpu->env;
int ret = 0; int ret = 0;
int n; 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; ret = EXCP_DEBUG;
} }
if (ret == 0) { if (ret == 0) {
@ -1995,7 +2030,7 @@ static int kvm_handle_debug(CPUX86State *env,
return ret; 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[] = { const uint8_t type_code[] = {
[GDB_BREAKPOINT_HW] = 0x0, [GDB_BREAKPOINT_HW] = 0x0,
@ -2007,7 +2042,7 @@ void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg)
}; };
int n; int n;
if (kvm_sw_breakpoints_active(env)) { if (kvm_sw_breakpoints_active(cpu)) {
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
} }
if (nb_hw_breakpoint > 0) { if (nb_hw_breakpoint > 0) {
@ -2032,9 +2067,9 @@ static bool host_supports_vmx(void)
#define VMX_INVALID_GUEST_STATE 0x80000021 #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; uint64_t code;
int ret; int ret;
@ -2047,7 +2082,7 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
ret = 0; ret = 0;
break; break;
case KVM_EXIT_TPR_ACCESS: case KVM_EXIT_TPR_ACCESS:
ret = kvm_handle_tpr_access(env); ret = kvm_handle_tpr_access(cpu);
break; break;
case KVM_EXIT_FAIL_ENTRY: case KVM_EXIT_FAIL_ENTRY:
code = run->fail_entry.hardware_entry_failure_reason; code = run->fail_entry.hardware_entry_failure_reason;
@ -2073,7 +2108,7 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
break; break;
case KVM_EXIT_DEBUG: case KVM_EXIT_DEBUG:
DPRINTF("kvm_exit_debug\n"); DPRINTF("kvm_exit_debug\n");
ret = kvm_handle_debug(env, &run->debug.arch); ret = kvm_handle_debug(cpu, &run->debug.arch);
break; break;
default: default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason); 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; 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); kvm_cpu_synchronize_state(env);
return !(env->cr[0] & CR0_PE_MASK) || return !(env->cr[0] & CR0_PE_MASK) ||
((env->segs[R_CS].selector & 3) != 3); ((env->segs[R_CS].selector & 3) != 3);

View file

@ -25,11 +25,6 @@
#define SIGNBIT (1u << 31) #define SIGNBIT (1u << 31)
typedef struct M68kCPUListState {
fprintf_function cpu_fprintf;
FILE *file;
} M68kCPUListState;
/* Sort alphabetically, except for "any". */ /* Sort alphabetically, except for "any". */
static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b) 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) static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
{ {
ObjectClass *c = data; ObjectClass *c = data;
M68kCPUListState *s = user_data; CPUListState *s = user_data;
(*s->cpu_fprintf)(s->file, "%s\n", (*s->cpu_fprintf)(s->file, "%s\n",
object_class_get_name(c)); 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) void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{ {
M68kCPUListState s = { CPUListState s = {
.file = f, .file = f,
.cpu_fprintf = cpu_fprintf, .cpu_fprintf = cpu_fprintf,
}; };

View file

@ -99,8 +99,10 @@ int kvm_arch_init(KVMState *s)
return 0; 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; struct kvm_sregs sregs;
int ret; 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) { if (ret) {
return ret; return ret;
} }
sregs.pvr = cenv->spr[SPR_PVR]; 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 */ /* 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_book3e_206_tlb_params params = {};
struct kvm_config_tlb cfg = {}; struct kvm_config_tlb cfg = {};
struct kvm_enable_cap encap = {}; struct kvm_enable_cap encap = {};
@ -136,7 +140,7 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
int ret, i; int ret, i;
if (!kvm_enabled() || 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; return 0;
} }
@ -161,7 +165,7 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
encap.cap = KVM_CAP_SW_TLB; encap.cap = KVM_CAP_SW_TLB;
encap.args[0] = (uintptr_t)&cfg; 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) { if (ret < 0) {
fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n", fprintf(stderr, "%s: couldn't enable KVM_CAP_SW_TLB: %s\n",
__func__, strerror(-ret)); __func__, strerror(-ret));
@ -174,9 +178,12 @@ static int kvm_booke206_tlb_init(CPUPPCState *env)
#if defined(TARGET_PPC64) #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) struct kvm_ppc_smmu_info *info)
{ {
CPUPPCState *env = &cpu->env;
CPUState *cs = CPU(cpu);
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
/* We don't have the new KVM_PPC_GET_SMMU_INFO ioctl, so /* 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 * implements KVM_CAP_PPC_GET_SMMU_INFO and thus doesn't hit
* this fallback. * 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 */ /* No flags */
info->flags = 0; info->flags = 0;
info->slb_size = 64; 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; int ret;
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) { if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_SMMU_INFO)) {
ret = kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_SMMU_INFO, info); ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_SMMU_INFO, info);
if (ret == 0) { if (ret == 0) {
return; return;
} }
} }
kvm_get_fallback_smmu_info(env, info); kvm_get_fallback_smmu_info(cpu, info);
} }
static long getrampagesize(void) 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; 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 struct kvm_ppc_smmu_info smmu_info;
static bool has_smmu_info; static bool has_smmu_info;
CPUPPCState *env = &cpu->env;
long rampagesize; long rampagesize;
int iq, ik, jq, jk; 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 */ /* Collect MMU info from kernel if not already */
if (!has_smmu_info) { if (!has_smmu_info) {
kvm_get_smmu_info(env, &smmu_info); kvm_get_smmu_info(cpu, &smmu_info);
has_smmu_info = true; has_smmu_info = true;
} }
@ -369,22 +378,23 @@ static void kvm_fixup_page_sizes(CPUPPCState *env)
} }
#else /* defined (TARGET_PPC64) */ #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) */ #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; int ret;
/* Gather server mmu info from KVM and update the CPU state */ /* 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 */ /* Synchronize sregs with kvm */
ret = kvm_arch_sync_sregs(cenv); ret = kvm_arch_sync_sregs(cpu);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -394,7 +404,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv)
/* Some targets support access to KVM's guest TLB. */ /* Some targets support access to KVM's guest TLB. */
switch (cenv->mmu_model) { switch (cenv->mmu_model) {
case POWERPC_MMU_BOOKE206: case POWERPC_MMU_BOOKE206:
ret = kvm_booke206_tlb_init(cenv); ret = kvm_booke206_tlb_init(cpu);
break; break;
default: default:
break; break;
@ -403,12 +413,14 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv)
return ret; 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; struct kvm_dirty_tlb dirty_tlb;
unsigned char *bitmap; unsigned char *bitmap;
int ret; int ret;
@ -423,7 +435,7 @@ static void kvm_sw_tlb_put(CPUPPCState *env)
dirty_tlb.bitmap = (uintptr_t)bitmap; dirty_tlb.bitmap = (uintptr_t)bitmap;
dirty_tlb.num_dirty = env->nb_tlb; 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) { if (ret) {
fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n", fprintf(stderr, "%s: KVM_DIRTY_TLB: %s\n",
__func__, strerror(-ret)); __func__, strerror(-ret));
@ -432,15 +444,18 @@ static void kvm_sw_tlb_put(CPUPPCState *env)
g_free(bitmap); 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; struct kvm_regs regs;
int ret; int ret;
int i; int i;
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs); ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
if (ret < 0) if (ret < 0) {
return ret; return ret;
}
regs.ctr = env->ctr; regs.ctr = env->ctr;
regs.lr = env->lr; regs.lr = env->lr;
@ -465,12 +480,12 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
for (i = 0;i < 32; i++) for (i = 0;i < 32; i++)
regs.gpr[i] = env->gpr[i]; regs.gpr[i] = env->gpr[i];
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs); ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (env->tlb_dirty) { if (env->tlb_dirty) {
kvm_sw_tlb_put(env); kvm_sw_tlb_put(cpu);
env->tlb_dirty = false; env->tlb_dirty = false;
} }
@ -503,7 +518,7 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
| env->IBAT[1][i]; | env->IBAT[1][i];
} }
ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -516,7 +531,7 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
.addr = (uintptr_t) &hior, .addr = (uintptr_t) &hior,
}; };
ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &reg); ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret) { if (ret) {
return ret; return ret;
} }
@ -525,14 +540,16 @@ int kvm_arch_put_registers(CPUPPCState *env, int level)
return ret; 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_regs regs;
struct kvm_sregs sregs; struct kvm_sregs sregs;
uint32_t cr; uint32_t cr;
int i, ret; int i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs); ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -566,7 +583,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
env->gpr[i] = regs.gpr[i]; env->gpr[i] = regs.gpr[i];
if (cap_booke_sregs) { 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) { if (ret < 0) {
return ret; return ret;
} }
@ -670,7 +687,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
} }
if (cap_segstate) { if (cap_segstate) {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -702,7 +719,7 @@ int kvm_arch_get_registers(CPUPPCState *env)
return 0; 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; 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; return 0;
} }
kvm_vcpu_ioctl(env, KVM_INTERRUPT, &virq); kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq);
return 0; return 0;
} }
@ -727,8 +744,10 @@ int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level)
#define PPC_INPUT_INT PPC6xx_INPUT_INT #define PPC_INPUT_INT PPC6xx_INPUT_INT
#endif #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; int r;
unsigned irq; unsigned irq;
@ -746,7 +765,7 @@ void kvm_arch_pre_run(CPUPPCState *env, struct kvm_run *run)
irq = KVM_INTERRUPT_SET; irq = KVM_INTERRUPT_SET;
dprintf("injected interrupt %d\n", irq); 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) if (r < 0)
printf("cpu %d fail inject %x\n", env->cpu_index, irq); 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. */ * 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) 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; 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; int ret;
switch (run->exit_reason) { switch (run->exit_reason) {
@ -817,7 +839,7 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run)
#ifdef CONFIG_PSERIES #ifdef CONFIG_PSERIES
case KVM_EXIT_PAPR_HCALL: case KVM_EXIT_PAPR_HCALL:
dprintf("handle PAPR hypercall\n"); 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.nr,
run->papr_hcall.args); run->papr_hcall.args);
ret = 0; ret = 0;
@ -969,12 +991,14 @@ uint32_t kvmppc_get_dfp(void)
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len) 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; uint32_t *hc = (uint32_t*)buf;
struct kvm_ppc_pvinfo pvinfo; struct kvm_ppc_pvinfo pvinfo;
if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) && if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
!kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) { !kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
memcpy(buf, pvinfo.hcall, buf_len); memcpy(buf, pvinfo.hcall, buf_len);
return 0; return 0;
@ -997,13 +1021,15 @@ int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
return 0; 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 = {}; struct kvm_enable_cap cap = {};
int ret; int ret;
cap.cap = KVM_CAP_PPC_PAPR; 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) { if (ret) {
cpu_abort(env, "This KVM version does not support PAPR\n"); 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; 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; return 1;
} }

View file

@ -20,8 +20,8 @@ uint64_t kvmppc_get_clockfreq(void);
uint32_t kvmppc_get_vmx(void); uint32_t kvmppc_get_vmx(void);
uint32_t kvmppc_get_dfp(void); uint32_t kvmppc_get_dfp(void);
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len); int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(CPUPPCState *env, int irq, int level); int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
void kvmppc_set_papr(CPUPPCState *env); void kvmppc_set_papr(PowerPCCPU *cpu);
int kvmppc_smt_threads(void); int kvmppc_smt_threads(void);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem); 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; 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; return -1;
} }
static inline void kvmppc_set_papr(CPUPPCState *env) static inline void kvmppc_set_papr(PowerPCCPU *cpu)
{ {
} }

View file

@ -296,21 +296,21 @@ void s390x_cpu_timer(void *opaque);
int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall); int s390_virtio_hypercall(CPUS390XState *env, uint64_t mem, uint64_t hypercall);
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
void kvm_s390_interrupt(CPUS390XState *env, int type, uint32_t code); void kvm_s390_interrupt(S390CPU *cpu, int type, uint32_t code);
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);
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); uint64_t parm64, int vm);
#else #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) 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, uint32_t parm, uint64_t parm64,
int vm) int vm)
{ {

View file

@ -19,7 +19,8 @@ void s390_sclp_extint(uint32_t parm)
if (kvm_enabled()) { if (kvm_enabled()) {
#ifdef CONFIG_KVM #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 #endif
} else { } else {
env->psw.addr += 4; env->psw.addr += 4;

View file

@ -72,43 +72,45 @@ int kvm_arch_init(KVMState *s)
return 0; return 0;
} }
int kvm_arch_init_vcpu(CPUS390XState *env) int kvm_arch_init_vcpu(CPUState *cpu)
{ {
int ret = 0; 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"); perror("cannot init reset vcpu");
} }
return ret; return ret;
} }
void kvm_arch_reset_vcpu(CPUS390XState *env) void kvm_arch_reset_vcpu(CPUState *cpu)
{ {
/* FIXME: add code to reset vcpu. */ /* 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_sregs sregs;
struct kvm_regs regs; struct kvm_regs regs;
int ret; int ret;
int i; int i;
/* always save the PSW and the GPRS*/ /* always save the PSW and the GPRS*/
env->kvm_run->psw_addr = env->psw.addr; cs->kvm_run->psw_addr = env->psw.addr;
env->kvm_run->psw_mask = env->psw.mask; 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++) { for (i = 0; i < 16; i++) {
env->kvm_run->s.regs.gprs[i] = env->regs[i]; cs->kvm_run->s.regs.gprs[i] = env->regs[i];
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS;
} }
} else { } else {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
regs.gprs[i] = env->regs[i]; regs.gprs[i] = env->regs[i];
} }
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs); ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -120,53 +122,55 @@ int kvm_arch_put_registers(CPUS390XState *env, int level)
} }
if (cap_sync_regs && if (cap_sync_regs &&
env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && cs->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_CRS) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
env->kvm_run->s.regs.acrs[i] = env->aregs[i]; cs->kvm_run->s.regs.acrs[i] = env->aregs[i];
env->kvm_run->s.regs.crs[i] = env->cregs[i]; cs->kvm_run->s.regs.crs[i] = env->cregs[i];
} }
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; cs->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_CRS;
} else { } else {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
sregs.acrs[i] = env->aregs[i]; sregs.acrs[i] = env->aregs[i];
sregs.crs[i] = env->cregs[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) { if (ret < 0) {
return ret; return ret;
} }
} }
/* Finally the prefix */ /* Finally the prefix */
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
env->kvm_run->s.regs.prefix = env->psa; cs->kvm_run->s.regs.prefix = env->psa;
env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX;
} else { } else {
/* prefix is only supported via sync regs */ /* prefix is only supported via sync regs */
} }
return 0; 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_sregs sregs;
struct kvm_regs regs; struct kvm_regs regs;
int ret; int ret;
int i; int i;
/* get the PSW */ /* get the PSW */
env->psw.addr = env->kvm_run->psw_addr; env->psw.addr = cs->kvm_run->psw_addr;
env->psw.mask = env->kvm_run->psw_mask; env->psw.mask = cs->kvm_run->psw_mask;
/* the GPRS */ /* 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++) { 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 { } else {
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs); ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -177,14 +181,14 @@ int kvm_arch_get_registers(CPUS390XState *env)
/* The ACRS and CRS */ /* The ACRS and CRS */
if (cap_sync_regs && if (cap_sync_regs &&
env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && cs->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_CRS) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
env->aregs[i] = env->kvm_run->s.regs.acrs[i]; env->aregs[i] = cs->kvm_run->s.regs.acrs[i];
env->cregs[i] = env->kvm_run->s.regs.crs[i]; env->cregs[i] = cs->kvm_run->s.regs.crs[i];
} }
} else { } else {
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); ret = kvm_vcpu_ioctl(cs, KVM_GET_SREGS, &sregs);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -195,8 +199,8 @@ int kvm_arch_get_registers(CPUS390XState *env)
} }
/* Finally the prefix */ /* Finally the prefix */
if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { if (cap_sync_regs && cs->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) {
env->psa = env->kvm_run->s.regs.prefix; env->psa = cs->kvm_run->s.regs.prefix;
} else { } else {
/* no prefix without sync regs */ /* 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}; 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) || 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; 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]; uint8_t t[4];
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01}; 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; 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) uint64_t parm64, int vm)
{ {
CPUState *cs = CPU(cpu);
struct kvm_s390_interrupt kvmint; struct kvm_s390_interrupt kvmint;
int r; int r;
if (!env->kvm_state) { if (!cs->kvm_state) {
return; return;
} }
@ -294,9 +304,9 @@ void kvm_s390_interrupt_internal(CPUS390XState *env, int type, uint32_t parm,
kvmint.parm64 = parm64; kvmint.parm64 = parm64;
if (vm) { 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 { } else {
r = kvm_vcpu_ioctl(env, KVM_S390_INTERRUPT, &kvmint); r = kvm_vcpu_ioctl(cs, KVM_S390_INTERRUPT, &kvmint);
} }
if (r < 0) { 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); 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); CPUS390XState *env = &cpu->env;
env->kvm_run->psw_mask |= (cc & 3) << 44; 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 &= ~(3ul << 44);
env->psw.mask |= (cc & 3) << 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) uint16_t ipbh0)
{ {
CPUS390XState *env = &cpu->env;
uint32_t sccb; uint32_t sccb;
uint64_t code; uint64_t code;
int r = 0; 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); r = sclp_service_call(sccb, code);
if (r < 0) { if (r < 0) {
enter_pgmcheck(env, -r); enter_pgmcheck(cpu, -r);
} }
setcc(env, r); setcc(cpu, r);
return 0; 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; int r = 0;
uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16; 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); dprintf("KVM: PRIV: %d\n", ipa1);
switch (ipa1) { switch (ipa1) {
case PRIV_SCLP_CALL: case PRIV_SCLP_CALL:
r = kvm_sclp_service_call(env, run, ipbh0); r = kvm_sclp_service_call(cpu, run, ipbh0);
break; break;
default: default:
dprintf("KVM: unknown PRIV: 0x%x\n", ipa1); dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
@ -401,7 +415,7 @@ static int s390_cpu_restart(S390CPU *cpu)
{ {
CPUS390XState *env = &cpu->env; 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); s390_add_running_cpu(env);
qemu_cpu_kick(CPU(cpu)); qemu_cpu_kick(CPU(cpu));
dprintf("DONE: SIGP cpu restart: %p\n", env); dprintf("DONE: SIGP cpu restart: %p\n", env);
@ -415,12 +429,13 @@ static int s390_store_status(CPUS390XState *env, uint32_t parameter)
return -1; return -1;
} }
static int s390_cpu_initial_reset(CPUS390XState *env) static int s390_cpu_initial_reset(S390CPU *cpu)
{ {
CPUS390XState *env = &cpu->env;
int i; int i;
s390_del_running_cpu(env); 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"); perror("cannot init reset vcpu");
} }
@ -434,8 +449,9 @@ static int s390_cpu_initial_reset(CPUS390XState *env)
return 0; 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; uint8_t order_code;
uint32_t parameter; uint32_t parameter;
uint16_t cpu_addr; 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 */ /* make the caller panic */
return -1; return -1;
case SIGP_INITIAL_CPU_RESET: case SIGP_INITIAL_CPU_RESET:
r = s390_cpu_initial_reset(target_env); r = s390_cpu_initial_reset(target_cpu);
break; break;
default: default:
fprintf(stderr, "KVM: unknown SIGP: 0x%x\n", order_code); 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: out:
setcc(env, r ? 3 : 0); setcc(cpu, r ? 3 : 0);
return 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); unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff; uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16; 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); dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
switch (ipa0) { switch (ipa0) {
case IPA0_PRIV: case IPA0_PRIV:
r = handle_priv(env, run, ipa1); r = handle_priv(cpu, run, ipa1);
break; break;
case IPA0_DIAG: case IPA0_DIAG:
r = handle_diag(env, run, ipb_code); r = handle_diag(env, run, ipb_code);
break; break;
case IPA0_SIGP: case IPA0_SIGP:
r = handle_sigp(env, run, ipa1); r = handle_sigp(cpu, run, ipa1);
break; break;
} }
if (r < 0) { if (r < 0) {
enter_pgmcheck(env, 0x0001); enter_pgmcheck(cpu, 0x0001);
} }
return 0; return 0;
} }
static bool is_special_wait_psw(CPUS390XState *env) static bool is_special_wait_psw(CPUState *cs)
{ {
/* signal quiesce */ /* 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 icpt_code = run->s390_sieic.icptcode;
int r = 0; int r = 0;
dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code, 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) { switch (icpt_code) {
case ICPT_INSTRUCTION: case ICPT_INSTRUCTION:
r = handle_instruction(env, run); r = handle_instruction(cpu, run);
break; break;
case ICPT_WAITPSW: case ICPT_WAITPSW:
if (s390_del_running_cpu(env) == 0 && if (s390_del_running_cpu(env) == 0 &&
is_special_wait_psw(env)) { is_special_wait_psw(cs)) {
qemu_system_shutdown_request(); qemu_system_shutdown_request();
} }
r = EXCP_HALTED; r = EXCP_HALTED;
@ -565,13 +584,14 @@ static int handle_intercept(CPUS390XState *env)
return r; 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; int ret = 0;
switch (run->exit_reason) { switch (run->exit_reason) {
case KVM_EXIT_S390_SIEIC: case KVM_EXIT_S390_SIEIC:
ret = handle_intercept(env); ret = handle_intercept(cpu);
break; break;
case KVM_EXIT_S390_RESET: case KVM_EXIT_S390_RESET:
qemu_system_reset_request(); qemu_system_reset_request();
@ -587,12 +607,12 @@ int kvm_arch_handle_exit(CPUS390XState *env, struct kvm_run *run)
return ret; return ret;
} }
bool kvm_arch_stop_on_emulation_error(CPUS390XState *env) bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
{ {
return true; 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; return 1;
} }

View file

@ -57,7 +57,7 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc)
if (kvm_enabled()) { if (kvm_enabled()) {
#ifdef CONFIG_KVM #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 #endif
} else { } else {
env->int_pgm_code = code; env->int_pgm_code = code;