vgic.c 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2023 MediaTek Inc.
  4. */
  5. #include <linux/irqchip/arm-gic-v3.h>
  6. #include <linux/gzvm.h>
  7. #include <linux/gzvm_drv.h>
  8. #include "gzvm_arch_common.h"
  9. int gzvm_arch_create_device(u16 vm_id, struct gzvm_create_device *gzvm_dev)
  10. {
  11. struct arm_smccc_res res;
  12. return gzvm_hypcall_wrapper(MT_HVC_GZVM_CREATE_DEVICE, vm_id,
  13. virt_to_phys(gzvm_dev), 0, 0, 0, 0, 0,
  14. &res);
  15. }
  16. /**
  17. * gzvm_arch_inject_irq() - Inject virtual interrupt to a VM
  18. * @gzvm: Pointer to struct gzvm
  19. * @vcpu_idx: vcpu index, only valid if PPI
  20. * @irq: *SPI* irq number (excluding offset value `32`)
  21. * @level: 1 if true else 0
  22. *
  23. * Return:
  24. * * 0 - Success.
  25. * * Negative - Failure.
  26. */
  27. int gzvm_arch_inject_irq(struct gzvm *gzvm, unsigned int vcpu_idx,
  28. u32 irq, bool level)
  29. {
  30. unsigned long a1 = assemble_vm_vcpu_tuple(gzvm->vm_id, vcpu_idx);
  31. struct arm_smccc_res res;
  32. /*
  33. * VMM's virtual device irq number starts from 0, but ARM's shared peripheral
  34. * interrupt number starts from 32. hypervisor adds offset 32
  35. */
  36. gzvm_hypcall_wrapper(MT_HVC_GZVM_IRQ_LINE, a1, irq, level,
  37. 0, 0, 0, 0, &res);
  38. if (res.a0) {
  39. pr_err("Failed to set IRQ level (%d) to irq#%u on vcpu %d with ret=%d\n",
  40. level, irq, vcpu_idx, (int)res.a0);
  41. return -EFAULT;
  42. }
  43. return 0;
  44. }