mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
vPCI: introduce private header
Before adding more private stuff to xen/vpci.h, split it up. In order to be able to include the private header first in a CU, the per-arch struct decls also need to move (to new asm/vpci.h files). While adjusting the test harness'es Makefile, also switch the pre-existing header symlink-ing rule to a pattern one. Apart from in the test harness code, things only move; no functional change intended. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Stewart Hildebrand <stewart.hildebrand@amd.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
1 parent
bbfb30f649
commit
c6f5590c93
14 files changed
+190
-139
No files matched your search
@@ -154,6 +154,7 @@ tools/tests/x86_emulator/test_x86_emulator
|
||||
tools/tests/x86_emulator/x86_emulate
|
||||
tools/tests/x86_emulator/xop*.[ch]
|
||||
tools/tests/vpci/list.h
|
||||
tools/tests/vpci/private.h
|
||||
tools/tests/vpci/vpci.[hc]
|
||||
tools/tests/vpci/test_vpci
|
||||
tools/xcutils/lsevtchn
|
||||
|
||||
@@ -14,12 +14,12 @@ else
|
||||
$(warning HOSTCC != CC, will not run test)
|
||||
endif
|
||||
|
||||
$(TARGET): vpci.c vpci.h list.h main.c emul.h
|
||||
$(CC) $(CFLAGS_xeninclude) -g -o $@ vpci.c main.c
|
||||
$(TARGET): vpci.c vpci.h list.h private.h main.c emul.h
|
||||
$(CC) $(CFLAGS_xeninclude) -include emul.h -g -o $@ vpci.c main.c
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(TARGET) *.o *~ vpci.h vpci.c list.h
|
||||
rm -rf $(TARGET) *.o *~ vpci.h vpci.c list.h private.h
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
@@ -34,10 +34,10 @@ uninstall:
|
||||
$(RM) -- $(DESTDIR)$(LIBEXEC)/tests/$(TARGET)
|
||||
|
||||
vpci.c: $(XEN_ROOT)/xen/drivers/vpci/vpci.c
|
||||
# Remove includes and add the test harness header
|
||||
sed -e '/#include/d' -e '1s/^/#include "emul.h"/' <$< >$@
|
||||
|
||||
list.h: $(XEN_ROOT)/xen/include/xen/list.h
|
||||
vpci.h: $(XEN_ROOT)/xen/include/xen/vpci.h
|
||||
list.h vpci.h:
|
||||
sed -e '/#include/d' <$< >$@
|
||||
|
||||
private.h: %.h: $(XEN_ROOT)/xen/drivers/vpci/%.h
|
||||
sed -e '/#include/d' <$< >$@
|
||||
|
||||
list.h vpci.h: %.h: $(XEN_ROOT)/xen/include/xen/%.h
|
||||
sed -e '/#include/d' <$< >$@
|
||||
@@ -86,6 +86,7 @@ typedef union {
|
||||
|
||||
#define CONFIG_HAS_VPCI
|
||||
#include "vpci.h"
|
||||
#include "private.h"
|
||||
|
||||
#define __hwdom_init
|
||||
|
||||
|
||||
@@ -31,14 +31,6 @@ struct arch_pci_dev {
|
||||
struct device dev;
|
||||
};
|
||||
|
||||
/* Arch-specific MSI data for vPCI. */
|
||||
struct vpci_arch_msi {
|
||||
};
|
||||
|
||||
/* Arch-specific MSI-X entry data for vPCI. */
|
||||
struct vpci_arch_msix_entry {
|
||||
};
|
||||
|
||||
/*
|
||||
* Because of the header cross-dependencies, e.g. we need both
|
||||
* struct pci_dev and struct arch_pci_dev at the same time, this cannot be
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef ARM_VPCI_H
|
||||
#define ARM_VPCI_H
|
||||
|
||||
/* Arch-specific MSI data for vPCI. */
|
||||
struct vpci_arch_msi {
|
||||
};
|
||||
|
||||
/* Arch-specific MSI-X entry data for vPCI. */
|
||||
struct vpci_arch_msix_entry {
|
||||
};
|
||||
|
||||
#endif /* ARM_VPCI_H */
|
||||
@@ -97,17 +97,6 @@ void msixtbl_init(struct domain *d);
|
||||
static inline void msixtbl_init(struct domain *d) {}
|
||||
#endif
|
||||
|
||||
/* Arch-specific MSI data for vPCI. */
|
||||
struct vpci_arch_msi {
|
||||
int pirq;
|
||||
bool bound;
|
||||
};
|
||||
|
||||
/* Arch-specific MSI-X entry data for vPCI. */
|
||||
struct vpci_arch_msix_entry {
|
||||
int pirq;
|
||||
};
|
||||
|
||||
void stdvga_init(struct domain *d);
|
||||
|
||||
extern void hvm_dpci_msi_eoi(struct domain *d, int vector);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef X86_VPCI_H
|
||||
#define X86_VPCI_H
|
||||
|
||||
#include <xen/stdbool.h>
|
||||
|
||||
/* Arch-specific MSI data for vPCI. */
|
||||
struct vpci_arch_msi {
|
||||
int pirq;
|
||||
bool bound;
|
||||
};
|
||||
|
||||
/* Arch-specific MSI-X entry data for vPCI. */
|
||||
struct vpci_arch_msix_entry {
|
||||
int pirq;
|
||||
};
|
||||
|
||||
#endif /* X86_VPCI_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -17,11 +17,12 @@
|
||||
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xen/iocap.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/vpci.h>
|
||||
|
||||
#include <xsm/xsm.h>
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xen/sched.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/vpci.h>
|
||||
|
||||
#include <asm/msi.h>
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xen/io.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/vpci.h>
|
||||
|
||||
#include <asm/msi.h>
|
||||
#include <asm/p2m.h>
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#ifndef VPCI_PRIVATE_H
|
||||
#define VPCI_PRIVATE_H
|
||||
|
||||
#include <xen/vpci.h>
|
||||
|
||||
typedef uint32_t vpci_read_t(const struct pci_dev *pdev, unsigned int reg,
|
||||
void *data);
|
||||
|
||||
typedef void vpci_write_t(const struct pci_dev *pdev, unsigned int reg,
|
||||
uint32_t val, void *data);
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
bool is_ext;
|
||||
int (* init)(struct pci_dev *pdev);
|
||||
int (* cleanup)(const struct pci_dev *pdev, bool hide);
|
||||
} vpci_capability_t;
|
||||
|
||||
#define REGISTER_VPCI_CAPABILITY(cap, name, finit, fclean, ext) \
|
||||
static const vpci_capability_t name##_entry \
|
||||
__used_section(".data.rel.ro.vpci") = { \
|
||||
.id = (cap), \
|
||||
.init = (finit), \
|
||||
.cleanup = (fclean), \
|
||||
.is_ext = (ext), \
|
||||
}
|
||||
|
||||
#define REGISTER_VPCI_CAP(name, finit, fclean) \
|
||||
REGISTER_VPCI_CAPABILITY(PCI_CAP_ID_##name, name, finit, fclean, false)
|
||||
#define REGISTER_VPCI_EXTCAP(name, finit, fclean) \
|
||||
REGISTER_VPCI_CAPABILITY(PCI_EXT_CAP_ID_##name, name, finit, fclean, true)
|
||||
|
||||
int __must_check vpci_init_header(struct pci_dev *pdev);
|
||||
|
||||
/* Add/remove a register handler. */
|
||||
int __must_check vpci_add_register_mask(struct vpci *vpci,
|
||||
vpci_read_t *read_handler,
|
||||
vpci_write_t *write_handler,
|
||||
unsigned int offset, unsigned int size,
|
||||
void *data, uint32_t ro_mask,
|
||||
uint32_t rw1c_mask, uint32_t rsvdp_mask,
|
||||
uint32_t rsvdz_mask);
|
||||
int __must_check vpci_add_register(struct vpci *vpci,
|
||||
vpci_read_t *read_handler,
|
||||
vpci_write_t *write_handler,
|
||||
unsigned int offset, unsigned int size,
|
||||
void *data);
|
||||
|
||||
int vpci_remove_registers(struct vpci *vpci, unsigned int start,
|
||||
unsigned int size);
|
||||
|
||||
/* Helper to return the value passed in data. */
|
||||
uint32_t cf_check vpci_read_val(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
|
||||
/* Passthrough handlers. */
|
||||
uint32_t cf_check vpci_hw_read8(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
uint32_t cf_check vpci_hw_read16(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
uint32_t cf_check vpci_hw_read32(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
void cf_check vpci_hw_write8(
|
||||
const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data);
|
||||
void cf_check vpci_hw_write16(
|
||||
const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data);
|
||||
|
||||
#ifdef __XEN__
|
||||
/* Make sure there's a hole in the p2m for the MSIX mmio areas. */
|
||||
int vpci_make_msix_hole(const struct pci_dev *pdev);
|
||||
|
||||
/*
|
||||
* Helper functions to fetch MSIX related data. They are used by both the
|
||||
* emulated MSIX code and the BAR handlers.
|
||||
*/
|
||||
static inline paddr_t vmsix_table_host_base(const struct vpci *vpci,
|
||||
unsigned int nr)
|
||||
{
|
||||
return vpci->header.bars[vpci->msix->tables[nr] & PCI_MSIX_BIRMASK].addr;
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_host_addr(const struct vpci *vpci,
|
||||
unsigned int nr)
|
||||
{
|
||||
return vmsix_table_host_base(vpci, nr) +
|
||||
(vpci->msix->tables[nr] & ~PCI_MSIX_BIRMASK);
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_base(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return vpci->header.bars[vpci->msix->tables[nr] &
|
||||
PCI_MSIX_BIRMASK].guest_addr;
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_addr(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return vmsix_table_base(vpci, nr) +
|
||||
(vpci->msix->tables[nr] & ~PCI_MSIX_BIRMASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note regarding the size calculation of the PBA: the spec mentions "The last
|
||||
* QWORD will not necessarily be fully populated", so it implies that the PBA
|
||||
* size is 64-bit aligned.
|
||||
*/
|
||||
static inline size_t vmsix_table_size(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return
|
||||
(nr == VPCI_MSIX_TABLE) ? vpci->msix->max_entries * PCI_MSIX_ENTRY_SIZE
|
||||
: ROUNDUP(DIV_ROUND_UP(vpci->msix->max_entries,
|
||||
8), 8);
|
||||
}
|
||||
|
||||
#endif /* __XEN__ */
|
||||
|
||||
#endif /* VPCI_PRIVATE_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -5,8 +5,9 @@
|
||||
* Author: Jiqian Chen <Jiqian.Chen@amd.com>
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xen/sched.h>
|
||||
#include <xen/vpci.h>
|
||||
|
||||
static void cf_check rebar_ctrl_write(const struct pci_dev *pdev,
|
||||
unsigned int reg,
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include <xen/sched.h>
|
||||
#include <xen/vpci.h>
|
||||
#include <xen/vmap.h>
|
||||
|
||||
/* Internal struct to store the emulated PCI registers. */
|
||||
|
||||
+1
-106
@@ -7,18 +7,7 @@
|
||||
#include <xen/types.h>
|
||||
#include <xen/list.h>
|
||||
|
||||
typedef uint32_t vpci_read_t(const struct pci_dev *pdev, unsigned int reg,
|
||||
void *data);
|
||||
|
||||
typedef void vpci_write_t(const struct pci_dev *pdev, unsigned int reg,
|
||||
uint32_t val, void *data);
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
bool is_ext;
|
||||
int (* init)(struct pci_dev *pdev);
|
||||
int (* cleanup)(const struct pci_dev *pdev, bool hide);
|
||||
} vpci_capability_t;
|
||||
#include <asm/vpci.h>
|
||||
|
||||
#define VPCI_ECAM_BDF(addr) (((addr) & 0x0ffff000) >> 12)
|
||||
|
||||
@@ -30,66 +19,17 @@ typedef struct {
|
||||
*/
|
||||
#define VPCI_MAX_VIRT_DEV (PCI_SLOT(~0) + 1)
|
||||
|
||||
#define REGISTER_VPCI_CAPABILITY(cap, name, finit, fclean, ext) \
|
||||
static const vpci_capability_t name##_entry \
|
||||
__used_section(".data.rel.ro.vpci") = { \
|
||||
.id = (cap), \
|
||||
.init = (finit), \
|
||||
.cleanup = (fclean), \
|
||||
.is_ext = (ext), \
|
||||
}
|
||||
|
||||
#define REGISTER_VPCI_CAP(name, finit, fclean) \
|
||||
REGISTER_VPCI_CAPABILITY(PCI_CAP_ID_##name, name, finit, fclean, false)
|
||||
#define REGISTER_VPCI_EXTCAP(name, finit, fclean) \
|
||||
REGISTER_VPCI_CAPABILITY(PCI_EXT_CAP_ID_##name, name, finit, fclean, true)
|
||||
|
||||
int __must_check vpci_init_header(struct pci_dev *pdev);
|
||||
|
||||
/* Assign vPCI to device by adding handlers. */
|
||||
int __must_check vpci_assign_device(struct pci_dev *pdev);
|
||||
|
||||
/* Remove all handlers and free vpci related structures. */
|
||||
void vpci_deassign_device(struct pci_dev *pdev);
|
||||
|
||||
/* Add/remove a register handler. */
|
||||
int __must_check vpci_add_register_mask(struct vpci *vpci,
|
||||
vpci_read_t *read_handler,
|
||||
vpci_write_t *write_handler,
|
||||
unsigned int offset, unsigned int size,
|
||||
void *data, uint32_t ro_mask,
|
||||
uint32_t rw1c_mask, uint32_t rsvdp_mask,
|
||||
uint32_t rsvdz_mask);
|
||||
int __must_check vpci_add_register(struct vpci *vpci,
|
||||
vpci_read_t *read_handler,
|
||||
vpci_write_t *write_handler,
|
||||
unsigned int offset, unsigned int size,
|
||||
void *data);
|
||||
|
||||
int vpci_remove_registers(struct vpci *vpci, unsigned int start,
|
||||
unsigned int size);
|
||||
|
||||
/* Generic read/write handlers for the PCI config space. */
|
||||
uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int size);
|
||||
void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size,
|
||||
uint32_t data);
|
||||
|
||||
/* Helper to return the value passed in data. */
|
||||
uint32_t cf_check vpci_read_val(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
|
||||
/* Passthrough handlers. */
|
||||
uint32_t cf_check vpci_hw_read8(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
uint32_t cf_check vpci_hw_read16(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
uint32_t cf_check vpci_hw_read32(
|
||||
const struct pci_dev *pdev, unsigned int reg, void *data);
|
||||
void cf_check vpci_hw_write8(
|
||||
const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data);
|
||||
void cf_check vpci_hw_write16(
|
||||
const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data);
|
||||
|
||||
/*
|
||||
* Check for pending vPCI operations on this vcpu. Returns true if the vcpu
|
||||
* should not run.
|
||||
@@ -213,9 +153,6 @@ struct vpci_vcpu {
|
||||
#ifdef __XEN__
|
||||
void vpci_dump_msi(void);
|
||||
|
||||
/* Make sure there's a hole in the p2m for the MSIX mmio areas. */
|
||||
int vpci_make_msix_hole(const struct pci_dev *pdev);
|
||||
|
||||
/* Arch-specific vPCI MSI helpers. */
|
||||
void vpci_msi_arch_mask(struct vpci_msi *msi, const struct pci_dev *pdev,
|
||||
unsigned int entry, bool mask);
|
||||
@@ -238,48 +175,6 @@ int __must_check vpci_msix_arch_disable_entry(struct vpci_msix_entry *entry,
|
||||
void vpci_msix_arch_init_entry(struct vpci_msix_entry *entry);
|
||||
int vpci_msix_arch_print(const struct vpci_msix *msix);
|
||||
|
||||
/*
|
||||
* Helper functions to fetch MSIX related data. They are used by both the
|
||||
* emulated MSIX code and the BAR handlers.
|
||||
*/
|
||||
static inline paddr_t vmsix_table_host_base(const struct vpci *vpci,
|
||||
unsigned int nr)
|
||||
{
|
||||
return vpci->header.bars[vpci->msix->tables[nr] & PCI_MSIX_BIRMASK].addr;
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_host_addr(const struct vpci *vpci,
|
||||
unsigned int nr)
|
||||
{
|
||||
return vmsix_table_host_base(vpci, nr) +
|
||||
(vpci->msix->tables[nr] & ~PCI_MSIX_BIRMASK);
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_base(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return vpci->header.bars[vpci->msix->tables[nr] &
|
||||
PCI_MSIX_BIRMASK].guest_addr;
|
||||
}
|
||||
|
||||
static inline paddr_t vmsix_table_addr(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return vmsix_table_base(vpci, nr) +
|
||||
(vpci->msix->tables[nr] & ~PCI_MSIX_BIRMASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note regarding the size calculation of the PBA: the spec mentions "The last
|
||||
* QWORD will not necessarily be fully populated", so it implies that the PBA
|
||||
* size is 64-bit aligned.
|
||||
*/
|
||||
static inline size_t vmsix_table_size(const struct vpci *vpci, unsigned int nr)
|
||||
{
|
||||
return
|
||||
(nr == VPCI_MSIX_TABLE) ? vpci->msix->max_entries * PCI_MSIX_ENTRY_SIZE
|
||||
: ROUNDUP(DIV_ROUND_UP(vpci->msix->max_entries,
|
||||
8), 8);
|
||||
}
|
||||
|
||||
static inline unsigned int vmsix_entry_nr(const struct vpci_msix *msix,
|
||||
const struct vpci_msix_entry *entry)
|
||||
{
|
||||
|
||||