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; }
static bool __hyp_text __is_be(struct kvm_vcpu *vcpu) { if (vcpu_mode_is_32bit(vcpu)) return !!(read_sysreg_el2(spsr) & PSR_AA32_E_BIT); return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE); }
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) { struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu; wait_queue_head_t *wq; unsigned long cpu_id; phys_addr_t target_pc; cpu_id = *vcpu_reg(source_vcpu, 1); if (vcpu_mode_is_32bit(source_vcpu)) cpu_id &= ~((u32) 0); if (cpu_id >= atomic_read(&kvm->online_vcpus)) return KVM_PSCI_RET_INVAL; target_pc = *vcpu_reg(source_vcpu, 2); vcpu = kvm_get_vcpu(kvm, cpu_id); wq = kvm_arch_vcpu_wq(vcpu); if (!waitqueue_active(wq)) return KVM_PSCI_RET_INVAL; 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); } *vcpu_pc(vcpu) = target_pc; vcpu->arch.pause = false; smp_mb(); /* Make sure the above is visible */ wake_up_interruptible(wq); return KVM_PSCI_RET_SUCCESS; }
static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) { struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL, *tmp; wait_queue_head_t *wq; unsigned long cpu_id; unsigned long context_id; unsigned long mpidr; phys_addr_t target_pc; int i; cpu_id = *vcpu_reg(source_vcpu, 1); if (vcpu_mode_is_32bit(source_vcpu)) cpu_id &= ~((u32) 0); kvm_for_each_vcpu(i, tmp, kvm) { mpidr = kvm_vcpu_get_mpidr(tmp); if ((mpidr & MPIDR_HWID_BITMASK) == (cpu_id & MPIDR_HWID_BITMASK)) { vcpu = tmp; break; } }