blob: da08f40b45c455897cb6afd771e0d3471470a2dd [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <zircon/syscalls/pci.h>
#include <gtest/gtest.h>
#include "tools/fidlcat/interception_tests/interception_workflow_test.h"
namespace fidlcat {
// zx_pci_get_nth_device tests.
std::unique_ptr<SystemCallTest> ZxPciGetNthDevice(int64_t result, std::string_view result_name,
zx_handle_t handle, uint32_t index,
zx_pcie_device_info_t* out_info,
zx_handle_t* out_handle) {
auto value = std::make_unique<SystemCallTest>("zx_pci_get_nth_device", result, result_name);
value->AddInput(handle);
value->AddInput(index);
value->AddInput(reinterpret_cast<uint64_t>(out_info));
value->AddInput(reinterpret_cast<uint64_t>(out_handle));
return value;
}
#define PCI_GET_NTH_DEVICE_DISPLAY_TEST_CONTENT(result, expected) \
zx_pcie_device_info_t out_info = {.vendor_id = 1, \
.device_id = 2, \
.base_class = 3, \
.sub_class = 4, \
.program_interface = 5, \
.revision_id = 6, \
.bus_id = 7, \
.dev_id = 8, \
.func_id = 9}; \
zx_handle_t out_handle = kHandleOut; \
PerformDisplayTest("$plt(zx_pci_get_nth_device)", \
ZxPciGetNthDevice(result, #result, kHandle, 1234, &out_info, &out_handle), \
expected)
#define PCI_GET_NTH_DEVICE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_GET_NTH_DEVICE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_GET_NTH_DEVICE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_GET_NTH_DEVICE_DISPLAY_TEST(
ZxPciGetNthDevice, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_get_nth_device("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"index: \x1B[32muint32\x1B[0m = \x1B[34m1234\x1B[0m)\n"
" out_info: \x1B[32mzx_pcie_device_info_t\x1B[0m = {\n"
" vendor_id: \x1B[32muint16\x1B[0m = \x1B[34m1\x1B[0m\n"
" device_id: \x1B[32muint16\x1B[0m = \x1B[34m2\x1B[0m\n"
" base_class: \x1B[32muint8\x1B[0m = \x1B[34m3\x1B[0m\n"
" sub_class: \x1B[32muint8\x1B[0m = \x1B[34m4\x1B[0m\n"
" program_interface: \x1B[32muint8\x1B[0m = \x1B[34m5\x1B[0m\n"
" revision_id: \x1B[32muint8\x1B[0m = \x1B[34m6\x1B[0m\n"
" bus_id: \x1B[32muint8\x1B[0m = \x1B[34m7\x1B[0m\n"
" dev_id: \x1B[32muint8\x1B[0m = \x1B[34m8\x1B[0m\n"
" func_id: \x1B[32muint8\x1B[0m = \x1B[34m9\x1B[0m\n"
" }\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_handle: \x1B[32mhandle\x1B[0m = \x1B[31mbde90caf\x1B[0m)\n")
// zx_pci_enable_bus_master tests.
std::unique_ptr<SystemCallTest> ZxPciEnableBusMaster(int64_t result, std::string_view result_name,
zx_handle_t handle, bool enable) {
auto value = std::make_unique<SystemCallTest>("zx_pci_enable_bus_master", result, result_name);
value->AddInput(handle);
value->AddInput(enable);
return value;
}
#define PCI_ENABLE_BUS_MASTER_DISPLAY_TEST_CONTENT(result, expected) \
PerformDisplayTest("$plt(zx_pci_enable_bus_master)", \
ZxPciEnableBusMaster(result, #result, kHandle, true), expected)
#define PCI_ENABLE_BUS_MASTER_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_ENABLE_BUS_MASTER_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_ENABLE_BUS_MASTER_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_ENABLE_BUS_MASTER_DISPLAY_TEST(ZxPciEnableBusMaster, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_enable_bus_master("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"enable: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
// zx_pci_reset_device tests.
std::unique_ptr<SystemCallTest> ZxPciResetDevice(int64_t result, std::string_view result_name,
zx_handle_t handle) {
auto value = std::make_unique<SystemCallTest>("zx_pci_reset_device", result, result_name);
value->AddInput(handle);
return value;
}
#define PCI_RESET_DEVICE_DISPLAY_TEST_CONTENT(result, expected) \
PerformDisplayTest("$plt(zx_pci_reset_device)", ZxPciResetDevice(result, #result, kHandle), \
expected)
#define PCI_RESET_DEVICE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_RESET_DEVICE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_RESET_DEVICE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_RESET_DEVICE_DISPLAY_TEST(
ZxPciResetDevice, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_reset_device(handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
// zx_pci_config_read tests.
std::unique_ptr<SystemCallTest> ZxPciConfigRead(int64_t result, std::string_view result_name,
zx_handle_t handle, uint16_t offset, size_t width,
uint32_t* out_val) {
auto value = std::make_unique<SystemCallTest>("zx_pci_config_read", result, result_name);
value->AddInput(handle);
value->AddInput(offset);
value->AddInput(width);
value->AddInput(reinterpret_cast<uint64_t>(out_val));
return value;
}
#define PCI_CONFIG_READ_DISPLAY_TEST_CONTENT(result, expected) \
uint32_t out_val = 1234; \
PerformDisplayTest("$plt(zx_pci_config_read)", \
ZxPciConfigRead(result, #result, kHandle, 1000, 4, &out_val), expected)
#define PCI_CONFIG_READ_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_CONFIG_READ_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_CONFIG_READ_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_CONFIG_READ_DISPLAY_TEST(
ZxPciConfigRead, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_config_read("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"offset: \x1B[32muint16\x1B[0m = \x1B[34m1000\x1B[0m, "
"width: \x1B[32msize\x1B[0m = \x1B[34m4\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_val: \x1B[32muint32\x1B[0m = \x1B[34m1234\x1B[0m)\n")
CREATE_AUTOMATION_TEST(ZxPciConfigReadAutomation, "zx_pci_config_read", ZX_OK,
"Invoked bp instructions:\n"
" stored_value(0) = rcx\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n",
"Invoked bp instructions:\n"
" stored_value(0) = x3\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n")
// zx_pci_config_write tests.
std::unique_ptr<SystemCallTest> ZxPciConfigWrite(int64_t result, std::string_view result_name,
zx_handle_t handle, uint16_t offset, size_t width,
uint32_t val) {
auto value = std::make_unique<SystemCallTest>("zx_pci_config_write", result, result_name);
value->AddInput(handle);
value->AddInput(offset);
value->AddInput(width);
value->AddInput(val);
return value;
}
#define PCI_CONFIG_WRITE_DISPLAY_TEST_CONTENT(result, expected) \
PerformDisplayTest("$plt(zx_pci_config_write)", \
ZxPciConfigWrite(result, #result, kHandle, 1000, 4, 1234), expected)
#define PCI_CONFIG_WRITE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_CONFIG_WRITE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_CONFIG_WRITE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_CONFIG_WRITE_DISPLAY_TEST(ZxPciConfigWrite, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_config_write("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"offset: \x1B[32muint16\x1B[0m = \x1B[34m1000\x1B[0m, "
"width: \x1B[32msize\x1B[0m = \x1B[34m4\x1B[0m, "
"val: \x1B[32muint32\x1B[0m = \x1B[34m1234\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
// zx_pci_cfg_pio_rw tests.
std::unique_ptr<SystemCallTest> ZxPciCfgPioRw(int64_t result, std::string_view result_name,
zx_handle_t handle, uint8_t bus, uint8_t dev,
uint8_t func, uint8_t offset, uint32_t* val,
size_t width, bool write) {
auto value = std::make_unique<SystemCallTest>("zx_pci_cfg_pio_rw", result, result_name);
value->AddInput(handle);
value->AddInput(bus);
value->AddInput(dev);
value->AddInput(func);
value->AddInput(offset);
value->AddInput(reinterpret_cast<uint64_t>(val));
value->AddInput(width);
value->AddInput(write);
return value;
}
#define PCI_CFG_PIO_RW_DISPLAY_TEST_CONTENT(result, write, expected) \
uint32_t val = 1234; \
PerformDisplayTest("$plt(zx_pci_cfg_pio_rw)", \
ZxPciCfgPioRw(result, #result, kHandle, 1, 2, 3, 100, &val, 4, write), \
expected)
#define PCI_CFG_PIO_RW_DISPLAY_TEST(name, errno, write, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_CFG_PIO_RW_DISPLAY_TEST_CONTENT(errno, write, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_CFG_PIO_RW_DISPLAY_TEST_CONTENT(errno, write, expected); \
}
PCI_CFG_PIO_RW_DISPLAY_TEST(
ZxPciCfgPioRwRead, ZX_OK, false,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_cfg_pio_rw("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"bus: \x1B[32muint8\x1B[0m = \x1B[34m1\x1B[0m, "
"dev: \x1B[32muint8\x1B[0m = \x1B[34m2\x1B[0m, "
"func: \x1B[32muint8\x1B[0m = \x1B[34m3\x1B[0m, "
"offset: \x1B[32muint8\x1B[0m = \x1B[34m100\x1B[0m, "
"width: \x1B[32msize\x1B[0m = \x1B[34m4\x1B[0m, "
"write: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (val: \x1B[32muint32\x1B[0m = \x1B[34m1234\x1B[0m)\n")
PCI_CFG_PIO_RW_DISPLAY_TEST(ZxPciCfgPioRwWrite, ZX_OK, true,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_cfg_pio_rw("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"bus: \x1B[32muint8\x1B[0m = \x1B[34m1\x1B[0m, "
"dev: \x1B[32muint8\x1B[0m = \x1B[34m2\x1B[0m, "
"func: \x1B[32muint8\x1B[0m = \x1B[34m3\x1B[0m, "
"offset: \x1B[32muint8\x1B[0m = \x1B[34m100\x1B[0m, "
"width: \x1B[32msize\x1B[0m = \x1B[34m4\x1B[0m, "
"val: \x1B[32muint32\x1B[0m = \x1B[34m1234\x1B[0m, "
"write: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
CREATE_AUTOMATION_TEST(ZxPciCfgPioRwAutomation, "zx_pci_cfg_pio_rw", ZX_OK,
"Invoked bp instructions:\n"
" stored_value(0) = [xsp + 0x8]/64\n"
" stored_value(1) = r9. conditions: stored_value(0) == 0\n"
"Exit bp instructions:\n"
" load_memory stored_value(1), 4. conditions: stored_value(0) == 0\n"
" clear_stored_values\n",
"Invoked bp instructions:\n"
" stored_value(0) = x7\n"
" stored_value(1) = x5. conditions: stored_value(0) == 0\n"
"Exit bp instructions:\n"
" load_memory stored_value(1), 4. conditions: stored_value(0) == 0\n"
" clear_stored_values\n")
// zx_pci_get_bar tests.
std::unique_ptr<SystemCallTest> ZxPciGetBar(int64_t result, std::string_view result_name,
zx_handle_t handle, uint32_t bar_num,
zx_pci_bar_t* out_bar, zx_handle_t* out_handle) {
auto value = std::make_unique<SystemCallTest>("zx_pci_get_bar", result, result_name);
value->AddInput(handle);
value->AddInput(bar_num);
value->AddInput(reinterpret_cast<uint64_t>(out_bar));
value->AddInput(reinterpret_cast<uint64_t>(out_handle));
return value;
}
#define PCI_GET_BAR_UNUSED_DISPLAY_TEST_CONTENT(result, expected) \
zx_pci_bar_t out_bar = {.id = 1000, .type = ZX_PCI_BAR_TYPE_UNUSED}; \
zx_handle_t out_handle = kHandleOut; \
PerformDisplayTest("$plt(zx_pci_get_bar)", \
ZxPciGetBar(result, #result, kHandle, 1, &out_bar, &out_handle), expected)
#define PCI_GET_BAR_UNUSED_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_GET_BAR_UNUSED_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_GET_BAR_UNUSED_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_GET_BAR_UNUSED_DISPLAY_TEST(
ZxPciGetBarUnused, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_get_bar("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"bar_num: \x1B[32muint32\x1B[0m = \x1B[34m1\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_handle: \x1B[32mhandle\x1B[0m = \x1B[31mbde90caf\x1B[0m)\n"
" out_bar: \x1B[32mzx_pci_bar_t\x1B[0m = { "
"id: \x1B[32muint32\x1B[0m = \x1B[34m1000\x1B[0m, "
"type: \x1B[32mzx.pci_bar_type\x1B[0m = \x1B[34mZX_PCI_BAR_TYPE_UNUSED\x1B[0m"
" }\n")
#define PCI_GET_BAR_MMIO_DISPLAY_TEST_CONTENT(result, expected) \
zx_pci_bar_t out_bar = {.id = 1000, .type = ZX_PCI_BAR_TYPE_MMIO, .handle = kHandle2}; \
zx_handle_t out_handle = kHandleOut; \
PerformDisplayTest("$plt(zx_pci_get_bar)", \
ZxPciGetBar(result, #result, kHandle, 2, &out_bar, &out_handle), expected)
#define PCI_GET_BAR_MMIO_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_GET_BAR_MMIO_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_GET_BAR_MMIO_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_GET_BAR_MMIO_DISPLAY_TEST(
ZxPciGetBarMmio, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_get_bar("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"bar_num: \x1B[32muint32\x1B[0m = \x1B[34m2\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_handle: \x1B[32mhandle\x1B[0m = \x1B[31mbde90caf\x1B[0m)\n"
" out_bar: \x1B[32mzx_pci_bar_t\x1B[0m = { "
"id: \x1B[32muint32\x1B[0m = \x1B[34m1000\x1B[0m, "
"type: \x1B[32mzx.pci_bar_type\x1B[0m = \x1B[34mZX_PCI_BAR_TYPE_MMIO\x1B[0m, "
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1222\x1B[0m"
" }\n")
#define PCI_GET_BAR_PIO_DISPLAY_TEST_CONTENT(result, expected) \
zx_pci_bar_t out_bar = {.id = 1000, .type = ZX_PCI_BAR_TYPE_PIO, .size = 1024, .addr = 0x45678}; \
zx_handle_t out_handle = kHandleOut; \
PerformDisplayTest("$plt(zx_pci_get_bar)", \
ZxPciGetBar(result, #result, kHandle, 3, &out_bar, &out_handle), expected)
#define PCI_GET_BAR_PIO_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_GET_BAR_PIO_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_GET_BAR_PIO_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_GET_BAR_PIO_DISPLAY_TEST(
ZxPciGetBarPio, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_get_bar("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"bar_num: \x1B[32muint32\x1B[0m = \x1B[34m3\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_handle: \x1B[32mhandle\x1B[0m = \x1B[31mbde90caf\x1B[0m)\n"
" out_bar: \x1B[32mzx_pci_bar_t\x1B[0m = {\n"
" id: \x1B[32muint32\x1B[0m = \x1B[34m1000\x1B[0m\n"
" type: \x1B[32mzx.pci_bar_type\x1B[0m = \x1B[34mZX_PCI_BAR_TYPE_PIO\x1B[0m\n"
" size: \x1B[32msize\x1B[0m = \x1B[34m1024\x1B[0m\n"
" addr: \x1B[32muintptr\x1B[0m = \x1B[34m0000000000045678\x1B[0m\n"
" }\n")
// zx_pci_map_interrupt tests.
std::unique_ptr<SystemCallTest> ZxPciMapInterrupt(int64_t result, std::string_view result_name,
zx_handle_t handle, int32_t which_irq,
zx_handle_t* out_handle) {
auto value = std::make_unique<SystemCallTest>("zx_pci_map_interrupt", result, result_name);
value->AddInput(handle);
value->AddInput(which_irq);
value->AddInput(reinterpret_cast<uint64_t>(out_handle));
return value;
}
#define PCI_MAP_INTERRUPT_DISPLAY_TEST_CONTENT(result, expected) \
zx_handle_t out_handle = kHandleOut; \
PerformDisplayTest("$plt(zx_pci_map_interrupt)", \
ZxPciMapInterrupt(result, #result, kHandle, 5, &out_handle), expected)
#define PCI_MAP_INTERRUPT_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_MAP_INTERRUPT_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_MAP_INTERRUPT_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_MAP_INTERRUPT_DISPLAY_TEST(
ZxPciMapInterrupt, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_map_interrupt("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"which_irq: \x1B[32mint32\x1B[0m = \x1B[34m5\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_handle: \x1B[32mhandle\x1B[0m = \x1B[31mbde90caf\x1B[0m)\n")
CREATE_AUTOMATION_TEST(ZxPciMapInterruptAutomation, "zx_pci_map_interrupt", ZX_OK,
"Invoked bp instructions:\n"
" stored_value(0) = rdx\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n",
"Invoked bp instructions:\n"
" stored_value(0) = x2\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n")
// zx_pci_query_irq_mode tests.
std::unique_ptr<SystemCallTest> ZxPciQueryIrqMode(int64_t result, std::string_view result_name,
zx_handle_t handle, uint32_t mode,
uint32_t* out_max_irqs) {
auto value = std::make_unique<SystemCallTest>("zx_pci_query_irq_mode", result, result_name);
value->AddInput(handle);
value->AddInput(mode);
value->AddInput(reinterpret_cast<uint64_t>(out_max_irqs));
return value;
}
#define PCI_QUERY_IRQ_MODE_DISPLAY_TEST_CONTENT(result, expected) \
uint32_t out_max_irqs = 12; \
PerformDisplayTest("$plt(zx_pci_query_irq_mode)", \
ZxPciQueryIrqMode(result, #result, kHandle, 0, &out_max_irqs), expected)
#define PCI_QUERY_IRQ_MODE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_QUERY_IRQ_MODE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_QUERY_IRQ_MODE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_QUERY_IRQ_MODE_DISPLAY_TEST(
ZxPciQueryIrqMode, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_query_irq_mode("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"mode: \x1B[32muint32\x1B[0m = \x1B[34m0\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m (out_max_irqs: \x1B[32muint32\x1B[0m = \x1B[34m12\x1B[0m)\n")
CREATE_AUTOMATION_TEST(ZxPciQueryIrqModeAutomation, "zx_pci_query_irq_mode", ZX_OK,
"Invoked bp instructions:\n"
" stored_value(0) = rdx\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n",
"Invoked bp instructions:\n"
" stored_value(0) = x2\n"
"Exit bp instructions:\n"
" load_memory stored_value(0), 4\n"
" clear_stored_values\n")
// zx_pci_set_irq_mode tests.
std::unique_ptr<SystemCallTest> ZxPciSetIrqMode(int64_t result, std::string_view result_name,
zx_handle_t handle, uint32_t mode,
uint32_t requested_irq_count) {
auto value = std::make_unique<SystemCallTest>("zx_pci_set_irq_mode", result, result_name);
value->AddInput(handle);
value->AddInput(mode);
value->AddInput(requested_irq_count);
return value;
}
#define PCI_SET_IRQ_MODE_DISPLAY_TEST_CONTENT(result, expected) \
PerformDisplayTest("$plt(zx_pci_set_irq_mode)", ZxPciSetIrqMode(result, #result, kHandle, 0, 5), \
expected)
#define PCI_SET_IRQ_MODE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_SET_IRQ_MODE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_SET_IRQ_MODE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_SET_IRQ_MODE_DISPLAY_TEST(ZxPciSetIrqMode, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_set_irq_mode("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"mode: \x1B[32muint32\x1B[0m = \x1B[34m0\x1B[0m, "
"requested_irq_count: \x1B[32muint32\x1B[0m = \x1B[34m5\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
// zx_pci_init tests.
std::unique_ptr<SystemCallTest> ZxPciInit(int64_t result, std::string_view result_name,
zx_handle_t handle, const zx_pci_init_arg_t* init_buf,
uint32_t len) {
auto value = std::make_unique<SystemCallTest>("zx_pci_init", result, result_name);
value->AddInput(handle);
value->AddInput(reinterpret_cast<uint64_t>(init_buf));
value->AddInput(len);
return value;
}
#define PCI_INIT_DISPLAY_TEST_CONTENT(result, expected) \
std::vector<uint8_t> buffer(sizeof(zx_pci_init_arg_t) + \
3 * sizeof(zx_pci_init_arg_addr_window_t)); \
zx_pci_init_arg_t* init_buf = reinterpret_cast<zx_pci_init_arg_t*>(buffer.data()); \
for (unsigned device = 0; device < ZX_PCI_MAX_DEVICES_PER_BUS; ++device) { \
for (unsigned function = 0; function < ZX_PCI_MAX_FUNCTIONS_PER_DEVICE; ++function) { \
for (unsigned pin = 0; pin < ZX_PCI_MAX_LEGACY_IRQ_PINS; ++pin) { \
init_buf->dev_pin_to_global_irq[device][function][pin] = \
pin + function * 16 + device * 256; \
} \
} \
} \
init_buf->num_irqs = 2; \
init_buf->irqs[0] = {.global_irq = 10, .level_triggered = false, .active_high = true}; \
init_buf->irqs[1] = {.global_irq = 20, .level_triggered = true, .active_high = false}; \
init_buf->addr_window_count = 3; \
init_buf->addr_windows[0] = {.base = 1000, \
.size = 1024, \
.bus_start = 1, \
.bus_end = 2, \
.cfg_space_type = 3, \
.has_ecam = false}; \
init_buf->addr_windows[1] = {.base = 2000, \
.size = 2024, \
.bus_start = 21, \
.bus_end = 22, \
.cfg_space_type = 23, \
.has_ecam = true}; \
init_buf->addr_windows[2] = {.base = 3000, \
.size = 3024, \
.bus_start = 31, \
.bus_end = 32, \
.cfg_space_type = 33, \
.has_ecam = false}; \
PerformDisplayTest("$plt(zx_pci_init)", \
ZxPciInit(result, #result, kHandle, init_buf, buffer.size()), expected)
#define PCI_INIT_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { PCI_INIT_DISPLAY_TEST_CONTENT(errno, expected); } \
TEST_F(InterceptionWorkflowTestArm, name) { PCI_INIT_DISPLAY_TEST_CONTENT(errno, expected); }
std::string FillPins(std::string_view header, std::string_view footer) {
std::stringstream stream;
stream << header;
std::vector<char> buffer(sizeof(uint32_t) * kCharactersPerByte + 1);
const char* separator = "";
int printed_elems = 0;
for (unsigned device = 0; device < ZX_PCI_MAX_DEVICES_PER_BUS; ++device) {
for (unsigned function = 0; function < ZX_PCI_MAX_FUNCTIONS_PER_DEVICE; ++function) {
for (unsigned pin = 0; pin < ZX_PCI_MAX_LEGACY_IRQ_PINS; ++pin) {
++printed_elems;
snprintf(buffer.data(), buffer.size(), "%08x", pin + function * 16 + device * 256);
stream << separator << "\x1B[34m" << buffer.data() << "\x1B[0m";
if (printed_elems == 12) {
printed_elems = 0;
separator = "\n ";
} else {
separator = ", ";
}
}
}
}
stream << "\n";
stream << footer;
return stream.str();
}
PCI_INIT_DISPLAY_TEST(
ZxPciInit, ZX_OK,
FillPins("\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m zx_pci_init("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"len: \x1B[32muint32\x1B[0m = \x1B[34m5968\x1B[0m)\n"
" init_buf: \x1B[32mzx_pci_init_arg_t\x1B[0m = {\n"
" dev_pin_to_global_irq: array<\x1B[32muint32\x1B[0m> = [\n ",
" ]\n"
" num_irqs: \x1B[32muint32\x1B[0m = \x1B[34m2\x1B[0m\n"
" irqs: vector<\x1B[32mzx_pci_init_arg_irq_t\x1B[0m> = [\n"
" { "
"global_irq: \x1B[32muint32\x1B[0m = \x1B[34m10\x1B[0m, "
"level_triggered: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m, "
"active_high: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m"
" }\n"
" { "
"global_irq: \x1B[32muint32\x1B[0m = \x1B[34m20\x1B[0m, "
"level_triggered: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m, "
"active_high: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m"
" }\n"
" ]\n"
" addr_window_count: \x1B[32muint32\x1B[0m = \x1B[34m3\x1B[0m\n"
" addr_windows: vector<\x1B[32mzx_pci_init_arg_addr_window_t\x1B[0m> = [\n"
" {\n"
" base: \x1B[32muint64\x1B[0m = \x1B[34m1000\x1B[0m\n"
" size: \x1B[32msize\x1B[0m = \x1B[34m1024\x1B[0m\n"
" bus_start: \x1B[32muint8\x1B[0m = \x1B[34m1\x1B[0m\n"
" bus_end: \x1B[32muint8\x1B[0m = \x1B[34m2\x1B[0m\n"
" cfg_space_type: \x1B[32muint8\x1B[0m = \x1B[34m3\x1B[0m\n"
" has_ecam: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m\n"
" }\n"
" {\n"
" base: \x1B[32muint64\x1B[0m = \x1B[34m2000\x1B[0m\n"
" size: \x1B[32msize\x1B[0m = \x1B[34m2024\x1B[0m\n"
" bus_start: \x1B[32muint8\x1B[0m = \x1B[34m21\x1B[0m\n"
" bus_end: \x1B[32muint8\x1B[0m = \x1B[34m22\x1B[0m\n"
" cfg_space_type: \x1B[32muint8\x1B[0m = \x1B[34m23\x1B[0m\n"
" has_ecam: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m\n"
" }\n"
" {\n"
" base: \x1B[32muint64\x1B[0m = \x1B[34m3000\x1B[0m\n"
" size: \x1B[32msize\x1B[0m = \x1B[34m3024\x1B[0m\n"
" bus_start: \x1B[32muint8\x1B[0m = \x1B[34m31\x1B[0m\n"
" bus_end: \x1B[32muint8\x1B[0m = \x1B[34m32\x1B[0m\n"
" cfg_space_type: \x1B[32muint8\x1B[0m = \x1B[34m33\x1B[0m\n"
" has_ecam: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m\n"
" }\n"
" ]\n"
" }\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
.c_str())
// zx_pci_add_subtract_io_range tests.
std::unique_ptr<SystemCallTest> ZxPciAddSubtractIoRange(int64_t result,
std::string_view result_name,
zx_handle_t handle, bool mmio,
uint64_t base, uint64_t len, bool add) {
auto value =
std::make_unique<SystemCallTest>("zx_pci_add_subtract_io_range", result, result_name);
value->AddInput(handle);
value->AddInput(mmio);
value->AddInput(base);
value->AddInput(len);
value->AddInput(add);
return value;
}
#define PCI_ADD_SUBTRACT_IO_RANGE_DISPLAY_TEST_CONTENT(result, expected) \
PerformDisplayTest("$plt(zx_pci_add_subtract_io_range)", \
ZxPciAddSubtractIoRange(result, #result, kHandle, true, 1000, 1024, false), \
expected);
#define PCI_ADD_SUBTRACT_IO_RANGE_DISPLAY_TEST(name, errno, expected) \
TEST_F(InterceptionWorkflowTestX64, name) { \
PCI_ADD_SUBTRACT_IO_RANGE_DISPLAY_TEST_CONTENT(errno, expected); \
} \
TEST_F(InterceptionWorkflowTestArm, name) { \
PCI_ADD_SUBTRACT_IO_RANGE_DISPLAY_TEST_CONTENT(errno, expected); \
}
PCI_ADD_SUBTRACT_IO_RANGE_DISPLAY_TEST(ZxPciAddSubtractIoRange, ZX_OK,
"\n"
"\x1B[32m0.000000\x1B[0m "
"test_3141 \x1B[31m3141\x1B[0m:\x1B[31m8764\x1B[0m "
"zx_pci_add_subtract_io_range("
"handle: \x1B[32mhandle\x1B[0m = \x1B[31mcefa1db0\x1B[0m, "
"mmio: \x1B[32mbool\x1B[0m = \x1B[34mtrue\x1B[0m, "
"base: \x1B[32muint64\x1B[0m = \x1B[34m1000\x1B[0m, "
"len: \x1B[32muint64\x1B[0m = \x1B[34m1024\x1B[0m, "
"add: \x1B[32mbool\x1B[0m = \x1B[34mfalse\x1B[0m)\n"
"\x1B[32m0.000000\x1B[0m "
" -> \x1B[32mZX_OK\x1B[0m\n")
} // namespace fidlcat