diff --git a/arch/x86_64/mem.c b/arch/x86_64/mem.c index 462efd5..2753850 100644 --- a/arch/x86_64/mem.c +++ b/arch/x86_64/mem.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/arch/x86_64/meson.build b/arch/x86_64/meson.build index b73eb4f..bdb743b 100644 --- a/arch/x86_64/meson.build +++ b/arch/x86_64/meson.build @@ -14,7 +14,6 @@ kernel_sources += files( 'mem.c', 'percpu.c', 'pmap.c', - 'pmap.c', 'random.c', 'sched.c', 'serial.c', diff --git a/arch/x86_64/sched.c b/arch/x86_64/sched.c index 1bfc345..f2cfbd2 100644 --- a/arch/x86_64/sched.c +++ b/arch/x86_64/sched.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,11 @@ struct task* arch_sched_switch(struct task* from, struct task* to) { return perform_switch(&from_ctx->rsp, to_ctx->rsp, from); } +constexpr size_t FPU_FCW_OFFSET = 0; +constexpr size_t FPU_MXCSR_OFFSET = 24; +constexpr uint16_t FPU_DEFAULT_FCW = 0x37F; +constexpr uint32_t FPU_DEFAULT_MXCSR = 0x1F80; + // Calls task_entry with the correct parameters. [[__naked]] void task_entry_thunk() { @@ -142,6 +148,11 @@ errno_t arch_task_init( context->fpu_region = (void*)fpu_base; context->fpu_phys = pages; + const uint16_t fcw = FPU_DEFAULT_FCW; + const uint32_t mxcsr = FPU_DEFAULT_MXCSR; + memcpy((uint8_t*)fpu_base + FPU_FCW_OFFSET, &fcw, sizeof(fcw)); + memcpy((uint8_t*)fpu_base + FPU_MXCSR_OFFSET, &mxcsr, sizeof(mxcsr)); + context->ds = asm_read_ds(); context->es = asm_read_es(); context->fs = asm_read_fs(); diff --git a/arch/x86_64/smp.c b/arch/x86_64/smp.c index 7feebc1..ccc36bb 100644 --- a/arch/x86_64/smp.c +++ b/arch/x86_64/smp.c @@ -148,7 +148,7 @@ static void smp_trampoline() { [kernel64_cs] "i"(offsetof(struct gdt, kernel_code64)), [kernel64_ds] "i"(offsetof(struct gdt, kernel_data64)), [cr0] "i"(CR0_PE | CR0_ET), - [cr0_pg] "i"(CR0_PG), + [cr0_pg] "i"((uint32_t)CR0_PG), [cr4_pae] "i"(CR4_PAE), [msr_efer] "i"(MSR_EFER), [efer_lme] "i"(MSR_EFER_LME), diff --git a/core/spin.c b/core/spin.c index 8cfac39..24d7897 100644 --- a/core/spin.c +++ b/core/spin.c @@ -17,6 +17,16 @@ void spin_lock(struct spinlock* spin) { } } +bool spin_trylock(struct spinlock* spin) { + irq_lock(); + uint32_t owner = atomic_load(&spin->owner, ATOMIC_RELAXED); + uint32_t expected = owner; + if (atomic_compare_exchange(&spin->next, &expected, owner + 1, ATOMIC_ACQUIRE, ATOMIC_RELAXED)) + return true; + irq_unlock(); + return false; +} + void spin_unlock(struct spinlock* spin) { uint32_t val = atomic_load(&spin->owner, ATOMIC_RELAXED); atomic_store(&spin->owner, val + 1, ATOMIC_RELEASE); diff --git a/fs/vfs/ident.c b/fs/vfs/ident.c index 24cf39d..5106fa3 100644 --- a/fs/vfs/ident.c +++ b/fs/vfs/ident.c @@ -5,3 +5,13 @@ static const struct ident kernel_identity = {0}; const struct ident* ident_kernel() { return &kernel_identity; } + +bool ident_in_group(const struct ident* identity, gid_t gid, bool use_real) { + if (gid == (use_real ? identity->gid : identity->egid)) + return true; + vec_foreach(&identity->groups, i) { + if (vec_elem_get(&identity->groups, i) == gid) + return true; + } + return false; +} diff --git a/include/zinnia/ident.h b/include/zinnia/ident.h index 7fd3ee1..b064716 100644 --- a/include/zinnia/ident.h +++ b/include/zinnia/ident.h @@ -11,3 +11,5 @@ struct ident { }; const struct ident* ident_kernel(void); + +bool ident_in_group(const struct ident* identity, gid_t gid, bool use_real); diff --git a/include/zinnia/list.h b/include/zinnia/list.h index d7c2114..9a8c025 100644 --- a/include/zinnia/list.h +++ b/include/zinnia/list.h @@ -10,7 +10,7 @@ type _sl_link; \ } -#define list_is_empty(head) ((head)->_sl_head == NULL) +#define list_is_empty(head) ((head)->_sl_head == nullptr) #define list_first(head) ((head)->_sl_head) #define list_next(elm, field) ((elm)->field._sl_link) diff --git a/include/zinnia/refcount.h b/include/zinnia/refcount.h index d1ede0f..7469cb2 100644 --- a/include/zinnia/refcount.h +++ b/include/zinnia/refcount.h @@ -16,6 +16,15 @@ static inline void refcount_inc(struct refcount* rc) { atomic_fetch_add(&rc->count, 1, ATOMIC_RELAXED); } +static inline bool refcount_inc_not_zero(struct refcount* rc) { + size_t count = atomic_load(&rc->count, ATOMIC_RELAXED); + do { + if (count == 0) + return false; + } while (!atomic_compare_exchange_weak(&rc->count, &count, count + 1, ATOMIC_ACQUIRE, ATOMIC_RELAXED)); + return true; +} + static inline bool refcount_dec(struct refcount* rc) { if (atomic_fetch_sub(&rc->count, 1, ATOMIC_RELEASE) != 1) return false; diff --git a/include/zinnia/spin.h b/include/zinnia/spin.h index 810e7ae..f513534 100644 --- a/include/zinnia/spin.h +++ b/include/zinnia/spin.h @@ -14,5 +14,7 @@ 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); +bool spin_trylock(struct spinlock* spin); + // Unlocks a spinlock. void spin_unlock(struct spinlock* spin);