Beispiel #1
0
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
{
    struct kvm *kvm = source_vcpu->kvm;
    struct kvm_vcpu *vcpu = NULL;
    wait_queue_head_t *wq;
    unsigned long cpu_id;
    unsigned long context_id;
    phys_addr_t target_pc;

    cpu_id = *vcpu_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK;
    if (vcpu_mode_is_32bit(source_vcpu))
        cpu_id &= ~((u32) 0);

    vcpu = kvm_mpidr_to_vcpu(kvm, cpu_id);

    /*
     * Make sure the caller requested a valid CPU and that the CPU is
     * turned off.
     */
    if (!vcpu)
        return PSCI_RET_INVALID_PARAMS;
    if (!vcpu->arch.power_off) {
        if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
            return PSCI_RET_ALREADY_ON;
        else
            return PSCI_RET_INVALID_PARAMS;
    }

    target_pc = *vcpu_reg(source_vcpu, 2);
    context_id = *vcpu_reg(source_vcpu, 3);

    kvm_reset_vcpu(vcpu);

    /* Gracefully handle Thumb2 entry point */
    if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
        target_pc &= ~((phys_addr_t) 1);
        vcpu_set_thumb(vcpu);
    }

    /* Propagate caller endianness */
    if (kvm_vcpu_is_be(source_vcpu))
        kvm_vcpu_set_be(vcpu);

    *vcpu_pc(vcpu) = target_pc;
    /*
     * NOTE: We always update r0 (or x0) because for PSCI v0.1
     * the general puspose registers are undefined upon CPU_ON.
     */
    *vcpu_reg(vcpu, 0) = context_id;
    vcpu->arch.power_off = false;
    smp_mb();		/* Make sure the above is visible */

    wq = kvm_arch_vcpu_wq(vcpu);
    wake_up_interruptible(wq);

    return PSCI_RET_SUCCESS;
}
Beispiel #2
0
int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
		       struct vgic_reg_attr *reg_attr)
{
	unsigned long vgic_mpidr, mpidr_reg;

	/*
	 * For KVM_DEV_ARM_VGIC_GRP_DIST_REGS group,
	 * attr might not hold MPIDR. Hence assume vcpu0.
	 */
	if (attr->group != KVM_DEV_ARM_VGIC_GRP_DIST_REGS) {
		vgic_mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
			      KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;

		mpidr_reg = VGIC_TO_MPIDR(vgic_mpidr);
		reg_attr->vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr_reg);
	} else {