virt: acrn: Introduce interfaces for PIO region passthrough
PIO region passthrough enables an OS in a virtual machine to directly access a PIO device in the host. It promises almost the native performance, which is required in performance-critical scenarios of ACRN. ACRN hypervisor will pass through most resource to Service VM at the begining except those pre-allocated to hypervisor itself and pre-launched VM. GPA and HPA of all these passthrough resource are identical mapped in Service VM. In this case, user space program can manipulate the PIO region in Service VM as PIO region in Host, such as delivering GPA in Service VM to hypervisor to assign PIO region to other post launched VM. HSM provides the following ioctls: - Assign - ACRN_IOCTL_ASSIGN_PIO_REGION Pass data struct acrn_pio_region from userspace to the hypervisor, and inform the hypervisor to assign a PIO region to a User VM. - De-assign - ACRN_IOCTL_DEASSIGN_PIO_REGION Pass data struct acrn_pio_region from userspace to the hypervisor, and inform the hypervisor to de-assign a PIO region from a User VM. These hypercalls are for ACPI device passthrough function of ACRN. Now ACRN only support legacy UART which has a PIO region. Before passing through this PIO region to a post-launched VM, ACRN device model would unbind UART device from Service VM through sysfs node /sys/bus/pnp/drivers/serial/unbind. Tracked-On: projectacrn/acrn-hypervisor#8635 Signed-off-by: Yichong Tang <yichong.tang@intel.com>
This commit is contained in:
parent
51b9a968e5
commit
7159ad071b
|
@ -116,6 +116,7 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
|
|||
struct acrn_ioeventfd ioeventfd;
|
||||
struct acrn_vm_memmap memmap;
|
||||
struct acrn_mmiodev *mmiodev;
|
||||
struct acrn_pio_region *pio_region;
|
||||
struct acrn_msi_entry *msi;
|
||||
struct acrn_pcidev *pcidev;
|
||||
struct acrn_irqfd irqfd;
|
||||
|
@ -331,6 +332,30 @@ static long acrn_dev_ioctl(struct file *filp, unsigned int cmd,
|
|||
"Failed to reset intr for ptdev!\n");
|
||||
kfree(irq_info);
|
||||
break;
|
||||
case ACRN_IOCTL_ASSIGN_PIO_REGION:
|
||||
pio_region = memdup_user((void __user *)ioctl_param,
|
||||
sizeof(struct acrn_pio_region));
|
||||
if (IS_ERR(pio_region))
|
||||
return PTR_ERR(pio_region);
|
||||
|
||||
ret = hcall_assign_pio_region(vm->vmid, virt_to_phys(pio_region));
|
||||
if (ret < 0)
|
||||
dev_dbg(acrn_dev.this_device,
|
||||
"Failed to assign PIO resource!\n");
|
||||
kfree(pio_region);
|
||||
break;
|
||||
case ACRN_IOCTL_DEASSIGN_PIO_REGION:
|
||||
pio_region = memdup_user((void __user *)ioctl_param,
|
||||
sizeof(struct acrn_pio_region));
|
||||
if (IS_ERR(pio_region))
|
||||
return PTR_ERR(pio_region);
|
||||
|
||||
ret = hcall_deassign_pio_region(vm->vmid, virt_to_phys(pio_region));
|
||||
if (ret < 0)
|
||||
dev_dbg(acrn_dev.this_device,
|
||||
"Failed to deassign PIO resource!\n");
|
||||
kfree(pio_region);
|
||||
break;
|
||||
case ACRN_IOCTL_SET_IRQLINE:
|
||||
ret = hcall_set_irqline(vm->vmid, ioctl_param);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#define HC_DEASSIGN_MMIODEV _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x08)
|
||||
#define HC_CREATE_VDEV _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x09)
|
||||
#define HC_DESTROY_VDEV _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x0A)
|
||||
#define HC_ASSIGN_PIO_REGION _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x0B)
|
||||
#define HC_DEASSIGN_PIO_REGION _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x0C)
|
||||
|
||||
#define HC_ID_DBG_BASE 0x60UL
|
||||
#define HC_SETUP_SBUF _HC_ID(HC_ID, HC_ID_DBG_BASE + 0x00)
|
||||
|
@ -328,6 +330,30 @@ static inline long hcall_reset_ptdev_intr(u64 vmid, u64 irq)
|
|||
return acrn_hypercall2(HC_RESET_PTDEV_INTR, vmid, irq);
|
||||
}
|
||||
|
||||
/**
|
||||
* hcall_assign_pio_region() - Assign a PIO region to a User VM
|
||||
* @vmid: User VM ID
|
||||
* @addr: Service VM GPA of the &struct acrn_pio_region
|
||||
*
|
||||
* Return: 0 on success, <0 on failure
|
||||
*/
|
||||
static inline long hcall_assign_pio_region(u64 vmid, u64 addr)
|
||||
{
|
||||
return acrn_hypercall2(HC_ASSIGN_PIO_REGION, vmid, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* hcall_deassign_pio_region() - De-assign a PIO region from a User VM
|
||||
* @vmid: User VM ID
|
||||
* @addr: Service VM GPA of the &struct acrn_pio_region
|
||||
*
|
||||
* Return: 0 on success, <0 on failure
|
||||
*/
|
||||
static inline long hcall_deassign_pio_region(u64 vmid, u64 addr)
|
||||
{
|
||||
return acrn_hypercall2(HC_DEASSIGN_PIO_REGION, vmid, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* hcall_get_cpu_state() - Get P-states and C-states info from the hypervisor
|
||||
* @state: Service VM GPA of buffer of P-states and C-states
|
||||
|
|
|
@ -441,6 +441,22 @@ struct acrn_mmiodev {
|
|||
} res[ACRN_MMIODEV_RES_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct acrn_pio_region - Info for assigning or de-assigning a PIO region
|
||||
* @name: Name of the PIO device.
|
||||
* @res[].port_address: Physical address of PIO region.
|
||||
* @res[].size: Size of the PIO region for the PIO device.
|
||||
*
|
||||
* This structure will be passed to hypervisor directly.
|
||||
*/
|
||||
struct acrn_pio_region {
|
||||
__u8 name[8];
|
||||
struct {
|
||||
__u16 port_address;
|
||||
__u16 size;
|
||||
} res;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct acrn_vdev - Info for creating or destroying a virtual device
|
||||
* @id: Union of identifier of the virtual device
|
||||
|
@ -724,6 +740,10 @@ struct sbuf_setup_param {
|
|||
_IOW(ACRN_IOCTL_TYPE, 0x59, struct acrn_vdev)
|
||||
#define ACRN_IOCTL_DESTROY_VDEV \
|
||||
_IOW(ACRN_IOCTL_TYPE, 0x5A, struct acrn_vdev)
|
||||
#define ACRN_IOCTL_ASSIGN_PIO_REGION \
|
||||
_IOW(ACRN_IOCTL_TYPE, 0x5B, struct acrn_pio_region)
|
||||
#define ACRN_IOCTL_DEASSIGN_PIO_REGION \
|
||||
_IOW(ACRN_IOCTL_TYPE, 0x5C, struct acrn_pio_region)
|
||||
|
||||
#define ACRN_IOCTL_PM_GET_CPU_STATE \
|
||||
_IOWR(ACRN_IOCTL_TYPE, 0x60, __u64)
|
||||
|
|
Loading…
Reference in New Issue