mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 13:37:10 +00:00
hv: vpci: reshuffle pci_bar structure
The current code declare pci_bar structure following the PCI bar spec. However, we could not tell whether the value in virtual BAR configuration space is valid base address base on current pci_bar structure. We need to add more fields which are duplicated instances of the vBAR information. Basides these fields which will added, bar_base_mapped is another duplicated instance of the vBAR information. This patch try to reshuffle the pci_bar structure to declare pci_bar structure following the software implement benefit not the PCI bar spec. Tracked-On: #3475 Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
parent
f53baadd5a
commit
c049c5c965
@ -32,68 +32,6 @@
|
||||
#include <logmsg.h>
|
||||
#include "vpci_priv.h"
|
||||
|
||||
/**
|
||||
* @brief get bar's full base address in 64-bit
|
||||
* @pre (pci_get_bar_type(bars[idx].reg.value) == PCIBAR_MEM64) ? ((idx + 1U) < nr_bars) : (idx < nr_bars)
|
||||
* For 64-bit MMIO bar, its lower 32-bits base address and upper 32-bits base are combined
|
||||
* into one 64-bit base address
|
||||
*/
|
||||
static uint64_t pci_bar_2_bar_base(const struct pci_bar *bars, uint32_t nr_bars, uint32_t idx)
|
||||
{
|
||||
uint64_t base = 0UL;
|
||||
uint64_t tmp;
|
||||
const struct pci_bar *bar;
|
||||
enum pci_bar_type type;
|
||||
|
||||
bar = &bars[idx];
|
||||
type = pci_get_bar_type(bar->reg.value);
|
||||
switch (type) {
|
||||
case PCIBAR_IO_SPACE:
|
||||
/* IO bar, BITS 31-2 = base address, 4-byte aligned */
|
||||
base = (uint64_t)(bar->reg.bits.io.base);
|
||||
base <<= 2U;
|
||||
break;
|
||||
|
||||
case PCIBAR_MEM32:
|
||||
base = (uint64_t)(bar->reg.bits.mem.base);
|
||||
base <<= 4U;
|
||||
break;
|
||||
|
||||
case PCIBAR_MEM64:
|
||||
if ((idx + 1U) < nr_bars) {
|
||||
const struct pci_bar *next_bar = &bars[idx + 1U];
|
||||
|
||||
/* Upper 32-bit of 64-bit bar */
|
||||
base = (uint64_t)(next_bar->reg.value);
|
||||
base <<= 32U;
|
||||
|
||||
/* Lower 32-bit of a 64-bit bar (BITS 31-4 = base address, 16-byte aligned) */
|
||||
tmp = (uint64_t)(bar->reg.bits.mem.base);
|
||||
tmp <<= 4U;
|
||||
|
||||
base |= tmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get vbar's full base address in 64-bit
|
||||
* For 64-bit MMIO bar, its lower 32-bits base address and upper 32-bits base are combined
|
||||
* into one 64-bit base address
|
||||
* @pre vdev != NULL
|
||||
*/
|
||||
static uint64_t get_vbar_base(const struct pci_vdev *vdev, uint32_t idx)
|
||||
{
|
||||
return pci_bar_2_bar_base(&vdev->bar[0], vdev->nr_bars, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vdev != NULL
|
||||
*/
|
||||
@ -120,11 +58,11 @@ static void vdev_pt_unmap_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
|
||||
if (vdev->bar_base_mapped[idx] != 0UL) {
|
||||
if (vbar->base != 0UL) {
|
||||
ept_del_mr(vm, (uint64_t *)(vm->arch_vm.nworld_eptp),
|
||||
vdev->bar_base_mapped[idx], /* GPA (old vbar) */
|
||||
vbar->base, /* GPA (old vbar) */
|
||||
vbar->size);
|
||||
vdev->bar_base_mapped[idx] = 0UL;
|
||||
vbar->base = 0UL;
|
||||
}
|
||||
|
||||
is_msix_table_bar = (has_msix_cap(vdev) && (idx == vdev->msix.table_bar));
|
||||
@ -169,7 +107,7 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
|
||||
vbar_base = get_vbar_base(vdev, idx);
|
||||
vbar_base = pci_vdev_get_bar_base(vdev, idx);
|
||||
if (vbar_base != 0UL) {
|
||||
if (ept_is_mr_valid(vm, vbar_base, vbar->size)) {
|
||||
uint64_t hpa = gpa2hpa(vdev->vpci->vm, vbar_base);
|
||||
@ -183,7 +121,7 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
EPT_WR | EPT_RD | EPT_UNCACHED);
|
||||
}
|
||||
/* Remember the previously mapped MMIO vbar */
|
||||
vdev->bar_base_mapped[idx] = vbar_base;
|
||||
vbar->base = vbar_base;
|
||||
} else {
|
||||
pr_fatal("%s, %x:%x.%x set invalid bar[%d] address: 0x%lx\n", __func__,
|
||||
vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, vbar_base);
|
||||
@ -195,8 +133,8 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
uint64_t addr_hi, addr_lo;
|
||||
struct pci_msix *msix = &vdev->msix;
|
||||
|
||||
if (vdev->bar_base_mapped[idx] != 0UL) {
|
||||
addr_lo = vdev->bar_base_mapped[idx] + msix->table_offset;
|
||||
if (vbar->base != 0UL) {
|
||||
addr_lo = vbar->base + msix->table_offset;
|
||||
addr_hi = addr_lo + (msix->table_count * MSIX_TABLE_ENTRY_SIZE);
|
||||
|
||||
addr_lo = round_page_down(addr_lo);
|
||||
@ -204,7 +142,7 @@ static void vdev_pt_map_mem_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
register_mmio_emulation_handler(vm, vmsix_table_mmio_access_handler,
|
||||
addr_lo, addr_hi, vdev);
|
||||
ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, addr_lo, addr_hi - addr_lo);
|
||||
msix->mmio_gpa = vdev->bar_base_mapped[idx];
|
||||
msix->mmio_gpa = vbar->base;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -220,11 +158,11 @@ static void vdev_pt_allow_io_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
/* For SOS, all port IO access is allowed by default, so skip SOS here */
|
||||
if (!is_sos_vm(vdev->vpci->vm)) {
|
||||
struct pci_bar *vbar = &vdev->bar[idx];
|
||||
uint64_t vbar_base = get_vbar_base(vdev, idx); /* vbar (gpa) */
|
||||
uint64_t vbar_base = pci_vdev_get_bar_base(vdev, idx); /* vbar (gpa) */
|
||||
if (vbar_base != 0UL) {
|
||||
allow_guest_pio_access(vdev->vpci->vm, (uint16_t)vbar_base, (uint32_t)(vbar->size));
|
||||
/* Remember the previously allowed IO vbar base */
|
||||
vdev->bar_base_mapped[idx] = vbar_base;
|
||||
vbar->base = vbar_base;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,117 +178,56 @@ static void vdev_pt_deny_io_vbar(struct pci_vdev *vdev, uint32_t idx)
|
||||
/* For SOS, all port IO access is allowed by default, so skip SOS here */
|
||||
if (!is_sos_vm(vdev->vpci->vm)) {
|
||||
struct pci_bar *vbar = &vdev->bar[idx];
|
||||
if (vdev->bar_base_mapped[idx] != 0UL) {
|
||||
deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vdev->bar_base_mapped[idx]),
|
||||
(uint32_t)(vbar->size));
|
||||
vdev->bar_base_mapped[idx] = 0UL;
|
||||
if (vbar->base != 0UL) {
|
||||
deny_guest_pio_access(vdev->vpci->vm, (uint16_t)(vbar->base), (uint32_t)(vbar->size));
|
||||
vbar->base = 0UL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the base address portion of the vbar base address register (32-bit)
|
||||
* base: bar value with flags portion masked off
|
||||
* @pre vbar != NULL
|
||||
*/
|
||||
static void set_vbar_base(struct pci_bar *vbar, uint32_t base)
|
||||
{
|
||||
union pci_bar_reg bar_reg;
|
||||
|
||||
bar_reg.value = base;
|
||||
|
||||
if (vbar->is_64bit_high) {
|
||||
/* Upper 32-bit of a 64-bit bar does not have the flags portion */
|
||||
vbar->reg.value = bar_reg.value;
|
||||
} else if (vbar->reg.bits.io.is_io == 1U) {
|
||||
/* IO bar, BITS 31-2 = base address, 4-byte aligned */
|
||||
vbar->reg.bits.io.base = bar_reg.bits.io.base;
|
||||
} else {
|
||||
/* MMIO bar, BITS 31-4 = base address, 16-byte aligned */
|
||||
vbar->reg.bits.mem.base = bar_reg.bits.mem.base;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vdev != NULL
|
||||
*/
|
||||
static void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t offset, uint32_t val)
|
||||
void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
|
||||
{
|
||||
uint32_t idx;
|
||||
uint64_t base;
|
||||
bool bar_update_normal;
|
||||
struct pci_bar *vbar;
|
||||
bool update_bar = false;
|
||||
uint32_t update_idx = idx;
|
||||
uint32_t offset = pci_bar_offset(idx);
|
||||
struct pci_bar *vbar = &vdev->bar[idx];
|
||||
|
||||
base = 0UL;
|
||||
idx = (offset - pci_bar_offset(0U)) >> 2U;
|
||||
bar_update_normal = (val != (uint32_t)~0U);
|
||||
switch (vbar->type) {
|
||||
case PCIBAR_IO_SPACE:
|
||||
vdev_pt_deny_io_vbar(vdev, update_idx);
|
||||
if (val != ~0U) {
|
||||
pci_vdev_write_bar(vdev, idx, val);
|
||||
vdev_pt_allow_io_vbar(vdev, update_idx);
|
||||
} else {
|
||||
pci_vdev_write_cfg_u32(vdev, offset, vbar->mask);
|
||||
}
|
||||
break;
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
|
||||
if (vbar->is_64bit_high) {
|
||||
if (idx > 0U) {
|
||||
uint32_t prev_idx = idx - 1U;
|
||||
|
||||
vdev_pt_unmap_mem_vbar(vdev, prev_idx);
|
||||
base = git_size_masked_bar_base(vdev->bar[prev_idx].size, ((uint64_t)val) << 32U) >> 32U;
|
||||
set_vbar_base(vbar, (uint32_t)base);
|
||||
|
||||
if (bar_update_normal) {
|
||||
vdev_pt_map_mem_vbar(vdev, prev_idx);
|
||||
case PCIBAR_MEM64HI:
|
||||
update_idx = idx - 1U;
|
||||
/* falls through */
|
||||
case PCIBAR_MEM32:
|
||||
update_bar = true;
|
||||
/* falls through */
|
||||
case PCIBAR_MEM64:
|
||||
vdev_pt_unmap_mem_vbar(vdev, update_idx);
|
||||
if (val != ~0U) {
|
||||
pci_vdev_write_bar(vdev, idx, val);
|
||||
if (update_bar) {
|
||||
vdev_pt_map_mem_vbar(vdev, update_idx);
|
||||
}
|
||||
} else {
|
||||
ASSERT(false, "idx for upper 32-bit of the 64-bit bar should be greater than 0!");
|
||||
pci_vdev_write_cfg_u32(vdev, offset, vbar->mask);
|
||||
}
|
||||
} else {
|
||||
enum pci_bar_type type = pci_get_bar_type(vbar->reg.value);
|
||||
break;
|
||||
|
||||
switch (type) {
|
||||
case PCIBAR_IO_SPACE:
|
||||
vdev_pt_deny_io_vbar(vdev, idx);
|
||||
base = git_size_masked_bar_base(vbar->size, (uint64_t)val) & 0xffffUL;
|
||||
set_vbar_base(vbar, (uint32_t)base);
|
||||
|
||||
if (bar_update_normal) {
|
||||
vdev_pt_allow_io_vbar(vdev, idx);
|
||||
}
|
||||
break;
|
||||
|
||||
case PCIBAR_MEM32:
|
||||
vdev_pt_unmap_mem_vbar(vdev, idx);
|
||||
base = git_size_masked_bar_base(vbar->size, (uint64_t)val);
|
||||
set_vbar_base(vbar, (uint32_t)base);
|
||||
|
||||
if (bar_update_normal) {
|
||||
vdev_pt_map_mem_vbar(vdev, idx);
|
||||
}
|
||||
break;
|
||||
|
||||
case PCIBAR_MEM64:
|
||||
vdev_pt_unmap_mem_vbar(vdev, idx);
|
||||
base = git_size_masked_bar_base(vbar->size, (uint64_t)val);
|
||||
set_vbar_base(vbar, (uint32_t)base);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the vbar value to corresponding virtualized vbar reg */
|
||||
pci_vdev_write_cfg_u32(vdev, offset, vbar->reg.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vdev != NULL
|
||||
* bar write access must be 4 bytes and offset must also be 4 bytes aligned, it will be dropped otherwise
|
||||
*/
|
||||
void vdev_pt_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val)
|
||||
{
|
||||
/* bar write access must be 4 bytes and offset must also be 4 bytes aligned */
|
||||
if ((bytes == 4U) && ((offset & 0x3U) == 0U)) {
|
||||
vdev_pt_write_vbar(vdev, offset, val);
|
||||
default:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,8 +291,10 @@ void init_vdev_pt(struct pci_vdev *vdev)
|
||||
size32 = pci_pdev_read_cfg(pbdf, offset, 4U);
|
||||
pci_pdev_write_cfg(pbdf, offset, 4U, lo);
|
||||
|
||||
vbar->type = type;
|
||||
vbar->mask = size32 & mask;
|
||||
vbar->fixed = lo & (~mask);
|
||||
vbar->size = (uint64_t)size32 & mask;
|
||||
vbar->reg.value = lo;
|
||||
|
||||
if (is_prelaunched_vm(vdev->vpci->vm)) {
|
||||
lo = (uint32_t)vdev->pci_dev_config->vbar_base[idx];
|
||||
@ -433,20 +312,20 @@ void init_vdev_pt(struct pci_vdev *vdev)
|
||||
vbar->size = round_page_up(vbar->size);
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
vbar->is_64bit_high = true;
|
||||
vbar->reg.value = hi;
|
||||
vbar->mask = size32;
|
||||
vbar->type = PCIBAR_MEM64HI;
|
||||
|
||||
if (is_prelaunched_vm(vdev->vpci->vm)) {
|
||||
hi = (uint32_t)(vdev->pci_dev_config->vbar_base[idx - 1U] >> 32U);
|
||||
}
|
||||
vdev_pt_write_vbar(vdev, pci_bar_offset(idx - 1U), lo);
|
||||
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), hi);
|
||||
vdev_pt_write_vbar(vdev, idx - 1U, lo);
|
||||
vdev_pt_write_vbar(vdev, idx, hi);
|
||||
} else {
|
||||
vbar->size = vbar->size & ~(vbar->size - 1UL);
|
||||
if (type == PCIBAR_MEM32) {
|
||||
vbar->size = round_page_up(vbar->size);
|
||||
}
|
||||
vdev_pt_write_vbar(vdev, pci_bar_offset(idx), lo);
|
||||
vdev_pt_write_vbar(vdev, idx, lo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,3 +91,47 @@ struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf)
|
||||
|
||||
return vdev;
|
||||
}
|
||||
|
||||
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val)
|
||||
{
|
||||
struct pci_bar *vbar;
|
||||
uint32_t bar, offset;
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
bar = val & vbar->mask;
|
||||
bar |= vbar->fixed;
|
||||
offset = pci_bar_offset(idx);
|
||||
pci_vdev_write_cfg_u32(vdev, offset, bar);
|
||||
}
|
||||
|
||||
uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx)
|
||||
{
|
||||
const struct pci_bar *vbar;
|
||||
enum pci_bar_type type;
|
||||
uint64_t base = 0UL;
|
||||
uint32_t lo, hi, offset;
|
||||
|
||||
vbar = &vdev->bar[idx];
|
||||
offset = pci_bar_offset(idx);
|
||||
lo = pci_vdev_read_cfg_u32(vdev, offset);
|
||||
if ((vbar->type != PCIBAR_NONE) && (lo != ~0U)) {
|
||||
type = vbar->type;
|
||||
base = lo & vbar->mask;
|
||||
|
||||
if (vbar->type == PCIBAR_MEM64) {
|
||||
vbar = &vdev->bar[idx + 1U];
|
||||
hi = pci_vdev_read_cfg_u32(vdev, offset + 4U);
|
||||
if (hi != ~0U) {
|
||||
hi &= vbar->mask;
|
||||
base |= ((uint64_t)hi << 32U);
|
||||
} else {
|
||||
base = 0UL;
|
||||
}
|
||||
}
|
||||
if (type == PCIBAR_IO_SPACE) {
|
||||
base &= 0xffffUL;
|
||||
}
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
@ -329,7 +329,10 @@ static int32_t vpci_write_pt_dev_cfg(struct pci_vdev *vdev, uint32_t offset,
|
||||
uint32_t bytes, uint32_t val)
|
||||
{
|
||||
if (vbar_access(vdev, offset)) {
|
||||
vdev_pt_write_cfg(vdev, offset, bytes, val);
|
||||
/* bar write access must be 4 bytes and offset must also be 4 bytes aligned */
|
||||
if ((bytes == 4U) && ((offset & 0x3U) == 0U)) {
|
||||
vdev_pt_write_vbar(vdev, pci_bar_index(offset), val);
|
||||
}
|
||||
} else if (msicap_access(vdev, offset)) {
|
||||
vmsi_write_cfg(vdev, offset, bytes, val);
|
||||
} else if (msixcap_access(vdev, offset)) {
|
||||
|
@ -127,7 +127,7 @@ static inline bool msicap_access(const struct pci_vdev *vdev, uint32_t offset)
|
||||
|
||||
void init_vdev_pt(struct pci_vdev *vdev);
|
||||
void vdev_pt_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
|
||||
void vdev_pt_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||
void vdev_pt_write_vbar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
|
||||
|
||||
void init_vmsi(struct pci_vdev *vdev);
|
||||
void vmsi_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t *val);
|
||||
@ -145,4 +145,6 @@ void pci_vdev_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes,
|
||||
|
||||
struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf);
|
||||
|
||||
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
|
||||
uint64_t pci_vdev_get_bar_base(const struct pci_vdev *vdev, uint32_t idx);
|
||||
#endif /* VPCI_PRIV_H_ */
|
||||
|
@ -34,6 +34,15 @@
|
||||
#include <pci.h>
|
||||
|
||||
|
||||
struct pci_bar {
|
||||
enum pci_bar_type type;
|
||||
uint64_t size; /* BAR size */
|
||||
uint64_t base; /* BAR guest physical address */
|
||||
uint64_t base_hpa; /* BAR host physical address */
|
||||
uint32_t fixed; /* BAR fix memory type encoding */
|
||||
uint32_t mask; /* BAR size mask */
|
||||
};
|
||||
|
||||
struct msix_table_entry {
|
||||
uint64_t addr;
|
||||
uint32_t data;
|
||||
@ -61,8 +70,8 @@ struct pci_msix {
|
||||
|
||||
union pci_cfgdata {
|
||||
uint8_t data_8[PCI_REGMAX + 1U];
|
||||
uint16_t data_16[(PCI_REGMAX + 1U) >> 2U];
|
||||
uint32_t data_32[(PCI_REGMAX + 1U) >> 4U];
|
||||
uint16_t data_16[(PCI_REGMAX + 1U) >> 1U];
|
||||
uint32_t data_32[(PCI_REGMAX + 1U) >> 2U];
|
||||
};
|
||||
|
||||
struct pci_vdev;
|
||||
@ -86,9 +95,6 @@ struct pci_vdev {
|
||||
uint32_t nr_bars; /* 6 for normal device, 2 for bridge, 1 for cardbus */
|
||||
struct pci_bar bar[PCI_BAR_COUNT];
|
||||
|
||||
/* Remember the previously mapped/registered vbar base for undo purpose */
|
||||
uint64_t bar_base_mapped[PCI_BAR_COUNT];
|
||||
|
||||
struct pci_msi msi;
|
||||
struct pci_msix msix;
|
||||
|
||||
|
@ -151,47 +151,7 @@ enum pci_bar_type {
|
||||
PCIBAR_IO_SPACE,
|
||||
PCIBAR_MEM32,
|
||||
PCIBAR_MEM64,
|
||||
};
|
||||
|
||||
/*
|
||||
* Base Address Register for MMIO, pf=prefetchable, type=0 (32-bit), 1 (<=1MB), 2 (64-bit):
|
||||
* 31 4 3 2 1 0
|
||||
* +----------+--------------+-------------+
|
||||
* | Base address |pf| type | 0 |
|
||||
* +---------------------------------------+
|
||||
*
|
||||
* Base Address Register for IO (R=reserved):
|
||||
* 31 2 1 0
|
||||
* +----------+----------------------------+
|
||||
* | Base address | R | 1 |
|
||||
* +---------------------------------------+
|
||||
*/
|
||||
union pci_bar_reg {
|
||||
uint32_t value;
|
||||
|
||||
/* Base address + flags portion */
|
||||
union {
|
||||
struct {
|
||||
uint32_t is_io:1; /* 0 for memory */
|
||||
uint32_t type:2;
|
||||
uint32_t prefetchable:1;
|
||||
uint32_t base:28; /* BITS 31-4 = base address, 16-byte aligned */
|
||||
} mem;
|
||||
|
||||
struct {
|
||||
uint32_t is_io:1; /* 1 for I/O */
|
||||
uint32_t:1;
|
||||
uint32_t base:30; /* BITS 31-2 = base address, 4-byte aligned */
|
||||
} io;
|
||||
} bits;
|
||||
};
|
||||
|
||||
struct pci_bar {
|
||||
/* Base Address Register */
|
||||
union pci_bar_reg reg;
|
||||
uint64_t size;
|
||||
uint64_t base_hpa;
|
||||
bool is_64bit_high; /* true if this is the upper 32-bit of a 64-bit bar */
|
||||
PCIBAR_MEM64HI,
|
||||
};
|
||||
|
||||
/* Basic MSIX capability info */
|
||||
@ -221,6 +181,11 @@ static inline uint32_t pci_bar_offset(uint32_t idx)
|
||||
return PCIR_BARS + (idx << 2U);
|
||||
}
|
||||
|
||||
static inline uint32_t pci_bar_index(uint32_t offset)
|
||||
{
|
||||
return (offset - PCIR_BARS) >> 2U;
|
||||
}
|
||||
|
||||
static inline bool is_bar_offset(uint32_t nr_bars, uint32_t offset)
|
||||
{
|
||||
bool ret;
|
||||
@ -244,7 +209,6 @@ static inline enum pci_bar_type pci_get_bar_type(uint32_t val)
|
||||
} else {
|
||||
switch (val & PCIM_BAR_MEM_TYPE) {
|
||||
case PCIM_BAR_MEM_32:
|
||||
case PCIM_BAR_MEM_1MB:
|
||||
type = PCIBAR_MEM32;
|
||||
break;
|
||||
|
||||
@ -261,19 +225,6 @@ static inline enum pci_bar_type pci_get_bar_type(uint32_t val)
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given bar size and raw bar value, return bar base address by masking off its lower flag bits
|
||||
* size/val: all in 64-bit values to accommodate 64-bit MMIO bar size masking
|
||||
*/
|
||||
static inline uint64_t git_size_masked_bar_base(uint64_t size, uint64_t val)
|
||||
{
|
||||
uint64_t mask;
|
||||
|
||||
mask = ~(size - 1UL);
|
||||
|
||||
return (mask & val);
|
||||
}
|
||||
|
||||
static inline bool bdf_is_equal(union pci_bdf a, union pci_bdf b)
|
||||
{
|
||||
return (a.value == b.value);
|
||||
|
Loading…
Reference in New Issue
Block a user