diff --git a/.gitignore b/.gitignore index 57d54f676f..bfc7bdf043 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/tools/tests/vpci/Makefile b/tools/tests/vpci/Makefile index 97359ff67f..28b6009332 100644 --- a/tools/tests/vpci/Makefile +++ b/tools/tests/vpci/Makefile @@ -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' <$< >$@ diff --git a/tools/tests/vpci/emul.h b/tools/tests/vpci/emul.h index dd048cffbf..38211afbb8 100644 --- a/tools/tests/vpci/emul.h +++ b/tools/tests/vpci/emul.h @@ -86,6 +86,7 @@ typedef union { #define CONFIG_HAS_VPCI #include "vpci.h" +#include "private.h" #define __hwdom_init diff --git a/xen/arch/arm/include/asm/pci.h b/xen/arch/arm/include/asm/pci.h index 73c3be74ae..7c3211823f 100644 --- a/xen/arch/arm/include/asm/pci.h +++ b/xen/arch/arm/include/asm/pci.h @@ -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 diff --git a/xen/arch/arm/include/asm/vpci.h b/xen/arch/arm/include/asm/vpci.h new file mode 100644 index 0000000000..db04687fc0 --- /dev/null +++ b/xen/arch/arm/include/asm/vpci.h @@ -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 */ diff --git a/xen/arch/x86/include/asm/hvm/io.h b/xen/arch/x86/include/asm/hvm/io.h index c12f099a03..986822ff15 100644 --- a/xen/arch/x86/include/asm/hvm/io.h +++ b/xen/arch/x86/include/asm/hvm/io.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); diff --git a/xen/arch/x86/include/asm/vpci.h b/xen/arch/x86/include/asm/vpci.h new file mode 100644 index 0000000000..c501ff1709 --- /dev/null +++ b/xen/arch/x86/include/asm/vpci.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef X86_VPCI_H +#define X86_VPCI_H + +#include + +/* 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: + */ diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index 739a5f610e..b90a7f2b4e 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -17,11 +17,12 @@ * License along with this program; If not, see . */ +#include "private.h" + #include #include #include #include -#include #include diff --git a/xen/drivers/vpci/msi.c b/xen/drivers/vpci/msi.c index 737770ffa3..f736054b2b 100644 --- a/xen/drivers/vpci/msi.c +++ b/xen/drivers/vpci/msi.c @@ -16,9 +16,10 @@ * License along with this program; If not, see . */ +#include "private.h" + #include #include -#include #include diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c index eaf8fae970..f87212b46f 100644 --- a/xen/drivers/vpci/msix.c +++ b/xen/drivers/vpci/msix.c @@ -17,10 +17,11 @@ * License along with this program; If not, see . */ +#include "private.h" + #include #include #include -#include #include #include diff --git a/xen/drivers/vpci/private.h b/xen/drivers/vpci/private.h new file mode 100644 index 0000000000..5a7ca47557 --- /dev/null +++ b/xen/drivers/vpci/private.h @@ -0,0 +1,126 @@ +#ifndef VPCI_PRIVATE_H +#define VPCI_PRIVATE_H + +#include + +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: + */ diff --git a/xen/drivers/vpci/rebar.c b/xen/drivers/vpci/rebar.c index 4d22f08af3..ab5c5453a8 100644 --- a/xen/drivers/vpci/rebar.c +++ b/xen/drivers/vpci/rebar.c @@ -5,8 +5,9 @@ * Author: Jiqian Chen */ +#include "private.h" + #include -#include static void cf_check rebar_ctrl_write(const struct pci_dev *pdev, unsigned int reg, diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c index f66f50c8ba..ce0f297b44 100644 --- a/xen/drivers/vpci/vpci.c +++ b/xen/drivers/vpci/vpci.c @@ -17,8 +17,9 @@ * License along with this program; If not, see . */ +#include "private.h" + #include -#include #include /* Internal struct to store the emulated PCI registers. */ diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index d6310104ea..d104efbce2 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -7,18 +7,7 @@ #include #include -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 #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) {