mirror of
https://github.com/qemu/qemu.git
synced 2024-11-30 07:13:38 +08:00
msix: function mask support
Function mask is a mandatory feature in MSIX spec so not implementing it is a spec violation. Implement. Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
2760952ba9
commit
5b5cb08683
64
hw/msix.c
64
hw/msix.c
@ -20,6 +20,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 */
|
||||
@ -30,6 +31,7 @@
|
||||
/* 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
|
||||
@ -101,22 +103,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_CONTROL_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_CONTROL_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;
|
||||
@ -157,10 +148,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,
|
||||
@ -170,10 +201,7 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
|
||||
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
|
||||
int vector = offset / MSIX_ENTRY_SIZE;
|
||||
pci_set_long(dev->msix_table_page + offset, val);
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user