mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 14:33:38 +00:00
hv: Introduce Global System Interrupt (GSI) into INTx Remapping
As ACRN prepares to support platforms with multiple IO-APICs, GSI is a better way to represent physical and virtual INTx interrupt source. 1) This patch replaces usage of "pin" with "gsi" whereever applicable across the modules. 2) PIC pin to gsi is trickier and needs to consider the usage of "Interrupt Source Override" structure in ACPI for the corresponding VM. Tracked-On: #4151 Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Acked-by: Eddie Dong <eddie.dong@Intel.com>
This commit is contained in:
parent
b0997e7606
commit
ec86921444
@ -170,18 +170,18 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
|||||||
union ioapic_rte virt_rte;
|
union ioapic_rte virt_rte;
|
||||||
bool phys;
|
bool phys;
|
||||||
|
|
||||||
vioapic_get_rte(vm, virt_sid->intx_id.pin, &virt_rte);
|
vioapic_get_rte(vm, virt_sid->intx_id.gsi, &virt_rte);
|
||||||
rte = virt_rte;
|
rte = virt_rte;
|
||||||
|
|
||||||
/* init polarity & pin state */
|
/* init polarity & pin state */
|
||||||
if (rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) {
|
if (rte.bits.intr_polarity == IOAPIC_RTE_INTPOL_ALO) {
|
||||||
if (entry->polarity == 0U) {
|
if (entry->polarity == 0U) {
|
||||||
vioapic_set_irqline_nolock(vm, virt_sid->intx_id.pin, GSI_SET_HIGH);
|
vioapic_set_irqline_nolock(vm, virt_sid->intx_id.gsi, GSI_SET_HIGH);
|
||||||
}
|
}
|
||||||
entry->polarity = 1U;
|
entry->polarity = 1U;
|
||||||
} else {
|
} else {
|
||||||
if (entry->polarity == 1U) {
|
if (entry->polarity == 1U) {
|
||||||
vioapic_set_irqline_nolock(vm, virt_sid->intx_id.pin, GSI_SET_LOW);
|
vioapic_set_irqline_nolock(vm, virt_sid->intx_id.gsi, GSI_SET_LOW);
|
||||||
}
|
}
|
||||||
entry->polarity = 0U;
|
entry->polarity = 0U;
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
|
|||||||
ioapic_get_rte(phys_irq, &phys_rte);
|
ioapic_get_rte(phys_irq, &phys_rte);
|
||||||
rte = phys_rte;
|
rte = phys_rte;
|
||||||
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_EDGE;
|
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_EDGE;
|
||||||
vpic_get_irqline_trigger_mode(vm_pic(vm), (uint32_t)virt_sid->intx_id.pin, &trigger);
|
vpic_get_irqline_trigger_mode(vm_pic(vm), (uint32_t)virt_sid->intx_id.gsi, &trigger);
|
||||||
if (trigger == LEVEL_TRIGGER) {
|
if (trigger == LEVEL_TRIGGER) {
|
||||||
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_LEVEL;
|
rte.bits.trigger_mode = IOAPIC_RTE_TRGRMODE_LEVEL;
|
||||||
}
|
}
|
||||||
@ -342,13 +342,13 @@ remove_msix_remapping(const struct acrn_vm *vm, uint16_t virt_bdf, uint32_t entr
|
|||||||
* - if the entry already be added by sos_vm, then change the owner to current vm
|
* - if the entry already be added by sos_vm, then change the owner to current vm
|
||||||
* - if the entry already be added by other vm, return NULL
|
* - if the entry already be added by other vm, return NULL
|
||||||
*/
|
*/
|
||||||
static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin,
|
static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi,
|
||||||
uint32_t phys_pin, enum intx_ctlr vpin_ctlr)
|
uint32_t phys_gsi, enum intx_ctlr vgsi_ctlr)
|
||||||
{
|
{
|
||||||
struct ptirq_remapping_info *entry = NULL;
|
struct ptirq_remapping_info *entry = NULL;
|
||||||
DEFINE_INTX_SID(phys_sid, phys_pin, INTX_CTLR_IOAPIC);
|
DEFINE_INTX_SID(phys_sid, phys_gsi, INTX_CTLR_IOAPIC);
|
||||||
DEFINE_INTX_SID(virt_sid, virt_pin, vpin_ctlr);
|
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
|
||||||
uint32_t phys_irq = ioapic_pin_to_irq(phys_pin);
|
uint32_t phys_irq = ioapic_gsi_to_irq(phys_gsi);
|
||||||
|
|
||||||
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL);
|
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
@ -366,7 +366,7 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_err("INTX re-add vpin %d", virt_pin);
|
pr_err("INTX re-add vpin %d", virt_gsi);
|
||||||
}
|
}
|
||||||
} else if (entry->vm != vm) {
|
} else if (entry->vm != vm) {
|
||||||
if (is_sos_vm(entry->vm)) {
|
if (is_sos_vm(entry->vm)) {
|
||||||
@ -374,8 +374,8 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
|
|||||||
entry->virt_sid.value = virt_sid.value;
|
entry->virt_sid.value = virt_sid.value;
|
||||||
entry->polarity = 0U;
|
entry->polarity = 0U;
|
||||||
} else {
|
} else {
|
||||||
pr_err("INTX pin%d already in vm%d with vpin%d, not able to add into vm%d with vpin%d",
|
pr_err("INTX gsi%d already in vm%d with vgsi%d, not able to add into vm%d with vgsi%d",
|
||||||
phys_pin, entry->vm->vm_id, entry->virt_sid.intx_id.pin, vm->vm_id, virt_pin);
|
phys_gsi, entry->vm->vm_id, entry->virt_sid.intx_id.gsi, vm->vm_id, virt_gsi);
|
||||||
entry = NULL;
|
entry = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -389,20 +389,20 @@ static struct ptirq_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint3
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
dev_dbg(DBG_LEVEL_IRQ, "VM%d INTX add pin mapping vpin%d:ppin%d",
|
dev_dbg(DBG_LEVEL_IRQ, "VM%d INTX add pin mapping vgsi%d:pgsi%d",
|
||||||
entry->vm->vm_id, virt_pin, phys_pin);
|
entry->vm->vm_id, virt_gsi, phys_gsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deactive & remove mapping entry of vpin for vm */
|
/* deactive & remove mapping entry of vpin for vm */
|
||||||
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_ctlr)
|
static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr)
|
||||||
{
|
{
|
||||||
uint32_t phys_irq;
|
uint32_t phys_irq;
|
||||||
struct ptirq_remapping_info *entry;
|
struct ptirq_remapping_info *entry;
|
||||||
struct intr_source intr_src;
|
struct intr_source intr_src;
|
||||||
DEFINE_INTX_SID(virt_sid, virt_pin, vpin_ctlr);
|
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
|
||||||
|
|
||||||
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
@ -417,11 +417,11 @@ static void remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_pin, e
|
|||||||
|
|
||||||
dmar_free_irte(intr_src, (uint16_t)phys_irq);
|
dmar_free_irte(intr_src, (uint16_t)phys_irq);
|
||||||
dev_dbg(DBG_LEVEL_IRQ,
|
dev_dbg(DBG_LEVEL_IRQ,
|
||||||
"deactive %s intx entry:ppin=%d, pirq=%d ",
|
"deactive %s intx entry:pgsi=%d, pirq=%d ",
|
||||||
(vpin_ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
|
(vgsi_ctlr == INTX_CTLR_PIC) ? "vPIC" : "vIOAPIC",
|
||||||
entry->phys_sid.intx_id.pin, phys_irq);
|
entry->phys_sid.intx_id.gsi, phys_irq);
|
||||||
dev_dbg(DBG_LEVEL_IRQ, "from vm%d vpin=%d\n",
|
dev_dbg(DBG_LEVEL_IRQ, "from vm%d vgsi=%d\n",
|
||||||
entry->vm->vm_id, virt_pin);
|
entry->vm->vm_id, virt_gsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptirq_release_entry(entry);
|
ptirq_release_entry(entry);
|
||||||
@ -439,22 +439,22 @@ static void ptirq_handle_intx(struct acrn_vm *vm,
|
|||||||
bool trigger_lvl = false;
|
bool trigger_lvl = false;
|
||||||
|
|
||||||
/* INTX_CTLR_IOAPIC means we have vioapic enabled */
|
/* INTX_CTLR_IOAPIC means we have vioapic enabled */
|
||||||
vioapic_get_rte(vm, (uint32_t)virt_sid->intx_id.pin, &rte);
|
vioapic_get_rte(vm, (uint32_t)virt_sid->intx_id.gsi, &rte);
|
||||||
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
if (rte.bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL) {
|
||||||
trigger_lvl = true;
|
trigger_lvl = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigger_lvl) {
|
if (trigger_lvl) {
|
||||||
if (entry->polarity != 0U) {
|
if (entry->polarity != 0U) {
|
||||||
vioapic_set_irqline_lock(vm, virt_sid->intx_id.pin, GSI_SET_LOW);
|
vioapic_set_irqline_lock(vm, virt_sid->intx_id.gsi, GSI_SET_LOW);
|
||||||
} else {
|
} else {
|
||||||
vioapic_set_irqline_lock(vm, virt_sid->intx_id.pin, GSI_SET_HIGH);
|
vioapic_set_irqline_lock(vm, virt_sid->intx_id.gsi, GSI_SET_HIGH);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entry->polarity != 0U) {
|
if (entry->polarity != 0U) {
|
||||||
vioapic_set_irqline_lock(vm, virt_sid->intx_id.pin, GSI_FALLING_PULSE);
|
vioapic_set_irqline_lock(vm, virt_sid->intx_id.gsi, GSI_FALLING_PULSE);
|
||||||
} else {
|
} else {
|
||||||
vioapic_set_irqline_lock(vm, virt_sid->intx_id.pin, GSI_RAISING_PULSE);
|
vioapic_set_irqline_lock(vm, virt_sid->intx_id.gsi, GSI_RAISING_PULSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,11 +470,11 @@ static void ptirq_handle_intx(struct acrn_vm *vm,
|
|||||||
enum vpic_trigger trigger;
|
enum vpic_trigger trigger;
|
||||||
|
|
||||||
/* INTX_CTLR_PIC means we have vpic enabled */
|
/* INTX_CTLR_PIC means we have vpic enabled */
|
||||||
vpic_get_irqline_trigger_mode(vm_pic(vm), virt_sid->intx_id.pin, &trigger);
|
vpic_get_irqline_trigger_mode(vm_pic(vm), virt_sid->intx_id.gsi, &trigger);
|
||||||
if (trigger == LEVEL_TRIGGER) {
|
if (trigger == LEVEL_TRIGGER) {
|
||||||
vpic_set_irqline(vm_pic(vm), virt_sid->intx_id.pin, GSI_SET_HIGH);
|
vpic_set_irqline(vm_pic(vm), virt_sid->intx_id.gsi, GSI_SET_HIGH);
|
||||||
} else {
|
} else {
|
||||||
vpic_set_irqline(vm_pic(vm), virt_sid->intx_id.pin, GSI_RAISING_PULSE);
|
vpic_set_irqline(vm_pic(vm), virt_sid->intx_id.gsi, GSI_RAISING_PULSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -525,11 +525,11 @@ void ptirq_softirq(uint16_t pcpu_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ptirq_intx_ack(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_ctlr)
|
void ptirq_intx_ack(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr)
|
||||||
{
|
{
|
||||||
uint32_t phys_irq;
|
uint32_t phys_irq;
|
||||||
struct ptirq_remapping_info *entry;
|
struct ptirq_remapping_info *entry;
|
||||||
DEFINE_INTX_SID(virt_sid, virt_pin, vpin_ctlr);
|
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
|
||||||
|
|
||||||
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
@ -538,20 +538,20 @@ void ptirq_intx_ack(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_c
|
|||||||
/* NOTE: only Level trigger will process EOI/ACK and if we got here
|
/* NOTE: only Level trigger will process EOI/ACK and if we got here
|
||||||
* means we have this vioapic or vpic or both enabled
|
* means we have this vioapic or vpic or both enabled
|
||||||
*/
|
*/
|
||||||
switch (vpin_ctlr) {
|
switch (vgsi_ctlr) {
|
||||||
case INTX_CTLR_IOAPIC:
|
case INTX_CTLR_IOAPIC:
|
||||||
if (entry->polarity != 0U) {
|
if (entry->polarity != 0U) {
|
||||||
vioapic_set_irqline_lock(vm, virt_pin, GSI_SET_HIGH);
|
vioapic_set_irqline_lock(vm, virt_gsi, GSI_SET_HIGH);
|
||||||
} else {
|
} else {
|
||||||
vioapic_set_irqline_lock(vm, virt_pin, GSI_SET_LOW);
|
vioapic_set_irqline_lock(vm, virt_gsi, GSI_SET_LOW);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INTX_CTLR_PIC:
|
case INTX_CTLR_PIC:
|
||||||
vpic_set_irqline(vm_pic(vm), virt_pin, GSI_SET_LOW);
|
vpic_set_irqline(vm_pic(vm), virt_gsi, GSI_SET_LOW);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* In this switch statement, vpin_ctlr shall either be
|
* In this switch statement, vgsi_ctlr shall either be
|
||||||
* INTX_CTLR_IOAPIC or INTX_CTLR_PIC.
|
* INTX_CTLR_IOAPIC or INTX_CTLR_PIC.
|
||||||
* Gracefully return if prior case clauses have not been met.
|
* Gracefully return if prior case clauses have not been met.
|
||||||
*/
|
*/
|
||||||
@ -670,12 +670,12 @@ static void activate_physical_ioapic(struct acrn_vm *vm,
|
|||||||
/* Main entry for PCI/Legacy device assignment with INTx, calling from vIOAPIC
|
/* Main entry for PCI/Legacy device assignment with INTx, calling from vIOAPIC
|
||||||
* or vPIC
|
* or vPIC
|
||||||
*/
|
*/
|
||||||
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_ctlr)
|
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr)
|
||||||
{
|
{
|
||||||
int32_t status = 0;
|
int32_t status = 0;
|
||||||
struct ptirq_remapping_info *entry = NULL;
|
struct ptirq_remapping_info *entry = NULL;
|
||||||
DEFINE_INTX_SID(virt_sid, virt_pin, vpin_ctlr);
|
DEFINE_INTX_SID(virt_sid, virt_gsi, vgsi_ctlr);
|
||||||
DEFINE_INTX_SID(alt_virt_sid, virt_pin, vpin_ctlr);
|
DEFINE_INTX_SID(alt_virt_sid, virt_gsi, vgsi_ctlr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* virt pin could come from vpic master, vpic slave or vioapic
|
* virt pin could come from vpic master, vpic slave or vioapic
|
||||||
@ -689,7 +689,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ct
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* no remap for vuart intx */
|
/* no remap for vuart intx */
|
||||||
if (!is_vuart_intx(vm, virt_sid.intx_id.pin)) {
|
if (!is_vuart_intx(vm, virt_sid.intx_id.gsi)) {
|
||||||
/* query if we have virt to phys mapping */
|
/* query if we have virt to phys mapping */
|
||||||
spinlock_obtain(&ptdev_lock);
|
spinlock_obtain(&ptdev_lock);
|
||||||
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm);
|
||||||
@ -703,38 +703,32 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ct
|
|||||||
* the other vpin source for legacy pin. If yes, then
|
* the other vpin source for legacy pin. If yes, then
|
||||||
* switch vpin source is needed
|
* switch vpin source is needed
|
||||||
*/
|
*/
|
||||||
if (virt_pin < NR_LEGACY_PIN) {
|
if (virt_gsi < NR_LEGACY_PIN) {
|
||||||
uint32_t vpin = get_pic_pin_from_ioapic_pin(virt_pin);
|
|
||||||
|
|
||||||
if (vpin_ctlr == INTX_CTLR_PIC) {
|
if (vgsi_ctlr == INTX_CTLR_PIC) {
|
||||||
alt_virt_sid.intx_id.ctlr = INTX_CTLR_IOAPIC;
|
alt_virt_sid.intx_id.ctlr = INTX_CTLR_IOAPIC;
|
||||||
} else {
|
} else {
|
||||||
alt_virt_sid.intx_id.ctlr = INTX_CTLR_PIC;
|
alt_virt_sid.intx_id.ctlr = INTX_CTLR_PIC;
|
||||||
}
|
}
|
||||||
alt_virt_sid.intx_id.pin = vpin;
|
|
||||||
|
|
||||||
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &alt_virt_sid, vm);
|
entry = ptirq_lookup_entry_by_sid(PTDEV_INTR_INTX, &alt_virt_sid, vm);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
entry->virt_sid.value = virt_sid.value;
|
entry->virt_sid.value = virt_sid.value;
|
||||||
dev_dbg(DBG_LEVEL_IRQ,
|
dev_dbg(DBG_LEVEL_IRQ,
|
||||||
"IOAPIC pin=%hhu pirq=%u vpin=%d switch from %s to %s vpin=%d for vm%d",
|
"IOAPIC gsi=%hhu pirq=%u vgsi=%d switch from %s to %s for vm%d",
|
||||||
entry->phys_sid.intx_id.pin,
|
entry->phys_sid.intx_id.gsi,
|
||||||
entry->allocated_pirq, entry->virt_sid.intx_id.pin,
|
entry->allocated_pirq, entry->virt_sid.intx_id.gsi,
|
||||||
(vpin_ctlr == INTX_CTLR_IOAPIC) ? "vPIC" : "vIOAPIC",
|
(vgsi_ctlr == INTX_CTLR_IOAPIC) ? "vPIC" : "vIOAPIC",
|
||||||
(vpin_ctlr == INTX_CTLR_IOAPIC) ? "vIOPIC" : "vPIC",
|
(vgsi_ctlr == INTX_CTLR_IOAPIC) ? "vIOPIC" : "vPIC",
|
||||||
virt_pin, entry->vm->vm_id);
|
entry->vm->vm_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* entry could be updated by above switch check */
|
/* entry could be updated by above switch check */
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
uint32_t phys_pin = virt_pin;
|
uint32_t phys_gsi = virt_gsi;
|
||||||
|
|
||||||
/* fix vPIC pin to correct native IOAPIC pin */
|
entry = add_intx_remapping(vm, virt_gsi, phys_gsi, vgsi_ctlr);
|
||||||
if (vpin_ctlr == INTX_CTLR_PIC) {
|
|
||||||
phys_pin = get_pic_pin_from_ioapic_pin(virt_pin);
|
|
||||||
}
|
|
||||||
entry = add_intx_remapping(vm, virt_pin, phys_pin, vpin_ctlr);
|
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
pr_err("%s, add intx remapping failed",
|
pr_err("%s, add intx remapping failed",
|
||||||
__func__);
|
__func__);
|
||||||
@ -769,13 +763,13 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ct
|
|||||||
* - currently, one phys_pin can only be held by one pin source (vPIC or
|
* - currently, one phys_pin can only be held by one pin source (vPIC or
|
||||||
* vIOAPIC)
|
* vIOAPIC)
|
||||||
*/
|
*/
|
||||||
int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin, uint32_t phys_pin, bool pic_pin)
|
int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi, uint32_t phys_gsi, bool pic_pin)
|
||||||
{
|
{
|
||||||
struct ptirq_remapping_info *entry;
|
struct ptirq_remapping_info *entry;
|
||||||
enum intx_ctlr vpin_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
enum intx_ctlr vgsi_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
||||||
|
|
||||||
spinlock_obtain(&ptdev_lock);
|
spinlock_obtain(&ptdev_lock);
|
||||||
entry = add_intx_remapping(vm, virt_pin, phys_pin, vpin_ctlr);
|
entry = add_intx_remapping(vm, virt_gsi, phys_gsi, vgsi_ctlr);
|
||||||
spinlock_release(&ptdev_lock);
|
spinlock_release(&ptdev_lock);
|
||||||
|
|
||||||
return (entry != NULL) ? 0 : -ENODEV;
|
return (entry != NULL) ? 0 : -ENODEV;
|
||||||
@ -784,12 +778,12 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin, uint32_t
|
|||||||
/*
|
/*
|
||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*/
|
*/
|
||||||
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_pin, bool pic_pin)
|
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, bool pic_pin)
|
||||||
{
|
{
|
||||||
enum intx_ctlr vpin_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
enum intx_ctlr vgsi_ctlr = pic_pin ? INTX_CTLR_PIC : INTX_CTLR_IOAPIC;
|
||||||
|
|
||||||
spinlock_obtain(&ptdev_lock);
|
spinlock_obtain(&ptdev_lock);
|
||||||
remove_intx_remapping(vm, virt_pin, vpin_ctlr);
|
remove_intx_remapping(vm, virt_gsi, vgsi_ctlr);
|
||||||
spinlock_release(&ptdev_lock);
|
spinlock_release(&ptdev_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,18 +301,12 @@ bool ioapic_is_pin_valid(uint32_t pin)
|
|||||||
return (pin != INVALID_INTERRUPT_PIN);
|
return (pin != INVALID_INTERRUPT_PIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ioapic_pin_to_irq(uint32_t pin)
|
/*
|
||||||
|
*@pre ioapic_irq_is_gsi(gsi) == true
|
||||||
|
*/
|
||||||
|
uint32_t ioapic_gsi_to_irq(uint32_t gsi)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
return gsi;
|
||||||
uint32_t irq = IRQ_INVALID;
|
|
||||||
|
|
||||||
for (i = 0U; i < ioapic_nr_gsi; i++) {
|
|
||||||
if (gsi_table_data[i].pin == pin) {
|
|
||||||
irq = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return irq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1054,7 +1054,7 @@ static int32_t shell_show_cpu_int(__unused int32_t argc, __unused char **argv)
|
|||||||
|
|
||||||
static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
||||||
uint32_t *irq, uint32_t *vector, uint64_t *dest, bool *lvl_tm,
|
uint32_t *irq, uint32_t *vector, uint64_t *dest, bool *lvl_tm,
|
||||||
uint32_t *pin, uint32_t *vpin, uint32_t *bdf, uint32_t *vbdf)
|
uint32_t *pgsi, uint32_t *vgsi, uint32_t *bdf, uint32_t *vbdf)
|
||||||
{
|
{
|
||||||
if (is_entry_active(entry)) {
|
if (is_entry_active(entry)) {
|
||||||
if (entry->intr_type == PTDEV_INTR_MSI) {
|
if (entry->intr_type == PTDEV_INTR_MSI) {
|
||||||
@ -1065,8 +1065,8 @@ static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
|||||||
} else {
|
} else {
|
||||||
*lvl_tm = false;
|
*lvl_tm = false;
|
||||||
}
|
}
|
||||||
*pin = INVALID_INTERRUPT_PIN;
|
*pgsi = INVALID_INTERRUPT_PIN;
|
||||||
*vpin = INVALID_INTERRUPT_PIN;
|
*vgsi = INVALID_INTERRUPT_PIN;
|
||||||
*bdf = entry->phys_sid.msi_id.bdf;
|
*bdf = entry->phys_sid.msi_id.bdf;
|
||||||
*vbdf = entry->virt_sid.msi_id.bdf;
|
*vbdf = entry->virt_sid.msi_id.bdf;
|
||||||
} else {
|
} else {
|
||||||
@ -1085,8 +1085,8 @@ static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
|||||||
} else {
|
} else {
|
||||||
*lvl_tm = false;
|
*lvl_tm = false;
|
||||||
}
|
}
|
||||||
*pin = entry->phys_sid.intx_id.pin;
|
*pgsi = entry->phys_sid.intx_id.gsi;
|
||||||
*vpin = entry->virt_sid.intx_id.pin;
|
*vgsi = entry->virt_sid.intx_id.gsi;
|
||||||
*bdf = 0U;
|
*bdf = 0U;
|
||||||
*vbdf = 0U;
|
*vbdf = 0U;
|
||||||
}
|
}
|
||||||
@ -1098,8 +1098,8 @@ static void get_entry_info(const struct ptirq_remapping_info *entry, char *type,
|
|||||||
*vector = 0U;
|
*vector = 0U;
|
||||||
*dest = 0UL;
|
*dest = 0UL;
|
||||||
*lvl_tm = 0;
|
*lvl_tm = 0;
|
||||||
*pin = -1;
|
*pgsi = ~0U;
|
||||||
*vpin = -1;
|
*vgsi = ~0U;
|
||||||
*bdf = 0U;
|
*bdf = 0U;
|
||||||
*vbdf = 0U;
|
*vbdf = 0U;
|
||||||
}
|
}
|
||||||
@ -1115,10 +1115,10 @@ static void get_ptdev_info(char *str_arg, size_t str_max)
|
|||||||
char type[16];
|
char type[16];
|
||||||
uint64_t dest;
|
uint64_t dest;
|
||||||
bool lvl_tm;
|
bool lvl_tm;
|
||||||
uint32_t pin, vpin;
|
uint32_t pgsi, vgsi;
|
||||||
union pci_bdf bdf, vbdf;
|
union pci_bdf bdf, vbdf;
|
||||||
|
|
||||||
len = snprintf(str, size, "\r\nVM\tTYPE\tIRQ\tVEC\tDEST\tTM\tPIN\tVPIN\tBDF\tVBDF");
|
len = snprintf(str, size, "\r\nVM\tTYPE\tIRQ\tVEC\tDEST\tTM\tGSI\tVGSI\tBDF\tVBDF");
|
||||||
if (len >= size) {
|
if (len >= size) {
|
||||||
goto overflow;
|
goto overflow;
|
||||||
}
|
}
|
||||||
@ -1128,7 +1128,7 @@ static void get_ptdev_info(char *str_arg, size_t str_max)
|
|||||||
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
|
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
|
||||||
entry = &ptirq_entries[idx];
|
entry = &ptirq_entries[idx];
|
||||||
if (is_entry_active(entry)) {
|
if (is_entry_active(entry)) {
|
||||||
get_entry_info(entry, type, &irq, &vector, &dest, &lvl_tm, &pin, &vpin,
|
get_entry_info(entry, type, &irq, &vector, &dest, &lvl_tm, &pgsi, &vgsi,
|
||||||
(uint32_t *)&bdf, (uint32_t *)&vbdf);
|
(uint32_t *)&bdf, (uint32_t *)&vbdf);
|
||||||
len = snprintf(str, size, "\r\n%d\t%s\t%d\t0x%X\t0x%X",
|
len = snprintf(str, size, "\r\n%d\t%s\t%d\t0x%X\t0x%X",
|
||||||
entry->vm->vm_id, type, irq, vector, dest);
|
entry->vm->vm_id, type, irq, vector, dest);
|
||||||
@ -1140,7 +1140,7 @@ static void get_ptdev_info(char *str_arg, size_t str_max)
|
|||||||
|
|
||||||
len = snprintf(str, size, "\t%s\t%hhu\t%hhu\t%x:%x.%x\t%x:%x.%x",
|
len = snprintf(str, size, "\t%s\t%hhu\t%hhu\t%x:%x.%x\t%x:%x.%x",
|
||||||
is_entry_active(entry) ? (lvl_tm ? "level" : "edge") : "none",
|
is_entry_active(entry) ? (lvl_tm ? "level" : "edge") : "none",
|
||||||
pin, vpin, bdf.bits.b, bdf.bits.d, bdf.bits.f,
|
pgsi, vgsi, bdf.bits.b, bdf.bits.d, bdf.bits.f,
|
||||||
vbdf.bits.b, vbdf.bits.d, vbdf.bits.f);
|
vbdf.bits.b, vbdf.bits.d, vbdf.bits.f);
|
||||||
if (len >= size) {
|
if (len >= size) {
|
||||||
goto overflow;
|
goto overflow;
|
||||||
@ -1173,7 +1173,7 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid)
|
|||||||
uint32_t delmode, vector, dest;
|
uint32_t delmode, vector, dest;
|
||||||
bool level, phys, remote_irr, mask;
|
bool level, phys, remote_irr, mask;
|
||||||
struct acrn_vm *vm = get_vm_from_vmid(vmid);
|
struct acrn_vm *vm = get_vm_from_vmid(vmid);
|
||||||
uint32_t pin, pincount;
|
uint32_t gsi, pincount;
|
||||||
|
|
||||||
if (is_poweroff_vm(vm)) {
|
if (is_poweroff_vm(vm)) {
|
||||||
len = snprintf(str, size, "\r\nvm is not exist for vmid %hu", vmid);
|
len = snprintf(str, size, "\r\nvm is not exist for vmid %hu", vmid);
|
||||||
@ -1194,8 +1194,8 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid)
|
|||||||
|
|
||||||
pincount = vioapic_pincount(vm);
|
pincount = vioapic_pincount(vm);
|
||||||
rte.full = 0UL;
|
rte.full = 0UL;
|
||||||
for (pin = 0U; pin < pincount; pin++) {
|
for (gsi = 0U; gsi < pincount; gsi++) {
|
||||||
vioapic_get_rte(vm, pin, &rte);
|
vioapic_get_rte(vm, gsi, &rte);
|
||||||
mask = (rte.bits.intr_mask == IOAPIC_RTE_MASK_SET);
|
mask = (rte.bits.intr_mask == IOAPIC_RTE_MASK_SET);
|
||||||
remote_irr = (rte.bits.remote_irr == IOAPIC_RTE_REM_IRR);
|
remote_irr = (rte.bits.remote_irr == IOAPIC_RTE_REM_IRR);
|
||||||
phys = (rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
phys = (rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
|
||||||
@ -1205,7 +1205,7 @@ static void get_vioapic_info(char *str_arg, size_t str_max, uint16_t vmid)
|
|||||||
dest = rte.bits.dest_field;
|
dest = rte.bits.dest_field;
|
||||||
|
|
||||||
len = snprintf(str, size, "\r\n%hhu\t0x%X\t%s\t0x%X\t%s\t%u\t%d\t%d",
|
len = snprintf(str, size, "\r\n%hhu\t0x%X\t%s\t0x%X\t%s\t%u\t%d\t%d",
|
||||||
pin, vector, phys ? "phys" : "logic", dest, level ? "level" : "edge",
|
gsi, vector, phys ? "phys" : "logic", dest, level ? "level" : "edge",
|
||||||
delmode >> 8U, remote_irr, mask);
|
delmode >> 8U, remote_irr, mask);
|
||||||
if (len >= size) {
|
if (len >= size) {
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
@ -130,10 +130,10 @@ vioapic_set_pinstate(struct acrn_vioapic *vioapic, uint32_t pin, uint32_t level)
|
|||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation)
|
vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation)
|
||||||
{
|
{
|
||||||
struct acrn_vioapic *vioapic;
|
struct acrn_vioapic *vioapic;
|
||||||
uint32_t pin = irqline;
|
uint32_t pin = vgsi;
|
||||||
|
|
||||||
vioapic = vm_ioapic(vm);
|
vioapic = vm_ioapic(vm);
|
||||||
|
|
||||||
@ -174,9 +174,10 @@ vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t irqline, uint32_t
|
|||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation)
|
vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation)
|
||||||
{
|
{
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
|
uint32_t irqline = vgsi;
|
||||||
struct acrn_vioapic *vioapic = vm_ioapic(vm);
|
struct acrn_vioapic *vioapic = vm_ioapic(vm);
|
||||||
if (vioapic->ready) {
|
if (vioapic->ready) {
|
||||||
spinlock_irqsave_obtain(&(vioapic->mtx), &rflags);
|
spinlock_irqsave_obtain(&(vioapic->mtx), &rflags);
|
||||||
@ -524,9 +525,10 @@ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_pri
|
|||||||
* @pre vm->arch_vm.vioapic != NULL
|
* @pre vm->arch_vm.vioapic != NULL
|
||||||
* @pre rte != NULL
|
* @pre rte != NULL
|
||||||
*/
|
*/
|
||||||
void vioapic_get_rte(const struct acrn_vm *vm, uint32_t pin, union ioapic_rte *rte)
|
void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte *rte)
|
||||||
{
|
{
|
||||||
struct acrn_vioapic *vioapic;
|
struct acrn_vioapic *vioapic;
|
||||||
|
uint32_t pin = vgsi;
|
||||||
|
|
||||||
vioapic = vm_ioapic(vm);
|
vioapic = vm_ioapic(vm);
|
||||||
*rte = vioapic->rtbl[pin];
|
*rte = vioapic->rtbl[pin];
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <assign.h>
|
#include <assign.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <logmsg.h>
|
#include <logmsg.h>
|
||||||
|
#include <ioapic.h>
|
||||||
|
|
||||||
#define DBG_LEVEL_PIC 6U
|
#define DBG_LEVEL_PIC 6U
|
||||||
|
|
||||||
@ -311,6 +312,79 @@ static int32_t vpic_icw4(const struct acrn_vpic *vpic, struct i8259_reg_state *i
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t vpin_to_vgsi(const struct acrn_vm *vm, uint32_t vpin)
|
||||||
|
{
|
||||||
|
uint32_t vgsi = vpin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remap depending on the type of VM
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (is_sos_vm(vm)) {
|
||||||
|
/*
|
||||||
|
* For SOS VM vPIC pin to GSI is same as the one
|
||||||
|
* that is used for platform
|
||||||
|
*/
|
||||||
|
vgsi = get_pic_pin_from_ioapic_pin(vpin);
|
||||||
|
} else if (is_postlaunched_vm(vm)) {
|
||||||
|
/*
|
||||||
|
* Devicemodel provides Interrupt Source Override Structure
|
||||||
|
* via ACPI to Post-Launched VM.
|
||||||
|
*
|
||||||
|
* 1) Interrupt source connected to vPIC pin 0 is connected to vIOAPIC pin 2
|
||||||
|
* 2) Devicemodel, as of today, does not request to hold ptirq entry with vPIC as
|
||||||
|
* interrupt controller, for a Post-Launched VM.
|
||||||
|
*/
|
||||||
|
if (vpin == 0U) {
|
||||||
|
vgsi = 2U;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* For Pre-launched VMs, Interrupt Source Override Structure
|
||||||
|
* and IO-APIC Structure are not provided in the VM's ACPI info.
|
||||||
|
* No remapping needed.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return vgsi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t vgsi_to_vpin(const struct acrn_vm *vm, uint32_t vgsi)
|
||||||
|
{
|
||||||
|
uint32_t vpin = vgsi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remap depending on the type of VM
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (is_sos_vm(vm)) {
|
||||||
|
/*
|
||||||
|
* For SOS VM vPIC pin to GSI is same as the one
|
||||||
|
* that is used for platform
|
||||||
|
*/
|
||||||
|
vpin = get_pic_pin_from_ioapic_pin(vgsi);
|
||||||
|
} else if (is_postlaunched_vm(vm)) {
|
||||||
|
/*
|
||||||
|
* Devicemodel provides Interrupt Source Override Structure
|
||||||
|
* via ACPI to Post-Launched VM.
|
||||||
|
*
|
||||||
|
* 1) Interrupt source connected to vPIC pin 0 is connected to vIOAPIC pin 2
|
||||||
|
* 2) Devicemodel, as of today, does not request to hold ptirq entry with vPIC as
|
||||||
|
* interrupt controller, for a Post-Launched VM.
|
||||||
|
*/
|
||||||
|
if (vgsi == 2U) {
|
||||||
|
vpin = 0U;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* For Pre-launched VMs, Interrupt Source Override Structure
|
||||||
|
* and IO-APIC Structure are not provided in the VM's ACPI info.
|
||||||
|
* No remapping needed.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return vpin;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t vpic_ocw1(const struct acrn_vpic *vpic, struct i8259_reg_state *i8259, uint8_t val)
|
static int32_t vpic_ocw1(const struct acrn_vpic *vpic, struct i8259_reg_state *i8259, uint8_t val)
|
||||||
{
|
{
|
||||||
uint32_t pin, i, bit;
|
uint32_t pin, i, bit;
|
||||||
@ -331,6 +405,7 @@ static int32_t vpic_ocw1(const struct acrn_vpic *vpic, struct i8259_reg_state *i
|
|||||||
*/
|
*/
|
||||||
if (((i8259->mask & bit) == 0U) && ((old & bit) != 0U)) {
|
if (((i8259->mask & bit) == 0U) && ((old & bit) != 0U)) {
|
||||||
uint32_t virt_pin;
|
uint32_t virt_pin;
|
||||||
|
uint32_t vgsi;
|
||||||
|
|
||||||
/* master i8259 pin2 connect with slave i8259,
|
/* master i8259 pin2 connect with slave i8259,
|
||||||
* not device, so not need pt remap
|
* not device, so not need pt remap
|
||||||
@ -342,7 +417,9 @@ static int32_t vpic_ocw1(const struct acrn_vpic *vpic, struct i8259_reg_state *i
|
|||||||
|
|
||||||
virt_pin = (master_pic(vpic, i8259)) ?
|
virt_pin = (master_pic(vpic, i8259)) ?
|
||||||
pin : (pin + 8U);
|
pin : (pin + 8U);
|
||||||
(void)ptirq_intx_pin_remap(vpic->vm, virt_pin, INTX_CTLR_PIC);
|
|
||||||
|
vgsi = vpin_to_vgsi(vpic->vm, virt_pin);
|
||||||
|
(void)ptirq_intx_pin_remap(vpic->vm, vgsi, INTX_CTLR_PIC);
|
||||||
}
|
}
|
||||||
pin = (pin + 1U) & 0x7U;
|
pin = (pin + 1U) & 0x7U;
|
||||||
}
|
}
|
||||||
@ -359,6 +436,7 @@ static int32_t vpic_ocw2(const struct acrn_vpic *vpic, struct i8259_reg_state *i
|
|||||||
|
|
||||||
if ((val & OCW2_EOI) != 0U) {
|
if ((val & OCW2_EOI) != 0U) {
|
||||||
uint32_t isr_bit;
|
uint32_t isr_bit;
|
||||||
|
uint32_t vgsi;
|
||||||
|
|
||||||
if ((val & OCW2_SL) != 0U) {
|
if ((val & OCW2_SL) != 0U) {
|
||||||
/* specific EOI */
|
/* specific EOI */
|
||||||
@ -378,8 +456,8 @@ static int32_t vpic_ocw2(const struct acrn_vpic *vpic, struct i8259_reg_state *i
|
|||||||
|
|
||||||
/* if level ack PTDEV */
|
/* if level ack PTDEV */
|
||||||
if ((i8259->elc & (1U << (isr_bit & 0x7U))) != 0U) {
|
if ((i8259->elc & (1U << (isr_bit & 0x7U))) != 0U) {
|
||||||
ptirq_intx_ack(vpic->vm, (master_pic(vpic, i8259) ? isr_bit : isr_bit + 8U),
|
vgsi = vpin_to_vgsi(vpic->vm, (master_pic(vpic, i8259) ? isr_bit : isr_bit + 8U));
|
||||||
INTX_CTLR_PIC);
|
ptirq_intx_ack(vpic->vm, vgsi, INTX_CTLR_PIC);
|
||||||
}
|
}
|
||||||
} else if (((val & OCW2_SL) != 0U) && i8259->rotate) {
|
} else if (((val & OCW2_SL) != 0U) && i8259->rotate) {
|
||||||
/* specific priority */
|
/* specific priority */
|
||||||
@ -461,17 +539,18 @@ static void vpic_set_pinstate(struct acrn_vpic *vpic, uint32_t pin, uint8_t leve
|
|||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t irqline, uint32_t operation)
|
void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t vgsi, uint32_t operation)
|
||||||
{
|
{
|
||||||
struct i8259_reg_state *i8259;
|
struct i8259_reg_state *i8259;
|
||||||
uint32_t pin;
|
uint32_t pin;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
|
|
||||||
if (irqline < NR_VPIC_PINS_TOTAL) {
|
|
||||||
i8259 = &vpic->i8259[irqline >> 3U];
|
if (vgsi < NR_VPIC_PINS_TOTAL) {
|
||||||
pin = irqline;
|
i8259 = &vpic->i8259[vgsi >> 3U];
|
||||||
|
|
||||||
if (i8259->ready) {
|
if (i8259->ready) {
|
||||||
|
pin = vgsi_to_vpin(vpic->vm, vgsi);
|
||||||
spinlock_irqsave_obtain(&(vpic->lock), &rflags);
|
spinlock_irqsave_obtain(&(vpic->lock), &rflags);
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case GSI_SET_HIGH:
|
case GSI_SET_HIGH:
|
||||||
@ -511,9 +590,11 @@ vpic_pincount(void)
|
|||||||
* @pre irqline < NR_VPIC_PINS_TOTAL
|
* @pre irqline < NR_VPIC_PINS_TOTAL
|
||||||
* @pre this function should be called after vpic_init()
|
* @pre this function should be called after vpic_init()
|
||||||
*/
|
*/
|
||||||
void vpic_get_irqline_trigger_mode(const struct acrn_vpic *vpic, uint32_t irqline,
|
void vpic_get_irqline_trigger_mode(const struct acrn_vpic *vpic, uint32_t vgsi,
|
||||||
enum vpic_trigger *trigger)
|
enum vpic_trigger *trigger)
|
||||||
{
|
{
|
||||||
|
uint32_t irqline = vgsi_to_vpin(vpic->vm, vgsi);
|
||||||
|
|
||||||
if ((vpic->i8259[irqline >> 3U].elc & (1U << (irqline & 0x7U))) != 0U) {
|
if ((vpic->i8259[irqline >> 3U].elc & (1U << (irqline & 0x7U))) != 0U) {
|
||||||
*trigger = LEVEL_TRIGGER;
|
*trigger = LEVEL_TRIGGER;
|
||||||
} else {
|
} else {
|
||||||
|
@ -616,13 +616,13 @@ static void vuart_deinit_connection(struct acrn_vuart *vu)
|
|||||||
vu->target_vu = NULL;
|
vu->target_vu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_pin)
|
bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
for (i = 0U; i < MAX_VUART_NUM_PER_VM; i++) {
|
for (i = 0U; i < MAX_VUART_NUM_PER_VM; i++) {
|
||||||
if ((vm->vuart[i].active) && (vm->vuart[i].irq == intx_pin)) {
|
if ((vm->vuart[i].active) && (vm->vuart[i].irq == intx_gsi)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,15 +29,15 @@
|
|||||||
* Acknowledge a virtual legacy interrupt for a passthrough device.
|
* Acknowledge a virtual legacy interrupt for a passthrough device.
|
||||||
*
|
*
|
||||||
* @param[in] vm pointer to acrn_vm
|
* @param[in] vm pointer to acrn_vm
|
||||||
* @param[in] virt_pin virtual pin number associated with the passthrough device
|
* @param[in] virt_gsi virtual GSI number associated with the passthrough device
|
||||||
* @param[in] vpin_ctlr INTX_CTLR_IOAPIC or INTX_CTLR_PIC
|
* @param[in] vgsi_ctlr INTX_CTLR_IOAPIC or INTX_CTLR_PIC
|
||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
*
|
*
|
||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ptirq_intx_ack(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_ctlr);
|
void ptirq_intx_ack(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief MSI/MSI-x remapping for passthrough device.
|
* @brief MSI/MSI-x remapping for passthrough device.
|
||||||
@ -72,8 +72,8 @@ int32_t ptirq_prepare_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, uint16_
|
|||||||
* This is the main entry for PCI/Legacy device assignment with INTx, calling from vIOAPIC or vPIC.
|
* This is the main entry for PCI/Legacy device assignment with INTx, calling from vIOAPIC or vPIC.
|
||||||
*
|
*
|
||||||
* @param[in] vm pointer to acrn_vm
|
* @param[in] vm pointer to acrn_vm
|
||||||
* @param[in] virt_pin virtual pin number associated with the passthrough device
|
* @param[in] virt_gsi virtual GSI number associated with the passthrough device
|
||||||
* @param[in] vpin_ctlr INTX_CTLR_IOAPIC or INTX_CTLR_PIC
|
* @param[in] vgsi_ctlr INTX_CTLR_IOAPIC or INTX_CTLR_PIC
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* - 0: on success
|
* - 0: on success
|
||||||
@ -84,7 +84,7 @@ int32_t ptirq_prepare_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, uint16_
|
|||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ctlr vpin_ctlr);
|
int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_gsi, enum intx_ctlr vgsi_ctlr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add an interrupt remapping entry for INTx as pre-hold mapping.
|
* @brief Add an interrupt remapping entry for INTx as pre-hold mapping.
|
||||||
@ -94,8 +94,8 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ct
|
|||||||
* Currently, one phys_pin can only be held by one pin source (vPIC or vIOAPIC).
|
* Currently, one phys_pin can only be held by one pin source (vPIC or vIOAPIC).
|
||||||
*
|
*
|
||||||
* @param[in] vm pointer to acrn_vm
|
* @param[in] vm pointer to acrn_vm
|
||||||
* @param[in] virt_pin virtual pin number associated with the passthrough device
|
* @param[in] virt_gsi virtual pin number associated with the passthrough device
|
||||||
* @param[in] phys_pin physical pin number associated with the passthrough device
|
* @param[in] phys_gsi physical pin number associated with the passthrough device
|
||||||
* @param[in] pic_pin true for pic, false for ioapic
|
* @param[in] pic_pin true for pic, false for ioapic
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
@ -106,7 +106,7 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, enum intx_ct
|
|||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin, uint32_t phys_pin, bool pic_pin);
|
int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_gsi, uint32_t phys_gsi, bool pic_pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove an interrupt remapping entry for INTx.
|
* @brief Remove an interrupt remapping entry for INTx.
|
||||||
@ -114,7 +114,7 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin, uint32_t
|
|||||||
* Deactivate & remove mapping entry of the given virt_pin for given vm.
|
* Deactivate & remove mapping entry of the given virt_pin for given vm.
|
||||||
*
|
*
|
||||||
* @param[in] vm pointer to acrn_vm
|
* @param[in] vm pointer to acrn_vm
|
||||||
* @param[in] virt_pin virtual pin number associated with the passthrough device
|
* @param[in] virt_gsi virtual pin number associated with the passthrough device
|
||||||
* @param[in] pic_pin true for pic, false for ioapic
|
* @param[in] pic_pin true for pic, false for ioapic
|
||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
@ -122,7 +122,7 @@ int32_t ptirq_add_intx_remapping(struct acrn_vm *vm, uint32_t virt_pin, uint32_t
|
|||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_pin, bool pic_pin);
|
void ptirq_remove_intx_remapping(const struct acrn_vm *vm, uint32_t virt_gsi, bool pic_pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove interrupt remapping entry/entries for MSI/MSI-x.
|
* @brief Remove interrupt remapping entry/entries for MSI/MSI-x.
|
||||||
|
@ -35,14 +35,13 @@ uint8_t ioapic_irq_to_ioapic_id(uint32_t irq);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get irq num from pin num
|
* @brief Get irq num from gsi num
|
||||||
*
|
*
|
||||||
* @param[in] pin The pin number
|
* @param[in] gsi The gsi number
|
||||||
*
|
*
|
||||||
* @return irq number
|
* @return irq number
|
||||||
*/
|
*/
|
||||||
uint32_t ioapic_pin_to_irq(uint32_t pin);
|
uint32_t ioapic_gsi_to_irq(uint32_t gsi);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the redirection table entry
|
* @brief Set the redirection table entry
|
||||||
*
|
*
|
||||||
|
@ -25,7 +25,7 @@ enum intx_ctlr {
|
|||||||
union source_id (name) = {.msi_id = {.bdf = (a), .entry_nr = (b)} }
|
union source_id (name) = {.msi_id = {.bdf = (a), .entry_nr = (b)} }
|
||||||
|
|
||||||
#define DEFINE_INTX_SID(name, a, b) \
|
#define DEFINE_INTX_SID(name, a, b) \
|
||||||
union source_id (name) = {.intx_id = {.pin = (a), .ctlr = (b)} }
|
union source_id (name) = {.intx_id = {.gsi = (a), .ctlr = (b)} }
|
||||||
|
|
||||||
union irte_index {
|
union irte_index {
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
@ -49,7 +49,7 @@ union source_id {
|
|||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
enum intx_ctlr ctlr;
|
enum intx_ctlr ctlr;
|
||||||
uint32_t pin;
|
uint32_t gsi;
|
||||||
} intx_id;
|
} intx_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ void vioapic_reset(struct acrn_vm *vm);
|
|||||||
* @brief Set vIOAPIC IRQ line status.
|
* @brief Set vIOAPIC IRQ line status.
|
||||||
*
|
*
|
||||||
* @param[in] vm Pointer to target VM
|
* @param[in] vm Pointer to target VM
|
||||||
* @param[in] irqline Target IRQ number
|
* @param[in] vgsi GSI for the virtual interrupt
|
||||||
* @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/
|
* @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/
|
||||||
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
||||||
*
|
*
|
||||||
@ -84,7 +84,7 @@ void vioapic_reset(struct acrn_vm *vm);
|
|||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation);
|
void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set vIOAPIC IRQ line status.
|
* @brief Set vIOAPIC IRQ line status.
|
||||||
@ -93,18 +93,18 @@ void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t irqline, uint32
|
|||||||
* operation be done with ioapic lock.
|
* operation be done with ioapic lock.
|
||||||
*
|
*
|
||||||
* @param[in] vm Pointer to target VM
|
* @param[in] vm Pointer to target VM
|
||||||
* @param[in] irqline Target IRQ number
|
* @param[in] vgsi GSI for the virtual interrupt
|
||||||
* @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/
|
* @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/
|
||||||
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
||||||
*
|
*
|
||||||
* @pre irqline < vioapic_pincount(vm)
|
* @pre irqline < vioapic_pincount(vm)
|
||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t irqline, uint32_t operation);
|
void vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation);
|
||||||
|
|
||||||
uint32_t vioapic_pincount(const struct acrn_vm *vm);
|
uint32_t vioapic_pincount(const struct acrn_vm *vm);
|
||||||
void vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector);
|
void vioapic_process_eoi(struct acrn_vm *vm, uint32_t vector);
|
||||||
void vioapic_get_rte(const struct acrn_vm *vm, uint32_t pin, union ioapic_rte *rte);
|
void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte *rte);
|
||||||
int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data);
|
int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,13 +149,13 @@ void vpic_init(struct acrn_vm *vm);
|
|||||||
* @brief Set vPIC IRQ line status.
|
* @brief Set vPIC IRQ line status.
|
||||||
*
|
*
|
||||||
* @param[in] vpic Pointer to target VM's vpic table
|
* @param[in] vpic Pointer to target VM's vpic table
|
||||||
* @param[in] irqline Target IRQ number
|
* @param[in] vgsi GSI for the virtual interrupt
|
||||||
* @param[in] operation action options:GSI_SET_HIGH/GSI_SET_LOW/
|
* @param[in] operation action options:GSI_SET_HIGH/GSI_SET_LOW/
|
||||||
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
* GSI_RAISING_PULSE/GSI_FALLING_PULSE
|
||||||
*
|
*
|
||||||
* @return None
|
* @return None
|
||||||
*/
|
*/
|
||||||
void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t irqline, uint32_t operation);
|
void vpic_set_irqline(struct acrn_vpic *vpic, uint32_t vgsi, uint32_t operation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get pending virtual interrupts for vPIC.
|
* @brief Get pending virtual interrupts for vPIC.
|
||||||
@ -179,7 +179,7 @@ void vpic_pending_intr(struct acrn_vpic *vpic, uint32_t *vecptr);
|
|||||||
* @pre vm != NULL
|
* @pre vm != NULL
|
||||||
*/
|
*/
|
||||||
void vpic_intr_accepted(struct acrn_vpic *vpic, uint32_t vector);
|
void vpic_intr_accepted(struct acrn_vpic *vpic, uint32_t vector);
|
||||||
void vpic_get_irqline_trigger_mode(const struct acrn_vpic *vpic, uint32_t irqline, enum vpic_trigger *trigger);
|
void vpic_get_irqline_trigger_mode(const struct acrn_vpic *vpic, uint32_t vgsi, enum vpic_trigger *trigger);
|
||||||
uint32_t vpic_pincount(void);
|
uint32_t vpic_pincount(void);
|
||||||
struct acrn_vpic *vm_pic(const struct acrn_vm *vm);
|
struct acrn_vpic *vm_pic(const struct acrn_vm *vm);
|
||||||
|
|
||||||
|
@ -88,5 +88,5 @@ void vuart_putchar(struct acrn_vuart *vu, char ch);
|
|||||||
char vuart_getchar(struct acrn_vuart *vu);
|
char vuart_getchar(struct acrn_vuart *vu);
|
||||||
void vuart_toggle_intr(const struct acrn_vuart *vu);
|
void vuart_toggle_intr(const struct acrn_vuart *vu);
|
||||||
|
|
||||||
bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_pin);
|
bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi);
|
||||||
#endif /* VUART_H */
|
#endif /* VUART_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user