提交 b1d28ec6 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20141010' into staging

various s390x updates:
- cpu state handling in qemu and migration
- vhost-scsi-ccw bugfix

# gpg: Signature made Fri 10 Oct 2014 14:01:34 BST using RSA key ID C6F02FAF
# gpg: Can't check signature: public key not found

* remotes/cohuck/tags/s390x-20141010:
  s390x/virtio-ccw: fix vhost-scsi intialization
  s390x/migration: migrate CPU state
  s390x/kvm: synchronize the cpu state after SIGP (INITIAL) CPU RESET
  s390x/kvm: reuse kvm_s390_reset_vcpu() to get rid of ifdefs
  s390x/kvm: propagate s390 cpu state to kvm
  s390x/kvm: proper use of the cpu states OPERATING and STOPPED
  s390x/kvm: introduce proper states for s390 cpus
  linux-headers: update to 3.17-rc7
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -176,7 +176,7 @@ static void s390_ipl_reset(DeviceState *dev)
}
}
s390_add_running_cpu(cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
}
static void s390_ipl_class_init(ObjectClass *klass, void *data)
......
......@@ -125,38 +125,6 @@ static void s390_virtio_register_hcalls(void)
s390_virtio_hcall_set_status);
}
/*
* The number of running CPUs. On s390 a shutdown is the state of all CPUs
* being either stopped or disabled (for interrupts) waiting. We have to
* track this number to call the shutdown sequence accordingly. This
* number is modified either on startup or while holding the big qemu lock.
*/
static unsigned s390_running_cpus;
void s390_add_running_cpu(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
if (cs->halted) {
s390_running_cpus++;
cs->halted = 0;
cs->exception_index = -1;
}
}
unsigned s390_del_running_cpu(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
if (cs->halted == 0) {
assert(s390_running_cpus >= 1);
s390_running_cpus--;
cs->halted = 1;
cs->exception_index = EXCP_HLT;
}
return s390_running_cpus;
}
void s390_init_ipl_dev(const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
......
......@@ -1528,7 +1528,7 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data)
static const TypeInfo vhost_ccw_scsi = {
.name = TYPE_VHOST_SCSI_CCW,
.parent = TYPE_VIRTIO_CCW_DEVICE,
.instance_size = sizeof(VirtIOSCSICcw),
.instance_size = sizeof(VHostSCSICcw),
.instance_init = vhost_ccw_scsi_instance_init,
.class_init = vhost_ccw_scsi_class_init,
};
......
#include <asm-generic/kvm_para.h>
#ifndef _ASM_MIPS_KVM_PARA_H
#define _ASM_MIPS_KVM_PARA_H
#endif /* _ASM_MIPS_KVM_PARA_H */
......@@ -548,6 +548,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
#define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
#define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
/* Architecture compatibility level */
......@@ -555,6 +556,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
......
......@@ -23,7 +23,10 @@
#define GP_VECTOR 13
#define PF_VECTOR 14
#define MF_VECTOR 16
#define AC_VECTOR 17
#define MC_VECTOR 18
#define XM_VECTOR 19
#define VE_VECTOR 20
/* Select x86 specific features in <linux/kvm.h> */
#define __KVM_HAVE_PIT
......
......@@ -162,7 +162,7 @@ struct kvm_pit_config {
#define KVM_EXIT_TPR_ACCESS 12
#define KVM_EXIT_S390_SIEIC 13
#define KVM_EXIT_S390_RESET 14
#define KVM_EXIT_DCR 15
#define KVM_EXIT_DCR 15 /* deprecated */
#define KVM_EXIT_NMI 16
#define KVM_EXIT_INTERNAL_ERROR 17
#define KVM_EXIT_OSI 18
......@@ -268,7 +268,7 @@ struct kvm_run {
__u64 trans_exc_code;
__u32 pgm_code;
} s390_ucontrol;
/* KVM_EXIT_DCR */
/* KVM_EXIT_DCR (deprecated) */
struct {
__u32 dcrn;
__u32 data;
......@@ -399,13 +399,18 @@ struct kvm_vapic_addr {
__u64 vapic_addr;
};
/* for KVM_SET_MPSTATE */
/* for KVM_SET_MP_STATE */
/* not all states are valid on all architectures */
#define KVM_MP_STATE_RUNNABLE 0
#define KVM_MP_STATE_UNINITIALIZED 1
#define KVM_MP_STATE_INIT_RECEIVED 2
#define KVM_MP_STATE_HALTED 3
#define KVM_MP_STATE_SIPI_RECEIVED 4
#define KVM_MP_STATE_STOPPED 5
#define KVM_MP_STATE_CHECK_STOP 6
#define KVM_MP_STATE_OPERATING 7
#define KVM_MP_STATE_LOAD 8
struct kvm_mp_state {
__u32 mp_state;
......@@ -758,6 +763,8 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_VM_ATTRIBUTES 101
#define KVM_CAP_ARM_PSCI_0_2 102
#define KVM_CAP_PPC_FIXUP_HCALL 103
#define KVM_CAP_PPC_ENABLE_HCALL 104
#define KVM_CAP_CHECK_EXTENSION_VM 105
#ifdef KVM_CAP_IRQ_ROUTING
......
......@@ -20,6 +20,9 @@
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
#define KVM_HC_KICK_CPU 5
#define KVM_HC_MIPS_GET_CLOCK_FREQ 6
#define KVM_HC_MIPS_EXIT_VM 7
#define KVM_HC_MIPS_CONSOLE_OUTPUT 8
/*
* hypercalls use architecture specific
......
......@@ -30,6 +30,9 @@
*/
#define VFIO_DMA_CC_IOMMU 4
/* Check if EEH is supported */
#define VFIO_EEH 5
/*
* The IOCTL interface is designed for extensibility by embedding the
* structure length (argsz) and flags into structures passed between
......@@ -455,6 +458,37 @@ struct vfio_iommu_spapr_tce_info {
#define VFIO_IOMMU_SPAPR_TCE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
/*
* EEH PE operation struct provides ways to:
* - enable/disable EEH functionality;
* - unfreeze IO/DMA for frozen PE;
* - read PE state;
* - reset PE;
* - configure PE.
*/
struct vfio_eeh_pe_op {
__u32 argsz;
__u32 flags;
__u32 op;
};
#define VFIO_EEH_PE_DISABLE 0 /* Disable EEH functionality */
#define VFIO_EEH_PE_ENABLE 1 /* Enable EEH functionality */
#define VFIO_EEH_PE_UNFREEZE_IO 2 /* Enable IO for frozen PE */
#define VFIO_EEH_PE_UNFREEZE_DMA 3 /* Enable DMA for frozen PE */
#define VFIO_EEH_PE_GET_STATE 4 /* PE state retrieval */
#define VFIO_EEH_PE_STATE_NORMAL 0 /* PE in functional state */
#define VFIO_EEH_PE_STATE_RESET 1 /* PE reset in progress */
#define VFIO_EEH_PE_STATE_STOPPED 2 /* Stopped DMA and IO */
#define VFIO_EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA only */
#define VFIO_EEH_PE_STATE_UNAVAIL 5 /* State unavailable */
#define VFIO_EEH_PE_RESET_DEACTIVATE 5 /* Deassert PE reset */
#define VFIO_EEH_PE_RESET_HOT 6 /* Assert hot reset */
#define VFIO_EEH_PE_RESET_FUNDAMENTAL 7 /* Assert fundamental reset */
#define VFIO_EEH_PE_CONFIGURE 8 /* PE configuration */
#define VFIO_EEH_PE_OP _IO(VFIO_TYPE, VFIO_BASE + 21)
/* ***************************************************************** */
#endif /* VFIO_H */
......@@ -14,7 +14,7 @@
#include <linux/ioctl.h>
#include <linux/virtio_config.h>
#include "hw/virtio/virtio_ring.h"
#include <linux/virtio_ring.h>
struct vhost_vring_state {
unsigned int index;
......
obj-y += translate.o helper.o cpu.o interrupt.o
obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o
obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o
obj-$(CONFIG_KVM) += kvm.o
......@@ -77,6 +77,10 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
#define ENV_OFFSET offsetof(S390CPU, env)
#ifndef CONFIG_USER_ONLY
extern const struct VMStateDescription vmstate_s390_cpu;
#endif
void s390_cpu_do_interrupt(CPUState *cpu);
bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
......
......@@ -26,7 +26,9 @@
#include "cpu.h"
#include "qemu-common.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
#include "hw/hw.h"
#include "trace.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/arch_init.h"
#endif
......@@ -81,7 +83,7 @@ static void s390_cpu_load_normal(CPUState *s)
S390CPU *cpu = S390_CPU(s);
cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
s390_add_running_cpu(cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
}
#endif
......@@ -93,11 +95,8 @@ static void s390_cpu_reset(CPUState *s)
CPUS390XState *env = &cpu->env;
env->pfault_token = -1UL;
s390_del_running_cpu(cpu);
scc->parent_reset(s);
#if !defined(CONFIG_USER_ONLY)
s->halted = 1;
#endif
s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
tlb_flush(s, 1);
}
......@@ -118,14 +117,10 @@ static void s390_cpu_initial_reset(CPUState *s)
env->pfault_token = -1UL;
#if defined(CONFIG_KVM)
/* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) {
if (kvm_vcpu_ioctl(s, KVM_S390_INITIAL_RESET, NULL)) {
perror("Initial CPU reset failed");
}
kvm_s390_reset_vcpu(cpu);
}
#endif
}
/* CPUClass:reset() */
......@@ -135,9 +130,8 @@ static void s390_cpu_full_reset(CPUState *s)
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
CPUS390XState *env = &cpu->env;
s390_del_running_cpu(cpu);
scc->parent_reset(s);
s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
memset(env, 0, offsetof(CPUS390XState, cpu_num));
......@@ -147,16 +141,10 @@ static void s390_cpu_full_reset(CPUState *s)
env->pfault_token = -1UL;
/* set halted to 1 to make sure we can add the cpu in
* s390_ipl_cpu code, where CPUState::halted is set back to 0
* after incrementing the cpu counter */
#if !defined(CONFIG_USER_ONLY)
s->halted = 1;
/* Reset state inside the kernel that we cannot access yet from QEMU. */
if (kvm_enabled()) {
kvm_s390_reset_vcpu(cpu);
}
#endif
tlb_flush(s, 1);
}
......@@ -206,10 +194,7 @@ static void s390_cpu_initfn(Object *obj)
env->tod_basetime = 0;
env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
/* set CPUState::halted state to 1 to avoid decrementing the running
* cpu counter in s390_cpu_reset to a negative number at
* initial ipl */
cs->halted = 1;
s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
#endif
env->cpu_num = cpu_num++;
env->ext_index = -1;
......@@ -229,10 +214,83 @@ static void s390_cpu_finalize(Object *obj)
#endif
}
static const VMStateDescription vmstate_s390_cpu = {
.name = "cpu",
.unmigratable = 1,
};
#if !defined(CONFIG_USER_ONLY)
static bool disabled_wait(CPUState *cpu)
{
return cpu->halted && !(S390_CPU(cpu)->env.psw.mask &
(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK));
}
static unsigned s390_count_running_cpus(void)
{
CPUState *cpu;
int nr_running = 0;
CPU_FOREACH(cpu) {
uint8_t state = S390_CPU(cpu)->env.cpu_state;
if (state == CPU_STATE_OPERATING ||
state == CPU_STATE_LOAD) {
if (!disabled_wait(cpu)) {
nr_running++;
}
}
}
return nr_running;
}
unsigned int s390_cpu_halt(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
trace_cpu_halt(cs->cpu_index);
if (!cs->halted) {
cs->halted = 1;
cs->exception_index = EXCP_HLT;
}
return s390_count_running_cpus();
}
void s390_cpu_unhalt(S390CPU *cpu)
{
CPUState *cs = CPU(cpu);
trace_cpu_unhalt(cs->cpu_index);
if (cs->halted) {
cs->halted = 0;
cs->exception_index = -1;
}
}
unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
{
trace_cpu_set_state(CPU(cpu)->cpu_index, cpu_state);
switch (cpu_state) {
case CPU_STATE_STOPPED:
case CPU_STATE_CHECK_STOP:
/* halt the cpu for common infrastructure */
s390_cpu_halt(cpu);
break;
case CPU_STATE_OPERATING:
case CPU_STATE_LOAD:
/* unhalt the cpu for common infrastructure */
s390_cpu_unhalt(cpu);
break;
default:
error_report("Requested CPU state is not a valid S390 CPU state: %u",
cpu_state);
exit(1);
}
if (kvm_enabled() && cpu->env.cpu_state != cpu_state) {
kvm_s390_set_cpu_state(cpu, cpu_state);
}
cpu->env.cpu_state = cpu_state;
return s390_count_running_cpus();
}
#endif
static void s390_cpu_class_init(ObjectClass *oc, void *data)
{
......@@ -260,11 +318,11 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
#else
cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_s390_cpu;
cc->write_elf64_note = s390_cpu_write_elf64_note;
cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote;
cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
#endif
dc->vmsd = &vmstate_s390_cpu;
cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
cc->gdb_core_xml_file = "s390x-core64.xml";
}
......
......@@ -141,6 +141,20 @@ typedef struct CPUS390XState {
QEMUTimer *tod_timer;
QEMUTimer *cpu_timer;
/*
* The cpu state represents the logical state of a cpu. In contrast to other
* architectures, there is a difference between a halt and a stop on s390.
* If all cpus are either stopped (including check stop) or in the disabled
* wait state, the vm can be shut down.
*/
#define CPU_STATE_UNINITIALIZED 0x00
#define CPU_STATE_STOPPED 0x01
#define CPU_STATE_CHECK_STOP 0x02
#define CPU_STATE_OPERATING 0x03
#define CPU_STATE_LOAD 0x04
uint8_t cpu_state;
} CPUS390XState;
#include "cpu-qom.h"
......@@ -375,16 +389,12 @@ int s390_virtio_hypercall(CPUS390XState *env);
void s390_virtio_irq(int config_change, uint64_t token);
#ifdef CONFIG_KVM
void kvm_s390_reset_vcpu(S390CPU *cpu);
void kvm_s390_virtio_irq(int config_change, uint64_t token);
void kvm_s390_service_interrupt(uint32_t parm);
void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
#else
static inline void kvm_s390_reset_vcpu(S390CPU *cpu)
{
}
static inline void kvm_s390_virtio_irq(int config_change, uint64_t token)
{
}
......@@ -393,8 +403,9 @@ static inline void kvm_s390_service_interrupt(uint32_t parm)
}
#endif
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
void s390_add_running_cpu(S390CPU *cpu);
unsigned s390_del_running_cpu(S390CPU *cpu);
unsigned int s390_cpu_halt(S390CPU *cpu);
void s390_cpu_unhalt(S390CPU *cpu);
unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
/* service interrupts are floating therefore we must not pass an cpustate */
void s390_sclp_extint(uint32_t parm);
......@@ -403,11 +414,16 @@ void s390_sclp_extint(uint32_t parm);
extern const hwaddr virtio_size;
#else
static inline void s390_add_running_cpu(S390CPU *cpu)
static inline unsigned int s390_cpu_halt(S390CPU *cpu)
{
return 0;
}
static inline unsigned s390_del_running_cpu(S390CPU *cpu)
static inline void s390_cpu_unhalt(S390CPU *cpu)
{
}
static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
{
return 0;
}
......@@ -1052,6 +1068,8 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
int kvm_s390_cpu_restart(S390CPU *cpu);
int kvm_s390_get_memslot_count(KVMState *s);
void kvm_s390_clear_cmma_callback(void *opaque);
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
void kvm_s390_reset_vcpu(S390CPU *cpu);
#else
static inline void kvm_s390_io_interrupt(uint16_t subchannel_id,
uint16_t subchannel_nr,
......@@ -1082,6 +1100,13 @@ static inline int kvm_s390_get_memslot_count(KVMState *s)
{
return MAX_AVAIL_SLOTS;
}
static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
{
return -ENOSYS;
}
static inline void kvm_s390_reset_vcpu(S390CPU *cpu)
{
}
#endif
static inline void cmma_reset(S390CPU *cpu)
......
......@@ -504,23 +504,18 @@ hwaddr s390_cpu_get_phys_addr_debug(CPUState *cs, vaddr vaddr)
void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
{
env->psw.addr = addr;
env->psw.mask = mask;
env->cc_op = (mask >> 44) & 3;
if (mask & PSW_MASK_WAIT) {
S390CPU *cpu = s390_env_get_cpu(env);
CPUState *cs = CPU(cpu);
if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
if (s390_del_running_cpu(cpu) == 0) {
if (s390_cpu_halt(cpu) == 0) {
#ifndef CONFIG_USER_ONLY
qemu_system_shutdown_request();
qemu_system_shutdown_request();
#endif
}
}
cs->halted = 1;
cs->exception_index = EXCP_HLT;
}
env->psw.addr = addr;
env->psw.mask = mask;
env->cc_op = (mask >> 44) & 3;
}
static uint64_t get_psw_mask(CPUS390XState *env)
......@@ -818,7 +813,7 @@ void s390_cpu_do_interrupt(CPUState *cs)
qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n",
__func__, cs->exception_index, env->psw.addr);
s390_add_running_cpu(cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
/* handle machine checks */
if ((env->psw.mask & PSW_MASK_MCHECK) &&
(cs->exception_index == -1)) {
......
......@@ -181,9 +181,10 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
return cpu->cpu_index;
}
int kvm_arch_init_vcpu(CPUState *cpu)
int kvm_arch_init_vcpu(CPUState *cs)
{
/* nothing todo yet */
S390CPU *cpu = S390_CPU(cs);
kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state);
return 0;
}
......@@ -197,7 +198,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu)
* Before this ioctl cpu_synchronize_state() is called in common kvm
* code (kvm-all) */
if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) {
perror("Can't reset vcpu\n");
error_report("Initial CPU reset failed on CPU %i\n", cs->cpu_index);
}
}
......@@ -921,7 +922,7 @@ static void sigp_cpu_start(void *arg)
CPUState *cs = arg;
S390CPU *cpu = S390_CPU(cs);
s390_add_running_cpu(cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
DPRINTF("DONE: KVM cpu start: %p\n", &cpu->env);
}
......@@ -934,7 +935,7 @@ static void sigp_cpu_restart(void *arg)
};
kvm_s390_vcpu_interrupt(cpu, &irq);
s390_add_running_cpu(cpu);
s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
}
int kvm_s390_cpu_restart(S390CPU *cpu)
......@@ -951,6 +952,7 @@ static void sigp_initial_cpu_reset(void *arg)
cpu_synchronize_state(cpu);
scc->initial_cpu_reset(cpu);
cpu_synchronize_post_reset(cpu);
}
static void sigp_cpu_reset(void *arg)
......@@ -960,6 +962,7 @@ static void sigp_cpu_reset(void *arg)
cpu_synchronize_state(cpu);
scc->cpu_reset(cpu);
cpu_synchronize_post_reset(cpu);
}
#define SIGP_ORDER_MASK 0x000000ff
......@@ -1074,7 +1077,7 @@ static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx",
str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
s390_del_running_cpu(cpu);
s390_cpu_halt(cpu);
guest_panicked();
}
......@@ -1103,7 +1106,8 @@ static int handle_intercept(S390CPU *cpu)
break;
case ICPT_WAITPSW:
/* disabled wait, since enabled wait is handled in kernel */
if (s390_del_running_cpu(cpu) == 0) {
cpu_synchronize_state(cs);
if (s390_cpu_halt(cpu) == 0) {
if (is_special_wait_psw(cs)) {
qemu_system_shutdown_request();
} else {
......@@ -1113,7 +1117,7 @@ static int handle_intercept(S390CPU *cpu)
r = EXCP_HALTED;
break;
case ICPT_CPU_STOP:
if (s390_del_running_cpu(cpu) == 0) {
if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
qemu_system_shutdown_request();
}
r = EXCP_HALTED;
......@@ -1320,3 +1324,41 @@ int kvm_s390_get_memslot_count(KVMState *s)
{
return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
}
int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
{
struct kvm_mp_state mp_state = {};
int ret;
/* the kvm part might not have been initialized yet */
if (CPU(cpu)->kvm_state == NULL) {
return 0;
}
switch (cpu_state) {
case CPU_STATE_STOPPED:
mp_state.mp_state = KVM_MP_STATE_STOPPED;
break;
case CPU_STATE_CHECK_STOP:
mp_state.mp_state = KVM_MP_STATE_CHECK_STOP;
break;
case CPU_STATE_OPERATING:
mp_state.mp_state = KVM_MP_STATE_OPERATING;
break;
case CPU_STATE_LOAD:
mp_state.mp_state = KVM_MP_STATE_LOAD;
break;
default:
error_report("Requested CPU state is not a valid S390 CPU state: %u",
cpu_state);
exit(1);
}
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state);
if (ret) {
trace_kvm_failed_cpu_state_set(CPU(cpu)->cpu_index, cpu_state,
strerror(-ret));
}
return ret;
}
/*
* S390x machine definitions and functions
*
* Copyright IBM Corp. 2014
*
* Authors:
* Thomas Huth <thuth@linux.vnet.ibm.com>
* Christian Borntraeger <borntraeger@de.ibm.com>
* Jason J. Herne <jjherne@us.ibm.com>
*
* This work is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*/
#include "hw/hw.h"
#include "cpu.h"
#include "sysemu/kvm.h"
static int cpu_post_load(void *opaque, int version_id)
{
S390CPU *cpu = opaque;
/*
* As the cpu state is pushed to kvm via kvm_set_mp_state rather
* than via cpu_synchronize_state, we need update kvm here.
*/
if (kvm_enabled()) {
kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state);
}
return 0;
}
const VMStateDescription vmstate_s390_cpu = {
.name = "cpu",
.post_load = cpu_post_load,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT64(env.fregs[0].ll, S390CPU),
VMSTATE_UINT64(env.fregs[1].ll, S390CPU),
VMSTATE_UINT64(env.fregs[2].ll, S390CPU),
VMSTATE_UINT64(env.fregs[3].ll, S390CPU),
VMSTATE_UINT64(env.fregs[4].ll, S390CPU),
VMSTATE_UINT64(env.fregs[5].ll, S390CPU),
VMSTATE_UINT64(env.fregs[6].ll, S390CPU),
VMSTATE_UINT64(env.fregs[7].ll, S390CPU),
VMSTATE_UINT64(env.fregs[8].ll, S390CPU),
VMSTATE_UINT64(env.fregs[9].ll, S390CPU),
VMSTATE_UINT64(env.fregs[10].ll, S390CPU),
VMSTATE_UINT64(env.fregs[11].ll, S390CPU),
VMSTATE_UINT64(env.fregs[12].ll, S390CPU),
VMSTATE_UINT64(env.fregs[13].ll, S390CPU),
VMSTATE_UINT64(env.fregs[14].ll, S390CPU),
VMSTATE_UINT64(env.fregs[15].ll, S390CPU),
VMSTATE_UINT64_ARRAY(env.regs, S390CPU, 16),
VMSTATE_UINT64(env.psw.mask, S390CPU),
VMSTATE_UINT64(env.psw.addr, S390CPU),
VMSTATE_UINT64(env.psa, S390CPU),
VMSTATE_UINT32(env.fpc, S390CPU),
VMSTATE_UINT32(env.todpr, S390CPU),
VMSTATE_UINT64(env.pfault_token, S390CPU),
VMSTATE_UINT64(env.pfault_compare, S390CPU),
VMSTATE_UINT64(env.pfault_select, S390CPU),
VMSTATE_UINT64(env.cputm, S390CPU),
VMSTATE_UINT64(env.ckc, S390CPU),
VMSTATE_UINT64(env.gbea, S390CPU),
VMSTATE_UINT64(env.pp, S390CPU),
VMSTATE_UINT32_ARRAY(env.aregs, S390CPU, 16),
VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16),
VMSTATE_UINT8(env.cpu_state, S390CPU),
VMSTATE_END_OF_LIST()
},
};
......@@ -1369,6 +1369,12 @@ mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
# target-s390x/kvm.c
kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
kvm_clear_cmma(int rc) "CMMA: clearing with result code %d"
kvm_failed_cpu_state_set(int cpu_index, uint8_t state, const char *msg) "Warning: Unable to set cpu %d state %" PRIu8 " to KVM: %s"
# hw/dma/i8257.c
i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d"
# target-s390x/cpu.c
cpu_set_state(int cpu_index, uint8_t state) "setting cpu %d state to %" PRIu8
cpu_halt(int cpu_index) "halting cpu %d"
cpu_unhalt(int cpu_index) "unhalting cpu %d"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册