diff --git a/tools/include/xen-tools/common-macros.h b/tools/include/xen-tools/common-macros.h index 88b4a0e5a6..1f9146b23b 100644 --- a/tools/include/xen-tools/common-macros.h +++ b/tools/include/xen-tools/common-macros.h @@ -68,6 +68,8 @@ }) #endif +#define IS_ALIGNED(val, align) (!((val) & ((align) - 1))) + #define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUNDDOWN(x, a) ((x) & ~((a) - 1)) diff --git a/xen/arch/x86/x86_64/pci.c b/xen/arch/x86/x86_64/pci.c index 8d33429103..6298141c3c 100644 --- a/xen/arch/x86/x86_64/pci.c +++ b/xen/arch/x86/x86_64/pci.c @@ -26,7 +26,7 @@ uint8_t pci_conf_read8(pci_sbdf_t sbdf, unsigned int reg) uint16_t pci_conf_read16(pci_sbdf_t sbdf, unsigned int reg) { - if ( sbdf.seg || reg > 255 ) + if ( sbdf.seg || reg > 255 || !IS_ALIGNED(reg, 2) ) { uint32_t value; @@ -39,7 +39,7 @@ uint16_t pci_conf_read16(pci_sbdf_t sbdf, unsigned int reg) uint32_t pci_conf_read32(pci_sbdf_t sbdf, unsigned int reg) { - if ( sbdf.seg || reg > 255 ) + if ( sbdf.seg || reg > 255 || !IS_ALIGNED(reg, 4) ) { uint32_t value; @@ -60,7 +60,7 @@ void pci_conf_write8(pci_sbdf_t sbdf, unsigned int reg, uint8_t data) void pci_conf_write16(pci_sbdf_t sbdf, unsigned int reg, uint16_t data) { - if ( sbdf.seg || reg > 255 ) + if ( sbdf.seg || reg > 255 || !IS_ALIGNED(reg, 2) ) pci_mmcfg_write(sbdf.seg, sbdf.bus, sbdf.devfn, reg, 2, data); else pci_conf_write(PCI_CONF_ADDRESS(sbdf, reg), reg & 2, 2, data); @@ -68,7 +68,7 @@ void pci_conf_write16(pci_sbdf_t sbdf, unsigned int reg, uint16_t data) void pci_conf_write32(pci_sbdf_t sbdf, unsigned int reg, uint32_t data) { - if ( sbdf.seg || reg > 255 ) + if ( sbdf.seg || reg > 255 || !IS_ALIGNED(reg, 4) ) pci_mmcfg_write(sbdf.seg, sbdf.bus, sbdf.devfn, reg, 4, data); else pci_conf_write(PCI_CONF_ADDRESS(sbdf, reg), 0, 4, data); diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c index 0ac9ec8b04..9e2c27e3a3 100644 --- a/xen/drivers/vpci/vpci.c +++ b/xen/drivers/vpci/vpci.c @@ -685,6 +685,8 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size, /* Helper function to check an access size and alignment on vpci space. */ bool vpci_access_allowed(unsigned int reg, unsigned int len) { + const struct domain *currd = current->domain; + /* Check access size. */ if ( len != 1 && len != 2 && len != 4 && len != 8 ) return false; @@ -695,8 +697,8 @@ bool vpci_access_allowed(unsigned int reg, unsigned int len) return false; #endif - /* Check that access is size aligned. */ - if ( (reg & (len - 1)) ) + /* Refuse unaligned accesses for non-hardware domains. */ + if ( !is_hardware_domain(currd) && !IS_ALIGNED(reg, len) ) return false; return true;