forked from PoliEcho-holding-org/kern
Compare commits
15
Commits
675ff8519a
...
rewrite
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c74ea060e5 | ||
|
|
a2cd3aa1b1 | ||
|
|
92268b70fc | ||
|
|
6dd0823c93 | ||
|
|
ffa23b1dba | ||
|
|
6c609e9840 | ||
|
|
318fe96319 | ||
|
|
b0ab02c634 | ||
|
|
a95839c7c6 | ||
|
|
3fe3d05b1b | ||
|
|
700b1ec4b4 | ||
|
|
07bd738566 | ||
|
|
16fde28a8b | ||
|
|
7c0ac01110 | ||
|
|
b917ebe973 |
@@ -14,7 +14,7 @@ Low-Level Hardware & Interrupts
|
||||
[x] IDT
|
||||
[x] Basic IRQs (Internal/Legacy)
|
||||
[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)
|
||||
[ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC)
|
||||
[ ] HPET driver (High precision timing)
|
||||
|
||||
+18
-17
@@ -13,23 +13,24 @@
|
||||
// TODO: Add correct errno.h numbers
|
||||
enum {
|
||||
SUCCESS = 0,
|
||||
ENOMEM, // Cannot allocate memory
|
||||
EPERM, // Operation not permitted
|
||||
ENOENT, // No entry (no such file or directory)
|
||||
EIO, // Input/Output error
|
||||
ENXIO, // No such device or address
|
||||
EAGAIN, // Resource temporarly busy
|
||||
EACCES, // Permission denied
|
||||
EFAULT, // Bad address
|
||||
ENODEV, // No such device
|
||||
EINVAL, // Invalid argument
|
||||
EDOM, // Numerical argument out of domain
|
||||
ERANGE, // Numerical result out of range
|
||||
ENOSYS, // Function not implemented
|
||||
ENOTSUP, // Not supported
|
||||
EILLSEQ, // Illegal byte sequence
|
||||
EOVERFLOW, //
|
||||
EALIGN, // Not aligned
|
||||
ENOMEM, // Cannot allocate memory
|
||||
EPERM, // Operation not permitted
|
||||
ENOENT, // No entry (no such file or directory)
|
||||
EIO, // Input/Output error
|
||||
ENXIO, // No such device or address
|
||||
EAGAIN, // Resource temporarly busy
|
||||
EACCES, // Permission denied
|
||||
EFAULT, // Bad address
|
||||
ENODEV, // No such device
|
||||
EINVAL, // Invalid argument
|
||||
EDOM, // Numerical argument out of domain
|
||||
ERANGE, // Numerical result out of range
|
||||
ENOSYS, // Function not implemented
|
||||
ENOTSUP, // Not supported
|
||||
EILLSEQ, // Illegal byte sequence
|
||||
EOVERFLOW, //
|
||||
EALIGN, // Not aligned
|
||||
EEXIST, // already exists
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+75
-34
@@ -15,49 +15,90 @@ void* kzalloc(size_t size);
|
||||
// zeroed-out memory. Returns a pointer to allocated memory or NULL.
|
||||
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
|
||||
#define KMALLOC_MAX_SIZE 17
|
||||
#define LOWEST_POWER 3
|
||||
|
||||
union per_cpu_freelist_cache {
|
||||
void** freelists[KMALLOC_MAX_SIZE];
|
||||
struct freelist {
|
||||
struct freelist* nextnode;
|
||||
};
|
||||
|
||||
struct partialy_freelist {
|
||||
struct freelist* 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 {
|
||||
struct freelist* freelists[KMALLOC_MAX_SIZE];
|
||||
struct {
|
||||
void** kmalloc_8;
|
||||
void** kmalloc_16;
|
||||
void** kmalloc_32;
|
||||
void** kmalloc_64;
|
||||
void** kmalloc_128;
|
||||
void** kmalloc_256;
|
||||
void** kmalloc_512;
|
||||
void** kmalloc_1024;
|
||||
void** kmalloc_2048;
|
||||
void** kmalloc_4096;
|
||||
void** kmalloc_8192;
|
||||
void** kmalloc_16384;
|
||||
void** kmalloc_32768;
|
||||
void** kmalloc_65536;
|
||||
void** kmalloc_131072;
|
||||
struct freelist* kmalloc_8;
|
||||
struct freelist* kmalloc_16;
|
||||
struct freelist* kmalloc_32;
|
||||
struct freelist* kmalloc_64;
|
||||
struct freelist* kmalloc_128;
|
||||
struct freelist* kmalloc_256;
|
||||
struct freelist* kmalloc_512;
|
||||
struct freelist* kmalloc_1024;
|
||||
struct freelist* kmalloc_2048;
|
||||
struct freelist* kmalloc_4096;
|
||||
struct freelist* kmalloc_8192;
|
||||
struct freelist* kmalloc_16384;
|
||||
struct freelist* kmalloc_32768;
|
||||
struct freelist* kmalloc_65536;
|
||||
struct freelist* kmalloc_131072;
|
||||
};
|
||||
};
|
||||
|
||||
union partial_list {
|
||||
void** freelists[KMALLOC_MAX_SIZE];
|
||||
union partialy_freelists_list {
|
||||
struct partialy_freelist* partialy_freelists[KMALLOC_MAX_SIZE];
|
||||
struct {
|
||||
void** kmalloc_8;
|
||||
void** kmalloc_16;
|
||||
void** kmalloc_32;
|
||||
void** kmalloc_64;
|
||||
void** kmalloc_128;
|
||||
void** kmalloc_256;
|
||||
void** kmalloc_512;
|
||||
void** kmalloc_1024;
|
||||
void** kmalloc_2048;
|
||||
void** kmalloc_4096;
|
||||
void** kmalloc_8192;
|
||||
void** kmalloc_16384;
|
||||
void** kmalloc_32768;
|
||||
void** kmalloc_65536;
|
||||
void** kmalloc_131072;
|
||||
struct partialy_freelist* kmalloc_8;
|
||||
struct partialy_freelist* kmalloc_16;
|
||||
struct partialy_freelist* kmalloc_32;
|
||||
struct partialy_freelist* kmalloc_64;
|
||||
struct partialy_freelist* kmalloc_128;
|
||||
struct partialy_freelist* kmalloc_256;
|
||||
struct partialy_freelist* kmalloc_512;
|
||||
struct partialy_freelist* kmalloc_1024;
|
||||
struct partialy_freelist* kmalloc_2048;
|
||||
struct partialy_freelist* kmalloc_4096;
|
||||
struct partialy_freelist* kmalloc_8192;
|
||||
struct partialy_freelist* kmalloc_16384;
|
||||
struct partialy_freelist* kmalloc_32768;
|
||||
struct partialy_freelist* kmalloc_65536;
|
||||
struct partialy_freelist* kmalloc_131072;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
#ifndef _LIMIT_H
|
||||
#define _LIMIT_H
|
||||
|
||||
#define CHAR_BIT 8
|
||||
|
||||
#define INT8_WIDTH 8
|
||||
#define INT16_WIDTH 16
|
||||
#define INT32_WIDTH 32
|
||||
#define INT64_WIDTH 64
|
||||
|
||||
#define UINT8_WIDTH 8
|
||||
#define UINT16_WIDTH 16
|
||||
#define UINT32_WIDTH 32
|
||||
#define UINT64_WIDTH 64
|
||||
|
||||
#define INT8_MAX 127
|
||||
#define INT16_MAX 32767
|
||||
#define INT32_MAX 2147483647
|
||||
#define INT64_MAX 9223372036854775807LL
|
||||
|
||||
#define INT8_MIN (-128)
|
||||
#define INT16_MIN (-32768)
|
||||
#define INT32_MIN (-2147483647 - 1)
|
||||
#define INT64_MIN (-9223372036854775807LL - 1LL)
|
||||
|
||||
#define UINT8_MAX 255U
|
||||
#define UINT16_MAX 65535U
|
||||
#define UINT32_MAX 4294967295U
|
||||
#define UINT64_MAX 18446744073709551615ULL
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _RANDOM_H
|
||||
#define _RANDOM_H
|
||||
|
||||
#include <types.h>
|
||||
void rand_init(bool rdrand, bool rdseed);
|
||||
|
||||
extern uint64_t (*get_random_number)();
|
||||
#endif
|
||||
@@ -9,6 +9,8 @@
|
||||
* CPUID
|
||||
*/
|
||||
enum {
|
||||
CPUID_FEAT_EBX_RDSEED = 1 << 18,
|
||||
|
||||
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
||||
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
||||
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
||||
@@ -87,4 +89,6 @@ void outl(uint16_t port, uint32_t data);
|
||||
void cli(void);
|
||||
void sti(void);
|
||||
|
||||
extern uint8_t (*popcountll)(uint64_t num);
|
||||
void detect_processor_features();
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _VMM_H
|
||||
#define _VMM_H
|
||||
#include "types.h"
|
||||
|
||||
#define CANONICAL_MASK_KERNEL 0xFFFF800000000000
|
||||
#define CANONICAL_MASK_USER 0x00007FFFFFFFFFF000
|
||||
|
||||
int vmm_alloc(void** vaddr, uint64_t count, uint64_t flags);
|
||||
int vmm_free(void* vaddr);
|
||||
#endif
|
||||
+36
-15
@@ -1,22 +1,28 @@
|
||||
#include "errno.h"
|
||||
#include "types.h"
|
||||
#include <bootloader.h>
|
||||
#include <kernel.h>
|
||||
#include <paging.h>
|
||||
#include <serial.h>
|
||||
#include <splash.h>
|
||||
#include <system.h>
|
||||
#include <gdt.h>
|
||||
#include <isr.h>
|
||||
#include <kernel.h>
|
||||
#include <paging.h>
|
||||
#include <pmm.h>
|
||||
#include <random.h>
|
||||
#include <serial.h>
|
||||
#include <splash.h>
|
||||
#include <string.h>
|
||||
#include <system.h>
|
||||
#include <vmm.h>
|
||||
|
||||
__noreturn
|
||||
void _start(void) {
|
||||
__noreturn void _start(void) {
|
||||
int err = 0;
|
||||
|
||||
// Serial console for debugging
|
||||
if ((err = serial_init(COM1)) < 0) panic(NULL, "Failed to initialize Serial driver. (%d)", err);
|
||||
if ((err = serial_init(COM1)) < 0)
|
||||
panic(NULL, "Failed to initialize Serial driver. (%d)", err);
|
||||
|
||||
// Load structures from bootloader
|
||||
if ((err = boot_init()) < 0) panic(NULL, "Failed to parse bootloader structures. (%d)", err);
|
||||
if ((err = boot_init()) < 0)
|
||||
panic(NULL, "Failed to parse bootloader structures. (%d)", err);
|
||||
|
||||
// CPUID thingy :p
|
||||
uint32_t eax = 0;
|
||||
@@ -24,18 +30,33 @@ void _start(void) {
|
||||
cpuid(&eax, (void*)&s[0], (void*)&s[8], (void*)&s[4]);
|
||||
pr_info("[kernel] CPUID_GETVENDORID: %s\n", s);
|
||||
|
||||
// enable processor extensions
|
||||
detect_processor_features();
|
||||
|
||||
// System init
|
||||
if ((err = gdt_init()) < 0) panic(NULL, "Failed to initalize GDT. (%d)", err);
|
||||
if ((err = isr_init()) < 0) panic(NULL, "Failed to initalize ISRs. (%d)", err);
|
||||
if ((err = gdt_init()) < 0)
|
||||
panic(NULL, "Failed to initalize GDT. (%d)", err);
|
||||
if ((err = isr_init()) < 0)
|
||||
panic(NULL, "Failed to initalize ISRs. (%d)", err);
|
||||
|
||||
// Memory management
|
||||
if ((err = pmm_init()) < 0) panic(NULL, "Failed to initalize Physical Memory Manager. (%d)", err);
|
||||
if ((err = pag_init()) < 0) panic(NULL, "Failed to initalize Paging. (%d)", err);
|
||||
if ((err = pmm_init()) < 0)
|
||||
panic(NULL, "Failed to initalize Physical Memory Manager. (%d)",
|
||||
err);
|
||||
if ((err = pag_init()) < 0)
|
||||
panic(NULL, "Failed to initalize Paging. (%d)", err);
|
||||
|
||||
|
||||
// test random number generation
|
||||
printk("Random number generation test:\n");
|
||||
for (uint8_t i = 0; i <= 16; i++) {
|
||||
printk("%d: %lu\n", i, get_random_number());
|
||||
}
|
||||
|
||||
// The most important function in the world.
|
||||
splash();
|
||||
|
||||
// Patiently wait for things to do :)
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
};
|
||||
|
||||
|
||||
+104
-6
@@ -1,12 +1,17 @@
|
||||
#include "errno.h"
|
||||
#include "kernel.h"
|
||||
#include "paging.h"
|
||||
#include "types.h"
|
||||
#include "vmm.h"
|
||||
#include <kmalloc.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <system.h>
|
||||
// this file contains SLUB inspired HEAP allocator
|
||||
|
||||
// TODO this will be an allocated array later when we have APIC MADT
|
||||
union per_cpu_freelist_cache freelists_all_cpus[1];
|
||||
union freelists_list freelists_all_cpus[1];
|
||||
union partialy_freelists_list partial_free_lists[1];
|
||||
|
||||
void* kcalloc(size_t count, size_t size) {
|
||||
size_t size_to_alloc;
|
||||
@@ -53,27 +58,120 @@ void* kmalloc(size_t size) {
|
||||
|
||||
size_t alloc_index;
|
||||
{
|
||||
// TODO remove buildin
|
||||
uint8_t leading_zeros = __builtin_clzll(size);
|
||||
if (__builtin_popcountll(size) == 1) {
|
||||
if (popcountll(size) == 1) {
|
||||
alloc_index = leading_zeros;
|
||||
} else {
|
||||
alloc_index = sizeof(size) * CHAR_BIT - leading_zeros;
|
||||
}
|
||||
if (alloc_index > KMALLOC_MAX_SIZE) {
|
||||
// NOT IMPLEMENTED
|
||||
printk("Cannot allocate [%lu] bytes: \e[1MNOT "
|
||||
"IMPLEMENTED!\e[8M\n",
|
||||
printk("Cannot allocate [%lu] bytes: \e[1mNOT "
|
||||
"IMPLEMENTED!\e[0m\n",
|
||||
size);
|
||||
return NULL;
|
||||
}
|
||||
alloc_index -= LOWEST_POWER;
|
||||
}
|
||||
void** selected_freelist =
|
||||
size_t object_size = (1 << (alloc_index + LOWEST_POWER));
|
||||
|
||||
struct freelist* selected_freelist =
|
||||
freelists_all_cpus[core_id].freelists[alloc_index];
|
||||
if (selected_freelist != NULL) {
|
||||
// fast path
|
||||
void** second_item_in_list = *selected_freelist;
|
||||
if (selected_freelist->nextnode == NULL) {
|
||||
freelists_all_cpus[core_id].freelists[alloc_index] =
|
||||
NULL;
|
||||
} else {
|
||||
freelists_all_cpus[core_id].freelists[alloc_index] =
|
||||
selected_freelist->nextnode;
|
||||
}
|
||||
return selected_freelist;
|
||||
|
||||
} else {
|
||||
// slower path
|
||||
if (partial_free_lists[core_id]
|
||||
.partialy_freelists[alloc_index] != NULL) {
|
||||
// partialy freelist available
|
||||
struct partialy_freelist* selected_partialy_freelist =
|
||||
partial_free_lists[core_id]
|
||||
.partialy_freelists[alloc_index];
|
||||
|
||||
if (selected_partialy_freelist->freelist_nextnode ==
|
||||
NULL) {
|
||||
// only one free object available
|
||||
if (selected_partialy_freelist
|
||||
->partialy_freelist_nextnode != NULL) {
|
||||
// next partialy free list
|
||||
// available
|
||||
partial_free_lists[core_id]
|
||||
.partialy_freelists[alloc_index] =
|
||||
selected_partialy_freelist
|
||||
->partialy_freelist_nextnode;
|
||||
|
||||
} else {
|
||||
// no other partialy free list
|
||||
// available
|
||||
partial_free_lists[core_id]
|
||||
.partialy_freelists[alloc_index] =
|
||||
NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
// multiple free objects available
|
||||
partial_free_lists[core_id]
|
||||
.partialy_freelists[alloc_index] =
|
||||
selected_partialy_freelist
|
||||
->partialy_freelist_nextnode;
|
||||
|
||||
freelists_all_cpus[core_id]
|
||||
.freelists[alloc_index] =
|
||||
selected_partialy_freelist
|
||||
->freelist_nextnode;
|
||||
}
|
||||
return selected_partialy_freelist;
|
||||
|
||||
} else {
|
||||
// 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) {}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "kernel.h"
|
||||
#include <system.h>
|
||||
#include <types.h>
|
||||
|
||||
uint64_t (*get_random_number)();
|
||||
|
||||
// this starting value it truly random i have thrown a dice few times
|
||||
uint64_t LFSR = 61113534451;
|
||||
|
||||
// RDSEED may be backdoored by NSA
|
||||
extern uint64_t rand_rdrand();
|
||||
asm(".intel_syntax noprefix\n"
|
||||
".global rand_rdrand\n"
|
||||
"rand_rdrand:"
|
||||
" rdrand rax\n"
|
||||
" ret\n"
|
||||
".att_syntax prefix\n");
|
||||
|
||||
uint64_t rand_software() {
|
||||
uint64_t lsb = LFSR & 1;
|
||||
LFSR >>= 1;
|
||||
if (lsb) {
|
||||
LFSR ^= 0x800000000000000DULL;
|
||||
}
|
||||
return LFSR;
|
||||
}
|
||||
|
||||
void rand_init(bool rdrand, bool rdseed) {
|
||||
|
||||
// check for RDRAND
|
||||
if (rdrand) {
|
||||
get_random_number = rand_rdrand;
|
||||
} else {
|
||||
printk("[\e[33mWARNING\e[0m] RDRAND not available falling back "
|
||||
"to software\n");
|
||||
// check for RDSEED
|
||||
if (rdseed) {
|
||||
asm(".intel_syntax noprefix\n"
|
||||
"rdseed %0\n"
|
||||
".att_syntax prefix\n"
|
||||
: "=r"(LFSR));
|
||||
} else {
|
||||
printk("[\e[\e[33mWARNING\e[0m] RDSEED not available "
|
||||
"falling back "
|
||||
"to developers dice trows\n");
|
||||
}
|
||||
get_random_number = rand_software;
|
||||
}
|
||||
printk("[\e[32mINFO\e[0m] RNG initialized!\n");
|
||||
}
|
||||
+60
-19
@@ -1,52 +1,93 @@
|
||||
#include "types.h"
|
||||
#include <kernel.h>
|
||||
#include <random.h>
|
||||
#include <system.h>
|
||||
|
||||
void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
|
||||
__asm__ volatile ("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(*eax)
|
||||
: "memory");
|
||||
__asm__ volatile("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(*eax)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
void iowait(void) {
|
||||
outb(0x80, 0);
|
||||
}
|
||||
void iowait(void) { outb(0x80, 0); }
|
||||
|
||||
uint8_t inb(uint16_t port) {
|
||||
uint8_t r;
|
||||
__asm__ volatile ("inb %1, %0" : "=a"(r) : "dN"(port));
|
||||
__asm__ volatile("inb %1, %0" : "=a"(r) : "dN"(port));
|
||||
return r;
|
||||
}
|
||||
|
||||
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 r;
|
||||
__asm__ volatile ("inw %1, %0" : "=a"(r) : "dN"(port));
|
||||
__asm__ volatile("inw %1, %0" : "=a"(r) : "dN"(port));
|
||||
return r;
|
||||
}
|
||||
|
||||
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 r;
|
||||
__asm__ volatile ("inl %1, %0" : "=a"(r) : "dN"(port));
|
||||
__asm__ volatile("inl %1, %0" : "=a"(r) : "dN"(port));
|
||||
return r;
|
||||
}
|
||||
|
||||
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) {
|
||||
__asm__ volatile ("cli");
|
||||
void cli(void) { __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) {
|
||||
__asm__ volatile ("sti");
|
||||
}
|
||||
void detect_processor_features() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#include "vmm.h"
|
||||
#include "kernel.h"
|
||||
#include <errno.h>
|
||||
#include <isr.h>
|
||||
#include <limits.h>
|
||||
#include <paging.h>
|
||||
#include <pmm.h>
|
||||
#include <random.h>
|
||||
#include <types.h>
|
||||
|
||||
// allocates set number of pages at address provided
|
||||
// if address is NULL address is chosen internaly
|
||||
int vmm_alloc(void** vaddr, uint64_t count, uint64_t flags) {
|
||||
if (flags == 0) {
|
||||
flags = PTE_FLAG_PRESENT | PTE_FLAG_WRITE | PTE_FLAG_NOEXEC;
|
||||
}
|
||||
bool random_vaddr = *vaddr ? false : true;
|
||||
|
||||
uint64_t* pml4 = pag_get_pml4();
|
||||
{
|
||||
uint8_t limit_counter = 0;
|
||||
while (true) {
|
||||
if (random_vaddr) {
|
||||
retry_selection:
|
||||
*vaddr = (void*)ALIGN_DOWN(get_random_number(),
|
||||
PAGE_SIZE);
|
||||
|
||||
*vaddr = (void*)((uint64_t)(*vaddr) &
|
||||
CANONICAL_MASK_USER);
|
||||
if (!(flags & PTE_FLAG_USER)) {
|
||||
*vaddr = (void*)((uint64_t)(*vaddr) |
|
||||
CANONICAL_MASK_KERNEL);
|
||||
}
|
||||
} else {
|
||||
if (flags & PTE_FLAG_USER) {
|
||||
if ((void*)((uint64_t)(*vaddr) &
|
||||
CANONICAL_MASK_KERNEL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (!((void*)((uint64_t)(*vaddr) &
|
||||
CANONICAL_MASK_KERNEL))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (uint64_t i = 0; i < count; i++) {
|
||||
uint64_t* pte =
|
||||
pag_get_pte(pml4, *vaddr + (i * PAGE_SIZE));
|
||||
if (!IS_ERR(pte) && (*pte & PTE_FLAG_PRESENT)) {
|
||||
if (!random_vaddr) {
|
||||
return -EEXIST;
|
||||
} else {
|
||||
if (limit_counter < UINT8_MAX) {
|
||||
goto retry_selection;
|
||||
} else {
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < count; i++) {
|
||||
void* paddr = pmm_alloc();
|
||||
int pag_map_ret =
|
||||
pag_map(pml4, *vaddr + (i * PAGE_SIZE), paddr, flags);
|
||||
if (pag_map_ret != SUCCESS) {
|
||||
if (i != 0) {
|
||||
for (i -= 1; i != UINT64_MAX; i--) {
|
||||
if (pag_unmap(pml4,
|
||||
*vaddr +
|
||||
(i * PAGE_SIZE)) !=
|
||||
SUCCESS) {
|
||||
panic(NULL,
|
||||
"failed to unmap "
|
||||
"previously mapped "
|
||||
"page. %s:%d",
|
||||
__FILE_NAME__, __LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pag_map_ret;
|
||||
}
|
||||
}
|
||||
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