#Nyaux
1 messages · Page 19 of 1
so what am i supposed to do
ok think of *mut T as &mut T without the compiler checks
but with identical semantics
right
i.e. you still have to do ownership
is there nothing i can do
just stop writing c like code and using raw pointers all over the place
"sometimes" phantompinned can get you out of some soundness issues
but also that
or more accurately checks on them
i am unsure of how to solve this cause i need to the data of vnode into my directory
pub struct tmpfsdir {
pub head: Option<Box<tmpfsdirentry>>
}
struct tmpfsfile {
data: Option<*mut u8>,
size: usize
}
pub struct tmpfsdirentry {
name: String,
vnode: vnode,
next: Option<Box<tmpfsdirentry>>
}
this is how my tmpfs structs are defined
struct tmpfsfile {
data: Option<*mut u8>,
size: usize
}```
what the actual fuck
first of all
if your file has 0 bytes
you can just use a null pointer
no reason to use option
second
have you heard of fucking &mut [u8]
😭
why is vnode inside tmpfsdirectory?
store it in the struct
its better 😎
shouldn't tmpfsdirectory be a vnode so to say and implement the vnode trait
no because that would be too much like rust
just make vnode like
Box<dyn VNode>
and make vnodes just implement a vnode trait
what about flags
what flags?
vnode flags
what kind of flags do they even have?
dir
oh also i guess Rc<dyn VNode>
you dont need to copy paste what they do 1:1 lol
also that design is fucked because of hardlinks anyway
and if you need flags then you can just store the flags inside the thing that implements the trait
plus there are other things that arent files that you can put in an fd
e.g. epollfd
or pipes
etc
i think a linux-style namecache design is cleaner (though i havent implemented it because writing code is boring, theorizing is much more fun)
trait vnode {
// ops
}
struct tmpfsdir {
pub head: Option<Box<tmpfsdirentry>>
}
impl vnode for tmpfsdir {
//blah blah
}
struct tmpfsdirentry {
name: String,
flags: vnodeflags:
next: Option<Box<tmpfsdirentry>>
}
struct tmpfsfile {
data: &mut [u8],
}
is this better?
??
hm?
have you heard of naming things the normal rust way lol
lol but is it better tho at the very least
you have a bounds checked array
and then a size
what the fuck are you doing
just
right
and also why do you need flags on a dir
theres exactly one type of file a dir can be
(and also it's part of its of its stats you don't actually need to know the kind of file it is for any anything)
oh okay, so tmpfsentry only needs flags
cause how else are u gonna check if a dir entry is a directory or whatever or yea
okay when u call v_rdwr
on a vnode trait object
and if its a directory ur calling this on
its enough that the ops on the directory know that its a directory (and return error if the op isn't supported on a dir, though you could also have a default impl for the op that returns an error about it not being supported)
the default one should just be ENOSYS probably
what?
use crate::{alloc::{Vec, String, Box}, tree::Map, sys::{Result, Errno}};
trait Object {
fn read(&self, buf: &mut [u8]) -> Result<usize>;
fn write(&self, buf: &[u8]) -> Result<usize>;
fn lookup(&self, child: &str) -> Result<Rc<dyn Object>>;
}
struct TmpfsDir { files: Map<String, Rc<dyn Object>> }
``` just do like this or whatever
plus some op to create files
okay so what if i want tmpfsdir to have a directory called test right? and what if i call the read operation on it, whats gonna happen
return EISDIR?
impl Object for TmpfsDir {
fn read(&self, buf: &mut [u8]) -> Result<usize> { Err(Errno::EISDIR) }
// ...
}
oh im fucking stupid
😭
i forgot u impl individually
this is a much better design
i will implment this now
thanks pitust
wait
why is it rc'd
just a question
also you dont actually have to do mounts at the fs level you can actually do them on top of that in the fs entry lookup cache
thats what linux does
what
and their cache is called a namecache
like if you have an fs mounted somewhere
you have a cache in front of the directory's "lookup file" function so perf doesnt suck
and you can inject fake entries into the cache for when you mount
so even if / is ext2, the cache entry for /tmp points you to a tmpfs vnode
and you make sure you dont ever get rid of that entry
can you explain further with like code or smthin cause im kind of confused here
like what are you trying to say? like a cache? in front of a function what?
im confused lmao
you have fs driver
yep
when the user wants to open a file
it would suck if you have to go to the fs driver every time
so you have a cache for that
the cache needs some entries
you can insert an entry that the FS driver didn't create
basically just an overlay
how wwould the cache look like
idk probably a hashtable?
so like
HashMap<String, Rc<dyn Object>
or am i misunderstanding
possibly
where would this hashmap be storeed if this is correct
but also theres other things
like the cache needs to be a tree
and also you need parent pointers
okay things are getting complicated real fast
Couldn't a naive namecache just be a hashmap from string to vnode
not really because mounts exist
like
honestly i dont think i will implement this, i dont mind the performance loss. im not trying to be linux anyway this is a hobby os lol
its a cache but not a great one
it also gives you a bunch of other nice things like bind mounts
and normal mounts without fs involvement
and .. handling
for free
well i dont know how to implment this like at all
Yeah right
sorry but is that an extern "C" ISR?
If you mount / to something else then all your / nodes are wrong
yea
why is that a problem?
wait
what the actual fuck
yes extern "C" has a prologue
is that
whats wrong
no because of #[naked]
oh
yea
its fine how i do it to be fair
I'd suggest you use extern "x86-interrupt" for x86
i believe it's stable?
at least the RFC is merged it might be nightly-only tho
ok fine
*real osdev
It's better to use assembly for that type of thing, you know exactly the state you're in then
naked functions are assembly it's fine
Every function is getting compiled down to assembly
ok mr duolingo bird
naked functions are written in assembly *
Oh
they don't compile if you put anything but asm!
extern "C" would matter if this was being called by a some other function instead of being an ISR tho i think
because then it would be a C abi function but no prologue so it would be UB, since you're clearly not doing what a C abi function must do
What even is the rust ABI anyway
undefined
for now*
probably forever
there is finally some momentum towards a rust spec tho
it could
can we all just ask what duolingo bird is doing here
it should
why is duolingo here
are you here for my family
i told you ill practice japanese later 
it does guarantee a couple things i think (i can't think of anything other than order of arguments which is last to first
will nyaux use nixstrap™️
i dont know nixstrap
#1279525023127830609
lol
that doesnt use shitty raw ptrs everywhere lol
just let me
get a working """virtual memory manager"""
literally only need it to map pages and nothing special
trait vnode {
fn lookup(&self, child: &str) -> Result<Rc<dyn vnode>>;
fn read(&self, buf: &mut [u8]) -> Result<usize>;
fn write(&self, buf: &[u8]) -> Result<usize>;
fn mkdir(&mut self, name: &str) -> Result<Rc<dyn vnode>>;
fn create(&mut self, name: &str) -> Result<Rc<dyn vnode>>;
}
okay i made these ops
pub struct tmpfsdir {
files: Map<String, Rc<dyn vfs::vnode>>
}
pub struct tmpfsfile<'a> {
data: &'a mut [u8]
}
okay
now to implment the ops
fwiw that doesnt deal with file resizing
and the fact that you might not be able to allocate it all in virtually contignous memory
wha
do i need an op for that
i mean if you are cool with making the most naiive kernel possible then thats cool
yeah keep a list of pages per file
theres also a bunch of stuff around like map private and cow
yeah so on mmap you can map N pages from it
if you need to grow, you just add a page
im rllyy confused sorry, am i supposed to keep a count of pages or a list of page addresses?
what?
you could keep a vector
you only need push and pop
so thats fine
why do i need a list of pages, why cant i just have a pointer to the data directly
what is the purpose of that
because you cant necessarily allocate a lot of contignous memory like that
you prooobably shouldnt use a single level vec either, but an rbtree or something
cant i just
map it contingous
are these pages physical or virtual or what?
there is so much im confused abt
depends on your impl
my allocator maps anything above 4096 contingous using my vmm allocator
because my pmm cannot allocate contingous pages
i might use a hashmap instead of Map
fn mkdir(&mut self, name: &str) -> Result<Rc<dyn vfs::vnode>, UNIXERROR> {
let dir = &mut self.files;
let ifeelsick = Rc::new(tmpfsdir::default());
dir.insert(String::from(name), ifeelsick.clone());
return Ok(ifeelsick);
}
pitust this design is SO much better
this is like
so easy now
pub struct tmpfsfile<'a> {
data: &'a mut [u8]
}
impl<'a> Default for tmpfsfile<'a> {
fn default() -> Self {
Self {
data: ?:
}
}
}
how would i init the data?
maybe you should make it a boxed slice instead? or just a vector
would a vec be better or worse
unless you are planning on keeping eg. the initramfs tar or whatever around, then keeping it as an un-owned slice that is fine
it doesn't need to be a slice if its a vec
alr
can just be a Vec<u8>
alright
as it owns the data (though ofc then that means you are going to be copying the data from the initramfs to there)
but then ig you can discard the original initramfs
yea i could
how would i discard the initramfs
is there a way to get limine to deallocate it
right
do separate modules have different entries in the memory map or are they merged?
undefined
you shouldn't use the memory map for this
you should deallocate in your pmm from module->address, module->size / page_size pages
ah
i would have to loop and do that since my pmm can only deallocate singular pages
so thats fine
i mean that's a you issue™️
yea
i think ill have it be a vec u8 cause maybe i wanna reuse tmpfs for smthin not initramfs
to be fair
yeah its probably the easiest option because if you want to eg. create new files or delete files then you'd have to allocate memory for the slice and also keep around info that the slice is allocated so you know to free it
yea
qwinci question, how would i read a vec<u8> into a &mut [u8]?
do i really gotta use unsafe raw ptrs here
is there no escape
in your file read/write function?
there is copy_from_slice that you can use on the dest slice but then you have to make sure that both of the slices have the same length
what if i need to do with offset
- offset
read and write need offset
you use it to create a slice to the vector
wha
&vec[offset..offset + size] gets you a slice that has the bytes the vec has at [offset, offset + size]
ah okay
if offset + buf.len() > self.data.len() {
}
this is probs a good way to check
=
right
let mut size = offset + buf.len();
if offset + buf.len() >= self.data.len() {
size = self.data.len();
}
qwinci i have the slice
now what do i do
what if the buffer is smaller then the slice
is there a copy_to_slice?
if the buffer is smaller than the slice you got by slicing the vector then the function was passed an invalid size
that should never happen
cause i do buf.len
to get the buffer length
so
thats fine
buut is there a function like thissss or???
you just use copy_from_slice on the dest
oh fair
though when writing to a file then it might also exceed the size of the vector so you might need to resize the vec before you copy
right
yooooo
source slice length (0) does not match destination slice length (256)
right
need to handle that
Rc<RefCell<T>>
i tried
look here ^
what was the code like
you need .borrow_mut()
likely
probably just a function that return a result of stat struct or an error
and stat struct contains things like the type of the file, size, owner etc
usually you can't really get a name out of a vnode because there may be multiple paths that end up in the same vnode
eg. with symlinks or whatever
this is not pro
this means length is 0
did it not write?
what does the write method look like
fn write(&mut self, buf: &[u8], offset: usize) -> Result<usize, UNIXERROR> {
let mut size = offset + buf.len();
if offset + buf.len() >= self.data.len() {
size = self.data.len();
}
if self.data.len() == 0 {
return Err(UNIXERROR::EPERM);
}
self.data.resize(size, 0);
self.data.copy_from_slice(&buf[offset..size]);
// SO EASY
return Ok(size);
}
writing 0 bytes should be fine?
i mean returning EPERM if the data size is 0 is not correct
offset + buf.len() >= self.data.len() ends up being true when self.data has a smaller size than offset + buf.len() tho
i know
how do i check then
fn write(&mut self, buf: &[u8], offset: usize) -> Result<usize, UNIXERROR> {
if offset + buf.len() > self.data.len() {
self.data.resize(offset + buf.len(), 0);
}
self.data[offset..offset + buf.len()].copy_from_slice(buf);
// SO EASY
return Ok(size);
}
``` something like this
being able to test it in userspace sounds cool
i know
really useful
glad i set this uo
up
i see
because I'd have to include the kernel sources in tests and that'd mess up my build system
does #[test] compile like a normal userspace program?
yea
can you use, for example, std in it?
yea
very noice
yep
bru
you forgot the above code tho
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, UNIXERROR> {
let mut size = offset + buf.len();
if offset + buf.len() >= self.data.len() {
size = self.data.len();
}
if self.data.len() == 0 {
return Err(UNIXERROR::EPERM);
}
buf.copy_from_slice(&self.data[offset..size]);
return Ok(size);
}
above code?
you need to slice buffer to the appropriate length too
oh right
yea ur right
I have memory objects ™ (*not ™) in my kernel which take ownership of memory occupied by modules, which can be reclaimed as usual
(In other words, I treat modules as usable but kernel occupied memory)
(so like maybe cache pages ?)
lol
man
this gets worse
:c
size is more like the end offset in that code
ah
but size isn't a correct index to buf
buf[..size] isn't correct as size is the end offset within self.data and not within buf (which starts at offset)
right
so it should be
file.size.len or whatever
or wait
i shouldnt add offset to size to begin with
just assign the src slice you are giving to copy_from_slice to a variable and then use the length of that to slice buf (or make size actually be a size and not an offset within self.data)
okay
IT SUCCEDDED
QWINCI
IT WORKS
AIOW JBKKLCKXLDV:JLGI
YOOOO
LETS FUCKING
GOOOOOO

// this code so pro
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, UNIXERROR> {
let mut size = offset + buf.len();
if buf.len() == 1 {
return Err(UNIXERROR::EINVAL);
}
if offset + buf.len() >= self.data.len() {
size = self.data.len();
}
if self.data.len() == 0 {
return Err(UNIXERROR::EPERM);
}
let pro = &self.data[offset..size];
buf[..pro.len()].copy_from_slice(pro);
return Ok(size);
}
fn write(&mut self, buf: &[u8], offset: usize) -> Result<usize, UNIXERROR> {
let size = offset + buf.len();
if offset + buf.len() > self.data.len() {
self.data.resize(offset + buf.len(), 0);
}
if self.data.len() == 0 {
return Err(UNIXERROR::EPERM);
}
self.data.resize(size, 0);
self.data.copy_from_slice(&buf[offset..size]);
// SO EASY
return Ok(size);
}
😎
okay time to populate the vfs IN a test
good idea?
yes
😎
I CANNOT STOP WRITING TESTS
AAAAA
at least its a good one (as long as you don't write too many of them but doing that would be really hard)
imagine using proper rust naming
bru
well @molten grotto thats not pro gamer

fails
hmmmm
help
i dont understand
why this wont work

okay
okay i fixed it
LETS GO
i wrote the data as well 😎
noooo

NVM
WE HAVE TMPFS BOIS
II KNEW WRITING THOSE TESTS WERE WORTH IT
WE ARE SO PRO'D
can anyone give me an initramfs.tar to test :)
hey @elder shoal you got any initramfs.tar's i can test to verify my system is robust?
:))
probs parsed the tar wrong
no?
pretty sure tar has a symlink type
then you fucked up 
done :)
good
okay chat
i have vfs
what next
:)
Okay we need SMP
and the APIC
okay scary
Ive NEVER done smp before
im scared
but its okay
so we need to start up the other cpus
im unsure of how to do this as ive NEVER done smp before but its okay !
well
rust should've forbidden you from doing anything stupid
so you should be fine thread safety-wise
for now
hopefully
so i just write to the goto address?
that all
actually
lets do the apic first
thats easy
okay so since i have smp in mind
since there can be multiple io apics
how should a driver for the ioapic be implmented?
do we have a freelist of ioapics or smthin?
HUH????
BRO WHAT
okay what is an NMI
i cant stop saying that word everywhere
non maskable interrupt but what does that mean
struct ioapic {
handles: (usize, usize), // base gsi to max gsi
sourceoveride: HashMap<usize, &mut MadtIrqSourceOverride>, // if theres a irq source override for a gsi, it will be in this hashmap
// you can check for it and get the REAL gsi from the value
id: u8, // ioapic id
addr: u32, // addr of ioapic
}
is this a good way?
how would that even work
do lapic initialization per cpu
for multiple ioapics
I personally have a per-CPU list of interrupt handlers (for LAPIC vectors)
asks about io apic, answers give about lapic
And then a list (bst) of mappings of IOAPIC => {CPU, vector}
I haven't finished lol
lol fair - wasnt directly solely at you
And these get assigned to random CPU on the first use
I have source overrides as a global variable
But like this could probably work...
huh/
bst?
wha?
also do yall think this is a good idea
thats not what i meant
i mean
ioapic
Binary Search Tree
what
Sorted HashMap
(it doesn't matter)
(a list with fast lookup, like HashMap could be)
i could have a hashmap in the cpu struct
struct cpu {
gsi_to_vec: Hashmap<usize, usize>
}
but i dont see why i would need to store this
(And flat set for this lol)
oh?
You need legacy ISA => GSI translation
Not the other way around
okay i have that in the ioapic struct
GSI tells you which IOAPIC and pin the interrupts go to
okay i know
Technically legacy interrupts could go to different IOAPICs
i know
And then a list (bst) of mappings of IOAPIC => {CPU, vector}
Maybe store this?
Hashmap<i32, (usize, usize)> // ioapic id -> cpu id, vec
smthin like this?
Possibly
It also kinda depens on how you handle your interrupts
(now that I think of it)
You can also just broadcast them to all CPUs
explain
And let the first free one handle them
Kinda
Instead of assigning it to a single CPU
which approach is better
letting a single cpu handle it or
letting all cpus handle it or what
"It depends"
explain
The first one is kinda potentially easier but also slower
Letting only one CPU handle a given interrupt
You could
that introduces things like data races and whatever
as all cpus are executing the same code
Just use Arc<Mutex> or whatever
yea but what if cpu 0 waits for cpu 1 to release the lock, but the irq interrupt didnt fire 2 times so cpu 0 is unnecessary executing wasted time
I've gone with this because of how my kernel is, but like it really depends
that time could be used executing a thread
That won't really happen I think
The hardware would not issue more interrupts unless you acknowledge the first one
does the ioapic randomly pick a cpu or smthin
Yeah
i see
there is a 'first available' mode
yea thats fine
It tries to valance it or smth
but i dont know how portable that is, if you care about that
It "sends a message through an internal bus"
But also all high performance hardware supports MSIs
So you're only routing legacy stuff through APICs
(or use it if you don't support them, at which point performance probably doesn't matter (?))
Fixed or lowest priority
For fixed you want physical mode
Logical is a bitmap
Also ignore "lapic id is 4 bits"
okay so what should physical be if i want it to send randomly to a cpu core
Read SDM as well
IOAPIC and LAPIC IPIs basically function the same
It explains it somewhere
(have you though about IPIs already?
)
Just set it to all 1s I think
okay @flat nymph either a single destination (local APIC IDs 00H through FEH)
or a broadcast to all APICs (the APIC ID is FFH)
sdm says FFH
11: (All Excluding Self)
what
is it FFH or 11
struct ioapic {
handles: (usize, usize), // base gsi to max gsi this ioapic handles
sourceoveride: HashMap<usize, MadtIrqSourceOverride>, // if theres a irq source override for a gsi, it will be in this hashmap
// you can check for it and get the REAL gsi from the value
id: u8, // ioapic id
addr: u32, // addr of ioapic
}
struct SystemAPIC {
apics: Vec<ioapic>
}
this is how i will implement
found bug
running in kvm causes issue 
rayan@pop-os:~/NyauxKT$ addr2line -e kernel/kernel FFFFFFFF80033F75
/home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/interpreter.c:5600
rayan@pop-os:~/NyauxKT$
NOOOOO
@kind root more memory bug hell :(
static void execution_context_release(struct execution_context *ctx)
{
if (ctx->ret)
uacpi_object_unref(ctx->ret);
while (held_mutexes_array_size(&ctx->held_mutexes) != 0) {
> page fault happened here held_mutexes_array_remove_and_release(
&ctx->held_mutexes,
*held_mutexes_array_last(&ctx->held_mutexes),
FORCE_RELEASE_YES
);
}
call_frame_array_clear(&ctx->call_stack);
held_mutexes_array_clear(&ctx->held_mutexes);
uacpi_free(ctx, sizeof(*ctx));
}
why is it page faulting on this???
because your allocator is bad

works for literally everyone else
why does it work in non kvm but in kvm it dont work
bru
and not tcg
unlucky
what
im confused what you mean by implicit
u cant disable read on x86
that
unless u pop the present bit
oh
but then its unmapped
so to find out if something is non-readable or unmapped you need to keep track of that yourself
CR2=0x0 
either a pte bit or some other data structure, like somewhere in your memory manager
unmap the page and emulate writes on page fault 
yeah that is cancer
this is cancer
or you can map it and use the debug registers to single step
or even better, enable the single step flag and let it write
yeaaah
yeye
but the user might modify the code so its racey
but emulating the instruction in kernel mode is kinda cancer too
unless u have RxW or something
fwiw it could be an avx512 instruction, so unless you want to kill the user process because it uses fancy instructions your kernel doesnt know how to disassemble your best bet is to execute that instruction with single step flag on
backtrace
can u even attach gdb with kvm
what even is a nullptr here
i have no idea
yeah, why not?
the best idea is to just not allow executable code to be writable if u want to protect from that
you gotta use hardware breakpoints tho
what
true
hardware breakpoints
what are those
🤯
(gdb) hb *0xFFFFFFFF80033F75
No hardware breakpoint support in the target.
(gdb)
WHAT
wdym no hardware breakpoint support
huh???
oh forgot to set target
okay
#0 execution_context_release (ctx=0xffff80019058b000)
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/interpreter.c:5600
#1 0xffffffff8003429b in uacpi_execute_control_method (scope=0xffffffff8005ee00 <predefined_namespaces>,
method=0xffff80007eaac9e8, args=0x0, out_obj=0x0)
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/interpreter.c:5696
#2 0xffffffff8002bad2 in do_load_table (parent=0xffffffff8005ee00 <predefined_namespaces>, tbl=0xffff80007fb7a000,
cause=UACPI_TABLE_LOAD_CAUSE_INIT)
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/interpreter.c:1265
#3 0xffffffff8002c2f6 in uacpi_execute_table (tbl=0xffff80007fb7a000, cause=UACPI_TABLE_LOAD_CAUSE_INIT)
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/interpreter.c:1505
#4 0xffffffff80023833 in uacpi_table_load_with_cause (idx=0, cause=UACPI_TABLE_LOAD_CAUSE_INIT)
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/tables.c:672
#5 0xffffffff80026d8a in uacpi_namespace_load ()
at /home/rayan/.cargo/git/checkouts/uacpi-rs-659c6afd660c3588/bdfded0/uacpi-sys/vendor/source/uacpi.c:438
#6 0xffffffff80022076 in uacpi::namespace_load () at src/lib.rs:38
#7 0xffffffff80007f59 in NyauxKT::acpi::ACPIMANAGER::new () at src/acpi/mod.rs:264
#8 0xffffffff800005ff in NyauxKT::kmain () at src/main.rs:79
okayyy
ctx looks valid
why cant i take screenshots HUH??
damn pop os 24.04
buggy
ah
brb will reboot
this is an array with inline storage
its size is 0
it doesnt matter what contents there are
Idk I just do ioapic initialization once I think and it works fine for multicore
Unless it doesn't
do the parameters look valid at least?
no idea
yes
okay so wtf
thats what im trying to do
i am
yes
what more do you need?
yeah just find the pointer its trying to deref
figure out why its doing that
and where it comes from
gdb) p &ctx->held_mutexes
$2 = (struct held_mutexes_array *) 0xffff80019058cce0
(gdb)
thats valid
brother
does it pf when freeing that?
im unsure
u literally have cr2
cr2 is 0
cr2 is 0
i am looking at the code
the highlighted one?
held_mutexs_array_remove_and_release
okay
probably the held_mutexes_array_last deref?
what does that have inside show us
inb4 a good ol return NULL
bruh
lmao
clean
yeah u corrupted the context hard

do u have memset 0xAF anywhere?
no?
well u definitely wrote that in there somehow lol

put a hw breakpoint like iretq suggested and see who writes it in there
rayan@pop-os:~/NyauxKT$ objdump -d --demangle kernel/kernel | grep ffffffff80033f75 -A 10
ffffffff80033f75: 48 8b 00 mov (%rax),%rax
ffffffff80033f78: 48 8b 55 f8 mov -0x8(%rbp),%rdx
ffffffff80033f7c: 48 8d 8a e0 1c 00 00 lea 0x1ce0(%rdx),%rcx
ffffffff80033f83: ba 01 00 00 00 mov $0x1,%edx
ffffffff80033f88: 48 89 c6 mov %rax,%rsi
ffffffff80033f8b: 48 89 cf mov %rcx,%rdi
ffffffff80033f8e: e8 7b 55 ff ff call ffffffff8002950e <held_mutexes_array_remove_and_release>
ffffffff80033f93: 48 8b 45 f8 mov -0x8(%rbp),%rax
ffffffff80033f97: 48 05 e0 1c 00 00 add $0x1ce0,%rax
ffffffff80033f9d: 48 89 c7 mov %rax,%rdi
ffffffff80033fa0: e8 b3 52 ff ff call ffffffff80029258 <held_mutexes_array_size>
thats the disassembly if u care
okay
the command for watching memory is watch right?
-B 10
okay sec
i dont care whats after the crash lol
the disassembly doesnt matter
yeah
its trying to do while array not empty: pop
now that we know
rayan@pop-os:~/NyauxKT$ objdump -d --demangle kernel/kernel | grep ffffffff80033f75 -B 10
ffffffff80033f50: 74 41 je ffffffff80033f93 <execution_context_release+0x5d>
ffffffff80033f52: 48 8b 45 f8 mov -0x8(%rbp),%rax
ffffffff80033f56: 48 8b 00 mov (%rax),%rax
ffffffff80033f59: 48 89 c7 mov %rax,%rdi
ffffffff80033f5c: e8 c3 13 ff ff call ffffffff80025324 <uacpi_object_unref>
ffffffff80033f61: eb 30 jmp ffffffff80033f93 <execution_context_release+0x5d>
ffffffff80033f63: 48 8b 45 f8 mov -0x8(%rbp),%rax
ffffffff80033f67: 48 05 e0 1c 00 00 add $0x1ce0,%rax
ffffffff80033f6d: 48 89 c7 mov %rax,%rdi
ffffffff80033f70: e8 fd 52 ff ff call ffffffff80029272 <held_mutexes_array_last>
ffffffff80033f75: 48 8b 00 mov (%rax),%rax
you trashed the memory
your array has size 0xAFAFAFAF
the issue is obvious
?
okay yea it is
(gdb) continue
Continuing.
Warning:
Could not insert hardware watchpoint 2.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
Command aborted.
(gdb)
bro
it wont let me watch the address wtf
bro
gdb moment truly
does anyone know?
This is a shorthand for IPIs
You need logical destination, lowest priority
And FFh
Are you using KVM?
Also are you using OS-specific toolchain? 
(I've had bad luck with Debian's binutils and QEMU)
(like compile QEMU from scratch and patch binutils and llvm for your OS)
(or just LLVM, though I haven't played with lld and stuff)
ywes
help 
with what
gdb wont let me watch the address
did you disable kvm
the bug only happens with kvm on
something is memsetting uacpis shit with 0xfa
only happens in kvm for some reason
i do not understand why

Uninitialized memory? (Although very unlikely)
no i memset everything?
Idk
Add tests for heap allocator
@kind root nyauxmaster try not to have memory bug in nyaux challenge for 1251255th time 
With mmap
i dont know how to use my allocator instead of the default one
Huh
wait
Yup
Look for what sets the memory to AF
i cant
Maybe its some rust thing
gdb wont let me watch the address on kvm
Idk
what does it say
kvm+gdb are quite annoying at times
too many hardware breakpoints
just wont let me
even tho i have one breakpoint
have you tried removing all breakpoints
yep
kvm sure do be weird huh
true
not rlly
Sounds like a very specific pattern
i found nothing in the rust docs abt it anyway or on google
has to be a me issue

no more refactoring?
it didnt help
ive checked
its not alignment
something is mesetting the fucking address and its driving me mad
rewrite 3 in pure assembly when
lmao
do you have up to date version in git
yep
all pushed
go look at it
please

You should've used C++
^
it only happens under kvm btw
kvm
for some oddball reason
which makes it harder to debug
cause no watch 
now the kernel is broken everywhere tho
Check tlb flushing
C++ is better suited for osdev than rust
wha
its a null deref
wait one second
Although you don't unmap anything
Ok it can't be it
just wait a second
Also doesn't Rust have like a million crates with memory allocator?
okay
for an example the new size can be smaller than old size and you are copying the old size amount of bytes to a smaller region
but yeah you don't need to implement it yourself at all
the issue is that you aren't zeroing the pages properly
where
diff --git a/kernel/src/mem/virt/mod.rs b/kernel/src/mem/virt/mod.rs
index 756737d..251a175 100644
--- a/kernel/src/mem/virt/mod.rs
+++ b/kernel/src/mem/virt/mod.rs
@@ -279,7 +279,7 @@ impl PageMap {
for i in 0..amou {
let mut e = PMM.alloc().unwrap();
e = (e as u64 + HDDM_OFFSET.get_response().unwrap().offset()) as *mut u8;
- e.write_bytes(0, 4096 / 8);
+ e.write_bytes(0, 4096);
e = (e as u64 - HDDM_OFFSET.get_response().unwrap().offset()) as *mut u8;
self.map((*new_guy).base + (i * 0x1000) as u64, e as u64, flags)
.unwrap();
.write_bytes does count * sizeof::<T>
it works just fine for me unless you also changed it somewhere else where you shouldn't have
okay try my version ill push it
pushed
you changed it in the wrong place
where
in that place area is a *mut u64 so diving it by 8 was correct
i still do that
??
wait no
i dont
okay works under tcg
moment of truth
STILL
IT DOESNT WORK UNDER KVM 
did you revert this
yes
and applied this to kernel/src/mem/virt/mod.rs
NOW I DIID
IT WORKS
QWINICI OH MY FUCKING GOD
UR MY SAVIOR LITERARLY
LETS GOOOOO
AND THE RAMUSAGE WENT DOWN
12mb now
(on kvm)
tcg is still 30mb
but whatever
IM GONNA TRY THIS ON REAL HARDWARE !!!!
black screen
😔
@orchid dawn could you test nyaux on your real hardware please
hang on
alr
@orchid dawn results?
Inb4 triple faulted on everything
yeah that be unfortunate 
While you're at it, test obos 
Test master tho
Not the other branches
ii have serial driver now
time for smp
