ANDROID: virt: geniezone: Refactoring vgic to align with upstream v6

Refactor the implementation of virtual gic as below.
- Remove the codes related to vgic ppi because the virtual interrupt
  injection interface is only exposed to VMM which does peripheral
  device emulation, we can assume only spi is used.
- Simplify the api for virtual interrupt injection.

Change-Id: I18ece99f8a678b72483a93ab47b080871d2bb81c
Signed-off-by: kevenny hsieh <kevenny.hsieh@mediatek.com>
Signed-off-by: Yingshiuan Pan <yingshiuan.pan@mediatek.com>
Signed-off-by: Liju-Clr Chen <liju-clr.chen@mediatek.com>
Signed-off-by: Yi-De Wu <yi-de.wu@mediatek.com>
Bug: 301179926
Link: https://lore.kernel.org/all/20230919111210.19615-9-yi-de.wu@mediatek.com/
This commit is contained in:
Yi-De Wu 2023-08-21 16:52:30 +08:00 committed by Todd Kjos
parent f9291d7af0
commit 544b128747
9 changed files with 24 additions and 116 deletions

View File

@ -8,60 +8,36 @@
#include <linux/gzvm_drv.h>
#include "gzvm_arch_common.h"
/**
* is_irq_valid() - Check the irq number and irq_type are matched
* @irq: interrupt number
* @irq_type: interrupt type
*
* Return:
* true if irq is valid else false.
*/
static bool is_irq_valid(u32 irq, u32 irq_type)
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev)
{
switch (irq_type) {
case GZVM_IRQ_TYPE_CPU:
/* 0 ~ 15: SGI */
if (likely(irq <= GZVM_IRQ_CPU_FIQ))
return true;
break;
case GZVM_IRQ_TYPE_PPI:
/* 16 ~ 31: PPI */
if (likely(irq >= GZVM_VGIC_NR_SGIS &&
irq < GZVM_VGIC_NR_PRIVATE_IRQS))
return true;
break;
case GZVM_IRQ_TYPE_SPI:
/* 32 ~ : SPT */
if (likely(irq >= GZVM_VGIC_NR_PRIVATE_IRQS))
return true;
break;
default:
return false;
}
return false;
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_vgic_inject_irq() - Inject virtual interrupt to a VM
* gzvm_arch_inject_irq() - Inject virtual interrupt to a VM
* @gzvm: Pointer to struct gzvm
* @vcpu_idx: vcpu index, only valid if PPI
* @irq_type: Interrupt type
* @irq: irq number
* @irq: *SPI* irq number (excluding offset value `32`)
* @level: 1 if true else 0
*
* Return:
* * 0 - Success.
* * Negative - Failure.
*/
static int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq_type, u32 irq, bool level)
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;
if (!unlikely(is_irq_valid(irq, irq_type)))
return -EINVAL;
/*
* 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) {
@ -72,37 +48,3 @@ static int gzvm_vgic_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
return 0;
}
/**
* gzvm_vgic_inject_spi() - Inject virtual spi interrupt
* @gzvm: Pointer to struct gzvm
* @vcpu_idx: vcpu index
* @spi_irq: This is spi interrupt number (starts from 0 instead of 32)
* @level: 1 if true else 0
*
* Return:
* * 0 if succeed else other negative values indicating each errors
*/
static int gzvm_vgic_inject_spi(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 spi_irq, bool level)
{
return gzvm_vgic_inject_irq(gzvm, 0, GZVM_IRQ_TYPE_SPI,
spi_irq + GZVM_VGIC_NR_PRIVATE_IRQS,
level);
}
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);
}
int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq_type, u32 irq, bool level)
{
/* default use spi */
return gzvm_vgic_inject_spi(gzvm, vcpu_idx, irq, level);
}

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2023 MediaTek Inc.
*/
#ifndef __GZVM_ARCH_H__
#define __GZVM_ARCH_H__
#include <linux/types.h>
#define GZVM_VGIC_NR_SGIS 16
#define GZVM_VGIC_NR_PPIS 16
#define GZVM_VGIC_NR_PRIVATE_IRQS (GZVM_VGIC_NR_SGIS + GZVM_VGIC_NR_PPIS)
#endif /* __GZVM_ARCH_H__ */

View File

@ -7,6 +7,6 @@
#define __GZ_COMMON_H__
int gzvm_irqchip_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq_type, u32 irq, bool level);
u32 irq, bool level);
#endif /* __GZVM_COMMON_H__ */

View File

@ -39,18 +39,15 @@ struct gzvm_kernel_irqfd {
static struct workqueue_struct *irqfd_cleanup_wq;
/**
* irqfd_set_spi(): irqfd to inject virtual interrupt.
* irqfd_set_irq(): irqfd to inject virtual interrupt.
* @gzvm: Pointer to gzvm.
* @irq_source_id: irq source id.
* @irq: This is spi interrupt number (starts from 0 instead of 32).
* @level: irq triggered level.
* @line_status: irq status.
*/
static void irqfd_set_spi(struct gzvm *gzvm, int irq_source_id, u32 irq,
int level, bool line_status)
static void irqfd_set_irq(struct gzvm *gzvm, u32 irq, int level)
{
if (level)
gzvm_irqchip_inject_irq(gzvm, irq_source_id, 0, irq, level);
gzvm_irqchip_inject_irq(gzvm, 0, irq, level);
}
/**
@ -131,8 +128,7 @@ static int irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync,
eventfd_ctx_do_read(irqfd->eventfd, &cnt);
/* gzvm's irq injection is not blocked, don't need workq */
irqfd_set_spi(gzvm, GZVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi,
1, false);
irqfd_set_irq(gzvm, irqfd->gsi, 1);
}
if (flags & EPOLLHUP) {

View File

@ -269,24 +269,23 @@ gzvm_vm_ioctl_set_memory_region(struct gzvm *gzvm,
}
int gzvm_irqchip_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq_type, u32 irq, bool level)
u32 irq, bool level)
{
return gzvm_arch_inject_irq(gzvm, vcpu_idx, irq_type, irq, level);
return gzvm_arch_inject_irq(gzvm, vcpu_idx, irq, level);
}
static int gzvm_vm_ioctl_irq_line(struct gzvm *gzvm,
struct gzvm_irq_level *irq_level)
{
u32 irq = irq_level->irq;
u32 irq_type, vcpu_idx, vcpu2_idx, irq_num;
u32 vcpu_idx, vcpu2_idx, irq_num;
bool level = irq_level->level;
irq_type = FIELD_GET(GZVM_IRQ_LINE_TYPE, irq);
vcpu_idx = FIELD_GET(GZVM_IRQ_LINE_VCPU, irq);
vcpu2_idx = FIELD_GET(GZVM_IRQ_LINE_VCPU2, irq) * (GZVM_IRQ_VCPU_MASK + 1);
irq_num = FIELD_GET(GZVM_IRQ_LINE_NUM, irq);
return gzvm_irqchip_inject_irq(gzvm, vcpu_idx + vcpu2_idx, irq_type, irq_num,
return gzvm_irqchip_inject_irq(gzvm, vcpu_idx + vcpu2_idx, irq_num,
level);
}

View File

@ -26,7 +26,6 @@
#define ERR_NOT_SUPPORTED (-24)
#define ERR_NOT_IMPLEMENTED (-27)
#define ERR_FAULT (-40)
#define GZVM_USERSPACE_IRQ_SOURCE_ID 0
#define GZVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
/*
@ -133,7 +132,7 @@ int gzvm_arch_inform_exit(u16 vm_id);
int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev);
int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
u32 irq_type, u32 irq, bool level);
u32 irq, bool level);
void gzvm_notify_acked_irq(struct gzvm *gzvm, unsigned int gsi);
int gzvm_irqfd(struct gzvm *gzvm, struct gzvm_irqfd *args);

View File

@ -34,4 +34,3 @@ mandatory-y += termbits.h
mandatory-y += termios.h
mandatory-y += types.h
mandatory-y += unistd.h
mandatory-y += gzvm_arch.h

View File

@ -1,10 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2023 MediaTek Inc.
*/
#ifndef __ASM_GENERIC_GZVM_ARCH_H
#define __ASM_GENERIC_GZVM_ARCH_H
/* geniezone only supports aarch64 platform for now */
#endif /* __ASM_GENERIC_GZVM_ARCH_H */

View File

@ -16,8 +16,6 @@
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/gzvm_arch.h>
#define GZVM_CAP_VM_GPA_SIZE 0xa5
#define GZVM_CAP_PROTECTED_VM 0xffbadab1