Skip to content

Commit f27d475

Browse files
Junming Liuwenlingz
authored andcommitted
dm:gvt:adjust pci bar region with reserved bar regions
ACRN-DM has reserved gvt bar regions. This patch ensures other pci devices' bar regions won't overlap with reserved bar regions. v6 -> v7: * rename some struct and func v5 -> v6: * remove outdated comment * add comments for code reading * code cleaning about gvt bar0 and bar2 size v4 -> v5: * rename adjust_bar_region and adjust_bar_region_by_gvt_bars * change adjust_bar_region_by_gvt_bars interface for code cleaning v3 -> v4: * add static struct gvt_region instead of definition or pointer array. v2 -> v3: * repalce pci_emul_alloc_bar with gvt_reserve_resource when allocate gvt bars * use register_bar to detect if gvt bars confilts with pci devices v1 -> v2: * don't limit the gvt bar type is MEM32 when deal with pci bar * add is_two_region_overlap func to detect if two regions overlap * add region array to store gvt bar0 and bar2 regions Tracked-On: #4005 Signed-off-by: Junming Liu <junming.liu@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Liu XinYun <xinyun.liu@intel.com> Reviewed-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent 1ac0b57 commit f27d475

File tree

2 files changed

+86
-38
lines changed

2 files changed

+86
-38
lines changed

devicemodel/hw/pci/core.c

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,36 @@ void destory_mmio_rsvd_rgns(struct pci_vdev *vdev){
166166
reserved_bar_regions[i].vdev = NULL;
167167
}
168168

169+
static bool
170+
is_mmio_rgns_overlap(uint64_t x1, uint64_t x2, uint64_t y1, uint64_t y2)
171+
{
172+
if(x1 <= y2 && y1 <= x2)
173+
return true;
174+
return false;
175+
}
176+
177+
/* reserved_bar_regions has sorted mmio_rsvd_rgns.
178+
* iterate all mmio_rsvd_rgn in reserved_bar_regions,
179+
* if [base, base + size - 1] with any mmio_rsvd_rgn,
180+
* adjust base addr to ensure [base, base + size - 1]
181+
* won't overlap with reserved mmio_rsvd_rgn
182+
*/
183+
static void
184+
adjust_bar_region(uint64_t *base, uint64_t size, int bar_type)
185+
{
186+
int i;
187+
188+
for(i = 0; i < REGION_NUMS; i++){
189+
if(!reserved_bar_regions[i].vdev ||
190+
reserved_bar_regions[i].bar_type != bar_type)
191+
continue;
192+
if(is_mmio_rgns_overlap(reserved_bar_regions[i].start,
193+
reserved_bar_regions[i].end, *base, *base + size -1)){
194+
*base = roundup2(reserved_bar_regions[i].end + 1, size);
195+
}
196+
}
197+
}
198+
169199
static inline void
170200
CFGWRITE(struct pci_vdev *dev, int coff, uint32_t val, int bytes)
171201
{
@@ -525,10 +555,9 @@ pci_emul_mem_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
525555
return 0;
526556
}
527557

528-
529558
static int
530559
pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size,
531-
uint64_t *addr)
560+
uint64_t *addr, int bar_type)
532561
{
533562
uint64_t base;
534563

@@ -539,6 +568,14 @@ pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size,
539568

540569
base = roundup2(*baseptr, size);
541570

571+
/* TODO:Currently, we only reserve gvt mmio regions,
572+
* so ignore PCIBAR_IO when adjust_bar_region.
573+
* If other devices also use reserved bar regions later,
574+
* need remove pcibar_type != PCIBAR_IO condition
575+
*/
576+
if(bar_type != PCIBAR_IO)
577+
adjust_bar_region(&base, size, bar_type);
578+
542579
if (base + size <= limit) {
543580
*addr = base;
544581
*baseptr = base + size;
@@ -622,10 +659,10 @@ unregister_bar(struct pci_vdev *dev, int idx)
622659
modify_bar_registration(dev, idx, 0);
623660
}
624661

625-
static void
662+
static int
626663
register_bar(struct pci_vdev *dev, int idx)
627664
{
628-
modify_bar_registration(dev, idx, 1);
665+
return modify_bar_registration(dev, idx, 1);
629666
}
630667

631668
/* Are we decoding i/o port accesses for the emulated pci device? */
@@ -699,12 +736,28 @@ update_bar_address(struct vmctx *ctx, struct pci_vdev *dev, uint64_t addr,
699736
dev->dev_ops->vdev_update_bar_map(ctx, dev, idx, orig_addr);
700737
}
701738

739+
static struct mmio_rsvd_rgn *
740+
get_mmio_rsvd_rgn_by_vdev_idx(struct pci_vdev *pdi, int idx)
741+
{
742+
int i;
743+
744+
for(i = 0; i < REGION_NUMS; i++){
745+
if(reserved_bar_regions[i].vdev &&
746+
reserved_bar_regions[i].idx == idx &&
747+
reserved_bar_regions[i].vdev == pdi)
748+
return &reserved_bar_regions[i];
749+
}
750+
751+
return NULL;
752+
}
753+
702754
int
703755
pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
704756
enum pcibar_type type, uint64_t size)
705757
{
706758
int error;
707759
uint64_t *baseptr, limit, addr, mask, lobits, bar;
760+
struct mmio_rsvd_rgn *region;
708761

709762
if ((size & (size - 1)) != 0)
710763
size = 1UL << flsl(size); /* round up to a power of 2 */
@@ -773,8 +826,12 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
773826
return -1;
774827
}
775828

776-
if (baseptr != NULL) {
777-
error = pci_emul_alloc_resource(baseptr, limit, size, &addr);
829+
region = get_mmio_rsvd_rgn_by_vdev_idx(pdi, idx);
830+
if(region)
831+
addr = region->start;
832+
833+
if (baseptr != NULL && !region) {
834+
error = pci_emul_alloc_resource(baseptr, limit, size, &addr, type);
778835
if (error != 0)
779836
return error;
780837
}
@@ -792,7 +849,20 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase,
792849
pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32);
793850
}
794851

795-
register_bar(pdi, idx);
852+
error = register_bar(pdi, idx);
853+
854+
if(error != 0){
855+
/* FIXME: Currently, only gvt needs reserve regions.
856+
* because gvt isn't firstly initialized, previous pci
857+
* devices' bars may conflict with gvt bars.
858+
* Use register_bar to detect this case,
859+
* but this case rarely happen.
860+
* If this case always happens, we need to
861+
* change core.c code to ensure gvt firstly initialzed
862+
*/
863+
printf("%s failed to register_bar\n", pdi->name);
864+
return error;
865+
}
796866

797867
return 0;
798868
}

devicemodel/hw/pci/gvt.c

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
static int pci_gvt_debug;
2323

24+
static struct pci_vdev *gvt_dev;
25+
2426
#define DPRINTF(params) do { if (pci_gvt_debug) printf params; } while (0)
2527

2628
#define WPRINTF(params) (printf params)
@@ -89,8 +91,6 @@ gvt_init_config(struct pci_gvt *gvt)
8991
int ret;
9092
char name[PATH_MAX];
9193
uint8_t cap_ptr = 0;
92-
uint8_t aperture_size_reg;
93-
uint16_t aperture_size = 256;
9494
char res_name[PATH_MAX];
9595
char resource[512];
9696
int res_fd;
@@ -203,42 +203,15 @@ gvt_init_config(struct pci_gvt *gvt)
203203
/* processor graphics control register */
204204
pci_set_cfgdata16(gvt->gvt_pi, 0x52, gvt->host_config[0x52]);
205205

206-
/* Alloc resource only and no need to register bar for gvt */
207206
ret = pci_emul_alloc_bar(gvt->gvt_pi, 0, PCIBAR_MEM32,
208-
16 * 1024 * 1024);
207+
bar0_end_addr - bar0_start_addr + 1);
209208
if (ret != 0) {
210209
pr_err("allocate gvt pci bar[0] failed\n");
211210
return -1;
212211
}
213212

214-
/* same as host, but guest only use partition of it by ballon */
215-
aperture_size_reg = gvt->host_config[0x62];
216-
switch(aperture_size_reg & 0b1111){
217-
case 0b00000:
218-
aperture_size = 128;
219-
break;
220-
case 0b00001:
221-
aperture_size = 256;
222-
break;
223-
case 0b00011:
224-
aperture_size = 512;
225-
break;
226-
case 0b00111:
227-
aperture_size = 1024;
228-
break;
229-
case 0b01111:
230-
aperture_size = 2048;
231-
break;
232-
case 0b11111:
233-
aperture_size = 4096;
234-
break;
235-
default:
236-
aperture_size = 256;
237-
break;
238-
}
239-
240213
ret = pci_emul_alloc_bar(gvt->gvt_pi, 2, PCIBAR_MEM32,
241-
aperture_size * 1024 * 1024);
214+
bar2_end_addr - bar2_start_addr + 1);
242215
if (ret != 0) {
243216
pr_err("allocate gvt pci bar[2] failed\n");
244217
return -1;
@@ -344,6 +317,8 @@ pci_gvt_init(struct vmctx *ctx, struct pci_vdev *pi, char *opts)
344317
gvt->gvt_pi = pi;
345318
guest_domid = ctx->vmid;
346319

320+
gvt_dev = pi;
321+
347322
ret = gvt_init_config(gvt);
348323

349324
if (ret)
@@ -354,6 +329,7 @@ pci_gvt_init(struct vmctx *ctx, struct pci_vdev *pi, char *opts)
354329
if(!ret)
355330
return ret;
356331
fail:
332+
gvt_dev = NULL;
357333
ctx->gvt_enabled = false;
358334
perror("GVT: init failed\n");
359335
free(gvt);
@@ -372,8 +348,10 @@ pci_gvt_deinit(struct vmctx *ctx, struct pci_vdev *pi, char *opts)
372348
if (ret)
373349
WPRINTF(("GVT: %s: failed: errno=%d\n", __func__, ret));
374350

351+
destory_mmio_rsvd_rgns(gvt_dev);
375352
free(gvt);
376353
pi->arg = NULL;
354+
gvt_dev = NULL;
377355
}
378356
}
379357

0 commit comments

Comments
 (0)