diff --git a/base/usr/include/kernel/process.h b/base/usr/include/kernel/process.h index 92861fd..90a7a1f 100644 --- a/base/usr/include/kernel/process.h +++ b/base/usr/include/kernel/process.h @@ -155,10 +155,16 @@ struct ProcessorLocal { union PML * current_pml; #ifdef __x86_64__ int lapic_id; + /* Processor information loaded at startup. */ + int cpu_model; + int cpu_family; + char cpu_model_name[48]; + const char * cpu_manufacturer; #endif }; extern struct ProcessorLocal processor_local_data[32]; +extern int processor_count; /** * @brief Core-local kernel data. diff --git a/kernel/arch/x86_64/acpi.c b/kernel/arch/x86_64/acpi.c index 67d10d2..38e5bd8 100644 --- a/kernel/arch/x86_64/acpi.c +++ b/kernel/arch/x86_64/acpi.c @@ -3,10 +3,13 @@ #include #include #include +#include #include #include -void __ap_bootstrap(void) { +__attribute__((used)) +__attribute__((naked)) +static void __ap_bootstrap(void) { asm volatile ( ".code16\n" ".org 0x0\n" @@ -77,6 +80,7 @@ extern union PML init_page_region[]; uintptr_t _ap_stack_base = 0; static volatile int _ap_startup_flag = 0; +void load_processor_info(void); /* For timing delays on IPIs */ static inline uint64_t read_tsc(void) { @@ -92,12 +96,14 @@ static void short_delay(unsigned long amount) { static volatile int _ap_current = 0; +#define cpuid(in,a,b,c,d) do { asm volatile ("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(in)); } while(0) + /* C entrypoint for APs */ void ap_main(void) { arch_set_core_base((uintptr_t)&processor_local_data[_ap_current]); - uint32_t ebx; - asm volatile ("cpuid" : "=b"(ebx) : "a"(0x1) : "ecx", "edx", "memory"); + uint32_t ebx, _unused; + cpuid(0x1,_unused,ebx,_unused,_unused); if (this_core->lapic_id != (int)(ebx >> 24)) { printf("acpi: lapic id does not match\n"); } @@ -115,12 +121,46 @@ void ap_main(void) { this_core->kernel_idle_task = spawn_kidle(0); this_core->current_process = this_core->kernel_idle_task; + load_processor_info(); + /* Inform BSP it can continue. */ _ap_startup_flag = 1; switch_next(); } +void load_processor_info(void) { + unsigned long a, b, unused; + cpuid(0,unused,b,unused,unused); + + this_core->cpu_manufacturer = "Unknown"; + + if (b == 0x756e6547) { + cpuid(1, a, b, unused, unused); + this_core->cpu_manufacturer = "Intel"; + this_core->cpu_model = (a >> 4) & 0x0F; + this_core->cpu_family = (a >> 8) & 0x0F; + } else if (b == 0x68747541) { + cpuid(1, a, unused, unused, unused); + this_core->cpu_manufacturer = "AMD"; + this_core->cpu_model = (a >> 4) & 0x0F; + this_core->cpu_family = (a >> 8) & 0x0F; + } + + snprintf(processor_local_data[this_core->cpu_id].cpu_model_name, 20, "(unknown)"); + + /* See if we can get a long manufacturer strings */ + cpuid(0x80000000, a, unused, unused, unused); + if (a >= 0x80000004) { + uint32_t brand[12]; + cpuid(0x80000002, brand[0], brand[1], brand[2], brand[3]); + cpuid(0x80000003, brand[4], brand[5], brand[6], brand[7]); + cpuid(0x80000004, brand[8], brand[9], brand[10], brand[11]); + memcpy(processor_local_data[this_core->cpu_id].cpu_model_name, brand, 48); + } +} + + uintptr_t lapic_final = 0; void lapic_send_ipi(int i, uint32_t val) { *((volatile uint32_t*)(lapic_final + 0x310)) = (i << 24); @@ -147,6 +187,8 @@ void acpi_initialize(void) { } } + load_processor_info(); + if (!good) { printf("acpi: No RSD PTR found\n"); return; @@ -163,6 +205,10 @@ void acpi_initialize(void) { return; /* bad checksum */ } + /* Load information for the current CPU. */ + + if (args_present("nosmp")) return; + struct rsdt * rsdt = mmu_map_from_physical(rsdp->rsdt_address); int cores = 0; @@ -196,6 +242,8 @@ void acpi_initialize(void) { return; } + processor_count = cores; + /* Allocate a virtual address with which we can poke the lapic */ lapic_final = (uintptr_t)mmu_map_mmio_region(lapic_base, 0x1000); diff --git a/kernel/arch/x86_64/main.c b/kernel/arch/x86_64/main.c index 10154a6..54bd93a 100644 --- a/kernel/arch/x86_64/main.c +++ b/kernel/arch/x86_64/main.c @@ -281,10 +281,7 @@ int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) { framebuffer_initialize(); fbterm_initialize(); - /* Allow SMP to disabled with an arg */ - if (!args_present("nosmp")) { - acpi_initialize(); - } + acpi_initialize(); /* Decompress and mount all initial ramdisks. */ mount_multiboot_ramdisks(mboot); diff --git a/kernel/sys/process.c b/kernel/sys/process.c index 79df72d..8bf7901 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -46,6 +46,7 @@ list_t * process_queue; /* Scheduler ready queue. This the round-robin source. T list_t * sleep_queue; /* Ordered list of processes waiting to be awoken by timeouts. The head is the earliest thread to awaken. */ struct ProcessorLocal processor_local_data[32] = {0}; +int processor_count = 1; /* The following locks protect access to the process tree, scheduler queue, * sleeping, and the very special wait queue... */ diff --git a/kernel/vfs/procfs.c b/kernel/vfs/procfs.c index f5298df..1cb9ba6 100644 --- a/kernel/vfs/procfs.c +++ b/kernel/vfs/procfs.c @@ -250,51 +250,31 @@ static fs_node_t * procfs_procdir_create(process_t * process) { return fnode; } -#define cpuid(in,a,b,c,d) do { asm volatile ("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(in)); } while(0) - static uint64_t cpuinfo_func(fs_node_t *node, uint64_t offset, uint64_t size, uint8_t *buffer) { - char buf[1024]; - - unsigned long a, b, unused;; - cpuid(0,unused,b,unused,unused); - - const char * _manu = "Unknown"; - int _model = 0, _family = 0; - - if (b == 0x756e6547) { - cpuid(1, a, b, unused, unused); - _manu = "Intel"; - _model = (a >> 4) & 0x0F; - _family = (a >> 8) & 0x0F; - } else if (b == 0x68747541) { - cpuid(1, a, unused, unused, unused); - _manu = "AMD"; - _model = (a >> 4) & 0x0F; - _family = (a >> 8) & 0x0F; - } + char buf[4096]; + size_t _bsize = 0; - char model_name[48] = "(unknown)"; - - /* See if we can get a long manufacturer strings */ - cpuid(0x80000000, a, unused, unused, unused); - if (a >= 0x80000004) { - uint32_t brand[12]; - cpuid(0x80000002, brand[0], brand[1], brand[2], brand[3]); - cpuid(0x80000003, brand[4], brand[5], brand[6], brand[7]); - cpuid(0x80000004, brand[8], brand[9], brand[10], brand[11]); - - memcpy(model_name, brand, 48); +#ifdef __x86_64__ + for (int i = 0; i < processor_count; ++i) { + _bsize += snprintf(buf + _bsize, 1000, + "Processor: %d\n" + "Manufacturer: %s\n" + "MHz: %zd\n" + "Family: %d\n" + "Model: %d\n" + "Model name: %s\n" + "LAPIC id: %d\n" + "\n", + processor_local_data[i].cpu_id, + processor_local_data[i].cpu_manufacturer, + arch_cpu_mhz(), /* TODO Should this be per-cpu? */ + processor_local_data[i].cpu_family, + processor_local_data[i].cpu_model, + processor_local_data[i].cpu_model_name, + processor_local_data[i].lapic_id + ); } - - size_t _mhz = arch_cpu_mhz(); - - size_t _bsize = snprintf(buf, 1000, - "Manufacturer: %s\n" - "MHz: %zd\n" - "Family: %d\n" - "Model: %d\n" - "Model name: %s\n" - , _manu, _mhz, _family, _model, model_name); +#endif if (offset > _bsize) return 0; if (size > _bsize - offset) size = _bsize - offset;