forked from PoliEcho-holding-org/kern
Compare commits
4
Commits
ffa23b1dba
...
c74ea060e5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c74ea060e5 | ||
|
|
a2cd3aa1b1 | ||
|
|
92268b70fc | ||
|
|
6dd0823c93 |
@@ -14,7 +14,7 @@ Low-Level Hardware & Interrupts
|
|||||||
[x] IDT
|
[x] IDT
|
||||||
[x] Basic IRQs (Internal/Legacy)
|
[x] Basic IRQs (Internal/Legacy)
|
||||||
[x] Proper fault handling (Exceptions, Page Faults, #GP)
|
[x] Proper fault handling (Exceptions, Page Faults, #GP)
|
||||||
[ ] Check for features with CPUID (NX-bit, SSE, AVX)
|
[-] Check for features with CPUID (NX-bit, SSE, AVX)
|
||||||
[ ] APIC driver (Local APIC & I/O APIC)
|
[ ] APIC driver (Local APIC & I/O APIC)
|
||||||
[ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC)
|
[ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC)
|
||||||
[ ] HPET driver (High precision timing)
|
[ ] HPET driver (High precision timing)
|
||||||
|
|||||||
@@ -15,6 +15,32 @@ void* kzalloc(size_t size);
|
|||||||
// zeroed-out memory. Returns a pointer to allocated memory or NULL.
|
// zeroed-out memory. Returns a pointer to allocated memory or NULL.
|
||||||
void* kcalloc(size_t count, size_t size);
|
void* kcalloc(size_t count, size_t size);
|
||||||
|
|
||||||
|
// 9 bytes in 8 bytes
|
||||||
|
#define TAG_SHIFT 56
|
||||||
|
#define TAG_MASK ((uintptr_t)0xFF << TAG_SHIFT)
|
||||||
|
#define SIGN_BIT ((uintptr_t)1 << 55)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uintptr_t bits;
|
||||||
|
} tagged_ptr;
|
||||||
|
|
||||||
|
static inline tagged_ptr tp_make(void* p, uint8_t tag) {
|
||||||
|
uintptr_t addr = (uintptr_t)p & ~TAG_MASK;
|
||||||
|
return (tagged_ptr){addr | ((uintptr_t)tag << TAG_SHIFT)};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t tp_tag(tagged_ptr t) {
|
||||||
|
return (uint8_t)(t.bits >> TAG_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void* tp_ptr(tagged_ptr t) {
|
||||||
|
/* Bits 48..55 were untouched and still equal the canonical sign.
|
||||||
|
Copy bit 55 into bits 56..63. */
|
||||||
|
uintptr_t addr =
|
||||||
|
(t.bits & SIGN_BIT) ? (t.bits | TAG_MASK) : (t.bits & ~TAG_MASK);
|
||||||
|
return (void*)addr;
|
||||||
|
}
|
||||||
|
|
||||||
// powers of 2
|
// powers of 2
|
||||||
#define KMALLOC_MAX_SIZE 17
|
#define KMALLOC_MAX_SIZE 17
|
||||||
#define LOWEST_POWER 3
|
#define LOWEST_POWER 3
|
||||||
@@ -28,6 +54,12 @@ struct partialy_freelist {
|
|||||||
struct partialy_freelist* partialy_freelist_nextnode;
|
struct partialy_freelist* partialy_freelist_nextnode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// this is used when object is too small to hold the big one in this case we use
|
||||||
|
// first object as pointer storage and dont allocate it
|
||||||
|
struct partialy_freelist_short {
|
||||||
|
struct partialy_freelist_short* partialy_freelist_nextnode;
|
||||||
|
};
|
||||||
|
|
||||||
union freelists_list {
|
union freelists_list {
|
||||||
struct freelist* freelists[KMALLOC_MAX_SIZE];
|
struct freelist* freelists[KMALLOC_MAX_SIZE];
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define _RANDOM_H
|
#define _RANDOM_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
void rand_init();
|
void rand_init(bool rdrand, bool rdseed);
|
||||||
|
|
||||||
extern uint64_t (*get_random_number)();
|
extern uint64_t (*get_random_number)();
|
||||||
#endif
|
#endif
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
* CPUID
|
* CPUID
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
CPUID_FEAT_EBX_RDSEED = 1 << 18,
|
||||||
|
|
||||||
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
||||||
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
||||||
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
||||||
@@ -87,4 +89,6 @@ void outl(uint16_t port, uint32_t data);
|
|||||||
void cli(void);
|
void cli(void);
|
||||||
void sti(void);
|
void sti(void);
|
||||||
|
|
||||||
|
extern uint8_t (*popcountll)(uint64_t num);
|
||||||
|
void detect_processor_features();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,4 +6,5 @@
|
|||||||
#define CANONICAL_MASK_USER 0x00007FFFFFFFFFF000
|
#define CANONICAL_MASK_USER 0x00007FFFFFFFFFF000
|
||||||
|
|
||||||
int vmm_alloc(void** vaddr, uint64_t count, uint64_t flags);
|
int vmm_alloc(void** vaddr, uint64_t count, uint64_t flags);
|
||||||
|
int vmm_free(void* vaddr);
|
||||||
#endif
|
#endif
|
||||||
+4
-2
@@ -30,6 +30,9 @@ __noreturn void _start(void) {
|
|||||||
cpuid(&eax, (void*)&s[0], (void*)&s[8], (void*)&s[4]);
|
cpuid(&eax, (void*)&s[0], (void*)&s[8], (void*)&s[4]);
|
||||||
pr_info("[kernel] CPUID_GETVENDORID: %s\n", s);
|
pr_info("[kernel] CPUID_GETVENDORID: %s\n", s);
|
||||||
|
|
||||||
|
// enable processor extensions
|
||||||
|
detect_processor_features();
|
||||||
|
|
||||||
// System init
|
// System init
|
||||||
if ((err = gdt_init()) < 0)
|
if ((err = gdt_init()) < 0)
|
||||||
panic(NULL, "Failed to initalize GDT. (%d)", err);
|
panic(NULL, "Failed to initalize GDT. (%d)", err);
|
||||||
@@ -43,8 +46,7 @@ __noreturn void _start(void) {
|
|||||||
if ((err = pag_init()) < 0)
|
if ((err = pag_init()) < 0)
|
||||||
panic(NULL, "Failed to initalize Paging. (%d)", err);
|
panic(NULL, "Failed to initalize Paging. (%d)", err);
|
||||||
|
|
||||||
// random number generation
|
|
||||||
rand_init();
|
|
||||||
// test random number generation
|
// test random number generation
|
||||||
printk("Random number generation test:\n");
|
printk("Random number generation test:\n");
|
||||||
for (uint8_t i = 0; i <= 16; i++) {
|
for (uint8_t i = 0; i <= 16; i++) {
|
||||||
|
|||||||
+51
-4
@@ -1,8 +1,12 @@
|
|||||||
|
#include "errno.h"
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
#include "paging.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "vmm.h"
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <system.h>
|
||||||
// this file contains SLUB inspired HEAP allocator
|
// this file contains SLUB inspired HEAP allocator
|
||||||
|
|
||||||
// TODO this will be an allocated array later when we have APIC MADT
|
// TODO this will be an allocated array later when we have APIC MADT
|
||||||
@@ -54,8 +58,9 @@ void* kmalloc(size_t size) {
|
|||||||
|
|
||||||
size_t alloc_index;
|
size_t alloc_index;
|
||||||
{
|
{
|
||||||
|
// TODO remove buildin
|
||||||
uint8_t leading_zeros = __builtin_clzll(size);
|
uint8_t leading_zeros = __builtin_clzll(size);
|
||||||
if (/*__builtin_popcountll(size) == */1) {
|
if (popcountll(size) == 1) {
|
||||||
alloc_index = leading_zeros;
|
alloc_index = leading_zeros;
|
||||||
} else {
|
} else {
|
||||||
alloc_index = sizeof(size) * CHAR_BIT - leading_zeros;
|
alloc_index = sizeof(size) * CHAR_BIT - leading_zeros;
|
||||||
@@ -69,6 +74,8 @@ void* kmalloc(size_t size) {
|
|||||||
}
|
}
|
||||||
alloc_index -= LOWEST_POWER;
|
alloc_index -= LOWEST_POWER;
|
||||||
}
|
}
|
||||||
|
size_t object_size = (1 << (alloc_index + LOWEST_POWER));
|
||||||
|
|
||||||
struct freelist* selected_freelist =
|
struct freelist* selected_freelist =
|
||||||
freelists_all_cpus[core_id].freelists[alloc_index];
|
freelists_all_cpus[core_id].freelists[alloc_index];
|
||||||
if (selected_freelist != NULL) {
|
if (selected_freelist != NULL) {
|
||||||
@@ -96,14 +103,16 @@ void* kmalloc(size_t size) {
|
|||||||
// only one free object available
|
// only one free object available
|
||||||
if (selected_partialy_freelist
|
if (selected_partialy_freelist
|
||||||
->partialy_freelist_nextnode != NULL) {
|
->partialy_freelist_nextnode != NULL) {
|
||||||
// next partialy free list available
|
// next partialy free list
|
||||||
|
// available
|
||||||
partial_free_lists[core_id]
|
partial_free_lists[core_id]
|
||||||
.partialy_freelists[alloc_index] =
|
.partialy_freelists[alloc_index] =
|
||||||
selected_partialy_freelist
|
selected_partialy_freelist
|
||||||
->partialy_freelist_nextnode;
|
->partialy_freelist_nextnode;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// no other partialy free list available
|
// no other partialy free list
|
||||||
|
// available
|
||||||
partial_free_lists[core_id]
|
partial_free_lists[core_id]
|
||||||
.partialy_freelists[alloc_index] =
|
.partialy_freelists[alloc_index] =
|
||||||
NULL;
|
NULL;
|
||||||
@@ -125,6 +134,44 @@ void* kmalloc(size_t size) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// slowest path
|
// slowest path
|
||||||
|
|
||||||
|
uint8_t page_count =
|
||||||
|
object_size < PAGE_SIZE
|
||||||
|
? 1
|
||||||
|
: (object_size * 2) / PAGE_SIZE;
|
||||||
|
|
||||||
|
void** alloc_addr = 0;
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = vmm_alloc((void**)&alloc_addr, page_count,
|
||||||
|
0);
|
||||||
|
if (ret != SUCCESS) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct the linked list
|
||||||
|
// start at offset if object too small for partial free
|
||||||
|
// list pointer
|
||||||
|
for (size_t i =
|
||||||
|
object_size < sizeof(struct partialy_freelist)
|
||||||
|
? object_size
|
||||||
|
: 0;
|
||||||
|
i < page_count * PAGE_SIZE; i += object_size) {
|
||||||
|
if ((i + 1) * object_size >=
|
||||||
|
page_count * PAGE_SIZE) {
|
||||||
|
alloc_addr[i * object_size] = NULL;
|
||||||
|
} else {
|
||||||
|
alloc_addr[i * object_size] =
|
||||||
|
alloc_addr +
|
||||||
|
((i + 1) * object_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freelists_all_cpus[core_id].freelists[alloc_index] =
|
||||||
|
(struct freelist*)(alloc_addr + object_size);
|
||||||
|
return alloc_addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void* kfree(void* p) {}
|
||||||
+3
-5
@@ -25,18 +25,16 @@ uint64_t rand_software() {
|
|||||||
return LFSR;
|
return LFSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rand_init() {
|
void rand_init(bool rdrand, bool rdseed) {
|
||||||
uint32_t eax = 1, ebx = 0, ecx = 0, edx = 0;
|
|
||||||
cpuid(&eax, &ebx, &ecx, &edx);
|
|
||||||
|
|
||||||
// check for RDRAND
|
// check for RDRAND
|
||||||
if ((ecx >> 30) & 1) {
|
if (rdrand) {
|
||||||
get_random_number = rand_rdrand;
|
get_random_number = rand_rdrand;
|
||||||
} else {
|
} else {
|
||||||
printk("[\e[33mWARNING\e[0m] RDRAND not available falling back "
|
printk("[\e[33mWARNING\e[0m] RDRAND not available falling back "
|
||||||
"to software\n");
|
"to software\n");
|
||||||
// check for RDSEED
|
// check for RDSEED
|
||||||
if ((ebx >> 18) & 1) {
|
if (rdseed) {
|
||||||
asm(".intel_syntax noprefix\n"
|
asm(".intel_syntax noprefix\n"
|
||||||
"rdseed %0\n"
|
"rdseed %0\n"
|
||||||
".att_syntax prefix\n"
|
".att_syntax prefix\n"
|
||||||
|
|||||||
+60
-19
@@ -1,52 +1,93 @@
|
|||||||
|
#include "types.h"
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <random.h>
|
||||||
#include <system.h>
|
#include <system.h>
|
||||||
|
|
||||||
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
|
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
|
||||||
__asm__ volatile ("cpuid"
|
__asm__ volatile("cpuid"
|
||||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||||
: "a"(*eax)
|
: "a"(*eax)
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void iowait(void) {
|
void iowait(void) { outb(0x80, 0); }
|
||||||
outb(0x80, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t inb(uint16_t port) {
|
uint8_t inb(uint16_t port) {
|
||||||
uint8_t r;
|
uint8_t r;
|
||||||
__asm__ volatile ("inb %1, %0" : "=a"(r) : "dN"(port));
|
__asm__ volatile("inb %1, %0" : "=a"(r) : "dN"(port));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outb(uint16_t port, uint8_t data) {
|
void outb(uint16_t port, uint8_t data) {
|
||||||
__asm__ volatile ("outb %1, %0" :: "dN"(port), "a"(data));
|
__asm__ volatile("outb %1, %0" ::"dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t inw(uint16_t port) {
|
uint16_t inw(uint16_t port) {
|
||||||
uint16_t r;
|
uint16_t r;
|
||||||
__asm__ volatile ("inw %1, %0" : "=a"(r) : "dN"(port));
|
__asm__ volatile("inw %1, %0" : "=a"(r) : "dN"(port));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outw(uint16_t port, uint16_t data) {
|
void outw(uint16_t port, uint16_t data) {
|
||||||
__asm__ volatile ("outw %1, %0" :: "dN"(port), "a"(data));
|
__asm__ volatile("outw %1, %0" ::"dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t inl(uint16_t port) {
|
uint32_t inl(uint16_t port) {
|
||||||
uint32_t r;
|
uint32_t r;
|
||||||
__asm__ volatile ("inl %1, %0" : "=a"(r) : "dN"(port));
|
__asm__ volatile("inl %1, %0" : "=a"(r) : "dN"(port));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void outl(uint16_t port, uint32_t data) {
|
void outl(uint16_t port, uint32_t data) {
|
||||||
__asm__ volatile ("outl %1, %0" :: "dN"(port), "a"(data));
|
__asm__ volatile("outl %1, %0" ::"dN"(port), "a"(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli(void) {
|
void cli(void) { __asm__ volatile("cli"); }
|
||||||
__asm__ volatile ("cli");
|
|
||||||
|
void sti(void) { __asm__ volatile("sti"); }
|
||||||
|
|
||||||
|
uint8_t (*popcountll)(uint64_t num);
|
||||||
|
|
||||||
|
extern uint8_t popcountll_native(uint64_t num);
|
||||||
|
asm(".intel_syntax noprefix\n"
|
||||||
|
".global popcountll_native\n"
|
||||||
|
"popcountll_native:"
|
||||||
|
" popcnt rax, rdi\n"
|
||||||
|
" ret\n"
|
||||||
|
".att_syntax prefix\n");
|
||||||
|
|
||||||
|
// I have no idea how this works but it is apperently called SWAR
|
||||||
|
uint8_t popcountll_software(uint64_t num) {
|
||||||
|
num = num - ((num >> 1) & 0x5555555555555555ULL);
|
||||||
|
num = (num & 0x3333333333333333ULL) +
|
||||||
|
((num >> 2) & 0x3333333333333333ULL);
|
||||||
|
num = (num + (num >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
|
||||||
|
return (int)((num * 0x0101010101010101ULL) >> 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sti(void) {
|
void detect_processor_features() {
|
||||||
__asm__ volatile ("sti");
|
// leaf 1
|
||||||
}
|
uint32_t eax = 1, ebx = 0, ecx = 0, edx = 0;
|
||||||
|
cpuid(&eax, &ebx, &ecx, &edx);
|
||||||
|
|
||||||
|
bool rdrand = false;
|
||||||
|
if (ecx & CPUID_FEAT_ECX_RDRAND) {
|
||||||
|
rdrand = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecx & CPUID_FEAT_ECX_POPCNT) {
|
||||||
|
popcountll = popcountll_native;
|
||||||
|
} else {
|
||||||
|
popcountll = popcountll_software;
|
||||||
|
}
|
||||||
|
|
||||||
|
// leaf 7
|
||||||
|
eax = 7, ebx = 0, ecx = 0, edx = 0;
|
||||||
|
cpuid(&eax, &ebx, &ecx, &edx);
|
||||||
|
bool rdseed = false;
|
||||||
|
if (ebx & CPUID_FEAT_EBX_RDSEED) {
|
||||||
|
rdseed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init rng
|
||||||
|
rand_init(rdrand, rdseed);
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,4 +86,9 @@ int vmm_alloc(void** vaddr, uint64_t count, uint64_t flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vmm_free(void* vaddr) {
|
||||||
|
uint64_t* pml4 = pag_get_pml4();
|
||||||
|
return pag_unmap(pml4, vaddr);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user