/*
 * 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/compiler.h>
#include <linux/kvm_host.h>

#include <asm/debug-monitors.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_hyp.h>

#define read_debug(r,n)		read_sysreg(r##n##_el1)
#define write_debug(v,r,n)	write_sysreg(v, r##n##_el1)

#define save_debug(ptr,reg,nr)						\
	switch (nr) {							\
	case 15:	ptr[15] = read_debug(reg, 15);			\
	case 14:	ptr[14] = read_debug(reg, 14);			\
	case 13:	ptr[13] = read_debug(reg, 13);			\
	case 12:	ptr[12] = read_debug(reg, 12);			\
	case 11:	ptr[11] = read_debug(reg, 11);			\
	case 10:	ptr[10] = read_debug(reg, 10);			\
	case 9:		ptr[9] = read_debug(reg, 9);			\
	case 8:		ptr[8] = read_debug(reg, 8);			\
	case 7:		ptr[7] = read_debug(reg, 7);			\
	case 6:		ptr[6] = read_debug(reg, 6);			\
	case 5:		ptr[5] = read_debug(reg, 5);			\
	case 4:		ptr[4] = read_debug(reg, 4);			\
	case 3:		ptr[3] = read_debug(reg, 3);			\
	case 2:		ptr[2] = read_debug(reg, 2);			\
	case 1:		ptr[1] = read_debug(reg, 1);			\
	default:	ptr[0] = read_debug(reg, 0);			\
	}

#define restore_debug(ptr,reg,nr)					\
	switch (nr) {							\
	case 15:	write_debug(ptr[15], reg, 15);			\
	case 14:	write_debug(ptr[14], reg, 14);			\
	case 13:	write_debug(ptr[13], reg, 13);			\
	case 12:	write_debug(ptr[12], reg, 12);			\
	case 11:	write_debug(ptr[11], reg, 11);			\
	case 10:	write_debug(ptr[10], reg, 10);			\
	case 9:		write_debug(ptr[9], reg, 9);			\
	case 8:		write_debug(ptr[8], reg, 8);			\
	case 7:		write_debug(ptr[7], reg, 7);			\
	case 6:		write_debug(ptr[6], reg, 6);			\
	case 5:		write_debug(ptr[5], reg, 5);			\
	case 4:		write_debug(ptr[4], reg, 4);			\
	case 3:		write_debug(ptr[3], reg, 3);			\
	case 2:		write_debug(ptr[2], reg, 2);			\
	case 1:		write_debug(ptr[1], reg, 1);			\
	default:	write_debug(ptr[0], reg, 0);			\
	}

static void __hyp_text __debug_save_spe_vhe(u64 *pmscr_el1)
{
	/* The vcpu can run. but it can't hide. */
}

static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1)
{
	u64 reg;

	/* SPE present on this CPU? */
	if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
						  ID_AA64DFR0_PMSVER_SHIFT))
		return;

	/* Yes; is it owned by EL3? */
	reg = read_sysreg_s(SYS_PMBIDR_EL1);
	if (reg & BIT(SYS_PMBIDR_EL1_P_SHIFT))
		return;

	/* No; is the host actually using the thing? */
	reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
	if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)))
		return;

	/* Yes; save the control register and disable data generation */
	*pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1);
	write_sysreg_s(0, SYS_PMSCR_EL1);
	isb();

	/* Now drain all buffered data to memory */
	psb_csync();
	dsb(nsh);
}

static hyp_alternate_select(__debug_save_spe,
			    __debug_save_spe_nvhe, __debug_save_spe_vhe,
			    ARM64_HAS_VIRT_HOST_EXTN);

static void __hyp_text __debug_restore_spe(u64 pmscr_el1)
{
	if (!pmscr_el1)
		return;

	/* The host page table is installed, but not yet synchronised */
	isb();

	/* Re-enable data generation */
	write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
}

void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
				   struct kvm_guest_debug_arch *dbg,
				   struct kvm_cpu_context *ctxt)
{
	u64 aa64dfr0;
	int brps, wrps;

	if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
		return;

	aa64dfr0 = read_sysreg(id_aa64dfr0_el1);
	brps = (aa64dfr0 >> 12) & 0xf;
	wrps = (aa64dfr0 >> 20) & 0xf;

	save_debug(dbg->dbg_bcr, dbgbcr, brps);
	save_debug(dbg->dbg_bvr, dbgbvr, brps);
	save_debug(dbg->dbg_wcr, dbgwcr, wrps);
	save_debug(dbg->dbg_wvr, dbgwvr, wrps);

	ctxt->sys_regs[MDCCINT_EL1] = read_sysreg(mdccint_el1);
}

void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
				      struct kvm_guest_debug_arch *dbg,
				      struct kvm_cpu_context *ctxt)
{
	u64 aa64dfr0;
	int brps, wrps;

	if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
		return;

	aa64dfr0 = read_sysreg(id_aa64dfr0_el1);

	brps = (aa64dfr0 >> 12) & 0xf;
	wrps = (aa64dfr0 >> 20) & 0xf;

	restore_debug(dbg->dbg_bcr, dbgbcr, brps);
	restore_debug(dbg->dbg_bvr, dbgbvr, brps);
	restore_debug(dbg->dbg_wcr, dbgwcr, wrps);
	restore_debug(dbg->dbg_wvr, dbgwvr, wrps);

	write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1);
}

void __hyp_text __debug_cond_save_host_state(struct kvm_vcpu *vcpu)
{
	/* If any of KDE, MDE or KVM_ARM64_DEBUG_DIRTY is set, perform
	 * a full save/restore cycle. */
	if ((vcpu->arch.ctxt.sys_regs[MDSCR_EL1] & DBG_MDSCR_KDE) ||
	    (vcpu->arch.ctxt.sys_regs[MDSCR_EL1] & DBG_MDSCR_MDE))
		vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;

	__debug_save_state(vcpu, &vcpu->arch.host_debug_state.regs,
			   kern_hyp_va(vcpu->arch.host_cpu_context));
	__debug_save_spe()(&vcpu->arch.host_debug_state.pmscr_el1);
}

void __hyp_text __debug_cond_restore_host_state(struct kvm_vcpu *vcpu)
{
	__debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
	__debug_restore_state(vcpu, &vcpu->arch.host_debug_state.regs,
			      kern_hyp_va(vcpu->arch.host_cpu_context));

	if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
		vcpu->arch.debug_flags &= ~KVM_ARM64_DEBUG_DIRTY;
}

u32 __hyp_text __kvm_get_mdcr_el2(void)
{
	return read_sysreg(mdcr_el2);
}
