more
This commit is contained in:
+1
-1
@@ -2,8 +2,8 @@
|
||||
#include <zinnia/cmdline.h>
|
||||
#include <zinnia/init.h>
|
||||
#include <zinnia/print.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include "limine.h"
|
||||
|
||||
[[__initdata_sorted("limine.0")]]
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include <zinnia/dpc.h>
|
||||
|
||||
// TODO
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// Compiler runtime support like libgcc or compiler-rt.
|
||||
// Extend as required.
|
||||
// Compiler runtime support.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
+1
-1
@@ -2,9 +2,9 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/pmap.h>
|
||||
#include <zinnia/spin.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/vma.h>
|
||||
#include <config.h>
|
||||
#include <zinnia/string.h>
|
||||
|
||||
// TODO: For now, we assume that we can do generic PTE lookups on every arch that has a MMU.
|
||||
static_assert(CONFIG_HAVE_MMU_GENERIC);
|
||||
|
||||
+1
-1
@@ -3,9 +3,9 @@
|
||||
#include <zinnia/panic.h>
|
||||
#include <zinnia/print.h>
|
||||
#include <zinnia/spin.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/virt.h>
|
||||
#include <stdint.h>
|
||||
#include <zinnia/string.h>
|
||||
|
||||
uintptr_t mem_hhdm_base = 0;
|
||||
|
||||
|
||||
+3
-4
@@ -60,7 +60,7 @@ static struct vma_mapping* find_mapping(struct vma* v, size_t page) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool access_allowed(enum prot_flags prot, const struct vma_fault_info* info) {
|
||||
static bool can_access(enum prot_flags prot, const struct vma_fault_info* info) {
|
||||
if (info->caused_by_write)
|
||||
return prot & PROT_WRITE;
|
||||
if (info->caused_by_fetch)
|
||||
@@ -87,7 +87,7 @@ bool vma_page_fault(struct vma* v, const struct vma_fault_info* info) {
|
||||
|
||||
spin_lock(&v->lock);
|
||||
struct vma_mapping* mapping = find_mapping(v, faulty_page);
|
||||
if (!mapping || !access_allowed(mapping->prot, info)) {
|
||||
if (!mapping || !can_access(mapping->prot, info)) {
|
||||
spin_unlock(&v->lock);
|
||||
return false;
|
||||
}
|
||||
@@ -107,8 +107,7 @@ bool vma_page_fault(struct vma* v, const struct vma_fault_info* info) {
|
||||
spin_lock(&v->lock);
|
||||
mapping = find_mapping(v, faulty_page);
|
||||
const bool still_valid = mapping && mapping->object == object &&
|
||||
(faulty_page - mapping->start_page) + mapping->offset_page == object_page &&
|
||||
access_allowed(mapping->prot, info);
|
||||
(faulty_page - mapping->start_page) + mapping->offset_page == object_page && can_access(mapping->prot, info);
|
||||
|
||||
if (still_valid) {
|
||||
errno_t status =
|
||||
|
||||
+20
-1
@@ -1,9 +1,9 @@
|
||||
#include <zinnia/alloc.h>
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/list.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <zinnia/vmo.h>
|
||||
#include <zinnia/string.h>
|
||||
|
||||
void vmo_ref(struct vmo* obj) {
|
||||
refcount_inc(&obj->rc);
|
||||
@@ -211,6 +211,25 @@ errno_t vmo_new_phys(struct paged_vmo** out) {
|
||||
return vmo_new_paged(phys_pager, out);
|
||||
}
|
||||
|
||||
void vmo_truncate_paged(struct paged_vmo* paged, size_t length) {
|
||||
const size_t page_size = arch_mem_page_size();
|
||||
const size_t keep_pages = ROUND_UP(length, page_size) / page_size;
|
||||
|
||||
spin_lock(&paged->lock);
|
||||
struct page_list** pp = &list_first(&paged->cache);
|
||||
while (*pp) {
|
||||
struct page_list* entry = *pp;
|
||||
if (entry->offset >= keep_pages) {
|
||||
*pp = list_next(entry, next);
|
||||
paged->source.put_page(&paged->source, entry->offset, entry->value);
|
||||
mem_free(entry);
|
||||
} else {
|
||||
pp = &list_next(entry, next);
|
||||
}
|
||||
}
|
||||
spin_unlock(&paged->lock);
|
||||
}
|
||||
|
||||
struct phys_range_vmo {
|
||||
struct vmo object;
|
||||
uintptr_t start;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
kernel_sources += files(
|
||||
'clock.c',
|
||||
'console.c',
|
||||
'elf.c',
|
||||
'irq.c',
|
||||
'module.c',
|
||||
'panic.c',
|
||||
|
||||
@@ -29,6 +29,9 @@ struct percpu* percpu_new() {
|
||||
const size_t size = __ld_percpu_end - __ld_percpu_start;
|
||||
const size_t num_pages = ALIGN_UP(size, arch_mem_page_size()) / arch_mem_page_size();
|
||||
|
||||
// TODO: Map pages past the end of the kernel.
|
||||
// TODO: Document how allocations work.
|
||||
|
||||
phys_t mem;
|
||||
if (mem_phys_alloc(num_pages, 0, &mem))
|
||||
return nullptr;
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#include <zinnia/spin.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
void spin_init(struct spinlock* spin) {
|
||||
spin->next = 0;
|
||||
spin->owner = 0;
|
||||
}
|
||||
|
||||
void spin_lock(struct spinlock* spin) {
|
||||
uint32_t my = atomic_fetch_add_explicit(&spin->next, 1, memory_order_relaxed);
|
||||
|
||||
|
||||
+1
-4
@@ -1,12 +1,9 @@
|
||||
subdir('common')
|
||||
subdir('block')
|
||||
subdir('dt')
|
||||
|
||||
if kconfig.get('CONFIG_ACPI', 'n') == 'y'
|
||||
subdir('acpi')
|
||||
endif
|
||||
|
||||
if kconfig.get('CONFIG_DT', 'n') == 'y'
|
||||
subdir('dt')
|
||||
endif
|
||||
|
||||
module_lds = meson.current_source_dir() / 'module.ld'
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <zinnia/sched.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <zinnia/vfs.h>
|
||||
#include <zinnia/vma.h>
|
||||
#include <zinnia/vmo.h>
|
||||
#include <bits/elf.h>
|
||||
@@ -0,0 +1,3 @@
|
||||
kernel_sources += files(
|
||||
'elf.c',
|
||||
)
|
||||
+1
-1
@@ -1 +1 @@
|
||||
subdir('tmpfs')
|
||||
subdir('exec')
|
||||
@@ -1 +0,0 @@
|
||||
kernel_sources += files('tmpfs.c')
|
||||
@@ -1 +0,0 @@
|
||||
// TODO
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <zinnia/ident.h>
|
||||
|
||||
static const struct ident kernel_identity = {0};
|
||||
|
||||
const struct ident* ident_kernel() {
|
||||
return &kernel_identity;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
kernel_sources += files(
|
||||
'ident.c',
|
||||
)
|
||||
+2
-2
@@ -17,12 +17,12 @@ struct __timeval {
|
||||
__suseconds_t tv_usec;
|
||||
};
|
||||
|
||||
struct itimerval {
|
||||
struct __itimerval {
|
||||
struct __timeval it_interval;
|
||||
struct __timeval it_value;
|
||||
};
|
||||
|
||||
struct itimerspec {
|
||||
struct __itimerspec {
|
||||
struct __timespec it_interval;
|
||||
struct __timespec it_value;
|
||||
};
|
||||
|
||||
@@ -26,7 +26,10 @@ struct phys_mem {
|
||||
|
||||
// Base address of the HHDM.
|
||||
extern uintptr_t mem_hhdm_base;
|
||||
#define HHDM_PTR(paddr) (void*)(mem_hhdm_base + (paddr))
|
||||
|
||||
static inline void* HHDM_PTR(phys_t paddr) {
|
||||
return (void*)(mem_hhdm_base + paddr);
|
||||
}
|
||||
|
||||
// Allocates a region of memory which can be smaller than the page size.
|
||||
// Returns `nullptr` if the allocator cannot provide an allocation for the given `length` + `flags`.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/list.h>
|
||||
#include <zinnia/percpu.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
struct dpc {
|
||||
void (*const callback)(struct dpc* dpc, void* data);
|
||||
void* data;
|
||||
atomic_bool inserted;
|
||||
|
||||
list_link(struct dpc*) link;
|
||||
};
|
||||
|
||||
void dpc_dispatch();
|
||||
|
||||
struct dpc_percpu {};
|
||||
extern struct dpc_percpu dpc_percpu_data;
|
||||
+1
-11
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/vfs.h>
|
||||
#include <bits/elf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -341,15 +342,4 @@ static inline uint32_t ELF64_R_TYPE(uint64_t info) {
|
||||
return info & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
struct vma;
|
||||
struct vmo;
|
||||
struct task;
|
||||
|
||||
struct exec_info {
|
||||
struct vma* space;
|
||||
struct vmo* file_obj;
|
||||
const char** argv;
|
||||
const char** envp;
|
||||
};
|
||||
|
||||
errno_t elf_load(struct exec_info* info, struct task** out);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct fdt_header {
|
||||
uint32_t magic;
|
||||
uint32_t total_size;
|
||||
uint32_t structs_offset;
|
||||
uint32_t strings_offset;
|
||||
uint32_t reserved_offset;
|
||||
uint32_t version;
|
||||
uint32_t compat_version;
|
||||
uint32_t boot_cpuid;
|
||||
uint32_t strings_size;
|
||||
uint32_t structs_size;
|
||||
};
|
||||
|
||||
constexpr uint32_t FDT_BEGIN_NODE = 0x00000001;
|
||||
constexpr uint32_t FDT_END_NODE = 0x00000002;
|
||||
constexpr uint32_t FDT_PROP = 0x00000003;
|
||||
constexpr uint32_t FDT_NOP = 0x00000004;
|
||||
constexpr uint32_t FDT_END = 0x00000009;
|
||||
|
||||
struct fdt {
|
||||
uint32_t version;
|
||||
uint32_t compat_version;
|
||||
uint32_t boot_cpuid;
|
||||
|
||||
const uint8_t* structs;
|
||||
size_t structs_len;
|
||||
const uint8_t* strings;
|
||||
size_t strings_len;
|
||||
};
|
||||
|
||||
struct fdt_node {
|
||||
struct fdt* tree;
|
||||
};
|
||||
|
||||
struct fdt_prop {
|
||||
struct fdt* tree;
|
||||
};
|
||||
|
||||
// Root of the device tree.
|
||||
struct fdt_node fdt_root(struct fdt* tree);
|
||||
@@ -1,5 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/types.h>
|
||||
#include <zinnia/vec.h>
|
||||
|
||||
struct ident {
|
||||
// TODO
|
||||
uid_t uid, euid, suid;
|
||||
gid_t gid, egid, sgid;
|
||||
|
||||
vec(gid_t) groups;
|
||||
};
|
||||
|
||||
const struct ident* ident_kernel(void);
|
||||
|
||||
+26
-1
@@ -1,12 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/string.h>
|
||||
#include <zinnia/usercopy.h>
|
||||
#include <zinnia/utils.h>
|
||||
#include <stddef.h>
|
||||
#include <uapi/uio.h>
|
||||
|
||||
struct iovec_iter {
|
||||
struct iovec* iovecs;
|
||||
struct __iovec* iovecs;
|
||||
size_t iovecs_len;
|
||||
size_t total_len;
|
||||
size_t total_offset;
|
||||
size_t current_idx;
|
||||
size_t current_offset;
|
||||
};
|
||||
|
||||
static inline size_t iovec_iter_len(struct iovec_iter* iter) {
|
||||
return iter->total_len - iter->total_offset;
|
||||
}
|
||||
|
||||
// Creates an iovec iterator over kernel memory.
|
||||
static inline struct iovec_iter iovec_iter_kernel(struct __iovec* iovecs, size_t count) {
|
||||
size_t total = 0;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
total += iovecs[i].len;
|
||||
|
||||
return (struct iovec_iter){
|
||||
.iovecs = iovecs,
|
||||
.iovecs_len = count,
|
||||
.total_len = total,
|
||||
.total_offset = 0,
|
||||
.current_idx = 0,
|
||||
.current_offset = 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ struct spinlock {
|
||||
_Atomic(uint32_t) next;
|
||||
};
|
||||
|
||||
void spin_init(struct spinlock* spin);
|
||||
|
||||
// Attempts to lock a spinlock. If it's already locked, waits until it's freed.
|
||||
void spin_lock(struct spinlock* spin);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ struct pager_ops {
|
||||
errno_t (*put_page)(struct pager_ops* pager, uintptr_t offset_idx, struct page* page);
|
||||
};
|
||||
|
||||
// TODO: change to btree
|
||||
// TODO: change to rbtree
|
||||
struct page_list {
|
||||
uintptr_t offset;
|
||||
struct page* value;
|
||||
@@ -50,5 +50,8 @@ struct paged_vmo {
|
||||
errno_t vmo_new_paged(struct pager_ops ops, struct paged_vmo** out);
|
||||
errno_t vmo_new_phys(struct paged_vmo** out);
|
||||
|
||||
// Drops all cached pages past `length` bytes.
|
||||
void vmo_truncate_paged(struct paged_vmo* paged, size_t length);
|
||||
|
||||
// Creates a VMO backed by a specific physical address range (e.g. for MMIO).
|
||||
errno_t vmo_new_phys_range(uintptr_t addr, size_t length, struct vmo** out);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ static struct __utsname uname_buf = {
|
||||
.version = CONFIG_KERNEL_FLAVOR,
|
||||
.nodename = "localhost",
|
||||
.machine = ZINNIA_ARCH,
|
||||
.domainname = "none",
|
||||
.domainname = "(none)",
|
||||
};
|
||||
|
||||
struct syscall_ret sys_setuname(const __user struct __utsname* ptr) {
|
||||
|
||||
Reference in New Issue
Block a user