hv:Add vpin to ptdev entry mapping for vpic/vioapic

Now if the vmexit reason is virtulized EOI for level triggered
interrupts, HV will loop all the ptdev entries, it is time-consuming,
this patch add vpin to ptdev entry mapping for vpic and vioapic
when add intx entry for a vm,it can use the ptdev entry directly
according to the mapping for vpin and ptdev entry when EOI vmexit.

v3-->v4:
  -- add check vpin in remove_intx_remapping
  -- move check vpin from ptdev_add_intx_remapping to add_intx_remapping

Tracked-On: #861
Signed-off-by: Mingqiang Chi <mingqiang.chi@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Mingqiang Chi 2018-11-19 11:35:22 +08:00 committed by lijinxia
parent 297a264a74
commit 538ba08c2b
5 changed files with 58 additions and 33 deletions

View File

@ -39,6 +39,19 @@ ptdev_lookup_entry_by_sid(uint32_t intr_type,
return NULL; return NULL;
} }
static inline struct ptdev_remapping_info *
ptdev_lookup_entry_by_vpin(struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin)
{
struct ptdev_remapping_info *entry;
if (pic_pin) {
entry = vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin];
} else {
entry = vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin];
}
return entry;
}
#ifdef HV_DEBUG #ifdef HV_DEBUG
static bool ptdev_hv_owned_intx(const struct acrn_vm *vm, const union source_id *virt_sid) static bool ptdev_hv_owned_intx(const struct acrn_vm *vm, const union source_id *virt_sid)
{ {
@ -277,6 +290,12 @@ static struct ptdev_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src); DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src);
uint32_t phys_irq = pin_to_irq(phys_pin); uint32_t phys_irq = pin_to_irq(phys_pin);
if ((!pic_pin && virt_pin >= vioapic_pincount(vm))
|| (pic_pin && virt_pin >= vpic_pincount())) {
pr_err("ptdev_add_intx_remapping fails!\n");
return NULL;
}
if (!irq_is_gsi(phys_irq)) { if (!irq_is_gsi(phys_irq)) {
pr_err("%s, invalid phys_pin: %d <-> irq: 0x%x is not a GSI\n", __func__, phys_pin, phys_irq); pr_err("%s, invalid phys_pin: %d <-> irq: 0x%x is not a GSI\n", __func__, phys_pin, phys_irq);
return NULL; return NULL;
@ -284,7 +303,7 @@ static struct ptdev_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8
entry = ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL); entry = ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &phys_sid, NULL);
if (entry == NULL) { if (entry == NULL) {
if (ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm) != NULL) { if (ptdev_lookup_entry_by_vpin(vm, virt_pin, pic_pin) != NULL) {
pr_err("INTX re-add vpin %d", virt_pin); pr_err("INTX re-add vpin %d", virt_pin);
return NULL; return NULL;
} }
@ -314,26 +333,33 @@ static struct ptdev_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8
* required. */ * required. */
} }
dev_dbg(ACRN_DBG_IRQ, "VM%d INTX add pin mapping vpin%d:ppin%d", vm->vm_id, virt_pin, phys_pin); if (pic_pin) {
vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = entry;
} else {
vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = entry;
}
dev_dbg(ACRN_DBG_IRQ, "VM%d INTX add pin mapping vpin%d:ppin%d", entry->vm->vm_id, virt_pin, phys_pin);
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, uint8_t virt_pin, bool pic_pin) static void remove_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin)
{ {
uint32_t phys_irq; uint32_t phys_irq;
struct ptdev_remapping_info *entry; struct ptdev_remapping_info *entry;
enum ptdev_vpin_source vpin_src =
pic_pin ? PTDEV_VPIN_PIC : PTDEV_VPIN_IOAPIC;
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src);
if ((!pic_pin && virt_pin >= vioapic_pincount(vm))
entry = ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm); || (pic_pin && virt_pin >= vpic_pincount())) {
if (entry == NULL) { pr_err("virtual irq pin is invalid!\n");
return; return;
} }
entry = ptdev_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
if (entry == NULL) {
return;
}
if (is_entry_active(entry)) { if (is_entry_active(entry)) {
phys_irq = entry->allocated_pirq; phys_irq = entry->allocated_pirq;
/* disable interrupt */ /* disable interrupt */
@ -342,13 +368,18 @@ static void remove_intx_remapping(const struct acrn_vm *vm, uint8_t virt_pin, bo
ptdev_deactivate_entry(entry); ptdev_deactivate_entry(entry);
dev_dbg(ACRN_DBG_IRQ, dev_dbg(ACRN_DBG_IRQ,
"deactive %s intx entry:ppin=%d, pirq=%d ", "deactive %s intx entry:ppin=%d, pirq=%d ",
vpin_src == PTDEV_VPIN_PIC ? pic_pin ? "vPIC" : "vIOAPIC",
"vPIC" : "vIOAPIC",
entry->phys_sid.intx_id.pin, phys_irq); entry->phys_sid.intx_id.pin, phys_irq);
dev_dbg(ACRN_DBG_IRQ, "from vm%d vpin=%d\n", dev_dbg(ACRN_DBG_IRQ, "from vm%d vpin=%d\n",
entry->vm->vm_id, virt_pin); entry->vm->vm_id, virt_pin);
} }
if (pic_pin) {
vm->arch_vm.vpic.vpin_to_pt_entry[virt_pin] = NULL;
} else {
vm->arch_vm.vioapic.vpin_to_pt_entry[virt_pin] = NULL;
}
release_entry(entry); release_entry(entry);
} }
@ -464,9 +495,9 @@ void ptdev_intx_ack(struct acrn_vm *vm, uint8_t virt_pin,
{ {
uint32_t phys_irq; uint32_t phys_irq;
struct ptdev_remapping_info *entry; struct ptdev_remapping_info *entry;
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src); bool pic_pin = (vpin_src == PTDEV_VPIN_PIC);
entry = ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm); entry = ptdev_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
if (entry == NULL) { if (entry == NULL) {
return; return;
} }
@ -600,6 +631,7 @@ int ptdev_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
struct ptdev_remapping_info *entry; struct ptdev_remapping_info *entry;
bool need_switch_vpin_src = false; bool need_switch_vpin_src = false;
DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src); DEFINE_IOAPIC_SID(virt_sid, virt_pin, vpin_src);
bool pic_pin = (vpin_src == PTDEV_VPIN_PIC);
/* /*
* virt pin could come from vpic master, vpic slave or vioapic * virt pin could come from vpic master, vpic slave or vioapic
@ -620,10 +652,9 @@ int ptdev_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
#endif #endif
/* 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 = ptdev_lookup_entry_by_sid(PTDEV_INTR_INTX, &virt_sid, vm); entry = ptdev_lookup_entry_by_vpin(vm, virt_pin, pic_pin);
if (entry == NULL) { if (entry == NULL) {
if (is_vm0(vm)) { if (is_vm0(vm)) {
bool pic_pin = (vpin_src == PTDEV_VPIN_PIC);
/* for vm0, there is chance of vpin source switch /* for vm0, there is chance of vpin source switch
* between vPIC & vIOAPIC for one legacy phys_pin. * between vPIC & vIOAPIC for one legacy phys_pin.
@ -633,12 +664,9 @@ int ptdev_intx_pin_remap(struct acrn_vm *vm, uint8_t virt_pin,
* switch vpin source is needed * switch vpin source is needed
*/ */
if (virt_pin < NR_LEGACY_PIN) { if (virt_pin < NR_LEGACY_PIN) {
DEFINE_IOAPIC_SID(tmp_vsid, uint8_t vpin = pic_ioapic_pin_map[virt_pin];
pic_ioapic_pin_map[virt_pin],
pic_pin ? PTDEV_VPIN_IOAPIC : entry = ptdev_lookup_entry_by_vpin(vm, vpin, !pic_pin);
PTDEV_VPIN_PIC);
entry = ptdev_lookup_entry_by_sid(
PTDEV_INTR_INTX, &tmp_vsid, vm);
if (entry != NULL) { if (entry != NULL) {
need_switch_vpin_src = true; need_switch_vpin_src = true;
} }
@ -707,12 +735,6 @@ int ptdev_add_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, uint8_t phys_
{ {
struct ptdev_remapping_info *entry; struct ptdev_remapping_info *entry;
if ((!pic_pin && virt_pin >= vioapic_pincount(vm))
|| (pic_pin && virt_pin >= vpic_pincount())) {
pr_err("ptdev_add_intx_remapping fails!\n");
return -EINVAL;
}
spinlock_obtain(&ptdev_lock); spinlock_obtain(&ptdev_lock);
entry = add_intx_remapping(vm, virt_pin, phys_pin, pic_pin); entry = add_intx_remapping(vm, virt_pin, phys_pin, pic_pin);
spinlock_release(&ptdev_lock); spinlock_release(&ptdev_lock);
@ -723,7 +745,7 @@ int ptdev_add_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, uint8_t phys_
/* /*
* @pre vm != NULL * @pre vm != NULL
*/ */
void ptdev_remove_intx_remapping(const struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin) void ptdev_remove_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin)
{ {
spinlock_obtain(&ptdev_lock); spinlock_obtain(&ptdev_lock);
remove_intx_remapping(vm, virt_pin, pic_pin); remove_intx_remapping(vm, virt_pin, pic_pin);

View File

@ -31,10 +31,6 @@
#define ACRN_DBG_PIC 6U #define ACRN_DBG_PIC 6U
#define NR_VPIC_PINS_PER_CHIP 8U
#define NR_VPIC_PINS_TOTAL 16U
#define VPIC_INVALID_PIN 0xffU
static void vpic_set_pinstate(struct acrn_vpic *vpic, uint8_t pin, uint8_t level); static void vpic_set_pinstate(struct acrn_vpic *vpic, uint8_t pin, uint8_t level);
static inline bool master_pic(const struct acrn_vpic *vpic, struct i8259_reg_state *i8259) static inline bool master_pic(const struct acrn_vpic *vpic, struct i8259_reg_state *i8259)

View File

@ -119,7 +119,7 @@ int ptdev_add_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, uint8_t phys_
* @pre vm != NULL * @pre vm != NULL
* *
*/ */
void ptdev_remove_intx_remapping(const struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin); void ptdev_remove_intx_remapping(struct acrn_vm *vm, uint8_t virt_pin, bool pic_pin);
/** /**
* @brief Add interrupt remapping entry/entries for MSI/MSI-x as pre-hold mapping. * @brief Add interrupt remapping entry/entries for MSI/MSI-x as pre-hold mapping.

View File

@ -41,6 +41,7 @@
#define VIOAPIC_BASE 0xFEC00000UL #define VIOAPIC_BASE 0xFEC00000UL
#define VIOAPIC_SIZE 4096UL #define VIOAPIC_SIZE 4096UL
#define VIOAPIC_MAX_PIN 256U
#define REDIR_ENTRIES_HW 120U /* SOS align with native ioapic */ #define REDIR_ENTRIES_HW 120U /* SOS align with native ioapic */
#define STATE_BITMAP_SIZE INT_DIV_ROUNDUP(REDIR_ENTRIES_HW, 64U) #define STATE_BITMAP_SIZE INT_DIV_ROUNDUP(REDIR_ENTRIES_HW, 64U)
@ -53,6 +54,7 @@ struct acrn_vioapic {
union ioapic_rte rtbl[REDIR_ENTRIES_HW]; union ioapic_rte rtbl[REDIR_ENTRIES_HW];
/* pin_state status bitmap: 1 - high, 0 - low */ /* pin_state status bitmap: 1 - high, 0 - low */
uint64_t pin_state[STATE_BITMAP_SIZE]; uint64_t pin_state[STATE_BITMAP_SIZE];
struct ptdev_remapping_info *vpin_to_pt_entry[VIOAPIC_MAX_PIN];
}; };
void vioapic_init(struct acrn_vm *vm); void vioapic_init(struct acrn_vm *vm);

View File

@ -92,6 +92,10 @@
#define IO_ELCR1 0x4d0U #define IO_ELCR1 0x4d0U
#define IO_ELCR2 0x4d1U #define IO_ELCR2 0x4d1U
#define NR_VPIC_PINS_PER_CHIP 8U
#define NR_VPIC_PINS_TOTAL 16U
#define VPIC_INVALID_PIN 0xffU
enum vpic_trigger { enum vpic_trigger {
EDGE_TRIGGER, EDGE_TRIGGER,
LEVEL_TRIGGER LEVEL_TRIGGER
@ -124,6 +128,7 @@ struct acrn_vpic {
struct acrn_vm *vm; struct acrn_vm *vm;
spinlock_t lock; spinlock_t lock;
struct i8259_reg_state i8259[2]; struct i8259_reg_state i8259[2];
struct ptdev_remapping_info *vpin_to_pt_entry[NR_VPIC_PINS_TOTAL];
}; };
void vpic_init(struct acrn_vm *vm); void vpic_init(struct acrn_vm *vm);