#Zinnia
1 messages ยท Page 8 of 1
near the data prob
i store my data in my struct page
doesn't that waste a lot of memory though?
8 bytes
but I don't really need metadata for a pmm, do I
well this got a lot easier
https://github.com/48cf/osdev/blob/main/kernel/src/mm.c
relevant functions:
order_from_sizesize_from_orderadd_to_free_listpop_from_free_listfree_regionmm_initmm_alloc_pagemm_free_page
though my implementation relies on being able to store the next/order/max_order in the struct page responsible for the page it's tracking
You probably want to store metadata for shared memory anyway, so you can just union it with that
oh nah
like bro wtf are all these people doing
lmao
trolled
XD
mimalloc using malloc underneath
well i mean it's quite normal under non-kernel circumstances
for performance?
if you know your constraints you may be able to allocate memory in a better way
and buddy may as well be a good candidate for something, idk
How else would you do it?
If you're implementing zones, you can't know how many there will be
memory regions probably
well u know that ahead of time, kinda, no?
Idk
you know how many you want to support
just not how many you will have
you might not have memory >4G
idk how numa works
Yeah
Me neither
But my allocator supports multiple regions
does numa matter when starting out? or this that some high tier optimization?
I have <1MB, <4GB and >4GB atm
server systems mostly i guess
accessing memory that belongs to another processor is slow as balls apparently
so you want to allocate physical memory with respect to that
makes sense
that's why i said mostly
but native numa is seen on systems with multiple cpu sockets
Do new consumer CPUs use them?
Now that both AMD and Intel stuff is using chiplets
they all share one memory bus
Yeah
that's not numa
is it normal to feel like a brainlet
yes
idk but every time i have to think about mem management my brain shuts off
me when uvm
memory management is a whole thing, isn't it?
Certainly got me a few times in BadgerOS while initially setting up vmem, though my kryptonite is more like schedulers
same with threads XD
When thread
And you say you don't know stuff damn
real
there already was a thread
but i kind of abandoned it
just because i can write a buddy allocator doesn't mean i can write a kernel ๐ญ
i still don't know how to write a decent scheduler
like i know how to implement context switching between kernel threads
that's piss easy
but idk how to tie it to a scheduler
preemption vs explicit thread switch is something idk stuff about
preemption is hard lol
is it really?

preemption is either done by a timer or by the thread itself when it e.g blocks
ok but how does a timer do it?
nah just me being a literal idiot
allocators will stay the bane of my existence forever man
im pretty sure i did everything correctly, but i somehow manage to have more pages than memory and a buddy with an order of 0
note to self: check page and buddy orders again, maybe calculation is off
if i can't get this working today I'll just use a bitmap for now...
order 0 is just a 4k page
or should be, anyway
hm
it trips the assertion " buddy.order == page.order-1"
i beg you to take a look at some point today so i can finally move on from this shit. i quadruple checked all functions already and it still doesn't work.
Had to skip a bit of conversation; At least for me I figured out how to do a lockless buddy with 24B/page if you squeeze it overhead and O(1) fit everything except alloc/dealloc
And there is one more place where you need continuous memory, when you aggregate towards larger pages
I could give you my buddy once I actually wrote it
My scheduler is also total trash, I don't really get how quantum and time slices and related are supposed to work
The concept of a quantum in this context is basically the "smallest increment possible", though time quantum is often said when time slice is actually meant. Then, a time slice is merely how long the scheduler gives a thread before preempting it, assuming it does not yield before then.
But what happens to io bound threads?
Like do you just give them a full time slice?
An I/O bound thread will likely block on said I/O, thereby implicitly yielding and resuming only when the I/O is ready.
Usually these threads don't get scheduled again until they can be unblocked; until it no longer needs to wait for the current I/O operation.
I get that
But do you place them at the end of the ready queue and give them a full time slice? In which case they get to run for more time than the rest of the threads
I keep track of how much CPU time the thread has used and it automatically yields if that exceeds its time slice
It could yield a thousand times for IO, the timeslice clock will keep ticking
This is a question of scheduling policy. In BadgerOS, a thread that is unblocked will be placed at the front of the queue, getting a full time slice immediately. Not ideal for perfect fairness, but great for response time.
If you don't want to have this issue then you can place the thread at the end of the queue, a blocking action behaving as though the thread had yielded the remainder of its time slice because the other threads in the queue will run before the thread that just unblocked.
That's kinda what I do at the moment
Important note: My beginning of queue means thread that will start next, end of queue means thread that will start last.
why "only slightly"?
well it's still not particularly complex
It's linear in the number of pages
Vs. logarithmic
so in that sense it's exponentially worse
Oh I wasn't talking about computational complexity, just implementation complexity
if page is an order-N page that you are freeing, and page_buddy(page, N) is free but of a different order than page, you cannot merge them.
remember that if you coalesce a page with its buddy, to remove whichever page has the higher address, and is thus misaligned for an order-N+1 page, and keep the other (potentially coalescing with an order-N+2, order-N+3, ... page)
you can only merge two pages if they are buddies and of the same order
so idk what the "expected buddy for order 2 to have order 1, but it was 0" thing is supposed to mean.
i looked at iretq's code and it had that assert
can you link iretq's code?
nvm. found it
thanks anyways
I'm just going to assume that order_from_size, ยดsize_from_order, etc. are correct
L243-L254 hurt my eyes
why not just
struct page *page = pop_from_free_list(order);
page->current_order = desired_order;
for (; order != desired_order; ) {
struct page *buddy = buddy_of (page, --order);
buddy->current_order = order;
add_to_free_list (buddy);
}
yeah so I assume this kernel panic originates from your translation of L248 of iretq's code
in which case, iretq's invariant that order_of(page_buddy(page, order_of(page)) == order_of(page)-1 for any free page with order > 0 is probably broken somewhere
Page::pop_from_free_list() should probably clear page.on_free_list
@vast lotus how do you get away with not using the idt_frame_t during a context switch?
how are rax, rdx, etc. saved?
rax, rdx, etc. are caller-saved registers
so whatever called x86_64_switch_thread is responsible for saving them
that effectively means they're already somewhere on the stack
oh so you just save the kernel stack + callee saved regs?
yep
ahh
the compiler will take care of the rest at the callsite
oh damn so i would need sysv C abi, right?
any specified abi would work (you'd just need to save a different set of registers) but yeah
well, rust abi isn't exactly stable :D
so like, if you can just use the stack, why save any registers at all if they're already on the stack?
the callee-saved registers aren't guaranteed to be on the stack, since they're callee-saved
I think the rust syntax would be something like this? as long as the compiler knows what your ASM expects you're fine, even if the code calling this function is a different callconv ```rust
#[naked]
extern "sysv" fn switch_thread(from: *mut usize, to: usize) {
// ...
}
i can do extern C
they're not? aren't they always part of idt_frame_t?
like, when a preempt ipi happens, does that not always give you the regs
those are the registers of the interrupted context, the kernel code leading up to the context switch might have (read: probably will have) used those registers for other purposes
remember, this part of the scheduler should not rely on interrupts being a thing at all
yea i'm having trouble getting that in my head
pretend you're writing a cooperative scheduler - the only difference is sometimes you're calling yield from an interrupt
tbh i'm still failing to see what exactly the call stack is and where the registers of the preempted task are saved
would really appreciate a call stack example
assming an interrupt
user_func_a
user_func_b
<INTERRUPT> <-- idt_frame_t contains the values the registers had here
x86_64_idt_thunks[X86_64_IDT_LAPIC_TIMER]
x86_64_idt_entry
x86_64_idt_dispatch
x86_64_handle_timer
preempt_unlock
do_yield <-- this was queued by one of the events x86_64_handle_timer ran
arch_switch_thread
x86_64_switch_thread
arch_switch_thread saves rax, rcx, rdx, rsi, rdi, r8, r9, r10, r11 to the stack (or discards them if they aren't used after that point)
x86_64_switch_thread saves rbx, rbp, r12, r13, r14, r15 to the stack, then saves rsp to the thread structure
when this thread is switched back to, x86_64_switch_thread restores rsp from the thread structure and restores rbx, rbp, r12, r13, r14, r15 from the loaded rsp, then returns to arch_switch_thread, which restores the registers it saved
then all the functions on the call stack return until eventually x86_64_idt_entry restores the interrupted code's registers and does an iretq
https://github.com/proxima-os/hydrogen/blob/rewrite2/arch%2Fx86_64%2Fkernel%2Fproc%2Fsched.c#L12-L20 this is all that's explicitly saved and restored to/from the stack on context switches, the rest is taken care of by the compiler at the callsite
(the rip there is saved by the call instruction that led to x86_64_switch_thread)
new threads are initialized by building this structure on a fresh stack with rip pointing to a small thunk that moves some of the callee saved registers in that struct into the argument registers before calling into c code
hm, so would i have to make sure all functions called up until that point are extern "C"?
or just arch_switch
no, you just have to make sure the actual assembly function that switches threads is extern "C"
oh
in this case x86_64_switch_thread
that makes sense to be extern C
arch_switch_thread would be extern "Rust", the compiler will take care of any callconv differences
oh wait i think i get it?
so the way i understand it now, assuming 2 threads for example:
- t1 is preempted
- idt handler pushes all regs to the kernel stack
- do_yield is called to switch to t2
- arch prepares the switch by changing e.g. fsbase and gsbase
- callee saved regs are saved to t1 task
- callee saved regs from t2 are loaded
- rsp is switched to t2's kernel stack
- code returns until it's back at the idt handler (?)
- t2 idt_frame is popped back
- iretq
rsp is a callee saved reg so that being an explicit step is a bit redundant but that's correct yes
in my case I also arrange for x86_64_switch_thread to return the location it saved the previous task's rsp to which lets me get a pointer to the thread that was switched away from, I use this for e.g. putting exiting tasks on the reaper queue
you determine what stack values x86_64_switch_thread expects and initialize them in such a way that your thread init function gets called
in my case: x86_64_switch_thread expects this struct. rbx is initialized to the function that should be called in the new thread, r12 to the argument that function wants, and rip to x86_64_thread_entry. x86_64_thead_entry is a small ASM thunk that sets up the call convention and calls x86_64_init_thead(old_rsp_location, rbx, r12). at this point we're in C code again
there's some initial processing done in that init_thread call and then the function initially passed through (rbx,r12) is called
โค๏ธ
oh and CONTAINER(a, b, c) is just a helper macro that returns a pointer to the a structure whose member b is at c
I'm not familiar enough with the linux src to say but judging by the name, probably
there's no reason it's specially r12
is it just arbitrarily used by your code for kernel threads?
it just has to be one of the registers x86_64_switch_thread restores
got it
the small ASM stub moves it into the right register for it to be picked up as an argument to the thread's first c function
i see
it's essentially a miniature callconv
the disadvantage of not saving all regs is that you can't always inspect userspace state when you're in the kernel
so you need to unwind to the kernel entry when that becomes necessary
You're still saving all regs on interrupt entry, so you have the full user state
You're just not saving all kernel registers, but there's never really a reason to read those
Ah i misunderstood what you were proposing
I thought you just saved caller saved regs on kernel entry
Nah I save all regs on interrupts, we were only talking about context switches though
@vast lotus as long as the last function i call before the switch has C ABI, this should work, right?
the only function whose abi declaration matters is the actual assembly function doing the switch
by adding extern "C" to that function, you're saying, among other things, "this function expects that the caller has saved the registers that the C abi (aka System V ABI) says should be saved by the caller"
the compiler will take care of satisfying that requirement
yeah
It also doesn't work on mine
it just shuts down
maybe display out is broken?
I'm connecting to a 4K monitor
I can try disabling ACPI
Like DTB only mode
Though idk, Ubuntu did work in ACPI mode somehow
It doesn't work in ACPI mode either 
time to buy orion o6
I guess I can just flash different firmware..?
Also Ubuntu does work
Poorly
So like mainline linux needs to get their shit together idk
I can also try limine with linux protocol instead of efistub 
idk, I'm using whatever the installers ship with
mainline ubuntu is working ok actually
shrug
I ran speedtest-cli and it gave very slow ethernet speeds
but I guess it was just a weird server
(I need to figure out how to compile the limine template)
(I failed successfully the last time I tried it (last weekend))
Ubuntu's kernel is not that old?
neat
@near tartan If you are going to test what I asked to, then use this build, pls. It turned, that I checked for the strict WC match for memory attribute, but what if it's more bits over there? So I changed it to print about any range, having WC bit in the Attribute field. It's weird, but seems like the only machine this test has been conducted on with WC typed framebuffer was that Lenovo Snapdragon laptop. Others, both x64 and arm64 just don't. So, if you'll do the test, pls, take a pic.
okay
@ionic lava
Looks like it hung?
it just halts CPU in the end of what it has reached to, Thanks, @near tartan ^_^
Also didn't it try to print something at the end
whoopsie. anyway, thanks to microkernel. ๐
now it's a sh1t ton of WC regions. ๐
that doubling in the end is a bug of printing function. it didn't print after that.
what does this mean? (I'm planning to support ARM eventually and want to know)
the 1st number is an address (system), the 2nd is number of pages, the 3rd is the attribute. 0x0E means, it's ored WC, WT, WB, those 2 with additional 8 in the topmost bite are RUNTIME. It's just a jump into kernel test. it's running now in the kernel address space with all system control registers set up. Because of too many entries, the top of the print got scrolled up and we didn't see, what EL edk is set to run. But now, when I got why WC attribute didn't appear, this huge 455 list might be excluded.
here, I removed that excessive list, so we can see the EL edk runs in. It's important for collecting knowledge. If you can test it yet once, please test. @lofty copper
Nice, thank you, so it's EL2. On qualcomm it's EL1.
yea you're not getting el2 on qcom
lol, so, edk just marks all pages as WC. ๐ nice, very helpful.
Qualcomm hypervisor my beloved
lol
on x1e, not even linux is allowed el2
because some signed blob bullshit from microsoft
@near tartan didn't you say something about using eir as a prekernel for menix :^)
i said i could do a prekernel like eir
ah
@lofty copper is this OPi 5 (Plus)? Well, now I have tests on all feasible arm real hardware except rpi, but I have no idea if edk works there. both uboot (its UEFI) and edk have shown as pretty normal things to deal with. at least so far. Thank to all, now to the further work.
Yes
I hed RPi4, but it was sent to Russia lol
(Plus)
So like you can run KVM and stuff?
yes.
i found that linux does the same
pretty cool tbh
@vast lotus why are you putting these functions in their own section?
do u have a warning enabled where it tells u u have sections that arent explicitly specified in the linker script?
i think thats better than blindly discarding stuff
or actually maybe gc-sections is smarter
but the warning is still good
That's not how gc-sections works
It deletes sections that have no references at all
All you have to do is instead of .text also include .text.* in your linker script.
i had this anyways
u kinda had to do this for bss already and maybe other sections
at least c++ sometimes generates .bss.idk
yea
rust idk tho
better safe than sorry
yeah it wont hurt
i actually do a funny in my script
i don't know why but, if i want dynsyms to be loaded i have to put them in the text segment
or else i'll get linker errors
lol
how
Which segment it's in shouldn't matter
Well it's telling you right there 
myes
Aren't linker scripts just fun?
String'd
ok

okay i'm getting a fucking page fault before it prints ANYTHING to serial
it might actually be stack
give it 64MB stacks in Debug build and print the current stack usage at certain points
MEGABYTES???
yea no still crashes with 256 mb
trust bro
aparently more than marvin anticipated
framebuffer would use at least half of that
it can't be stack
lol
BadgerOS has been running on 16KiB stacks for its entire life now
No problems there
oh wait
this only happened after i changed the lds
64 MB stack??
ah ok XD
arent they used by pic/pie? so that the programm might write to them after obtaining control?
oh
crashes even if i put it in data
yes
lets see what happens if i put it back to text
?????????????
it does not work
WHY DID IT BREAK SUDDENLY???
the smell of ub
okay i'm going to reset this fucking ld script
the only diff i have rn is that i do what @hoary cave said
this
it's still broken??????????????
i fucking reverted
i once had the problem with linker scripts that cargo didnt detect changes to them and the incremental builds where invalid because of that and each time i needed to touch the linker script i had to disable incremental builds
no like i do a rebuild
i'm nuking the result every time
?????????????????????????????????????????
xbps is creating a dir with the name of the package when i install it
what the hell man
i'm going to explode
are you sure you're not messing up the xbps args?
i'm not calling xbps directly
jinx is
and this has worked before
it just now decided to break
oh bruh
@spark surge i'm sorry
i may have broken something
echoing sysroot yields this:
idk how
wait...

omfg
please kill me
idk how i didn't see it
60iq strikes again
this is exactly why i love osdev
it still doesn't work btw 
okay wait
hear me out... what if
this is a limine bug
i know, daring today
cpu bug
OSDev is a good consistent way to make yourself feel like a troglodite
but this page faults before my early init runs
i'm gonna make it print a letter to serial as the very first op
real
if that doesn't work idk what will
Have you checked whether your kernel ELF file uses constructors?
how can it
.init, ELF initialization functions (not called that; I forget the exact name) can be implicitly emitted by your compiler.
i mean yes, i have an .init_array section, but rust doesn't have language-level constructors
i have .init too yes
This does seem like a case for running GDB on the very first instruction after bootloader handover.
like half a month ago
isn't arch supposed to be bleeding edge
idk
yes
they are also behind on xfce packages
last time my friend checked, on llvm/clang too
But in practice you still need packagers so the less important packages including this one won't be updated as quickly.
i'm guessing qemu 10 used to be in testing for a while
what about llvm 
Skill issue 
That means Limine loaded your executable incorrectly 
Use function, not line, breakpoint.
single step through the instructions?
i have
one sec
okay it actually gets somewhere
it doesn't die immediately
it sets the idt
then ?????
Does your code rely on the addresses of the sections as defined by symbols in your ldscript?
not at this point
it should print at least the memory map before it even touches virtual memory
I suppose later for when you take over the page table.
yes
How easy is it for me to download and debug this with you?
right
you need to build llvm to compile the kernel?
yes
why
I'm on a laptop right now so I'll wait with that one.
uacpi
wdym uacpi?
ah L
and i need host-llvm anyways for other builds
If I'm gonna compile LLVM, I'm gonna compile it on my desktop, which is actually capable of this. My laptop didn't have enough RAM last time I tried compiling LLVM.
how much does it have?
Oh it has 40G now. Must have been a long time ago then because that had like 16 at the time.
I can compile llvm with 16 gigs
Still though, don't want to burn my battery in public transit for two hours only to get home before I compile Menix 
just don't give it more than 8 cores
i was pung
I still don't get why this needs custom-built LLVM btw. uACPI doesn't depend explicitly on stdlib after all.
ah
It sounded like you were talking for the kernel.
you could just compile the kernel on its own but then you'd have to wire it yourself
no
you do need libclang though
and clang
That means I already have what I need.
I already installed both a while back
Then the next question from me to you is: How compile Menix?
Yeah but just the kernel repo? Or do I need the bootstrap repo too?
if you don't want to wire everything yourself, just clone the bootstrap repo (that will build llvm though)
I'll just comment out the LLVM builder lol
o
and it prolly doesn't have an up to date llvm
just the kernel it is
Main branch correct? Because I get this error:
Wouldn't you want to sort those?
you're probably on an outdated toolchain
I do no has nightly
idk, why?
I just did cargo build since you said as much 
I know that you have to do it with constructors
Maybe there's something similar
maybe
oh bruh
i think i have found the culprit?
.early_array is NOT a fan of being run
???????
what the hell?
this is obviously wrong
Not good
How do you define it?
Can you verify the array size with objdump -t?
here
exactly 8 bytes large
which is that one function
hm
early_end is wrong
early_start is correct
only serial::init should be in there
Does the assembly look like what you'd expect? You'd expect to see two lea instructions, one for each end of the array.
pretty much
Since I haven't managed to build it yet, care to show me said asm?
??? This assembly doesn't look correct to me
how so
It's calling libm_math::exp2? Why? Where are the references to your LD symbols?
oh yeah good point
call <sin+...> -> obviously incorrect
It's weird to me your GOT doesn't have a symbol. Could this be causing problems?
BTW I managed to build your kernel
target/release
or target/debug
sorry wait
target/x86_64-kernel/debug
is what you want
menix.kso
Ok
I've built it and I see assembly but not how that assembly gets its hands on LD_EARLY_ARRAY
plt moment
ye
try linking with -z now?
what it do
turns off lazy binding
should turn JUMP_SLOT relocs into GLOB_DAT
actually limine does not do either of those
btw whats the advantage of it
why is a plt needed at all
link with -Bsymbolic or build with rust's equivalent of -fno-semantic-interposition
the plt and got is used to minimize the amount of relocations, instead of needing to relocate every call site you only relocate the got entry
same issue
but it introduces a runtime cost no?
minimal
you can turn the plt off with -fno-plt to have the compiler inline the plt thunk into every call site
It theoretically does but modern CPUs don't care
but that will still go through the GOT
They will predict the branch target address before fully decoding the instruction levels of don't care
hmm, well basically what you want is for the main kernel executable to not have any JUMP_SLOT or GLOB_DAT relocations
only RELATIVE
since that's the only one limine handles
well it would panic if it encountered those, right?
no because undefined weak functions also cause JUMP_SLOT
it just writes 0 to the relocation target for it
-static-pie?
just checked, i only have RELATIVE relocs
afaicu the idea is for the main kernel exec to export symbols?
-static-pie won't work then
yes
So you want to export symbols and basically interpret your own kernel as a dynamic library for the purpose of dynamic modules?
actually my bad, limine does resolve JUMP_SLOT and GLOB_DAT fully
pretty much
it allows me to treat modules as regular .so's
which have DT_NEEDED and so on
that integrates tightly into the cargo build system
if it's not weak, it looks for the target symbol and uses it's address
Does Limine dynamically link modules into the kernel this way?
no limine does not do any dynamic linking
limine just loads them as blobs
I see
it only processes a small set of relocations on the main kernel executable
the kernel has functions to relocate and resolve
still, i don't get why this is broken now
send executable?
neat readelf can demangle rust names
these relocations look strange, why are the addends negative ```
ffffffff80291950 0000000000000008 R_X86_64_RELATIVE -7fd51788
or is readelf trolling
>>> hex((-0x7fd51788) & ((1<<64)-1))
'0xffffffff802ae878'
strange
whats the order of operations with & and as here?
&(... as ...) would be right, (&...) as ... wouldn't? (unless const fn() is a function pointer already?)
end points one past?
Is this with the original ldscript again?
yep
actually the debugger output suggests what's in parenthesis is right
first & then as
yeah
otherwise it wouldn't even compile
oh well i think the executable i sent you has 2 entries
serial init and a test function
which should be empty
while cur < end
well yes but i mean end points exactly after all early_init entries
so it makes sense that in the debugger it points to an unrelated fn
oh
right
but the address for end is somewhere where it shouldn't be
actually wtf
imagine some bullshit with callconv lol
i hate everything
i think i know what's actually going on
@eternal wharf lol
the debugger was wrong
i did a little UB moment

it tries to read the command line to determine if it should print to COM1
but that hasn't been set in early_init
mfw
or rather,
i shouldn't be calling early_init at that point
easy fix
@hybrid island @eternal wharf thanks for trying to help anyways
is it normal for my tsc to overflow after like 5 seconds
i can't multiply by 1 sec and divide by frequency
this kind of wraps immediately
wtf should i do here
Actually yeah I see this happening if the TSC is like GHz kinda fast.
yep, mine is 3.8GHz
In a 64-bit multiplication like this that could overflow quickly
divide+remainder by tsc freq, use remainder to calculate sub-second time
how fast is the tsc going to wrap?
Well at least 4 billion seconds by that method
Or 126 years
good enough
I should do this in BadgerOS too tbh
But I've been spoiled with MHz-speed timers :P
I've been using the time CSR for RISC-V reasons
makes sense
i wanna start porting to risc-v as soon as i have scheduling running
(or as soon as userspace works again lmao)
riscv is fun
i know
is almost like your nickname contains riscv
real menix score leaked
yes yes 
smh
lets see if it still boots on real hw
very good
letsgo
Running hobby os on framework laptop

I'll get to that eventually too but first I need x86_64 support literally at all.
3/3
very cool
menix doesn't boot on my amd machine bc i don't have !x2apic support :(
can also do 128 bit multiplication + fixed point math to replace 128 bit division with a shift
This is probably more efficient actually
Since the coefficient can be precalculated
what's the math for that?
coeff = (1 << 64) / tsc_freq
Then when you want time, do (ticks * coeff) >> 64
All in 128-bit context of course
i wonder how rust translates u128
Multiple 64-bit multiplies, it's not how rust translates it but how clang does so.
x86 has native 128 bit unsigned mul
or rather
64x64 = 128
which is what the managarm code takes advantage of
i should too
So does RISC-V. And FWIW ARM prolly also does that.
the managarm timer code precomputes freq / 1e9 and 1e9 / freq as two fixed point fractions (with a 64-bit size)
with the point being positioned dynamically based on how many bits are actually needed
to avoid 128-bit division when computing the constants
that was both ticks -> ns and ns -> ticks are just a mul and a shift
lmao
not worth going to sleep at this point
insomnia time

Idk your tz but it's 00:27 here
Lmao
well it's utc+1 +dst now no?
uhhhhh
('ate dst)
gmt+1?
Oh you're German, we're basically neighbors
yea
hate time zones
(also thanks windows for storing fucking timestamps in local time inside efi)
does windows still program the rtc to local time instead of utc?
it appears so
Yes it does
whenever i switch back from windows my clock is off by an hour
amazign
Just don't use windows 
yeah easy as
i nuked my windows partition recently and haven't been happier
free 80GB for my linux rootfs
i have it on a different nvme now, but i have like 3 games I cant play on linux
cuz ac
tell windows to use utc
reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_DWORD /d 1
i use uacpi too and i dont need it..
i do but i dont need to compile it myself
no
i use the host llvm to also build programs with clang
for user space
so i can just reuse that
the container comes with debian
so forget ever getting uo to date llvm
cant you usre fedora or arch or something else for the container?
no
jinx requires debian
to the rust nerds here: how the hell does one detect the current crate type?
something along the lines of #[cfg(crate_type = "dylib")]
you cant do that
cringe
what you can do is make a custom cfg flag
yeah
or -cfg SOMETHING in rustflags
println!("cargo:rustc-cfg=something"); // build.rs
#[cfg(something)]
and in build.rs you can just read cargo toml
to see what crate type it is
how exactly am i supposed to map an ELF like this?
This shares flags with a virtual address that's less than a page big
Where did it come from?
rust
it's a kernel module i made
do i just add an align(4k) everywhere
oh shit yeah that was it
we are so fucking back
I mean the member of the struct
It looks like an array
What's its type?
&[PciVariant]
Interesting
'Static means it must be a global?
Btw how does it know the length of that array
rust
i'd imagine it just stores it
So its like a slice
it's exactly a slice
Ah
tbh that's terminology bingo, an array would be [PciVariant; 16]
i want to have a dynamic amount of possible variants, so just use a slice
Is it possible to make an unbounded array that doesn't store the size?
not safely
I see
Ig
this pci variant matching is quite nice
i just have to implement the MMIO stuff
actually i think that's already working
How easy is it to make an inline data structure similar to how container_of works with e.g. rb trees?
Do u have something like that for lists for example?
nope, but i will have to at some point for sure
there's intrusive_collections
which use traits to implement struct member access
Interesting
the loaded module references a symbol that should have been relocated
but this is obviously not mapped
man, issue after issue
Limine bug?
i hope not
but the module has no knowledge of this address
and the kernel doesn't either if it's been relocated
AHA
it doesn't relocate symbols
mfw
ok bruh this is bad
i don't think it's the bootloader's job tbh
but that means i can't use kaslr
eh fair enough
idk how to enforce this though
i have to build as a dylib for this shit to work
but that makes me ET_DYN
@grave peak lol the random page fault was a tlb flush problem
it works now even with kaslr
nice
tomorrow i will have time to finally go to user space
(and not do a lot because the vfs is like 3 lines atm)
does anyone have a better idea for logos besides the gears
i might want something less boring
but i can't think of anything that's just a cat or seal
current logo for reference
rusty and blazing fast. 
It does
Opt level 3 does most of the work but fat lto will get you at least 300k
what cpu?
intel ultra 265kf
can you test my kernel?
send iso + cmdline
qemu-system-x86_64 \
-M q35 \
-cpu host \
-display none \
-debugcon stdio \
-bios OVMF_x86_64.fd \
-enable-kvm \
-cdrom chronos-x86_64.iso
-smp 4 -m 2G | grep 'avg'
its a bit slower without the OVMF
-display none 
same points without it, the flag is just for convenience when testing
why are you stalking me
@near tartan could you also test this
qemu-system-x86_64 -serial stdio -cpu host,migratable=off -M q35 -accel kvm -bios OVMF_x86_64.fd -cdrom image-x86_64.iso
run it a few times, I get vastly different scores on each boot
ill be home in a few h
same
sometimes i get 2.7, sometimes 4.8
same
How do you guys create ISO files?
I have a tool that will hopefully work but it's not very automated
I assume most people are using xorriso or however you spell it
Same here.... I'd rathere make a disk image, and go from there...
i might just distribute compressed disk images
That don't sound like a bad idea honestly
limine template just straight up gives you a way to make an iso
you can take a look at it, just a makefile
what if i don't want to 
I'd rather make my disk image.
my neck
Oh God ๐ณ
tuff
cursed but it work
what was wrong with it
wait do you have two seperate pcs connected to those two monitors
?
broken bios
and?
no
i need to see what my main pc is doing and what my server is doing
if my server can't boot i can't ssh into it
so i need to connect to it physically
Ah makes sense


