// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
 */

#include <linux/err.h>
#include <linux/errno.h>
#include <asm/kvm_csr.h>
#include <asm/kvm_vcpu.h>

static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
	[INT_TI]	= CPU_TIMER,
	[INT_IPI]	= CPU_IPI,
	[INT_SWI0]	= CPU_SIP0,
	[INT_SWI1]	= CPU_SIP1,
	[INT_HWI0]	= CPU_IP0,
	[INT_HWI1]	= CPU_IP1,
	[INT_HWI2]	= CPU_IP2,
	[INT_HWI3]	= CPU_IP3,
	[INT_HWI4]	= CPU_IP4,
	[INT_HWI5]	= CPU_IP5,
	[INT_HWI6]	= CPU_IP6,
	[INT_HWI7]	= CPU_IP7,
	[INT_AVEC]	= CPU_AVEC,
};

static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
{
	unsigned int irq = 0;
	unsigned long old, new;

	clear_bit(priority, &vcpu->arch.irq_pending);
	if (priority < EXCCODE_INT_NUM)
		irq = priority_to_irq[priority];

	if (kvm_guest_has_msgint(&vcpu->arch) && (priority == INT_AVEC)) {
		set_gcsr_estat(irq);
		return 1;
	}

	switch (priority) {
	case INT_TI:
	case INT_IPI:
	case INT_SWI0:
	case INT_SWI1:
		old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
		set_gcsr_estat(irq);
		new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);

		/* Inject TI if TVAL inverted */
		if (new > old)
			set_gcsr_estat(CPU_TIMER);
		break;

	case INT_HWI0 ... INT_HWI7:
		set_csr_gintc(irq);
		break;

	default:
		break;
	}

	return 1;
}

static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
{
	unsigned int irq = 0;
	unsigned long old, new;

	clear_bit(priority, &vcpu->arch.irq_clear);
	if (priority < EXCCODE_INT_NUM)
		irq = priority_to_irq[priority];

	if (kvm_guest_has_msgint(&vcpu->arch) && (priority == INT_AVEC)) {
		clear_gcsr_estat(irq);
		return 1;
	}

	switch (priority) {
	case INT_TI:
	case INT_IPI:
	case INT_SWI0:
	case INT_SWI1:
		old = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);
		clear_gcsr_estat(irq);
		new = kvm_read_hw_gcsr(LOONGARCH_CSR_TVAL);

		/* Inject TI if TVAL inverted */
		if (new > old)
			set_gcsr_estat(CPU_TIMER);
		break;

	case INT_HWI0 ... INT_HWI7:
		clear_csr_gintc(irq);
		break;

	default:
		break;
	}

	return 1;
}

void kvm_deliver_intr(struct kvm_vcpu *vcpu)
{
	unsigned int priority;
	unsigned long *pending = &vcpu->arch.irq_pending;
	unsigned long *pending_clr = &vcpu->arch.irq_clear;

	for_each_set_bit(priority, pending_clr, EXCCODE_INT_NUM)
		kvm_irq_clear(vcpu, priority);

	for_each_set_bit(priority, pending, EXCCODE_INT_NUM)
		kvm_irq_deliver(vcpu, priority);
}

int kvm_pending_timer(struct kvm_vcpu *vcpu)
{
	return test_bit(INT_TI, &vcpu->arch.irq_pending);
}

/*
 * Only support illegal instruction or illegal Address Error exception,
 * Other exceptions are injected by hardware in kvm mode
 */
static void _kvm_deliver_exception(struct kvm_vcpu *vcpu,
				unsigned int code, unsigned int subcode)
{
	unsigned long val, vec_size;

	/*
	 * BADV is added for EXCCODE_ADE exception
	 *  Use PC register (GVA address) if it is instruction exeception
	 *  Else use BADV from host side (GPA address) for data exeception
	 */
	if (code == EXCCODE_ADE) {
		if (subcode == EXSUBCODE_ADEF)
			val = vcpu->arch.pc;
		else
			val = vcpu->arch.badv;
		kvm_write_hw_gcsr(LOONGARCH_CSR_BADV, val);
	}

	/* Set exception instruction */
	kvm_write_hw_gcsr(LOONGARCH_CSR_BADI, vcpu->arch.badi);

	/*
	 * Save CRMD in PRMD
	 * Set IRQ disabled and PLV0 with CRMD
	 */
	val = kvm_read_hw_gcsr(LOONGARCH_CSR_CRMD);
	kvm_write_hw_gcsr(LOONGARCH_CSR_PRMD, val);
	val = val & ~(CSR_CRMD_PLV | CSR_CRMD_IE);
	kvm_write_hw_gcsr(LOONGARCH_CSR_CRMD, val);

	/* Set exception PC address */
	kvm_write_hw_gcsr(LOONGARCH_CSR_ERA, vcpu->arch.pc);

	/*
	 * Set exception code
	 * Exception and interrupt can be inject at the same time
	 * Hardware will handle exception first and then extern interrupt
	 * Exception code is Ecode in ESTAT[16:21]
	 * Interrupt code in ESTAT[0:12]
	 */
	val = kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT);
	val = (val & ~CSR_ESTAT_EXC) | code;
	kvm_write_hw_gcsr(LOONGARCH_CSR_ESTAT, val);

	/* Calculate expcetion entry address */
	val = kvm_read_hw_gcsr(LOONGARCH_CSR_ECFG);
	vec_size = (val & CSR_ECFG_VS) >> CSR_ECFG_VS_SHIFT;
	if (vec_size)
		vec_size = (1 << vec_size) * 4;
	val =  kvm_read_hw_gcsr(LOONGARCH_CSR_EENTRY);
	vcpu->arch.pc = val + code * vec_size;
}

void kvm_deliver_exception(struct kvm_vcpu *vcpu)
{
	unsigned int code;
	unsigned long *pending = &vcpu->arch.exception_pending;

	if (*pending) {
		code = __ffs(*pending);
		_kvm_deliver_exception(vcpu, code, vcpu->arch.esubcode);
		*pending = 0;
		vcpu->arch.esubcode = 0;
	}
}
