#EvalynOS
1 messages · Page 5 of 1
thank you so much
you're welcome!
o n o
wat
imma read more of ur kernel before i do
Is my kernel really that cool?
maybe document this in a md file : )

yes :D
from what i saw, you added back the saving of all the registers
i still don't know why that works
n e i t h e r d o i : )
that's why i sa i d
d o n 't j u d g e : )
this is me taking shots at random shit
when u have nothing, do random bullshit
until u actually do get it
You might wana checkout my HRMR codebase if you like my kernel code
@obtuse loom why would saving all the regs on ctx switch fix this?
im presuming that this doesn't return to garbage anymore
That’s some of my c++ work
oke imma do that
(My not horrible c++ work actually)
Wait
@devout path @viral bison
The real hardware test
Let me generate a patch file
send me the elf directly

and the initramfs
True
Remember when my kernel was like 5MB
Because the bad apple was bundled inside of it
XD
Oh also remember when it was kernel.bin and not kernel.elf
When I had my own bootloader
oh god
fix what? 😩
isn't it bcuz every thread expects to get back exactly the cpu state it had?
That never wanted to work between real machines
i nuked the kernel before the cli initialized
Because universal my ass UEFI
the stack corruption
This right?
im juggling between what i know and what theory would be
and both contradicts atp
i have no fuckin clue anymore
can I have some more context
yeah supposedly
btw @hazy saddle pressing enter or whatever key before it says press enter, will lock up the kernel
Thread one saves data in R9
Kernel switches to thread 2
Thread 2 puts its own shit in R9
Kernel switches back to thread one
Thread one gets wrong data from R9 and fucks over the stack
scroll up a bit
the framebuffer was getting nuked after a bit
link plox you guys chat a lot
Ehhhhh that check is gonna get removed soon actually
so was the whole stack
Once I get a user space shell
y e s
huuh, sec
This chat has so many messages compared to how mature others are because my kernel has been so buggy and fun to debug 
lovely
@obtuse loom from here basically
It’s held up with sticks and stone and ten pounds of Elmer’s glue
btw, it's working on real hw
LETS GOOOO
tho i hear my cpu crying in pain

im going to cry
pls put pause on the quit thread
It’s CPU rendering the entire bas apple
okay cool

what does the context switch look like
mmmmmmm
before it looked like this
before it was this
global thread_switch
global thread_switch_user
global switch_to_user
section .text
thread_switch:
pushfq
push rbx
push rbp
push r12
push r13
push r14
push r15
mov [rdi], rsp
mov rsp, rsi
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
popfq
ret
USER_STACK_TOP equ 0x0000000080000000
switch_to_user:
mov ax, 0x30 | 3
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push 0x30 | 3
mov rax, USER_STACK_TOP
push rax
push 0x200
push 0x28 | 3
push 0x4000
iretq
now this
now it looks like this
global thread_switch
global switch_to_user
section .text
thread_switch:
pushfq
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov [rdi], rsp
mov rsp, rsi
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
popfq
ret
USER_STACK_TOP equ 0x0000000080000000
switch_to_user:
mov ax, 0x30 | 3
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push 0x30 | 3
mov rax, USER_STACK_TOP
push rax
push 0x200
push 0x28 | 3
push 0x4000
iretq
Switch to user will get rewritten btw so I can load them anywhere and maybe even have ASLR?
With how buggy it is though I don’t know if we should have ASLR XD

That’s you for helping
xd
this looks fine to me
yeah and then i decided to change it
somehow saving all the regs fixed it tho?
I think your diff just happens to make another bug not happen
yeah and then i saved every reg
But then why wouldn’t a bug like this happen?
you probably have some situation with some corruption hitting the stack of another task
that's my best guess
and changing the layout like this happens to make the important values move somewhere that's not overwritten

all the registers you added to the push/pop list are callee saved
so the compiler should manage it correctly
y e s
well i think it was with the create_thread funct earlier it had dupe pops
so i was like
: )
am i right
m literally just
completely guessing
Until it didn’t 
y e s
it didn't when you changed something inside badapple
it had dupe pops so the ptr after the switch wasn't pointing at a valid saved rip
huuh
the old thread_switch is correct, can't say the same for the rest of the codebase
:^)
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
REALLY
so it wasn't the ret jumping to whatever the fuck?
no
im gonna stop thinking
Question? How much of a performance penalty is there from manually putting the pushes and pops verses the compiler doing it for you
: )
depends on what the calling code looks like, it increases register pressure which makes register allocation give worse results in functions with a lot of values
well I mean
you're not changing the declaration
so the calling code will still save all those registers for you
and then you're saving them again
so there wasn't any missing regs or anything??!
so you're not getting the benefit of the compiler not saving them for you either
no
not that I can tell
im damn hallucinating
oh yeah right
the compiler knows calling an external function will clobber all the other registers
as I said, as long as you're not misusing inline assembly to call it
I don’t think I am
as long as you're calling it from normal C there should be no bugs related to this
this would be proper for setting up the inital stack though right?
and feeding in an argument
don't need pagemap there
abi rules only apply to funct calls no? not switches?
i may of removed that
yes
switches are not functions
yes i did remove that
yeah
should be sys-v
huh
how would i do that?
i dont think i would be
o m h
I assume you would know :^)
honestly should set an explicit target but yeah
yeaaah
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
i had to do readelf xd
okay you're good
if i put this back in i gett an uhh page fault right away
HUH
well, did you also change the stack?
cool, tried debugging it?
yeah well
yes
yeah
it should work theoretically
@devout path
dramatic drum roll please
dramatic drumroll
It works
amazing
Thank you for your help @obtuse loom
🎉
;-;
no worries
It was the friends we made along the way
what was it
God if I know
it was about saving the flags?
it's time for me to finish implementing syscalls
Who needs system calls when you have int 0x69
shouldn't be needed either
lesson learned: 67
NOOOO
but if you want it to simplify initial state setup then like whatever
fair
one push isnt hurting modern CPUs
honestly yeah
it's fine
but it's not needed
up to you if you want to remove it
how would one go about doing that btw
removing pushf and popf?
oh
task quit should not be needed here
What happens if the thread attempts to return to nothing though?
Better safe than sorry?

Task quit could also start auto cleanup of the thread on return
but what if the thread its self was also the reaper?
it might end up very badly

these what if shouldn't be discussed when it hasn't happened yet : )
i love making problems for myself
this causes the PF unless i remove an extra thing from the stack and then it locks up
wack
Wdym
unexpected
Ah
wat featuers would u like to have in ur OS @hazy saddle
I eventually want it to be able to compile its self
try to debug it maybe?
And to run a window manager
I’m too lazy for saving a few CPU cycles 
Wdym?
develop somethin
And run doom
i mean

btw, that code is for IOApics
so if they ever reach 0x80, i just make them go up by 1
Can’t that u8 be a Boolean
boolean is an u8
A PR to what
just u
Wait what are you building 
ext2 support : )
Don’t I need a physical disk driver tho?
f a i r
I was gonna hold off on that until PCIe and USB so I can have a driver for nvme ssd and mass storage devices

true

so you can get accurate timings
But yeah ext2 would be really low priority
And honestly jumping the gun to ext4 would be based
yea ;-;
Perhaps you can work on the APIC and co drivers?
hhhhhhhhhhhhhhhhhhmmmmmmmmmm
yeah why not
After I do some basic cleanup on this and push
Can you also use sata in a legacy mode to make it more easy to talk to too?
That could work for ext2 perhaps
yes
And I can get a cheap SSD and throw it in my PC for testing
me who wanna support HPFS
uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh it'll prolly take me a week though ;-; but yes yes ofc ofc
or was it APFS
And then ext4 can come with the USB + PCIe + NVMe stack
it was APFS
yeaa
xd
;-;
if you're going to API match linux you might as well ABI match and not have to port anything
And at that point I should just get inspired by Linux /s
i will have syscall support for linux and my os
I mean sure lol the license allows it
- i plan to have macos and windows ones too in the future
Yes here is my kernel which is just Linux but I found and replace the entire thing
Has anyone ever done that before here

there are even people who do it without releasing the source and breaking the license
i copy linux (the kernels) subsystem's architecture : )
true
Honestly my kernel should be able to get doom once I get a libc done?
there are conspiracy theories that the kernel is being ported to rust so that companies can grab the code and edit it in closed source
you wish
It’s not that much more than libc and 5 functions
... but why? 💀
so they don't have to share their edits
corpos are strange
why would they rewrite it in rust is my question
Moss kernel?
you can already break the license
MIT license
no one is getting in trouble for it
they are giving the rust ports MIT licenses
Huh
plenty of companies have changed linux, not released changes and gotten away with it
it happens daily
I think I may of broken the license when I had to modify the driver on my local device to get a controller working 
it only applies if you release a binary publically
this is a strange memmap, lol
What were the parts you were gonna work on again
uefi and its strange stuff
also, you should prob not use bootloader reclaimable stuff
I mean that literally means usable after you're done using bootloader data
isn't the kernel stack in there too tho?
how should I know
what stack are you using
i leave the default one alone
from the bootloader?
yes
then check the spec
k
hi
just simple stuff
i plan to make a block driver for now
are you using the limine protocol?
or something else?
yes, limine
okay then yes it is
"rsp is set to point to the top of a stack, in bootloader-reclaimable memory, which is at least 64KiB (65536 bytes) in size, or the size specified in the Stack Size feature. An invalid return address of 0 is pushed to this stack before jumping to the executable's entry point."
...or just allocate a stack in the kernel :^)
i can do that?
i already get the stack top
1: Just set up multitasking and exit the init task that's using it
2: Just write to rsp in the entry point, declare it in asm
oh i do that already
there are probably many more
all the tasks have their own rsps
yes and when you're done using bootloader data (including that stack) then you could use bootloader reclaimable memory
wait @devout path how should i handle returning systemcall data?
would i just do frame->rax = ...
yeah that works
and now this clobber list can go bye bye now i control registers properly

i wonder what n00b thinks of this
heh

yep
i really like C alot tbh
what's weird is that u declare by making it a constant xd
same
imma hit the sack
mention me here once you're done cleanin up
wait before you do
mm?
from SATA and ext2 right?
nice ;3
what devices will it be selecting lol
also if i make any changes il ping
so the merge conflict isnt an ass
uuh wdym
like what if there are two sata drivers

HEH
have it check GPT parition table for the right UUID?
and pass it in as a limine boot cli arg
its how linux does it right
LMAO
i was planning to deviate from what linux does
but if i get extremely lazy
i'd probably just do that
but i mean wouldnt it be good to be able to spesifiy the drive and partition to mount
maybe have it handled in the initramfs?
yeah yeah
yeah why not
and then that can even start the shell etc
No need for a FULL init system
But having a program to read a config on how to mount the root drive and start the shell?
That way you can make the conf file run any program
Or have it be a chain of programs to run?
To say mount drive and then run program to setup network card layer
And THEN run the shell
Maybe use TOML for the config that’s easy to parse right
yeah
Or “TOON” 
hmmm maybe only
XD
wat
was that sarcastic or
xD
o h
What’s the issue with TOML
gonna need one more test on irl hardware before push
but im almost done reviewing and getting rid of stargglers
nice
next commit will be a simple generic constructor for threads
what do these refer to again
ehhh il figure it out
should work with sysv
worst case
inline asm grab the reg
For redundancy xd
Basically making sure it doesn't go to garbage
can i also get a video recording of the many bad apples for friends?
oh
yes but if i need to pass an argument
Lemme boot my pc again
WTF
why
just finished eating
code review looks good enough and its LGTM
send it if you want me to try
Peak
@hazy saddle
Fuck yeah
@tawdry ingot get in here and look at this
I did it buddy. It’s gonna be pushed to main soon and then you can get inspired
Your kernel is saved
@viral bison this about sums it up right
@devout path its pushed
Used to pray for times like this
No thank you!
Tar.gz as initram FS might be cool at some point ngl
Il add that to the list for far things in the future
yea
you're welcome!
If the initramFS is starting to near ~16MB il start work on compression probs
Aleighty
My next steps are gonna be getting doom working
I think I can compile it as a freestanding app and point it to my headers for a libc and generate a .a file for static linking
As il need to make a really custom libc because I’m missing some semantics it would need
And il have to emulate them
oooh nice nice
Because I don’t have semantics for opening and closing files or seeking or file descriptors
I’m gonna have to have the libc emulate them
And that will handle FDs and map them to the right file operations for the system call side
@viral bison how do the system call instructions work on x86-64 btw
Like how would I be meant to set them up
I know it’s an MSR but isn’t a bit more than that?
sec
this is how i do it
Frame and Syscall regs contain basically the same values
What are the values of these magic numbers that I can’t see?
Looks really easy tho
which ones
the Segments?
And then in userspace it’s just load things into register and call syseenter?
syscall*
The selectors and the MSR addresses
The selectors are offsets to the GDT entires right
the msrs are fucked up
they want UCODE32, UDATA and UCODE64 in that exact order
same for KCODE and KDATA

you can skip UCODE 32 tho
and just set that value to the entry before UDATA
if you don't want to use the syscall instruction in a 32 bit env
i do support compat mode too
So why is it user code 32 and kernel code 64 here?
(or well, it should)
it sets the base entry
then as i said, the msrs are fucked up
so it gets the other entries by hardcoded offsets
This looks like a mess
but yeah
it's not really
I don’t know the magic numbers I have to fill in here 
I mean the order
Ok the wiki has the right numbers
Il change to #defines and then use them
These are the 32bit ones
And then I just need this order
yes
Plug in the MSRs real quick and have a basic assembly handler and we are all good
Should be easy
we hope
20 minute quick adventure in and out
@devout path i may wana make a dev server for github commit notis and shit so its easier for you if i am pushing stuff when you work
or just in general
i dunno if the mods here could get a web hook in a thread?
wait
wtf do flags match to
@viral bison anything wrong with this
the wiki values dont wana work
even just for 64 bit ones
wait why did this skip 4??
i think a flag is wrong here?
?
XD
then wdym it doesn't work
well, the last 2 are flipped if you wanna use them for syscalls
triple fault
when?
when do this
then would this jsut work™
well, did you edit all the selector values too?
like, in every other asm file
you should have to edit: GDT asm file and the ctx switch
I don’t have a GDT asm file
well, the code you use to load it
What code do I need to change? The segments were at the same offset for atleast trying to replicate the wikis version
well, you did swap ucode and udata
did you also swap their values in the loading / ctx switch?
Wait what
But its faulting even before my context switch code
But yeah I’d have to change that I think
well, i think you did not swap those values in the gdt loading
I’m
Too sleepy for this rn
oh wait
i don't think you have to swap them there
hmm
i think the flags are wrong
Then why do these flags work when 5 and 6 are swapped
And these don’t
oke
ohhhhhhhhhhhh
@devout path do you know if this is correct
I’m trying to get system calls to use the right instruction
What is : 4 mean
it's just 4 bits
So like a compiler hint?
no, it sets the size to 4 bits only
Oh you can’t do that in C 
Or can you?
You can
Huh neat
wait @viral bison how do these constructors work to mappings things out
wdym
i mean how does c++ map the consttor arguments to parts of the struct
this shoiuld be okay ho
void gdt_set_tss (int num) {
gdt[num].limit_low = sizeof(tss);
gdt[num].base_low = (uint64_t)&tss & 0xffff;
gdt[num].base_mid = ((uint64_t)&tss >> 16) & 0xffff;
gdt[num].access = 0x89;
gdt[num].flags = 0;
gdt[num].base_high = gdt[num].base_mid = ((uint64_t)&tss >> 24) & 0xff;
gdt[num].base_high = gdt[num].base_mid = ((uint64_t)&tss >> 32);
}
try to set the flags like i do
also
ltr is just wrong
ltr should be loading 0x18
oh wait no
you changed it
then yes it's ok
then why triple fault
idk
we need the full log
what log its faulting i cant get anyb data out
Run QEMU with following flags: -M accel=tcg,smm=off -d int -no-reboot -no-shutdown
i did fix this line gdt[num].base_higher = gdt[num].base_mid = ((uint64_t)&tss >> 32);
here
also -D log.txt
wat wat happened
h u h
i did find one minor issue
the base_high vs base_higher
@devout path @viral bison
thats blocked by the server?
no
yeah it got automodded
damn
thats a tripple fault no?
doesn't seem like so
i mean without the flags it auto reboots
then its a triple fault
but i only see 2 exceptions there
last line
i'll take a look at this tmr if it's not fixed yet
check RIP ffffffff80001e37
im still tryna figure out why my fix worked yesterday
- im ded rn fr
absolute dead
OBJ dump my .elf?
addr2line -fai -e <exe> <addr>
/home/evalyn/Documents/Programming/C/evalynOS/src/kernel/drivers/x86_64/gdt.c:73
i on't think doin any static analysis would come up to somethin useful
ok im gonna regret saying that but
nvm
ok nice
well, what's there?

this is correct
wtf
Isn’t my kernel lovely
did you set the ist of every other interrupt to a non 0 or 1 value?
I don’t think so
that might cause problem
like this
yes
but remember to update it too
where you set the ints
TRIPLE FAULT
ehm
What
you set DF to 2 here
shit
still TFs
how is the stack represented btw
would this be proper qwinci?
struct __attribute__((packed)) GDTEntry {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_mid;
uint8_t access;
uint8_t limit_high : 4;
uint8_t flags : 4;
uint8_t base_high;
uint32_t base_higher;
uint32_t _reserved;
};
void gdt_fill_entry (int num, uint8_t access, uint8_t flags) {
gdt[num].limit_low = 0;
gdt[num].base_low = 0;
gdt[num].base_mid = 0;
gdt[num].access = access;
gdt[num].limit_high = 0;
gdt[num].flags = flags;
gdt[num].base_high = 0;
gdt[num].base_higher = 0;
}
void gdt_set_tss (int num) {
gdt[num].limit_low = sizeof(tss) - 1;
gdt[num].base_low = (uint64_t)&tss & 0xffff;
gdt[num].base_mid = ((uint64_t)&tss >> 16) & 0xffff;
gdt[num].access = 0x89;
gdt[num].limit_high = 0;
gdt[num].flags = 0;
gdt[num].base_high = gdt[num].base_mid = ((uint64_t)&tss >> 24) & 0xff;
gdt[num].base_higher = gdt[num].base_mid = ((uint64_t)&tss >> 32);
}

__attribute__ ((aligned (16))) uint8_t kernel_stack[16384];
__attribute__ ((aligned (16))) uint8_t user_stack[65536];
__attribute__ ((aligned (16))) uint8_t df_stack[65536];
__attribute__ ((aligned (16))) uint8_t nmi_stack[65536];
ah
65k is too much i think btw
i only gave it 4k
anyway, let's go back to that TF
the gdt entry is too big
it should only be 64 bits
and the 64-bit int following the actual tss gdt entry is what you should set to tss_addr >> 32 like you did in the old code you had in git
i copied this for that 
you don't need a separate one for the tss one anyways, if you really want to keep the gdt entry split to separate fields like that instead of just one u64 you could make it an union of a struct that contains the normal fields and then just a plain u64
and then do smth like ```c
gdt[index].entry = make_gdt_entry(...);
gdt[index + 1].tss_addr = tss_addr >> 32;
whats a union
you haven't ever used an union in c?
nope my first time
but i think i got it?
it works
unions are cool
wait nvm
i think i got this one though
@viral bison
New stscalls?
Gg
Could you re give the screenshots for the MSRs and stuff for the new syscall thing
Sec, i'm finishing my pizza
Oooo what kind
Oooooo
thank you
arent msrs a u32?
Note that the Kernel does not automatically have a kernel stack loaded. This is the handler's responsibility.
@viral bison should i just grab this from the threads->stack_top?
yours says u64
yes

you also need to enable again interrupts After you loaded rsp
yeah mine just combines the value into 1 u64
and split it inside
i mean for the first arg
ima do that frfr rn
it should be u64
the osdev wiki says otherwise 
it's a 64 bit reg
don't mind it
i think it's still in 32 bit
lol
XD
for the ID
here we go
huuh
rdmsr is wrong
it's the same as wrmsr XD
it's reading
so it should be returning stuff
that is using pointers
ah
you are not
here is a C one ```c
static inline uint64_t x86_64_msr_read(uint64_t msr) {
uint32_t low;
uint32_t high;
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
return low + ((uint64_t) high << 32);
}
yeah i sent it above
bonk me
c != c++
wait i also need to set bit zero here
me when __readmsr(SOME_MSR_MACRO) intrinsic 
xd, is that a clang one
oh it exists???
i think the bootloader does this tho
you can never be sure
limine doesnt at least
LME
only?
could double check the proto, I dont use limine after all
msvc lol (though clang's intrin.h implements that too, idk if you can use that with other targets than windows tho might not be able to because of sizeof(long) being different)
ah 😄
does fast FXSAVE enable any other instruction?
and LMA?
lma isn't something you can set yeah
k
uint64_t efer = rdmsr(EFER);
efer |= (1 << 0);
efer |= (1 << 11);
wrmsr(EFER, efer);
hmm
don't do 11
that enable NX right
limine enables that for you if the cpu supports it
yep

btw @rancid viper
🤷♂️
I just unconditionally use it without even panicking
would have to be a very old cpu for it to not support nx
yep
I check a bunch of cpuid bullshit in init somewhere
so happens to be there iirc
if your CPU dosnt have NX get a cheap used office pc from ebay for cheap
will prolly come across that code soon, im revamping my init system
for the fxsave bit as far as I can tell the intel sdm doesn't say its even there, it falls within a reserved range so it might be amd only
done
its probably nothing you should worry about (and you should prefer xsave/xrstor to fxsave/fxrstor anyway if they are present)
i sent the explanation from the osdev forum above
this is what i do for fxsave and it works on intel. i enabled it to fix a crash when i had kernel sse
yeah seems to be an amd meme
i dont use kernel sse anymore tho
hmm

saving this rq
#define true (__rdtsc() % 2 == 0)
boolean
wrmsr(SFMASK, ~0x2); why is this a NOT 0x2?
so you disable every rflag except res1
ah
@viral bison ?
void init_syscall() {
// enable syscall instruction
uint64_t efer = rdmsr(EFER);
efer |= (1 << 0);
wrmsr(EFER, efer);
uint64_t star = ((uint64_t)0x18 < 48) | ((uint64_t)0x08 << 32);
wrmsr(STAR, star);
wrmsr(LSTAR, (uint64_t)syscall_handler);
wrmsr(SFMASK, ~0x2);
}
void execute_syscall(struct syscall_frame* frame) {
asm volatile (
"movq %0, %%rsp"
:
: "r"(get_current_thread()->stack_top)
: "rsp"
);
do you have a user code 32?
yes
k, it should be ok then
then i swap this out
i don't see an int 0x69 there
it was
wait, i think the mov rsp here is a bit bad
idk if it'll work
yeah shit
il just not inline it
its easier
change_stack:
mov rsp, rdi
ret
wait what else did i have to do other than chanign stacks? @viral bison
it still GPFs
at in usercode
i think you are still changing the rsp wrong
huh
strange that is failing in the IDT

