mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-18 19:57:31 +00:00
HV: pci-vuart support create vdev hcall
Add cteate method for vmcs9900 vdev in hypercalls. The destroy method of ivshmem is also suitable for other emulated vdev, move it into hcall_destroy_vdev() for all emulated vdevs Tracked-On: #5394 Signed-off-by: Tao Yuhong <yuhong.tao@intel.com> Reviewed-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
a371815462
commit
996e8f680c
@ -26,6 +26,7 @@
|
||||
#include <rdt.h>
|
||||
#include <sgx.h>
|
||||
#include <uart16550.h>
|
||||
#include <vpci.h>
|
||||
#include <ivshmem.h>
|
||||
|
||||
#define CPU_UP_TIMEOUT 100U /* millisecond */
|
||||
|
@ -21,19 +21,21 @@
|
||||
#include <ioapic.h>
|
||||
#include <mmio_dev.h>
|
||||
#include <ivshmem.h>
|
||||
#include <vmcs9900.h>
|
||||
|
||||
#define DBG_LEVEL_HYCALL 6U
|
||||
|
||||
typedef int32_t (*emul_dev_op) (struct acrn_vm *vm, struct acrn_emul_dev *dev);
|
||||
typedef int32_t (*emul_dev_create) (struct acrn_vm *vm, struct acrn_emul_dev *dev);
|
||||
typedef int32_t (*emul_dev_destroy) (struct pci_vdev *vdev);
|
||||
struct emul_dev_ops {
|
||||
/*
|
||||
* The low 32 bits represent the vendor id and device id of PCI device,
|
||||
* and the high 32 bits represent the device number of the legacy device
|
||||
*/
|
||||
uint64_t dev_id;
|
||||
emul_dev_op create;
|
||||
emul_dev_op destroy;
|
||||
|
||||
/* TODO: to re-use vdev_init/vdev_deinit directly in hypercall */
|
||||
emul_dev_create create;
|
||||
emul_dev_destroy destroy;
|
||||
};
|
||||
|
||||
static struct emul_dev_ops emul_dev_ops_tbl[] = {
|
||||
@ -42,6 +44,7 @@ static struct emul_dev_ops emul_dev_ops_tbl[] = {
|
||||
#else
|
||||
{(IVSHMEM_VENDOR_ID | (IVSHMEM_DEVICE_ID << 16U)), NULL, NULL},
|
||||
#endif
|
||||
{(MCS9900_VENDOR | (MCS9900_DEV << 16U)), create_vmcs9900_vdev, destroy_vmcs9900_vdev},
|
||||
};
|
||||
|
||||
bool is_hypercall_from_ring0(void)
|
||||
@ -1216,16 +1219,30 @@ int32_t hcall_destroy_vdev(struct acrn_vm *vm, struct acrn_vm *target_vm, __unus
|
||||
{
|
||||
int32_t ret = -EINVAL;
|
||||
struct acrn_emul_dev dev;
|
||||
struct pci_vdev *vdev;
|
||||
struct emul_dev_ops *op;
|
||||
union pci_bdf bdf;
|
||||
|
||||
/* We should only destroy a device to a post-launched VM at creating or pausing time for safety, not runtime or other cases*/
|
||||
if (is_created_vm(target_vm) || is_paused_vm(target_vm)) {
|
||||
if (copy_from_gpa(vm, &dev, param2, sizeof(dev)) == 0) {
|
||||
op = find_emul_dev_ops(&dev);
|
||||
if ((op != NULL) && (op->destroy != NULL)) {
|
||||
ret = op->destroy(target_vm, &dev);
|
||||
op = find_emul_dev_ops(&dev);
|
||||
if (op != NULL) {
|
||||
bdf.value = (uint16_t) dev.slot;
|
||||
vdev = pci_find_vdev(&vm->vpci, bdf);
|
||||
if (vdev != NULL) {
|
||||
vdev->pci_dev_config->vbdf.value = UNASSIGNED_VBDF;
|
||||
if (op->destroy != NULL) {
|
||||
ret = op->destroy(vdev);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
pr_warn("%s, failed to destroy emulated device %x:%x.%x\n",
|
||||
__func__, bdf.bits.b, bdf.bits.d, bdf.bits.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pr_err("%s, vm[%d] is not a postlaunched VM, or not in CREATED/PAUSED status to destroy a vdev\n", __func__, target_vm->vm_id);
|
||||
}
|
||||
|
@ -394,27 +394,15 @@ int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
* @pre dev != NULL
|
||||
*/
|
||||
int32_t destroy_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev)
|
||||
int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev)
|
||||
{
|
||||
struct pci_vdev *vdev;
|
||||
union pci_bdf bdf;
|
||||
int32_t ret = 0;
|
||||
uint32_t i;
|
||||
|
||||
bdf.value = (uint16_t) dev->slot;
|
||||
vdev = pci_find_vdev(&vm->vpci, bdf);
|
||||
if (vdev != NULL) {
|
||||
vdev->pci_dev_config->vbdf.value = UNASSIGNED_VBDF;
|
||||
(void)memset(vdev->pci_dev_config->vbar_base, 0U, sizeof(vdev->pci_dev_config->vbar_base));
|
||||
} else {
|
||||
pr_warn("%s, failed to destroy ivshmem device %x:%x.%x\n",
|
||||
__func__, bdf.bits.b, bdf.bits.d, bdf.bits.f);
|
||||
ret = -EINVAL;
|
||||
for (i = 0U; i < vdev->nr_bars; i++) {
|
||||
vpci_update_one_vbar(vdev, i, 0U, NULL, ivshmem_vbar_unmap);
|
||||
}
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pci_vdev_ops vpci_ivshmem_ops = {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <logmsg.h>
|
||||
#include <vmcs9900.h>
|
||||
#include "vpci_priv.h"
|
||||
#include <errno.h>
|
||||
|
||||
#define MCS9900_MMIO_BAR 0U
|
||||
#define MCS9900_MSIX_BAR 1U
|
||||
@ -167,3 +168,43 @@ const struct pci_vdev_ops vmcs9900_ops = {
|
||||
.write_vdev_cfg = write_vmcs9900_cfg,
|
||||
.read_vdev_cfg = read_vmcs9900_cfg,
|
||||
};
|
||||
|
||||
int32_t create_vmcs9900_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev)
|
||||
{
|
||||
uint32_t i;
|
||||
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
|
||||
struct acrn_vm_pci_dev_config *dev_config = NULL;
|
||||
int32_t ret = -EINVAL;
|
||||
uint16_t vuart_idx = *((uint16_t*)(dev->args));
|
||||
|
||||
for (i = 0U; i < vm_config->pci_dev_num; i++) {
|
||||
dev_config = &vm_config->pci_devs[i];
|
||||
if (dev_config->vuart_idx == vuart_idx) {
|
||||
dev_config->vbdf.value = (uint16_t) dev->slot;
|
||||
dev_config->vbar_base[0] = (uint64_t) dev->io_addr[0];
|
||||
dev_config->vbar_base[1] = (uint64_t) dev->io_addr[1];
|
||||
(void) vpci_init_vdev(&vm->vpci, dev_config, NULL);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
pr_err("Unsupport: create VM%d vuart_idx=%d", vm->vm_id, vuart_idx);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t destroy_vmcs9900_vdev(struct pci_vdev *vdev)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < vdev->nr_bars; i++) {
|
||||
vpci_update_one_vbar(vdev, i, 0U, NULL, unmap_vmcs9900_vbar);
|
||||
}
|
||||
|
||||
deinit_pci_vuart(vdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ extern const struct pci_vdev_ops vpci_ivshmem_ops;
|
||||
void init_ivshmem_shared_memory(void);
|
||||
|
||||
int32_t create_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev);
|
||||
int32_t destroy_ivshmem_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev);
|
||||
int32_t destroy_ivshmem_vdev(struct pci_vdev *vdev);
|
||||
#endif /* CONFIG_IVSHMEM_ENABLED */
|
||||
|
||||
#endif /* IVSHMEM_H */
|
||||
|
@ -12,5 +12,7 @@
|
||||
|
||||
extern const struct pci_vdev_ops vmcs9900_ops;
|
||||
void trigger_vmcs9900_msix(struct pci_vdev *vdev);
|
||||
int32_t create_vmcs9900_vdev(struct acrn_vm *vm, struct acrn_emul_dev *dev);
|
||||
int32_t destroy_vmcs9900_vdev(struct pci_vdev *vdev);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user