MFC r271889, 272799, 272800, 274976
This brings in bus_get_domain() and the related reporting via devinfo, dmesg, and sysctl. Obtained from: adrian, jhb Sponsored by: Netflix, Inc.
This commit is contained in:
parent
27912a446f
commit
565f091b88
@ -207,6 +207,7 @@ static device_method_t acpi_methods[] = {
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
|
||||
DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit),
|
||||
DEVMETHOD(bus_get_domain, acpi_get_domain),
|
||||
|
||||
/* ACPI bus */
|
||||
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
|
||||
@ -797,6 +798,7 @@ acpi_print_child(device_t bus, device_t child)
|
||||
retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld");
|
||||
if (device_get_flags(child))
|
||||
retval += printf(" flags %#x", device_get_flags(child));
|
||||
retval += bus_print_child_domain(bus, child);
|
||||
retval += bus_print_child_footer(bus, child);
|
||||
|
||||
return (retval);
|
||||
@ -853,11 +855,18 @@ acpi_child_location_str_method(device_t cbdev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct acpi_device *dinfo = device_get_ivars(child);
|
||||
char buf2[32];
|
||||
int pxm;
|
||||
|
||||
if (dinfo->ad_handle)
|
||||
snprintf(buf, buflen, "handle=%s", acpi_name(dinfo->ad_handle));
|
||||
else
|
||||
snprintf(buf, buflen, "unknown");
|
||||
if (dinfo->ad_handle) {
|
||||
snprintf(buf, buflen, "handle=%s", acpi_name(dinfo->ad_handle));
|
||||
if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ad_handle, "_PXM", &pxm))) {
|
||||
snprintf(buf2, 32, " _PXM=%d", pxm);
|
||||
strlcat(buf, buf2, buflen);
|
||||
}
|
||||
} else {
|
||||
snprintf(buf, buflen, "unknown");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1062,6 +1071,35 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fech the NUMA domain for the given device.
|
||||
*
|
||||
* If a device has a _PXM method, map that to a NUMA domain.
|
||||
*
|
||||
* If none is found, then it'll call the parent method.
|
||||
* If there's no domain, return ENOENT.
|
||||
*/
|
||||
int
|
||||
acpi_get_domain(device_t dev, device_t child, int *domain)
|
||||
{
|
||||
#if MAXMEMDOM > 1
|
||||
ACPI_HANDLE h;
|
||||
int d, pxm;
|
||||
|
||||
h = acpi_get_handle(child);
|
||||
if ((h != NULL) &&
|
||||
ACPI_SUCCESS(acpi_GetInteger(h, "_PXM", &pxm))) {
|
||||
d = acpi_map_pxm_to_vm_domainid(pxm);
|
||||
if (d < 0)
|
||||
return (ENOENT);
|
||||
*domain = d;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
/* No _PXM node; go up a level */
|
||||
return (bus_generic_get_domain(dev, child, domain));
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-allocate/manage all memory and IO resources. Since rman can't handle
|
||||
* duplicates, we merge any in the sysresource attach routine.
|
||||
|
@ -94,6 +94,7 @@ static device_method_t acpi_pci_methods[] = {
|
||||
DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar),
|
||||
DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method),
|
||||
DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag),
|
||||
DEVMETHOD(bus_get_domain, acpi_get_domain),
|
||||
|
||||
/* PCI interface */
|
||||
DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method),
|
||||
@ -149,12 +150,19 @@ acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
|
||||
int pxm;
|
||||
char buf2[32];
|
||||
|
||||
pci_child_location_str_method(cbdev, child, buf, buflen);
|
||||
|
||||
|
||||
if (dinfo->ap_handle) {
|
||||
strlcat(buf, " handle=", buflen);
|
||||
strlcat(buf, acpi_name(dinfo->ap_handle), buflen);
|
||||
strlcat(buf, " handle=", buflen);
|
||||
strlcat(buf, acpi_name(dinfo->ap_handle), buflen);
|
||||
|
||||
if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ap_handle, "_PXM", &pxm))) {
|
||||
snprintf(buf2, 32, " _PXM=%d", pxm);
|
||||
strlcat(buf, buf2, buflen);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -489,5 +489,16 @@ ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj);
|
||||
|
||||
SYSCTL_DECL(_debug_acpi);
|
||||
|
||||
/*
|
||||
* Map a PXM to a VM domain.
|
||||
*
|
||||
* Returns the VM domain ID if found, or -1 if not found / invalid.
|
||||
*/
|
||||
#if MAXMEMDOM > 1
|
||||
extern int acpi_map_pxm_to_vm_domainid(int pxm);
|
||||
#endif
|
||||
|
||||
extern int acpi_get_domain(device_t dev, device_t child, int *domain);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* !_ACPIVAR_H_ */
|
||||
|
@ -3781,6 +3781,7 @@ pci_print_child(device_t dev, device_t child)
|
||||
retval += printf(" at device %d.%d", pci_get_slot(child),
|
||||
pci_get_function(child));
|
||||
|
||||
retval += bus_print_child_domain(dev, child);
|
||||
retval += bus_print_child_footer(dev, child);
|
||||
|
||||
return (retval);
|
||||
|
@ -670,3 +670,16 @@ METHOD int remap_intr {
|
||||
device_t _child;
|
||||
u_int _irq;
|
||||
} DEFAULT null_remap_intr;
|
||||
|
||||
/**
|
||||
* @brief Get the VM domain handle for the given bus and child.
|
||||
*
|
||||
* @param _dev the bus device
|
||||
* @param _child the child device
|
||||
* @param _domain a pointer to the bus's domain handle identifier
|
||||
*/
|
||||
METHOD int get_domain {
|
||||
device_t _dev;
|
||||
device_t _child;
|
||||
int *_domain;
|
||||
} DEFAULT bus_generic_get_domain;
|
||||
|
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/uio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/interrupt.h>
|
||||
#include <sys/cpuset.h>
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
@ -284,6 +285,7 @@ static void
|
||||
device_sysctl_init(device_t dev)
|
||||
{
|
||||
devclass_t dc = dev->devclass;
|
||||
int domain;
|
||||
|
||||
if (dev->sysctl_tree != NULL)
|
||||
return;
|
||||
@ -313,6 +315,10 @@ device_sysctl_init(device_t dev)
|
||||
OID_AUTO, "%parent", CTLTYPE_STRING | CTLFLAG_RD,
|
||||
dev, DEVICE_SYSCTL_PARENT, device_sysctl_handler, "A",
|
||||
"parent device");
|
||||
if (bus_get_domain(dev, &domain) == 0)
|
||||
SYSCTL_ADD_INT(&dev->sysctl_ctx,
|
||||
SYSCTL_CHILDREN(dev->sysctl_tree), OID_AUTO, "%domain",
|
||||
CTLFLAG_RD, NULL, domain, "NUMA domain");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3716,6 +3722,25 @@ bus_print_child_footer(device_t dev, device_t child)
|
||||
return (printf(" on %s\n", device_get_nameunit(dev)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for implementing BUS_PRINT_CHILD().
|
||||
*
|
||||
* This function prints out the VM domain for the given device.
|
||||
*
|
||||
* @returns the number of characters printed
|
||||
*/
|
||||
int
|
||||
bus_print_child_domain(device_t dev, device_t child)
|
||||
{
|
||||
int domain;
|
||||
|
||||
/* No domain? Don't print anything */
|
||||
if (BUS_GET_DOMAIN(dev, child, &domain) != 0)
|
||||
return (0);
|
||||
|
||||
return (printf(" numa-domain %d", domain));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function for implementing BUS_PRINT_CHILD().
|
||||
*
|
||||
@ -3730,6 +3755,7 @@ bus_generic_print_child(device_t dev, device_t child)
|
||||
int retval = 0;
|
||||
|
||||
retval += bus_print_child_header(dev, child);
|
||||
retval += bus_print_child_domain(dev, child);
|
||||
retval += bus_print_child_footer(dev, child);
|
||||
|
||||
return (retval);
|
||||
@ -4144,6 +4170,16 @@ bus_generic_child_present(device_t dev, device_t child)
|
||||
return (BUS_CHILD_PRESENT(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
int
|
||||
bus_generic_get_domain(device_t dev, device_t child, int *domain)
|
||||
{
|
||||
|
||||
if (dev->parent)
|
||||
return (BUS_GET_DOMAIN(dev->parent, dev, domain));
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some convenience functions to make it easier for drivers to use the
|
||||
* resource-management functions. All these really do is hide the
|
||||
@ -4476,6 +4512,18 @@ bus_get_dma_tag(device_t dev)
|
||||
return (BUS_GET_DMA_TAG(parent, dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrapper function for BUS_GET_DOMAIN().
|
||||
*
|
||||
* This function simply calls the BUS_GET_DOMAIN() method of the
|
||||
* parent of @p dev.
|
||||
*/
|
||||
int
|
||||
bus_get_domain(device_t dev, int *domain)
|
||||
{
|
||||
return (BUS_GET_DOMAIN(device_get_parent(dev), dev, domain));
|
||||
}
|
||||
|
||||
/* Resume all devices and then notify userland that we're up again. */
|
||||
static int
|
||||
root_resume(device_t dev)
|
||||
|
@ -332,6 +332,7 @@ struct resource_list *
|
||||
bus_generic_get_resource_list (device_t, device_t);
|
||||
void bus_generic_new_pass(device_t dev);
|
||||
int bus_print_child_header(device_t dev, device_t child);
|
||||
int bus_print_child_domain(device_t dev, device_t child);
|
||||
int bus_print_child_footer(device_t dev, device_t child);
|
||||
int bus_generic_print_child(device_t dev, device_t child);
|
||||
int bus_generic_probe(device_t dev);
|
||||
@ -363,6 +364,8 @@ int bus_generic_teardown_intr(device_t dev, device_t child,
|
||||
int bus_generic_write_ivar(device_t dev, device_t child, int which,
|
||||
uintptr_t value);
|
||||
|
||||
int bus_generic_get_domain(device_t dev, device_t child, int *domain);
|
||||
|
||||
/*
|
||||
* Wrapper functions for the BUS_*_RESOURCE methods to make client code
|
||||
* a little simpler.
|
||||
@ -389,6 +392,7 @@ int bus_activate_resource(device_t dev, int type, int rid,
|
||||
int bus_deactivate_resource(device_t dev, int type, int rid,
|
||||
struct resource *r);
|
||||
bus_dma_tag_t bus_get_dma_tag(device_t dev);
|
||||
int bus_get_domain(device_t dev, int *domain);
|
||||
int bus_release_resource(device_t dev, int type, int rid,
|
||||
struct resource *r);
|
||||
int bus_free_resource(device_t dev, int type, struct resource *r);
|
||||
|
@ -62,6 +62,8 @@ int num_mem;
|
||||
static ACPI_TABLE_SRAT *srat;
|
||||
static vm_paddr_t srat_physaddr;
|
||||
|
||||
static int vm_domains[VM_PHYSSEG_MAX];
|
||||
|
||||
static void srat_walk_table(acpi_subtable_handler *handler, void *arg);
|
||||
|
||||
/*
|
||||
@ -247,7 +249,6 @@ check_phys_avail(void)
|
||||
static int
|
||||
renumber_domains(void)
|
||||
{
|
||||
int domains[VM_PHYSSEG_MAX];
|
||||
int i, j, slot;
|
||||
|
||||
/* Enumerate all the domains. */
|
||||
@ -255,17 +256,17 @@ renumber_domains(void)
|
||||
for (i = 0; i < num_mem; i++) {
|
||||
/* See if this domain is already known. */
|
||||
for (j = 0; j < vm_ndomains; j++) {
|
||||
if (domains[j] >= mem_info[i].domain)
|
||||
if (vm_domains[j] >= mem_info[i].domain)
|
||||
break;
|
||||
}
|
||||
if (j < vm_ndomains && domains[j] == mem_info[i].domain)
|
||||
if (j < vm_ndomains && vm_domains[j] == mem_info[i].domain)
|
||||
continue;
|
||||
|
||||
/* Insert the new domain at slot 'j'. */
|
||||
slot = j;
|
||||
for (j = vm_ndomains; j > slot; j--)
|
||||
domains[j] = domains[j - 1];
|
||||
domains[slot] = mem_info[i].domain;
|
||||
vm_domains[j] = vm_domains[j - 1];
|
||||
vm_domains[slot] = mem_info[i].domain;
|
||||
vm_ndomains++;
|
||||
if (vm_ndomains > MAXMEMDOM) {
|
||||
vm_ndomains = 1;
|
||||
@ -280,15 +281,15 @@ renumber_domains(void)
|
||||
* If the domain is already the right value, no need
|
||||
* to renumber.
|
||||
*/
|
||||
if (domains[i] == i)
|
||||
if (vm_domains[i] == i)
|
||||
continue;
|
||||
|
||||
/* Walk the cpu[] and mem_info[] arrays to renumber. */
|
||||
for (j = 0; j < num_mem; j++)
|
||||
if (mem_info[j].domain == domains[i])
|
||||
if (mem_info[j].domain == vm_domains[i])
|
||||
mem_info[j].domain = i;
|
||||
for (j = 0; j <= MAX_APIC_ID; j++)
|
||||
if (cpus[j].enabled && cpus[j].domain == domains[i])
|
||||
if (cpus[j].enabled && cpus[j].domain == vm_domains[i])
|
||||
cpus[j].domain = i;
|
||||
}
|
||||
KASSERT(vm_ndomains > 0,
|
||||
@ -368,4 +369,23 @@ srat_set_cpus(void *dummy)
|
||||
}
|
||||
}
|
||||
SYSINIT(srat_set_cpus, SI_SUB_CPU, SI_ORDER_ANY, srat_set_cpus, NULL);
|
||||
|
||||
/*
|
||||
* Map a _PXM value to a VM domain ID.
|
||||
*
|
||||
* Returns the domain ID, or -1 if no domain ID was found.
|
||||
*/
|
||||
int
|
||||
acpi_map_pxm_to_vm_domainid(int pxm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vm_ndomains; i++) {
|
||||
if (vm_domains[i] == pxm)
|
||||
return (i);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#endif /* MAXMEMDOM > 1 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user