* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <sys/types.h>
+#include "qemu/osdep.h"
#include <sys/ioctl.h>
#include <sys/mman.h>
return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
}
-void kvm_s390_clear_cmma_callback(void *opaque)
+void kvm_s390_cmma_reset(void)
{
int rc;
- KVMState *s = opaque;
struct kvm_device_attr attr = {
.group = KVM_S390_VM_MEM_CTRL,
.attr = KVM_S390_VM_MEM_CLR_CMMA,
};
- rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
+ rc = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
trace_kvm_clear_cmma(rc);
}
}
rc = kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
- if (!rc) {
- qemu_register_reset(kvm_s390_clear_cmma_callback, s);
- }
trace_kvm_enable_cmma(rc);
}
}
}
-static void kvm_s390_init_crypto(void)
+void kvm_s390_crypto_reset(void)
{
kvm_s390_init_aes_kw();
kvm_s390_init_dea_kw();
cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
- kvm_s390_enable_cmma(s);
+ if (!mem_path) {
+ kvm_s390_enable_cmma(s);
+ }
if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {
if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) {
error_report("Initial CPU reset failed on CPU %i", cs->cpu_index);
}
-
- kvm_s390_init_crypto();
}
static int can_sync_regs(CPUState *cs, int regs)
}
cs->kvm_run->s.regs.fpc = env->fpc;
cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_VRS;
+ } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
+ for (i = 0; i < 16; i++) {
+ cs->kvm_run->s.regs.fprs[i] = get_freg(env, i)->ll;
+ }
+ cs->kvm_run->s.regs.fpc = env->fpc;
+ cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_FPRS;
} else {
/* Floating point */
for (i = 0; i < 16; i++) {
env->vregs[i][1].ll = cs->kvm_run->s.regs.vrs[i][1];
}
env->fpc = cs->kvm_run->s.regs.fpc;
+ } else if (can_sync_regs(cs, KVM_SYNC_FPRS)) {
+ for (i = 0; i < 16; i++) {
+ get_freg(env, i)->ll = cs->kvm_run->s.regs.fprs[i];
+ }
+ env->fpc = cs->kvm_run->s.regs.fpc;
} else {
r = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
if (r < 0) {
* @addr: the logical start address in guest memory
* @ar: the access register number
* @hostbuf: buffer in host memory. NULL = do only checks w/o copying
- * @len: length that should be transfered
+ * @len: length that should be transferred
* @is_write: true = write, false = read
- * Returns: 0 on success, non-zero if an exception or error occured
+ * Returns: 0 on success, non-zero if an exception or error occurred
*
* Use KVM ioctl to read/write from/to guest memory. An access exception
* is injected into the vCPU in case of translation errors.
__kvm_s390_floating_interrupt(irq);
}
-void kvm_s390_virtio_irq(int config_change, uint64_t token)
-{
- struct kvm_s390_irq irq = {
- .type = KVM_S390_INT_VIRTIO,
- .u.ext.ext_params = config_change,
- .u.ext.ext_params2 = token,
- };
-
- kvm_s390_floating_interrupt(&irq);
-}
-
void kvm_s390_service_interrupt(uint32_t parm)
{
struct kvm_s390_irq irq = {
cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1);
}
for (i = 0; i < 16; ++i) {
- *((uint64 *)mem + i) = get_freg(&cpu->env, i)->ll;
+ *((uint64_t *)mem + i) = get_freg(&cpu->env, i)->ll;
}
memcpy(mem + 128, &cpu->env.regs, 128);
memcpy(mem + 256, &cpu->env.psw, 16);
return cs->kvm_run->psw_addr == 0xfffUL;
}
-static void guest_panicked(void)
-{
- qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
- &error_abort);
- vm_stop(RUN_STATE_GUEST_PANICKED);
-}
-
static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset)
{
CPUState *cs = CPU(cpu);
str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset),
ldq_phys(cs->as, cpu->env.psa + pswoffset + 8));
s390_cpu_halt(cpu);
- guest_panicked();
+ qemu_system_guest_panicked();
}
static int handle_intercept(S390CPU *cpu)
if (is_special_wait_psw(cs)) {
qemu_system_shutdown_request();
} else {
- guest_panicked();
+ qemu_system_guest_panicked();
}
}
r = EXCP_HALTED;
kvm_s390_floating_interrupt(&irq);
}
+static uint64_t build_channel_report_mcic(void)
+{
+ uint64_t mcic;
+
+ /* subclass: indicate channel report pending */
+ mcic = MCIC_SC_CP |
+ /* subclass modifiers: none */
+ /* storage errors: none */
+ /* validity bits: no damage */
+ MCIC_VB_WP | MCIC_VB_MS | MCIC_VB_PM | MCIC_VB_IA | MCIC_VB_FP |
+ MCIC_VB_GR | MCIC_VB_CR | MCIC_VB_ST | MCIC_VB_AR | MCIC_VB_PR |
+ MCIC_VB_FC | MCIC_VB_CT | MCIC_VB_CC;
+ if (kvm_check_extension(kvm_state, KVM_CAP_S390_VECTOR_REGISTERS)) {
+ mcic |= MCIC_VB_VR;
+ }
+ return mcic;
+}
+
void kvm_s390_crw_mchk(void)
{
struct kvm_s390_irq irq = {
.type = KVM_S390_MCHK,
.u.mchk.cr14 = 1 << 28,
- .u.mchk.mcic = 0x00400f1d40330000ULL,
+ .u.mchk.mcic = build_channel_report_mcic(),
};
kvm_s390_floating_interrupt(&irq);
}
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
S390PCIBusDevice *pbdev;
uint32_t fid = data >> ZPCI_MSI_VEC_BITS;