Skip to content
This repository has been archived by the owner on May 31, 2021. It is now read-only.

Commit

Permalink
Collect per-core data for /proc/cpuinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
klange committed May 27, 2021
1 parent ccbd8fd commit ae0c5ca
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 49 deletions.
6 changes: 6 additions & 0 deletions base/usr/include/kernel/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
54 changes: 51 additions & 3 deletions kernel/arch/x86_64/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
#include <kernel/process.h>
#include <kernel/printf.h>
#include <kernel/misc.h>
#include <kernel/args.h>
#include <kernel/arch/x86_64/acpi.h>
#include <kernel/arch/x86_64/mmu.h>

void __ap_bootstrap(void) {
__attribute__((used))
__attribute__((naked))
static void __ap_bootstrap(void) {
asm volatile (
".code16\n"
".org 0x0\n"
Expand Down Expand Up @@ -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) {
Expand All @@ -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");
}
Expand All @@ -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);
Expand All @@ -147,6 +187,8 @@ void acpi_initialize(void) {
}
}

load_processor_info();

if (!good) {
printf("acpi: No RSD PTR found\n");
return;
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
5 changes: 1 addition & 4 deletions kernel/arch/x86_64/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions kernel/sys/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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... */
Expand Down
64 changes: 22 additions & 42 deletions kernel/vfs/procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit ae0c5ca

Please sign in to comment.