Beispiel #1
0
static int handle_set_prefix(struct kvm_vcpu *vcpu)
{
	u64 operand2;
	u32 address = 0;
	u8 tmp;

	vcpu->stat.instruction_spx++;

	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);

	operand2 = kvm_s390_get_base_disp_s(vcpu);

	/* must be word boundary */
	if (operand2 & 3)
		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);

	/* get the value */
	if (get_guest(vcpu, address, (u32 __user *) operand2))
		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);

	address = address & 0x7fffe000u;

	/* make sure that the new value is valid memory */
	if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
	   (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)))
		return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);

	kvm_s390_set_prefix(vcpu, address);

	VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
	trace_kvm_s390_handle_prefix(vcpu, 1, address);
	return 0;
}
Beispiel #2
0
static int handle_set_prefix(struct kvm_vcpu *vcpu)
{
	int base2 = vcpu->arch.sie_block->ipb >> 28;
	int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
	u64 operand2;
	u32 address = 0;
	u8 tmp;

	vcpu->stat.instruction_spx++;

	operand2 = disp2;
	if (base2)
		operand2 += vcpu->run->s.regs.gprs[base2];

	/* must be word boundary */
	if (operand2 & 3) {
		kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
		goto out;
	}

	/* get the value */
	if (get_guest_u32(vcpu, operand2, &address)) {
		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
		goto out;
	}

	address = address & 0x7fffe000u;

	/* make sure that the new value is valid memory */
	if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
	   (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) {
		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
		goto out;
	}

	kvm_s390_set_prefix(vcpu, address);

	VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
out:
	return 0;
}
Beispiel #3
0
static int handle_set_prefix(struct kvm_vcpu *vcpu)
{
	u64 operand2;
	u32 address = 0;
	u8 tmp;

	vcpu->stat.instruction_spx++;

	operand2 = kvm_s390_get_base_disp_s(vcpu);

	/* must be word boundary */
	if (operand2 & 3) {
		kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
		goto out;
	}

	/* get the value */
	if (get_guest_u32(vcpu, operand2, &address)) {
		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
		goto out;
	}

	address = address & 0x7fffe000u;

	/* make sure that the new value is valid memory */
	if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
	   (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) {
		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
		goto out;
	}

	kvm_s390_set_prefix(vcpu, address);

	VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
	trace_kvm_s390_handle_prefix(vcpu, 1, address);
out:
	return 0;
}
Beispiel #4
0
static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                                   struct kvm_s390_interrupt_info *inti)
{
    const unsigned short table[] = { 2, 4, 4, 6 };
    int rc, exception = 0;

    switch (inti->type) {
    case KVM_S390_INT_EMERGENCY:
        VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
        vcpu->stat.deliver_emergency_signal++;
        rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, inti->emerg.code);
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;
        break;

    case KVM_S390_INT_EXTERNAL_CALL:
        VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
        vcpu->stat.deliver_external_call++;
        rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, inti->extcall.code);
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;
        break;

    case KVM_S390_INT_SERVICE:
        VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
                   inti->ext.ext_params);
        vcpu->stat.deliver_service_signal++;
        rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
        if (rc == -EFAULT)
            exception = 1;
        break;

    case KVM_S390_INT_VIRTIO:
        VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
                   inti->ext.ext_params, inti->ext.ext_params2);
        vcpu->stat.deliver_virtio_interrupt++;
        rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u16(vcpu, __LC_EXT_CPU_ADDR, 0x0d00);
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             __LC_EXT_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u32(vcpu, __LC_EXT_PARAMS, inti->ext.ext_params);
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u64(vcpu, __LC_EXT_PARAMS2,
                           inti->ext.ext_params2);
        if (rc == -EFAULT)
            exception = 1;
        break;

    case KVM_S390_SIGP_STOP:
        VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
        vcpu->stat.deliver_stop_signal++;
        __set_intercept_indicator(vcpu, inti);
        break;

    case KVM_S390_SIGP_SET_PREFIX:
        VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
                   inti->prefix.address);
        vcpu->stat.deliver_prefix_signal++;
        kvm_s390_set_prefix(vcpu, inti->prefix.address);
        break;

    case KVM_S390_RESTART:
        VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
        vcpu->stat.deliver_restart_signal++;
        rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
                                          restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;
        atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
        break;

    case KVM_S390_PROGRAM_INT:
        VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
                   inti->pgm.code,
                   table[vcpu->arch.sie_block->ipa >> 14]);
        vcpu->stat.deliver_program_int++;
        rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
        if (rc == -EFAULT)
            exception = 1;

        rc = put_guest_u16(vcpu, __LC_PGM_ILC,
                           table[vcpu->arch.sie_block->ipa >> 14]);
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_to_guest(vcpu, __LC_PGM_OLD_PSW,
                           &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;

        rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw,
                             __LC_PGM_NEW_PSW, sizeof(psw_t));
        if (rc == -EFAULT)
            exception = 1;
        break;

    default:
        BUG();
    }
    if (exception) {
        printk("kvm: The guest lowcore is not mapped during interrupt "
               "delivery, killing userspace\n");
        do_exit(SIGKILL);
    }
}