#include "util.h" // dprintf
#include "config.h" // CONFIG_*
#include "mptable.h" // MPTABLE_SIGNATURE
-#include "paravirt.h"
-
-static inline unsigned long
-fls(unsigned long word)
-{
- asm("bsr %1,%0"
- : "=r" (word)
- : "rm" (word));
- return word + 1;
-}
+#include "paravirt.h" // qemu_cfg_irq0_override
void
mptable_init(void)
dprintf(3, "init MPTable\n");
+ // Allocate memory
int length = (sizeof(struct mptable_config_s)
+ sizeof(struct mpt_cpu) * MaxCountCPUs
+ sizeof(struct mpt_bus)
struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
if (!config || !floating) {
dprintf(1, "No room for MPTABLE!\n");
+ free(config);
+ free(floating);
return;
}
memcpy(config->productid, "0.1 ", sizeof(config->productid));
config->lapic = BUILD_APIC_ADDR;
- // CPU definitions.
+ // Detect cpu info
u32 cpuid_signature, ebx, ecx, cpuid_features;
cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
- struct mpt_cpu *cpus = (void*)&config[1];
- int i, actual_cpu_count;
- for (i = 0, actual_cpu_count = 0; i < MaxCountCPUs; i++) {
- struct mpt_cpu *cpu = &cpus[i];
- int log_cpus = (ebx >> 16) & 0xff;
- log_cpus = 1UL << fls(log_cpus - 1); /* round up to power of 2 */
-
- /* Only populate the MPS tables with the first logical CPU in each
- package */
- if ((cpuid_features & (1 << 28)) && (i & (log_cpus - 1)) != 0)
- continue;
-
- actual_cpu_count++;
+ int pkgcpus = 1;
+ if (cpuid_features & (1 << 28)) {
+ /* Only populate the MPS tables with the first logical CPU in
+ each package */
+ pkgcpus = (ebx >> 16) & 0xff;
+ pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */
+ }
+ // CPU definitions.
+ struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus;
+ int i;
+ for (i = 0; i < MaxCountCPUs; i+=pkgcpus) {
memset(cpu, 0, sizeof(*cpu));
cpu->type = MPT_TYPE_CPU;
cpu->apicid = i;
cpu->apicver = 0x11;
/* cpu flags: enabled, bootstrap cpu */
- if (i < CountCPUs)
- cpu->cpuflag = 1 | ((i == 0) ? 2 : 0);
- else
- cpu->cpuflag = 0;
+ cpu->cpuflag = (i < CountCPUs) | ((i == 0) << 1);
if (cpuid_signature) {
cpu->cpusignature = cpuid_signature;
cpu->featureflag = cpuid_features;
cpu->cpusignature = 0x600;
cpu->featureflag = 0x201;
}
+ cpu++;
}
-
- config->entrycount = actual_cpu_count + 2 + 16;
+ int entrycount = cpu - cpus;
/* isa bus */
- struct mpt_bus *bus = (void*)&cpus[actual_cpu_count];
+ struct mpt_bus *bus = (void*)cpu;
memset(bus, 0, sizeof(*bus));
bus->type = MPT_TYPE_BUS;
memcpy(bus->bustype, "ISA ", sizeof(bus->bustype));
+ entrycount++;
/* ioapic */
u8 ioapic_id = CountCPUs;
ioapic->apicver = 0x11;
ioapic->flags = 1; // enable
ioapic->apicaddr = BUILD_IOAPIC_ADDR;
+ entrycount++;
/* irqs */
- struct mpt_intsrc *intsrc = (void*)&ioapic[1];
+ struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs;
for (i = 0; i < 16; i++) {
memset(intsrc, 0, sizeof(*intsrc));
intsrc->type = MPT_TYPE_INTSRC;
}
intsrc++;
}
+ entrycount += intsrc - intsrcs;
- // Set checksum.
+ // Finalize config structure.
+ config->entrycount = entrycount;
config->length = (void*)intsrc - (void*)config;
config->checksum -= checksum(config, config->length);