mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
When dom0 is PVH, and passthrough a device to dumU, xl will use the gsi number of device to do a pirq mapping, see pci_add_dm_done->xc_physdev_map_pirq, but the gsi number is got from file /sys/bus/pci/devices/<sbdf>/irq, that confuses irq and gsi, they are in different space and are not equal, so it will fail when mapping. To solve this issue, to get the real gsi and add a new function xc_physdev_map_pirq_gsi to get a free pirq for gsi. Note: why not use current function xc_physdev_map_pirq, because it doesn't support to allocate a free pirq, what's more, to prevent changing it and affecting its callers, so add xc_physdev_map_pirq_gsi. Besides, PVH dom0 doesn't have PIRQs flag, it doesn't do PHYSDEVOP_map_pirq for each gsi. So grant function callstack pci_add_dm_done->XEN_DOMCTL_irq_permission will fail at function domain_pirq_to_irq. And old hypercall XEN_DOMCTL_irq_permission requires passing in pirq, it is not suitable for PVH dom0 that doesn't have PIRQs to grant irq permission. To solve this issue, use the another hypercall XEN_DOMCTL_gsi_permission to grant the permission of irq( translate from gsi) to dumU when dom0 has no PIRQs. Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com> Signed-off-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Chen Jiqian <Jiqian.Chen@amd.com> Reviewed-by: Anthony PERARD <anthony.perard@vates.tech>
141 lines
3.5 KiB
C
141 lines
3.5 KiB
C
/******************************************************************************
|
|
* xc_physdev.c
|
|
*
|
|
* API for manipulating physical-device access permissions.
|
|
*
|
|
* Copyright (c) 2004, Rolf Neugebauer (Intel Research Cambridge)
|
|
* Copyright (c) 2004, K A Fraser (University of Cambridge)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "xc_private.h"
|
|
|
|
int xc_physdev_pci_access_modify(xc_interface *xch,
|
|
uint32_t domid,
|
|
int bus,
|
|
int dev,
|
|
int func,
|
|
int enable)
|
|
{
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
int xc_physdev_map_pirq(xc_interface *xch,
|
|
uint32_t domid,
|
|
int index,
|
|
int *pirq)
|
|
{
|
|
int rc;
|
|
struct physdev_map_pirq map;
|
|
|
|
if ( !pirq )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
memset(&map, 0, sizeof(struct physdev_map_pirq));
|
|
map.domid = domid;
|
|
map.type = MAP_PIRQ_TYPE_GSI;
|
|
map.index = index;
|
|
map.pirq = *pirq < 0 ? index : *pirq;
|
|
|
|
rc = do_physdev_op(xch, PHYSDEVOP_map_pirq, &map, sizeof(map));
|
|
|
|
if ( !rc )
|
|
*pirq = map.pirq;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_physdev_map_pirq_msi(xc_interface *xch,
|
|
uint32_t domid,
|
|
int index,
|
|
int *pirq,
|
|
int devfn,
|
|
int bus,
|
|
int entry_nr,
|
|
uint64_t table_base)
|
|
{
|
|
int rc;
|
|
struct physdev_map_pirq map;
|
|
|
|
if ( !pirq )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
memset(&map, 0, sizeof(struct physdev_map_pirq));
|
|
map.domid = domid;
|
|
map.type = MAP_PIRQ_TYPE_MSI;
|
|
map.index = index;
|
|
map.pirq = *pirq;
|
|
map.bus = bus;
|
|
map.devfn = devfn;
|
|
map.entry_nr = entry_nr;
|
|
map.table_base = table_base;
|
|
|
|
rc = do_physdev_op(xch, PHYSDEVOP_map_pirq, &map, sizeof(map));
|
|
|
|
if ( !rc )
|
|
*pirq = map.pirq;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_physdev_map_pirq_gsi(xc_interface *xch,
|
|
uint32_t domid,
|
|
int gsi,
|
|
int *pirq)
|
|
{
|
|
int rc;
|
|
struct physdev_map_pirq map = {
|
|
.domid = domid,
|
|
.type = MAP_PIRQ_TYPE_GSI,
|
|
.index = gsi,
|
|
};
|
|
|
|
if ( !pirq )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
map.pirq = *pirq;
|
|
|
|
rc = do_physdev_op(xch, PHYSDEVOP_map_pirq, &map, sizeof(map));
|
|
|
|
if ( !rc )
|
|
*pirq = map.pirq;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int xc_physdev_unmap_pirq(xc_interface *xch,
|
|
uint32_t domid,
|
|
int pirq)
|
|
{
|
|
int rc;
|
|
struct physdev_unmap_pirq unmap;
|
|
|
|
memset(&unmap, 0, sizeof(struct physdev_unmap_pirq));
|
|
unmap.domid = domid;
|
|
unmap.pirq = pirq;
|
|
|
|
rc = do_physdev_op(xch, PHYSDEVOP_unmap_pirq, &unmap, sizeof(unmap));
|
|
|
|
return rc;
|
|
}
|
|
|