3 ms·
> These are generally memory errors, and are certainly undefined behavior, so yes. USB registers might be in DMA buffers or another memory location that might
by _pmf_ 6y ago
> These are generally memory errors, and are certainly undefined behavior, so yes.
USB registers might be in DMA buffers or another memory location that might get mapped/unmapped at any point. Not everything fits a simplistic linear memory model.
- asveikau 6y agoThis is an interesting point. Rust's borrow checker or bounds checks probably also can't know about a page table change happening underneath it. Anyone want to correct me on that?
- monocasa 6y agoIt's pretty easy to wrap those constructs in RAII wrappers to replace or augment the normal reference counting that C code would be using to keep those buffers mapped, along with associating the lifetime of the relevant buffers with that refcnt. So it won't be perfect, but you can add safety versus what you get in C. You can even add safety versus what you'd get in C++ because of the lifetimes you can associate.
- asveikau 6y agoI know it's possible to reference count a page table mapping, in any language. My question is has anybody really attempted it in a rust kernel to make the sort of automatic safety measures we know rust for mean anything at all. It seems like if you really want correctness, every allocation must bump such a recount, which is very expensive.
- gpm 6y agoSo the general trick with reference counted pointers in rust, is that you don't have to touch the allocation count when creating a new pointer as long as you already have a pointer that you know lives for longer than your new pointer, and the rust type system will check that you didn't make a mistake when you thought you did. I.e. say I have a `x: Rc<[u8]>`, that is a ref counted pointer to some memory, and a length of that memory. I can do `let y: &[u8] = &x;`. `y` is now a not-ref counted pointer to the same memory (with the same length), that's guaranteed to be dropped before `x` is so the memory won't be freed from under it. I can also do `let z: &u8 = &x[5]`. `z` is now a pointer to a byte in `x`. Like `y` it's not ref counted and the compiler will force us to drop it before we drop `x`. You can make a whole allocator in this fashion (people have, even in the standard library I believe). If you get really clever you can probably even make an allocator in this fashion where the allocator doesn't use any unsafe code, you can easily make one where the users of the allocator don't need any unsafe code.
- gpm 6y agoThere's no fundamental reason why you couldn't write an abstraction around the page table that the rust borrow checker understands. The rust borrow checker works on the principle of ensuring that if you have a unique pointer (&mut) to something, nothing else can access it. If you have a shared pointer (&) to something, nothing else is mutating it except where internal mutability is explicitly marked (UnsafeCell, and abstractions using UnsafeCell such as Cell, RefCell, Mutex, RwLock, and so on). To mutate a page table entry you would need an &mut reference to it, to access a page you would need an & reference to the page table entry (from the &PageTableEntry you would get a &[u8] pointing to the data which the borrow checker would guarantee you drop before you drop the &PageTableEntry before anything mutates the PageTableEntry).
- steveklabnik 6y agoThis isn't exactly what you're asking about, but I really really love https://os.phil-opp.com/paging-implementation/ https://os.phil-opp.com/paging-implementation/ Shows you how you might implement paging, and how much unsafe you need to do so.