Skip to content

Add go bindings for libpqos - #297

Draft
rucoder wants to merge 3 commits into
intel:masterfrom
rucoder:rucoder/go-lib
Draft

Add go bindings for libpqos#297
rucoder wants to merge 3 commits into
intel:masterfrom
rucoder:rucoder/go-lib

Conversation

@rucoder

@rucoder rucoder commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

This PR introduces CGO bindings for libpqos library. Almost all functionality is covered except for some specialized features

NOTE This is just a draft PR to start a discussion. It may be updated as I proceed with testing

Description

The Go bindings provide complete coverage of the core PQoS API (initialization, capability detection, cache/memory allocation, monitoring) but are missing some advanced/specialized features from the C library.

Coverage: ~85% of commonly-used APIs, ~65% of total C APIs


Fully Implemented

Core Library (100%)

  • pqos_init() - Initialize library
  • pqos_fini() - Finalize library
  • pqos_cap_get() - Get capabilities
  • pqos_inter_get() - Get interface type

Capability Detection (100%)

  • pqos_cap_get_type() - Get capability by type (via HasL3CA(), HasL2CA(), etc.)
  • All capability structures (L3CA, L2CA, MBA, MON)
  • CPU topology information
  • Cache information (L2/L3)

L3 Cache Allocation (100%)

  • pqos_l3ca_set() - Set L3 CAT configuration
  • pqos_l3ca_get() - Get L3 CAT configuration
  • pqos_l3ca_get_min_cbm_bits() - Get minimum CBM bits
  • CDP support (Code/Data Prioritization)
  • Non-contiguous CBM support

L2 Cache Allocation (100%)

  • pqos_l2ca_set() - Set L2 CAT configuration
  • pqos_l2ca_get() - Get L2 CAT configuration
  • pqos_l2ca_get_min_cbm_bits() - Get minimum CBM bits
  • CDP support

Memory Bandwidth Allocation (100%)

  • pqos_mba_set() - Set MBA configuration
  • pqos_mba_get() - Get MBA configuration
  • Controller mode support
  • SMBA field support

Core/Process Association (100%)

  • pqos_alloc_assoc_set() - Associate core with COS
  • pqos_alloc_assoc_get() - Get core's COS
  • pqos_alloc_assoc_set_pid() - Associate PID with COS
  • pqos_alloc_assoc_get_pid() - Get PID's COS
  • pqos_alloc_assign() - Auto-assign COS to cores
  • pqos_alloc_release() - Release cores to default
  • pqos_alloc_assign_pid() - Auto-assign COS to PIDs
  • pqos_alloc_release_pid() - Release PIDs to default
  • pqos_alloc_reset() - Reset allocation

Resource Monitoring - Cores (100%)

  • pqos_mon_start_cores() - Start core monitoring
  • pqos_mon_stop() - Stop monitoring
  • pqos_mon_poll() - Poll monitoring data
  • pqos_mon_reset() - Reset monitoring
  • pqos_mon_assoc_get() - Get core RMID

Resource Monitoring - Processes (100%)

  • pqos_mon_start_pids2() - Start PID monitoring
  • pqos_mon_add_pids() - Add PIDs to group
  • pqos_mon_remove_pids() - Remove PIDs from group

Event Values (100%)

  • LLC occupancy
  • Local/Total/Remote memory bandwidth
  • Instructions per cycle (IPC)
  • LLC misses/references
  • Helper methods (GetIPC, GetLLCMissRate)

Partially Implemented

Capability Queries (50%)

Implemented:

  • Check if feature supported (HasL3CA, HasMBA, etc.)
  • Get capability details (GetL3CA, GetMBA, etc.)

Missing:

  • pqos_l3ca_get_cos_num() - Get number of COS
  • pqos_l2ca_get_cos_num() - Get number of COS
  • pqos_mba_get_cos_num() - Get number of COS
  • pqos_smba_get_cos_num() - Get number of COS
  • pqos_l3ca_cdp_enabled() - Check CDP status
  • pqos_l2ca_cdp_enabled() - Check CDP status
  • pqos_mba_ctrl_enabled() - Check MBA controller status
  • pqos_l3ca_iordt_enabled() - Check I/O RDT status
  • pqos_cap_get_event() - Get monitoring event details

Workaround: These can be accessed via capability structures, e.g., l3ca.NumClasses, l3ca.CDPOn


Not Implemented

I/O RDT - Device/Channel Monitoring (0%)

  • pqos_mon_start_channels() - Monitor I/O channels
  • pqos_mon_start_dev() - Monitor specific device
  • pqos_mon_assoc_get_channel() - Get channel RMID
  • pqos_mon_assoc_get_dev() - Get device RMID
  • Channel and device structures

Impact: Cannot monitor I/O RDT devices (PCIe, etc.)

I/O RDT - Device Allocation (0%)

  • pqos_alloc_assoc_set_channel() - Associate channel with COS
  • pqos_alloc_assoc_get_channel() - Get channel's COS
  • pqos_alloc_assoc_set_dev() - Associate device with COS
  • pqos_alloc_assoc_get_dev() - Get device's COS

Impact: Cannot allocate resources to I/O devices

Uncore Monitoring (0%)

  • pqos_mon_start_uncore() - Monitor uncore/socket level

Impact: Cannot do socket-level monitoring, only core/process

Advanced Configuration (0%)

  • pqos_sysconfig_get() - Get system configuration
  • pqos_mon_reset_config() - Reset with config
  • pqos_alloc_reset_config() - Reset allocation with config
  • Configuration structures (pqos_sysconfig, pqos_mon_config, pqos_alloc_config)

Impact: Cannot use advanced reset/configuration options

CPU Topology Helpers (0%)

  • pqos_cpu_get_one_by_mba_id() - Get core by MBA ID
  • pqos_cpu_get_one_by_smba_id() - Get core by SMBA ID
  • pqos_cpu_get_one_core() - Get one core from socket
  • pqos_cpu_get_one_by_numaid() - Get core by NUMA ID
  • pqos_cpu_get_one_by_l3cat_id() - Get core by L3 CAT ID
  • pqos_cpu_get_one_by_l2id() - Get core by L2 ID
  • pqos_cpu_check_core() - Check if core is valid
  • pqos_cpu_get_socketid() - Get socket ID for core
  • pqos_cpu_get_numaid() - Get NUMA ID for core
  • pqos_cpu_get_clusterid() - Get cluster ID for core

Impact: Need to manually search core arrays
Workaround: Use CPUInfo methods like FindCore(), GetCoresBySocket()

Monitoring Value Helpers (0%)

  • pqos_mon_get_value() - Get specific event value
  • pqos_mon_get_ipc() - Get IPC value

Impact: Minor - values accessible via MonData.Values struct
Workaround: Use MonData.GetIPC(), MonData.Values.LLC, etc.

Deprecated Functions (Intentionally Skipped)

  • pqos_mon_start() - Deprecated, use pqos_mon_start_cores()
  • pqos_mon_start_pid() - Deprecated, use pqos_mon_start_pids2()
  • pqos_mon_start_pids() - Deprecated, use pqos_mon_start_pids2()

Missing Structs/Types

Not Implemented

  • pqos_sysconfig - System configuration
  • pqos_devinfo - Device information
  • pqos_dev - Device structure
  • pqos_channel - Channel structure
  • pqos_mon_config - Monitoring configuration
  • pqos_alloc_config - Allocation configuration
  • pqos_channel_t - Channel ID type

Affected parts

  • library
  • pqos utility
  • rdtset utility
  • other: introduce Go bindings

Motivation and Context

These bindings are required to add a support for Intel RTD technologies into EVE OS https://github.com/lf-edge/eve

How Has This Been Tested?

The test is ongoing. This is a draft PR to start a discussion

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation. - maybe yes
  • I have updated the documentation accordingly.

@rucoder
rucoder marked this pull request as draft November 14, 2025 10:21
@rucoder
rucoder force-pushed the rucoder/go-lib branch 2 times, most recently from 0ef849c to 95683ad Compare November 18, 2025 12:10
@ajherdri

Copy link
Copy Markdown

Hi Michael,
Thanks for the contribution! This is quite interesting. We are reviewing and will get back to you soon.
Thanks,
~Andrew

@ajherdri

Copy link
Copy Markdown

Hi Michael,
Update -- We are interested in supporting, and we would like to discuss the long-term support model for this code, we will set up a calendar invite to discuss in early December.
Thanks!
~Andrew

@rstorozh
rstorozh requested a review from Copilot December 9, 2025 09:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces comprehensive Go bindings for the Intel RDT PQoS library, enabling Go applications to utilize Resource Director Technology features. The bindings provide idiomatic Go interfaces for cache allocation, memory bandwidth management, and resource monitoring capabilities.

Key Changes:

  • Added complete CGO bindings for core PQoS library functionality (initialization, capability detection, resource allocation)
  • Implemented resource monitoring APIs for cores and processes with support for LLC occupancy and memory bandwidth metrics
  • Created example programs demonstrating capability detection and basic library usage

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/go/pqos/pqos.go Core library initialization, configuration, and singleton pattern implementation
lib/go/pqos/capability.go Capability detection for L3/L2 CAT, MBA, and monitoring features
lib/go/pqos/cpuinfo.go CPU topology information and cache hierarchy utilities
lib/go/pqos/allocation.go Cache and memory bandwidth allocation APIs with COS management
lib/go/pqos/monitoring.go Resource monitoring for cores/processes with event data structures
lib/go/pqos/pqos_test.go Unit tests for core functionality and CPU topology methods
lib/go/examples/simple/main.go Basic example demonstrating initialization and capability detection
lib/go/examples/capability/main.go Comprehensive example showing detailed capability inspection
lib/go/Makefile Build configuration with dependency checking and example compilation
lib/go/go.mod Go module definition requiring Go 1.21
lib/go/API.md Complete API documentation with usage examples
lib/go/.gitignore Git ignore patterns for build artifacts
Comments suppressed due to low confidence (1)

lib/go/pqos/pqos.go:1

  • The helper functions safeCString and freeCString are defined but never used in the codebase. Remove these unused functions or add documentation explaining their intended future use.
// Copyright(c) 2025 Zededa, Inc.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/go/pqos/pqos_test.go
}

err := p.Init(nil)
if err != nil {

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test TestInitWithNilConfig lacks verification of the initialized state's configuration. Add assertions to verify that when nil config is passed, the library initializes with expected defaults (InterAuto interface and LogVerbosityDefault).

Copilot uses AI. Check for mistakes.
Comment thread lib/go/pqos/monitoring.go
}

ret := C.pqos_mon_poll(&cGroups[0], C.uint(len(groups)))
if ret != C.PQOS_RETVAL_OK && ret != C.PQOS_RETVAL_OVERFLOW {

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overflow error message on line 319 loses information about which group(s) experienced the overflow. Consider enhancing the error message to include the group indices that had overflow to aid debugging.

Copilot uses AI. Check for mistakes.
Comment thread lib/go/Makefile

check-deps:
@echo "Checking dependencies..."
@if [ ! -f "$(LIBPQOS_PATH)/libpqos.so.6" ]; then \

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded version number '.6' in the library name makes the build fragile to version changes. Consider using a wildcard pattern like libpqos.so* or extracting the version to a variable for easier maintenance.

Suggested change
@if [ ! -f "$(LIBPQOS_PATH)/libpqos.so.6" ]; then \
@if [ -z "$(wildcard $(LIBPQOS_PATH)/libpqos.so*)" ]; then \

Copilot uses AI. Check for mistakes.
Comment thread lib/go/go.mod
@@ -0,0 +1,7 @@
module github.com/intel/intel-cmt-cat/lib/go

go 1.21

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The minimum Go version requirement of 1.21 should be documented in the PR description or README, explaining why this specific version is required (e.g., specific language features, standard library dependencies).

Copilot uses AI. Check for mistakes.
Comment thread lib/go/pqos/pqos_test.go
Comment on lines +270 to +272
func TestCPUInfoL2Methods(t *testing.T) {
// Create a mock CPUInfo with some test data
cpuInfo := &CPUInfo{

Copilot AI Dec 9, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The L2 topology tests use hardcoded mock data but don't test against actual hardware capabilities. Add integration tests that verify L2 methods against real CPU topology when available, potentially skipping if hardware isn't present.

Copilot uses AI. Check for mistakes.
@rucoder
rucoder force-pushed the rucoder/go-lib branch 4 times, most recently from d749698 to 0c9b9d4 Compare July 1, 2026 11:22
rucoder added 3 commits July 1, 2026 11:24
Topology consumers need to identify SMT siblings as logical CPUs that
share the same physical core. L2 cache id is not sufficient for this:
on Intel E-core modules a single L2 is shared by 4 distinct physical
cores.

Add an unsigned core_id field to struct pqos_coreinfo and populate it on
Linux from /sys/devices/system/cpu/cpu%u/topology/core_id. The OS
interface reads it in os_cpuinfo_topology() via a new
os_cpuinfo_cpu_core() (mirroring os_cpuinfo_cpu_socket()); the MSR/MMIO
CPUID topology builder (cpuinfo_build_topo()) reads the same sysfs value.
SMT siblings are then the logical CPUs sharing (socket, core_id).

Signed-off-by: Mikhail Malyshev <mike.malyshev@gmail.com>
CGO bindings for libpqos (init/fini, capability detection, cpuinfo,
allocation and monitoring). CoreInfo exposes the physical core id as
CoreID so callers can group logical CPUs into SMT siblings by
(Socket, CoreID).

Signed-off-by: Mikhail Malyshev <mike.malyshev@gmail.com>
On CONFIG_STRICT_DEVMEM=y kernels, acpi_get_sig() falling back to
acpi_get_mmap() maps and reads physical memory via /dev/mem, which the
kernel restricts. The mmap of the RSDP/BIOS region either fails or, worse,
succeeds and then faults on access, taking down a CGO host process such as
the Go bindings.

When the kernel exposes ACPI tables under /sys/firmware/acpi/tables but the
requested table is not present there, return NULL instead of scanning
/dev/mem. The memory fallback is still used on legacy kernels that do not
expose the sysfs ACPI tables directory at all.

Fixes: intel#307
Signed-off-by: Mikhail Malyshev <mike.malyshev@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants