summaryrefslogtreecommitdiff
path: root/hw/msix.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-14 16:54:46 +0200
committerAvi Kivity <avi@redhat.com>2009-12-14 16:54:46 +0200
commit4c15e26323b38f4b5688eb3cb5b3b27e792c1f0d (patch)
tree7cc9bb0c932c159bf60275e762bfaed231b50077 /hw/msix.c
parentRevert "Temporarily avoid loading pxe option roms" (diff)
parentmsix: function mask support (diff)
downloadqemu-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.c74
1 files changed, 51 insertions, 23 deletions
diff --git a/hw/msix.c b/hw/msix.c
index 6d598ee24..d117bcfaa 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -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);
}