Skip to content

Commit b7bbf81

Browse files
mingqiangchilijinxia
authored andcommitted
hv:Replace dynamic memory with static for ptdev
-- Config MAX_PT_IRQ_ENTRIES 64 in Kconfig -- Remove ptdev list -- Add alloc_ptdev_entry_id api v3-->v4: -- move is_entry_active from assign.c to ptdev.h -- Add clear active flag in release_entry v2-->v3: -- Remove redundancy active check for ptdev entry in release_all_entries and get_ptdev_info v1-->v2: -- split to small patches 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>
1 parent b0e1657 commit b7bbf81

File tree

4 files changed

+68
-45
lines changed

4 files changed

+68
-45
lines changed

hypervisor/arch/x86/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ config MAX_EMULATED_MMIO_REGIONS
113113
range 0 128
114114
default 16
115115

116+
config MAX_PT_IRQ_ENTRIES
117+
int "Maximum number of interrupt source for PT devices"
118+
range 0 128
119+
default 64
120+
116121
config MAX_IOMMU_NUM
117122
int "Maximum number of IOMMU devices"
118123
range 1 2

hypervisor/arch/x86/assign.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ static inline struct ptdev_remapping_info *
1919
ptdev_lookup_entry_by_sid(uint32_t intr_type,
2020
const union source_id *sid,const struct acrn_vm *vm)
2121
{
22+
uint16_t idx;
2223
struct ptdev_remapping_info *entry;
23-
struct list_head *pos;
2424

25-
list_for_each(pos, &ptdev_list) {
26-
entry = list_entry(pos, struct ptdev_remapping_info,
27-
entry_node);
25+
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
26+
entry = &ptdev_irq_entries[idx];
27+
if (!is_entry_active(entry)) {
28+
continue;
29+
}
2830
if ((intr_type == entry->intr_type) &&
2931
((vm == NULL) ?
3032
(sid->value == entry->phys_sid.value) :
@@ -37,12 +39,6 @@ ptdev_lookup_entry_by_sid(uint32_t intr_type,
3739
return NULL;
3840
}
3941

40-
static inline bool
41-
is_entry_active(const struct ptdev_remapping_info *entry)
42-
{
43-
return atomic_load32(&entry->active) == ACTIVE_FLAG;
44-
}
45-
4642
#ifdef HV_DEBUG
4743
static bool ptdev_hv_owned_intx(const struct acrn_vm *vm, const union source_id *virt_sid)
4844
{
@@ -209,6 +205,9 @@ static struct ptdev_remapping_info *add_msix_remapping(struct acrn_vm *vm,
209205
}
210206

211207
entry = alloc_entry(vm, PTDEV_INTR_MSI);
208+
if (entry == NULL) {
209+
return NULL;
210+
}
212211
entry->phys_sid.value = phys_sid.value;
213212
entry->virt_sid.value = virt_sid.value;
214213

@@ -299,6 +298,9 @@ static struct ptdev_remapping_info *add_intx_remapping(struct acrn_vm *vm, uint8
299298
return NULL;
300299
}
301300
entry = alloc_entry(vm, PTDEV_INTR_INTX);
301+
if (entry == NULL) {
302+
return NULL;
303+
}
302304
entry->phys_sid.value = phys_sid.value;
303305
entry->virt_sid.value = virt_sid.value;
304306

@@ -830,14 +832,14 @@ void get_ptdev_info(char *str_arg, size_t str_max)
830832
{
831833
char *str = str_arg;
832834
struct ptdev_remapping_info *entry;
835+
uint16_t idx;
833836
size_t len, size = str_max;
834837
uint32_t irq, vector;
835838
char type[16];
836839
uint64_t dest;
837840
bool lvl_tm;
838841
uint8_t pin, vpin;
839842
uint32_t bdf, vbdf;
840-
struct list_head *pos;
841843

842844
len = snprintf(str, size, "\r\nVM\tTYPE\tIRQ\tVEC\tDEST\tTM\tPIN\tVPIN\tBDF\tVBDF");
843845
if (len >= size) {
@@ -847,9 +849,8 @@ void get_ptdev_info(char *str_arg, size_t str_max)
847849
str += len;
848850

849851
spinlock_obtain(&ptdev_lock);
850-
list_for_each(pos, &ptdev_list) {
851-
entry = list_entry(pos, struct ptdev_remapping_info,
852-
entry_node);
852+
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
853+
entry = &ptdev_irq_entries[idx];
853854
if (is_entry_active(entry)) {
854855
get_entry_info(entry, type, &irq, &vector,
855856
&dest, &lvl_tm, &pin, &vpin,

hypervisor/common/ptdev.c

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,30 @@
88
#include <softirq.h>
99
#include <ptdev.h>
1010

11-
/* passthrough device link */
12-
struct list_head ptdev_list;
11+
#define PTDEV_BITMAP_ARRAY_SIZE INT_DIV_ROUNDUP(CONFIG_MAX_PT_IRQ_ENTRIES, 64U)
12+
struct ptdev_remapping_info ptdev_irq_entries[CONFIG_MAX_PT_IRQ_ENTRIES];
13+
static uint64_t ptdev_entry_bitmaps[PTDEV_BITMAP_ARRAY_SIZE];
14+
1315
spinlock_t ptdev_lock;
1416

15-
/*
16-
* entry could both be in ptdev_list and vm->softirq_dev_entry_list.
17-
* When release entry, we need make sure entry deleted from both
18-
* lists. We have to require two locks and the lock sequence is:
19-
* ptdev_lock
20-
* vm->softirq_dev_lock
21-
*/
17+
bool is_entry_active(const struct ptdev_remapping_info *entry)
18+
{
19+
return atomic_load32(&entry->active) == ACTIVE_FLAG;
20+
}
21+
22+
static inline uint16_t alloc_ptdev_entry_id(void)
23+
{
24+
uint16_t id = (uint16_t)ffz64_ex(ptdev_entry_bitmaps, CONFIG_MAX_PT_IRQ_ENTRIES);
25+
26+
while (id < CONFIG_MAX_PT_IRQ_ENTRIES) {
27+
if (!bitmap_test_and_set_lock((id & 0x3FU), &ptdev_entry_bitmaps[id >> 6U])) {
28+
return id;
29+
}
30+
id = (uint16_t)ffz64_ex(ptdev_entry_bitmaps, CONFIG_MAX_PT_IRQ_ENTRIES);
31+
}
32+
33+
return INVALID_PTDEV_ENTRY_ID;
34+
}
2235

2336
static void ptdev_enqueue_softirq(struct ptdev_remapping_info *entry)
2437
{
@@ -78,22 +91,26 @@ struct ptdev_remapping_info *
7891
alloc_entry(struct acrn_vm *vm, uint32_t intr_type)
7992
{
8093
struct ptdev_remapping_info *entry;
94+
uint16_t ptdev_id = alloc_ptdev_entry_id();
8195

82-
/* allocate */
83-
entry = calloc(1U, sizeof(*entry));
84-
ASSERT(entry != NULL, "alloc memory failed");
96+
if (ptdev_id >= CONFIG_MAX_PT_IRQ_ENTRIES) {
97+
pr_err("Alloc ptdev irq entry failed");
98+
return NULL;
99+
}
100+
101+
entry = &ptdev_irq_entries[ptdev_id];
102+
(void)memset((void *)entry, 0U, sizeof(struct ptdev_remapping_info));
103+
entry->ptdev_entry_id = ptdev_id;
85104
entry->intr_type = intr_type;
86105
entry->vm = vm;
106+
entry->intr_count = 0UL;
87107

88108
INIT_LIST_HEAD(&entry->softirq_node);
89-
INIT_LIST_HEAD(&entry->entry_node);
90109

91-
entry->intr_count = 0UL;
92110
initialize_timer(&entry->intr_delay_timer, ptdev_intr_delay_callback,
93111
entry, 0UL, 0, 0UL);
94112

95113
atomic_clear32(&entry->active, ACTIVE_FLAG);
96-
list_add(&entry->entry_node, &ptdev_list);
97114

98115
return entry;
99116
}
@@ -104,30 +121,26 @@ release_entry(struct ptdev_remapping_info *entry)
104121
{
105122
uint64_t rflags;
106123

107-
/* remove entry from ptdev_list */
108-
list_del_init(&entry->entry_node);
109-
110124
/*
111125
* remove entry from softirq list.the ptdev_lock
112126
* is required before calling release_entry.
113127
*/
114128
spinlock_irqsave_obtain(&entry->vm->softirq_dev_lock, &rflags);
115129
list_del_init(&entry->softirq_node);
116130
spinlock_irqrestore_release(&entry->vm->softirq_dev_lock, rflags);
117-
118-
free(entry);
131+
atomic_clear32(&entry->active, ACTIVE_FLAG);
132+
bitmap_clear_nolock((entry->ptdev_entry_id) & 0x3FU, &ptdev_entry_bitmaps[(entry->ptdev_entry_id) >> 6U]);
119133
}
120134

121135
/* require ptdev_lock protect */
122136
static void
123137
release_all_entries(const struct acrn_vm *vm)
124138
{
125139
struct ptdev_remapping_info *entry;
126-
struct list_head *pos, *tmp;
140+
uint16_t idx;
127141

128-
list_for_each_safe(pos, tmp, &ptdev_list) {
129-
entry = list_entry(pos, struct ptdev_remapping_info,
130-
entry_node);
142+
for (idx = 0U; idx < CONFIG_MAX_PT_IRQ_ENTRIES; idx++) {
143+
entry = &ptdev_irq_entries[idx];
131144
if (entry->vm == vm) {
132145
release_entry(entry);
133146
}
@@ -200,7 +213,6 @@ void ptdev_init(void)
200213
return;
201214
}
202215

203-
INIT_LIST_HEAD(&ptdev_list);
204216
spinlock_init(&ptdev_lock);
205217

206218
register_softirq(SOFTIRQ_PTDEV, ptdev_softirq);
@@ -218,12 +230,14 @@ uint32_t get_vm_ptdev_intr_data(const struct acrn_vm *target_vm, uint64_t *buffe
218230
uint32_t buffer_cnt)
219231
{
220232
uint32_t index = 0U;
233+
uint16_t i;
221234
struct ptdev_remapping_info *entry;
222-
struct list_head *pos, *tmp;
223235

224-
list_for_each_safe(pos, tmp, &ptdev_list) {
225-
entry = list_entry(pos, struct ptdev_remapping_info,
226-
entry_node);
236+
for (i = 0U; i < CONFIG_MAX_PT_IRQ_ENTRIES; i++) {
237+
entry = &ptdev_irq_entries[i];
238+
if (!is_entry_active(entry)) {
239+
continue;
240+
}
227241
if (entry->vm == target_vm) {
228242
buffer[index] = entry->allocated_pirq;
229243
buffer[index + 1U] = entry->intr_count;

hypervisor/include/common/ptdev.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define PTDEV_INTR_MSI (1U << 0U)
1313
#define PTDEV_INTR_INTX (1U << 1U)
1414

15+
#define INVALID_PTDEV_ENTRY_ID 0xffffU
16+
1517
enum ptdev_vpin_source {
1618
PTDEV_VPIN_IOAPIC,
1719
PTDEV_VPIN_PIC,
@@ -51,6 +53,7 @@ struct ptdev_msi_info {
5153
* with interrupt handler and softirq.
5254
*/
5355
struct ptdev_remapping_info {
56+
uint16_t ptdev_entry_id;
5457
uint32_t intr_type;
5558
union source_id phys_sid;
5659
union source_id virt_sid;
@@ -59,16 +62,16 @@ struct ptdev_remapping_info {
5962
uint32_t allocated_pirq;
6063
uint32_t polarity; /* 0=active high, 1=active low*/
6164
struct list_head softirq_node;
62-
struct list_head entry_node;
6365
struct ptdev_msi_info msi;
6466

6567
uint64_t intr_count;
6668
struct hv_timer intr_delay_timer; /* used for delay intr injection */
6769
};
6870

69-
extern struct list_head ptdev_list;
71+
extern struct ptdev_remapping_info ptdev_irq_entries[];
7072
extern spinlock_t ptdev_lock;
7173

74+
bool is_entry_active(const struct ptdev_remapping_info *entry);
7275
void ptdev_softirq(uint16_t pcpu_id);
7376
void ptdev_init(void);
7477
void ptdev_release_all_entries(const struct acrn_vm *vm);

0 commit comments

Comments
 (0)