#FrostyOS
1 messages ยท Page 5 of 1
and it fails very fast
of course it does
why wouldn't it
PMM test time
its very slow
this might take a while
its really weird that something that works well on kvm, fails instantly on plain tcg
the PMM test passes of course
why???
this doesn't make sense
maybe there is some memory corruption??
seems like there is something that a size in the PMM free list is not page aligned
there must be some edge case where that can happen
the error occurs at entry to the function
not at exit
which suggests corruption
its not being overwritten by a page table
maybe something else?
this is very annoying and strange
ubsan is off, so I'll try enabling it to see what difference it makes
it did something
the error is on free now
thats good
maybe
it might actually mean there is some ub
its at entry
so corruption it is...
a rewrite is definitely on my mind
If I don't figure this out soon, I might need to
theres no virtual memory overlap in PageManager regions
I think the VMM heap could be responsible
because, the bad region in the PMM free list looks a lot like a Heap ChunkHeader
I'm suspecting an use after free somewhere
I wonder if I disable PMM::FreePage/PMM::FreePages and just give it a lot of memory if it will work
yep
I'll try unmapping the pages as they get freed to see if I can catch the issue
there is some kind of assertion failure in Heap::Verify()
I'll deal with that when I work out this use-after-free
I'll disable larger pages for simplicity
doesn't catch it
maybe its something else
maybe I should try making a userspace program
and putting it in there
so I can use valgrind to find any bad accesses
the heap that is
Yep
I've spent so much time debugging this, and still have no clue what the problem is
I'm still avoiding making a userspace test
i've wrote a userspace heap test
I'm currently running it normally
I'll also run it in valgrind
its not looking like valgrind is going to catch anything
it's at 1.7 million out of 10 million iterations of the test
with no errors so far
if I don't work this out soon, I'm just going to rewrite
I'm getting really frustrated with this
If I choose to rewrite, it won't be a full rewrite, but all new memory management
I have no idea what to do now
so the heap isn't responsible
what else could it be?
there is PMM corruption somehow
there are very few places that the PMM is used directly
vmm heap is one, which I have confirmed is fine
the other is the PageManager
and I previously confirmed that no pages are being double mapped
almost forgot about page mapping
that code could be responsible
i have an idea
I'm going to re-enable PMM freeing
but leave larger page sizes disabled
it fails
i thought for a moment that it could be bad freeing of unused page table levels
but that code is never reached
it fails during iteration 11653
the actual error is that the PMM reports a nodes size being not page aligned
its inconsistent
it varies each time
I've had enough of this for today
the code is here: https://github.com/FrostyOS-dev/FrostyOS/tree/testing
FrostyOS. Contribute to FrostyOS-dev/FrostyOS development by creating an account on GitHub.
If anyone wants to have a look, all the memory management related code is in kernel/src/Memory/ and kernel/src/arch/x86_64/Memory/
I've left the test in the end of kernel/src/kernel.cpp
Could it be something using the heap is going out of bounds?
Or maybe some buffer accessed through the hhdm is going out of bounds?
I thought it was that, but valgrind doesn't report anything
it could actually still be that
the heap itself is fine, but maybe something using it is being bad
I'll try doing what r4 once said about adding guard pages to allocations when I next have time
I might even try getting kasan working
Ah that's what I was meaning - another component is overrunning/underrunning the buffer and ausing your corruption
I've been meaning to take a look at your code too
I'll look into this again tomorrow
I haven't had time the last few days due to assignments
I don't like having 5 assignments all due at a similar time
I have time now, so I'll get back to debugging this
I'll be looking for vmm heap allocated objects going out of bounds
GCC's anaylser caught some stuff
I'm going to have to build uACPI as a separate library without -Wpedantic
one of the outputs is in kernel symbol loading
related to the possibility of new returning nullptr
maybe if I add an assert to new to ensure it cannot return nullptr it will go away
doesn't do anything
there must be some form of attribute I can give to new so GCC can realise that it cannot return nullptr
the other few outputs are related to lambdas, but aren't actually an issue
there probably is, but I can't be bothered to find it
I've tried adding calls to PMM::Verify in more places
and it fails at entry to PageManager::FreePages
which indicates something else is stuffing things up as I suspected
didn't seem to have an effect
you also tried aligning the end of the allocation to an unmapped region as well as the beginning (at separate times ofc)
and I know noexcept new can return nullptr, but non-noexcept new throws (and I assume cant return null)? Unless thats what you're doing and its still complaining.
yeah try the end, that'll catch overruns. I have (had) an optional to toggle which end got checked
exceptions are disabled, and I don't specify anything extra
I found it strange that even with a guard page to either end of each individual allocation, the error still occurred
so maybe something else is causing it
yeah that is interesting
could it be a use-after-free?
oh you said you disabled freeing a while ago
so maybe not
I changed kmalloc_vmm to align the size to pages, and then allocate n+2 physical pages, then unmap the start and end pages. kfree_vmm does nothing
and the issues still occurs
it happens on the latest commit of the testing branch?
i haven't pushed the test, but i don't think there was any other changes
I'm on windows rn, but I can quickly reboot and commit the test
I've committed it
great ty, I'll have a look at it now
the corrupted state is happening in the kmalloc_vmm stuff?
stupid ovmf has renamed itself in the system directories from OVMF_CODE.fd to OVMF_CODE.4m.fd
oops, just noticed something in the run script
I was experimenting with different display modes and forgot to reset it
fixed
the ovmf stuff I'll keep local for now
I probably need to find a better solution
I think I might know what parts of the code is causing this
I changed the PageManager to just allocate a PMM region and return the HHDM address of it instead of the fancy stuff
and it seems to work
so maybe my mapping code is dodgy
I changed PageManager::AllocatePages back to normal and disabled PageManager::FreePages, and it seems to work
so maybe this code is dodgy: https://github.com/FrostyOS-dev/FrostyOS/blob/testing/kernel/src/Memory/PageManager.cpp#L68-L89
nice, I'll start there (got distracted with cats)
specifically m_vma->FreePages(address, pageCount) on line 83 in that file
don't know if it is direct or indirect
I made the VMM heap normal again, and same issue
so it is definitely that function call thats stuffs everything up
I tried re-enabling all the self verifying stuff in the VirtualMemoryAllocator and I ended up with a linked list looking like this:
that shouldn't be possible
yeah they can, especially when theyre trying to relocate things
nice, that narrows it quite a bit
you'll want to flip the order of these calls:
m_vma->FreePages(address, pageCount);
m_regions.remove(address);
Since there is a race condition where the pages can be freed but the region still exists, and I dont see any locking around them that would prevent that
yeah, didn't think of that. This is currently all single threaded however
so it probably isn't the issue
yeah I didnt think it was your issue
but as a general rule for releasing a resource you want to deny access and make sure no one is using it (and can get access to it) before freeing it.
makes sense
I've been comparing the page managers structures to the virtual memory allocator's ones, and it seems to be consistent
I've only checked the free list so far though
the all address tree appears to match as well
I can't work on this today, but I should be able to work on this a lot more after today
maybe I'll return to this soon
this bug has been really annoying
I had intended on playing minecraft today, but the server I play on isn't currently running
so I'll debug this while I wait
back to the bug
I had discovered that freeing the virtual page region would trigger the issue
so I need to work out why
it doesn't make sense why
unless maybe something in that function is going just enough out of bounds
I've got some time this weekend
So I'll investigate a bit more
Tomorrow not today though
I've been working on this issue for a while now
I'm starting to consider a partial rewrite
I don't know how far back I would go
Before PMM or after VMM heap
Or even after page mapping, but before VMA
Everything seemed fine until I tried porting uACPI and it all fell apart
This message was when I first thought that PageManager::FreePages is where the issue is coming from, and I was right
First mistake
Big mistake 
Yep
i don't have much motivation for this project at the moment
I think maybe a partial rewrite is needed
the problem is that if it is a data structure issue, then a rewrite might not solve it
when I next feel motivated to work on this, I might try swapping my avl trees with the rb tree that oberrow was using
it's from freebsd btw
ok
sys/tree.h
I couldn't remember if it was freebsd or openbsd
you also have some c++ trees out there if you want to use them: managarm/frigg, qwinci had one in crescent iirc, I've seen a few other fairly complete ones floating around.
although those are rbtrees iirc
The purpose of using a different tree structure is more to eliminate the possibility of it being the issue
thats the attitude
the main issue was pmm data corruption
which was being caused in some way by VirtualMemoryAllocator::FreePages
never found out how or why
the idea I thought of 5 days ago was to use a different tree structure instead of my AVL trees incase it was the problem
they have caused problems in the past, so I wouldn't be surprised
wait no, it was 9 days ago originally
wow
I really have been avoiding this
school is finished for the year now, so I have nothing better to do
the last time I properly worked on this was 19 days ago
just reading through that function I don't see anything obvious, so I might try the tree change
I just noticed that if I disable merging of free regions in the VMA, the issue appears much faster
disabling freeing of the physical page also makes the problem disappear
interesting
maybe my PMM is an issue
but is only triggered in this situation
I've been working on one of my other projects a lot lately
A rewrite is really on my mind at the moment
I've been try to debug this for at least a month now
And I haven't really made much progress
All the components seem to work on their own
But not together
So some linking code is the issue
I did a little bit more investigating
The unmap code is fine
I suspect the virtual memory region allocator
so I'll be testing it properly again when I feel motivated to
I've been working on another project a lot lately
I started this rewrite back in august
So I think I should just rewrite again
It's probably a good idea
instead of doing that I've made a userspace test for the vma
and am currently running it through valgrind to see if it will catch anything
there were no errors
but there was a significant amount of leaks
that might be from not clearing the VMM at exit
vma*
now I have to wait another 20 minutes to see if that is where the leaks are coming from
I'm going to reduce the number of iterations
so I don't have to wait as long for a result
there are definitely leaks
meow
I should probably just rewrite at this point
damn, hopefully this one has more success ๐
I hope it does
I'm not sure when I'll make a start
I've been mostly focused on another project lately
It has been a while
I've had a minecraft distraction over the last 4 or 5 days
And I've lost most of my motivation for my other project
And for the first time in a few weeks, I'm actually starting to feel motivated to work on this
I'm not sure how long the minecraft distraction will be full on for
But probably not for much longer
I want to properly design stuff this time
I guess I should start soon
First I'll just get Framebuffer printing, GDT, IDT out of the way
Then I'll do PMM I think
Then page mapping
Then basic scheduler, no preemption yet.
I guess then I can do VMM heap, virtual memory allocation, kernel heap, IRQ system, page cache
SMP will be at a similar time to the IRQ system
The current iteration failed when I tried to port uACPI for the irq system
So I think I'll need to do a different testing approach to avoid that happening again?
I've committed the latest code, and moved it to a new old-code branch
testing branch is gone
I'll clear out master in a moment
I've cleared it out mostly
I'm keeping all the basic TTY and graphics stuff
it triple faults though unfortunately
-d int doesn't print anything though

Yeah I kinda miss frosty os work
oh I know why this doesn't want to work
I need to do global constructors
finally:
GDT time
its happening ๐ , good luck with this iteration
[GDT INIT] OK
and the IDT is done
PMM is next
first kernel was bitmap
next was freelist
I don't know which one I liked better
for bitmap, allocate was O(n) (could be optimised to be O(1) best case), free was always O(1)
for freelist, allocating a single page is O(1), allocating more than that is O(n), free unoptimised is O(n), but can be very easily optimised to be O(1)
I'll do a free list
I see that limine has a new base revision since I last looked
seems like the biggest change is that ACPI memory regions aren't mapped in the HHDM
which doesn't really have an impact since I'll remap it all anyway
I do like that idea though
I might do that when I do page mapping
since I'll be using uACPI, it doesn't really matter
this might be an issue though:
my previous iterations both used the 0th page for the SMP trampoline
but if I ever want to do something like suspend, that can't happen
so I guess I'll just find an alternative when the time comes
an alternative to using the 0th page that is
single page allocation and freeing is done
now I need to test it
I'm go to use a similar approach as before
I am going to quickly make a new bitmap implementation first since the old one was horrible
time to continue on this
yesterday, I ran the test and an assertion failed
specifically the one that checks the free list is in order
which it should be
iirc limine memory map entries are guaranteed to be in order
think so
yep, that isn't the issue
my free code is stuffing it up
this is not good:
an allocated object is in the free list
I've wrote a proper Verify() now
and there is a lot of uninitialised memory bugs which I keep finding
somehow there is 1 less node in the free list than there should be
it only happens when an object getting freed fits perfectly between 2 nodes
oh I'm stupid
I see why
the test looks like it is going well so far
it has to do 1 million test iterations
the test passed
next is multipage allocate/free
free is done
because it is almost identical to single page
allocate will be a little bit different though
maybe
yeah it will be
single page allocation just takes the first free region
but multipage will have to search for a region
I've made sure to make PMM::AllocatePages call PMM::AllocatePage if the page count is 1
multipage allocate/free worked first try
I think that means the PMM is done?
nevermind
it froze when I ran the test again...
oh I know why
it works again
alright, PMM is done
next is page mapping
I don't know why I need page mapping
scheduler doesn't need it?
A custom page map would be helpful though?
I guess I'll do page mapping anyway
I think I want to do a different approach this time
What are you thinking of?
Oh. I forgot to finish what I was saying
My previous 2 kernels just went through all the page table levels in one function
I was thinking of looping through the different levels
Probably with something like a GetNextLevel function
Which would make it possible to support 5 level paging
I forget to do system updates for a few days, and I end up with 272 packages needing to do an update...
qemu being about 100 of those
anyway
GCC is weird when it comes to inline assembly
just as a test I wrote a inline assembly cpuid function:
and GCC did this:
I just did this:
wait nvm, I just noticed an issue. This is what I actually do:
why is GCC generating so much extra stuff
I keep getting distracted by what it happening in the other threads
I'm trying to make this kernel support 5 level paging
but I just realised an issue with the way I was trying to approach it
I was trying to just enable 5 level paging as soon as it is checked that the CPU supports it, which won't work
I have to check for it, then later when I go to load the page tables, I have to disable paging, enable 5 level, then enable paging again
I could just have limine enable it for me...
I should just do that
relatable, there's a lot of osdev happing over the summer
yesterday I didn't end up getting much done
but I did make some assembly functions for checking for 5 level paging, nx, 2MiB pages, and 1GiB pages
my host CPU doesn't support 5 level paging, so I will have to test it with KVM off
for obvious reasons, 5 level paging is an optional feature that will only be used if it is supported
same with the larger page sizes
nx is required though
I also discovered that the qemu64 CPU doesn't support 1GiB pages by default
with low RAM that is. I think I remember it supporting it with larger RAM sizes
nevermind, it doesn't
I wonder if that contributed to my old kernel having issues...
because I'm pretty sure it thought that the qemu64 CPU had 1GiB pages
and I know it isn't an issue with the way I check in this kernel because when I add +pdpe1gb to the cpu, they are supported
Starting today, I'll need to update the copyright years in any files I edit
My page mapping function is now done
the main 4KiB page one anyway
the larger page ones are very similar
all the map functions are done
I'll make sure these work before I worry about remap or unmap
looks like 5 level paging is getting enabled by limine which is good
why don't you just bulk update them in a single commit?
only if you advertise support for it :p
I only update it in the files that I change so that the copyright year range reflects the time period those files have been worked on for.
Yes of course. I have the minimum mode set to 4 level, but the preferred and maximum set to 5 level.
๐
i usually do that, but project wide, also considering i don't really put copyright dates inside individual file headers... lol
I just followed what the license I use, GPLv3, told me to do, except that I changed the "c" to a "ยฉ" since at the time I think I had read that in Australia, something is only copyrighted if that symbol is used?
I feel like I've been getting distracted a lot over the past few days
I think I've made all the functions I need now to switch over to custom page tables instead of limine's
almost
I just realised I forgot the PAT
ok, PAT is done
I think mapping everything is done
time to test it...
I've obviously stuffed something up:
I stuffed up the CPUID function somehow
looks like my code for converting edx:ecx into rdx is wrong
show your cpuid function
well why do you merge edx:ecx into rdx
to build this struct:
ah
this does not need [[gnu::packed]] btw
unless you want to force the alignment of the struct to 1 for some reason
wouldn't all the uint32_ts get promoted to uint64_ts?
why?
I thought that without packing all items in the struct are 8 byte aligned?
no
ah
they are aligned to their alignment
ok
which for integers is the same as their size
I got it to work by swapping the mov edx, ecx with an or rdx, rcx
I don't understand the difference
interacting with the low 32-bit portion shouldn't affect the high 32-bit portion?
anyway, there is now an OOM when building the page tables
I just noticed that the HHDM offset limine provides is different with 5 level paging
that does make sense
more virtual address space
it does, writing to the 32-bit register zeroes out the upper 32-bits of the 64-bit register
but writing to the 16-bit register doesn't affect the higher parts iirc
that is weird
multiple bugs were contributing to this
the one I am dealing with now is that memory that shouldn't be getting mapped into the HHDM still is somehow
ohhh
I see why
the size was too small, so it didn't want to work
1 bug down
how ever many more to go
still getting an OOM
I don't know why
it seems to be mapping multiple new page table levels each time
I accidentally crashed gdb...
I tried to access something out of bounds in QEMU
and it did not like it
gdb may be broken:
when I press up to get the previous command, it returns as if there were a 5 there
it gets increasingly more broken
I closed the terminal completely, I'll see if it works now
it seems to be working again
and these paging structures are completely messed up
gdb is still behaving a little weird though
so I'll do a raw memory dump from QEMU to see what it says
the font on the qemu monitor is so hard to read
I don't know why
it never used to be
lol nice
yeah i'm not a fan of the builtin qemu monitor, I always route to it some output I can hook up my own terminal too
stdio is being used by the debug console, so I don't know what I can route it to
I could try route it directly to one of the various pts consoles, but my terminal emulator would not like that
the raw memory dump contains an address, but it is at the wrong location
its at offset 0x3f8 in the page
when it should be at 0xff8
so highest 2 bits are missing?
I thought it may have been an operator precedence issue, but that appears to not be the case
I found the bug
I was on the right track
stupid off by 1
still haven't completely fixed the issue though
the highest page table level is no longer messed up
but all the others below still are
I just saw the next bug
what was I thinking
now it page faults
and the stack trace from gdb is a mess as always
it never prints it properly from an interrupt context no matter what I try
a forgot a to_HHDM
now there is a general protection fault even earlier
I've noticed that CR2 will contain the bad address if a GPF is due to a non-canonical address
oh I know why that was happening
the HHDM offset needs to be added only in the case when a new page table level wasn't allocated
now somehow the level index has wrapped around into a negative?
maybe it is trying to double map something and it doesn't go well?
but I have a check to prevent that from being possible
I'll add an assert(false); into the case where the x86_64_GetNextPageTable function gets an out of bounds index
It's when mapping a 2MiB page
I just found another bug similar to the one before
once again, what was I thinking:
and now it is back to mapping something outside of accessible physical memory
I'm going to make some changes to my region mapping function
to prevent this kind of issue
and that is done
but it is somehow back to trying to read page table level 0
how is that possible
it is the 2MiB page one, so it shouldn't even be reaching level 1
oh I see why
it is trying to map a 2MiB page at an unaligned address
I've added some safety checks to mapping of larger pages sizes to prevent it from trying to read more than it is supposed to
this means my attempted changes to the region mapping function made things worse
my approach is completely wrong
the size alignment doesn't matter, it's the address that does
finally it appears to work
triple faults though
probably when actually loading the tables
yep
the HHDM portion appears to be good
but the kernel itself is not
the region mapping function is still wrong
I don't feel like dealing with this right now
time to deal with this
it doesn't triple fault anymore
but it page faults
then page faults whilst trying to print the panic to the screen
so the kernel and its stack are being mapped properly, but the framebuffer isn't
original page fault is whilst trying to print to the screen
qemu has a really annoying bug with 5 level paging where the info mem monitor command doesn't print anything
looks like the entire framebuffer isn't being mapped
the page mapping functions are being called with the correct addresses though
appears like it isn't reaching level 1
maybe the page size bit is set incorrectly for some reason?
the offsets at each level appear to be correct for the single page mapping
I'll verify the ones for the 2MiB pages just in case the page size bit is being set in the wrong place
it all makes sense
this is weird
I did a memory dump
and the table entry causing the problem is zero
I found the bug
for some reason in the check for if the GetNextPageTable function returns nullptr due to a large page, I was using the 0th entry instead of the correct one
it finally works
so many bugs
I'll deal with remap and unmap tomorrow. Shouldn't take long as unmap is essentially an extension of remap.
I'll quickly test this with normal 4 level paging
it works
ok that is good
my kernel can do both 4 level and 5 level paging with no issues
I'll also need to do some real hardware testing tomorrow
-monitor file:/dev/stdout
i can test now
How do I provide input?
move the debug console to file:/dev/stdout
and put monitor on stdio
which is enough to trick qemu into having both on there
this seems to have worked
I'll change the run command to do that for debug mode
release mode doesn't have the debug console, so it would be weird for it to have the monitor
I set the RAM size to 16G and it still works, which means 1GiB pages must be working
I'll quickly test this on my laptop
it works
idk if my laptop supports 5 level paging, but it definitely supports 1GiB pages
I'll quickly see what linux says
no it doesn't
which means I don't have an x86 machine that supports it
because my PC doesn't
if 4 level works, then 5 level should as well because of the way it goes through the table levels
time for this
remap is essentially map but I don't need to create page table levels if they don't exist
I'll start with remap, then I'll deal with unmap
also need to make a function for getting a physical address at some point
remap for standard pages is done
I'll try make a test for it
I'll just remap the first page of the kernel as read-write-execute instead of read-execute and then just see what the QEMU monitor command info tlb says
it works
for testing 2MiB pages, I'll just remap the first page of the framebuffer as read-write-execute instead of read-write
and it works
I'm not going to bother with 1GiB pages since they are essentially the same process as 2MiB
unmap time
I just realised that the QEMU monitor command doesn't care if the TLB has been flushed or not
unmap is annoying because you have to go down the tables to find the entry, then you have to work back up the tables to delete unused tables
I haven't really decided on how to approach this
I'll need to do the normal process of going down the tables, clear the lowest entry
but then how do I work back up the tables?
I guess I could have a mini stack of the entries?
it was actually simpler than I thought
I need to test that it actually works
I'll test it by allocating a page from the PMM, mapping it into some address where all the table levels will need to be created, then unmapping
since the HHDM offset is 0xFF00'0000'0000'0000, I'll map it at 0xFF10'0000'0000'0000
this is the test:
I hope it works
the message is printed
the QEMU monitor says it isn't mapped anymore
I'll do a physical memory dump of the root page table to see if it is gone
I can just run the xp monitor command to read from an address
and the entry is empty at the root page table
which means unmap works correctly
I think this is the first time I've properly tested unmap
I just realised my unmap is going through the levels in reverse order when it is trying to delete the empty ones
it is a simple fix though
it works still
for larger pages, it is essentially the same, so there is no point in trying to make a test
I guess this means page mapping is done
actually no
I need to make some basic TLB flushing and getting a physical address
getting a physical address works
and basic TLB flushing works
both a full table reload and just invalidating individual pages are supported
now page mapping is done
everything still works with KVM on and the default CPU features
alright, scheduler time
I think first I'm going to make a basic PIT driver so I can do preemption
which does mean basic legacy i8259 PIC support
I needed to do it eventually anyway since they need to be disabled to be able to use the APICs
I want to make it easier for my scheduler to support multiple CPUs later, so I'll implement some cpu local stuff next
I'll need to make some changes later so that each processor gets its own GDT and IDT
I won't worry about that for now
so far I've just made some changes to abstract arch init a bit, but in a way that makes adding support for SMP later a bit easier
Are you thinking of going multi arch this time, or is it an organisayion thing?
I'm trying to make it easier to go multi arch for when I want to.
Also an organisation thing
But other archs I had in mind are aarch64 and the m68k
aarch64 because I have some raspberry pi's to test it on
(So no one corrects me, I added a ' so it couldn't be confused with raspberry pis)
Also maybe my custom arch one day
That's if I can be bothered to finish the LLVM port
There's also some other things as well
Does raspberry pi have ventoy
Idk
flashing every time microsd or usb is terrible
yeah fair, well good luck if/when you go ahead with aarch64 and m68k ๐
I haven't much time to work on this today
I'll have limited time over the next 2 weeks due to various things
most of that being because I'll be in a different part of the country starting on tuesday
anyway
so last night I made some abstraction for arch init
I didn't end up comitting it
I'll quickly do that now
I think it's time to start on the actual scheduler
I definitely want to go multi privilege level EDIT: I mean priority
not sure how many I want
the scheduler from my original kernel had 4: LOW, MEDIUM, HIGH, and KERNEL
I'll have a look at what mintia does
maybe some other OSes as well
mintia is too confusing
its based on freebsd ule
I didn't have any time today
Didn't have any yesterday either and probably not today as I'll be stuck in the car all day
I'm not sure how much time I'll have over the next 2 weeks as I won't be at home
Haven't had any time yet
And the place I was at yesterday has horrible mobile reception, so I couldn't do anything if I wanted to. Tomorrow I'll be busy exploring Sydney, but after that hopefully I'll have some time to start on my scheduler.
oh nice, enjoy sydney - unfortunately the weather is awful this week (so much for summer lol)
I was thinking about a design for my scheduler last night
My original scheduler had priority levels, but they were weird
A lower level thread would be scheduled if a higher level thread had been run 3 times (only if there is an available thread in that level)
It was weird
I also didn't have thread-specific run time frames, it was just after a certain number of ticks, something would get scheduled
Unfortunately, I don't know when I'll have time to start
The scheduler for this kernel will be different
I haven't completely decided between priority or niceness
I'm not entirely sure how priorities are supposed to work
Niceness makes sense
I'm going to try make a start
I have a little bit of time
I haven't used my laptop in so long
i forgot how annoying my laptop's keyboard is
I guess I'll start by making the data structures for all the various parts of the scheduler
there will be processes, which then have a list of threads
I won't worry about the process stuff for now
since it will be annoying to make a list without a heap
the schedulers list will be a bit different
they will be using intrusive lists instead
I'll make them doubly linked so they can be traversed in either direction
wow the mobile reception here is so slow
I would expect it to be decent considering I'm in the capital of the country
but nope
vscode is taking ages to update extensions
why is microsoft c/c++ trying to install
I have clangd
finally it finished
picom has decided it doesn't want to work
just noticed I left a define in the kernel main file
I hope my gpg key is on my laptop
nope
I'm also signed in on the wrong git account
nevermind, the gpg key is there
I'm not dealing with this right now
๐ฆ
I have not work on this since then
Because git is annoying
I had to switch account for some reason
And I can't remember how I reset the auth keys
Because I use git credential manager via secret service to log in
The GPG stuff is easy
Switching account is a pain
I feel really motivated to do osdev, but demotivated at the same time because of git being a pain
I'm not home yet, but I really want to do osdev
The mobile reception where I am right now is actually decent
When I was in Sydney a week ago, my reception was good, but not that fast because the transmitters were too close...
Where I am now seems to be a good distance from one
I'm going to try get git to behave itself so I can work on this
I don't know how long I'll do it for though
As I've been awake since 4:30am
Its currently 8:44pm
that was simpler than I thought
for future reference, if using anything related to freedesktop secret service, use seahorse to manage credentials
I'm too tired for osdev
maybe tomorrow
osdev time
I made a basic kernel context switch function
which worked the first time I set the registers parameter properly...
I might actually do some work on my custom arch for the next little bit instead
So I did go ahead with that idea
I haven't really felt like working on this much
Partially because I'm too lazy to transfer some of the stuff I did on my laptop over to my PC
I'm also back at school
Which limits my time a lot
school? how old are you
yall are crazy bro
๐ญ
if you are a high schooler making a kernel thats crazy
What, did you expect reasonable projects at the OSDev Discord server? LMAO
And yes, while I don't know what the case is for Frosty, some of the OS projects here are indeed made by high schoolers.
Me too but I got distracted by CPU dev :P
I've been distracted by my custom CPU arch a lot over the last few months
๐ญ
I find it more fun most of the time than this project
There it is 
Same EXACT thing ROFL
Oh believe me I did goober shit when I was 14 too. And 16. And 18. And now.
There are a lot of people doing osdev in high school, (for you americans, there would also be some towards the end of middle school)
America is more like south Canada
Every time I look over at America they have done something else that makes me go "WTF"
i mean id rather be american than turkish
Well not historically
Idk being Turkish sounds cool
bro i am literally using a vpn to use discord right now
it is banned
does it sound cool now
Maybe being in Turkey isn't cool
Let's not flood this thread with off topic conversation please
sorry for chatting in your thread bro
When project in Digital Design HQ?
Huh?
I hereby notify you of the existance of that Discord server.
You're welcome.
I wish I had that when I first started doing CPU crap
My CPU is purely virtual, no physical designs are planned
I mean
So are all but one of mine
I made a breadboard CPU once but I don't think I'll do that ever again.
My custom design is 64-bit, so trying to make it on a breadboard wouldn't really be feasible, let alone making some form of physical design
FPGAs it is then
Also, that server you mentioned is a massive pain to get in to
It's worth it after the verification.
I haven't seen such a bot-free place filled with experienced digital designers anywhere else yet.
They certainly helped me multiple times, saving me loads of time on my projects.
If you decide not to join, you can always ask me questions instead ;)
I can't seem to get in to the server. I've gone through the verification process, but nothing has happened
It's working now
I'm not sure when I'll return to this project
I'm feel like doing osdev
I*
It's been a while
I finally could be bothered transferring the changes I made on my laptop 5 weeks ago
and I've had enough of dealing with llvm for a bit
so it is finally osdev time
the last thing I did was make a context switch function
and it worked first try
I think I had designed most of my scheduler in my head, but it has been 6 weeks, so I don't remember any of it
I do remember finally understanding the difference between priority-based and niceness-based
and I decided on niceness-based
since it seems more fair
I've been considering using limine's SMP feature to get the other processors online so I can make my scheduler support multiple CPUs from the start
and then later I switch over to a more custom system
since I want to make a scheduler that relies on the least amount of things I can
I have a basic PIT driver for preemption
I don't know if I mentioned this, but my old scheduler did it in a really dodgy way
it was very simple
every so many ms (40 iirc), the scheduler would just reschedule on all cores regardless of how long the current threads had run for
which is definitely wrong
I'm not doing that again
I just went to try get the value of CR3 and use that as the pagemap for threads, completely forgetting that I had done all the page mapping stuff
which means I could technically test the scheduler in user mode when it is time
all the surrounding stuff is mostly done, it is time to actually implement the algorithm
I have chosen to go with 16 nice levels
15 being the highest, and 0 being the lowest
I was thinking maybe making it so a thread with higher nice value is twice as likely to run as a thread with a lower nice value
I haven't completely decided on how to split kernel and user threads
kernel threads are probably just going to be used for DPCs mostly
wait no
I forgot some of the multi-processor stuff
but it'll have to wait until tomorrow
I'm out of time today
time to continue on this
I ended up getting distracted for a few hours by school shenanigans
I ended up wasting some time last night making an enum for a bunch of MSR names
I keep getting distracted whilst trying to do this, so progress is slow
I'm trying to design a way of picking the next thread without recursion
the checking system needs to be able to move down the list of levels if the run count for a level is >=2
but if it finds no levels below having any threads, it then needs to be able to move back up
it is fairly simple with recursion, but I'm not sure how to do it properly without
and it needs to work for an arbitrary amount of niceness values
I have an idea
maybe I could go through the niceness levels lowest to highest instead
time to continue on this
after I finish updating the linux kernel
I was using 6.12.10, when the latest is 6.13.5, so it was overdue
PickNext is done
I think it is time for a test
there is going to be 16 processes (1 for each niceness level), each with 4 threads
single processor for now
test has been made
time to see if this works
page fault
attempted write to nullptr
forgot some stuff so it doesn't try use the non-existant heap
nvm
something else as well
still that issue
fixed that
it appears to be stuck
it is stuck trying to get the length of a linked list
it is a looping list for some reason
why is next and previous equal to the node itself
the scheduler hasn't even started yet
oh I know why
I forgot to init the node pool
oops
I'll also make it a bit bigger since it is currently not big enough
QEMU seems to freeze when you try load a high address into CR3
it succesfully started the first task
but I forgot that the GS base gets cleared when the GS segment register is reloaded
I don't even really need to set that segment register anyway for a kernel mode switch
it is still page faulting
GS base is still 0?
oh, interrupt return sets it
I'll need to make some changes to that function
later
I'll just comment out the GS segment reload for now
it seems to be able to switch thread once
then it doesn't again
something is messing up one of the fields in the processor's state struct
so the scheduler thinks that the processor shouldn't be getting anything scheduled to it
I had set the stack addresses wrong
it is actually switching threads now
but it is wrong
the niceness pattern currently is 15 14 15 15 14 15 14 15 15 14, which is wrong
it should be 15 15 14 15 15 14 15 15 13 and so on
and now the pattern is 15 15 14 15 15 14 again
I'll try resetting the PIT ticks just before the scheduler is started
didn't change anything
every so often it seems to double up on picking in between printing what thread is running
which could be an stdio issue
wait nvm
I know what is causing that
I had made a makeshift sleep so it wouldn't spam the debug console
but replacing it with just a hlt is enough
it prints after every interrupt
here's the algorithm if anyone is interested:
only thing i dont like about it is the number of locks involved
Wdym?
What is bad about lots of locks?
I understand they make code more prone to deadlocks
a lot of locks means a lot of contention for said locks
But wouldn't more locks break it up so more stuff can happen at once instead of waiting ages for the one lock to be released
especially in places like the scheduer which should ideally be lock free
barring thread migration between cpus
How is that even possible? There would need to be some kind of locks on the lists?
I can understand on other fields by ensuring atomic reads/writes
a lot of ways, for example you can submit threads to run via an ipi
so only the cpu itself can modify its queue
I see
time to debug this
I think I understand the problem now
it is because of the way the run count for a level is reset
the pattern will be 15 15 14 15 15 14 15 15
in this case, both have run counts of 2
should*
but don't
since the run count for 14 is reset on the second last 15
when it shouldn't be
it's an issue with how the algorithm runs
the run count should only be reset when either when something of a lower nice runs, or there is nothing of a lower nice
it seems to be working now finally
maybe 1/3 is not frequent enough
it took 10 minutes to get down to level 6
that means level 5 will take 30 minutes
4 -> 90 minutes
3 -> 3 hours
2 -> 6 hours
wait no
3 -> 4 and a half
2 -> 13 and a half
1 -> roughly 1 and a half days
0 -> roughly 4 and a half days
maybe my chosen timeslice is too big?
or should nice also change the timeslice?
those numbers are considering there is at least 1 thread in every nice level
@red swift you're good with schedulers, what do you think?
just because youre locking a lock doesnt mean youre contending on the lock
having lots of locks where 99% of the time its a totally core-local lock and theyre only grabbed cross-core during thread migration is fine
this is commonly done
what ur describing doing instead is unusual and has drawbacks
this causes lots of extra ipis and causes the target core to take an interrupt which is much more expensive than
if it had to spin on its core-local queue lock for a bit while you placed a thread into it
(and otherwise never contends on that spinlock)
and in the latter scheme you only need to ipi if you enqueue a higher priority thread than its currently running (or if its idle)
im bad at scheduler policy im only good with mechanism lol
thats why i just ripped off ULE for the policy for mine
the freebsd scheduler, its well documented
ok thanks
Kinda doubt that's the case, task migration between cores isn't done that often, and doing so all the time that ipis are noticeable would kill performance for other locality related reasons
I'm going to try get this scheduler working multi-core
which will be an interesting experience
considering I have no VMM or heap
I need to setup uACPI for tables
just early loading
I can probably just allocate a smallish region with the PMM
btw if you're willing to test, the PR for UACPI_BAREBONES_MODE is already available
I'll have a look
it basically does this
ok
clangd is being annoying. It's saying an include is unused, but if it isn't included, there is a not defined error
I've set everything up and get a page fault
reading a HHDM address
why
oh I know why
I don't map ACPI regions by default
I guess I'll change my uacpi_kernel_map to actually do something instead of just converting it to a HHDM address
@hollow trail should I be mapping ACPI regions as UC?
on x86 u can map as WB
since u have MTRRs
on other architectures (at least what linux does) is scan the memory map to see what it is being mapped, and then pick caching accordingly
is this barebones_mode?
yep
nice
I don't think I've done a real hardware test on this version of my kernel yet
so I'll see if it works
it works
It has some interesting tables
like what is IHIS, LPIT, BDAT, DBG2, DBGP, NPKT, PRAM, DMAR, WDAT
that's not flanterm is it?
It's a random one I found on stack overflow 2 and half years ago
with some minor modifications to some letters
almost all of the tables seem to be page aligned
yeah cool font
DBGP is debug port, DMAR is IOMMU, PRAM probably persistent ram?
DBG2 is debug table 2
with serial ports i think
btw is it intended that there is no space before the ) on that one line that ends up being shorter than the rest?
seems weird
yes, RSDP has no OEM ID
which?
DpftTab one

