Compare commits

...

9 Commits

Author SHA1 Message Date
ecad19bb5e fix warn
All checks were successful
Check / Build ISO (nightly-2025-04-27) (push) Successful in 43s
Release ISO / release (push) Successful in 57s
2025-08-22 12:29:01 +00:00
94cbcd6a1f io bitmap
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 45s
2025-08-22 12:18:50 +00:00
de21059b53 add pic
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 44s
2025-08-22 10:06:38 +00:00
7fb000f5ce intr subscriber
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 46s
2025-08-22 09:51:20 +00:00
fc93be3043 add CR handler
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 44s
2025-08-22 09:07:00 +00:00
4a44cdea8d qual, cr
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 45s
2025-08-22 09:01:32 +00:00
a0a204b43c cr vmexit
Some checks failed
Check / Build ISO (nightly-2025-04-27) (push) Failing after 46s
2025-08-22 08:34:41 +00:00
52098ee0e9 ignore img
All checks were successful
Check / Build ISO (nightly-2025-04-27) (push) Successful in 1m17s
2025-08-22 15:09:06 +09:00
26db917d24 wip 2025-08-22 15:07:05 +09:00
22 changed files with 1210 additions and 41 deletions

1
.gitignore vendored
View File

@ -2,5 +2,6 @@ nel_os_bootloader/target
nel_os_kernel/target
nel_os_common/target
nel_os_bootloader/fat.img
nel_os_bootloader/myOSimage.img
nel_os_bootloader/iso/
nel_os_bootloader/nel_os.iso

Binary file not shown.

BIN
nel_os_bootloader/OVMF.fd Normal file

Binary file not shown.

408
nel_os_bootloader/bochs.out Normal file
View File

@ -0,0 +1,408 @@
00000000000i[ ] Bochs x86 Emulator 3.0.devel
00000000000i[ ] Built from GitHub snapshot after release 3.0
00000000000i[ ] Compiled on Aug 21 2025 at 19:02:35
00000000000i[ ] System configuration
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
00000000000i[ ] A20 line support: yes
00000000000i[ ] IPS is set to 4000000
00000000000i[ ] CPU configuration
00000000000i[ ] SMP support: no
00000000000i[ ] Using pre-defined CPU configuration: corei7_sandy_bridge_2600k
00000000000i[ ] Optimization configuration
00000000000i[ ] RepeatSpeedups support: no
00000000000i[ ] Fast function calls: no
00000000000i[ ] Handlers Chaining speedups: no
00000000000i[ ] Devices configuration
00000000000i[ ] PCI support: i440FX i430FX i440BX
00000000000i[ ] Networking: no
00000000000i[ ] Sound support: no
00000000000i[ ] USB support: no
00000000000i[ ] VGA extension support: vbe
00000000000i[IMG ] Disk image modules
00000000000i[IMG ] flat concat sparse dll growing undoable volatile vmware3
00000000000i[IMG ] vmware4 vbox vpc vvfat
00000000000i[MEM0 ] allocated memory at 0x7d9025bdd010. after alignment, vector=0x7d9025bde000, block_size = 128K
00000000000i[MEM0 ] 256.00MB
00000000000i[MEM0 ] mem block size = 0x00020000, blocks=2048
00000000000i[MEM0 ] rom at 0xffe00000/2097152 ('./OVMF-pure-efi.fd')
00000000000i[CPU0 ] initialized CPU model corei7_sandy_bridge_2600k
00000000000i[DEV ] will paste characters every 100 iodev timer ticks
00000000000i[PLUGIN] init_dev of 'pci' plugin device by virtual method
00000000000i[DEV ] i440FX PMC present at device 0, function 0
00000000000i[PLUGIN] init_dev of 'pci2isa' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method
00000000000i[CMOS ] Using local time for initial clock
00000000000i[CMOS ] Setting initial clock to: Fri Aug 22 15:03:30 2025 tz=utc (time0=1755875010)
00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method
00000000000i[DMA ] channel 4 used by cascade
00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'pit' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'vga' plugin device by virtual method
00000000000i[MEM0 ] Register memory access handlers: 0x0000000a0000 - 0x0000000bffff
00000000000i[VGA ] interval=100000, mode=realtime
00000000000i[VGA ] Setting VGA update interval to 100000 (10.0 Hz)
00000000000i[VGA ] VSYNC using standard mode
00000000000i[BXVGA ] VBE Bochs Display Extension Enabled (16 MB)
00000000000i[DEV ] PCI slot #1 used by plugin 'pcivga'
00000000000i[DEV ] Experimental PCI VGA present at device 2, function 0
00000000000i[BXVGA ] loaded PCI ROM '/usr/local/share/bochs/VGABIOS-lgpl-latest-cirrus.bin' (size=33792 / PCI=64k)
00000000000i[PLUGIN] init_dev of 'floppy' plugin device by virtual method
00000000000i[DMA ] channel 2 used by Floppy Drive
00000000000i[FLOPPY] Using boot sequence disk, none, none
00000000000i[FLOPPY] Floppy boot signature check is enabled
00000000000i[PLUGIN] init_dev of 'acpi' plugin device by virtual method
00000000000i[DEV ] ACPI Controller present at device 1, function 3
00000000000i[PLUGIN] init_dev of 'hpet' plugin device by virtual method
00000000000i[HPET ] initializing HPET
00000000000i[MEM0 ] Register memory access handlers: 0x0000fed00000 - 0x0000fed003ff
00000000000i[PLUGIN] init_dev of 'ioapic' plugin device by virtual method
00000000000i[IOAPIC] initializing I/O APIC
00000000000i[MEM0 ] Register memory access handlers: 0x0000fec00000 - 0x0000fec00fff
00000000000i[IOAPIC] IOAPIC enabled (base address = 0xfec00000)
00000000000i[PLUGIN] init_dev of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method
00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1
00000000000i[PLUGIN] init_dev of 'harddrv' plugin device by virtual method
00000000000i[HD ] HD on ata0-0: './myOSimage.img', 'flat' mode
00000000000i[IMG ] hd_size: 67108864
00000000000i[HD ] ata0-0: autodetect geometry: CHS=130/16/63 (sector size=512)
00000000000i[HD ] ata0-0: extra data outside of CHS address range
00000000000i[HD ] translation on ata0-0 set to 'none'
00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'speaker' plugin device by virtual method
00000000000e[PCSPK ] Failed to open /dev/console: 許可がありません
00000000000e[PCSPK ] Deactivating beep on console
00000000000i[PLUGIN] init_dev of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] init_dev of 'parallel' plugin device by virtual method
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
00000000000i[PLUGIN] init_dev of 'serial' plugin device by virtual method
00000000000i[SER ] com1 at 0x03f8 irq 4 (mode: null)
00000000000i[PLUGIN] init_dev of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] register state of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] register state of 'dma' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pit' plugin device by virtual method
00000000000i[PLUGIN] register state of 'vga' plugin device by virtual method
00000000000i[PLUGIN] register state of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] register state of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] register state of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] register state of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] register state of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] register state of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] register state of 'serial' plugin device by virtual method
00000000000i[PLUGIN] register state of 'iodebug' plugin device by virtual method
00000000000i[PLUGIN] register state of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] register state of 'hpet' plugin device by virtual method
00000000000i[PLUGIN] register state of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] register state of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] register state of 'pci_ide' plugin device by virtual method
00000000000i[PLUGIN] register state of 'harddrv' plugin device by virtual method
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00000000000i[CPU0 ] cpu hardware reset
00000000000i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
00000000000i[CPU0 ] CPUID[0x00000000]: 0000000d 756e6547 6c65746e 49656e69
00000000000i[CPU0 ] CPUID[0x00000001]: 000206a7 00010800 079ae3bf afebfbff
00000000000i[CPU0 ] CPUID[0x00000002]: 76035a01 00f0b0ff 00000000 00ca0000
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000004]: 1c004121 01c0003f 0000003f 00000000
00000000000i[CPU0 ] CPUID[0x00000005]: 00000040 00000040 00000003 00001120
00000000000i[CPU0 ] CPUID[0x00000006]: 00000077 00000002 0000000b 00000000
00000000000i[CPU0 ] CPUID[0x00000007]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000008]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x00000009]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] WARNING: Architectural Performance Monitoring is not implemented
00000000000i[CPU0 ] CPUID[0x0000000a]: 07300803 00000000 00000000 00000603
00000000000i[CPU0 ] CPUID[0x0000000b]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x0000000c]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x0000000d]: 00000003 00000240 00000240 00000000
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000001]: 00000000 00000000 00000001 28100000
00000000000i[CPU0 ] CPUID[0x80000002]: 20202020 49202020 6c65746e 20295228
00000000000i[CPU0 ] CPUID[0x80000003]: 65726f43 294d5428 2d376920 30303632
00000000000i[CPU0 ] CPUID[0x80000004]: 5043204b 20402055 30342e33 007a4847
00000000000i[CPU0 ] CPUID[0x80000005]: 00000000 00000000 00000000 00000000
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 00000000 01006040 00000000
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000100
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000200 00000000 00000000
00000000000i[CPU0 ] CPU Features supported:
00000000000i[CPU0 ] x87
00000000000i[CPU0 ] 486ni
00000000000i[CPU0 ] pentium_ni
00000000000i[CPU0 ] p6ni
00000000000i[CPU0 ] mmx
00000000000i[CPU0 ] debugext
00000000000i[CPU0 ] vme
00000000000i[CPU0 ] pse
00000000000i[CPU0 ] pae
00000000000i[CPU0 ] pge
00000000000i[CPU0 ] mtrr
00000000000i[CPU0 ] pat
00000000000i[CPU0 ] sysenter_sysexit
00000000000i[CPU0 ] clflush
00000000000i[CPU0 ] sse
00000000000i[CPU0 ] sse2
00000000000i[CPU0 ] sse3
00000000000i[CPU0 ] ssse3
00000000000i[CPU0 ] sse4_1
00000000000i[CPU0 ] sse4_2
00000000000i[CPU0 ] popcnt
00000000000i[CPU0 ] mwait
00000000000i[CPU0 ] longmode
00000000000i[CPU0 ] lm_lahf_sahf
00000000000i[CPU0 ] nx
00000000000i[CPU0 ] cmpxhg16b
00000000000i[CPU0 ] rdtscp
00000000000i[CPU0 ] xsave
00000000000i[CPU0 ] xsaveopt
00000000000i[CPU0 ] aes_pclmulqdq
00000000000i[CPU0 ] vmx
00000000000i[CPU0 ] xapic
00000000000i[CPU0 ] pcid
00000000000i[CPU0 ] tsc_deadline
00000000000i[PLUGIN] reset of 'pci' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci2isa' plugin device by virtual method
00000000000i[PLUGIN] reset of 'cmos' plugin device by virtual method
00000000000i[PLUGIN] reset of 'dma' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pit' plugin device by virtual method
00000000000i[PLUGIN] reset of 'vga' plugin device by virtual method
00000000000i[DDC ] Using default EDID for resolution 1920x1200
00000000000i[PLUGIN] reset of 'floppy' plugin device by virtual method
00000000000i[PLUGIN] reset of 'acpi' plugin device by virtual method
00000000000i[PLUGIN] reset of 'hpet' plugin device by virtual method
00000000000i[PLUGIN] reset of 'ioapic' plugin device by virtual method
00000000000i[PLUGIN] reset of 'keyboard' plugin device by virtual method
00000000000i[PLUGIN] reset of 'pci_ide' plugin device by virtual method
00000000000i[PLUGIN] reset of 'harddrv' plugin device by virtual method
00000000000i[PLUGIN] reset of 'unmapped' plugin device by virtual method
00000000000i[PLUGIN] reset of 'biosdev' plugin device by virtual method
00000000000i[PLUGIN] reset of 'speaker' plugin device by virtual method
00000000000i[PLUGIN] reset of 'extfpuirq' plugin device by virtual method
00000000000i[PLUGIN] reset of 'parallel' plugin device by virtual method
00000000000i[PLUGIN] reset of 'serial' plugin device by virtual method
00000000000i[PLUGIN] reset of 'iodebug' plugin device by virtual method
00000055493i[ACPI ] new PM base address: 0xb000
00000055938i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056097i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056270i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056429i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056598i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056757i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000056929i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057088i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057261i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057420i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057589i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057748i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000057919i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00000058078i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699010i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699261i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699420i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699586i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699747i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404699909e[CPU0 ] RDMSR: Unknown register 0x17
00404701729i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404701888i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702065i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702224i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702404i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702563i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702739i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404702898i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404703078i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404703237i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404703414i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404703573i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404706952i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707111i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707287i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707446i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707627i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707786i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404707962i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404708121i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404708293i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404708452i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404708665i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404708836i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404749196i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404749367i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404750562i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404750733i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404953225i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404955765i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404956646i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404957662i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404957821i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404957987i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404958148i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404959043i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404959921i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404960937i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404961096i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404961262i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404961423i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00404962673i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455692544i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455721201i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455721452i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455721612i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455721802i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455721963i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455722125e[CPU0 ] RDMSR: Unknown register 0x17
00455727961i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455728121i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455728322i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455728482i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455728686i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455728846i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729046i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729206i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729410i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729570i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729771i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455729931i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455731779i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455731939i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455732129i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455732290i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455733787i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455733947i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455734137i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00455734298i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461046195i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461046350i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461046524i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461046679i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047124i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047279i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047448i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047603i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047777i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047932i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461047952i[APIC0 ] set timer divide factor to 1
00461048098i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461048253i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461048427i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461048582i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461048753i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461048908i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461049074i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461049229i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461049402i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00461049557i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00471049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00471049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00477485335e[CMOS ] write to control register 0x0d ignored (read-only)
00481049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00481049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00491049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00491049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00501049476i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00501049631i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00511049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00511049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00521049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00521049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00531049476i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00531049631i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00541049476i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00541049631i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00550634745i[PIDE ] BAR #4: i/o base address = 0xc000
00550635289i[MEM0 ] Register memory access handlers: 0x000080000000 - 0x000080ffffff
00550635289i[BXVGA ] BAR #0: mem base address = 0x80000000
00550637278i[MEM0 ] Register memory access handlers: 0x000081000000 - 0x00008100ffff
00550637278i[BXVGA ] new ROM address = 0x81000000
00551049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00551049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00556732034i[SER ] com1: FIFO enabled
00558548658i[SER ] com1: FIFO enabled
00561049475i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00561049630i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00562088041i[KBD ] Switched to scancode set 2
00571052468i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00571052623i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00581052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00581052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00581767851i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0a
00581767938i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x0a
00581768025i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b
00581768112i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x0b
00591052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00591052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00601052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00601052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00611053746i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00611053901i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00621053540i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00621053695i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00631052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00631052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00641052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00641052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00651052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00651052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00661053540i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00661053695i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00671052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00671052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00681052467i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00681052622i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00691053746i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00691053901i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00701053540i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00701053695i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00711053746i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00711053901i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00721052468i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00721052623i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00731052468i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00731052623i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00741058328i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00741058483i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00751053746i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00751053901i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00761053540i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00761053695i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00764170096i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00764170251i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00764170425i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
00764170580i[CPU0 ] RDMSR: Read 00000000:fee00900 from MSR_APICBASE
02367208064p[IOAPIC] >>PANIC<< I/O APIC read at address 0x0000fec00008 spans 32-bit boundary !
02367208064i[CPU0 ] CPU is in long mode (active)
02367208064i[CPU0 ] CS.mode = 64 bit
02367208064i[CPU0 ] SS.mode = 64 bit
02367208064i[CPU0 ] EFER = 0x00000d00: ffxsr NXE LMA LME sce
02367208064i[CPU0 ] XCR0=0x00000001: tiledata tilecfg hwp lbr uintr hdc cet_s cet_u pasid pkru pt hi_zmm zmm_hi256 opmask bndcfg bndregs ymm sse FPU
02367208064i[CPU0 ] | RAX=0000000000000000 RBX=0000000000232188
02367208064i[CPU0 ] | RCX=ffffffffffffffff RDX=00000000fec00000
02367208064i[CPU0 ] | RSP=0000000000232060 RBP=000000000fd7e518
02367208064i[CPU0 ] | RSI=ffffffffffffffff RDI=0000000000232188
02367208064i[CPU0 ] | R8=0000000000000000 R9=0000000000000001
02367208064i[CPU0 ] | R10=0000000000000000 R11=0000000000000002
02367208064i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
02367208064i[CPU0 ] | R14=00000000002320c0 R15=00000000001297e0
02367208064i[CPU0 ] | EFLAGS=00000087: id vip vif ac vm rf nt IOPL=0 of df if tf SF zf af PF CF
02367208064i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
02367208064i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 0
02367208064i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
02367208064i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
02367208064i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
02367208064i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
02367208064i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
02367208064i[CPU0 ] | MSR_FS_BASE:0000000000000000
02367208064i[CPU0 ] | MSR_GS_BASE:0000000000000000
02367208064i[CPU0 ] | RIP=0000000000110ed5 (0000000000110ed0)
02367208064i[CPU0 ] | CR0=0x80010033: PG cd nw ac WP NE ET ts em MP PE
02367208064i[CPU0 ] | CR2=0x0000000000000000
02367208064i[CPU0 ] | CR3=0x000000000fa01000
02367208064i[CPU0 ] | CR4=0x00000668: lass uintr pks cet pke smap smep keylock osxsave pcid fsgsbase smx vmx la57 umip OSXMMEXCPT OSFXSR pce pge MCE PAE pse DE tsd pvi vme
02367208064i[CPU0 ] 0x0000000000110ed0>> mov rsi, qword ptr ds:[r13+rdx+8] : 498B741508
02367208064i[CMOS ] Last time: 1755875601 tz=utc (Fri Aug 22 15:13:21 2025)
02367208064i[ ] restoring default signal behavior
02367208064i[SIM ] quit_sim called with exit code 1

20
nel_os_bootloader/bochsrc Normal file
View File

@ -0,0 +1,20 @@
# ---- 画面/入力 ----
display_library: sdl2
vga: extension=cirrus
pci: enabled=1, chipset=i440fx, slot1=pcivga
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus.bin
romimage: file="./OVMF-pure-efi.fd", address=0x0, options=none
# ---- メモリ/CPU ----
memory: guest=256
cpu: count=1, model=corei7_sandy_bridge_2600k, reset_on_triple_fault=1
# ---- ストレージUEFI ESP を作った “本物のディスク” ----
ata0: enabled=1
ata0-master: type=disk, mode=flat, path="./myOSimage.img", status=inserted
boot: disk
# ---- ログ ----
log: bochs.out

Binary file not shown.

View File

Binary file not shown.

View File

@ -131,9 +131,20 @@ fn load_elf(bin: Box<[u8]>) -> u64 {
elf.entry
}
fn get_frame_buffer() -> gop::FrameBuffer {
let gop_handle = uefi::boot::get_handle_for_protocol::<GraphicsOutput>().unwrap();
let mut gop = boot::open_protocol_exclusive::<GraphicsOutput>(gop_handle).unwrap();
fn get_frame_buffer() -> Option<gop::FrameBuffer> {
let gop_handle = if let Ok(gop_handle) = uefi::boot::get_handle_for_protocol::<GraphicsOutput>()
{
gop_handle
} else {
println!("GraphicsOutput protocol not found");
return None;
};
let mut gop = if let Ok(gop) = boot::open_protocol_exclusive::<GraphicsOutput>(gop_handle) {
gop
} else {
println!("Failed to open GraphicsOutput protocol");
return None;
};
let info = gop.current_mode_info();
let (width, height) = info.resolution();
@ -141,7 +152,7 @@ fn get_frame_buffer() -> gop::FrameBuffer {
let stride = info.stride();
let pixel_format = info.pixel_format();
gop::FrameBuffer {
Some(gop::FrameBuffer {
frame_buffer,
width,
height,
@ -151,15 +162,15 @@ fn get_frame_buffer() -> gop::FrameBuffer {
PixelFormat::Bgr => gop::PixelFormat::Bgr,
format => panic!("Unsupported pixel_format: {:?}", format),
},
}
})
}
fn get_rsdp() -> u64 {
fn get_rsdp() -> Option<u64> {
uefi::system::with_config_table(move |c| {
c.iter()
.find(|config| config.guid == uefi::table::cfg::ACPI_GUID)
.map(|config| config.address as u64)
.expect("Failed to find RSDP in config table")
.or(None)
})
}

View File

@ -0,0 +1,6 @@
#!/bin/sh
cargo b -r
sudo mount /dev/loop0 /mnt
sudo cp ./target/x86_64-unknown-uefi/release/nel_os_bootloader.efi /mnt/EFI/BOOT/BOOTX64.EFI
sudo sync
sudo umount /mnt

View File

@ -7,8 +7,8 @@ pub mod memory;
pub struct BootInfo {
pub usable_memory: UsableMemory,
pub frame_buffer: FrameBuffer,
pub rsdp: u64,
pub frame_buffer: Option<FrameBuffer>,
pub rsdp: Option<u64>,
pub bzimage_addr: u64,
pub bzimage_size: u64,
pub rootfs_addr: u64,

View File

@ -5,6 +5,7 @@ use crate::{
interrupt::{
apic::{EOI, LAPIC},
gdt,
subscriber::InterruptContext,
},
time, warn,
};
@ -40,6 +41,17 @@ pub fn init_idt() {
}
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
let context = InterruptContext {
vector: 3,
instruction_pointer: stack_frame.instruction_pointer.as_u64(),
code_segment: stack_frame.code_segment.0 as u64,
cpu_flags: stack_frame.cpu_flags.bits(),
stack_pointer: stack_frame.stack_pointer.as_u64(),
stack_segment: stack_frame.stack_segment.0 as u64,
};
crate::interrupt::subscriber::dispatch_to_subscribers(&context);
warn!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
}
@ -47,6 +59,17 @@ extern "x86-interrupt" fn double_fault_handler(
stack_frame: InterruptStackFrame,
_error_code: u64,
) -> ! {
let context = InterruptContext {
vector: 8,
instruction_pointer: stack_frame.instruction_pointer.as_u64(),
code_segment: stack_frame.code_segment.0 as u64,
cpu_flags: stack_frame.cpu_flags.bits(),
stack_pointer: stack_frame.stack_pointer.as_u64(),
stack_segment: stack_frame.stack_segment.0 as u64,
};
crate::interrupt::subscriber::dispatch_to_subscribers(&context);
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
}
@ -56,6 +79,17 @@ extern "x86-interrupt" fn page_fault_handler(
) {
use x86_64::registers::control::Cr2;
let context = InterruptContext {
vector: 14,
instruction_pointer: stack_frame.instruction_pointer.as_u64(),
code_segment: stack_frame.code_segment.0 as u64,
cpu_flags: stack_frame.cpu_flags.bits(),
stack_pointer: stack_frame.stack_pointer.as_u64(),
stack_segment: stack_frame.stack_segment.0 as u64,
};
crate::interrupt::subscriber::dispatch_to_subscribers(&context);
panic!(
"EXCEPTION: PAGE FAULT\n{:#?}\nAccessed address: {:#x}",
stack_frame,
@ -63,7 +97,18 @@ extern "x86-interrupt" fn page_fault_handler(
);
}
extern "x86-interrupt" fn timer_handler(_stack_frame: InterruptStackFrame) {
extern "x86-interrupt" fn timer_handler(stack_frame: InterruptStackFrame) {
let context = InterruptContext {
vector: IRQ_TIMER as u8,
instruction_pointer: stack_frame.instruction_pointer.as_u64(),
code_segment: stack_frame.code_segment.0 as u64,
cpu_flags: stack_frame.cpu_flags.bits(),
stack_pointer: stack_frame.stack_pointer.as_u64(),
stack_segment: stack_frame.stack_segment.0 as u64,
};
crate::interrupt::subscriber::dispatch_to_subscribers(&context);
time::tick();
LAPIC.get().unwrap().write(EOI, 0);
}

View File

@ -1,3 +1,4 @@
pub mod apic;
pub mod gdt;
pub mod idt;
pub mod subscriber;

View File

@ -0,0 +1,68 @@
use spin::Mutex;
#[derive(Debug)]
pub struct InterruptContext {
pub vector: u8,
pub instruction_pointer: u64,
pub code_segment: u64,
pub cpu_flags: u64,
pub stack_pointer: u64,
pub stack_segment: u64,
}
pub type SubscriberCallback = fn(*mut core::ffi::c_void, &InterruptContext);
#[derive(Debug, Clone, Copy)]
pub struct Subscriber {
pub callback: SubscriberCallback,
pub context: *mut core::ffi::c_void,
}
unsafe impl Send for Subscriber {}
unsafe impl Sync for Subscriber {}
const MAX_SUBSCRIBERS: usize = 10;
static SUBSCRIBERS: Mutex<[Option<Subscriber>; MAX_SUBSCRIBERS]> =
Mutex::new([None; MAX_SUBSCRIBERS]);
pub fn subscribe(
callback: SubscriberCallback,
context: *mut core::ffi::c_void,
) -> Result<(), &'static str> {
let mut subscribers = SUBSCRIBERS.lock();
for slot in subscribers.iter_mut() {
if slot.is_none() {
*slot = Some(Subscriber { callback, context });
return Ok(());
}
}
Err("No available subscriber slots")
}
pub fn unsubscribe(callback: SubscriberCallback) -> Result<(), &'static str> {
let mut subscribers = SUBSCRIBERS.lock();
for slot in subscribers.iter_mut() {
if let Some(subscriber) = slot {
if core::ptr::fn_addr_eq(subscriber.callback, callback) {
*slot = None;
return Ok(());
}
}
}
Err("Subscriber not found")
}
pub fn dispatch_to_subscribers(context: &InterruptContext) {
let subscribers = SUBSCRIBERS.lock();
for subscriber in subscribers.iter() {
if let Some(subscriber) = subscriber {
(subscriber.callback)(subscriber.context, context);
}
}
}

View File

@ -82,6 +82,8 @@ fn hlt_loop() -> ! {
#[unsafe(no_mangle)]
pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
serial::disable_screen_output();
interrupt::gdt::init();
interrupt::idt::init_idt();
@ -126,10 +128,15 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
allocator::init_heap(&mut mapper, &mut bitmap_table).unwrap();
let frame_buffer = FrameBuffer::from_raw_buffer(&boot_info.frame_buffer, (64, 64, 64));
frame_buffer.clear();
if boot_info.frame_buffer.is_some() {
let frame_buffer =
FrameBuffer::from_raw_buffer(&boot_info.frame_buffer.as_ref().unwrap(), (64, 64, 64));
frame_buffer.clear();
FRAME_BUFFER.lock().replace(frame_buffer);
FRAME_BUFFER.lock().replace(frame_buffer);
} else {
error!("No frame buffer found");
}
println!("");
info!("Kernel initialized successfully");
@ -150,20 +157,20 @@ pub extern "sysv64" fn main(boot_info: &nel_os_common::BootInfo) {
usable_frame as f64 * 4. / 1024. / 1024.
);
info!("RSDP: {:#x}", boot_info.rsdp);
if let Some(rsdp) = boot_info.rsdp {
info!("RSDP: {:#x}", rsdp);
let acpi_tables =
unsafe { AcpiTables::from_rsdp(KernelAcpiHandler, boot_info.rsdp as usize) }.unwrap();
let platform_info = acpi_tables.platform_info().unwrap();
let acpi_tables =
unsafe { AcpiTables::from_rsdp(KernelAcpiHandler, rsdp as usize) }.unwrap();
let platform_info = acpi_tables.platform_info().unwrap();
apic::init_local_apic(platform_info);
info!("Local APIC initialized",);
apic::init_local_apic(platform_info);
info!("Local APIC initialized",);
x86_64::instructions::interrupts::enable();
x86_64::instructions::interrupts::enable();
info!("Interrupts enabled");
serial::disable_screen_output();
info!("Interrupts enabled");
}
BZIMAGE_ADDR.call_once(|| boot_info.bzimage_addr);
BZIMAGE_SIZE.call_once(|| boot_info.bzimage_size);

View File

@ -1,4 +1,7 @@
use crate::vmm::x86_64::{common, intel::vmcs};
use crate::vmm::x86_64::{
common,
intel::{vmcs, vmwrite},
};
pub fn setup_exec_controls() -> Result<(), &'static str> {
let basic_msr = common::read_msr(0x480);
@ -12,8 +15,8 @@ pub fn setup_exec_controls() -> Result<(), &'static str> {
raw_pin_exec_ctrl |= (reserved_bits & 0xFFFFFFFF) as u32;
raw_pin_exec_ctrl &= (reserved_bits >> 32) as u32;
let pin_exec_ctrl = vmcs::controls::PinBasedVmExecutionControls::from(raw_pin_exec_ctrl);
//pin_exec_ctrl.set_external_interrupt_exiting(false);
let mut pin_exec_ctrl = vmcs::controls::PinBasedVmExecutionControls::from(raw_pin_exec_ctrl);
pin_exec_ctrl.set_external_interrupt_exiting(false);
pin_exec_ctrl.write()?;
@ -33,6 +36,8 @@ pub fn setup_exec_controls() -> Result<(), &'static str> {
primary_exec_ctrl.set_hlt(true);
primary_exec_ctrl.set_activate_secondary_controls(true);
primary_exec_ctrl.set_use_msr_bitmap(false);
primary_exec_ctrl.set_unconditional_io(false);
primary_exec_ctrl.set_use_io_bitmap(true);
primary_exec_ctrl.write()?;
@ -55,6 +60,9 @@ pub fn setup_exec_controls() -> Result<(), &'static str> {
secondary_exec_ctrl.write()?;
vmwrite(x86::vmx::vmcs::control::CR0_GUEST_HOST_MASK, u64::MAX)?;
vmwrite(x86::vmx::vmcs::control::CR4_GUEST_HOST_MASK, u64::MAX)?;
Ok(())
}
@ -101,7 +109,13 @@ pub fn setup_exit_controls() -> Result<(), &'static str> {
exit_ctrl.write()?;
//vmwrite(0x4004, 1u64 << 6)?; // EXCEPTION_BITMAP
/*vmwrite(
0x4004,
1u64 << x86::irq::DOUBLE_FAULT_VECTOR
| 1u64 << x86::irq::GENERAL_PROTECTION_FAULT_VECTOR
| 1u64 << x86::irq::PAGE_FAULT_VECTOR
| 1u64 << x86::irq::X87_FPU_VECTOR,
)?;*/
Ok(())
}

View File

@ -0,0 +1,166 @@
use x86::vmx::vmcs;
use crate::vmm::x86_64::{
common::read_msr,
intel::{
qual::{AccessType, QualCr, Register},
vcpu::IntelVCpu,
vmread, vmwrite,
},
};
pub fn handle_cr_access(vcpu: &mut IntelVCpu, qual: &QualCr) -> Result<(), &'static str> {
match qual.access_type() {
AccessType::MovTo => match qual.index() {
0 | 4 => {
passthrough_write(vcpu, qual)?;
update_ia32e(vcpu)?;
}
_ => panic!("Unsupported CR index: {}", qual.index()),
},
AccessType::MovFrom => passthrough_read(vcpu, qual)?,
_ => {
panic!("Unsupported CR access type: {:?}", qual.access_type());
}
}
Ok(())
}
fn passthrough_read(vcpu: &mut IntelVCpu, qual: &QualCr) -> Result<(), &'static str> {
let value = match qual.index() {
3 => vmread(x86::vmx::vmcs::guest::CR3)?,
_ => panic!("Unsupported CR index: {}", qual.index()),
};
set_value(vcpu, qual, value)?;
Ok(())
}
fn passthrough_write(vcpu: &mut IntelVCpu, qual: &QualCr) -> Result<(), &'static str> {
let value = get_value(vcpu, qual)?;
match qual.index() {
0 => {
vmwrite(vmcs::guest::CR0, adjust_cr0(value))?;
vmwrite(vmcs::control::CR0_READ_SHADOW, value)?;
}
4 => {
vmwrite(vmcs::guest::CR4, adjust_cr4(value))?;
vmwrite(vmcs::control::CR4_READ_SHADOW, value)?;
}
_ => {
panic!("Unsupported CR index: {}", qual.index());
}
}
Ok(())
}
pub fn update_ia32e(vcpu: &mut IntelVCpu) -> Result<(), &'static str> {
let cr0 = vmread(x86::vmx::vmcs::guest::CR0)?;
let cr4 = vmread(x86::vmx::vmcs::guest::CR4)?;
let ia32e_enabled = (cr0 & 1 << 31) != 0 && (cr4 & 1 << 5) != 0;
vcpu.ia32e_enabled = ia32e_enabled;
let mut entry_ctrl = super::vmcs::controls::EntryControls::read()?;
entry_ctrl.set_ia32e_mode_guest(ia32e_enabled);
entry_ctrl.write()?;
let mut efer = vmread(x86::vmx::vmcs::guest::IA32_EFER_FULL)?;
let lma = (vcpu.ia32e_enabled as u64) << 10;
if lma != 0 {
efer |= lma;
} else {
efer &= !lma;
}
let lme = if cr0 & (1 << 31) != 0 {
efer & (1 << 10)
} else {
efer & !(1 << 8)
};
if lme != 0 {
efer |= lme;
} else {
efer &= lme;
}
vmwrite(x86::vmx::vmcs::guest::IA32_EFER_FULL, efer)?;
Ok(())
}
pub fn adjust_cr0(value: u64) -> u64 {
let mut result = value;
let cr0_fixed0 = read_msr(x86::msr::IA32_VMX_CR0_FIXED0);
let cr0_fixed1 = read_msr(x86::msr::IA32_VMX_CR0_FIXED1);
result |= cr0_fixed0;
result &= cr0_fixed1;
result
}
pub fn adjust_cr4(value: u64) -> u64 {
let mut result = value;
let cr4_fixed0 = read_msr(x86::msr::IA32_VMX_CR4_FIXED0);
let cr4_fixed1 = read_msr(x86::msr::IA32_VMX_CR4_FIXED1);
result |= cr4_fixed0;
result &= cr4_fixed1;
result
}
fn set_value(vcpu: &mut IntelVCpu, qual: &QualCr, value: u64) -> Result<(), &'static str> {
let guest_regs = &mut vcpu.guest_registers;
match qual.register() {
Register::Rax => guest_regs.rax = value,
Register::Rcx => guest_regs.rcx = value,
Register::Rdx => guest_regs.rdx = value,
Register::Rbx => guest_regs.rbx = value,
Register::Rbp => guest_regs.rbp = value,
Register::Rsi => guest_regs.rsi = value,
Register::Rdi => guest_regs.rdi = value,
Register::R8 => guest_regs.r8 = value,
Register::R9 => guest_regs.r9 = value,
Register::R10 => guest_regs.r10 = value,
Register::R11 => guest_regs.r11 = value,
Register::R12 => guest_regs.r12 = value,
Register::R13 => guest_regs.r13 = value,
Register::R14 => guest_regs.r14 = value,
Register::R15 => guest_regs.r15 = value,
Register::Rsp => vmwrite(x86::vmx::vmcs::guest::RSP, value)?,
}
Ok(())
}
fn get_value(vcpu: &mut IntelVCpu, qual: &QualCr) -> Result<u64, &'static str> {
let guest_regs = &mut vcpu.guest_registers;
Ok(match qual.register() {
Register::Rax => guest_regs.rax,
Register::Rcx => guest_regs.rcx,
Register::Rdx => guest_regs.rdx,
Register::Rbx => guest_regs.rbx,
Register::Rbp => guest_regs.rbp,
Register::Rsi => guest_regs.rsi,
Register::Rdi => guest_regs.rdi,
Register::R8 => guest_regs.r8,
Register::R9 => guest_regs.r9,
Register::R10 => guest_regs.r10,
Register::R11 => guest_regs.r11,
Register::R12 => guest_regs.r12,
Register::R13 => guest_regs.r13,
Register::R14 => guest_regs.r14,
Register::R15 => guest_regs.r15,
Register::Rsp => vmread(x86::vmx::vmcs::guest::RSP)?,
})
}

View File

@ -0,0 +1,249 @@
use x86::vmx::vmcs;
use x86_64::structures::paging::{FrameAllocator, PhysFrame, Size4KiB};
use super::qual::QualIo;
use crate::{
info,
vmm::x86_64::intel::{register::GuestRegisters, vmwrite},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InitPhase {
Uninitialized,
Phase1,
Phase2,
Phase3,
Initialized,
}
pub enum ReadSel {
IRR,
ISR,
}
pub struct PIC {
pub primary_mask: u8,
pub secondary_mask: u8,
pub primary_phase: InitPhase,
pub secondary_phase: InitPhase,
pub primary_base: u8,
pub secondary_base: u8,
pub primary_irr: u8,
pub primary_isr: u8,
pub secondary_irr: u8,
pub secondary_isr: u8,
pub primary_read_sel: ReadSel,
pub secondary_read_sel: ReadSel,
}
impl PIC {
pub fn new() -> Self {
Self {
primary_mask: 0xFF,
secondary_mask: 0xFF,
primary_phase: InitPhase::Uninitialized,
secondary_phase: InitPhase::Uninitialized,
primary_base: 0,
secondary_base: 0,
primary_irr: 0,
primary_isr: 0,
secondary_irr: 0,
secondary_isr: 0,
primary_read_sel: ReadSel::IRR,
secondary_read_sel: ReadSel::IRR,
}
}
pub fn handle_io(&mut self, regs: &mut GuestRegisters, qual: QualIo) {
match qual.direction() {
0 => {
self.handle_io_out(regs, qual);
}
1 => {
self.handle_io_in(regs, qual);
}
_ => {}
}
}
pub fn handle_io_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
match qual.port() {
0x0CF8..=0x0CFF => regs.rax = 0,
0xC000..=0xCFFF => {} //ignore
0x20..=0x21 => self.handle_pic_in(regs, qual),
0xA0..=0xA1 => self.handle_pic_in(regs, qual),
0x0070..=0x0071 => regs.rax = 0,
_ => regs.rax = 0,
}
}
pub fn handle_io_out(&mut self, regs: &mut GuestRegisters, qual: QualIo) {
match qual.port() {
0x0CF8..=0x0CFF => {} //ignore
0xC000..=0xCFFF => {} //ignore
0x20..=0x21 => self.handle_pic_out(regs, qual),
0xA0..=0xA1 => self.handle_pic_out(regs, qual),
0x0070..=0x0071 => {} //ignore
_ => {}
}
}
pub fn handle_pic_in(&self, regs: &mut GuestRegisters, qual: QualIo) {
match qual.port() {
0x20 => {
let v = match self.primary_read_sel {
ReadSel::IRR => self.primary_irr,
ReadSel::ISR => self.primary_isr,
};
regs.rax = v as u64;
}
0xA0 => {
let v = match self.secondary_read_sel {
ReadSel::IRR => self.secondary_irr,
ReadSel::ISR => self.secondary_isr,
};
regs.rax = v as u64;
}
0x21 => match self.primary_phase {
InitPhase::Uninitialized | InitPhase::Initialized => {
regs.rax = self.primary_mask as u64;
}
_ => {}
},
0xA1 => match self.secondary_phase {
InitPhase::Uninitialized | InitPhase::Initialized => {
regs.rax = self.secondary_mask as u64;
}
_ => {}
},
_ => {}
}
}
pub fn handle_pic_out(&mut self, regs: &mut GuestRegisters, qual: QualIo) {
let pic = self;
let dx = regs.rax as u8;
match qual.port() {
0x20 => match dx {
0x11 => pic.primary_phase = InitPhase::Phase1,
0x0A => pic.primary_read_sel = ReadSel::ISR,
0x0B => pic.primary_read_sel = ReadSel::IRR,
0x20 => {
pic.primary_isr = 0;
}
0x60..=0x67 => {
let irq = dx & 0x7;
pic.primary_isr &= !(1 << irq);
}
_ => panic!("Primary PIC command: {:#x}", dx),
},
0x21 => match pic.primary_phase {
InitPhase::Uninitialized | InitPhase::Initialized => pic.primary_mask = dx,
InitPhase::Phase1 => {
pic.primary_base = dx;
pic.primary_phase = InitPhase::Phase2;
}
InitPhase::Phase2 => {
pic.primary_phase = InitPhase::Phase3;
}
InitPhase::Phase3 => {
info!("Primary PIC Initialized");
pic.primary_phase = InitPhase::Initialized
}
},
0xA0 => match dx {
0x11 => pic.secondary_phase = InitPhase::Phase1,
0x0A => pic.secondary_read_sel = ReadSel::ISR,
0x0B => pic.secondary_read_sel = ReadSel::IRR,
0x20 => {
pic.secondary_isr = 0;
}
0x60..=0x67 => {
let irq = dx & 0x7;
pic.secondary_isr &= !(1 << irq);
}
_ => panic!("Secondary PIC command: {:#x}", dx),
},
0xA1 => match pic.secondary_phase {
InitPhase::Uninitialized | InitPhase::Initialized => pic.secondary_mask = dx,
InitPhase::Phase1 => {
pic.secondary_base = dx;
pic.secondary_phase = InitPhase::Phase2;
}
InitPhase::Phase2 => {
pic.secondary_phase = InitPhase::Phase3;
}
InitPhase::Phase3 => {
info!("Secondary PIC Initialized");
pic.secondary_phase = InitPhase::Initialized
}
},
_ => {}
}
}
}
pub struct IOBitmap {
pub bitmap_a: PhysFrame,
pub bitmap_b: PhysFrame,
}
impl IOBitmap {
pub fn new(frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Self {
let bitmap_a = frame_allocator
.allocate_frame()
.expect("Failed to allocate I/O bitmap A");
let bitmap_b = frame_allocator
.allocate_frame()
.expect("Failed to allocate I/O bitmap B");
Self { bitmap_a, bitmap_b }
}
pub fn setup(&mut self) -> Result<(), &'static str> {
let bitmap_a_addr = self.bitmap_a.start_address().as_u64() as usize;
let bitmap_b_addr = self.bitmap_b.start_address().as_u64() as usize;
unsafe {
core::ptr::write_bytes(bitmap_a_addr as *mut u8, u8::MAX, 4096);
core::ptr::write_bytes(bitmap_b_addr as *mut u8, u8::MAX, 4096);
}
self.set_io_ports(0x02F8..=0x03FF);
self.set_io_ports(0x0040..=0x0047);
vmwrite(vmcs::control::IO_BITMAP_A_ADDR_FULL, bitmap_a_addr as u64)?;
vmwrite(vmcs::control::IO_BITMAP_B_ADDR_FULL, bitmap_b_addr as u64)?;
Ok(())
}
pub fn set_io_ports(&mut self, ports: core::ops::RangeInclusive<u16>) {
for port in ports {
if port <= 0x7FFF {
let byte_index = port as usize / 8;
let bit_index = port as usize % 8;
self.get_bitmap_a()[byte_index] &= !(1 << bit_index);
} else {
let adjusted_port = port - 0x8000;
let byte_index = adjusted_port as usize / 8;
let bit_index = adjusted_port as usize % 8;
self.get_bitmap_b()[byte_index] &= !(1 << bit_index);
}
}
}
fn get_bitmap_a(&self) -> &mut [u8] {
unsafe {
core::slice::from_raw_parts_mut(self.bitmap_a.start_address().as_u64() as *mut u8, 4096)
}
}
fn get_bitmap_b(&self) -> &mut [u8] {
unsafe {
core::slice::from_raw_parts_mut(self.bitmap_b.start_address().as_u64() as *mut u8, 4096)
}
}
}

View File

@ -2,8 +2,11 @@ pub mod asm;
mod auditor;
mod controls;
mod cpuid;
mod cr;
mod ept;
mod io;
mod msr;
mod qual;
mod register;
pub mod vcpu;
mod vmcs;

View File

@ -92,7 +92,7 @@ pub fn register_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
Ok(())
}
pub fn update_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
pub fn _update_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
info!("updating MSRs");
let indices_to_update: alloc::vec::Vec<u32> = vcpu
.host_msr
@ -101,8 +101,6 @@ pub fn update_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
.map(|entry| entry.index)
.collect();
info!("1");
for index in indices_to_update {
info!("{}", index);
let value = read_msr(index);
@ -110,25 +108,21 @@ pub fn update_msrs(vcpu: &mut IntelVCpu) -> Result<(), MsrError> {
vcpu.host_msr.set_by_index(index, value).unwrap();
}
info!("2");
vmwrite(
vmcs::control::VMEXIT_MSR_LOAD_COUNT,
vcpu.host_msr.saved_ents().len() as u64,
)
.unwrap();
info!("3");
vmwrite(
vmcs::control::VMEXIT_MSR_STORE_COUNT,
vcpu.guest_msr.saved_ents().len() as u64,
)
.unwrap();
info!("4");
vmwrite(
vmcs::control::VMENTRY_MSR_LOAD_COUNT,
vcpu.guest_msr.saved_ents().len() as u64,
)
.unwrap();
info!("5");
Ok(())
}

View File

@ -0,0 +1,124 @@
#![allow(non_snake_case)]
use core::convert::TryFrom;
use core::fmt::Debug;
use modular_bitfield::prelude::{B1, B16, B32, B4, B8};
use modular_bitfield::{bitfield, Specifier};
#[repr(u8)]
#[derive(Specifier, Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessType {
MovTo = 0,
MovFrom = 1,
Clts = 2,
Lmsw = 3,
}
impl TryFrom<u8> for AccessType {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(AccessType::MovTo),
1 => Ok(AccessType::MovFrom),
2 => Ok(AccessType::Clts),
3 => Ok(AccessType::Lmsw),
_ => Err("Invalid AccessType value"),
}
}
}
#[repr(u8)]
#[derive(Specifier, Debug, Clone, Copy, PartialEq, Eq)]
pub enum LmswOperandType {
Reg = 0,
Mem = 1,
}
impl TryFrom<u8> for LmswOperandType {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(LmswOperandType::Reg),
1 => Ok(LmswOperandType::Mem),
_ => Err("Invalid LmswOperandType value"),
}
}
}
#[repr(u8)]
#[derive(Specifier, Debug, Clone, Copy, PartialEq, Eq)]
pub enum Register {
Rax = 0,
Rcx = 1,
Rdx = 2,
Rbx = 3,
Rsp = 4,
Rbp = 5,
Rsi = 6,
Rdi = 7,
R8 = 8,
R9 = 9,
R10 = 10,
R11 = 11,
R12 = 12,
R13 = 13,
R14 = 14,
R15 = 15,
}
impl TryFrom<u8> for Register {
type Error = &'static str;
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0 => Ok(Register::Rax),
1 => Ok(Register::Rcx),
2 => Ok(Register::Rdx),
3 => Ok(Register::Rbx),
4 => Ok(Register::Rsp),
5 => Ok(Register::Rbp),
6 => Ok(Register::Rsi),
7 => Ok(Register::Rdi),
8 => Ok(Register::R8),
9 => Ok(Register::R9),
10 => Ok(Register::R10),
11 => Ok(Register::R11),
12 => Ok(Register::R12),
13 => Ok(Register::R13),
14 => Ok(Register::R14),
15 => Ok(Register::R15),
_ => Err("Invalid Register value"),
}
}
}
#[bitfield]
#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub struct QualCr {
pub index: B4,
#[bits = 2]
pub access_type: AccessType,
#[bits = 1]
pub lmsw_operand_type: LmswOperandType,
_reserved1: B1,
#[bits = 4]
pub register: Register,
_reserved2: B4,
pub lmsw_source: B16,
_reseved3: B32,
}
#[bitfield]
#[repr(u64)]
#[derive(Debug, Clone, Copy)]
pub struct QualIo {
pub size: B4,
pub direction: B1,
pub string: B1,
pub rep: B1,
pub operand_encoding: B1,
_reserved1: B8,
pub port: B16,
_reserved2: B32,
}

View File

@ -12,7 +12,9 @@ use crate::{
common::{self, read_msr},
intel::{
auditor, controls, cpuid, ept,
io::IOBitmap,
msr::{self, ShadowMsr},
qual::{QualCr, QualIo},
register::GuestRegisters,
vmcs::{
self,
@ -42,6 +44,9 @@ pub struct IntelVCpu {
guest_memory_size: u64,
pub host_msr: ShadowMsr,
pub guest_msr: ShadowMsr,
pub ia32e_enabled: bool,
pic: super::io::PIC,
io_bitmap: IOBitmap,
}
impl IntelVCpu {
@ -76,7 +81,6 @@ impl IntelVCpu {
self.step_next_inst()?;
}
VmxExitReason::CPUID => {
info!("VM exit reason: CPUID");
cpuid::handle_cpuid_vmexit(self);
self.step_next_inst()?;
}
@ -88,11 +92,53 @@ impl IntelVCpu {
msr::ShadowMsr::handle_wrmsr_vmexit(self);
self.step_next_inst()?;
}
VmxExitReason::CONTROL_REGISTER_ACCESSES => {
let qual = vmread(vmcs::ro::EXIT_QUALIFICATION)?;
let qual = QualCr::from(qual);
super::cr::handle_cr_access(self, &qual)?;
self.step_next_inst()?;
}
VmxExitReason::IO_INSTRUCTION => {
let qual = vmread(vmcs::ro::EXIT_QUALIFICATION)?;
let qual_io = QualIo::from(qual);
self.pic.handle_io(&mut self.guest_registers, qual_io);
self.step_next_inst()?;
}
VmxExitReason::EPT_VIOLATION => {
let guest_address = vmread(vmcs::ro::GUEST_PHYSICAL_ADDR_FULL)?;
info!("EPT Violation at guest address: {:#x}", guest_address);
return Err("EPT Violation");
}
VmxExitReason::TRIPLE_FAULT => {
info!("Triple fault detected");
return Err("Triple fault");
}
VmxExitReason::EXCEPTION => {
let vmexit_intr_info = vmread(vmcs::ro::VMEXIT_INTERRUPTION_INFO)?;
let vector = (vmexit_intr_info & 0xFF) as u8;
let error_code = (vmexit_intr_info >> 8) & 0b111;
let error_code_valid = (vmexit_intr_info >> 11) & 0b1 != 0;
let idt_vectoring_info = vmread(vmcs::ro::IDT_VECTORING_INFO)?;
info!("idt valid: {}", idt_vectoring_info >> 31 & 0b1 != 0);
let rip = vmread(vmcs::guest::RIP)?;
let hpa = self.ept.get_phys_addr(rip).unwrap();
if error_code_valid {
info!(
"VM exit due to exception: vector {}, error code {}, at RIP {:#x} (hpa: {:#x})",
vector, error_code, rip, hpa
);
} else {
info!("VM exit due to exception: vector {}", vector);
}
return Err("VM exit due to exception");
}
_ => {
info!("VM exit reason: {:?}", exit_reason);
return Err("Unhandled VM exit reason");
@ -114,8 +160,6 @@ impl IntelVCpu {
}
fn vmentry(&mut self) -> Result<(), InstructionError> {
msr::update_msrs(self).unwrap();
auditor::controls::check_vmcs_control_fields().unwrap();
let success = {
@ -152,6 +196,7 @@ impl IntelVCpu {
controls::setup_exit_controls()?;
Self::setup_host_state()?;
self.setup_guest_state()?;
self.io_bitmap.setup()?;
self.init_guest_memory(frame_allocator)?;
@ -233,14 +278,18 @@ impl IntelVCpu {
fn setup_guest_state(&mut self) -> Result<(), &'static str> {
use x86::{controlregs::*, vmx::vmcs};
let cr0 = Cr0::empty()
let cr0 = (Cr0::empty()
| Cr0::CR0_PROTECTED_MODE
| Cr0::CR0_NUMERIC_ERROR & !Cr0::CR0_ENABLE_PAGING;
| Cr0::CR0_NUMERIC_ERROR
| Cr0::CR0_EXTENSION_TYPE)
& !Cr0::CR0_ENABLE_PAGING;
vmwrite(vmcs::guest::CR0, cr0.bits() as u64)?;
vmwrite(vmcs::guest::CR3, unsafe { cr3() })?;
vmwrite(vmcs::guest::CR3, 0)?;
vmwrite(
vmcs::guest::CR4,
vmread(vmcs::guest::CR4)? & !Cr4Flags::VIRTUAL_MACHINE_EXTENSIONS.bits(),
vmread(vmcs::guest::CR4)?
| Cr4Flags::VIRTUAL_MACHINE_EXTENSIONS.bits()
& !Cr4Flags::PHYSICAL_ADDRESS_EXTENSION.bits(),
)?;
vmwrite(vmcs::guest::CS_BASE, 0)?;
@ -638,6 +687,9 @@ impl VCpu for IntelVCpu {
guest_memory_size: 1024 * 1024 * 256, // 256 MiB
host_msr: ShadowMsr::new(),
guest_msr: ShadowMsr::new(),
ia32e_enabled: false,
pic: super::io::PIC::new(),
io_bitmap: IOBitmap::new(frame_allocator),
})
}