Skip to content

Commit

Permalink
efi: Add --pci_pt to passthrough a specific device
Browse files Browse the repository at this point in the history
  • Loading branch information
chp-io committed Apr 19, 2021
1 parent 6baced5 commit 7658043
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 28 deletions.
14 changes: 14 additions & 0 deletions deps/hypervisor/bfdriver/src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ uint64_t pci_pt_class_count = 0;
uint64_t no_pci_pt_list[NO_PCI_PT_LIST_SIZE];
uint64_t no_pci_pt_count = 0;

#define PCI_PT_LIST_SIZE 256
uint64_t pci_pt_list[PCI_PT_LIST_SIZE];
uint64_t pci_pt_count = 0;

#ifdef USE_XUE
struct xue g_xue;
struct xue_ops g_xue_ops;
Expand Down Expand Up @@ -549,6 +553,16 @@ common_load_vmm(void)
}
}

for (i = 0; i < pci_pt_class_count; i++) {
ret = platform_call_vmm_on_core(0,
BF_REQUEST_PCI_PT,
pci_pt_list[i],
0);
if (ret != BF_SUCCESS) {
goto failure;
}
}

ret = private_add_modules_mdl();
if (ret != BF_SUCCESS) {
goto failure;
Expand Down
87 changes: 61 additions & 26 deletions deps/hypervisor/bfdriver/src/platform/efi/entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static const CHAR16 *opt_enable_winpv = L"--enable-winpv";
static const CHAR16 *opt_disable_winpv = L"--disable-winpv";
static const CHAR16 *opt_pci_pt_class = L"--pci-pt-class";
static const CHAR16 *opt_no_pci_pt = L"--no-pci-pt";
static const CHAR16 *opt_pci_pt = L"--pci-pt";
static const CHAR16 *opt_enable_xue = L"--enable-xue";

#define PCI_PT_CLASS_LIST_SIZE 14
Expand All @@ -67,6 +68,10 @@ extern uint64_t pci_pt_class_count;
extern uint64_t no_pci_pt_list[NO_PCI_PT_LIST_SIZE];
extern uint64_t no_pci_pt_count;

#define PCI_PT_LIST_SIZE 256
extern uint64_t pci_pt_list[PCI_PT_LIST_SIZE];
extern uint64_t pci_pt_count;

#ifndef EFI_BOOT_NEXT
#define EFI_BOOT_NEXT L"\\EFI\\boot\\bootx64.efi"
#endif
Expand Down Expand Up @@ -261,6 +266,41 @@ load_start_vm(EFI_HANDLE ParentImage)
return EFI_ABORTED;
}

static uint64_t bdf_str_to_uint(const CHAR16 *bdf_str)
{
UINTN bdf_len = StrLen(bdf_str);

if (bdf_len != 7) {
BFALERT("Invalid BDF string size: %u\n", bdf_len);
BFALERT(" usage: --no-pci-pt BB:DD.F\n");
return -1ULL;
}

CHAR8 bus_str[16];
CHAR8 dev_str[16];
CHAR8 fun_str[16];

ZeroMem(bus_str, 16);
ZeroMem(dev_str, 16);
ZeroMem(fun_str, 16);

CopyMem(bus_str, bdf_str, 4);
CopyMem(dev_str, (char *)bdf_str + 6, 4);
CopyMem(fun_str, (char *)bdf_str + 12, 2);

UINTN bus = xtoi((CHAR16 *)bus_str);
UINTN dev = xtoi((CHAR16 *)dev_str);
UINTN fun = xtoi((CHAR16 *)fun_str);

if (bus > 255 || dev > 31 || fun > 7) {
BFALERT("BDF out of range: bus=%lx, dev=%lx, fun=%lx\n",
bus, dev, fun);
return -1ULL;
}

return (bus << 16) | (dev << 11) | (fun << 8);
}

void parse_cmdline(INTN argc, CHAR16 **argv)
{
INTN i;
Expand Down Expand Up @@ -314,42 +354,37 @@ void parse_cmdline(INTN argc, CHAR16 **argv)
continue;
}

CHAR16 *bdf_str = argv[i + 1];
UINTN bdf_len = StrLen(bdf_str);

if (bdf_len != 7) {
BFALERT("Invalid BDF string size: %u\n", bdf_len);
BFALERT(" usage: --no-pci-pt BB:DD.F\n");
uint64_t bdf = bdf_str_to_uint(argv[i + 1]);
if (bdf == -1ULL) {
continue;
}

CHAR8 bus_str[16];
CHAR8 dev_str[16];
CHAR8 fun_str[16];

ZeroMem(bus_str, 16);
ZeroMem(dev_str, 16);
ZeroMem(fun_str, 16);
no_pci_pt_list[no_pci_pt_count] = bdf;
no_pci_pt_count++;

CopyMem(bus_str, bdf_str, 4);
CopyMem(dev_str, (char *)bdf_str + 6, 4);
CopyMem(fun_str, (char *)bdf_str + 12, 2);
BFINFO("Disabling passthrough for %02x:%02x.%02x\n",
(bdf & 0x00FF0000) >> 16,
(bdf & 0x0000F800) >> 11,
(bdf & 0x00000700) >> 8);
}

UINTN bus = xtoi((CHAR16 *)bus_str);
UINTN dev = xtoi((CHAR16 *)dev_str);
UINTN fun = xtoi((CHAR16 *)fun_str);
if (!StrnCmp(opt_pci_pt, argv[i], StrLen(opt_pci_pt) + 1)) {
if (i >= argc - 1) {
continue;
}

if (bus > 255 || dev > 31 || fun > 7) {
BFALERT("BDF out of range: bus=%lx, dev=%lx, fun=%lx\n",
bus, dev, fun);
uint64_t bdf = bdf_str_to_uint(argv[i + 1]);
if (bdf == -1ULL) {
continue;
}

no_pci_pt_list[no_pci_pt_count] =
(bus << 16) | (dev << 11) | (fun << 8);
no_pci_pt_count++;
pci_pt_list[pci_pt_count] = bdf;
pci_pt_count++;

BFINFO("Disabling passthrough for %02x:%02x.%02x\n", bus, dev, fun);
BFINFO("Enabling passthrough for %02x:%02x.%02x\n",
(bdf & 0x00FF0000) >> 16,
(bdf & 0x0000F800) >> 11,
(bdf & 0x00000700) >> 8);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions deps/hypervisor/bfintrinsics/include/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ inline bool g_disable_xen_pfd = false;
inline bool g_enable_xue = false;
inline std::unordered_set<uint8_t> g_pci_pt_class;
inline std::unordered_set<uint32_t> g_no_pci_pt;
inline std::unordered_set<uint32_t> g_pci_pt;

#ifdef BF_X64
#include <arch/x64/cache.h>
Expand Down
1 change: 1 addition & 0 deletions deps/hypervisor/bfsdk/include/bfsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ struct crt_info_t {
#define BF_REQUEST_WINPV 9
#define BF_REQUEST_NO_PCI_PT 10
#define BF_REQUEST_PCI_PT_CLASS 11
#define BF_REQUEST_PCI_PT 12
#define BF_REQUEST_END 0xFFFF

/* @endcond */
Expand Down
10 changes: 10 additions & 0 deletions deps/hypervisor/bfvmm/src/entry/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ private_no_pci_pt(uint64_t bdf) noexcept
return ENTRY_SUCCESS;
}

extern "C" int64_t
private_pci_pt(uint64_t bdf) noexcept
{
g_pci_pt.emplace((1UL << 31) | (uint32_t)bdf);
return ENTRY_SUCCESS;
}

extern "C" int64_t
private_init_vmm(uint64_t arg) noexcept
{
Expand Down Expand Up @@ -228,6 +235,9 @@ bfmain(uintptr_t request, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
case BF_REQUEST_PCI_PT_CLASS:
return private_pci_pt_class(arg1);

case BF_REQUEST_PCI_PT:
return private_pci_pt(arg1);

default:
break;
}
Expand Down
5 changes: 3 additions & 2 deletions vmm/src/pci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,9 @@ static void probe_bus(uint32_t b, struct pci_dev *bridge)
for (auto next = secondary; next <= subordinate; next++) {
probe_bus(next, pdev);
}
} else if (pdev->is_netdev()
&& g_pci_pt_class.count(pci_cc_network)) {
} else if (pdev->is_netdev() &&
g_pci_pt_class.count(pci_cc_network) ||
g_pci_pt.count(addr)) {
if (g_no_pci_pt.count(addr)) {
printv("pci: %s: passthrough disabled via boot option\n",
pdev->bdf_str());
Expand Down

0 comments on commit 7658043

Please sign in to comment.