åç·š
æåã®èšäºã«ã¯ãŸã å·ããæéããããŸããã§ããã®ã§ãèå³ãããããç¶ç·šãæžããªãããšã«ããŸããã
ãã®ãããåã®èšäºã§ããªã³ã¯ãã«ãŒãã«ãã¡ã€ã«ã®èªã¿èŸŒã¿ãããã³ãã©ã€ããªåæåã«ã€ããŠèª¬æããŸããã ããã€ãã®æçšãªãªã³ã¯ãæäŸããããŒããããã«ãŒãã«ãã¡ã¢ãªå
ã«é
眮ãããæ¹æ³ãããŒãæã«ä»®æ³ã¢ãã¬ã¹ãšç©çã¢ãã¬ã¹ãæ¯èŒããæ¹æ³ãããã³ããŒãžã¡ã«ããºã ã®ãµããŒããæå¹ã«ããæ¹æ³ã説æããŸããã æåŸã«ãRustã§æžãããã«ãŒãã«ã®kmain颿°ã«å¶åŸ¡ãæž¡ãããŸããã æ¬¡ã¯ããŠãµã®ã®ç©Žã®æ·±ãã調ã¹ãŸãããïŒ
ããŒãã®ãã®éšåã§ã¯ãRustã®æ§æã«ã€ããŠç°¡åã«èª¬æããäžè¬çã«ã¯VGAã§ã®æ
å ±ã®åºåã«ã€ããŠèª¬æããã»ã°ã¡ã³ããšå²ã蟌ã¿ã®ã»ããã¢ããã«ã€ããŠè©³ãã説æããŸã ã ã«ããã«èå³ããããã¹ãŠã®äººã«å°ãããšãç§ãã¡ã¯å§ããŸãã
ãã³ã®ã»ããã¢ãã
äžè¬ã«ããã®æé ã«ã¯ç¹ã«è€éãªããšã¯ãããŸããã詳现ã«ã€ããŠã¯ã Philippeããã°ã«é£çµ¡ããŠãã ããã ãã ããããã€ãã®æç¹ã§åæ¢ããŸãã
Stable Rustã¯äœã¬ãã«ã®éçºã«å¿
èŠãªäžéšã®æ©èœããŸã ãµããŒãããŠããªããããæšæºã©ã€ãã©ãªãç¡å¹ã«ããŠBare Bonesã§ãã«ãããã«ã¯ãRustãæ¯æ©å¿
èŠã§ãã æ³šæããŠãã ãããææ°çã«ã¢ããã°ã¬ãŒãããåŸãå®å
šã«åäœããªãã³ã³ãã€ã©ãååŸããæãè¿ãå®å®ããã³ã³ãã€ã©ã«ããŒã«ããã¯ããå¿
èŠããããŸããã ã³ã³ãã€ã©ãæšæ¥ã¯åäœããŠããããæŽæ°ãããŠåäœããªãããšã確å®ãªå Žåã¯ãå¿
èŠãªæ¥ä»ã眮ãæããŠã³ãã³ããå®è¡ããŸã
rustup override add nightly-YYYY-MM-DD
ã¡ã«ããºã ã®è©³çްã«ã€ããŠã¯ã ãã¡ããããåãåãããã ãã ã
次ã«ãç®çã®ãã©ãããã©ãŒã ãæ§æããŸãã ç§ã¯Philip Oppermanã®ããã°ã«åºã¥ããŠããã®ã§ããã®ã»ã¯ã·ã§ã³ã®å€ãã®ããšã¯åœŒããåããã骚ã«ãã£ãŠåè§£ãããç§ã®ããŒãºã«é©åããŸããã Phillipã¯åœŒã®ããã°ã§x64åãã«éçºäžã§ããåœåã¯x32ãéžæããŠããŸããã®ã§ãtarget.jsonã¯å°ãç°ãªããŸãã ç§ã¯åœŒãå®å
šã«é£ããŠè¡ããŸã
{ "llvm-target": "i686-unknown-none", "data-layout": "em:ep:32:32-f64:32:64-f80:32-n8:16:32-S128", "arch": "x86", "target-endian": "little", "target-pointer-width": "32", "target-c-int-width": "32", "os": "none", "executables": true, "linker-flavor": "ld.lld", "linker": "rust-lld", "panic-strategy": "abort", "disable-redzone": true, "features": "-mmx,-sse,+soft-float" }
ããã§æãé£ããéšåã¯ãã data-layout ããã©ã¡ãŒã¿ãŒã§ãã LLVMã®ããã¥ã¡ã³ãã«ã¯ãããããã-ãã§åºåãããããŒã¿ã¬ã€ã¢ãŠããªãã·ã§ã³ã§ããããšã瀺ãããŠããŸãã æåã®ãeããã£ã©ã¯ã¿ãŒã¯ã€ã³ãæ§ãæ
åœããŸãããã®äŸã§ã¯ããã©ãããã©ãŒã ãå¿
èŠãšãããªãã«ãšã³ãã£ã¢ã³ã§ãã 2çªç®ã®æåã¯mããæªã¿ãã§ãã ã¬ã€ã¢ãŠãäžã®ãã£ã©ã¯ã¿ãŒåãæ
åœããŸãã åºå圢åŒã¯ELFã§ããããïŒãã«ãã¹ã¯ãªãããåç
§ïŒãå€ãmïŒeããéžæããŸãã 3çªç®ã®æåã¯ããããåäœã®ãã€ã³ã¿ãŒã®ãµã€ãºãšABIïŒã¢ããªã±ãŒã·ã§ã³ãã€ããªã€ã³ã¿ãŒãã§ã€ã¹ïŒã§ãã ããã§ã¯ãã¹ãŠãåçŽã§ã32ãããã§ããããããpïŒ32ïŒ32ããšå€§èã«é
眮ããŸãã æ¬¡ã¯æµ®åå°æ°ç¹æ°ã§ãã ã¢ã©ã€ã³ã¡ã³ã64-ãf64ïŒ32ïŒ64ãã®ABI 32ã«æºæ ãã64ãããæ°ãšãããã©ã«ãã§ã¢ã©ã€ã³ã¡ã³ãã®ãã80ãããæ°-ãf80ïŒ32ãããµããŒããããšå ±åããŠããŸãã æ¬¡ã®èŠçŽ ã¯æŽæ°ã§ãã 8ãããããéå§ãããã©ãããã©ãŒã ã®æå€§32ãããïŒãn8ïŒ16ïŒ32ãïŒã«ç§»åããŸãã æåŸã¯ã¹ã¿ãã¯ã®æŽåã§ãã 128ãããæŽæ°ãå¿
èŠãªã®ã§ãS128ã«ããŸãã ãããã«ãããLLVMã¯ãã®ãã©ã¡ãŒã¿ãŒãå®å
šã«ç¡èŠã§ããŸãããããç§ãã¡ã®å¥œã¿ã§ãã
æ®ãã®ãã©ã¡ãŒã¿ãŒã«ã€ããŠã¯ããã£ãªãããèŠãããšãã§ããŸãã圌ã¯ãã¹ãŠãããŸã説æããŠããŸãã
ãŸããcargo-xbuildãå¿
èŠã§ããããã¯ããªãã¿ã®ãªãã¿ãŒã²ãããã©ãããã©ãŒã ã§ãã«ããããšãã«ãrust-coreãã¯ãã¹ã³ã³ãã€ã«ã§ããããŒã«ã§ãã
ã€ã³ã¹ããŒã«ã
cargo install cargo-xbuild
ãã®ããã«çµã¿ç«ãŠãŸãã
cargo xbuild -Z unstable-options --manifest-path=kernel/Cargo.toml --target kernel/targets/$(ARCH).json --out-dir=build/lib
ã«ãŒããã£ã¬ã¯ããªããèµ·åãããã«ãŒãã«ã¯ã«ãŒãã«ãã£ã¬ã¯ããªã«ãããããMakeã®æ£ããæäœã®ããã«ãããã§ã¹ããå¿
èŠã§ããã
ãããã§ã¹ãã®æ©èœã®ãã¡ã crate-type = ["staticlib"]ã®ã¿ãéžæã§ããŸããããã«ãããåºåã«ãªã³ã¯å¯èœãªãã¡ã€ã«ãæäŸãããŸãã ç§ãã¡ã¯åœŒãLLDã§é€ããŸãã
kmainãšåæèšå®
Rustã®èŠåã«ããã°ãéçã©ã€ãã©ãªïŒãŸãã¯ããã©ããããªãã€ããªãã¡ã€ã«ïŒãäœæããå Žåãã¯ã¬ãŒãã®ã«ãŒãã«ã¯ãšã³ããªãã€ã³ãã§ãããã¡ã€ã«lib.rsãå«ãŸããŠããå¿
èŠããããŸãã ãã®äžã«ã屿§ã®å©ããåããŠãèšèªæ©èœãæ§æããããŸã倧åãªkmainãèŠã€ããããŸãã
ãã®ãããæåã®ã¹ãããã§ã¯ãstdã©ã€ãã©ãªãç¡å¹ã«ããå¿
èŠããããŸãã ããã¯ãã¯ãã§è¡ãããŸãã
#![no_std]
ãã®ãããªç°¡åãªæé ã§ããã«ãã¹ã¬ãããåçã¡ã¢ãªãããã³æšæºã©ã€ãã©ãªã®ãã®ä»ã®æ¥œãã¿ãããã«å¿ããŠããŸããŸãã ããã«ãprintlnïŒãã¯ããèªåèªèº«ãã奪ããããèªåã§å®è£
ããå¿
èŠããããŸãã æ¬¡åã¯ãã®æ¹æ³ã説æããŸãã
ãã®å Žæã®ã©ããã«ããå€ãã®ãã¥ãŒããªã¢ã«ã¯ããHello Worldãã®åºåã§çµãããçãæ¹ã説æããŠããŸããã ç§ãã¡ã¯ä»ã®æ¹æ³ã§è¡ããŸãã ãŸãããããã¯ãã¢ãŒãã®ã³ãŒããšããŒã¿ã»ã°ã¡ã³ããèšå®ããVGAãæ§æããå²ã蟌ã¿ãæ§æããå¿
èŠããããŸãã
#![no_std] #[macro_use] pub mod debug; #[cfg(target_arch = "x86")] #[path = "arch/i686/mod.rs"] pub mod arch; #[no_mangle] extern "C" fn kmain(pd: usize, mb_pointer: usize, mb_magic: usize) { arch::arch_init(pd); ...... } #[panic_handler] fn panic(_info: &PanicInfo) -> ! { println!("{}", _info); loop {} }
ããã§äœãèµ·ãã£ãŠããŸããïŒ ç§ãèšã£ãããã«ãæšæºã©ã€ãã©ãªããªãã«ããŸãã ãŸãã2ã€ã®éåžžã«éèŠãªã¢ãžã¥ãŒã«ãdebugïŒç»é¢ã«æžã蟌ãïŒãšarchïŒãã¹ãŠã®ãã©ãããã©ãŒã äŸåã®ããžãã¯ãååšããïŒãçºè¡šããŸãã Rustæ©èœãæ§æãšå
±ã«äœ¿çšããŠãç°ãªãã¢ãŒããã¯ãã£ãŒå®è£
ã§åãã€ã³ã¿ãŒãã§ãŒã¹ã宣èšããããããæå€§éã«äœ¿çšããŸãã ããã§ã¯ãx86ã§ã®ã¿åæ¢ããããã«ã€ããŠã®ã¿èª¬æããŸãã
Rustãå¿
èŠãšããå®å
šã«åå§çãªãããã¯ãã³ãã©ãŒã宣èšããŸããã ãã®åŸãããã倿Žããããšãå¯èœã«ãªããŸãã
kmainã¯3ã€ã®åŒæ°ãåãå
¥ããååã®æªã¿ã®ãªãC衚èšã§ãšã¯ã¹ããŒããããããããªã³ã«ã¯é¢æ°ã_loaderããã®åŒã³åºãã«æ£ããé¢é£ä»ããããšãã§ããŸããããã«ã€ããŠã¯ãåã®èšäºã§èª¬æããŸããã æåã®åŒæ°ã¯PDããŒãžããŒãã«ã®ã¢ãã¬ã¹ã2çªç®ã¯ã¡ã¢ãªã«ãŒããååŸããGRUBæ§é ã®ç©çã¢ãã¬ã¹ã3çªç®ã¯ããžãã¯ãã³ããŒã§ãã å°æ¥çã«ã¯ãMultiboot 2ãµããŒããšç¬èªã®ããŒãããŒããŒã®äž¡æ¹ãå®è£
ãããã®ã§ãããžãã¯ãã³ããŒã䜿çšããŠããŒãæ¹æ³ãèå¥ããŸãã
æåã®kmainåŒã³åºãã¯ããã©ãããã©ãŒã åºæã®åæåã§ãã äžã«å
¥ããŸãã arch_init颿°ã¯arch / i686 / mod.rsãã¡ã€ã«ã«ããã32ãããx86åºæã®ãããªãã¯ã§ãããæ¬¡ã®ããã«ãªããŸãã
pub fn arch_init(pd: usize) { unsafe { vga::VGA_WRITER.lock().init(); gdt::setup_gdt(); idt::init_idt(); paging::setup_pd(pd); } }
ã芧ã®ãšãããx86ã®å Žåãåºåãã»ã°ã¡ã³ããŒã·ã§ã³ãå²ã蟌ã¿ãããã³ããŒãžã³ã°ã¯ââé çªã«åæåãããŸãã VGAããå§ããŸãããã
VGAåæå
åãã¥ãŒããªã¢ã«ã§ã¯ãHello Worldãå°å·ããããšã矩åä»ããããŠãããããã©ãã§ãVGAãæäœããæ¹æ³ãããããŸãã ãã®ãããã§ããã ãç°¡åã«èª¬æããŸããèªåã§äœã£ããããã«ã®ã¿çŠç¹ãåœãŠãŸãã lazy_staticã®äœ¿çšã«ã€ããŠã¯ãPhilippeã®ããã°ã«éä¿¡ããŸããã詳现ã«ã€ããŠã¯èª¬æããŸããã const fnã¯ãŸã ãªãªãŒã¹ãããŠããªããããçŸããéçãªåæåã¯ãŸã è¡ããŸããã ãŸããã¹ãã³ããã¯ã远å ããŠãæ··ä¹±ããªãããã«ããŸãã
use lazy_static::lazy_static; use spin::Mutex; lazy_static! { pub static ref VGA_WRITER : Mutex<Writer> = Mutex::new(Writer { cursor_position: 0, vga_color: ColorCode::new(Color::LightGray, Color::Black), buffer: unsafe { &mut *(0xC00B8000 as *mut VgaBuffer) } }); }
ãåãã®ããã«ãç»é¢ãããã¡ãŒã¯ç©çã¢ãã¬ã¹0xB8000ã«ããããµã€ãºã¯80x25x2ãã€ãïŒç»é¢ã®å¹
ãšé«ããæåããšã®ãã€ããšå±æ§ïŒè²ãã¡ãã€ãïŒã§ãã ãã§ã«ä»®æ³ã¡ã¢ãªãæå¹ã«ããŠããããããã®ã¢ãã¬ã¹ã«ã¢ã¯ã»ã¹ãããšã¯ã©ãã·ã¥ããããã3 GBã远å ããŸãã ãŸããå®å
šã§ã¯ãªãçã®ãã€ã³ã¿ãéåç
§ããŸãããäœãããŠããã®ãã¯ããã£ãŠããŸãã
ãã®ãã¡ã€ã«ã®è峿·±ãç¹ã¯ããããããWriteræ§é ã®å®è£
ã ãã§ãããã®æ§é ã§ã¯ãæåãé£ç¶ããŠè¡šç€ºã§ããã ãã§ãªããã¹ã¯ããŒã«ãç»é¢äžã®ä»»æã®å Žæãžã®ç§»åããã®ä»ã®æ¥œããæäœãå¯èœã§ãã
VGAã©ã€ã¿ãŒ pub struct Writer { cursor_position: usize, vga_color: ColorCode, buffer: &'static mut VgaBuffer, } impl Writer { pub fn init(&mut self) { let vga_color = self.vga_color; for y in 0..(VGA_HEIGHT - 1) { for x in 0..VGA_WIDTH { self.buffer.chars[y * VGA_WIDTH + x] = ScreenChar { ascii_character: b' ', color_code: vga_color, } } } self.set_cursor_abs(0); } fn set_cursor_abs(&mut self, position: usize) { unsafe { outb(0x3D4, 0x0F); outb(0x3D5, (position & 0xFF) as u8); outb(0x3D4, 0x0E); outb(0x3D4, ((position >> 8) & 0xFF) as u8); } self.cursor_position = position; } pub fn set_cursor(&mut self, x: usize, y: usize) { self.set_cursor_abs(y * VGA_WIDTH + x); } pub fn move_cursor(&mut self, offset: usize) { self.cursor_position = self.cursor_position + offset; self.set_cursor_abs(self.cursor_position); } pub fn get_x(&mut self) -> u8 { (self.cursor_position % VGA_WIDTH) as u8 } pub fn get_y(&mut self) -> u8 { (self.cursor_position / VGA_WIDTH) as u8 } pub fn scroll(&mut self) { for y in 0..(VGA_HEIGHT - 1) { for x in 0..VGA_WIDTH { self.buffer.chars[y * VGA_WIDTH + x] = self.buffer.chars[(y + 1) * VGA_WIDTH + x] } } for x in 0..VGA_WIDTH { let color_code = self.vga_color; self.buffer.chars[(VGA_HEIGHT - 1) * VGA_WIDTH + x] = ScreenChar { ascii_character: b' ', color_code } } } pub fn ln(&mut self) { let next_line = self.get_y() as usize + 1; if next_line >= VGA_HEIGHT { self.scroll(); self.set_cursor(0, VGA_HEIGHT - 1); } else { self.set_cursor(0, next_line) } } pub fn write_byte_at_xy(&mut self, byte: u8, color: ColorCode, x: usize, y: usize) { self.buffer.chars[y * VGA_WIDTH + x] = ScreenChar { ascii_character: byte, color_code: color } } pub fn write_byte_at_pos(&mut self, byte: u8, color: ColorCode, position: usize) { self.buffer.chars[position] = ScreenChar { ascii_character: byte, color_code: color } } pub fn write_byte(&mut self, byte: u8) { if self.cursor_position >= VGA_WIDTH * VGA_HEIGHT { self.scroll(); self.set_cursor(0, VGA_HEIGHT - 1); } self.write_byte_at_pos(byte, self.vga_color, self.cursor_position); self.move_cursor(1); } pub fn write_string(&mut self, s: &str) { for byte in s.bytes() { match byte { 0x20...0xFF => self.write_byte(byte), b'\n' => self.ln(), _ => self.write_byte(0xfe), } } } }
å·»ãæ»ããšãã¯ãã¡ã¢ãªã®ã»ã¯ã·ã§ã³ãç»é¢å¹
ã®ãµã€ãºã ãéæ¹åã«ã³ããŒããæ°ããè¡ã空çœã§åããŸãïŒããããç§ãã¯ãªãŒãã³ã°ãè¡ãæ¹æ³ã§ãïŒã OutbåŒã³åºãã¯ããå°ãè峿·±ãã§ã-I / OããŒããæäœãã以å€ã«ã«ãŒãœã«ãç§»åããããšã¯äžå¯èœã§ãã ãã ããããŒããä»ããå
¥åºåãå¿
èŠãªãããå¥ã®ããã±ãŒãžã§æäŸãããå®å
šãªã©ãããŒã§ã©ãããããŠããŸãã 以äžã®ãã¿ãã¬ã®äžã«ã¢ã»ã³ãã©ãŒã³ãŒãããããŸãã ä»ã®ãšããããããç¥ãã ãã§ååã§ãïŒ
- 座æšã§ã¯ãªãã絶察ã«ãŒãœã«ãªãã»ããã衚瀺ãããŸãã
- äžåºŠã«1ãã€ããã€ã³ã³ãããŒã©ãŒã«åºåã§ããŸã
- 1ãã€ãã®åºåã¯2ã€ã®ã³ãã³ãã§çºçããŸããæåã«ã³ãã³ããã³ã³ãããŒã©ãŒã«æžã蟌ã¿ã次ã«ããŒã¿ãæžã蟌ã¿ãŸãã
- ã³ãã³ãã®ããŒãã¯0x3D4ãããŒã¿ããŒãã¯0x3D5ã§ã
- æåã«ãã³ãã³ã0x0Fã§äœçœ®ã®æäžäœãã€ããå°å·ããæ¬¡ã«ã³ãã³ã0x0Eã§æäžäœãã€ããå°å·ããŸã
out.asmã¹ã¿ãã¯ã§æž¡ããã倿°ãæäœããããšã«æ³šæããŠãã ããã ã¹ã¿ãã¯ã¯ã¹ããŒã¹ã®æåŸããå§ãŸãã颿°ãåŒã³åºããããšãã«ã¹ã¿ãã¯ãã€ã³ã¿ãŒãæžããããããã©ã¡ãŒã¿ãŒããªã¿ãŒã³ãã€ã³ããªã©ãååŸããããã«ãã¹ã¿ãã¯ã®ã¢ã©ã€ã¡ã³ãã«åãããŠåŒæ°ã®ãµã€ãºãESPã¬ãžã¹ã¿ïŒãã®å Žåã¯4ãã€ãïŒã«è¿œå ããå¿
èŠããããŸãã
global writeb global writew global writed section .text writeb: push ebp mov ebp, esp mov edx, [ebp + 8] ;port in stack: 8 = 4 (push ebp) + 4 (parameter port length is 2 bytes but stack aligned 4 bytes) mov eax, [ebp + 8 + 4] ;value in stack - 8 = see ^, 4 = 1 byte value aligned 4 bytes out dx, al ;write byte by port number an dx - value in al mov esp, ebp pop ebp ret writew: push ebp mov ebp, esp mov edx, [ebp + 8] ;port in stack: 8 = 4 (push ebp) + 4 (parameter port length is 2 bytes but stack aligned 4 bytes) mov eax, [ebp + 8 + 4] ;value in stack - 8 = see ^, 4 = 1 word value aligned 4 bytes out dx, ax ;write word by port number an dx - value in ax mov esp, ebp pop ebp ret writed: push ebp mov ebp, esp mov edx, [ebp + 8] ;port in stack: 8 = 4 (push ebp) + 4 (parameter port length is 2 bytes but stack aligned 4 bytes) mov eax, [ebp + 8 + 4] ;value in stack - 8 = see ^, 4 = 1 double word value aligned 4 bytes out dx, eax ;write double word by port number an dx - value in eax mov esp, ebp pop ebp ret
ã»ã°ã¡ã³ãèšå®
ç§ãã¡ã¯æãäžå¯è§£ã§ããããåæã«æãç°¡åãªãããã¯ã«å°éããŸããã åã®èšäºã§è¿°ã¹ãããã«ãã¡ã¢ãªå
ã®ããŒãžãšã»ã°ã¡ã³ãã®æ§æãé ã®äžã«æ··åšããŠãããããããŒãžããŒãã«ã®ã¢ãã¬ã¹ãGDTRã«ããŒãããŠé ãã€ãã¿ãŸããã ååãªè³æãèªã¿ããããæ¶åããŠå®çŸããã®ã«æ°ã¶æããããŸããã ããŒã¿ãŒã¢ãã«ã®æç§æžã¢ã»ã³ãã©ãŒã®ç ç²è
ã«ãªã£ããããããŸããã ã€ã³ãã«8086ã®ã»ã°ã¡ã³ããŒã·ã§ã³ã説æããIBM PCã®èšèªãšããã°ã©ãã³ã°ïŒçŽ æŽãããæ¬ã§ãïŒïŒããããã®æ¥œããæä»£ã«ã20ãããã¢ãã¬ã¹ã®äžäœ16ããããã»ã°ã¡ã³ãã¬ãžã¹ã¿ã«ããŒããããããã¡ã¢ãªå
ã®ã¢ãã¬ã¹ã§ããã ä¿è·ã¢ãŒãã®i286ããå§ããŠããã¹ãŠãå®å
šã«ééã£ãŠãããšããã®ã¯æ®é
·ãªå€±æã§ããããšã倿ããŸããã
ãã®ãããå€ãããã°ã©ã ã¯640 KBãè¶
ããŠãã1 MBã®ã¡ã¢ãªãè¶
ããããšãã§ãããããx86ã¯ã»ã°ã¡ã³ãåãããã¡ã¢ãªã¢ãã«ããµããŒãããŠãããšããçè«ããããŸãã
ããã°ã©ãã¯ãå®è¡å¯èœã³ãŒããé
眮ããæ¹æ³ãããŒã¿ãé
眮ããæ¹æ³ãããã³å®å
šæ§ãç¶æããæ¹æ³ã«ã€ããŠèããå¿
èŠããããŸããã ããŒãžç·šæã®åºçŸã«ãããã»ã°ã¡ã³ãåãããç·šæã¯äžèŠã«ãªããŸããããäºææ§ãšä¿è·ïŒã«ãŒãã«ç©ºéãšãŠãŒã¶ãŒç©ºéã®ç¹æš©ã®åé¢ïŒã®ç®çã®ããã«æ®ã£ãããããããªãã§ã¯ã©ãã«ããããŸããã ç¹æš©ã¬ãã«ã0æªæºã®å Žåãäžéšã®ããã»ããµåœä»€ã¯çŠæ¢ãããŠãããããã°ã©ã ãšã«ãŒãã«ã»ã°ã¡ã³ãéã®ã¢ã¯ã»ã¹ã«ããã»ã°ã¡ã³ããŒã·ã§ã³ãšã©ãŒãçºçããŸãã
ã¢ãã¬ã¹å€æã«ã€ããŠããäžåºŠïŒã§ããã°æåŸã«ïŒãããŸããã
è¡ã¢ãã¬ã¹[0x08ïŒ0xFFFFFFFF]->ã»ã°ã¡ã³ãã®èš±å¯ã確èª0x08->ä»®æ³ã¢ãã¬ã¹[0xFFFFFFFF]->ããŒãžããŒãã«+ TLB->ç©çã¢ãã¬ã¹[0xAAAAFFFF]
ã»ã°ã¡ã³ãã¯ããã»ããµå
ã§ã®ã¿äœ¿çšãããç¹å¥ãªã»ã°ã¡ã³ãã¬ãžã¹ã¿ïŒCSãSSãDSãESãFSãGSïŒã«æ ŒçŽãããã³ãŒããå®è¡ããŠå¶åŸ¡ã転éããæš©éã確èªããããã«ã®ã¿äœ¿çšãããŸãã ãã®ããããŠãŒã¶ãŒç©ºéããã«ãŒãã«é¢æ°ãååŸããŠåŒã³åºãããšã¯ã§ããŸããã èšè¿°åã0x18ã®ã»ã°ã¡ã³ãïŒç§ãæã£ãŠãããã®ã¯ç°ãªããŸãïŒã«ã¯ã¬ãã«3ã®æš©å©ããããèšè¿°åã0x08ã®ã»ã°ã¡ã³ãã«ã¯ã¬ãã«0ã®æš©å©ããããŸãã jmp 0x08çµç±ã®æš©å©ïŒ[EAX]ãããã©ãããã²ãŒããå²ã蟌ã¿ãªã©ã®ä»ã®ã¡ã«ããºã ã䜿çšãã矩åããããŸãã
ã»ã°ã¡ã³ããšãã®ã¿ã€ãïŒã³ãŒããããŒã¿ãã©ããŒãã²ãŒãïŒã¯ãã°ããŒãã«èšè¿°åããŒãã«GDTã«èšè¿°ãããŠããå¿
èŠãããããã®ä»®æ³ã¢ãã¬ã¹ãšãµã€ãºã¯GDTRã¬ãžã¹ã¿ã«ããŒããããŸãã ã»ã°ã¡ã³ãéãé·ç§»ãããšãïŒç°¡åã«ããããã«ãçŽæ¥é·ç§»ãå¯èœã§ãããšæ³å®ããŠããŸãïŒãjmp 0x08ïŒ[EAX]åœä»€ãåŒã³åºãå¿
èŠããããŸãã ãªãã»ããïŒã»ã¬ã¯ã¿ãŒïŒã¯CSã¬ãžã¹ã¿ãŒã«ããŒãããã察å¿ããèšè¿°åã¯ããã»ããµãŒã®ã·ã£ããŒã¬ãžã¹ã¿ãŒã«ããŒããããŸãã åèšè¿°åã¯8ãã€ãæ§é ã§ãã ååã«ææžåãããŠããããã®èª¬æã¯OSDevãšIntelã®ããã¥ã¡ã³ãã®äž¡æ¹ã«ãããŸãïŒæåã®èšäºãåç
§ïŒã
ãŸãšããŸãã GDTãåæåããŠjmp 0x08ïŒ[EAX]ãã©ã³ãžã·ã§ã³ãå®è¡ãããšãããã»ããµãŒã®ã¹ããŒã¿ã¹ã¯æ¬¡ã®ããã«ãªããŸãã
- GDTRã«ã¯ä»®æ³ GDTã¢ãã¬ã¹ãå«ãŸããŠããŸã
- CSã«ã¯å€0x08ãå«ãŸããŸã
- ã¢ãã¬ã¹[GDTR + 0x08]ãžã®ãã³ãã«ãã·ã£ããŠã¬ãžã¹ã¿CSããã³ããŒãããŸããã
- EIPã¬ãžã¹ã¿ã«ã¯ãEAXã¬ãžã¹ã¿ããã®ã¢ãã¬ã¹ãå«ãŸããŠããŸã
ãŒãèšè¿°åã¯åžžã«åæåãããŠããªãå¿
èŠããããã¢ã¯ã»ã¹ã¯çŠæ¢ãããŠããŸãã ãã«ãã¹ã¬ããã«ã€ããŠèª¬æãããšãã«ãTSSèšè¿°åãšãã®æå³ã«ã€ããŠè©³ãã説æããŸãã GDTããŒãã«ã¯æ¬¡ã®ããã«ãªããŸãã
extern { fn load_gdt(base: *const GdtEntry, limit: u16); } pub unsafe fn setup_gdt() { GDT[5].set_offset((&super::tss::TSS) as *const _ as u32); GDT[5].set_limit(core::mem::size_of::<super::tss::Tss>() as u32); let gdt_ptr: *const GdtEntry = GDT.as_ptr(); let limit = (GDT.len() * core::mem::size_of::<GdtEntry>() - 1) as u16; load_gdt(gdt_ptr, limit); } static mut GDT: [GdtEntry; 7] = [
ãããŠãããã§åæåã«ã€ããŠèª¬æããŸããã GDTã¢ãã¬ã¹ãšãµã€ãºã®ããŒãã¯ã2ã€ã®ãã£ãŒã«ãã®ã¿ãå«ãå¥ã®æ§é ãä»ããŠè¡ãããŸãã ãã®æ§é äœã®ã¢ãã¬ã¹ã¯ãlgdtã³ãã³ãã«æž¡ãããŸãã ããŒã¿ã»ã°ã¡ã³ãã¬ãžã¹ã¿ã§ããªãã»ãã0x10ã§æ¬¡ã®èšè¿°åãããŒãããŸãã
global load_gdt section .text gdtr dw 0 ; For limit storage dd 0 ; For base storage load_gdt: mov eax, [esp + 4] mov [gdtr + 2], eax mov ax, [esp + 8] mov [gdtr], ax lgdt [gdtr] jmp 0x08:.reload_CS .reload_CS: mov ax, 0x10 ; 0x10 points at the new data selector mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov ax, 0x28 ltr ax ret
ããããã°ããã¹ãŠãå°ãç°¡åã«ãªããŸãããããã»ã©é¢çœããªãã§ãããã
äžæ
å®éãã³ã¢ãšå¯Ÿè©±ããïŒå°ãªããšãããŒããŒãã§ã¯ãªãã¯ãããã®ã確èªããïŒæ©äŒãç§ãã¡ã«äžããŸãã ãããè¡ãã«ã¯ãå²ã蟌ã¿ã³ã³ãããŒã©ãŒãåæåããå¿
èŠããããŸãã
ã³ãŒãã¹ã¿ã€ã«ã«é¢ããåæ
çãªäœè«ã
ã³ãã¥ããã£ãç¹ã«Philip Oppermanã®åªåã®ãããã§ãx86å²ã蟌ã¿åŒã³åºãèŠçŽãRustã«è¿œå ãããŸãããããã«ãããiretãå®è¡ããå²ã蟌ã¿ãã³ãã©ãŒãäœæã§ããŸãã ããããã¢ã»ã³ãã©ãŒãšRustãå¥ã
ã®ãã¡ã€ã«ã«åé¢ããããšã決å®ããããããã®ã«ãŒãã䜿çšããªãããšãæèããŠæ±ºå®ããŸããã ã¯ããã¹ã¿ãã¯ã¡ã¢ãªãäžåœã«äœ¿çšããŠããŸããããã¯æ¿ç¥ããŠããŸãããããã§ããã¬ãŒããŒã§ãã ç§ã®å²ã蟌ã¿ãã³ãã©ãŒã¯ã¢ã»ã³ãã©ãŒã§èšè¿°ãããŠãããRustã§èšè¿°ããããã®ãšã»ãŒåãå²ã蟌ã¿ãã³ãã©ãŒãåŒã³åºããŸãã ãã®äºå®ãåãå
¥ããŠãçããããŠãã ããã
äžè¬ã«ãå²ã蟌ã¿ã®åæåããã»ã¹ã¯GDTã®åæåãšäŒŒãŠããŸãããçè§£ããããã§ãã äžæ¹ãå€ãã®çµ±äžãããã³ãŒããå¿
èŠã§ãã Redox OSã®éçºè
ã¯ãèšèªã®ãã¹ãŠã®æ¥œãã¿ã䜿çšããŠçŸããæ±ºå®ãäžããŸãããç§ã¯ãé¡ã«ãè¡ã£ãŠãã³ãŒãã®è€è£œãèš±å¯ããããšã«ããŸããã
x86ã®èŠåã«ãããšãäžæã¯ãããŸãããäŸå€çãªç¶æ³ããããŸãã ãã®ã³ã³ããã¹ãã§ã¯ãç§ãã¡ã®èšå®ã¯å®è³ªçã«åãã§ãã å¯äžã®éãã¯ãäŸå€ãã¹ããŒããããšãã¹ã¿ãã¯ã«è¿œå æ
å ±ãå«ãŸããããšãããããšã§ãã ããšãã°ãç§ã¯ããã䜿çšããŠãæãæäœãããšãã«ããŒãžã®äžè¶³ãåŠçããŸãïŒãã ãããã¹ãŠã«æéããããŸãïŒã å²ã蟌ã¿ãšäŸå€ã®äž¡æ¹ãåãããŒãã«ããåŠçãããããããŠãŒã¶ãŒãšç§ãèšå
¥ããå¿
èŠããããŸãã PICïŒProgrammable Interrupt ControllerïŒãããã°ã©ã ããããšãå¿
èŠã§ãã APICããããŸããããŸã ããããŸããã
PICã§ã®äœæ¥ã«é¢ããŠã¯ããããã¯ãŒã¯äžã«å€ãã®äŸããããŸãã®ã§ãPICã§ã®äœæ¥ã«ã€ããŠã¯ããŸãã³ã¡ã³ãããŸããã ã¢ã»ã³ãã©ãŒã®ãã³ãã©ãŒããå§ããŸãã ãããã¯ãã¹ãŠå®å
šã«åããªã®ã§ãã¹ãã€ã©ãŒã®ã³ãŒããåé€ããŸãã
IRQ global irq0 global irq1 ...... global irq14 global irq15 extern kirq0 extern kirq1 ...... extern kirq14 extern kirq15 section .text irq0: pusha call kirq0 popa iret irq1: pusha call kirq1 popa iret ...... irq14: pusha call kirq14 popa iret irq15: pusha call kirq15 popa iret
ã芧ã®ãšãããRust颿°ã®åŒã³åºãã¯ãã¹ãŠåºå¥ãšå©äŸ¿æ§ã®ããã«ãkããã¬ãã£ãã¯ã¹ã§å§ãŸããŸãã äŸå€åŠçã¯ãŸã£ããåãã§ãã ã¢ã»ã³ãã©ãŒé¢æ°ã®å Žåãæ¥é èŸãeããéžæãããRustã®å ŽåãkããéžæãããŸãã ããŒãžãã©ãŒã«ããã³ãã©ãŒã¯ç°ãªããŸãããããã«ã€ããŠ-ã¡ã¢ãªç®¡çã«é¢ããæ³šæäºé
ã«èšèŒãããŠããŸãã
äŸå€ global e0_zero_divide global e1_debug ...... global eE_page_fault ...... global e14_virtualization global e1E_security extern k0_zero_divide extern k1_debug ...... extern kE_page_fault ...... extern k14_virtualization extern k1E_security section .text e0_zero_divide: pushad call k0_zero_divide popad iret e1_debug: pushad call k1_debug popad iret ...... 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 ...... e14_virtualization: pushad call k14_virtualization popad iret e1E_security: pushad call k1E_security popad iret
ã¢ã»ã³ãã©ãŒãã³ãã©ãŒã宣èšããŸãã
extern { fn load_idt(base: *const IdtEntry, limit: u16); fn e0_zero_divide(); fn e1_debug(); ...... fn e14_virtualization(); fn e1E_security(); fn irq0(); fn irq1(); ...... fn irq14(); fn irq15(); }
äžèšã§åŒã³åºãRustãã³ãã©ãŒãå®çŸ©ããŸãã ããŒããŒããäžæããã«ã¯ãåä¿¡ããã³ãŒãã衚瀺ããã ãã§ãããŒã0x60ããååŸããããšã«æ³šæããŠãã ãã-ããã¯ãããŒããŒããæãåçŽãªã¢ãŒãã§åäœããæ¹æ³ã§ãã å°æ¥çã«ã¯ããããæ¬æ Œçãªãã©ã€ããŒã«å€ãããšæããŸãã åå²ã蟌ã¿ã®åŸã0x20ã®åŠççµäºã®ä¿¡å·ãã³ã³ãããŒã©ãŒã«åºåããå¿
èŠããããŸããããã¯éèŠã§ãïŒ ããããªããšãå²ã蟌ã¿ãçºçããªããªããŸãã
#[no_mangle] pub unsafe extern fn kirq0() {
IDTããã³PICã®åæåã PICãšãã®åãããã³ã°ã«ã€ããŠãOSDevã§å§ãŸãã¢ããã¥ã¢ãµã€ãã§çµãã詳现床ã®ç°ãªããã¥ãŒããªã¢ã«ã倿°èŠã€ãããŸããã ããã°ã©ãã³ã°æé ã¯äžå®ã®æäœã·ãŒã±ã³ã¹ãšäžå®ã®ã³ãã³ãã§åäœããããããã以äžèª¬æããããšãªããã®ã³ãŒããæäŸããŸãã , 0x20-0x2F , 0x20 0x28, 16 IDT.
unsafe fn setup_pic(pic1: u8, pic2: u8) {
IDTR GDTR â . STI â â , , ASCII- -.
global load_idt section .text idtr dw 0 ; For limit storage dd 0 ; For base storage load_idt: mov eax, [esp + 4] mov [idtr + 2], eax mov ax, [esp + 8] mov [idtr], ax lidt [idtr] sti ret
ããšãã
ããŠããã®èšäºã¯éåžžã«èšå€§ã§ããããšã倿ãããããæ¬¡åã¯ã¡ã¢ãªã®åæåãšç®¡çã«ã€ããŠèª¬æããŸããsetup_pd颿°ãã³ãŒãã®ç«¯ã«ããã¯ããŸããããæ¬¡ã®åŒã³åºãã®ããã«ãã®ç®çãšããã€ã¹ã«é¢ããè©±ãæ®ããŸããã³ã³ãã³ãã®æ¹åç¹ãã³ãŒãã«æžãããšããããããªãã§ãã ããã
ãœãŒã¹ã³ãŒãã¯ãŸã GitLabã§å
¥æã§ããŸãã
ãæž
èŽããããšãããããŸããïŒ
UPDïŒããŒã3