diff --git a/sys/compat/linuxkpi/common/include/asm/processor.h b/sys/compat/linuxkpi/common/include/asm/processor.h --- a/sys/compat/linuxkpi/common/include/asm/processor.h +++ b/sys/compat/linuxkpi/common/include/asm/processor.h @@ -41,7 +41,7 @@ }; extern struct cpuinfo_x86 boot_cpu_data; -extern struct cpuinfo_x86 __cpu_data[]; +extern struct cpuinfo_x86 *__cpu_data; #define cpu_data(cpu) __cpu_data[cpu] #endif diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -131,7 +131,7 @@ static struct vm_area_struct *linux_cdev_handle_find(void *handle); cpumask_t cpu_online_mask; -static cpumask_t static_single_cpu_mask[MAXCPU]; +static cpumask_t **static_single_cpu_mask; struct kobject linux_class_root; struct device linux_root_device; struct class linux_class_misc; @@ -2759,17 +2759,17 @@ #if defined(__i386__) || defined(__amd64__) bool linux_cpu_has_clflush; struct cpuinfo_x86 boot_cpu_data; -struct cpuinfo_x86 __cpu_data[MAXCPU]; +struct cpuinfo_x86 *__cpu_data; #endif cpumask_t * lkpi_get_static_single_cpu_mask(int cpuid) { - KASSERT((cpuid >= 0 && cpuid < MAXCPU), ("%s: invalid cpuid %d\n", + KASSERT((cpuid >= 0 && cpuid <= mp_maxid), ("%s: invalid cpuid %d\n", __func__, cpuid)); - return (&static_single_cpu_mask[cpuid]); + return (static_single_cpu_mask[cpuid]); } static void @@ -2785,7 +2785,9 @@ boot_cpu_data.x86 = CPUID_TO_FAMILY(cpu_id); boot_cpu_data.x86_model = CPUID_TO_MODEL(cpu_id); - for (i = 0; i < MAXCPU; i++) { + __cpu_data = mallocarray(mp_maxid + 1, + sizeof(*__cpu_data), M_KMALLOC, M_WAITOK | M_ZERO); + for (i = 0; i < mp_maxid + 1; i++) { __cpu_data[i].x86_clflush_size = cpu_clflush_line_size; __cpu_data[i].x86_max_cores = mp_ncpus; __cpu_data[i].x86 = CPUID_TO_FAMILY(cpu_id); @@ -2820,13 +2822,51 @@ CPU_COPY(&all_cpus, &cpu_online_mask); /* * Generate a single-CPU cpumask_t for each CPU (possibly) in the system. - * CPUs are indexed from 0..(MAXCPU-1). The entry for cpuid 0 will only + * CPUs are indexed from 0..(mp_maxid). The entry for cpuid 0 will only * have itself in the cpumask, cupid 1 only itself on entry 1, and so on. + * If we have more than (2 * _BITSET_BITS) CPUs we do magic to save a lot + * of memory given the sets are static and we shift them out. * This is used by cpumask_of() (and possibly others in the future) for, * e.g., drivers to pass hints to irq_set_affinity_hint(). */ - for (i = 0; i < MAXCPU; i++) - CPU_SET(i, &static_single_cpu_mask[i]); + static_single_cpu_mask = mallocarray(mp_maxid + 1, + sizeof(static_single_cpu_mask), M_KMALLOC, M_WAITOK | M_ZERO); + if (mp_maxid < (2 * _BITSET_BITS)) { + cpumask_t *lcs; + + lcs = mallocarray(mp_maxid + 1, + sizeof(**static_single_cpu_mask), M_KMALLOC, M_WAITOK | M_ZERO); + for (i = 0; i < mp_maxid + 1; i++) { + static_single_cpu_mask[i] = lcs++; + CPU_SET(i, static_single_cpu_mask[i]); + } + } else { + cpumask_t *lcs, *cs; + + /* + * [[63..0]{n}[63..0]{n}] = { cpuset_t->__bits[], zeros } + * We double allocate (in theory one _BITSET_BITS too much). + */ + lcs = mallocarray(_BITSET_BITS, + 2 * sizeof(**static_single_cpu_mask), M_KMALLOC, M_WAITOK | M_ZERO); + /* + * Initialize the first static _BITSET_BITS sets, + * leaving an entire "__bits[]" empty after so we can shift. + */ + for (i = 0; i < _BITSET_BITS; i++) { + cs = lcs + (2 * i); + CPU_SET(i, cs); + } + /* + * Now shift the sets through every _BITSET_BITS until we have + * enough static sets for mp_maxid + 1. + */ + for (i = 0; i < mp_maxid + 1; i++) { + cs = lcs + ((i % _BITSET_BITS) * 2); + cs = (cpuset_t *)(&cs->__bits[0] - (i / _BITSET_BITS)); + static_single_cpu_mask[i] = cs; + } + } strlcpy(init_uts_ns.name.release, osrelease, sizeof(init_uts_ns.name.release)); } @@ -2839,6 +2879,12 @@ linux_kobject_kfree_name(&linux_root_device.kobj); linux_kobject_kfree_name(&linux_class_misc.kobj); + free(static_single_cpu_mask[0], M_KMALLOC); + free(static_single_cpu_mask, M_KMALLOC); +#if defined(__i386__) || defined(__amd64__) + free(__cpu_data, M_KMALLOC); +#endif + mtx_destroy(&vmmaplock); spin_lock_destroy(&pci_lock); rw_destroy(&linux_vma_lock);