Skip to content

Commit 32d1a9d

Browse files
donshengacrnsi
authored andcommitted
HV: move bar emulation initialization code to pci_pt.c
Create the init_vdev_pt() function to host bar emulation initialization code Add design philosophy for bar emulation Move common functions to pci.h as they are generic and can be used by other files. Rename is_valid_bar to is_bar_supported and keep it as a private local function in pci_pt.c Tracked-On: #3056 Signed-off-by: dongshen <dongsheng.x.zhang@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com>
1 parent 67b2e2b commit 32d1a9d

File tree

4 files changed

+93
-51
lines changed

4 files changed

+93
-51
lines changed

hypervisor/dm/vpci/pci_pt.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,74 @@ int32_t vdev_pt_cfgwrite(struct pci_vdev *vdev, uint32_t offset,
261261

262262
return ret;
263263
}
264+
265+
/**
266+
* For bar emulation, currently only MMIO is supported and bar size cannot be greater than 4GB
267+
* @pre bar != NULL
268+
*/
269+
static inline bool is_bar_supported(const struct pci_bar *bar)
270+
{
271+
return (is_mmio_bar(bar) && is_valid_bar_size(bar));
272+
}
273+
274+
/**
275+
* PCI base address register (bar) virtualization:
276+
*
277+
* Virtualize the PCI bars (up to 6 bars at byte offset 0x10~0x24 for type 0 PCI device,
278+
* 2 bars at byte offset 0x10-0x14 for type 1 PCI device) of the PCI configuration space
279+
* header.
280+
*
281+
* pbar: bar for the physical PCI device (pci_pdev), the value of pbar (hpa) is assigned
282+
* by platform firmware during boot. It is assumed a valid hpa is always assigned to a
283+
* mmio pbar, hypervisor shall not change the value of a pbar.
284+
*
285+
* vbar: for each pci_pdev, it has a virtual PCI device (pci_vdev) counterpart. pci_vdev
286+
* virtualizes all the bars (called vbars). a vbar can be initialized by hypervisor by
287+
* assigning a gpa to it; if vbar has a value of 0 (unassigned), guest may assign
288+
* and program a gpa to it. The guest only sees the vbars, it will not see and can
289+
* never change the pbars.
290+
*
291+
* Hypervisor traps guest changes to the mmio vbar (gpa) to establish ept mapping
292+
* between vbar(gpa) and pbar(hpa). pbar should always align on 4K boundary.
293+
*
294+
* @pre vdev != NULL
295+
* @pre vdev->vpci != NULL
296+
* @pre vdev->vpci->vm != NULL
297+
* @pre vdev->pdev != NULL
298+
*/
299+
void init_vdev_pt(struct pci_vdev *vdev)
300+
{
301+
uint32_t idx;
302+
struct pci_bar *pbar, *vbar;
303+
uint16_t pci_command;
304+
305+
if (is_prelaunched_vm(vdev->vpci->vm)) {
306+
for (idx = 0U; idx < (uint32_t)PCI_BAR_COUNT; idx++) {
307+
pbar = &vdev->pdev->bar[idx];
308+
vbar = &vdev->bar[idx];
309+
310+
if (is_bar_supported(pbar)) {
311+
/**
312+
* If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on
313+
* its bar size boundary, so in order to ensure the vbar allocated by guest
314+
* is 4k aligned, set its size to be 4K aligned.
315+
*/
316+
vbar->size = round_page_up(pbar->size);
317+
318+
/**
319+
* Only 32-bit bar is supported for now so both PCIBAR_MEM32 and PCIBAR_MEM64
320+
* are reported to guest as PCIBAR_MEM32
321+
*/
322+
vbar->type = PCIBAR_MEM32;
323+
} else {
324+
vbar->size = 0UL;
325+
vbar->type = PCIBAR_NONE;
326+
}
327+
}
328+
329+
pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U);
330+
/* Disable INTX */
331+
pci_command |= 0x400U;
332+
pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command);
333+
}
334+
}

hypervisor/dm/vpci/vpci.c

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -268,31 +268,6 @@ static inline bool is_hostbridge(const struct pci_vdev *vdev)
268268
return (vdev->vbdf.value == 0U);
269269
}
270270

271-
/**
272-
* @pre bar != NULL
273-
*/
274-
static inline bool is_valid_bar_type(const struct pci_bar *bar)
275-
{
276-
return (bar->type == PCIBAR_MEM32) || (bar->type == PCIBAR_MEM64);
277-
}
278-
279-
/**
280-
* @pre bar != NULL
281-
*/
282-
static inline bool is_valid_bar_size(const struct pci_bar *bar)
283-
{
284-
return (bar->size > 0UL) && (bar->size <= 0xffffffffU);
285-
}
286-
287-
/**
288-
* Only MMIO is supported and bar size cannot be greater than 4GB
289-
* @pre bar != NULL
290-
*/
291-
static inline bool is_valid_bar(const struct pci_bar *bar)
292-
{
293-
return (is_valid_bar_type(bar) && is_valid_bar_size(bar));
294-
}
295-
296271
/**
297272
* @pre vdev != NULL
298273
* @pre vdev->vpci != NULL
@@ -341,35 +316,12 @@ static void remove_vdev_pt_iommu_domain(const struct pci_vdev *vdev)
341316
static void partition_mode_pdev_init(struct pci_vdev *vdev, union pci_bdf pbdf)
342317
{
343318
struct pci_pdev *pdev;
344-
uint32_t idx;
345-
struct pci_bar *pbar, *vbar;
346-
uint16_t pci_command;
347319

348320
pdev = find_pci_pdev(pbdf);
349321
ASSERT(pdev != NULL, "pdev is NULL");
350322

351323
vdev->pdev = pdev;
352324

353-
/* Sanity checking for vbar */
354-
for (idx = 0U; idx < (uint32_t)PCI_BAR_COUNT; idx++) {
355-
pbar = &vdev->pdev->bar[idx];
356-
vbar = &vdev->bar[idx];
357-
358-
if (is_valid_bar(pbar)) {
359-
vbar->size = (pbar->size < 0x1000U) ? 0x1000U : pbar->size;
360-
vbar->type = PCIBAR_MEM32;
361-
} else {
362-
/* Mark this vbar as invalid */
363-
vbar->size = 0UL;
364-
vbar->type = PCIBAR_NONE;
365-
}
366-
}
367-
368-
pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U);
369-
/* Disable INTX */
370-
pci_command |= 0x400U;
371-
pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command);
372-
373325
assign_vdev_pt_iommu_domain(vdev);
374326
}
375327

@@ -402,6 +354,8 @@ int32_t partition_mode_vpci_init(struct acrn_vm *vm)
402354
} else {
403355
partition_mode_pdev_init(vdev, ptdev_config->pbdf);
404356

357+
init_vdev_pt(vdev);
358+
405359
vmsi_init(vdev);
406360

407361
vmsix_init(vdev);
@@ -560,7 +514,6 @@ static void init_vdev_for_pdev(struct pci_pdev *pdev, const void *vm)
560514
}
561515
}
562516

563-
564517
/**
565518
* @pre vm != NULL
566519
* @pre is_sos_vm(vm) == true

hypervisor/dm/vpci/vpci_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ int32_t vhostbridge_cfgread(const struct pci_vdev *vdev, uint32_t offset, uint32
8080
int32_t vhostbridge_cfgwrite(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
8181
void vhostbridge_deinit(__unused const struct pci_vdev *vdev);
8282

83+
void init_vdev_pt(struct pci_vdev *vdev);
8384
int32_t vdev_pt_cfgread(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
8485
int32_t vdev_pt_cfgwrite(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
8586

hypervisor/include/hw/pci.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,31 @@ static inline uint8_t pci_devfn(uint16_t bdf)
220220
return (uint8_t)(bdf & 0xFFU);
221221
}
222222

223-
/*
224-
* @pre a != NULL && b != NULL
223+
/**
224+
* @pre a != NULL
225+
* @pre b != NULL
225226
*/
226227
static inline bool bdf_is_equal(const union pci_bdf *a, const union pci_bdf *b)
227228
{
228229
return (a->value == b->value);
229230
}
230231

232+
/**
233+
* @pre bar != NULL
234+
*/
235+
static inline bool is_mmio_bar(const struct pci_bar *bar)
236+
{
237+
return (bar->type == PCIBAR_MEM32) || (bar->type == PCIBAR_MEM64);
238+
}
239+
240+
/**
241+
* @pre bar != NULL
242+
*/
243+
static inline bool is_valid_bar_size(const struct pci_bar *bar)
244+
{
245+
return (bar->size > 0UL) && (bar->size <= 0xffffffffU);
246+
}
247+
231248
uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes);
232249
void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val);
233250
void enable_disable_pci_intx(union pci_bdf bdf, bool enable);

0 commit comments

Comments
 (0)