mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-05 06:56:57 +00:00
ptirq: Fix ptirq hash tables
ptirq_remapping_info records which physical interrupt is mapped to the virtual interrupt in a VM. As we need to knonw whether a physical sid has been mapped to a VM and whether a virtual sid in a VM has been used, there should be two hash tables to link and iterate ptirq_remapping_info: - One is used to lookup from physical sid, linking phys_link. - The other is used to lookup from virtual sid in a VM, linking virt_link Without this patch, phys_link or virt_link from different ptirq_remapping_info was linked by one hash list head if they got the same hash value, as shown in following diagram. When looking for a ptirq_remapping_info from physical sid, the original code took all hash list node as phys_link and failed to get ptirq_remapping_info linked with virt_link and later references to its members are wrong. The same problem also occurred when looking for a ptirq_remapping_info from virtual sid and vm. ---------- <- hash table |hlist_head| --actual ptirq_remapping_info address ---------- --------- / --used as ptirq_remapping_info | ... | |phys_link| ___/ ---------- --------- --------- / --------- |hlist_head| -> |phys_link| <-> |virt_link| <-> |phys_link| ---------- --------- --------- --------- | ... | |virt_link| | other | |virt_link| ---------- --------- | members | --------- | other | --------- | other | | members | | members | --------- --------- Tracked-On: #8370 Signed-off-by: Qiang Zhang <qiang4.zhang@linux.intel.com> Reviewed-by: Junjie Mao <junjie.mao@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
c8bf91c788
commit
bf9341844a
@ -22,9 +22,10 @@ struct ptirq_remapping_info ptirq_entries[CONFIG_MAX_PT_IRQ_ENTRIES];
|
||||
static uint64_t ptirq_entry_bitmaps[PTIRQ_BITMAP_ARRAY_SIZE];
|
||||
spinlock_t ptdev_lock = { .head = 0U, .tail = 0U, };
|
||||
|
||||
static struct ptirq_entry_head {
|
||||
struct hlist_head list;
|
||||
} ptirq_entry_heads[PTIRQ_ENTRY_HASHSIZE];
|
||||
/* lookup mapping info from phyical sid, hashing from sid + acrn_vm structure address (NULL) */
|
||||
static struct hlist_head phys_sid_htable[PTIRQ_ENTRY_HASHSIZE];
|
||||
/* lookup mapping info from virtual sid within a vm, hashing from sid + acrn_vm structure address */
|
||||
static struct hlist_head virt_sid_htable[PTIRQ_ENTRY_HASHSIZE];
|
||||
|
||||
static inline uint16_t ptirq_alloc_entry_id(void)
|
||||
{
|
||||
@ -40,28 +41,52 @@ static inline uint16_t ptirq_alloc_entry_id(void)
|
||||
return (id < CONFIG_MAX_PT_IRQ_ENTRIES) ? id: INVALID_PTDEV_ENTRY_ID;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the hash key when looking up ptirq_remapping_info from virtual
|
||||
* source id in a VM, or just physical source id (vm == NULL).
|
||||
* Hashing from source id value and acrn_vm structure address can decrease
|
||||
* the probability of hash collisions as different VMs may have equal
|
||||
* virtual source ids.
|
||||
*/
|
||||
static inline uint64_t ptirq_hash_key(const struct acrn_vm *vm,
|
||||
const union source_id *sid)
|
||||
{
|
||||
return hash64(sid->value + (uint64_t)vm, PTIRQ_ENTRY_HASHBITS);
|
||||
}
|
||||
|
||||
/*
|
||||
* to find ptirq_remapping_info from phyical source id (vm == NULL) or
|
||||
* virtual source id in a vm.
|
||||
*/
|
||||
struct ptirq_remapping_info *find_ptirq_entry(uint32_t intr_type,
|
||||
const union source_id *sid, const struct acrn_vm *vm)
|
||||
{
|
||||
struct hlist_node *p;
|
||||
struct hlist_head *b;
|
||||
struct ptirq_remapping_info *n, *entry = NULL;
|
||||
uint64_t key = hash64(sid->value, PTIRQ_ENTRY_HASHBITS);
|
||||
struct ptirq_entry_head *b = &ptirq_entry_heads[key];
|
||||
uint64_t key = ptirq_hash_key(vm, sid);
|
||||
|
||||
hlist_for_each(p, &b->list) {
|
||||
if (vm == NULL) {
|
||||
if (vm == NULL) {
|
||||
b = &(phys_sid_htable[key]);
|
||||
|
||||
hlist_for_each(p, b) {
|
||||
n = hlist_entry(p, struct ptirq_remapping_info, phys_link);
|
||||
} else {
|
||||
n = hlist_entry(p, struct ptirq_remapping_info, virt_link);
|
||||
if (is_entry_active(n)) {
|
||||
if ((intr_type == n->intr_type) && (sid->value == n->phys_sid.value)) {
|
||||
entry = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_entry_active(n)) {
|
||||
if ((intr_type == n->intr_type) &&
|
||||
((vm == NULL) ?
|
||||
(sid->value == n->phys_sid.value) :
|
||||
((vm == n->vm) && (sid->value == n->virt_sid.value)))) {
|
||||
entry = n;
|
||||
break;
|
||||
} else {
|
||||
b = &(virt_sid_htable[key]);
|
||||
hlist_for_each(p, b) {
|
||||
n = hlist_entry(p, struct ptirq_remapping_info, virt_link);
|
||||
if (is_entry_active(n)) {
|
||||
if ((intr_type == n->intr_type) && (sid->value == n->virt_sid.value) && (vm == n->vm)) {
|
||||
entry = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -211,10 +236,10 @@ int32_t ptirq_activate_entry(struct ptirq_remapping_info *entry, uint32_t phys_i
|
||||
entry->allocated_pirq = irq;
|
||||
entry->active = true;
|
||||
|
||||
key = hash64(entry->phys_sid.value, PTIRQ_ENTRY_HASHBITS);
|
||||
hlist_add_head(&entry->phys_link, &(ptirq_entry_heads[key].list));
|
||||
key = hash64(entry->virt_sid.value, PTIRQ_ENTRY_HASHBITS);
|
||||
hlist_add_head(&entry->virt_link, &(ptirq_entry_heads[key].list));
|
||||
key = ptirq_hash_key(NULL, &(entry->phys_sid));
|
||||
hlist_add_head(&entry->phys_link, &(phys_sid_htable[key]));
|
||||
key = ptirq_hash_key(entry->vm, &(entry->virt_sid));
|
||||
hlist_add_head(&entry->virt_link, &(virt_sid_htable[key]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user