Message ID | 1486655834-9708-14-git-send-email-vijay.kilari@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hello Vijay, On 09/02/17 15:57, vijay.kilari@gmail.com wrote: > From: Vijaya Kumar K <Vijaya.Kumar@cavium.com> > > Move SRAT handling code which is common across > architecture is moved to new file xen/commom/srat.c > from xen/arch/x86/srat.c file. New header file srat.h is > introduced. > > Signed-off-by: Vijaya Kumar <Vijaya.Kumar@cavium.com> > --- > xen/arch/x86/domain_build.c | 1 + > xen/arch/x86/numa.c | 1 + > xen/arch/x86/physdev.c | 1 + > xen/arch/x86/setup.c | 1 + > xen/arch/x86/smpboot.c | 1 + > xen/arch/x86/srat.c | 129 +------------------------------ > xen/arch/x86/x86_64/mm.c | 1 + > xen/common/Makefile | 1 + > xen/common/srat.c | 150 ++++++++++++++++++++++++++++++++++++ This new file should be created in xen/drivers/acpi/ > xen/drivers/passthrough/vtd/iommu.c | 1 + > xen/include/asm-x86/numa.h | 2 - > xen/include/xen/numa.h | 1 - > xen/include/xen/srat.h | 13 ++++ This new file should be created in xen/include/acpi/ [...] > diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c > index 58dee09..af12e26 100644 > --- a/xen/arch/x86/srat.c > +++ b/xen/arch/x86/srat.c > @@ -18,91 +18,20 @@ > #include <xen/acpi.h> > #include <xen/numa.h> > #include <xen/pfn.h> > +#include <xen/srat.h> > #include <asm/e820.h> > #include <asm/page.h> > > -static struct acpi_table_slit *__read_mostly acpi_slit; > +extern struct acpi_table_slit *__read_mostly acpi_slit; This should be defined in the header. However, I don't like the idea of exposing acpi_slit. Looking at the usage it is only to parse the distance that can be common. [...] > /* Callback for Proximity Domain -> x2APIC mapping */ > void __init > acpi_numa_x2apic_affinity_init(const struct acpi_srat_x2apic_cpu_affinity *pa) > @@ -456,18 +343,6 @@ int __init acpi_scan_nodes(u64 start, u64 end) > return 0; > } The code of acpi_numa_memory_affinity_init looks pretty generic. Why didn't you move it in the common code? [...] > diff --git a/xen/common/Makefile b/xen/common/Makefile > index c1bd2ff..a668094 100644 > --- a/xen/common/Makefile > +++ b/xen/common/Makefile > @@ -64,6 +64,7 @@ obj-bin-y += warning.init.o > obj-$(CONFIG_XENOPROF) += xenoprof.o > obj-y += xmalloc_tlsf.o > obj-y += numa.o > +obj-y += srat.o This should be only compiled when CONFIG_ACPI is enabled. > > obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > > diff --git a/xen/common/srat.c b/xen/common/srat.c > new file mode 100644 > index 0000000..cf50c78 > --- /dev/null > +++ b/xen/common/srat.c > @@ -0,0 +1,150 @@ > +/* > + * ACPI 3.0 based NUMA setup > + * Copyright 2004 Andi Kleen, SuSE Labs. > + * > + * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. > + * > + * Called from acpi_numa_init while reading the SRAT and SLIT tables. > + * Assumes all memory regions belonging to a single proximity domain > + * are in one chunk. Holes between them will be included in the node. > + * > + * Adapted for Xen: Ryan Harper <ryanh@us.ibm.com> > + * > + * Moved this generic code from xen/arch/x86/srat.c for other arch usage > + * by Vijaya Kumar K <Vijaya.Kumar@cavium.com> > + */ > + > +#include <xen/init.h> > +#include <xen/mm.h> > +#include <xen/inttypes.h> > +#include <xen/nodemask.h> > +#include <xen/acpi.h> > +#include <xen/numa.h> > +#include <xen/pfn.h> > +#include <xen/srat.h> > +#include <asm/page.h> > + > +struct acpi_table_slit *__read_mostly acpi_slit; This should really be static. > +extern struct node nodes[MAX_NUMNODES] __initdata; > + > +struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] = > + { [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} }; So this is not only exposed because of bad_srat(). The code should be reworked to avoid that. > + > +static inline bool_t node_found(unsigned idx, unsigned pxm) > +{ > + return ((pxm2node[idx].pxm == pxm) && > + (pxm2node[idx].node != NUMA_NO_NODE)); > +} > + > +nodeid_t pxm_to_node(unsigned pxm) > +{ > + unsigned i; > + > + if ( (pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm) ) > + return pxm2node[pxm].node; > + > + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) > + if ( node_found(i, pxm) ) > + return pxm2node[i].node; > + > + return NUMA_NO_NODE; > +} > + > +nodeid_t setup_node(unsigned pxm) This name is too generic. The name of the function should make clear it is an ACPI only function. [...] > +unsigned node_to_pxm(nodeid_t n) > +{ > + unsigned i; > + > + if ( (n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n) ) > + return pxm2node[n].pxm; > + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) > + if ( pxm2node[i].node == n ) > + return pxm2node[i].pxm; > + return 0; > +} Missing emacs magic here. > diff --git a/xen/include/asm-x86/numa.h b/xen/include/asm-x86/numa.h > index 659ff6a..79a445c 100644 > --- a/xen/include/asm-x86/numa.h > +++ b/xen/include/asm-x86/numa.h > @@ -17,8 +17,6 @@ extern cpumask_t node_to_cpumask[]; > #define node_to_first_cpu(node) (__ffs(node_to_cpumask[node])) > #define node_to_cpumask(node) (node_to_cpumask[node]) > > -extern nodeid_t pxm_to_node(unsigned int pxm); > - > #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) > > extern void numa_init_array(void); > diff --git a/xen/include/xen/numa.h b/xen/include/xen/numa.h > index 4f04ab4..eb18380 100644 > --- a/xen/include/xen/numa.h > +++ b/xen/include/xen/numa.h > @@ -73,7 +73,6 @@ extern int valid_numa_range(u64 start, u64 end, nodeid_t node); > extern int conflicting_memblks(u64 start, u64 end); > extern void cutoff_node(int i, u64 start, u64 end); > extern void numa_add_cpu(int cpu); > -extern nodeid_t setup_node(unsigned int pxm); > extern void numa_set_node(int cpu, nodeid_t node); > extern void setup_node_bootmem(nodeid_t nodeid, u64 start, u64 end); > extern int compute_hash_shift(struct node *nodes, int numnodes, > diff --git a/xen/include/xen/srat.h b/xen/include/xen/srat.h > new file mode 100644 > index 0000000..978f1e8 > --- /dev/null > +++ b/xen/include/xen/srat.h > @@ -0,0 +1,13 @@ > +#ifndef __XEN_SRAT_H__ > +#define __XEN_SRAT_H__ > + > +struct pxm2node { > + unsigned pxm; > + nodeid_t node; > +}; > + > +extern struct pxm2node __read_mostly pxm2node[MAX_NUMNODES]; > +nodeid_t pxm_to_node(unsigned pxm); > +nodeid_t setup_node(unsigned pxm); > +unsigned node_to_pxm(nodeid_t n); > +#endif /* __XEN_SRAT_H__ */ Missing emacs magic. > Regards,
On Thu, Mar 2, 2017 at 9:00 PM, Julien Grall <julien.grall@arm.com> wrote: > Hello Vijay, > > On 09/02/17 15:57, vijay.kilari@gmail.com wrote: >> >> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com> >> >> Move SRAT handling code which is common across >> architecture is moved to new file xen/commom/srat.c >> from xen/arch/x86/srat.c file. New header file srat.h is >> introduced. >> >> Signed-off-by: Vijaya Kumar <Vijaya.Kumar@cavium.com> >> --- >> xen/arch/x86/domain_build.c | 1 + >> xen/arch/x86/numa.c | 1 + >> xen/arch/x86/physdev.c | 1 + >> xen/arch/x86/setup.c | 1 + >> xen/arch/x86/smpboot.c | 1 + >> xen/arch/x86/srat.c | 129 +------------------------------ >> xen/arch/x86/x86_64/mm.c | 1 + >> xen/common/Makefile | 1 + >> xen/common/srat.c | 150 >> ++++++++++++++++++++++++++++++++++++ > > > This new file should be created in xen/drivers/acpi/ OK > >> xen/drivers/passthrough/vtd/iommu.c | 1 + >> xen/include/asm-x86/numa.h | 2 - >> xen/include/xen/numa.h | 1 - >> xen/include/xen/srat.h | 13 ++++ > > > This new file should be created in xen/include/acpi/ OK > > [...] > >> diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c >> index 58dee09..af12e26 100644 >> --- a/xen/arch/x86/srat.c >> +++ b/xen/arch/x86/srat.c >> @@ -18,91 +18,20 @@ >> #include <xen/acpi.h> >> #include <xen/numa.h> >> #include <xen/pfn.h> >> +#include <xen/srat.h> >> #include <asm/e820.h> >> #include <asm/page.h> >> >> -static struct acpi_table_slit *__read_mostly acpi_slit; >> +extern struct acpi_table_slit *__read_mostly acpi_slit; > > > This should be defined in the header. However, I don't like the idea of > exposing acpi_slit. > > Looking at the usage it is only to parse the distance that can be common. node_distance() of x86 and arm is quite different as arm has DT mechanism. I will check if possible to make ACPI node_distance part common between x86 and arm. > > [...] > >> /* Callback for Proximity Domain -> x2APIC mapping */ >> void __init >> acpi_numa_x2apic_affinity_init(const struct acpi_srat_x2apic_cpu_affinity >> *pa) >> @@ -456,18 +343,6 @@ int __init acpi_scan_nodes(u64 start, u64 end) >> return 0; >> } > > > The code of acpi_numa_memory_affinity_init looks pretty generic. Why didn't > you move it in the common code? Agreed. > > [...] > >> diff --git a/xen/common/Makefile b/xen/common/Makefile >> index c1bd2ff..a668094 100644 >> --- a/xen/common/Makefile >> +++ b/xen/common/Makefile >> @@ -64,6 +64,7 @@ obj-bin-y += warning.init.o >> obj-$(CONFIG_XENOPROF) += xenoprof.o >> obj-y += xmalloc_tlsf.o >> obj-y += numa.o >> +obj-y += srat.o > > > This should be only compiled when CONFIG_ACPI is enabled. OK > > >> >> obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo >> unlz4 earlycpio,$(n).init.o) >> >> diff --git a/xen/common/srat.c b/xen/common/srat.c >> new file mode 100644 >> index 0000000..cf50c78 >> --- /dev/null >> +++ b/xen/common/srat.c >> @@ -0,0 +1,150 @@ >> +/* >> + * ACPI 3.0 based NUMA setup >> + * Copyright 2004 Andi Kleen, SuSE Labs. >> + * >> + * Reads the ACPI SRAT table to figure out what memory belongs to which >> CPUs. >> + * >> + * Called from acpi_numa_init while reading the SRAT and SLIT tables. >> + * Assumes all memory regions belonging to a single proximity domain >> + * are in one chunk. Holes between them will be included in the node. >> + * >> + * Adapted for Xen: Ryan Harper <ryanh@us.ibm.com> >> + * >> + * Moved this generic code from xen/arch/x86/srat.c for other arch usage >> + * by Vijaya Kumar K <Vijaya.Kumar@cavium.com> >> + */ >> + >> +#include <xen/init.h> >> +#include <xen/mm.h> >> +#include <xen/inttypes.h> >> +#include <xen/nodemask.h> >> +#include <xen/acpi.h> >> +#include <xen/numa.h> >> +#include <xen/pfn.h> >> +#include <xen/srat.h> >> +#include <asm/page.h> >> + >> +struct acpi_table_slit *__read_mostly acpi_slit; > > > This should really be static. > >> +extern struct node nodes[MAX_NUMNODES] __initdata; >> + >> +struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] = >> + { [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} }; > > > So this is not only exposed because of bad_srat(). The code should be > reworked to avoid that. I will check. > >> + >> +static inline bool_t node_found(unsigned idx, unsigned pxm) >> +{ >> + return ((pxm2node[idx].pxm == pxm) && >> + (pxm2node[idx].node != NUMA_NO_NODE)); >> +} >> + >> +nodeid_t pxm_to_node(unsigned pxm) >> +{ >> + unsigned i; >> + >> + if ( (pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm) ) >> + return pxm2node[pxm].node; >> + >> + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) >> + if ( node_found(i, pxm) ) >> + return pxm2node[i].node; >> + >> + return NUMA_NO_NODE; >> +} >> + >> +nodeid_t setup_node(unsigned pxm) > > > This name is too generic. The name of the function should make clear it is > an ACPI only function. > OK > [...] > >> +unsigned node_to_pxm(nodeid_t n) >> +{ >> + unsigned i; >> + >> + if ( (n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n) ) >> + return pxm2node[n].pxm; >> + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) >> + if ( pxm2node[i].node == n ) >> + return pxm2node[i].pxm; >> + return 0; >> +} > > > Missing emacs magic here. You mean this at the end of the file? /* * Local variables: * mode: C * c-file-style: "BSD" * c-basic-offset: 4 * indent-tabs-mode: nil * End: */
On 02/03/17 16:31, Vijay Kilari wrote: > On Thu, Mar 2, 2017 at 9:00 PM, Julien Grall <julien.grall@arm.com> wrote: >> Missing emacs magic here. > You mean this at the end of the file? Yes. > > /* > * Local variables: > * mode: C > * c-file-style: "BSD" > * c-basic-offset: 4 > * indent-tabs-mode: nil > * End: > */ >
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 243df96..4d7795b 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -22,6 +22,7 @@ #include <xen/compat.h> #include <xen/libelf.h> #include <xen/pfn.h> +#include <xen/srat.h> #include <asm/regs.h> #include <asm/system.h> #include <asm/io.h> diff --git a/xen/arch/x86/numa.c b/xen/arch/x86/numa.c index 28d1891..58de324 100644 --- a/xen/arch/x86/numa.c +++ b/xen/arch/x86/numa.c @@ -14,6 +14,7 @@ #include <xen/time.h> #include <xen/smp.h> #include <xen/pfn.h> +#include <xen/srat.h> #include <asm/acpi.h> #include <xen/sched.h> #include <xen/softirq.h> diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 5a49796..2184d62 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -9,6 +9,7 @@ #include <xen/guest_access.h> #include <xen/iocap.h> #include <xen/serial.h> +#include <xen/srat.h> #include <asm/current.h> #include <asm/io_apic.h> #include <asm/msi.h> diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 176ee74..ee7a368 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -28,6 +28,7 @@ #include <xen/tmem_xen.h> #include <xen/virtual_region.h> #include <xen/watchdog.h> +#include <xen/srat.h> #include <public/version.h> #include <compat/platform.h> #include <compat/xen.h> diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 9b390b8..6c61114 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -34,6 +34,7 @@ #include <xen/serial.h> #include <xen/numa.h> #include <xen/cpu.h> +#include <xen/srat.h> #include <asm/current.h> #include <asm/mc146818rtc.h> #include <asm/desc.h> diff --git a/xen/arch/x86/srat.c b/xen/arch/x86/srat.c index 58dee09..af12e26 100644 --- a/xen/arch/x86/srat.c +++ b/xen/arch/x86/srat.c @@ -18,91 +18,20 @@ #include <xen/acpi.h> #include <xen/numa.h> #include <xen/pfn.h> +#include <xen/srat.h> #include <asm/e820.h> #include <asm/page.h> -static struct acpi_table_slit *__read_mostly acpi_slit; +extern struct acpi_table_slit *__read_mostly acpi_slit; static nodemask_t memory_nodes_parsed __initdata; static nodemask_t processor_nodes_parsed __initdata; extern struct node nodes[MAX_NUMNODES] __initdata; - -struct pxm2node { - unsigned pxm; - nodeid_t node; -}; -static struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] = - { [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} }; - -static unsigned node_to_pxm(nodeid_t n); - extern int num_node_memblks; extern struct node node_memblk_range[NR_NODE_MEMBLKS]; extern nodeid_t memblk_nodeid[NR_NODE_MEMBLKS]; static __initdata DECLARE_BITMAP(memblk_hotplug, NR_NODE_MEMBLKS); -static inline bool_t node_found(unsigned idx, unsigned pxm) -{ - return ((pxm2node[idx].pxm == pxm) && - (pxm2node[idx].node != NUMA_NO_NODE)); -} - -nodeid_t pxm_to_node(unsigned pxm) -{ - unsigned i; - - if ((pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm)) - return pxm2node[pxm].node; - - for (i = 0; i < ARRAY_SIZE(pxm2node); i++) - if (node_found(i, pxm)) - return pxm2node[i].node; - - return NUMA_NO_NODE; -} - -nodeid_t setup_node(unsigned pxm) -{ - nodeid_t node; - unsigned idx; - static bool_t warned; - static unsigned nodes_found; - - BUILD_BUG_ON(MAX_NUMNODES >= NUMA_NO_NODE); - - if (pxm < ARRAY_SIZE(pxm2node)) { - if (node_found(pxm, pxm)) - return pxm2node[pxm].node; - - /* Try to maintain indexing of pxm2node by pxm */ - if (pxm2node[pxm].node == NUMA_NO_NODE) { - idx = pxm; - goto finish; - } - } - - for (idx = 0; idx < ARRAY_SIZE(pxm2node); idx++) - if (pxm2node[idx].node == NUMA_NO_NODE) - goto finish; - - if (!warned) { - printk(KERN_WARNING "SRAT: Too many proximity domains (%#x)\n", - pxm); - warned = 1; - } - - return NUMA_NO_NODE; - - finish: - node = nodes_found++; - if (node >= MAX_NUMNODES) - return NUMA_NO_NODE; - pxm2node[idx].pxm = pxm; - pxm2node[idx].node = node; - - return node; -} - static __init void bad_srat(void) { int i; @@ -115,48 +44,6 @@ static __init void bad_srat(void) mem_hotplug = 0; } -/* - * A lot of BIOS fill in 10 (= no distance) everywhere. This messes - * up the NUMA heuristics which wants the local node to have a smaller - * distance than the others. - * Do some quick checks here and only use the SLIT if it passes. - */ -static __init int slit_valid(struct acpi_table_slit *slit) -{ - int i, j; - int d = slit->locality_count; - for (i = 0; i < d; i++) { - for (j = 0; j < d; j++) { - u8 val = slit->entry[d*i + j]; - if (i == j) { - if (val != 10) - return 0; - } else if (val <= 10) - return 0; - } - } - return 1; -} - -/* Callback for SLIT parsing */ -void __init acpi_numa_slit_init(struct acpi_table_slit *slit) -{ - unsigned long mfn; - if (!slit_valid(slit)) { - printk(KERN_INFO "ACPI: SLIT table looks invalid. " - "Not used.\n"); - return; - } - mfn = alloc_boot_pages(PFN_UP(slit->header.length), 1); - if (!mfn) { - printk(KERN_ERR "ACPI: Unable to allocate memory for " - "saving ACPI SLIT numa information.\n"); - return; - } - acpi_slit = mfn_to_virt(mfn); - memcpy(acpi_slit, slit, slit->header.length); -} - /* Callback for Proximity Domain -> x2APIC mapping */ void __init acpi_numa_x2apic_affinity_init(const struct acpi_srat_x2apic_cpu_affinity *pa) @@ -456,18 +343,6 @@ int __init acpi_scan_nodes(u64 start, u64 end) return 0; } -static unsigned node_to_pxm(nodeid_t n) -{ - unsigned i; - - if ((n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n)) - return pxm2node[n].pxm; - for (i = 0; i < ARRAY_SIZE(pxm2node); i++) - if (pxm2node[i].node == n) - return pxm2node[i].pxm; - return 0; -} - u8 __node_distance(nodeid_t a, nodeid_t b) { unsigned index; diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index 9ead02e..f823fb3 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -27,6 +27,7 @@ asm(".file \"" __FILE__ "\""); #include <xen/guest_access.h> #include <xen/hypercall.h> #include <xen/mem_access.h> +#include <xen/srat.h> #include <asm/current.h> #include <asm/asm_defns.h> #include <asm/page.h> diff --git a/xen/common/Makefile b/xen/common/Makefile index c1bd2ff..a668094 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -64,6 +64,7 @@ obj-bin-y += warning.init.o obj-$(CONFIG_XENOPROF) += xenoprof.o obj-y += xmalloc_tlsf.o obj-y += numa.o +obj-y += srat.o obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) diff --git a/xen/common/srat.c b/xen/common/srat.c new file mode 100644 index 0000000..cf50c78 --- /dev/null +++ b/xen/common/srat.c @@ -0,0 +1,150 @@ +/* + * ACPI 3.0 based NUMA setup + * Copyright 2004 Andi Kleen, SuSE Labs. + * + * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. + * + * Called from acpi_numa_init while reading the SRAT and SLIT tables. + * Assumes all memory regions belonging to a single proximity domain + * are in one chunk. Holes between them will be included in the node. + * + * Adapted for Xen: Ryan Harper <ryanh@us.ibm.com> + * + * Moved this generic code from xen/arch/x86/srat.c for other arch usage + * by Vijaya Kumar K <Vijaya.Kumar@cavium.com> + */ + +#include <xen/init.h> +#include <xen/mm.h> +#include <xen/inttypes.h> +#include <xen/nodemask.h> +#include <xen/acpi.h> +#include <xen/numa.h> +#include <xen/pfn.h> +#include <xen/srat.h> +#include <asm/page.h> + +struct acpi_table_slit *__read_mostly acpi_slit; +extern struct node nodes[MAX_NUMNODES] __initdata; + +struct pxm2node __read_mostly pxm2node[MAX_NUMNODES] = + { [0 ... MAX_NUMNODES - 1] = {.node = NUMA_NO_NODE} }; + +static inline bool_t node_found(unsigned idx, unsigned pxm) +{ + return ((pxm2node[idx].pxm == pxm) && + (pxm2node[idx].node != NUMA_NO_NODE)); +} + +nodeid_t pxm_to_node(unsigned pxm) +{ + unsigned i; + + if ( (pxm < ARRAY_SIZE(pxm2node)) && node_found(pxm, pxm) ) + return pxm2node[pxm].node; + + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) + if ( node_found(i, pxm) ) + return pxm2node[i].node; + + return NUMA_NO_NODE; +} + +nodeid_t setup_node(unsigned pxm) +{ + nodeid_t node; + unsigned idx; + static bool_t warned; + static unsigned nodes_found; + + BUILD_BUG_ON(MAX_NUMNODES >= NUMA_NO_NODE); + + if ( pxm < ARRAY_SIZE(pxm2node) ) { + if (node_found(pxm, pxm)) + return pxm2node[pxm].node; + + /* Try to maintain indexing of pxm2node by pxm */ + if ( pxm2node[pxm].node == NUMA_NO_NODE ) { + idx = pxm; + goto finish; + } + } + + for ( idx = 0; idx < ARRAY_SIZE(pxm2node); idx++ ) + if ( pxm2node[idx].node == NUMA_NO_NODE ) + goto finish; + + if ( !warned ) { + printk(KERN_WARNING "SRAT: Too many proximity domains (%#x)\n", + pxm); + warned = 1; + } + + return NUMA_NO_NODE; + + finish: + node = nodes_found++; + if (node >= MAX_NUMNODES) + return NUMA_NO_NODE; + pxm2node[idx].pxm = pxm; + pxm2node[idx].node = node; + + return node; +} + +/* + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes + * up the NUMA heuristics which wants the local node to have a smaller + * distance than the others. + * Do some quick checks here and only use the SLIT if it passes. + */ +static __init int slit_valid(struct acpi_table_slit *slit) +{ + int i, j; + int d = slit->locality_count; + + for ( i = 0; i < d; i++ ) { + for ( j = 0; j < d; j++ ) { + u8 val = slit->entry[d*i + j]; + if ( i == j ) { + if (val != 10) + return 0; + } else if ( val <= 10 ) + return 0; + } + } + + return 1; +} + +/* Callback for SLIT parsing */ +void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +{ + unsigned long mfn; + + if ( !slit_valid(slit) ) { + printk(KERN_INFO "ACPI: SLIT table looks invalid. " + "Not used.\n"); + return; + } + mfn = alloc_boot_pages(PFN_UP(slit->header.length), 1); + if ( !mfn ) { + printk(KERN_ERR "ACPI: Unable to allocate memory for " + "saving ACPI SLIT numa information.\n"); + return; + } + acpi_slit = mfn_to_virt(mfn); + memcpy(acpi_slit, slit, slit->header.length); +} + +unsigned node_to_pxm(nodeid_t n) +{ + unsigned i; + + if ( (n < ARRAY_SIZE(pxm2node)) && (pxm2node[n].node == n) ) + return pxm2node[n].pxm; + for ( i = 0; i < ARRAY_SIZE(pxm2node); i++ ) + if ( pxm2node[i].node == n ) + return pxm2node[i].pxm; + return 0; +} diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index a5c61c6..7a4463d 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -30,6 +30,7 @@ #include <xen/pci.h> #include <xen/pci_regs.h> #include <xen/keyhandler.h> +#include <xen/srat.h> #include <asm/msi.h> #include <asm/irq.h> #include <asm/hvm/vmx/vmx.h> diff --git a/xen/include/asm-x86/numa.h b/xen/include/asm-x86/numa.h index 659ff6a..79a445c 100644 --- a/xen/include/asm-x86/numa.h +++ b/xen/include/asm-x86/numa.h @@ -17,8 +17,6 @@ extern cpumask_t node_to_cpumask[]; #define node_to_first_cpu(node) (__ffs(node_to_cpumask[node])) #define node_to_cpumask(node) (node_to_cpumask[node]) -extern nodeid_t pxm_to_node(unsigned int pxm); - #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) extern void numa_init_array(void); diff --git a/xen/include/xen/numa.h b/xen/include/xen/numa.h index 4f04ab4..eb18380 100644 --- a/xen/include/xen/numa.h +++ b/xen/include/xen/numa.h @@ -73,7 +73,6 @@ extern int valid_numa_range(u64 start, u64 end, nodeid_t node); extern int conflicting_memblks(u64 start, u64 end); extern void cutoff_node(int i, u64 start, u64 end); extern void numa_add_cpu(int cpu); -extern nodeid_t setup_node(unsigned int pxm); extern void numa_set_node(int cpu, nodeid_t node); extern void setup_node_bootmem(nodeid_t nodeid, u64 start, u64 end); extern int compute_hash_shift(struct node *nodes, int numnodes, diff --git a/xen/include/xen/srat.h b/xen/include/xen/srat.h new file mode 100644 index 0000000..978f1e8 --- /dev/null +++ b/xen/include/xen/srat.h @@ -0,0 +1,13 @@ +#ifndef __XEN_SRAT_H__ +#define __XEN_SRAT_H__ + +struct pxm2node { + unsigned pxm; + nodeid_t node; +}; + +extern struct pxm2node __read_mostly pxm2node[MAX_NUMNODES]; +nodeid_t pxm_to_node(unsigned pxm); +nodeid_t setup_node(unsigned pxm); +unsigned node_to_pxm(nodeid_t n); +#endif /* __XEN_SRAT_H__ */