hv: Add bit representation for MSI addr and data

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>
This commit is contained in:
Sainath Grandhi
2019-01-26 01:31:14 -08:00
committed by wenlingz
parent 6825043078
commit 7d57eb056e
7 changed files with 92 additions and 55 deletions

View File

@@ -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
@@ -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);
}
}
}
@@ -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;
}

View File

@@ -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.
@@ -1955,12 +1959,12 @@ 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);
@@ -1968,7 +1972,7 @@ vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg)
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;
}