API Reference
This page is auto-generated from the PCIem kernel headers. Do not edit it by hand — run make docs to regenerate.
PCIem exposes a userspace-facing API through /dev/pciem that lets developers configure and emulate PCIe devices entirely from userspace.
Contents
- Constants
- Structures
pciem_create_devicepciem_bar_configpciem_cap_msi_userspacepciem_cap_msix_userspacepciem_cap_pasid_userspacepciem_cap_configpciem_config_spacepciem_eventpciem_responsepciem_irq_injectpciem_dma_oppciem_dma_atomicpciem_p2p_op_userpciem_bar_info_querypciem_eventfd_configpciem_irqfd_configpciem_dma_indirectpciem_trace_barpciem_shared_ring
- IOCTLs
PCIEM_IOCTL_CREATE_DEVICEPCIEM_IOCTL_ADD_BARPCIEM_IOCTL_ADD_CAPABILITYPCIEM_IOCTL_SET_CONFIGPCIEM_IOCTL_REGISTERPCIEM_IOCTL_INJECT_IRQPCIEM_IOCTL_DMAPCIEM_IOCTL_DMA_ATOMICPCIEM_IOCTL_P2PPCIEM_IOCTL_GET_BAR_INFOPCIEM_IOCTL_SET_EVENTFDPCIEM_IOCTL_SET_IRQFDPCIEM_IOCTL_DMA_INDIRECTPCIEM_IOCTL_TRACE_BARPCIEM_IOCTL_START
Constants
PCIEM_CAP_*
| Name | Value | Description |
|---|---|---|
PCIEM_CAP_MSI | 0 | |
PCIEM_CAP_MSIX | 1 | |
PCIEM_CAP_PASID | 5 | |
PCIEM_CAP_PCIE | 3 | |
PCIEM_CAP_PM | 2 | |
PCIEM_CAP_VSEC | 4 |
PCIEM_EVENT_*
| Name | Value | Description |
|---|---|---|
PCIEM_EVENT_CONFIG_READ | 3 | |
PCIEM_EVENT_CONFIG_WRITE | 4 | |
PCIEM_EVENT_MMIO_READ | 1 | |
PCIEM_EVENT_MMIO_WRITE | 2 | |
PCIEM_EVENT_MSI_ACK | 5 | |
PCIEM_EVENT_RESET | 6 |
PCIEM_TRACE_*
| Name | Value | Description |
|---|---|---|
PCIEM_TRACE_READS | (1 << 0) | |
PCIEM_TRACE_STOP_WRITES | (1 << 2) | |
PCIEM_TRACE_WRITES | (1 << 1) |
PCIEM_ATOMIC_*
| Name | Value | Description |
|---|---|---|
PCIEM_ATOMIC_CAS | 4 | |
PCIEM_ATOMIC_FETCH_ADD | 1 | |
PCIEM_ATOMIC_FETCH_AND | 5 | |
PCIEM_ATOMIC_FETCH_OR | 6 | |
PCIEM_ATOMIC_FETCH_SUB | 2 | |
PCIEM_ATOMIC_FETCH_XOR | 7 | |
PCIEM_ATOMIC_SWAP | 3 |
PCIEM_DMA_FLAG_*
| Name | Value | Description |
|---|---|---|
PCIEM_DMA_FLAG_READ | 0x1 | |
PCIEM_DMA_FLAG_WRITE | 0x2 |
PCIEM_IRQFD_FLAG_*
| Name | Value | Description |
|---|---|---|
PCIEM_IRQFD_FLAG_DEASSERT | (1 << 1) | |
PCIEM_IRQFD_FLAG_LEVEL | (1 << 0) |
PCIEM_WP_FLAG_BAR_*
| Name | Value | Description |
|---|---|---|
PCIEM_WP_FLAG_BAR_KPROBES | (1 << 0) | |
PCIEM_WP_FLAG_BAR_MANUAL | (1 << 1) |
PCIEM_CREATE_FLAG_BUS_MODE_*
| Name | Value | Description |
|---|---|---|
PCIEM_CREATE_FLAG_BUS_MODE_ATTACH | 0x00000001 | Attach to an existing physical PCIe bus. |
PCIEM_CREATE_FLAG_BUS_MODE_MASK | 0x00000003 | Mask to extract the bus mode bits from the flags field. |
PCIEM_CREATE_FLAG_BUS_MODE_VIRTUAL | 0x00000000 | Create a virtual PCIe bus owned entirely by PCIem. |
Miscellaneous
| Name | Value | Description |
|---|---|---|
PCIEM_MAX_IRQFDS | 32 | |
PCIEM_RING_SIZE | 256 |
Structures
Defined in
pciem_api.h
pciem_create_device
struct pciem_create_device
{
uint32_t flags;
};
| Field | Type | Description |
|---|---|---|
flags | uint32_t |
Used by: PCIEM_IOCTL_CREATE_DEVICE
pciem_bar_config
struct pciem_bar_config
{
uint32_t bar_index;
uint32_t flags;
uint64_t size;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
bar_index | uint32_t | |
flags | uint32_t | |
size | uint64_t | |
reserved | uint32_t |
Used by: PCIEM_IOCTL_ADD_BAR
pciem_cap_msi_userspace
struct pciem_cap_msi_userspace
{
uint8_t num_vectors_log2;
uint8_t has_64bit;
uint8_t has_masking;
uint8_t reserved;
};
| Field | Type | Description |
|---|---|---|
num_vectors_log2 | uint8_t | |
has_64bit | uint8_t | |
has_masking | uint8_t | |
reserved | uint8_t |
pciem_cap_msix_userspace
struct pciem_cap_msix_userspace
{
uint8_t bar_index;
uint8_t reserved[3];
uint32_t table_offset;
uint32_t pba_offset;
uint16_t table_size;
uint16_t reserved2;
};
| Field | Type | Description |
|---|---|---|
bar_index | uint8_t | |
reserved | uint8_t[3] | |
table_offset | uint32_t | |
pba_offset | uint32_t | |
table_size | uint16_t | |
reserved2 | uint16_t |
pciem_cap_pasid_userspace
struct pciem_cap_pasid_userspace
{
uint8_t max_pasid_width;
uint8_t execute_permission;
uint8_t privileged_mode;
uint8_t reserved;
};
| Field | Type | Description |
|---|---|---|
max_pasid_width | uint8_t | |
execute_permission | uint8_t | |
privileged_mode | uint8_t | |
reserved | uint8_t |
pciem_cap_config
struct pciem_cap_config
{
uint32_t cap_type;
struct pciem_cap_msi_userspace msi;
struct pciem_cap_msix_userspace msix;
struct pciem_cap_pasid_userspace pasid;
};
| Field | Type | Description |
|---|---|---|
cap_type | uint32_t | |
msi | struct pciem_cap_msi_userspace | |
msix | struct pciem_cap_msix_userspace | |
pasid | struct pciem_cap_pasid_userspace |
Used by: PCIEM_IOCTL_ADD_CAPABILITY
pciem_config_space
struct pciem_config_space
{
uint16_t vendor_id;
uint16_t device_id;
uint16_t subsys_vendor_id;
uint16_t subsys_device_id;
uint8_t revision;
uint8_t class_code[3];
uint8_t header_type;
uint8_t reserved[7];
};
| Field | Type | Description |
|---|---|---|
vendor_id | uint16_t | |
device_id | uint16_t | |
subsys_vendor_id | uint16_t | |
subsys_device_id | uint16_t | |
revision | uint8_t | |
class_code | uint8_t[3] | |
header_type | uint8_t | |
reserved | uint8_t[7] |
Used by: PCIEM_IOCTL_SET_CONFIG
pciem_event
struct pciem_event
{
uint64_t seq;
uint32_t type;
uint32_t bar;
uint64_t offset;
uint32_t size;
uint32_t reserved;
uint64_t data;
uint64_t timestamp;
};
| Field | Type | Description |
|---|---|---|
seq | uint64_t | |
type | uint32_t | |
bar | uint32_t | |
offset | uint64_t | |
size | uint32_t | |
reserved | uint32_t | |
data | uint64_t | |
timestamp | uint64_t |
pciem_response
struct pciem_response
{
uint64_t seq;
uint64_t data;
int32_t status;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
seq | uint64_t | |
data | uint64_t | |
status | int32_t | |
reserved | uint32_t |
pciem_irq_inject
Parameters for PCIEM_IOCTL_INJECT_IRQ.
struct pciem_irq_inject
{
uint32_t vector;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
vector | uint32_t | MSI/MSI-X vector number to inject into the guest. |
reserved | uint32_t | Must be zero. |
Used by: PCIEM_IOCTL_INJECT_IRQ
pciem_dma_op
struct pciem_dma_op
{
uint64_t guest_iova;
uint64_t user_addr;
uint32_t length;
uint32_t pasid;
uint32_t flags;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
guest_iova | uint64_t | |
user_addr | uint64_t | |
length | uint32_t | |
pasid | uint32_t | |
flags | uint32_t | |
reserved | uint32_t |
Used by: PCIEM_IOCTL_DMA
pciem_dma_atomic
struct pciem_dma_atomic
{
uint64_t guest_iova;
uint64_t operand;
uint64_t compare;
uint32_t op_type;
uint32_t pasid;
uint64_t result;
};
| Field | Type | Description |
|---|---|---|
guest_iova | uint64_t | |
operand | uint64_t | |
compare | uint64_t | |
op_type | uint32_t | |
pasid | uint32_t | |
result | uint64_t |
Used by: PCIEM_IOCTL_DMA_ATOMIC
pciem_p2p_op_user
struct pciem_p2p_op_user
{
uint64_t target_phys_addr;
uint64_t user_addr;
uint32_t length;
uint32_t flags;
};
| Field | Type | Description |
|---|---|---|
target_phys_addr | uint64_t | |
user_addr | uint64_t | |
length | uint32_t | |
flags | uint32_t |
Used by: PCIEM_IOCTL_P2P
pciem_bar_info_query
struct pciem_bar_info_query
{
uint32_t bar_index;
uint64_t phys_addr;
uint64_t size;
uint32_t flags;
};
| Field | Type | Description |
|---|---|---|
bar_index | uint32_t | |
phys_addr | uint64_t | |
size | uint64_t | |
flags | uint32_t |
Used by: PCIEM_IOCTL_GET_BAR_INFO
pciem_eventfd_config
struct pciem_eventfd_config
{
int32_t eventfd;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
eventfd | int32_t | |
reserved | uint32_t |
Used by: PCIEM_IOCTL_SET_EVENTFD
pciem_irqfd_config
struct pciem_irqfd_config
{
int32_t eventfd;
uint32_t vector;
uint32_t flags;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
eventfd | int32_t | |
vector | uint32_t | |
flags | uint32_t | |
reserved | uint32_t |
Used by: PCIEM_IOCTL_SET_IRQFD
pciem_dma_indirect
struct pciem_dma_indirect
{
uint64_t prp1;
uint64_t prp2;
uint64_t user_addr;
uint32_t length;
uint32_t page_size;
uint32_t pasid;
uint32_t flags;
uint32_t reserved;
};
| Field | Type | Description |
|---|---|---|
prp1 | uint64_t | |
prp2 | uint64_t | |
user_addr | uint64_t | |
length | uint32_t | |
page_size | uint32_t | |
pasid | uint32_t | |
flags | uint32_t | |
reserved | uint32_t |
Used by: PCIEM_IOCTL_DMA_INDIRECT
pciem_trace_bar
struct pciem_trace_bar
{
uint32_t bar_index;
uint32_t flags;
};
| Field | Type | Description |
|---|---|---|
bar_index | uint32_t | |
flags | uint32_t |
Used by: PCIEM_IOCTL_TRACE_BAR
pciem_shared_ring
Lock-free single-producer/single-consumer event ring shared between the kernel and userspace.
The kernel writes events by advancing @head; userspace consumes them by advancing @tail. Each counter is cache-line padded. The ring is mapped read-only into userspace via mmap on the PCIem fd.
@head from @tail.
@tail from the event array.
struct pciem_shared_ring
{
atomic_t head;
char _pad1[60];
atomic_t tail;
char _pad2[60];
struct pciem_event events[PCIEM_RING_SIZE];
};
| Field | Type | Description |
|---|---|---|
head | atomic_t | Write index, owned by the kernel. Incremented atomically after each event is committed. |
_pad1 | char[60] | Cache-line padding to isolate |
tail | atomic_t | Read index, owned by userspace. Incremented after each event is consumed. |
_pad2 | char[60] | Cache-line padding to isolate |
events | struct pciem_event[PCIEM_RING_SIZE] | Circular buffer of PCIEM_RING_SIZE events. |
IOCTLs
All ioctls are issued on the
/dev/pciemfile descriptor unless noted otherwise.
PCIEM_IOCTL_CREATE_DEVICE
#define PCIEM_IOCTL_CREATE_DEVICE _IOWR(PCIEM_IOCTL_MAGIC, 10, struct pciem_create_device)
Direction: read/write (both directions)
Parameter struct: pciem_create_device
struct pciem_create_device arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_CREATE_DEVICE, &arg);
PCIEM_IOCTL_ADD_BAR
#define PCIEM_IOCTL_ADD_BAR _IOW(PCIEM_IOCTL_MAGIC, 11, struct pciem_bar_config)
Direction: write (userspace → kernel)
Parameter struct: pciem_bar_config
struct pciem_bar_config arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_ADD_BAR, &arg);
PCIEM_IOCTL_ADD_CAPABILITY
#define PCIEM_IOCTL_ADD_CAPABILITY _IOW(PCIEM_IOCTL_MAGIC, 12, struct pciem_cap_config)
Direction: write (userspace → kernel)
Parameter struct: pciem_cap_config
struct pciem_cap_config arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_ADD_CAPABILITY, &arg);
PCIEM_IOCTL_SET_CONFIG
#define PCIEM_IOCTL_SET_CONFIG _IOW(PCIEM_IOCTL_MAGIC, 13, struct pciem_config_space)
Direction: write (userspace → kernel)
Parameter struct: pciem_config_space
struct pciem_config_space arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_SET_CONFIG, &arg);
PCIEM_IOCTL_REGISTER
#define PCIEM_IOCTL_REGISTER _IO(PCIEM_IOCTL_MAGIC, 14)
Direction: none (no data transfer)
int ret = ioctl(fd, PCIEM_IOCTL_REGISTER);
PCIEM_IOCTL_INJECT_IRQ
#define PCIEM_IOCTL_INJECT_IRQ _IOW(PCIEM_IOCTL_MAGIC, 15, struct pciem_irq_inject)
Direction: write (userspace → kernel)
Parameter struct: pciem_irq_inject
struct pciem_irq_inject arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_INJECT_IRQ, &arg);
PCIEM_IOCTL_DMA
#define PCIEM_IOCTL_DMA _IOWR(PCIEM_IOCTL_MAGIC, 16, struct pciem_dma_op)
Direction: read/write (both directions)
Parameter struct: pciem_dma_op
struct pciem_dma_op arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_DMA, &arg);
PCIEM_IOCTL_DMA_ATOMIC
#define PCIEM_IOCTL_DMA_ATOMIC _IOWR(PCIEM_IOCTL_MAGIC, 17, struct pciem_dma_atomic)
Direction: read/write (both directions)
Parameter struct: pciem_dma_atomic
struct pciem_dma_atomic arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_DMA_ATOMIC, &arg);
PCIEM_IOCTL_P2P
#define PCIEM_IOCTL_P2P _IOWR(PCIEM_IOCTL_MAGIC, 18, struct pciem_p2p_op_user)
Direction: read/write (both directions)
Parameter struct: pciem_p2p_op_user
struct pciem_p2p_op_user arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_P2P, &arg);
PCIEM_IOCTL_GET_BAR_INFO
#define PCIEM_IOCTL_GET_BAR_INFO _IOWR(PCIEM_IOCTL_MAGIC, 19, struct pciem_bar_info_query)
Direction: read/write (both directions)
Parameter struct: pciem_bar_info_query
struct pciem_bar_info_query arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_GET_BAR_INFO, &arg);
PCIEM_IOCTL_SET_EVENTFD
#define PCIEM_IOCTL_SET_EVENTFD _IOW(PCIEM_IOCTL_MAGIC, 21, struct pciem_eventfd_config)
Direction: write (userspace → kernel)
Parameter struct: pciem_eventfd_config
struct pciem_eventfd_config arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_SET_EVENTFD, &arg);
PCIEM_IOCTL_SET_IRQFD
#define PCIEM_IOCTL_SET_IRQFD _IOW(PCIEM_IOCTL_MAGIC, 22, struct pciem_irqfd_config)
Direction: write (userspace → kernel)
Parameter struct: pciem_irqfd_config
struct pciem_irqfd_config arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_SET_IRQFD, &arg);
PCIEM_IOCTL_DMA_INDIRECT
#define PCIEM_IOCTL_DMA_INDIRECT _IOWR(PCIEM_IOCTL_MAGIC, 24, struct pciem_dma_indirect)
Direction: read/write (both directions)
Parameter struct: pciem_dma_indirect
struct pciem_dma_indirect arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_DMA_INDIRECT, &arg);
PCIEM_IOCTL_TRACE_BAR
#define PCIEM_IOCTL_TRACE_BAR _IOWR(PCIEM_IOCTL_MAGIC, 25, struct pciem_trace_bar)
Direction: read/write (both directions)
Parameter struct: pciem_trace_bar
struct pciem_trace_bar arg = { /* ... */ };
int ret = ioctl(fd, PCIEM_IOCTL_TRACE_BAR, &arg);
PCIEM_IOCTL_START
#define PCIEM_IOCTL_START _IO(PCIEM_IOCTL_MAGIC, 26)
Direction: none (no data transfer)
int ret = ioctl(fd, PCIEM_IOCTL_START);