#SnowOS
1 messages · Page 5 of 1
on windows ABI you cannot pass a 128 bit return value

and only 4 registers are used for arguments
otherwise its not as bad as i rememeber?
it doesnt allow to pass struct fields as registers
so e.g. string_view or similar gets a lot more expensive than on sysv
pointer to the struct on the caller's stack i think
also sysv is generaly just nice to work with in assembly imo
like look at this stack crap
On sysv I never really have to touch the stack for like most things
Esp for tiny leaf functions im making
Like this
uhhh, is there a flag to tell clang to use ths SysV ABI? I'd rather not spam __attribute__((sysv_abi)) everywhere
ah okay
You also want to disable the redzone
Because it’s a fancy part of the ABI
And for kernels interrupt handlers will fuck up the redzone
It’s basically a part of the stack for leaf functions to use as scratch space and not need to allocate from the shack
And IRQ handlers may push shit inside of it
🫠
Well
Rather the CPU will
I just told clang "make PE" 
figured
But also something that you possibly want to use in any case
uhhh, I think that's it? Not particularly interesting but eh 
[] - Tweak Spinlock Implementation
[] - Clean up code some
[] - Timer Interrupts
use LAPIC for timer IRQs
:3
its garunteed on all x86-64 chips
just needs clibration from another timer
Ye that's what I'm planning one :3
was gonna use the HPET for that
waow based based based based based
my kernel picks from ACPI Timer -> HPET -> PIT
then if the TSC is constant calibrate that
then use that for clibrstion of LAPIC
oh ye, I keep forgetting about the ACPI timer 😆
Oh! I also need to update to Limine 11
I think this should work?
static inline VOID SpinlockAcquire(PSPINLOCK Lock)
{
// Get the state of the IF before disabling interrupts
Lock->IntsEnabled = HalInterruptsEnabled();
__asm__ volatile ("cli" ::: "memory");
while (true)
{
if (!__atomic_exchange_n(&Lock->Flag, 1, __ATOMIC_ACQUIRE))
{
return;
}
while (__atomic_load_n(&Lock->Flag, __ATOMIC_RELAXED))
{
__asm__ volatile ("pause" ::: "memory");
}
}
}
static inline VOID SpinlockRelease(PSPINLOCK Lock)
{
__atomic_store_n(&Lock->Flag, 0, __ATOMIC_RELEASE);
if (Lock->IntsEnabled)
{
__asm__ volatile ("sti" ::: "memory");
}
else
{
__asm__ volatile ("cli" ::: "memory");
}
}
i wouldnt store it in the lock
it should be a return value
and you have the atomics reversed to be proper
and the return
🥀
also i hatr this code style but 
how come 
somthing takes the locks with IRQs disabled
then somthing takes it with them enabled
then when the first one returns
they get enabled
💥
using the [[nodiscard]] attrbute makes it so you cannot ignore the return value
making you pass it to the unlock funcion or similar
this better?
[[nodiscard]]
static inline BOOL SpinlockAcquire(PSPINLOCK Lock)
{
// Get the state of the IF before disabling interrupts
BOOL IntsEnabled = HalInterruptsEnabled();
__asm__ volatile ("cli" ::: "memory");
while (true)
{
if (!__atomic_exchange_n(&Lock->Flag, 1, __ATOMIC_ACQUIRE))
{
break;
}
while (__atomic_load_n(&Lock->Flag, __ATOMIC_RELAXED))
{
__asm__ volatile ("pause" ::: "memory");
}
}
return IntsEnabled;
}
static inline VOID SpinlockRelease(PSPINLOCK Lock, BOOL IntsEnabled)
{
__atomic_store_n(&Lock->Flag, 0, __ATOMIC_RELEASE);
if (IntsEnabled)
{
__asm__ volatile ("sti" ::: "memory");
}
else
{
__asm__ volatile ("cli" ::: "memory");
}
}
yes i think so

no 
You don’t even need the brackets
what about it?
You can do an if and else
which brackets?
static inline VOID SpinlockRelease(PSPINLOCK Lock, BOOL IntsEnabled) {
__atomic_store_n(&Lock->Flag, 0, __ATOMIC_RELEASE);
if (IntsEnabled)
__asm__ volatile ("sti" ::: "memory");
else
__asm__ volatile ("cli" ::: "memory");
}
thats valid
I personally don't really like how that looks, hence why I didn't do it 
But why do you make it take like 3x likes of code
is it just to get your stats up

does it really matter 😭
lol
I hate gnu styles
I mean ig I can change it 

I mean there's nothing for the other CPUs to do but hey 
What’s the bootstrap allocator for?
For a freelist PMM and a buddy you can store the freelist nodes inside of the free pages themselves ;3
allocating pages for the PFNdb and mapping said PFNdb
no it is a bump allocator 🤣
also If I decide to go down the route of "scheduler inits before everything else" I'm pretty sure I need a bootstrap allocator as well
I mean you could just delay it until you have a heap setup
Do GDT IDT (to catch faults and panic) PMM/PFNDB VMM Heap -> scheduler
ik but liam said it was a good idea to setup the scheduler first before pretty much anything else :3 (ofc I'm doing it the easier way first because my brain can't handle that order of operations right now
)
Why would you want a scheduler before you can do basic memory management?
lots of things depend on the scheduler, or so I've been told 
My kernel inits the schedular very late lol
You also possibly want timers before the scheduler
I found it
I really should just take a screenshot of it at this point
so I don't have to go searching for it every time 🤣
How would you setup the scheduler if you cannot allocate memory properly?
Ask liam not me
but from my understanding, the scheduler doesn't really rely upon process creation to work, all it does is look a queue and say "yup, that thread gets to run next" 

yikes
okay both Limine and Flanterm should be updated now :3 lemme push the commit
there! 
also I got distracted lol
I'll uh, work on timer interrupts now ^w^
was debating on whether or not to support the PIT. On one hand, I would think any modern PC would have the HPET/ACPI Timer/TSC, on the other hand, I presume the PIT's fairly simple so it's kind of seems silly to not support it 
would ACPI be a Hal thing or a Ke thing, or maybe something else? 
idk I'll put it in Hal for now and I can move it somewhere else later if I need to
siiiiigh
huh? 😭

nothing is ever simple
what if I just copy the header to freestnd-c-hdrs 
no

once again, clang posing as MSVC is causing problems (at least I think that's the issue, intrin.h seems to be a MSVC thing)
okay wait hol' up
haha! I shrimply commented out the include in compiler.h 
don't ask why I said this, I don't think this makes any sense 
hmmm 
I'm guessing it's mapped with the HHDM?
seems like it

I really gotta implement proper VA allocation
in fact
I'll probably start on that right after timer interrupts
I'm just now seeing an issue with this code 
big oof
I'll read the vmem paper tmrw
this entire function is broken in fact (I'm fairly sure) what the frick was I thinking when I wrote this 🤣
Y'know what? on second thought maybe we'll go ahead and implement vmem tmrw lol
I can't wait to work on scheduling :3
fricking context-switching is what thwarted me the last time I tried to write SnowOS 😭
as evidenced by my crashouts 
you probably don't want to auto enable interrupts, lol
I'm aware, it's been fixed 
I should implement a ring buffer for logging 
It’s not so hard
I’d probably have a staging page or a few on BSS to log before your allocator is up
Then allocate a larger buffer
And copy it and reclaim the old buffer
Then you can let userspace read it
Ala dmesg
Make sure that it’s page aligned on the linker script
And that it’s padded properly etc
Though you could maybe use attributes
I don't have a linker script 

I dunno how to write one for PEs 😭
Why do you need to use a PE for the kernel
well I don't need to but I wanna
You don't need a linker script for making a section for any purpose in PE. Just look into samples of windows drivers for example. pragmas.
resource heaven:
https://learn.microsoft.com/en-us/cpp/preprocessor/section?view=msvc-170
It's incomparably better than elf.
I'm going on a road trip 
Which means SnowOS time!!!!
(or at least til my laptop dies in the car
)
I should probably consider writing some unit tests
Okay wait, my old Slab impl doesn't really sound like the same thing the paper describes. It seems like I pretty much wrote a Slab but just without object caching, which... seems like it kind of defeats the point of a Slab 😅
I should also take a looksie at how Windows does this 
Okay Vmem doesn't seem too dreadfully hard (I'm still too dumb to completely understand it but oh well
)
I should also read up on UVM :3
If you manage to figure it out
Let me know


Don’t be scared
I only skimmed it while I was half asleep
💀
That’s why I don’t get it to be clear
ye (resource allocation in general it seems, but virtual allocations seems to be the big thing)
Virtual allocations will be heavily wanted by Userspace iirc?
For the kernel I plan to use my buddy allocater for large allocations for kernel stacks etc
well, while I try to wrap my head around vmem, imma implment page unmapping functions, and maybe try to figure out how I can make the hal a dll 
Btw page unmap can be the same as mapping a page except setting its PTE to zero and doing a tlb invalidation
And maybe checking if that level is empty etc
(If you want to free the tables as you go but that can be seperate)
yup, that's exactly what I'm doing :3
Nice :3
okay so an arena is just a range of integers, simple enough
but like this I don't understand
The slab allocator can provide object caching for any vmem arena
doesn't the slab depend upon vmem?
how is it providing object caching then? 😭
They both depend on each other
vmem has this quantum caching thing that uses the slab allocator
I don't think it's worth it tho
Here's my implementation from a while ago
thx! I'll take a look at it :3
can't suck anymore than whatever I'll end up writing 
It’s pretty easy to implement anyways
okie, back to trying to implement vmem :3
is there some reaons this needs to return a pointer 
cuz like, doesn't that mean I need some way to allocate a vmem arena
oh wait
ah
At compile time we statically declare a few vmem arena structures and boundary tags to get us through boot.
well I guess there's my answer
solaris has a convention to do that for some reason, but I think it is better to let the caller pass a pointer
well I have a function that chucks stuff into a vmem arena struct
not much
but better than nothing 
no

I'm on vacation gimme a break lol
I will actually try today tho
gonna write a generic linked list impl
should class names be the same style as struct names or in PascalCase like I usually do? 
function overloading! Everyone's favorite 
having data in the second overload is actually kind of redundant now that I think of it
actually overloading might be annoying for debugging now that I think about it
ofc I can't debug my kernel rn anyhow so 
I say as if I don't use namespaces, which cause namemangling anyhow 
want mine in case?
it works somewhat well
sure 
oh ye, I forgor I can overload new 
also seems like the segment list needs to be ordered
range to use for the kernel heap``` okay so clearly this is the arena for VAs used for the kernel heap
Once we have the heap arena, we can create new boundary tags dynamically but then I can suddenly allocate things now that I have it? Even though it doesn't actually allocate pages
am I supposed to start the slab after creating the heap_arena?
I would think?
also pretty sure I need to use a hashmap for this
so I need to learn about those
ah, they don't seem that complicated
I shouldn't be having this much trouble trying to implement this 
what if I just try to do a more naive implementation of a VA allocator and come back to this later 
just so that I can get to do other things
eh screw it I think I'll do that 
sub title should be winter will come
I'm officially announcing that SnowOS will be completely rewritten into Rust! 
SnowOS - A modern OS written entirely in Rust
SnowOS
I'm pulling y'all's leg 
I don't think you could pay me enough to use a different language for this lol
anyhow
10 grand?
I really would like to get VA allocation setup to day 😔
no 
C++ foevaaaaa!!! >:3
You mark a hard bargain
200 grand when I get a load and take 3 mortgages on my house

That’s my final offer
okie I'm finally getting somewhere 
userspace impl of vmem is going well
I can't imagine actually implementing it in the kernel will be much harder :3
also might make the code style slightly less NT-pilled, for personality™
okay I think I'll focus on vmem for now, this seems slightly harder than I initially thought 😅
You need to make it more NT pilled than NT
gonna be heading back home today
maybe I'll actually get some work done :p
currently working on the freelists for an arena
I think I'll make my goal for this month to be to launch a userspace process
Surely I can get the scheduler done by the end of the month 
it was a bit of a pain for me XD
but now i can do that!
Mine didn't even work the last time I tried 
it's not that bad
Might clean the code up some before I continue
I forgot how boring this was 
if I ever try to change to code-style again, please yell at me 
I do think I like this style better though
extern "C" void keMain(void *snowbootInfo)
{
keRunConstructors();
hal::initialize();
hal::printString("Snow Operating System (c) 2025, 2026 UtsumiFuyuki\r\n");
ke::print("Yuki Kernel Version %d.%d.%d\r\n", YUKI_VERSION_MAJOR, YUKI_VERSION_MINOR, YUKI_VERSION_PATCH);
ke::print("Booted by: ");
if (snowbootInfo == nullptr)
{
ke::print("Limine %s\r\n\r\n", hal::blVersion());
}
else
{
ke::print("SnowBoot\r\n");
}
hal::initCpu();
mm::earlyInit();
hal::initializePaging();
mm::initialize();
mm::initializeVmm();
// We're done, just hang...
hal::haltCpu();
}
this code style is still ass because the
whatever
{

}
Why is that an issue? 😭

its too gnu
also why are you putting \r\n in every line
when your printf can convert \n to \r\n
I don't think I've ever seen a line of gnu code so I wouldn't know 
I can't be bothered rn, mostly
more pressing matters
Fine I'll change it 😛 for what it's worth I flip between the two anyhow 
I'm not a very experienced programmer gimme a break 
I'm trying to find mah style 
coolio :3
the font makes your name look like O++ Shill
barely any black separating space, because of the glow
Oh it does 

when'd I start trying to implment vmem?
like a week ago 
anyhow
think I hafta implement vmemFree now
just trying to get something simple setup :3
also need to figure out what the heck I do about sources 😭
freeing is a bit more complicated than allocating lol
You do have to keep coalescing in mind tho
I only have instantfit implemented at the moment lol. Though bestfit and nextfit don't seem that complicated
WE GOT SOMETHING WORKING!!! 
seems to work! ^w^
I guess I'll find out later if it's broken 
Anyhow now I have to make it actually put the newly freed segment back onto the freelist, because currently I'm only manipulating the segment list
this is so messy 
granted this is my first time writing a coalescing, ordered freelist, so I guess it's bound to be a little messy
what are you having trouble with
ahhh nooo
why are you using pow
you can very quickly get one size's freelist using log2
and log2 is pretty damn fast
base 2 logarithm
ah
you can implement it very cheaply using ctlzl
yeah I dunno how to do logarithms so that probably explains why I didn't think of it
now that you say it though that does make more sense
you dont ever need to iterate over 64 freelists
the rotor handling is wrong i am an idiot
I don't even know what "rotor" means 😭
ah
okie :3
okay I went ahead and pushed the commit, I'll work on the freelist manipulation tmrw :p
aight, Imma go work on my math some, and then by like, 7 or 8 I'll do some more OSDev >:3
Aight, I need to write a log2 function, uh, however I'm supposed to do that 
feel free to look at mine, be aware it isn't my work. it's a combination of freebsd code and questioning an LLM to kind of understand the concepts as a non mathematician
but I know it works, and didn't didn't want to spend time making maths stuff
According to stackoverflow if you just need it to work for integers
Or looping methods
ah okie! neat :3
it's more work for floating point
I can't be bothered to do floating point rn 
check log and log2f
https://github.com/brainboxdotcc/retro-rocket/blob/master/src/maths.c#L158
(I don't think I need it rn anyhow)
I needed it to work with double, and didn't know my naive approach was wrong until I tried to make an xm player
This
this is undefined for zero and only works for positive integers
what's ctlzl? 😅
the 2nd one never increments index so is an infinite loop
Me when you can add a few if statments
Sorry clzl
isn't there an sse2 log2?
okay that makes more sense lol
Integer log2 is really cheap idk why you'd use sse or something more complex
Yeah but use gcc intrinsics
for when you want real maths
just to ask, is there a reason I shouldn't use std::countl_zero()?
You don't need that here
if you're implementing libm you'd need it
He's not implementing libm
well they haven't said what the use case of log2 is
what's libm? 
generic maths lib
finding which freelist a segment belongs to (vmem)
that is, freelist[n] contains all free segments
whose sizes are in the range [2n, 2n+1). To allocate a
segment we search the appropriate freelist for a
segment large enough to satisfy the allocation.```
isn't this just bit shifts
it's <<
and yeah lzcnt
I use the bit count intrinsics in my FS driver
What you wanna do is 64 - clzl(num) - 1
okay yeah, figured :3
it works! 
uhhhh, how do I actually coalesce the block though
because it's getting chucked onto the freelist the block it was allocated from isn't on
actually do I have to change the freelist a block is on upon allocation? Since it's size has changed?
hmm?
Like, my initial free segment has a size of 0xF0000000 and get's put on freelist 31. And say eventually after some allocations it's size goes down to 0x70000000, which should now be on freelist 30, even though it should be on freelist 30 now, it remains on freelist 31, which seems like it would kind of defeat the point of having a size segregated freelist 
You would split it

You need to remove the segment and put it back on its appropriate freelist
okay figured 👍
segment we search the appropriate freelist for a
segment large enough to satisfy the allocation.```
Slight question, I would *presume* that I also check freelists above n, in the case that freelist[n] is empty. I don't get the feeling I'm supposed to just fail the allocation if freelist n is empty, wouldn't make much sense 
Yes
okay I think I just have to fix this?
And then I should have an, albeit janky, technically working vmem implementation
Emphasis on the "technically" 
it'll probably break eventually, but I'll cross that road when I get there
No FRED implementing 
I mean it would be a decent break
It’s actually not too bad to implement imo
Though it does look like your vmem is going well
FRED I'll either try to implement after this or after I work on scheduling some 
I really wanna work on scheduling >:3
FRED does swap up how you may do some of that with entry into userspace :3
(It’s not bad tho)
uhh, as incomplete as my vmem implementation is I know that shouldn't be happening 
time to spam printfs 
lmfaoooo
ah yes, vmemAllocate is broken, idk why I did it the way I did 
for (auto *currentNode = arena->segmentList.getHead(); currentNode != nullptr; currentNode = currentNode->next) {
// Find corresponding node in segment list
if (currentNode->data.segmentBase == head->data.segmentBase && currentNode->data.type != VMEM_SEGMENT_SPAN) {
if (currentNode->data.segmentSize == size) {
currentNode->data.type = VMEM_SEGMENT_ALLOCATED;
return currentNode->data.segmentBase;
}
auto *allocatedNode = &initNodes[nextFreeNode];
allocatedNode->data.segmentSize = size;
allocatedNode->data.segmentBase = currentNode->data.segmentBase;
allocatedNode->data.type = VMEM_SEGMENT_ALLOCATED;
currentNode->data.segmentBase += size;
arena->segmentList.insert(currentNode, allocatedNode);
nextFreeNode++;
return allocatedNode->data.segmentBase;
}
}
``` for some reason I do this, which would *usually* work, except because the freelist doesn't get coalesced properly (working on figuring out how to do that) there's no longer a "corresponding node" and it just returns 0 lol
pretty simple fix tho :3
freeing must also be broken I suppose 
how it's broken idk 
but evidently uACPI is not happy
eh, I'll figure it out later :p
I honestly may work on scheduling some rn 
since I don't actually need a timer
well that ain't very helpful =/
boy I sure wish LLDB would work lol
try llvm-addr2line or just objdump it
ah well that worked! :3
weird
I shouldn't be calling any uACPI functions atm =/
I'm guessing my context switch is screwed up in some way then 
you may have rebuilt the executable and now that address is wrong
ah yeah
oh god I'm dumb

mov rsp, [rcx+128]
mov rax, [rcx+8]
mov rbx, [rcx+16]
mov rcx, [rcx+24]
mov rdx, [rcx+32]
``` gee, I wonder what the issue here could possibly be  (does it matter if I move in values from a thread struct into the gp regs, or should I put them on the stack?)
hmm, yeah seems like they should be on the stack 
What’s this for?
/ what’s the context for this
context switch
And Intel or Nasm
lol

this should be all you need
extern void thread_switch(spinlock_t* spinlock, int irqs, uint64_t* old_sp, uint64_t new_sp);
then after calculating the thread its a
uint64_t* old_rsp = &previous_thread->krsp;
uint64_t new_rsp = next_thread->krsp;
thread_switch(&scheduler_spinlock, lock1r, old_rsp, new_rsp);
aren't you supposed to iret?
Not for a thread switch
ah
That’s for when you need a privelege change
This does assume that you setup a threads stack properly though
And pre push things initially
eg
uhhh, what does ret pop off the stack again?
okie
And I push many function pointers there
So when one returns it goes to the next etc
The first return here pops the first one off etc
And this will also break if you try and switch to the same exact thread iirc?
so wut happens when there's only one thread in the queue?
My schedular checks if the next thread is the same as the previous
And if so it won’t run switch
But just return
ah
this is the trampoline i use to make it properly follow sysv aswell
and this is to jump to CPL3 just to be complete
Oh btw sorry @hushed spire for dumping code
😅
I should have asked
Yooooo
Make one print A and the other B

or even better
make them take arguments proper etc
to control the behavior at thread start
now uhh, lemme implement the rest of the switch, because currently it only does half the work 
(use malloc if you do a string)
will do :3
I don't have malloc yet 
Or any kind of memory allocation
Because you can’t give it a local reference to a new thread
true
The Microsoft one I'm pretty sure
My code is for sysv ABI
Because it’s actualy sane

Your gonna need diff code then
ye figured
I couldn't figure out how to compile a PE with the SysV ABI 😭
x64 ABI hasn't gotten in my way that much yet tho so 
Fingers crossed
Just tweak the code to save and restore and swap the right registers
Okay, I'm gonna draw some, read OSTEP some, then I'll work more on thread-switching :3
after that I think I'm gonna go through the code and see if there's anything I can clean up
Aight 
What did OSTEP tell ya?
I haven't read it yet, it's too flipping windy outside 
I should just start reading it before I leave at this point 
I feel like it's never not windy
But not the low level code that’s required as per ABI and architecture

Which is generally easy enough to change early on
And esp if you make static asserts for the position if things
So your assembly won’t magically fuck up

anyhow I think it should maybe work rn
in theory anyways. Current conundrum is that setupStack well, pushes things onto the stack, and when I try to preform the switch the old thread will push things onto the stack (because it doesn't know it's already been setup) and then 💥
I'm thinking maybe just write a small trampoline 
That’s why you push them on the first time
And then when the initial thread gets preempted
It pushes things into the empty stack
So it just kinda works
it saves things on the current stack. swaps stacks. then returns
When you first setup scheduling
And enable it
The thing that gets preempted
Gets saved first
So it’s a bit funky but it works out for me
You can control that more specialy by making a dummy thread to get populated when it switches from it
And this either returns back into the previous thread from when after it called the task switchi
Or it returns into the dummy things you put into the stack

anything can call the scheudle function
not just an interupt
thread A -> calls task switch
the return value is pushed onto the stack
the asm pushes a bunch of things onto the stack
it swaps stacks
restores off of thread B's stack
Returns
thread B would have had the return value on its stack from when it called task switch
or if you had just made it
it wiuld have the things you pushed
for return to pop from
and jump to
okay, so what happens if I had just made thread A and thread B for the first time, and then tried to switch to one of them? 
how i have it here is not the best for SMP as shouldSchedule should be CPU local but
the idle thrread
thats the first thread the schedular will try and use
the kmain function then gets assigned
to that bit
because it does a save state
so the stuff you allocated and pushed to it dosnt matter
it just gets reused into the idle loop
in the rewrite id make it more intentinal but

it just sorta plays out fine
though it caused me confusion
and some issues now knowing it did that
@hushed spire because the task switch function says. okay im gonna save the currently running codes state on this stack. swap stacks. and then restore as if i had saved state before
hmmm, okay Imma just guess I wrote schedule() wrong or something then 
when you make a thread. you push things onto the stack so it can "restore" state when its the first time running
so you can do it blindly
show me
void ke::schedule() {
if (queue.empty()) {
ke::log(__FILE__, "Can't schedule anything, sadge =(\r\n");
}
else {
LL_NODE<THREAD_CONTROL_BLOCK> *oldThread = currentThread;
currentThread = currentThread->next;
contextSwitch(&oldThread->data, ¤tThread->data);
}
}
contextSwitch:
mov rsp, [rdx+128]
; Save current context
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rbp
push rsi
push rdi
push rdx
push rcx
push rbx
push rax
mov [rdx+128], rsp
mov rsp, [rcx+128]
pop rax
pop rbx
pop rcx
pop rdx
pop rdi
pop rsi
pop rbp
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
ret
``` I don't think I have to push *every* gp registers, but not sure if that matters for correctness
it would be alot easier if you did a
uint64_t* old_rsp = &previous_thread->krsp;
uint64_t new_rsp = next_thread->krsp;
thread_switch(&scheduler_spinlock, lock1r, old_rsp, new_rsp);
then its just
thread_switch:
; push crap
; swap stacks
mov [rdx], rsp
mov rsp, rcx
; unlock schedular when its safe and enable preemption if lock does so
call spinlock_unlock_nil
; pop same crap
ret
it puts the RSP into the thread strcuture
then it just needs to load the new one
doing it like this also lets the C/++ code do more of the work
for the compiler to do its job and optmise
fair
also makes it harder toi fuck up
if you do need magic offsets in ASM make sure to annotate them and add static asserts in the high level defintions too
so if you change things
you get reminded to fix the assemblt

else you will have bad things happen™
speaking of which I need to write assert() 
well I did kind of have to do a hack to get it to work, but 
now I'm cleaning my code up before doing anything else 
Did my magic words help?
A little bit? I still don't really know what I'm supposed to do tbh 
ig maybe I should have a main kernel thread?
not really
I don’t use one
I spawn the other threads
And then they call into kernel code where needed
Either via syscalls or if it’s a kernel thread just by calling it
You don’t need a “game loop”
You just spawn a thread for that sub system
Like for an NVME driver that may need to wake up and do work when it gets an interrupt
And some drivers are simple enough to just in on an interrupt context without its own thread for its own things
(Serial PS/2 somtimes)
How would I get the ball rolling then?
because trying to preform a context switch when there's no context to save it doesn't really like that 😅
Anyhow, I'll clean the codebase up some and then probably get started on FRED support if I haven't decided I've coded enough for one day 
FRED is life
FRED is god
FRED is the savior
you should have a context_load function
Oh, yeah wait I think that's what I'm doing
that would be pushing things on a new threads stack yeah?
yes
when would you want that?
was playing kirby :p
now I'll actually clean up the codebase some
anyone who has the time to take a looksie through the codebase and suggest improvments would be appreciated :3
I'm awake :3
The agenda for today will probably mainly be FRED
I'll also probably work on vmen some more if I have the time
Oh, I also think my PFNDB is mapping more pages than it's actually using, so I should fix that.

I was playing smash with my brother
and I have to run by Barnes & Noble rq
but when I get back... FRED TIME!!! 
Yoooooo
Remember if you need help
Press the triangle key on your keyboard for help
I'll read the FRED spec in the car 
56 pages or so yeah
FRED event delivery is always to ring 0 and ERETU returns only to ring 3, it is not
possible to enter ring 1 or ring 2 while FRED transitions are enabled.``` Lmao, even Intel knows rings 1 and 2 are useless 
Whaaaaat nooooo
Honestly they would be less useless if they had more protection things you can apply :x
But no they can still access all ram
And they barely lock anything off
heck is a shadow stack? 
its a stack that prevents ROP chains
its seperate and hidden
all call and ret functions also push there
and it verifies that and the normal stack match
ROP chains?
Return-oriented programming (ROP) is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as executable-space protection and code signing.
In this technique, an attacker gains control of the call stack to hijack program control flow and then executes carefully chosen machine inst...
Ah
@narrow storm where were those QEMU patches again?

Yeah it by default dedicated 8gb to the VM
lol
Also I hope that laptop has an Intel CPU
both my latitude and MSI have an intel yes lol
ah, okie
Also I’m sure it’s even slower but that’s just what I can eyeball from a few things

I mean it actually wasn't that bad 
It’s mostly the docs that are annoying tbf
Oh also you know what I picked for my bootstrap allocator?
Lazy free list
And tracking how much I’ve allocated into it
So then later when I do the later stage PMM
I can know what memory to not use from the mem map (as it’s bootstrap stuff)
And I can reclaim what’s left on the freelist after going through the memory map
oh cool, I just use a bump allocator tbh 
Mines basically that but it supports free so you can use it as primary if desired. Since you shouldn’t be freeing on bootstrap stuff it’s “the same”
But it also handles cross memory map regions etc
I really got to clean up my code
I'm sure there's a bunch of small stuff I haven't implemented 
We’ll get ready for FREZ
FRED
Do you wana do it in a hacky way
Or a non hacky way

Since the interrupt frames differ on the stack
non hacky way preferably. I think I do things in a hacky way enough as is lmao
You may wana use some magic 🪄
Which is chopping up the frame
Refer to how I did it because it’s nice
But basically I split the vector the registers saved and the frame pushed by the CPU
And then I pass the arguments through assembly for the IDT seperatly
Then in FRED it goes to C code which does the decoding and then sends it off with pointers to the right parts
push r12
push r13
push r14
push r15
mov rdi, rsp ; irq_saved_regs_t ; also same as lea rdi, [rsp + 0]
lea rsi, [rsp + 128] ; irq_cpu_frame_t
mov rdx, [rsp + 120] ; uint64_t vector
cld
sti
call dispatch_interrupt
cli
pop r15
pop r14
pop r13
For example this for IDT
Which id rework first to use this system
And to edit your C side structures where possible
void dispatch_interrupt(irq_saved_regs_t* regs, irq_cpu_frame_t* frame, uint64_t vector)
okie :3
Afaik this is the best way for performance and keeping it sane on both sides so
Nobody has corrected me

(Please correct me and show me benchmarks or proof)
fixed my cpuid function :3
When checking for FRED make sure that the subleaf is supported too :3
You need to make sure the leaf and subleaf
simics isnt that slow on my AMD pc
not fast, but bearable for testing
wouldn't want to do rendering on it
I have awoken

After I finish with my school stuff I might work on this some more :3
Bad Apple runs at like 10FPS or so
hmmm, mine is a lot faster than that on simics
ok not a lot
whats your CPU?
maybe 15fps? but that is gif streaming and gzip decompression
also my bad apple demo runs in CPL3 and uses SSE and other things. and its RLE compressON
so context switch overhead etc
esp for the mass of syscalls it spams for audio
its not fully utilising it
this is my fastest demo on simics
this is bad apple
bear in mind, its running on an interpterer, too
Maybe on windows they use hyperv instead of a custom driver
if they did, fred wouldn't work?
badly lol
I don't think it's hyperv, qemu runs under hyperv for me and that's blazingly fast
but a pain to get working at all
does audio work for you in simics?
and checking for the time etc
I'm finished with my school stuff, gonna give my other projects some love first tho :3
okie dokie
time for more fred ^w^
I uh, need to figure out what I'm actually doing next tho lol
You can always ask
okie, what should I do next evalyn 
FRED
oh wait
I might need rdmsr and wrmsr functions 
I mostly meant about FRED in specific lol, I have a rough idea of what I'm doing after this
Ahh
although I will take suggestions lol
Well first you want to tweak the IDT path to be more normalized
Like how I have it
So it can work with FRED easier
normalized? 
Since you want them to both end up calling the same dispatch function
The formats differ
But are similar enough
So you can get away with splitting it up into 3 things
The things you push. The vector and what the CPU pushes
okie dokie :3
So a FRED stack frame would look something like this right? 
(i have a C struct if you wana make sure)
but uhh it looks about right yeah. the parts not of event data and the reserved are the same as IDT btw except it always pushes it
okie figured 
My new kernel is actually a good reference for FRED this time too (well it will be perfect once I get userspace up soonish)
how come you clear the direction flag here btw?
cld
sti
call dispatch_interrupt
cli
It’s required by the systemv ABI
And things can be really bad if they aren’t compared to most other flags
ah
Eg making string operations run in the wrong direction
okay I think the interrupt dispatch code should be good now ^w^
Kind of late now so I think I'll start on actually implementing fred tomorrow
Show the class
...the class? 
I mean it's pretty much the same as yours except for some minor naming differences 
keInterruptDispatch:
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rsi
push rdi
push rbp
push rdx
push rcx
push rbx
push rax
mov rcx, rsp
lea rdx, [rsp + 128]
mov r8, [rsp + 120]
cld
sti
call keInterruptHandler
cli
pop rax
pop rbx
pop rcx
pop rdx
pop rbp
pop rdi
pop rsi
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
add rsp, 16
iretq
Did you make sure to add static asserts to the offsets in the C structure?
So if you ever change it it causes a compile time error
(Because then the assembly will break if you don’t fix it)
ah no, lemme do that :p
patpat
Static asserts are very nice for stuff esp for things that may be compiler/platform specific
(And ofc ASM interop)
aight, there we go :3
you mean like, arch abstractions?
Well rdmsr and cpuid is arch specific
But you want to abstract it to make it not annoying to use
tis what i do. instead of seperate functions for it all
then its a cpuid_check(CPUID_HAS_FRED) etc
ah, yeah mine is slightly less abstracted lmao
may i see?
namespace hal {
namespace x64 {
static inline CPUID_REGISTERS getCpuid(uint64_t rax, uint64_t rcx) {
CPUID_REGISTERS cpuidRegs{};
__asm__ volatile (
"cpuid" :
"=a"(cpuidRegs.rax),
"=b"(cpuidRegs.rbx),
"=c"(cpuidRegs.rcx),
"=d"(cpuidRegs.rdx) :
"a"(rax),
"c"(rcx)
);
return cpuidRegs;
}
}
}
``` I also need to add a check for whether or not CPUID is actually supported :p
All x86-64 CPUs have it
I mean I would think I don't really need a check in that case 
yeah you may wana abstract it extra becase you need alot of extra checks to ensure you dont get a garbage result
Yes
CPUID is on late 486s and all 586s
So like
Your fine lol
CPUID can also tell you your inside a virtual machine and what kind it is
And the CPU name and vendor
coolio 
you need to check in cpuid if cpuid is supported

what I do is I only do a few cpuid on boot and cache it
true, but some things you only need to check once in place
pub const CpuFeatures = struct {
x2apic: bool,
five_level_paging: bool,
gib_pages: bool,
tsc_deadline: bool,
fxsave: bool,
xsave: bool,
invariant_tsc: bool,
nx: bool,
pcid: bool,
smap: bool,
smep: bool,
pge: bool,
vendor: CpuVendor,
family: u8,
brand_string: [48]u8,
};
I fill this
I was thinking of doing something like that 
Same, I just pre parse all features I care about into bitmaps
@narrow storm what's up with the OR with 3 here? 
uint64_t star = ((uint64_t)(0x18 | 3) << 48) | ((uint64_t)0x08 << 32);
ah
The bottom 2 bits of the segment selector/register set the CPL
And if that’s incorrect there
Your kernel uhhhh
And have fun tracking it down to that
And it also depends on your CPU brand if it will or won’t do that too
oh how come I can't use an or here? :p
"bts $32, %%rax\n"
actually wait I may have just made a typo lol
but anyhow
@narrow storm 
You did it

You may want a bit more boot logs lol
I'm sure the code isn't perfect and I'll have to tweak it some, but it works! 
pretty sure I do, but they get printed to serial so they don't clog up the screen :p
Ah
I like big logs scrolling on my screen lol
But fair
Does your serial driver work on real hardware?

mine prob does
never checked XD
I have no way of testing it at the moment I'm afraid 😔
(My desktop has a working serial port and I have a cable)
(Next time I go and use it want me to test yours too)
sure :3
Also @hushed spire you may wana trigger a page fault for testing this
As you get a non zero error and vector
Also use format spesifiers to make your printfs look consistent

literally just did as you said that lol works fine :3
Sick :3
So, now that I've done that side-quest, I think I'll go back to finishing up my vmem implementation (for the time being), then move on to writing the Slab allocator, and then after that... working on the Object Manager maybe? 
Perhaps
aight, pretty sure my vmem implementation is complete enough that I can start on the slab allocator :3
Think I may just axe object caching and only cache object size for now 
send vmem implementation
un français qui fait du zig
insane
main thing I gotta figure out is proper coalescing
https://github.com/UtsumiFuyuki/SnowOS/blob/main/yuki/source/mm/vmem.cpp
...is there something I'm not getting here? 
ya un serveur osdev français en passant
I'll check it out and roast you

this is a double number, a perfect, like 1111, 2222, 3333, i love view this
fair lol
j'arrive 👀
il est pas ref dans la barre de recherche des serveurs pour ca je l'ai pas trouvé
dm
I'm sure there is, I don't have very high faith in my code 
also there seems to be NT larp but the code style is inconsistent
I did this all manually 💀 so yeah there's bound to be some screw-ups in places lol
idk, ask me from like, 6 months ago 
I presume the slab can allocate from itself for the bufctls for large slabs
also interestingly
of all its slabs. The slab list is partially sorted, in
that the empty slabs (all buffers allocated) come
first, followed by the partial slabs (some buffers
allocated, some free), and finally the complete slabs
(all buffers free, refcnt == 0).``` It seems my old slab impl used three seperate freelist instead of one partially sorted one
surely having three separate lists would be better though no? 
honestly I think imma just clean this up some first
wasn't really in an osdevving mood yesterday
I'll try to get some work done today tho :3
Now if only I had enough braincells to figure out what to fix 
