blob: 122125f7f8d4734382f838d1d0a4fb71e8c1cf0a [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 MediaTek Inc.
*/
#include <linux/irqchip/arm-gic-v3.h>
#include <linux/gzvm.h>
#include <linux/gzvm_drv.h>
#include "gzvm_arch_common.h"
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev)
{
struct arm_smccc_res res;
return gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_DEVICE, vm_id,
virt_to_phys(gzvm_dev), 0, 0, 0, 0, 0,
&res);
}
/**
* gzvm_arch_inject_irq() - Inject virtual interrupt to a VM
* @gzvm: Pointer to struct gzvm
* @vcpu_idx: vcpu index, only valid if PPI
* @irq: *SPI* irq number (excluding offset value `32`)
* @level: 1 if true else 0
*
* Return:
* * 0 - Success.
* * Negative - Failure.
*/
int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq, bool level)
{
unsigned long a1 = assemble_vm_vcpu_tuple(gzvm->vm_id, vcpu_idx);
struct arm_smccc_res res;
/*
* VMM's virtual device irq number starts from 0, but ARM's shared peripheral
* interrupt number starts from 32. hypervisor adds offset 32
*/
gzvm_hypcall_wrapper(MT_HVC_GZVM_IRQ_LINE, a1, irq, level,
0, 0, 0, 0, &res);
if (res.a0) {
pr_err("Failed to set IRQ level (%d) to irq#%u on vcpu %d with ret=%d\n",
level, irq, vcpu_idx, (int)res.a0);
return -EFAULT;
}
return 0;
}