Skip to content

Commit

Permalink
hv: Add bit representation for MSI addr and data
Browse files Browse the repository at this point in the history
As we enable Interrupt Remapping, bit positions in MSI address and
data registers have a different syntax for programming. This patch adds
bit granularity for MSI address and data structs.

Tracked-On: #2407
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
  • Loading branch information
Sainath Grandhi authored and wenlingz committed Jan 26, 2019
1 parent 6825043 commit 7d57eb0
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 55 deletions.
37 changes: 19 additions & 18 deletions hypervisor/arch/x86/assign.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,32 +77,33 @@ static void ptirq_build_physical_msi(struct acrn_vm *vm, struct ptirq_msi_info *
bool phys;

/* get physical destination cpu mask */
dest = (uint32_t)(info->vmsi_addr & MSI_ADDR_DEST) >> MSI_ADDR_DEST_SHIFT;
phys = ((info->vmsi_addr & MSI_ADDR_LOG) != MSI_ADDR_LOG);
dest = info->vmsi_addr.bits.dest_field;
phys = (info->vmsi_addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS);

vlapic_calcdest(vm, &vdmask, dest, phys, false);
pdmask = vcpumask2pcpumask(vm, vdmask);

/* get physical delivery mode */
delmode = info->vmsi_data & APIC_DELMODE_MASK;
if ((delmode != APIC_DELMODE_FIXED) && (delmode != APIC_DELMODE_LOWPRIO)) {
delmode = APIC_DELMODE_LOWPRIO;
delmode = info->vmsi_data.bits.delivery_mode;
if ((delmode != MSI_DATA_DELMODE_FIXED) && (delmode != MSI_DATA_DELMODE_LOPRI)) {
delmode = MSI_DATA_DELMODE_LOPRI;
}

/* update physical delivery mode & vector */
info->pmsi_data = info->vmsi_data;
info->pmsi_data &= ~0x7FFU;
info->pmsi_data |= delmode | vector;
info->pmsi_data.bits.delivery_mode = delmode;
info->pmsi_data.bits.vector = vector;

dest_mask = calculate_logical_dest_mask(pdmask);
/* update physical dest mode & dest field */
info->pmsi_addr = info->vmsi_addr;
info->pmsi_addr &= ~0xFF00CU;
info->pmsi_addr |= (dest_mask << MSI_ADDR_DEST_SHIFT) | MSI_ADDR_RH | MSI_ADDR_LOG;
info->pmsi_addr.bits.dest_mode = MSI_ADDR_DESTMODE_LOGICAL;
info->pmsi_addr.bits.rh = MSI_ADDR_RH;
info->pmsi_addr.bits.dest_field = dest_mask;

dev_dbg(ACRN_DBG_IRQ, "MSI addr:data = 0x%llx:%x(V) -> 0x%llx:%x(P)",
info->vmsi_addr, info->vmsi_data,
info->pmsi_addr, info->pmsi_data);
info->vmsi_addr.full, info->vmsi_data.full,
info->pmsi_addr.full, info->pmsi_data.full);
}

static union ioapic_rte
Expand Down Expand Up @@ -442,14 +443,14 @@ void ptirq_softirq(uint16_t pcpu_id)
} else {
if (msi != NULL) {
/* TODO: msi destmode check required */
(void)vlapic_intr_msi(vm, msi->vmsi_addr, msi->vmsi_data);
(void)vlapic_intr_msi(vm, msi->vmsi_addr.full, msi->vmsi_data.full);
dev_dbg(ACRN_DBG_PTIRQ, "dev-assign: irq=0x%x MSI VR: 0x%x-0x%x",
entry->allocated_pirq,
msi->vmsi_data & 0xFFU,
msi->vmsi_data.bits.vector,
irq_to_vector(entry->allocated_pirq));
dev_dbg(ACRN_DBG_PTIRQ, " vmsi_addr: 0x%llx vmsi_data: 0x%x",
msi->vmsi_addr,
msi->vmsi_data);
msi->vmsi_addr.full,
msi->vmsi_data.full);
}
}
}
Expand Down Expand Up @@ -534,16 +535,16 @@ int32_t ptirq_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf,
spinlock_release(&ptdev_lock);

if (entry != NULL) {
if (is_entry_active(entry) && (info->vmsi_data == 0U)) {
if (is_entry_active(entry) && (info->vmsi_data.full == 0U)) {
/* handle destroy case */
info->pmsi_data = 0U;
info->pmsi_data.full = 0U;
} else {
/* build physical config MSI, update to info->pmsi_xxx */
ptirq_build_physical_msi(vm, info, irq_to_vector(entry->allocated_pirq));
entry->msi = *info;
dev_dbg(ACRN_DBG_IRQ, "PCI %x:%x.%x MSI VR[%d] 0x%x->0x%x assigned to vm%d",
pci_bus(virt_bdf), pci_slot(virt_bdf), pci_func(virt_bdf), entry_nr,
info->vmsi_data & 0xFFU, irq_to_vector(entry->allocated_pirq), entry->vm->vm_id);
info->vmsi_data.bits.vector, irq_to_vector(entry->allocated_pirq), entry->vm->vm_id);
}
ret = 0;
}
Expand Down
20 changes: 12 additions & 8 deletions hypervisor/arch/x86/guest/vlapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1940,10 +1940,14 @@ vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg)
uint32_t dest;
bool phys, rh;
int32_t ret;
union msi_addr_reg address;
union msi_data_reg data;

dev_dbg(ACRN_DBG_LAPIC, "lapic MSI addr: %#lx msg: %#lx", addr, msg);
address.full = addr;
data.full = (uint32_t) msg;
dev_dbg(ACRN_DBG_LAPIC, "lapic MSI addr: %#lx msg: %#lx", address.full, data.full);

if ((addr & MSI_ADDR_MASK) == MSI_ADDR_BASE) {
if (address.bits.addr_base == MSI_ADDR_BASE) {
/*
* Extract the x86-specific fields from the MSI addr/msg
* params according to the Intel Arch spec, Vol3 Ch 10.
Expand All @@ -1955,20 +1959,20 @@ vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg)
* the Redirection Hint and Destination Mode are '1' and
* physical otherwise.
*/
dest = (uint32_t)(addr >> 12U) & 0xffU;
phys = ((addr & MSI_ADDR_LOG) != MSI_ADDR_LOG);
rh = ((addr & MSI_ADDR_RH) == MSI_ADDR_RH);
dest = address.bits.dest_field;
phys = (address.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS);
rh = (address.bits.rh == MSI_ADDR_RH);

delmode = (uint32_t)msg & APIC_DELMODE_MASK;
vec = (uint32_t)msg & 0xffU;
delmode = data.bits.delivery_mode;
vec = data.bits.vector;

dev_dbg(ACRN_DBG_LAPIC, "lapic MSI %s dest %#x, vec %u",
phys ? "physical" : "logical", dest, vec);

vlapic_deliver_intr(vm, LAPIC_TRIG_EDGE, dest, phys, delmode, vec, rh);
ret = 0;
} else {
dev_dbg(ACRN_DBG_LAPIC, "lapic MSI invalid addr %#lx", addr);
dev_dbg(ACRN_DBG_LAPIC, "lapic MSI invalid addr %#lx", address.full);
ret = -1;
}

Expand Down
4 changes: 2 additions & 2 deletions hypervisor/debug/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,8 +907,8 @@ static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
if (is_entry_active(entry)) {
if (entry->intr_type == PTDEV_INTR_MSI) {
(void)strncpy_s(type, 16U, "MSI", 16U);
*dest = (entry->msi.pmsi_addr & 0xFF000U) >> PAGE_SHIFT;
if ((entry->msi.pmsi_data & APIC_TRIGMOD_LEVEL) != 0U) {
*dest = entry->msi.pmsi_addr.bits.dest_field;
if (entry->msi.pmsi_data.bits.trigger_mode == MSI_DATA_TRGRMODE_LEVEL) {
*lvl_tm = true;
} else {
*lvl_tm = false;
Expand Down
14 changes: 7 additions & 7 deletions hypervisor/dm/vpci/msi.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,24 @@ static int32_t vmsi_remap(const struct pci_vdev *vdev, bool enable)
}

info.is_msix = 0;
info.vmsi_addr = (uint64_t)addrlo | ((uint64_t)addrhi << 32U);
info.vmsi_addr.full = (uint64_t)addrlo | ((uint64_t)addrhi << 32U);

/* MSI is being enabled or disabled */
if (enable) {
info.vmsi_data = msgdata;
info.vmsi_data.full = msgdata;
} else {
info.vmsi_data = 0U;
info.vmsi_data.full = 0U;
}

ret = ptirq_msix_remap(vm, vdev->vbdf.value, 0U, &info);
if (ret == 0) {
/* Update MSI Capability structure to physical device */
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_ADDR, 0x4U, (uint32_t)info.pmsi_addr);
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_ADDR, 0x4U, (uint32_t)info.pmsi_addr.full);
if ((msgctrl & PCIM_MSICTRL_64BIT) != 0U) {
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_ADDR_HIGH, 0x4U, (uint32_t)(info.pmsi_addr >> 32U));
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_DATA_64BIT, 0x2U, (uint16_t)info.pmsi_data);
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_ADDR_HIGH, 0x4U, (uint32_t)(info.pmsi_addr.full >> 32U));
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_DATA_64BIT, 0x2U, (uint16_t)info.pmsi_data.full);
} else {
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_DATA, 0x2U, (uint16_t)info.pmsi_data);
pci_pdev_write_cfg(pbdf, capoff + PCIR_MSI_DATA, 0x2U, (uint16_t)info.pmsi_data.full);
}

/* If MSI Enable is being set, make sure INTxDIS bit is set */
Expand Down
10 changes: 5 additions & 5 deletions hypervisor/dm/vpci/msix.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ static int32_t vmsix_remap_entry(const struct pci_vdev *vdev, uint32_t index, bo
int32_t ret;

info.is_msix = 1;
info.vmsi_addr = vdev->msix.tables[index].addr;
info.vmsi_data = (enable) ? vdev->msix.tables[index].data : 0U;
info.vmsi_addr.full = vdev->msix.tables[index].addr;
info.vmsi_data.full = (enable) ? vdev->msix.tables[index].data : 0U;

ret = ptirq_msix_remap(vdev->vpci->vm, vdev->vbdf.value, (uint16_t)index, &info);
if (ret == 0) {
Expand All @@ -71,10 +71,10 @@ static int32_t vmsix_remap_entry(const struct pci_vdev *vdev, uint32_t index, bo
* write only
*/
stac();
mmio_write32((uint32_t)(info.pmsi_addr), (void *)&(pentry->addr));
mmio_write32((uint32_t)(info.pmsi_addr >> 32U), (void *)((char *)&(pentry->addr) + 4U));
mmio_write32((uint32_t)(info.pmsi_addr.full), (void *)&(pentry->addr));
mmio_write32((uint32_t)(info.pmsi_addr.full >> 32U), (void *)((char *)&(pentry->addr) + 4U));

mmio_write32(info.pmsi_data, (void *)&(pentry->data));
mmio_write32(info.pmsi_data.full, (void *)&(pentry->data));
mmio_write32(vdev->msix.tables[index].vector_control, (void *)&(pentry->vector_control));
clac();
}
Expand Down
11 changes: 0 additions & 11 deletions hypervisor/include/arch/x86/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,6 @@ uint32_t alloc_irq_vector(uint32_t irq);
*/
uint32_t irq_to_vector(uint32_t irq);

/*
* Some MSI message definitions
*/
#define MSI_ADDR_MASK 0xfff00000UL
#define MSI_ADDR_BASE 0xfee00000UL
#define MSI_ADDR_RH 0x00000008UL /* Redirection Hint */
#define MSI_ADDR_LOG 0x00000004UL /* Destination Mode */
#define MSI_ADDR_DEST 0x000FF000UL /* Destination Field */

#define MSI_ADDR_DEST_SHIFT (12U)

/* RFLAGS */
#define HV_ARCH_VCPU_RFLAGS_IF (1UL<<9U)

Expand Down
51 changes: 47 additions & 4 deletions hypervisor/include/common/ptdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,55 @@ union source_id {
} intx_id;
};

/*
* Macros for bits in union msi_addr_reg
*/

#define MSI_ADDR_BASE 0xfeeUL /* Base address for MSI messages */
#define MSI_ADDR_RH 0x1U /* Redirection Hint */
#define MSI_ADDR_DESTMODE_LOGICAL 0x1U /* Destination Mode: Logical*/
#define MSI_ADDR_DESTMODE_PHYS 0x0U /* Destination Mode: Physical*/

union msi_addr_reg {
uint64_t full;
struct {
uint32_t rsvd_1:2;
uint32_t dest_mode:1;
uint32_t rh:1;
uint32_t rsvd_2:8;
uint32_t dest_field:8;
uint32_t addr_base:12;
uint32_t hi_32;
} bits __packed;
};

/*
* Macros for bits in union msi_data_reg
*/

#define MSI_DATA_DELMODE_FIXED 0x0U /* Delivery Mode: Fixed */
#define MSI_DATA_DELMODE_LOPRI 0x1U /* Delivery Mode: Low Priority */
#define MSI_DATA_TRGRMODE_EDGE 0x0U /* Trigger Mode: Edge */
#define MSI_DATA_TRGRMODE_LEVEL 0x1U /* Trigger Mode: Level */

union msi_data_reg {
uint32_t full;
struct {
uint32_t vector:8;
uint32_t delivery_mode:3;
uint32_t rsvd_1:3;
uint32_t level:1;
uint32_t trigger_mode:1;
uint32_t rsvd_2:16;
} bits __packed;
};

/* entry per guest virt vector */
struct ptirq_msi_info {
uint64_t vmsi_addr; /* virt msi_addr */
uint32_t vmsi_data; /* virt msi_data */
uint64_t pmsi_addr; /* phys msi_addr */
uint32_t pmsi_data; /* phys msi_data */
union msi_addr_reg vmsi_addr; /* virt msi_addr */
union msi_data_reg vmsi_data; /* virt msi_data */
union msi_addr_reg pmsi_addr; /* phys msi_addr */
union msi_data_reg pmsi_data; /* phys msi_data */
int32_t is_msix; /* 0-MSI, 1-MSIX */
};

Expand Down

0 comments on commit 7d57eb0

Please sign in to comment.