diff options
author | Avi Kivity <avi@redhat.com> | 2009-12-14 16:54:46 +0200 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-12-14 16:54:46 +0200 |
commit | 4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d (patch) | |
tree | 7cc9bb0c932c159bf60275e762bfaed231b50077 /hw/msix.c | |
parent | Revert "Temporarily avoid loading pxe option roms" (diff) | |
parent | msix: function mask support (diff) | |
download | qemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.tar.gz qemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.tar.bz2 qemu-kvm-4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d.zip |
Merge commit 'c99d32efe6970493c44fe410ee4a4aafc1a35428' into stable-0.12-merge
* commit 'c99d32efe6970493c44fe410ee4a4aafc1a35428':
msix: function mask support
msix: macro rename for function mask support
cpuid: Fix multicore setup on Intel
kvm: x86: Fix initial kvm_has_msr_star
Update OpenBIOS images to r640
Update version to -rc1
Conflicts:
hw/msix.c
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'hw/msix.c')
-rw-r--r-- | hw/msix.c | 74 |
1 files changed, 51 insertions, 23 deletions
@@ -22,6 +22,7 @@ #define PCI_MSIX_FLAGS 2 /* Table at lower 11 bits */ #define PCI_MSIX_FLAGS_QSIZE 0x7FF #define PCI_MSIX_FLAGS_ENABLE (1 << 15) +#define PCI_MSIX_FLAGS_MASKALL (1 << 14) #define PCI_MSIX_FLAGS_BIRMASK (7 << 0) /* MSI-X capability structure */ @@ -29,9 +30,10 @@ #define MSIX_PBA_OFFSET 8 #define MSIX_CAP_LENGTH 12 -/* MSI enable bit is in byte 1 in FLAGS register */ -#define MSIX_ENABLE_OFFSET (PCI_MSIX_FLAGS + 1) +/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */ +#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1) #define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8) +#define MSIX_MASKALL_MASK (PCI_MSIX_FLAGS_MASKALL >> 8) /* MSI-X table format */ #define MSIX_MSG_ADDR 0 @@ -214,22 +216,11 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries, bar_nr); pdev->msix_cap = config_offset; /* Make flags bit writeable. */ - pdev->wmask[config_offset + MSIX_ENABLE_OFFSET] |= MSIX_ENABLE_MASK; + pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK | + MSIX_MASKALL_MASK; return 0; } -/* Handle MSI-X capability config write. */ -void msix_write_config(PCIDevice *dev, uint32_t addr, - uint32_t val, int len) -{ - unsigned enable_pos = dev->msix_cap + MSIX_ENABLE_OFFSET; - if (addr + len <= enable_pos || addr > enable_pos) - return; - - if (msix_enabled(dev)) - qemu_set_irq(dev->irq[0], 0); -} - static uint32_t msix_mmio_readl(void *opaque, target_phys_addr_t addr) { PCIDevice *dev = opaque; @@ -270,10 +261,50 @@ static void msix_clr_pending(PCIDevice *dev, int vector) *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector); } +static int msix_function_masked(PCIDevice *dev) +{ + return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK; +} + static int msix_is_masked(PCIDevice *dev, int vector) { unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL; - return dev->msix_table_page[offset] & MSIX_VECTOR_MASK; + return msix_function_masked(dev) || + dev->msix_table_page[offset] & MSIX_VECTOR_MASK; +} + +static void msix_handle_mask_update(PCIDevice *dev, int vector) +{ + if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) { + msix_clr_pending(dev, vector); + msix_notify(dev, vector); + } +} + +/* Handle MSI-X capability config write. */ +void msix_write_config(PCIDevice *dev, uint32_t addr, + uint32_t val, int len) +{ + unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET; + int vector; + + if (addr + len <= enable_pos || addr > enable_pos) { + return; + } + + if (!msix_enabled(dev)) { + return; + } + + qemu_set_irq(dev->irq[0], 0); + + if (msix_function_masked(dev)) { + return; + } + + for (vector = 0; vector < dev->msix_entries_nr; ++vector) { + msix_handle_mask_update(dev, vector); + } } static void msix_mmio_writel(void *opaque, target_phys_addr_t addr, @@ -287,10 +318,7 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr, if (kvm_enabled() && kvm_irqchip_in_kernel()) { kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector)); } - if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) { - msix_clr_pending(dev, vector); - msix_notify(dev, vector); - } + msix_handle_mask_update(dev, vector); } static void msix_mmio_write_unallowed(void *opaque, target_phys_addr_t addr, @@ -462,7 +490,7 @@ int msix_present(PCIDevice *dev) int msix_enabled(PCIDevice *dev) { return (dev->cap_present & QEMU_PCI_CAP_MSIX) && - (dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] & + (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_ENABLE_MASK); } @@ -505,8 +533,8 @@ void msix_reset(PCIDevice *dev) if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return; msix_free_irq_entries(dev); - dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= - ~dev->wmask[dev->msix_cap + MSIX_ENABLE_OFFSET]; + dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &= + ~dev->wmask[dev->msix_cap + MSIX_CONTROL_OFFSET]; memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE); msix_mask_all(dev, dev->msix_entries_nr); } |