/*
 * Copyright (C) 2015 - ARM Ltd
 * Author: Marc Zyngier <marc.zyngier@arm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <linux/jump_label.h>

#include <asm/kvm_asm.h>
#include <asm/kvm_hyp.h>

__asm__(".arch_extension     virt");

/*
 * Activate the traps, saving the host's fpexc register before
 * overwriting it. We'll restore it on VM exit.
 */
static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
{
	u32 val;

	/*
	 * We are about to set HCPTR.TCP10/11 to trap all floating point
	 * register accesses to HYP, however, the ARM ARM clearly states that
	 * traps are only taken to HYP if the operation would not otherwise
	 * trap to SVC.  Therefore, always make sure that for 32-bit guests,
	 * we set FPEXC.EN to prevent traps to SVC, when setting the TCP bits.
	 */
	val = read_sysreg(VFP_FPEXC);
	*fpexc_host = val;
	if (!(val & FPEXC_EN)) {
		write_sysreg(val | FPEXC_EN, VFP_FPEXC);
		isb();
	}

	write_sysreg(vcpu->arch.hcr | vcpu->arch.irq_lines, HCR);
	/* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
	write_sysreg(HSTR_T(15), HSTR);
	write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
	val = read_sysreg(HDCR);
	write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR);
}

static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
{
	u32 val;

	/*
	 * If we pended a virtual abort, preserve it until it gets
	 * cleared. See B1.9.9 (Virtual Abort exception) for details,
	 * but the crucial bit is the zeroing of HCR.VA in the
	 * pseudocode.
	 */
	if (vcpu->arch.hcr & HCR_VA)
		vcpu->arch.hcr = read_sysreg(HCR);

	write_sysreg(0, HCR);
	write_sysreg(0, HSTR);
	val = read_sysreg(HDCR);
	write_sysreg(val & ~(HDCR_TPM | HDCR_TPMCR), HDCR);
	write_sysreg(0, HCPTR);
}

static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
{
	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
	write_sysreg(kvm->arch.vttbr, VTTBR);
	write_sysreg(vcpu->arch.midr, VPIDR);
}

static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
{
	write_sysreg(0, VTTBR);
	write_sysreg(read_sysreg(MIDR), VPIDR);
}


static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu)
{
	if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
		__vgic_v3_save_state(vcpu);
	else
		__vgic_v2_save_state(vcpu);
}

static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
{
	if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
		__vgic_v3_restore_state(vcpu);
	else
		__vgic_v2_restore_state(vcpu);
}

static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
{
	u32 hsr = read_sysreg(HSR);
	u8 ec = hsr >> HSR_EC_SHIFT;
	u32 hpfar, far;

	vcpu->arch.fault.hsr = hsr;

	if (ec == HSR_EC_IABT)
		far = read_sysreg(HIFAR);
	else if (ec == HSR_EC_DABT)
		far = read_sysreg(HDFAR);
	else
		return true;

	/*
	 * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
	 *
	 * Abort on the stage 2 translation for a memory access from a
	 * Non-secure PL1 or PL0 mode:
	 *
	 * For any Access flag fault or Translation fault, and also for any
	 * Permission fault on the stage 2 translation of a memory access
	 * made as part of a translation table walk for a stage 1 translation,
	 * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
	 * is UNKNOWN.
	 */
	if (!(hsr & HSR_DABT_S1PTW) && (hsr & HSR_FSC_TYPE) == FSC_PERM) {
		u64 par, tmp;

		par = read_sysreg(PAR);
		write_sysreg(far, ATS1CPR);
		isb();

		tmp = read_sysreg(PAR);
		write_sysreg(par, PAR);

		if (unlikely(tmp & 1))
			return false; /* Translation failed, back to guest */

		hpfar = ((tmp >> 12) & ((1UL << 28) - 1)) << 4;
	} else {
		hpfar = read_sysreg(HPFAR);
	}

	vcpu->arch.fault.hxfar = far;
	vcpu->arch.fault.hpfar = hpfar;
	return true;
}

int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
{
	struct kvm_cpu_context *host_ctxt;
	struct kvm_cpu_context *guest_ctxt;
	bool fp_enabled;
	u64 exit_code;
	u32 fpexc;

	vcpu = kern_hyp_va(vcpu);
	write_sysreg(vcpu, HTPIDR);

	host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
	guest_ctxt = &vcpu->arch.ctxt;

	__sysreg_save_state(host_ctxt);
	__banked_save_state(host_ctxt);

	__activate_traps(vcpu, &fpexc);
	__activate_vm(vcpu);

	__vgic_restore_state(vcpu);
	__timer_restore_state(vcpu);

	__sysreg_restore_state(guest_ctxt);
	__banked_restore_state(guest_ctxt);

	/* Jump in the fire! */
again:
	exit_code = __guest_enter(vcpu, host_ctxt);
	/* And we're baaack! */

	if (exit_code == ARM_EXCEPTION_HVC && !__populate_fault_info(vcpu))
		goto again;

	fp_enabled = __vfp_enabled();

	__banked_save_state(guest_ctxt);
	__sysreg_save_state(guest_ctxt);
	__timer_save_state(vcpu);
	__vgic_save_state(vcpu);

	__deactivate_traps(vcpu);
	__deactivate_vm(vcpu);

	__banked_restore_state(host_ctxt);
	__sysreg_restore_state(host_ctxt);

	if (fp_enabled) {
		__vfp_save_state(&guest_ctxt->vfp);
		__vfp_restore_state(&host_ctxt->vfp);
	}

	write_sysreg(fpexc, VFP_FPEXC);

	return exit_code;
}

static const char * const __hyp_panic_string[] = {
	[ARM_EXCEPTION_RESET]      = "\nHYP panic: RST   PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_UNDEFINED]  = "\nHYP panic: UNDEF PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_SOFTWARE]   = "\nHYP panic: SVC   PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_PREF_ABORT] = "\nHYP panic: PABRT PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_DATA_ABORT] = "\nHYP panic: DABRT PC:%08x ADDR:%08x",
	[ARM_EXCEPTION_IRQ]        = "\nHYP panic: IRQ   PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_FIQ]        = "\nHYP panic: FIQ   PC:%08x CPSR:%08x",
	[ARM_EXCEPTION_HVC]        = "\nHYP panic: HVC   PC:%08x CPSR:%08x",
};

void __hyp_text __noreturn __hyp_panic(int cause)
{
	u32 elr = read_special(ELR_hyp);
	u32 val;

	if (cause == ARM_EXCEPTION_DATA_ABORT)
		val = read_sysreg(HDFAR);
	else
		val = read_special(SPSR);

	if (read_sysreg(VTTBR)) {
		struct kvm_vcpu *vcpu;
		struct kvm_cpu_context *host_ctxt;

		vcpu = (struct kvm_vcpu *)read_sysreg(HTPIDR);
		host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
		__deactivate_traps(vcpu);
		__deactivate_vm(vcpu);
		__sysreg_restore_state(host_ctxt);
	}

	/* Call panic for real */
	__hyp_do_panic(__hyp_panic_string[cause], elr, val);

	unreachable();
}
