x86: make the arrays that depend on MAX_APIC_ID dynamic
So that MAX_APIC_ID can be bumped without wasting memory. Note that the usage of MAX_APIC_ID in the SRAT parsing forces the parser to allocate memory directly from the phys_avail physical memory array, which is not the best approach probably, but I haven't found any other way to allocate memory so early in boot. This memory is not returned to the system afterwards, but at least it's sized according to the maximum APIC ID found in the MADT table. Sponsored by: Citrix Systems R&D MFC after: 1 month Reviewed by: kib Differential revision: https://reviews.freebsd.org/D11912
This commit is contained in:
parent
fd1f83fb45
commit
84525e55c1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=322348
@ -59,7 +59,7 @@ static struct {
|
||||
static struct lapic_info {
|
||||
u_int la_enabled;
|
||||
u_int la_acpi_id;
|
||||
} lapics[MAX_APIC_ID + 1];
|
||||
} *lapics;
|
||||
|
||||
int madt_found_sci_override;
|
||||
static ACPI_TABLE_MADT *madt;
|
||||
@ -141,8 +141,6 @@ madt_setup_local(void)
|
||||
int user_x2apic;
|
||||
bool bios_x2apic;
|
||||
|
||||
madt = pmap_mapbios(madt_physaddr, madt_length);
|
||||
madt_walk_table(madt_setup_cpus_handler, NULL);
|
||||
if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
|
||||
reason = NULL;
|
||||
|
||||
@ -214,6 +212,11 @@ madt_setup_local(void)
|
||||
}
|
||||
}
|
||||
|
||||
madt = pmap_mapbios(madt_physaddr, madt_length);
|
||||
lapics = malloc(sizeof(*lapics) * (max_apic_id + 1), M_MADT,
|
||||
M_WAITOK | M_ZERO);
|
||||
madt_walk_table(madt_setup_cpus_handler, NULL);
|
||||
|
||||
lapic_init(madt->Address);
|
||||
printf("ACPI APIC Table: <%.*s %.*s>\n",
|
||||
(int)sizeof(madt->Header.OemId), madt->Header.OemId,
|
||||
@ -236,6 +239,8 @@ madt_setup_io(void)
|
||||
u_int pin;
|
||||
int i;
|
||||
|
||||
KASSERT(lapics != NULL, ("local APICs not initialized"));
|
||||
|
||||
/* Try to initialize ACPI so that we can access the FADT. */
|
||||
i = acpi_Startup();
|
||||
if (ACPI_FAILURE(i)) {
|
||||
@ -282,6 +287,10 @@ madt_setup_io(void)
|
||||
free(ioapics, M_MADT);
|
||||
ioapics = NULL;
|
||||
|
||||
/* NB: this is the last use of the lapics array. */
|
||||
free(lapics, M_MADT);
|
||||
lapics = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -332,7 +341,7 @@ madt_add_cpu(u_int acpi_id, u_int apic_id, u_int flags)
|
||||
"enabled" : "disabled");
|
||||
if (!(flags & ACPI_MADT_ENABLED))
|
||||
return;
|
||||
if (apic_id > MAX_APIC_ID) {
|
||||
if (apic_id > max_apic_id) {
|
||||
printf("MADT: Ignoring local APIC ID %u (too high)\n",
|
||||
apic_id);
|
||||
return;
|
||||
@ -471,7 +480,7 @@ madt_find_cpu(u_int acpi_id, u_int *apic_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= MAX_APIC_ID; i++) {
|
||||
for (i = 0; i <= max_apic_id; i++) {
|
||||
if (!lapics[i].la_enabled)
|
||||
continue;
|
||||
if (lapics[i].la_acpi_id != acpi_id)
|
||||
@ -723,6 +732,9 @@ madt_set_ids(void *dummy)
|
||||
|
||||
if (madt == NULL)
|
||||
return;
|
||||
|
||||
KASSERT(lapics != NULL, ("local APICs not initialized"));
|
||||
|
||||
CPU_FOREACH(i) {
|
||||
pc = pcpu_find(i);
|
||||
KASSERT(pc != NULL, ("no pcpu data for CPU %u", i));
|
||||
|
@ -55,11 +55,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/acpica/acpivar.h>
|
||||
|
||||
#if MAXMEMDOM > 1
|
||||
struct cpu_info {
|
||||
static struct cpu_info {
|
||||
int enabled:1;
|
||||
int has_memory:1;
|
||||
int domain;
|
||||
} cpus[MAX_APIC_ID + 1];
|
||||
} *cpus;
|
||||
|
||||
struct mem_affinity mem_info[VM_PHYSSEG_MAX + 1];
|
||||
int num_mem;
|
||||
@ -204,7 +204,7 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg)
|
||||
"enabled" : "disabled");
|
||||
if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED))
|
||||
break;
|
||||
if (cpu->ApicId > MAX_APIC_ID) {
|
||||
if (cpu->ApicId > max_apic_id) {
|
||||
printf("SRAT: Ignoring local APIC ID %u (too high)\n",
|
||||
cpu->ApicId);
|
||||
break;
|
||||
@ -228,7 +228,7 @@ srat_parse_entry(ACPI_SUBTABLE_HEADER *entry, void *arg)
|
||||
"enabled" : "disabled");
|
||||
if (!(x2apic->Flags & ACPI_SRAT_CPU_ENABLED))
|
||||
break;
|
||||
if (x2apic->ApicId > MAX_APIC_ID) {
|
||||
if (x2apic->ApicId > max_apic_id) {
|
||||
printf("SRAT: Ignoring local APIC ID %u (too high)\n",
|
||||
x2apic->ApicId);
|
||||
break;
|
||||
@ -294,7 +294,7 @@ check_domains(void)
|
||||
|
||||
for (i = 0; i < num_mem; i++) {
|
||||
found = 0;
|
||||
for (j = 0; j <= MAX_APIC_ID; j++)
|
||||
for (j = 0; j <= max_apic_id; j++)
|
||||
if (cpus[j].enabled &&
|
||||
cpus[j].domain == mem_info[i].domain) {
|
||||
cpus[j].has_memory = 1;
|
||||
@ -306,7 +306,7 @@ check_domains(void)
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= MAX_APIC_ID; i++)
|
||||
for (i = 0; i <= max_apic_id; i++)
|
||||
if (cpus[i].enabled && !cpus[i].has_memory) {
|
||||
printf("SRAT: No memory found for CPU %d\n", i);
|
||||
return (ENXIO);
|
||||
@ -401,7 +401,7 @@ renumber_domains(void)
|
||||
for (j = 0; j < num_mem; j++)
|
||||
if (mem_info[j].domain == domain_pxm[i])
|
||||
mem_info[j].domain = i;
|
||||
for (j = 0; j <= MAX_APIC_ID; j++)
|
||||
for (j = 0; j <= max_apic_id; j++)
|
||||
if (cpus[j].enabled && cpus[j].domain == domain_pxm[i])
|
||||
cpus[j].domain = i;
|
||||
}
|
||||
@ -415,6 +415,8 @@ renumber_domains(void)
|
||||
static int
|
||||
parse_srat(void)
|
||||
{
|
||||
unsigned int idx, size;
|
||||
vm_paddr_t addr;
|
||||
int error;
|
||||
|
||||
if (resource_disabled("srat", 0))
|
||||
@ -424,6 +426,25 @@ parse_srat(void)
|
||||
if (srat_physaddr == 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Allocate data structure:
|
||||
*
|
||||
* Find the last physical memory region and steal some memory from
|
||||
* it. This is done because at this point in the boot process
|
||||
* malloc is still not usable.
|
||||
*/
|
||||
for (idx = 0; phys_avail[idx + 1] != 0; idx += 2);
|
||||
KASSERT(idx != 0, ("phys_avail is empty!"));
|
||||
idx -= 2;
|
||||
|
||||
size = sizeof(*cpus) * (max_apic_id + 1);
|
||||
addr = trunc_page(phys_avail[idx + 1] - size);
|
||||
KASSERT(addr >= phys_avail[idx],
|
||||
("Not enough memory for SRAT table items"));
|
||||
phys_avail[idx + 1] = addr - 1;
|
||||
|
||||
cpus = (struct cpu_info *)PHYS_TO_DMAP(addr);
|
||||
|
||||
/*
|
||||
* Make a pass over the table to populate the cpus[] and
|
||||
* mem_info[] tables.
|
||||
|
@ -182,7 +182,7 @@ inthand_t
|
||||
IDTVEC(spuriousint), IDTVEC(timerint);
|
||||
|
||||
extern vm_paddr_t lapic_paddr;
|
||||
extern int apic_cpuids[];
|
||||
extern int *apic_cpuids;
|
||||
|
||||
void apic_register_enumerator(struct apic_enumerator *enumerator);
|
||||
void *ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase);
|
||||
|
@ -54,7 +54,7 @@ struct cpu_info {
|
||||
int cpu_disabled:1;
|
||||
int cpu_hyperthread:1;
|
||||
};
|
||||
extern struct cpu_info cpu_info[];
|
||||
extern struct cpu_info *cpu_info;
|
||||
|
||||
#ifdef COUNT_IPIS
|
||||
extern u_long *ipi_invltlb_counts[MAXCPU];
|
||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/proc.h>
|
||||
@ -83,6 +84,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define GSEL_APIC GSEL(GCODE_SEL, SEL_KPL)
|
||||
#endif
|
||||
|
||||
static MALLOC_DEFINE(M_LAPIC, "local_apic", "Local APIC items");
|
||||
|
||||
/* Sanity checks on IDT vectors. */
|
||||
CTASSERT(APIC_IO_INTS + APIC_NUM_IOINTS == APIC_TIMER_INT);
|
||||
CTASSERT(APIC_TIMER_INT < APIC_LOCAL_INTS);
|
||||
@ -134,7 +137,7 @@ struct lapic {
|
||||
uint32_t lvt_timer_last;
|
||||
/* Include IDT_SYSCALL to make indexing easier. */
|
||||
int la_ioint_irqs[APIC_NUM_IOINTS + 1];
|
||||
} static lapics[MAX_APIC_ID + 1];
|
||||
} static *lapics;
|
||||
|
||||
/* Global defaults for local APIC LVT entries. */
|
||||
static struct lvt lvts[APIC_LVT_MAX + 1] = {
|
||||
@ -601,7 +604,7 @@ native_lapic_create(u_int apic_id, int boot_cpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (apic_id > MAX_APIC_ID) {
|
||||
if (apic_id > max_apic_id) {
|
||||
printf("APIC: Ignoring local APIC with ID %d\n", apic_id);
|
||||
if (boot_cpu)
|
||||
panic("Can't ignore BSP");
|
||||
@ -1661,7 +1664,7 @@ DB_SHOW_COMMAND(apic, db_show_apic)
|
||||
verbose = 1;
|
||||
else
|
||||
verbose = 0;
|
||||
for (apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) {
|
||||
for (apic_id = 0; apic_id <= max_apic_id; apic_id++) {
|
||||
if (lapics[apic_id].la_present == 0)
|
||||
continue;
|
||||
db_printf("Interrupts bound to lapic %u\n", apic_id);
|
||||
@ -1862,6 +1865,9 @@ apic_setup_local(void *dummy __unused)
|
||||
if (best_enum == NULL)
|
||||
return;
|
||||
|
||||
lapics = malloc(sizeof(*lapics) * (max_apic_id + 1), M_LAPIC,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
/* Initialize the local APIC. */
|
||||
retval = best_enum->apic_setup_local();
|
||||
if (retval != 0)
|
||||
|
@ -84,6 +84,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define BIOS_RESET (0x0f)
|
||||
#define BIOS_WARM (0x0a)
|
||||
|
||||
static MALLOC_DEFINE(M_CPUS, "cpus", "CPU items");
|
||||
|
||||
/* lock region used by kernel profiling */
|
||||
int mcount_lock;
|
||||
|
||||
@ -132,8 +134,8 @@ volatile int aps_ready = 0;
|
||||
* Store data from cpu_add() until later in the boot when we actually setup
|
||||
* the APs.
|
||||
*/
|
||||
struct cpu_info cpu_info[MAX_APIC_ID + 1];
|
||||
int apic_cpuids[MAX_APIC_ID + 1];
|
||||
struct cpu_info *cpu_info;
|
||||
int *apic_cpuids;
|
||||
int cpu_apic_ids[MAXCPU];
|
||||
|
||||
/* Holds pending bitmap based IPIs per CPU */
|
||||
@ -546,7 +548,7 @@ topo_probe(void)
|
||||
nlayers++;
|
||||
|
||||
topo_init_root(&topo_root);
|
||||
for (i = 0; i <= MAX_APIC_ID; ++i) {
|
||||
for (i = 0; i <= max_apic_id; ++i) {
|
||||
if (!cpu_info[i].cpu_present)
|
||||
continue;
|
||||
|
||||
@ -803,6 +805,19 @@ cpu_topo(void)
|
||||
return (cg_root);
|
||||
}
|
||||
|
||||
static void
|
||||
cpu_alloc(void *dummy __unused)
|
||||
{
|
||||
/*
|
||||
* Dynamically allocate the arrays that depend on the
|
||||
* maximum APIC ID.
|
||||
*/
|
||||
cpu_info = malloc(sizeof(*cpu_info) * (max_apic_id + 1), M_CPUS,
|
||||
M_WAITOK | M_ZERO);
|
||||
apic_cpuids = malloc(sizeof(*apic_cpuids) * (max_apic_id + 1), M_CPUS,
|
||||
M_WAITOK | M_ZERO);
|
||||
}
|
||||
SYSINIT(cpu_alloc, SI_SUB_CPU, SI_ORDER_FIRST, cpu_alloc, NULL);
|
||||
|
||||
/*
|
||||
* Add a logical CPU to the topology.
|
||||
@ -811,7 +826,7 @@ void
|
||||
cpu_add(u_int apic_id, char boot_cpu)
|
||||
{
|
||||
|
||||
if (apic_id > MAX_APIC_ID) {
|
||||
if (apic_id > max_apic_id) {
|
||||
panic("SMP: APIC ID %d too high", apic_id);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user