From cec4e441eb1c64cbc89ac15cfd9002a3ed1019ef Mon Sep 17 00:00:00 2001 From: lubenard Date: Sat, 10 Feb 2024 01:07:25 +0100 Subject: [PATCH] Get CPUid and capabilities --- Makefile | 2 + srcs/drivers/cpu/cpu.c | 42 +++++++++++++++ srcs/drivers/cpu/cpu.h | 58 ++++++++++++++++++++ srcs/drivers/cpu/cpu_asm.s | 76 +++++++++++++++++++++++++++ srcs/kernel/gdt/gdt.c | 6 +-- srcs/kernel/gdt/gdt.h | 1 + srcs/kernel/idt/idt.c | 11 ---- srcs/kernel/kernel.c | 16 +++++- srcs/kernel/processes/processes_asm.s | 14 ++--- 9 files changed, 198 insertions(+), 28 deletions(-) create mode 100644 srcs/drivers/cpu/cpu.c create mode 100644 srcs/drivers/cpu/cpu.h create mode 100644 srcs/drivers/cpu/cpu_asm.s diff --git a/Makefile b/Makefile index 6317915..0106764 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ IS_TEST = 0 SRC_FILES_ASM = kernel/boot.s \ kernel/gdt/gdt_asm.s \ + drivers/cpu/cpu_asm.s \ kernel/idt/idt_asm.s \ kernel/isr/isr_asm.s \ kernel/memory/paging_asm.s \ @@ -33,6 +34,7 @@ SRC_FILES_ASM = kernel/boot.s \ SRC_FILES_C = kernel/kernel.c \ drivers/vga/vga.c \ drivers/PS2_keyboard/PS2_keyboard.c \ + drivers/cpu/cpu.c \ kernel/gdt/gdt.c \ kernel/idt/idt.c \ kernel/isr/isr.c \ diff --git a/srcs/drivers/cpu/cpu.c b/srcs/drivers/cpu/cpu.c new file mode 100644 index 0000000..60ce875 --- /dev/null +++ b/srcs/drivers/cpu/cpu.c @@ -0,0 +1,42 @@ +#include "cpu.h" +#include "../../lib/iolib.h" + +void check_cpu_features() { + check_cpu_id(); + check_cpu_vendor(); + get_cpu_features(); +} + +// Letters are stored as int +// Example: +// ebx might look this: 1970169159, which is actually translated to 1110101 01101110 01100101 01000111 +// Each 8 bytes group can represent an Ascii letter. +// Once extracted, we need to put them in the right order to get the cpu vendor +// See here for more information: +// https://wiki.osdev.org/CPUID +void display_cpu_vendor(int ebx, int edx, int ecx) { + unsigned char ebx_l1 = ebx & 0xFF; + unsigned char ebx_l2 = (ebx >> 8) & 0xFF; + unsigned char ebx_l3 = (ebx >> 16) & 0xFF; + unsigned char ebx_l4 = (ebx >> 24) & 0xFF; + + unsigned char edx_l1 = edx & 0xFF; + unsigned char edx_l2 = (edx >> 8) & 0xFF; + unsigned char edx_l3 = (edx >> 16) & 0xFF; + unsigned char edx_l4 = (edx >> 24) & 0xFF; + + unsigned char ecx_l1 = ecx & 0xFF; + unsigned char ecx_l2 = (ecx >> 8) & 0xFF; + unsigned char ecx_l3 = (ecx >> 16) & 0xFF; + unsigned char ecx_l4 = (ecx >> 24) & 0xFF; + + printd(KERN_INFO, "CPU is %c%c%c%c%c%c%c%c%c%c%c%c", + ebx_l1, ebx_l2, ebx_l3, ebx_l4, + edx_l1, edx_l2, edx_l3, edx_l4, + ecx_l1, ecx_l2, ecx_l3, ecx_l4 + ); +} + +void display_cpu_features(int s1, int s2) { + printd(KERN_INFO, "CPU features are: %d %d", s1, s2); +} \ No newline at end of file diff --git a/srcs/drivers/cpu/cpu.h b/srcs/drivers/cpu/cpu.h new file mode 100644 index 0000000..db736d5 --- /dev/null +++ b/srcs/drivers/cpu/cpu.h @@ -0,0 +1,58 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cpu.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: luca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/02 14:11:48 by luca #+# #+# */ +/* Updated: 2024/02/02 14:11:48 by luca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef KFS_CPU_H +#define KFS_CPU_H + +// Vendor strings from CPUs. +#define CPUID_VENDOR_AMD "AuthenticAMD" +#define CPUID_VENDOR_AMD_OLD "AMDisbetter!" // Early engineering samples of AMD K5 processor +#define CPUID_VENDOR_INTEL "GenuineIntel" +#define CPUID_VENDOR_VIA "VIA VIA VIA " +#define CPUID_VENDOR_TRANSMETA "GenuineTMx86" +#define CPUID_VENDOR_TRANSMETA_OLD "TransmetaCPU" +#define CPUID_VENDOR_CYRIX "CyrixInstead" +#define CPUID_VENDOR_CENTAUR "CentaurHauls" +#define CPUID_VENDOR_NEXGEN "NexGenDriven" +#define CPUID_VENDOR_UMC "UMC UMC UMC " +#define CPUID_VENDOR_SIS "SiS SiS SiS " +#define CPUID_VENDOR_NSC "Geode by NSC" +#define CPUID_VENDOR_RISE "RiseRiseRise" +#define CPUID_VENDOR_VORTEX "Vortex86 SoC" +#define CPUID_VENDOR_AO486 "MiSTer AO486" +#define CPUID_VENDOR_AO486_OLD "GenuineAO486" +#define CPUID_VENDOR_ZHAOXIN " Shanghai " +#define CPUID_VENDOR_HYGON "HygonGenuine" +#define CPUID_VENDOR_ELBRUS "E2K MACHINE " + +// Vendor strings from hypervisors. +#define CPUID_VENDOR_QEMU "TCGTCGTCGTCG" +#define CPUID_VENDOR_KVM " KVMKVMKVM " +#define CPUID_VENDOR_VMWARE "VMwareVMware" +#define CPUID_VENDOR_VIRTUALBOX "VBoxVBoxVBox" +#define CPUID_VENDOR_XEN "XenVMMXenVMM" +#define CPUID_VENDOR_HYPERV "Microsoft Hv" +#define CPUID_VENDOR_PARALLELS " prl hyperv " +#define CPUID_VENDOR_PARALLELS_ALT " lrpepyh vr " // Sometimes Parallels incorrectly encodes "prl hyperv" as "lrpepyh vr" due to an endianness mismatch. +#define CPUID_VENDOR_BHYVE "bhyve bhyve " +#define CPUID_VENDOR_QNX " QNXQVMBSQG " + +void check_cpu_features(); +void display_cpu_vendor(int s1, int s2, int s3); +void display_cpu_features(int s1, int s2); + +// ASM functions +extern void check_cpu_id(); +extern void check_cpu_vendor(); +extern void get_cpu_features(); + +#endif //KFS_CPU_H diff --git a/srcs/drivers/cpu/cpu_asm.s b/srcs/drivers/cpu/cpu_asm.s new file mode 100644 index 0000000..c68ada8 --- /dev/null +++ b/srcs/drivers/cpu/cpu_asm.s @@ -0,0 +1,76 @@ + +[GLOBAL check_cpu_id] +[GLOBAL check_cpu_vendor] +[GLOBAL get_cpu_features] + +extern printd +extern display_cpu_vendor +extern display_cpu_features + +cpuid_not_supported db 'CPUID is not supported', 0 +cpuid_supported db 'CPUID is supported', 0 + +check_cpu_id: + push ebp ; Stack & Frame Setup and Save + mov ebp, esp + + pushfd ; Save EFLAGS + pushfd ; Store EFLAGS + xor dword [esp],0x00200000 ; Invert the ID bit in stored EFLAGS + popfd ; Load stored EFLAGS (with ID bit inverted) + pushfd ; Store EFLAGS again (ID bit may or may not be inverted) + pop eax ; eax = modified EFLAGS (ID bit may or may not be inverted) + xor eax,[esp] ; eax = whichever bits were changed + popfd ; Restore original EFLAGS + and eax, 0x00200000 ; eax = zero if ID bit can't be changed, else non-zero + cmp eax, 0 ; Compare eax to 0 + je id_not_supported ; if equal, jump to id_not_supported + jmp id_supported ; Else, jump to id_supported + ret + +id_not_supported: + push 0x0 ; Push flags + push cpuid_not_supported ; Push String + push 0x3 ; Push Info Type + call printd ; Call printf + mov esp, ebp ; Stack & Frame Restore + pop ebp + ret + +id_supported: + push 0x0 ; Push flags + push cpuid_supported ; Push String + push 0x0 ; Push Info Type + call printd ; Call printf + mov esp, ebp ; Stack & Frame Restore + pop ebp + ret + +check_cpu_vendor: + push ebp ; Stack & Frame Setup and Save + mov ebp, esp + + mov eax, 0x0 ; Get CPU Vendor ID String + cpuid ; Get Infos + push ecx ; Infos are returned in ebx, edx, ecx + push edx ; We push thoses on the stack to pass them to C function + push ebx + call display_cpu_vendor ; Call our C function + + mov esp, ebp ; Stack & Frame Restore + pop ebp + ret + +get_cpu_features: + push ebp ; Stack & Frame Setup and Save + mov ebp, esp + + mov eax, 0x1 ; Get CPU Vendor ID String + cpuid + push ecx ; Infos are returned in edx, ecx + push edx ; We push thoses on the stack to pass them to C function + call display_cpu_features + + mov esp, ebp ; Stack & Frame Restore + pop ebp + ret \ No newline at end of file diff --git a/srcs/kernel/gdt/gdt.c b/srcs/kernel/gdt/gdt.c index c41ee63..0d5ef50 100644 --- a/srcs/kernel/gdt/gdt.c +++ b/srcs/kernel/gdt/gdt.c @@ -44,7 +44,7 @@ static void setup_tss(uint32_t num, uint16_t ss0, uint32_t esp0) { uint32_t limit = base + sizeof(tss_entry); // Now, add our TSS descriptor's address to the GDT. - gdt_set_gate(num, base, limit, 0xE9, 0x00); + gdt_set_gate(num, base, limit, 0x89, 0x40); // Ensure the descriptor is initially zero. memset(&tss_entry, 0, sizeof(tss_entry)); @@ -62,9 +62,7 @@ static void setup_tss(uint32_t num, uint16_t ss0, uint32_t esp0) { tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; } - -void init_gdt() -{ +void init_gdt() { GDTDescriptor_t gdt_ptr; // Disable interruptions diff --git a/srcs/kernel/gdt/gdt.h b/srcs/kernel/gdt/gdt.h index c34c634..61c1ec4 100644 --- a/srcs/kernel/gdt/gdt.h +++ b/srcs/kernel/gdt/gdt.h @@ -72,6 +72,7 @@ typedef struct GDTDescriptor GDTDescriptor_t; /* Asm function */ extern void gdt_flush(uint32_t); extern void tss_flush(); +extern void check_kernel_long_mode(); /* Prototype to init GDT */ void init_gdt(); diff --git a/srcs/kernel/idt/idt.c b/srcs/kernel/idt/idt.c index a7d5fb0..fdc3c02 100644 --- a/srcs/kernel/idt/idt.c +++ b/srcs/kernel/idt/idt.c @@ -14,9 +14,6 @@ #include "../../lib/iolib.h" #include "../../lib/memlib.h" #include "../../io/io.h" -#include "../isr/irqs/irqs.h" -#include "../../io/shell/builtins/builtins.h" - struct idt_ptr_struct idt_ptr; struct idt32 idt_entries[256]; @@ -123,13 +120,5 @@ void init_idt() { idt_set_gate(80, (int32_t)syscalls, 0x08, 0x8E); printk(KERN_INFO, "IDT has been initialised at %p", &idt_ptr); - - // Init pit to get ticks - init_pit(); - - /* Init rtc to get date from bios */ - init_rtc(); - - date(0); } diff --git a/srcs/kernel/kernel.c b/srcs/kernel/kernel.c index 4bb0167..68c3cc7 100644 --- a/srcs/kernel/kernel.c +++ b/srcs/kernel/kernel.c @@ -24,6 +24,8 @@ #include "syscalls/syscalls.h" #include "isr/irqs/irqs.h" #include "../../tests/tests.h" +#include "../io/shell/builtins/builtins.h" +#include "../drivers/cpu/cpu.h" /* Check if the compiler thinks you are targeting the wrong operating system. */ #if defined(__linux__) @@ -65,8 +67,8 @@ int test_function1() { //terminal_writestr("Hello from function test 1"); //sleep(2); i++; - } - test_syscalls();*/ + }*/ + test_syscalls(); return 0; } @@ -96,12 +98,22 @@ void k_main(unsigned long magic, unsigned long addr) { printd(KERN_INFO, "Screen & COM port init"); + check_cpu_features(); + /* Initialize GDT (Global descriptor table) */ init_gdt(); /* Initialize IDT (Interruptor descriptor table) */ init_idt(); + // Init pit to get ticks + init_pit(); + + /* Init rtc to get date from bios */ + init_rtc(); + + date(0); + /* Init kbd management */ init_kbd(); diff --git a/srcs/kernel/processes/processes_asm.s b/srcs/kernel/processes/processes_asm.s index 6df7e6a..420c942 100644 --- a/srcs/kernel/processes/processes_asm.s +++ b/srcs/kernel/processes/processes_asm.s @@ -12,18 +12,8 @@ GLOBAL switch_regs -extern printd - -message: - db 'Ecx is %p', 0 - switch_regs: cli - ; Debug message - ;push dword [eax + 4] - ;push message - ;push 0x1 - ;call printd ; Move general registers mov ecx, [eax + 4] @@ -34,8 +24,10 @@ switch_regs: mov edi, [eax + 28] ; Right now, eax, ebp, esp are not restored yet + ; 0x23 is the User Data Segment push 0x23 - push esp + ; Esp is the stack pointer + push dword [eax + 16] ; Push new eflags on the stack push dword [eax + 32]