Feat: lab 4
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
**.img
|
**.img
|
||||||
**.elf
|
**.elf
|
||||||
**.cpio
|
**.cpio
|
||||||
|
.gdb_history
|
||||||
|
|||||||
45
Makefile
45
Makefile
@@ -5,7 +5,7 @@ GNU := $(ARCH)-linux-gnu
|
|||||||
GDB := $(GNU)-gdb
|
GDB := $(GNU)-gdb
|
||||||
|
|
||||||
QEMU := qemu-system-$(ARCH)
|
QEMU := qemu-system-$(ARCH)
|
||||||
QEMUFLAGS += -M raspi3b -display none -serial null -serial pty
|
QEMUFLAGS += -M raspi3b -display none -serial null
|
||||||
|
|
||||||
CC := $(GNU)-gcc
|
CC := $(GNU)-gcc
|
||||||
CCFLAGS += -Wall -Wextra -O0 \
|
CCFLAGS += -Wall -Wextra -O0 \
|
||||||
@@ -15,25 +15,32 @@ LD := $(GNU)-ld
|
|||||||
LDFLAGS += -g -nostdlib -no-pie
|
LDFLAGS += -g -nostdlib -no-pie
|
||||||
OBJCOPY := $(GNU)-objcopy
|
OBJCOPY := $(GNU)-objcopy
|
||||||
|
|
||||||
|
MISC_DIR := misc
|
||||||
|
QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb
|
||||||
|
|
||||||
|
LIB_DIR := lib
|
||||||
|
INCLUDE := -Iinclude
|
||||||
|
|
||||||
#TARGET := kernel8
|
#TARGET := kernel8
|
||||||
#TARGET_DIR := ./kernel
|
#TARGET_DIR := ./kernel
|
||||||
ELF := $(TARGET).elf
|
ELF := $(TARGET).elf
|
||||||
IMG := $(TARGET).img
|
IMG := $(TARGET).img
|
||||||
|
|
||||||
LD_SCRIPT := $(TARGET_DIR)/linker.ld
|
LD_SCRIPT := $(TARGET_DIR)/linker.ld
|
||||||
INCLUDE += -Iinclude
|
INCLUDE += -I$(TARGET_DIR)/include
|
||||||
LIB_DIR := ./lib
|
TARGET_LIB_DIR := $(TARGET_DIR)/lib
|
||||||
MISC_DIR := ./misc
|
|
||||||
QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb
|
|
||||||
|
|
||||||
BOOTLOADER_DIR := ./bootloader
|
BOOTLOADER_DIR := ./bootloader
|
||||||
ROOTFS_DIR := ./rootfs
|
|
||||||
|
|
||||||
|
# initramfs
|
||||||
|
ROOTFS_DIR := ./rootfs
|
||||||
CPIO := initramfs.cpio
|
CPIO := initramfs.cpio
|
||||||
QEMUFLAGS += -initrd $(CPIO)
|
QEMUFLAGS += -initrd $(CPIO)
|
||||||
|
|
||||||
SRCS := $(shell find $(TARGET_DIR) -name '*.[cS]') \
|
TARGET_SRCS := $(shell find $(TARGET_DIR) -maxdepth 1 -name '*.[cS]') \
|
||||||
$(shell find $(LIB_DIR) -name '*.c')
|
$(shell find $(TARGET_LIB_DIR) -name '*.[cS]')
|
||||||
|
TARGET_OBJS := $(TARGET_SRCS:%=%.o)
|
||||||
|
SRCS := $(shell find $(LIB_DIR) -name '*.c')
|
||||||
OBJS := $(SRCS:%=%.o)
|
OBJS := $(SRCS:%=%.o)
|
||||||
|
|
||||||
.PHONY: all build clean clean_target run kernel debug gdb
|
.PHONY: all build clean clean_target run kernel debug gdb
|
||||||
@@ -50,8 +57,8 @@ $(CPIO): $(shell find $(ROOTFS_DIR))
|
|||||||
$(IMG): $(ELF)
|
$(IMG): $(ELF)
|
||||||
$(OBJCOPY) -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
$(ELF): $(LD_SCRIPT) $(OBJS)
|
$(ELF): $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS)
|
||||||
$(LD) -o $@ -T $^ $(LDFLAGS)
|
$(LD) -o $@ -T $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS) $(LDFLAGS)
|
||||||
|
|
||||||
%.S.o: %.S
|
%.S.o: %.S
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
@@ -62,22 +69,26 @@ $(ELF): $(LD_SCRIPT) $(OBJS)
|
|||||||
$(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS)
|
$(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
-rm $(OBJS) $(CPIO)
|
||||||
$(MAKE) clean_target TARGET_DIR=./kernel TARGET=kernel8
|
$(MAKE) clean_target TARGET_DIR=./kernel TARGET=kernel8
|
||||||
$(MAKE) clean_target TARGET_DIR=./bootloader TARGET=bootloader
|
$(MAKE) clean_target TARGET_DIR=./bootloader TARGET=bootloader
|
||||||
|
|
||||||
clean_target:
|
clean_target:
|
||||||
-rm $(OBJS) $(ELF) $(IMG) $(CPIO)
|
-rm $(TARGET_OBJS) $(ELF) $(IMG)
|
||||||
|
|
||||||
run: all $(CPIO)
|
run: all $(CPIO)
|
||||||
|
$(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial pty
|
||||||
|
|
||||||
|
kernel: $(CPIO)
|
||||||
|
$(MAKE) build TARGET_DIR=kernel TARGET=kernel8
|
||||||
|
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio
|
||||||
|
|
||||||
|
bootloader: $(CPIO)
|
||||||
|
$(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader
|
||||||
$(QEMU) -kernel bootloader.img $(QEMUFLAGS)
|
$(QEMU) -kernel bootloader.img $(QEMUFLAGS)
|
||||||
|
|
||||||
kernel: all $(CPIO)
|
|
||||||
-killall screen
|
|
||||||
$(QEMU) -kernel kernel8.img $(QEMUFLAGS)
|
|
||||||
|
|
||||||
debug: all $(CPIO)
|
debug: all $(CPIO)
|
||||||
-killall screen
|
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio -S -s
|
||||||
$(QEMU) -kernel kernel8.img $(QEMUFLAGS) -S -s
|
|
||||||
|
|
||||||
gdb:
|
gdb:
|
||||||
$(GDB)
|
$(GDB)
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 64K
|
NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 32K
|
||||||
NEWRO (r) : ORIGIN = 0x20000, LENGTH = 16K
|
NEWRO (r) : ORIGIN = 0x18000, LENGTH = 8K
|
||||||
NEWDATA (rw) : ORIGIN = 0x24000, LENGTH = 16K
|
NEWDATA (rw) : ORIGIN = 0x1a000, LENGTH = 8K
|
||||||
NEWBSS (rw) : ORIGIN = 0x28000, LENGTH = 16K
|
NEWBSS (rw) : ORIGIN = 0x1c000, LENGTH = 8K
|
||||||
|
|
||||||
TEXT (rx) : ORIGIN = 0x80000, LENGTH = 64K
|
TEXT (rx) : ORIGIN = 0x80000, LENGTH = 32K
|
||||||
RO (r) : ORIGIN = 0x90000, LENGTH = 16K
|
RO (r) : ORIGIN = 0x88000, LENGTH = 8K
|
||||||
DATA (rw) : ORIGIN = 0x94000, LENGTH = 16K
|
DATA (rw) : ORIGIN = 0x8a000, LENGTH = 8K
|
||||||
BSS (rw) : ORIGIN = 0x98000, LENGTH = 16K
|
BSS (rw) : ORIGIN = 0x8c000, LENGTH = 8K
|
||||||
RAM (rw) : ORIGIN = 0x9c000, LENGTH = 4M
|
RAM (rw) : ORIGIN = 0xa4000, LENGTH = 4M
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <shell.h>
|
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
|
|
||||||
// extern uint64_t __kernel;
|
// extern uint64_t __kernel;
|
||||||
@@ -22,7 +21,7 @@ void main(void *dtb)
|
|||||||
kernel_header.buf[i] = uart_getb();
|
kernel_header.buf[i] = uart_getb();
|
||||||
|
|
||||||
uart_puts("received kernel size: ");
|
uart_puts("received kernel size: ");
|
||||||
uart_int(kernel_header.size);
|
uart_hex(kernel_header.size);
|
||||||
uart_puts(ENDL);
|
uart_puts(ENDL);
|
||||||
|
|
||||||
uart_puts("loaded addr: ");
|
uart_puts("loaded addr: ");
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ERR_NO_MEM 0x00000001
|
#define ERR_NO_MEM 0x00000001
|
||||||
#define ERR_UNREACHABLE 0x00000002
|
#define ERR_UNREACHABLE 0x00000002
|
||||||
#define ERR_CONVERSION 0x00000003
|
#define ERR_CONVERSION 0x00000003
|
||||||
#define ERR_VECTOR_OOR 0x00000101
|
#define ERR_OUT_OF_BOUND 0x00000004
|
||||||
|
#define ERR_INVALID_OP 0x00000005
|
||||||
|
#define ERR_INVALID_MEM 0x00000006
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void *simple_alloc(size_t size);
|
|
||||||
void *kmalloc(size_t size);
|
|
||||||
void kfree(void *ptr);
|
|
||||||
95
include/logger.h
Normal file
95
include/logger.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <uart.h>
|
||||||
|
|
||||||
|
#ifndef LOGLEVEL
|
||||||
|
#define LOGLEVEL 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOGGER_BUFLEN 0x100
|
||||||
|
|
||||||
|
static inline char *_do_nothing(char *dest, const char *) { return dest; }
|
||||||
|
static inline char *_logger_string(char *dest, const char *src)
|
||||||
|
{
|
||||||
|
while (*src != '\0')
|
||||||
|
*dest++ = *src++;
|
||||||
|
*dest = '\0';
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
static inline char *_logger_hex(char *dest, uint64_t x)
|
||||||
|
{
|
||||||
|
for (int n, c = 28; c >= 0; c -= 4) {
|
||||||
|
n = (x >> c) & 0xf;
|
||||||
|
n += (n > 9) ? 0x37 : 0x30;
|
||||||
|
*dest++ = (char)n;
|
||||||
|
}
|
||||||
|
*dest = '\0';
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
static inline char *_logger_pointer(char *dest, void *x)
|
||||||
|
{
|
||||||
|
*dest++ = '0';
|
||||||
|
*dest++ = 'x';
|
||||||
|
return _logger_hex(dest, (uint64_t)x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _I_HATE_C_LANG(msg) \
|
||||||
|
logger_cur = _Generic((msg), \
|
||||||
|
char * : _do_nothing, \
|
||||||
|
const char *: _do_nothing, \
|
||||||
|
default : _logger_string \
|
||||||
|
)(logger_cur, #msg " = "); \
|
||||||
|
logger_cur = _Generic((msg), \
|
||||||
|
char * : _logger_string, \
|
||||||
|
const char *: _logger_string, \
|
||||||
|
uint64_t : _logger_hex, \
|
||||||
|
default : _logger_pointer \
|
||||||
|
)(logger_cur, msg)
|
||||||
|
|
||||||
|
#define LOG(val) { \
|
||||||
|
if (logger_cur != logger_buf) \
|
||||||
|
logger_cur = _logger_string(logger_cur, ", "); \
|
||||||
|
_I_HATE_C_LANG(val); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FLUSH(prefix) { \
|
||||||
|
uart_puts(prefix); \
|
||||||
|
uart_puts(logger_buf); \
|
||||||
|
uart_puts(ENDL); \
|
||||||
|
logger_cur = logger_buf; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LOGLEVEL >= 0
|
||||||
|
#define ERROR(val) { \
|
||||||
|
LOG(val); \
|
||||||
|
FLUSH("[ERROR]: "); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define ERROR(val)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LOGLEVEL >= 1
|
||||||
|
#define INFOR(val) { \
|
||||||
|
LOG(val); \
|
||||||
|
FLUSH("[INFOR]: "); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define INFOR(val)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LOGLEVEL >= 2
|
||||||
|
#define DEBUG(val) { \
|
||||||
|
LOG(val); \
|
||||||
|
FLUSH("[DEBUG]: "); \
|
||||||
|
}
|
||||||
|
#define DEBUG_DTB(val) DEBUG(val)
|
||||||
|
#define DEBUG_MEM(val) DEBUG(val)
|
||||||
|
#else // #if LOGLEVEL >= 2
|
||||||
|
#define DEBUG(val)
|
||||||
|
#define DEBUG_DTB(val)
|
||||||
|
#define DEBUG_MEM(val)
|
||||||
|
#endif // #if LOGLEVEL >= 2
|
||||||
|
|
||||||
|
extern char logger_buf[LOGGER_BUFLEN];
|
||||||
|
extern char *logger_cur;
|
||||||
@@ -2,24 +2,11 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#define DEBUG(x) { \
|
|
||||||
uart_puts(#x " = "); \
|
|
||||||
uart_hex((unsigned int)(unsigned long)x); \
|
|
||||||
uart_puts(ENDL); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DEBUG_s(x) { \
|
|
||||||
uart_puts(#x " = "); \
|
|
||||||
uart_puts(x); \
|
|
||||||
uart_puts(ENDL); \
|
|
||||||
}
|
|
||||||
|
|
||||||
void uart_init();
|
void uart_init();
|
||||||
void uart_send(unsigned int c);
|
void uart_send(unsigned int c);
|
||||||
uint8_t uart_getb();
|
uint8_t uart_getb();
|
||||||
char uart_getc();
|
char uart_getc();
|
||||||
void uart_puts(const char *s);
|
void uart_puts(const char *s);
|
||||||
void uart_hex(unsigned int d);
|
void uart_hex(uint64_t d);
|
||||||
void uart_int(int d);
|
|
||||||
|
|
||||||
extern int is_uart_init;
|
extern int is_uart_init;
|
||||||
|
|||||||
@@ -40,13 +40,16 @@ typedef struct {
|
|||||||
|
|
||||||
#define FDT_PATH_BUFFER_LEN 0x10
|
#define FDT_PATH_BUFFER_LEN 0x10
|
||||||
|
|
||||||
typedef void (*fdt_callback_func_t)(const vector_t *props);
|
typedef void (*fdt_callback_func_t)(const vector_t *);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
const fdt_callback_func_t func;
|
const fdt_callback_func_t func;
|
||||||
} fdt_callback_t;
|
} fdt_callback_t;
|
||||||
|
|
||||||
void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props);
|
void fdt_traverse(const vector_t *struct_cbs);
|
||||||
void fdt_traverse(const vector_t *cbs);
|
|
||||||
|
|
||||||
extern void *dtb_addr;
|
extern void *dtb_start;
|
||||||
|
extern void *dtb_end;
|
||||||
|
extern void *dtb_memory_start;
|
||||||
|
extern void *dtb_memory_end;
|
||||||
|
extern vector_t *dtb_reserved_entries;
|
||||||
27
kernel/include/kmalloc.h
Normal file
27
kernel/include/kmalloc.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define KMALLOC_MAX_ALLOCATOR_SIZE 256
|
||||||
|
|
||||||
|
typedef struct kmalloc_header {
|
||||||
|
size_t unit;
|
||||||
|
size_t left;
|
||||||
|
void *begin;
|
||||||
|
struct kmalloc_header *page_prev, *page_next;
|
||||||
|
}__attribute__((packed)) kmalloc_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t left;
|
||||||
|
kmalloc_header_t *page_begin;
|
||||||
|
} kmalloc_allocator_t;
|
||||||
|
|
||||||
|
void init_mman_kmalloc();
|
||||||
|
void *simple_alloc(size_t size);
|
||||||
|
void *mman_alloc(size_t size);
|
||||||
|
void mman_free(void *ptr);
|
||||||
|
|
||||||
|
extern void *(*kmalloc)(size_t size);
|
||||||
|
extern void (*kfree)(void *ptr);
|
||||||
|
|
||||||
|
extern kmalloc_allocator_t mman_kmalloc_pool[KMALLOC_MAX_ALLOCATOR_SIZE + 1];
|
||||||
37
kernel/include/mman.h
Normal file
37
kernel/include/mman.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <dtb.h>
|
||||||
|
|
||||||
|
#define MMAN_NO_PAGE 0xffffffffffffffff
|
||||||
|
#define PAGE_SIZE (1 << 12)
|
||||||
|
|
||||||
|
// PAGE_FREE => available
|
||||||
|
// PAGE_ALLOCATED => this range is allocated explicitly
|
||||||
|
// PAGE_DIVIDED => this range is divided into smaller range
|
||||||
|
// PAGE_RESERVED => this range is reserved explicitly
|
||||||
|
typedef enum :uint8_t {
|
||||||
|
PAGE_FREE = 0,
|
||||||
|
PAGE_ALLOCATED = 1,
|
||||||
|
PAGE_DIVIDED = 2,
|
||||||
|
PAGE_RESERVED = 3,
|
||||||
|
} page_state_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
page_state_t state;
|
||||||
|
uint64_t maxsz;
|
||||||
|
} page_header_t;
|
||||||
|
|
||||||
|
void mman_init();
|
||||||
|
|
||||||
|
void *allocate_page(size_t page_cnt);
|
||||||
|
void free_page(void *ptr);
|
||||||
|
void reserve_page(void *begin, void *end);
|
||||||
|
|
||||||
|
void mman_fdt_memory_cb_func(const vector_t *props);
|
||||||
|
|
||||||
|
extern fdt_callback_t mman_dtb_memory_cb;
|
||||||
|
extern void *mman_memory_start;
|
||||||
|
extern void *mman_memory_end;
|
||||||
|
extern size_t mman_page_cnt;
|
||||||
|
extern page_header_t *mman_frame_array;
|
||||||
29
kernel/include/queue.h
Normal file
29
kernel/include/queue.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct queue_node {
|
||||||
|
struct queue_node *prev, *next;
|
||||||
|
uint64_t value;
|
||||||
|
} queue_node_t;
|
||||||
|
|
||||||
|
typedef struct queue {
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
queue_node_t *begin, *end;
|
||||||
|
} queue_t;
|
||||||
|
|
||||||
|
queue_t *make_queue();
|
||||||
|
|
||||||
|
uint64_t queue_back(const queue_t *queue);
|
||||||
|
uint64_t queue_front(const queue_t *queue);
|
||||||
|
|
||||||
|
void queue_push_back(queue_t *queue, uint64_t val);
|
||||||
|
void queue_push_front(queue_t *queue, uint64_t val);
|
||||||
|
|
||||||
|
#define QUEUE_BACK(type, queue) ((type *)queue_back(queue))
|
||||||
|
#define QUEUE_FRONT(type, queue) ((type *)queue_front(queue))
|
||||||
|
#define QUEUE_PUSH_BACK(queue, val) \
|
||||||
|
queue_push_back(queue, (uint64_t)val)
|
||||||
|
#define QUEUE_PUSH_FRONT(queue, val) \
|
||||||
|
queue_push_front(queue, (uint64_t)val)
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
|
|
||||||
uint32_t msb32(uint32_t);
|
uint32_t msb32(uint32_t);
|
||||||
|
uint64_t msb64(uint64_t);
|
||||||
|
|
||||||
uint32_t hton32(const uint32_t);
|
uint32_t hton32(const uint32_t);
|
||||||
uint32_t ntoh32(const uint32_t);
|
uint32_t ntoh32(const uint32_t);
|
||||||
@@ -23,9 +24,15 @@ void exit(int);
|
|||||||
|
|
||||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
|
#define MAX(x, y) (((x) < (y)) ? (y) : (x))
|
||||||
#define ALIGN4(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 2) + 1) << 2)
|
|
||||||
#define ALIGN8(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 3) + 1) << 3)
|
#define ALIGN(ptr, cnt) (void *)((( \
|
||||||
|
((uint64_t)(ptr) - 1) >> (cnt)) + 1) << (cnt))
|
||||||
|
|
||||||
|
#define ALIGN4(ptr) ALIGN(ptr, 2)
|
||||||
|
#define ALIGN8(ptr) ALIGN(ptr, 3)
|
||||||
|
#define ALIGN4K(ptr) ALIGN(ptr, 12)
|
||||||
|
|
||||||
#define BUMP(orig_type, bump_type, ptr) ( \
|
#define BUMP(orig_type, bump_type, ptr) ( \
|
||||||
(ptr = (orig_type *)((bump_type *)ptr + 1)), \
|
(ptr = (orig_type*)((bump_type*)ptr + 1)), \
|
||||||
((bump_type *)ptr - 1) \
|
((bump_type*)ptr - 1) \
|
||||||
)
|
)
|
||||||
@@ -12,7 +12,7 @@ typedef struct {
|
|||||||
vector_t *make_vector(size_t size);
|
vector_t *make_vector(size_t size);
|
||||||
|
|
||||||
uint64_t vec_at(const vector_t *vec, size_t idx);
|
uint64_t vec_at(const vector_t *vec, size_t idx);
|
||||||
vector_t *vec_push(vector_t *vec, uint64_t val);
|
void vec_push(vector_t *vec, uint64_t val);
|
||||||
|
|
||||||
#define VEC_AT(type, vec, idx) ((type *)vec_at((vec), (idx)))
|
#define VEC_AT(type, vec, idx) ((type *)vec_at((vec), (idx)))
|
||||||
#define VEC_PUSH(vec, val) vec = vec_push(vec, (uint64_t)val)
|
#define VEC_PUSH(vec, val) vec_push(vec, (uint64_t)val)
|
||||||
@@ -1,24 +1,43 @@
|
|||||||
|
#include <logger.h>
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
#include <dtb.h>
|
#include <dtb.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <uart.h>
|
|
||||||
#include <kmalloc.h>
|
#include <kmalloc.h>
|
||||||
#include <vector.h>
|
#include <vector.h>
|
||||||
|
|
||||||
void *dtb_addr;
|
void *dtb_start;
|
||||||
|
void *dtb_end;
|
||||||
|
void *dtb_memory_start;
|
||||||
|
void *dtb_memory_end;
|
||||||
|
vector_t *dtb_reserved_entries;
|
||||||
|
|
||||||
void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props)
|
fdt_reserve_entry_t *fdt_memory_cur;
|
||||||
|
uint32_t *fdt_struct_cur;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _fdt_struct_callback(const char *path, const vector_t *cbs, const vector_t *props)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)cbs->size; ++i)
|
for (int i = 0; i < (int)cbs->size; ++i)
|
||||||
if (!strcmp(path, VEC_AT(fdt_callback_t, cbs, i)->name))
|
if (!strcmp(path, VEC_AT(fdt_callback_t, cbs, i)->name))
|
||||||
VEC_AT(fdt_callback_t, cbs, i)->func(props);
|
VEC_AT(fdt_callback_t, cbs, i)->func(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *fdt_struct_cur;
|
static inline
|
||||||
|
void _memory_traverse()
|
||||||
|
{
|
||||||
|
dtb_reserved_entries = make_vector(0);
|
||||||
|
while (fdt_memory_cur->address != 0 || fdt_memory_cur->size != 0) {
|
||||||
|
DEBUG(ntoh64(fdt_memory_cur->address));
|
||||||
|
DEBUG(ntoh64(fdt_memory_cur->size));
|
||||||
|
|
||||||
|
VEC_PUSH(dtb_reserved_entries, fdt_memory_cur++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define nextnode(ptr) (void *)((((uint64_t)(ptr) >> 2) + 1) << 2)
|
#define nextnode(ptr) (void *)((((uint64_t)(ptr) >> 2) + 1) << 2)
|
||||||
void traverse(const char *path, const vector_t *cbs)
|
static inline
|
||||||
|
void _struct_traverse(const char *path, const vector_t *cbs)
|
||||||
{
|
{
|
||||||
vector_t *props = make_vector(0);
|
vector_t *props = make_vector(0);
|
||||||
|
|
||||||
@@ -31,7 +50,7 @@ void traverse(const char *path, const vector_t *cbs)
|
|||||||
|
|
||||||
switch (ntoh32(*fdt_struct_cur)) {
|
switch (ntoh32(*fdt_struct_cur)) {
|
||||||
case FDT_BEGIN_NODE:
|
case FDT_BEGIN_NODE:
|
||||||
BUMP(uint32_t, uint32_t, fdt_struct_cur);
|
++fdt_struct_cur;
|
||||||
fdt_node_path = (void *)fdt_struct_cur;
|
fdt_node_path = (void *)fdt_struct_cur;
|
||||||
do {
|
do {
|
||||||
BUMP(uint32_t, char, fdt_struct_cur);
|
BUMP(uint32_t, char, fdt_struct_cur);
|
||||||
@@ -39,19 +58,19 @@ void traverse(const char *path, const vector_t *cbs)
|
|||||||
BUMP(uint32_t, char, fdt_struct_cur); // '\0'
|
BUMP(uint32_t, char, fdt_struct_cur); // '\0'
|
||||||
|
|
||||||
fdt_struct_cur = ALIGN4(fdt_struct_cur);
|
fdt_struct_cur = ALIGN4(fdt_struct_cur);
|
||||||
traverse(fdt_node_path, cbs);
|
_struct_traverse(fdt_node_path, cbs);
|
||||||
break;
|
break;
|
||||||
case FDT_END_NODE:
|
case FDT_END_NODE:
|
||||||
fdt_struct_cur = nextnode(fdt_struct_cur);
|
fdt_struct_cur = nextnode(fdt_struct_cur);
|
||||||
goto traverse_callback;
|
goto traverse_struct_callback;
|
||||||
case FDT_PROP:
|
case FDT_PROP:
|
||||||
BUMP(uint32_t, uint32_t, fdt_struct_cur);
|
++fdt_struct_cur;
|
||||||
prop_header = BUMP(uint32_t, fdt_prop_header_t, fdt_struct_cur);
|
prop_header = BUMP(uint32_t, fdt_prop_header_t, fdt_struct_cur);
|
||||||
|
|
||||||
prop = kmalloc(sizeof(fdt_prop_t));
|
prop = kmalloc(sizeof(fdt_prop_t));
|
||||||
prop->len = ntoh32(prop_header->len);
|
prop->len = ntoh32(prop_header->len);
|
||||||
prop->name = dtb_addr +
|
prop->name = dtb_start +
|
||||||
ntoh32(((fdt_header_t *)dtb_addr)->off_dt_strings) +
|
ntoh32(((fdt_header_t *)dtb_start)->off_dt_strings) +
|
||||||
ntoh32(prop_header->nameoff);
|
ntoh32(prop_header->nameoff);
|
||||||
prop->value = (void *)fdt_struct_cur;
|
prop->value = (void *)fdt_struct_cur;
|
||||||
VEC_PUSH(props, prop);
|
VEC_PUSH(props, prop);
|
||||||
@@ -69,13 +88,23 @@ void traverse(const char *path, const vector_t *cbs)
|
|||||||
exit(ERR_UNREACHABLE);
|
exit(ERR_UNREACHABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse_callback:
|
traverse_struct_callback:
|
||||||
fdt_callback(path, cbs, props);
|
_fdt_struct_callback(path, cbs, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fdt_traverse(const vector_t *cbs)
|
void fdt_traverse(const vector_t *struct_cbs)
|
||||||
{
|
{
|
||||||
fdt_struct_cur = dtb_addr + ntoh32(((fdt_header_t *)dtb_addr)->off_dt_struct);
|
fdt_memory_cur = dtb_start +
|
||||||
|
ntoh32(((fdt_header_t *)dtb_start)->off_mem_rsvmap);
|
||||||
|
fdt_struct_cur = dtb_start +
|
||||||
|
ntoh32(((fdt_header_t *)dtb_start)->off_dt_struct);
|
||||||
|
dtb_end = dtb_start +
|
||||||
|
ntoh32(((fdt_header_t *)dtb_start)->totalsize);
|
||||||
|
|
||||||
traverse("", cbs);
|
DEBUG(fdt_memory_cur);
|
||||||
|
DEBUG(fdt_struct_cur);
|
||||||
|
_memory_traverse();
|
||||||
|
DEBUG_DTB("memory traverse done");
|
||||||
|
_struct_traverse("", struct_cbs);
|
||||||
|
DEBUG_DTB("struct traverse done");
|
||||||
}
|
}
|
||||||
@@ -29,14 +29,14 @@ void initrd_fdt_callback(const vector_t *props)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init_node(file_node_t *node) {
|
static inline void _init_node(file_node_t *node) {
|
||||||
node->l = nullnode;
|
node->l = nullnode;
|
||||||
node->r = nullnode;
|
node->r = nullnode;
|
||||||
node->rand = random();
|
node->rand = random();
|
||||||
node->node_size = 1;
|
node->node_size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pull_from(file_node_t *to, file_node_t *from)
|
static inline void _pull_from(file_node_t *to, file_node_t *from)
|
||||||
{
|
{
|
||||||
if (!from)
|
if (!from)
|
||||||
return;
|
return;
|
||||||
@@ -44,14 +44,14 @@ void _pull_from(file_node_t *to, file_node_t *from)
|
|||||||
to->node_size += from->node_size;
|
to->node_size += from->node_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pull(file_node_t *node)
|
static inline void _pull(file_node_t *node)
|
||||||
{
|
{
|
||||||
node->node_size = 1;
|
node->node_size = 1;
|
||||||
_pull_from(node, node->l);
|
_pull_from(node, node->l);
|
||||||
_pull_from(node, node->r);
|
_pull_from(node, node->r);
|
||||||
}
|
}
|
||||||
|
|
||||||
file_node_t *_merge(file_node_t *a, file_node_t *b)
|
static inline file_node_t *_merge(file_node_t *a, file_node_t *b)
|
||||||
{
|
{
|
||||||
if (!a || !b)
|
if (!a || !b)
|
||||||
return a ?: b;
|
return a ?: b;
|
||||||
@@ -66,7 +66,8 @@ file_node_t *_merge(file_node_t *a, file_node_t *b)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b)
|
static inline void _split(file_node_t *rt, const char *s,
|
||||||
|
file_node_t **a, file_node_t **b)
|
||||||
{
|
{
|
||||||
if (!rt) {
|
if (!rt) {
|
||||||
*a = *b = nullnode;
|
*a = *b = nullnode;
|
||||||
@@ -96,7 +97,7 @@ file_node_t *initrd_init(void)
|
|||||||
|
|
||||||
file_node_t *root = nullnode, *ltr, *rtr;
|
file_node_t *root = nullnode, *ltr, *rtr;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
header = BUMP(cpio_newc_header_t, cpio_newc_header_t, initrd_cur);
|
header = initrd_cur++;
|
||||||
|
|
||||||
filename = (void *)initrd_cur;
|
filename = (void *)initrd_cur;
|
||||||
if (!strcmp(filename, "TRAILER!!!"))
|
if (!strcmp(filename, "TRAILER!!!"))
|
||||||
@@ -124,8 +125,6 @@ file_node_t *initrd_init(void)
|
|||||||
newnode->filename = filename;
|
newnode->filename = filename;
|
||||||
newnode->filecontent = filecontent;
|
newnode->filecontent = filecontent;
|
||||||
|
|
||||||
DEBUG_s(filename);
|
|
||||||
|
|
||||||
_split(root, filename, <r, &rtr);
|
_split(root, filename, <r, &rtr);
|
||||||
root = _merge(ltr, _merge(newnode, rtr));
|
root = _merge(ltr, _merge(newnode, rtr));
|
||||||
}
|
}
|
||||||
@@ -133,7 +132,7 @@ file_node_t *initrd_init(void)
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_node_t *_node_bs(file_node_t *cur, const char *s)
|
static inline file_node_t *_node_bs(file_node_t *cur, const char *s)
|
||||||
{
|
{
|
||||||
if (!cur)
|
if (!cur)
|
||||||
return nullnode;
|
return nullnode;
|
||||||
114
kernel/lib/kmalloc.c
Normal file
114
kernel/lib/kmalloc.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#include <uart.h>
|
||||||
|
#include <errcode.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <mman.h>
|
||||||
|
|
||||||
|
extern uint64_t __heap_start;
|
||||||
|
extern uint64_t __heap_end;
|
||||||
|
|
||||||
|
void *(*kmalloc)(size_t size) = simple_alloc;
|
||||||
|
void (*kfree)(void *ptr) = (void (*)(void *))0x0;
|
||||||
|
|
||||||
|
kmalloc_allocator_t mman_kmalloc_pool[KMALLOC_MAX_ALLOCATOR_SIZE + 1];
|
||||||
|
|
||||||
|
void *_heap_top = (void *)0x0;
|
||||||
|
|
||||||
|
void init_mman_kmalloc()
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= KMALLOC_MAX_ALLOCATOR_SIZE; ++i)
|
||||||
|
mman_kmalloc_pool[i] = (kmalloc_allocator_t){
|
||||||
|
.left = 0,
|
||||||
|
.page_begin = (kmalloc_header_t *)0x0,
|
||||||
|
};
|
||||||
|
|
||||||
|
kmalloc = mman_alloc;
|
||||||
|
kfree = mman_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
// simple 8-byte aligned linear allocation
|
||||||
|
void *simple_alloc(size_t size)
|
||||||
|
{
|
||||||
|
if (!_heap_top) {
|
||||||
|
_heap_top = (void *)&__heap_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (size_t)ALIGN8(size);
|
||||||
|
|
||||||
|
if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end)
|
||||||
|
exit(ERR_NO_MEM);
|
||||||
|
|
||||||
|
void *ret = _heap_top;
|
||||||
|
_heap_top = (void *)((uint64_t)_heap_top + size);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PAGE_HEADER(ptr) ((kmalloc_header_t *)(((uint64_t)(ptr) >> 12) << 12))
|
||||||
|
|
||||||
|
void *mman_alloc(size_t unit)
|
||||||
|
{
|
||||||
|
unit = (size_t)ALIGN8(unit);
|
||||||
|
if (unit > (KMALLOC_MAX_ALLOCATOR_SIZE << 3))
|
||||||
|
return allocate_page(((unit - 1) >> 12) + 1);
|
||||||
|
|
||||||
|
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
||||||
|
if (!pool->left) {
|
||||||
|
void *page = allocate_page(1), *ptr = page + sizeof(kmalloc_header_t);
|
||||||
|
*(kmalloc_header_t *)page = (kmalloc_header_t){
|
||||||
|
.unit = unit,
|
||||||
|
.left = (PAGE_SIZE - sizeof(kmalloc_header_t)) / unit,
|
||||||
|
.begin = page + sizeof(kmalloc_header_t),
|
||||||
|
.page_prev = (kmalloc_header_t *)0x0,
|
||||||
|
.page_next = (kmalloc_header_t *)0x0,
|
||||||
|
};
|
||||||
|
*pool = (kmalloc_allocator_t){
|
||||||
|
.left = ((kmalloc_header_t *)page)->left,
|
||||||
|
.page_begin = (kmalloc_header_t *)page,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (; ptr + unit <= page + PAGE_SIZE; ptr += unit)
|
||||||
|
*(void **)ptr = ptr + unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ret = pool->page_begin->begin;
|
||||||
|
pool->page_begin->begin = *(void **)pool->page_begin->begin;
|
||||||
|
|
||||||
|
--pool->left;
|
||||||
|
--pool->page_begin->left;
|
||||||
|
if (!pool->page_begin->left)
|
||||||
|
pool->page_begin = *(void **)pool->page_begin->page_next;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mman_free(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr == ALIGN4K(ptr)) {
|
||||||
|
free_page(ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t unit = PAGE_HEADER(ptr)->unit;
|
||||||
|
kmalloc_allocator_t *pool = &mman_kmalloc_pool[unit >> 3];
|
||||||
|
if (!PAGE_HEADER(ptr)->left) {
|
||||||
|
PAGE_HEADER(ptr)->page_next = pool->page_begin;
|
||||||
|
pool->page_begin->page_prev = PAGE_HEADER(ptr);
|
||||||
|
pool->page_begin = PAGE_HEADER(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(void **)ptr = pool->page_begin->begin;
|
||||||
|
pool->page_begin->begin = ptr;
|
||||||
|
|
||||||
|
++pool->left;
|
||||||
|
++PAGE_HEADER(ptr)->left;
|
||||||
|
size_t cap = (PAGE_SIZE - sizeof(kmalloc_allocator_t)) / unit;
|
||||||
|
if (PAGE_HEADER(ptr)->left == cap && pool->left >= 2 * cap) {
|
||||||
|
if (PAGE_HEADER(ptr)->page_prev)
|
||||||
|
PAGE_HEADER(ptr)->page_prev->page_next = PAGE_HEADER(ptr)->page_next;
|
||||||
|
if (PAGE_HEADER(ptr)->page_next)
|
||||||
|
PAGE_HEADER(ptr)->page_next->page_prev = PAGE_HEADER(ptr)->page_prev;
|
||||||
|
free_page(PAGE_HEADER(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
248
kernel/lib/mman.c
Normal file
248
kernel/lib/mman.c
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
#include <mman.h>
|
||||||
|
#include <logger.h>
|
||||||
|
#include <errcode.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
#include <dtb.h>
|
||||||
|
#include <initrd.h>
|
||||||
|
|
||||||
|
extern uint64_t __kernel_start;
|
||||||
|
extern uint64_t __kernel_end;
|
||||||
|
extern uint64_t __heap_start;
|
||||||
|
extern uint64_t __stack_end;
|
||||||
|
|
||||||
|
fdt_callback_t mman_dtb_memory_cb = {
|
||||||
|
.name = "memory@0",
|
||||||
|
.func = mman_fdt_memory_cb_func,
|
||||||
|
};
|
||||||
|
|
||||||
|
void *mman_memory_start = 0x0;
|
||||||
|
void *mman_memory_end = 0x0;
|
||||||
|
size_t mman_page_cnt = 0;
|
||||||
|
page_header_t *mman_frame_array = 0x0;
|
||||||
|
|
||||||
|
void mman_fdt_memory_cb_func(const vector_t *props)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (int)props->size; ++i) {
|
||||||
|
if (!strcmp(VEC_AT(fdt_prop_t, props, i)->name, "reg")) {
|
||||||
|
mman_memory_start = (void *)(uint64_t)ntoh32(
|
||||||
|
*((uint32_t *)VEC_AT(fdt_prop_t, props, i)->value));
|
||||||
|
mman_memory_end = (void *)(uint64_t)ntoh32(
|
||||||
|
*((uint32_t *)VEC_AT(fdt_prop_t, props, i)->value + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an array-like binary tree structure, where LCH (left-child) will
|
||||||
|
// always be the largest 2^k size block while RCH not empty.
|
||||||
|
#define CUR (&mman_frame_array[idx])
|
||||||
|
#define LIDX (((idx + 1) << 1) - 1)
|
||||||
|
#define LCH (&mman_frame_array[LIDX])
|
||||||
|
#define RIDX (((idx + 1) << 1 | 1) - 1)
|
||||||
|
#define RCH (&mman_frame_array[RIDX])
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _pull(int idx, size_t sz)
|
||||||
|
{
|
||||||
|
if (LCH->state == PAGE_FREE && RCH->state == PAGE_FREE) {
|
||||||
|
if (CUR->state != PAGE_FREE) {
|
||||||
|
LOG("node merged");
|
||||||
|
DEBUG_MEM((uint64_t)idx);
|
||||||
|
}
|
||||||
|
CUR->state = PAGE_FREE;
|
||||||
|
}
|
||||||
|
if (LCH->state != PAGE_FREE || RCH->state != PAGE_FREE)
|
||||||
|
CUR->state = PAGE_DIVIDED;
|
||||||
|
switch (CUR->state) {
|
||||||
|
case PAGE_FREE:
|
||||||
|
CUR->maxsz = sz;
|
||||||
|
break;
|
||||||
|
case PAGE_DIVIDED:
|
||||||
|
CUR->maxsz = MAX(LCH->maxsz, RCH->maxsz);
|
||||||
|
break;
|
||||||
|
case PAGE_ALLOCATED:
|
||||||
|
case PAGE_RESERVED:
|
||||||
|
CUR->maxsz = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(ERR_UNREACHABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mman_init()
|
||||||
|
{
|
||||||
|
mman_memory_start = ALIGN4K(mman_memory_start);
|
||||||
|
mman_memory_end = ALIGN4K(mman_memory_end);
|
||||||
|
|
||||||
|
// 4KB per page
|
||||||
|
mman_page_cnt = (mman_memory_end - mman_memory_start) >> 12;
|
||||||
|
mman_frame_array = simple_alloc((mman_page_cnt << 1) * sizeof(page_header_t));
|
||||||
|
|
||||||
|
LOG(mman_memory_start);
|
||||||
|
LOG(mman_memory_end);
|
||||||
|
DEBUG_MEM((uint64_t)mman_page_cnt);
|
||||||
|
|
||||||
|
mman_frame_array[0] = (page_header_t){
|
||||||
|
.state = PAGE_FREE,
|
||||||
|
.maxsz = msb64(mman_page_cnt),
|
||||||
|
};
|
||||||
|
|
||||||
|
fdt_reserve_entry_t *entry = 0x0;
|
||||||
|
for (int i = 0; i < (int)dtb_reserved_entries->size; ++i) {
|
||||||
|
entry = VEC_AT(fdt_reserve_entry_t, dtb_reserved_entries, i);
|
||||||
|
LOG(ntoh64(entry->address));
|
||||||
|
DEBUG_MEM(ntoh64(entry->address) + ntoh64(entry->size));
|
||||||
|
reserve_page((void *)ntoh64(entry->address),
|
||||||
|
(void *)ntoh64(entry->address) + ntoh64(entry->size));
|
||||||
|
}
|
||||||
|
|
||||||
|
reserve_page(&__kernel_start, &__kernel_end);
|
||||||
|
reserve_page(&__heap_start, &__stack_end);
|
||||||
|
reserve_page(dtb_start, dtb_end);
|
||||||
|
reserve_page(initrd_start, initrd_end);
|
||||||
|
|
||||||
|
init_mman_kmalloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
|
||||||
|
{
|
||||||
|
uint64_t sz = r - l;
|
||||||
|
if (req > sz || req > CUR->maxsz) {
|
||||||
|
return MMAN_NO_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
|
||||||
|
switch (CUR->state) {
|
||||||
|
case PAGE_FREE:
|
||||||
|
if (req == sz) {
|
||||||
|
LOG("page allocated");
|
||||||
|
LOG(l);
|
||||||
|
DEBUG_MEM(r);
|
||||||
|
CUR->state = PAGE_ALLOCATED;
|
||||||
|
CUR->maxsz = 0;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
LCH->state = RCH->state = PAGE_FREE;
|
||||||
|
LCH->maxsz = msb64(m - l);
|
||||||
|
RCH->maxsz = msb64(r - m);
|
||||||
|
break;
|
||||||
|
case PAGE_DIVIDED:
|
||||||
|
break;
|
||||||
|
case PAGE_ALLOCATED:
|
||||||
|
case PAGE_RESERVED:
|
||||||
|
return MMAN_NO_PAGE;
|
||||||
|
default:
|
||||||
|
exit(ERR_UNREACHABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ret = MMAN_NO_PAGE;
|
||||||
|
if (ret == MMAN_NO_PAGE && LCH->maxsz >= req)
|
||||||
|
ret = _allocate_page(req, LIDX, l, m);
|
||||||
|
if (ret == MMAN_NO_PAGE && RCH->maxsz >= req)
|
||||||
|
ret = _allocate_page(req, RIDX, m, r);
|
||||||
|
_pull(idx, sz);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *allocate_page(size_t page_cnt)
|
||||||
|
{
|
||||||
|
if (msb64(page_cnt) != page_cnt)
|
||||||
|
exit(ERR_INVALID_OP);
|
||||||
|
|
||||||
|
uint64_t offset = _allocate_page(page_cnt, 0, 0, mman_page_cnt);
|
||||||
|
|
||||||
|
if (offset == MMAN_NO_PAGE)
|
||||||
|
exit(ERR_NO_MEM);
|
||||||
|
// return (void *)0x0;
|
||||||
|
|
||||||
|
return mman_memory_start + offset * (1 << 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _free_page(uint64_t req, int idx, uint64_t l, uint64_t r)
|
||||||
|
{
|
||||||
|
uint64_t sz = r - l;
|
||||||
|
|
||||||
|
switch (CUR->state) {
|
||||||
|
case PAGE_FREE:
|
||||||
|
return;
|
||||||
|
case PAGE_ALLOCATED:
|
||||||
|
if (req == l) {
|
||||||
|
LOG("page freed");
|
||||||
|
LOG(l);
|
||||||
|
DEBUG_MEM(r);
|
||||||
|
CUR->state = PAGE_FREE;
|
||||||
|
CUR->maxsz = sz;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case PAGE_DIVIDED:
|
||||||
|
break;
|
||||||
|
case PAGE_RESERVED:
|
||||||
|
default:
|
||||||
|
exit(ERR_UNREACHABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
|
||||||
|
if (l <= req && req < m)
|
||||||
|
_free_page(req, LIDX, l, m);
|
||||||
|
if (m <= req && req < r)
|
||||||
|
_free_page(req, RIDX, m, r);
|
||||||
|
_pull(idx, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_page(void *page)
|
||||||
|
{
|
||||||
|
if (ALIGN4K(page) != page)
|
||||||
|
exit(ERR_INVALID_OP);
|
||||||
|
|
||||||
|
uint64_t start = ((uint64_t)page - (uint64_t)mman_memory_start) >> 12;
|
||||||
|
_free_page(start, 0, 0, mman_page_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _reserve_page(uint64_t ql, uint64_t qr, int idx, uint64_t l, uint64_t r)
|
||||||
|
{
|
||||||
|
if (qr <= l || r <= ql)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t sz = r - l;
|
||||||
|
if (ql <= l && r <= qr && msb64(sz) == sz) {
|
||||||
|
if (CUR->state == PAGE_RESERVED)
|
||||||
|
return;
|
||||||
|
if (CUR->state != PAGE_FREE)
|
||||||
|
exit(ERR_INVALID_MEM);
|
||||||
|
|
||||||
|
LOG("page reserved");
|
||||||
|
LOG(l);
|
||||||
|
DEBUG_MEM(r);
|
||||||
|
CUR->state = PAGE_RESERVED;
|
||||||
|
CUR->maxsz = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t m = l + ((msb64(sz) == sz) ? (sz >> 1) : msb64(sz));
|
||||||
|
if (CUR->state == PAGE_FREE) {
|
||||||
|
LCH->state = RCH->state = PAGE_FREE;
|
||||||
|
LCH->maxsz = msb64(m - l);
|
||||||
|
RCH->maxsz = msb64(r - m);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ql < m)
|
||||||
|
_reserve_page(ql, qr, LIDX, l, m);
|
||||||
|
if (m < qr)
|
||||||
|
_reserve_page(ql, qr, RIDX, m, r);
|
||||||
|
_pull(idx, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve_page(void *begin, void *end)
|
||||||
|
{
|
||||||
|
uint64_t ql = ((uint64_t)begin - (uint64_t)mman_memory_start) >> 12;
|
||||||
|
uint64_t qr = (((uint64_t)end - (uint64_t)mman_memory_start - 1) >> 12) + 1;
|
||||||
|
|
||||||
|
LOG("reserve page");
|
||||||
|
LOG(ql);
|
||||||
|
DEBUG_MEM(qr);
|
||||||
|
_reserve_page(ql, qr, 0, 0, mman_page_cnt);
|
||||||
|
}
|
||||||
57
kernel/lib/queue.c
Normal file
57
kernel/lib/queue.c
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include <queue.h>
|
||||||
|
#include <errcode.h>
|
||||||
|
#include <utils.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
|
|
||||||
|
queue_t *make_queue()
|
||||||
|
{
|
||||||
|
queue_t *ret = kmalloc(sizeof(queue_t));
|
||||||
|
ret->size = 0;
|
||||||
|
ret->begin = kmalloc(sizeof(queue_node_t));
|
||||||
|
ret->end = kmalloc(sizeof(queue_node_t));
|
||||||
|
*ret->begin = *ret->end = (queue_node_t){
|
||||||
|
.prev = (queue_node_t *)ret->begin,
|
||||||
|
.next = (queue_node_t *)ret->end,
|
||||||
|
.value = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t queue_back(const queue_t *queue)
|
||||||
|
{
|
||||||
|
if (!queue->size)
|
||||||
|
exit(ERR_OUT_OF_BOUND);
|
||||||
|
return queue->end->prev->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t queue_front(const queue_t *queue)
|
||||||
|
{
|
||||||
|
if (!queue->size)
|
||||||
|
exit(ERR_OUT_OF_BOUND);
|
||||||
|
return queue->begin->next->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_back(queue_t *queue, uint64_t val)
|
||||||
|
{
|
||||||
|
queue->end->value = val;
|
||||||
|
queue->end->next = kmalloc(sizeof(queue_node_t));
|
||||||
|
*queue->end->next = (queue_node_t){
|
||||||
|
.prev = queue->end,
|
||||||
|
.next = queue->end->next,
|
||||||
|
.value = 0,
|
||||||
|
};
|
||||||
|
queue->end = queue->end->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void queue_push_front(queue_t *queue, uint64_t val)
|
||||||
|
{
|
||||||
|
queue->begin->value = val;
|
||||||
|
queue->begin->prev = kmalloc(sizeof(queue_node_t));
|
||||||
|
*queue->begin->prev = (queue_node_t){
|
||||||
|
.prev = queue->begin->prev,
|
||||||
|
.next = queue->begin,
|
||||||
|
.value = 0,
|
||||||
|
};
|
||||||
|
queue->begin = queue->begin->prev;
|
||||||
|
}
|
||||||
@@ -53,9 +53,14 @@ void hwinfo (void)
|
|||||||
|
|
||||||
void memalloc(size_t size)
|
void memalloc(size_t size)
|
||||||
{
|
{
|
||||||
DEBUG(size);
|
|
||||||
void *addr = kmalloc(size);
|
void *addr = kmalloc(size);
|
||||||
DEBUG(addr);
|
uart_puts("size: ");
|
||||||
|
uart_hex(size);
|
||||||
|
uart_puts(ENDL);
|
||||||
|
|
||||||
|
uart_puts("addr: ");
|
||||||
|
uart_hex((uint64_t)addr);
|
||||||
|
uart_puts(ENDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ls_initrd_callback(file_node_t *tr)
|
void ls_initrd_callback(file_node_t *tr)
|
||||||
@@ -4,18 +4,24 @@
|
|||||||
|
|
||||||
uint32_t msb32(uint32_t x)
|
uint32_t msb32(uint32_t x)
|
||||||
{
|
{
|
||||||
static const int msb[32] = {
|
uint32_t res = 0x0;
|
||||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
asm volatile(
|
||||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
"clz %[res], %[val]"
|
||||||
};
|
: [res] "=r" (res)
|
||||||
|
: [val] "r" (x)
|
||||||
|
);
|
||||||
|
return res == 32 ? 0 : (1 << (31 - res));
|
||||||
|
}
|
||||||
|
|
||||||
x |= x >> 1;
|
uint64_t msb64(uint64_t x)
|
||||||
x |= x >> 2;
|
{
|
||||||
x |= x >> 4;
|
uint64_t res = 0x0;
|
||||||
x |= x >> 8;
|
asm volatile(
|
||||||
x |= x >> 16;
|
"clz %[res], %[val]"
|
||||||
|
: [res] "=r" (res)
|
||||||
return msb[(uint32_t)(x * 0x07c4acddu) >> 27];
|
: [val] "r" (x)
|
||||||
|
);
|
||||||
|
return res == 64 ? 0 : ((uint64_t)1 << (63 - res));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hton32(const uint32_t h)
|
uint32_t hton32(const uint32_t h)
|
||||||
@@ -21,12 +21,12 @@ vector_t *make_vector(size_t size)
|
|||||||
uint64_t vec_at(const vector_t *vec, size_t idx)
|
uint64_t vec_at(const vector_t *vec, size_t idx)
|
||||||
{
|
{
|
||||||
if (idx >= vec->size)
|
if (idx >= vec->size)
|
||||||
exit(ERR_VECTOR_OOR);
|
exit(ERR_OUT_OF_BOUND);
|
||||||
|
|
||||||
return vec->data[idx];
|
return vec->data[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
vector_t *vec_push(vector_t *vec, uint64_t val)
|
void vec_push(vector_t *vec, uint64_t val)
|
||||||
{
|
{
|
||||||
if (vec->size == vec->cap) {
|
if (vec->size == vec->cap) {
|
||||||
uint64_t *old = vec->data;
|
uint64_t *old = vec->data;
|
||||||
@@ -35,5 +35,4 @@ vector_t *vec_push(vector_t *vec, uint64_t val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec->data[vec->size++] = val;
|
vec->data[vec->size++] = val;
|
||||||
return vec;
|
|
||||||
}
|
}
|
||||||
@@ -25,9 +25,11 @@ SECTIONS
|
|||||||
__bss_end = .;
|
__bss_end = .;
|
||||||
} >DATA
|
} >DATA
|
||||||
|
|
||||||
__stack_end = ORIGIN(RAM) + LENGTH(RAM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__heap_start = ORIGIN(RAM);
|
PROVIDE(__kernel_start = ORIGIN(TEXT));
|
||||||
__heap_end = ORIGIN(RAM) + 32M;
|
PROVIDE(__kernel_end = ORIGIN(DATA) + LENGTH(DATA));
|
||||||
__bss_size = (__bss_end - __bss_start)>>3;
|
PROVIDE(__heap_start = ORIGIN(RAM));
|
||||||
|
PROVIDE(__heap_end = ORIGIN(RAM) + 32M);
|
||||||
|
PROVIDE(__stack_end = ORIGIN(RAM) + LENGTH(RAM));
|
||||||
|
PROVIDE(__bss_size = (__bss_end - __bss_start)>>3);
|
||||||
|
|||||||
@@ -1,25 +1,82 @@
|
|||||||
|
#include <logger.h>
|
||||||
|
#include <kmalloc.h>
|
||||||
#include <uart.h>
|
#include <uart.h>
|
||||||
#include <dtb.h>
|
#include <dtb.h>
|
||||||
#include <initrd.h>
|
#include <initrd.h>
|
||||||
|
#include <mman.h>
|
||||||
#include <shell.h>
|
#include <shell.h>
|
||||||
#include <vector.h>
|
#include <vector.h>
|
||||||
|
|
||||||
|
void init(void *dtb, file_node_t **initrd_root)
|
||||||
|
{
|
||||||
|
// UART
|
||||||
|
uart_init();
|
||||||
|
|
||||||
|
// Device tree
|
||||||
|
INFOR(dtb);
|
||||||
|
dtb_start = dtb;
|
||||||
|
vector_t *dtb_struct_cbs = make_vector(0);
|
||||||
|
VEC_PUSH(dtb_struct_cbs, &initrd_dtb_cb);
|
||||||
|
VEC_PUSH(dtb_struct_cbs, &mman_dtb_memory_cb);
|
||||||
|
fdt_traverse(dtb_struct_cbs);
|
||||||
|
DEBUG("device tree parse done");
|
||||||
|
|
||||||
|
// Initramfs
|
||||||
|
INFOR(initrd_start);
|
||||||
|
*initrd_root = initrd_init();
|
||||||
|
|
||||||
|
// Memory (Buddy system)
|
||||||
|
mman_init();
|
||||||
|
}
|
||||||
|
|
||||||
void main(void *dtb)
|
void main(void *dtb)
|
||||||
{
|
{
|
||||||
uart_init();
|
file_node_t *initrd_root = 0x0;
|
||||||
uart_getc();
|
init(dtb, &initrd_root);
|
||||||
|
|
||||||
DEBUG(dtb);
|
|
||||||
|
|
||||||
dtb_addr = dtb;
|
void *page1 = allocate_page(1);
|
||||||
vector_t *dtb_cbs = make_vector(0);
|
INFOR(page1);
|
||||||
VEC_PUSH(dtb_cbs, &initrd_dtb_cb);
|
|
||||||
fdt_traverse(dtb_cbs);
|
|
||||||
|
|
||||||
DEBUG(initrd_start);
|
void *page2 = allocate_page(2);
|
||||||
DEBUG(initrd_end);
|
INFOR(page2);
|
||||||
|
|
||||||
file_node_t *initrd_root = initrd_init();
|
void *page4 = allocate_page(4);
|
||||||
|
INFOR(page4);
|
||||||
|
|
||||||
|
void *page16 = allocate_page(16);
|
||||||
|
INFOR(page16);
|
||||||
|
|
||||||
|
free_page(page1);
|
||||||
|
free_page(page2);
|
||||||
|
free_page(page4);
|
||||||
|
free_page(page16);
|
||||||
|
|
||||||
|
void *page32 = allocate_page(32);
|
||||||
|
INFOR(page32);
|
||||||
|
page1 = allocate_page(1);
|
||||||
|
INFOR(page1);
|
||||||
|
|
||||||
|
free_page(page1);
|
||||||
|
|
||||||
|
void *kmalloc8 = kmalloc(8);
|
||||||
|
INFOR(kmalloc8);
|
||||||
|
kfree(kmalloc8);
|
||||||
|
|
||||||
|
kmalloc8 = kmalloc(8);
|
||||||
|
INFOR(kmalloc8);
|
||||||
|
kfree(kmalloc8);
|
||||||
|
|
||||||
|
void *kmalloc7k = kmalloc(7 * (1 << 10));
|
||||||
|
INFOR(kmalloc7k);
|
||||||
|
|
||||||
|
void *kmalloc8k = kmalloc(1 << 13);
|
||||||
|
INFOR(kmalloc8k);
|
||||||
|
|
||||||
|
kfree(kmalloc7k);
|
||||||
|
kfree(kmalloc8k);
|
||||||
|
|
||||||
|
page1 = allocate_page(1);
|
||||||
|
INFOR(page1);
|
||||||
|
|
||||||
int shell_cont = 1;
|
int shell_cont = 1;
|
||||||
while (shell_cont) {
|
while (shell_cont) {
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
#include <uart.h>
|
|
||||||
#include <errcode.h>
|
|
||||||
#include <utils.h>
|
|
||||||
#include <kmalloc.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
extern uint64_t __heap_start;
|
|
||||||
extern uint64_t __heap_end;
|
|
||||||
|
|
||||||
void *_heap_top = (void *)0;
|
|
||||||
|
|
||||||
// simple 8-byte aligned linear allocation
|
|
||||||
void *simple_alloc(size_t size)
|
|
||||||
{
|
|
||||||
if (!_heap_top) {
|
|
||||||
_heap_top = (void *)&__heap_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = (size_t)ALIGN8(size);
|
|
||||||
|
|
||||||
if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end)
|
|
||||||
exit(ERR_NO_MEM);
|
|
||||||
|
|
||||||
void *ret = _heap_top;
|
|
||||||
_heap_top = (void *)((uint64_t)_heap_top + size);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *kmalloc(size_t size)
|
|
||||||
{
|
|
||||||
return simple_alloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void kfree(void *ptr)
|
|
||||||
{
|
|
||||||
// not implemented for now
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
4
lib/logger.c
Normal file
4
lib/logger.c
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#include <logger.h>
|
||||||
|
|
||||||
|
char logger_buf[LOGGER_BUFLEN];
|
||||||
|
char *logger_cur = logger_buf;
|
||||||
@@ -95,7 +95,7 @@ void uart_puts(const char *s) {
|
|||||||
/**
|
/**
|
||||||
* Display a binary value in hexadecimal
|
* Display a binary value in hexadecimal
|
||||||
*/
|
*/
|
||||||
void uart_hex(const unsigned int d) {
|
void uart_hex(uint64_t d) {
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
int c;
|
int c;
|
||||||
for(c=28;c>=0;c-=4) {
|
for(c=28;c>=0;c-=4) {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
from pwn import *
|
|
||||||
|
|
||||||
kernel = open("kernel8.img", "rb").read()
|
|
||||||
r = serialtube("/dev/ttyS5", convert_newlines=False)
|
|
||||||
|
|
||||||
|
|
||||||
input("@")
|
|
||||||
r.send(str(len(kernel))+"\n")
|
|
||||||
#print(r.recv())
|
|
||||||
#r.interactive()
|
|
||||||
print(r.recvuntil(b") : "))
|
|
||||||
r.send(kernel)
|
|
||||||
|
|
||||||
|
|
||||||
r.interactive()
|
|
||||||
Reference in New Issue
Block a user