OS1: x86 рдХреЗ рд▓рд┐рдП рдЬрдВрдЧ рдкрд░ рдПрдХ рдЖрджрд┐рдо рдХрд░реНрдиреЗрд▓ред рднрд╛рдЧ 3. рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб, рдкреГрд╖реНрда рджреЛрд╖ рдЕрдкрд╡рд╛рдж, рдвреЗрд░ рдФрд░ рдЖрд╡рдВрдЯрди

рдкрд╣рд▓рд╛ рднрд╛рдЧ
рджреВрд╕рд░рд╛ рднрд╛рдЧ


рдЖрдЬ рдХреА рдмрд╛рддрдЪреАрдд рдХрд╛ рд╡рд┐рд╖рдп рд╕реНрдореГрддрд┐ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реИред рдореИрдВ рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ, рдлрд┐рдЬрд┐рдХрд▓ рдореЗрдореЛрд░реА рдореИрдк рдХрд░рдиреЗ, рд╡рд░реНрдЪреБрдЕрд▓ рдореИрдиреЗрдЬ рдХрд░рдиреЗ рдФрд░ рдПрд▓реЛрдХреЗрдЯрд░ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдСрд░реНрдЧрдирд╛рдЗрдЬреЗрд╢рди рд╣реАрдк рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдХрд╣рд╛ рдерд╛, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдЬреАрд╡рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП 4 рдПрдордмреА рдкреГрд╖реНрдареЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдФрд░ рдкрджрд╛рдиреБрдХреНрд░рдорд┐рдд рддрд╛рд▓рд┐рдХрд╛рдУрдВ рд╕реЗ рдирд╣реАрдВ рдирд┐рдкрдЯрдирд╛ рдЪрд╛рд╣рд┐рдПред рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдореБрдЭреЗ рд╕рдмрд╕реЗ рдЖрдзреБрдирд┐рдХ рд╕рд┐рд╕реНрдЯрдо рдХреА рддрд░рд╣, 4 рдХреЗрдмреА рдкреЗрдЬ рдкрд░ рдЬрд╛рдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИред рдореИрдВ рдПрдХ рддреИрдпрд╛рд░ рдПрдХ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдмреНрд▓реЙрдХ рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореЗрд░рд╛ рдЦреБрдж рдХрд╛ рд▓рд┐рдЦрдирд╛ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдерд╛ рдФрд░ рдореИрдВ рдереЛрдбрд╝рд╛ рдФрд░ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рд╕реНрдореГрддрд┐ рдХреИрд╕реЗ рд░рд╣рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдЖрдкрдХреЛ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╣реИред


рдкрд┐рдЫрд▓реА рдмрд╛рд░ рдЬрдм рдореИрдВ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдкрд░ рдирд┐рд░реНрднрд░ setup_pd рд╡рд┐рдзрд┐ рдкрд░ рдмрд╕ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдЬрд╛рд░реА рд░рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдПрдХ рдФрд░ рд╡рд┐рд╡рд░рдг рдерд╛ рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдХрд╡рд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдерд╛ - рд╡реАрдЬреАрдП рдЖрдЙрдЯрдкреБрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрдВрдЧ рдФрд░ рдорд╛рдирдХ рдкреНрд░рд┐рдВрдЯрд▓ рдореИрдХреНрд░реЛред рдЪреВрдВрдХрд┐ рдЗрд╕рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рддреБрдЪреНрдЫ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдмрд┐рдЧрд╛рдбрд╝рдиреЗ рдХреЗ рддрд╣рдд рд╣рдЯрд╛ рджреВрдВрдЧрд╛ред рдХреЛрдб рдбреАрдмрдЧ рдкреИрдХреЗрдЬ рдореЗрдВ рд╣реИред


рдореИрдХреНрд░реЛ рдкреНрд░рд┐рдВрдЯрд▓
#[macro_export] macro_rules! print { ($($arg:tt)*) => ($crate::debug::_print(format_args!($($arg)*))); } #[macro_export] macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ($crate::print!("{}\n", format_args!($($arg)*))); } #[cfg(target_arch = "x86")] pub fn _print(args: core::fmt::Arguments) { use core::fmt::Write; use super::arch::vga; vga::VGA_WRITER.lock().write_fmt(args).unwrap(); } #[cfg(target_arch = "x86_64")] pub fn _print(args: core::fmt::Arguments) { use core::fmt::Write; use super::arch::vga; // vga::VGA_WRITER.lock().write_fmt(args).unwrap(); } 

рдЕрдм, рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рд╡реЗрдХ рдХреЗ рд╕рд╛рде, рдореИрдВ рд╕реНрдореГрддрд┐ рдореЗрдВ рд▓реМрдЯрддрд╛ рд╣реВрдВред


рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди


рд╣рдорд╛рд░реА kmain рдкрджреНрдзрддрд┐ рдиреЗ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рддреАрди рддрд░реНрдХ рджрд┐рдП, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдПрдХ рдкреГрд╖реНрда рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдЖрднрд╛рд╕реА рдкрддрд╛ рд╣реИред рдЖрд╡рдВрдЯрди рдФрд░ рдореЗрдореЛрд░реА рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдмрд╛рдж рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд░рд┐рдХреЙрд░реНрдб рдФрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред X86 рдХреЗ рд▓рд┐рдП, рдкреЗрдЬ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдФрд░ рдкреЗрдЬ рдЯреЗрдмрд▓ рдХрд╛рдлреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЦреБрдж рдХреЛ рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдкрд░рд┐рдЪрдп рддрдХ рд╕реАрдорд┐рдд рдХрд░реВрдВрдЧрд╛ред рдкреГрд╖реНрда рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдПрдХ рд╕реВрдЪрдХ рдЖрдХрд╛рд░ рд╕рдВрд░рдЪрдирд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдпрд╣ 4 рдмрд╛рдЗрдЯреНрд╕ рд╣реИред рдорд╛рди рдореЗрдВ рдкреГрд╖реНрда рдХрд╛ 4KB рднреМрддрд┐рдХ рдкрддрд╛ рд╣реЛрддрд╛ рд╣реИред рд░рд┐рдХреЙрд░реНрдб рдХрд╛ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдЗрдЯ рдЭрдВрдбреЗ рдХреЗ рд▓рд┐рдП рдЖрд░рдХреНрд╖рд┐рдд рд╣реИред рдПрдХ рдЖрднрд╛рд╕реА рдкрддреЗ рдХреЛ рднреМрддрд┐рдХ рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рддрдВрддреНрд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ (рдореЗрд░реА 4 рдПрдордмреА рдЧреНрд░реИрдиреНрдпреБрд▓реИрд░рд┐рдЯреА рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╢рд┐рдлреНрдЯ 22 рдмрд┐рдЯреНрд╕ рд╕реЗ рд╣реЛрддреА рд╣реИред рдЕрдиреНрдп рдЧреНрд░реИрдиреНрдпреБрд▓реИрд░рд┐рдЯреА рдХреЗ рд▓рд┐рдП, рд╢рд┐рдлреНрдЯ рдЕрд▓рдЧ рд╣реЛрдЧреА рдФрд░ рдкрджрд╛рдиреБрдХреНрд░рдорд┐рдд рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛!)ред


рдЖрднрд╛рд╕реА рдкрддрд╛ 0xC010A110 -> 22 рдмрд┐рдЯ рдкрддреЗ рдХреЛ рджрд╛рдИрдВ рдУрд░ рд▓реЗ рдЬрд╛рдХрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ -> рд╕реВрдЪрдХрд╛рдВрдХ 0x300 -> рд╕реВрдЪрдХрд╛рдВрдХ 0x300 рджреНрд╡рд╛рд░рд╛ рдкреГрд╖реНрда рдХрд╛ рднреМрддрд┐рдХ рдкрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ, рдЭрдВрдбреЗ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВ -> 0x1000000 -> рдиреАрдЪреЗ рджрд┐рдП рдЧрдП 22 22 рдмрд┐рдЯреНрд╕ рд╡рд░реНрдЪреБрдЕрд▓ рдкрддреЗ рдХреЛ рдСрдлрд╕реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ, рдЬреЛрдбрд╝реЗрдВ рдкреГрд╖реНрда рдХрд╛ рднреМрддрд┐рдХ рдкрддрд╛ -> 0x1000000 + 0x10A110 = рд╕реНрдореГрддрд┐ рдореЗрдВ рднреМрддрд┐рдХ рдкрддрд╛ 0x110A110

рдПрдХреНрд╕реЗрд╕ рдХреЛ рддреЗрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд░реЛрд╕реЗрд╕рд░ TLB - рдЯреНрд░рд╛рдВрд╕рд▓реЗрд╢рди рд▓реБрдХрд╕рд╛рдЗрдб рдмрдлрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдкреЗрдЬ рдПрдбреНрд░реЗрд╕ рдХреЛ рдХреИрд╢ рдХрд░рддрд╛ рд╣реИред


рддреЛ, рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореЗрд░реА рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдФрд░ рдЗрд╕рдХреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдмрд╣реБрдд рд╣реА setup_pd рд╡рд┐рдзрд┐ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред рдкреЗрдЬ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, "рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░" рд╡рд┐рдзрд┐ рд▓рд╛рдЧреВ рдХреА рдЧрдИ рд╣реИ, рдЬреЛ 4 рдХреЗрдмреА рджреНрд╡рд╛рд░рд╛ рд╕рдВрд░реЗрдЦрдг рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ рдФрд░ рдЭрдВрдбреЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкреГрд╖реНрда рдХрд╛ рднреМрддрд┐рдХ рдкрддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рд╣реИред рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ 1024 рдЪрд╛рд░-рдмрд╛рдЗрдЯ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИред рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рд╡рд░реНрдЪреБрдЕрд▓ рдкреЗрдЬ рдХреЛ set_by_addr рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдкреЗрдЬ рд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреА рд╣реИред


 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct PDirectoryEntry(u32); impl PDirectoryEntry { pub fn by_phys_address(address: usize, flags: PDEntryFlags) -> Self { PDirectoryEntry((address as u32) & ADDRESS_MASK | flags.bits()) } pub fn flags(&self) -> PDEntryFlags { PDEntryFlags::from_bits_truncate(self.0) } pub fn phys_address(&self) -> u32 { self.0 & ADDRESS_MASK } pub fn dbg(&self) -> u32 { self.0 } } pub struct PDirectory { entries: [PDirectoryEntry; 1024] } impl PDirectory { pub fn at(&self, idx: usize) -> PDirectoryEntry { self.entries[idx] } pub fn set_by_addr(&mut self, logical_addr: usize, entry: PDirectoryEntry) { self.set(PDirectory::to_idx(logical_addr), entry); } pub fn set(&mut self, idx: usize, entry: PDirectoryEntry) { self.entries[idx] = entry; unsafe { invalidate_page(idx); } } pub fn to_logical_addr(idx: usize) -> usize { (idx << 22) } pub fn to_idx(logical_addr: usize) -> usize { (logical_addr >> 22) } } use lazy_static::lazy_static; use spin::Mutex; lazy_static! { static ref PAGE_DIRECTORY: Mutex<&'static mut PDirectory> = Mutex::new( unsafe { &mut *(0xC0000000 as *mut PDirectory) } ); } pub unsafe fn setup_pd(pd: usize) { let mut data = PAGE_DIRECTORY.lock(); *data = &mut *(pd as *mut PDirectory); } 

рдореИрдВрдиреЗ рдмрд╣реБрдд рд╣реА рдЕрдЬреАрдм рддрд░реАрдХреЗ рд╕реЗ рд╢реБрд░реБрдЖрддреА рд╕реНрдереИрддрд┐рдХ рдЖрд░рдВрднреАрдХрд░рдг рдХреЛ рдПрдХ рдЕрд▓рд╣рджрд╛ рд╕рдВрдмреЛрдзрди рдмрдирд╛рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЖрднрд╛рд░реА рд░рд╣реВрдВрдЧрд╛ рдпрджрд┐ рдЖрдк рдореБрдЭреЗ рд▓рд┐рдЦреЗрдВрдЧреЗ рдХрд┐ рд▓рд┐рдВрдХ рдкреБрди: рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдХреЗ рд╕рд╛рде рдЗрд╕ рддрд░рд╣ рдХреЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╕реНрдЯ рд╕рдореБрджрд╛рдп рдореЗрдВ рдпрд╣ рдХреИрд╕реЗ рдкреНрд░рдерд╛рдЧрдд рд╣реИред


рдЕрдм рдЬрдм рд╣рдо рдЙрдЪреНрдЪ-рд╕реНрддрд░реАрдп рдХреЛрдб рд╕реЗ рдкреГрд╖реНрдареЛрдВ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдореЗрдореЛрд░реА рд╕рдВрдХрд▓рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рджреЛ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╣реЛрдЧрд╛: рднреМрддрд┐рдХ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рдЖрднрд╛рд╕реА рдкреНрд░рдмрдВрдзрдХ рдХреЛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ


  match mb_magic { 0x2BADB002 => { println!("multibooted v1, yeah, reading mb info"); boot::init_with_mb1(mb_pointer); }, . . . . . . } memory::init(); 

GRUB рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдФрд░ OS1 рднреМрддрд┐рдХ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб


GRUB рд╕реЗ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмреВрдЯ рд╕реНрдЯреЗрдЬ рдкрд░ рдореИрдВрдиреЗ рд╣реЗрдбрд░ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдзреНрд╡рдЬ рдХреЛ рд╕реЗрдЯ рдХрд┐рдпрд╛, рдФрд░ GRUB рдиреЗ рдореБрдЭреЗ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рднреМрддрд┐рдХ рдкрддрд╛ рджрд┐рдпрд╛ред рдореИрдВрдиреЗ рдЗрд╕реЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕реЗ рд░рд╕реНрдЯ рдЕрдВрдХрди рдореЗрдВ рдкреЛрд░реНрдЯ рдХрд┐рдпрд╛, рдФрд░ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдкрд░ рдЖрд░рд╛рдо рд╕реЗ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рднреА рдЬреЛрдбрд╝рд╛ред рдЕрдзрд┐рдХрд╛рдВрд╢ GRUB рд╕рдВрд░рдЪрдирд╛ рдирд╣реАрдВ рднрд░реА рдЬрд╛рдПрдЧреА, рдФрд░ рдЗрд╕ рд╕реНрддрд░ рдкрд░ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╣реИред рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдЙрдкрд▓рдмреНрдз рдореЗрдореЛрд░реА рдХреА рдорд╛рддреНрд░рд╛ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред


рдорд▓реНрдЯреАрдмреВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХрд░рддреЗ рд╕рдордп, рд╣рдо рдкрд╣рд▓реЗ рднреМрддрд┐рдХ рдкрддреЗ рдХреЛ рдЖрднрд╛рд╕реА рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВред рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, GRUB рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдХрд╣реАрдВ рднреА рд░рдЦ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдкрддрд╛ рдкреГрд╖реНрда рд╕реЗ рдЖрдЧреЗ рдирд┐рдХрд▓рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдкреГрд╖реНрда рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдПрдХ рдЖрднрд╛рд╕реА рдкреГрд╖реНрда рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рд╕рдВрд░рдЪрдирд╛ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдкрд╣рд▓реА рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдХреЗ рдмрдЧрд▓ рдореЗрдВ рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рдмреВрдЯ рдЪрд░рдг рдореЗрдВ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рд╣реИред рдмрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рдзреНрд╡рдЬ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдореМрдЬреВрдж рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝реЗрдВред


 pub mod multiboot2; pub mod multiboot; use super::arch; unsafe fn process_pointer(mb_pointer: usize) -> usize { //if in first 4 MB - map to kernel address space if mb_pointer < 0x400000 { arch::KERNEL_BASE | mb_pointer } else { arch::paging::allocate_page(mb_pointer, arch::MB_INFO_BASE, arch::paging::PDEntryFlags::PRESENT | arch::paging::PDEntryFlags::WRITABLE | arch::paging::PDEntryFlags::HUGE_PAGE ); arch::MB_INFO_BASE | mb_pointer } } pub fn init_with_mb1(mb_pointer: usize) { let ln_pointer = unsafe { process_pointer(mb_pointer) }; println!("mb pointer 0x{:X}", ln_pointer); let mb_info = multiboot::from_ptr(ln_pointer); println!("mb flags: {:?}", mb_info.flags().unwrap()); if mb_info.flags().unwrap().contains(multiboot::MBInfoFlags::MEM_MAP) { multiboot::parse_mmap(mb_info); println!("Multiboot memory map parsed, physical memory map has been built"); } else { panic!("MB mmap is not presented"); } } 

рдПрдХ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдПрдХ рд▓рд┐рдВрдХ рдХреА рдЧрдИ рд╕реВрдЪреА рд╣реИ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рднреМрддрд┐рдХ рдкрддрд╛ рдореВрд▓ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ (рд╡рд░реНрдЪреБрдЕрд▓ рдЪреАрдЬрд╝реЛрдВ рдореЗрдВ рд╕рдм рдХреБрдЫ рдЕрдиреБрд╡рд╛рдж рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ) рдФрд░ рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рд╕рд░рдгреА рдХрд╛ рдЖрдХрд╛рд░ред рдЖрдкрдХреЛ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рдЖрдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕реВрдЪреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдЙрдирдХреЗ рдЖрдХрд╛рд░ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдХреИрд╕рд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИ:


 impl MultibootInfo { . . . . . . pub unsafe fn get_mmap(&self, index: usize) -> Option<*const MemMapEntry> { use crate::arch::get_mb_pointer_base; let base: usize = get_mb_pointer_base(self.mmap_addr as usize); let mut iter: *const MemMapEntry = (base as u32 + self.mmap_addr) as *const MemMapEntry; for _i in 0..index { iter = ((iter as usize) + ((*iter).size as usize) + 4) as *const MemMapEntry; if ((iter as usize) - base) >= (self.mmap_addr + self.mmap_lenght) as usize { return None } else {} } Some(iter) } } 

рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╕рдордп, рд╣рдо GRUB рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдмрд┐рдЯрдореИрдк рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ OS1 рднреМрддрд┐рдХ рдореЗрдореЛрд░реА рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдореИрдВрдиреЗ рдирд┐рдпрдВрддреНрд░рдг рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдореВрд▓реНрдпреЛрдВ рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рд╕рдореВрд╣ рдореЗрдВ рдЦреБрдж рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ - рдореБрдХреНрдд, рд╡реНрдпрд╕реНрдд, рдЖрд░рдХреНрд╖рд┐рдд, рдЕрдиреБрдкрд▓рдмреНрдз, рд╣рд╛рд▓рд╛рдВрдХрд┐ GRUB рдФрд░ BIOS рдЕрдзрд┐рдХ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдорд╛рдирдЪрд┐рддреНрд░ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рд░рд╛рдЬреНрдп рдХреЛ GRUB / BIOS рдорд╛рдиреЛрдВ рд╕реЗ OS1 рдХреЗ рдорд╛рдиреЛрдВ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


 pub fn parse_mmap(mbi: &MultibootInfo) { unsafe { let mut mmap_opt = mbi.get_mmap(0); let mut i: usize = 1; loop { let mmap = mmap_opt.unwrap(); crate::memory::physical::map((*mmap).addr as usize, (*mmap).len as usize, translate_multiboot_mem_to_os1(&(*mmap).mtype)); mmap_opt = mbi.get_mmap(i); match mmap_opt { None => break, _ => i += 1, } } } } pub fn translate_multiboot_mem_to_os1(mtype: &u32) -> usize { use crate::memory::physical::{RESERVED, UNUSABLE, USABLE}; match mtype { &MULTIBOOT_MEMORY_AVAILABLE => USABLE, &MULTIBOOT_MEMORY_RESERVED => UNUSABLE, &MULTIBOOT_MEMORY_ACPI_RECLAIMABLE => RESERVED, &MULTIBOOT_MEMORY_NVS => UNUSABLE, &MULTIBOOT_MEMORY_BADRAM => UNUSABLE, _ => UNUSABLE } } 

рднреМрддрд┐рдХ рдореЗрдореЛрд░реА рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ :: рднреМрддрд┐рдХ рдореЙрдбреНрдпреВрд▓, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдКрдкрд░ рджрд┐рдП рдЧрдП рдорд╛рдирдЪрд┐рддреНрд░ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рдХреНрд╖реЗрддреНрд░ рдХреЗ рдкрддреЗ, рдЗрд╕рдХреА рд▓рдВрдмрд╛рдИ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рд╕рднреА 4 рдЬреАрдмреА рдореЗрдореЛрд░реА рд╕рдВрднрд╛рд╡рд┐рдд рд░реВрдк рд╕реЗ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ рдФрд░ рдЪрд╛рд░ рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рдкреЗрдЬ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реИ, рдПрдХ рдмрд┐рдЯрдореИрдк рдореЗрдВ рджреЛ рдмрд┐рдЯреНрд╕ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ 1024 рдкреЗрдЬреЛрдВ рдХреЗ рд▓рд┐рдП 4 рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдпрд╣ рдирд┐рд░реНрдорд╛рдг 256 рдмрд╛рдЗрдЯреНрд╕ рд▓реЗрддрд╛ рд╣реИред рдПрдХ рдмрд┐рдЯрдореИрдк рднрдпрд╛рдирдХ рд╕реНрдореГрддрд┐ рд╡рд┐рдЦрдВрдбрди рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдордЭрдиреЗ рдФрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ, рдЬреЛ рдореЗрд░реЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рдмрд╛рдд рд╣реИред


рдореИрдВ рдмрд┐рдЧрд╛рдбрд╝рдиреЗ рдХреЗ рддрд╣рдд рдмрд┐рдЯрдореИрдк рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╣рдЯрд╛ рджреВрдВрдЧрд╛ рддрд╛рдХрд┐ рд▓реЗрдЦ рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рди рдХрд┐рдпрд╛ рдЬрд╛рдПред рд╕рдВрд░рдЪрдирд╛ рдХрдХреНрд╖рд╛рдУрдВ рдФрд░ рдореБрдлреНрдд рдореЗрдореЛрд░реА рдХреА рд╕рдВрдЦреНрдпрд╛, рд╕реВрдЪрдХрд╛рдВрдХ рдФрд░ рдкрддреЗ рд╕реЗ рдкреГрд╖реНрдареЛрдВ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдиреЗ рдФрд░ рдореБрдлреНрдд рдкреГрд╖реНрдареЛрдВ рдХреА рдЦреЛрдЬ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ (рдпрд╣ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдвреЗрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА)ред рдХрд╛рд░реНрдб рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ 64 u32 рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рд╣реИ, рдЖрд╡рд╢реНрдпрдХ рджреЛ рдмрд┐рдЯреНрд╕ (рдмреНрд▓реЙрдХ) рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рддрдерд╛рдХрдерд┐рдд рдЪрдВрдХ (рд╕рд░рдгреА рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ, 16 рдмреНрд▓реЙрдХ рдХреА рдкреИрдХрд┐рдВрдЧ) рдФрд░ рдмреНрд▓реЙрдХ (рдЪрдВрдХ рдореЗрдВ рдмрд┐рдЯ рд╕реНрдерд┐рддрд┐) рдореЗрдВ рд░реВрдкрд╛рдВрддрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рднреМрддрд┐рдХ рдореЗрдореЛрд░реА рдмрд┐рдЯрдореИрдк
 pub const USABLE: usize = 0; pub const USED: usize = 1; pub const RESERVED: usize = 2; pub const UNUSABLE: usize = 3; pub const DEAD: usize = 0xDEAD; struct PhysMemoryInfo { pub total: usize, used: usize, reserved: usize, chunks: [u32; 64], } impl PhysMemoryInfo { // returns (chunk, page) pub fn find_free(&self) -> (usize, usize) { for chunk in 0..64 { for page in 0.. 16 { if ((self.chunks[chunk] >> page * 2) & 3) ^ 3 == 3 { return (chunk, page) } else {} } } (DEAD, 0) } // marks page to given flag and returns its address pub fn mark(&mut self, chunk: usize, block: usize, flag: usize) -> usize { self.chunks[chunk] = self.chunks[chunk] ^ (3 << (block * 2)); let mask = (0xFFFFFFFC ^ flag).rotate_left(block as u32 * 2); self.chunks[chunk] = self.chunks[chunk] & (mask as u32); if flag == USED { self.used += 1; } else if flag == UNUSABLE || flag == RESERVED { self.reserved += 1; } else { if self.used > 0 { self.used -= 1; } } (chunk * 16 + block) << 22 } pub fn mark_by_addr(&mut self, addr: usize, flag: usize) { let block_num = addr >> 22; let chunk: usize = (block_num / 16) as usize; let block: usize = block_num - chunk * 16; self.mark(chunk, block, flag); } pub fn count_total(& mut self) { let mut count: usize = 0; for i in 0..64 { let mut chunk = self.chunks[i]; for _j in 0..16 { if chunk & 0b11 != 0b11 { count += 1; } chunk = chunk >> 2; } } self.total = count; } pub fn get_total(&self) -> usize { self.total } pub fn get_used(&self) -> usize { self.used } pub fn get_reserved(&self) -> usize { self.reserved } pub fn get_free(&self) -> usize { self.total - self.used - self.reserved } } 

рдФрд░ рдЕрдм рд╣рдо рдорд╛рдирдЪрд┐рддреНрд░ рдХреЗ рдПрдХ рддрддреНрд╡ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реЛ рдЧрдПред рдпрджрд┐ рдХреЛрдИ рдорд╛рдирдЪрд┐рддреНрд░ рддрддреНрд╡ рдПрдХ рдореЗрдореЛрд░реА рдХреНрд╖реЗрддреНрд░ рдХрд╛ рд╡рд░реНрдгрди 4 рдПрдордмреА рд╕реЗ рдХрдо рдпрд╛ рдЙрд╕рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕ рдкреГрд╖реНрда рдХреЛ рд╕рдВрдкреВрд░реНрдг рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЕрдзрд┐рдХ - 4 рдПрдордмреА рдХреЗ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рд╣рд░рд╛рдпрд╛ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЯреБрдХрдбрд╝реЗ рдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрд▓рдЧ рд╕реЗ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВред рдмрд┐рдЯрдореИрдк рдХреЗ рдЖрд░рдВрднреАрдХрд░рдг рдХреЗ рдЪрд░рдг рдореЗрдВ, рд╣рдо рдореЗрдореЛрд░реА рдХреЗ рд╕рднреА рд╡рд░реНрдЧреЛрдВ рдХреЛ рджреБрд░реНрдЧрдо рдорд╛рдирддреЗ рд╣реИрдВ, рддрд╛рдХрд┐ рдЬрдм рдХрд╛рд░реНрдб рдЦрддреНрдо рд╣реЛ рдЬрд╛рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 128 рдПрдордмреА рдкрд░, рд╢реЗрд╖ рдЦрдВрдбреЛрдВ рдХреЛ рджреБрд░реНрдЧрдо рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 use lazy_static::lazy_static; use spin::Mutex; lazy_static! { static ref RAM_INFO: Mutex<PhysMemoryInfo> = Mutex::new(PhysMemoryInfo { total: 0, used: 0, reserved: 0, chunks: [0xFFFFFFFF; 64] }); } pub fn map(addr: usize, len: usize, flag: usize) { // if len <= 4MiB then mark whole page with flag if len <= 4 * 1024 * 1024 { RAM_INFO.lock().mark_by_addr(addr, flag); } else { let pages: usize = len >> 22; for map_page in 0..(pages - 1) { map(addr + map_page << 22, 4 * 1024 * 1024, flag); } map(addr + (pages << 22), len - (pages << 22), flag); } } 

рдвреЗрд░ рдФрд░ рдЙрд╕рдХрд╛ рдкреНрд░рдмрдВрдзрди


рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдкреНрд░рдмрдВрдзрди рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдХреЗрд╡рд▓ рдвреЗрд░ рдкреНрд░рдмрдВрдзрди рддрдХ рд╣реА рд╕реАрдорд┐рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХрд░реНрдиреЗрд▓ рдЕрдзрд┐рдХ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реИред рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рд╕рднреА рдореЗрдореЛрд░реА рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛, рдФрд░ рдпрд╣ рдЫреЛрдЯрд╛ рдкреНрд░рдмрдВрдзрдХ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рд╕рдордп, рдореБрдЭреЗ рд╕рднреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╕реНрдерд┐рд░ рдореЗрдореЛрд░реА рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЧреНрдп рдХреЛрдб рдФрд░ рд╕реНрдЯреИрдХ, рдФрд░ рдбрд╛рдпрдиреЗрдорд┐рдХ рд╣реАрдк рдореЗрдореЛрд░реА рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЬрд╣рд╛рдВ рдореИрдВ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░реВрдВрдЧрд╛ред рд╣рдо рдмреВрдЯ рд╕реНрдЯреЗрдЬ рдкрд░ рд╕реНрдерд┐рд░ рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдФрд░ рдЕрдм рддрдХ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 4 рдПрдордмреА рд╕реАрдорд┐рдд рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХрд░реНрдиреЗрд▓ рдЙрдирдореЗрдВ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИ) рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░ рдЕрдм рдЗрд╕рдХреЗ рд╕рд╛рде рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рд╕реНрддрд░ рдкрд░, рдореЗрд░реЗ рдкрд╛рд╕ рдбреАрдПрдордП рдбрд┐рд╡рд╛рдЗрд╕ рдирд╣реАрдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рдмреЗрд╣рдж рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рд╣реИред


рдореИрдВрдиреЗ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдХрд░реНрдиреЗрд▓ рдореЗрдореЛрд░реА рд╕реНрдкреЗрд╕ (0xE0000000) рдХреЗ 512 рдПрдордмреА рдХреЛ рдвреЗрд░ рдореЗрдВ рджрд┐рдпрд╛, рдореИрдВ рдвреЗрд░ рдЙрдкрдпреЛрдЧ рдорд╛рдирдЪрд┐рддреНрд░ (0xDFC00000) рдХреЛ 4 рдПрдордмреА рдХрдо рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реВрдВред рдореИрдВ рд░рд╛рдЬреНрдп рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд┐рдЯрдореИрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рднреМрддрд┐рдХ рд╕реНрдореГрддрд┐ рдХреА рддрд░рд╣, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдХреЗрд╡рд▓ 2 рд░рд╛рдЬреНрдп рд╣реИрдВ - рд╡реНрдпрд╕реНрдд / рдореБрдлреНрддред рдореЗрдореЛрд░реА рдмреНрд▓реЙрдХ рдХрд╛ рдЖрдХрд╛рд░ 64 рдмрд╛рдЗрдЯреНрд╕ рд╣реИ - рдпрд╣ u32, u8 рдЬреИрд╕реЗ рдЫреЛрдЯреЗ рдЪрд░ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХреБрдЫ рд╣реИ, рд▓реЗрдХрд┐рди, рд╢рд╛рдпрдж, рдпрд╣ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╖реНрдЯрддрдо рд╣реИред рдлрд┐рд░ рднреА, рдпрд╣ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдвреЗрд░ рдкрд░ рдПрдХрд▓ рдЪрд░ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЕрдм рдЗрд╕рдХрд╛ рдореБрдЦреНрдп рдЙрджреНрджреЗрд╢реНрдп рдорд▓реНрдЯреАрдЯрд╛рд╕реНрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реИред


64 рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдмреНрд▓реЙрдХ рдХреЛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рд╕рдореВрд╣реАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдкреВрд░реЗ 4 рдПрдордмреА рдкреЗрдЬ рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдХрдИ рдкрдиреНрдиреЛрдВ рдореЗрдВ рджреЛрдиреЛрдВ рдЫреЛрдЯреА рдФрд░ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╢рдмреНрджреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ: chunk - 64 рдмрд╛рдЗрдЯреНрд╕, рдкреИрдХ - 2 KB (рдПрдХ u32 - 64 рдмрд╛рдЗрдЯреНрд╕ * 32 рдмрд┐рдЯреНрд╕ рдкреНрд░рддрд┐ рдкреИрдХреЗрдЬ), рдкреЗрдЬ - 4 рдПрдордмреАред


 #[repr(packed)] #[derive(Copy, Clone)] struct HeapPageInfo { //every bit represents 64 bytes chunk of memory. 0 is free, 1 is busy //u32 size is 4 bytes, so page information total size is 8KiB pub _4mb_by_64b: [u32; 2048], } #[repr(packed)] #[derive(Copy, Clone)] struct HeapInfo { //Here we can know state of any 64 bit chunk in any of 128 4-MiB pages //Page information total size is 8KiB, so information about 128 pages requires 1MiB reserved data pub _512mb_by_4mb: [HeapPageInfo; 128], } 

рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рд╕реЗ рд╕реНрдореГрддрд┐ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╕рдордп, рдореИрдВ рддреАрди рдорд╛рдорд▓реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ, рдЬреЛ рдХрд┐ рдЧреНрд░реИрдиреНрдпреБрд▓реИрд░рд┐рдЯреА рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ:


  • 2 рдХреЗрдмреА рд╕реЗ рдХрдо рдореЗрдореЛрд░реА рдХрд╛ рдЕрдиреБрд░реЛрдз рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рд╕реЗ рдЖрдпрд╛ рдерд╛ред рдЖрдкрдХреЛ рдПрдХ рдкреИрдХ рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдпрд╣ рдореБрдлрд╝реНрдд рд╣реЛрдЧрд╛ [рдЖрдХрд╛рд░ / 64, рдХреЛрдИ рднреА рдЧреИрд░-рд╢реВрдиреНрдп рд╢реЗрд╖ рдПрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИ] рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╡рд┐рдЦрдВрдбреВ, рдЗрди рд╡рд┐рдЦрдВрдбреВ рдХреЛ рд╡реНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВ, рдкрд╣рд▓реЗ рдЪрдВрдХ рдХрд╛ рдкрддрд╛ рд╡рд╛рдкрд╕ рдХрд░реЗрдВред
  • рдЖрдмрдВрдЯрдХ рд╕реЗ 4 рдПрдордмреА рд╕реЗ рдХрдо рдореЗрдореЛрд░реА рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдЖрдпрд╛, рд▓реЗрдХрд┐рди 2 рдХреЗрдмреА рд╕реЗ рдЕрдзрд┐рдХред рдЖрдкрдХреЛ рдПрдХ рдРрд╕рд╛ рдкреГрд╖реНрда рдЦреЛрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдореБрдлрд╝реНрдд [рдЖрдХрд╛рд░ / 2048 рд╣реЛ, рдХреЛрдИ рднреА рдиреЙрдирдЬрд╝рд░реЛ рд╢реЗрд╖ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдПрдХ] рдкреИрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдорд╛рд░реНрдХ [рдЖрдХрд╛рд░ / 2048] рд╡реНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдкреИрдХ рдХрд░рддрд╛ рд╣реИ, рдпрджрд┐ рдХреЛрдИ рд╢реЗрд╖ рд╣реИ, рддреЛ рдирд┐рд╢рд╛рди [рд╢реЗрд╖] рдХреЛ рдЕрдВрддрд┐рдо рдкреИрдХ рдореЗрдВ рд╡реНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВред
  • рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рд╕реЗ 4 рдПрдордмреА рд╕реЗ рдЕрдзрд┐рдХ рдХреА рдореЗрдореЛрд░реА рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдЖрдпрд╛ред [рдЖрдХрд╛рд░ / 4 Mi, рдХрд┐рд╕реА рднреА рдиреЙрдирдЬрд░реЛ рдмреИрд▓реЗрдВрд╕ рдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдПрдХ] рдкреГрд╖реНрда рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рд╡реНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ [рдЖрдХрд╛рд░ / 4 Mi] рдкреГрд╖реНрдареЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЕрдЧрд░ рдХреЛрдИ рд╕рдВрддреБрд▓рди рд╣реИ - рдЪрд┐рд╣реНрди [рд╕рдВрддреБрд▓рди] рд╡реНрдпрд╕реНрдд рдХреЗ рд░реВрдк рдореЗрдВ рдкреИрдХ рдХрд░рддрд╛ рд╣реИред рдЕрдВрддрд┐рдо рдкреИрдХ рдореЗрдВ, рд╢реЗрд╖ рднрд╛рдЧ рдХреЛ рд╡реНрдпрд╕реНрдд рдорд╛рдирдХрд░ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВред

рдореБрдХреНрдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЦреЛрдЬ рднреА рдЧреНрд░реИрдиреНрдпреБрд▓реИрд░рд┐рдЯреА рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИ - рдПрдХ рд╕рд░рдгреА рдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдпрд╛ рдмрд┐рдЯ рдорд╛рд╕реНрдХ рдХреЗ рд▓рд┐рдП рдЪреБрдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм рднреА рдЖрдк рд╡рд┐рджреЗрд╢ рдЬрд╛рддреЗ рд╣реИрдВ, OOM рд╣реЛрддрд╛ рд╣реИред рдЬрдм рдбреАрд▓реНрд▓реЛрдХреЗрд╢рди, рдПрдХ рд╕рдорд╛рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдЬрд╛рд░реА рдХрд┐рдП рдЧрдП рдЕрдВрдХрди рдХреЗ рд▓рд┐рдПред рдореБрдХреНрдд рдХреА рдЧрдИ рдореЗрдореЛрд░реА рд░реАрд╕реЗрдЯ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдкреВрд░рд╛ рдХреЛрдб рдмрдбрд╝рд╛ рд╣реИ, рдореИрдВ рдЗрд╕реЗ рд╕реНрдкреЙрдЗрд▓рд░ рдХреЗ рдиреАрдЪреЗ рд░рдЦреВрдВрдЧрд╛ред


рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдмрд┐рдЯрдореИрдк
 //512 MiB should be enough for kernel heap. If not - ooops... pub const KHEAP_START: usize = 0xE0000000; //I will keep 1MiB info about my heap in separate 4MiB page before heap at this point pub const KHEAP_INFO_ADDR: usize = 0xDFC00000; pub const KHEAP_CHUNK_SIZE: usize = 64; pub fn init() { KHEAP_INFO.lock().init(); } #[repr(packed)] #[derive(Copy, Clone)] struct HeapPageInfo { //every bit represents 64 bytes chunk of memory. 0 is free, 1 is busy //u32 size is 4 bytes, so page information total size is 8KiB pub _4mb_by_64b: [u32; 2048], } impl HeapPageInfo { pub fn init(&mut self) { for i in 0..2048 { self._4mb_by_64b[i] = 0; } } pub fn mark_chunks_used(&mut self, _32pack: usize, chunk: usize, n: usize) { let mask: u32 = 0xFFFFFFFF >> (32 - n) << chunk; self._4mb_by_64b[_32pack] = self._4mb_by_64b[_32pack] | mask; } pub fn mark_chunks_free(&mut self, _32pack: usize, chunk: usize, n: usize) { let mask: u32 = 0xFFFFFFFF >> (32 - n) << chunk; self._4mb_by_64b[_32pack] = self._4mb_by_64b[_32pack] ^ mask; } pub fn empty(&self) -> bool { for i in 0..2048 { if self._4mb_by_64b[i] != 0 { return false } } true } } #[repr(packed)] #[derive(Copy, Clone)] struct HeapInfo { //Here we can know state of any 64 bit chunk in any of 128 4-MiB pages //Page information total size is 8KiB, so information about 128 pages requires 1MiB reserved data pub _512mb_by_4mb: [HeapPageInfo; 128], } impl HeapInfo { pub fn init(&mut self) { for i in 0..128 { self._512mb_by_4mb[i].init(); } } // returns page number pub fn find_free_pages_of_size(&self, n: usize) -> usize { if n >= 128 { 0xFFFFFFFF } else { let mut start_page: usize = 0xFFFFFFFF; let mut current_page: usize = 0xFFFFFFFF; for page in 0..128 { if self._512mb_by_4mb[page].empty() { if current_page - start_page == n { return start_page } if start_page == 0xFFFFFFFF { start_page = page; } current_page = page; } else { start_page = 0xFFFFFFFF; current_page = 0xFFFFFFFF; } } 0xFFFFFFFF } } // returns (page number, 32pack number) pub fn find_free_packs_of_size(&self, n: usize) -> (usize, usize) { if n < 2048 { for page in 0..128 { let mut start_pack: usize = 0xFFFFFFFF; let mut current_pack: usize = 0xFFFFFFFF; for _32pack in 0..2048 { let _32pack_info = self._512mb_by_4mb[page]._4mb_by_64b[_32pack]; if _32pack_info == 0 { if current_pack - start_pack == n { return (page, start_pack) } if start_pack == 0xFFFFFFFF { start_pack = _32pack; } current_pack = _32pack; } else { start_pack = 0xFFFFFFFF; current_pack = 0xFFFFFFFF; } } } (0xFFFFFFFF, 0xFFFFFFFF) } else { (0xFFFFFFFF, 0xFFFFFFFF) } } // returns (page number, 32pack number, chunk number) pub fn find_free_chunks_of_size(&self, n: usize) -> (usize, usize, usize) { if n < 32 { for page in 0..128 { for _32pack in 0..2048 { let _32pack_info = self._512mb_by_4mb[page]._4mb_by_64b[_32pack]; let mask: u32 = 0xFFFFFFFF >> (32 - n); for chunk in 0..(32-n) { if ((_32pack_info >> chunk) & mask) ^ mask == mask { return (page, _32pack, chunk) } } } } (0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) } else { (0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF) } } fn mark_chunks_used(&mut self, page: usize, _32pack: usize, chunk: usize, n: usize) { self._512mb_by_4mb[page].mark_chunks_used(_32pack, chunk, n); } fn mark_chunks_free(&mut self, page: usize, _32pack: usize, chunk: usize, n: usize) { self._512mb_by_4mb[page].mark_chunks_free(_32pack, chunk, n); } fn mark_packs_used(&mut self, page: usize, _32pack:usize, n: usize) { for i in _32pack..(_32pack + n) { self._512mb_by_4mb[page]._4mb_by_64b[i] = 0xFFFFFFFF; } } fn mark_packs_free(&mut self, page: usize, _32pack:usize, n: usize) { for i in _32pack..(_32pack + n) { self._512mb_by_4mb[page]._4mb_by_64b[i] = 0; } } } use lazy_static::lazy_static; use spin::Mutex; lazy_static! { static ref KHEAP_INFO: Mutex<&'static mut HeapInfo> = Mutex::new(unsafe { &mut *(KHEAP_INFO_ADDR as *mut HeapInfo) }); } fn allocate_n_chunks_less_than_pack(n: usize, align: usize) -> *mut u8 { let mut heap_info = KHEAP_INFO.lock(); let (page, _32pack, chunk) = heap_info.find_free_chunks_of_size(n); if page == 0xFFFFFFFF { core::ptr::null_mut() } else { let tptr: usize = KHEAP_START + 0x400000 * page + _32pack * 32 * 64 + chunk * 64; let res = tptr % align; let uptr = if res == 0 { tptr } else { tptr + align - res }; //check bounds: more than start and less than 4GiB - 64B //but according to chunks error should never happen if uptr >= KHEAP_START && uptr <= 0xFFFFFFFF - 64 * n { heap_info.mark_chunks_used(page, _32pack, chunk, n); uptr as *mut u8 } else { core::ptr::null_mut() } } } fn allocate_n_chunks_less_than_page(n: usize, align: usize) -> *mut u8 { let mut heap_info = KHEAP_INFO.lock(); let packs_n: usize = n / 32; let lost_chunks = n - packs_n * 32; let mut packs_to_alloc = packs_n; if lost_chunks != 0 { packs_to_alloc += 1; } let (page, pack) = heap_info.find_free_packs_of_size(packs_to_alloc); if page == 0xFFFFFFFF { core::ptr::null_mut() } else { let tptr: usize = KHEAP_START + 0x400000 * page + pack * 32 * 64; let res = tptr % align; let uptr = if res == 0 { tptr } else { tptr + align - res }; //check bounds: more than start and less than 4GiB - 64B //but according to chunks error should never happen if uptr >= KHEAP_START && uptr <= 0xFFFFFFFF - 64 * n { heap_info.mark_packs_used(page, pack, packs_n); if lost_chunks != 0 { heap_info.mark_chunks_used(page, pack + packs_to_alloc, 0, lost_chunks); } uptr as *mut u8 } else { core::ptr::null_mut() } } } //unsupported yet fn allocate_n_chunks_more_than_page(n: usize, align: usize) -> *mut u8 { let mut heap_info = KHEAP_INFO.lock(); let packs_n: usize = n / 32; let lost_chunks = n - packs_n * 32; let mut packs_to_alloc = packs_n; if lost_chunks != 0 { packs_to_alloc += 1; } let pages_n: usize = packs_to_alloc / 2048; let mut lost_packs = packs_to_alloc - pages_n * 2048; let mut pages_to_alloc = pages_n; if lost_packs != 0 { pages_to_alloc += 1; } if lost_chunks != 0 { lost_packs -= 1; } let page = heap_info.find_free_pages_of_size(pages_to_alloc); if page == 0xFFFFFFFF { core::ptr::null_mut() } else { let tptr: usize = KHEAP_START + 0x400000 * page; let res = tptr % align; let uptr = if res == 0 { tptr } else { tptr + align - res }; //check bounds: more than start and less than 4GiB - 64B * n //but according to chunks error should never happen if uptr >= KHEAP_START && uptr <= 0xFFFFFFFF - 64 * n { for i in page..(page + pages_n) { heap_info.mark_packs_used(i, 0, 2048); } if lost_packs != 0 { heap_info.mark_packs_used(page + pages_to_alloc, 0, lost_packs); } if lost_chunks != 0 { heap_info.mark_chunks_used(page + pages_to_alloc, lost_packs, 0, lost_chunks); } uptr as *mut u8 } else { core::ptr::null_mut() } } } // returns pointer pub fn allocate_n_chunks(n: usize, align: usize) -> *mut u8 { if n < 32 { allocate_n_chunks_less_than_pack(n, align) } else if n < 32 * 2048 { allocate_n_chunks_less_than_page(n, align) } else { allocate_n_chunks_more_than_page(n, align) } } pub fn free_chunks(ptr: usize, n: usize) { let page: usize = (ptr - KHEAP_START) / 0x400000; let _32pack: usize = ((ptr - KHEAP_START) - (page * 0x400000)) / (32 * 64); let chunk: usize = ((ptr - KHEAP_START) - (page * 0x400000) - (_32pack * (32 * 64))) / 64; let mut heap_info = KHEAP_INFO.lock(); if n < 32 { heap_info.mark_chunks_free(page, _32pack, chunk, n); } else if n < 32 * 2048 { let packs_n: usize = n / 32; let lost_chunks = n - packs_n * 32; heap_info.mark_packs_free(page, _32pack, packs_n); if lost_chunks != 0 { heap_info.mark_chunks_free(page, _32pack + packs_n, 0, lost_chunks); } } else { let packs_n: usize = n / 32; let pages_n: usize = packs_n / 2048; let lost_packs: usize = packs_n - pages_n * 2048; let lost_chunks = n - packs_n * 32; for i in page..(page + pages_n) { heap_info.mark_packs_free(i, 0, 2048); } if lost_packs != 0 { heap_info.mark_packs_free(page + pages_n, 0, lost_packs); } if lost_chunks != 0 { heap_info.mark_chunks_free(page + pages_n, packs_n, 0, lost_chunks); } } } 

рдЖрд╡рдВрдЯрди рдФрд░ рдкреГрд╖реНрда рджреЛрд╖


рдвреЗрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕реЗ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рд╡реЗрдХреНрдЯрд░, рдкреЗрдбрд╝, рд╣реИрд╢ рдЯреЗрдмрд▓, рдмреЙрдХреНрд╕ рдФрд░ рдмрд╣реБрдд рдХреБрдЫ рдЦреБрд▓ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдХреЗ рдмрд┐рдирд╛ рдЬреАрдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИред рдЬреИрд╕реЗ рд╣реА рд╣рдо рдЖрд╡рдВрдЯрди рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдкреНрд▓рдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╡реИрд╢реНрд╡рд┐рдХ рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рдШреЛрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреАрд╡рди рддреБрд░рдВрдд рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рдПрдЧрд╛ред


рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ - рдпрд╣ рдХреЗрд╡рд▓ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рддрдВрддреНрд░ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред


 use alloc::alloc::{GlobalAlloc, Layout}; pub struct Os1Allocator; unsafe impl Sync for Os1Allocator {} unsafe impl GlobalAlloc for Os1Allocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { use super::logical::{KHEAP_CHUNK_SIZE, allocate_n_chunks}; let size = layout.size(); let mut chunk_count: usize = 1; if size > KHEAP_CHUNK_SIZE { chunk_count = size / KHEAP_CHUNK_SIZE; if KHEAP_CHUNK_SIZE * chunk_count != size { chunk_count += 1; } } allocate_n_chunks(chunk_count, layout.align()) } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { use super::logical::{KHEAP_CHUNK_SIZE, free_chunks}; let size = layout.size(); let mut chunk_count: usize = 1; if size > KHEAP_CHUNK_SIZE { chunk_count = size / KHEAP_CHUNK_SIZE; if KHEAP_CHUNK_SIZE * chunk_count != size { chunk_count += 1; } } free_chunks(ptr as usize, chunk_count); } } 

Lib.rs рдореЗрдВ рдЖрд╡рдВрдЯрди рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:


 #![feature(alloc, alloc_error_handler)] extern crate alloc; #[global_allocator] static ALLOCATOR: memory::allocate::Os1Allocator = memory::allocate::Os1Allocator; 

рдФрд░ рдЬрдм рд╣рдо рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдкреГрд╖реНрда рджреЛрд╖ рдЕрдкрд╡рд╛рдж рдорд┐рд▓рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдЕрднреА рддрдХ рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдХреЗ рдЖрд╡рдВрдЯрди рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рдЦреИрд░, рдпрд╣ рдХреИрд╕реЗ! рдЦреИрд░, рдЖрдкрдХреЛ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреА рд╕рд╛рдордЧреНрд░реА рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рдореИрдВрдиреЗ рд╡рд░реНрдЪреБрдЕрд▓ рдореЗрдореЛрд░реА рдХреЗ рдЖрд▓рд╕реА рдЖрд╡рдВрдЯрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛, рдЕрд░реНрдерд╛рддреН, рдпрд╣ рдкреГрд╖реНрда рдореЗрдореЛрд░реА рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рдордп рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рд╕рдордпред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, x86 рдкреНрд░реЛрд╕реЗрд╕рд░ рдЗрд╕рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЗрд╕реЗ рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рднреА рдХрд░рддрд╛ рд╣реИред Page fault , , , тАФ , , CR2 тАФ , .


, . 32 ( , , 32 ), . Rust. , . , , iret , , Page fault Protection fault. Protection fault тАФ , .


 eE_page_fault: pushad mov eax, [esp + 32] push eax mov eax, cr2 push eax call kE_page_fault pop eax pop eax popad add esp, 4 iret 

Rust , . , . . .


 bitflags! { struct PFErrorCode: usize { const PROTECTION = 1; //1 - protection caused, 0 - not present page caused const WRITE = 1 << 1; //1 - write caused, 0 - read caused const USER_MODE = 1 << 2; //1 - from user mode, 0 - from kernel const RESERVED = 1 << 3; //1 - reserved page (PAE/PSE), 0 - not const INSTRUCTION = 1 << 4; //1 - instruction fetch caused, 0 - not } } impl PFErrorCode { pub fn to_pd_flags(&self) -> super::super::paging::PDEntryFlags { use super::super::paging; let mut flags = paging::PDEntryFlags::empty(); if self.contains(PFErrorCode::WRITE) { flags.set(paging::PDEntryFlags::WRITABLE, true); } if self.contains(PFErrorCode::USER_MODE) { flags.set(paging::PDEntryFlags::USER_ACCESSIBLE, true); } flags } } #[no_mangle] pub unsafe extern fn kE_page_fault(ptr: usize, code: usize) { use super::super::paging; println!("Page fault occured at addr 0x{:X}, code {:X}", ptr, code); let phys_address = crate::memory::physical::alloc_page(); let code_flags: PFErrorCode = PFErrorCode::from_bits(code).unwrap(); if !code_flags.contains(PFErrorCode::PROTECTION) { //page not presented, we need to allocate the new one let mut flags: paging::PDEntryFlags = code_flags.to_pd_flags(); flags.set(paging::PDEntryFlags::HUGE_PAGE, true); paging::allocate_page(phys_address, ptr, flags); println!("Page frame allocated at Paddr {:#X} Laddr {:#X}", phys_address, ptr); } else { panic!("Protection error occured, cannot handle yet"); } } 

, . , . . , . , , :


  println!("memory: total {} used {} reserved {} free {}", memory::physical::total(), memory::physical::used(), memory::physical::reserved(), memory::physical::free()); use alloc::vec::Vec; let mut vec: Vec<usize> = Vec::new(); for i in 0..1000000 { vec.push(i); } println!("vec len {}, ptr is {:?}", vec.len(), vec.as_ptr()); println!("Still works, check reusage!"); let mut vec2: Vec<usize> = Vec::new(); for i in 0..10 { vec2.push(i); } println!("vec2 len {}, ptr is {:?}, vec is still here? {}", vec2.len(), vec2.as_ptr(), vec.get(1000).unwrap()); println!("Still works!"); println!("memory: total {} used {} reserved {} free {}", memory::physical::total(), memory::physical::used(), memory::physical::reserved(), memory::physical::free()); 

:
OS1 heap


, , . 3,5 + 3 , . 3,5 .


IRQ 1 тАФ Alt + PrntScrn :)


, , Rust тАФ , тАФ , !


, .


рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!

Source: https://habr.com/ru/post/hi446214/


All Articles