linux_dsm_epyc7002/arch/x86/kernel
Gu Zheng f7c28833c2 x86/acpi: Enable acpi to register all possible cpus at boot time
cpuid <-> nodeid mapping is firstly established at boot time. And workqueue caches
the mapping in wq_numa_possible_cpumask in wq_numa_init() at boot time.

When doing node online/offline, cpuid <-> nodeid mapping is established/destroyed,
which means, cpuid <-> nodeid mapping will change if node hotplug happens. But
workqueue does not update wq_numa_possible_cpumask.

So here is the problem:

Assume we have the following cpuid <-> nodeid in the beginning:

  Node | CPU

------------------------
node 0 |  0-14, 60-74
node 1 | 15-29, 75-89
node 2 | 30-44, 90-104
node 3 | 45-59, 105-119

and we hot-remove node2 and node3, it becomes:

  Node | CPU
------------------------
node 0 |  0-14, 60-74
node 1 | 15-29, 75-89

and we hot-add node4 and node5, it becomes:

  Node | CPU
------------------------
node 0 |  0-14, 60-74
node 1 | 15-29, 75-89
node 4 | 30-59
node 5 | 90-119

But in wq_numa_possible_cpumask, cpu30 is still mapped to node2, and the like.

When a pool workqueue is initialized, if its cpumask belongs to a node, its
pool->node will be mapped to that node. And memory used by this workqueue will
also be allocated on that node.

static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs){
...
        /* if cpumask is contained inside a NUMA node, we belong to that node */
        if (wq_numa_enabled) {
                for_each_node(node) {
                        if (cpumask_subset(pool->attrs->cpumask,
                                           wq_numa_possible_cpumask[node])) {
                                pool->node = node;
                                break;
                        }
                }
        }

Since wq_numa_possible_cpumask is not updated, it could be mapped to an offline node,
which will lead to memory allocation failure:

 SLUB: Unable to allocate memory on node 2 (gfp=0x80d0)
  cache: kmalloc-192, object size: 192, buffer size: 192, default order: 1, min order: 0
  node 0: slabs: 6172, objs: 259224, free: 245741
  node 1: slabs: 3261, objs: 136962, free: 127656

It happens here:

create_worker(struct worker_pool *pool)
 |--> worker = alloc_worker(pool->node);

static struct worker *alloc_worker(int node)
{
        struct worker *worker;

        worker = kzalloc_node(sizeof(*worker), GFP_KERNEL, node); --> Here, useing the wrong node.

        ......

        return worker;
}

[Solution]

There are four mappings in the kernel:
1. nodeid (logical node id)   <->   pxm
2. apicid (physical cpu id)   <->   nodeid
3. cpuid (logical cpu id)     <->   apicid
4. cpuid (logical cpu id)     <->   nodeid

1. pxm (proximity domain) is provided by ACPI firmware in SRAT, and nodeid <-> pxm
   mapping is setup at boot time. This mapping is persistent, won't change.

2. apicid <-> nodeid mapping is setup using info in 1. The mapping is setup at boot
   time and CPU hotadd time, and cleared at CPU hotremove time. This mapping is also
   persistent.

3. cpuid <-> apicid mapping is setup at boot time and CPU hotadd time. cpuid is
   allocated, lower ids first, and released at CPU hotremove time, reused for other
   hotadded CPUs. So this mapping is not persistent.

4. cpuid <-> nodeid mapping is also setup at boot time and CPU hotadd time, and
   cleared at CPU hotremove time. As a result of 3, this mapping is not persistent.

To fix this problem, we establish cpuid <-> nodeid mapping for all the possible
cpus at boot time, and make it persistent. And according to init_cpu_to_node(),
cpuid <-> nodeid mapping is based on apicid <-> nodeid mapping and cpuid <-> apicid
mapping. So the key point is obtaining all cpus' apicid.

apicid can be obtained by _MAT (Multiple APIC Table Entry) method or found in
MADT (Multiple APIC Description Table). So we finish the job in the following steps:

1. Enable apic registeration flow to handle both enabled and disabled cpus.
   This is done by introducing an extra parameter to generic_processor_info to let the
   caller control if disabled cpus are ignored.

2. Introduce a new array storing all possible cpuid <-> apicid mapping. And also modify
   the way cpuid is calculated. Establish all possible cpuid <-> apicid mapping when
   registering local apic. Store the mapping in this array.

3. Enable _MAT and MADT relative apis to return non-present or disabled cpus' apicid.
   This is also done by introducing an extra parameter to these apis to let the caller
   control if disabled cpus are ignored.

4. Establish all possible cpuid <-> nodeid mapping.
   This is done via an additional acpi namespace walk for processors.

This patch finished step 1.

Signed-off-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Signed-off-by: Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
Cc: mika.j.penttila@gmail.com
Cc: len.brown@intel.com
Cc: rafael@kernel.org
Cc: rjw@rjwysocki.net
Cc: yasu.isimatu@gmail.com
Cc: linux-mm@kvack.org
Cc: linux-acpi@vger.kernel.org
Cc: isimatu.yasuaki@jp.fujitsu.com
Cc: gongzhaogang@inspur.com
Cc: tj@kernel.org
Cc: izumi.taku@jp.fujitsu.com
Cc: cl@linux.com
Cc: chen.tang@easystack.cn
Cc: akpm@linux-foundation.org
Cc: kamezawa.hiroyu@jp.fujitsu.com
Cc: lenb@kernel.org
Link: http://lkml.kernel.org/r/1472114120-3281-3-git-send-email-douly.fnst@cn.fujitsu.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2016-09-21 21:18:38 +02:00
..
acpi x86/apic: Get rid of apic_version[] array 2016-09-20 00:31:19 +02:00
apic x86/acpi: Enable acpi to register all possible cpus at boot time 2016-09-21 21:18:38 +02:00
cpu Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
fpu x86/mm/pkeys: Fix compact mode by removing protection keys' XSAVE buffer manipulation 2016-08-10 16:12:26 +02:00
kprobes kprobes/x86: Clear TF bit in fault on single-stepping 2016-06-14 12:00:54 +02:00
.gitignore
alternative.c x86/asm: Stop depending on ptrace.h in alternative.h 2016-04-29 11:56:40 +02:00
amd_gart_64.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
amd_nb.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
apb_timer.c x86/apb_timer: Convert to hotplug state machine 2016-07-15 10:40:22 +02:00
aperture_64.c param: convert some "on"/"off" users to strtobool 2016-03-17 15:09:34 -07:00
apm_32.c x86/apm32: Remove paravirt_enabled() use 2016-04-22 10:29:03 +02:00
asm-offsets_32.c x86/entry/32: Simplify and fix up the SYSENTER stack #DB/NMI fixup 2016-03-10 09:48:14 +01:00
asm-offsets_64.c x86/syscalls: Add syscall entry qualifiers 2016-01-29 09:46:38 +01:00
asm-offsets.c x86/uaccess: Move thread_info::addr_limit to thread_struct 2016-07-15 10:26:30 +02:00
audit_64.c
bootflag.c
check.c
cpuid.c
crash_dump_32.c
crash_dump_64.c
crash.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
devicetree.c x86/cpufeature: Replace cpu_has_apic with boot_cpu_has() usage 2016-04-13 11:37:41 +02:00
doublefault.c
dumpstack_32.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
dumpstack_64.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
dumpstack.c Merge branch 'x86-debug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-07-25 18:18:04 -07:00
e820.c Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-03-15 09:32:27 -07:00
early_printk.c x86: Fix misspellings in comments 2016-02-24 08:44:58 +01:00
early-quirks.c Linux 4.7 2016-07-26 17:26:29 +10:00
ebda.c x86/boot: Simplify EBDA-vs-BIOS reservation logic 2016-07-22 11:46:01 +02:00
espfix_64.c x86: get rid of superfluous __GFP_REPEAT 2016-06-24 17:23:52 -07:00
ftrace.c Nothing major this round. Mostly small clean ups and fixes. 2016-03-24 10:52:25 -07:00
head32.c x86/boot: Run reserve_bios_regions() after we initialize the memory map 2016-08-11 11:14:59 +02:00
head64.c x86/boot: Run reserve_bios_regions() after we initialize the memory map 2016-08-11 11:14:59 +02:00
head_32.S Merge branch 'x86/urgent' into x86/asm, to refresh the tree 2016-04-29 11:55:04 +02:00
head_64.S x86/mm: Enable KASLR for physical mapping memory regions 2016-07-08 17:35:15 +02:00
hpet.c x86/hpet: Fix /dev/rtc breakage caused by RTC cleanup 2016-08-10 14:37:06 +02:00
hw_breakpoint.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
i386_ksyms_32.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
i8237.c
i8253.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
i8259.c
io_delay.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
ioport.c x86/iopl: Fix iopl capability check on Xen PV 2016-03-17 09:49:27 +01:00
irq_32.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
irq_64.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
irq_work.c
irq.c x86/irq: Do not substract irq_tlb_count from irq_call_count 2016-08-11 11:14:59 +02:00
irqinit.c
jump_label.c x86/asm: Stop depending on ptrace.h in alternative.h 2016-04-29 11:56:40 +02:00
kdebugfs.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
kexec-bzimage64.c KEYS: Generalise system_verify_data() to provide access to internal content 2016-04-06 16:14:24 +01:00
kgdb.c x86/asm: Stop depending on ptrace.h in alternative.h 2016-04-29 11:56:40 +02:00
ksysfs.c
kvm.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
kvmclock.c x86: Fix misspellings in comments 2016-02-24 08:44:58 +01:00
ldt.c x86/mm: Factor out LDT init from context init 2016-02-18 19:46:31 +01:00
machine_kexec_32.c
machine_kexec_64.c kexec: provide arch_kexec_protect(unprotect)_crashkres() 2016-05-23 17:04:14 -07:00
Makefile Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching 2016-05-17 17:11:27 -07:00
mcount_64.S ftrace/x86: Set ftrace_stub to weak to prevent gcc from using short jumps to it 2016-05-20 13:28:40 -04:00
mmconf-fam10h_64.c
module.c x86/asm: Stop depending on ptrace.h in alternative.h 2016-04-29 11:56:40 +02:00
mpparse.c x86/mm/numa: Open code function early_get_boot_cpu_id() 2016-08-15 08:51:54 +02:00
msr.c x86/cpufeature: Carve out X86_FEATURE_* 2016-01-30 11:22:17 +01:00
nmi_selftest.c
nmi.c x86: include linux/ratelimit.h in nmi.c 2016-06-06 17:10:15 +02:00
paravirt_patch_32.c
paravirt_patch_64.c
paravirt-spinlocks.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
paravirt.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
pci-calgary_64.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
pci-dma.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
pci-iommu_table.c x86: Fix non-static inlines 2016-04-16 13:21:40 +02:00
pci-nommu.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
pci-swiotlb.c dma-mapping: use unsigned long for dma_attrs 2016-08-04 08:50:07 -04:00
pcspeaker.c
perf_regs.c
platform-quirks.c x86/boot: Reorganize and clean up the BIOS area reservation code 2016-07-21 10:11:57 +02:00
pmem.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
probe_roms.c
process_32.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
process_64.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
process.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
ptrace.c x86/ptrace: Stop setting TS_COMPAT in ptrace code 2016-07-27 11:09:43 +02:00
pvclock.c pvclock: introduce seqcount-like API 2016-08-04 13:52:21 +02:00
quirks.c
reboot_fixups_32.c
reboot.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
relocate_kernel_32.S
relocate_kernel_64.S
resource.c
rtc.c char/genrtc: x86: remove remnants of asm/rtc.h 2016-06-04 00:20:07 +02:00
setup_percpu.c x86/acpi: store ACPI ids from MADT for future usage 2016-07-25 13:30:53 +01:00
setup.c x86/mm/numa: Open code function early_get_boot_cpu_id() 2016-08-15 08:51:54 +02:00
signal_compat.c x86/signals: Add build-time checks to the siginfo compat code 2016-06-14 12:19:24 +02:00
signal.c Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-06 09:04:35 -04:00
smp.c
smpboot.c x86/apic: Get rid of apic_version[] array 2016-09-20 00:31:19 +02:00
stacktrace.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
step.c
sys_x86_64.c
sysfb_efi.c Merge branch 'linus' into efi/core, to pick up fixes 2016-05-07 07:00:07 +02:00
sysfb_simplefb.c
sysfb.c
tboot.c x86/tboot: Convert to hotplug state machine 2016-07-15 10:40:30 +02:00
tce_64.c x86/cpufeature: Remove cpu_has_clflush 2016-03-31 13:35:09 +02:00
test_nx.c x86/mm: Always enable CONFIG_DEBUG_RODATA and remove the Kconfig option 2016-02-22 08:51:38 +01:00
test_rodata.c x86: Don't use module.h just for AUTHOR / LICENSE tags 2016-07-14 13:04:20 +02:00
time.c
tls.c x86/tls: Synchronize segment registers in set_thread_area() 2016-04-29 11:56:42 +02:00
tls.h
topology.c
trace_clock.c
tracepoint.c
traps.c x86/kernel: Audit and remove any unnecessary uses of module.h 2016-07-14 15:06:41 +02:00
tsc_msr.c x86/tsc_msr: Remove irqoff around MSR-based TSC enumeration 2016-07-11 21:30:12 +02:00
tsc_sync.c
tsc.c Merge branch 'linus' into timers/urgent, to pick up fixes 2016-08-10 14:36:23 +02:00
uprobes.c uprobes/x86: Fix RIP-relative handling of EVEX-encoded instructions 2016-08-12 08:29:24 +02:00
verify_cpu.S x86/cpufeature: Carve out X86_FEATURE_* 2016-01-30 11:22:17 +01:00
vm86_32.c x86, bitops: remove use of "sbb" to return CF 2016-06-08 12:41:20 -07:00
vmlinux.lds.S x86/boot: Move compressed kernel to the end of the decompression buffer 2016-04-29 11:03:29 +02:00
vsmp_64.c
x86_init.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00
x8664_ksyms_64.c Merge branch 'x86-headers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-08-01 14:23:42 -04:00