From bc153c692ff962bda50532211fdc0086a58e6c52 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 2 May 2016 18:00:38 +0000 Subject: Add a new bus method to fetch device-specific CPU sets. bus_get_cpus() returns a specified set of CPUs for a device. It accepts an enum for the second parameter that indicates the type of cpuset to request. Currently two valus are supported: - LOCAL_CPUS (on x86 this returns all the CPUs in the package closest to the device when DEVICE_NUMA is enabled) - INTR_CPUS (like LOCAL_CPUS but only returns 1 SMT thread for each core) For systems that do not support NUMA (or if it is not enabled in the kernel config), LOCAL_CPUS fails with EINVAL. INTR_CPUS is mapped to 'all_cpus' by default. The idea is that INTR_CPUS should always return a valid set. Device drivers which want to use per-CPU interrupts should start using INTR_CPUS instead of simply assigning interrupts to all available CPUs. In the future we may wish to add tunables to control the policy of INTR_CPUS (e.g. should it be local-only or global, should it ignore SMT threads or not). The x86 nexus driver exposes the internal set of interrupt CPUs from the the x86 interrupt code via INTR_CPUS. The ACPI bus driver and PCI bridge drivers use _PXM to return a suitable LOCAL_CPUS set when _PXM exists and DEVICE_NUMA is enabled. They also and the global INTR_CPUS set from the nexus driver with the per-domain set from _PXM to generate a local INTR_CPUS set for child devices. Reviewed by: wblock (manpage) Differential Revision: https://reviews.freebsd.org/D5519 --- sys/sys/bus.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'sys/sys/bus.h') diff --git a/sys/sys/bus.h b/sys/sys/bus.h index 4992cdb4847e..db86aeda1846 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -32,6 +32,7 @@ #include #include #include +#include #include /** @@ -272,6 +273,16 @@ enum intr_polarity { INTR_POLARITY_LOW = 2 }; +/** + * CPU sets supported by bus_get_cpus(). Note that not all sets may be + * supported for a given device. If a request is not supported by a + * device (or its parents), then bus_get_cpus() will fail with EINVAL. + */ +enum cpu_sets { + LOCAL_CPUS = 0, + INTR_CPUS +}; + typedef int (*devop_t)(void); /** @@ -388,6 +399,8 @@ int bus_generic_deactivate_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int bus_generic_detach(device_t dev); void bus_generic_driver_added(device_t dev, driver_t *driver); +int bus_generic_get_cpus(device_t dev, device_t child, enum cpu_sets op, + size_t setsize, cpuset_t *cpuset); bus_dma_tag_t bus_generic_get_dma_tag(device_t dev, device_t child); bus_space_tag_t @@ -457,6 +470,8 @@ int bus_activate_resource(device_t dev, int type, int rid, struct resource *r); int bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r); +int bus_get_cpus(device_t dev, enum cpu_sets op, size_t setsize, + cpuset_t *cpuset); bus_dma_tag_t bus_get_dma_tag(device_t dev); bus_space_tag_t bus_get_bus_tag(device_t dev); int bus_get_domain(device_t dev, int *domain); -- cgit v1.2.3