Skip to content

Commit af163d5

Browse files
donshengwenlingz
authored andcommitted
HV: add support for 64-bit bar emulation
Enable 64-bit bar emulation, if pbar is of type PCIBAR_MEM64, vbar will also be of type PCIBAR_MEM64 instead of PCIBAR_MEM32 With 64-bit bar emulation code in place, we can remove enum pci_bar_type type from struct pci_bar as bar type can be derived from struct pci_bar's reg member by using the pci_get_bar_type function Rename functions: pci_base_from_size_mask --> git_size_masked_bar_base Remove unused functions Tracked-On: #3241 Signed-off-by: dongshen <dongsheng.x.zhang@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com>
1 parent 09a6356 commit af163d5

File tree

3 files changed

+66
-68
lines changed

3 files changed

+66
-68
lines changed

hypervisor/dm/vpci/pci_pt.c

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ static void set_vbar_base(struct pci_bar *vbar, uint32_t base)
346346

347347
/**
348348
* @pre vdev != NULL
349-
* @pre (vdev->bar[idx].type == PCIBAR_NONE) || (vdev->bar[idx].type == PCIBAR_MEM32)
350349
*/
351350
static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t val)
352351
{
@@ -361,22 +360,41 @@ static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t
361360

362361
vbar = &vdev->bar[idx];
363362

364-
switch (vdev->bar[idx].type) {
365-
case PCIBAR_NONE:
366-
break;
363+
if (vbar->is_64bit_high) {
364+
if (idx > 0U) {
365+
uint32_t prev_idx = idx - 1U;
367366

368-
case PCIBAR_MEM32:
369-
base = pci_base_from_size_mask(vbar->size, (uint64_t)val);
370-
set_vbar_base(vbar, (uint32_t)base);
367+
base = git_size_masked_bar_base(vdev->bar[prev_idx].size, ((uint64_t)val) << 32U) >> 32U;
368+
set_vbar_base(vbar, (uint32_t)base);
371369

372-
if (bar_update_normal) {
373-
vdev_pt_remap_mem_vbar(vdev, idx);
370+
if (bar_update_normal) {
371+
vdev_pt_remap_mem_vbar(vdev, prev_idx);
372+
}
373+
} else {
374+
ASSERT(false, "idx for upper 32-bit of the 64-bit bar should be greater than 0!");
374375
}
375-
break;
376+
} else {
377+
enum pci_bar_type type = pci_get_bar_type(vbar->reg.value);
378+
379+
switch (type) {
380+
case PCIBAR_MEM32:
381+
base = git_size_masked_bar_base(vbar->size, (uint64_t)val);
382+
set_vbar_base(vbar, (uint32_t)base);
376383

377-
default:
378-
/* Should never reach here, init_vdev_pt() only sets vbar type to PCIBAR_NONE and PCIBAR_MEM32 */
379-
break;
384+
if (bar_update_normal) {
385+
vdev_pt_remap_mem_vbar(vdev, idx);
386+
}
387+
break;
388+
389+
case PCIBAR_MEM64:
390+
base = git_size_masked_bar_base(vbar->size, (uint64_t)val);
391+
set_vbar_base(vbar, (uint32_t)base);
392+
break;
393+
394+
default:
395+
/* Nothing to do */
396+
break;
397+
}
380398
}
381399

382400
/* Write the vbar value to corresponding virtualized vbar reg */
@@ -403,15 +421,6 @@ int32_t vdev_pt_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes
403421
return ret;
404422
}
405423

406-
/**
407-
* For bar emulation, currently only MMIO is supported and bar size cannot be greater than 4GB
408-
* @pre bar != NULL
409-
*/
410-
static inline bool is_bar_supported(const struct pci_bar *bar)
411-
{
412-
return (is_mmio_bar(bar) && is_valid_bar_size(bar));
413-
}
414-
415424
/**
416425
* PCI base address register (bar) virtualization:
417426
*
@@ -453,40 +462,47 @@ void init_vdev_pt(struct pci_vdev *vdev)
453462
pbar = &vdev->pdev->bar[idx];
454463
vbar = &vdev->bar[idx];
455464

456-
if (is_bar_supported(pbar)) {
457-
vbar->reg.value = pbar->reg.value;
458-
vbar->reg.bits.mem.base = 0x0U; /* clear vbar base */
459-
if (vbar->reg.bits.mem.type == 0x2U) {
460-
/* Clear vbar 64-bit flag and set it to 32-bit */
461-
vbar->reg.bits.mem.type = 0x0U;
462-
}
463-
464-
/**
465-
* If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on
466-
* its bar size boundary, so in order to ensure the MMIO vbar allocated by guest
467-
* is 4k aligned, set its size to be 4K aligned.
468-
*/
469-
vbar->size = round_page_up(pbar->size);
470-
471-
/**
472-
* Only 32-bit bar is supported for now so both PCIBAR_MEM32 and PCIBAR_MEM64
473-
* are reported to guest as PCIBAR_MEM32
474-
*/
475-
vbar->type = PCIBAR_MEM32;
465+
vbar->size = 0UL;
466+
vbar->reg.value = pbar->reg.value;
467+
vbar->is_64bit_high = pbar->is_64bit_high;
476468

477-
/* For pre-launched VMs: vbar base is predefined in vm_config */
478-
vbar_base = vdev->ptdev_config->vbar_base[idx];
469+
if (pbar->is_64bit_high) {
470+
ASSERT(idx > 0U, "idx for upper 32-bit of the 64-bit bar should be greater than 0!");
479471

480-
/* Set the new vbar base */
481-
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)vbar_base);
472+
if (idx > 0U) {
473+
/* For pre-launched VMs: vbar base is predefined in vm_config */
474+
vbar_base = vdev->ptdev_config->vbar_base[idx - 1U];
475+
/* Write the upper 32-bit of a 64-bit bar */
476+
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)(vbar_base >> 32U));
477+
}
482478
} else {
483-
vbar->reg.value = 0x0U;
484-
vbar->size = 0UL;
485-
vbar->type = PCIBAR_NONE;
479+
enum pci_bar_type type = pci_get_bar_type(pbar->reg.value);
480+
481+
switch (type) {
482+
case PCIBAR_MEM32:
483+
case PCIBAR_MEM64:
484+
/**
485+
* If vbar->base is 0 (unassigned), Linux kernel will reprogram the vbar on
486+
* its bar size boundary, so in order to ensure the MMIO vbar allocated by guest
487+
* is 4k aligned, set its size to be 4K aligned.
488+
*/
489+
vbar->size = round_page_up(pbar->size);
490+
491+
/* For pre-launched VMs: vbar base is predefined in vm_config */
492+
vbar_base = vdev->ptdev_config->vbar_base[idx];
493+
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), (uint32_t)vbar_base);
494+
break;
495+
496+
default:
497+
vbar->reg.value = 0x0U;
498+
vbar->size = 0UL;
499+
break;
500+
}
486501
}
487502
}
488503

489504
pci_command = (uint16_t)pci_pdev_read_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U);
505+
490506
/* Disable INTX */
491507
pci_command |= 0x400U;
492508
pci_pdev_write_cfg(vdev->pdev->bdf, PCIR_COMMAND, 2U, pci_command);

hypervisor/hw/pci.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@ static uint32_t pci_pdev_read_bar(union pci_bdf bdf, uint32_t idx, struct pci_ba
287287
}
288288

289289
bar->size = size;
290-
bar->type = type;
291290

292291
return (type == PCIBAR_MEM64)?2U:1U;
293292
}

hypervisor/include/hw/pci.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,6 @@ struct pci_bar {
183183
/* Base Address Register */
184184
union pci_bar_reg reg;
185185
uint64_t size;
186-
enum pci_bar_type type;
187186
bool is_64bit_high; /* true if this is the upper 32-bit of a 64-bit bar */
188187
};
189188

@@ -270,7 +269,7 @@ static inline enum pci_bar_type pci_get_bar_type(uint32_t val)
270269
* Given bar size and raw bar value, return bar base address by masking off its lower flag bits
271270
* size/val: all in 64-bit values to accommodate 64-bit MMIO bar size masking
272271
*/
273-
static inline uint64_t pci_base_from_size_mask(uint64_t size, uint64_t val)
272+
static inline uint64_t git_size_masked_bar_base(uint64_t size, uint64_t val)
274273
{
275274
uint64_t mask;
276275

@@ -308,22 +307,6 @@ static inline bool bdf_is_equal(const union pci_bdf *a, const union pci_bdf *b)
308307
return (a->value == b->value);
309308
}
310309

311-
/**
312-
* @pre bar != NULL
313-
*/
314-
static inline bool is_mmio_bar(const struct pci_bar *bar)
315-
{
316-
return (bar->type == PCIBAR_MEM32) || (bar->type == PCIBAR_MEM64);
317-
}
318-
319-
/**
320-
* @pre bar != NULL
321-
*/
322-
static inline bool is_valid_bar_size(const struct pci_bar *bar)
323-
{
324-
return (bar->size > 0UL) && (bar->size <= 0xffffffffU);
325-
}
326-
327310
uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes);
328311
void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val);
329312
void enable_disable_pci_intx(union pci_bdf bdf, bool enable);

0 commit comments

Comments
 (0)