From cc8a6f6a6f3573836c4d56261b84055118be0332 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 14:37:23 +0100 Subject: [PATCH 001/151] first commit! --- kernel-rs/Makefile | 36 +++++++++ kernel-rs/Vagrantfile | 77 +++++++++++++++++++ kernel-rs/src/arch/x86_64/boot.asm | 8 ++ kernel-rs/src/arch/x86_64/linker.ld | 16 ++++ .../src/arch/x86_64/multiboot_header.asm | 15 ++++ 5 files changed, 152 insertions(+) create mode 100644 kernel-rs/Makefile create mode 100644 kernel-rs/Vagrantfile create mode 100644 kernel-rs/src/arch/x86_64/boot.asm create mode 100644 kernel-rs/src/arch/x86_64/linker.ld create mode 100644 kernel-rs/src/arch/x86_64/multiboot_header.asm diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile new file mode 100644 index 00000000..464c7329 --- /dev/null +++ b/kernel-rs/Makefile @@ -0,0 +1,36 @@ +arch ?= x86_64 +kernel := build/kernel-$(arch).bin +iso := build/os-$(arch).iso + +linker_script := src/arch/$(arch)/linker.ld +grub.cfg := src/arch/$(arch)/grub.cfg +asm_source_files := $(wildcard src/arch/$(arch)/*.asm) +asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ + build/arch/$(arch)/%.o, $(asm_source_files)) + +.PHONY: all clean run iso + +all: $(kernel) + +clean: + @rm -r build + +run: $(iso) + @qemu-system-x86_64 -cdrom $(iso) + +iso: $(iso) + +$(iso): $(kernel) $(grub.cfg) + @mkdir -p build/isofiles/boot/grub + @cp $(kernel) build/isofiles/boot/kernel.bin + @cp $(grub.cfg) build/isofiles/boot/grub + @grub-mkrescue -o $(iso) build/isofiles 2>/dev/null + @rm -r build/isofiles + +$(kernel): $(asm_object_files) $(linker_script) + @ld -n -T $(linker_script) -o $(kernel) $(asm_object_files) + +# compile asm files +build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm + @mkdir -p $(shell dirname $@) + @nasm -felf64 $< -o $@ diff --git a/kernel-rs/Vagrantfile b/kernel-rs/Vagrantfile new file mode 100644 index 00000000..d46deb85 --- /dev/null +++ b/kernel-rs/Vagrantfile @@ -0,0 +1,77 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure(2) do |config| + # The most common configuration options are documented and commented below. + # For a complete reference, please see the online documentation at + # https://docs.vagrantup.com. + + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. + config.vm.box = "debian/jessie64" + + # Disable automatic box update checking. If you disable this, then + # boxes will only be checked for updates when the user runs + # `vagrant box outdated`. This is not recommended. + # config.vm.box_check_update = false + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + # config.vm.network "forwarded_port", guest: 80, host: 8080 + + # Create a private network, which allows host-only access to the machine + # using a specific IP. + # config.vm.network "private_network", ip: "192.168.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + # config.vm.network "public_network" + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + # config.vm.provider "virtualbox" do |vb| + # # Display the VirtualBox GUI when booting the machine + # vb.gui = true + # + # # Customize the amount of memory on the VM: + # vb.memory = "1024" + # end + # + # View the documentation for the provider you are using for more + # information on available options. + + # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies + # such as FTP and Heroku are also available. See the documentation at + # https://docs.vagrantup.com/v2/push/atlas.html for more information. + # config.push.define "atlas" do |push| + # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" + # end + + # Enable provisioning with a shell script. Additional provisioners such as + # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the + # documentation for more information about their specific syntax and use. + config.vm.provision "shell", inline: <<-SHELL + sudo apt-get update + sudo apt-get install nasm -y + sudo apt-get install xorriso -y + sudo apt-get install git -y + sudo apt-get install vim -y + sudo apt-get install -y qemu + # curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes + # multirust default nightly-2015-11-19 + SHELL + + config.ssh.forward_x11 = true +end diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm new file mode 100644 index 00000000..ec460075 --- /dev/null +++ b/kernel-rs/src/arch/x86_64/boot.asm @@ -0,0 +1,8 @@ +global start + +section .text +bits 32 +start: + ; print OK to screen + mov dword [0xb8000], 0x2f4b2f4f + hlt diff --git a/kernel-rs/src/arch/x86_64/linker.ld b/kernel-rs/src/arch/x86_64/linker.ld new file mode 100644 index 00000000..89751965 --- /dev/null +++ b/kernel-rs/src/arch/x86_64/linker.ld @@ -0,0 +1,16 @@ +ENTRY(start) + +SECTIONS { + . = 1M; + + .boot : + { + /* ensure that the multiboot header is at the beginning */ + *(.multiboot_header) + } + + .text : + { + *(.text) + } +} diff --git a/kernel-rs/src/arch/x86_64/multiboot_header.asm b/kernel-rs/src/arch/x86_64/multiboot_header.asm new file mode 100644 index 00000000..737a2b95 --- /dev/null +++ b/kernel-rs/src/arch/x86_64/multiboot_header.asm @@ -0,0 +1,15 @@ +section .multiboot_header +header_start: + dd 0xe85250d6 ; magic number (multiboot 2) + dd 0 ; architecture - (protected mode i386) + dd header_end - header_start ; header length + ; checksum + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) + + ; insert optional multiboot tags here + + ; required end tag here + dw 0 ; type + dw 0 ; flags + dd 0 ; size +header_end: From 39e3de544eff05d70248ea20d8e3831edd75b0ff Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 15:09:27 +0100 Subject: [PATCH 002/151] no more vagrantfile --- kernel-rs/Vagrantfile | 77 ------------------------------------------- 1 file changed, 77 deletions(-) delete mode 100644 kernel-rs/Vagrantfile diff --git a/kernel-rs/Vagrantfile b/kernel-rs/Vagrantfile deleted file mode 100644 index d46deb85..00000000 --- a/kernel-rs/Vagrantfile +++ /dev/null @@ -1,77 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what -# you're doing. -Vagrant.configure(2) do |config| - # The most common configuration options are documented and commented below. - # For a complete reference, please see the online documentation at - # https://docs.vagrantup.com. - - # Every Vagrant development environment requires a box. You can search for - # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "debian/jessie64" - - # Disable automatic box update checking. If you disable this, then - # boxes will only be checked for updates when the user runs - # `vagrant box outdated`. This is not recommended. - # config.vm.box_check_update = false - - # Create a forwarded port mapping which allows access to a specific port - # within the machine from a port on the host machine. In the example below, - # accessing "localhost:8080" will access port 80 on the guest machine. - # config.vm.network "forwarded_port", guest: 80, host: 8080 - - # Create a private network, which allows host-only access to the machine - # using a specific IP. - # config.vm.network "private_network", ip: "192.168.33.10" - - # Create a public network, which generally matched to bridged network. - # Bridged networks make the machine appear as another physical device on - # your network. - # config.vm.network "public_network" - - # Share an additional folder to the guest VM. The first argument is - # the path on the host to the actual folder. The second argument is - # the path on the guest to mount the folder. And the optional third - # argument is a set of non-required options. - # config.vm.synced_folder "../data", "/vagrant_data" - - # Provider-specific configuration so you can fine-tune various - # backing providers for Vagrant. These expose provider-specific options. - # Example for VirtualBox: - # - # config.vm.provider "virtualbox" do |vb| - # # Display the VirtualBox GUI when booting the machine - # vb.gui = true - # - # # Customize the amount of memory on the VM: - # vb.memory = "1024" - # end - # - # View the documentation for the provider you are using for more - # information on available options. - - # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies - # such as FTP and Heroku are also available. See the documentation at - # https://docs.vagrantup.com/v2/push/atlas.html for more information. - # config.push.define "atlas" do |push| - # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" - # end - - # Enable provisioning with a shell script. Additional provisioners such as - # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the - # documentation for more information about their specific syntax and use. - config.vm.provision "shell", inline: <<-SHELL - sudo apt-get update - sudo apt-get install nasm -y - sudo apt-get install xorriso -y - sudo apt-get install git -y - sudo apt-get install vim -y - sudo apt-get install -y qemu - # curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes - # multirust default nightly-2015-11-19 - SHELL - - config.ssh.forward_x11 = true -end From 6411831e67a6a74bbe55105297ec02468bc3a2ba Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 17:32:46 +0000 Subject: [PATCH 003/151] readme, also paging is enabled --- kernel-rs/Makefile | 11 ++- kernel-rs/README.md | 13 +++ kernel-rs/src/arch/x86_64/boot.asm | 136 ++++++++++++++++++++++++++++- kernel-rs/src/arch/x86_64/grub.cfg | 7 ++ 4 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 kernel-rs/README.md create mode 100644 kernel-rs/src/arch/x86_64/grub.cfg diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 464c7329..19b2e1b3 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -6,8 +6,7 @@ linker_script := src/arch/$(arch)/linker.ld grub.cfg := src/arch/$(arch)/grub.cfg asm_source_files := $(wildcard src/arch/$(arch)/*.asm) asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ - build/arch/$(arch)/%.o, $(asm_source_files)) - + build/arch/$(arch)/%.o, $(asm_source_files)) .PHONY: all clean run iso all: $(kernel) @@ -22,10 +21,10 @@ iso: $(iso) $(iso): $(kernel) $(grub.cfg) @mkdir -p build/isofiles/boot/grub - @cp $(kernel) build/isofiles/boot/kernel.bin - @cp $(grub.cfg) build/isofiles/boot/grub - @grub-mkrescue -o $(iso) build/isofiles 2>/dev/null - @rm -r build/isofiles + cp $(kernel) build/isofiles/boot/kernel.bin + cp $(grub.cfg) build/isofiles/boot/grub + grub-mkrescue -o $(iso) build/isofiles 2>/dev/null + rm -r build/isofiles $(kernel): $(asm_object_files) $(linker_script) @ld -n -T $(linker_script) -o $(kernel) $(asm_object_files) diff --git a/kernel-rs/README.md b/kernel-rs/README.md new file mode 100644 index 00000000..342e5999 --- /dev/null +++ b/kernel-rs/README.md @@ -0,0 +1,13 @@ +# compiling + +a standard development environment can be invoked: + +``` +docker run jzck/arch-kernel -it /usr/bin/zsh +``` + +clone the repo and `make iso` + +# running + +`make run` in your host operating system to launch qemu gtk window diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm index ec460075..f717b7dd 100644 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ b/kernel-rs/src/arch/x86_64/boot.asm @@ -3,6 +3,138 @@ global start section .text bits 32 start: - ; print OK to screen - mov dword [0xb8000], 0x2f4b2f4f + mov esp, stack_top + + call check_multiboot + call check_cpuid + call check_long_mode + + call set_up_page_tables + call enable_paging + + ; print 'OK' to screen + mov dword [0xb8000], 0x2f4b2f4f + hlt +error: + ; print 'ERR: ' and the given error code to screen and hangs + mov dword [0xb8000], 0x4f524f45 + mov dword [0xb8004], 0x4f3a4f52 + mov dword [0xb8008], 0x4f204f20 + mov byte [0xb800a], al hlt + +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "0" + jmp error + +check_cpuid: + ; Check if CPUID is supported by attempting to flip the ID bit (bit 21) + ; in the FLAGS register. If we can flip it, CPUID is available. + + ; Copy FLAGS in to EAX via stack + pushfd + pop eax + ; Copy to ECX as well for comparing later on + mov ecx, eax + ; Flip the ID bit + xor eax, 1 << 21 + ; Copy EAX to FLAGS via the stack + push eax + popfd + ; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) + pushfd + pop eax + ; Restore FLAGS from the old version stored in ECX (i.e. flipping the + ; ID bit back if it was ever flipped). + push ecx + popfd + + ; Compare EAX and ECX. If they are equal then that means the bit + ; wasn't flipped, and CPUID isn't supported. + cmp eax, ecx + je .no_cpuid + ret +.no_cpuid: + mov al, "1" + jmp error + +check_long_mode: + ; test if extended processor info in available + mov eax, 0x80000000 ; implicit argument for cpuid + cpuid ; get highest supported argument + cmp eax, 0x80000001 ; it needs to be at least 0x80000001 + jb .no_long_mode ; if it's less, the CPU is too old for long mode + + ; use extended info to test if long mode is available + mov eax, 0x80000001 ; argument for extended processor info + cpuid ; returns various feature bits in ecx and edx + test edx, 1 << 29 ; test if the LM-bit is set in the D-register + jz .no_long_mode ; If it's not set, there is no long mode + ret +.no_long_mode: + mov al, "2" + jmp error + +set_up_page_tables: + ; map first P4 entry to P3 table + mov eax, p3_table + or eax, 0b11 ; present + writeable + mov [p4_table], eax + + ; map first P3 entry to P2 table + mov eax, p2_table + or eax, 0b11 ; present + writeable + mov [p3_table], eax + + mov ecx, 0 ;counter variable +.map_p2_table: + ; map ecx-th P2 entry to a huge page that start at address 2MiB*ecx + mov eax, 0x200000 ; 2MiB + mul ecx ; start address of ecx-th page + or eax, 0b10000011 ; present + writeable + huge + mov [p2_table + ecx * 8], eax ; map ecx-th entry + + inc ecx ; increase counter + cmp ecx, 512 ; if counter == 512, the whole P2 table is mapped + jne .map_p2_table ; else map the next entry + + ret + +enable_paging: + ; load P4 to cr3 register (cpu uses this to acces the P4 table) + mov eax, p4_table + mov cr3, eax + + ; enable PAE-flag in cr4 (Physical Address Extension) + mov eax, cr4 + or eax, 1 << 5 + mov cr4, eax + + ; set the long mode bit in the EFER MSR (model specific register) + mov ecx, 0xC0000080 + rdmsr + or eax, 1 << 8 + wrmsr + + ; enable paging in the cr0 register + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret + +section .bss + align 4096 +p4_table: + resb 4096 +p3_table: + resb 4096 +p2_table: + resb 4096 +stack_bottom: + resb 64 +stack_top: diff --git a/kernel-rs/src/arch/x86_64/grub.cfg b/kernel-rs/src/arch/x86_64/grub.cfg new file mode 100644 index 00000000..a1f38c91 --- /dev/null +++ b/kernel-rs/src/arch/x86_64/grub.cfg @@ -0,0 +1,7 @@ +set timeout=0 +set default=0 + +menuentry "my os" { + multiboot2 /boot/kernel.bin + boot +} From 687b60924421ed3ed04e3371825ec58561f38de1 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 18:51:25 +0100 Subject: [PATCH 004/151] long mode achieved, starting rust --- kernel-rs/src/arch/x86_64/boot.asm | 15 +++++++++++++++ kernel-rs/src/arch/x86_64/long_mode_init.asm | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 kernel-rs/src/arch/x86_64/long_mode_init.asm diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm index f717b7dd..e4037e21 100644 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ b/kernel-rs/src/arch/x86_64/boot.asm @@ -1,4 +1,5 @@ global start +extern long_mode_start section .text bits 32 @@ -12,6 +13,11 @@ start: call set_up_page_tables call enable_paging + ; load the 64-bit GDT + lgdt [gdt64.pointer] + + jmp gdt64.code:long_mode_start + ; print 'OK' to screen mov dword [0xb8000], 0x2f4b2f4f hlt @@ -138,3 +144,12 @@ p2_table: stack_bottom: resb 64 stack_top: + +section .rodata +gdt64: + dq 0 ; zero entry +.code: equ $ - gdt64 + dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment +.pointer: + dw $ - gdt64 - 1 + dq gdt64 diff --git a/kernel-rs/src/arch/x86_64/long_mode_init.asm b/kernel-rs/src/arch/x86_64/long_mode_init.asm new file mode 100644 index 00000000..318764af --- /dev/null +++ b/kernel-rs/src/arch/x86_64/long_mode_init.asm @@ -0,0 +1,16 @@ +global long_mode_start + +section .text +bits 64 +long_mode_start: + ; load 0 into all data segment registers + mov ax, 0 + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + ;print 'OKAY' to screen + mov rax, 0x2f592f412f4b2f4f + mov qword [0xb8000], rax + hlt From 68abeabb0f8ed33b5d015d666b99602bc0b8cb27 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 18:08:45 +0000 Subject: [PATCH 005/151] README with blog url --- kernel-rs/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 342e5999..fe70ace6 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -1,3 +1,5 @@ +based on [Writing an OS in rust](https://os.phil-opp.com/) + # compiling a standard development environment can be invoked: From 93b06cea11bf97440afb513b60f84b0ecaa3153a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 18:16:37 +0000 Subject: [PATCH 006/151] readme --- kernel-rs/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index fe70ace6..26fb2ac5 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -2,6 +2,15 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) # compiling +## dependencies + +`pacman -S \ + grub2\ + xorriso\ + mtools\ + binutils +` + a standard development environment can be invoked: ``` From c78d7a06aa2e6cb6a5cc3b498f06e97b77d59aeb Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:17:19 +0100 Subject: [PATCH 007/151] Update README.md --- kernel-rs/README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 26fb2ac5..9821c5db 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,13 +4,9 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) ## dependencies -`pacman -S \ - grub2\ - xorriso\ - mtools\ - binutils -` +`pacman -S grub2 xorriso mtools binutils` +## docker a standard development environment can be invoked: ``` From b77dcc8ee3a53b4ad8fb821a6183fffb3a8c5bef Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:17:35 +0100 Subject: [PATCH 008/151] Update README.md --- kernel-rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 9821c5db..1aad36dc 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,7 +4,7 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) ## dependencies -`pacman -S grub2 xorriso mtools binutils` +for archlinux `pacman -S make grub2 xorriso mtools binutils` ## docker a standard development environment can be invoked: From a13899fd59477926f6857af15075cb97fac51dd4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:37:15 +0100 Subject: [PATCH 009/151] Update README.md --- kernel-rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 1aad36dc..4fa8a25a 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,7 +4,7 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) ## dependencies -for archlinux `pacman -S make grub2 xorriso mtools binutils` +for archlinux `pacman -S make grub2 xorriso mtools binutils rustup` ## docker a standard development environment can be invoked: From 84b5dcbb8b2cfe5bdd85625c4d9488c3e40d29a2 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:42:05 +0100 Subject: [PATCH 010/151] Update README.md --- kernel-rs/README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 4fa8a25a..29a8bf33 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -2,9 +2,18 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) # compiling -## dependencies +## dependencies for assembly and boot -for archlinux `pacman -S make grub2 xorriso mtools binutils rustup` +grub is the default bootloader, we need `ld` and `nasm` to compile the bootcode +for archlinux `pacman -S make grub2 xorriso mtools binutils` + +## rust setup + +``` +pacman -S rustup +rustup component add rust-src +cargo install xargo +``` ## docker a standard development environment can be invoked: From 808a111b04b46dba139b6dbe5d5254cec5a45412 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:42:19 +0100 Subject: [PATCH 011/151] Update README.md --- kernel-rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 29a8bf33..42f1a8e3 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,7 +4,7 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) ## dependencies for assembly and boot -grub is the default bootloader, we need `ld` and `nasm` to compile the bootcode +grub is the default bootloader, we need `ld` and `nasm` to compile the bootcode for archlinux `pacman -S make grub2 xorriso mtools binutils` ## rust setup From 88020a6fc35709a5f08a9e86c04a1ba3eb3df47d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:48:13 +0100 Subject: [PATCH 012/151] Update README.md --- kernel-rs/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 42f1a8e3..20331f3e 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,8 +4,13 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) ## dependencies for assembly and boot -grub is the default bootloader, we need `ld` and `nasm` to compile the bootcode -for archlinux `pacman -S make grub2 xorriso mtools binutils` + - `nasm` compiles the bootcode + - `ld` links the bootcode + - `grub-mkrescue` builds the iso + - `xargo` builds rust code + - `qemu` runs the iso + +on archlinux `pacman -S make grub2 xorriso mtools binutils gcc qemu` ## rust setup From 4c019ca6951618719fb105a3f624124d4a6dced7 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 19:48:28 +0100 Subject: [PATCH 013/151] Update README.md --- kernel-rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 20331f3e..f68da820 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -2,7 +2,7 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) # compiling -## dependencies for assembly and boot +## dependencies - `nasm` compiles the bootcode - `ld` links the bootcode From b347842b8d3428c83a03549328b02bc5abf1e366 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 4 Feb 2018 18:57:20 +0000 Subject: [PATCH 014/151] rust setup stuff --- kernel-rs/Cargo.toml | 7 +++++++ kernel-rs/Makefile | 14 +++++++++++--- kernel-rs/src/arch/x86_64/long_mode_init.asm | 4 ++++ kernel-rs/src/lib.rs | 8 ++++++++ kernel-rs/x86_64-KFS.json | 12 ++++++++++++ 5 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 kernel-rs/Cargo.toml create mode 100755 kernel-rs/src/lib.rs create mode 100644 kernel-rs/x86_64-KFS.json diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml new file mode 100644 index 00000000..765e83c8 --- /dev/null +++ b/kernel-rs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "kfs" +version = "0.1.0" +authors = ["Jack Halford "] + +[lib] +crate-type = ["staticlib"] diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 19b2e1b3..b43759b2 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -2,12 +2,16 @@ arch ?= x86_64 kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso +target ?= $(arch)-KFS +rust_os := target/$(target)/debug/libkfs.a + linker_script := src/arch/$(arch)/linker.ld grub.cfg := src/arch/$(arch)/grub.cfg asm_source_files := $(wildcard src/arch/$(arch)/*.asm) asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ build/arch/$(arch)/%.o, $(asm_source_files)) -.PHONY: all clean run iso + +.PHONY: all clean run iso kernel all: $(kernel) @@ -26,8 +30,12 @@ $(iso): $(kernel) $(grub.cfg) grub-mkrescue -o $(iso) build/isofiles 2>/dev/null rm -r build/isofiles -$(kernel): $(asm_object_files) $(linker_script) - @ld -n -T $(linker_script) -o $(kernel) $(asm_object_files) +$(kernel): kernel $(asm_object_files) $(linker_script) + @ld -n -T $(linker_script) -o $(kernel) \ + $(asm_object_files) $(rust_os) + +kernel: + @xargo build --target $(target) # compile asm files build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm diff --git a/kernel-rs/src/arch/x86_64/long_mode_init.asm b/kernel-rs/src/arch/x86_64/long_mode_init.asm index 318764af..5b693dd1 100644 --- a/kernel-rs/src/arch/x86_64/long_mode_init.asm +++ b/kernel-rs/src/arch/x86_64/long_mode_init.asm @@ -10,6 +10,10 @@ long_mode_start: mov es, ax mov fs, ax mov gs, ax + + extern rust_main + call rust_main + ;print 'OKAY' to screen mov rax, 0x2f592f412f4b2f4f mov qword [0xb8000], rax diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs new file mode 100755 index 00000000..e65b4ff0 --- /dev/null +++ b/kernel-rs/src/lib.rs @@ -0,0 +1,8 @@ +#![feature(lang_items)] +#![no_std] + +#[no_mangle] +pub extern fn rust_main() {} + +#[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} +#[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt() -> ! {loop{}} diff --git a/kernel-rs/x86_64-KFS.json b/kernel-rs/x86_64-KFS.json new file mode 100644 index 00000000..ab1cb664 --- /dev/null +++ b/kernel-rs/x86_64-KFS.json @@ -0,0 +1,12 @@ +{ + "llvm-target": "x86_64-unknown-none", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "linker-flavor": "gcc", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "arch": "x86_64", + "os": "none", + "disable-redzone": true, + "features": "-mmx,-sse,+soft-float" +} From aea724a64d6dfffa26efd6b5e7c7f86e2d7a7534 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Feb 2018 10:28:16 +0100 Subject: [PATCH 015/151] Update README.md --- kernel-rs/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index f68da820..b6eb0cce 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -16,6 +16,7 @@ on archlinux `pacman -S make grub2 xorriso mtools binutils gcc qemu` ``` pacman -S rustup +rustup override add nightly rustup component add rust-src cargo install xargo ``` From 2b4ee5d846c347b9b8014e7325bdea31ef269768 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Feb 2018 11:16:01 +0100 Subject: [PATCH 016/151] Update README.md --- kernel-rs/README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index b6eb0cce..ef0dd502 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -1,8 +1,8 @@ -based on [Writing an OS in rust](https://os.phil-opp.com/) +Kernel from scratch (KFS) series of projects at Ecole 42 ! # compiling -## dependencies +### dependencies - `nasm` compiles the bootcode - `ld` links the bootcode @@ -12,7 +12,7 @@ based on [Writing an OS in rust](https://os.phil-opp.com/) on archlinux `pacman -S make grub2 xorriso mtools binutils gcc qemu` -## rust setup +### rust setup ``` pacman -S rustup @@ -21,7 +21,7 @@ rustup component add rust-src cargo install xargo ``` -## docker +### docker a standard development environment can be invoked: ``` @@ -33,3 +33,8 @@ clone the repo and `make iso` # running `make run` in your host operating system to launch qemu gtk window + +# References + + - [Rust page on OSDev wiki](https://wiki.osdev.org/Rust) + - [Writing an OS in rust](https://os.phil-opp.com/) extremely helpful to get things going on x86 and nightly rust From deb033ff50e70652e28b8d2309feb3addb00bd5e Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Feb 2018 18:13:10 +0100 Subject: [PATCH 017/151] stuck in the middle of paging --- kernel-rs/Cargo.toml | 7 + kernel-rs/Makefile | 10 +- kernel-rs/src/arch/x86_64/boot.asm | 15 +- kernel-rs/src/arch/x86_64/linker.ld | 12 +- kernel-rs/src/arch/x86_64/long_mode_init.asm | 6 +- kernel-rs/src/lib.rs | 67 ++++++++- kernel-rs/src/memory/area_frame_allocator.rs | 92 ++++++++++++ kernel-rs/src/memory/mod.rs | 28 ++++ kernel-rs/src/memory/paging/entry.rs | 47 ++++++ kernel-rs/src/memory/paging/mod.rs | 10 ++ kernel-rs/src/memory/paging/table.rs | 51 +++++++ kernel-rs/src/vga_buffer.rs | 148 +++++++++++++++++++ kernel-rs/x86_64-KFS.json | 3 +- 13 files changed, 480 insertions(+), 16 deletions(-) create mode 100644 kernel-rs/src/memory/area_frame_allocator.rs create mode 100644 kernel-rs/src/memory/mod.rs create mode 100644 kernel-rs/src/memory/paging/entry.rs create mode 100644 kernel-rs/src/memory/paging/mod.rs create mode 100644 kernel-rs/src/memory/paging/table.rs create mode 100644 kernel-rs/src/vga_buffer.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 765e83c8..7f432ba4 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -5,3 +5,10 @@ authors = ["Jack Halford "] [lib] crate-type = ["staticlib"] + +[dependencies] +rlibc = "1.0" +volatile = "0.1.0" +spin = "0.4.5" +multiboot2 = "0.1.0" +bitflags = "0.9.1" diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index b43759b2..881368fc 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -2,7 +2,7 @@ arch ?= x86_64 kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso -target ?= $(arch)-KFS +target ?= $(arch)-kfs rust_os := target/$(target)/debug/libkfs.a linker_script := src/arch/$(arch)/linker.ld @@ -16,9 +16,10 @@ asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ all: $(kernel) clean: + @cargo clean @rm -r build -run: $(iso) +run: @qemu-system-x86_64 -cdrom $(iso) iso: $(iso) @@ -31,11 +32,10 @@ $(iso): $(kernel) $(grub.cfg) rm -r build/isofiles $(kernel): kernel $(asm_object_files) $(linker_script) - @ld -n -T $(linker_script) -o $(kernel) \ - $(asm_object_files) $(rust_os) + @ld -n --gc-sections -T $(linker_script) -o $(kernel) $(asm_object_files) $(rust_os) kernel: - @xargo build --target $(target) + @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target) # compile asm files build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm index e4037e21..2cb30b12 100644 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ b/kernel-rs/src/arch/x86_64/boot.asm @@ -6,6 +6,10 @@ bits 32 start: mov esp, stack_top + ; Move multiboot info pointer to edi + ; which is the first argument for the rust main + mov edi, ebx + call check_multiboot call check_cpuid call check_long_mode @@ -86,14 +90,19 @@ check_long_mode: jmp error set_up_page_tables: + ; map P4 511th byte recursively to P4 + mov eax, p4_table + or eax, 0b11 ; present + writable + mov [p4_table + 511 * 8], eax + ; map first P4 entry to P3 table mov eax, p3_table - or eax, 0b11 ; present + writeable + or eax, 0b11 ; present + writable mov [p4_table], eax ; map first P3 entry to P2 table mov eax, p2_table - or eax, 0b11 ; present + writeable + or eax, 0b11 ; present + writable mov [p3_table], eax mov ecx, 0 ;counter variable @@ -142,7 +151,7 @@ p3_table: p2_table: resb 4096 stack_bottom: - resb 64 + resb 4096 * 4 stack_top: section .rodata diff --git a/kernel-rs/src/arch/x86_64/linker.ld b/kernel-rs/src/arch/x86_64/linker.ld index 89751965..06648ad5 100644 --- a/kernel-rs/src/arch/x86_64/linker.ld +++ b/kernel-rs/src/arch/x86_64/linker.ld @@ -6,11 +6,19 @@ SECTIONS { .boot : { /* ensure that the multiboot header is at the beginning */ - *(.multiboot_header) + KEEP(*(.multiboot_header)) } .text : { - *(.text) + *(.text .text.*) + } + + .rodata : { + *(.rodata .rodata.*) + } + + .data.rel.ro : { + *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) } } diff --git a/kernel-rs/src/arch/x86_64/long_mode_init.asm b/kernel-rs/src/arch/x86_64/long_mode_init.asm index 5b693dd1..e89e7955 100644 --- a/kernel-rs/src/arch/x86_64/long_mode_init.asm +++ b/kernel-rs/src/arch/x86_64/long_mode_init.asm @@ -14,7 +14,7 @@ long_mode_start: extern rust_main call rust_main - ;print 'OKAY' to screen - mov rax, 0x2f592f412f4b2f4f - mov qword [0xb8000], rax + ;;print 'OKAY' to screen + ;mov rax, 0x2f592f412f4b2f4f + ;mov qword [0xb8000], rax hlt diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index e65b4ff0..11c52c83 100755 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,8 +1,71 @@ #![feature(lang_items)] +#![feature(const_fn)] +#![feature(ptr_internals)] #![no_std] +extern crate rlibc; +extern crate volatile; +extern crate spin; +extern crate multiboot2; +#[macro_use] extern crate bitflags; +#[macro_use] mod vga_buffer; +mod memory; + #[no_mangle] -pub extern fn rust_main() {} +pub extern fn rust_main(multiboot_information_address: usize) { + use memory::FrameAllocator; + + vga_buffer::clear_screen(); + println!("Hello World {}", "!"); + + let boot_info = unsafe{ multiboot2::load(multiboot_information_address)}; + + let memory_map_tag = boot_info.memory_map_tag() + .expect("Memory map tag required"); + println!("memory areas:"); + for area in memory_map_tag.memory_areas() { + println!(" start: 0x{:x}, length: 0x{:x}", + area.base_addr, area.length); + } + + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("ELF sections tag required"); + println!("kernel sections:"); + for section in elf_sections_tag.sections() { + println!(" addr: 0x{:x}, length: 0x{:x}, flags: 0x{:x}", + section.addr, section.size, section.flags); + } + + let kernel_start = elf_sections_tag.sections().map(|s| s.addr) + .min().unwrap(); + let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size) + .max().unwrap(); + + let multiboot_start = multiboot_information_address; + let multiboot_end = multiboot_start + (boot_info.total_size as usize); + + let mut frame_allocator = memory::AreaFrameAllocator::new( + kernel_start as usize, kernel_end as usize, multiboot_start, + multiboot_end, memory_map_tag.memory_areas() + ); + + for i in 0.. { + if let None = frame_allocator.allocate_frame() { + println!("allocated {} frames", i); + break; + } + } + + loop{}; +} #[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} -#[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt() -> ! {loop{}} + +#[lang = "panic_fmt"] +#[no_mangle] +pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, + line: u32) -> ! { + println!("\n\nPANIC in {} at line {}:", file, line); + println!(" {}", fmt); + loop{} +} diff --git a/kernel-rs/src/memory/area_frame_allocator.rs b/kernel-rs/src/memory/area_frame_allocator.rs new file mode 100644 index 00000000..123aa879 --- /dev/null +++ b/kernel-rs/src/memory/area_frame_allocator.rs @@ -0,0 +1,92 @@ +use memory::{Frame, FrameAllocator}; +use multiboot2::{MemoryAreaIter, MemoryArea}; + +pub struct AreaFrameAllocator { + next_free_frame: Frame, + current_area: Option<&'static MemoryArea>, + areas: MemoryAreaIter, + kernel_start: Frame, + kernel_end: Frame, + multiboot_start: Frame, + multiboot_end: Frame, +} + +impl AreaFrameAllocator { + pub fn new( + kernel_start: usize, + kernel_end: usize, + multiboot_start: usize, + multiboot_end: usize, + memory_areas: MemoryAreaIter + ) -> AreaFrameAllocator { + let mut allocator = AreaFrameAllocator { + next_free_frame: Frame::containing_address(0), + current_area: None, + areas: memory_areas, + kernel_start: Frame::containing_address(kernel_start), + kernel_end: Frame::containing_address(kernel_end), + multiboot_start: Frame::containing_address(multiboot_start), + multiboot_end: Frame::containing_address(multiboot_end), + }; + allocator.choose_next_area(); + allocator + } + + fn choose_next_area(&mut self) { + self.current_area = self.areas.clone().filter(|area| { + let address = area.base_addr + area.length - 1; + Frame::containing_address(address as usize) >= self.next_free_frame + }).min_by_key(|area| area.base_addr); + + if let Some(area) = self.current_area { + let start_frame = Frame::containing_address(area.base_addr as usize); + if self.next_free_frame < start_frame { + self.next_free_frame = start_frame; + } + } + } +} + +impl FrameAllocator for AreaFrameAllocator { + fn allocate_frame(&mut self) -> Option { + if let Some(area) = self.current_area { + // "Clone" the frame to return it if it's free. Frame doesn't + // implement Clone, but we can construct an identical frame. + let frame = Frame{ number: self.next_free_frame.number }; + + // the last frame of the current area + let current_area_last_frame = { + let address = area.base_addr + area.length - 1; + Frame::containing_address(address as usize) + }; + + if frame > current_area_last_frame { + // all frames of current area are used, switch to next area + self.choose_next_area(); + } else if frame >= self.kernel_start && frame <= self.kernel_end { + // 'frame' is used by the kernel + self.next_free_frame = Frame { + number: self.kernel_end.number + 1 + }; + } else if frame >= self.multiboot_start && frame <= self.multiboot_end { + // 'frame' is used by the multiboot information structure + self.next_free_frame = Frame { + number: self.multiboot_end.number + 1 + }; + } else { + // 'frame' is unused, increment next_free_frame and return it; + self.next_free_frame.number += 1; + return Some(frame) + }; + // frame was not valid, try it again with the updated next_free_frame + self.allocate_frame() + } else { + None // no free frames left + } + } + + fn deallocate_frame(&mut self, frame: Frame) { + unimplemented!() + } + +} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs new file mode 100644 index 00000000..a1358219 --- /dev/null +++ b/kernel-rs/src/memory/mod.rs @@ -0,0 +1,28 @@ +pub use self::area_frame_allocator::AreaFrameAllocator; +use self::paging::PhysicalAddress; + +mod area_frame_allocator; +mod paging; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Frame { + number: usize, +} + +pub const PAGE_SIZE: usize = 4096; + + +impl Frame { + fn containing_address(address: usize) -> Frame { + Frame{ number: address / PAGE_SIZE } + } + + fn start_address(&self) -> PhysicalAddress { + self.number * PAGE_SIZE + } +} + +pub trait FrameAllocator { + fn allocate_frame(&mut self) -> Option; + fn deallocate_frame(&mut self, frame: Frame); +} diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs new file mode 100644 index 00000000..18415098 --- /dev/null +++ b/kernel-rs/src/memory/paging/entry.rs @@ -0,0 +1,47 @@ +use memory::Frame; + +pub struct Entry(u64) + +bitflags! { + pub struct EntryFlags: u64 { + const PRESENT = 1 << 0; + const WRITABLE = 1 << 1; + const USER_ACCESSIBLE = 1 << 2; + const WRITE_THROUGH = 1 << 3; + const NO_CACHE = 1 << 4; + const ACCESSED = 1 << 5; + const DIRTY = 1 << 6; + const HUGE_PAGE = 1 << 7; + const GLOBAL = 1 << 8; + const NO_EXECUTE = 1 << 63; + } +} + +impl Entry { + pub fn is_unused(&self) -> bool { + self.0 == 0; + } + + pub fn set_unused(&mut self) { + self.0 = 0; + } + + pub fn flags(&self) -> EntryFlags { + EntryFlags::from_bits_truncate(self.0) + } + + pub fn pointed_frame(&self) -> Option { + if self.flags().contains(PRESENT) { + Some(Frame::containing_address( + self.0 as usize & 0x000fffff_fffff000 + )) + } else { + None + } + } + + pub fn set(&mut self, frame: Frame, flags: EntryFlags) { + assert!(frame.start_address() & !0x000fffff_fffff000 == 0); + self.0 = (frame.start_address() as u64) | flags.bits(); + } +} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs new file mode 100644 index 00000000..17896565 --- /dev/null +++ b/kernel-rs/src/memory/paging/mod.rs @@ -0,0 +1,10 @@ +use memory::PAGE_SIZE; + +const ENTRY_COUNT: usize = 512; + +pub type PhysicalAddress = usize; +pub type VirtualAddress = usize; + +pub struct Page { + number: usize, +} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs new file mode 100644 index 00000000..e8b1244d --- /dev/null +++ b/kernel-rs/src/memory/paging/table.rs @@ -0,0 +1,51 @@ +use memory::paging::entry::* +use memory::paging::ENTRY_COUNT; +use core::ops::{Index, IndexMut}; + +pub const P4: *mut Table = 0xffffffff_fffff000 as *mut _; + +pub struct Table { + entries: [Entry; ENTRY_COUNT], +} + +impl Index for Table { + type Output = Entry; + + fn index(&sef, index: usize) -> &Entry { + &self.entries[index] + } +} + +impl IndexMut for Table { + fn index_mut(&mut self, index: usize) -> &mut Entry { + &mut self.entries[index] + } +} + +impl Table { + pub fn zero(&mut self) { + for entry in self.entries.iter_mut() { + entry.set_unused(); + } + } + + pub fn next_table(&self, index: usize) -> Option<&Table> { + self.next_table_address(index) + .map(|address| unsafe { &*(address as *const _) }) + } + + pub fn next_table_mut(&self, index: usize) -> Option<&mut Table> { + self.next_table_address(index) + .map(|address| unsafe { &*(address as *mut _) }) + } + + fn next_table_address(&self, index: usize) -> Option { + let entry_flags = self[index].flags(); + if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) { + let table_address = self as *const _ as usize; + Some((table_address << 9) | (index << 12)) + } else { + None + } + } +} diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs new file mode 100644 index 00000000..394ded69 --- /dev/null +++ b/kernel-rs/src/vga_buffer.rs @@ -0,0 +1,148 @@ +use core::ptr::Unique; +use volatile::Volatile; +use core::fmt; +use spin::Mutex; + +pub static WRITER: Mutex = Mutex::new(Writer { + column_position: 0, + color_code: ColorCode::new(Color::LightRed, Color::Black), + buffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, +}); + +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::vga_buffer::print(format_args!($($arg)*)); + }); +} + +pub fn print(args: fmt::Arguments) { + use core::fmt::Write; + WRITER.lock().write_fmt(args).unwrap(); +} + +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> fmt::Result { + for byte in s.bytes() { + self.write_byte(byte) + } + Ok(()) + } +} + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} + +#[derive(Debug, Clone, Copy)] +struct ColorCode(u8); + +impl ColorCode { + const fn new(foreground: Color, background: Color) -> ColorCode { + ColorCode((background as u8) << 4 | (foreground as u8)) + } +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct ScreenChar { + ascii_character: u8, + color_code: ColorCode, +} + +const BUFFER_HEIGHT: usize = 25; +const BUFFER_WIDTH: usize = 80; + +struct Buffer { + chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT] +} + +pub struct Writer { + column_position: usize, + color_code: ColorCode, + buffer: Unique, +} + +#[allow(dead_code)] +impl Writer { + pub fn write_byte(&mut self, byte: u8) { + match byte { + b'\n' => self.new_line(), + byte => { + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } + + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + + let color_code = self.color_code; + self.buffer().chars[row][col].write(ScreenChar { + ascii_character: byte, + color_code: color_code, + }); + self.column_position += 1; + } + } + } + + pub fn write_str(&mut self, s: &str) { + for byte in s.bytes() { + self.write_byte(byte) + } + } + + fn buffer(&mut self) -> &mut Buffer { + unsafe{ self.buffer.as_mut()} + } + + fn new_line(&mut self) { + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + let buffer = self.buffer(); + let character = buffer.chars[row][col].read(); + buffer.chars[row - 1][col].write(character); + } + } + self.clear_row(BUFFER_HEIGHT - 1); + self.column_position = 0; + } + + fn clear_row(&mut self, row: usize) { + let blank = ScreenChar { + ascii_character: b' ', + color_code: self.color_code, + }; + for col in 0..BUFFER_WIDTH { + self.buffer().chars[row][col].write(blank); + } + } +} + +pub fn clear_screen() { + for _ in 0..BUFFER_HEIGHT { + println!(""); + } +} diff --git a/kernel-rs/x86_64-KFS.json b/kernel-rs/x86_64-KFS.json index ab1cb664..d2fa22e1 100644 --- a/kernel-rs/x86_64-KFS.json +++ b/kernel-rs/x86_64-KFS.json @@ -8,5 +8,6 @@ "arch": "x86_64", "os": "none", "disable-redzone": true, - "features": "-mmx,-sse,+soft-float" + "features": "-mmx,-sse,+soft-float", + "panic-strategy": "abort" } From 1bfdff2a766e3d3a1c0484c5ecc837f680ae4a1f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Feb 2018 20:15:08 +0100 Subject: [PATCH 018/151] comments --- kernel-rs/src/memory/area_frame_allocator.rs | 2 ++ kernel-rs/src/memory/mod.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel-rs/src/memory/area_frame_allocator.rs b/kernel-rs/src/memory/area_frame_allocator.rs index 123aa879..3693f45d 100644 --- a/kernel-rs/src/memory/area_frame_allocator.rs +++ b/kernel-rs/src/memory/area_frame_allocator.rs @@ -34,6 +34,8 @@ impl AreaFrameAllocator { fn choose_next_area(&mut self) { self.current_area = self.areas.clone().filter(|area| { + // filter in areas with remaining free frames + // i.e. next_free_frame is before the last frame let address = area.base_addr + area.length - 1; Frame::containing_address(address as usize) >= self.next_free_frame }).min_by_key(|area| area.base_addr); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index a1358219..8cd88e6e 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -11,7 +11,6 @@ pub struct Frame { pub const PAGE_SIZE: usize = 4096; - impl Frame { fn containing_address(address: usize) -> Frame { Frame{ number: address / PAGE_SIZE } From 6c252fb5dae52c35907c5117f8c84b6636eeb034 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 6 Feb 2018 14:44:29 +0100 Subject: [PATCH 019/151] Update README.md --- kernel-rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index ef0dd502..33b89b5f 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -10,7 +10,7 @@ Kernel from scratch (KFS) series of projects at Ecole 42 ! - `xargo` builds rust code - `qemu` runs the iso -on archlinux `pacman -S make grub2 xorriso mtools binutils gcc qemu` +on archlinux `pacman -S make grub xorriso mtools binutils gcc qemu` ### rust setup From aec4b53e53c5b46de8a9d16214292820617e70a1 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 6 Feb 2018 23:39:33 +0100 Subject: [PATCH 020/151] stuff --- kernel-rs/src/arch/x86_64/boot.asm | 3 +- kernel-rs/src/lib.rs | 58 +++++++++--------------------- kernel-rs/src/vga_buffer.rs | 16 ++++----- 3 files changed, 27 insertions(+), 50 deletions(-) diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm index 2cb30b12..d17c833e 100644 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ b/kernel-rs/src/arch/x86_64/boot.asm @@ -142,8 +142,9 @@ enable_paging: ret + section .bss - align 4096 +align 4096 p4_table: resb 4096 p3_table: diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 11c52c83..cc210957 100755 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,6 +1,7 @@ #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] +#![feature(asm)] #![no_std] extern crate rlibc; @@ -8,55 +9,30 @@ extern crate volatile; extern crate spin; extern crate multiboot2; #[macro_use] extern crate bitflags; + #[macro_use] mod vga_buffer; -mod memory; + + +// mod memory; #[no_mangle] pub extern fn rust_main(multiboot_information_address: usize) { - use memory::FrameAllocator; - vga_buffer::clear_screen(); - println!("Hello World {}", "!"); - let boot_info = unsafe{ multiboot2::load(multiboot_information_address)}; + use core::ptr::{read_volatile, write_volatile}; + let kbd1 = &0x60 as *const i32; + let kbd2 = &0x64 as *const i32; - let memory_map_tag = boot_info.memory_map_tag() - .expect("Memory map tag required"); - println!("memory areas:"); - for area in memory_map_tag.memory_areas() { - println!(" start: 0x{:x}, length: 0x{:x}", - area.base_addr, area.length); - } - - let elf_sections_tag = boot_info.elf_sections_tag() - .expect("ELF sections tag required"); - println!("kernel sections:"); - for section in elf_sections_tag.sections() { - println!(" addr: 0x{:x}, length: 0x{:x}, flags: 0x{:x}", - section.addr, section.size, section.flags); - } - - let kernel_start = elf_sections_tag.sections().map(|s| s.addr) - .min().unwrap(); - let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size) - .max().unwrap(); - - let multiboot_start = multiboot_information_address; - let multiboot_end = multiboot_start + (boot_info.total_size as usize); - - let mut frame_allocator = memory::AreaFrameAllocator::new( - kernel_start as usize, kernel_end as usize, multiboot_start, - multiboot_end, memory_map_tag.memory_areas() - ); - - for i in 0.. { - if let None = frame_allocator.allocate_frame() { - println!("allocated {} frames", i); - break; + loop{ + unsafe { + if (read_volatile(kbd1) != 96) { + println!("0x60: {} !!!!!!", read_volatile(kbd1)); + break; + } + println!("0x60: {} 0x64: {}", + read_volatile(kbd1), read_volatile(kbd2) ); } - } - - loop{}; + }; } #[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs index 394ded69..76473320 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga_buffer.rs @@ -5,7 +5,7 @@ use spin::Mutex; pub static WRITER: Mutex = Mutex::new(Writer { column_position: 0, - color_code: ColorCode::new(Color::LightRed, Color::Black), + color_code: ColorCode::new(Color::Green, Color::Black), buffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, }); @@ -28,7 +28,7 @@ pub fn print(args: fmt::Arguments) { impl fmt::Write for Writer { fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { - self.write_byte(byte) + self.putchar(byte) } Ok(()) } @@ -87,12 +87,12 @@ pub struct Writer { #[allow(dead_code)] impl Writer { - pub fn write_byte(&mut self, byte: u8) { + pub fn putchar(&mut self, byte: u8) { match byte { - b'\n' => self.new_line(), + b'\n' => self.put_endl(), byte => { if self.column_position >= BUFFER_WIDTH { - self.new_line(); + self.put_endl(); } let row = BUFFER_HEIGHT - 1; @@ -108,9 +108,9 @@ impl Writer { } } - pub fn write_str(&mut self, s: &str) { + pub fn putstr(&mut self, s: &str) { for byte in s.bytes() { - self.write_byte(byte) + self.putchar(byte) } } @@ -118,7 +118,7 @@ impl Writer { unsafe{ self.buffer.as_mut()} } - fn new_line(&mut self) { + fn put_endl(&mut self) { for row in 1..BUFFER_HEIGHT { for col in 0..BUFFER_WIDTH { let buffer = self.buffer(); From 612662870c117751a904ab69dc4b88d16a45bdf9 Mon Sep 17 00:00:00 2001 From: wescande Date: Wed, 7 Feb 2018 20:01:36 +0100 Subject: [PATCH 021/151] make split tmux screen --- kernel-rs/Makefile | 8 +++++++- kernel-rs/{x86_64-KFS.json => x86_64-kfs.json} | 0 2 files changed, 7 insertions(+), 1 deletion(-) rename kernel-rs/{x86_64-KFS.json => x86_64-kfs.json} (100%) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 881368fc..da90be37 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -12,6 +12,7 @@ asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ build/arch/$(arch)/%.o, $(asm_source_files)) .PHONY: all clean run iso kernel +SHELL := /bin/bash all: $(kernel) @@ -20,7 +21,12 @@ clean: @rm -r build run: - @qemu-system-x86_64 -cdrom $(iso) + @qemu-system-x86_64 -curses -cdrom $(iso) + +devrun: + @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } + @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" + @qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait -curses -cdrom build/os-x86_64.iso iso: $(iso) diff --git a/kernel-rs/x86_64-KFS.json b/kernel-rs/x86_64-kfs.json similarity index 100% rename from kernel-rs/x86_64-KFS.json rename to kernel-rs/x86_64-kfs.json From 69299bda2db9cdfabc8c89e65b8989ae9ac28875 Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 8 Feb 2018 19:18:14 +0100 Subject: [PATCH 022/151] basic rust call in 32b --- kernel-rs/Cargo.toml | 12 +- kernel-rs/Makefile | 71 ++++---- kernel-rs/src/arch/x86/boot.asm | 23 +++ kernel-rs/src/arch/x86/grub.cfg | 7 + kernel-rs/src/arch/x86/linker.ld | 15 ++ .../arch/{x86_64 => x86}/multiboot_header.asm | 14 +- kernel-rs/src/arch/x86_64/boot.asm | 165 ------------------ kernel-rs/src/arch/x86_64/grub.cfg | 7 - kernel-rs/src/arch/x86_64/linker.ld | 24 --- kernel-rs/src/arch/x86_64/long_mode_init.asm | 20 --- kernel-rs/src/lib.rs | 67 +++---- kernel-rs/src/memory/area_frame_allocator.rs | 94 ---------- kernel-rs/src/memory/mod.rs | 27 --- kernel-rs/src/memory/paging/entry.rs | 47 ----- kernel-rs/src/memory/paging/mod.rs | 10 -- kernel-rs/src/memory/paging/table.rs | 51 ------ kernel-rs/src/vga_buffer.rs | 148 ---------------- kernel-rs/x86-bluesnow.json | 15 ++ kernel-rs/x86_64-kfs.json | 13 -- 19 files changed, 136 insertions(+), 694 deletions(-) create mode 100644 kernel-rs/src/arch/x86/boot.asm create mode 100644 kernel-rs/src/arch/x86/grub.cfg create mode 100644 kernel-rs/src/arch/x86/linker.ld rename kernel-rs/src/arch/{x86_64 => x86}/multiboot_header.asm (66%) delete mode 100644 kernel-rs/src/arch/x86_64/boot.asm delete mode 100644 kernel-rs/src/arch/x86_64/grub.cfg delete mode 100644 kernel-rs/src/arch/x86_64/linker.ld delete mode 100644 kernel-rs/src/arch/x86_64/long_mode_init.asm mode change 100755 => 100644 kernel-rs/src/lib.rs delete mode 100644 kernel-rs/src/memory/area_frame_allocator.rs delete mode 100644 kernel-rs/src/memory/mod.rs delete mode 100644 kernel-rs/src/memory/paging/entry.rs delete mode 100644 kernel-rs/src/memory/paging/mod.rs delete mode 100644 kernel-rs/src/memory/paging/table.rs delete mode 100644 kernel-rs/src/vga_buffer.rs create mode 100644 kernel-rs/x86-bluesnow.json delete mode 100644 kernel-rs/x86_64-kfs.json diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 7f432ba4..6a7f203c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -1,14 +1,12 @@ [package] -name = "kfs" +name = "bluesnow" version = "0.1.0" -authors = ["Jack Halford "] +authors = ["Jack Halford ", "William Escande "] [lib] crate-type = ["staticlib"] +[profile.release] +panic = "abort" + [dependencies] -rlibc = "1.0" -volatile = "0.1.0" -spin = "0.4.5" -multiboot2 = "0.1.0" -bitflags = "0.9.1" diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index da90be37..a31c2d95 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,49 +1,50 @@ -arch ?= x86_64 +project := bluesnow +arch ?= x86 +NASM := nasm -f elf +LD := ld -m elf_i386 -n +QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait + kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso +DIRISO := build/isofiles -target ?= $(arch)-kfs -rust_os := target/$(target)/debug/libkfs.a +target ?= $(arch)-$(project) +rust_os := target/$(target)/release/lib$(project).a +SHELL := /bin/bash -linker_script := src/arch/$(arch)/linker.ld -grub.cfg := src/arch/$(arch)/grub.cfg -asm_source_files := $(wildcard src/arch/$(arch)/*.asm) -asm_object_files := $(patsubst src/arch/$(arch)/%.asm, \ - build/arch/$(arch)/%.o, $(asm_source_files)) - -.PHONY: all clean run iso kernel -SHELL := /bin/bash +linker_script := src/arch/$(arch)/linker.ld +grub.cfg := src/arch/$(arch)/grub.cfg +asm_source := $(wildcard src/arch/$(arch)/*.asm) +asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) all: $(kernel) +build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile + @mkdir -p $(shell dirname $@) + @$(NASM) $< -o $@ + +$(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile + @$(LD) -o $(kernel) -T $(linker_script) $(asm_object) $(rust_os) + +$(iso): $(kernel) $(grub.cfg) Makefile + @mkdir -p $(DIRISO)/boot/grub + @cp $(grub.cfg) $(DIRISO)/boot/grub + @cp $(kernel) $(DIRISO)/boot/kernel.bin + @grub-mkrescue -o $(iso) $(DIRISO) 2>/dev/null + +run: $(iso) Makefile + @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } + @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" + @$(QEMU) -curses -cdrom $(iso) + clean: @cargo clean @rm -r build -run: - @qemu-system-x86_64 -curses -cdrom $(iso) - -devrun: - @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" - @qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait -curses -cdrom build/os-x86_64.iso +$(rust_os): $(target).json Makefile + @xargo build --release --target $(target) +kernel: $(rust_os) iso: $(iso) -$(iso): $(kernel) $(grub.cfg) - @mkdir -p build/isofiles/boot/grub - cp $(kernel) build/isofiles/boot/kernel.bin - cp $(grub.cfg) build/isofiles/boot/grub - grub-mkrescue -o $(iso) build/isofiles 2>/dev/null - rm -r build/isofiles - -$(kernel): kernel $(asm_object_files) $(linker_script) - @ld -n --gc-sections -T $(linker_script) -o $(kernel) $(asm_object_files) $(rust_os) - -kernel: - @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target) - -# compile asm files -build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm - @mkdir -p $(shell dirname $@) - @nasm -felf64 $< -o $@ +.PHONY: run clean kernel iso diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm new file mode 100644 index 00000000..8624af56 --- /dev/null +++ b/kernel-rs/src/arch/x86/boot.asm @@ -0,0 +1,23 @@ +global start +extern kmain + +section .text +bits 32 +start: + ; print `OK` to screen + ; mov dword [0xb8000], 0x2f4b2f4f + mov word [0xb8000], 0x0248 ; H + mov word [0xb8002], 0x0265 ; e + mov word [0xb8004], 0x026c ; l + mov word [0xb8006], 0x026c ; l + mov word [0xb8008], 0x026f ; o + mov word [0xb800a], 0x022c ; , + mov word [0xb800c], 0x0220 ; + mov word [0xb800e], 0x0277 ; w + mov word [0xb8010], 0x026f ; o + mov word [0xb8012], 0x0272 ; r + mov word [0xb8014], 0x026c ; l + mov word [0xb8016], 0x0264 ; d + mov word [0xb8018], 0x0221 ; ! + call kmain + hlt diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg new file mode 100644 index 00000000..982ff586 --- /dev/null +++ b/kernel-rs/src/arch/x86/grub.cfg @@ -0,0 +1,7 @@ +set timeout=5 +set default=0 + +menuentry "Blue Snow" { + multiboot2 /boot/kernel.bin + boot +} diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld new file mode 100644 index 00000000..b86d432e --- /dev/null +++ b/kernel-rs/src/arch/x86/linker.ld @@ -0,0 +1,15 @@ +ENTRY(start) +OUTPUT_FORMAT(elf32-i386) + +SECTIONS { + . = 1M; + + .boot : { + /* ensure that the multiboot header is at the beginning */ + *(.multiboot_header) + } + + .text : { + *(.text) + } +} diff --git a/kernel-rs/src/arch/x86_64/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm similarity index 66% rename from kernel-rs/src/arch/x86_64/multiboot_header.asm rename to kernel-rs/src/arch/x86/multiboot_header.asm index 737a2b95..9f87d3bb 100644 --- a/kernel-rs/src/arch/x86_64/multiboot_header.asm +++ b/kernel-rs/src/arch/x86/multiboot_header.asm @@ -1,15 +1,15 @@ section .multiboot_header header_start: dd 0xe85250d6 ; magic number (multiboot 2) - dd 0 ; architecture - (protected mode i386) + dd 0 ; architecture 0 (protected mode i386) dd header_end - header_start ; header length - ; checksum - dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) + + dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)); checksum ; insert optional multiboot tags here - ; required end tag here - dw 0 ; type - dw 0 ; flags - dd 0 ; size + ; required end tag + dw 0 ; type + dw 0 ; flags + dd 8 ; size header_end: diff --git a/kernel-rs/src/arch/x86_64/boot.asm b/kernel-rs/src/arch/x86_64/boot.asm deleted file mode 100644 index d17c833e..00000000 --- a/kernel-rs/src/arch/x86_64/boot.asm +++ /dev/null @@ -1,165 +0,0 @@ -global start -extern long_mode_start - -section .text -bits 32 -start: - mov esp, stack_top - - ; Move multiboot info pointer to edi - ; which is the first argument for the rust main - mov edi, ebx - - call check_multiboot - call check_cpuid - call check_long_mode - - call set_up_page_tables - call enable_paging - - ; load the 64-bit GDT - lgdt [gdt64.pointer] - - jmp gdt64.code:long_mode_start - - ; print 'OK' to screen - mov dword [0xb8000], 0x2f4b2f4f - hlt -error: - ; print 'ERR: ' and the given error code to screen and hangs - mov dword [0xb8000], 0x4f524f45 - mov dword [0xb8004], 0x4f3a4f52 - mov dword [0xb8008], 0x4f204f20 - mov byte [0xb800a], al - hlt - -check_multiboot: - cmp eax, 0x36d76289 - jne .no_multiboot - ret -.no_multiboot: - mov al, "0" - jmp error - -check_cpuid: - ; Check if CPUID is supported by attempting to flip the ID bit (bit 21) - ; in the FLAGS register. If we can flip it, CPUID is available. - - ; Copy FLAGS in to EAX via stack - pushfd - pop eax - ; Copy to ECX as well for comparing later on - mov ecx, eax - ; Flip the ID bit - xor eax, 1 << 21 - ; Copy EAX to FLAGS via the stack - push eax - popfd - ; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported) - pushfd - pop eax - ; Restore FLAGS from the old version stored in ECX (i.e. flipping the - ; ID bit back if it was ever flipped). - push ecx - popfd - - ; Compare EAX and ECX. If they are equal then that means the bit - ; wasn't flipped, and CPUID isn't supported. - cmp eax, ecx - je .no_cpuid - ret -.no_cpuid: - mov al, "1" - jmp error - -check_long_mode: - ; test if extended processor info in available - mov eax, 0x80000000 ; implicit argument for cpuid - cpuid ; get highest supported argument - cmp eax, 0x80000001 ; it needs to be at least 0x80000001 - jb .no_long_mode ; if it's less, the CPU is too old for long mode - - ; use extended info to test if long mode is available - mov eax, 0x80000001 ; argument for extended processor info - cpuid ; returns various feature bits in ecx and edx - test edx, 1 << 29 ; test if the LM-bit is set in the D-register - jz .no_long_mode ; If it's not set, there is no long mode - ret -.no_long_mode: - mov al, "2" - jmp error - -set_up_page_tables: - ; map P4 511th byte recursively to P4 - mov eax, p4_table - or eax, 0b11 ; present + writable - mov [p4_table + 511 * 8], eax - - ; map first P4 entry to P3 table - mov eax, p3_table - or eax, 0b11 ; present + writable - mov [p4_table], eax - - ; map first P3 entry to P2 table - mov eax, p2_table - or eax, 0b11 ; present + writable - mov [p3_table], eax - - mov ecx, 0 ;counter variable -.map_p2_table: - ; map ecx-th P2 entry to a huge page that start at address 2MiB*ecx - mov eax, 0x200000 ; 2MiB - mul ecx ; start address of ecx-th page - or eax, 0b10000011 ; present + writeable + huge - mov [p2_table + ecx * 8], eax ; map ecx-th entry - - inc ecx ; increase counter - cmp ecx, 512 ; if counter == 512, the whole P2 table is mapped - jne .map_p2_table ; else map the next entry - - ret - -enable_paging: - ; load P4 to cr3 register (cpu uses this to acces the P4 table) - mov eax, p4_table - mov cr3, eax - - ; enable PAE-flag in cr4 (Physical Address Extension) - mov eax, cr4 - or eax, 1 << 5 - mov cr4, eax - - ; set the long mode bit in the EFER MSR (model specific register) - mov ecx, 0xC0000080 - rdmsr - or eax, 1 << 8 - wrmsr - - ; enable paging in the cr0 register - mov eax, cr0 - or eax, 1 << 31 - mov cr0, eax - - ret - - -section .bss -align 4096 -p4_table: - resb 4096 -p3_table: - resb 4096 -p2_table: - resb 4096 -stack_bottom: - resb 4096 * 4 -stack_top: - -section .rodata -gdt64: - dq 0 ; zero entry -.code: equ $ - gdt64 - dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment -.pointer: - dw $ - gdt64 - 1 - dq gdt64 diff --git a/kernel-rs/src/arch/x86_64/grub.cfg b/kernel-rs/src/arch/x86_64/grub.cfg deleted file mode 100644 index a1f38c91..00000000 --- a/kernel-rs/src/arch/x86_64/grub.cfg +++ /dev/null @@ -1,7 +0,0 @@ -set timeout=0 -set default=0 - -menuentry "my os" { - multiboot2 /boot/kernel.bin - boot -} diff --git a/kernel-rs/src/arch/x86_64/linker.ld b/kernel-rs/src/arch/x86_64/linker.ld deleted file mode 100644 index 06648ad5..00000000 --- a/kernel-rs/src/arch/x86_64/linker.ld +++ /dev/null @@ -1,24 +0,0 @@ -ENTRY(start) - -SECTIONS { - . = 1M; - - .boot : - { - /* ensure that the multiboot header is at the beginning */ - KEEP(*(.multiboot_header)) - } - - .text : - { - *(.text .text.*) - } - - .rodata : { - *(.rodata .rodata.*) - } - - .data.rel.ro : { - *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) - } -} diff --git a/kernel-rs/src/arch/x86_64/long_mode_init.asm b/kernel-rs/src/arch/x86_64/long_mode_init.asm deleted file mode 100644 index e89e7955..00000000 --- a/kernel-rs/src/arch/x86_64/long_mode_init.asm +++ /dev/null @@ -1,20 +0,0 @@ -global long_mode_start - -section .text -bits 64 -long_mode_start: - ; load 0 into all data segment registers - mov ax, 0 - mov ss, ax - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - extern rust_main - call rust_main - - ;;print 'OKAY' to screen - ;mov rax, 0x2f592f412f4b2f4f - ;mov qword [0xb8000], rax - hlt diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs old mode 100755 new mode 100644 index cc210957..8cc59775 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,47 +1,36 @@ +// #![no_std] +// #[cfg(test)] +// mod tests { +// #[test] +// fn it_works() { +// assert_eq!(2 + 2, 4); +// } +// } + #![feature(lang_items)] -#![feature(const_fn)] -#![feature(ptr_internals)] -#![feature(asm)] #![no_std] -extern crate rlibc; -extern crate volatile; -extern crate spin; -extern crate multiboot2; -#[macro_use] extern crate bitflags; +#[lang = "eh_personality"] +extern fn eh_personality() { -#[macro_use] mod vga_buffer; - - -// mod memory; - -#[no_mangle] -pub extern fn rust_main(multiboot_information_address: usize) { - vga_buffer::clear_screen(); - - use core::ptr::{read_volatile, write_volatile}; - let kbd1 = &0x60 as *const i32; - let kbd2 = &0x64 as *const i32; - - loop{ - unsafe { - if (read_volatile(kbd1) != 96) { - println!("0x60: {} !!!!!!", read_volatile(kbd1)); - break; - } - println!("0x60: {} 0x64: {}", - read_volatile(kbd1), read_volatile(kbd2) ); - } - }; } -#[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() {} - #[lang = "panic_fmt"] -#[no_mangle] -pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, - line: u32) -> ! { - println!("\n\nPANIC in {} at line {}:", file, line); - println!(" {}", fmt); - loop{} +extern fn rust_begin_panic() -> ! { + loop {} + +} + + +#[no_mangle] +pub extern fn kmain() -> ! { + unsafe { + let vga = 0xb8000 as *mut u32; + + *vga = 0x2f592f412f; + + }; + + loop { } + } diff --git a/kernel-rs/src/memory/area_frame_allocator.rs b/kernel-rs/src/memory/area_frame_allocator.rs deleted file mode 100644 index 3693f45d..00000000 --- a/kernel-rs/src/memory/area_frame_allocator.rs +++ /dev/null @@ -1,94 +0,0 @@ -use memory::{Frame, FrameAllocator}; -use multiboot2::{MemoryAreaIter, MemoryArea}; - -pub struct AreaFrameAllocator { - next_free_frame: Frame, - current_area: Option<&'static MemoryArea>, - areas: MemoryAreaIter, - kernel_start: Frame, - kernel_end: Frame, - multiboot_start: Frame, - multiboot_end: Frame, -} - -impl AreaFrameAllocator { - pub fn new( - kernel_start: usize, - kernel_end: usize, - multiboot_start: usize, - multiboot_end: usize, - memory_areas: MemoryAreaIter - ) -> AreaFrameAllocator { - let mut allocator = AreaFrameAllocator { - next_free_frame: Frame::containing_address(0), - current_area: None, - areas: memory_areas, - kernel_start: Frame::containing_address(kernel_start), - kernel_end: Frame::containing_address(kernel_end), - multiboot_start: Frame::containing_address(multiboot_start), - multiboot_end: Frame::containing_address(multiboot_end), - }; - allocator.choose_next_area(); - allocator - } - - fn choose_next_area(&mut self) { - self.current_area = self.areas.clone().filter(|area| { - // filter in areas with remaining free frames - // i.e. next_free_frame is before the last frame - let address = area.base_addr + area.length - 1; - Frame::containing_address(address as usize) >= self.next_free_frame - }).min_by_key(|area| area.base_addr); - - if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(area.base_addr as usize); - if self.next_free_frame < start_frame { - self.next_free_frame = start_frame; - } - } - } -} - -impl FrameAllocator for AreaFrameAllocator { - fn allocate_frame(&mut self) -> Option { - if let Some(area) = self.current_area { - // "Clone" the frame to return it if it's free. Frame doesn't - // implement Clone, but we can construct an identical frame. - let frame = Frame{ number: self.next_free_frame.number }; - - // the last frame of the current area - let current_area_last_frame = { - let address = area.base_addr + area.length - 1; - Frame::containing_address(address as usize) - }; - - if frame > current_area_last_frame { - // all frames of current area are used, switch to next area - self.choose_next_area(); - } else if frame >= self.kernel_start && frame <= self.kernel_end { - // 'frame' is used by the kernel - self.next_free_frame = Frame { - number: self.kernel_end.number + 1 - }; - } else if frame >= self.multiboot_start && frame <= self.multiboot_end { - // 'frame' is used by the multiboot information structure - self.next_free_frame = Frame { - number: self.multiboot_end.number + 1 - }; - } else { - // 'frame' is unused, increment next_free_frame and return it; - self.next_free_frame.number += 1; - return Some(frame) - }; - // frame was not valid, try it again with the updated next_free_frame - self.allocate_frame() - } else { - None // no free frames left - } - } - - fn deallocate_frame(&mut self, frame: Frame) { - unimplemented!() - } - -} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs deleted file mode 100644 index 8cd88e6e..00000000 --- a/kernel-rs/src/memory/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -pub use self::area_frame_allocator::AreaFrameAllocator; -use self::paging::PhysicalAddress; - -mod area_frame_allocator; -mod paging; - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Frame { - number: usize, -} - -pub const PAGE_SIZE: usize = 4096; - -impl Frame { - fn containing_address(address: usize) -> Frame { - Frame{ number: address / PAGE_SIZE } - } - - fn start_address(&self) -> PhysicalAddress { - self.number * PAGE_SIZE - } -} - -pub trait FrameAllocator { - fn allocate_frame(&mut self) -> Option; - fn deallocate_frame(&mut self, frame: Frame); -} diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs deleted file mode 100644 index 18415098..00000000 --- a/kernel-rs/src/memory/paging/entry.rs +++ /dev/null @@ -1,47 +0,0 @@ -use memory::Frame; - -pub struct Entry(u64) - -bitflags! { - pub struct EntryFlags: u64 { - const PRESENT = 1 << 0; - const WRITABLE = 1 << 1; - const USER_ACCESSIBLE = 1 << 2; - const WRITE_THROUGH = 1 << 3; - const NO_CACHE = 1 << 4; - const ACCESSED = 1 << 5; - const DIRTY = 1 << 6; - const HUGE_PAGE = 1 << 7; - const GLOBAL = 1 << 8; - const NO_EXECUTE = 1 << 63; - } -} - -impl Entry { - pub fn is_unused(&self) -> bool { - self.0 == 0; - } - - pub fn set_unused(&mut self) { - self.0 = 0; - } - - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) - } - - pub fn pointed_frame(&self) -> Option { - if self.flags().contains(PRESENT) { - Some(Frame::containing_address( - self.0 as usize & 0x000fffff_fffff000 - )) - } else { - None - } - } - - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!(frame.start_address() & !0x000fffff_fffff000 == 0); - self.0 = (frame.start_address() as u64) | flags.bits(); - } -} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs deleted file mode 100644 index 17896565..00000000 --- a/kernel-rs/src/memory/paging/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -use memory::PAGE_SIZE; - -const ENTRY_COUNT: usize = 512; - -pub type PhysicalAddress = usize; -pub type VirtualAddress = usize; - -pub struct Page { - number: usize, -} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs deleted file mode 100644 index e8b1244d..00000000 --- a/kernel-rs/src/memory/paging/table.rs +++ /dev/null @@ -1,51 +0,0 @@ -use memory::paging::entry::* -use memory::paging::ENTRY_COUNT; -use core::ops::{Index, IndexMut}; - -pub const P4: *mut Table = 0xffffffff_fffff000 as *mut _; - -pub struct Table { - entries: [Entry; ENTRY_COUNT], -} - -impl Index for Table { - type Output = Entry; - - fn index(&sef, index: usize) -> &Entry { - &self.entries[index] - } -} - -impl IndexMut for Table { - fn index_mut(&mut self, index: usize) -> &mut Entry { - &mut self.entries[index] - } -} - -impl Table { - pub fn zero(&mut self) { - for entry in self.entries.iter_mut() { - entry.set_unused(); - } - } - - pub fn next_table(&self, index: usize) -> Option<&Table> { - self.next_table_address(index) - .map(|address| unsafe { &*(address as *const _) }) - } - - pub fn next_table_mut(&self, index: usize) -> Option<&mut Table> { - self.next_table_address(index) - .map(|address| unsafe { &*(address as *mut _) }) - } - - fn next_table_address(&self, index: usize) -> Option { - let entry_flags = self[index].flags(); - if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) { - let table_address = self as *const _ as usize; - Some((table_address << 9) | (index << 12)) - } else { - None - } - } -} diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs deleted file mode 100644 index 76473320..00000000 --- a/kernel-rs/src/vga_buffer.rs +++ /dev/null @@ -1,148 +0,0 @@ -use core::ptr::Unique; -use volatile::Volatile; -use core::fmt; -use spin::Mutex; - -pub static WRITER: Mutex = Mutex::new(Writer { - column_position: 0, - color_code: ColorCode::new(Color::Green, Color::Black), - buffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}); - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::vga_buffer::print(format_args!($($arg)*)); - }); -} - -pub fn print(args: fmt::Arguments) { - use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); -} - -impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> fmt::Result { - for byte in s.bytes() { - self.putchar(byte) - } - Ok(()) - } -} - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} - -#[derive(Debug, Clone, Copy)] -struct ColorCode(u8); - -impl ColorCode { - const fn new(foreground: Color, background: Color) -> ColorCode { - ColorCode((background as u8) << 4 | (foreground as u8)) - } -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; - -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT] -} - -pub struct Writer { - column_position: usize, - color_code: ColorCode, - buffer: Unique, -} - -#[allow(dead_code)] -impl Writer { - pub fn putchar(&mut self, byte: u8) { - match byte { - b'\n' => self.put_endl(), - byte => { - if self.column_position >= BUFFER_WIDTH { - self.put_endl(); - } - - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - - let color_code = self.color_code; - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; - } - } - } - - pub fn putstr(&mut self, s: &str) { - for byte in s.bytes() { - self.putchar(byte) - } - } - - fn buffer(&mut self) -> &mut Buffer { - unsafe{ self.buffer.as_mut()} - } - - fn put_endl(&mut self) { - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = self.buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); - } - } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - - fn clear_row(&mut self, row: usize) { - let blank = ScreenChar { - ascii_character: b' ', - color_code: self.color_code, - }; - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(blank); - } - } -} - -pub fn clear_screen() { - for _ in 0..BUFFER_HEIGHT { - println!(""); - } -} diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json new file mode 100644 index 00000000..73bedb92 --- /dev/null +++ b/kernel-rs/x86-bluesnow.json @@ -0,0 +1,15 @@ +{ + "arch": "x86", + "cpu": "pentium4", + "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "llvm-target": "i686-unknown-none", + "linker-flavor": "gcc", + "no-compiler-rt": true, + "os": "bluesnow", + "target-endian": "little", + "target-pointer-width": "32", + "target-c-int-width": "32", + "features": "-mmx,-fxsr,-sse,-sse2,+soft-float", + "eliminate-frame-pointer": false + +} diff --git a/kernel-rs/x86_64-kfs.json b/kernel-rs/x86_64-kfs.json deleted file mode 100644 index d2fa22e1..00000000 --- a/kernel-rs/x86_64-kfs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "llvm-target": "x86_64-unknown-none", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "linker-flavor": "gcc", - "target-endian": "little", - "target-pointer-width": "64", - "target-c-int-width": "32", - "arch": "x86_64", - "os": "none", - "disable-redzone": true, - "features": "-mmx,-sse,+soft-float", - "panic-strategy": "abort" -} From 4c12c768dc58a09ace7a879cf39abe8bd2667fe4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 8 Feb 2018 23:02:32 +0100 Subject: [PATCH 023/151] vga_buffer code first commit --- kernel-rs/Cargo.toml | 6 +- kernel-rs/Makefile | 8 +- kernel-rs/src/arch/x86/linker.ld | 2 +- kernel-rs/src/lib.rs | 55 +++++------ kernel-rs/src/vga_buffer.rs | 152 +++++++++++++++++++++++++++++++ kernel-rs/x86-bluesnow.json | 4 +- 6 files changed, 191 insertions(+), 36 deletions(-) create mode 100644 kernel-rs/src/vga_buffer.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 6a7f203c..acbbad72 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Jack Halford ", "William Escande ! { + vga_buffer::clear_screen(); + println!("Kernel startup..."); + + loop { + + } +} + +#[lang = "eh_personality"] #[no_mangle] +pub extern fn eh_personality() { } -#[lang = "panic_fmt"] -extern fn rust_begin_panic() -> ! { +#[lang = "panic_fmt"] #[no_mangle] +pub extern fn panic_fmt( + fmt: core::fmt::Arguments, + file: &'static str, + line: u32) +-> ! { + println!("\n\nPANIC in {} at line {}:", file, line); + println!(" {}", fmt); loop {} } - -#[no_mangle] -pub extern fn kmain() -> ! { - unsafe { - let vga = 0xb8000 as *mut u32; - - *vga = 0x2f592f412f; - - }; - - loop { } - -} diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs new file mode 100644 index 00000000..d35903bb --- /dev/null +++ b/kernel-rs/src/vga_buffer.rs @@ -0,0 +1,152 @@ +// Copyright 2016 Philipp Oppermann. See the README.md +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::ptr::Unique; +use core::fmt; +use spin::Mutex; +use volatile::Volatile; + +struct Buffer { + chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], +} + +const BUFFER_HEIGHT: usize = 25; +const BUFFER_WIDTH: usize = 80; + +static mut VGA_BUFFER: Unique = unsafe { + Unique::new_unchecked(0xb8000 as *mut _) +}; + +fn vga_buffer() -> &'static mut Buffer { + unsafe { VGA_BUFFER.as_mut() } +} + +pub static WRITER: Mutex = Mutex::new(Writer { + column_position: 0, + color_code: ColorCode::new(Color::LightGreen, Color::Black), +}); + +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::vga_buffer::print(format_args!($($arg)*)); + }); +} + +pub fn print(args: fmt::Arguments) { + use core::fmt::Write; + WRITER.lock().write_fmt(args).unwrap(); +} + +pub fn clear_screen() { + for _ in 0..BUFFER_HEIGHT { + println!(""); + } +} + +#[allow(dead_code)] +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} + +pub struct Writer { + column_position: usize, + color_code: ColorCode, +} + +impl Writer { + pub fn write_byte(&mut self, byte: u8) { + match byte { + b'\n' => self.new_line(), + byte => { + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + + let color_code = self.color_code; + + vga_buffer().chars[row][col].write(ScreenChar { + ascii_character: byte, + color_code: color_code, + }); + self.column_position += 1; + } + } + } + + fn new_line(&mut self) { + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + let buffer = vga_buffer(); + let character = buffer.chars[row][col].read(); + buffer.chars[row - 1][col].write(character); + } + } + self.clear_row(BUFFER_HEIGHT - 1); + self.column_position = 0; + } + + fn clear_row(&mut self, row: usize) { + let blank = ScreenChar { + ascii_character: b' ', + color_code: self.color_code, + }; + for col in 0..BUFFER_WIDTH { + vga_buffer().chars[row][col].write(blank); + } + } +} + +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + for byte in s.bytes() { + self.write_byte(byte) + } + Ok(()) + } +} + +#[derive(Debug, Clone, Copy)] +struct ColorCode(u8); + +impl ColorCode { + const fn new(foreground: Color, background: Color) -> ColorCode { + ColorCode((background as u8) << 4 | (foreground as u8)) + } +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct ScreenChar { + ascii_character: u8, + color_code: ColorCode, +} diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json index 73bedb92..6be11f62 100644 --- a/kernel-rs/x86-bluesnow.json +++ b/kernel-rs/x86-bluesnow.json @@ -10,6 +10,6 @@ "target-pointer-width": "32", "target-c-int-width": "32", "features": "-mmx,-fxsr,-sse,-sse2,+soft-float", - "eliminate-frame-pointer": false - + "eliminate-frame-pointer": false, + "panic-strategy": "abort" } From 56c937e6207503d2d5c7e76c3ab85d3d828f7424 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 14:50:07 +0100 Subject: [PATCH 024/151] vga --- kernel-rs/README.md | 11 +-- kernel-rs/src/lib.rs | 23 ++++- kernel-rs/src/vga_buffer.rs | 168 +++++++++++++++++++----------------- 3 files changed, 111 insertions(+), 91 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 33b89b5f..833c270a 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -21,18 +21,9 @@ rustup component add rust-src cargo install xargo ``` -### docker -a standard development environment can be invoked: - -``` -docker run jzck/arch-kernel -it /usr/bin/zsh -``` - -clone the repo and `make iso` - # running -`make run` in your host operating system to launch qemu gtk window +`make run` runs the OS + a tmux split for the qemu terminal # References diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 6c05c06a..168d3651 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -12,11 +12,28 @@ mod vga_buffer; #[no_mangle] pub extern fn kmain() -> ! { - vga_buffer::clear_screen(); - println!("Kernel startup..."); + use vga_buffer::WRITER; + use vga_buffer::Color; + use vga_buffer::ColorCode; + + WRITER.lock().reset_screen(); + println!(">> Kernel startup..."); + println!(">> Kernel startup..."); + + WRITER.lock().color_code = ColorCode::new(Color::Blue, Color::Yellow); + println!(">> Kernel startup..."); + println!(">> Kernel startup..."); + println!(">> Kernel startup..."); + + WRITER.lock().color_code = ColorCode::new(Color::Red, Color::Green); + println!(">> Kernel startup..."); + println!(">> Kernel startup..."); + println!(">> Kernel startup..."); + + WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); loop { - + } } diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs index d35903bb..6b65d081 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga_buffer.rs @@ -12,26 +12,27 @@ use core::fmt; use spin::Mutex; use volatile::Volatile; -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], -} - const BUFFER_HEIGHT: usize = 25; const BUFFER_WIDTH: usize = 80; -static mut VGA_BUFFER: Unique = unsafe { - Unique::new_unchecked(0xb8000 as *mut _) -}; - -fn vga_buffer() -> &'static mut Buffer { - unsafe { VGA_BUFFER.as_mut() } -} - pub static WRITER: Mutex = Mutex::new(Writer { column_position: 0, - color_code: ColorCode::new(Color::LightGreen, Color::Black), + color_code: ColorCode::new(Color::White, Color::Black), + vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, }); +pub struct Writer { + column_position: usize, + pub color_code: ColorCode, + vgabuffer: Unique, +} + +struct VScreen { + column_position: usize, + pub color_code: ColorCode, + buffer: Buffer, +} + macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); @@ -39,7 +40,7 @@ macro_rules! println { macro_rules! print { ($($arg:tt)*) => ({ - $crate::vga_buffer::print(format_args!($($arg)*)); + $crate::vga_buffer::print(format_args!($($arg)*)); }); } @@ -48,9 +49,75 @@ pub fn print(args: fmt::Arguments) { WRITER.lock().write_fmt(args).unwrap(); } -pub fn clear_screen() { - for _ in 0..BUFFER_HEIGHT { - println!(""); +impl Writer { + pub fn reset_screen(&mut self) + { + let color_code = self.color_code; + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + self.buffer().chars[row][col].write(ScreenChar { + ascii_character: b' ', + color_code, + }); + } + } + self.column_position = 0; + } + + pub fn write_byte(&mut self, byte: u8) { + match byte { + b'\n' => self.new_line(), + byte => { + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + + let color_code = self.color_code; + + self.buffer().chars[row][col].write(ScreenChar { + ascii_character: byte, + color_code: color_code, + }); + self.column_position += 1; + } + } + } + + fn buffer(&mut self) -> &mut Buffer { + unsafe { self.vgabuffer.as_mut() } + } + + fn new_line(&mut self) { + for row in 1..BUFFER_HEIGHT { + for col in 0..BUFFER_WIDTH { + let buffer = self.buffer(); + let character = buffer.chars[row][col].read(); + buffer.chars[row - 1][col].write(character); + } + } + self.clear_row(BUFFER_HEIGHT - 1); + self.column_position = 0; + } + + fn clear_row(&mut self, row: usize) { + let blank = ScreenChar { + ascii_character: b' ', + color_code: ColorCode::new(Color::White, Color::Black), + }; + for col in 0..BUFFER_WIDTH { + self.buffer().chars[row][col].write(blank); + } + } +} + +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + for byte in s.bytes() { + self.write_byte(byte) + } + Ok(()) } } @@ -76,70 +143,11 @@ pub enum Color { White = 15, } -pub struct Writer { - column_position: usize, - color_code: ColorCode, -} - -impl Writer { - pub fn write_byte(&mut self, byte: u8) { - match byte { - b'\n' => self.new_line(), - byte => { - if self.column_position >= BUFFER_WIDTH { - self.new_line(); - } - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - - let color_code = self.color_code; - - vga_buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; - } - } - } - - fn new_line(&mut self) { - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = vga_buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); - } - } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - - fn clear_row(&mut self, row: usize) { - let blank = ScreenChar { - ascii_character: b' ', - color_code: self.color_code, - }; - for col in 0..BUFFER_WIDTH { - vga_buffer().chars[row][col].write(blank); - } - } -} - -impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { - for byte in s.bytes() { - self.write_byte(byte) - } - Ok(()) - } -} - #[derive(Debug, Clone, Copy)] -struct ColorCode(u8); +pub struct ColorCode(u8); impl ColorCode { - const fn new(foreground: Color, background: Color) -> ColorCode { + pub const fn new(foreground: Color, background: Color) -> ColorCode { ColorCode((background as u8) << 4 | (foreground as u8)) } } @@ -150,3 +158,7 @@ struct ScreenChar { ascii_character: u8, color_code: ColorCode, } + +struct Buffer { + chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], +} From be1b0def36c0ecfd0401424f70920e57c204bfd0 Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 9 Feb 2018 14:54:01 +0100 Subject: [PATCH 025/151] rectif port telnet --- kernel-rs/Makefile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 562fc52a..797f2288 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,8 +1,16 @@ +SHELL := /bin/bash + +ifeq ($(shell whoami), william) + PORT := 4321 +else + PORT := 1234 +endif + project := bluesnow arch ?= x86 NASM := nasm -f elf LD := ld -m elf_i386 -n --gc-sections -QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:1234,server,nowait +QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso @@ -10,7 +18,6 @@ DIRISO := build/isofiles target ?= $(arch)-$(project) rust_os := target/$(target)/debug/lib$(project).a -SHELL := /bin/bash linker_script := src/arch/$(arch)/linker.ld grub.cfg := src/arch/$(arch)/grub.cfg @@ -34,7 +41,7 @@ $(iso): $(kernel) $(grub.cfg) Makefile run: $(iso) Makefile @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 1234" + @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 $(PORT)" @$(QEMU) -curses -cdrom $(iso) clean: From f2405aaa580ef6415733d9c521e46fd4cdd21204 Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 9 Feb 2018 17:00:41 +0100 Subject: [PATCH 026/151] makefile over 9000 --- kernel-rs/Makefile | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 797f2288..507d4ae7 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,16 +1,18 @@ SHELL := /bin/bash ifeq ($(shell whoami), william) - PORT := 4321 + PORT := 4242 + PORTG := 4244 else - PORT := 1234 + PORT := 4342 + PORTG := 4344 endif project := bluesnow arch ?= x86 NASM := nasm -f elf LD := ld -m elf_i386 -n --gc-sections -QEMU := qemu-system-x86_64 -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait +QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait kernel := build/kernel-$(arch).bin iso := build/os-$(arch).iso @@ -24,6 +26,11 @@ grub.cfg := src/arch/$(arch)/grub.cfg asm_source := $(wildcard src/arch/$(arch)/*.asm) asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) +KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) +MONITOR := sleep 0.5; telnet 127.0.0.1 $(PORT); kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 2 \` +GDB := gdb -q -ex \"target remote localhost:$(PORTG)\" -ex \"continue\" + + all: $(kernel) build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile @@ -41,8 +48,8 @@ $(iso): $(kernel) $(grub.cfg) Makefile run: $(iso) Makefile @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux split-window "tmux resize-pane -y 20; sleep 0.5; telnet 127.0.0.1 $(PORT)" - @$(QEMU) -curses -cdrom $(iso) + tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' + @# @$(QEMU) -curses -cdrom $(iso) clean: @cargo clean From 15b0890ad3a7e9e80e6f963caf9cc132db098765 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 17:07:47 +0100 Subject: [PATCH 027/151] stuff --- kernel-rs/src/lib.rs | 23 +++++++++++++++++++++-- kernel-rs/src/vga_buffer.rs | 6 ------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 168d3651..d82ba782 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,6 +1,7 @@ #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] +#![feature(asm)] #![no_std] extern crate spin; @@ -10,6 +11,10 @@ extern crate rlibc; #[macro_use] mod vga_buffer; +#[allow(dead_code)] +mod cpuio; +mod keyboard; + #[no_mangle] pub extern fn kmain() -> ! { use vga_buffer::WRITER; @@ -27,13 +32,27 @@ pub extern fn kmain() -> ! { WRITER.lock().color_code = ColorCode::new(Color::Red, Color::Green); println!(">> Kernel startup..."); + print!("\n"); println!(">> Kernel startup..."); + print!("\n"); println!(">> Kernel startup..."); + print!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); + // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); loop { - + let control = unsafe { cpuio::inb(0x64) }; + if (control & 1) == 1 { + let keycode = unsafe { cpuio::inb(0x60) }; + match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { + Some(ascii) => { + print!("{}", *ascii as char); + // unsafe { cpuio::outb(28, 0x64) }; + }, + None =>{}, + // None => println!("nokey ctrl {:x}", control), + } + } } } diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs index 6b65d081..5217ea6b 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga_buffer.rs @@ -27,12 +27,6 @@ pub struct Writer { vgabuffer: Unique, } -struct VScreen { - column_position: usize, - pub color_code: ColorCode, - buffer: Buffer, -} - macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); From 1476c49f2b4766fe7cc27254b2ca7a5ce7e4f2c2 Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 9 Feb 2018 17:25:36 +0100 Subject: [PATCH 028/151] Gdb enabled --- kernel-rs/Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 507d4ae7..1f901701 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -27,8 +27,14 @@ asm_source := $(wildcard src/arch/$(arch)/*.asm) asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) -MONITOR := sleep 0.5; telnet 127.0.0.1 $(PORT); kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 2 \` -GDB := gdb -q -ex \"target remote localhost:$(PORTG)\" -ex \"continue\" +MONITOR := sleep 0.5;\ + telnet 127.0.0.1 $(PORT);\ + kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 1 \` +GDB := gdb -q\ + -ex \"set arch i386:x86-64\"\ + -ex \"file build/kernel-x86.bin\"\ + -ex \"target remote localhost:$(PORTG)\"\ + -ex \"continue\" all: $(kernel) From 44e6787e2eb39b0fbfa7b8d1ec71b2fa79895634 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 17:28:53 +0100 Subject: [PATCH 029/151] makefile gdb --- kernel-rs/Makefile | 2 +- kernel-rs/src/lib.rs | 33 ++++++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 507d4ae7..a76a6dca 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -27,7 +27,7 @@ asm_source := $(wildcard src/arch/$(arch)/*.asm) asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) -MONITOR := sleep 0.5; telnet 127.0.0.1 $(PORT); kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 2 \` +MONITOR := sleep 0.5; telnet 127.0.0.1 $(PORT); kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 1 \` GDB := gdb -q -ex \"target remote localhost:$(PORTG)\" -ex \"continue\" diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index d82ba782..b5ced73a 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -22,24 +22,23 @@ pub extern fn kmain() -> ! { use vga_buffer::ColorCode; WRITER.lock().reset_screen(); + WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black); + println!(r#" ,--, "#); + println!(r#" ,--.'| ,----, "#); + println!(r#" ,--, | : .' .' \ "#); + println!(r#",---.'| : ' ,----,' | "#); + println!(r#"; : | | ; | : . ; "#); + println!(r#"| | : _' | ; |.' / "#); + println!(r#": : |.' | `----'/ ; "#); + println!(r#"| ' ' ; : / ; / "#); + println!(r#"\ \ .'. | ; / /-, "#); + println!(r#" `---`: | ' / / /.`| "#); + println!(r#" ' ; |./__; : "#); + println!(r#" | : ;| : .' "#); + println!(r#" ' ,/ ; | .' "#); + println!(r#" '--' `---' "#); + WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); println!(">> Kernel startup..."); - println!(">> Kernel startup..."); - - WRITER.lock().color_code = ColorCode::new(Color::Blue, Color::Yellow); - println!(">> Kernel startup..."); - println!(">> Kernel startup..."); - println!(">> Kernel startup..."); - - WRITER.lock().color_code = ColorCode::new(Color::Red, Color::Green); - println!(">> Kernel startup..."); - print!("\n"); - println!(">> Kernel startup..."); - print!("\n"); - println!(">> Kernel startup..."); - print!("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); - loop { let control = unsafe { cpuio::inb(0x64) }; if (control & 1) == 1 { From c2df8effbeab32f95efc0a66d089439841e83d27 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 17:36:36 +0100 Subject: [PATCH 030/151] it compiles --- kernel-rs/Makefile | 2 +- kernel-rs/src/cpuio.rs | 39 +++++++++++++++++++++++++++++++++++++++ kernel-rs/src/keyboard.rs | 1 + 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 kernel-rs/src/cpuio.rs create mode 100644 kernel-rs/src/keyboard.rs diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 1f901701..ff3a4de6 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -54,7 +54,7 @@ $(iso): $(kernel) $(grub.cfg) Makefile run: $(iso) Makefile @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' + @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' @# @$(QEMU) -curses -cdrom $(iso) clean: diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs new file mode 100644 index 00000000..cec23ce5 --- /dev/null +++ b/kernel-rs/src/cpuio.rs @@ -0,0 +1,39 @@ +//! Rust wrappers around the x86-family I/O instructions. + +/// Read a `u8`-sized value from `port`. +pub unsafe fn inb(port: u16) -> u8 { + // The registers for the `in` and `out` instructions are always the + // same: `a` for value, and `d` for the port address. + let result: u8; + asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile"); + result +} + +/// Write a `u8`-sized `value` to `port`. +pub unsafe fn outb(value: u8, port: u16) { + asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile"); +} + +/// Read a `u16`-sized value from `port`. +pub unsafe fn inw(port: u16) -> u16 { + let result: u16; + asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile"); + result +} + +/// Write a `u8`-sized `value` to `port`. +pub unsafe fn outw(value: u16, port: u16) { + asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile"); +} + +/// Read a `u32`-sized value from `port`. +pub unsafe fn inl(port: u16) -> u32 { + let result: u32; + asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile"); + result +} + +/// Write a `u32`-sized `value` to `port`. +pub unsafe fn outl(value: u32, port: u16) { + asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile"); +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs new file mode 100644 index 00000000..daf172f5 --- /dev/null +++ b/kernel-rs/src/keyboard.rs @@ -0,0 +1 @@ +pub static KEY_CODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; From f53468a1f507cee6b8105b2ae8672bd76bfa0699 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 17:51:38 +0100 Subject: [PATCH 031/151] cursor support :) --- kernel-rs/Makefile | 1 - kernel-rs/src/lib.rs | 5 +---- kernel-rs/src/vga_buffer.rs | 28 +++++++++++++++++++++------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index ff3a4de6..e42f45ee 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -36,7 +36,6 @@ GDB := gdb -q\ -ex \"target remote localhost:$(PORTG)\"\ -ex \"continue\" - all: $(kernel) build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b5ced73a..40486a2d 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -44,10 +44,7 @@ pub extern fn kmain() -> ! { if (control & 1) == 1 { let keycode = unsafe { cpuio::inb(0x60) }; match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { - Some(ascii) => { - print!("{}", *ascii as char); - // unsafe { cpuio::outb(28, 0x64) }; - }, + Some(ascii) => print!("{}", *ascii as char), None =>{}, // None => println!("nokey ctrl {:x}", control), } diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs index 5217ea6b..5bbaedfb 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga_buffer.rs @@ -21,6 +21,18 @@ pub static WRITER: Mutex = Mutex::new(Writer { vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, }); +// cursor is lightgray for everyone +static CURSOR: ScreenChar = ScreenChar { + ascii_character: b' ', + color_code: ColorCode::new(Color::LightGray, Color::LightGray), +}; + +// blank is black for everyone, could make screens choose this +static BLANK: ScreenChar = ScreenChar { + ascii_character: b' ', + color_code: ColorCode::new(Color::White, Color::Black), +}; + pub struct Writer { column_position: usize, pub color_code: ColorCode, @@ -67,9 +79,7 @@ impl Writer { } let row = BUFFER_HEIGHT - 1; let col = self.column_position; - let color_code = self.color_code; - self.buffer().chars[row][col].write(ScreenChar { ascii_character: byte, color_code: color_code, @@ -77,6 +87,9 @@ impl Writer { self.column_position += 1; } } + let row = BUFFER_HEIGHT - 1; + let col = self.column_position; + self.buffer().chars[row][col].write(CURSOR); } fn buffer(&mut self) -> &mut Buffer { @@ -84,6 +97,11 @@ impl Writer { } fn new_line(&mut self) { + // remove cursor if newline isnt from end of screen + if self.column_position < BUFFER_WIDTH { + let col = self.column_position; + self.buffer().chars[BUFFER_HEIGHT - 1][col].write(BLANK); + } for row in 1..BUFFER_HEIGHT { for col in 0..BUFFER_WIDTH { let buffer = self.buffer(); @@ -96,12 +114,8 @@ impl Writer { } fn clear_row(&mut self, row: usize) { - let blank = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::White, Color::Black), - }; for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(blank); + self.buffer().chars[row][col].write(BLANK); } } } From 8f2f89eae6db42218656e27aeada742aeb614e19 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 17:53:03 +0100 Subject: [PATCH 032/151] ignore --- kernel-rs/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 kernel-rs/.gitignore diff --git a/kernel-rs/.gitignore b/kernel-rs/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/kernel-rs/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock From 7429ab83c87015b3f6dbccebc864d1b69128d3a3 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Feb 2018 18:56:10 +0100 Subject: [PATCH 033/151] better panic formatting --- kernel-rs/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 40486a2d..a4556262 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -59,12 +59,11 @@ pub extern fn eh_personality() { #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt( - fmt: core::fmt::Arguments, - file: &'static str, - line: u32) + fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { - println!("\n\nPANIC in {} at line {}:", file, line); - println!(" {}", fmt); + println!("PANIC: {}", fmt); + println!("FILE: {}", file); + println!("LINE: {}", line); loop {} } From 66d75c08956dcbf9fa01094d576987e0455e8b8a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 10 Feb 2018 18:18:58 +0100 Subject: [PATCH 034/151] starting to make vga more modular, keyboard controls which screen is in scope --- kernel-rs/src/keyboard.rs | 33 ++++- kernel-rs/src/lib.rs | 66 +++++----- .../src/{vga_buffer.rs => vga/buffer.rs} | 117 ++++++------------ kernel-rs/src/vga/color.rs | 30 +++++ kernel-rs/src/vga/mod.rs | 27 ++++ kernel-rs/src/vga/terminal.rs | 19 +++ 6 files changed, 176 insertions(+), 116 deletions(-) rename kernel-rs/src/{vga_buffer.rs => vga/buffer.rs} (65%) create mode 100644 kernel-rs/src/vga/color.rs create mode 100644 kernel-rs/src/vga/mod.rs create mode 100644 kernel-rs/src/vga/terminal.rs diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index daf172f5..09b4f3be 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1 +1,32 @@ -pub static KEY_CODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; +pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; + +use vga; +use cpuio; + +use vga::buffer::{Writer, Screen}; + +pub fn kbd_loop(writer: &mut Writer) { + let terminal_one: vga::terminal::Terminal = vga::Screen::new(); + // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); + + let control = unsafe { cpuio::inb(0x64) }; + if (control & 1) == 1 { + let scancode = unsafe { cpuio::inb(0x60) }; + + //TODO current_screen() with mutex lock? + let current_screen = terminal_one; + + //TODO implement logic to translate scancode->ascii + match self::SCANCODE_TO_ASCII.get(scancode as usize) { + Some(ascii) => { + //TODO screen switching logic + // if let Some(action) = Screen::keypress(current_screen, *ascii as char) { + if let Some(action) = current_screen.keypress(*ascii as char) { + writer.action(action); + } + }, + None =>{}, + // None => println!("nokey ctrl {:x}", control), + } + } +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index a4556262..636dbbfb 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -9,7 +9,7 @@ extern crate volatile; extern crate rlibc; #[macro_use] -mod vga_buffer; +mod vga; #[allow(dead_code)] mod cpuio; @@ -17,39 +17,30 @@ mod keyboard; #[no_mangle] pub extern fn kmain() -> ! { - use vga_buffer::WRITER; - use vga_buffer::Color; - use vga_buffer::ColorCode; + // use vga::VgaScreen; + // use vga::color::Color; + // use vga::color::ColorCode; - WRITER.lock().reset_screen(); - WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black); - println!(r#" ,--, "#); - println!(r#" ,--.'| ,----, "#); - println!(r#" ,--, | : .' .' \ "#); - println!(r#",---.'| : ' ,----,' | "#); - println!(r#"; : | | ; | : . ; "#); - println!(r#"| | : _' | ; |.' / "#); - println!(r#": : |.' | `----'/ ; "#); - println!(r#"| ' ' ; : / ; / "#); - println!(r#"\ \ .'. | ; / /-, "#); - println!(r#" `---`: | ' / / /.`| "#); - println!(r#" ' ; |./__; : "#); - println!(r#" | : ;| : .' "#); - println!(r#" ' ,/ ; | .' "#); - println!(r#" '--' `---' "#); - WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); - println!(">> Kernel startup..."); - loop { - let control = unsafe { cpuio::inb(0x64) }; - if (control & 1) == 1 { - let keycode = unsafe { cpuio::inb(0x60) }; - match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { - Some(ascii) => print!("{}", *ascii as char), - None =>{}, - // None => println!("nokey ctrl {:x}", control), - } - } - } + // WRITER.lock().reset_screen(); + // WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black); + // println!(r#" ,--, "#); + // println!(r#" ,--.'| ,----, "#); + // println!(r#" ,--, | : .' .' \ "#); + // println!(r#",---.'| : ' ,----,' | "#); + // println!(r#"; : | | ; | : . ; "#); + // println!(r#"| | : _' | ; |.' / "#); + // println!(r#": : |.' | `----'/ ; "#); + // println!(r#"| ' ' ; : / ; / "#); + // println!(r#"\ \ .'. | ; / /-, "#); + // println!(r#" `---`: | ' / / /.`| "#); + // println!(r#" ' ; |./__; : "#); + // println!(r#" | : ;| : .' "#); + // println!(r#" ' ,/ ; | .' "#); + // println!(r#" '--' `---' "#); + // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); + // println!(">> Kernel startup..."); + + unsafe { loop { keyboard::kbd_loop(&mut vga::buffer::WRITER); } }; } #[lang = "eh_personality"] #[no_mangle] @@ -59,11 +50,12 @@ pub extern fn eh_personality() { #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt( - fmt: core::fmt::Arguments, file: &'static str, line: u32) + // fmt: core::fmt::Arguments, file: &'static str, line: u32 + ) -> ! { - println!("PANIC: {}", fmt); - println!("FILE: {}", file); - println!("LINE: {}", line); + // println!("PANIC: {}", fmt); + // println!("FILE: {}", file); + // println!("LINE: {}", line); loop {} } diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga/buffer.rs similarity index 65% rename from kernel-rs/src/vga_buffer.rs rename to kernel-rs/src/vga/buffer.rs index 5bbaedfb..34617c44 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -7,24 +7,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use volatile::Volatile; + +use super::{Color, ColorCode}; use core::ptr::Unique; use core::fmt; -use spin::Mutex; -use volatile::Volatile; + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct ScreenChar { + ascii_character: u8, + color_code: ColorCode, +} const BUFFER_HEIGHT: usize = 25; const BUFFER_WIDTH: usize = 80; -pub static WRITER: Mutex = Mutex::new(Writer { +pub struct Writer { + pub column_position: usize, + pub color_code: ColorCode, + vgabuffer: Unique, +} + +// Writer is the default object to use to print to screen +pub static mut WRITER: Writer = Writer { column_position: 0, color_code: ColorCode::new(Color::White, Color::Black), vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}); - -// cursor is lightgray for everyone -static CURSOR: ScreenChar = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::LightGray, Color::LightGray), }; // blank is black for everyone, could make screens choose this @@ -33,29 +42,14 @@ static BLANK: ScreenChar = ScreenChar { color_code: ColorCode::new(Color::White, Color::Black), }; -pub struct Writer { - column_position: usize, - pub color_code: ColorCode, - vgabuffer: Unique, -} - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::vga_buffer::print(format_args!($($arg)*)); - }); -} - -pub fn print(args: fmt::Arguments) { - use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); -} - impl Writer { + pub fn action(&mut self, action: BufferAction) { + match action { + BufferAction::WRITE_BYTE(ascii) => self.write_byte(ascii as u8), + BufferAction::CLEAR_SCREEN => self.reset_screen(), + } + } + pub fn reset_screen(&mut self) { let color_code = self.color_code; @@ -72,7 +66,7 @@ impl Writer { pub fn write_byte(&mut self, byte: u8) { match byte { - b'\n' => self.new_line(), + b'\n' => { self.new_line(); } byte => { if self.column_position >= BUFFER_WIDTH { self.new_line(); @@ -87,9 +81,6 @@ impl Writer { self.column_position += 1; } } - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - self.buffer().chars[row][col].write(CURSOR); } fn buffer(&mut self) -> &mut Buffer { @@ -97,11 +88,6 @@ impl Writer { } fn new_line(&mut self) { - // remove cursor if newline isnt from end of screen - if self.column_position < BUFFER_WIDTH { - let col = self.column_position; - self.buffer().chars[BUFFER_HEIGHT - 1][col].write(BLANK); - } for row in 1..BUFFER_HEIGHT { for col in 0..BUFFER_WIDTH { let buffer = self.buffer(); @@ -129,44 +115,19 @@ impl fmt::Write for Writer { } } -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} - -#[derive(Debug, Clone, Copy)] -pub struct ColorCode(u8); - -impl ColorCode { - pub const fn new(foreground: Color, background: Color) -> ColorCode { - ColorCode((background as u8) << 4 | (foreground as u8)) - } -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - struct Buffer { chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], } + +pub enum BufferAction { + WRITE_BYTE(char), + CLEAR_SCREEN, +} + +/// Implementors of this trait can use the vga screen for any purpose +pub trait Screen { + fn new() -> Self; // + fn keypress(self, keycode: char) -> Option; + // fn load(); + // fn unload() -> ; +} diff --git a/kernel-rs/src/vga/color.rs b/kernel-rs/src/vga/color.rs new file mode 100644 index 00000000..dc24b1ef --- /dev/null +++ b/kernel-rs/src/vga/color.rs @@ -0,0 +1,30 @@ +#[allow(dead_code)] +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + Pink = 13, + Yellow = 14, + White = 15, +} + +#[derive(Debug, Clone, Copy)] +pub struct ColorCode(u8); + +impl ColorCode { + pub const fn new(foreground: Color, background: Color) -> ColorCode { + ColorCode((background as u8) << 4 | (foreground as u8)) + } +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs new file mode 100644 index 00000000..2a7984e3 --- /dev/null +++ b/kernel-rs/src/vga/mod.rs @@ -0,0 +1,27 @@ +#[macro_use] +pub mod buffer; +pub mod color; +pub mod terminal; + +pub use self::color::{Color, ColorCode}; +pub use self::buffer::{WRITER, Screen, BufferAction}; + +// use self::buffer::Writer; +// use core::fmt; +// use core::ptr::Unique; + +// macro_rules! println { +// ($fmt:expr) => (print!(concat!($fmt, "\n"))); +// ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +// } + +// macro_rules! print { +// ($($arg:tt)*) => ({ +// $crate::vga::print(format_args!($($arg)*)); +// }); +// } + +// pub fn print(args: fmt::Arguments) { +// use core::fmt::Write; +// self::WRITER.write_fmt(args).unwrap(); +// } diff --git a/kernel-rs/src/vga/terminal.rs b/kernel-rs/src/vga/terminal.rs new file mode 100644 index 00000000..0f1fcb9a --- /dev/null +++ b/kernel-rs/src/vga/terminal.rs @@ -0,0 +1,19 @@ +//! terminal.rs implements a basic cursor terminal using the vga::buffer module + +use super::{Color, ColorCode}; +use vga; + +// cursor is lightgray for everyone +static CURSOR: ColorCode = ColorCode::new(Color::LightGray, Color::White); + +pub struct Terminal { } + +impl vga::Screen for Terminal { + fn new() -> Terminal { + Terminal { } + } + + fn keypress(self, ascii: char) -> Option { + Some(vga::BufferAction::WRITE_BYTE(ascii)) + } +} From 6dd33393dfdb82bb616e70752e3e23d61c065c70 Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 12 Feb 2018 12:54:11 +0100 Subject: [PATCH 035/151] keyboard handle maj --- kernel-rs/keycode | 258 ++++++++++++++++++++++++++++++++++++ kernel-rs/keycode2 | 249 ++++++++++++++++++++++++++++++++++ kernel-rs/src/keyboard.rs | 159 +++++++++++++++++++++- kernel-rs/src/lib.rs | 28 ++-- kernel-rs/src/vga_buffer.rs | 3 + 5 files changed, 687 insertions(+), 10 deletions(-) create mode 100644 kernel-rs/keycode create mode 100644 kernel-rs/keycode2 diff --git a/kernel-rs/keycode b/kernel-rs/keycode new file mode 100644 index 00000000..5a9d4d08 --- /dev/null +++ b/kernel-rs/keycode @@ -0,0 +1,258 @@ +0x01 escape pressed +0x02 1 pressed +0x03 2 pressed +0x04 3 pressed +0x05 4 pressed +0x06 5 pressed +0x07 6 pressed +0x08 7 pressed +0x09 8 pressed +0x0A 9 pressed +0x0B 0 (zero) pressed +0x0C - pressed +0x0D = pressed +0x0E backspace pressed +0x0F tab pressed +0x10 Q pressed +0x11 W pressed +0x12 E pressed +0x13 R pressed +0x14 T pressed +0x15 Y pressed +0x16 U pressed +0x17 I pressed +0x18 O pressed +0x19 P pressed +0x1A [ pressed +0x1B ] pressed +0x1C enter pressed +0x1D left control pressed +0x1E A pressed +0x1F S pressed +0x20 D pressed +0x21 F pressed +0x22 G pressed +0x23 H pressed +0x24 J pressed +0x25 K pressed +0x26 L pressed +0x27 ; pressed +0x28 ' (single quote) pressed +0x29 ` (back tick) pressed +0x2A left shift pressed +0x2B \ pressed +0x2C Z pressed +0x2D X pressed +0x2E C pressed +0x2F V pressed +0x30 B pressed +0x31 N pressed +0x32 M pressed +0x33 , pressed +0x34 . pressed +0x35 / pressed +0x36 right shift pressed +0x37 (keypad) * pressed +0x38 left alt pressed +0x39 space pressed +0x3A CapsLock pressed +0x3B F1 pressed +0x3C F2 pressed +0x3D F3 pressed +0x3E F4 pressed +0x3F F5 pressed +0x40 F6 pressed +0x41 F7 pressed +0x42 F8 pressed +0x43 F9 pressed +0x44 F10 pressed +0x45 NumberLock pressed +0x46 ScrollLock pressed +0x47 (keypad) 7 pressed +0x48 (keypad) 8 pressed +0x49 (keypad) 9 pressed +0x4A (keypad) - pressed +0x4B (keypad) 4 pressed +0x4C (keypad) 5 pressed +0x4D (keypad) 6 pressed +0x4E (keypad) + pressed +0x4F (keypad) 1 pressed +0x50 (keypad) 2 pressed +0x51 (keypad) 3 pressed +0x52 (keypad) 0 pressed +0x53 (keypad) . pressed +0x57 F11 pressed +0x58 F12 pressed + + + + + + + + + +0x81 escape released +0x82 1 released +0x83 2 released +0x84 3 released +0x85 4 released +0x86 5 released +0x87 6 released +0x88 7 released +0x89 8 released +0x8A 9 released +0x8B 0 (zero) released +0x8C - released +0x8D = released +0x8E backspace released +0x8F tab released +0x90 Q released +0x91 W released +0x92 E released +0x93 R released +0x94 T released +0x95 Y released +0x96 U released +0x97 I released +0x98 O released +0x99 P released +0x9A [ released +0x9B ] released +0x9C enter released +0x9D left control released +0x9E A released +0x9F S released +0xA0 D released +0xA1 F released +0xA2 G released +0xA3 H released +0xA4 J released +0xA5 K released +0xA6 L released +0xA7 ; released +0xA8 ' (single quote) released +0xA9 ` (back tick) released +0xAA left shift released +0xAB \ released +0xAC Z released +0xAD X released +0xAE C released +0xAF V released +0xB0 B released +0xB1 N released +0xB2 M released +0xB3 , released +0xB4 . released +0xB5 / released +0xB6 right shift released +0xB7 (keypad) * released +0xB8 left alt released +0xB9 space released +0xBA CapsLock released +0xBB F1 released +0xBC F2 released +0xBD F3 released +0xBE F4 released +0xBF F5 released +0xC0 F6 released +0xC1 F7 released +0xC2 F8 released +0xC3 F9 released +0xC4 F10 released +0xC5 NumberLock released +0xC6 ScrollLock released +0xC7 (keypad) 7 released +0xC8 (keypad) 8 released +0xC9 (keypad) 9 released +0xCA (keypad) - released +0xCB (keypad) 4 released +0xCC (keypad) 5 released +0xCD (keypad) 6 released +0xCE (keypad) + released +0xCF (keypad) 1 released +0xD0 (keypad) 2 released +0xD1 (keypad) 3 released +0xD2 (keypad) 0 released +0xD3 (keypad) . released +0xD7 F11 released +0xD8 F12 released +0xE0, 0x10 (multimedia) previous track pressed +0xE0, 0x19 (multimedia) next track pressed +0xE0, 0x1C (keypad) enter pressed +0xE0, 0x1D right control pressed +0xE0, 0x20 (multimedia) mute pressed +0xE0, 0x21 (multimedia) calculator pressed +0xE0, 0x22 (multimedia) play pressed +0xE0, 0x24 (multimedia) stop pressed +0xE0, 0x2E (multimedia) volume down pressed +0xE0, 0x30 (multimedia) volume up pressed +0xE0, 0x32 (multimedia) WWW home pressed +0xE0, 0x35 (keypad) / pressed +0xE0, 0x38 right alt (or altGr) pressed +0xE0, 0x47 home pressed +0xE0, 0x48 cursor up pressed +0xE0, 0x49 page up pressed +0xE0, 0x4B cursor left pressed +0xE0, 0x4D cursor right pressed +0xE0, 0x4F end pressed +0xE0, 0x50 cursor down pressed +0xE0, 0x51 page down pressed +0xE0, 0x52 insert pressed +0xE0, 0x53 delete pressed +0xE0, 0x5B left GUI pressed +0xE0, 0x5C right GUI pressed +0xE0, 0x5D "apps" pressed +0xE0, 0x5E (ACPI) power pressed +0xE0, 0x5F (ACPI) sleep pressed +0xE0, 0x63 (ACPI) wake pressed +0xE0, 0x65 (multimedia) WWW search pressed +0xE0, 0x66 (multimedia) WWW favorites pressed +0xE0, 0x67 (multimedia) WWW refresh pressed +0xE0, 0x68 (multimedia) WWW stop pressed +0xE0, 0x69 (multimedia) WWW forward pressed +0xE0, 0x6A (multimedia) WWW back pressed +0xE0, 0x6B (multimedia) my computer pressed +0xE0, 0x6C (multimedia) email pressed +0xE0, 0x6D (multimedia) media select pressed +0xE0, 0x90 (multimedia) previous track released +0xE0, 0x99 (multimedia) next track released +0xE0, 0x9C (keypad) enter released +0xE0, 0x9D right control released +0xE0, 0xA0 (multimedia) mute released +0xE0, 0xA1 (multimedia) calculator released +0xE0, 0xA2 (multimedia) play released +0xE0, 0xA4 (multimedia) stop released +0xE0, 0xAE (multimedia) volume down released +0xE0, 0xB0 (multimedia) volume up released +0xE0, 0xB2 (multimedia) WWW home released +0xE0, 0xB5 (keypad) / released +0xE0, 0xB8 right alt (or altGr) released +0xE0, 0xC7 home released +0xE0, 0xC8 cursor up released +0xE0, 0xC9 page up released +0xE0, 0xCB cursor left released +0xE0, 0xCD cursor right released +0xE0, 0xCF end released +0xE0, 0xD0 cursor down released +0xE0, 0xD1 page down released +0xE0, 0xD2 insert released +0xE0, 0xD3 delete released +0xE0, 0xDB left GUI released +0xE0, 0xDC right GUI released +0xE0, 0xDD "apps" released +0xE0, 0xDE (ACPI) power released +0xE0, 0xDF (ACPI) sleep released +0xE0, 0xE3 (ACPI) wake released +0xE0, 0xE5 (multimedia) WWW search released +0xE0, 0xE6 (multimedia) WWW favorites released +0xE0, 0xE7 (multimedia) WWW refresh released +0xE0, 0xE8 (multimedia) WWW stop released +0xE0, 0xE9 (multimedia) WWW forward released +0xE0, 0xEA (multimedia) WWW back released +0xE0, 0xEB (multimedia) my computer released +0xE0, 0xEC (multimedia) email released +0xE0, 0xED (multimedia) media select released +0xE0, 0x2A, 0xE0, 0x37 print screen pressed +0xE0, 0xB7, 0xE0, 0xAA print screen released +0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 pause pressed diff --git a/kernel-rs/keycode2 b/kernel-rs/keycode2 new file mode 100644 index 00000000..a7473619 --- /dev/null +++ b/kernel-rs/keycode2 @@ -0,0 +1,249 @@ +0x01 F9 pressed +0x03 F5 pressed +0x04 F3 pressed +0x05 F1 pressed +0x06 F2 pressed +0x07 F12 pressed +0x09 F10 pressed +0x0A F8 pressed +0x0B F6 pressed +0x0C F4 pressed +0x0D tab pressed +0x0E ` (back tick) pressed +0x11 left alt pressed +0x12 left shift pressed +0x14 left control pressed +0x15 Q pressed +0x16 1 pressed +0x1A Z pressed +0x1B S pressed +0x1C A pressed +0x1D W pressed +0x1E 2 pressed +0x21 C pressed +0x22 X pressed +0x23 D pressed +0x24 E pressed +0x25 4 pressed +0x26 3 pressed +0x29 space pressed +0x2A V pressed +0x2B F pressed +0x2C T pressed +0x2D R pressed +0x2E 5 pressed +0x31 N pressed +0x32 B pressed +0x33 H pressed +0x34 G pressed +0x35 Y pressed +0x36 6 pressed +0x3A M pressed +0x3B J pressed +0x3C U pressed +0x3D 7 pressed +0x3E 8 pressed +0x41 , pressed +0x42 K pressed +0x43 I pressed +0x44 O pressed +0x45 0 (zero) pressed +0x46 9 pressed +0x49 . pressed +0x4A / pressed +0x4B L pressed +0x4C ; pressed +0x4D P pressed +0x4E - pressed +0x52 ' pressed +0x54 [ pressed +0x55 = pressed +0x58 CapsLock pressed +0x59 right shift pressed +0x5A enter pressed +0x5B ] pressed +0x5D \ pressed +0x66 backspace pressed +0x69 (keypad) 1 pressed +0x6B (keypad) 4 pressed +0x6C (keypad) 7 pressed +0x70 (keypad) 0 pressed +0x71 (keypad) . pressed +0x72 (keypad) 2 pressed +0x73 (keypad) 5 pressed +0x74 (keypad) 6 pressed +0x75 (keypad) 8 pressed +0x76 escape pressed +0x77 NumberLock pressed +0x78 F11 pressed +0x79 (keypad) + pressed +0x7A (keypad) 3 pressed +0x7B (keypad) - pressed +0x7C (keypad) * pressed +0x7D (keypad) 9 pressed +0x7E ScrollLock pressed +0x83 F7 pressed +0xE0, 0x10 (multimedia) WWW search pressed +0xE0, 0x11 right alt pressed +0xE0, 0x14 right control pressed +0xE0, 0x15 (multimedia) previous track pressed +0xE0, 0x18 (multimedia) WWW favourites pressed +0xE0, 0x1F left GUI pressed +0xE0, 0x20 (multimedia) WWW refresh pressed +0xE0, 0x21 (multimedia) volume down pressed +0xE0, 0x23 (multimedia) mute pressed +0xE0, 0x27 right GUI pressed +0xE0, 0x28 (multimedia) WWW stop pressed +0xE0, 0x2B (multimedia) calculator pressed +0xE0, 0x2F apps pressed +0xE0, 0x30 (multimedia) WWW forward pressed +0xE0, 0x32 (multimedia) volume up pressed +0xE0, 0x34 (multimedia) play/pause pressed +0xE0, 0x37 (ACPI) power pressed +0xE0, 0x38 (multimedia) WWW back pressed +0xE0, 0x3A (multimedia) WWW home pressed +0xE0, 0x3B (multimedia) stop pressed +0xE0, 0x3F (ACPI) sleep pressed +0xE0, 0x40 (multimedia) my computer pressed +0xE0, 0x48 (multimedia) email pressed +0xE0, 0x4A (keypad) / pressed +0xE0, 0x4D (multimedia) next track pressed +0xE0, 0x50 (multimedia) media select pressed +0xE0, 0x5A (keypad) enter pressed +0xE0, 0x5E (ACPI) wake pressed +0xE0, 0x69 end pressed +0xE0, 0x6B cursor left pressed +0xE0, 0x6C home pressed +0xE0, 0x70 insert pressed +0xE0, 0x71 delete pressed +0xE0, 0x72 cursor down pressed +0xE0, 0x74 cursor right pressed +0xE0, 0x75 cursor up pressed +0xE0, 0x7A page down pressed +0xE0, 0x7D page up pressed +0xF0, 0x01 F9 released +0xF0, 0x03 F5 released +0xF0, 0x04 F3 released +0xF0, 0x05 F1 released +0xF0, 0x06 F2 released +0xF0, 0x07 F12 released +0xF0, 0x09 F10 released +0xF0, 0x0A F8 released +0xF0, 0x0B F6 released +0xF0, 0x0C F4 released +0xF0, 0x0D tab released +0xF0, 0x0E ` (back tick) released +0xF0, 0x11 left alt released +0xF0, 0x12 left shift released +0xF0, 0x14 left control released +0xF0, 0x15 Q released +0xF0, 0x16 1 released +0xF0, 0x1A Z released +0xF0, 0x1B S released +0xF0, 0x1C A released +0xF0, 0x1D W released +0xF0, 0x1E 2 released +0xF0, 0x21 C released +0xF0, 0x22 X released +0xF0, 0x23 D released +0xF0, 0x24 E released +0xF0, 0x25 4 released +0xF0, 0x26 3 released +0xF0, 0x29 space released +0xF0, 0x2A V released +0xF0, 0x2B F released +0xF0, 0x2C T released +0xF0, 0x2D R released +0xF0, 0x2E 5 released +0xF0, 0x31 N released +0xF0, 0x32 B released +0xF0, 0x33 H released +0xF0, 0x34 G released +0xF0, 0x35 Y released +0xF0, 0x36 6 released +0xF0, 0x3A M released +0xF0, 0x3B J released +0xF0, 0x3C U released +0xF0, 0x3D 7 released +0xF0, 0x3E 8 released +0xF0, 0x41 , released +0xF0, 0x42 K released +0xF0, 0x43 I released +0xF0, 0x44 O released +0xF0, 0x45 0 (zero) released +0xF0, 0x46 9 released +0xF0, 0x49 . released +0xF0, 0x4A / released +0xF0, 0x4B L released +0xF0, 0x4C ; released +0xF0, 0x4D P released +0xF0, 0x4E - released +0xF0, 0x52 ' released +0xF0, 0x54 [ released +0xF0, 0x55 = released +0xF0, 0x58 CapsLock released +0xF0, 0x59 right shift released +0xF0, 0x5A enter released +0xF0, 0x5B ] released +0xF0, 0x5D \ released +0xF0, 0x66 backspace released +0xF0, 0x69 (keypad) 1 released +0xF0, 0x6B (keypad) 4 released +0xF0, 0x6C (keypad) 7 released +0xF0, 0x70 (keypad) 0 released +0xF0, 0x71 (keypad) . released +0xF0, 0x72 (keypad) 2 released +0xF0, 0x73 (keypad) 5 released +0xF0, 0x74 (keypad) 6 released +0xF0, 0x75 (keypad) 8 released +0xF0, 0x76 escape released +0xF0, 0x77 NumberLock released +0xF0, 0x78 F11 released +0xF0, 0x79 (keypad) + released +0xF0, 0x7A (keypad) 3 released +0xF0, 0x7B (keypad) - released +0xF0, 0x7C (keypad) * released +0xF0, 0x7D (keypad) 9 released +0xF0, 0x7E ScrollLock released +0xF0, 0x83 F7 released +0xE0, 0x12, 0xE0, 0x7C print screen pressed +0xE0, 0xF0, 0x10 (multimedia) WWW search released +0xE0, 0xF0, 0x11 right alt released +0xE0, 0xF0, 0x14 right control released +0xE0, 0xF0, 0x15 (multimedia) previous track released +0xE0, 0xF0, 0x18 (multimedia) WWW favourites released +0xE0, 0xF0, 0x1F left GUI released +0xE0, 0xF0, 0x20 (multimedia) WWW refresh released +0xE0, 0xF0, 0x21 (multimedia) volume down released +0xE0, 0xF0, 0x23 (multimedia) mute released +0xE0, 0xF0, 0x27 right GUI released +0xE0, 0xF0, 0x28 (multimedia) WWW stop released +0xE0, 0xF0, 0x2B (multimedia) calculator released +0xE0, 0xF0, 0x2F apps released +0xE0, 0xF0, 0x30 (multimedia) WWW forward released +0xE0, 0xF0, 0x32 (multimedia) volume up released +0xE0, 0xF0, 0x34 (multimedia) play/pause released +0xE0, 0xF0, 0x37 (ACPI) power released +0xE0, 0xF0, 0x38 (multimedia) WWW back released +0xE0, 0xF0, 0x3A (multimedia) WWW home released +0xE0, 0xF0, 0x3B (multimedia) stop released +0xE0, 0xF0, 0x3F (ACPI) sleep released +0xE0, 0xF0, 0x40 (multimedia) my computer released +0xE0, 0xF0, 0x48 (multimedia) email released +0xE0, 0xF0, 0x4A (keypad) / released +0xE0, 0xF0, 0x4D (multimedia) next track released +0xE0, 0xF0, 0x50 (multimedia) media select released +0xE0, 0xF0, 0x5A (keypad) enter released +0xE0, 0xF0, 0x5E (ACPI) wake released +0xE0, 0xF0, 0x69 end released +0xE0, 0xF0, 0x6B cursor left released +0xE0, 0xF0, 0x6C home released +0xE0, 0xF0, 0x70 insert released +0xE0, 0xF0, 0x71 delete released +0xE0, 0xF0, 0x72 cursor down released +0xE0, 0xF0, 0x74 cursor right released +0xE0, 0xF0, 0x75 cursor up released +0xE0, 0xF0, 0x7A page down released +0xE0, 0xF0, 0x7D page up released +0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12 print screen released +0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77 pause pressed diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index daf172f5..94b35fdc 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1 +1,158 @@ -pub static KEY_CODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; +// pub static KEY_CODE_TO_ASCII: [u8; 59] = *b"\0\01234567890-=\0\0qwertyuiop[]\n\0asdfghjkl;'`\0\\zxcvbnm,./\0*\0 \0"; + +const MAX_KEYS: usize = 59; +const TOUCH_RELEASE: u8 = 1 << 7; +// static ASCII_GUARD:[u8;2] = *b"\0\0"; + +static mut SHIFT: bool = false; +const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ + *b"\0\0", + *b"\0\0",//escape + *b"1!", + *b"2@", + *b"3#", + *b"4$", + *b"5%", + *b"6^", + *b"7&", + *b"8*", + *b"9(", + *b"0)", + *b"-_", + *b"=+", + *b"\0\0",//backspace + *b"\0\0",//tab + *b"qQ", + *b"wW", + *b"eE", + *b"rR", + *b"tT", + *b"yY", + *b"uU", + *b"iI", + *b"oO", + *b"pP", + *b"[{", + *b"]}", + *b"\n\n", + *b"\0\0",//left_control + *b"aA", + *b"sS", + *b"dD", + *b"fF", + *b"gG", + *b"hH", + *b"jJ", + *b"kK", + *b"lL", + *b";:", + *b"'\"", + *b"`~", + *b"\0\0",//left shift + *b"\\|", + *b"zZ", + *b"xX", + *b"cC", + *b"vV", + *b"bB", + *b"nN", + *b"mM", + *b",<", + *b".>", + *b"/?", + *b"\0\0",//right shift + *b"**", + *b"\0\0",//left alt + *b" ", + *b"\0\0",//capslock + ]; +// use vga_buffer; +use cpuio; + +// use vga_buffer::buffer::{Writer, Screen}; +use vga_buffer::WRITER; + +fn check_touch_state(key: u8) -> (bool, usize) { + if (key & TOUCH_RELEASE) == TOUCH_RELEASE { + (true, (key - TOUCH_RELEASE) as usize) + } else { + (false, key as usize) + } +} + +pub fn kbd_loop() { + // let terminal_one: vga::terminal::Terminal = vga::Screen::new(); + // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); + + let control = unsafe { cpuio::inb(0x64) }; + if (control & 1) == 1 { + let scancode = unsafe { cpuio::inb(0x60) }; + let (is_release, scancode) = check_touch_state(scancode); + if scancode < MAX_KEYS { + let key_array = KEYMAP_US[scancode]; + if key_array == *b"\0\0"{ + match scancode { + 0x2A | 0x36 => { + unsafe {SHIFT = !is_release}; + } + _ => {} + } + } + else if !is_release { + unsafe { + if SHIFT { + WRITER.lock().write_byte(key_array[1]); + } + else { + WRITER.lock().write_byte(key_array[0]); + } + } + } + } + } + //match self::KEYMAP_US.get(scancode as usize) { + // Some(ASCII_GUARD) => {}, + // Some(touch_array) if !is_release => { + // //TODO screen switching logic + // // if let Some(action) = Screen::keypress(current_screen, *ascii as char) { + // if let Some(action) = current_screen.keypress(*ascii as char) { + // writer.action(action); + // } + // }, + // _ =>{}, + // None => println!("nokey ctrl {:x}", control), + // } + // if scancode < MAX_KEYS { + // let ascii = KEYMAP_US[scancode]; + // if ascii != *b"\0\0" { + // if shift { + // writer.write(ascii[1] as char); + // } + // else { + // writer.write(ascii[0] as char); + // } + + // } + // else { + // if scancode == 0x2A || scancode == 0x36 + + // } + + // } + + //TODO current_screen() with mutex lock? + // let current_screen = terminal_one; + + //TODO implement logic to translate scancode->ascii + //match self::SCANCODE_TO_ASCII.get(scancode as usize) { + // Some(ascii) => { + // //TODO screen switching logic + // // if let Some(action) = Screen::keypress(current_screen, *ascii as char) { + // if let Some(action) = current_screen.keypress(*ascii as char) { + // writer.action(action); + // } + // }, + // None =>{}, + // // None => println!("nokey ctrl {:x}", control), + //} +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index a4556262..7acccf37 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -15,6 +15,15 @@ mod vga_buffer; mod cpuio; mod keyboard; +// fn check_shift(key: u8) -> u8 { +// print!("{:b} vs {:b}\n", key as u8, (1<<7) as u8); +// if (key >> 7 & 1) == 1 { +// print!("MATCH"); +// key - (1 << 7) +// } else { +// key +// } +// } #[no_mangle] pub extern fn kmain() -> ! { use vga_buffer::WRITER; @@ -40,15 +49,16 @@ pub extern fn kmain() -> ! { WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); println!(">> Kernel startup..."); loop { - let control = unsafe { cpuio::inb(0x64) }; - if (control & 1) == 1 { - let keycode = unsafe { cpuio::inb(0x60) }; - match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { - Some(ascii) => print!("{}", *ascii as char), - None =>{}, - // None => println!("nokey ctrl {:x}", control), - } - } + keyboard::kbd_loop(); + // let control = unsafe { cpuio::inb(0x64) }; + // if (control & 1) == 1 { + // let keycode = unsafe { cpuio::inb(0x60) }; + // match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { + // Some(ascii) => print!("{}", *ascii as char), + // None =>{}, + // // None => println!("nokey ctrl {:x}", control), + // } + // } } } diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs index 5bbaedfb..b245d306 100644 --- a/kernel-rs/src/vga_buffer.rs +++ b/kernel-rs/src/vga_buffer.rs @@ -87,6 +87,9 @@ impl Writer { self.column_position += 1; } } + if self.column_position >= BUFFER_WIDTH { + self.new_line(); + } let row = BUFFER_HEIGHT - 1; let col = self.column_position; self.buffer().chars[row][col].write(CURSOR); From 67dbf5d9b3020e4da65bf7a642bcac4bfe60a3e6 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 15:22:35 +0100 Subject: [PATCH 036/151] context::Context handles multiple Writers, Writer handles cursor --- kernel-rs/src/context.rs | 44 +++++++++++ kernel-rs/src/keyboard.rs | 30 ++++---- kernel-rs/src/lib.rs | 7 +- kernel-rs/src/vga/buffer.rs | 137 +++++++++++++--------------------- kernel-rs/src/vga/color.rs | 2 +- kernel-rs/src/vga/mod.rs | 3 +- kernel-rs/src/vga/terminal.rs | 19 ----- 7 files changed, 119 insertions(+), 123 deletions(-) create mode 100644 kernel-rs/src/context.rs delete mode 100644 kernel-rs/src/vga/terminal.rs diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs new file mode 100644 index 00000000..cb61b08f --- /dev/null +++ b/kernel-rs/src/context.rs @@ -0,0 +1,44 @@ +extern crate core; + +use vga; + + +pub struct Context { + pub current_term: u8, + pub vga1: vga::Writer<&'static mut [u8]>, + pub vga2: vga::Writer<&'static mut [u8]>, +} + +impl Context { + pub fn new() -> Context { + let slice1 = unsafe { + core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) + }; + + let slice2 = unsafe { + core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) + }; + + Context { + current_term: 0, + vga1: vga::Writer::new(slice1), + vga2: vga::Writer::new(slice2), + } + } + + pub fn switch_term(&mut self) { + self.current_term = { + if self.current_term == 0 { 1 } + else { 0 } + }; + } + + pub fn current_term(&mut self) -> &mut vga::Writer<&'static mut [u8]>{ + if self.current_term == 0 { + &mut self.vga1 + } else { + &mut self.vga2 + } + } +} + diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 09b4f3be..7653340c 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,32 +1,30 @@ +extern crate core; + +use cpuio; +use context; +// use vga::color::{Color, ColorCode}; + pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; -use vga; -use cpuio; -use vga::buffer::{Writer, Screen}; - -pub fn kbd_loop(writer: &mut Writer) { - let terminal_one: vga::terminal::Terminal = vga::Screen::new(); +pub fn kbd_callback(context: &mut context::Context) { // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); - let control = unsafe { cpuio::inb(0x64) }; if (control & 1) == 1 { let scancode = unsafe { cpuio::inb(0x60) }; - - //TODO current_screen() with mutex lock? - let current_screen = terminal_one; - //TODO implement logic to translate scancode->ascii match self::SCANCODE_TO_ASCII.get(scancode as usize) { + Some(&b'1') => { + context.switch_term(); + context.current_term().flush(); + } Some(ascii) => { - //TODO screen switching logic - // if let Some(action) = Screen::keypress(current_screen, *ascii as char) { - if let Some(action) = current_screen.keypress(*ascii as char) { - writer.action(action); - } + let mut terminal = context.current_term(); + terminal.keypress(*ascii); }, None =>{}, // None => println!("nokey ctrl {:x}", control), } + // current_screen.flush(); } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 636dbbfb..51bb83a1 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -14,6 +14,7 @@ mod vga; #[allow(dead_code)] mod cpuio; mod keyboard; +mod context; #[no_mangle] pub extern fn kmain() -> ! { @@ -40,7 +41,11 @@ pub extern fn kmain() -> ! { // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); // println!(">> Kernel startup..."); - unsafe { loop { keyboard::kbd_loop(&mut vga::buffer::WRITER); } }; + let mut context = context::Context::new(); + + loop { + keyboard::kbd_callback(&mut context); + } } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index 34617c44..7461d9ca 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -7,11 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use volatile::Volatile; - use super::{Color, ColorCode}; -use core::ptr::Unique; -use core::fmt; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -20,93 +16,83 @@ struct ScreenChar { color_code: ColorCode, } -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; +const BUFFER_ROWS: usize = 25; +const BUFFER_COLS: usize = 80 * 2; -pub struct Writer { - pub column_position: usize, - pub color_code: ColorCode, - vgabuffer: Unique, +pub struct Writer> { + pub position: usize, + color_code: ColorCode, + slice: T, + buffer: [u8; BUFFER_ROWS * BUFFER_COLS], } -// Writer is the default object to use to print to screen -pub static mut WRITER: Writer = Writer { - column_position: 0, - color_code: ColorCode::new(Color::White, Color::Black), - vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}; - -// blank is black for everyone, could make screens choose this -static BLANK: ScreenChar = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::White, Color::Black), -}; - -impl Writer { - pub fn action(&mut self, action: BufferAction) { - match action { - BufferAction::WRITE_BYTE(ascii) => self.write_byte(ascii as u8), - BufferAction::CLEAR_SCREEN => self.reset_screen(), +impl> Writer { + pub fn new(slice: T) -> Writer { + Writer { + slice, + position: 0, + color_code: ColorCode::new(Color::White, Color::Black), + buffer: [0; BUFFER_ROWS * BUFFER_COLS], } } - pub fn reset_screen(&mut self) - { - let color_code = self.color_code; - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: b' ', - color_code, - }); - } - } - self.column_position = 0; + pub fn keypress(&mut self, ascii: u8) { + self.write_byte(ascii); } pub fn write_byte(&mut self, byte: u8) { + let i = self.position; + match byte { - b'\n' => { self.new_line(); } + + b'\n' => { + //reset cursor + self.buffer[self.position + 1] = ColorCode::new(Color::White, Color::Black).0; + let current_line = self.position / (BUFFER_COLS); + self.position = (current_line + 1) * BUFFER_COLS; + } byte => { - if self.column_position >= BUFFER_WIDTH { - self.new_line(); - } - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - let color_code = self.color_code; - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; + self.buffer[i] = byte; + self.buffer[i + 1] = self.color_code.0; + self.position += 2; } } + + if self.position >= self.buffer.len() { + self.scroll(); + } + + // cursor + self.buffer[self.position] = b' '; + self.buffer[self.position + 1] = ColorCode::new(Color::LightGray, Color::LightGray).0; + + self.flush(); } - fn buffer(&mut self) -> &mut Buffer { - unsafe { self.vgabuffer.as_mut() } + pub fn flush(&mut self) { + self.slice.as_mut().clone_from_slice(&self.buffer); } - fn new_line(&mut self) { - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = self.buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); + fn scroll(&mut self) { + + for row in 1..BUFFER_ROWS { + for col in 0..BUFFER_COLS { + let prev_position = ((row - 1) * BUFFER_COLS) + col; + let current_position = (row * BUFFER_COLS) + col; + self.buffer[prev_position] = self.buffer[current_position]; } } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - fn clear_row(&mut self, row: usize) { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(BLANK); + for col in 0..BUFFER_COLS/2 { + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; } + + self.position = (BUFFER_ROWS - 1) * BUFFER_COLS; } } -impl fmt::Write for Writer { +use core::fmt; +impl> fmt::Write for Writer { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { for byte in s.bytes() { self.write_byte(byte) @@ -114,20 +100,3 @@ impl fmt::Write for Writer { Ok(()) } } - -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], -} - -pub enum BufferAction { - WRITE_BYTE(char), - CLEAR_SCREEN, -} - -/// Implementors of this trait can use the vga screen for any purpose -pub trait Screen { - fn new() -> Self; // - fn keypress(self, keycode: char) -> Option; - // fn load(); - // fn unload() -> ; -} diff --git a/kernel-rs/src/vga/color.rs b/kernel-rs/src/vga/color.rs index dc24b1ef..91bf39c4 100644 --- a/kernel-rs/src/vga/color.rs +++ b/kernel-rs/src/vga/color.rs @@ -21,7 +21,7 @@ pub enum Color { } #[derive(Debug, Clone, Copy)] -pub struct ColorCode(u8); +pub struct ColorCode(pub u8); impl ColorCode { pub const fn new(foreground: Color, background: Color) -> ColorCode { diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 2a7984e3..6d491ba0 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,10 +1,9 @@ #[macro_use] pub mod buffer; pub mod color; -pub mod terminal; pub use self::color::{Color, ColorCode}; -pub use self::buffer::{WRITER, Screen, BufferAction}; +pub use self::buffer::{Writer}; // use self::buffer::Writer; // use core::fmt; diff --git a/kernel-rs/src/vga/terminal.rs b/kernel-rs/src/vga/terminal.rs deleted file mode 100644 index 0f1fcb9a..00000000 --- a/kernel-rs/src/vga/terminal.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! terminal.rs implements a basic cursor terminal using the vga::buffer module - -use super::{Color, ColorCode}; -use vga; - -// cursor is lightgray for everyone -static CURSOR: ColorCode = ColorCode::new(Color::LightGray, Color::White); - -pub struct Terminal { } - -impl vga::Screen for Terminal { - fn new() -> Terminal { - Terminal { } - } - - fn keypress(self, ascii: char) -> Option { - Some(vga::BufferAction::WRITE_BYTE(ascii)) - } -} From c1cb1e562033aadc71388d18595bc85e6087863b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 16:06:00 +0100 Subject: [PATCH 037/151] greatly simplified Writer by removing T generic, 0xb8000 is now hardcoded in flush() --- kernel-rs/src/context.rs | 18 +++++------------- kernel-rs/src/keyboard.rs | 1 - kernel-rs/src/vga/buffer.rs | 36 +++++++++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index cb61b08f..6eb76626 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -5,24 +5,16 @@ use vga; pub struct Context { pub current_term: u8, - pub vga1: vga::Writer<&'static mut [u8]>, - pub vga2: vga::Writer<&'static mut [u8]>, + pub vga1: vga::Writer, + pub vga2: vga::Writer, } impl Context { pub fn new() -> Context { - let slice1 = unsafe { - core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) - }; - - let slice2 = unsafe { - core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) - }; - Context { current_term: 0, - vga1: vga::Writer::new(slice1), - vga2: vga::Writer::new(slice2), + vga1: vga::Writer::new(), + vga2: vga::Writer::new(), } } @@ -33,7 +25,7 @@ impl Context { }; } - pub fn current_term(&mut self) -> &mut vga::Writer<&'static mut [u8]>{ + pub fn current_term(&mut self) -> &mut vga::Writer{ if self.current_term == 0 { &mut self.vga1 } else { diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 7653340c..7cc66263 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -6,7 +6,6 @@ use context; pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; - pub fn kbd_callback(context: &mut context::Context) { // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); let control = unsafe { cpuio::inb(0x64) }; diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index 7461d9ca..a7765905 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -16,20 +16,41 @@ struct ScreenChar { color_code: ColorCode, } +// macro_rules! print { +// ($($arg:tt)*) => ({ +// $crate::vga_buffer::print(format_args!($($arg)*)); +// }); +// } + +// macro_rules! println { +// ($fmt:expr) => (print!(concat!($fmt, "\n"))); +// ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +// } + +// pub fn print(args: fmt::Arguments) { +// use core::fmt::Write; +// context.current_screen().write_fmt(args).unwrap(); +// } + + +extern crate core; + +// pub const unsafe fn vga_slice() -> &'static [u8] { +// unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) } +// } + const BUFFER_ROWS: usize = 25; const BUFFER_COLS: usize = 80 * 2; -pub struct Writer> { +pub struct Writer { pub position: usize, color_code: ColorCode, - slice: T, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], } -impl> Writer { - pub fn new(slice: T) -> Writer { +impl Writer { + pub fn new() -> Writer { Writer { - slice, position: 0, color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], @@ -70,7 +91,8 @@ impl> Writer { } pub fn flush(&mut self) { - self.slice.as_mut().clone_from_slice(&self.buffer); + let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; + slice.as_mut().clone_from_slice(&self.buffer); } fn scroll(&mut self) { @@ -92,7 +114,7 @@ impl> Writer { } use core::fmt; -impl> fmt::Write for Writer { +impl fmt::Write for Writer { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { for byte in s.bytes() { self.write_byte(byte) From 2503fdb96defd2e096397b5e7d3bf0fa1d2058ab Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 16:11:47 +0100 Subject: [PATCH 038/151] CONTEXT is instanciated at compile time now --- kernel-rs/src/context.rs | 13 +++++-------- kernel-rs/src/keyboard.rs | 27 +++++++++++++-------------- kernel-rs/src/lib.rs | 4 +--- kernel-rs/src/vga/buffer.rs | 2 +- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 6eb76626..06ca9bb4 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -2,6 +2,11 @@ extern crate core; use vga; +pub static mut CONTEXT: Context = Context { + current_term: 0, + vga1: vga::Writer::new(), + vga2: vga::Writer::new(), +}; pub struct Context { pub current_term: u8, @@ -10,14 +15,6 @@ pub struct Context { } impl Context { - pub fn new() -> Context { - Context { - current_term: 0, - vga1: vga::Writer::new(), - vga2: vga::Writer::new(), - } - } - pub fn switch_term(&mut self) { self.current_term = { if self.current_term == 0 { 1 } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 7cc66263..8ea0148b 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,29 +1,28 @@ extern crate core; use cpuio; -use context; +use context::CONTEXT; // use vga::color::{Color, ColorCode}; pub static SCANCODE_TO_ASCII: [u8; 59] = *b"??1234567890-=??qwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ?"; -pub fn kbd_callback(context: &mut context::Context) { +pub fn kbd_callback() { // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); let control = unsafe { cpuio::inb(0x64) }; if (control & 1) == 1 { let scancode = unsafe { cpuio::inb(0x60) }; - //TODO implement logic to translate scancode->ascii - match self::SCANCODE_TO_ASCII.get(scancode as usize) { - Some(&b'1') => { - context.switch_term(); - context.current_term().flush(); + unsafe { + match self::SCANCODE_TO_ASCII.get(scancode as usize) { + Some(&b'1') => { + CONTEXT.switch_term(); + CONTEXT.current_term().flush(); + } + Some(ascii) => { + CONTEXT.current_term().keypress(*ascii); + }, + None =>{}, + // None => println!("nokey ctrl {:x}", control), } - Some(ascii) => { - let mut terminal = context.current_term(); - terminal.keypress(*ascii); - }, - None =>{}, - // None => println!("nokey ctrl {:x}", control), } - // current_screen.flush(); } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 51bb83a1..77f1d37d 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -41,10 +41,8 @@ pub extern fn kmain() -> ! { // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); // println!(">> Kernel startup..."); - let mut context = context::Context::new(); - loop { - keyboard::kbd_callback(&mut context); + keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index a7765905..eb946ea9 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -49,7 +49,7 @@ pub struct Writer { } impl Writer { - pub fn new() -> Writer { + pub const fn new() -> Writer { Writer { position: 0, color_code: ColorCode::new(Color::White, Color::Black), From 3f2068de993067e8321eb6f383d63ac74f94b2e9 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 16:16:42 +0100 Subject: [PATCH 039/151] print[ln] macros in place --- kernel-rs/src/keyboard.rs | 1 + kernel-rs/src/lib.rs | 33 +++++++++++++++------------------ kernel-rs/src/vga/buffer.rs | 29 +++++++++++++++-------------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 8ea0148b..cb679002 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -19,6 +19,7 @@ pub fn kbd_callback() { } Some(ascii) => { CONTEXT.current_term().keypress(*ascii); + CONTEXT.current_term().flush(); }, None =>{}, // None => println!("nokey ctrl {:x}", control), diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 77f1d37d..35fd69ad 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -22,24 +22,21 @@ pub extern fn kmain() -> ! { // use vga::color::Color; // use vga::color::ColorCode; - // WRITER.lock().reset_screen(); - // WRITER.lock().color_code = ColorCode::new(Color::Yellow, Color::Black); - // println!(r#" ,--, "#); - // println!(r#" ,--.'| ,----, "#); - // println!(r#" ,--, | : .' .' \ "#); - // println!(r#",---.'| : ' ,----,' | "#); - // println!(r#"; : | | ; | : . ; "#); - // println!(r#"| | : _' | ; |.' / "#); - // println!(r#": : |.' | `----'/ ; "#); - // println!(r#"| ' ' ; : / ; / "#); - // println!(r#"\ \ .'. | ; / /-, "#); - // println!(r#" `---`: | ' / / /.`| "#); - // println!(r#" ' ; |./__; : "#); - // println!(r#" | : ;| : .' "#); - // println!(r#" ' ,/ ; | .' "#); - // println!(r#" '--' `---' "#); - // WRITER.lock().color_code = ColorCode::new(Color::White, Color::Black); - // println!(">> Kernel startup..."); + println!(r#" ,--, "#); + println!(r#" ,--.'| ,----, "#); + println!(r#" ,--, | : .' .' \ "#); + println!(r#",---.'| : ' ,----,' | "#); + println!(r#"; : | | ; | : . ; "#); + println!(r#"| | : _' | ; |.' / "#); + println!(r#": : |.' | `----'/ ; "#); + println!(r#"| ' ' ; : / ; / "#); + println!(r#"\ \ .'. | ; / /-, "#); + println!(r#" `---`: | ' / / /.`| "#); + println!(r#" ' ; |./__; : "#); + println!(r#" | : ;| : .' "#); + println!(r#" ' ,/ ; | .' "#); + println!(r#" '--' `---' "#); + println!(">> Kernel startup..."); loop { keyboard::kbd_callback(); diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index eb946ea9..7faf3e43 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -8,6 +8,7 @@ // except according to those terms. use super::{Color, ColorCode}; +use ::context::CONTEXT; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -16,21 +17,21 @@ struct ScreenChar { color_code: ColorCode, } -// macro_rules! print { -// ($($arg:tt)*) => ({ -// $crate::vga_buffer::print(format_args!($($arg)*)); -// }); -// } +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::vga::buffer::print(format_args!($($arg)*)); + }); +} -// macro_rules! println { -// ($fmt:expr) => (print!(concat!($fmt, "\n"))); -// ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -// } +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} -// pub fn print(args: fmt::Arguments) { -// use core::fmt::Write; -// context.current_screen().write_fmt(args).unwrap(); -// } +pub fn print(args: fmt::Arguments) { + use core::fmt::Write; + unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; +} extern crate core; @@ -87,7 +88,6 @@ impl Writer { self.buffer[self.position] = b' '; self.buffer[self.position + 1] = ColorCode::new(Color::LightGray, Color::LightGray).0; - self.flush(); } pub fn flush(&mut self) { @@ -119,6 +119,7 @@ impl fmt::Write for Writer { for byte in s.bytes() { self.write_byte(byte) } + self.flush(); Ok(()) } } From 097dfd7ddcaeadf55f192b4533090a08c7b12e70 Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 12 Feb 2018 16:49:30 +0100 Subject: [PATCH 040/151] yolo --- kernel-rs/src/vga_buffer.rs | 175 ------------------------------------ 1 file changed, 175 deletions(-) delete mode 100644 kernel-rs/src/vga_buffer.rs diff --git a/kernel-rs/src/vga_buffer.rs b/kernel-rs/src/vga_buffer.rs deleted file mode 100644 index b245d306..00000000 --- a/kernel-rs/src/vga_buffer.rs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2016 Philipp Oppermann. See the README.md -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use core::ptr::Unique; -use core::fmt; -use spin::Mutex; -use volatile::Volatile; - -const BUFFER_HEIGHT: usize = 25; -const BUFFER_WIDTH: usize = 80; - -pub static WRITER: Mutex = Mutex::new(Writer { - column_position: 0, - color_code: ColorCode::new(Color::White, Color::Black), - vgabuffer: unsafe { Unique::new_unchecked(0xb8000 as *mut _) }, -}); - -// cursor is lightgray for everyone -static CURSOR: ScreenChar = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::LightGray, Color::LightGray), -}; - -// blank is black for everyone, could make screens choose this -static BLANK: ScreenChar = ScreenChar { - ascii_character: b' ', - color_code: ColorCode::new(Color::White, Color::Black), -}; - -pub struct Writer { - column_position: usize, - pub color_code: ColorCode, - vgabuffer: Unique, -} - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::vga_buffer::print(format_args!($($arg)*)); - }); -} - -pub fn print(args: fmt::Arguments) { - use core::fmt::Write; - WRITER.lock().write_fmt(args).unwrap(); -} - -impl Writer { - pub fn reset_screen(&mut self) - { - let color_code = self.color_code; - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: b' ', - color_code, - }); - } - } - self.column_position = 0; - } - - pub fn write_byte(&mut self, byte: u8) { - match byte { - b'\n' => self.new_line(), - byte => { - if self.column_position >= BUFFER_WIDTH { - self.new_line(); - } - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - let color_code = self.color_code; - self.buffer().chars[row][col].write(ScreenChar { - ascii_character: byte, - color_code: color_code, - }); - self.column_position += 1; - } - } - if self.column_position >= BUFFER_WIDTH { - self.new_line(); - } - let row = BUFFER_HEIGHT - 1; - let col = self.column_position; - self.buffer().chars[row][col].write(CURSOR); - } - - fn buffer(&mut self) -> &mut Buffer { - unsafe { self.vgabuffer.as_mut() } - } - - fn new_line(&mut self) { - // remove cursor if newline isnt from end of screen - if self.column_position < BUFFER_WIDTH { - let col = self.column_position; - self.buffer().chars[BUFFER_HEIGHT - 1][col].write(BLANK); - } - for row in 1..BUFFER_HEIGHT { - for col in 0..BUFFER_WIDTH { - let buffer = self.buffer(); - let character = buffer.chars[row][col].read(); - buffer.chars[row - 1][col].write(character); - } - } - self.clear_row(BUFFER_HEIGHT - 1); - self.column_position = 0; - } - - fn clear_row(&mut self, row: usize) { - for col in 0..BUFFER_WIDTH { - self.buffer().chars[row][col].write(BLANK); - } - } -} - -impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { - for byte in s.bytes() { - self.write_byte(byte) - } - Ok(()) - } -} - -#[allow(dead_code)] -#[derive(Debug, Clone, Copy)] -#[repr(u8)] -pub enum Color { - Black = 0, - Blue = 1, - Green = 2, - Cyan = 3, - Red = 4, - Magenta = 5, - Brown = 6, - LightGray = 7, - DarkGray = 8, - LightBlue = 9, - LightGreen = 10, - LightCyan = 11, - LightRed = 12, - Pink = 13, - Yellow = 14, - White = 15, -} - -#[derive(Debug, Clone, Copy)] -pub struct ColorCode(u8); - -impl ColorCode { - pub const fn new(foreground: Color, background: Color) -> ColorCode { - ColorCode((background as u8) << 4 | (foreground as u8)) - } -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - -struct Buffer { - chars: [[Volatile; BUFFER_WIDTH]; BUFFER_HEIGHT], -} From 37d51d2afea4a926ceae9c4af87be4ccbf615338 Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 12 Feb 2018 17:08:06 +0100 Subject: [PATCH 041/151] init kfs_2 --- kernel-rs/Makefile | 1 + kernel-rs/src/arch/x86/boot.asm | 38 +++++++++++++++-------- kernel-rs/src/arch/x86/grub.cfg | 2 +- kernel-rs/src/arch/x86/linker.ld | 4 +++ kernel-rs/src/cpuio.rs | 30 ++++++++++-------- kernel-rs/src/lib.rs | 52 ++++++++++++++++++++++++++------ 6 files changed, 92 insertions(+), 35 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index e42f45ee..96353929 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -12,6 +12,7 @@ project := bluesnow arch ?= x86 NASM := nasm -f elf LD := ld -m elf_i386 -n --gc-sections +# QEMU := qemu-system-x86_64 -device isa-debug-exit,iobase=0xf4,iosize=0x04 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait kernel := build/kernel-$(arch).bin diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 8624af56..0dfa76b8 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -6,18 +6,30 @@ bits 32 start: ; print `OK` to screen ; mov dword [0xb8000], 0x2f4b2f4f - mov word [0xb8000], 0x0248 ; H - mov word [0xb8002], 0x0265 ; e - mov word [0xb8004], 0x026c ; l - mov word [0xb8006], 0x026c ; l - mov word [0xb8008], 0x026f ; o - mov word [0xb800a], 0x022c ; , - mov word [0xb800c], 0x0220 ; - mov word [0xb800e], 0x0277 ; w - mov word [0xb8010], 0x026f ; o - mov word [0xb8012], 0x0272 ; r - mov word [0xb8014], 0x026c ; l - mov word [0xb8016], 0x0264 ; d - mov word [0xb8018], 0x0221 ; ! + ; mov word [0xb8000], 0x0248 ; H + ; mov word [0xb8002], 0x0265 ; e + ; mov word [0xb8004], 0x026c ; l + ; mov word [0xb8006], 0x026c ; l + ; mov word [0xb8008], 0x026f ; o + ; mov word [0xb800a], 0x022c ; , + ; mov word [0xb800c], 0x0220 ; + ; mov word [0xb800e], 0x0277 ; w + ; mov word [0xb8010], 0x026f ; o + ; mov word [0xb8012], 0x0272 ; r + ; mov word [0xb8014], 0x026c ; l + ; mov word [0xb8016], 0x0264 ; d + ; mov word [0xb8018], 0x0221 ; ! + lgdt [gdt_info] call kmain hlt + +; WARNING: Do not insert random label/lines between gdt_xxx label +gdt_start: + ;TODO GDT entries, like null, kernel code, kernel data, user code, user data, TSS... +gdt_info: + dw gdt_info - gdt_start - 1 + dq gdt_start + +section .bss + resb 64 +head_stack: diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg index 982ff586..4e624c0f 100644 --- a/kernel-rs/src/arch/x86/grub.cfg +++ b/kernel-rs/src/arch/x86/grub.cfg @@ -1,4 +1,4 @@ -set timeout=5 +set timeout=0 set default=0 menuentry "Blue Snow" { diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 0e899042..22edafd1 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -12,4 +12,8 @@ SECTIONS { .text : { *(.text) } + + .stack : { + *(.bss) + } } diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index cec23ce5..5ce962a2 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -1,39 +1,45 @@ //! Rust wrappers around the x86-family I/O instructions. /// Read a `u8`-sized value from `port`. -pub unsafe fn inb(port: u16) -> u8 { +pub fn inb(port: u16) -> u8 { // The registers for the `in` and `out` instructions are always the // same: `a` for value, and `d` for the port address. let result: u8; - asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile"); + unsafe {asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile")}; result } /// Write a `u8`-sized `value` to `port`. -pub unsafe fn outb(value: u8, port: u16) { - asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile"); +pub fn outb(value: u8, port: u16) { + unsafe {asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile")}; } /// Read a `u16`-sized value from `port`. -pub unsafe fn inw(port: u16) -> u16 { +pub fn inw(port: u16) -> u16 { let result: u16; - asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile"); + unsafe {asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile")}; result } /// Write a `u8`-sized `value` to `port`. -pub unsafe fn outw(value: u16, port: u16) { - asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile"); +pub fn outw(value: u16, port: u16) { + unsafe {asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile")}; } /// Read a `u32`-sized value from `port`. -pub unsafe fn inl(port: u16) -> u32 { +pub fn inl(port: u16) -> u32 { let result: u32; - asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile"); + unsafe {asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile")}; result } /// Write a `u32`-sized `value` to `port`. -pub unsafe fn outl(value: u32, port: u16) { - asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile"); +pub fn outl(value: u32, port: u16) { + unsafe {asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile")}; +} + +pub fn halt() -> ! { + loop { + unsafe {asm!("hlt")}; //TODO volatile ????? + } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 1f0a7fe5..ce6f1035 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -19,15 +19,40 @@ mod keyboard; #[allow(dead_code)] mod cpuio; -// fn check_shift(key: u8) -> u8 { -// print!("{:b} vs {:b}\n", key as u8, (1<<7) as u8); -// if (key >> 7 & 1) == 1 { -// print!("MATCH"); -// key - (1 << 7) -// } else { -// key -// } -// } + +//TODO implement ACPI to have such functionality +/// Reboot the kernel +/// +/// If reboot failed, will loop on a halt cmd +/// +#[allow(dead_code)] +fn reboot() { + //TODO disable interrupt here something like : asm volatile ("cli"); + + // I will now clear the keyboard buffer + let mut buffer: u8 = 0x02; + while buffer == 0x02 { + buffer = cpuio::inb(0x64); + } + cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work + println!("Reicv reboot command. System cannot reboot yet, he is now halt\n"); + cpuio::halt(); +} + +/// Shutdown the kernel +/// +/// # Pre-requist: +/// Seems that he have to use following line command : +/// `-device isa-debug-exit,iobase=0xf4,iosize=0x04` +/// +/// If shutdown failed, will loop on a halt cmd +/// +#[allow(dead_code)] +fn shutdown() -> ! { + cpuio::outb(0xf4, 0x00);//TODO doesn't work :( + println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); + cpuio::halt(); +} #[no_mangle] pub extern fn kmain() -> ! { // use vga::VgaScreen; @@ -53,6 +78,15 @@ pub extern fn kmain() -> ! { loop { keyboard::kbd_callback(); } + // let control = unsafe { cpuio::inb(0x64) }; + // if (control & 1) == 1 { + // let keycode = unsafe { cpuio::inb(0x60) }; + // match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { + // Some(ascii) => print!("{}", *ascii as char), + // None =>{}, + // // None => println!("nokey ctrl {:x}", control), + // } + // } } #[lang = "eh_personality"] #[no_mangle] From 1e278eebe3328163bc1f6f9f57874e4689fdc0a4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 17:49:39 +0100 Subject: [PATCH 042/151] colors at startup --- kernel-rs/src/lib.rs | 36 +++++++++++++++++++++--------------- kernel-rs/src/vga/buffer.rs | 4 ++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 1f0a7fe5..2ef02d66 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -16,6 +16,9 @@ mod vga; mod context; mod keyboard; +use context::CONTEXT; +use vga::{Color, ColorCode}; + #[allow(dead_code)] mod cpuio; @@ -34,21 +37,24 @@ pub extern fn kmain() -> ! { // use vga::color::Color; // use vga::color::ColorCode; - println!(r#" ,--, "#); - println!(r#" ,--.'| ,----, "#); - println!(r#" ,--, | : .' .' \ "#); - println!(r#",---.'| : ' ,----,' | "#); - println!(r#"; : | | ; | : . ; "#); - println!(r#"| | : _' | ; |.' / "#); - println!(r#": : |.' | `----'/ ; "#); - println!(r#"| ' ' ; : / ; / "#); - println!(r#"\ \ .'. | ; / /-, "#); - println!(r#" `---`: | ' / / /.`| "#); - println!(r#" ' ; |./__; : "#); - println!(r#" | : ;| : .' "#); - println!(r#" ' ,/ ; | .' "#); - println!(r#" '--' `---' "#); - println!(">> Kernel startup..."); + unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}\n", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); + unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } + print!(">"); loop { keyboard::kbd_callback(); diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index 9ead4ce9..5e9e6312 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -31,6 +31,7 @@ macro_rules! println { pub fn print(args: fmt::Arguments) { use core::fmt::Write; unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; + unsafe { CONTEXT.current_term().flush() }; } @@ -45,7 +46,7 @@ const BUFFER_COLS: usize = 80 * 2; pub struct Writer { pub position: usize, - color_code: ColorCode, + pub color_code: ColorCode, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], } @@ -120,7 +121,6 @@ impl fmt::Write for Writer { for byte in s.bytes() { self.write_byte(byte) } - self.flush(); Ok(()) } } From bd86aae5368993516fccc033d8cc3b82052faeff Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Feb 2018 18:00:15 +0100 Subject: [PATCH 043/151] lol --- kernel-rs/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 2ef02d66..c1c05fcc 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -38,7 +38,7 @@ pub extern fn kmain() -> ! { // use vga::color::ColorCode; unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}\n", + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", format_args!("{: ^80}", r#" ,--, "#), format_args!("{: ^80}", r#" ,--.'| ,----, "#), format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), From 9bb408b77a9e30b5a43e53b082058464c184e7da Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 12 Feb 2018 18:19:01 +0100 Subject: [PATCH 044/151] lol --- kernel-rs/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index ce6f1035..dffe3fd0 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -51,6 +51,7 @@ fn reboot() { fn shutdown() -> ! { cpuio::outb(0xf4, 0x00);//TODO doesn't work :( println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); + test cpuio::halt(); } #[no_mangle] From 864d2dca4e8f931f0a8b6a5005b2e14a19d064f4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Feb 2018 09:38:25 +0100 Subject: [PATCH 045/151] cleanup --- kernel-rs/src/keyboard.rs | 75 +++++++++++++++++++-------------------- kernel-rs/src/lib.rs | 21 +++-------- 2 files changed, 40 insertions(+), 56 deletions(-) diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 37f58647..f874aa8c 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -82,48 +82,45 @@ pub fn kbd_callback() { static mut CTRL: bool = false; static mut ALT: bool = false; // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); - let control = unsafe { cpuio::inb(0x64) }; + let control = cpuio::inb(0x64); if (control & 1) == 1 { - let scancode = unsafe { cpuio::inb(0x60) }; + let scancode = cpuio::inb(0x60); let (is_release, scancode) = check_key_state(scancode); - //TODO implement logic to translate scancode->ascii unsafe {//TODO remove unsafe - match self::KEYMAP_US.get(scancode as usize) { - Some(b"\0\0") => { - match scancode { - 0x2A | 0x36 => {SHIFT = !is_release}, - 0x38 => {ALT = !is_release; println!("atl")}, - 0x1D => {CTRL = !is_release; println!("ctrl")}, - 0x0F if !is_release => { - CONTEXT.switch_term(); - CONTEXT.current_term().flush(); - }, - _ => {} - } - }, - // Some(b"2@") if ALT => { - // CONTEXT.switch_term(); - // CONTEXT.current_term().flush(); - // }, - // Some(b"1!") if CTRL && !is_release => { - // CONTEXT.switch_term(); - // CONTEXT.current_term().keypress('>' as u8); - // CONTEXT.current_term().flush(); - // }, - Some(ascii) if !is_release => { - let mut terminal = CONTEXT.current_term(); - if SHIFT { - terminal.keypress(ascii[1]); - } - else { - terminal.keypress(ascii[0]); - } - }, - Some(_) => {}, - None =>{}, - // None => println!("nokey ctrl {:x}", control), + match self::KEYMAP_US.get(scancode as usize) { + Some(b"\0\0") => { + match scancode { + 0x2A | 0x36 => {SHIFT = !is_release}, + 0x38 => {ALT = !is_release; println!("atl")}, + 0x1D => {CTRL = !is_release; println!("ctrl")}, + 0x0F if !is_release => { + CONTEXT.switch_term(); + CONTEXT.current_term().flush(); + }, + _ => {} + } + }, + // Some(b"2@") if ALT => { + // CONTEXT.switch_term(); + // CONTEXT.current_term().flush(); + // }, + // Some(b"1!") if CTRL && !is_release => { + // CONTEXT.switch_term(); + // CONTEXT.current_term().keypress('>' as u8); + // CONTEXT.current_term().flush(); + // }, + Some(ascii) if !is_release => { + let mut terminal = CONTEXT.current_term(); + if SHIFT { + terminal.keypress(ascii[1]); + } + else { + terminal.keypress(ascii[0]); + } + }, + Some(_) => {}, + None =>{}, + } } - } - // current_screen.flush(); } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index ce6f1035..3fe7cd67 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -55,10 +55,6 @@ fn shutdown() -> ! { } #[no_mangle] pub extern fn kmain() -> ! { - // use vga::VgaScreen; - // use vga::color::Color; - // use vga::color::ColorCode; - println!(r#" ,--, "#); println!(r#" ,--.'| ,----, "#); println!(r#" ,--, | : .' .' \ "#); @@ -78,15 +74,6 @@ pub extern fn kmain() -> ! { loop { keyboard::kbd_callback(); } - // let control = unsafe { cpuio::inb(0x64) }; - // if (control & 1) == 1 { - // let keycode = unsafe { cpuio::inb(0x60) }; - // match keyboard::KEY_CODE_TO_ASCII.get(keycode as usize) { - // Some(ascii) => print!("{}", *ascii as char), - // None =>{}, - // // None => println!("nokey ctrl {:x}", control), - // } - // } } #[lang = "eh_personality"] #[no_mangle] @@ -96,12 +83,12 @@ pub extern fn eh_personality() { #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt( - // fmt: core::fmt::Arguments, file: &'static str, line: u32 + fmt: core::fmt::Arguments, file: &'static str, line: u32 ) -> ! { - // println!("PANIC: {}", fmt); - // println!("FILE: {}", file); - // println!("LINE: {}", line); + println!("PANIC: {}", fmt); + println!("FILE: {}", file); + println!("LINE: {}", line); loop {} } From d6423d5a78e080c530d56d98544de6476e848544 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Feb 2018 09:40:26 +0100 Subject: [PATCH 046/151] cleanup --- kernel-rs/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 3fe7cd67..66a72252 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -11,15 +11,12 @@ extern crate rlibc; #[macro_use] mod vga; -#[allow(dead_code)] -#[macro_use] mod context; mod keyboard; #[allow(dead_code)] mod cpuio; - //TODO implement ACPI to have such functionality /// Reboot the kernel /// From 6598cbe3eb13ec9ad61e4428ffd1a01288d1893d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Feb 2018 14:35:17 +0100 Subject: [PATCH 047/151] cursor is now the real VGA buffer cursor --- kernel-rs/src/vga/buffer.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index 5e9e6312..d5491b1d 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -9,6 +9,7 @@ use super::{Color, ColorCode}; use ::context::CONTEXT; +use cpuio; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -34,13 +35,8 @@ pub fn print(args: fmt::Arguments) { unsafe { CONTEXT.current_term().flush() }; } - extern crate core; -// pub const unsafe fn vga_slice() -> &'static [u8] { -// unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) } -// } - const BUFFER_ROWS: usize = 25; const BUFFER_COLS: usize = 80 * 2; @@ -70,8 +66,6 @@ impl Writer { match byte { b'\n' => { - //reset cursor - self.buffer[self.position + 1] = ColorCode::new(Color::White, Color::Black).0; let current_line = self.position / (BUFFER_COLS); self.position = (current_line + 1) * BUFFER_COLS; } @@ -86,10 +80,11 @@ impl Writer { self.scroll(); } - // cursor - self.buffer[self.position] = b' '; - self.buffer[self.position + 1] = ColorCode::new(Color::LightGray, Color::LightGray).0; - + let cursor_position = self.position / 2; + cpuio::outb(14, 0x3D4); + cpuio::outb((cursor_position >> 8) as u8, 0x3D5); + cpuio::outb(15, 0x3D4); + cpuio::outb((cursor_position >> 0) as u8 & 0x00ff, 0x3D5); } pub fn flush(&mut self) { From f6384015d62e30379e449b8abfd3d643097f7c28 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 15 Feb 2018 11:09:27 +0100 Subject: [PATCH 048/151] starting to convert vga buffer to a terminal --- kernel-rs/src/vga/buffer.rs | 43 ++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index d5491b1d..c8aa0643 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -41,48 +41,70 @@ const BUFFER_ROWS: usize = 25; const BUFFER_COLS: usize = 80 * 2; pub struct Writer { - pub position: usize, + pub buffer_pos: usize, pub color_code: ColorCode, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], + command: [u8; 10], + command_len: usize, } impl Writer { pub const fn new() -> Writer { Writer { - position: 0, + buffer_pos: 0, color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], + command: [0; 10], + command_len: 0, } } pub fn keypress(&mut self, ascii: u8) { - self.write_byte(ascii); + match ascii { + b'\n' => { + self.command_len = 0; + self.write_byte(b'\n'); + println!("{:?}", self.command.iter()); + self.write_byte(b'>'); + } + byte => { + if self.command_len >= 10 { return }; + + self.write_byte(byte); + self.command_len += 1; + } + } self.flush(); } pub fn write_byte(&mut self, byte: u8) { - let i = self.position; + let i = self.buffer_pos; match byte { b'\n' => { - let current_line = self.position / (BUFFER_COLS); - self.position = (current_line + 1) * BUFFER_COLS; + let current_line = self.buffer_pos / (BUFFER_COLS); + self.buffer_pos = (current_line + 1) * BUFFER_COLS; } byte => { self.buffer[i] = byte; self.buffer[i + 1] = self.color_code.0; - self.position += 2; + self.buffer_pos += 2; } } - if self.position >= self.buffer.len() { + if self.buffer_pos >= self.buffer.len() { self.scroll(); } + } - let cursor_position = self.position / 2; + fn flush_cursor(&self) + { + let cursor_position = self.buffer_pos / 2; + // 14 awaits the rightmost 8bits cpuio::outb(14, 0x3D4); cpuio::outb((cursor_position >> 8) as u8, 0x3D5); + // 15 awaits the leftmost 8bits cpuio::outb(15, 0x3D4); cpuio::outb((cursor_position >> 0) as u8 & 0x00ff, 0x3D5); } @@ -90,6 +112,7 @@ impl Writer { pub fn flush(&mut self) { let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; slice.as_mut().clone_from_slice(&self.buffer); + self.flush_cursor(); } fn scroll(&mut self) { @@ -106,7 +129,7 @@ impl Writer { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; } - self.position = (BUFFER_ROWS - 1) * BUFFER_COLS; + self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; } } From c3f7c123f61601df7cc77ad3f8520fb3ba1a80be Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 15 Feb 2018 17:55:41 +0100 Subject: [PATCH 049/151] gdt rocks --- kernel-rs/Makefile | 6 +- kernel-rs/src/arch/x86/boot.asm | 112 ++++++++++++++++++++++++------- kernel-rs/src/arch/x86/linker.ld | 30 +++++---- kernel-rs/src/arch/x86/start.asm | 25 +++++++ kernel-rs/src/keyboard.rs | 4 +- kernel-rs/src/lib.rs | 2 +- 6 files changed, 135 insertions(+), 44 deletions(-) create mode 100644 kernel-rs/src/arch/x86/start.asm diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 96353929..b4f1aed8 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -30,11 +30,12 @@ asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_ KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ - kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 1 \` + kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 1 \`;\ + kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 2 \` GDB := gdb -q\ -ex \"set arch i386:x86-64\"\ -ex \"file build/kernel-x86.bin\"\ - -ex \"target remote localhost:$(PORTG)\"\ + -ex \"target remote localhost:$(PORTG)\" \ -ex \"continue\" all: $(kernel) @@ -42,6 +43,7 @@ all: $(kernel) build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile @mkdir -p $(shell dirname $@) @$(NASM) $< -o $@ + @echo "Compiling (ASM) $@..." $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile @$(LD) -o $(kernel) -T $(linker_script) $(asm_object) $(rust_os) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 0dfa76b8..51629f02 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -1,35 +1,95 @@ global start -extern kmain +extern x86_start section .text bits 32 start: - ; print `OK` to screen - ; mov dword [0xb8000], 0x2f4b2f4f - ; mov word [0xb8000], 0x0248 ; H - ; mov word [0xb8002], 0x0265 ; e - ; mov word [0xb8004], 0x026c ; l - ; mov word [0xb8006], 0x026c ; l - ; mov word [0xb8008], 0x026f ; o - ; mov word [0xb800a], 0x022c ; , - ; mov word [0xb800c], 0x0220 ; - ; mov word [0xb800e], 0x0277 ; w - ; mov word [0xb8010], 0x026f ; o - ; mov word [0xb8012], 0x0272 ; r - ; mov word [0xb8014], 0x026c ; l - ; mov word [0xb8016], 0x0264 ; d - ; mov word [0xb8018], 0x0221 ; ! - lgdt [gdt_info] - call kmain - hlt + mov esp, head_stack + mov edi, ebx + + call check_multiboot + lgdt [GDTR.ptr] + jmp GDTR.gdt_cs:x86_start + +error: + mov dword [0xb8000], 0x4f524f45 + mov dword [0xb8004], 0x4f3a4f52 + mov dword [0xb8008], 0x4f204f20 + mov byte [0xb800a], al + cli +HALT: + hlt + jmp HALT + +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "0" + jmp error + +section .gdt +GDTR: +; http://tuttlem.github.io/2014/07/11/a-gdt-primer.html +.gdt_top: + DD 0, 0 +.gdt_cs: equ $ - .gdt_top; the code segment Aka KERNEL CODE + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0x9A ; [ Access Flags: 0x9A=10011010b = (present)|(Privilege Ring 0=00b)|(1)|(code => 1)|(expand down => 0)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_ds: equ $ - .gdt_top; the data segment Aka KERNEL DATA + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0x92 ; [ Access Flags: 0x92=10010010b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK + DW 0x0 ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK + DW 0x0 ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0xF2 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) + +.gdt_bottom: +.ptr: + DW .gdt_bottom - .gdt_top - 1 + DD .gdt_top -; WARNING: Do not insert random label/lines between gdt_xxx label -gdt_start: - ;TODO GDT entries, like null, kernel code, kernel data, user code, user data, TSS... -gdt_info: - dw gdt_info - gdt_start - 1 - dq gdt_start section .bss - resb 64 +align 4 +stack_end: + resb 4096 * 4 head_stack: diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 22edafd1..c0555f73 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -2,18 +2,22 @@ ENTRY(start) OUTPUT_FORMAT(elf32-i386) SECTIONS { + /* GDT for the win */ + . = 0x800; + .gdt : {KEEP(*(.gdt))} + /* VGA, cannot use section for this */ + . = 0xb8000; + VGA_PTR = . ; + . += 80 * 25 * 2; + . = 1M; - - .boot : { - /* ensure that the multiboot header is at the beginning */ - KEEP(*(.multiboot_header)) - } - - .text : { - *(.text) - } - - .stack : { - *(.bss) - } + kernel_start = . ; + /* ensure that the multiboot header is at the beginning */ + .boot : {KEEP(*(.multiboot_header))} + .text : {*(.text)} + /* .rodata BLOCK(4K) : ALIGN(4K) {*(.rodata)} */ + /* .data BLOCK(4K) : ALIGN(4K) {*(.data)} */ +/* load stack */ + .bss : {*(.bss)} + kernel_end = . ; } diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm new file mode 100644 index 00000000..53125fab --- /dev/null +++ b/kernel-rs/src/arch/x86/start.asm @@ -0,0 +1,25 @@ +global x86_start +extern kmain + +section .text +bits 32 +x86_start: +; we should clear register but it does not work +; mov ax, 0 +; mov ss, ax +; mov ds, ax +; mov es, ax +; mov fs, ax +; mov gs, ax + +; PRINT OK +; mov dword [0xb8000], 0x2f4b2f4f +; hlt + + call kmain + +; if main return, loop forever ; that should NEVER append + cli ; clear interrupt +HALT: + hlt + jmp HALT diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 37f58647..eabca0fa 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -82,9 +82,9 @@ pub fn kbd_callback() { static mut CTRL: bool = false; static mut ALT: bool = false; // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); - let control = unsafe { cpuio::inb(0x64) }; + let control = cpuio::inb(0x64); if (control & 1) == 1 { - let scancode = unsafe { cpuio::inb(0x60) }; + let scancode = cpuio::inb(0x60); let (is_release, scancode) = check_key_state(scancode); //TODO implement logic to translate scancode->ascii unsafe {//TODO remove unsafe diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index dffe3fd0..5ea57084 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -51,9 +51,9 @@ fn reboot() { fn shutdown() -> ! { cpuio::outb(0xf4, 0x00);//TODO doesn't work :( println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); - test cpuio::halt(); } + #[no_mangle] pub extern fn kmain() -> ! { // use vga::VgaScreen; From 0e7b73e2fa3441457725aa8add0dfa4fd88b1de1 Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 15 Feb 2018 19:38:27 +0100 Subject: [PATCH 050/151] mini-shell for 3 cmd. we have to implemente it now --- kernel-rs/src/arch/x86/start.asm | 14 +++---- kernel-rs/src/keyboard.rs | 16 +++----- kernel-rs/src/lib.rs | 12 ++++-- kernel-rs/src/vga/buffer.rs | 65 ++++++++++++++++++++++++++++++-- 4 files changed, 82 insertions(+), 25 deletions(-) diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index 53125fab..0ac7dd3d 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -4,13 +4,13 @@ extern kmain section .text bits 32 x86_start: -; we should clear register but it does not work -; mov ax, 0 -; mov ss, ax -; mov ds, ax -; mov es, ax -; mov fs, ax -; mov gs, ax +; we should clear register but it does not work, it's okay with 0x10 instead of 0 +mov ax, 0x10 +mov ss, ax +mov ds, ax +mov es, ax +mov fs, ax +mov gs, ax ; PRINT OK ; mov dword [0xb8000], 0x2f4b2f4f diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index f874aa8c..acc65937 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -91,24 +91,18 @@ pub fn kbd_callback() { Some(b"\0\0") => { match scancode { 0x2A | 0x36 => {SHIFT = !is_release}, - 0x38 => {ALT = !is_release; println!("atl")}, - 0x1D => {CTRL = !is_release; println!("ctrl")}, + 0x38 => {ALT = !is_release}, + 0x1D => {CTRL = !is_release}, 0x0F if !is_release => { CONTEXT.switch_term(); CONTEXT.current_term().flush(); }, + 0x0E if !is_release => { + CONTEXT.current_term().backspace(); + } _ => {} } }, - // Some(b"2@") if ALT => { - // CONTEXT.switch_term(); - // CONTEXT.current_term().flush(); - // }, - // Some(b"1!") if CTRL && !is_release => { - // CONTEXT.switch_term(); - // CONTEXT.current_term().keypress('>' as u8); - // CONTEXT.current_term().flush(); - // }, Some(ascii) if !is_release => { let mut terminal = CONTEXT.current_term(); if SHIFT { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 8fcdaedc..d9bbf662 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -25,7 +25,6 @@ mod cpuio; /// /// If reboot failed, will loop on a halt cmd /// -#[allow(dead_code)] fn reboot() { //TODO disable interrupt here something like : asm volatile ("cli"); @@ -47,13 +46,19 @@ fn reboot() { /// /// If shutdown failed, will loop on a halt cmd /// -#[allow(dead_code)] fn shutdown() -> ! { cpuio::outb(0xf4, 0x00);//TODO doesn't work :( println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); cpuio::halt(); } +/// Print the kernel stack +/// +fn print_kernel_stack() { + println!("It's a stack print"); + +} + #[no_mangle] pub extern fn kmain() -> ! { unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } @@ -73,7 +78,8 @@ pub extern fn kmain() -> ! { format_args!("{: ^80}", r#" ' ,/ ; | .' "#), format_args!("{: ^80}", r#" '--' `---' "#)); unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } - print!(">"); + unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } + unsafe { CONTEXT.vga2.prompt(); } loop { keyboard::kbd_callback(); diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index c8aa0643..b454fc1d 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -44,32 +44,75 @@ pub struct Writer { pub buffer_pos: usize, pub color_code: ColorCode, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], - command: [u8; 10], + command: [char; 10], command_len: usize, } +// enum shell_command { +// "reboot" => super::reboot(); +// } + +const NULL: [char; 10] = ['\0'; 10]; +const REBOOT: [char; 10] = ['r', 'e', 'b', 'o', 'o', 't', '\0', '\0', '\0', '\0']; +const HALT: [char; 10] = ['h', 'a', 'l', 't', '\0', '\0', '\0', '\0', '\0', '\0']; +const SHUTDOWN: [char; 10] = ['s', 'h', 'u', 't', 'd', 'o', 'w', 'n', '\0', '\0']; +const STACK: [char; 10] = ['s', 't', 'a', 'c', 'k', '\0', '\0', '\0', '\0', '\0']; impl Writer { pub const fn new() -> Writer { Writer { buffer_pos: 0, color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], - command: [0; 10], + command: NULL, command_len: 0, } } + pub fn prompt(&mut self) { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Blue, Color::Black); + self.write_str("> "); + self.color_code = color_code_save; + } + + pub fn backspace(&mut self) { + if self.command_len > 0 { + self.command_len -= 1; + self.command[self.command_len] = '\0'; + self.erase_byte(); + } + } + pub fn keypress(&mut self, ascii: u8) { match ascii { b'\n' => { self.command_len = 0; self.write_byte(b'\n'); - println!("{:?}", self.command.iter()); - self.write_byte(b'>'); + // println!("{:?}", self.command.iter()); + match self.command { + SHUTDOWN | HALT => { + super::super::shutdown(); + } + REBOOT => { + super::super::reboot(); + } + STACK => { + super::super::print_kernel_stack(); + } + _ => { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Red, Color::Black); + println!("Command unknown !"); + self.color_code = color_code_save; + } + } + self.command = NULL; + self.prompt(); } byte => { if self.command_len >= 10 { return }; + self.command[self.command_len] = byte as char; self.write_byte(byte); self.command_len += 1; } @@ -77,6 +120,14 @@ impl Writer { self.flush(); } + pub fn erase_byte(&mut self) { + self.buffer_pos -= 2; + let i = self.buffer_pos; + self.buffer[i] = b' '; + self.buffer[i + 1] = 0; + self.flush(); + } + pub fn write_byte(&mut self, byte: u8) { let i = self.buffer_pos; @@ -98,6 +149,12 @@ impl Writer { } } + fn write_str(&mut self, s: &str) { + for byte in s.bytes() { + self.write_byte(byte) + } + } + fn flush_cursor(&self) { let cursor_position = self.buffer_pos / 2; From 554872c8facfd0b6a17632d487bb04bd21c9ee70 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 13:28:59 +0100 Subject: [PATCH 051/151] added console.rs to group commands, refactored the command buffer and command matching code --- kernel-rs/src/console.rs | 41 +++++++++++++++++++++++++ kernel-rs/src/cpuio.rs | 4 +++ kernel-rs/src/lib.rs | 60 +++++++------------------------------ kernel-rs/src/vga/buffer.rs | 53 +++++++++++++------------------- 4 files changed, 75 insertions(+), 83 deletions(-) create mode 100644 kernel-rs/src/console.rs diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs new file mode 100644 index 00000000..c5f8a075 --- /dev/null +++ b/kernel-rs/src/console.rs @@ -0,0 +1,41 @@ +use cpuio; + +//TODO implement ACPI to have such functionality +/// Reboot the kernel +/// +/// If reboot failed, will loop on a halt cmd +/// +pub fn reboot() { + //TODO disable interrupt here something like : asm volatile ("cli"); + + // I will now clear the keyboard buffer + let mut buffer: u8 = 0x02; + while buffer == 0x02 { + buffer = cpuio::inb(0x64); + } + cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work + println!("Reicv reboot command. System cannot reboot yet, he is now halt\n"); + cpuio::halt(); +} + +/// Shutdown the kernel +/// +/// # Pre-requist: +/// Seems that he have to use following line command : +/// `-device isa-debug-exit,iobase=0xf4,iosize=0x04` +/// +/// If shutdown failed, will loop on a halt cmd +/// +pub fn shutdown() -> ! { + cpuio::outb(0xf4, 0x00);//TODO doesn't work :( + println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); + cpuio::halt(); +} + +/// Print the kernel stack +/// +pub fn print_kernel_stack() { + println!("It's a stack print"); + +} + diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 5ce962a2..30821f39 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -1,4 +1,8 @@ //! Rust wrappers around the x86-family I/O instructions. +//! this cmodule uses inline assembly so you need to add +//! `#![feature(asm)]` to yourcrate attributes + +#![allow(dead_code)] /// Read a `u8`-sized value from `port`. pub fn inb(port: u16) -> u8 { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index d9bbf662..b47e56e6 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,64 +1,24 @@ +#![no_std] + #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] -#![feature(asm)] -#![no_std] +#![feature(asm)] //needed by cpuio for inline asm -extern crate spin; -extern crate volatile; +// extern crate spin; +// extern crate volatile; extern crate rlibc; #[macro_use] -mod vga; - -mod context; -mod keyboard; +mod vga; // 80x25 screen and terminal +mod context; // kernel init and environment +mod keyboard; // PS/2 detection and processing +mod console; // vga terminal commands +mod cpuio; // asm wrapper to cpu i/o use context::CONTEXT; use vga::{Color, ColorCode}; -#[allow(dead_code)] -mod cpuio; - -//TODO implement ACPI to have such functionality -/// Reboot the kernel -/// -/// If reboot failed, will loop on a halt cmd -/// -fn reboot() { - //TODO disable interrupt here something like : asm volatile ("cli"); - - // I will now clear the keyboard buffer - let mut buffer: u8 = 0x02; - while buffer == 0x02 { - buffer = cpuio::inb(0x64); - } - cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work - println!("Reicv reboot command. System cannot reboot yet, he is now halt\n"); - cpuio::halt(); -} - -/// Shutdown the kernel -/// -/// # Pre-requist: -/// Seems that he have to use following line command : -/// `-device isa-debug-exit,iobase=0xf4,iosize=0x04` -/// -/// If shutdown failed, will loop on a halt cmd -/// -fn shutdown() -> ! { - cpuio::outb(0xf4, 0x00);//TODO doesn't work :( - println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); - cpuio::halt(); -} - -/// Print the kernel stack -/// -fn print_kernel_stack() { - println!("It's a stack print"); - -} - #[no_mangle] pub extern fn kmain() -> ! { unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs index b454fc1d..65724e7d 100644 --- a/kernel-rs/src/vga/buffer.rs +++ b/kernel-rs/src/vga/buffer.rs @@ -10,6 +10,7 @@ use super::{Color, ColorCode}; use ::context::CONTEXT; use cpuio; +use ::console; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -20,8 +21,8 @@ struct ScreenChar { macro_rules! print { ($($arg:tt)*) => ({ - $crate::vga::buffer::print(format_args!($($arg)*)); - }); + $crate::vga::buffer::print(format_args!($($arg)*)); + }); } macro_rules! println { @@ -44,26 +45,17 @@ pub struct Writer { pub buffer_pos: usize, pub color_code: ColorCode, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], - command: [char; 10], + command: [u8; 10], command_len: usize, } -// enum shell_command { -// "reboot" => super::reboot(); -// } - -const NULL: [char; 10] = ['\0'; 10]; -const REBOOT: [char; 10] = ['r', 'e', 'b', 'o', 'o', 't', '\0', '\0', '\0', '\0']; -const HALT: [char; 10] = ['h', 'a', 'l', 't', '\0', '\0', '\0', '\0', '\0', '\0']; -const SHUTDOWN: [char; 10] = ['s', 'h', 'u', 't', 'd', 'o', 'w', 'n', '\0', '\0']; -const STACK: [char; 10] = ['s', 't', 'a', 'c', 'k', '\0', '\0', '\0', '\0', '\0']; impl Writer { pub const fn new() -> Writer { Writer { buffer_pos: 0, color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], - command: NULL, + command: [b'\0'; 10], command_len: 0, } } @@ -78,7 +70,6 @@ impl Writer { pub fn backspace(&mut self) { if self.command_len > 0 { self.command_len -= 1; - self.command[self.command_len] = '\0'; self.erase_byte(); } } @@ -86,33 +77,28 @@ impl Writer { pub fn keypress(&mut self, ascii: u8) { match ascii { b'\n' => { - self.command_len = 0; self.write_byte(b'\n'); - // println!("{:?}", self.command.iter()); - match self.command { - SHUTDOWN | HALT => { - super::super::shutdown(); - } - REBOOT => { - super::super::reboot(); - } - STACK => { - super::super::print_kernel_stack(); - } - _ => { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); - println!("Command unknown !"); - self.color_code = color_code_save; + { + let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; + match command { + "shutdown" | "halt" => console::shutdown(), + "reboot" => console::reboot(), + "stack" => console::print_kernel_stack(), + _ => { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Red, Color::Black); + println!("`{}': Command unknown ", command); + self.color_code = color_code_save; + } } } - self.command = NULL; + self.command_len = 0; self.prompt(); } byte => { if self.command_len >= 10 { return }; - self.command[self.command_len] = byte as char; + self.command[self.command_len] = byte; self.write_byte(byte); self.command_len += 1; } @@ -190,6 +176,7 @@ impl Writer { } } +// trait needed by formatting macros use core::fmt; impl fmt::Write for Writer { fn write_str(&mut self, s: &str) -> ::core::fmt::Result { From 4f809497ca000f29243fd32ff960c75599642908 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 13:41:23 +0100 Subject: [PATCH 052/151] cargo toml --- kernel-rs/Cargo.toml | 2 - kernel-rs/keycode | 258 ------------------------------------------- kernel-rs/keycode2 | 249 ----------------------------------------- 3 files changed, 509 deletions(-) delete mode 100644 kernel-rs/keycode delete mode 100644 kernel-rs/keycode2 diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index acbbad72..3bb6580b 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -8,5 +8,3 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" -spin = "0.4.5" -volatile = "0.1.0" diff --git a/kernel-rs/keycode b/kernel-rs/keycode deleted file mode 100644 index 5a9d4d08..00000000 --- a/kernel-rs/keycode +++ /dev/null @@ -1,258 +0,0 @@ -0x01 escape pressed -0x02 1 pressed -0x03 2 pressed -0x04 3 pressed -0x05 4 pressed -0x06 5 pressed -0x07 6 pressed -0x08 7 pressed -0x09 8 pressed -0x0A 9 pressed -0x0B 0 (zero) pressed -0x0C - pressed -0x0D = pressed -0x0E backspace pressed -0x0F tab pressed -0x10 Q pressed -0x11 W pressed -0x12 E pressed -0x13 R pressed -0x14 T pressed -0x15 Y pressed -0x16 U pressed -0x17 I pressed -0x18 O pressed -0x19 P pressed -0x1A [ pressed -0x1B ] pressed -0x1C enter pressed -0x1D left control pressed -0x1E A pressed -0x1F S pressed -0x20 D pressed -0x21 F pressed -0x22 G pressed -0x23 H pressed -0x24 J pressed -0x25 K pressed -0x26 L pressed -0x27 ; pressed -0x28 ' (single quote) pressed -0x29 ` (back tick) pressed -0x2A left shift pressed -0x2B \ pressed -0x2C Z pressed -0x2D X pressed -0x2E C pressed -0x2F V pressed -0x30 B pressed -0x31 N pressed -0x32 M pressed -0x33 , pressed -0x34 . pressed -0x35 / pressed -0x36 right shift pressed -0x37 (keypad) * pressed -0x38 left alt pressed -0x39 space pressed -0x3A CapsLock pressed -0x3B F1 pressed -0x3C F2 pressed -0x3D F3 pressed -0x3E F4 pressed -0x3F F5 pressed -0x40 F6 pressed -0x41 F7 pressed -0x42 F8 pressed -0x43 F9 pressed -0x44 F10 pressed -0x45 NumberLock pressed -0x46 ScrollLock pressed -0x47 (keypad) 7 pressed -0x48 (keypad) 8 pressed -0x49 (keypad) 9 pressed -0x4A (keypad) - pressed -0x4B (keypad) 4 pressed -0x4C (keypad) 5 pressed -0x4D (keypad) 6 pressed -0x4E (keypad) + pressed -0x4F (keypad) 1 pressed -0x50 (keypad) 2 pressed -0x51 (keypad) 3 pressed -0x52 (keypad) 0 pressed -0x53 (keypad) . pressed -0x57 F11 pressed -0x58 F12 pressed - - - - - - - - - -0x81 escape released -0x82 1 released -0x83 2 released -0x84 3 released -0x85 4 released -0x86 5 released -0x87 6 released -0x88 7 released -0x89 8 released -0x8A 9 released -0x8B 0 (zero) released -0x8C - released -0x8D = released -0x8E backspace released -0x8F tab released -0x90 Q released -0x91 W released -0x92 E released -0x93 R released -0x94 T released -0x95 Y released -0x96 U released -0x97 I released -0x98 O released -0x99 P released -0x9A [ released -0x9B ] released -0x9C enter released -0x9D left control released -0x9E A released -0x9F S released -0xA0 D released -0xA1 F released -0xA2 G released -0xA3 H released -0xA4 J released -0xA5 K released -0xA6 L released -0xA7 ; released -0xA8 ' (single quote) released -0xA9 ` (back tick) released -0xAA left shift released -0xAB \ released -0xAC Z released -0xAD X released -0xAE C released -0xAF V released -0xB0 B released -0xB1 N released -0xB2 M released -0xB3 , released -0xB4 . released -0xB5 / released -0xB6 right shift released -0xB7 (keypad) * released -0xB8 left alt released -0xB9 space released -0xBA CapsLock released -0xBB F1 released -0xBC F2 released -0xBD F3 released -0xBE F4 released -0xBF F5 released -0xC0 F6 released -0xC1 F7 released -0xC2 F8 released -0xC3 F9 released -0xC4 F10 released -0xC5 NumberLock released -0xC6 ScrollLock released -0xC7 (keypad) 7 released -0xC8 (keypad) 8 released -0xC9 (keypad) 9 released -0xCA (keypad) - released -0xCB (keypad) 4 released -0xCC (keypad) 5 released -0xCD (keypad) 6 released -0xCE (keypad) + released -0xCF (keypad) 1 released -0xD0 (keypad) 2 released -0xD1 (keypad) 3 released -0xD2 (keypad) 0 released -0xD3 (keypad) . released -0xD7 F11 released -0xD8 F12 released -0xE0, 0x10 (multimedia) previous track pressed -0xE0, 0x19 (multimedia) next track pressed -0xE0, 0x1C (keypad) enter pressed -0xE0, 0x1D right control pressed -0xE0, 0x20 (multimedia) mute pressed -0xE0, 0x21 (multimedia) calculator pressed -0xE0, 0x22 (multimedia) play pressed -0xE0, 0x24 (multimedia) stop pressed -0xE0, 0x2E (multimedia) volume down pressed -0xE0, 0x30 (multimedia) volume up pressed -0xE0, 0x32 (multimedia) WWW home pressed -0xE0, 0x35 (keypad) / pressed -0xE0, 0x38 right alt (or altGr) pressed -0xE0, 0x47 home pressed -0xE0, 0x48 cursor up pressed -0xE0, 0x49 page up pressed -0xE0, 0x4B cursor left pressed -0xE0, 0x4D cursor right pressed -0xE0, 0x4F end pressed -0xE0, 0x50 cursor down pressed -0xE0, 0x51 page down pressed -0xE0, 0x52 insert pressed -0xE0, 0x53 delete pressed -0xE0, 0x5B left GUI pressed -0xE0, 0x5C right GUI pressed -0xE0, 0x5D "apps" pressed -0xE0, 0x5E (ACPI) power pressed -0xE0, 0x5F (ACPI) sleep pressed -0xE0, 0x63 (ACPI) wake pressed -0xE0, 0x65 (multimedia) WWW search pressed -0xE0, 0x66 (multimedia) WWW favorites pressed -0xE0, 0x67 (multimedia) WWW refresh pressed -0xE0, 0x68 (multimedia) WWW stop pressed -0xE0, 0x69 (multimedia) WWW forward pressed -0xE0, 0x6A (multimedia) WWW back pressed -0xE0, 0x6B (multimedia) my computer pressed -0xE0, 0x6C (multimedia) email pressed -0xE0, 0x6D (multimedia) media select pressed -0xE0, 0x90 (multimedia) previous track released -0xE0, 0x99 (multimedia) next track released -0xE0, 0x9C (keypad) enter released -0xE0, 0x9D right control released -0xE0, 0xA0 (multimedia) mute released -0xE0, 0xA1 (multimedia) calculator released -0xE0, 0xA2 (multimedia) play released -0xE0, 0xA4 (multimedia) stop released -0xE0, 0xAE (multimedia) volume down released -0xE0, 0xB0 (multimedia) volume up released -0xE0, 0xB2 (multimedia) WWW home released -0xE0, 0xB5 (keypad) / released -0xE0, 0xB8 right alt (or altGr) released -0xE0, 0xC7 home released -0xE0, 0xC8 cursor up released -0xE0, 0xC9 page up released -0xE0, 0xCB cursor left released -0xE0, 0xCD cursor right released -0xE0, 0xCF end released -0xE0, 0xD0 cursor down released -0xE0, 0xD1 page down released -0xE0, 0xD2 insert released -0xE0, 0xD3 delete released -0xE0, 0xDB left GUI released -0xE0, 0xDC right GUI released -0xE0, 0xDD "apps" released -0xE0, 0xDE (ACPI) power released -0xE0, 0xDF (ACPI) sleep released -0xE0, 0xE3 (ACPI) wake released -0xE0, 0xE5 (multimedia) WWW search released -0xE0, 0xE6 (multimedia) WWW favorites released -0xE0, 0xE7 (multimedia) WWW refresh released -0xE0, 0xE8 (multimedia) WWW stop released -0xE0, 0xE9 (multimedia) WWW forward released -0xE0, 0xEA (multimedia) WWW back released -0xE0, 0xEB (multimedia) my computer released -0xE0, 0xEC (multimedia) email released -0xE0, 0xED (multimedia) media select released -0xE0, 0x2A, 0xE0, 0x37 print screen pressed -0xE0, 0xB7, 0xE0, 0xAA print screen released -0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 pause pressed diff --git a/kernel-rs/keycode2 b/kernel-rs/keycode2 deleted file mode 100644 index a7473619..00000000 --- a/kernel-rs/keycode2 +++ /dev/null @@ -1,249 +0,0 @@ -0x01 F9 pressed -0x03 F5 pressed -0x04 F3 pressed -0x05 F1 pressed -0x06 F2 pressed -0x07 F12 pressed -0x09 F10 pressed -0x0A F8 pressed -0x0B F6 pressed -0x0C F4 pressed -0x0D tab pressed -0x0E ` (back tick) pressed -0x11 left alt pressed -0x12 left shift pressed -0x14 left control pressed -0x15 Q pressed -0x16 1 pressed -0x1A Z pressed -0x1B S pressed -0x1C A pressed -0x1D W pressed -0x1E 2 pressed -0x21 C pressed -0x22 X pressed -0x23 D pressed -0x24 E pressed -0x25 4 pressed -0x26 3 pressed -0x29 space pressed -0x2A V pressed -0x2B F pressed -0x2C T pressed -0x2D R pressed -0x2E 5 pressed -0x31 N pressed -0x32 B pressed -0x33 H pressed -0x34 G pressed -0x35 Y pressed -0x36 6 pressed -0x3A M pressed -0x3B J pressed -0x3C U pressed -0x3D 7 pressed -0x3E 8 pressed -0x41 , pressed -0x42 K pressed -0x43 I pressed -0x44 O pressed -0x45 0 (zero) pressed -0x46 9 pressed -0x49 . pressed -0x4A / pressed -0x4B L pressed -0x4C ; pressed -0x4D P pressed -0x4E - pressed -0x52 ' pressed -0x54 [ pressed -0x55 = pressed -0x58 CapsLock pressed -0x59 right shift pressed -0x5A enter pressed -0x5B ] pressed -0x5D \ pressed -0x66 backspace pressed -0x69 (keypad) 1 pressed -0x6B (keypad) 4 pressed -0x6C (keypad) 7 pressed -0x70 (keypad) 0 pressed -0x71 (keypad) . pressed -0x72 (keypad) 2 pressed -0x73 (keypad) 5 pressed -0x74 (keypad) 6 pressed -0x75 (keypad) 8 pressed -0x76 escape pressed -0x77 NumberLock pressed -0x78 F11 pressed -0x79 (keypad) + pressed -0x7A (keypad) 3 pressed -0x7B (keypad) - pressed -0x7C (keypad) * pressed -0x7D (keypad) 9 pressed -0x7E ScrollLock pressed -0x83 F7 pressed -0xE0, 0x10 (multimedia) WWW search pressed -0xE0, 0x11 right alt pressed -0xE0, 0x14 right control pressed -0xE0, 0x15 (multimedia) previous track pressed -0xE0, 0x18 (multimedia) WWW favourites pressed -0xE0, 0x1F left GUI pressed -0xE0, 0x20 (multimedia) WWW refresh pressed -0xE0, 0x21 (multimedia) volume down pressed -0xE0, 0x23 (multimedia) mute pressed -0xE0, 0x27 right GUI pressed -0xE0, 0x28 (multimedia) WWW stop pressed -0xE0, 0x2B (multimedia) calculator pressed -0xE0, 0x2F apps pressed -0xE0, 0x30 (multimedia) WWW forward pressed -0xE0, 0x32 (multimedia) volume up pressed -0xE0, 0x34 (multimedia) play/pause pressed -0xE0, 0x37 (ACPI) power pressed -0xE0, 0x38 (multimedia) WWW back pressed -0xE0, 0x3A (multimedia) WWW home pressed -0xE0, 0x3B (multimedia) stop pressed -0xE0, 0x3F (ACPI) sleep pressed -0xE0, 0x40 (multimedia) my computer pressed -0xE0, 0x48 (multimedia) email pressed -0xE0, 0x4A (keypad) / pressed -0xE0, 0x4D (multimedia) next track pressed -0xE0, 0x50 (multimedia) media select pressed -0xE0, 0x5A (keypad) enter pressed -0xE0, 0x5E (ACPI) wake pressed -0xE0, 0x69 end pressed -0xE0, 0x6B cursor left pressed -0xE0, 0x6C home pressed -0xE0, 0x70 insert pressed -0xE0, 0x71 delete pressed -0xE0, 0x72 cursor down pressed -0xE0, 0x74 cursor right pressed -0xE0, 0x75 cursor up pressed -0xE0, 0x7A page down pressed -0xE0, 0x7D page up pressed -0xF0, 0x01 F9 released -0xF0, 0x03 F5 released -0xF0, 0x04 F3 released -0xF0, 0x05 F1 released -0xF0, 0x06 F2 released -0xF0, 0x07 F12 released -0xF0, 0x09 F10 released -0xF0, 0x0A F8 released -0xF0, 0x0B F6 released -0xF0, 0x0C F4 released -0xF0, 0x0D tab released -0xF0, 0x0E ` (back tick) released -0xF0, 0x11 left alt released -0xF0, 0x12 left shift released -0xF0, 0x14 left control released -0xF0, 0x15 Q released -0xF0, 0x16 1 released -0xF0, 0x1A Z released -0xF0, 0x1B S released -0xF0, 0x1C A released -0xF0, 0x1D W released -0xF0, 0x1E 2 released -0xF0, 0x21 C released -0xF0, 0x22 X released -0xF0, 0x23 D released -0xF0, 0x24 E released -0xF0, 0x25 4 released -0xF0, 0x26 3 released -0xF0, 0x29 space released -0xF0, 0x2A V released -0xF0, 0x2B F released -0xF0, 0x2C T released -0xF0, 0x2D R released -0xF0, 0x2E 5 released -0xF0, 0x31 N released -0xF0, 0x32 B released -0xF0, 0x33 H released -0xF0, 0x34 G released -0xF0, 0x35 Y released -0xF0, 0x36 6 released -0xF0, 0x3A M released -0xF0, 0x3B J released -0xF0, 0x3C U released -0xF0, 0x3D 7 released -0xF0, 0x3E 8 released -0xF0, 0x41 , released -0xF0, 0x42 K released -0xF0, 0x43 I released -0xF0, 0x44 O released -0xF0, 0x45 0 (zero) released -0xF0, 0x46 9 released -0xF0, 0x49 . released -0xF0, 0x4A / released -0xF0, 0x4B L released -0xF0, 0x4C ; released -0xF0, 0x4D P released -0xF0, 0x4E - released -0xF0, 0x52 ' released -0xF0, 0x54 [ released -0xF0, 0x55 = released -0xF0, 0x58 CapsLock released -0xF0, 0x59 right shift released -0xF0, 0x5A enter released -0xF0, 0x5B ] released -0xF0, 0x5D \ released -0xF0, 0x66 backspace released -0xF0, 0x69 (keypad) 1 released -0xF0, 0x6B (keypad) 4 released -0xF0, 0x6C (keypad) 7 released -0xF0, 0x70 (keypad) 0 released -0xF0, 0x71 (keypad) . released -0xF0, 0x72 (keypad) 2 released -0xF0, 0x73 (keypad) 5 released -0xF0, 0x74 (keypad) 6 released -0xF0, 0x75 (keypad) 8 released -0xF0, 0x76 escape released -0xF0, 0x77 NumberLock released -0xF0, 0x78 F11 released -0xF0, 0x79 (keypad) + released -0xF0, 0x7A (keypad) 3 released -0xF0, 0x7B (keypad) - released -0xF0, 0x7C (keypad) * released -0xF0, 0x7D (keypad) 9 released -0xF0, 0x7E ScrollLock released -0xF0, 0x83 F7 released -0xE0, 0x12, 0xE0, 0x7C print screen pressed -0xE0, 0xF0, 0x10 (multimedia) WWW search released -0xE0, 0xF0, 0x11 right alt released -0xE0, 0xF0, 0x14 right control released -0xE0, 0xF0, 0x15 (multimedia) previous track released -0xE0, 0xF0, 0x18 (multimedia) WWW favourites released -0xE0, 0xF0, 0x1F left GUI released -0xE0, 0xF0, 0x20 (multimedia) WWW refresh released -0xE0, 0xF0, 0x21 (multimedia) volume down released -0xE0, 0xF0, 0x23 (multimedia) mute released -0xE0, 0xF0, 0x27 right GUI released -0xE0, 0xF0, 0x28 (multimedia) WWW stop released -0xE0, 0xF0, 0x2B (multimedia) calculator released -0xE0, 0xF0, 0x2F apps released -0xE0, 0xF0, 0x30 (multimedia) WWW forward released -0xE0, 0xF0, 0x32 (multimedia) volume up released -0xE0, 0xF0, 0x34 (multimedia) play/pause released -0xE0, 0xF0, 0x37 (ACPI) power released -0xE0, 0xF0, 0x38 (multimedia) WWW back released -0xE0, 0xF0, 0x3A (multimedia) WWW home released -0xE0, 0xF0, 0x3B (multimedia) stop released -0xE0, 0xF0, 0x3F (ACPI) sleep released -0xE0, 0xF0, 0x40 (multimedia) my computer released -0xE0, 0xF0, 0x48 (multimedia) email released -0xE0, 0xF0, 0x4A (keypad) / released -0xE0, 0xF0, 0x4D (multimedia) next track released -0xE0, 0xF0, 0x50 (multimedia) media select released -0xE0, 0xF0, 0x5A (keypad) enter released -0xE0, 0xF0, 0x5E (ACPI) wake released -0xE0, 0xF0, 0x69 end released -0xE0, 0xF0, 0x6B cursor left released -0xE0, 0xF0, 0x6C home released -0xE0, 0xF0, 0x70 insert released -0xE0, 0xF0, 0x71 delete released -0xE0, 0xF0, 0x72 cursor down released -0xE0, 0xF0, 0x74 cursor right released -0xE0, 0xF0, 0x75 cursor up released -0xE0, 0xF0, 0x7A page down released -0xE0, 0xF0, 0x7D page up released -0xE0, 0xF0, 0x7C, 0xE0, 0xF0, 0x12 print screen released -0xE1, 0x14, 0x77, 0xE1, 0xF0, 0x14, 0xF0, 0x77 pause pressed From 3c2b7f3f75f017fbd05ed736325a46c668bf92ab Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 14:07:26 +0100 Subject: [PATCH 053/151] doesnt compile, 2 sec --- kernel-rs/src/cpuio.rs | 4 - kernel-rs/src/keyboard.rs | 1 - kernel-rs/src/lib.rs | 15 ++- kernel-rs/src/vga/buffer.rs | 188 ----------------------------------- kernel-rs/src/vga/mod.rs | 192 +++++++++++++++++++++++++++++++++--- 5 files changed, 186 insertions(+), 214 deletions(-) delete mode 100644 kernel-rs/src/vga/buffer.rs diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 30821f39..148ee020 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -1,7 +1,3 @@ -//! Rust wrappers around the x86-family I/O instructions. -//! this cmodule uses inline assembly so you need to add -//! `#![feature(asm)]` to yourcrate attributes - #![allow(dead_code)] /// Read a `u8`-sized value from `port`. diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index acc65937..e9832de5 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -2,7 +2,6 @@ extern crate core; use cpuio; use context::CONTEXT; -// use vga::color::{Color, ColorCode}; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b47e56e6..6ecbf2ee 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -10,11 +10,16 @@ extern crate rlibc; #[macro_use] -mod vga; // 80x25 screen and terminal -mod context; // kernel init and environment -mod keyboard; // PS/2 detection and processing -mod console; // vga terminal commands -mod cpuio; // asm wrapper to cpu i/o +/// 80x25 screen and simplistic terminal driver +pub mod vga; +/// kernel init and environment +pub mod context; +/// PS/2 detection and processing +pub mod keyboard; +/// simplisitc kernel commands +pub mod console; +/// wrappers around the x86-family I/O instructions. +pub mod cpuio; use context::CONTEXT; use vga::{Color, ColorCode}; diff --git a/kernel-rs/src/vga/buffer.rs b/kernel-rs/src/vga/buffer.rs deleted file mode 100644 index 65724e7d..00000000 --- a/kernel-rs/src/vga/buffer.rs +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2016 Philipp Oppermann. See the README.md -// file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use super::{Color, ColorCode}; -use ::context::CONTEXT; -use cpuio; -use ::console; - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -struct ScreenChar { - ascii_character: u8, - color_code: ColorCode, -} - -macro_rules! print { - ($($arg:tt)*) => ({ - $crate::vga::buffer::print(format_args!($($arg)*)); - }); -} - -macro_rules! println { - ($fmt:expr) => (print!(concat!($fmt, "\n"))); - ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -} - -pub fn print(args: fmt::Arguments) { - use core::fmt::Write; - unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; - unsafe { CONTEXT.current_term().flush() }; -} - -extern crate core; - -const BUFFER_ROWS: usize = 25; -const BUFFER_COLS: usize = 80 * 2; - -pub struct Writer { - pub buffer_pos: usize, - pub color_code: ColorCode, - buffer: [u8; BUFFER_ROWS * BUFFER_COLS], - command: [u8; 10], - command_len: usize, -} - -impl Writer { - pub const fn new() -> Writer { - Writer { - buffer_pos: 0, - color_code: ColorCode::new(Color::White, Color::Black), - buffer: [0; BUFFER_ROWS * BUFFER_COLS], - command: [b'\0'; 10], - command_len: 0, - } - } - - pub fn prompt(&mut self) { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Blue, Color::Black); - self.write_str("> "); - self.color_code = color_code_save; - } - - pub fn backspace(&mut self) { - if self.command_len > 0 { - self.command_len -= 1; - self.erase_byte(); - } - } - - pub fn keypress(&mut self, ascii: u8) { - match ascii { - b'\n' => { - self.write_byte(b'\n'); - { - let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; - match command { - "shutdown" | "halt" => console::shutdown(), - "reboot" => console::reboot(), - "stack" => console::print_kernel_stack(), - _ => { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); - println!("`{}': Command unknown ", command); - self.color_code = color_code_save; - } - } - } - self.command_len = 0; - self.prompt(); - } - byte => { - if self.command_len >= 10 { return }; - - self.command[self.command_len] = byte; - self.write_byte(byte); - self.command_len += 1; - } - } - self.flush(); - } - - pub fn erase_byte(&mut self) { - self.buffer_pos -= 2; - let i = self.buffer_pos; - self.buffer[i] = b' '; - self.buffer[i + 1] = 0; - self.flush(); - } - - pub fn write_byte(&mut self, byte: u8) { - let i = self.buffer_pos; - - match byte { - - b'\n' => { - let current_line = self.buffer_pos / (BUFFER_COLS); - self.buffer_pos = (current_line + 1) * BUFFER_COLS; - } - byte => { - self.buffer[i] = byte; - self.buffer[i + 1] = self.color_code.0; - self.buffer_pos += 2; - } - } - - if self.buffer_pos >= self.buffer.len() { - self.scroll(); - } - } - - fn write_str(&mut self, s: &str) { - for byte in s.bytes() { - self.write_byte(byte) - } - } - - fn flush_cursor(&self) - { - let cursor_position = self.buffer_pos / 2; - // 14 awaits the rightmost 8bits - cpuio::outb(14, 0x3D4); - cpuio::outb((cursor_position >> 8) as u8, 0x3D5); - // 15 awaits the leftmost 8bits - cpuio::outb(15, 0x3D4); - cpuio::outb((cursor_position >> 0) as u8 & 0x00ff, 0x3D5); - } - - pub fn flush(&mut self) { - let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; - slice.as_mut().clone_from_slice(&self.buffer); - self.flush_cursor(); - } - - fn scroll(&mut self) { - - for row in 1..BUFFER_ROWS { - for col in 0..BUFFER_COLS { - let prev_position = ((row - 1) * BUFFER_COLS) + col; - let current_position = (row * BUFFER_COLS) + col; - self.buffer[prev_position] = self.buffer[current_position]; - } - } - - for col in 0..BUFFER_COLS/2 { - self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; - } - - self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; - } -} - -// trait needed by formatting macros -use core::fmt; -impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { - for byte in s.bytes() { - self.write_byte(byte) - } - Ok(()) - } -} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 6d491ba0..f1f95742 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -5,22 +5,182 @@ pub mod color; pub use self::color::{Color, ColorCode}; pub use self::buffer::{Writer}; -// use self::buffer::Writer; -// use core::fmt; -// use core::ptr::Unique; +use super::{Color, ColorCode}; +use ::context::CONTEXT; +use cpuio; +use ::console; -// macro_rules! println { -// ($fmt:expr) => (print!(concat!($fmt, "\n"))); -// ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); -// } +#[derive(Debug, Clone, Copy)] +#[repr(C)] +struct ScreenChar { + ascii_character: u8, + color_code: ColorCode, +} -// macro_rules! print { -// ($($arg:tt)*) => ({ -// $crate::vga::print(format_args!($($arg)*)); -// }); -// } +macro_rules! print { + ($($arg:tt)*) => ({ + $crate::vga::buffer::print(format_args!($($arg)*)); + }); +} -// pub fn print(args: fmt::Arguments) { -// use core::fmt::Write; -// self::WRITER.write_fmt(args).unwrap(); -// } +macro_rules! println { + ($fmt:expr) => (print!(concat!($fmt, "\n"))); + ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); +} + +pub fn print(args: fmt::Arguments) { + use core::fmt::Write; + unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; + unsafe { CONTEXT.current_term().flush() }; +} + +extern crate core; + +const BUFFER_ROWS: usize = 25; +const BUFFER_COLS: usize = 80 * 2; + +pub struct Writer { + pub buffer_pos: usize, + pub color_code: ColorCode, + buffer: [u8; BUFFER_ROWS * BUFFER_COLS], + command: [u8; 10], + command_len: usize, +} + +impl Writer { + pub const fn new() -> Writer { + Writer { + buffer_pos: 0, + color_code: ColorCode::new(Color::White, Color::Black), + buffer: [0; BUFFER_ROWS * BUFFER_COLS], + command: [b'\0'; 10], + command_len: 0, + } + } + + pub fn prompt(&mut self) { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Blue, Color::Black); + self.write_str("> "); + self.color_code = color_code_save; + } + + pub fn backspace(&mut self) { + if self.command_len > 0 { + self.command_len -= 1; + self.erase_byte(); + } + } + + pub fn keypress(&mut self, ascii: u8) { + match ascii { + b'\n' => { + self.write_byte(b'\n'); + { + let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; + match command { + "shutdown" | "halt" => console::shutdown(), + "reboot" => console::reboot(), + "stack" => console::print_kernel_stack(), + _ => { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Red, Color::Black); + println!("`{}': Command unknown ", command); + self.color_code = color_code_save; + } + } + } + self.command_len = 0; + self.prompt(); + } + byte => { + if self.command_len >= 10 { return }; + + self.command[self.command_len] = byte; + self.write_byte(byte); + self.command_len += 1; + } + } + self.flush(); + } + + pub fn erase_byte(&mut self) { + self.buffer_pos -= 2; + let i = self.buffer_pos; + self.buffer[i] = b' '; + self.buffer[i + 1] = 0; + self.flush(); + } + + pub fn write_byte(&mut self, byte: u8) { + let i = self.buffer_pos; + + match byte { + + b'\n' => { + let current_line = self.buffer_pos / (BUFFER_COLS); + self.buffer_pos = (current_line + 1) * BUFFER_COLS; + } + byte => { + self.buffer[i] = byte; + self.buffer[i + 1] = self.color_code.0; + self.buffer_pos += 2; + } + } + + if self.buffer_pos >= self.buffer.len() { + self.scroll(); + } + } + + fn write_str(&mut self, s: &str) { + for byte in s.bytes() { + self.write_byte(byte) + } + } + + fn flush_cursor(&self) + { + let cursor_position = self.buffer_pos / 2; + // 14 awaits the rightmost 8bits + cpuio::outb(14, 0x3D4); + cpuio::outb((cursor_position >> 8) as u8, 0x3D5); + // 15 awaits the leftmost 8bits + cpuio::outb(15, 0x3D4); + cpuio::outb((cursor_position >> 0) as u8 & 0x00ff, 0x3D5); + } + + pub fn flush(&mut self) { + let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; + slice.as_mut().clone_from_slice(&self.buffer); + self.flush_cursor(); + } + + fn scroll(&mut self) { + + for row in 1..BUFFER_ROWS { + for col in 0..BUFFER_COLS { + let prev_position = ((row - 1) * BUFFER_COLS) + col; + let current_position = (row * BUFFER_COLS) + col; + self.buffer[prev_position] = self.buffer[current_position]; + } + } + + for col in 0..BUFFER_COLS/2 { + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; + } + + self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; + } +} + +// trait needed by formatting macros +use core::fmt; +impl fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + for byte in s.bytes() { + self.write_byte(byte) + } + Ok(()) + } +} From 32616c2497d183debf20a634b17ced54d3497e9d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 14:09:31 +0100 Subject: [PATCH 054/151] ok it compiles --- kernel-rs/src/vga/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index f1f95742..5c054a9b 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,11 +1,8 @@ #[macro_use] -pub mod buffer; pub mod color; pub use self::color::{Color, ColorCode}; -pub use self::buffer::{Writer}; -use super::{Color, ColorCode}; use ::context::CONTEXT; use cpuio; use ::console; @@ -19,7 +16,7 @@ struct ScreenChar { macro_rules! print { ($($arg:tt)*) => ({ - $crate::vga::buffer::print(format_args!($($arg)*)); + $crate::vga::print(format_args!($($arg)*)); }); } From 4a12411aa862a8fecfd6fd62547f285e62d20f42 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 15:52:44 +0100 Subject: [PATCH 055/151] travis and readme --- kernel-rs/.travis.yml | 18 ++++++++++++++++++ kernel-rs/README.md | 17 ++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 kernel-rs/.travis.yml diff --git a/kernel-rs/.travis.yml b/kernel-rs/.travis.yml new file mode 100644 index 00000000..462f1d9d --- /dev/null +++ b/kernel-rs/.travis.yml @@ -0,0 +1,18 @@ +language: rust +before_install: + - sudo apt-get update + - sudo apt-get install -y nasm build-essential gcc + - cargo install xargo + - rustup override add nightly + - rustup component add rust-src +script: + - make +after_success: | + cargo doc && + echo "" > target/doc/index.html && + sudo pip install ghp-import && + ghp-import -n target/doc && + git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages +env: + global: + secure: KugnyzyUuT4x292BIJoXYBcHbGb1o8961gzrmQzdxCkn0sjg+UI9WUmQj2rZqxxRXCHK9VOaT/vYk9oYXoRv3cISDmsQbJpisUapmil8u3NWn2UVU6oePQrdj2+gF+hy7/K8NeEFE2X8Gv8MX6lsv7NZLTiN67UEpkuxWTrX4RKHDvIQDonUlI+56vgY3hvl4/kI6mE+BSVw9RPK8OWD1T0wwMzAjTCKERonAwI846HDNadWjXRq0+j+n84BJekxICAQRquO2MM94j+MQgCIV0ZQsa9bpG7CfvgLVXLh3NWjEYwkmWFz6hyxLhY4XnG9MNlBh+dN391tDuRoRUlsoI7P1Ym10aYAz1uEEfTQKemVWXOI8DqZDJL0MO3y9+LePb9hTjJ9GOoQ7q9v6v1l9MzWYCy4KBv4QWDEpIKsa7WM/ExfqlZ7MuVW6rzTZmmCScElSk295Z6aH993FrzsyREP16Ch2RniewA598lwinahYR8eYXKjkasi1WTJcLMvQN9nnUe0vhFUFNXPDQPLeX7ZEvzvvcOBY7kZG5zHUeXzIWq7D7tXZTqu/48cgwTvjQ5Q/FARXoffd+RaX/nZInVMdeI7phruOEawUNPXSEdNjNxIedi4PPnIRXT+DgstQeBSKrgl7HYNwnFC3Q+NfoU7oWoyivUtcQ1xZZj03f8= diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 833c270a..14731766 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -1,31 +1,34 @@ Kernel from scratch (KFS) series of projects at Ecole 42 ! -# compiling +### [documentation](https://jzck.github.io/kernel/bluesnow/index.html) ### dependencies - `nasm` compiles the bootcode - - `ld` links the bootcode + - `ld` links the bootcode and rust binary - `grub-mkrescue` builds the iso - `xargo` builds rust code - `qemu` runs the iso -on archlinux `pacman -S make grub xorriso mtools binutils gcc qemu` +See `.travis.yml` to get an ubuntu environment ready +on archlinux `pacman -S rustup make grub xorriso mtools binutils gcc qemu` ### rust setup ``` -pacman -S rustup rustup override add nightly rustup component add rust-src cargo install xargo ``` -# running +### running -`make run` runs the OS + a tmux split for the qemu terminal +`make run` runs the OS in a tmux window with `qemu` + `gdb` +`make iso` generate an iso to run wherever # References - - [Rust page on OSDev wiki](https://wiki.osdev.org/Rust) + - [wiki.osdev.org](https://wiki.osdev.org) is a fucking goldmine + - [wiki.osdev.org/Rust](https://wiki.osdev.org/Rust) everything rust related to OSes - [Writing an OS in rust](https://os.phil-opp.com/) extremely helpful to get things going on x86 and nightly rust + - [Rust OS comparison](https://github.com/flosse/rust-os-comparison) roundup of current projects From 3ee75083319b68e3d58ef8be4a16e25287ba8342 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 21 Feb 2018 15:56:27 +0100 Subject: [PATCH 056/151] doc comment testing --- kernel-rs/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 6ecbf2ee..1c42b201 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,12 +1,11 @@ -#![no_std] +//! project hosted at [https://github.com/jzck/kernel] +#![no_std] #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] #![feature(asm)] //needed by cpuio for inline asm -// extern crate spin; -// extern crate volatile; extern crate rlibc; #[macro_use] From fc3c60d970501e88ed170717c177116c5c21ab74 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 22 Feb 2018 18:54:08 +0100 Subject: [PATCH 057/151] use objdump -h build/kernel-x86.bin to show sections, linker scripts squishes relevant ones together --- kernel-rs/Cargo.toml | 1 + kernel-rs/src/arch/x86/boot.asm | 20 ++++------- kernel-rs/src/arch/x86/linker.ld | 14 ++++---- kernel-rs/src/arch/x86/start.asm | 17 ++++----- kernel-rs/src/lib.rs | 60 +++++++++++++++++++++----------- 5 files changed, 60 insertions(+), 52 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 3bb6580b..c128e21e 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -8,3 +8,4 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" +multiboot2 = "0.1.0" diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 51629f02..4a7dfad4 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -4,11 +4,10 @@ extern x86_start section .text bits 32 start: - mov esp, head_stack - mov edi, ebx + push ebx call check_multiboot - lgdt [GDTR.ptr] + lgdt [GDTR.ptr] ; load the new gdt jmp GDTR.gdt_cs:x86_start error: @@ -78,18 +77,11 @@ GDTR: DW 0x0 ; Limit ( bits 0 -15 ) DW 0x0 ; Base ( bits 0 -15 ) DB 0x0 ; Base ( bits 16 -23 ) - DB 0xF2 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) .gdt_bottom: .ptr: - DW .gdt_bottom - .gdt_top - 1 - DD .gdt_top - - -section .bss -align 4 -stack_end: - resb 4096 * 4 -head_stack: + DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 + DD .gdt_top ; pointer to top of gdt diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index c0555f73..21070800 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -13,11 +13,13 @@ SECTIONS { . = 1M; kernel_start = . ; /* ensure that the multiboot header is at the beginning */ - .boot : {KEEP(*(.multiboot_header))} - .text : {*(.text)} - /* .rodata BLOCK(4K) : ALIGN(4K) {*(.rodata)} */ - /* .data BLOCK(4K) : ALIGN(4K) {*(.data)} */ + .multiboot_header : { KEEP(*(.multiboot_header)) } + .text : { *(.text .text.*) } + .rodata : { *(.rodata .rodata.*) } + .data.rel.ro : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) } + .debug : { *(.debug_*) } + /* load stack */ - .bss : {*(.bss)} - kernel_end = . ; +.bss : {*(.bss .bss.*)} +/* kernel_end = . ; */ } diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index 0ac7dd3d..01589d74 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -4,17 +4,12 @@ extern kmain section .text bits 32 x86_start: -; we should clear register but it does not work, it's okay with 0x10 instead of 0 -mov ax, 0x10 -mov ss, ax -mov ds, ax -mov es, ax -mov fs, ax -mov gs, ax - -; PRINT OK -; mov dword [0xb8000], 0x2f4b2f4f -; hlt + mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) + mov ss, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax call kmain diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 1c42b201..2e42ab22 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,4 +1,4 @@ -//! project hosted at [https://github.com/jzck/kernel] +//! project hosted at (https://github.com/jzck/kernel) #![no_std] #![feature(lang_items)] @@ -7,10 +7,10 @@ #![feature(asm)] //needed by cpuio for inline asm extern crate rlibc; +extern crate multiboot2; -#[macro_use] /// 80x25 screen and simplistic terminal driver -pub mod vga; +#[macro_use] pub mod vga; /// kernel init and environment pub mod context; /// PS/2 detection and processing @@ -24,24 +24,42 @@ use context::CONTEXT; use vga::{Color, ColorCode}; #[no_mangle] -pub extern fn kmain() -> ! { - unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); - unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } +pub extern fn kmain(multiboot_information_address: usize) -> ! { + // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } + // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + // format_args!("{: ^80}", r#" ,--, "#), + // format_args!("{: ^80}", r#" ,--.'| ,----, "#), + // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + // format_args!("{: ^80}", r#" ' ; |./__; : "#), + // format_args!("{: ^80}", r#" | : ;| : .' "#), + // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + // format_args!("{: ^80}", r#" '--' `---' "#)); + // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } + let boot_info = unsafe{ multiboot2::load(multiboot_information_address) }; + let memory_map_tag = boot_info.memory_map_tag() + .expect("Memory map tag required"); + + println!("memory areas:"); + for area in memory_map_tag.memory_areas() { + println!(" start: 0x{:x}, length: 0x{:x}", + area.base_addr, area.length); + } + + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("Elf-sections tag required"); + + println!("kernel sections:"); + for section in elf_sections_tag.sections() { + println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", + section.addr, section.size, section.flags); + } unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } From 0877ac2cc6682b71f8af9776181bb2a4bbf6bf1d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 22 Feb 2018 19:17:52 +0100 Subject: [PATCH 058/151] linker script again --- kernel-rs/src/arch/x86/linker.ld | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 21070800..2c96fb77 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -12,14 +12,14 @@ SECTIONS { . = 1M; kernel_start = . ; + /* ensure that the multiboot header is at the beginning */ .multiboot_header : { KEEP(*(.multiboot_header)) } .text : { *(.text .text.*) } .rodata : { *(.rodata .rodata.*) } - .data.rel.ro : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) } + .data : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) } .debug : { *(.debug_*) } + .bss : {*(.bss .bss.*)} -/* load stack */ -.bss : {*(.bss .bss.*)} -/* kernel_end = . ; */ + /* kernel_end = . ; */ } From 063cab66f289505efec26530897faa8b6e5dbd7d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 26 Feb 2018 13:15:12 +0100 Subject: [PATCH 059/151] rudimentary hexdump --- kernel-rs/src/arch/x86/boot.asm | 57 +++++++++++----------- kernel-rs/src/arch/x86/linker.ld | 3 +- kernel-rs/src/console.rs | 84 ++++++++++++++++++++++++++++++-- kernel-rs/src/lib.rs | 32 ++++++------ kernel-rs/src/vga/mod.rs | 4 +- 5 files changed, 130 insertions(+), 50 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 4a7dfad4..1eb8b68b 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -9,6 +9,7 @@ start: call check_multiboot lgdt [GDTR.ptr] ; load the new gdt jmp GDTR.gdt_cs:x86_start + ; jmp x86_start error: mov dword [0xb8000], 0x4f524f45 @@ -49,37 +50,37 @@ GDTR: DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) -.gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK - DW 0x0 ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) +; .gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK +; DW 0x0 ; Limit ( bits 0 -15 ) +; DW 0x0 ; Base ( bits 0 -15 ) +; DB 0x0 ; Base ( bits 16 -23 ) +; DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] +; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] +; DB 0x0 ; Base ( bits 24 -31 ) -.gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE - DW 0xffff ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) +; .gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE +; DW 0xffff ; Limit ( bits 0 -15 ) +; DW 0x0 ; Base ( bits 0 -15 ) +; DB 0x0 ; Base ( bits 16 -23 ) +; DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] +; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] +; DB 0x0 ; Base ( bits 24 -31 ) -.gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA - DW 0xffff ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) +; .gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA +; DW 0xffff ; Limit ( bits 0 -15 ) +; DW 0x0 ; Base ( bits 0 -15 ) +; DB 0x0 ; Base ( bits 16 -23 ) +; DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] +; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] +; DB 0x0 ; Base ( bits 24 -31 ) -.gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK - DW 0x0 ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) +; .gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK +; DW 0x0 ; Limit ( bits 0 -15 ) +; DW 0x0 ; Base ( bits 0 -15 ) +; DB 0x0 ; Base ( bits 16 -23 ) +; DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] +; DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] +; DB 0x0 ; Base ( bits 24 -31 ) .gdt_bottom: .ptr: diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 2c96fb77..91b1860b 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -5,9 +5,10 @@ SECTIONS { /* GDT for the win */ . = 0x800; .gdt : {KEEP(*(.gdt))} + /* VGA, cannot use section for this */ + VGA_PTR = 0xb8000; . = 0xb8000; - VGA_PTR = . ; . += 80 * 25 * 2; . = 1M; diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index c5f8a075..2bb2b7ff 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,4 +1,7 @@ +extern crate core; + use cpuio; +use core::char; //TODO implement ACPI to have such functionality /// Reboot the kernel @@ -32,10 +35,85 @@ pub fn shutdown() -> ! { cpuio::halt(); } +pub fn print_hexdump(data: &[u8], offset: usize, display: char, bytes: usize) { + let mut address = 0; + while address <= data.len() { + let end = core::cmp::min(address + 16, data.len()); + print_line(&data[address..end], address + offset, display, bytes); + address = address + 16; + } +} + +fn is_control(c: char) -> bool { + !(c >= ' ' && c <= '~') +} + +fn print_line(line: &[u8], address: usize, display: char, bytes: usize) { + // print address + print!("\n{:08x}:", address); + let words = match (line.len() % bytes) == 0 { + true => line.len() / bytes, + false => (line.len() / bytes) + 1, + }; + for b in 0..words { + let word = match bytes { + 1 => line[b] as u16, + _ => match line.len() == bytes*b + 1 { + true => u16::from_be(((line[bytes * b] as u16) << 8) + 0), + false => u16::from_be(((line[bytes * b] as u16) << 8) + (line[bytes * b + 1] as u16)), + }, + }; + match display { + 'b' => print!(" {:03o}", word), + 'c' => match is_control((word as u8) as char) { + true => print!(" "), + false => print!(" {:03}", (word as u8) as char), + }, + 'C' => print!(" {:02x}", word), + 'x' => print!(" {:04x}", word), + 'o' => print!(" {:06o} ", word), + 'd' => print!(" {:05} ", word), + _ => print!(" {:04x}", word), + } + } + + if display != 'c' { + if (line.len() % 16) > 0 { + // align + let words_left = (16 - line.len()) / bytes; + let word_size = match display { + 'b' => 4, + 'c' => 4, + 'C' => 3, + 'x' => 5, + 'o' => 8, + 'd' => 8, + _ => 5, + }; + for _ in 0..word_size * words_left { + print!(" "); + } + } + + print!(" "); + for c in line { + // replace all control chars with dots + match is_control(*c as char) { + true => print!("."), + false => print!("{}", (*c as char)), + } + } + } +} + /// Print the kernel stack /// pub fn print_kernel_stack() { - println!("It's a stack print"); - + let esp: usize; + let ebp: usize; + unsafe { asm!("": "={esp}"(esp), "={ebp}"(ebp):::) }; + println!("{:#x} -> {:#x} (size={} bytes)", ebp, esp, ebp - esp); + let slice = unsafe { core::slice::from_raw_parts_mut(ebp as *mut u8, ebp - esp) }; + print_hexdump(slice, 0, 'x', ebp - esp); + println!(""); } - diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 2e42ab22..3b7ebedf 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -42,24 +42,26 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! { // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), // format_args!("{: ^80}", r#" '--' `---' "#)); // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } - let boot_info = unsafe{ multiboot2::load(multiboot_information_address) }; - let memory_map_tag = boot_info.memory_map_tag() - .expect("Memory map tag required"); + + // let boot_info = unsafe{ multiboot2::load(multiboot_information_address) }; + // let memory_map_tag = boot_info.memory_map_tag() + // .expect("Memory map tag required"); - println!("memory areas:"); - for area in memory_map_tag.memory_areas() { - println!(" start: 0x{:x}, length: 0x{:x}", - area.base_addr, area.length); - } + // println!("memory areas:"); + // for area in memory_map_tag.memory_areas() { + // println!(" start: 0x{:x}, length: 0x{:x}", + // area.base_addr, area.length); + // } - let elf_sections_tag = boot_info.elf_sections_tag() - .expect("Elf-sections tag required"); + // let elf_sections_tag = boot_info.elf_sections_tag() + // .expect("Elf-sections tag required"); + + // println!("kernel sections:"); + // for section in elf_sections_tag.sections() { + // println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", + // section.addr, section.size, section.flags); + // } - println!("kernel sections:"); - for section in elf_sections_tag.sections() { - println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", - section.addr, section.size, section.flags); - } unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 5c054a9b..5b04795b 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -39,8 +39,7 @@ const BUFFER_COLS: usize = 80 * 2; pub struct Writer { pub buffer_pos: usize, pub color_code: ColorCode, - buffer: [u8; BUFFER_ROWS * BUFFER_COLS], - command: [u8; 10], + buffer: [u8; BUFFER_ROWS * BUFFER_COLS], command: [u8; 10], command_len: usize, } @@ -154,7 +153,6 @@ impl Writer { } fn scroll(&mut self) { - for row in 1..BUFFER_ROWS { for col in 0..BUFFER_COLS { let prev_position = ((row - 1) * BUFFER_COLS) + col; From 7d08ddf53cff88518a81d08722dc05bab0c5f2c5 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 26 Feb 2018 16:14:59 +0100 Subject: [PATCH 060/151] stack printed, but is it really the stack ? --- kernel-rs/src/console.rs | 74 ++++++++-------------------------------- kernel-rs/src/lib.rs | 2 +- kernel-rs/src/vga/mod.rs | 11 ++++-- 3 files changed, 24 insertions(+), 63 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 2bb2b7ff..16466ccf 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -35,11 +35,11 @@ pub fn shutdown() -> ! { cpuio::halt(); } -pub fn print_hexdump(data: &[u8], offset: usize, display: char, bytes: usize) { +pub fn print_hexdump(data: &[u8], offset: usize) { let mut address = 0; while address <= data.len() { let end = core::cmp::min(address + 16, data.len()); - print_line(&data[address..end], address + offset, display, bytes); + print_line(&data[address..end], address + offset); address = address + 16; } } @@ -48,72 +48,28 @@ fn is_control(c: char) -> bool { !(c >= ' ' && c <= '~') } -fn print_line(line: &[u8], address: usize, display: char, bytes: usize) { - // print address - print!("\n{:08x}:", address); - let words = match (line.len() % bytes) == 0 { - true => line.len() / bytes, - false => (line.len() / bytes) + 1, - }; - for b in 0..words { - let word = match bytes { - 1 => line[b] as u16, - _ => match line.len() == bytes*b + 1 { - true => u16::from_be(((line[bytes * b] as u16) << 8) + 0), - false => u16::from_be(((line[bytes * b] as u16) << 8) + (line[bytes * b + 1] as u16)), - }, +fn print_line(line: &[u8], address: usize) { + print!("\n{:08x}: ", address); + for byte in line { + print!("{:02x} ", *byte); + } + print!("|"); + for byte in line { + match is_control(*byte as char) { + true => print!("."), + false => print!("{}", *byte as char), }; - match display { - 'b' => print!(" {:03o}", word), - 'c' => match is_control((word as u8) as char) { - true => print!(" "), - false => print!(" {:03}", (word as u8) as char), - }, - 'C' => print!(" {:02x}", word), - 'x' => print!(" {:04x}", word), - 'o' => print!(" {:06o} ", word), - 'd' => print!(" {:05} ", word), - _ => print!(" {:04x}", word), - } - } - - if display != 'c' { - if (line.len() % 16) > 0 { - // align - let words_left = (16 - line.len()) / bytes; - let word_size = match display { - 'b' => 4, - 'c' => 4, - 'C' => 3, - 'x' => 5, - 'o' => 8, - 'd' => 8, - _ => 5, - }; - for _ in 0..word_size * words_left { - print!(" "); - } - } - - print!(" "); - for c in line { - // replace all control chars with dots - match is_control(*c as char) { - true => print!("."), - false => print!("{}", (*c as char)), - } - } } + print!("|"); } /// Print the kernel stack -/// pub fn print_kernel_stack() { let esp: usize; let ebp: usize; - unsafe { asm!("": "={esp}"(esp), "={ebp}"(ebp):::) }; + unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; println!("{:#x} -> {:#x} (size={} bytes)", ebp, esp, ebp - esp); let slice = unsafe { core::slice::from_raw_parts_mut(ebp as *mut u8, ebp - esp) }; - print_hexdump(slice, 0, 'x', ebp - esp); + print_hexdump(slice, ebp); println!(""); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 3b7ebedf..e7ab1782 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -21,10 +21,10 @@ pub mod console; pub mod cpuio; use context::CONTEXT; -use vga::{Color, ColorCode}; #[no_mangle] pub extern fn kmain(multiboot_information_address: usize) -> ! { + // use vga::{Color, ColorCode}; // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", // format_args!("{: ^80}", r#" ,--, "#), diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 5b04795b..0319a929 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -25,10 +25,13 @@ macro_rules! println { ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } +macro_rules! flush { + () => (unsafe { CONTEXT.current_term().flush() }); +} + pub fn print(args: fmt::Arguments) { use core::fmt::Write; unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; - unsafe { CONTEXT.current_term().flush() }; } extern crate core; @@ -59,6 +62,8 @@ impl Writer { self.color_code = ColorCode::new(Color::Blue, Color::Black); self.write_str("> "); self.color_code = color_code_save; + // self.flush(); + flush!(); } pub fn backspace(&mut self) { @@ -66,8 +71,7 @@ impl Writer { self.command_len -= 1; self.erase_byte(); } - } - + } pub fn keypress(&mut self, ascii: u8) { match ascii { b'\n' => { @@ -106,6 +110,7 @@ impl Writer { self.buffer[i] = b' '; self.buffer[i + 1] = 0; self.flush(); + // flush!(); } pub fn write_byte(&mut self, byte: u8) { From 52af278a91c2cd5c76553dc1394e86d3d7d82a0c Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Feb 2018 15:10:17 +0100 Subject: [PATCH 061/151] added multiboot as a local crate --- kernel-rs/.gitmodules | 3 ++ kernel-rs/Cargo.toml | 2 +- kernel-rs/multiboot2-elf64 | 1 + kernel-rs/src/arch/x86/boot.asm | 56 +++++++++++++++--------------- kernel-rs/src/arch/x86/start.asm | 2 +- kernel-rs/src/console.rs | 2 +- kernel-rs/src/lib.rs | 58 +++++++++++--------------------- kernel-rs/src/vga/mod.rs | 1 - 8 files changed, 54 insertions(+), 71 deletions(-) create mode 100644 kernel-rs/.gitmodules create mode 160000 kernel-rs/multiboot2-elf64 diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules new file mode 100644 index 00000000..7612dca4 --- /dev/null +++ b/kernel-rs/.gitmodules @@ -0,0 +1,3 @@ +[submodule "multiboot2-elf64"] + path = multiboot2-elf64 + url = git@github.com:jzck/multiboot2-elf64.git diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index c128e21e..63983b02 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -8,4 +8,4 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" -multiboot2 = "0.1.0" +multiboot2 = { path = "multiboot2-elf64" } diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 new file mode 160000 index 00000000..4d6ad9cd --- /dev/null +++ b/kernel-rs/multiboot2-elf64 @@ -0,0 +1 @@ +Subproject commit 4d6ad9cde926f2ad5d47041e3f3a2cda18f8e11e diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 1eb8b68b..bf201d5f 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -50,37 +50,37 @@ GDTR: DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) -; .gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK -; DW 0x0 ; Limit ( bits 0 -15 ) -; DW 0x0 ; Base ( bits 0 -15 ) -; DB 0x0 ; Base ( bits 16 -23 ) -; DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] -; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] -; DB 0x0 ; Base ( bits 24 -31 ) +.gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK + DW 0x0 ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) -; .gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE -; DW 0xffff ; Limit ( bits 0 -15 ) -; DW 0x0 ; Base ( bits 0 -15 ) -; DB 0x0 ; Base ( bits 16 -23 ) -; DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] -; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] -; DB 0x0 ; Base ( bits 24 -31 ) +.gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) -; .gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA -; DW 0xffff ; Limit ( bits 0 -15 ) -; DW 0x0 ; Base ( bits 0 -15 ) -; DB 0x0 ; Base ( bits 16 -23 ) -; DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] -; DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] -; DB 0x0 ; Base ( bits 24 -31 ) +.gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA + DW 0xffff ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) -; .gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK -; DW 0x0 ; Limit ( bits 0 -15 ) -; DW 0x0 ; Base ( bits 0 -15 ) -; DB 0x0 ; Base ( bits 16 -23 ) -; DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] -; DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] -; DB 0x0 ; Base ( bits 24 -31 ) +.gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK + DW 0x0 ; Limit ( bits 0 -15 ) + DW 0x0 ; Base ( bits 0 -15 ) + DB 0x0 ; Base ( bits 16 -23 ) + DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0x0 ; Base ( bits 24 -31 ) .gdt_bottom: .ptr: diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index 01589d74..d93b89af 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -5,8 +5,8 @@ section .text bits 32 x86_start: mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) - mov ss, ax mov ds, ax + mov ss, ax mov es, ax mov fs, ax mov gs, ax diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 16466ccf..cbe7800a 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -49,7 +49,7 @@ fn is_control(c: char) -> bool { } fn print_line(line: &[u8], address: usize) { - print!("\n{:08x}: ", address); + print!("\n{:#08x}: ", address); for byte in line { print!("{:02x} ", *byte); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index e7ab1782..3e7f8fcb 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -7,7 +7,7 @@ #![feature(asm)] //needed by cpuio for inline asm extern crate rlibc; -extern crate multiboot2; +extern crate multiboot2; //slightly modified fork from official 0.3.2 /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -23,51 +23,31 @@ pub mod cpuio; use context::CONTEXT; #[no_mangle] -pub extern fn kmain(multiboot_information_address: usize) -> ! { - // use vga::{Color, ColorCode}; - // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } - // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - // format_args!("{: ^80}", r#" ,--, "#), - // format_args!("{: ^80}", r#" ,--.'| ,----, "#), - // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - // format_args!("{: ^80}", r#" ' ; |./__; : "#), - // format_args!("{: ^80}", r#" | : ;| : .' "#), - // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - // format_args!("{: ^80}", r#" '--' `---' "#)); - // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } - - // let boot_info = unsafe{ multiboot2::load(multiboot_information_address) }; - // let memory_map_tag = boot_info.memory_map_tag() - // .expect("Memory map tag required"); +pub extern fn kmain(multiboot_info_addr: usize) -> ! { + let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; - // println!("memory areas:"); - // for area in memory_map_tag.memory_areas() { - // println!(" start: 0x{:x}, length: 0x{:x}", - // area.base_addr, area.length); - // } + let memory_map_tag = boot_info.memory_map_tag() + .expect("Memory map tag required"); - // let elf_sections_tag = boot_info.elf_sections_tag() - // .expect("Elf-sections tag required"); + println!("memory areas:"); + for area in memory_map_tag.memory_areas() { + println!(" start: 0x{:x}, length: 0x{:x}", + area.base_addr, area.length); + } - // println!("kernel sections:"); - // for section in elf_sections_tag.sections() { - // println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", - // section.addr, section.size, section.flags); - // } + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("Elf-sections tag required"); + + println!("kernel sections:"); + for section in elf_sections_tag.sections() { + println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", + section.addr, section.size, section.flags); + } unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } - loop { - keyboard::kbd_callback(); - } + loop { keyboard::kbd_callback(); } } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 0319a929..4911dae7 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -62,7 +62,6 @@ impl Writer { self.color_code = ColorCode::new(Color::Blue, Color::Black); self.write_str("> "); self.color_code = color_code_save; - // self.flush(); flush!(); } From bcf58de7ac12501307f054568a837a959fe70f83 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Feb 2018 19:28:48 +0100 Subject: [PATCH 062/151] some sweet commands to finish up kfs2, gonna start the frame allocator now --- kernel-rs/multiboot2-elf64 | 2 +- kernel-rs/src/arch/x86/boot.asm | 5 ++ kernel-rs/src/arch/x86/linker.ld | 2 +- kernel-rs/src/arch/x86/multiboot_header.asm | 2 +- kernel-rs/src/console.rs | 83 ++++++++++++++++++--- kernel-rs/src/context.rs | 2 + kernel-rs/src/lib.rs | 20 +---- kernel-rs/src/vga/mod.rs | 26 +++---- 8 files changed, 95 insertions(+), 47 deletions(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index 4d6ad9cd..d66e8cb0 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit 4d6ad9cde926f2ad5d47041e3f3a2cda18f8e11e +Subproject commit d66e8cb0e5b10c2097a9aef985b4181694db9ce8 diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index bf201d5f..2b8b5995 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -86,3 +86,8 @@ GDTR: .ptr: DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 DD .gdt_top ; pointer to top of gdt + +section .bss +stack_bottom: + resb 4096 * 16 +stack_top: diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 91b1860b..c93a2140 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -15,7 +15,7 @@ SECTIONS { kernel_start = . ; /* ensure that the multiboot header is at the beginning */ - .multiboot_header : { KEEP(*(.multiboot_header)) } + .multiboot : { KEEP(*(.multiboot)) } .text : { *(.text .text.*) } .rodata : { *(.rodata .rodata.*) } .data : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) } diff --git a/kernel-rs/src/arch/x86/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm index 9f87d3bb..75fb5eb5 100644 --- a/kernel-rs/src/arch/x86/multiboot_header.asm +++ b/kernel-rs/src/arch/x86/multiboot_header.asm @@ -1,4 +1,4 @@ -section .multiboot_header +section .multiboot header_start: dd 0xe85250d6 ; magic number (multiboot 2) dd 0 ; architecture 0 (protected mode i386) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index cbe7800a..f32c67ad 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,14 +1,33 @@ extern crate core; +extern crate multiboot2; use cpuio; use core::char; +use context::CONTEXT; +use vga::*; + +pub fn dispatch(command: &str) { + match command { + "shutdown" | "halt" => self::shutdown(), + "reboot" => self::reboot(), + "stack" => self::print_stack(), + "multiboot" => self::mb2_info(), + "memory" => self::mb2_memory(), + "sections" => self::mb2_sections(), + _ => { + set_color!(Red); + println!("`{}': Command unknown ", command); + set_color!(); + } + } +} //TODO implement ACPI to have such functionality /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd /// -pub fn reboot() { +fn reboot() { //TODO disable interrupt here something like : asm volatile ("cli"); // I will now clear the keyboard buffer @@ -29,19 +48,21 @@ pub fn reboot() { /// /// If shutdown failed, will loop on a halt cmd /// -pub fn shutdown() -> ! { +fn shutdown() -> ! { cpuio::outb(0xf4, 0x00);//TODO doesn't work :( println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); cpuio::halt(); } -pub fn print_hexdump(data: &[u8], offset: usize) { +fn hexdump(start: usize, end: usize) { let mut address = 0; + let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) }; while address <= data.len() { - let end = core::cmp::min(address + 16, data.len()); - print_line(&data[address..end], address + offset); + let next_end = core::cmp::min(address + 16, data.len()); + print_line(&data[address..next_end], address + start); address = address + 16; } + println!(""); } fn is_control(c: char) -> bool { @@ -63,13 +84,53 @@ fn print_line(line: &[u8], address: usize) { print!("|"); } -/// Print the kernel stack -pub fn print_kernel_stack() { +fn print_stack() { let esp: usize; let ebp: usize; unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; - println!("{:#x} -> {:#x} (size={} bytes)", ebp, esp, ebp - esp); - let slice = unsafe { core::slice::from_raw_parts_mut(ebp as *mut u8, ebp - esp) }; - print_hexdump(slice, ebp); - println!(""); + println!("esp = {:#x}", esp); + println!("ebp = {:#x}", ebp); + println!("size = {:#X} bytes", ebp - esp); + hexdump(esp, ebp); +} + +fn mb2_memory() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let memory_map_tag = boot_info.memory_map_tag() + .expect("Memory map tag required"); + + println!("memory areas:"); + for area in memory_map_tag.memory_areas() { + println!(" start: 0x{:x}, length: 0x{:x}", + area.start_address(), area.size()); + } +} + +fn mb2_sections() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("Elf-sections tag required"); + + println!("kernel sections:"); + for section in elf_sections_tag.sections() { + println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}", + section.name(), section.start_address(), section.size(), section.flags()); + } +} + +fn mb2_info() { + let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + + let command_line_tag = boot_info.command_line_tag() + .expect("Elf-sections tag required"); + + let bootloader_tag = boot_info.boot_loader_name_tag() + .expect("Elf-sections tag required"); + + println!("bootloader: {}", bootloader_tag.name()); + if command_line_tag.command_line().len() != 0 { + println!("command line: {}", command_line_tag.command_line()); + } } diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 06ca9bb4..2b6b3b93 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -4,12 +4,14 @@ use vga; pub static mut CONTEXT: Context = Context { current_term: 0, + boot_info_addr: 0, vga1: vga::Writer::new(), vga2: vga::Writer::new(), }; pub struct Context { pub current_term: u8, + pub boot_info_addr: usize, pub vga1: vga::Writer, pub vga2: vga::Writer, } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 3e7f8fcb..6aca6b97 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -24,25 +24,7 @@ use context::CONTEXT; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { - let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; - - let memory_map_tag = boot_info.memory_map_tag() - .expect("Memory map tag required"); - - println!("memory areas:"); - for area in memory_map_tag.memory_areas() { - println!(" start: 0x{:x}, length: 0x{:x}", - area.base_addr, area.length); - } - - let elf_sections_tag = boot_info.elf_sections_tag() - .expect("Elf-sections tag required"); - - println!("kernel sections:"); - for section in elf_sections_tag.sections() { - println!(" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}", - section.addr, section.size, section.flags); - } + unsafe { CONTEXT.boot_info_addr = multiboot_info_addr }; unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 4911dae7..1d8aec36 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -29,6 +29,15 @@ macro_rules! flush { () => (unsafe { CONTEXT.current_term().flush() }); } +macro_rules! set_color { + () => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::White, Color::Black) }); + ($fg:ident) => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::$fg, Color::Black) }); + ($fg:ident, $bg:ident) => (unsafe { CONTEXT.current_term().color_code = + ColorCode::new(Color::$fg, Color::$bg) }); +} + pub fn print(args: fmt::Arguments) { use core::fmt::Write; unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; @@ -58,10 +67,9 @@ impl Writer { } pub fn prompt(&mut self) { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Blue, Color::Black); + set_color!(Blue); self.write_str("> "); - self.color_code = color_code_save; + set_color!(); flush!(); } @@ -77,17 +85,7 @@ impl Writer { self.write_byte(b'\n'); { let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; - match command { - "shutdown" | "halt" => console::shutdown(), - "reboot" => console::reboot(), - "stack" => console::print_kernel_stack(), - _ => { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); - println!("`{}': Command unknown ", command); - self.color_code = color_code_save; - } - } + console::dispatch(command); } self.command_len = 0; self.prompt(); From 614da57de3e6eff8555c335a7b0e67e4519c12a6 Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 2 Mar 2018 15:48:06 +0100 Subject: [PATCH 063/151] Add FULL ACPI support, change exec mode --- kernel-rs/Makefile | 33 +++-- kernel-rs/src/acpi/dsdt.rs | 84 ++++++++++++ kernel-rs/src/acpi/fadt.rs | 143 +++++++++++++++++++ kernel-rs/src/acpi/mod.rs | 145 ++++++++++++++++++++ kernel-rs/src/acpi/rsdp.rs | 89 ++++++++++++ kernel-rs/src/acpi/rsdt.rs | 19 +++ kernel-rs/src/acpi/xsdt.rs | 21 +++ kernel-rs/src/arch/x86/grub.cfg | 2 +- kernel-rs/src/arch/x86/linker.ld | 4 - kernel-rs/src/arch/x86/multiboot_header.asm | 3 +- kernel-rs/src/console.rs | 35 ++--- kernel-rs/src/cpuio.rs | 7 +- kernel-rs/src/lib.rs | 47 ++++--- kernel-rs/src/vga/mod.rs | 61 +++++--- 14 files changed, 617 insertions(+), 76 deletions(-) create mode 100644 kernel-rs/src/acpi/dsdt.rs create mode 100644 kernel-rs/src/acpi/fadt.rs create mode 100644 kernel-rs/src/acpi/mod.rs create mode 100644 kernel-rs/src/acpi/rsdp.rs create mode 100644 kernel-rs/src/acpi/rsdt.rs create mode 100644 kernel-rs/src/acpi/xsdt.rs diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index b4f1aed8..6485e460 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -11,12 +11,13 @@ endif project := bluesnow arch ?= x86 NASM := nasm -f elf -LD := ld -m elf_i386 -n --gc-sections +LD := ld -m elf_i386 -L ./ -n --gc-sections # QEMU := qemu-system-x86_64 -device isa-debug-exit,iobase=0xf4,iosize=0x04 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -kernel := build/kernel-$(arch).bin -iso := build/os-$(arch).iso +kerName := BlueSnow +kernel := build/$(kerName) +iso := $(kernel).iso DIRISO := build/isofiles target ?= $(arch)-$(project) @@ -30,11 +31,11 @@ asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_ KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ - kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 1 \`;\ - kill \`ps -x | grep gdb | head -n 2 | tail -n 1 | cut -d \ -f 2 \` + kill \`ps -x | grep \"[g]db\" | cut -d \ -f 1 \`;\ + kill \`ps -x | grep \"[g]db\" | cut -d \ -f 2 \` GDB := gdb -q\ -ex \"set arch i386:x86-64\"\ - -ex \"file build/kernel-x86.bin\"\ + -ex \"file $(kernel)\"\ -ex \"target remote localhost:$(PORTG)\" \ -ex \"continue\" @@ -46,18 +47,28 @@ build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile @echo "Compiling (ASM) $@..." $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile - @$(LD) -o $(kernel) -T $(linker_script) $(asm_object) $(rust_os) + @$(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) $(iso): $(kernel) $(grub.cfg) Makefile @mkdir -p $(DIRISO)/boot/grub @cp $(grub.cfg) $(DIRISO)/boot/grub - @cp $(kernel) $(DIRISO)/boot/kernel.bin - @grub-mkrescue -o $(iso) $(DIRISO) 2>/dev/null + @cp $(kernel) $(DIRISO)/boot/$(kerName) + @grub-mkrescue -o $@ $(DIRISO) 2>/dev/null + +# $(kernel).img: $(kernel) +# @cp .clean.img $@ +# @sudo mount -oloop=/dev/loop0,offset=32256 $@ /mnt +# @sudo cp $(kernel) /mnt/boot/. +# @sudo umount /mnt run: $(iso) Makefile @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' - @# @$(QEMU) -curses -cdrom $(iso) + +# Run without try to do a compile +R: + @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } + @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' clean: @cargo clean @@ -69,4 +80,4 @@ $(rust_os): $(target).json Makefile kernel: $(rust_os) iso: $(iso) -.PHONY: run clean kernel iso $(rust_os) +.PHONY: R run clean kernel iso $(rust_os) diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs new file mode 100644 index 00000000..5943e757 --- /dev/null +++ b/kernel-rs/src/acpi/dsdt.rs @@ -0,0 +1,84 @@ +use super::{check_signature,ACPISDTHeader}; +use core::mem; +use cpuio; + +static mut DSDT: DSDT = DSDT { + valid: false, + dsdt: None, + s5_ptr: 0, + slp_typ_a: 0, + slp_typ_b: 0 +}; + +struct DSDT { + valid: bool, + dsdt: Option<*const ACPISDTHeader>, + s5_ptr: u32, + slp_typ_a: u16, + slp_typ_b: u16 +} + +impl DSDT { + fn init(&mut self, addr: u32) -> Result <(), &'static str> { + self.dsdt = Some(addr as *const ACPISDTHeader); + self.s5_ptr = self.find_s5(addr)?; + self.parse_s5(); + self.valid = true; + Ok(()) + } + + fn find_s5(&self, addr: u32) -> Result { + let dsdt_start = addr + mem::size_of::() as u32; + let dsdt_end = dsdt_start + unsafe {(*self.dsdt.unwrap()).length}; + for addr in dsdt_start..dsdt_end { + if check_signature(addr, "_S5_") { + if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) && check_signature(addr + 4, "\x12") { + return Ok(addr); + } + } + } + Err("Can not find S5 section in DSDT") + } + + fn parse_s5(&mut self) { + let ptr = self.s5_ptr + 5; + let ptr = ((unsafe{*(ptr as *const u8)} & 0xC0) >> 6) + 2; + let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix + self.slp_typ_a = (unsafe {*(ptr as *const u8)} as u16) << 10; + let ptr = ptr + 1; + let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix + self.slp_typ_b = (unsafe {*(ptr as *const u8)} as u16) << 10; + } +} +fn is_init() -> Result <(), &'static str> { + match unsafe {DSDT.valid} { + true => Ok(()), + false => match unsafe {DSDT.dsdt} { + Some(_) => Err("Differentiated System Description Pointer (DSDP) is not valid"), + None => Err("Differentiated System Description Pointer (DSDP) is not initialized") + } + } +} + +/// ## Initialize Differentiated System Description Table (DSDT) +/// input param addr is contain in FADT +pub fn init(addr: u32) -> Result <(), &'static str> { + if ACPISDTHeader::valid(addr, "DSDT") { + return unsafe {DSDT.init(addr)}; + } + return Err("Can not find Differentiated System Description Table (DSDT)."); +} + +/// NOT COMPATIBLE WITH VIRTUALBOX +/// Send shutdown signal +/// outw(PM1a_CNT_BLK, SLP_TYPx | SLP_EN) +pub fn shutdown(pm1_cnt: [u16; 2]) -> Result <(), &'static str> { + is_init()?; + let slp_typ = unsafe{ DSDT.slp_typ_a } | (1 << 13); + cpuio::outw(pm1_cnt[0], slp_typ); + if pm1_cnt[1] != 0 { + let slp_typ = unsafe{ DSDT.slp_typ_b } | (1 << 13); + cpuio::outw(pm1_cnt[1], slp_typ); + } + Ok(()) +} diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs new file mode 100644 index 00000000..99686934 --- /dev/null +++ b/kernel-rs/src/acpi/fadt.rs @@ -0,0 +1,143 @@ +use super::{ACPISDTHeader,ACPISDTIter}; +use cpuio; + +#[repr(C)] +#[derive(Debug)] +struct GenericAddressStructure { + addressspace: u8, + bitwidth: u8, + bitoffset: u8, + accesssize: u8, + noused: u32, + address: u64 +} + +#[repr(C)] +#[derive(Debug)] +struct FADT +{ + header: ACPISDTHeader, + firmwarectrl: u32, + dsdt: u32, + + // field used in acpi 1.0; no longer in use, for compatibility only + reserved: u8, + + preferredpowermanagementprofile: u8, + sci_interrupt: u16, + smi_commandport: u32, + acpi_enable: u8, + acpidisable: u8, + s4bios_req: u8, //no use + pstate_control: u8, //no use + pm1aeventblock: u32, //no use + pm1beventblock: u32, //no use + pm1acontrolblock: u32, + pm1bcontrolblock: u32, + pm2controlblock: u32, //no use + pmtimerblock: u32, //no use + gpe0block: u32, //no use + gpe1block: u32, //no use + pm1eventlength: u8, //no use + pm1controllength: u8, + pm2controllength: u8, //no use + pmtimerlength: u8, //no use + gpe0length: u8, //no use + gpe1length: u8, //no use + gpe1base: u8, //no use + cstatecontrol: u8, //no use + worstc2latency: u16, //no use + worstc3latency: u16, //no use + flushsize: u16, //no use + flushstride: u16, //no use + dutyoffset: u8, //no use + dutywidth: u8, //no use + dayalarm: u8, //no use + monthalarm: u8, //no use + century: u8, //no use + + // reserved in acpi 1.0; used since acpi 2.0+ + bootarchitectureflags: u16, + + reserved2: u8, + flags: u32, + + // 12 byte structure; see below for details + resetreg: GenericAddressStructure, + + resetvalue: u8, + reserved3: [u8; 3], + + // 64bit pointers - Available on ACPI 2.0+ + x_firmwarecontrol: u64, + x_dsdt: u64, + + x_pm1aeventblock: GenericAddressStructure, + x_pm1beventblock: GenericAddressStructure, + x_pm1acontrolblock: GenericAddressStructure, + x_pm1bcontrolblock: GenericAddressStructure, + x_pm2controlblock: GenericAddressStructure, + x_pmtimerblock: GenericAddressStructure, + x_gpe0block: GenericAddressStructure, + x_gpe1block: GenericAddressStructure, + +} + +static mut FADT: Option<*const FADT> = None; + +/// ## Initialize Fixed ACPI Description Table (FADT) +/// input param addr is contain in other ptr of rsdt +pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { + for sdt_ptr in sdt_iter { + if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic + let ptr = sdt_ptr as *const FADT; + unsafe {FADT = Some(ptr)}; + if !is_enable()? { // TODO do i have to check if enabled before init ??? + let smi_cmd = unsafe {(*ptr).smi_commandport} as u16; // TODO WHY DO I NEED THIS FUCKING CAST + let acpi_enable = unsafe {(*ptr).acpi_enable}; + cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command + } + return Ok(()); + } + } + return Err("Can not find Fixed ACPI Description Table (FADT)."); +} + +fn is_init() -> Result <*const FADT, &'static str> { + match unsafe {FADT} { + Some(ptr) => Ok(ptr), + None => Err("Fixed ACPI Description Table (FADT) is not initialized") + } +} + +/// Return Dsdt address +/// FADT must have been initialized first +pub fn dsdtaddr() -> Result { + let ptr = is_init()?; + return Ok(unsafe {(*ptr).dsdt}); +} + +fn get_cnt(ptr: *const FADT) -> [u16; 2] { + [unsafe {(*ptr).pm1acontrolblock} as u16, unsafe {(*ptr).pm1bcontrolblock} as u16] // TODO WHY DO I NEED THIS FUCKING CAST +} + +/// Return true/false depending of acpi is enable +pub fn is_enable() -> Result { + let ptr = is_init()?; + let pm1_cnt = get_cnt(ptr); + if pm1_cnt[1] == 0 { + Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) + } else { + Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1 || cpuio::inw(pm1_cnt[1]) & 0x1 == 0x1) + } +} + +/// Return a array with [pm1a, pm1b] +/// FADT must have been initialized first +pub fn get_controlblock() -> Result <[u16; 2], &'static str> { + if !is_enable()? { + Err("ACPI is not enabled") + } else { + Ok(get_cnt(is_init()?)) // TODO redondant call to is_init + } +} diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs new file mode 100644 index 00000000..702e6f9c --- /dev/null +++ b/kernel-rs/src/acpi/mod.rs @@ -0,0 +1,145 @@ +mod rsdp; +mod rsdt; +mod xsdt; +mod fadt; +mod dsdt; + +use core; +use core::mem; + +#[repr(C)] +#[derive(Debug, Clone, Copy)] +struct ACPISDTHeader { + signature: [u8; 4], + length: u32, + revision: u8, + checksum: u8, + oemid: [u8; 6], + oemtableid: [u8; 8], + oemrevision: u32, + creatorid: u32, + creatorrevision: u32, +} + +impl ACPISDTHeader { + pub fn valid(addr: u32, signature: &str) -> bool { + if check_signature(addr, signature) { + let ptr_tmp = addr as *const ACPISDTHeader; + if check_checksum(addr, unsafe {(*ptr_tmp).length} as usize) { + return true; + } + } + return false; + } +} + +static mut ACPI: Acpi = Acpi { + valid: false, + v2: false +}; + +struct Acpi { + valid: bool, + v2: bool +} + +impl Acpi { + fn init(&mut self) -> Result <(), &'static str> { + self.v2 = rsdp::init()?; + if self.v2 { + // Xsdt Address: + // 64-bit physical address of the XSDT table. If you detect ACPI Version 2.0 you should use this table instead of RSDT even on x86, casting the address to uint32_t. + xsdt::init(rsdp::xsdtaddr()?)?; + fadt::init(xsdt::iter()?)?; + } else { + rsdt::init(rsdp::rsdtaddr()?)?; + fadt::init(rsdt::iter()?)?; + } + dsdt::init(fadt::dsdtaddr()?)?; + self.valid = true; + Ok(()) + } +} + +fn check_signature(addr: u32, id: &str) -> bool { + let signature = match core::str::from_utf8(unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, id.len())}) { + Ok(y) => y, + Err(_) => return false, + }; + return signature == id; +} + +fn check_checksum(addr: u32, len: usize) -> bool { + let byte_array = unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, len)}; + let mut sum: u32 = 0; + for byte in byte_array { + sum += *byte as u32; + } + return sum as u8 == 0; +} + +pub struct ACPISDTIter { + pos: usize, + width: usize, + sdt: u32, + len: usize +} + +impl ACPISDTIter { + fn new(acpi_sdt: Option<*const ACPISDTHeader>, ptr_len: usize) -> Result { + match acpi_sdt { + None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."), + Some(ptr) => Ok(ACPISDTIter { + pos: 0, + width: ptr_len, + sdt: ptr as u32 + mem::size_of::() as u32, + len: (unsafe {(*ptr).length} as usize - mem::size_of::()) / ptr_len + }) + } + } +} + +impl Iterator for ACPISDTIter { + type Item = u32; + + fn next(&mut self) -> Option { + self.pos += 1; + if self.pos > self.len { + return None; + } + let ret = Some(unsafe {*(self.sdt as *const u32)}); + self.sdt += self.width as u32; + return ret; + } +} + +fn is_init() -> Result <(), &'static str> { + if unsafe {ACPI.valid} { + Ok(()) + } else { + Err("ACPI is not initialized") + } +} + + +/// Initalized the ACPI module +pub fn init() -> Result <(), &'static str> { + if let Ok(()) = is_init() { + return Ok(()); + } + unsafe {ACPI.init()} +} + +/// Proceed to ACPI shutdown +/// This function doesn't work with Virtual Box yet +pub fn shutdown() -> Result <(), &'static str> { + is_init()?; + dsdt::shutdown(fadt::get_controlblock()?) +} + +/// Display state of ACPI +pub fn info() -> Result <(), &'static str> { + is_init()?; + println!("ACPI STATE:\n {}", if fadt::is_enable()? {"ENABLED"} else {"DISABLED"}); + Ok(()) +} diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs new file mode 100644 index 00000000..b5b6967b --- /dev/null +++ b/kernel-rs/src/acpi/rsdp.rs @@ -0,0 +1,89 @@ +use super::{check_signature,check_checksum}; +use core::mem; + +#[repr(C)] +struct RSDP { + signature: [u8; 8], + checksum: u8, + oemid: [u8; 6], + revision: u8, + rsdtaddr: u32, +} + +#[repr(C)] +pub struct RSDP20 { + rsdp: RSDP, + length: u32, + xsdtaddress: u64, + extendedchecksum: u8, + reserved: [u8; 3], +} + +static mut RSDPTR: Option<*const RSDP20> = None; + +/// RSDP load will check is RSDP is present at the addr sent. +/// Return a bool +/// true => RSDP is V2 +/// false => RSDP is V1 +pub fn load(addr: u32) -> Result { + if check_signature(addr, "RSD PTR ") { + let ptr_tmp = addr as *const RSDP20; + let revision = unsafe {(*ptr_tmp).rsdp.revision}; + if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { + unsafe {RSDPTR = Some(ptr_tmp)}; + return Ok(revision == 2); + } + } + Err("Not a valid RSD ptr") +} + +fn memory_finding(bound: u32) -> Result { + let mut i = 0; + while i < 0x1000000 { + i += bound; + if let Ok(result) = load(i) { + return Ok(result) + } + } + // HACK because RSDP is not always aligned on 16 bytes boundary with QEMU + if bound > 1 { + return memory_finding(bound / 2); + } + Err("Can not find Root System Description Pointer (RSDP).") +} + +fn is_init() -> Result <*const RSDP20, &'static str> { + match unsafe {RSDPTR} { + Some(ptr) => Ok(ptr), + None => Err("Root System Description Pointer (RSDP) is not initialized") + // if ptr == 0 as *const RSDP20 + // => Err("Root System Description Pointer (RSDP) is not initialized"), + // ptr + // => Ok(ptr) + } +} + +/// Return a ptr on xsdt +/// RSDP must have been initialized first +pub fn xsdtaddr() -> Result { + let ptr = is_init()?; + let revision = unsafe {(*ptr).rsdp.revision}; + if revision != 2 { + return Err("Wrong RSDP version asked"); + } + return Ok(unsafe {(*ptr).xsdtaddress}); +} + +/// Return a ptr on rsdt +/// RSDP must have been initialized first +pub fn rsdtaddr() -> Result { + let ptr = is_init()?; + return Ok(unsafe {(*ptr).rsdp.rsdtaddr}); +} + +/// RSDP init will iter on addr in [0x0 - 0x1000000] to find "RSDP PTR " +/// if you already know the location, you should prefer to use load function +/// return an Error if there is no RSDP in memory, or return the value of load function +pub fn init() -> Result { + memory_finding(16) +} diff --git a/kernel-rs/src/acpi/rsdt.rs b/kernel-rs/src/acpi/rsdt.rs new file mode 100644 index 00000000..61363973 --- /dev/null +++ b/kernel-rs/src/acpi/rsdt.rs @@ -0,0 +1,19 @@ +use super::{ACPISDTHeader,ACPISDTIter}; + +static mut RSDT: Option<*const ACPISDTHeader> = None; + +/// ## Initialize Root System Description Table (RSDT) +/// input param addr is contain in RSDP +pub fn init(addr: u32) -> Result <(), &'static str> { + if ACPISDTHeader::valid(addr, "RSDT") { + unsafe {RSDT = Some(addr as *const ACPISDTHeader)}; + return Ok(()); + } + return Err("Can not find Root System Description Table (RSDT)."); +} + +/// Return a iterable of ptr contained in RSDT +/// RSDT must have been initialized first +pub fn iter() -> Result { + ACPISDTIter::new(unsafe {RSDT}, 4) +} diff --git a/kernel-rs/src/acpi/xsdt.rs b/kernel-rs/src/acpi/xsdt.rs new file mode 100644 index 00000000..356be49d --- /dev/null +++ b/kernel-rs/src/acpi/xsdt.rs @@ -0,0 +1,21 @@ +use super::{ACPISDTHeader,ACPISDTIter}; + +static mut XSDT: Option<*const ACPISDTHeader> = None; + +/// ## Initialize Root System Description Table (XSDT) +/// input param addr is contain in RSDP +pub fn init(addr: u64) -> Result <(), &'static str> { + assert!((addr as u32) as u64 == addr); + let addr: u32 = addr as u32; + if ACPISDTHeader::valid(addr, "XSDT") { + unsafe {XSDT = Some(addr as *const ACPISDTHeader)}; + return Ok(()); + } + return Err("Can not find eXtended System Descriptor Table (XSDT)."); +} + +/// Return a iterable of ptr contained in XSDT +/// XSDT must have been initialized first +pub fn iter() -> Result { + ACPISDTIter::new(unsafe {XSDT}, 8) +} diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg index 4e624c0f..4cbeea5c 100644 --- a/kernel-rs/src/arch/x86/grub.cfg +++ b/kernel-rs/src/arch/x86/grub.cfg @@ -2,6 +2,6 @@ set timeout=0 set default=0 menuentry "Blue Snow" { - multiboot2 /boot/kernel.bin + multiboot2 /boot/BlueSnow boot } diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 2c96fb77..58b51fbc 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -11,8 +11,6 @@ SECTIONS { . += 80 * 25 * 2; . = 1M; - kernel_start = . ; - /* ensure that the multiboot header is at the beginning */ .multiboot_header : { KEEP(*(.multiboot_header)) } .text : { *(.text .text.*) } @@ -20,6 +18,4 @@ SECTIONS { .data : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) } .debug : { *(.debug_*) } .bss : {*(.bss .bss.*)} - - /* kernel_end = . ; */ } diff --git a/kernel-rs/src/arch/x86/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm index 9f87d3bb..584b3856 100644 --- a/kernel-rs/src/arch/x86/multiboot_header.asm +++ b/kernel-rs/src/arch/x86/multiboot_header.asm @@ -1,7 +1,8 @@ section .multiboot_header header_start: +align 4 dd 0xe85250d6 ; magic number (multiboot 2) - dd 0 ; architecture 0 (protected mode i386) + dd 0 ; TODO change it because architecture 0 means(protected mode i386) We could have problem here dd header_end - header_start ; header length dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)); checksum diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index c5f8a075..35960b2f 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,41 +1,44 @@ use cpuio; +use acpi; -//TODO implement ACPI to have such functionality /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd /// -pub fn reboot() { - //TODO disable interrupt here something like : asm volatile ("cli"); - +pub fn reboot() -> ! { + unsafe {asm!("cli")}; //TODO volatile ????? // I will now clear the keyboard buffer let mut buffer: u8 = 0x02; - while buffer == 0x02 { + while buffer & 0x02 != 0 { + cpuio::inb(0x60); buffer = cpuio::inb(0x64); } - cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work - println!("Reicv reboot command. System cannot reboot yet, he is now halt\n"); + cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot + println!("Unable to perform reboot. Kernel will be halted"); cpuio::halt(); } /// Shutdown the kernel /// -/// # Pre-requist: -/// Seems that he have to use following line command : -/// `-device isa-debug-exit,iobase=0xf4,iosize=0x04` +/// If shutdown is performed but failed, will loop on a halt cmd +/// If shutdown cannot be called, return a Err(&str) /// -/// If shutdown failed, will loop on a halt cmd -/// -pub fn shutdown() -> ! { - cpuio::outb(0xf4, 0x00);//TODO doesn't work :( - println!("Reicv shutdown command. System cannot shutdown properly yet, he is now halt\n"); +pub fn shutdown() -> Result <(), &'static str> { + println!("RECV SHUTDOWN"); + acpi::shutdown()?; + println!("Unable to perform ACPI shutdown. Kernel will be halted"); cpuio::halt(); } /// Print the kernel stack /// -pub fn print_kernel_stack() { +pub fn print_kernel_stack() -> Result <(), &'static str> { println!("It's a stack print"); + Ok(()) } +pub fn acpi_info() -> Result <(), &'static str> { + acpi::info()?; + Ok(()) +} diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 148ee020..ffd6ca9b 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -10,7 +10,7 @@ pub fn inb(port: u16) -> u8 { } /// Write a `u8`-sized `value` to `port`. -pub fn outb(value: u8, port: u16) { +pub fn outb(port: u16, value: u8) { unsafe {asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile")}; } @@ -22,7 +22,7 @@ pub fn inw(port: u16) -> u16 { } /// Write a `u8`-sized `value` to `port`. -pub fn outw(value: u16, port: u16) { +pub fn outw(port: u16, value: u16) { unsafe {asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile")}; } @@ -34,11 +34,12 @@ pub fn inl(port: u16) -> u32 { } /// Write a `u32`-sized `value` to `port`. -pub fn outl(value: u32, port: u16) { +pub fn outl(port: u16, value: u32) { unsafe {asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile")}; } pub fn halt() -> ! { + unsafe {asm!("cli")};//TODO sure here ? loop { unsafe {asm!("hlt")}; //TODO volatile ????? } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 2e42ab22..599d5c06 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -4,7 +4,7 @@ #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] -#![feature(asm)] //needed by cpuio for inline asm +#![feature(asm)] extern crate rlibc; extern crate multiboot2; @@ -19,29 +19,40 @@ pub mod keyboard; pub mod console; /// wrappers around the x86-family I/O instructions. pub mod cpuio; +/// ACPI self-content module +pub mod acpi; use context::CONTEXT; + +fn init_kernel() -> Result <(), &'static str> { + acpi::init()?; + Ok(()) +} use vga::{Color, ColorCode}; #[no_mangle] pub extern fn kmain(multiboot_information_address: usize) -> ! { - // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } - // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - // format_args!("{: ^80}", r#" ,--, "#), - // format_args!("{: ^80}", r#" ,--.'| ,----, "#), - // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - // format_args!("{: ^80}", r#" ' ; |./__; : "#), - // format_args!("{: ^80}", r#" | : ;| : .' "#), - // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - // format_args!("{: ^80}", r#" '--' `---' "#)); - // unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } + if let Err(msg) = init_kernel() { + println!("Kernel initialization has failed: {}", msg); + cpuio::halt(); + } + unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); + unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } let boot_info = unsafe{ multiboot2::load(multiboot_information_address) }; let memory_map_tag = boot_info.memory_map_tag() .expect("Memory map tag required"); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 5c054a9b..c6266ebd 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -69,30 +69,48 @@ impl Writer { } } + fn execute_cmd(&self, command: &str) -> Result <(), &'static str> { + match command { + "shutdown" | "halt" | "q" => console::shutdown(), + "reboot" | "r" => console::reboot(), + "acpi" | "a" => console::acpi_info(), + "stack" => console::print_kernel_stack(), + _ if self.command_len > 0 => Err("Command unknown"), + _ => Ok(()), + } + } + + fn exec(&mut self) -> Result <(), &'static str> { + self.write_byte(b'\n'); + let command = match core::str::from_utf8(&self.command) { + Ok(y) => &y[..self.command_len], + Err(_) => return Err("Command is not utf8 char") + }; + if let Err(msg) = self.execute_cmd(command) { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Red, Color::Black); + println!("`{}`: {}", command, msg); + self.color_code = color_code_save; + } + self.command_len = 0; + Ok(()) + } + pub fn keypress(&mut self, ascii: u8) { match ascii { b'\n' => { - self.write_byte(b'\n'); - { - let command: &str = &core::str::from_utf8(&self.command).unwrap()[..self.command_len]; - match command { - "shutdown" | "halt" => console::shutdown(), - "reboot" => console::reboot(), - "stack" => console::print_kernel_stack(), - _ => { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); - println!("`{}': Command unknown ", command); - self.color_code = color_code_save; - } - } + if let Err(msg) = self.exec() { + let color_code_save = self.color_code; + self.color_code = ColorCode::new(Color::Red, Color::Black); + println!("Something wrong: {}", msg); + self.color_code = color_code_save; } - self.command_len = 0; self.prompt(); } + _ if self.command_len >= 10 => (), + byte if self.command_len == 0 && byte == b' ' => (), byte => { if self.command_len >= 10 { return }; - self.command[self.command_len] = byte; self.write_byte(byte); self.command_len += 1; @@ -136,15 +154,14 @@ impl Writer { } } - fn flush_cursor(&self) - { + fn flush_cursor(&self) { let cursor_position = self.buffer_pos / 2; // 14 awaits the rightmost 8bits - cpuio::outb(14, 0x3D4); - cpuio::outb((cursor_position >> 8) as u8, 0x3D5); + cpuio::outb(0x3D4, 14); + cpuio::outb(0x3D5, (cursor_position >> 8) as u8); // 15 awaits the leftmost 8bits - cpuio::outb(15, 0x3D4); - cpuio::outb((cursor_position >> 0) as u8 & 0x00ff, 0x3D5); + cpuio::outb(0x3D4, 15); + cpuio::outb(0x3D5, (cursor_position >> 0) as u8 & 0x00ff); } pub fn flush(&mut self) { From 2ca356340a21843f54b5005ace95c328f3cb994a Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 2 Mar 2018 18:44:41 +0100 Subject: [PATCH 064/151] some minor fix --- kernel-rs/src/console.rs | 4 ++++ kernel-rs/src/lib.rs | 4 ++-- kernel-rs/src/vga/mod.rs | 5 ++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index e4067a7b..b43620e8 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -92,6 +92,10 @@ fn print_line(line: &[u8], address: usize) { for byte in line { print!("{:02x} ", *byte); } + let length : usize = 16 - line.len(); + for _ in 0..length { + print!(" "); + } print!("|"); for byte in line { match is_control(*byte as char) { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 29f5f1bd..0c0170cd 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -37,7 +37,7 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! { println!("Kernel initialization has failed: {}", msg); cpuio::halt(); } - unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Cyan); } + set_color!(White, Cyan); print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", format_args!("{: ^80}", r#" ,--, "#), format_args!("{: ^80}", r#" ,--.'| ,----, "#), @@ -53,7 +53,7 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! { format_args!("{: ^80}", r#" | : ;| : .' "#), format_args!("{: ^80}", r#" ' ,/ ; | .' "#), format_args!("{: ^80}", r#" '--' `---' "#)); - unsafe { CONTEXT.current_term().color_code = ColorCode::new(Color::White, Color::Black); } + set_color!(); unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } unsafe { CONTEXT.vga2.prompt(); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 8d0dc3ee..c448f91c 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -98,10 +98,9 @@ impl Writer { b'\n' => { self.write_byte(b'\n'); if let Err(msg) = console::exec(&self) { - let color_code_save = self.color_code; - self.color_code = ColorCode::new(Color::Red, Color::Black); + set_color!(Red, Black); println!("Something wrong: {}", msg); - self.color_code = color_code_save; + set_color!(); } self.command_len = 0; self.prompt(); From 2a2f377b9f225e981f398f21efced12ad5d1f791 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Feb 2018 20:36:19 +0100 Subject: [PATCH 065/151] first commit for kfs3 --- kernel-rs/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 0c0170cd..69fbe349 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -21,6 +21,8 @@ pub mod console; pub mod cpuio; /// ACPI self-content module pub mod acpi; +/// simple area frame allocator implementation +pub mod memory; use context::CONTEXT; From 0f5bf89493ff9018f6be9baa6a5e22cc2678011d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Feb 2018 20:36:29 +0100 Subject: [PATCH 066/151] -amend --- kernel-rs/src/memory/area_allocator.rs | 74 ++++++++++++++++++++++++++ kernel-rs/src/memory/mod.rs | 19 +++++++ 2 files changed, 93 insertions(+) create mode 100644 kernel-rs/src/memory/area_allocator.rs create mode 100644 kernel-rs/src/memory/mod.rs diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs new file mode 100644 index 00000000..4ce96334 --- /dev/null +++ b/kernel-rs/src/memory/area_allocator.rs @@ -0,0 +1,74 @@ +use memory::*; +use multiboot2::{MemoryAreaIter, MemoryArea}; + +pub struct AreaAllocator { + next_free_frame: Frame, + current_area: Option<&'static MemoryArea>, + areas: MemoryAreaIter, + kernel_start: Frame, + kernel_end: Frame, + multiboot_start: Frame, + multiboot_end: Frame, +} + +impl AreaFrameAllocator { + pub fn new(kernel_start: usize, kernel_end: usize + multiboot_start: usize, multiboot_end: usize + memory_areas: MemoryAreaIter) -> AreaAllocator { + let mut allocator = AreaAllocator { + next_free_frame: Frame::containing_address(0), + current_area: None, + areas: memory_areas, + kernel_start: Frame::containing_address(kernel_start), + kernel_end: Frame::containing_address(kernel_end), + multiboot_start: Frame::containing_address(multiboot_start), + multiboot_end: Frame::containing_address(multiboot_end), + } + allocator.choose_next_area(); + allocator + } + + fn choose_next_area(&mut self) { + // get next area with free frames + self.current_area = self.areas.clone().filter(|area| { + Frame::containing_address(area.end_address()) >= self.next_free_frame + }).min_by_key(|area| area.start_addr()); + + if let Some(area) = self.current_area { + let start_frame = Frame::containing_address(area.start_addr()); + if self.next_free_frame < start_frame { + self.next_free_frame = start_frame; + } + } + } +} + +impl FrameAllocator for AreaFrameAllocator { + fn allocate_frame(&mut self) -> Option { + if let Some(area) = sef.current_area { + let frame = Frame { number: self.next_free_frame.number }, + let current_area_last_frame = Frame::containing_address(area.end_address()); + if frame > current_area_last_frame { + // all frames are taken in this area + self.choose_next_area(); + } else if frame >= self.kernel_start && frame <= kernel_end { + // frame used by kernel + self.next_free_frame = Frame { + number: self.kernel_end.number + 1; + } + } else if frame >= self.multiboot_start && frame <= multiboot_end { + // frame used by multiboot + self.next_free_frame = Frame { + number: self.multiboot_end.number + 1; + } + } else { + self.next_free_frame_number += 1; + return Some(Frame); + } + } else { None } + } + + fn deallocate_frame(&mut self, frame: Frame) { + unimplemented!(); + } +} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs new file mode 100644 index 00000000..667a07cf --- /dev/null +++ b/kernel-rs/src/memory/mod.rs @@ -0,0 +1,19 @@ +pub const PAGE_SIZE: usize = 4096; + +// pub use self::area_allocator::*; + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Frame { + number: usize, +} + +impl Frame { + fn containing_address(address: usize) -> Frame { + Frame{ number: address / PAGE_SIZE } + } +} + +pub trait FrameAllocator { + fn allocate_frame(&mut self) -> Option; + fn deallocate_frame(&mut self, frame: Frame); +} From edfffc3b137a0b9331b1d6502260bdf2c6ccda0b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 1 Mar 2018 16:37:26 +0100 Subject: [PATCH 067/151] this shit compiles but crashes after fighting for eternity with the borrow checker --- kernel-rs/Cargo.toml | 4 ++ kernel-rs/src/console.rs | 9 ++-- kernel-rs/src/context.rs | 62 +++++++++++++++++++++----- kernel-rs/src/keyboard.rs | 17 +++---- kernel-rs/src/lib.rs | 22 ++++----- kernel-rs/src/memory/area_allocator.rs | 38 +++++++++------- kernel-rs/src/memory/mod.rs | 4 +- kernel-rs/src/vga/mod.rs | 21 +++++---- 8 files changed, 109 insertions(+), 68 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 63983b02..8acf6e4c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -9,3 +9,7 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" multiboot2 = { path = "multiboot2-elf64" } + +[dependencies.lazy_static] +version = "0.2.4" +features = ["spin_no_std"] diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index b43620e8..42566a12 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -4,7 +4,7 @@ extern crate multiboot2; use acpi; use cpuio; use core::char; -use context::CONTEXT; +use context::*; use vga::*; fn dispatch(command: &str) -> Result <(), &'static str> { @@ -120,7 +120,7 @@ fn print_stack() -> Result <(), &'static str> { } fn mb2_memory() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; let memory_map_tag = boot_info.memory_map_tag() .expect("Memory map tag required"); @@ -134,7 +134,8 @@ fn mb2_memory() -> Result <(), &'static str> { } fn mb2_sections() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; + let elf_sections_tag = boot_info.elf_sections_tag() .expect("Elf-sections tag required"); @@ -147,7 +148,7 @@ fn mb2_sections() -> Result <(), &'static str> { } fn mb2_info() -> Result <(), &'static str> { - let boot_info = unsafe { multiboot2::load(CONTEXT.boot_info_addr) }; + let boot_info = &context().boot_info; let command_line_tag = boot_info.command_line_tag() .expect("Elf-sections tag required"); diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 2b6b3b93..418b98d5 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -1,22 +1,56 @@ -extern crate core; - +use multiboot2; +use memory; use vga; +use cpuio; -pub static mut CONTEXT: Context = Context { - current_term: 0, - boot_info_addr: 0, - vga1: vga::Writer::new(), - vga2: vga::Writer::new(), -}; +pub static mut CONTEXT: Option = None; pub struct Context { pub current_term: u8, - pub boot_info_addr: usize, + pub multiboot_start: usize, + pub multiboot_end: usize, + pub kernel_start: usize, + pub kernel_end: usize, + pub boot_info: multiboot2::BootInformation, + pub frame_allocator: memory::AreaFrameAllocator, pub vga1: vga::Writer, pub vga2: vga::Writer, } -impl Context { +impl Context +{ + pub fn new(multiboot_start: usize) -> Context { + let boot_info = multiboot2::load(multiboot_start); + let multiboot_end = multiboot_start + boot_info.total_size(); + + let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); + let memory_map_tag = boot_info.memory_map_tag().unwrap(); + + let kernel_start = elf_sections_tag.sections().map( + |s| s.start_address()) + .min().unwrap() as usize; + let kernel_end = elf_sections_tag.sections().map( + |s| s.start_address() + s.size()) + .max().unwrap() as usize; + + let frame_allocator = memory::AreaFrameAllocator::new( + kernel_start, kernel_end, multiboot_start, + multiboot_end, memory_map_tag.memory_areas()); + + Context { + current_term: 0, + multiboot_start, + multiboot_end, + kernel_start, + kernel_end, + boot_info, + frame_allocator, + vga1: vga::Writer::new(), + vga2: vga::Writer::new(), + } + } + + pub fn switch_term(&mut self) { self.current_term = { if self.current_term == 0 { 1 } @@ -33,3 +67,11 @@ impl Context { } } +pub fn context() -> Context { + unsafe { + match CONTEXT.take() { + Some(context) => context, + None => panic!("heeelp"), + } + } +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index e9832de5..7084495a 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use cpuio; -use context::CONTEXT; +use context::*; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ @@ -93,23 +93,18 @@ pub fn kbd_callback() { 0x38 => {ALT = !is_release}, 0x1D => {CTRL = !is_release}, 0x0F if !is_release => { - CONTEXT.switch_term(); - CONTEXT.current_term().flush(); + context().switch_term(); + context().current_term().flush(); }, 0x0E if !is_release => { - CONTEXT.current_term().backspace(); + context().current_term().backspace(); } _ => {} } }, Some(ascii) if !is_release => { - let mut terminal = CONTEXT.current_term(); - if SHIFT { - terminal.keypress(ascii[1]); - } - else { - terminal.keypress(ascii[0]); - } + let sym = if SHIFT { ascii[1] } else { ascii[0] }; + context().current_term().keypress(sym); }, Some(_) => {}, None =>{}, diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 69fbe349..abb9a3b2 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -8,6 +8,8 @@ extern crate rlibc; extern crate multiboot2; //slightly modified fork from official 0.3.2 +#[macro_use] +extern crate lazy_static; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -24,21 +26,15 @@ pub mod acpi; /// simple area frame allocator implementation pub mod memory; -use context::CONTEXT; +use context::*; -fn init_kernel(multiboot_information_address: usize) -> Result <(), &'static str> { - unsafe { CONTEXT.boot_info_addr = multiboot_information_address }; - acpi::init()?; - Ok(()) -} use vga::{Color, ColorCode}; #[no_mangle] -pub extern fn kmain(multiboot_information_address: usize) -> ! { - if let Err(msg) = init_kernel(multiboot_information_address) { - println!("Kernel initialization has failed: {}", msg); - cpuio::halt(); - } +pub extern fn kmain(multiboot_info_addr: usize) -> ! { + unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + acpi::init().unwrap(); + set_color!(White, Cyan); print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", format_args!("{: ^80}", r#" ,--, "#), @@ -57,9 +53,7 @@ pub extern fn kmain(multiboot_information_address: usize) -> ! { format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); - unsafe { CONTEXT.vga1.prompt();CONTEXT.vga1.flush(); } - unsafe { CONTEXT.vga2.prompt(); } - + context(); loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 4ce96334..09304cb6 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -1,7 +1,7 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; -pub struct AreaAllocator { +pub struct AreaFrameAllocator { next_free_frame: Frame, current_area: Option<&'static MemoryArea>, areas: MemoryAreaIter, @@ -12,10 +12,10 @@ pub struct AreaAllocator { } impl AreaFrameAllocator { - pub fn new(kernel_start: usize, kernel_end: usize - multiboot_start: usize, multiboot_end: usize - memory_areas: MemoryAreaIter) -> AreaAllocator { - let mut allocator = AreaAllocator { + pub fn new(kernel_start: usize, kernel_end: usize, + multiboot_start: usize, multiboot_end: usize, + memory_areas: MemoryAreaIter) -> AreaFrameAllocator { + let mut allocator = AreaFrameAllocator { next_free_frame: Frame::containing_address(0), current_area: None, areas: memory_areas, @@ -23,7 +23,7 @@ impl AreaFrameAllocator { kernel_end: Frame::containing_address(kernel_end), multiboot_start: Frame::containing_address(multiboot_start), multiboot_end: Frame::containing_address(multiboot_end), - } + }; allocator.choose_next_area(); allocator } @@ -32,10 +32,10 @@ impl AreaFrameAllocator { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { Frame::containing_address(area.end_address()) >= self.next_free_frame - }).min_by_key(|area| area.start_addr()); + }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(area.start_addr()); + let start_frame = Frame::containing_address(area.start_address()); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -45,27 +45,31 @@ impl AreaFrameAllocator { impl FrameAllocator for AreaFrameAllocator { fn allocate_frame(&mut self) -> Option { - if let Some(area) = sef.current_area { - let frame = Frame { number: self.next_free_frame.number }, + if let Some(area) = self.current_area { + let frame = Frame { number: self.next_free_frame.number }; let current_area_last_frame = Frame::containing_address(area.end_address()); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); - } else if frame >= self.kernel_start && frame <= kernel_end { + } else if frame >= self.kernel_start && frame <= self.kernel_end { // frame used by kernel self.next_free_frame = Frame { - number: self.kernel_end.number + 1; + number: self.kernel_end.number + 1, } - } else if frame >= self.multiboot_start && frame <= multiboot_end { + } else if frame >= self.multiboot_start && frame <= self.multiboot_end { // frame used by multiboot self.next_free_frame = Frame { - number: self.multiboot_end.number + 1; + number: self.multiboot_end.number + 1, } } else { - self.next_free_frame_number += 1; - return Some(Frame); + self.next_free_frame.number += 1; + return Some(frame); } - } else { None } + // try again with next_free_frame + self.allocate_frame() + } else { + None + } } fn deallocate_frame(&mut self, frame: Frame) { diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 667a07cf..aa2b620e 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,6 +1,8 @@ pub const PAGE_SIZE: usize = 4096; -// pub use self::area_allocator::*; +mod area_allocator; + +pub use self::area_allocator::*; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Frame { diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index c448f91c..fa2efba8 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,11 +1,10 @@ -#[macro_use] pub mod color; pub use self::color::{Color, ColorCode}; -use ::context::CONTEXT; +use context::*; use cpuio; -use ::console; +use console; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -26,21 +25,21 @@ macro_rules! println { } macro_rules! flush { - () => (unsafe { CONTEXT.current_term().flush() }); + () => (context().current_term().flush()); } macro_rules! set_color { - () => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::White, Color::Black) }); - ($fg:ident) => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::$fg, Color::Black) }); - ($fg:ident, $bg:ident) => (unsafe { CONTEXT.current_term().color_code = - ColorCode::new(Color::$fg, Color::$bg) }); + () => (context().current_term().color_code = + ColorCode::new(Color::White, Color::Black)); + ($fg:ident) => (context().current_term().color_code = + ColorCode::new(Color::$fg, Color::Black)); + ($fg:ident, $bg:ident) => (context().current_term().color_code = + ColorCode::new(Color::$fg, Color::$bg)); } pub fn print(args: fmt::Arguments) { use core::fmt::Write; - unsafe { CONTEXT.current_term().write_fmt(args).unwrap() }; + context().current_term().write_fmt(args).unwrap(); } extern crate core; From 120292566d8ca30423b4bf8caf9fee4cee0d8962 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 1 Mar 2018 18:52:09 +0100 Subject: [PATCH 068/151] context works fianlly --- kernel-rs/Cargo.toml | 1 + kernel-rs/src/context.rs | 21 ++++++++++++++------- kernel-rs/src/lib.rs | 3 ++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 8acf6e4c..84dde790 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -8,6 +8,7 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" +spin = "0.4.5" multiboot2 = { path = "multiboot2-elf64" } [dependencies.lazy_static] diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 418b98d5..fddab663 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -1,7 +1,6 @@ use multiboot2; use memory; use vga; -use cpuio; pub static mut CONTEXT: Option = None; @@ -37,6 +36,9 @@ impl Context kernel_start, kernel_end, multiboot_start, multiboot_end, memory_map_tag.memory_areas()); + let vga1 = vga::Writer::new(); + let vga2 = vga::Writer::new(); + Context { current_term: 0, multiboot_start, @@ -45,11 +47,16 @@ impl Context kernel_end, boot_info, frame_allocator, - vga1: vga::Writer::new(), - vga2: vga::Writer::new(), + vga1, + vga2, } } + pub fn init_screen(&mut self) { + self.vga1.prompt(); + self.vga2.prompt(); + self.vga1.flush(); + } pub fn switch_term(&mut self) { self.current_term = { @@ -67,11 +74,11 @@ impl Context } } -pub fn context() -> Context { +pub fn context() -> &'static mut Context { unsafe { - match CONTEXT.take() { - Some(context) => context, - None => panic!("heeelp"), + match CONTEXT { + Some(ref mut x) => &mut *x, + None => panic!(), } } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index abb9a3b2..bbf6f05c 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -10,6 +10,7 @@ extern crate rlibc; extern crate multiboot2; //slightly modified fork from official 0.3.2 #[macro_use] extern crate lazy_static; +extern crate spin; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -34,6 +35,7 @@ use vga::{Color, ColorCode}; pub extern fn kmain(multiboot_info_addr: usize) -> ! { unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; acpi::init().unwrap(); + context().init_screen(); set_color!(White, Cyan); print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", @@ -53,7 +55,6 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); - context(); loop { keyboard::kbd_callback(); } } From 3d532a5a7ace06d49ed8227843f72ddc081627f0 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Mar 2018 11:18:30 +0100 Subject: [PATCH 069/151] memory stuff --- kernel-rs/Cargo.toml | 9 +++--- kernel-rs/src/context.rs | 2 +- kernel-rs/src/lib.rs | 5 ++- kernel-rs/src/memory/mod.rs | 6 ++++ kernel-rs/src/memory/paging/entry.rs | 47 ++++++++++++++++++++++++++++ kernel-rs/src/memory/paging/mod.rs | 10 ++++++ kernel-rs/src/memory/paging/table.rs | 28 +++++++++++++++++ 7 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 kernel-rs/src/memory/paging/entry.rs create mode 100644 kernel-rs/src/memory/paging/mod.rs create mode 100644 kernel-rs/src/memory/paging/table.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 84dde790..f7771995 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -8,9 +8,10 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" -spin = "0.4.5" +bitflags = "1.0.1" +# spin = "0.4.5" multiboot2 = { path = "multiboot2-elf64" } -[dependencies.lazy_static] -version = "0.2.4" -features = ["spin_no_std"] +# [dependencies.lazy_static] +# version = "0.2.4" +# features = ["spin_no_std"] diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index fddab663..6569012d 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -19,7 +19,7 @@ pub struct Context { impl Context { pub fn new(multiboot_start: usize) -> Context { - let boot_info = multiboot2::load(multiboot_start); + let boot_info = unsafe { multiboot2::load(multiboot_start) }; let multiboot_end = multiboot_start + boot_info.total_size(); let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index bbf6f05c..89dca7fa 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -8,9 +8,7 @@ extern crate rlibc; extern crate multiboot2; //slightly modified fork from official 0.3.2 -#[macro_use] -extern crate lazy_static; -extern crate spin; +#[macro_use] extern crate bitflags; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -28,6 +26,7 @@ pub mod acpi; pub mod memory; use context::*; +use memory::*; use vga::{Color, ColorCode}; diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index aa2b620e..68b3abd9 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,8 +1,10 @@ pub const PAGE_SIZE: usize = 4096; mod area_allocator; +mod paging; pub use self::area_allocator::*; +use self::paging::PhysicalAddress; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Frame { @@ -13,6 +15,10 @@ impl Frame { fn containing_address(address: usize) -> Frame { Frame{ number: address / PAGE_SIZE } } + + fn start_address(&self) -> PhysicalAddress { + self.number * PAGE_SIZE + } } pub trait FrameAllocator { diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs new file mode 100644 index 00000000..506bbf6a --- /dev/null +++ b/kernel-rs/src/memory/paging/entry.rs @@ -0,0 +1,47 @@ +use memory::Frame; + +pub struct Entry(u64); + +bitflags! { + pub struct EntryFlags: u64 { + const PRESENT = 1 << 0; + const WRITABLE = 1 << 1; + const USER_ACCESSIBLE = 1 << 2; + const WRITE_THROUGH = 1 << 3; + const NO_CACHE = 1 << 4; + const ACCESSED = 1 << 5; + const DIRTY = 1 << 6; + const HUGE_PAGE = 1 << 7; + const GLOBAL = 1 << 8; + const NO_EXECUTE = 1 << 63; + } +} + +impl Entry { + pub fn is_unused(&self) -> bool { + self.0 == 0; + } + + pub fn set_unused(&mut self) { + self.0 = 0; + } + + pub fn flags(&self) -> EntryFlags { + EntryFlags::from_bits_truncate(self.0); + } + + pub fn pointed_frame(&self) -> Option { + if self.flags().contains(PRESENT) { + Some(Frame::containing_address( + self.0 as usize & 0x000fffff_fffff000 // actual addr is bits 12-51 + )) + } else { + None + } + } + + pub fn set(&mut self, frame: Frame, flags: EntryFlags) { + assert!!(frame.start_address() & !0x000fffff_fffff000 == 0); + self.0 = (frame.start_address() as u64) | flags.bits(); + } +} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs new file mode 100644 index 00000000..17896565 --- /dev/null +++ b/kernel-rs/src/memory/paging/mod.rs @@ -0,0 +1,10 @@ +use memory::PAGE_SIZE; + +const ENTRY_COUNT: usize = 512; + +pub type PhysicalAddress = usize; +pub type VirtualAddress = usize; + +pub struct Page { + number: usize, +} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs new file mode 100644 index 00000000..aa11a3ab --- /dev/null +++ b/kernel-rs/src/memory/paging/table.rs @@ -0,0 +1,28 @@ +use memory::paging::entry::*; +use memory::paging::ENTRY_COUNT; + +use core::ops::{Index, IndexMut}; + +pub struct Table { + entries: [Entry; ENTRY_COUNT], +} + +impl Table { + for entry in self.entries.iter_mut() { + entry.set_unused(); + } +} + +impl Index for Table { + type Output = Entry; + + fn index(&self, index: usize) -> &Entry { + &self.entries[index] + } +} + +impl IndexMut for Table { + fn index(&self, index: usize) -> &mut Entry { + &mut self.entries[index] + } +} From 5412334168990aa42b1b3d3d0d30aba55346d006 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Mar 2018 13:12:02 +0100 Subject: [PATCH 070/151] it runs --- kernel-rs/Cargo.toml | 4 --- kernel-rs/src/console.rs | 17 ++++++----- kernel-rs/src/context.rs | 62 +++++++++++++++++++++++++++------------ kernel-rs/src/keyboard.rs | 10 +++---- kernel-rs/src/lib.rs | 27 ++--------------- kernel-rs/src/vga/mod.rs | 18 ++++++------ 6 files changed, 70 insertions(+), 68 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index f7771995..f854812c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -11,7 +11,3 @@ rlibc = "1.0" bitflags = "1.0.1" # spin = "0.4.5" multiboot2 = { path = "multiboot2-elf64" } - -# [dependencies.lazy_static] -# version = "0.2.4" -# features = ["spin_no_std"] diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 42566a12..d8e9fefc 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,10 +1,11 @@ extern crate core; -extern crate multiboot2; +// extern crate multiboot2; use acpi; use cpuio; +use context; +// use multiboot2; use core::char; -use context::*; use vga::*; fn dispatch(command: &str) -> Result <(), &'static str> { @@ -35,10 +36,10 @@ fn help() -> Result <(), &'static str> { print!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", "acpi => Return acpi state (ENABLED|DISABLE)", "help | h => Print this help", - "memory => lolilol", // TODO - "multiboot => lolilol", // TODO + "memory => print memory areas", // TODO + "multiboot => print multiboot information", // TODO "reboot => reboot", - "sections => lolilol", // TODO + "sections => print elf sections", // TODO "shutdown | halt | q => Kill a kitten, then shutdown", "stack => Print kernel stack in a fancy way"); Ok(()) @@ -120,7 +121,7 @@ fn print_stack() -> Result <(), &'static str> { } fn mb2_memory() -> Result <(), &'static str> { - let boot_info = &context().boot_info; + let boot_info = context::boot_info(); let memory_map_tag = boot_info.memory_map_tag() .expect("Memory map tag required"); @@ -134,7 +135,7 @@ fn mb2_memory() -> Result <(), &'static str> { } fn mb2_sections() -> Result <(), &'static str> { - let boot_info = &context().boot_info; + let boot_info = context::boot_info(); let elf_sections_tag = boot_info.elf_sections_tag() .expect("Elf-sections tag required"); @@ -148,7 +149,7 @@ fn mb2_sections() -> Result <(), &'static str> { } fn mb2_info() -> Result <(), &'static str> { - let boot_info = &context().boot_info; + let boot_info = context::boot_info(); let command_line_tag = boot_info.command_line_tag() .expect("Elf-sections tag required"); diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 6569012d..64eea470 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -52,29 +52,51 @@ impl Context } } - pub fn init_screen(&mut self) { - self.vga1.prompt(); - self.vga2.prompt(); - self.vga1.flush(); - } +} - pub fn switch_term(&mut self) { - self.current_term = { - if self.current_term == 0 { 1 } - else { 0 } - }; - } +pub fn init_screen() { + set_color!(White, Cyan); + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); + set_color!(); + context().vga1.prompt(); + context().vga2.prompt(); + context().vga1.flush(); +} - pub fn current_term(&mut self) -> &mut vga::Writer{ - if self.current_term == 0 { - &mut self.vga1 - } else { - &mut self.vga2 - } +pub fn switch_term() { + context().current_term = { + if context().current_term == 0 { 1 } + else { 0 } + }; +} + +pub fn current_term() -> &'static mut vga::Writer{ + if context().current_term == 0 { + &mut context().vga1 + } else { + &mut context().vga2 } } -pub fn context() -> &'static mut Context { +pub fn boot_info() -> &'static multiboot2::BootInformation { + &context().boot_info +} + +fn context() -> &'static mut Context { unsafe { match CONTEXT { Some(ref mut x) => &mut *x, @@ -82,3 +104,7 @@ pub fn context() -> &'static mut Context { } } } + +pub fn init(multiboot_info_addr: usize) { + unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 7084495a..a29f14b3 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use cpuio; -use context::*; +use context; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ @@ -93,18 +93,18 @@ pub fn kbd_callback() { 0x38 => {ALT = !is_release}, 0x1D => {CTRL = !is_release}, 0x0F if !is_release => { - context().switch_term(); - context().current_term().flush(); + context::switch_term(); + context::current_term().flush(); }, 0x0E if !is_release => { - context().current_term().backspace(); + context::current_term().backspace(); } _ => {} } }, Some(ascii) if !is_release => { let sym = if SHIFT { ascii[1] } else { ascii[0] }; - context().current_term().keypress(sym); + context::current_term().keypress(sym); }, Some(_) => {}, None =>{}, diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 89dca7fa..93c08533 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -25,34 +25,13 @@ pub mod acpi; /// simple area frame allocator implementation pub mod memory; -use context::*; -use memory::*; - -use vga::{Color, ColorCode}; +// use vga::{Color, ColorCode}; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { - unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + context::init(multiboot_info_addr); + context::init_screen(); acpi::init().unwrap(); - context().init_screen(); - - set_color!(White, Cyan); - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); - set_color!(); loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index fa2efba8..8bc3ebf6 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -2,7 +2,7 @@ pub mod color; pub use self::color::{Color, ColorCode}; -use context::*; +use context; use cpuio; use console; @@ -25,21 +25,21 @@ macro_rules! println { } macro_rules! flush { - () => (context().current_term().flush()); + () => (context::current_term().flush()); } macro_rules! set_color { - () => (context().current_term().color_code = - ColorCode::new(Color::White, Color::Black)); - ($fg:ident) => (context().current_term().color_code = - ColorCode::new(Color::$fg, Color::Black)); - ($fg:ident, $bg:ident) => (context().current_term().color_code = - ColorCode::new(Color::$fg, Color::$bg)); + () => ($crate::context::current_term().color_code = + $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)); + ($fg:ident) => ($crate::context::current_term().color_code = + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)); + ($fg:ident, $bg:ident) => ($crate::context::current_term().color_code = + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)); } pub fn print(args: fmt::Arguments) { use core::fmt::Write; - context().current_term().write_fmt(args).unwrap(); + context::current_term().write_fmt(args).unwrap(); } extern crate core; From d491624274ebc8cc211e836beac55295189b8520 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 5 Mar 2018 13:29:44 +0100 Subject: [PATCH 071/151] rut stable, going to do some assembly now --- kernel-rs/src/memory/paging/entry.rs | 12 ++++++------ kernel-rs/src/memory/paging/mod.rs | 3 +++ kernel-rs/src/memory/paging/table.rs | 8 +++++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs index 506bbf6a..ae2b7355 100644 --- a/kernel-rs/src/memory/paging/entry.rs +++ b/kernel-rs/src/memory/paging/entry.rs @@ -19,7 +19,7 @@ bitflags! { impl Entry { pub fn is_unused(&self) -> bool { - self.0 == 0; + self.0 == 0 } pub fn set_unused(&mut self) { @@ -27,21 +27,21 @@ impl Entry { } pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0); + EntryFlags::from_bits_truncate(self.0) } pub fn pointed_frame(&self) -> Option { - if self.flags().contains(PRESENT) { + if self.flags().contains(EntryFlags::PRESENT) { Some(Frame::containing_address( - self.0 as usize & 0x000fffff_fffff000 // actual addr is bits 12-51 - )) + // actual addr is bits 12-51 + self.0 as usize & 0x000fffff_fffff000)) } else { None } } pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!!(frame.start_address() & !0x000fffff_fffff000 == 0); + assert!(frame.start_address() & !0x000fffff_fffff000 == 0); self.0 = (frame.start_address() as u64) | flags.bits(); } } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 17896565..a4fa45aa 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,3 +1,6 @@ +mod entry; +mod table; + use memory::PAGE_SIZE; const ENTRY_COUNT: usize = 512; diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index aa11a3ab..5a22f689 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -8,8 +8,10 @@ pub struct Table { } impl Table { - for entry in self.entries.iter_mut() { - entry.set_unused(); + pub fn zero(&mut self) { + for entry in self.entries.iter_mut() { + entry.set_unused(); + } } } @@ -22,7 +24,7 @@ impl Index for Table { } impl IndexMut for Table { - fn index(&self, index: usize) -> &mut Entry { + fn index_mut(&mut self, index: usize) -> &mut Entry { &mut self.entries[index] } } From 3041cec87dcb93cb94031531fea2ff2303a444ef Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 7 Mar 2018 19:15:19 +0100 Subject: [PATCH 072/151] mmu code mostly written, needs a lot of debugging still --- kernel-rs/Cargo.toml | 1 - kernel-rs/src/arch/x86/boot.asm | 67 +++++- kernel-rs/src/arch/x86/linker.ld | 42 +++- kernel-rs/src/console.rs | 8 + kernel-rs/src/context.rs | 53 ++--- kernel-rs/src/lib.rs | 15 +- kernel-rs/src/memory/mod.rs | 32 +++ kernel-rs/src/memory/paging/entry.rs | 40 ++-- kernel-rs/src/memory/paging/mapper.rs | 85 ++++++++ kernel-rs/src/memory/paging/mod.rs | 191 +++++++++++++++++- kernel-rs/src/memory/paging/table.rs | 77 ++++++- kernel-rs/src/memory/paging/temporary_page.rs | 79 ++++++++ kernel-rs/src/vga/mod.rs | 2 +- kernel-rs/src/x86/mod.rs | 11 + 14 files changed, 622 insertions(+), 81 deletions(-) create mode 100644 kernel-rs/src/memory/paging/mapper.rs create mode 100644 kernel-rs/src/memory/paging/temporary_page.rs create mode 100644 kernel-rs/src/x86/mod.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index f854812c..68a70731 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -9,5 +9,4 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" bitflags = "1.0.1" -# spin = "0.4.5" multiboot2 = { path = "multiboot2-elf64" } diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 2b8b5995..b0e9c208 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -4,12 +4,61 @@ extern x86_start section .text bits 32 start: + ; our stack, located in bss, linker.ld puts bss at the end of the binary + mov esp, stack_top + ; multiboot information pointer push ebx call check_multiboot + + call set_up_page_tables + ; call enable_paging + lgdt [GDTR.ptr] ; load the new gdt jmp GDTR.gdt_cs:x86_start - ; jmp x86_start + +check_multiboot: + cmp eax, 0x36d76289 + jne .no_multiboot + ret +.no_multiboot: + mov al, "0" + jmp error + +set_up_page_tables: + ; map P2 table recursively + mov eax, p2_table + or eax, 0b11 ; present + writable + mov [p2_table + 1023 * 8], eax + + ; map each P2 entry to a huge 2MiB page + mov ecx, 0 ; counter variable + +.map_p2_table: + ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx + mov eax, 0x200000 ; 2MiB + ; mov eax, 0x2 ; WRITABLE, not PRESENT + mul ecx ; start address of ecx-th page + or eax, 0b10000011 ; present + writable + huge + mov [p2_table + ecx * 8], eax ; map ecx-th entry + + inc ecx ; increase counter + cmp ecx, 1023 ; if counter == 1023, the whole P2 table is mapped + jne .map_p2_table ; else map the next entry + + ret + +enable_paging: + ; load P2 to cr3 register (cpu uses this to access the P2 table) + mov eax, p2_table + mov cr3, eax + + ; enable paging in the cr0 register + mov eax, cr0 + or eax, 1 << 31 + mov cr0, eax + + ret error: mov dword [0xb8000], 0x4f524f45 @@ -21,14 +70,6 @@ HALT: hlt jmp HALT -check_multiboot: - cmp eax, 0x36d76289 - jne .no_multiboot - ret -.no_multiboot: - mov al, "0" - jmp error - section .gdt GDTR: ; http://tuttlem.github.io/2014/07/11/a-gdt-primer.html @@ -88,6 +129,12 @@ GDTR: DD .gdt_top ; pointer to top of gdt section .bss +align 4096 +p2_table: + resb 4096 +p1_table: + resb 4096 stack_bottom: - resb 4096 * 16 + resb 4096 * 4 stack_top: + diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 15716e72..27f2ae00 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -13,10 +13,38 @@ SECTIONS { . = 1M; /* ensure that the multiboot header is at the beginning */ - .multiboot : { KEEP(*(.multiboot)) } - .text : { *(.text .text.*) } - .rodata : { *(.rodata .rodata.*) } - .data : { *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) } - .debug : { *(.debug_*) } - .bss : {*(.bss .bss.*)} -} + .multiboot : + { + KEEP(*(.multiboot)) + . = ALIGN(4K); + } + + .text : + { + *(.text .text.*) + . = ALIGN(4K); + } + + .rodata : + { + *(.rodata .rodata.*) + . = ALIGN(4K); + } + + .data : + { + *(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*) *(.data.*) + . = ALIGN(4K); + } + + .debug : + { + *(.debug_*) + . = ALIGN(4K); + } + + .bss : + { + *(.bss .bss.*)} + . = ALIGN(4K); + } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index d8e9fefc..ebc033c9 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -4,6 +4,7 @@ extern crate core; use acpi; use cpuio; use context; +use memory; // use multiboot2; use core::char; use vga::*; @@ -18,6 +19,7 @@ fn dispatch(command: &str) -> Result <(), &'static str> { "sections" => self::mb2_sections(), "shutdown" | "halt" | "q" => self::shutdown(), "stack" => self::print_stack(), + "test" => self::test(), _ => Err("Command unknown. (h|help for help)"), } } @@ -45,6 +47,12 @@ fn help() -> Result <(), &'static str> { Ok(()) } +fn test() -> Result<(), &'static str> +{ + memory::test_paging(context::frame_allocator()); + Ok(()) +} + /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 64eea470..03f810ad 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -6,10 +6,6 @@ pub static mut CONTEXT: Option = None; pub struct Context { pub current_term: u8, - pub multiboot_start: usize, - pub multiboot_end: usize, - pub kernel_start: usize, - pub kernel_end: usize, pub boot_info: multiboot2::BootInformation, pub frame_allocator: memory::AreaFrameAllocator, pub vga1: vga::Writer, @@ -41,10 +37,6 @@ impl Context Context { current_term: 0, - multiboot_start, - multiboot_end, - kernel_start, - kernel_end, boot_info, frame_allocator, vga1, @@ -52,31 +44,41 @@ impl Context } } + + } pub fn init_screen() { set_color!(White, Cyan); print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); context().vga1.prompt(); context().vga2.prompt(); context().vga1.flush(); } +pub fn frame_allocator() -> &'static mut memory::AreaFrameAllocator { + &mut context().frame_allocator +} + +pub fn boot_info() -> &'static multiboot2::BootInformation { + &context().boot_info +} + pub fn switch_term() { context().current_term = { if context().current_term == 0 { 1 } @@ -92,10 +94,6 @@ pub fn current_term() -> &'static mut vga::Writer{ } } -pub fn boot_info() -> &'static multiboot2::BootInformation { - &context().boot_info -} - fn context() -> &'static mut Context { unsafe { match CONTEXT { @@ -107,4 +105,7 @@ fn context() -> &'static mut Context { pub fn init(multiboot_info_addr: usize) { unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + + // memory::remap_the_kernel(frame_allocator(), boot_info()); + self::init_screen(); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 93c08533..786bd74e 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,4 +1,4 @@ -//! project hosted at (https://github.com/jzck/kernel) +//! project hosted on [github](https://github.com/jzck/kernel) #![no_std] #![feature(lang_items)] @@ -22,17 +22,15 @@ pub mod console; pub mod cpuio; /// ACPI self-content module pub mod acpi; -/// simple area frame allocator implementation +/// physical frame allocator + paging module pub mod memory; - -// use vga::{Color, ColorCode}; +/// a few x86 instruction wrappers +pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { context::init(multiboot_info_addr); - context::init_screen(); acpi::init().unwrap(); - loop { keyboard::kbd_callback(); } } @@ -42,13 +40,12 @@ pub extern fn eh_personality() { } #[lang = "panic_fmt"] #[no_mangle] -pub extern fn panic_fmt( - fmt: core::fmt::Arguments, file: &'static str, line: u32 - ) +pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { println!("PANIC: {}", fmt); println!("FILE: {}", file); println!("LINE: {}", line); + flush!(); loop {} } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 68b3abd9..51629c66 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -4,6 +4,8 @@ mod area_allocator; mod paging; pub use self::area_allocator::*; +pub use self::paging::test_paging; +pub use self::paging::remap_the_kernel; use self::paging::PhysicalAddress; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -19,9 +21,39 @@ impl Frame { fn start_address(&self) -> PhysicalAddress { self.number * PAGE_SIZE } + + fn clone(&self) ->Frame { + Frame { number: self.number } + } + + fn range_inclusive(start: Frame, end: Frame) -> FrameIter { + FrameIter { + start, + end, + } + } } pub trait FrameAllocator { fn allocate_frame(&mut self) -> Option; fn deallocate_frame(&mut self, frame: Frame); } + +struct FrameIter { + start: Frame, + end: Frame, +} + +impl Iterator for FrameIter { + type Item = Frame; + + fn next(&mut self) -> Option { + if self.start <= self.end { + let frame = self.start.clone(); + self.start.number += 1; + Some(frame) + } else { + None + } + } +} diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs index ae2b7355..0f2803c7 100644 --- a/kernel-rs/src/memory/paging/entry.rs +++ b/kernel-rs/src/memory/paging/entry.rs @@ -1,21 +1,6 @@ use memory::Frame; -pub struct Entry(u64); - -bitflags! { - pub struct EntryFlags: u64 { - const PRESENT = 1 << 0; - const WRITABLE = 1 << 1; - const USER_ACCESSIBLE = 1 << 2; - const WRITE_THROUGH = 1 << 3; - const NO_CACHE = 1 << 4; - const ACCESSED = 1 << 5; - const DIRTY = 1 << 6; - const HUGE_PAGE = 1 << 7; - const GLOBAL = 1 << 8; - const NO_EXECUTE = 1 << 63; - } -} +pub struct Entry(u32); impl Entry { pub fn is_unused(&self) -> bool { @@ -33,15 +18,30 @@ impl Entry { pub fn pointed_frame(&self) -> Option { if self.flags().contains(EntryFlags::PRESENT) { Some(Frame::containing_address( - // actual addr is bits 12-51 - self.0 as usize & 0x000fffff_fffff000)) + self.0 as usize & 0xffff_f000)) } else { None } } pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!(frame.start_address() & !0x000fffff_fffff000 == 0); - self.0 = (frame.start_address() as u64) | flags.bits(); + assert!(frame.start_address() & !0xffff_f000 == 0); + self.0 = (frame.start_address() as u32) | flags.bits(); + } +} + +bitflags! { + pub struct EntryFlags: u32 { + const PRESENT = 1 << 0; + const WRITABLE = 1 << 1; + const USER_ACCESSIBLE = 1 << 2; + const WRITE_THROUGH = 1 << 3; + const NO_CACHE = 1 << 4; + const ACCESSED = 1 << 5; + const DIRTY = 1 << 6; + const HUGE_PAGE = 1 << 7; + const GLOBAL = 1 << 8; + // LONG MODE + // const NO_EXECUTE = 1 << 63; } } diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs new file mode 100644 index 00000000..652a1589 --- /dev/null +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -0,0 +1,85 @@ +use super::{VirtualAddress, PhysicalAddress, Page, ENTRY_COUNT}; +use super::entry::*; +use super::table::{self, Table, Level2, Level1}; +use memory::{PAGE_SIZE, Frame, FrameAllocator}; +use core::ptr::Unique; + +pub struct Mapper { + p2: Unique>, +} + +impl Mapper { + pub unsafe fn new() -> Mapper { + Mapper { + p2: Unique::new_unchecked(table::P2), + } + } + + // the remaining mapping methods, all public + pub fn p2(&self) -> &Table { + unsafe { self.p2.as_ref() } + } + + pub fn p2_mut(&mut self) -> &mut Table { + unsafe { self.p2.as_mut() } + } + + pub fn translate(&self, virtual_address: VirtualAddress) -> Option + { + let offset = virtual_address % PAGE_SIZE; + self.translate_page(Page::containing_address(virtual_address)) + .map(|frame| frame.number * PAGE_SIZE + offset) + } + + pub fn translate_page(&self, page: Page) -> Option { + + // huge page handler, unimplemented + let huge_page = || { + unimplemented!() + }; + + self.p2().next_table(page.p2_index()) + .and_then(|p1| p1[page.p1_index()].pointed_frame()) + .or_else(huge_page) + } + + + pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags, + allocator: &mut A) + where A: FrameAllocator + { + let p2 = self.p2_mut(); + let mut p1 = p2.next_table_create(page.p2_index(), allocator); + + assert!(p1[page.p1_index()].is_unused()); + p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); + } + + pub fn map(&mut self, page: Page, flags: EntryFlags, allocator: &mut A) + where A: FrameAllocator + { + let frame = allocator.allocate_frame().expect("out of memory"); + self.map_to(page, frame, flags, allocator) + } + + pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A) + where A: FrameAllocator + { + let page = Page::containing_address(frame.start_address()); + self.map_to(page, frame, flags, allocator); + } + + pub fn unmap(&mut self, page: Page, allocator: &mut A) + where A: FrameAllocator + { + assert!(self.translate(page.start_address()).is_some()); + + let p1 = self.p2_mut() + .next_table_mut(page.p2_index()) + .expect("mapping code does not support huge pages"); + let frame = p1[page.p1_index()].pointed_frame().unwrap(); + p1[page.p1_index()].set_unused(); + // TODO flush the tlb + allocator.deallocate_frame(frame); + } +} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index a4fa45aa..6a12207a 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,13 +1,202 @@ +#![allow(dead_code)] + mod entry; mod table; +mod temporary_page; +mod mapper; use memory::PAGE_SIZE; +use memory::*; +use self::mapper::Mapper; +use self::temporary_page::TemporaryPage; +use core::ops::{Deref, DerefMut}; +use multiboot2::BootInformation; +use x86; -const ENTRY_COUNT: usize = 512; +pub use self::entry::*; +pub use self::table::*; + +// x86 non PAE has 1024 entries per table +const ENTRY_COUNT: usize = 1024; pub type PhysicalAddress = usize; pub type VirtualAddress = usize; +#[derive(Debug, Clone, Copy)] pub struct Page { number: usize, } + +impl Page { + pub fn containing_address(address: VirtualAddress) -> Page { + // assert!(address < 0x0000_8000_0000_0000 || + // address >= 0xffff_8000_0000_0000, + // "invalid addres: 0x{:x}", address); + Page { number: address / PAGE_SIZE } + } + + fn start_address(&self) -> usize { + self.number * PAGE_SIZE + } + + fn p2_index(&self) -> usize { + (self.number >> 9) & 0o777 + } + + fn p1_index(&self) -> usize { + (self.number >> 0) & 0o777 + } +} + +pub struct ActivePageTable { + mapper: Mapper, +} + +impl Deref for ActivePageTable { + type Target = Mapper; + + fn deref(&self) -> &Mapper { + &self.mapper + } +} + +impl DerefMut for ActivePageTable { + fn deref_mut(&mut self) -> &mut Mapper { + &mut self.mapper + } +} + +impl ActivePageTable { + pub unsafe fn new() -> ActivePageTable { + ActivePageTable { + mapper: Mapper::new(), + } + } + + pub fn with(&mut self, + table: &mut InactivePageTable, + temporary_page: &mut temporary_page::TemporaryPage, + f: F) + where F: FnOnce(&mut Mapper) + { + self.p2_mut()[ENTRY_COUNT -1].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); + + //TODO tlb flush all + + // execute f in the nex context + f(self); + + // TODO restore recursive mapping to original p2 table + } + + pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { + + let p2_frame = Frame::containing_address(x86::cr3() as usize); + let old_table = InactivePageTable { + p2_frame, + }; + + unsafe { + let frame = Frame::containing_address(new_table.p2_frame.start_address()); + x86::cr3_write(frame.start_address()); + } + + old_table + } +} + +pub struct InactivePageTable { + p2_frame: Frame, +} + +impl InactivePageTable { + pub fn new(frame: Frame, + active_table: &mut ActivePageTable, + temporary_page: &mut TemporaryPage, + ) -> InactivePageTable { + { + let table = temporary_page.map_table_frame(frame.clone(), + active_table); + table.zero(); + // set up recursive mapping for the table + table[ENTRY_COUNT - 1].set(frame.clone(), EntryFlags::PRESENT | EntryFlags:: WRITABLE) + } + temporary_page.unmap(active_table); + InactivePageTable { p2_frame: frame } + } +} + +pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) + where A: FrameAllocator +{ + let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }, + allocator); + + let mut active_table = unsafe { ActivePageTable::new() }; + let mut new_table = { + let frame = allocator.allocate_frame().expect("no more frames"); + InactivePageTable::new(frame, &mut active_table, &mut temporary_page) + }; + + active_table.with(&mut new_table, &mut temporary_page, |mapper| { + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("Memory map tag required"); + + for section in elf_sections_tag.sections() { + use self::entry::EntryFlags; + + if !section.is_allocated() { + //section is not loaded to memory + continue; + } + assert!(section.start_address() % PAGE_SIZE as u64 == 0, + "sections need to be page aligned"); + + println!("mapping section at addr: {:#x}, size: {:#x}", + section.start_address(), section.size()); + + let flags = EntryFlags::WRITABLE; //TODO use real section flags + + let start_frame = Frame::containing_address(section.start_address() as usize); + let end_frame = Frame::containing_address(section.end_address() as usize - 1); + for frame in Frame::range_inclusive(start_frame, end_frame) { + mapper.identity_map(frame, flags, allocator); + } + } + + let vga_buffer_frame = Frame::containing_address(0xb8000); + mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); + + let multiboot_start = Frame::containing_address(boot_info.start_address()); + let multiboot_end = Frame::containing_address(boot_info.end_address() - 1); + for frame in Frame::range_inclusive(multiboot_start, multiboot_end) { + mapper.identity_map(frame, EntryFlags::PRESENT, allocator); + } + }); + + let old_table = active_table.switch(new_table); + println!("new table!"); +} + +pub fn test_paging(allocator: &mut A) + where A: FrameAllocator +{ + let mut page_table = unsafe { ActivePageTable::new() }; + + let addr = 0xffff_f000; + let page = Page::containing_address(addr); + let frame = allocator.allocate_frame().expect("no more frames"); + // println!("None = {:?}, map to {:?}", + // page_table.translate(addr), + // frame); + println!("check 0"); + flush!(); + page_table.map_to(page, frame, EntryFlags::empty(), allocator); + println!("check 1"); + flush!(); + println!("Some = {:?}", page_table.translate(addr)); + flush!(); + println!("next free frame: {:?}", allocator.allocate_frame()); + flush!(); + +} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 5a22f689..28289a03 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,13 +1,21 @@ -use memory::paging::entry::*; -use memory::paging::ENTRY_COUNT; +use memory::*; +use memory::paging::*; use core::ops::{Index, IndexMut}; +use core::marker::PhantomData; -pub struct Table { +// virtual address of P2 because its recursively mapped +// see protected mode Non-PAE +// https://wiki.osdev.org/Page_Tables +pub const P2: *mut Table = 0xffff_f000 as *mut _; + +pub struct Table { entries: [Entry; ENTRY_COUNT], + level: PhantomData, } -impl Table { +impl Table where L: TableLevel +{ pub fn zero(&mut self) { for entry in self.entries.iter_mut() { entry.set_unused(); @@ -15,7 +23,46 @@ impl Table { } } -impl Index for Table { +impl Table where L: HierarchicalLevel +{ + fn next_table_address(&self, index: usize) -> Option { + let entry_flags = self[index].flags(); + if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) { + let table_address = self as *const _ as usize; + Some((table_address << 9) | (index << 12)) + } else { + None + } + } + + pub fn next_table(&self, index: usize) -> Option<&Table> { + self.next_table_address(index) + .map(|address| unsafe { &*(address as *const _) }) + } + + pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table> { + self.next_table_address(index) + .map(|address| unsafe { &mut *(address as *mut _) }) + } + + pub fn next_table_create(&mut self, + index: usize, + allocator: &mut A) -> &mut Table + where A: FrameAllocator + { + if self.next_table(index).is_none() { + // assert!(!self.entries[index].flags().contains(EntryFlags::HUGE_PAGE), + // "mapping code does not support huge pages"); + let frame = allocator.allocate_frame().expect("no frames available"); + self.entries[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); + self.next_table_mut(index).expect("no next next table 1").zero() + } + self.next_table_mut(index).expect("no next table 2") + } +} + +impl Index for Table where L: TableLevel +{ type Output = Entry; fn index(&self, index: usize) -> &Entry { @@ -23,8 +70,26 @@ impl Index for Table { } } -impl IndexMut for Table { +impl IndexMut for Table where L: TableLevel +{ fn index_mut(&mut self, index: usize) -> &mut Entry { &mut self.entries[index] } } + +pub trait TableLevel {} + +pub enum Level4 {} +pub enum Level3 {} +pub enum Level2 {} +pub enum Level1 {} + +impl TableLevel for Level4 {} +impl TableLevel for Level3 {} +impl TableLevel for Level2 {} +impl TableLevel for Level1 {} + +pub trait HierarchicalLevel: TableLevel { type NextLevel: TableLevel; } +impl HierarchicalLevel for Level4 { type NextLevel = Level3; } +impl HierarchicalLevel for Level3 { type NextLevel = Level2; } +impl HierarchicalLevel for Level2 { type NextLevel = Level1; } diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs new file mode 100644 index 00000000..77ef6440 --- /dev/null +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -0,0 +1,79 @@ +use super::{Page, ActivePageTable, VirtualAddress}; +use super::table::{Table, Level1}; +use memory::{Frame, FrameAllocator}; + +pub struct TemporaryPage { + page: Page, + allocator: TinyAllocator, +} + +impl TemporaryPage { + pub fn new(page: Page, allocator: &mut A) -> TemporaryPage + where A: FrameAllocator + { + TemporaryPage { + page: page, + allocator: TinyAllocator::new(allocator), + } + } + + /// Maps the temporary page to the given frame in the active table. + /// Returns the start address of the temporary page. + pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) + -> VirtualAddress + { + use super::entry::EntryFlags; + + assert!(active_table.translate_page(self.page).is_none(), + "temporary page is already mapped"); + active_table.map_to(self.page, frame, EntryFlags::WRITABLE, &mut self.allocator); + self.page.start_address() + } + + /// Unmaps the temporary page in the active table. + pub fn unmap(&mut self, active_table: &mut ActivePageTable) { + active_table.unmap(self.page, &mut self.allocator) + } + + /// Maps the temporary page to the given page table frame in the active + /// table. Returns a reference to the now mapped table. + pub fn map_table_frame(&mut self, + frame: Frame, + active_table: &mut ActivePageTable) + -> &mut Table { + unsafe { &mut *(self.map(frame, active_table) as *mut Table) } + } +} + +struct TinyAllocator([Option; 1]); + +impl TinyAllocator { + fn new(allocator: &mut A) -> TinyAllocator + where A: FrameAllocator + { + let mut f = || allocator.allocate_frame(); + let frames = [f()]; + TinyAllocator(frames) + } +} + +impl FrameAllocator for TinyAllocator { + fn allocate_frame(&mut self) -> Option { + for frame_option in &mut self.0 { + if frame_option.is_some() { + return frame_option.take(); + } + } + None + } + + fn deallocate_frame(&mut self, frame: Frame) { + for frame_option in &mut self.0 { + if frame_option.is_none() { + *frame_option = Some(frame); + return; + } + } + panic!("Tiny allcoator can only hold 1 frame."); + } +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 8bc3ebf6..0a09fe1b 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -25,7 +25,7 @@ macro_rules! println { } macro_rules! flush { - () => (context::current_term().flush()); + () => ($crate::context::current_term().flush()); } macro_rules! set_color { diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs new file mode 100644 index 00000000..46a9b41b --- /dev/null +++ b/kernel-rs/src/x86/mod.rs @@ -0,0 +1,11 @@ +//! x86 (32 bit) only + +pub fn cr3() -> usize { + let ret: usize; + unsafe { asm!("mov %cr3, $0" : "=r" (ret)) }; + ret +} + +pub unsafe fn cr3_write(val: usize) { + asm!("mov $0, %cr3" :: "r" (val) : "memory"); +} From 9ba59d585811d8c0d2124c33cf0c718a6fea211f Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 8 Mar 2018 14:50:25 +0100 Subject: [PATCH 073/151] Set ready for KFS-2 --- kernel-rs/multiboot2-elf64 | 2 +- kernel-rs/src/acpi/mod.rs | 20 ++++++++++++++++++-- kernel-rs/src/acpi/rsdp.rs | 15 ++++----------- kernel-rs/src/arch/x86/boot.asm | 8 ++++---- kernel-rs/src/console.rs | 8 ++++---- kernel-rs/src/lib.rs | 12 +++++++++++- kernel-rs/src/vga/mod.rs | 1 - 7 files changed, 42 insertions(+), 24 deletions(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index d66e8cb0..4d6ad9cd 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit d66e8cb0e5b10c2097a9aef985b4181694db9ce8 +Subproject commit 4d6ad9cde926f2ad5d47041e3f3a2cda18f8e11e diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 702e6f9c..5256d1ae 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -44,8 +44,7 @@ struct Acpi { } impl Acpi { - fn init(&mut self) -> Result <(), &'static str> { - self.v2 = rsdp::init()?; + fn common_init(&mut self) -> Result <(), &'static str> { if self.v2 { // Xsdt Address: // 64-bit physical address of the XSDT table. If you detect ACPI Version 2.0 you should use this table instead of RSDT even on x86, casting the address to uint32_t. @@ -58,6 +57,15 @@ impl Acpi { dsdt::init(fadt::dsdtaddr()?)?; self.valid = true; Ok(()) + + } + fn init(&mut self) -> Result <(), &'static str> { + self.v2 = rsdp::init()?; + self.common_init() + } + fn load(&mut self, rsdp_addr: u32) -> Result <(), &'static str> { + self.v2 = rsdp::load(rsdp_addr)?; + self.common_init() } } @@ -130,6 +138,14 @@ pub fn init() -> Result <(), &'static str> { unsafe {ACPI.init()} } +/// Load the ACPI module, addr given is a ptr to RSDP +pub fn load(rsdp_addr: u32) -> Result <(), &'static str> { + if let Ok(()) = is_init() { + return Ok(()); + } + unsafe {ACPI.load(rsdp_addr)} +} + /// Proceed to ACPI shutdown /// This function doesn't work with Virtual Box yet pub fn shutdown() -> Result <(), &'static str> { diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs index b5b6967b..d1ec9d52 100644 --- a/kernel-rs/src/acpi/rsdp.rs +++ b/kernel-rs/src/acpi/rsdp.rs @@ -30,6 +30,7 @@ pub fn load(addr: u32) -> Result { let ptr_tmp = addr as *const RSDP20; let revision = unsafe {(*ptr_tmp).rsdp.revision}; if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { + println!("REAL FOUND AT {:x}", addr); unsafe {RSDPTR = Some(ptr_tmp)}; return Ok(revision == 2); } @@ -37,18 +38,14 @@ pub fn load(addr: u32) -> Result { Err("Not a valid RSD ptr") } -fn memory_finding(bound: u32) -> Result { +fn memory_finding() -> Result { let mut i = 0; while i < 0x1000000 { - i += bound; + i += 8; if let Ok(result) = load(i) { return Ok(result) } } - // HACK because RSDP is not always aligned on 16 bytes boundary with QEMU - if bound > 1 { - return memory_finding(bound / 2); - } Err("Can not find Root System Description Pointer (RSDP).") } @@ -56,10 +53,6 @@ fn is_init() -> Result <*const RSDP20, &'static str> { match unsafe {RSDPTR} { Some(ptr) => Ok(ptr), None => Err("Root System Description Pointer (RSDP) is not initialized") - // if ptr == 0 as *const RSDP20 - // => Err("Root System Description Pointer (RSDP) is not initialized"), - // ptr - // => Ok(ptr) } } @@ -85,5 +78,5 @@ pub fn rsdtaddr() -> Result { /// if you already know the location, you should prefer to use load function /// return an Error if there is no RSDP in memory, or return the value of load function pub fn init() -> Result { - memory_finding(16) + memory_finding() } diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 2b8b5995..ed470888 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -62,7 +62,7 @@ GDTR: DW 0xffff ; Limit ( bits 0 -15 ) DW 0x0 ; Base ( bits 0 -15 ) DB 0x0 ; Base ( bits 16 -23 ) - DB 0xFE ; [ Access Flags: 0x9A=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] + DB 0xFE ; [ Access Flags: 0xFE=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) @@ -70,7 +70,7 @@ GDTR: DW 0xffff ; Limit ( bits 0 -15 ) DW 0x0 ; Base ( bits 0 -15 ) DB 0x0 ; Base ( bits 16 -23 ) - DB 0xF2 ; [ Access Flags: 0x9A=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] + DB 0xF2 ; [ Access Flags: 0xF2=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) @@ -78,8 +78,8 @@ GDTR: DW 0x0 ; Limit ( bits 0 -15 ) DW 0x0 ; Base ( bits 0 -15 ) DB 0x0 ; Base ( bits 16 -23 ) - DB 0x00 ; [ Access Flags: 0x9A=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0x00 ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] + DB 0xF6 ; [ Access Flags: 0xF2=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] + DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) .gdt_bottom: diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index b43620e8..aba02cc6 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -35,10 +35,10 @@ fn help() -> Result <(), &'static str> { print!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", "acpi => Return acpi state (ENABLED|DISABLE)", "help | h => Print this help", - "memory => lolilol", // TODO - "multiboot => lolilol", // TODO - "reboot => reboot", - "sections => lolilol", // TODO + "memory => Print memory areas", + "multiboot => Print multiboot information", + "reboot => Reboot", + "sections => Print elf sections", "shutdown | halt | q => Kill a kitten, then shutdown", "stack => Print kernel stack in a fancy way"); Ok(()) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 0c0170cd..8ff0e619 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -26,7 +26,17 @@ use context::CONTEXT; fn init_kernel(multiboot_information_address: usize) -> Result <(), &'static str> { unsafe { CONTEXT.boot_info_addr = multiboot_information_address }; - acpi::init()?; + let mtboot = unsafe { multiboot2::load(multiboot_information_address)}; + if let Some(rsdp) = mtboot.rsdp_v2_tag() { + println!("rsdp at {:x}", rsdp); + acpi::load(rsdp)?; + } else if let Some(rsdp) = mtboot.rsdp_tag() { + println!("rsdp2 at {:x}", rsdp); + acpi::load(rsdp)?; + } + else { + acpi::init()?; + } Ok(()) } use vga::{Color, ColorCode}; diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index c448f91c..130da283 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -123,7 +123,6 @@ impl Writer { self.buffer[i] = b' '; self.buffer[i + 1] = 0; self.flush(); - // flush!(); } pub fn write_byte(&mut self, byte: u8) { From 11c3614060714e46fa5ab2dd6c627b31145b92a9 Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 8 Mar 2018 14:59:59 +0100 Subject: [PATCH 074/151] oop multiboot --- kernel-rs/multiboot2-elf64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index 4d6ad9cd..4425c197 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit 4d6ad9cde926f2ad5d47041e3f3a2cda18f8e11e +Subproject commit 4425c197f10d5bcada47eabb8b2f93a8e2422937 From 0d8ecdf191092872f6060dcfbaa5dd1d23cfe512 Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 8 Mar 2018 15:10:32 +0100 Subject: [PATCH 075/151] remove log --- kernel-rs/src/acpi/rsdp.rs | 1 - kernel-rs/src/lib.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs index d1ec9d52..c5eeb490 100644 --- a/kernel-rs/src/acpi/rsdp.rs +++ b/kernel-rs/src/acpi/rsdp.rs @@ -30,7 +30,6 @@ pub fn load(addr: u32) -> Result { let ptr_tmp = addr as *const RSDP20; let revision = unsafe {(*ptr_tmp).rsdp.revision}; if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { - println!("REAL FOUND AT {:x}", addr); unsafe {RSDPTR = Some(ptr_tmp)}; return Ok(revision == 2); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 8ff0e619..788715b8 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -28,10 +28,8 @@ fn init_kernel(multiboot_information_address: usize) -> Result <(), &'static str unsafe { CONTEXT.boot_info_addr = multiboot_information_address }; let mtboot = unsafe { multiboot2::load(multiboot_information_address)}; if let Some(rsdp) = mtboot.rsdp_v2_tag() { - println!("rsdp at {:x}", rsdp); acpi::load(rsdp)?; } else if let Some(rsdp) = mtboot.rsdp_tag() { - println!("rsdp2 at {:x}", rsdp); acpi::load(rsdp)?; } else { From 1f5a3618707dafd2f1b8cde0a76817ba09982797 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 9 Mar 2018 13:12:21 +0100 Subject: [PATCH 076/151] some changes --- kernel-rs/Makefile | 2 +- kernel-rs/src/arch/x86/boot.asm | 33 +++++++++++++-------------- kernel-rs/src/console.rs | 11 ++++++++- kernel-rs/src/keyboard.rs | 1 - kernel-rs/src/memory/paging/mapper.rs | 2 +- kernel-rs/src/memory/paging/mod.rs | 4 ++-- kernel-rs/src/memory/paging/table.rs | 2 +- kernel-rs/src/x86/mod.rs | 12 ++++++++++ 8 files changed, 43 insertions(+), 24 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 6485e460..f0ce373c 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -34,7 +34,7 @@ MONITOR := sleep 0.5;\ kill \`ps -x | grep \"[g]db\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db\" | cut -d \ -f 2 \` GDB := gdb -q\ - -ex \"set arch i386:x86-64\"\ + -ex \"set arch i386:x64-32\"\ -ex \"file $(kernel)\"\ -ex \"target remote localhost:$(PORTG)\" \ -ex \"continue\" diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index b0e9c208..ff6ad86e 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -12,7 +12,7 @@ start: call check_multiboot call set_up_page_tables - ; call enable_paging + call enable_paging lgdt [GDTR.ptr] ; load the new gdt jmp GDTR.gdt_cs:x86_start @@ -29,7 +29,7 @@ set_up_page_tables: ; map P2 table recursively mov eax, p2_table or eax, 0b11 ; present + writable - mov [p2_table + 1023 * 8], eax + mov [p2_table + 1023 * 4], eax ; map each P2 entry to a huge 2MiB page mov ecx, 0 ; counter variable @@ -37,22 +37,21 @@ set_up_page_tables: .map_p2_table: ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx mov eax, 0x200000 ; 2MiB - ; mov eax, 0x2 ; WRITABLE, not PRESENT mul ecx ; start address of ecx-th page or eax, 0b10000011 ; present + writable + huge - mov [p2_table + ecx * 8], eax ; map ecx-th entry + mov [p2_table + ecx * 4], eax ; map ecx-th entry inc ecx ; increase counter cmp ecx, 1023 ; if counter == 1023, the whole P2 table is mapped jne .map_p2_table ; else map the next entry - ret - -enable_paging: ; load P2 to cr3 register (cpu uses this to access the P2 table) mov eax, p2_table mov cr3, eax + ret + +enable_paging: ; enable paging in the cr0 register mov eax, cr0 or eax, 1 << 31 @@ -70,6 +69,16 @@ HALT: hlt jmp HALT +section .bss +align 4096 +p2_table: + resb 4096 +p1_table: + resb 4096 +stack_bottom: + resb 4096 * 4 +stack_top: + section .gdt GDTR: ; http://tuttlem.github.io/2014/07/11/a-gdt-primer.html @@ -128,13 +137,3 @@ GDTR: DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 DD .gdt_top ; pointer to top of gdt -section .bss -align 4096 -p2_table: - resb 4096 -p1_table: - resb 4096 -stack_bottom: - resb 4096 * 4 -stack_top: - diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index ebc033c9..ea547791 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -5,7 +5,7 @@ use acpi; use cpuio; use context; use memory; -// use multiboot2; +use x86; use core::char; use vga::*; @@ -20,6 +20,7 @@ fn dispatch(command: &str) -> Result <(), &'static str> { "shutdown" | "halt" | "q" => self::shutdown(), "stack" => self::print_stack(), "test" => self::test(), + "regs" => self::regs(), _ => Err("Command unknown. (h|help for help)"), } } @@ -176,3 +177,11 @@ pub fn acpi_info() -> Result <(), &'static str> { acpi::info()?; Ok(()) } + +pub fn regs() -> Result <(), &'static str> { + println!("cr0={:#b}", x86::cr0()); + println!("cr3={:#x}", x86::cr3()); + println!("cr4={:#b}", x86::cr4()); + Ok(()) +} + diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index a29f14b3..572f7ac4 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -80,7 +80,6 @@ pub fn kbd_callback() { static mut SHIFT: bool = false; static mut CTRL: bool = false; static mut ALT: bool = false; - // let terminal_two: vga::terminal::Terminal = vga::Screen::new(); let control = cpuio::inb(0x64); if (control & 1) == 1 { let scancode = cpuio::inb(0x60); diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 652a1589..91a41aa6 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -49,7 +49,7 @@ impl Mapper { where A: FrameAllocator { let p2 = self.p2_mut(); - let mut p1 = p2.next_table_create(page.p2_index(), allocator); + let p1 = p2.next_table_create(page.p2_index(), allocator); assert!(p1[page.p1_index()].is_unused()); p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 6a12207a..49981a40 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -40,11 +40,11 @@ impl Page { } fn p2_index(&self) -> usize { - (self.number >> 9) & 0o777 + (self.number >> 10) & 0x3ff } fn p1_index(&self) -> usize { - (self.number >> 0) & 0o777 + (self.number >> 0) & 0x3ff } } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 28289a03..705f0a87 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -29,7 +29,7 @@ impl Table where L: HierarchicalLevel let entry_flags = self[index].flags(); if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) { let table_address = self as *const _ as usize; - Some((table_address << 9) | (index << 12)) + Some((table_address << 10) | (index << 12)) } else { None } diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs index 46a9b41b..cd5ce658 100644 --- a/kernel-rs/src/x86/mod.rs +++ b/kernel-rs/src/x86/mod.rs @@ -1,11 +1,23 @@ //! x86 (32 bit) only +pub fn cr0() -> usize { + let ret: usize; + unsafe { asm!("mov %cr0, $0" : "=r" (ret)) }; + ret +} + pub fn cr3() -> usize { let ret: usize; unsafe { asm!("mov %cr3, $0" : "=r" (ret)) }; ret } +pub fn cr4() -> usize { + let ret: usize; + unsafe { asm!("mov %cr4, $0" : "=r" (ret)) }; + ret +} + pub unsafe fn cr3_write(val: usize) { asm!("mov $0, %cr3" :: "r" (val) : "memory"); } From bbe2b8b1e6a6aae82df2c474e7f51cbb6c473158 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 10 Mar 2018 17:35:51 +0100 Subject: [PATCH 077/151] still no debug symbols --- kernel-rs/Makefile | 17 ++++++++--------- kernel-rs/src/arch/x86/boot.asm | 22 +++++++++++++++++----- kernel-rs/src/arch/x86/start.asm | 1 - kernel-rs/src/context.rs | 2 +- kernel-rs/src/memory/paging/mapper.rs | 24 +++++++++++++++++------- kernel-rs/src/memory/paging/table.rs | 9 +++++---- kernel-rs/src/vga/mod.rs | 5 +++++ kernel-rs/src/x86/mod.rs | 4 ++++ kernel-rs/x86-bluesnow.json | 1 - 9 files changed, 57 insertions(+), 28 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index f0ce373c..e43fe467 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -10,8 +10,8 @@ endif project := bluesnow arch ?= x86 -NASM := nasm -f elf -LD := ld -m elf_i386 -L ./ -n --gc-sections +NASM := /usr/bin/nasm -f elf +LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections # QEMU := qemu-system-x86_64 -device isa-debug-exit,iobase=0xf4,iosize=0x04 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait @@ -34,20 +34,19 @@ MONITOR := sleep 0.5;\ kill \`ps -x | grep \"[g]db\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db\" | cut -d \ -f 2 \` GDB := gdb -q\ - -ex \"set arch i386:x64-32\"\ + -ex \"set arch i386:x86-64\"\ -ex \"file $(kernel)\"\ - -ex \"target remote localhost:$(PORTG)\" \ - -ex \"continue\" + -ex \"target remote :$(PORTG)\" + # -ex \"continue\" all: $(kernel) build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile @mkdir -p $(shell dirname $@) - @$(NASM) $< -o $@ - @echo "Compiling (ASM) $@..." + $(NASM) $< -o $@ $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile - @$(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) + $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) $(iso): $(kernel) $(grub.cfg) Makefile @mkdir -p $(DIRISO)/boot/grub @@ -71,7 +70,7 @@ R: @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' clean: - @cargo clean + @xargo clean @rm -r build $(rust_os): $(target).json Makefile diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index ff6ad86e..c6cb7cb3 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -12,9 +12,12 @@ start: call check_multiboot call set_up_page_tables - call enable_paging + ; call enable_pse + ; call enable_paging + + ; load the new gdt + lgdt [GDTR.ptr] - lgdt [GDTR.ptr] ; load the new gdt jmp GDTR.gdt_cs:x86_start check_multiboot: @@ -45,13 +48,22 @@ set_up_page_tables: cmp ecx, 1023 ; if counter == 1023, the whole P2 table is mapped jne .map_p2_table ; else map the next entry - ; load P2 to cr3 register (cpu uses this to access the P2 table) - mov eax, p2_table - mov cr3, eax + ret + +; PSE (Page Size Extension) allows huge pages to exist +enable_pse: + ; enable PSE in the cr4 register + mov eax, cr4 + or eax, 1 << 2 + mov cr4, eax ret enable_paging: + ; load P2 to cr3 register (cpu uses this to access the P2 table) + mov eax, p2_table + mov cr3, eax + ; enable paging in the cr0 register mov eax, cr0 or eax, 1 << 31 diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index d93b89af..8c69f1ce 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -13,7 +13,6 @@ x86_start: call kmain -; if main return, loop forever ; that should NEVER append cli ; clear interrupt HALT: hlt diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 03f810ad..25e0e30b 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -106,6 +106,6 @@ fn context() -> &'static mut Context { pub fn init(multiboot_info_addr: usize) { unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; - // memory::remap_the_kernel(frame_allocator(), boot_info()); + memory::remap_the_kernel(frame_allocator(), boot_info()); self::init_screen(); } diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 91a41aa6..b17d4ee7 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -33,14 +33,24 @@ impl Mapper { pub fn translate_page(&self, page: Page) -> Option { - // huge page handler, unimplemented - let huge_page = || { - unimplemented!() - }; + let p1 = self.p2().next_table(page.p2_index()); - self.p2().next_table(page.p2_index()) - .and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + let huge_page = || { + let p2_entry = &self.p2()[page.p2_index()]; + if let Some(start_frame) = p2_entry.pointed_frame() { + if p2_entry.flags().contains(EntryFlags::HUGE_PAGE) { + // 2MiB alignment check + assert!(start_frame.number % ENTRY_COUNT == 0); + return Some(Frame { + number: start_frame.number + page.p1_index() + }); + } + } + None + }; + + p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) + .or_else(huge_page) } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 705f0a87..57988f06 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -51,11 +51,12 @@ impl Table where L: HierarchicalLevel where A: FrameAllocator { if self.next_table(index).is_none() { - // assert!(!self.entries[index].flags().contains(EntryFlags::HUGE_PAGE), - // "mapping code does not support huge pages"); + assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), + "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); - self.entries[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); - self.next_table_mut(index).expect("no next next table 1").zero() + self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); + panic!("wtf"); + self.next_table_mut(index).expect("real wtf now").zero() } self.next_table_mut(index).expect("no next table 2") } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 0a09fe1b..2ab62cbd 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -5,6 +5,7 @@ pub use self::color::{Color, ColorCode}; use context; use cpuio; use console; +use x86; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -164,7 +165,11 @@ impl Writer { pub fn flush(&mut self) { let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; + + let cr0 = x86::cr0() & !(1 << 31); + unsafe { x86::cr0_write(cr0); } slice.as_mut().clone_from_slice(&self.buffer); + unsafe { x86::cr0_write(cr0 | (1 << 31)); } self.flush_cursor(); } diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs index cd5ce658..3659eb88 100644 --- a/kernel-rs/src/x86/mod.rs +++ b/kernel-rs/src/x86/mod.rs @@ -1,5 +1,9 @@ //! x86 (32 bit) only +pub unsafe fn cr0_write(val: usize) { + asm!("mov $0, %cr0" :: "r"(val) : "memory"); +} + pub fn cr0() -> usize { let ret: usize; unsafe { asm!("mov %cr0, $0" : "=r" (ret)) }; diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json index 6be11f62..6e895d2b 100644 --- a/kernel-rs/x86-bluesnow.json +++ b/kernel-rs/x86-bluesnow.json @@ -1,6 +1,5 @@ { "arch": "x86", - "cpu": "pentium4", "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", "llvm-target": "i686-unknown-none", "linker-flavor": "gcc", From f0456aa7fdc66d69e5ce6d26b7e0aa143756f180 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 11 Mar 2018 18:41:34 +0100 Subject: [PATCH 078/151] i must have done something right becuase now 0xffff_f000 points to p2 as expected, hurray --- kernel-rs/Makefile | 2 +- kernel-rs/src/arch/x86/boot.asm | 11 +++++----- kernel-rs/src/context.rs | 6 +++--- kernel-rs/src/lib.rs | 1 + kernel-rs/src/memory/paging/entry.rs | 19 ++++++++++++++++ kernel-rs/src/memory/paging/mapper.rs | 2 +- kernel-rs/src/memory/paging/mod.rs | 31 ++++++++++++++++++++------- kernel-rs/src/memory/paging/table.rs | 3 +-- kernel-rs/src/vga/mod.rs | 7 +++--- kernel-rs/x86-bluesnow.json | 3 +++ 10 files changed, 60 insertions(+), 25 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index e43fe467..a26b3e36 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -10,7 +10,7 @@ endif project := bluesnow arch ?= x86 -NASM := /usr/bin/nasm -f elf +NASM := /usr/bin/nasm -f elf -g LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections # QEMU := qemu-system-x86_64 -device isa-debug-exit,iobase=0xf4,iosize=0x04 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index c6cb7cb3..72a2fbe3 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -12,8 +12,8 @@ start: call check_multiboot call set_up_page_tables - ; call enable_pse - ; call enable_paging + call enable_pse + call enable_paging ; load the new gdt lgdt [GDTR.ptr] @@ -39,9 +39,9 @@ set_up_page_tables: .map_p2_table: ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx - mov eax, 0x200000 ; 2MiB + mov eax, 0x400000 ; 4MiB mul ecx ; start address of ecx-th page - or eax, 0b10000011 ; present + writable + huge + or eax, 0b10000011 ; huge + present + writable mov [p2_table + ecx * 4], eax ; map ecx-th entry inc ecx ; increase counter @@ -54,7 +54,7 @@ set_up_page_tables: enable_pse: ; enable PSE in the cr4 register mov eax, cr4 - or eax, 1 << 2 + or eax, 1 << 4 mov cr4, eax ret @@ -148,4 +148,3 @@ GDTR: .ptr: DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 DD .gdt_top ; pointer to top of gdt - diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 25e0e30b..38e5dd0a 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -104,8 +104,8 @@ fn context() -> &'static mut Context { } pub fn init(multiboot_info_addr: usize) { - unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + // unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; - memory::remap_the_kernel(frame_allocator(), boot_info()); - self::init_screen(); + // memory::remap_the_kernel(frame_allocator(), boot_info()); + // self::init_screen(); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 786bd74e..172fab12 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -30,6 +30,7 @@ pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { context::init(multiboot_info_addr); + loop {} acpi::init().unwrap(); loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs index 0f2803c7..26edb9c1 100644 --- a/kernel-rs/src/memory/paging/entry.rs +++ b/kernel-rs/src/memory/paging/entry.rs @@ -1,6 +1,7 @@ use memory::Frame; pub struct Entry(u32); +use multiboot2::ElfSection; impl Entry { pub fn is_unused(&self) -> bool { @@ -45,3 +46,21 @@ bitflags! { // const NO_EXECUTE = 1 << 63; } } + +impl EntryFlags { + pub fn from_elf_section_flags(section: &ElfSection) -> EntryFlags { + use multiboot2::ElfSectionFlags; + + let mut flags = EntryFlags::empty(); + if section.flags().contains(ElfSectionFlags::ALLOCATED) { + flags = flags | EntryFlags::PRESENT; + } + if section.flags().contains(ElfSectionFlags::WRITABLE) { + flags = flags | EntryFlags::WRITABLE; + } + // if !section.flags().contains(ElfSectionFlags::EXECUTABLE) { + // flags = flags | EntryFlags::NO_EXECUTE; + // } + flags + } +} diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index b17d4ee7..e3d2074f 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -1,6 +1,6 @@ use super::{VirtualAddress, PhysicalAddress, Page, ENTRY_COUNT}; use super::entry::*; -use super::table::{self, Table, Level2, Level1}; +use super::table::{self, Table, Level2}; use memory::{PAGE_SIZE, Frame, FrameAllocator}; use core::ptr::Unique; diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 49981a40..5e7277c4 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -79,14 +79,20 @@ impl ActivePageTable { f: F) where F: FnOnce(&mut Mapper) { - self.p2_mut()[ENTRY_COUNT -1].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); + let backup = Frame::containing_address(x86::cr3()); + // map temp page to current p2 + let p2_table = temporary_page.map_table_frame(backup.clone(), self); + + // overwrite recrusive map + self.p2_mut()[1023].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); //TODO tlb flush all - // execute f in the nex context + // execute f in the new context f(self); // TODO restore recursive mapping to original p2 table + p2_table[1023].set(backup, EntryFlags::PRESENT | EntryFlags::WRITABLE); } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { @@ -127,6 +133,7 @@ impl InactivePageTable { } pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) + -> ActivePageTable where A: FrameAllocator { let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }, @@ -139,6 +146,11 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) }; active_table.with(&mut new_table, &mut temporary_page, |mapper| { + + // identity map the VGA text buffer + let vga_buffer_frame = Frame::containing_address(0xb8000); + mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); + let elf_sections_tag = boot_info.elf_sections_tag() .expect("Memory map tag required"); @@ -155,8 +167,7 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) println!("mapping section at addr: {:#x}, size: {:#x}", section.start_address(), section.size()); - let flags = EntryFlags::WRITABLE; //TODO use real section flags - + let flags = EntryFlags::from_elf_section_flags(§ion); let start_frame = Frame::containing_address(section.start_address() as usize); let end_frame = Frame::containing_address(section.end_address() as usize - 1); for frame in Frame::range_inclusive(start_frame, end_frame) { @@ -164,9 +175,6 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) } } - let vga_buffer_frame = Frame::containing_address(0xb8000); - mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); - let multiboot_start = Frame::containing_address(boot_info.start_address()); let multiboot_end = Frame::containing_address(boot_info.end_address() - 1); for frame in Frame::range_inclusive(multiboot_start, multiboot_end) { @@ -175,7 +183,14 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) }); let old_table = active_table.switch(new_table); - println!("new table!"); + + let old_p2_page = Page::containing_address( + old_table.p2_frame.start_address() + ); + active_table.unmap(old_p2_page, allocator); + println!("guard page at {:#x}", old_p2_page.start_address()); + + active_table } pub fn test_paging(allocator: &mut A) diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 57988f06..da35e011 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -55,8 +55,7 @@ impl Table where L: HierarchicalLevel "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); - panic!("wtf"); - self.next_table_mut(index).expect("real wtf now").zero() + self.next_table_mut(index).expect("next_table_mut gave None").zero() } self.next_table_mut(index).expect("no next table 2") } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 2ab62cbd..605a84f1 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -165,11 +165,10 @@ impl Writer { pub fn flush(&mut self) { let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; - - let cr0 = x86::cr0() & !(1 << 31); - unsafe { x86::cr0_write(cr0); } + // let cr0 = x86::cr0() & !(1 << 31); + // unsafe { x86::cr0_write(cr0); } slice.as_mut().clone_from_slice(&self.buffer); - unsafe { x86::cr0_write(cr0 | (1 << 31)); } + // unsafe { x86::cr0_write(cr0 | (1 << 31)); } self.flush_cursor(); } diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json index 6e895d2b..22f12e60 100644 --- a/kernel-rs/x86-bluesnow.json +++ b/kernel-rs/x86-bluesnow.json @@ -1,6 +1,9 @@ { "arch": "x86", + + "_comment": "http://llvm.org/docs/LangRef.html#data-layout", "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "llvm-target": "i686-unknown-none", "linker-flavor": "gcc", "no-compiler-rt": true, From ec1e7c8a5bf7f21d14f4a892f220b2e00208ad02 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Mar 2018 14:53:26 +0100 Subject: [PATCH 079/151] tlb added, acpi still faults with the new memory --- kernel-rs/src/arch/x86/boot.asm | 8 +++----- kernel-rs/src/arch/x86/linker.ld | 25 ++++++++++++++++++++++--- kernel-rs/src/context.rs | 7 ++----- kernel-rs/src/lib.rs | 4 ++-- kernel-rs/src/memory/paging/mapper.rs | 8 +++++--- kernel-rs/src/memory/paging/mod.rs | 21 +++++++++++++-------- kernel-rs/src/memory/paging/table.rs | 1 + kernel-rs/src/vga/mod.rs | 4 ---- kernel-rs/src/x86/mod.rs | 2 ++ kernel-rs/src/x86/tlb.rs | 10 ++++++++++ 10 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 kernel-rs/src/x86/tlb.rs diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 72a2fbe3..8615c283 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -34,7 +34,7 @@ set_up_page_tables: or eax, 0b11 ; present + writable mov [p2_table + 1023 * 4], eax - ; map each P2 entry to a huge 2MiB page + ; map each P2 entry to a huge 4MiB page mov ecx, 0 ; counter variable .map_p2_table: @@ -45,7 +45,7 @@ set_up_page_tables: mov [p2_table + ecx * 4], eax ; map ecx-th entry inc ecx ; increase counter - cmp ecx, 1023 ; if counter == 1023, the whole P2 table is mapped + cmp ecx, 20 ; if counter == 1023, the whole P2 table is mapped jne .map_p2_table ; else map the next entry ret @@ -85,10 +85,8 @@ section .bss align 4096 p2_table: resb 4096 -p1_table: - resb 4096 stack_bottom: - resb 4096 * 4 + resb 4096 * 8 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 27f2ae00..d02b7510 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -3,8 +3,8 @@ OUTPUT_FORMAT(elf32-i386) SECTIONS { /* GDT for the win */ - . = 0x800; - .gdt : {KEEP(*(.gdt))} + /* . = 0x800; */ + /* .gdt : {KEEP(*(.gdt))} */ /* VGA, cannot use section for this */ VGA_PTR = 0xb8000; @@ -45,6 +45,25 @@ SECTIONS { .bss : { - *(.bss .bss.*)} + *(.bss .bss.*) . = ALIGN(4K); } + + .gdt : + { + *(.gdt) + . = ALIGN(4K); + } + + .got : + { + *(.got) + . = ALIGN(4K); + } + + .got.plt : + { + *(.got.plt) + . = ALIGN(4K); + } +} diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 38e5dd0a..fd258849 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -43,9 +43,6 @@ impl Context vga2, } } - - - } pub fn init_screen() { @@ -104,8 +101,8 @@ fn context() -> &'static mut Context { } pub fn init(multiboot_info_addr: usize) { - // unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; + unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; // memory::remap_the_kernel(frame_allocator(), boot_info()); - // self::init_screen(); + self::init_screen(); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 172fab12..6ea1a015 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -30,8 +30,8 @@ pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { context::init(multiboot_info_addr); - loop {} - acpi::init().unwrap(); + // println!("init done!"); + // acpi::init().unwrap(); loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index e3d2074f..93d5be86 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -3,6 +3,7 @@ use super::entry::*; use super::table::{self, Table, Level2}; use memory::{PAGE_SIZE, Frame, FrameAllocator}; use core::ptr::Unique; +use x86; pub struct Mapper { p2: Unique>, @@ -39,7 +40,7 @@ impl Mapper { let p2_entry = &self.p2()[page.p2_index()]; if let Some(start_frame) = p2_entry.pointed_frame() { if p2_entry.flags().contains(EntryFlags::HUGE_PAGE) { - // 2MiB alignment check + // 4KiB alignment check assert!(start_frame.number % ENTRY_COUNT == 0); return Some(Frame { number: start_frame.number + page.p1_index() @@ -89,7 +90,8 @@ impl Mapper { .expect("mapping code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); - // TODO flush the tlb - allocator.deallocate_frame(frame); + x86::tlb::flush(page.start_address()); + // TODO + // allocator.deallocate_frame(frame); } } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 5e7277c4..45a43f81 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -84,9 +84,9 @@ impl ActivePageTable { // map temp page to current p2 let p2_table = temporary_page.map_table_frame(backup.clone(), self); - // overwrite recrusive map + // overwrite recursive map self.p2_mut()[1023].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); - //TODO tlb flush all + x86::tlb::flush_all(); // execute f in the new context f(self); @@ -98,12 +98,15 @@ impl ActivePageTable { pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { let p2_frame = Frame::containing_address(x86::cr3() as usize); + + println!("old p2_frame at {}", p2_frame.number); let old_table = InactivePageTable { p2_frame, }; unsafe { let frame = Frame::containing_address(new_table.p2_frame.start_address()); + println!("new p2_frame at {:#x}", new_table.p2_frame.start_address()); x86::cr3_write(frame.start_address()); } @@ -124,8 +127,9 @@ impl InactivePageTable { let table = temporary_page.map_table_frame(frame.clone(), active_table); table.zero(); + // set up recursive mapping for the table - table[ENTRY_COUNT - 1].set(frame.clone(), EntryFlags::PRESENT | EntryFlags:: WRITABLE) + table[1023].set(frame.clone(), EntryFlags::PRESENT | EntryFlags:: WRITABLE) } temporary_page.unmap(active_table); InactivePageTable { p2_frame: frame } @@ -138,7 +142,6 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) { let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }, allocator); - let mut active_table = unsafe { ActivePageTable::new() }; let mut new_table = { let frame = allocator.allocate_frame().expect("no more frames"); @@ -158,7 +161,6 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) use self::entry::EntryFlags; if !section.is_allocated() { - //section is not loaded to memory continue; } assert!(section.start_address() % PAGE_SIZE as u64 == 0, @@ -187,8 +189,11 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) let old_p2_page = Page::containing_address( old_table.p2_frame.start_address() ); + active_table.unmap(old_p2_page, allocator); + println!("guard page at {:#x}", old_p2_page.start_address()); + println!("cr3 = {:#x}", x86::cr3()); active_table } @@ -201,9 +206,9 @@ pub fn test_paging(allocator: &mut A) let addr = 0xffff_f000; let page = Page::containing_address(addr); let frame = allocator.allocate_frame().expect("no more frames"); - // println!("None = {:?}, map to {:?}", - // page_table.translate(addr), - // frame); + println!("None = {:?}, map to {:?}", + page_table.translate(addr), + frame); println!("check 0"); flush!(); page_table.map_to(page, frame, EntryFlags::empty(), allocator); diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index da35e011..2a9e9a86 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -51,6 +51,7 @@ impl Table where L: HierarchicalLevel where A: FrameAllocator { if self.next_table(index).is_none() { + println!("index={} flags={:#b}", index, self[index].flags()); assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 605a84f1..0a09fe1b 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -5,7 +5,6 @@ pub use self::color::{Color, ColorCode}; use context; use cpuio; use console; -use x86; #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -165,10 +164,7 @@ impl Writer { pub fn flush(&mut self) { let slice = unsafe { core::slice::from_raw_parts_mut(0xb8000 as *mut u8, 4000) }; - // let cr0 = x86::cr0() & !(1 << 31); - // unsafe { x86::cr0_write(cr0); } slice.as_mut().clone_from_slice(&self.buffer); - // unsafe { x86::cr0_write(cr0 | (1 << 31)); } self.flush_cursor(); } diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs index 3659eb88..7d9cf902 100644 --- a/kernel-rs/src/x86/mod.rs +++ b/kernel-rs/src/x86/mod.rs @@ -1,5 +1,7 @@ //! x86 (32 bit) only +pub mod tlb; + pub unsafe fn cr0_write(val: usize) { asm!("mov $0, %cr0" :: "r"(val) : "memory"); } diff --git a/kernel-rs/src/x86/tlb.rs b/kernel-rs/src/x86/tlb.rs new file mode 100644 index 00000000..1890ebaa --- /dev/null +++ b/kernel-rs/src/x86/tlb.rs @@ -0,0 +1,10 @@ +use super::*; + +pub fn flush(addr: usize) { + unsafe { asm!("invlpg ($0)" :: "r"(addr) : "memory")} +} + +pub fn flush_all() { + let cr3 = cr3(); + unsafe { cr3_write(cr3); } +} From 36b51236b35d79aa8a4d74bfdc9b2f51ac561aaa Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Mar 2018 14:53:48 +0100 Subject: [PATCH 080/151] with the remap line --- kernel-rs/src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index fd258849..0ac48644 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -103,6 +103,6 @@ fn context() -> &'static mut Context { pub fn init(multiboot_info_addr: usize) { unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; - // memory::remap_the_kernel(frame_allocator(), boot_info()); + memory::remap_the_kernel(frame_allocator(), boot_info()); self::init_screen(); } From 3dfc440d205880114aa693bf48b59f83f50cbadc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 12 Mar 2018 17:48:24 +0100 Subject: [PATCH 081/151] heap allocator in place, no free yet --- kernel-rs/Xargo.toml | 2 + kernel-rs/src/console.rs | 92 +++++++++++++------------- kernel-rs/src/context.rs | 82 ----------------------- kernel-rs/src/keyboard.rs | 15 +++-- kernel-rs/src/lib.rs | 42 ++++++++++-- kernel-rs/src/memory/heap_allocator.rs | 60 +++++++++++++++++ kernel-rs/src/memory/mod.rs | 37 ++++++++++- kernel-rs/src/memory/paging/mod.rs | 60 ++++++++--------- kernel-rs/src/memory/paging/table.rs | 1 - kernel-rs/src/vga/mod.rs | 41 +++++++++--- 10 files changed, 247 insertions(+), 185 deletions(-) create mode 100644 kernel-rs/Xargo.toml create mode 100644 kernel-rs/src/memory/heap_allocator.rs diff --git a/kernel-rs/Xargo.toml b/kernel-rs/Xargo.toml new file mode 100644 index 00000000..91b4c5ff --- /dev/null +++ b/kernel-rs/Xargo.toml @@ -0,0 +1,2 @@ +[target.x86-bluesnow.dependencies] +alloc = {} diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index ea547791..91f046dd 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -3,24 +3,28 @@ extern crate core; use acpi; use cpuio; -use context; -use memory; use x86; use core::char; use vga::*; fn dispatch(command: &str) -> Result <(), &'static str> { match command { - "acpi" => self::acpi_info(), "help" | "h" => self::help(), - "memory" => self::mb2_memory(), - "multiboot" => self::mb2_info(), + + // multiboot + // "memory" => self::mb2_memory(), + // "multiboot" => self::mb2_info(), + // "sections" => self::mb2_sections(), + + // ACPI + "acpi" => self::acpi_info(), "reboot" => self::reboot(), - "sections" => self::mb2_sections(), "shutdown" | "halt" | "q" => self::shutdown(), + + // others "stack" => self::print_stack(), - "test" => self::test(), "regs" => self::regs(), + _ => Err("Command unknown. (h|help for help)"), } } @@ -48,12 +52,6 @@ fn help() -> Result <(), &'static str> { Ok(()) } -fn test() -> Result<(), &'static str> -{ - memory::test_paging(context::frame_allocator()); - Ok(()) -} - /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd @@ -129,49 +127,49 @@ fn print_stack() -> Result <(), &'static str> { Ok(()) } -fn mb2_memory() -> Result <(), &'static str> { - let boot_info = context::boot_info(); +// fn mb2_memory() -> Result <(), &'static str> { +// let boot_info = context::boot_info(); - let memory_map_tag = boot_info.memory_map_tag() - .expect("Memory map tag required"); +// let memory_map_tag = boot_info.memory_map_tag() +// .expect("Memory map tag required"); - println!("memory areas:"); - for area in memory_map_tag.memory_areas() { - println!(" start: 0x{:x}, length: 0x{:x}", - area.start_address(), area.size()); - } - Ok(()) -} +// println!("memory areas:"); +// for area in memory_map_tag.memory_areas() { +// println!(" start: 0x{:x}, length: 0x{:x}", +// area.start_address(), area.size()); +// } +// Ok(()) +// } -fn mb2_sections() -> Result <(), &'static str> { - let boot_info = context::boot_info(); +// fn mb2_sections() -> Result <(), &'static str> { +// let boot_info = context::boot_info(); - let elf_sections_tag = boot_info.elf_sections_tag() - .expect("Elf-sections tag required"); +// let elf_sections_tag = boot_info.elf_sections_tag() +// .expect("Elf-sections tag required"); - println!("kernel sections:"); - for section in elf_sections_tag.sections() { - println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}", - section.name(), section.start_address(), section.size(), section.flags()); - } - Ok(()) -} +// println!("kernel sections:"); +// for section in elf_sections_tag.sections() { +// println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}", +// section.name(), section.start_address(), section.size(), section.flags()); +// } +// Ok(()) +// } -fn mb2_info() -> Result <(), &'static str> { - let boot_info = context::boot_info(); +// fn mb2_info() -> Result <(), &'static str> { +// let boot_info = context::boot_info(); - let command_line_tag = boot_info.command_line_tag() - .expect("Elf-sections tag required"); +// let command_line_tag = boot_info.command_line_tag() +// .expect("Elf-sections tag required"); - let bootloader_tag = boot_info.boot_loader_name_tag() - .expect("Elf-sections tag required"); +// let bootloader_tag = boot_info.boot_loader_name_tag() +// .expect("Elf-sections tag required"); - println!("bootloader: {}", bootloader_tag.name()); - if command_line_tag.command_line().len() != 0 { - println!("command line: {}", command_line_tag.command_line()); - } - Ok(()) -} +// println!("bootloader: {}", bootloader_tag.name()); +// if command_line_tag.command_line().len() != 0 { +// println!("command line: {}", command_line_tag.command_line()); +// } +// Ok(()) +// } pub fn acpi_info() -> Result <(), &'static str> { acpi::info()?; diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs index 0ac48644..81b76627 100644 --- a/kernel-rs/src/context.rs +++ b/kernel-rs/src/context.rs @@ -6,8 +6,6 @@ pub static mut CONTEXT: Option = None; pub struct Context { pub current_term: u8, - pub boot_info: multiboot2::BootInformation, - pub frame_allocator: memory::AreaFrameAllocator, pub vga1: vga::Writer, pub vga2: vga::Writer, } @@ -15,94 +13,14 @@ pub struct Context { impl Context { pub fn new(multiboot_start: usize) -> Context { - let boot_info = unsafe { multiboot2::load(multiboot_start) }; - let multiboot_end = multiboot_start + boot_info.total_size(); - let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); - let memory_map_tag = boot_info.memory_map_tag().unwrap(); - - let kernel_start = elf_sections_tag.sections().map( - |s| s.start_address()) - .min().unwrap() as usize; - let kernel_end = elf_sections_tag.sections().map( - |s| s.start_address() + s.size()) - .max().unwrap() as usize; - - let frame_allocator = memory::AreaFrameAllocator::new( - kernel_start, kernel_end, multiboot_start, - multiboot_end, memory_map_tag.memory_areas()); - - let vga1 = vga::Writer::new(); - let vga2 = vga::Writer::new(); Context { current_term: 0, boot_info, - frame_allocator, vga1, vga2, } } } -pub fn init_screen() { - set_color!(White, Cyan); - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); - set_color!(); - context().vga1.prompt(); - context().vga2.prompt(); - context().vga1.flush(); -} - -pub fn frame_allocator() -> &'static mut memory::AreaFrameAllocator { - &mut context().frame_allocator -} - -pub fn boot_info() -> &'static multiboot2::BootInformation { - &context().boot_info -} - -pub fn switch_term() { - context().current_term = { - if context().current_term == 0 { 1 } - else { 0 } - }; -} - -pub fn current_term() -> &'static mut vga::Writer{ - if context().current_term == 0 { - &mut context().vga1 - } else { - &mut context().vga2 - } -} - -fn context() -> &'static mut Context { - unsafe { - match CONTEXT { - Some(ref mut x) => &mut *x, - None => panic!(), - } - } -} - -pub fn init(multiboot_info_addr: usize) { - unsafe { CONTEXT = Some(Context::new(multiboot_info_addr)) }; - - memory::remap_the_kernel(frame_allocator(), boot_info()); - self::init_screen(); -} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 572f7ac4..c29217a8 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use cpuio; -use context; +use vga; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ @@ -91,19 +91,20 @@ pub fn kbd_callback() { 0x2A | 0x36 => {SHIFT = !is_release}, 0x38 => {ALT = !is_release}, 0x1D => {CTRL = !is_release}, - 0x0F if !is_release => { - context::switch_term(); - context::current_term().flush(); - }, + // terminal switching + // 0x0F if !is_release => { + // context::switch_term(); + // context::current_term().flush(); + // }, 0x0E if !is_release => { - context::current_term().backspace(); + vga::VGA.backspace(); } _ => {} } }, Some(ascii) if !is_release => { let sym = if SHIFT { ascii[1] } else { ascii[0] }; - context::current_term().keypress(sym); + vga::VGA.keypress(sym); }, Some(_) => {}, None =>{}, diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 6ea1a015..2a791bc2 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -5,15 +5,17 @@ #![feature(const_fn)] #![feature(ptr_internals)] #![feature(asm)] +#![feature(alloc)] +#![feature(allocator_api)] +#![feature(global_allocator)] extern crate rlibc; -extern crate multiboot2; //slightly modified fork from official 0.3.2 +extern crate multiboot2; #[macro_use] extern crate bitflags; +#[macro_use] extern crate alloc; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; -/// kernel init and environment -pub mod context; /// PS/2 detection and processing pub mod keyboard; /// simplisitc kernel commands @@ -24,17 +26,37 @@ pub mod cpuio; pub mod acpi; /// physical frame allocator + paging module pub mod memory; -/// a few x86 instruction wrappers +/// a few x86 register and instruction wrappers pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { - context::init(multiboot_info_addr); - // println!("init done!"); // acpi::init().unwrap(); + let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; + enable_write_protect_bit(); + + vga::init(); + memory::init(&boot_info); + + use alloc::boxed::Box; + let mut heap_test = Box::new(42); + *heap_test -= 15; + let heap_test2 = Box::new("Hello"); + println!("{:?} {:?}", heap_test, heap_test2); + + let mut vec_test = vec![1,2,3,4,5,6,7]; + vec_test[3] = 42; + for i in &vec_test { + print!("{} ", i); + } + loop { keyboard::kbd_callback(); } } +fn enable_write_protect_bit() { + unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) }; +} + #[lang = "eh_personality"] #[no_mangle] pub extern fn eh_personality() { @@ -51,3 +73,11 @@ pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32 } +use memory::BumpAllocator; + +pub const HEAP_START: usize = (1 << 22); //first entry of p2 +pub const HEAP_SIZE: usize = 100 * 1024; //100 KiB + +#[global_allocator] +static HEAP_ALLOCATOR: BumpAllocator = BumpAllocator::new(HEAP_START, + HEAP_START + HEAP_SIZE); diff --git a/kernel-rs/src/memory/heap_allocator.rs b/kernel-rs/src/memory/heap_allocator.rs new file mode 100644 index 00000000..d6ed05b6 --- /dev/null +++ b/kernel-rs/src/memory/heap_allocator.rs @@ -0,0 +1,60 @@ +use alloc::heap::{Alloc, AllocErr, Layout}; +use core::sync::atomic::{AtomicUsize, Ordering}; + +#[derive(Debug)] +pub struct BumpAllocator { + heap_start: usize, + heap_end: usize, + next: AtomicUsize, +} + +impl BumpAllocator { + pub const fn new(heap_start: usize, heap_end: usize) -> Self { + Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) } + } +} + +unsafe impl<'a> Alloc for &'a BumpAllocator { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + loop { + // load current state of the `next` field + let current_next = self.next.load(Ordering::Relaxed); + let alloc_start = align_up(current_next, layout.align()); + let alloc_end = alloc_start.saturating_add(layout.size()); + + if alloc_end <= self.heap_end { + // update the `next` pointer if it still has the value `current_next` + let next_now = self.next.compare_and_swap(current_next, alloc_end, + Ordering::Relaxed); + if next_now == current_next { + return Ok(alloc_start as *mut u8); + } + } else { + return Err(AllocErr::Exhausted{ request: layout }) + } + } + } + + unsafe fn dealloc(&mut self, pt: *mut u8, layout: Layout) { + // TODO + // do nothing, leak memory + } +} + +/// Align downwards. Returns the greatest x with alignment `align` +/// so that x <= addr. The alignment must be a power of 2. +pub fn align_down(addr: usize, align: usize) -> usize { + if align.is_power_of_two() { + addr & !(align - 1) + } else if align == 0 { + addr + } else { + panic!("`align` must be a power of 2"); + } +} + +/// Align upwards. Returns the smallest x with alignment `align` +/// so that x >= addr. The alignment must be a power of 2. +pub fn align_up(addr: usize, align: usize) -> usize { + align_down(addr + align - 1, align) +} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 51629c66..76189437 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,12 +1,14 @@ pub const PAGE_SIZE: usize = 4096; mod area_allocator; +mod heap_allocator; mod paging; pub use self::area_allocator::*; -pub use self::paging::test_paging; +pub use self::heap_allocator::*; pub use self::paging::remap_the_kernel; use self::paging::PhysicalAddress; +use multiboot2; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Frame { @@ -57,3 +59,36 @@ impl Iterator for FrameIter { } } } + +/// memory initialisation should only be called once +pub fn init(boot_info: &multiboot2::BootInformation) { + let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); + let memory_map_tag = boot_info.memory_map_tag().unwrap(); + + let kernel_start = elf_sections_tag.sections() + .filter(|s| s.is_allocated()) + .map(|s| s.start_address()) + .min().unwrap(); + + let kernel_end = elf_sections_tag.sections() + .filter(|s| s.is_allocated()) + .map(|s| s.start_address() + s.size()) + .max().unwrap(); + + let mut frame_allocator = self::AreaFrameAllocator::new( + kernel_start as usize, kernel_end as usize, + boot_info.start_address(), boot_info.start_address(), + memory_map_tag.memory_areas()); + + let mut active_table = paging::remap_the_kernel(&mut frame_allocator, + boot_info); + use self::paging::Page; + use {HEAP_START, HEAP_SIZE}; + + let heap_start_page = Page::containing_address(HEAP_START); + let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1); + + for page in Page::range_inclusive(heap_start_page, heap_end_page) { + active_table.map(page, paging::EntryFlags::WRITABLE, &mut frame_allocator); + } +} diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 45a43f81..0e47014a 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -22,7 +22,7 @@ const ENTRY_COUNT: usize = 1024; pub type PhysicalAddress = usize; pub type VirtualAddress = usize; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Page { number: usize, } @@ -46,6 +46,33 @@ impl Page { fn p1_index(&self) -> usize { (self.number >> 0) & 0x3ff } + + pub fn range_inclusive(start: Page, end: Page) -> PageIter { + PageIter { + start, + end, + } + } +} + +#[derive(Clone)] +pub struct PageIter { + start: Page, + end: Page, +} + +impl Iterator for PageIter { + type Item = Page; + + fn next(&mut self) -> Option { + if self.start <= self.end { + let page = self.start; + self.start.number += 1; + Some(page) + } else { + None + } + } } pub struct ActivePageTable { @@ -99,14 +126,12 @@ impl ActivePageTable { let p2_frame = Frame::containing_address(x86::cr3() as usize); - println!("old p2_frame at {}", p2_frame.number); let old_table = InactivePageTable { p2_frame, }; unsafe { let frame = Frame::containing_address(new_table.p2_frame.start_address()); - println!("new p2_frame at {:#x}", new_table.p2_frame.start_address()); x86::cr3_write(frame.start_address()); } @@ -166,9 +191,6 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) assert!(section.start_address() % PAGE_SIZE as u64 == 0, "sections need to be page aligned"); - println!("mapping section at addr: {:#x}, size: {:#x}", - section.start_address(), section.size()); - let flags = EntryFlags::from_elf_section_flags(§ion); let start_frame = Frame::containing_address(section.start_address() as usize); let end_frame = Frame::containing_address(section.end_address() as usize - 1); @@ -192,31 +214,5 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) active_table.unmap(old_p2_page, allocator); - println!("guard page at {:#x}", old_p2_page.start_address()); - println!("cr3 = {:#x}", x86::cr3()); - active_table } - -pub fn test_paging(allocator: &mut A) - where A: FrameAllocator -{ - let mut page_table = unsafe { ActivePageTable::new() }; - - let addr = 0xffff_f000; - let page = Page::containing_address(addr); - let frame = allocator.allocate_frame().expect("no more frames"); - println!("None = {:?}, map to {:?}", - page_table.translate(addr), - frame); - println!("check 0"); - flush!(); - page_table.map_to(page, frame, EntryFlags::empty(), allocator); - println!("check 1"); - flush!(); - println!("Some = {:?}", page_table.translate(addr)); - flush!(); - println!("next free frame: {:?}", allocator.allocate_frame()); - flush!(); - -} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 2a9e9a86..da35e011 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -51,7 +51,6 @@ impl Table where L: HierarchicalLevel where A: FrameAllocator { if self.next_table(index).is_none() { - println!("index={} flags={:#b}", index, self[index].flags()); assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 0a09fe1b..b773b4ff 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -2,10 +2,11 @@ pub mod color; pub use self::color::{Color, ColorCode}; -use context; use cpuio; use console; +pub static mut VGA: Writer = self::Writer::new(); + #[derive(Debug, Clone, Copy)] #[repr(C)] struct ScreenChar { @@ -25,21 +26,21 @@ macro_rules! println { } macro_rules! flush { - () => ($crate::context::current_term().flush()); + () => (unsafe { $crate::vga::VGA.flush() }); } macro_rules! set_color { - () => ($crate::context::current_term().color_code = - $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)); - ($fg:ident) => ($crate::context::current_term().color_code = - $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)); - ($fg:ident, $bg:ident) => ($crate::context::current_term().color_code = - $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)); + () => (unsafe { $crate::vga::VGA.color_code = + $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} ); + ($fg:ident) => (unsafe { $crate::vga::VGA.color_code = + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} ); + ($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code = + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} ); } pub fn print(args: fmt::Arguments) { use core::fmt::Write; - context::current_term().write_fmt(args).unwrap(); + unsafe { self::VGA.write_fmt(args).unwrap(); } } extern crate core; @@ -195,3 +196,25 @@ impl fmt::Write for Writer { Ok(()) } } + +pub fn init() { + set_color!(White, Cyan); + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); + set_color!(); + unsafe { VGA.prompt(); } + unsafe { VGA.flush(); } +} From 0c3589655f82abe170a6cde36b3a03945b6070bb Mon Sep 17 00:00:00 2001 From: wescande Date: Tue, 13 Mar 2018 13:30:00 +0100 Subject: [PATCH 082/151] scroll is cleaning color --- kernel-rs/src/vga/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index b773b4ff..45227206 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -180,6 +180,7 @@ impl Writer { for col in 0..BUFFER_COLS/2 { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2) + 1] = 0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; From 99f0ec0b7d0e316a321337910d1abcdc1285a91a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Mar 2018 15:42:30 +0100 Subject: [PATCH 083/151] stuff --- kernel-rs/src/lib.rs | 2 +- kernel-rs/src/memory/paging/mod.rs | 8 ++------ kernel-rs/src/memory/paging/temporary_page.rs | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 2a791bc2..43d10e56 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -35,8 +35,8 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; enable_write_protect_bit(); - vga::init(); memory::init(&boot_info); + vga::init(); use alloc::boxed::Box; let mut heap_test = Box::new(42); diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 0e47014a..636f235d 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -118,7 +118,7 @@ impl ActivePageTable { // execute f in the new context f(self); - // TODO restore recursive mapping to original p2 table + // restore recursive mapping to original p2 table p2_table[1023].set(backup, EntryFlags::PRESENT | EntryFlags::WRITABLE); } @@ -207,12 +207,8 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) }); let old_table = active_table.switch(new_table); - - let old_p2_page = Page::containing_address( - old_table.p2_frame.start_address() - ); + let old_p2_page = Page::containing_address(old_table.p2_frame.start_address()); active_table.unmap(old_p2_page, allocator); - active_table } diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index 77ef6440..e098fef3 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -74,6 +74,6 @@ impl FrameAllocator for TinyAllocator { return; } } - panic!("Tiny allcoator can only hold 1 frame."); + panic!("Tiny allocator can only hold 1 frame."); } } From 0b38f701edd1aadd53f8e4916d8b15deee5baacc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 13 Mar 2018 20:06:25 +0100 Subject: [PATCH 084/151] WIP --- kernel-rs/.gitmodules | 3 + kernel-rs/Cargo.toml | 1 + kernel-rs/src/console.rs | 9 +- kernel-rs/src/lib.rs | 14 +-- kernel-rs/src/memory/area_allocator.rs | 38 ++++---- kernel-rs/src/memory/mod.rs | 42 ++------ kernel-rs/src/memory/paging/entry.rs | 66 ------------- kernel-rs/src/memory/paging/mapper.rs | 64 ++++++------ kernel-rs/src/memory/paging/mod.rs | 91 +++++------------ kernel-rs/src/memory/paging/table.rs | 97 ++++--------------- kernel-rs/src/memory/paging/temporary_page.rs | 27 +++--- kernel-rs/src/x86/mod.rs | 29 ------ kernel-rs/src/x86/structures/idt.rs | 4 + kernel-rs/src/x86/structures/mod.rs | 3 + kernel-rs/src/x86/tlb.rs | 10 -- kernel-rs/x86 | 1 + 16 files changed, 133 insertions(+), 366 deletions(-) delete mode 100644 kernel-rs/src/memory/paging/entry.rs delete mode 100644 kernel-rs/src/x86/mod.rs create mode 100644 kernel-rs/src/x86/structures/idt.rs create mode 100644 kernel-rs/src/x86/structures/mod.rs delete mode 100644 kernel-rs/src/x86/tlb.rs create mode 160000 kernel-rs/x86 diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules index 7612dca4..820f6043 100644 --- a/kernel-rs/.gitmodules +++ b/kernel-rs/.gitmodules @@ -1,3 +1,6 @@ [submodule "multiboot2-elf64"] path = multiboot2-elf64 url = git@github.com:jzck/multiboot2-elf64.git +[submodule "x86"] + path = x86 + url = https://github.com/jzck/x86.git diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 68a70731..558231c0 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["staticlib"] rlibc = "1.0" bitflags = "1.0.1" multiboot2 = { path = "multiboot2-elf64" } +x86 = { path = "x86" } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 91f046dd..fa9f34ca 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -3,7 +3,6 @@ extern crate core; use acpi; use cpuio; -use x86; use core::char; use vga::*; @@ -177,9 +176,11 @@ pub fn acpi_info() -> Result <(), &'static str> { } pub fn regs() -> Result <(), &'static str> { - println!("cr0={:#b}", x86::cr0()); - println!("cr3={:#x}", x86::cr3()); - println!("cr4={:#b}", x86::cr4()); + use x86::registers::control::*; + println!("cr0={:#b}", Cr0::read()); + println!("cr3={:#x}", Cr3::read()); + // TODO implement cr4 flags in `x86` module + // println!("cr4={:#b}", Cr4::read()); Ok(()) } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 43d10e56..1303e417 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -11,8 +11,9 @@ extern crate rlibc; extern crate multiboot2; -#[macro_use] extern crate bitflags; +// #[macro_use] extern crate bitflags; #[macro_use] extern crate alloc; +extern crate x86; /// 80x25 screen and simplistic terminal driver #[macro_use] pub mod vga; @@ -20,14 +21,14 @@ extern crate multiboot2; pub mod keyboard; /// simplisitc kernel commands pub mod console; -/// wrappers around the x86-family I/O instructions. +/// rust wrappers around cpu I/O instructions. pub mod cpuio; /// ACPI self-content module pub mod acpi; -/// physical frame allocator + paging module +/// physical frame allocator + paging module + heap allocator pub mod memory; -/// a few x86 register and instruction wrappers -pub mod x86; +/// x86 interruptions +// pub mod interrupts; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { @@ -54,7 +55,8 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { } fn enable_write_protect_bit() { - unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) }; + use x86::registers::control::{Cr0, Cr0Flags}; + unsafe { Cr0::write(Cr0::read() | Cr0Flags::WRITE_PROTECT) }; } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 09304cb6..011f6cb4 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -2,13 +2,13 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; pub struct AreaFrameAllocator { - next_free_frame: Frame, + next_free_frame: PhysFrame, current_area: Option<&'static MemoryArea>, areas: MemoryAreaIter, - kernel_start: Frame, - kernel_end: Frame, - multiboot_start: Frame, - multiboot_end: Frame, + kernel_start: PhysFrame, + kernel_end: PhysFrame, + multiboot_start: PhysFrame, + multiboot_end: PhysFrame, } impl AreaFrameAllocator { @@ -16,13 +16,13 @@ impl AreaFrameAllocator { multiboot_start: usize, multiboot_end: usize, memory_areas: MemoryAreaIter) -> AreaFrameAllocator { let mut allocator = AreaFrameAllocator { - next_free_frame: Frame::containing_address(0), + next_free_frame: PhysFrame::containing_address(0), current_area: None, areas: memory_areas, - kernel_start: Frame::containing_address(kernel_start), - kernel_end: Frame::containing_address(kernel_end), - multiboot_start: Frame::containing_address(multiboot_start), - multiboot_end: Frame::containing_address(multiboot_end), + kernel_start: PhysFrame::containing_address(kernel_start), + kernel_end: PhysFrame::containing_address(kernel_end), + multiboot_start: PhysFrame::containing_address(multiboot_start), + multiboot_end: PhysFrame::containing_address(multiboot_end), }; allocator.choose_next_area(); allocator @@ -31,11 +31,11 @@ impl AreaFrameAllocator { fn choose_next_area(&mut self) { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { - Frame::containing_address(area.end_address()) >= self.next_free_frame + PhysFrame::containing_address(area.end_address()) >= self.next_free_frame }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = Frame::containing_address(area.start_address()); + let start_frame = PhysFrame::containing_address(area.start_address()); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -44,21 +44,21 @@ impl AreaFrameAllocator { } impl FrameAllocator for AreaFrameAllocator { - fn allocate_frame(&mut self) -> Option { - if let Some(area) = self.current_area { - let frame = Frame { number: self.next_free_frame.number }; - let current_area_last_frame = Frame::containing_address(area.end_address()); + fn allocate_frame(&mut self) -> Option { + if let Some(area) = self.current_arPhysea { + let frame = PhysFrame { number: self.next_free_frame.number }; + let current_area_last_frame = PhysFrame::containing_address(area.end_address()); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); } else if frame >= self.kernel_start && frame <= self.kernel_end { // frame used by kernel - self.next_free_frame = Frame { + self.next_free_frame = PhysFrame { number: self.kernel_end.number + 1, } } else if frame >= self.multiboot_start && frame <= self.multiboot_end { // frame used by multiboot - self.next_free_frame = Frame { + self.next_free_frame = PhysFrame { number: self.multiboot_end.number + 1, } } else { @@ -72,7 +72,7 @@ impl FrameAllocator for AreaFrameAllocator { } } - fn deallocate_frame(&mut self, frame: Frame) { + fn deallocate_frame(&mut self, frame: PhysFrame) { unimplemented!(); } } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 76189437..89568f0b 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -7,49 +7,24 @@ mod paging; pub use self::area_allocator::*; pub use self::heap_allocator::*; pub use self::paging::remap_the_kernel; -use self::paging::PhysicalAddress; use multiboot2; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Frame { - number: usize, -} - -impl Frame { - fn containing_address(address: usize) -> Frame { - Frame{ number: address / PAGE_SIZE } - } - - fn start_address(&self) -> PhysicalAddress { - self.number * PAGE_SIZE - } - - fn clone(&self) ->Frame { - Frame { number: self.number } - } - - fn range_inclusive(start: Frame, end: Frame) -> FrameIter { - FrameIter { - start, - end, - } - } -} +use x86::structures::paging::*; pub trait FrameAllocator { - fn allocate_frame(&mut self) -> Option; - fn deallocate_frame(&mut self, frame: Frame); + fn allocate_frame(&mut self) -> Option; + fn deallocate_frame(&mut self, frame: PhysFrame); } struct FrameIter { - start: Frame, - end: Frame, + start: PhysFrame, + end: PhysFrame, } impl Iterator for FrameIter { - type Item = Frame; + type Item = PhysFrame; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.start <= self.end { let frame = self.start.clone(); self.start.number += 1; @@ -82,13 +57,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let mut active_table = paging::remap_the_kernel(&mut frame_allocator, boot_info); - use self::paging::Page; use {HEAP_START, HEAP_SIZE}; let heap_start_page = Page::containing_address(HEAP_START); let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1); for page in Page::range_inclusive(heap_start_page, heap_end_page) { - active_table.map(page, paging::EntryFlags::WRITABLE, &mut frame_allocator); + active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } } diff --git a/kernel-rs/src/memory/paging/entry.rs b/kernel-rs/src/memory/paging/entry.rs deleted file mode 100644 index 26edb9c1..00000000 --- a/kernel-rs/src/memory/paging/entry.rs +++ /dev/null @@ -1,66 +0,0 @@ -use memory::Frame; - -pub struct Entry(u32); -use multiboot2::ElfSection; - -impl Entry { - pub fn is_unused(&self) -> bool { - self.0 == 0 - } - - pub fn set_unused(&mut self) { - self.0 = 0; - } - - pub fn flags(&self) -> EntryFlags { - EntryFlags::from_bits_truncate(self.0) - } - - pub fn pointed_frame(&self) -> Option { - if self.flags().contains(EntryFlags::PRESENT) { - Some(Frame::containing_address( - self.0 as usize & 0xffff_f000)) - } else { - None - } - } - - pub fn set(&mut self, frame: Frame, flags: EntryFlags) { - assert!(frame.start_address() & !0xffff_f000 == 0); - self.0 = (frame.start_address() as u32) | flags.bits(); - } -} - -bitflags! { - pub struct EntryFlags: u32 { - const PRESENT = 1 << 0; - const WRITABLE = 1 << 1; - const USER_ACCESSIBLE = 1 << 2; - const WRITE_THROUGH = 1 << 3; - const NO_CACHE = 1 << 4; - const ACCESSED = 1 << 5; - const DIRTY = 1 << 6; - const HUGE_PAGE = 1 << 7; - const GLOBAL = 1 << 8; - // LONG MODE - // const NO_EXECUTE = 1 << 63; - } -} - -impl EntryFlags { - pub fn from_elf_section_flags(section: &ElfSection) -> EntryFlags { - use multiboot2::ElfSectionFlags; - - let mut flags = EntryFlags::empty(); - if section.flags().contains(ElfSectionFlags::ALLOCATED) { - flags = flags | EntryFlags::PRESENT; - } - if section.flags().contains(ElfSectionFlags::WRITABLE) { - flags = flags | EntryFlags::WRITABLE; - } - // if !section.flags().contains(ElfSectionFlags::EXECUTABLE) { - // flags = flags | EntryFlags::NO_EXECUTE; - // } - flags - } -} diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 93d5be86..27800c23 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -1,61 +1,52 @@ -use super::{VirtualAddress, PhysicalAddress, Page, ENTRY_COUNT}; -use super::entry::*; -use super::table::{self, Table, Level2}; -use memory::{PAGE_SIZE, Frame, FrameAllocator}; +use memory::{PAGE_SIZE, FrameAllocator}; use core::ptr::Unique; -use x86; +use x86::structures::paging::*; +use x86::instructions::tlb; +use x86::*; +// +// virtual address of recursively mapped P2 +// for protected mode non PAE +// https://wiki.osdev.org/Page_Tables +pub const P2: *mut PageTable = 0xffff_f000 as *mut _; pub struct Mapper { - p2: Unique>, + p2: Unique, } impl Mapper { pub unsafe fn new() -> Mapper { Mapper { - p2: Unique::new_unchecked(table::P2), + p2: Unique::new_unchecked(self::P2), } } // the remaining mapping methods, all public - pub fn p2(&self) -> &Table { + pub fn p2(&self) -> &PageTable { unsafe { self.p2.as_ref() } } - pub fn p2_mut(&mut self) -> &mut Table { + pub fn p2_mut(&mut self) -> &mut PageTable { unsafe { self.p2.as_mut() } } - pub fn translate(&self, virtual_address: VirtualAddress) -> Option + pub fn translate(&self, virtual_address: VirtAddr) -> Option { - let offset = virtual_address % PAGE_SIZE; + let offset = virtual_address.as_u32() % PAGE_SIZE as u32; self.translate_page(Page::containing_address(virtual_address)) - .map(|frame| frame.number * PAGE_SIZE + offset) + .map(|frame| frame.start_address() + offset) + } - pub fn translate_page(&self, page: Page) -> Option { + pub fn translate_page(&self, page: Page) -> Option { - let p1 = self.p2().next_table(page.p2_index()); + let p1 = self.p2()[page.p2_index()].points_to() + .and_then(|paddr| PageTable::from(paddr)); - let huge_page = || { - let p2_entry = &self.p2()[page.p2_index()]; - if let Some(start_frame) = p2_entry.pointed_frame() { - if p2_entry.flags().contains(EntryFlags::HUGE_PAGE) { - // 4KiB alignment check - assert!(start_frame.number % ENTRY_COUNT == 0); - return Some(Frame { - number: start_frame.number + page.p1_index() - }); - } - } - None - }; - - p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + p1.and_then() } - pub fn map_to(&mut self, page: Page, frame: Frame, flags: EntryFlags, + pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { @@ -63,20 +54,21 @@ impl Mapper { let p1 = p2.next_table_create(page.p2_index(), allocator); assert!(p1[page.p1_index()].is_unused()); - p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT); + p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); } - pub fn map(&mut self, page: Page, flags: EntryFlags, allocator: &mut A) + pub fn map(&mut self, page: Page, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { let frame = allocator.allocate_frame().expect("out of memory"); self.map_to(page, frame, flags, allocator) } - pub fn identity_map(&mut self, frame: Frame, flags: EntryFlags, allocator: &mut A) + pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator { - let page = Page::containing_address(frame.start_address()); + let virt_addr = VirtAddr::new(frame.start_address().as_u32()); + let page = Page::containing_address(virt_addr); self.map_to(page, frame, flags, allocator); } @@ -90,7 +82,7 @@ impl Mapper { .expect("mapping code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); - x86::tlb::flush(page.start_address()); + tlb::flush(page.start_address()); // TODO // allocator.deallocate_frame(frame); } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 636f235d..c5363e1e 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,59 +1,16 @@ #![allow(dead_code)] -mod entry; -mod table; +// mod table; mod temporary_page; mod mapper; -use memory::PAGE_SIZE; use memory::*; use self::mapper::Mapper; use self::temporary_page::TemporaryPage; use core::ops::{Deref, DerefMut}; use multiboot2::BootInformation; use x86; - -pub use self::entry::*; -pub use self::table::*; - -// x86 non PAE has 1024 entries per table -const ENTRY_COUNT: usize = 1024; - -pub type PhysicalAddress = usize; -pub type VirtualAddress = usize; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Page { - number: usize, -} - -impl Page { - pub fn containing_address(address: VirtualAddress) -> Page { - // assert!(address < 0x0000_8000_0000_0000 || - // address >= 0xffff_8000_0000_0000, - // "invalid addres: 0x{:x}", address); - Page { number: address / PAGE_SIZE } - } - - fn start_address(&self) -> usize { - self.number * PAGE_SIZE - } - - fn p2_index(&self) -> usize { - (self.number >> 10) & 0x3ff - } - - fn p1_index(&self) -> usize { - (self.number >> 0) & 0x3ff - } - - pub fn range_inclusive(start: Page, end: Page) -> PageIter { - PageIter { - start, - end, - } - } -} +use x86::registers::control::Cr3; #[derive(Clone)] pub struct PageIter { @@ -106,33 +63,33 @@ impl ActivePageTable { f: F) where F: FnOnce(&mut Mapper) { - let backup = Frame::containing_address(x86::cr3()); + let (cr3_back, cr3flags_back) = Cr3::read(); // map temp page to current p2 - let p2_table = temporary_page.map_table_frame(backup.clone(), self); + let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); // overwrite recursive map - self.p2_mut()[1023].set(table.p2_frame.clone(), EntryFlags::PRESENT | EntryFlags::WRITABLE); - x86::tlb::flush_all(); + self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE); + x86::instructions::tlb::flush_all(); // execute f in the new context f(self); // restore recursive mapping to original p2 table - p2_table[1023].set(backup, EntryFlags::PRESENT | EntryFlags::WRITABLE); + p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - let p2_frame = Frame::containing_address(x86::cr3() as usize); + let p2_frame = PhysFrame::containing_address(Cr3::read() as usize); let old_table = InactivePageTable { p2_frame, }; unsafe { - let frame = Frame::containing_address(new_table.p2_frame.start_address()); - x86::cr3_write(frame.start_address()); + let frame = PhysFrame::containing_address(new_table.p2_frame.start_address()); + Cr3::write(frame.start_address()); } old_table @@ -140,11 +97,11 @@ impl ActivePageTable { } pub struct InactivePageTable { - p2_frame: Frame, + p2_frame: PhysFrame, } impl InactivePageTable { - pub fn new(frame: Frame, + pub fn new(frame: PhysFrame, active_table: &mut ActivePageTable, temporary_page: &mut TemporaryPage, ) -> InactivePageTable { @@ -154,7 +111,7 @@ impl InactivePageTable { table.zero(); // set up recursive mapping for the table - table[1023].set(frame.clone(), EntryFlags::PRESENT | EntryFlags:: WRITABLE) + table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } temporary_page.unmap(active_table); InactivePageTable { p2_frame: frame } @@ -176,33 +133,31 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) active_table.with(&mut new_table, &mut temporary_page, |mapper| { // identity map the VGA text buffer - let vga_buffer_frame = Frame::containing_address(0xb8000); - mapper.identity_map(vga_buffer_frame, EntryFlags::WRITABLE, allocator); + let vga_buffer_frame = PhysFrame::containing_address(0xb8000); + mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE, allocator); let elf_sections_tag = boot_info.elf_sections_tag() .expect("Memory map tag required"); for section in elf_sections_tag.sections() { - use self::entry::EntryFlags; - if !section.is_allocated() { continue; } assert!(section.start_address() % PAGE_SIZE as u64 == 0, "sections need to be page aligned"); - let flags = EntryFlags::from_elf_section_flags(§ion); - let start_frame = Frame::containing_address(section.start_address() as usize); - let end_frame = Frame::containing_address(section.end_address() as usize - 1); - for frame in Frame::range_inclusive(start_frame, end_frame) { + let flags = PageTableFlags::from_elf_section_flags(§ion); + let start_frame = PhysFrame::containing_address(section.start_address() as usize); + let end_frame = PhysFrame::containing_address(section.end_address() as usize - 1); + for frame in PhysFrame::range_inclusive(start_frame, end_frame) { mapper.identity_map(frame, flags, allocator); } } - let multiboot_start = Frame::containing_address(boot_info.start_address()); - let multiboot_end = Frame::containing_address(boot_info.end_address() - 1); - for frame in Frame::range_inclusive(multiboot_start, multiboot_end) { - mapper.identity_map(frame, EntryFlags::PRESENT, allocator); + let multiboot_start = PhysFrame::containing_address(boot_info.start_address()); + let multiboot_end = PhysFrame::containing_address(boot_info.end_address() - 1); + for frame in PhysFrame::range_inclusive(multiboot_start, multiboot_end) { + mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index da35e011..d7aa7554 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,95 +1,32 @@ use memory::*; -use memory::paging::*; +use x86::structures::paging::*; -use core::ops::{Index, IndexMut}; -use core::marker::PhantomData; -// virtual address of P2 because its recursively mapped -// see protected mode Non-PAE -// https://wiki.osdev.org/Page_Tables -pub const P2: *mut Table = 0xffff_f000 as *mut _; - -pub struct Table { - entries: [Entry; ENTRY_COUNT], - level: PhantomData, -} - -impl Table where L: TableLevel +pub trait TableNext + where A: FrameAllocator { - pub fn zero(&mut self) { - for entry in self.entries.iter_mut() { - entry.set_unused(); - } - } -} - -impl Table where L: HierarchicalLevel -{ - fn next_table_address(&self, index: usize) -> Option { - let entry_flags = self[index].flags(); - if entry_flags.contains(EntryFlags::PRESENT) && !entry_flags.contains(EntryFlags::HUGE_PAGE) { - let table_address = self as *const _ as usize; - Some((table_address << 10) | (index << 12)) - } else { - None - } - } - - pub fn next_table(&self, index: usize) -> Option<&Table> { - self.next_table_address(index) - .map(|address| unsafe { &*(address as *const _) }) - } - - pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table> { - self.next_table_address(index) - .map(|address| unsafe { &mut *(address as *mut _) }) - } - - pub fn next_table_create(&mut self, + fn next_table_address(&self, index: usize) -> Option; + fn next_table(&self, index: usize) -> Option<&PageTable>; + fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; + fn next_table_create(&mut self, index: usize, - allocator: &mut A) -> &mut Table + allocator: &mut A) -> &mut PageTable; +} + +impl TableNext<> for PageTable +{ + fn next_table_create(&mut self, + index: usize, + allocator: &mut A) -> &mut PageTable where A: FrameAllocator { if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE), + assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE), "mapping code does not support huge pages"); let frame = allocator.allocate_frame().expect("no frames available"); - self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE); + self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); self.next_table_mut(index).expect("next_table_mut gave None").zero() } self.next_table_mut(index).expect("no next table 2") } } - -impl Index for Table where L: TableLevel -{ - type Output = Entry; - - fn index(&self, index: usize) -> &Entry { - &self.entries[index] - } -} - -impl IndexMut for Table where L: TableLevel -{ - fn index_mut(&mut self, index: usize) -> &mut Entry { - &mut self.entries[index] - } -} - -pub trait TableLevel {} - -pub enum Level4 {} -pub enum Level3 {} -pub enum Level2 {} -pub enum Level1 {} - -impl TableLevel for Level4 {} -impl TableLevel for Level3 {} -impl TableLevel for Level2 {} -impl TableLevel for Level1 {} - -pub trait HierarchicalLevel: TableLevel { type NextLevel: TableLevel; } -impl HierarchicalLevel for Level4 { type NextLevel = Level3; } -impl HierarchicalLevel for Level3 { type NextLevel = Level2; } -impl HierarchicalLevel for Level2 { type NextLevel = Level1; } diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index e098fef3..caab2d6a 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -1,6 +1,7 @@ -use super::{Page, ActivePageTable, VirtualAddress}; -use super::table::{Table, Level1}; -use memory::{Frame, FrameAllocator}; +use super::ActivePageTable; +use memory::{FrameAllocator}; +use x86::*; +use x86::structures::paging::*; pub struct TemporaryPage { page: Page, @@ -19,14 +20,12 @@ impl TemporaryPage { /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. - pub fn map(&mut self, frame: Frame, active_table: &mut ActivePageTable) - -> VirtualAddress + pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) + -> VirtAddr { - use super::entry::EntryFlags; - assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); - active_table.map_to(self.page, frame, EntryFlags::WRITABLE, &mut self.allocator); + active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); self.page.start_address() } @@ -38,14 +37,14 @@ impl TemporaryPage { /// Maps the temporary page to the given page table frame in the active /// table. Returns a reference to the now mapped table. pub fn map_table_frame(&mut self, - frame: Frame, + frame: PhysFrame, active_table: &mut ActivePageTable) - -> &mut Table { - unsafe { &mut *(self.map(frame, active_table) as *mut Table) } + -> &mut PageTable { + unsafe { &mut *(self.map(frame, active_table) as *mut PageTable) } } } -struct TinyAllocator([Option; 1]); +struct TinyAllocator([Option; 1]); impl TinyAllocator { fn new(allocator: &mut A) -> TinyAllocator @@ -58,7 +57,7 @@ impl TinyAllocator { } impl FrameAllocator for TinyAllocator { - fn allocate_frame(&mut self) -> Option { + fn allocate_frame(&mut self) -> Option { for frame_option in &mut self.0 { if frame_option.is_some() { return frame_option.take(); @@ -67,7 +66,7 @@ impl FrameAllocator for TinyAllocator { None } - fn deallocate_frame(&mut self, frame: Frame) { + fn deallocate_frame(&mut self, frame: PhysFrame) { for frame_option in &mut self.0 { if frame_option.is_none() { *frame_option = Some(frame); diff --git a/kernel-rs/src/x86/mod.rs b/kernel-rs/src/x86/mod.rs deleted file mode 100644 index 7d9cf902..00000000 --- a/kernel-rs/src/x86/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! x86 (32 bit) only - -pub mod tlb; - -pub unsafe fn cr0_write(val: usize) { - asm!("mov $0, %cr0" :: "r"(val) : "memory"); -} - -pub fn cr0() -> usize { - let ret: usize; - unsafe { asm!("mov %cr0, $0" : "=r" (ret)) }; - ret -} - -pub fn cr3() -> usize { - let ret: usize; - unsafe { asm!("mov %cr3, $0" : "=r" (ret)) }; - ret -} - -pub fn cr4() -> usize { - let ret: usize; - unsafe { asm!("mov %cr4, $0" : "=r" (ret)) }; - ret -} - -pub unsafe fn cr3_write(val: usize) { - asm!("mov $0, %cr3" :: "r" (val) : "memory"); -} diff --git a/kernel-rs/src/x86/structures/idt.rs b/kernel-rs/src/x86/structures/idt.rs new file mode 100644 index 00000000..c8129caf --- /dev/null +++ b/kernel-rs/src/x86/structures/idt.rs @@ -0,0 +1,4 @@ +#[repr(C)] +pub struct Idt { + +} diff --git a/kernel-rs/src/x86/structures/mod.rs b/kernel-rs/src/x86/structures/mod.rs new file mode 100644 index 00000000..b00763f0 --- /dev/null +++ b/kernel-rs/src/x86/structures/mod.rs @@ -0,0 +1,3 @@ +pub mod idt; +// pub mod gdt; +// pub mod tss; diff --git a/kernel-rs/src/x86/tlb.rs b/kernel-rs/src/x86/tlb.rs deleted file mode 100644 index 1890ebaa..00000000 --- a/kernel-rs/src/x86/tlb.rs +++ /dev/null @@ -1,10 +0,0 @@ -use super::*; - -pub fn flush(addr: usize) { - unsafe { asm!("invlpg ($0)" :: "r"(addr) : "memory")} -} - -pub fn flush_all() { - let cr3 = cr3(); - unsafe { cr3_write(cr3); } -} diff --git a/kernel-rs/x86 b/kernel-rs/x86 new file mode 160000 index 00000000..dc9eb5ce --- /dev/null +++ b/kernel-rs/x86 @@ -0,0 +1 @@ +Subproject commit dc9eb5ceb8981848d95e0ddd7040fb86ec9999e3 From 8cf793260c5668281d0bda4505baaa33507495ab Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 14 Mar 2018 18:59:17 +0100 Subject: [PATCH 085/151] it compiles now with the new x86 lib, triple faults when setting temp page to zero though --- kernel-rs/src/console.rs | 2 +- kernel-rs/src/memory/area_allocator.rs | 25 ++-- kernel-rs/src/memory/mod.rs | 29 +---- kernel-rs/src/memory/paging/mapper.rs | 23 +++- kernel-rs/src/memory/paging/mod.rs | 110 ++++++++++-------- kernel-rs/src/memory/paging/table.rs | 44 +++++-- kernel-rs/src/memory/paging/temporary_page.rs | 9 +- kernel-rs/x86 | 2 +- 8 files changed, 141 insertions(+), 103 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index fa9f34ca..6ababe05 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -178,7 +178,7 @@ pub fn acpi_info() -> Result <(), &'static str> { pub fn regs() -> Result <(), &'static str> { use x86::registers::control::*; println!("cr0={:#b}", Cr0::read()); - println!("cr3={:#x}", Cr3::read()); + println!("cr3={:?}", Cr3::read()); // TODO implement cr4 flags in `x86` module // println!("cr4={:#b}", Cr4::read()); Ok(()) diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/area_allocator.rs index 011f6cb4..6a24bb94 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/area_allocator.rs @@ -1,5 +1,6 @@ use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; +use x86::*; pub struct AreaFrameAllocator { next_free_frame: PhysFrame, @@ -16,13 +17,17 @@ impl AreaFrameAllocator { multiboot_start: usize, multiboot_end: usize, memory_areas: MemoryAreaIter) -> AreaFrameAllocator { let mut allocator = AreaFrameAllocator { - next_free_frame: PhysFrame::containing_address(0), + next_free_frame: PhysFrame { number: 0 }, current_area: None, areas: memory_areas, - kernel_start: PhysFrame::containing_address(kernel_start), - kernel_end: PhysFrame::containing_address(kernel_end), - multiboot_start: PhysFrame::containing_address(multiboot_start), - multiboot_end: PhysFrame::containing_address(multiboot_end), + kernel_start: PhysFrame::containing_address( + PhysAddr::new(kernel_start as u32)), + kernel_end: PhysFrame::containing_address( + PhysAddr::new(kernel_end as u32)), + multiboot_start: PhysFrame::containing_address( + PhysAddr::new(multiboot_start as u32)), + multiboot_end: PhysFrame::containing_address( + PhysAddr::new(multiboot_end as u32)), }; allocator.choose_next_area(); allocator @@ -31,11 +36,12 @@ impl AreaFrameAllocator { fn choose_next_area(&mut self) { // get next area with free frames self.current_area = self.areas.clone().filter(|area| { - PhysFrame::containing_address(area.end_address()) >= self.next_free_frame + area.end_address() >= self.next_free_frame.start_address().as_u32() as usize }).min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = PhysFrame::containing_address(area.start_address()); + let start_frame = PhysFrame::containing_address( + PhysAddr::new(area.start_address() as u32)); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -45,9 +51,10 @@ impl AreaFrameAllocator { impl FrameAllocator for AreaFrameAllocator { fn allocate_frame(&mut self) -> Option { - if let Some(area) = self.current_arPhysea { + if let Some(area) = self.current_area { let frame = PhysFrame { number: self.next_free_frame.number }; - let current_area_last_frame = PhysFrame::containing_address(area.end_address()); + let current_area_last_frame = PhysFrame::containing_address( + PhysAddr::new(area.end_address() as u32)); if frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 89568f0b..c2a6c244 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -8,7 +8,7 @@ pub use self::area_allocator::*; pub use self::heap_allocator::*; pub use self::paging::remap_the_kernel; use multiboot2; - +use x86::*; use x86::structures::paging::*; pub trait FrameAllocator { @@ -16,25 +16,6 @@ pub trait FrameAllocator { fn deallocate_frame(&mut self, frame: PhysFrame); } -struct FrameIter { - start: PhysFrame, - end: PhysFrame, -} - -impl Iterator for FrameIter { - type Item = PhysFrame; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let frame = self.start.clone(); - self.start.number += 1; - Some(frame) - } else { - None - } - } -} - /// memory initialisation should only be called once pub fn init(boot_info: &multiboot2::BootInformation) { let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); @@ -59,10 +40,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) { boot_info); use {HEAP_START, HEAP_SIZE}; - let heap_start_page = Page::containing_address(HEAP_START); - let heap_end_page = Page::containing_address(HEAP_START + HEAP_SIZE - 1); + let heap_start_page = Page::containing_address( + VirtAddr::new(HEAP_START as u32)); + let heap_end_page = Page::containing_address( + VirtAddr::new(HEAP_START as u32 + HEAP_SIZE as u32 - 1)); - for page in Page::range_inclusive(heap_start_page, heap_end_page) { + for page in heap_start_page..heap_end_page { active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } } diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 27800c23..d8be6889 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -3,7 +3,8 @@ use core::ptr::Unique; use x86::structures::paging::*; use x86::instructions::tlb; use x86::*; -// +use super::paging::table::RecTable; + // virtual address of recursively mapped P2 // for protected mode non PAE // https://wiki.osdev.org/Page_Tables @@ -29,6 +30,7 @@ impl Mapper { unsafe { self.p2.as_mut() } } + /// virtual addr to physical addr translation pub fn translate(&self, virtual_address: VirtAddr) -> Option { let offset = virtual_address.as_u32() % PAGE_SIZE as u32; @@ -37,15 +39,26 @@ impl Mapper { } + /// virtual page to physical frame translation pub fn translate_page(&self, page: Page) -> Option { + let p1 = self.p2().next_table(page.p2_index()); - let p1 = self.p2()[page.p2_index()].points_to() - .and_then(|paddr| PageTable::from(paddr)); + let huge_page = || { + let p2_entry = &self.p2()[page.p2_index()]; + if let Some(start_frame) = p2_entry.pointed_frame() { + if p2_entry.flags().contains(PageTableFlags::HUGE_PAGE) { + // TODO 4MiB alignment check + return Some(start_frame + u32::from(page.p1_index())); + } + } + None + }; - p1.and_then() + p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) + .or_else(huge_page) } - + /// map a virtual page to a physical frame in the page tables pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) where A: FrameAllocator diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index c5363e1e..39785015 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -// mod table; +mod table; mod temporary_page; mod mapper; @@ -9,28 +9,9 @@ use self::mapper::Mapper; use self::temporary_page::TemporaryPage; use core::ops::{Deref, DerefMut}; use multiboot2::BootInformation; -use x86; +use x86::*; use x86::registers::control::Cr3; - -#[derive(Clone)] -pub struct PageIter { - start: Page, - end: Page, -} - -impl Iterator for PageIter { - type Item = Page; - - fn next(&mut self) -> Option { - if self.start <= self.end { - let page = self.start; - self.start.number += 1; - Some(page) - } else { - None - } - } -} +use x86::instructions::tlb; pub struct ActivePageTable { mapper: Mapper, @@ -63,14 +44,14 @@ impl ActivePageTable { f: F) where F: FnOnce(&mut Mapper) { - let (cr3_back, cr3flags_back) = Cr3::read(); + let (cr3_back, _cr3flags_back) = Cr3::read(); // map temp page to current p2 let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); // overwrite recursive map self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - x86::instructions::tlb::flush_all(); + tlb::flush_all(); // execute f in the new context f(self); @@ -80,17 +61,9 @@ impl ActivePageTable { } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - - let p2_frame = PhysFrame::containing_address(Cr3::read() as usize); - - let old_table = InactivePageTable { - p2_frame, - }; - - unsafe { - let frame = PhysFrame::containing_address(new_table.p2_frame.start_address()); - Cr3::write(frame.start_address()); - } + let (p2_frame, cr3_flags) = Cr3::read(); + let old_table = InactivePageTable { p2_frame }; + unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } old_table } @@ -103,19 +76,27 @@ pub struct InactivePageTable { impl InactivePageTable { pub fn new(frame: PhysFrame, active_table: &mut ActivePageTable, - temporary_page: &mut TemporaryPage, - ) -> InactivePageTable { + temporary_page: &mut TemporaryPage) + -> InactivePageTable { { - let table = temporary_page.map_table_frame(frame.clone(), - active_table); - table.zero(); + let table = temporary_page.map_table_frame(frame.clone(), active_table); + // table.zero(); + let iter = table.entries.iter_mut(); + for entry in iter { + println!("entry = {:?}", entry as *const _); + // println!("entry = {:?}", entry.flags()); + } + + println!("frame = {:?}", frame); + flush!(); + loop {} // set up recursive mapping for the table table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } temporary_page.unmap(active_table); InactivePageTable { p2_frame: frame } - } + } } pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) @@ -133,7 +114,7 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) active_table.with(&mut new_table, &mut temporary_page, |mapper| { // identity map the VGA text buffer - let vga_buffer_frame = PhysFrame::containing_address(0xb8000); + let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE, allocator); let elf_sections_tag = boot_info.elf_sections_tag() @@ -146,24 +127,53 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) assert!(section.start_address() % PAGE_SIZE as u64 == 0, "sections need to be page aligned"); - let flags = PageTableFlags::from_elf_section_flags(§ion); - let start_frame = PhysFrame::containing_address(section.start_address() as usize); - let end_frame = PhysFrame::containing_address(section.end_address() as usize - 1); - for frame in PhysFrame::range_inclusive(start_frame, end_frame) { + let flags = elf_to_pagetable_flags(§ion.flags()); + let start_frame = PhysFrame::containing_address( + PhysAddr::new(section.start_address() as u32)); + let end_frame = PhysFrame::containing_address( + PhysAddr::new(section.end_address() as u32 - 1)); + for frame in start_frame..end_frame { mapper.identity_map(frame, flags, allocator); } } - let multiboot_start = PhysFrame::containing_address(boot_info.start_address()); - let multiboot_end = PhysFrame::containing_address(boot_info.end_address() - 1); - for frame in PhysFrame::range_inclusive(multiboot_start, multiboot_end) { + let multiboot_start = PhysFrame::containing_address( + PhysAddr::new(boot_info.start_address() as u32)); + let multiboot_end = PhysFrame::containing_address( + PhysAddr::new(boot_info.end_address() as u32 - 1)); + for frame in multiboot_start..multiboot_end { mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); + let old_table = active_table.switch(new_table); - let old_p2_page = Page::containing_address(old_table.p2_frame.start_address()); + let old_p2_page = Page::containing_address( + VirtAddr::new(old_table.p2_frame.start_address().as_u32())); active_table.unmap(old_p2_page, allocator); active_table } + +fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) + -> PageTableFlags +{ + use multiboot2::ElfSectionFlags; + + let mut flags = PageTableFlags::empty(); + + if elf_flags.contains(ElfSectionFlags::ALLOCATED) { + // section is loaded to memory + flags = flags | PageTableFlags::PRESENT; + } + if elf_flags.contains(ElfSectionFlags::WRITABLE) { + flags = flags | PageTableFlags::WRITABLE; + } + + // LONG MODE STUFF + // if !elf_flags.contains(ELF_SECTION_EXECUTABLE) { + // flags = flags | PageTableFlags::NO_EXECUTE; + // } + + flags +} diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index d7aa7554..916813c9 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,23 +1,43 @@ use memory::*; use x86::structures::paging::*; +use x86::ux::*; - -pub trait TableNext - where A: FrameAllocator +pub trait RecTable { - fn next_table_address(&self, index: usize) -> Option; - fn next_table(&self, index: usize) -> Option<&PageTable>; - fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; - fn next_table_create(&mut self, - index: usize, - allocator: &mut A) -> &mut PageTable; + fn next_table_address(&self, index: u10) -> Option; + fn next_table(&self, index: u10) -> Option<&PageTable>; + fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable>; + fn next_table_create(&mut self, + index: u10, + allocator: &mut A) + -> &mut PageTable; } -impl TableNext<> for PageTable +impl RecTable for PageTable { + fn next_table_address(&self, index: u10) -> Option { + let entry_flags = self[index].flags(); + if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) { + let table_address = self as *const _ as u32; + Some(table_address << 10 | u32::from(index << 12)) + } else { + None + } + } + + fn next_table(&self, index: u10) -> Option<&PageTable> { + self.next_table_address(index) + .map(|address| unsafe { &*(address as *const _) }) + } + + fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable> { + self.next_table_address(index) + .map(|address| unsafe { &mut *(address as *mut _) }) + } + fn next_table_create(&mut self, - index: usize, - allocator: &mut A) -> &mut PageTable + index: u10, + allocator: &mut A) -> &mut PageTable where A: FrameAllocator { if self.next_table(index).is_none() { diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index caab2d6a..709fcbfb 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -4,7 +4,7 @@ use x86::*; use x86::structures::paging::*; pub struct TemporaryPage { - page: Page, + pub page: Page, allocator: TinyAllocator, } @@ -26,6 +26,11 @@ impl TemporaryPage { assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); + // this kind of check should be done in a test routine + assert!(active_table.translate_page(self.page).is_some(), + "temporary page was not mapped"); + println!("trans = {:?}", active_table.translate_page(self.page)); + println!("page = {:?}", self.page.start_address()); self.page.start_address() } @@ -40,7 +45,7 @@ impl TemporaryPage { frame: PhysFrame, active_table: &mut ActivePageTable) -> &mut PageTable { - unsafe { &mut *(self.map(frame, active_table) as *mut PageTable) } + unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } } } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index dc9eb5ce..eae47083 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit dc9eb5ceb8981848d95e0ddd7040fb86ec9999e3 +Subproject commit eae470839b1ff232dbc4af5389e9a0b4fffe4b30 From 5c2b5f723b3f348a4cf9cf63b24a731c18747b96 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 15 Mar 2018 17:16:01 +0100 Subject: [PATCH 086/151] yuesterdays problem solved, now i triple fault on write to CR3, fun --- kernel-rs/src/memory/paging/mapper.rs | 10 ++--- kernel-rs/src/memory/paging/mod.rs | 38 ++++++++++++------- kernel-rs/src/memory/paging/table.rs | 20 +++++----- kernel-rs/src/memory/paging/temporary_page.rs | 2 - 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index d8be6889..408149ee 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -2,6 +2,7 @@ use memory::{PAGE_SIZE, FrameAllocator}; use core::ptr::Unique; use x86::structures::paging::*; use x86::instructions::tlb; +use x86::usize_conversions::usize_from; use x86::*; use super::paging::table::RecTable; @@ -41,7 +42,7 @@ impl Mapper { /// virtual page to physical frame translation pub fn translate_page(&self, page: Page) -> Option { - let p1 = self.p2().next_table(page.p2_index()); + let p1 = self.p2().next_table(usize_from(u32::from(page.p2_index()))); let huge_page = || { let p2_entry = &self.p2()[page.p2_index()]; @@ -55,7 +56,7 @@ impl Mapper { }; p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + .or_else(huge_page) } /// map a virtual page to a physical frame in the page tables @@ -64,8 +65,7 @@ impl Mapper { where A: FrameAllocator { let p2 = self.p2_mut(); - let p1 = p2.next_table_create(page.p2_index(), allocator); - + let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())), allocator); assert!(p1[page.p1_index()].is_unused()); p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); } @@ -91,7 +91,7 @@ impl Mapper { assert!(self.translate(page.start_address()).is_some()); let p1 = self.p2_mut() - .next_table_mut(page.p2_index()) + .next_table_mut(usize_from(u32::from(page.p2_index()))) .expect("mapping code does not support huge pages"); let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index 39785015..ce5a9bee 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -61,9 +61,23 @@ impl ActivePageTable { } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { + let (p2_frame, cr3_flags) = Cr3::read(); let old_table = InactivePageTable { p2_frame }; - unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } + + // unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } + + ::console::regs(); + flush!(); + loop {} + + unsafe { asm!("mov $0, %cr3" :: "r" (4096) : "memory"); } + + // let addr = new_table.p2_frame.start_address(); + // let value = addr.as_u32() | cr3_flags.bits(); + // println!("value = {}", 0); + // flush!(); + // loop {} old_table } @@ -81,16 +95,7 @@ impl InactivePageTable { { let table = temporary_page.map_table_frame(frame.clone(), active_table); - // table.zero(); - let iter = table.entries.iter_mut(); - for entry in iter { - println!("entry = {:?}", entry as *const _); - // println!("entry = {:?}", entry.flags()); - } - - println!("frame = {:?}", frame); - flush!(); - loop {} + table.zero(); // set up recursive mapping for the table table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) } @@ -103,14 +108,14 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) -> ActivePageTable where A: FrameAllocator { - let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }, - allocator); + let mut temporary_page = TemporaryPage::new(Page{number: 0xcafe}, allocator); let mut active_table = unsafe { ActivePageTable::new() }; let mut new_table = { let frame = allocator.allocate_frame().expect("no more frames"); InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; + active_table.with(&mut new_table, &mut temporary_page, |mapper| { // identity map the VGA text buffer @@ -146,12 +151,17 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) } }); - let old_table = active_table.switch(new_table); + + println!("check!"); + flush!(); + loop {} + let old_p2_page = Page::containing_address( VirtAddr::new(old_table.p2_frame.start_address().as_u32())); active_table.unmap(old_p2_page, allocator); + active_table } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 916813c9..16060b05 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -4,39 +4,39 @@ use x86::ux::*; pub trait RecTable { - fn next_table_address(&self, index: u10) -> Option; - fn next_table(&self, index: u10) -> Option<&PageTable>; - fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable>; + fn next_table_address(&self, index: usize) -> Option; + fn next_table(&self, index: usize) -> Option<&PageTable>; + fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; fn next_table_create(&mut self, - index: u10, + index: usize, allocator: &mut A) -> &mut PageTable; } impl RecTable for PageTable { - fn next_table_address(&self, index: u10) -> Option { + fn next_table_address(&self, index: usize) -> Option { let entry_flags = self[index].flags(); if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) { - let table_address = self as *const _ as u32; - Some(table_address << 10 | u32::from(index << 12)) + let table_address = self as *const _ as usize; + Some((table_address << 10 | index << 12) as u32) } else { None } } - fn next_table(&self, index: u10) -> Option<&PageTable> { + fn next_table(&self, index: usize) -> Option<&PageTable> { self.next_table_address(index) .map(|address| unsafe { &*(address as *const _) }) } - fn next_table_mut(&mut self, index: u10) -> Option<&mut PageTable> { + fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable> { self.next_table_address(index) .map(|address| unsafe { &mut *(address as *mut _) }) } fn next_table_create(&mut self, - index: u10, + index: usize, allocator: &mut A) -> &mut PageTable where A: FrameAllocator { diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index 709fcbfb..33756ba0 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -29,8 +29,6 @@ impl TemporaryPage { // this kind of check should be done in a test routine assert!(active_table.translate_page(self.page).is_some(), "temporary page was not mapped"); - println!("trans = {:?}", active_table.translate_page(self.page)); - println!("page = {:?}", self.page.start_address()); self.page.start_address() } From 904e7158d8cebfbd6ce9423dbe8d4bca7c2bbfef Mon Sep 17 00:00:00 2001 From: wescande Date: Fri, 16 Mar 2018 15:03:00 +0100 Subject: [PATCH 087/151] acpi in static not in reference --- kernel-rs/src/acpi/dsdt.rs | 6 +++--- kernel-rs/src/acpi/fadt.rs | 26 +++++++++++++------------- kernel-rs/src/acpi/mod.rs | 1 + kernel-rs/src/acpi/rsdp.rs | 27 ++++++++++++--------------- kernel-rs/src/acpi/rsdt.rs | 1 + kernel-rs/src/acpi/xsdt.rs | 1 + kernel-rs/src/arch/x86/boot.asm | 2 +- kernel-rs/src/lib.rs | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index 5943e757..66c187b0 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -12,7 +12,7 @@ static mut DSDT: DSDT = DSDT { struct DSDT { valid: bool, - dsdt: Option<*const ACPISDTHeader>, + dsdt: Option<&'static ACPISDTHeader>, s5_ptr: u32, slp_typ_a: u16, slp_typ_b: u16 @@ -20,7 +20,7 @@ struct DSDT { impl DSDT { fn init(&mut self, addr: u32) -> Result <(), &'static str> { - self.dsdt = Some(addr as *const ACPISDTHeader); + self.dsdt = Some(unsafe{ &(*(addr as *const ACPISDTHeader)) }); self.s5_ptr = self.find_s5(addr)?; self.parse_s5(); self.valid = true; @@ -29,7 +29,7 @@ impl DSDT { fn find_s5(&self, addr: u32) -> Result { let dsdt_start = addr + mem::size_of::() as u32; - let dsdt_end = dsdt_start + unsafe {(*self.dsdt.unwrap()).length}; + let dsdt_end = dsdt_start + self.dsdt.unwrap().length; for addr in dsdt_start..dsdt_end { if check_signature(addr, "_S5_") { if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) && check_signature(addr + 4, "\x12") { diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index 99686934..c06d0a16 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -83,18 +83,18 @@ struct FADT } -static mut FADT: Option<*const FADT> = None; +static mut FADT: Option<&'static FADT> = None; /// ## Initialize Fixed ACPI Description Table (FADT) /// input param addr is contain in other ptr of rsdt pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { for sdt_ptr in sdt_iter { if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic - let ptr = sdt_ptr as *const FADT; - unsafe {FADT = Some(ptr)}; + let ref fadt_tmp: &FADT = unsafe{ &(*(sdt_ptr as *const FADT)) }; + unsafe {FADT = Some(fadt_tmp)}; if !is_enable()? { // TODO do i have to check if enabled before init ??? - let smi_cmd = unsafe {(*ptr).smi_commandport} as u16; // TODO WHY DO I NEED THIS FUCKING CAST - let acpi_enable = unsafe {(*ptr).acpi_enable}; + let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST + let acpi_enable = fadt_tmp.acpi_enable; cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command } return Ok(()); @@ -103,9 +103,9 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { return Err("Can not find Fixed ACPI Description Table (FADT)."); } -fn is_init() -> Result <*const FADT, &'static str> { +fn is_init() -> Result <&'static FADT, &'static str> { match unsafe {FADT} { - Some(ptr) => Ok(ptr), + Some(fadt) => Ok(fadt), None => Err("Fixed ACPI Description Table (FADT) is not initialized") } } @@ -113,18 +113,18 @@ fn is_init() -> Result <*const FADT, &'static str> { /// Return Dsdt address /// FADT must have been initialized first pub fn dsdtaddr() -> Result { - let ptr = is_init()?; - return Ok(unsafe {(*ptr).dsdt}); + let fadt = is_init()?; + return Ok(fadt.dsdt); } -fn get_cnt(ptr: *const FADT) -> [u16; 2] { - [unsafe {(*ptr).pm1acontrolblock} as u16, unsafe {(*ptr).pm1bcontrolblock} as u16] // TODO WHY DO I NEED THIS FUCKING CAST +fn get_cnt(fadt: &'static FADT) -> [u16; 2] { + [fadt.pm1acontrolblock as u16, fadt.pm1bcontrolblock as u16] // TODO WHY DO I NEED THIS FUCKING CAST } /// Return true/false depending of acpi is enable pub fn is_enable() -> Result { - let ptr = is_init()?; - let pm1_cnt = get_cnt(ptr); + let fadt = is_init()?; + let pm1_cnt = get_cnt(fadt); if pm1_cnt[1] == 0 { Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) } else { diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 702e6f9c..de7a7358 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -6,6 +6,7 @@ mod dsdt; use core; use core::mem; +// use cpuio; #[repr(C)] #[derive(Debug, Clone, Copy)] diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs index b5b6967b..85e72418 100644 --- a/kernel-rs/src/acpi/rsdp.rs +++ b/kernel-rs/src/acpi/rsdp.rs @@ -19,7 +19,7 @@ pub struct RSDP20 { reserved: [u8; 3], } -static mut RSDPTR: Option<*const RSDP20> = None; +static mut RSDPTR: Option<&'static RSDP20> = None; /// RSDP load will check is RSDP is present at the addr sent. /// Return a bool @@ -27,10 +27,11 @@ static mut RSDPTR: Option<*const RSDP20> = None; /// false => RSDP is V1 pub fn load(addr: u32) -> Result { if check_signature(addr, "RSD PTR ") { - let ptr_tmp = addr as *const RSDP20; - let revision = unsafe {(*ptr_tmp).rsdp.revision}; + let ref rsdp_tmp: &RSDP20 = unsafe{ &(*(addr as *const RSDP20)) }; + let revision = rsdp_tmp.rsdp.revision; if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { - unsafe {RSDPTR = Some(ptr_tmp)}; + unsafe {RSDPTR = Some(rsdp_tmp)}; + println!("Found rsdptr at {:#x}", addr); return Ok(revision == 2); } } @@ -52,33 +53,29 @@ fn memory_finding(bound: u32) -> Result { Err("Can not find Root System Description Pointer (RSDP).") } -fn is_init() -> Result <*const RSDP20, &'static str> { +fn is_init() -> Result <&'static RSDP20, &'static str> { match unsafe {RSDPTR} { - Some(ptr) => Ok(ptr), + Some(rsdptr) => Ok(rsdptr), None => Err("Root System Description Pointer (RSDP) is not initialized") - // if ptr == 0 as *const RSDP20 - // => Err("Root System Description Pointer (RSDP) is not initialized"), - // ptr - // => Ok(ptr) } } /// Return a ptr on xsdt /// RSDP must have been initialized first pub fn xsdtaddr() -> Result { - let ptr = is_init()?; - let revision = unsafe {(*ptr).rsdp.revision}; + let rsdptr = is_init()?; + let revision = rsdptr.rsdp.revision; if revision != 2 { return Err("Wrong RSDP version asked"); } - return Ok(unsafe {(*ptr).xsdtaddress}); + return Ok(rsdptr.xsdtaddress); } /// Return a ptr on rsdt /// RSDP must have been initialized first pub fn rsdtaddr() -> Result { - let ptr = is_init()?; - return Ok(unsafe {(*ptr).rsdp.rsdtaddr}); + let rsdptr = is_init()?; + return Ok(rsdptr.rsdp.rsdtaddr); } /// RSDP init will iter on addr in [0x0 - 0x1000000] to find "RSDP PTR " diff --git a/kernel-rs/src/acpi/rsdt.rs b/kernel-rs/src/acpi/rsdt.rs index 61363973..dd2cb047 100644 --- a/kernel-rs/src/acpi/rsdt.rs +++ b/kernel-rs/src/acpi/rsdt.rs @@ -1,5 +1,6 @@ use super::{ACPISDTHeader,ACPISDTIter}; +//TODO this can work only if pagging is disabled static mut RSDT: Option<*const ACPISDTHeader> = None; /// ## Initialize Root System Description Table (RSDT) diff --git a/kernel-rs/src/acpi/xsdt.rs b/kernel-rs/src/acpi/xsdt.rs index 356be49d..06ae29bd 100644 --- a/kernel-rs/src/acpi/xsdt.rs +++ b/kernel-rs/src/acpi/xsdt.rs @@ -1,5 +1,6 @@ use super::{ACPISDTHeader,ACPISDTIter}; +//TODO this can work only if pagging is disabled static mut XSDT: Option<*const ACPISDTHeader> = None; /// ## Initialize Root System Description Table (XSDT) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 8615c283..0a05aa51 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -13,7 +13,7 @@ start: call set_up_page_tables call enable_pse - call enable_paging + ; call enable_paging ; load the new gdt lgdt [GDTR.ptr] diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 43d10e56..5ebdd124 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -31,7 +31,7 @@ pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { - // acpi::init().unwrap(); + acpi::init().unwrap(); let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; enable_write_protect_bit(); From 486394504281794ae0097a6d8f831a6d6d47d674 Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 19 Mar 2018 10:58:54 +0100 Subject: [PATCH 088/151] multiboot update --- kernel-rs/multiboot2-elf64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index d66e8cb0..4425c197 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit d66e8cb0e5b10c2097a9aef985b4181694db9ce8 +Subproject commit 4425c197f10d5bcada47eabb8b2f93a8e2422937 From cdea287ecd8ec1cc5ec520d370f26ab734f9711f Mon Sep 17 00:00:00 2001 From: wescande Date: Mon, 19 Mar 2018 11:23:53 +0100 Subject: [PATCH 089/151] acpi can run in kfs-3 --- kernel-rs/Makefile | 8 ++++---- kernel-rs/src/acpi/dsdt.rs | 1 + kernel-rs/src/acpi/fadt.rs | 19 +++++++++++-------- kernel-rs/src/acpi/rsdp.rs | 10 ++++++---- kernel-rs/src/arch/x86/boot.asm | 4 ++-- kernel-rs/src/lib.rs | 6 ++++++ 6 files changed, 30 insertions(+), 18 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index a26b3e36..6e832f9d 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -31,13 +31,13 @@ asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_ KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ - kill \`ps -x | grep \"[g]db\" | cut -d \ -f 1 \`;\ - kill \`ps -x | grep \"[g]db\" | cut -d \ -f 2 \` + kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ + kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` GDB := gdb -q\ -ex \"set arch i386:x86-64\"\ -ex \"file $(kernel)\"\ - -ex \"target remote :$(PORTG)\" - # -ex \"continue\" + -ex \"target remote :$(PORTG)\"\ + -ex \"continue\" all: $(kernel) diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index 66c187b0..aa3456e2 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -50,6 +50,7 @@ impl DSDT { self.slp_typ_b = (unsafe {*(ptr as *const u8)} as u16) << 10; } } + fn is_init() -> Result <(), &'static str> { match unsafe {DSDT.valid} { true => Ok(()), diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index c06d0a16..ed5da011 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -2,7 +2,7 @@ use super::{ACPISDTHeader,ACPISDTIter}; use cpuio; #[repr(C)] -#[derive(Debug)] +#[derive(Debug, Clone)] struct GenericAddressStructure { addressspace: u8, bitwidth: u8, @@ -13,7 +13,7 @@ struct GenericAddressStructure { } #[repr(C)] -#[derive(Debug)] +#[derive(Debug, Clone)] struct FADT { header: ACPISDTHeader, @@ -83,15 +83,15 @@ struct FADT } -static mut FADT: Option<&'static FADT> = None; +static mut FADT: Option = None; /// ## Initialize Fixed ACPI Description Table (FADT) /// input param addr is contain in other ptr of rsdt pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { for sdt_ptr in sdt_iter { if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic - let ref fadt_tmp: &FADT = unsafe{ &(*(sdt_ptr as *const FADT)) }; - unsafe {FADT = Some(fadt_tmp)}; + let fadt_tmp: FADT = unsafe{ (*(sdt_ptr as *const FADT)).clone() }; + unsafe {FADT = Some(fadt_tmp.clone())}; if !is_enable()? { // TODO do i have to check if enabled before init ??? let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST let acpi_enable = fadt_tmp.acpi_enable; @@ -103,8 +103,8 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { return Err("Can not find Fixed ACPI Description Table (FADT)."); } -fn is_init() -> Result <&'static FADT, &'static str> { - match unsafe {FADT} { +fn is_init() -> Result { + match unsafe {FADT.clone()} { Some(fadt) => Ok(fadt), None => Err("Fixed ACPI Description Table (FADT) is not initialized") } @@ -117,7 +117,7 @@ pub fn dsdtaddr() -> Result { return Ok(fadt.dsdt); } -fn get_cnt(fadt: &'static FADT) -> [u16; 2] { +fn get_cnt(fadt: FADT) -> [u16; 2] { [fadt.pm1acontrolblock as u16, fadt.pm1bcontrolblock as u16] // TODO WHY DO I NEED THIS FUCKING CAST } @@ -138,6 +138,9 @@ pub fn get_controlblock() -> Result <[u16; 2], &'static str> { if !is_enable()? { Err("ACPI is not enabled") } else { + // println!("HALT"); + // flush!(); + // cpuio::halt(); Ok(get_cnt(is_init()?)) // TODO redondant call to is_init } } diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs index 85e72418..5d1e2dc8 100644 --- a/kernel-rs/src/acpi/rsdp.rs +++ b/kernel-rs/src/acpi/rsdp.rs @@ -2,6 +2,7 @@ use super::{check_signature,check_checksum}; use core::mem; #[repr(C)] +#[derive(Clone)] struct RSDP { signature: [u8; 8], checksum: u8, @@ -11,6 +12,7 @@ struct RSDP { } #[repr(C)] +#[derive(Clone)] pub struct RSDP20 { rsdp: RSDP, length: u32, @@ -19,7 +21,7 @@ pub struct RSDP20 { reserved: [u8; 3], } -static mut RSDPTR: Option<&'static RSDP20> = None; +static mut RSDPTR: Option = None; /// RSDP load will check is RSDP is present at the addr sent. /// Return a bool @@ -27,7 +29,7 @@ static mut RSDPTR: Option<&'static RSDP20> = None; /// false => RSDP is V1 pub fn load(addr: u32) -> Result { if check_signature(addr, "RSD PTR ") { - let ref rsdp_tmp: &RSDP20 = unsafe{ &(*(addr as *const RSDP20)) }; + let rsdp_tmp: RSDP20 = unsafe{ (*(addr as *const RSDP20)).clone() }; let revision = rsdp_tmp.rsdp.revision; if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { unsafe {RSDPTR = Some(rsdp_tmp)}; @@ -53,8 +55,8 @@ fn memory_finding(bound: u32) -> Result { Err("Can not find Root System Description Pointer (RSDP).") } -fn is_init() -> Result <&'static RSDP20, &'static str> { - match unsafe {RSDPTR} { +fn is_init() -> Result { + match unsafe {RSDPTR.clone()} { Some(rsdptr) => Ok(rsdptr), None => Err("Root System Description Pointer (RSDP) is not initialized") } diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 0a05aa51..8e6f56da 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -48,6 +48,8 @@ set_up_page_tables: cmp ecx, 20 ; if counter == 1023, the whole P2 table is mapped jne .map_p2_table ; else map the next entry + mov eax, p2_table + mov cr3, eax ret ; PSE (Page Size Extension) allows huge pages to exist @@ -61,8 +63,6 @@ enable_pse: enable_paging: ; load P2 to cr3 register (cpu uses this to access the P2 table) - mov eax, p2_table - mov cr3, eax ; enable paging in the cr0 register mov eax, cr0 diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 5ebdd124..69020f85 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -32,7 +32,9 @@ pub mod x86; #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { acpi::init().unwrap(); + let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; + enable_paging(); enable_write_protect_bit(); memory::init(&boot_info); @@ -53,6 +55,10 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { loop { keyboard::kbd_callback(); } } +fn enable_paging() { + unsafe { x86::cr0_write(x86::cr0() | (1 << 31)) }; +} + fn enable_write_protect_bit() { unsafe { x86::cr0_write(x86::cr0() | (1 << 16)) }; } From ed03d247c715bb3111b45532eef9f91fb89c0bc2 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 19 Mar 2018 12:14:30 +0100 Subject: [PATCH 090/151] it works:))) --- kernel-rs/src/console.rs | 2 +- kernel-rs/src/lib.rs | 13 +--------- kernel-rs/src/memory/paging/mod.rs | 39 +++++++++--------------------- 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 6ababe05..4ffcdd54 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -179,8 +179,8 @@ pub fn regs() -> Result <(), &'static str> { use x86::registers::control::*; println!("cr0={:#b}", Cr0::read()); println!("cr3={:?}", Cr3::read()); + flush!(); // TODO implement cr4 flags in `x86` module // println!("cr4={:#b}", Cr4::read()); Ok(()) } - diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 1303e417..8cf31d6e 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -34,23 +34,12 @@ pub mod memory; pub extern fn kmain(multiboot_info_addr: usize) -> ! { // acpi::init().unwrap(); let boot_info = unsafe { multiboot2::load(multiboot_info_addr) }; + enable_write_protect_bit(); memory::init(&boot_info); vga::init(); - use alloc::boxed::Box; - let mut heap_test = Box::new(42); - *heap_test -= 15; - let heap_test2 = Box::new("Hello"); - println!("{:?} {:?}", heap_test, heap_test2); - - let mut vec_test = vec![1,2,3,4,5,6,7]; - vec_test[3] = 42; - for i in &vec_test { - print!("{} ", i); - } - loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/memory/paging/mod.rs index ce5a9bee..5b3fbd67 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/memory/paging/mod.rs @@ -65,19 +65,7 @@ impl ActivePageTable { let (p2_frame, cr3_flags) = Cr3::read(); let old_table = InactivePageTable { p2_frame }; - // unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } - - ::console::regs(); - flush!(); - loop {} - - unsafe { asm!("mov $0, %cr3" :: "r" (4096) : "memory"); } - - // let addr = new_table.p2_frame.start_address(); - // let value = addr.as_u32() | cr3_flags.bits(); - // println!("value = {}", 0); - // flush!(); - // loop {} + unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } old_table } @@ -92,15 +80,15 @@ impl InactivePageTable { active_table: &mut ActivePageTable, temporary_page: &mut TemporaryPage) -> InactivePageTable { - { - let table = temporary_page.map_table_frame(frame.clone(), active_table); + { + let table = temporary_page.map_table_frame(frame.clone(), active_table); - table.zero(); - // set up recursive mapping for the table - table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) - } - temporary_page.unmap(active_table); - InactivePageTable { p2_frame: frame } + table.zero(); + // set up recursive mapping for the table + table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) + } + temporary_page.unmap(active_table); + InactivePageTable { p2_frame: frame } } } @@ -137,7 +125,7 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) PhysAddr::new(section.start_address() as u32)); let end_frame = PhysFrame::containing_address( PhysAddr::new(section.end_address() as u32 - 1)); - for frame in start_frame..end_frame { + for frame in start_frame..end_frame + 1 { mapper.identity_map(frame, flags, allocator); } } @@ -146,17 +134,13 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) PhysAddr::new(boot_info.start_address() as u32)); let multiboot_end = PhysFrame::containing_address( PhysAddr::new(boot_info.end_address() as u32 - 1)); - for frame in multiboot_start..multiboot_end { + for frame in multiboot_start..multiboot_end + 1 { mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); } }); let old_table = active_table.switch(new_table); - println!("check!"); - flush!(); - loop {} - let old_p2_page = Page::containing_address( VirtAddr::new(old_table.p2_frame.start_address().as_u32())); @@ -179,7 +163,6 @@ fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) if elf_flags.contains(ElfSectionFlags::WRITABLE) { flags = flags | PageTableFlags::WRITABLE; } - // LONG MODE STUFF // if !elf_flags.contains(ELF_SECTION_EXECUTABLE) { // flags = flags | PageTableFlags::NO_EXECUTE; From 5c7daabdd065a57546041fe49b232dbf41cbfa8c Mon Sep 17 00:00:00 2001 From: wescande Date: Tue, 20 Mar 2018 13:37:51 +0100 Subject: [PATCH 091/151] little correctif --- kernel-rs/multiboot2-elf64 | 2 +- kernel-rs/src/arch/x86/boot.asm | 48 ++++--------------- kernel-rs/src/cpuio.rs | 5 +- kernel-rs/src/lib.rs | 12 ----- kernel-rs/src/memory/mod.rs | 6 ++- kernel-rs/src/memory/paging/mapper.rs | 7 ++- kernel-rs/src/memory/paging/table.rs | 10 ++-- kernel-rs/src/memory/paging/temporary_page.rs | 18 +++---- kernel-rs/src/vga/mod.rs | 2 - kernel-rs/x86 | 2 +- 10 files changed, 35 insertions(+), 77 deletions(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index 4425c197..73530c41 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit 4425c197f10d5bcada47eabb8b2f93a8e2422937 +Subproject commit 73530c41902a6991ca54ad6f12d05519d4870403 diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 1be8474b..f2fab7b6 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -12,12 +12,9 @@ start: call check_multiboot call set_up_page_tables - call enable_pse - ; call enable_paging ; load the new gdt lgdt [GDTR.ptr] - jmp GDTR.gdt_cs:x86_start check_multiboot: @@ -34,42 +31,13 @@ set_up_page_tables: or eax, 0b11 ; present + writable mov [p2_table + 1023 * 4], eax - ; map each P2 entry to a huge 4MiB page - mov ecx, 0 ; counter variable + ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx + mov eax, 0b10000011 ; huge + present + writable + mov [p2_table], eax ; map ecx-th entry -.map_p2_table: - ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx - mov eax, 0x400000 ; 4MiB - mul ecx ; start address of ecx-th page - or eax, 0b10000011 ; huge + present + writable - mov [p2_table + ecx * 4], eax ; map ecx-th entry - - inc ecx ; increase counter - cmp ecx, 20 ; if counter == 1023, the whole P2 table is mapped - jne .map_p2_table ; else map the next entry - - mov eax, p2_table - mov cr3, eax - ret - -; PSE (Page Size Extension) allows huge pages to exist -enable_pse: - ; enable PSE in the cr4 register - mov eax, cr4 - or eax, 1 << 4 - mov cr4, eax - - ret - -enable_paging: - ; load P2 to cr3 register (cpu uses this to access the P2 table) - - ; enable paging in the cr0 register - mov eax, cr0 - or eax, 1 << 31 - mov cr0, eax - - ret + mov eax, p2_table + mov cr3, eax + ret error: mov dword [0xb8000], 0x4f524f45 @@ -84,9 +52,9 @@ HALT: section .bss align 4096 p2_table: - resb 4096 + resb 4096 stack_bottom: - resb 4096 * 8 + resb 4096 * 8 stack_top: section .gdt diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index ffd6ca9b..57575a17 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -38,9 +38,10 @@ pub fn outl(port: u16, value: u32) { unsafe {asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile")}; } +/// Halt system pub fn halt() -> ! { - unsafe {asm!("cli")};//TODO sure here ? + unsafe {asm!("cli" : : : : "volatile")}; loop { - unsafe {asm!("hlt")}; //TODO volatile ????? + unsafe {asm!("hlt" : : : : "volatile")}; } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 83e48b4e..c92dfc7c 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -40,24 +40,12 @@ fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { else { acpi::init()?; } - enable_paging(); - enable_write_protect_bit(); memory::init(&boot_info); vga::init(); Ok(()) } -fn enable_paging() { - use x86::registers::control::{Cr0, Cr0Flags}; - unsafe { Cr0::write(Cr0::read() | Cr0Flags::PAGING) }; -} - -fn enable_write_protect_bit() { - use x86::registers::control::{Cr0, Cr0Flags}; - unsafe { Cr0::write(Cr0::read() | Cr0Flags::WRITE_PROTECT) }; -} - #[no_mangle] pub extern fn kmain(multiboot_info_addr: usize) -> ! { if let Err(msg) = init_kernel(multiboot_info_addr) { diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index c2a6c244..7294cce2 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -18,6 +18,10 @@ pub trait FrameAllocator { /// memory initialisation should only be called once pub fn init(boot_info: &multiboot2::BootInformation) { + use x86::registers::control::{Cr0, Cr4, Cr0Flags, Cr4Flags}; + Cr4::add(Cr4Flags::PSE); + Cr0::add(Cr0Flags::PAGING | Cr0Flags::WRITE_PROTECT); + let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); let memory_map_tag = boot_info.memory_map_tag().unwrap(); @@ -33,7 +37,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let mut frame_allocator = self::AreaFrameAllocator::new( kernel_start as usize, kernel_end as usize, - boot_info.start_address(), boot_info.start_address(), + boot_info.start_address(), boot_info.end_address(), memory_map_tag.memory_areas()); let mut active_table = paging::remap_the_kernel(&mut frame_allocator, diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/memory/paging/mapper.rs index 408149ee..319f8827 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/memory/paging/mapper.rs @@ -37,7 +37,6 @@ impl Mapper { let offset = virtual_address.as_u32() % PAGE_SIZE as u32; self.translate_page(Page::containing_address(virtual_address)) .map(|frame| frame.start_address() + offset) - } /// virtual page to physical frame translation @@ -50,13 +49,13 @@ impl Mapper { if p2_entry.flags().contains(PageTableFlags::HUGE_PAGE) { // TODO 4MiB alignment check return Some(start_frame + u32::from(page.p1_index())); - } + } } None - }; + }; p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + .or_else(huge_page) } /// map a virtual page to a physical frame in the page tables diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index 16060b05..b390b99a 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -8,9 +8,9 @@ pub trait RecTable fn next_table(&self, index: usize) -> Option<&PageTable>; fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; fn next_table_create(&mut self, - index: usize, - allocator: &mut A) - -> &mut PageTable; + index: usize, + allocator: &mut A) + -> &mut PageTable; } impl RecTable for PageTable @@ -36,8 +36,8 @@ impl RecTable for PageTable } fn next_table_create(&mut self, - index: usize, - allocator: &mut A) -> &mut PageTable + index: usize, + allocator: &mut A) -> &mut PageTable where A: FrameAllocator { if self.next_table(index).is_none() { diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/memory/paging/temporary_page.rs index 33756ba0..c7e9b094 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/memory/paging/temporary_page.rs @@ -18,17 +18,17 @@ impl TemporaryPage { } } - /// Maps the temporary page to the given frame in the active table. + /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) -> VirtAddr { assert!(active_table.translate_page(self.page).is_none(), - "temporary page is already mapped"); + "temporary page is already mapped"); active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); // this kind of check should be done in a test routine assert!(active_table.translate_page(self.page).is_some(), - "temporary page was not mapped"); + "temporary page was not mapped"); self.page.start_address() } @@ -37,14 +37,14 @@ impl TemporaryPage { active_table.unmap(self.page, &mut self.allocator) } - /// Maps the temporary page to the given page table frame in the active + /// Maps the temporary page to the given page table frame in the active /// table. Returns a reference to the now mapped table. pub fn map_table_frame(&mut self, - frame: PhysFrame, - active_table: &mut ActivePageTable) - -> &mut PageTable { - unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } - } + frame: PhysFrame, + active_table: &mut ActivePageTable) + -> &mut PageTable { + unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } + } } struct TinyAllocator([Option; 1]); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 26013c44..dc87c0d9 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -214,7 +214,5 @@ pub fn init() { format_args!("{: ^80}", r#" | : ;| : .' "#), format_args!("{: ^80}", r#" ' ,/ ; | .' "#), format_args!("{: ^80}", r#" '--' `---' "#)); - set_color!(); unsafe { VGA.prompt(); } - unsafe { VGA.flush(); } } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index eae47083..7b8227e3 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit eae470839b1ff232dbc4af5389e9a0b4fffe4b30 +Subproject commit 7b8227e36afe68ed2d518a2c7cede0466878ca9d From 098d222fc1aad13f4d37994e05912df6689c7e5a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 19 Mar 2018 15:24:26 +0100 Subject: [PATCH 092/151] int --- kernel-rs/Cargo.toml | 4 ++++ kernel-rs/src/interrupts/mod.rs | 21 +++++++++++++++++++++ kernel-rs/src/lib.rs | 21 ++++++++++++++++----- kernel-rs/src/memory/paging/table.rs | 2 +- kernel-rs/x86 | 2 +- 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 kernel-rs/src/interrupts/mod.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 558231c0..90aada02 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -11,3 +11,7 @@ rlibc = "1.0" bitflags = "1.0.1" multiboot2 = { path = "multiboot2-elf64" } x86 = { path = "x86" } + +[dependencies.lazy_static] +version = "1.0.0" +features = ["spin_no_std"] diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs new file mode 100644 index 00000000..29734748 --- /dev/null +++ b/kernel-rs/src/interrupts/mod.rs @@ -0,0 +1,21 @@ +use x86::structures::idt::*; + +lazy_static! { + static ref IDT: Idt = { + let mut idt = Idt::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + idt + }; +} + +pub fn init() { + IDT.load(); +} + +extern "x86-interrupt" fn breakpoint_handler( + stack_frame: &mut ExceptionStackFrame) +{ + println!("EXCEPTION: BREAKPOINT\n"); + flush!(); + loop{} +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index c92dfc7c..ba3c49f6 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -5,13 +5,16 @@ #![feature(const_fn)] #![feature(ptr_internals)] #![feature(asm)] + #![feature(alloc)] #![feature(allocator_api)] #![feature(global_allocator)] +#![feature(abi_x86_interrupt)] + extern crate rlibc; extern crate multiboot2; -// #[macro_use] extern crate bitflags; +#[macro_use] extern crate lazy_static; #[macro_use] extern crate alloc; extern crate x86; @@ -27,22 +30,28 @@ pub mod cpuio; pub mod acpi; /// physical frame allocator + paging module + heap allocator pub mod memory; -// x86 interruptions -// pub mod interrupts; +/// x86 interruptions +pub mod interrupts; fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { + let boot_info = unsafe { multiboot2::load(multiboot_info_addr)}; + if let Some(rsdp) = boot_info.rsdp_v2_tag() { acpi::load(rsdp)?; } else if let Some(rsdp) = boot_info.rsdp_tag() { acpi::load(rsdp)?; - } - else { + } else { acpi::init()?; } + enable_paging(); + enable_write_protect_bit(); + memory::init(&boot_info); + interrupts::init(); vga::init(); + Ok(()) } @@ -53,6 +62,8 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { cpuio::halt(); } + x86::instructions::interrupts::int3(); + loop { keyboard::kbd_callback(); } } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/memory/paging/table.rs index b390b99a..70a9731e 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/memory/paging/table.rs @@ -1,6 +1,6 @@ use memory::*; use x86::structures::paging::*; -use x86::ux::*; +// use x86::ux::*; pub trait RecTable { diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 7b8227e3..da544c83 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 7b8227e36afe68ed2d518a2c7cede0466878ca9d +Subproject commit da544c834b3f3d8b53f456c48b3aafa58d09198a From 30a8daf1a3648d690eb2a07a777347979fda504c Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 20 Mar 2018 13:27:18 +0100 Subject: [PATCH 093/151] first interrupts works --- kernel-rs/src/interrupts/mod.rs | 4 +--- kernel-rs/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs index 29734748..0a59bc83 100644 --- a/kernel-rs/src/interrupts/mod.rs +++ b/kernel-rs/src/interrupts/mod.rs @@ -15,7 +15,5 @@ pub fn init() { extern "x86-interrupt" fn breakpoint_handler( stack_frame: &mut ExceptionStackFrame) { - println!("EXCEPTION: BREAKPOINT\n"); - flush!(); - loop{} + println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index ba3c49f6..8b57dc33 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -64,6 +64,8 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { x86::instructions::interrupts::int3(); + flush!(); + loop { keyboard::kbd_callback(); } } From 9d69b7a82a5931cba520359d81fda7f068ffd32d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 20 Mar 2018 18:15:20 +0100 Subject: [PATCH 094/151] stack allocator, keyboard doesnt work with interrupts yet, i think i need to tell 0x20 and 0x21 to shift interrupt by 32 because of intel bug. tomorrow --- kernel-rs/src/interrupts/mod.rs | 16 ++++- kernel-rs/src/keyboard.rs | 6 +- kernel-rs/src/lib.rs | 19 +++--- kernel-rs/src/memory/mod.rs | 36 ++++++++++- kernel-rs/src/memory/stack_allocator.rs | 81 +++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 kernel-rs/src/memory/stack_allocator.rs diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs index 0a59bc83..dc5a3eef 100644 --- a/kernel-rs/src/interrupts/mod.rs +++ b/kernel-rs/src/interrupts/mod.rs @@ -4,16 +4,30 @@ lazy_static! { static ref IDT: Idt = { let mut idt = Idt::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); + idt.double_fault.set_handler_fn(double_fault_handler); + idt[0x21].set_handler_fn(::keyboard::kbd_callback); idt }; } -pub fn init() { +pub fn init(memory_controller: &mut ::memory::MemoryController) { + let double_fault_stack = memory_controller.alloc_stack(1) + .expect("could not allocate double fault stack"); + // println!("DF stack: {:#?}", double_fault_stack); + // flush!(); IDT.load(); } +extern "x86-interrupt" fn double_fault_handler( + stack_frame: &mut ExceptionStackFrame, _error_code: u32) +{ + println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); + flush!(); +} + extern "x86-interrupt" fn breakpoint_handler( stack_frame: &mut ExceptionStackFrame) { println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); + flush!(); } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index c29217a8..de6859db 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,4 +1,5 @@ extern crate core; +use x86::structures::idt::*; use cpuio; use vga; @@ -76,7 +77,10 @@ fn check_key_state(key: u8) -> (bool, usize) { } } -pub fn kbd_callback() { +pub extern "x86-interrupt" fn kbd_callback( + stack_frame: &mut ExceptionStackFrame) { + println!("kbd callback called"); + flush!(); static mut SHIFT: bool = false; static mut CTRL: bool = false; static mut ALT: bool = false; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 8b57dc33..cb08eff0 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -37,6 +37,7 @@ fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { let boot_info = unsafe { multiboot2::load(multiboot_info_addr)}; + // ACPI must be intialized BEFORE paging (memory::init()) is active if let Some(rsdp) = boot_info.rsdp_v2_tag() { acpi::load(rsdp)?; } else if let Some(rsdp) = boot_info.rsdp_tag() { @@ -45,11 +46,8 @@ fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { acpi::init()?; } - enable_paging(); - enable_write_protect_bit(); - - memory::init(&boot_info); - interrupts::init(); + let mut memory_controller = memory::init(&boot_info); + interrupts::init(&mut memory_controller); vga::init(); Ok(()) @@ -62,11 +60,16 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { cpuio::halt(); } - x86::instructions::interrupts::int3(); + // x86::instructions::interrupts::int3(); - flush!(); + // fn stack_overflow() { stack_overflow(); } + // stack_overflow(); - loop { keyboard::kbd_callback(); } + // unsafe { + // *(0xdead as *mut u32) = 42; + // }; + + loop {} } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 7294cce2..aad7c4ca 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,11 +1,11 @@ -pub const PAGE_SIZE: usize = 4096; - mod area_allocator; mod heap_allocator; +mod stack_allocator; mod paging; pub use self::area_allocator::*; pub use self::heap_allocator::*; +pub use self::stack_allocator::*; pub use self::paging::remap_the_kernel; use multiboot2; use x86::*; @@ -16,8 +16,25 @@ pub trait FrameAllocator { fn deallocate_frame(&mut self, frame: PhysFrame); } +pub struct MemoryController { + active_table: paging::ActivePageTable, + frame_allocator: AreaFrameAllocator, + stack_allocator: StackAllocator, +} + +impl MemoryController { + pub fn alloc_stack(&mut self, size_in_pages: usize) -> Option { + let &mut MemoryController { ref mut active_table, + ref mut frame_allocator, + ref mut stack_allocator } = self; + + stack_allocator.alloc_stack(active_table, frame_allocator, + size_in_pages) + } +} + /// memory initialisation should only be called once -pub fn init(boot_info: &multiboot2::BootInformation) { +pub fn init(boot_info: &multiboot2::BootInformation) -> MemoryController { use x86::registers::control::{Cr0, Cr4, Cr0Flags, Cr4Flags}; Cr4::add(Cr4Flags::PSE); Cr0::add(Cr0Flags::PAGING | Cr0Flags::WRITE_PROTECT); @@ -52,4 +69,17 @@ pub fn init(boot_info: &multiboot2::BootInformation) { for page in heap_start_page..heap_end_page { active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } + + let stack_allocator = { + let stack_alloc_start = heap_end_page + 1; + let stack_alloc_end = stack_alloc_start + 100; + let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; + StackAllocator::new(stack_alloc_range) + }; + + MemoryController { + active_table, + frame_allocator, + stack_allocator, + } } diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs new file mode 100644 index 00000000..27fec344 --- /dev/null +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -0,0 +1,81 @@ +use x86::*; +use x86::structures::paging::*; +use memory::paging::{self, ActivePageTable}; +use memory::*; +use core::ops::Range; + +#[derive(Debug)] +pub struct Stack { + top: usize, + bottom: usize, +} + +impl Stack { + fn new (top: usize, bottom: usize) -> Stack { + assert!(top > bottom); + Stack { + top, + bottom, + } + } + + pub fn top(&self) -> usize { + self.top + } + + pub fn bottom(&self) -> usize { + self.bottom + } +} + +#[derive(Debug)] +pub struct StackAllocator { + range: Range +} + +impl StackAllocator { + pub fn new(range: Range) -> StackAllocator { + StackAllocator { range } + } + + pub fn alloc_stack(&mut self, + active_table: &mut ActivePageTable, + frame_allocator: &mut FA, + size_in_pages: usize) -> Option { + if size_in_pages == 0 { + return None; /* a zero sized stack makes no sense */ + } + + // clone the range, since we only want to change it on success + let mut range = self.range.clone(); + + // try to allocate the stack pages and a guard page + let guard_page = range.next(); + let stack_start = range.next(); + let stack_end = if size_in_pages == 1 { + stack_start + } else { + // choose the (size_in_pages-2)th element, since index + // starts at 0 and we already allocated the start page + range.nth(size_in_pages - 2) + }; + + match (guard_page, stack_start, stack_end) { + (Some(_), Some(start), Some(end)) => { + // success! write back updated range + self.range = range.clone(); + + // map stack pages to physical frames + for page in range { + active_table.map(page, PageTableFlags::WRITABLE, frame_allocator); + } + + // create a new stack + let top_of_stack = end.start_address().as_u32() + PAGE_SIZE as u32; + Some(Stack::new(top_of_stack as usize, + start.start_address().as_u32() as usize)) + } + _ => None, /* not enough pages */ + } + } +} From 095c3690612778258f15c094917e8b189f8320dc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 26 Mar 2018 15:13:06 +0200 Subject: [PATCH 095/151] x86 tss --- kernel-rs/src/interrupts/mod.rs | 3 ++- kernel-rs/src/memory/stack_allocator.rs | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs index dc5a3eef..aba00559 100644 --- a/kernel-rs/src/interrupts/mod.rs +++ b/kernel-rs/src/interrupts/mod.rs @@ -5,7 +5,8 @@ lazy_static! { let mut idt = Idt::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); idt.double_fault.set_handler_fn(double_fault_handler); - idt[0x21].set_handler_fn(::keyboard::kbd_callback); + // int #1 is keyboard + idt.interrupts[1].set_handler_fn(::keyboard::kbd_callback); idt }; } diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs index 27fec344..3bce908e 100644 --- a/kernel-rs/src/memory/stack_allocator.rs +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -1,6 +1,5 @@ -use x86::*; use x86::structures::paging::*; -use memory::paging::{self, ActivePageTable}; +use memory::paging::{ActivePageTable}; use memory::*; use core::ops::Range; From 6d8c31b42c39c0ae23677d9dfa2956e746667f9f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 29 Mar 2018 17:10:42 +0200 Subject: [PATCH 096/151] major refactoring for upcoming cross platform, also recycle allocator for the physical frames --- kernel-rs/Cargo.toml | 4 + kernel-rs/Makefile | 70 ++++-------- kernel-rs/mk/qemu.mk | 25 +++++ kernel-rs/src/allocator/mod.rs | 27 +++++ kernel-rs/src/allocator/slab.rs | 43 +++++++ kernel-rs/src/arch/mod.rs | 1 + kernel-rs/src/arch/x86/grub.cfg | 2 +- kernel-rs/src/arch/x86/interrupt/exception.rs | 34 ++++++ kernel-rs/src/arch/x86/interrupt/irq.rs | 6 + kernel-rs/src/arch/x86/interrupt/mod.rs | 46 ++++++++ kernel-rs/src/arch/x86/macros.rs | 36 ++++++ kernel-rs/src/arch/x86/mod.rs | 42 +++++++ .../src/{memory => arch/x86}/paging/mapper.rs | 68 ++++++------ .../src/{memory => arch/x86}/paging/mod.rs | 39 ++++--- .../src/{memory => arch/x86}/paging/table.rs | 32 +++--- .../x86}/paging/temporary_page.rs | 51 +-------- kernel-rs/src/arch/x86/start.asm | 4 +- kernel-rs/src/interrupts/mod.rs | 34 ------ kernel-rs/src/keyboard.rs | 4 +- kernel-rs/src/lib.rs | 63 ++++------- .../src/memory/{area_allocator.rs => bump.rs} | 42 ++++--- kernel-rs/src/memory/heap_allocator.rs | 60 ---------- kernel-rs/src/memory/mod.rs | 102 ++++++++--------- kernel-rs/src/memory/recycle.rs | 105 ++++++++++++++++++ kernel-rs/src/vga/mod.rs | 4 +- kernel-rs/x86 | 2 +- 26 files changed, 567 insertions(+), 379 deletions(-) create mode 100644 kernel-rs/mk/qemu.mk create mode 100644 kernel-rs/src/allocator/mod.rs create mode 100644 kernel-rs/src/allocator/slab.rs create mode 100644 kernel-rs/src/arch/mod.rs create mode 100644 kernel-rs/src/arch/x86/interrupt/exception.rs create mode 100644 kernel-rs/src/arch/x86/interrupt/irq.rs create mode 100644 kernel-rs/src/arch/x86/interrupt/mod.rs create mode 100644 kernel-rs/src/arch/x86/macros.rs create mode 100644 kernel-rs/src/arch/x86/mod.rs rename kernel-rs/src/{memory => arch/x86}/paging/mapper.rs (51%) rename kernel-rs/src/{memory => arch/x86}/paging/mod.rs (85%) rename kernel-rs/src/{memory => arch/x86}/paging/table.rs (53%) rename kernel-rs/src/{memory => arch/x86}/paging/temporary_page.rs (51%) delete mode 100644 kernel-rs/src/interrupts/mod.rs rename kernel-rs/src/memory/{area_allocator.rs => bump.rs} (62%) delete mode 100644 kernel-rs/src/memory/heap_allocator.rs create mode 100644 kernel-rs/src/memory/recycle.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 90aada02..9f28fcab 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -9,9 +9,13 @@ crate-type = ["staticlib"] [dependencies] rlibc = "1.0" bitflags = "1.0.1" +spin = "0.4" multiboot2 = { path = "multiboot2-elf64" } +slab_allocator = "0.3.1" x86 = { path = "x86" } [dependencies.lazy_static] version = "1.0.0" features = ["spin_no_std"] + + diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 6e832f9d..7a9ed66b 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,77 +1,42 @@ SHELL := /bin/bash -ifeq ($(shell whoami), william) - PORT := 4242 - PORTG := 4244 -else - PORT := 4342 - PORTG := 4344 -endif +ARCH := x86 +OS := bluesnow +target ?= $(ARCH)-$(OS) -project := bluesnow -arch ?= x86 NASM := /usr/bin/nasm -f elf -g LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections -# QEMU := qemu-system-x86_64 -device isa-debug-exit,iobase=0xf4,iosize=0x04 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -QEMU := qemu-system-x86_64 -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait +MKDIR := mkdir -p -kerName := BlueSnow -kernel := build/$(kerName) +kernel := build/$(OS) iso := $(kernel).iso DIRISO := build/isofiles -target ?= $(arch)-$(project) -rust_os := target/$(target)/debug/lib$(project).a +rust_os := target/$(target)/debug/lib$(OS).a -linker_script := src/arch/$(arch)/linker.ld -grub.cfg := src/arch/$(arch)/grub.cfg -asm_source := $(wildcard src/arch/$(arch)/*.asm) -asm_object := $(patsubst src/arch/$(arch)/%.asm, build/arch/$(arch)/%.o, $(asm_source)) - -KERNEL_RUN := $(QEMU) -curses -cdrom $(iso) -MONITOR := sleep 0.5;\ - telnet 127.0.0.1 $(PORT);\ - kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ - kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` -GDB := gdb -q\ - -ex \"set arch i386:x86-64\"\ - -ex \"file $(kernel)\"\ - -ex \"target remote :$(PORTG)\"\ - -ex \"continue\" +linker_script := src/arch/$(ARCH)/linker.ld +grub.cfg := src/arch/$(ARCH)/grub.cfg +asm_source := $(wildcard src/arch/$(ARCH)/*.asm) +asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source)) all: $(kernel) -build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm Makefile - @mkdir -p $(shell dirname $@) +build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile + @$(MKDIR) $(shell dirname $@) $(NASM) $< -o $@ $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) $(iso): $(kernel) $(grub.cfg) Makefile - @mkdir -p $(DIRISO)/boot/grub + @$(MKDIR) $(DIRISO)/boot/grub @cp $(grub.cfg) $(DIRISO)/boot/grub - @cp $(kernel) $(DIRISO)/boot/$(kerName) + @cp $(kernel) $(DIRISO)/boot/$(OS) @grub-mkrescue -o $@ $(DIRISO) 2>/dev/null -# $(kernel).img: $(kernel) -# @cp .clean.img $@ -# @sudo mount -oloop=/dev/loop0,offset=32256 $@ /mnt -# @sudo cp $(kernel) /mnt/boot/. -# @sudo umount /mnt - -run: $(iso) Makefile - @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' - -# Run without try to do a compile -R: - @tmux info >&- || { echo -e "\033[38;5;16m ~~ NOT IN A VALID TMUX SESSION ~~\033[0m" ; exit 1; } - @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(KERNEL_RUN)' - clean: @xargo clean - @rm -r build + @rm -rf build $(rust_os): $(target).json Makefile @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target) @@ -79,4 +44,7 @@ $(rust_os): $(target).json Makefile kernel: $(rust_os) iso: $(iso) -.PHONY: R run clean kernel iso $(rust_os) +.PHONY: clean kernel iso $(rust_os) + +# Emulation recipes +include mk/qemu.mk diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk new file mode 100644 index 00000000..0ac107ab --- /dev/null +++ b/kernel-rs/mk/qemu.mk @@ -0,0 +1,25 @@ +ifeq ($(shell whoami), william) + PORT := 4242 + PORTG := 4244 +else + PORT := 4342 + PORTG := 4344 +endif + +QEMU := qemu-system-x86_64 +QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom + +MONITOR := sleep 0.5;\ + telnet 127.0.0.1 $(PORT);\ + kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ + kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` +GDB := gdb -q\ + -ex \"set arch i386:x86-64\"\ + -ex \"file $(kernel)\"\ + -ex \"target remote :$(PORTG)\"\ + -ex \"continue\" + +qemu: + @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } + @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU) $(QEMUFLAGS) $(iso)' + diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs new file mode 100644 index 00000000..2a4ca765 --- /dev/null +++ b/kernel-rs/src/allocator/mod.rs @@ -0,0 +1,27 @@ +pub use self::slab::Allocator; +mod slab; + +use x86::*; +use x86::structures::paging::*; +use arch::x86::paging::*; + +fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) +{ + let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32)); + let heap_end_page = Page::containing_address(VirtAddr::new( + offset as u32 + size as u32 - 1)); + + for page in heap_start_page..heap_end_page + 1 { + active_table.map(page, PageTableFlags::WRITABLE); + } +} + +/// should be called only once +pub unsafe fn init(active_table: &mut ActivePageTable) { + let offset = ::HEAP_START; + let size = ::HEAP_SIZE; + + map_heap(active_table, offset, size); + + Allocator::init(offset, size); +} diff --git a/kernel-rs/src/allocator/slab.rs b/kernel-rs/src/allocator/slab.rs new file mode 100644 index 00000000..ddc50501 --- /dev/null +++ b/kernel-rs/src/allocator/slab.rs @@ -0,0 +1,43 @@ +use alloc::heap::{Alloc, AllocErr, Layout}; +use spin::Mutex; +use slab_allocator::Heap; + +static HEAP: Mutex> = Mutex::new(None); + +pub struct Allocator; + +impl Allocator { + pub unsafe fn init(offset: usize, size: usize) { + *HEAP.lock() = Some(Heap::new(offset, size)); + } +} + +unsafe impl<'a> Alloc for &'a Allocator { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + if let Some(ref mut heap) = *HEAP.lock() { + heap.allocate(layout) + } else { + panic!("__rust_allocate: heap not initialized"); + } + } + + unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { + if let Some(ref mut heap) = *HEAP.lock() { + heap.deallocate(ptr, layout) + } else { + panic!("__rust_deallocate: heap not initialized"); + } + } + + fn oom(&mut self, error: AllocErr) -> ! { + panic!("Out of memory: {:?}", error); + } + + fn usable_size(&self, layout: &Layout) -> (usize, usize) { + if let Some(ref mut heap) = *HEAP.lock() { + heap.usable_size(layout) + } else { + panic!("__rust_usable_size: heap not initialized"); + } + } +} diff --git a/kernel-rs/src/arch/mod.rs b/kernel-rs/src/arch/mod.rs new file mode 100644 index 00000000..aebe1682 --- /dev/null +++ b/kernel-rs/src/arch/mod.rs @@ -0,0 +1 @@ +pub mod x86; diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg index 4cbeea5c..7bccc42f 100644 --- a/kernel-rs/src/arch/x86/grub.cfg +++ b/kernel-rs/src/arch/x86/grub.cfg @@ -2,6 +2,6 @@ set timeout=0 set default=0 menuentry "Blue Snow" { - multiboot2 /boot/BlueSnow + multiboot2 /boot/bluesnow boot } diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs new file mode 100644 index 00000000..40674263 --- /dev/null +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -0,0 +1,34 @@ +// https://wiki.osdev.org/Exceptions + +use x86::structures::idt::*; + +interrupt!(divide_by_zero, {}); +interrupt!(debug, {}); +interrupt!(non_maskable, {}); +interrupt!(breakpoint, {}); +interrupt!(overflow, {}); +interrupt!(bound_range, {}); +interrupt!(invalid_opcode, {}); +interrupt!(device_not_available, {}); +interrupt_err!(double_fault, {}); +interrupt!(coprocessor_segment_overrun, {}); +interrupt_err!(invalid_tss, {}); +interrupt_err!(segment_not_present, {}); +interrupt_err!(stack_segment, {}); +interrupt_err!(general_protection, {}); + +pub extern "x86-interrupt" fn page_fault( + stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode) +{ + println!("Exception: page_fault"); + println!("Error code: {:#b}", code); + println!("{:#?}", stack_frame); + flush!(); +} + +interrupt!(x87_fpu, {}); +interrupt_err!(alignment_check, {}); +interrupt!(machine_check, {}); +interrupt!(simd, {}); +interrupt!(virtualization, {}); +interrupt_err!(security, {}); diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs new file mode 100644 index 00000000..3460f22d --- /dev/null +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -0,0 +1,6 @@ +use x86::structures::idt::*; + +interrupt!(keyboard, { + println!("key pressed!"); + flush!(); +}); diff --git a/kernel-rs/src/arch/x86/interrupt/mod.rs b/kernel-rs/src/arch/x86/interrupt/mod.rs new file mode 100644 index 00000000..e024f5c2 --- /dev/null +++ b/kernel-rs/src/arch/x86/interrupt/mod.rs @@ -0,0 +1,46 @@ +use x86::structures::idt::*; + +#[macro_use] pub mod exception; +#[macro_use] pub mod irq; + + +lazy_static! { + static ref IDT: Idt = { + let mut idt = Idt::new(); + + // set up CPU exceptions + idt.breakpoint.set_handler_fn(exception::breakpoint); + idt.debug.set_handler_fn(exception::debug); + idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable); + idt.breakpoint.set_handler_fn(exception::breakpoint); + idt.overflow.set_handler_fn(exception::overflow); + idt.bound_range_exceeded.set_handler_fn(exception::bound_range); + idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); + idt.device_not_available.set_handler_fn(exception::device_not_available); + idt.double_fault.set_handler_fn(exception::double_fault); + idt.segment_not_present.set_handler_fn(exception::segment_not_present); + idt.stack_segment_fault.set_handler_fn(exception::stack_segment); + idt.general_protection_fault.set_handler_fn(exception::general_protection); + idt.page_fault.set_handler_fn(exception::page_fault); + idt.x87_floating_point.set_handler_fn(exception::x87_fpu); + idt.alignment_check.set_handler_fn(exception::alignment_check); + idt.machine_check.set_handler_fn(exception::machine_check); + idt.simd_floating_point.set_handler_fn(exception::simd); + idt.virtualization.set_handler_fn(exception::virtualization); + + // set up IRQs + idt.interrupts[0].set_handler_fn(irq::keyboard); + idt.interrupts[1].set_handler_fn(irq::keyboard); + idt.interrupts[2].set_handler_fn(irq::keyboard); + idt + }; +} + +// pub fn init(memory_controller: &mut ::memory::MemoryController) { +pub fn init() { + // let double_fault_stack = memory_controller.alloc_stack(1) + // .expect("could not allocate double fault stack"); + // println!("DF stack: {:#?}", double_fault_stack); + // flush!(); + IDT.load(); +} diff --git a/kernel-rs/src/arch/x86/macros.rs b/kernel-rs/src/arch/x86/macros.rs new file mode 100644 index 00000000..94b41202 --- /dev/null +++ b/kernel-rs/src/arch/x86/macros.rs @@ -0,0 +1,36 @@ +#[macro_export] +macro_rules! interrupt { + ($name:ident, $func:block) => { + pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) + { + println!("Exception: {}", stringify!($name)); + println!("{:#?}", stack_frame); + flush!(); + + #[allow(unused_variables)] + fn inner(stack: &mut ExceptionStackFrame) { + $func + } + inner(stack_frame); + } + } +} + +#[macro_export] +macro_rules! interrupt_err { + ($name:ident, $func:block) => { + pub extern "x86-interrupt" fn $name( + stack_frame: &mut ExceptionStackFrame, _error_code: u32) + { + println!("Exception: {}", stringify!($name)); + println!("{:#?}", stack_frame); + flush!(); + + #[allow(unused_variables)] + fn inner(stack: &mut ExceptionStackFrame) { + $func + } + inner(stack_frame); + } + } +} diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs new file mode 100644 index 00000000..da1e67cc --- /dev/null +++ b/kernel-rs/src/arch/x86/mod.rs @@ -0,0 +1,42 @@ +extern crate x86; + +#[macro_use] +pub mod macros; +pub mod paging; +pub mod interrupt; + +use multiboot2; +use acpi; + +#[no_mangle] +pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { + // parse multiboot2 info + let boot_info = multiboot2::load(multiboot_info_addr); + + // ACPI must be intialized BEFORE paging is active + if let Some(rsdp) = boot_info.rsdp_v2_tag() { + acpi::load(rsdp).expect("ACPI failed"); + } else if let Some(rsdp) = boot_info.rsdp_tag() { + acpi::load(rsdp).expect("ACPI failed"); + } else { + acpi::init().expect("ACPI failed"); + } + + // set up physical allocator + ::memory::init(&boot_info); + + // set up virtual mapping + let mut active_table = self::paging::init(&boot_info); + + // set up heap + ::allocator::init(&mut active_table); + + // after core has loaded + ::memory::init_noncore(); + + // set up interrupts + self::interrupt::init(); + + // primary CPU entry point + ::kmain(); +} diff --git a/kernel-rs/src/memory/paging/mapper.rs b/kernel-rs/src/arch/x86/paging/mapper.rs similarity index 51% rename from kernel-rs/src/memory/paging/mapper.rs rename to kernel-rs/src/arch/x86/paging/mapper.rs index 319f8827..128e82be 100644 --- a/kernel-rs/src/memory/paging/mapper.rs +++ b/kernel-rs/src/arch/x86/paging/mapper.rs @@ -1,10 +1,9 @@ -use memory::{PAGE_SIZE, FrameAllocator}; use core::ptr::Unique; use x86::structures::paging::*; use x86::instructions::tlb; use x86::usize_conversions::usize_from; use x86::*; -use super::paging::table::RecTable; +use super::table::RecTable; // virtual address of recursively mapped P2 // for protected mode non PAE @@ -59,43 +58,38 @@ impl Mapper { } /// map a virtual page to a physical frame in the page tables - pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags, - allocator: &mut A) - where A: FrameAllocator - { - let p2 = self.p2_mut(); - let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index())), allocator); - assert!(p1[page.p1_index()].is_unused()); - p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); - } + pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags) + { + let p2 = self.p2_mut(); + let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index()))); + assert!(p1[page.p1_index()].is_unused()); + p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); + } - pub fn map(&mut self, page: Page, flags: PageTableFlags, allocator: &mut A) - where A: FrameAllocator - { - let frame = allocator.allocate_frame().expect("out of memory"); - self.map_to(page, frame, flags, allocator) - } + pub fn map(&mut self, page: Page, flags: PageTableFlags) + { + let frame = ::memory::allocate_frames(1).expect("out of frames"); + self.map_to(page, frame, flags) + } - pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags, allocator: &mut A) - where A: FrameAllocator - { - let virt_addr = VirtAddr::new(frame.start_address().as_u32()); - let page = Page::containing_address(virt_addr); - self.map_to(page, frame, flags, allocator); - } + pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags) + { + let virt_addr = VirtAddr::new(frame.start_address().as_u32()); + let page = Page::containing_address(virt_addr); + self.map_to(page, frame, flags); + } - pub fn unmap(&mut self, page: Page, allocator: &mut A) - where A: FrameAllocator - { - assert!(self.translate(page.start_address()).is_some()); + pub fn unmap(&mut self, page: Page) + { + assert!(self.translate(page.start_address()).is_some()); - let p1 = self.p2_mut() - .next_table_mut(usize_from(u32::from(page.p2_index()))) - .expect("mapping code does not support huge pages"); - let frame = p1[page.p1_index()].pointed_frame().unwrap(); - p1[page.p1_index()].set_unused(); - tlb::flush(page.start_address()); - // TODO - // allocator.deallocate_frame(frame); - } + let p1 = self.p2_mut() + .next_table_mut(usize_from(u32::from(page.p2_index()))) + .expect("mapping code does not support huge pages"); + let frame = p1[page.p1_index()].pointed_frame().unwrap(); + p1[page.p1_index()].set_unused(); + tlb::flush(page.start_address()); + // TODO + ::memory::deallocate_frames(frame, 1); + } } diff --git a/kernel-rs/src/memory/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs similarity index 85% rename from kernel-rs/src/memory/paging/mod.rs rename to kernel-rs/src/arch/x86/paging/mod.rs index 5b3fbd67..1a4db1c7 100644 --- a/kernel-rs/src/memory/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -4,7 +4,7 @@ mod table; mod temporary_page; mod mapper; -use memory::*; +// use memory::*; use self::mapper::Mapper; use self::temporary_page::TemporaryPage; use core::ops::{Deref, DerefMut}; @@ -12,6 +12,19 @@ use multiboot2::BootInformation; use x86::*; use x86::registers::control::Cr3; use x86::instructions::tlb; +use x86::structures::paging::*; +use multiboot2; + +/// should be called only once +pub fn init(boot_info: &multiboot2::BootInformation) -> ActivePageTable { + use x86::registers::control::*; + Cr4::add(Cr4Flags::PSE); + Cr0::add(Cr0Flags::PAGING | Cr0Flags::WRITE_PROTECT); + + let active_table = remap_the_kernel(boot_info); + + active_table +} pub struct ActivePageTable { mapper: Mapper, @@ -92,27 +105,26 @@ impl InactivePageTable { } } -pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) - -> ActivePageTable - where A: FrameAllocator +pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable { - let mut temporary_page = TemporaryPage::new(Page{number: 0xcafe}, allocator); + let mut temporary_page = TemporaryPage::new(Page{number: 0xcafe}); let mut active_table = unsafe { ActivePageTable::new() }; let mut new_table = { - let frame = allocator.allocate_frame().expect("no more frames"); + let frame = ::memory::allocate_frames(1).expect("no more frames"); InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; active_table.with(&mut new_table, &mut temporary_page, |mapper| { - // identity map the VGA text buffer + // id map vga buffer let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); - mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE, allocator); + mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE); let elf_sections_tag = boot_info.elf_sections_tag() .expect("Memory map tag required"); + // id map kernel sections for section in elf_sections_tag.sections() { if !section.is_allocated() { continue; @@ -126,16 +138,17 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) let end_frame = PhysFrame::containing_address( PhysAddr::new(section.end_address() as u32 - 1)); for frame in start_frame..end_frame + 1 { - mapper.identity_map(frame, flags, allocator); + mapper.identity_map(frame, flags); } } + // id map multiboot let multiboot_start = PhysFrame::containing_address( PhysAddr::new(boot_info.start_address() as u32)); let multiboot_end = PhysFrame::containing_address( PhysAddr::new(boot_info.end_address() as u32 - 1)); for frame in multiboot_start..multiboot_end + 1 { - mapper.identity_map(frame, PageTableFlags::PRESENT, allocator); + mapper.identity_map(frame, PageTableFlags::PRESENT); } }); @@ -144,7 +157,7 @@ pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation) let old_p2_page = Page::containing_address( VirtAddr::new(old_table.p2_frame.start_address().as_u32())); - active_table.unmap(old_p2_page, allocator); + active_table.unmap(old_p2_page); active_table } @@ -163,10 +176,6 @@ fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) if elf_flags.contains(ElfSectionFlags::WRITABLE) { flags = flags | PageTableFlags::WRITABLE; } - // LONG MODE STUFF - // if !elf_flags.contains(ELF_SECTION_EXECUTABLE) { - // flags = flags | PageTableFlags::NO_EXECUTE; - // } flags } diff --git a/kernel-rs/src/memory/paging/table.rs b/kernel-rs/src/arch/x86/paging/table.rs similarity index 53% rename from kernel-rs/src/memory/paging/table.rs rename to kernel-rs/src/arch/x86/paging/table.rs index 70a9731e..41eec7e0 100644 --- a/kernel-rs/src/memory/paging/table.rs +++ b/kernel-rs/src/arch/x86/paging/table.rs @@ -1,15 +1,12 @@ -use memory::*; use x86::structures::paging::*; -// use x86::ux::*; pub trait RecTable { fn next_table_address(&self, index: usize) -> Option; fn next_table(&self, index: usize) -> Option<&PageTable>; fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; - fn next_table_create(&mut self, - index: usize, - allocator: &mut A) + fn next_table_create(&mut self, + index: usize) -> &mut PageTable; } @@ -35,18 +32,17 @@ impl RecTable for PageTable .map(|address| unsafe { &mut *(address as *mut _) }) } - fn next_table_create(&mut self, - index: usize, - allocator: &mut A) -> &mut PageTable - where A: FrameAllocator - { - if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE), - "mapping code does not support huge pages"); - let frame = allocator.allocate_frame().expect("no frames available"); - self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - self.next_table_mut(index).expect("next_table_mut gave None").zero() - } - self.next_table_mut(index).expect("no next table 2") + fn next_table_create(&mut self, + index: usize) -> &mut PageTable + { + if self.next_table(index).is_none() { + assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE), + "mapping code does not support huge pages"); + let frame = ::memory::allocate_frames(1) + .expect("out of memory"); + self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); + self.next_table_mut(index).expect("next_table_mut gave None").zero() } + self.next_table_mut(index).expect("no next table 2") + } } diff --git a/kernel-rs/src/memory/paging/temporary_page.rs b/kernel-rs/src/arch/x86/paging/temporary_page.rs similarity index 51% rename from kernel-rs/src/memory/paging/temporary_page.rs rename to kernel-rs/src/arch/x86/paging/temporary_page.rs index c7e9b094..becdb0fc 100644 --- a/kernel-rs/src/memory/paging/temporary_page.rs +++ b/kernel-rs/src/arch/x86/paging/temporary_page.rs @@ -1,22 +1,16 @@ use super::ActivePageTable; -use memory::{FrameAllocator}; use x86::*; use x86::structures::paging::*; pub struct TemporaryPage { pub page: Page, - allocator: TinyAllocator, } impl TemporaryPage { - pub fn new(page: Page, allocator: &mut A) -> TemporaryPage - where A: FrameAllocator - { - TemporaryPage { - page: page, - allocator: TinyAllocator::new(allocator), - } - } + pub fn new(page: Page) -> TemporaryPage + { + TemporaryPage { page: page } + } /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. @@ -25,7 +19,7 @@ impl TemporaryPage { { assert!(active_table.translate_page(self.page).is_none(), "temporary page is already mapped"); - active_table.map_to(self.page, frame, PageTableFlags::WRITABLE, &mut self.allocator); + active_table.map_to(self.page, frame, PageTableFlags::WRITABLE); // this kind of check should be done in a test routine assert!(active_table.translate_page(self.page).is_some(), "temporary page was not mapped"); @@ -34,7 +28,7 @@ impl TemporaryPage { /// Unmaps the temporary page in the active table. pub fn unmap(&mut self, active_table: &mut ActivePageTable) { - active_table.unmap(self.page, &mut self.allocator) + active_table.unmap(self.page) } /// Maps the temporary page to the given page table frame in the active @@ -46,36 +40,3 @@ impl TemporaryPage { unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } } } - -struct TinyAllocator([Option; 1]); - -impl TinyAllocator { - fn new(allocator: &mut A) -> TinyAllocator - where A: FrameAllocator - { - let mut f = || allocator.allocate_frame(); - let frames = [f()]; - TinyAllocator(frames) - } -} - -impl FrameAllocator for TinyAllocator { - fn allocate_frame(&mut self) -> Option { - for frame_option in &mut self.0 { - if frame_option.is_some() { - return frame_option.take(); - } - } - None - } - - fn deallocate_frame(&mut self, frame: PhysFrame) { - for frame_option in &mut self.0 { - if frame_option.is_none() { - *frame_option = Some(frame); - return; - } - } - panic!("Tiny allocator can only hold 1 frame."); - } -} diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index 8c69f1ce..45ec32c2 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -1,5 +1,5 @@ global x86_start -extern kmain +extern x86_rust_start section .text bits 32 @@ -11,7 +11,7 @@ x86_start: mov fs, ax mov gs, ax - call kmain + call x86_rust_start cli ; clear interrupt HALT: diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs deleted file mode 100644 index aba00559..00000000 --- a/kernel-rs/src/interrupts/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -use x86::structures::idt::*; - -lazy_static! { - static ref IDT: Idt = { - let mut idt = Idt::new(); - idt.breakpoint.set_handler_fn(breakpoint_handler); - idt.double_fault.set_handler_fn(double_fault_handler); - // int #1 is keyboard - idt.interrupts[1].set_handler_fn(::keyboard::kbd_callback); - idt - }; -} - -pub fn init(memory_controller: &mut ::memory::MemoryController) { - let double_fault_stack = memory_controller.alloc_stack(1) - .expect("could not allocate double fault stack"); - // println!("DF stack: {:#?}", double_fault_stack); - // flush!(); - IDT.load(); -} - -extern "x86-interrupt" fn double_fault_handler( - stack_frame: &mut ExceptionStackFrame, _error_code: u32) -{ - println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); - flush!(); -} - -extern "x86-interrupt" fn breakpoint_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); - flush!(); -} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index de6859db..c13360d4 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,5 +1,4 @@ extern crate core; -use x86::structures::idt::*; use cpuio; use vga; @@ -77,8 +76,7 @@ fn check_key_state(key: u8) -> (bool, usize) { } } -pub extern "x86-interrupt" fn kbd_callback( - stack_frame: &mut ExceptionStackFrame) { +pub fn kbd_callback() { println!("kbd callback called"); flush!(); static mut SHIFT: bool = false; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index cb08eff0..5bb68a28 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,5 +1,6 @@ //! project hosted on [github](https://github.com/jzck/kernel) - +//! exclusively x86 +//! #![no_std] #![feature(lang_items)] #![feature(const_fn)] @@ -13,12 +14,16 @@ #![feature(abi_x86_interrupt)] extern crate rlibc; -extern crate multiboot2; -#[macro_use] extern crate lazy_static; #[macro_use] extern crate alloc; +#[macro_use] extern crate lazy_static; +extern crate spin; +extern crate multiboot2; +extern crate slab_allocator; + +// used by arch/x86, need conditional compilation here extern crate x86; -/// 80x25 screen and simplistic terminal driver +/// 80x25 terminal driver #[macro_use] pub mod vga; /// PS/2 detection and processing pub mod keyboard; @@ -26,40 +31,21 @@ pub mod keyboard; pub mod console; /// rust wrappers around cpu I/O instructions. pub mod cpuio; -/// ACPI self-content module +/// ACPI self contained module pub mod acpi; -/// physical frame allocator + paging module + heap allocator +/// Heap allocators +pub mod allocator; +/// Memory management pub mod memory; -/// x86 interruptions -pub mod interrupts; +/// arch specific entry points +pub mod arch; -fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { +/// kernel entry point. arch module is responsible for calling this +pub fn kmain() -> ! { - let boot_info = unsafe { multiboot2::load(multiboot_info_addr)}; - - // ACPI must be intialized BEFORE paging (memory::init()) is active - if let Some(rsdp) = boot_info.rsdp_v2_tag() { - acpi::load(rsdp)?; - } else if let Some(rsdp) = boot_info.rsdp_tag() { - acpi::load(rsdp)?; - } else { - acpi::init()?; - } - - let mut memory_controller = memory::init(&boot_info); - interrupts::init(&mut memory_controller); + // vga is specific to chipset not cpu vga::init(); - Ok(()) -} - -#[no_mangle] -pub extern fn kmain(multiboot_info_addr: usize) -> ! { - if let Err(msg) = init_kernel(multiboot_info_addr) { - println!("Kernel initialization has failed: {}", msg); - cpuio::halt(); - } - // x86::instructions::interrupts::int3(); // fn stack_overflow() { stack_overflow(); } @@ -69,13 +55,13 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { // *(0xdead as *mut u32) = 42; // }; + println!("at main now!"); + loop {} } #[lang = "eh_personality"] #[no_mangle] -pub extern fn eh_personality() { - -} +pub extern fn eh_personality() {} #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) @@ -87,11 +73,8 @@ pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32 loop {} } -use memory::BumpAllocator; - pub const HEAP_START: usize = (1 << 22); //first entry of p2 -pub const HEAP_SIZE: usize = 100 * 1024; //100 KiB +pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB #[global_allocator] -static HEAP_ALLOCATOR: BumpAllocator = BumpAllocator::new(HEAP_START, - HEAP_START + HEAP_SIZE); +static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator; diff --git a/kernel-rs/src/memory/area_allocator.rs b/kernel-rs/src/memory/bump.rs similarity index 62% rename from kernel-rs/src/memory/area_allocator.rs rename to kernel-rs/src/memory/bump.rs index 6a24bb94..d45e595c 100644 --- a/kernel-rs/src/memory/area_allocator.rs +++ b/kernel-rs/src/memory/bump.rs @@ -1,8 +1,9 @@ -use memory::*; use multiboot2::{MemoryAreaIter, MemoryArea}; use x86::*; +use x86::structures::paging::PhysFrame; +use super::FrameAllocator; -pub struct AreaFrameAllocator { +pub struct BumpFrameAllocator { next_free_frame: PhysFrame, current_area: Option<&'static MemoryArea>, areas: MemoryAreaIter, @@ -12,11 +13,11 @@ pub struct AreaFrameAllocator { multiboot_end: PhysFrame, } -impl AreaFrameAllocator { +impl BumpFrameAllocator { pub fn new(kernel_start: usize, kernel_end: usize, multiboot_start: usize, multiboot_end: usize, - memory_areas: MemoryAreaIter) -> AreaFrameAllocator { - let mut allocator = AreaFrameAllocator { + memory_areas: MemoryAreaIter) -> BumpFrameAllocator { + let mut allocator = BumpFrameAllocator { next_free_frame: PhysFrame { number: 0 }, current_area: None, areas: memory_areas, @@ -49,37 +50,42 @@ impl AreaFrameAllocator { } } -impl FrameAllocator for AreaFrameAllocator { - fn allocate_frame(&mut self) -> Option { +impl FrameAllocator for BumpFrameAllocator { + fn allocate_frames(&mut self, count: usize) -> Option { + if count == 0 { return None }; if let Some(area) = self.current_area { - let frame = PhysFrame { number: self.next_free_frame.number }; + let start_frame = PhysFrame { number: self.next_free_frame.number }; + let end_frame = PhysFrame { number: self.next_free_frame.number + count as u32 - 1 }; + let current_area_last_frame = PhysFrame::containing_address( PhysAddr::new(area.end_address() as u32)); - if frame > current_area_last_frame { + if end_frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); - } else if frame >= self.kernel_start && frame <= self.kernel_end { + } else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) { // frame used by kernel self.next_free_frame = PhysFrame { number: self.kernel_end.number + 1, - } - } else if frame >= self.multiboot_start && frame <= self.multiboot_end { + }; + } else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end) || (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end) { // frame used by multiboot self.next_free_frame = PhysFrame { number: self.multiboot_end.number + 1, - } + }; } else { - self.next_free_frame.number += 1; - return Some(frame); + self.next_free_frame.number += count as u32; + return Some(start_frame); } // try again with next_free_frame - self.allocate_frame() + self.allocate_frames(count) } else { None } } - fn deallocate_frame(&mut self, frame: PhysFrame) { - unimplemented!(); + fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) { + // bump doesnt deallocate, must be used inside of a recycler + println!("lost frames {:#x} ({})", frame.start_address().as_u32(), count); + // unimplemented!(); } } diff --git a/kernel-rs/src/memory/heap_allocator.rs b/kernel-rs/src/memory/heap_allocator.rs deleted file mode 100644 index d6ed05b6..00000000 --- a/kernel-rs/src/memory/heap_allocator.rs +++ /dev/null @@ -1,60 +0,0 @@ -use alloc::heap::{Alloc, AllocErr, Layout}; -use core::sync::atomic::{AtomicUsize, Ordering}; - -#[derive(Debug)] -pub struct BumpAllocator { - heap_start: usize, - heap_end: usize, - next: AtomicUsize, -} - -impl BumpAllocator { - pub const fn new(heap_start: usize, heap_end: usize) -> Self { - Self { heap_start, heap_end, next: AtomicUsize::new(heap_start) } - } -} - -unsafe impl<'a> Alloc for &'a BumpAllocator { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - loop { - // load current state of the `next` field - let current_next = self.next.load(Ordering::Relaxed); - let alloc_start = align_up(current_next, layout.align()); - let alloc_end = alloc_start.saturating_add(layout.size()); - - if alloc_end <= self.heap_end { - // update the `next` pointer if it still has the value `current_next` - let next_now = self.next.compare_and_swap(current_next, alloc_end, - Ordering::Relaxed); - if next_now == current_next { - return Ok(alloc_start as *mut u8); - } - } else { - return Err(AllocErr::Exhausted{ request: layout }) - } - } - } - - unsafe fn dealloc(&mut self, pt: *mut u8, layout: Layout) { - // TODO - // do nothing, leak memory - } -} - -/// Align downwards. Returns the greatest x with alignment `align` -/// so that x <= addr. The alignment must be a power of 2. -pub fn align_down(addr: usize, align: usize) -> usize { - if align.is_power_of_two() { - addr & !(align - 1) - } else if align == 0 { - addr - } else { - panic!("`align` must be a power of 2"); - } -} - -/// Align upwards. Returns the smallest x with alignment `align` -/// so that x >= addr. The alignment must be a power of 2. -pub fn align_up(addr: usize, align: usize) -> usize { - align_down(addr + align - 1, align) -} diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index aad7c4ca..01514299 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,44 +1,26 @@ -mod area_allocator; -mod heap_allocator; -mod stack_allocator; -mod paging; +mod bump; +mod recycle; -pub use self::area_allocator::*; -pub use self::heap_allocator::*; -pub use self::stack_allocator::*; -pub use self::paging::remap_the_kernel; use multiboot2; -use x86::*; use x86::structures::paging::*; +use spin::Mutex; + +use self::bump::BumpFrameAllocator; +use self::recycle::RecycleAllocator; pub trait FrameAllocator { - fn allocate_frame(&mut self) -> Option; - fn deallocate_frame(&mut self, frame: PhysFrame); + fn allocate_frames(&mut self, size: usize) -> Option; + fn deallocate_frames(&mut self, frame: PhysFrame, size: usize); } -pub struct MemoryController { - active_table: paging::ActivePageTable, - frame_allocator: AreaFrameAllocator, - stack_allocator: StackAllocator, +pub struct MemoryControler { + frame_allocator: RecycleAllocator, + // stack_allocator: StackAllocator, } -impl MemoryController { - pub fn alloc_stack(&mut self, size_in_pages: usize) -> Option { - let &mut MemoryController { ref mut active_table, - ref mut frame_allocator, - ref mut stack_allocator } = self; - - stack_allocator.alloc_stack(active_table, frame_allocator, - size_in_pages) - } -} - -/// memory initialisation should only be called once -pub fn init(boot_info: &multiboot2::BootInformation) -> MemoryController { - use x86::registers::control::{Cr0, Cr4, Cr0Flags, Cr4Flags}; - Cr4::add(Cr4Flags::PSE); - Cr0::add(Cr0Flags::PAGING | Cr0Flags::WRITE_PROTECT); +static MEMORY_CONTROLER: Mutex> = Mutex::new(None); +pub fn init(boot_info: &multiboot2::BootInformation) { let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); let memory_map_tag = boot_info.memory_map_tag().unwrap(); @@ -52,34 +34,48 @@ pub fn init(boot_info: &multiboot2::BootInformation) -> MemoryController { .map(|s| s.start_address() + s.size()) .max().unwrap(); - let mut frame_allocator = self::AreaFrameAllocator::new( + let bump_allocator = BumpFrameAllocator::new( kernel_start as usize, kernel_end as usize, boot_info.start_address(), boot_info.end_address(), memory_map_tag.memory_areas()); - let mut active_table = paging::remap_the_kernel(&mut frame_allocator, - boot_info); - use {HEAP_START, HEAP_SIZE}; + let frame_allocator = RecycleAllocator::new(bump_allocator); - let heap_start_page = Page::containing_address( - VirtAddr::new(HEAP_START as u32)); - let heap_end_page = Page::containing_address( - VirtAddr::new(HEAP_START as u32 + HEAP_SIZE as u32 - 1)); + // let stack_allocator = { + // let stack_alloc_start = heap_end_page + 1; + // let stack_alloc_end = stack_alloc_start + 100; + // let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; + // StackAllocator::new(stack_alloc_range) + // }; - for page in heap_start_page..heap_end_page { - active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); - } - - let stack_allocator = { - let stack_alloc_start = heap_end_page + 1; - let stack_alloc_end = stack_alloc_start + 100; - let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; - StackAllocator::new(stack_alloc_range) - }; - - MemoryController { - active_table, + *MEMORY_CONTROLER.lock() = Some(MemoryControler { frame_allocator, - stack_allocator, + // stack_allocator, + }); +} + +pub fn allocate_frames(count: usize) -> Option { + if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { + controler.frame_allocator.allocate_frames(count) + } else { + panic!("frame allocator not initialized!"); + } +} + +pub fn deallocate_frames(frame: PhysFrame, count: usize) { + if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { + controler.frame_allocator.deallocate_frames(frame, count) + } else { + panic!("frame allocator not initialized!"); + } +} + +/// Init memory module after core +/// Must be called once, and only once, +pub unsafe fn init_noncore() { + if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { + controler.frame_allocator.set_core(true); + } else { + panic!("frame allocator not initialized"); } } diff --git a/kernel-rs/src/memory/recycle.rs b/kernel-rs/src/memory/recycle.rs new file mode 100644 index 00000000..6cebe2b4 --- /dev/null +++ b/kernel-rs/src/memory/recycle.rs @@ -0,0 +1,105 @@ +//! Recycle allocator +//! Uses freed frames if possible, then uses inner allocator + +use alloc::Vec; +use x86::*; +use x86::structures::paging::*; +use super::*; + +pub struct RecycleAllocator { + inner: T, + core: bool, + free: Vec<(usize, usize)>, +} + +impl RecycleAllocator { + pub fn new(inner: T) -> Self { + Self { + inner: inner, + core: true, + free: Vec::new(), + } + } + + pub fn set_core(&mut self, core: bool) { + self.core = core; + } + + fn merge(&mut self, address: usize, count: usize) -> bool { + for i in 0 .. self.free.len() { + let changed = { + let free = &mut self.free[i]; + if address + count * 4096 == free.0 { + free.0 = address; + free.1 += count; + true + } else if free.0 + free.1 * 4096 == address { + free.1 += count; + true + } else { + false + } + }; + + if changed { + //TODO: Use do not use recursion + let (address, count) = self.free[i]; + if self.merge(address, count) { + self.free.remove(i); + } + return true; + } + } + + false + } +} + +impl FrameAllocator for RecycleAllocator { + fn allocate_frames(&mut self, count: usize) -> Option { + let mut small_i = None; + { + let mut small = (0, 0); + for i in 0..self.free.len() { + let free = self.free[i]; + // Later entries can be removed faster + if free.1 >= count { + if free.1 <= small.1 || small_i.is_none() { + small_i = Some(i); + small = free; + } + } + } + } + + if let Some(i) = small_i { + let (address, remove) = { + let free = &mut self.free[i]; + free.1 -= count; + (free.0 + free.1 * 4096, free.1 == 0) + }; + + if remove { + self.free.remove(i); + } + + //println!("Restoring frame {:?}, {}", frame, count); + Some(PhysFrame::containing_address(PhysAddr::new(address as u32))) + } else { + //println!("No saved frames {}", count); + self.inner.allocate_frames(count) + } + } + + fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) { + // we cant use vec! before the heap has been initialized + if self.core { + self.inner.deallocate_frames(frame, count); + } else { + let address = frame.start_address().as_u32() as usize; + if ! self.merge(address, count) { + self.free.push((address, count)); + } + } + } +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index dc87c0d9..b773b4ff 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -123,6 +123,7 @@ impl Writer { self.buffer[i] = b' '; self.buffer[i + 1] = 0; self.flush(); + // flush!(); } pub fn write_byte(&mut self, byte: u8) { @@ -179,7 +180,6 @@ impl Writer { for col in 0..BUFFER_COLS/2 { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; - self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2) + 1] = 0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; @@ -214,5 +214,7 @@ pub fn init() { format_args!("{: ^80}", r#" | : ;| : .' "#), format_args!("{: ^80}", r#" ' ,/ ; | .' "#), format_args!("{: ^80}", r#" '--' `---' "#)); + set_color!(); unsafe { VGA.prompt(); } + unsafe { VGA.flush(); } } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index da544c83..3cef2945 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit da544c834b3f3d8b53f456c48b3aafa58d09198a +Subproject commit 3cef2945c884857a6ef44c942a3d949790792db7 From c24ac47698e7960ee8cfb2a261cd2e311fee697b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 29 Mar 2018 20:29:04 +0200 Subject: [PATCH 097/151] pio and x86/pic --- kernel-rs/src/arch/x86/device/mod.rs | 5 ++ kernel-rs/src/arch/x86/device/pic.rs | 64 +++++++++++++ kernel-rs/src/arch/x86/interrupt/exception.rs | 5 +- kernel-rs/src/arch/x86/interrupt/mod.rs | 4 +- kernel-rs/src/arch/x86/mod.rs | 9 +- kernel-rs/src/io/mod.rs | 26 ++++++ kernel-rs/src/io/pio.rs | 89 +++++++++++++++++++ kernel-rs/src/lib.rs | 5 +- 8 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 kernel-rs/src/arch/x86/device/mod.rs create mode 100644 kernel-rs/src/arch/x86/device/pic.rs create mode 100644 kernel-rs/src/io/mod.rs create mode 100644 kernel-rs/src/io/pio.rs diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs new file mode 100644 index 00000000..18600155 --- /dev/null +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -0,0 +1,5 @@ +pub mod pic; + +pub fn init() { + unsafe { pic::init(); } +} diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs new file mode 100644 index 00000000..6030f642 --- /dev/null +++ b/kernel-rs/src/arch/x86/device/pic.rs @@ -0,0 +1,64 @@ +use ::io::{Io, Pio}; + +pub static mut MASTER: Pic = Pic::new(0x20); +pub static mut SLAVE: Pic = Pic::new(0xA0); + +pub unsafe fn init() { + // Start initialization + MASTER.cmd.write(0x11); + SLAVE.cmd.write(0x11); + + // Set offsets + MASTER.data.write(0x20); + SLAVE.data.write(0x28); + + // Set up cascade + MASTER.data.write(4); + SLAVE.data.write(2); + + // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) + MASTER.data.write(1); + SLAVE.data.write(1); + + // Unmask interrupts + MASTER.data.write(0); + SLAVE.data.write(0); + + // Ack remaining interrupts + MASTER.ack(); + SLAVE.ack(); +} + +pub struct Pic { + cmd: Pio, + data: Pio, +} + +impl Pic { + pub const fn new(port: u16) -> Pic { + Pic { + cmd: Pio::new(port), + data: Pio::new(port + 1), + } + } + + pub fn ack(&mut self) { + self.cmd.write(0x20); + } + + pub fn mask_set(&mut self, irq: u8) { + assert!(irq < 8); + + let mut mask = self.data.read(); + mask |= 1 << irq; + self.data.write(mask); + } + + pub fn mask_clear(&mut self, irq: u8) { + assert!(irq < 8); + + let mut mask = self.data.read(); + mask &= !(1 << irq); + self.data.write(mask); + } +} diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 40674263..489c4011 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -5,7 +5,10 @@ use x86::structures::idt::*; interrupt!(divide_by_zero, {}); interrupt!(debug, {}); interrupt!(non_maskable, {}); -interrupt!(breakpoint, {}); +interrupt!(breakpoint, { + println!("testing here dont mind me"); + flush!(); +}); interrupt!(overflow, {}); interrupt!(bound_range, {}); interrupt!(invalid_opcode, {}); diff --git a/kernel-rs/src/arch/x86/interrupt/mod.rs b/kernel-rs/src/arch/x86/interrupt/mod.rs index e024f5c2..770d0f0c 100644 --- a/kernel-rs/src/arch/x86/interrupt/mod.rs +++ b/kernel-rs/src/arch/x86/interrupt/mod.rs @@ -29,9 +29,7 @@ lazy_static! { idt.virtualization.set_handler_fn(exception::virtualization); // set up IRQs - idt.interrupts[0].set_handler_fn(irq::keyboard); - idt.interrupts[1].set_handler_fn(irq::keyboard); - idt.interrupts[2].set_handler_fn(irq::keyboard); + idt[33].set_handler_fn(irq::keyboard); idt }; } diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index da1e67cc..887c6d18 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -4,6 +4,7 @@ extern crate x86; pub mod macros; pub mod paging; pub mod interrupt; +pub mod device; use multiboot2; use acpi; @@ -25,6 +26,12 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // set up physical allocator ::memory::init(&boot_info); + // pic + self::device::init(); + + // set up interrupts + self::interrupt::init(); + // set up virtual mapping let mut active_table = self::paging::init(&boot_info); @@ -34,8 +41,6 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // after core has loaded ::memory::init_noncore(); - // set up interrupts - self::interrupt::init(); // primary CPU entry point ::kmain(); diff --git a/kernel-rs/src/io/mod.rs b/kernel-rs/src/io/mod.rs new file mode 100644 index 00000000..3bb33f5f --- /dev/null +++ b/kernel-rs/src/io/mod.rs @@ -0,0 +1,26 @@ +mod pio; + +pub use self::pio::*; + +use core::ops::{BitAnd, BitOr, Not}; + +pub trait Io { + type Value: Copy + PartialEq + BitAnd + BitOr + Not; + + fn read(&self) -> Self::Value; + fn write(&mut self, value: Self::Value); + + #[inline(always)] + fn readf(&self, flags: Self::Value) -> bool { + (self.read() & flags) as Self::Value == flags + } + + #[inline(always)] + fn writef(&mut self, flags: Self::Value, value: bool) { + let tmp: Self::Value = match value { + true => self.read() | flags, + false => self.read() & !flags, + }; + self.write(tmp); + } +} diff --git a/kernel-rs/src/io/pio.rs b/kernel-rs/src/io/pio.rs new file mode 100644 index 00000000..2582066d --- /dev/null +++ b/kernel-rs/src/io/pio.rs @@ -0,0 +1,89 @@ +use core::marker::PhantomData; + +use super::*; + +/// Generic PIO +#[derive(Copy, Clone)] +pub struct Pio { + port: u16, + value: PhantomData, +} + +impl Pio { + /// Create a PIO from a given port + pub const fn new(port: u16) -> Self { + Pio:: { + port: port, + value: PhantomData, + } + } +} + +/// Read/Write for byte PIO +impl Io for Pio { + type Value = u8; + + /// Read + #[inline(always)] + fn read(&self) -> u8 { + let value: u8; + unsafe { + asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u8) { + unsafe { + asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} + +/// Read/Write for word PIO +impl Io for Pio { + type Value = u16; + + /// Read + #[inline(always)] + fn read(&self) -> u16 { + let value: u16; + unsafe { + asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u16) { + unsafe { + asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} + +/// Read/Write for doubleword PIO +impl Io for Pio { + type Value = u32; + + /// Read + #[inline(always)] + fn read(&self) -> u32 { + let value: u32; + unsafe { + asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + value + } + + /// Write + #[inline(always)] + fn write(&mut self, value: u32) { + unsafe { + asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); + } + } +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 5bb68a28..34129b8a 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -31,6 +31,7 @@ pub mod keyboard; pub mod console; /// rust wrappers around cpu I/O instructions. pub mod cpuio; +pub mod io; /// ACPI self contained module pub mod acpi; /// Heap allocators @@ -46,7 +47,9 @@ pub fn kmain() -> ! { // vga is specific to chipset not cpu vga::init(); + // x86::instructions::interrupts::disable(); // x86::instructions::interrupts::int3(); + // x86::instructions::interrupts::enable(); // fn stack_overflow() { stack_overflow(); } // stack_overflow(); @@ -55,8 +58,6 @@ pub fn kmain() -> ! { // *(0xdead as *mut u32) = 42; // }; - println!("at main now!"); - loop {} } From 42e06809acc2b19614cefe02bfbd371e39325e43 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 29 Mar 2018 20:32:23 +0200 Subject: [PATCH 098/151] x86lib update --- kernel-rs/src/arch/x86/mod.rs | 5 +++-- kernel-rs/src/lib.rs | 2 +- kernel-rs/x86 | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 887c6d18..bef3cee1 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -26,8 +26,6 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // set up physical allocator ::memory::init(&boot_info); - // pic - self::device::init(); // set up interrupts self::interrupt::init(); @@ -38,6 +36,9 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // set up heap ::allocator::init(&mut active_table); + // pic + self::device::init(); + // after core has loaded ::memory::init_noncore(); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 34129b8a..f4dc049a 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -29,7 +29,7 @@ extern crate x86; pub mod keyboard; /// simplisitc kernel commands pub mod console; -/// rust wrappers around cpu I/O instructions. +/// rust wrappers around cpu I/O instructions., cpuio.rs needs to go in favour of io module pub mod cpuio; pub mod io; /// ACPI self contained module diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 3cef2945..ea8512f4 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 3cef2945c884857a6ef44c942a3d949790792db7 +Subproject commit ea8512f4c21c6c84578e04eff1f0b4662f089cd9 From 19bf69bb290627693189edbf4b94e6b756713b47 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 29 Mar 2018 20:41:36 +0200 Subject: [PATCH 099/151] readme --- kernel-rs/README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 14731766..6f7bfaf4 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -23,12 +23,16 @@ cargo install xargo ### running -`make run` runs the OS in a tmux window with `qemu` + `gdb` -`make iso` generate an iso to run wherever +`make iso` generate the iso +`make qemu` runs the OS in a tmux window with `qemu` + `gdb` -# References +### todo + + - remove assembly for a pure rust entry point + - replace grub with something lighter + +### inspiration - [wiki.osdev.org](https://wiki.osdev.org) is a fucking goldmine - - [wiki.osdev.org/Rust](https://wiki.osdev.org/Rust) everything rust related to OSes - - [Writing an OS in rust](https://os.phil-opp.com/) extremely helpful to get things going on x86 and nightly rust - - [Rust OS comparison](https://github.com/flosse/rust-os-comparison) roundup of current projects + - [Phil Opperman's "Writing an OS in rust"](https://os.phil-opp.com/) + - [Redox kernel](https://github.com/redox/kernel) From 0f79f2843c23bf578b37c7014076a0261b273684 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 5 Apr 2018 12:25:53 +0200 Subject: [PATCH 100/151] cpuid support --- kernel-rs/.gitmodules | 3 + kernel-rs/Cargo.toml | 7 +- kernel-rs/rust-cpuid | 1 + kernel-rs/src/arch/x86/device/cpu.rs | 133 ++++++++++++++++++++ kernel-rs/src/arch/x86/device/local_apic.rs | 23 ++++ kernel-rs/src/arch/x86/device/mod.rs | 9 +- kernel-rs/src/arch/x86/device/pic.rs | 40 ++++-- kernel-rs/src/arch/x86/idt.rs | 57 +++++++++ kernel-rs/src/arch/x86/interrupt/irq.rs | 47 ++++++- kernel-rs/src/arch/x86/interrupt/mod.rs | 42 ------- kernel-rs/src/arch/x86/mod.rs | 15 +-- kernel-rs/src/cpuio.rs | 7 ++ kernel-rs/src/keyboard.rs | 2 - kernel-rs/src/lib.rs | 10 +- kernel-rs/src/vga/mod.rs | 30 ++--- kernel-rs/x86 | 2 +- 16 files changed, 339 insertions(+), 89 deletions(-) create mode 160000 kernel-rs/rust-cpuid create mode 100644 kernel-rs/src/arch/x86/device/cpu.rs create mode 100644 kernel-rs/src/arch/x86/device/local_apic.rs create mode 100644 kernel-rs/src/arch/x86/idt.rs diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules index 820f6043..782f58ec 100644 --- a/kernel-rs/.gitmodules +++ b/kernel-rs/.gitmodules @@ -4,3 +4,6 @@ [submodule "x86"] path = x86 url = https://github.com/jzck/x86.git +[submodule "rust-cpuid"] + path = rust-cpuid + url = https://github.com/jzck/rust-cpuid diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 9f28fcab..1c8920b7 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bluesnow" version = "0.1.0" -authors = ["Jack Halford ", "William Escande "] +authors = ["Jack Halford ", "William Escande "] [lib] crate-type = ["staticlib"] @@ -10,9 +10,10 @@ crate-type = ["staticlib"] rlibc = "1.0" bitflags = "1.0.1" spin = "0.4" -multiboot2 = { path = "multiboot2-elf64" } slab_allocator = "0.3.1" -x86 = { path = "x86" } +multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag +x86 = { path = "x86" } # forked for IA32 +raw-cpuid = { path = "rust-cpuid" } # forked for IA32 [dependencies.lazy_static] version = "1.0.0" diff --git a/kernel-rs/rust-cpuid b/kernel-rs/rust-cpuid new file mode 160000 index 00000000..07299b93 --- /dev/null +++ b/kernel-rs/rust-cpuid @@ -0,0 +1 @@ +Subproject commit 07299b93df57fcee2b6aec61502a5135b99967f8 diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/x86/device/cpu.rs new file mode 100644 index 00000000..cf7e3fbb --- /dev/null +++ b/kernel-rs/src/arch/x86/device/cpu.rs @@ -0,0 +1,133 @@ +extern crate raw_cpuid; + +use core::fmt::{Result}; + +use self::raw_cpuid::CpuId; + +pub fn cpu_info() -> Result { + let cpuid = CpuId::new(); + + if let Some(info) = cpuid.get_vendor_info() { + println!("CPU Vendor: {}", info.as_string()); + } + + if let Some(info) = cpuid.get_extended_function_info() { + if let Some(brand) = info.processor_brand_string() { + println!("CPU Model: {}", brand); + } + } + + if let Some(info) = cpuid.get_processor_frequency_info() { + println!("CPU Base MHz: {}", info.processor_base_frequency()); + println!("CPU Max MHz: {}", info.processor_max_frequency()); + println!("Bus MHz: {}", info.bus_frequency()); + } else { + set_color!(Red); + println!("couldn't retrieve CPU frequency info"); + set_color!(); + } + + if let Some(info) = cpuid.get_feature_info() { + print!("Features:"); + if info.has_fpu() { print!(" fpu") }; + if info.has_vme() { print!(", vme") }; + if info.has_de() { print!(", de") }; + if info.has_pse() { print!(", pse") }; + if info.has_tsc() { print!(", tsc") }; + if info.has_msr() { print!(", msr") }; + if info.has_pae() { print!(", pae") }; + if info.has_mce() { print!(", mce") }; + + if info.has_cmpxchg8b() { print!(", cx8") }; + if info.has_apic() { print!(", apic") }; + if info.has_sysenter_sysexit() { print!(", sep") }; + if info.has_mtrr() { print!(", mtrr") }; + if info.has_pge() { print!(", pge") }; + if info.has_mca() { print!(", mca") }; + if info.has_cmov() { print!(", cmov") }; + if info.has_pat() { print!(", pat") }; + + if info.has_pse36() { print!(", pse36") }; + if info.has_psn() { print!(", psn") }; + if info.has_clflush() { print!(", clflush") }; + if info.has_ds() { print!(", ds") }; + if info.has_acpi() { print!(", acpi") }; + if info.has_mmx() { print!(", mmx") }; + if info.has_fxsave_fxstor() { print!(", fxsr") }; + if info.has_sse() { print!(", sse") }; + + if info.has_sse2() { print!(", sse2") }; + if info.has_ss() { print!(", ss") }; + if info.has_htt() { print!(", ht") }; + if info.has_tm() { print!(", tm") }; + if info.has_pbe() { print!(", pbe") }; + + if info.has_sse3() { print!(", sse3") }; + if info.has_pclmulqdq() { print!(", pclmulqdq") }; + if info.has_ds_area() { print!(", dtes64") }; + if info.has_monitor_mwait() { print!(", monitor") }; + if info.has_cpl() { print!(", ds_cpl") }; + if info.has_vmx() { print!(", vmx") }; + if info.has_smx() { print!(", smx") }; + if info.has_eist() { print!(", est") }; + + if info.has_tm2() { print!(", tm2") }; + if info.has_ssse3() { print!(", ssse3") }; + if info.has_cnxtid() { print!(", cnxtid") }; + if info.has_fma() { print!(", fma") }; + if info.has_cmpxchg16b() { print!(", cx16") }; + if info.has_pdcm() { print!(", pdcm") }; + if info.has_pcid() { print!(", pcid") }; + if info.has_dca() { print!(", dca") }; + + if info.has_sse41() { print!(", sse4_1") }; + if info.has_sse42() { print!(", sse4_2") }; + if info.has_x2apic() { print!(", x2apic") }; + if info.has_movbe() { print!(", movbe") }; + if info.has_popcnt() { print!(", popcnt") }; + if info.has_tsc_deadline() { print!(", tsc_deadline_timer") }; + if info.has_aesni() { print!(", aes") }; + if info.has_xsave() { print!(", xsave") }; + + if info.has_oxsave() { print!(", xsaveopt") }; + if info.has_avx() { print!(", avx") }; + if info.has_f16c() { print!(", f16c") }; + if info.has_rdrand() { print!(", rdrand") }; + println!(""); + } + + if let Some(info) = cpuid.get_extended_function_info() { + print!("CPU extended function:"); + if info.has_64bit_mode() { print!(" lm") }; + if info.has_rdtscp() { print!(", rdtscp") }; + if info.has_1gib_pages() { print!(", pdpe1gb") }; + if info.has_execute_disable() { print!(", nx") }; + if info.has_syscall_sysret() { print!(", syscall") }; + if info.has_prefetchw() { print!(", prefetchw") }; + if info.has_lzcnt() { print!(", lzcnt") }; + if info.has_lahf_sahf() { print!(", lahf_lm") }; + if info.has_invariant_tsc() { print!(", constant_tsc") }; + println!(""); + } + + if let Some(info) = cpuid.get_extended_feature_info() { + print!("CPU extended features:"); + if info.has_fsgsbase() { print!(" fsgsbase") }; + if info.has_tsc_adjust_msr() { print!(", tsc_adjust") }; + if info.has_bmi1() { print!(", bmi1") }; + if info.has_hle() { print!(", hle") }; + if info.has_avx2() { print!(", avx2") }; + if info.has_smep() { print!(", smep") }; + if info.has_bmi2() { print!(", bmi2") }; + if info.has_rep_movsb_stosb() { print!(", erms") }; + if info.has_invpcid() { print!(", invpcid") }; + if info.has_rtm() { print!(", rtm") }; + if info.has_qm() { print!(", qm") }; + if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") }; + if info.has_mpx() { print!(", mpx") }; + println!(""); + } + + + Ok(()) +} diff --git a/kernel-rs/src/arch/x86/device/local_apic.rs b/kernel-rs/src/arch/x86/device/local_apic.rs new file mode 100644 index 00000000..dea9cd2b --- /dev/null +++ b/kernel-rs/src/arch/x86/device/local_apic.rs @@ -0,0 +1,23 @@ +use ::arch::x86::paging::ActivePageTable; + +pub static mut LOCAL_APIC: LocalApic = LocalApic { + address: 0, + x2: false +}; + +pub unsafe fn init(active_table: &mut ActivePageTable) { + LOCAL_APIC.init(active_table); +} + +pub struct LocalApic { + pub address: usize, + pub x2: bool +} + +impl LocalApic { + unsafe fn init(&mut self, active_table: &mut ActivePageTable) { + // let efer = Efer::read(); + // println!("efer = {:?}", efer); + // flush!(); + } +} diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index 18600155..d9b91aa5 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -1,5 +1,10 @@ +use ::arch::x86::paging::ActivePageTable; pub mod pic; +pub mod local_apic; +pub mod cpu; -pub fn init() { - unsafe { pic::init(); } +pub unsafe fn init(active_table: &mut ActivePageTable) { + pic::init(); + local_apic::init(active_table); + cpu::cpu_info().expect("cpuid not available"); } diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs index 6030f642..48738772 100644 --- a/kernel-rs/src/arch/x86/device/pic.rs +++ b/kernel-rs/src/arch/x86/device/pic.rs @@ -2,31 +2,47 @@ use ::io::{Io, Pio}; pub static mut MASTER: Pic = Pic::new(0x20); pub static mut SLAVE: Pic = Pic::new(0xA0); +pub static mut WAIT_PORT: Pio = Pio::new(0x80); pub unsafe fn init() { + let wait = || {WAIT_PORT.write(0)}; + let master_mask = MASTER.data.read(); + let slave_mask = SLAVE.data.read(); + // Start initialization - MASTER.cmd.write(0x11); - SLAVE.cmd.write(0x11); + MASTER.cmd.write(0x11); wait(); + SLAVE.cmd.write(0x11); wait(); // Set offsets - MASTER.data.write(0x20); - SLAVE.data.write(0x28); + MASTER.data.write(0x20); wait(); + SLAVE.data.write(0x28); wait(); // Set up cascade - MASTER.data.write(4); - SLAVE.data.write(2); + MASTER.data.write(4); wait(); + SLAVE.data.write(2); wait(); // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) - MASTER.data.write(1); - SLAVE.data.write(1); + MASTER.data.write(1); wait(); + SLAVE.data.write(1); wait(); // Unmask interrupts - MASTER.data.write(0); - SLAVE.data.write(0); + MASTER.data.write(0); wait(); + SLAVE.data.write(0); wait(); // Ack remaining interrupts - MASTER.ack(); - SLAVE.ack(); + MASTER.ack(); wait(); + SLAVE.ack(); wait(); + + MASTER.data.write(master_mask); wait(); + SLAVE.data.write(slave_mask); wait(); + + println!("master={:#b}", MASTER.data.read()); + println!("slave ={:#b}", SLAVE.data.read()); + + unsafe { ::arch::x86::interrupt::irq::trigger(1); } + + println!("master={:#b}", MASTER.data.read()); + println!("slave ={:#b}", SLAVE.data.read()); } pub struct Pic { diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs new file mode 100644 index 00000000..2b645697 --- /dev/null +++ b/kernel-rs/src/arch/x86/idt.rs @@ -0,0 +1,57 @@ +use x86::structures::idt::*; +use super::interrupt::*; + +lazy_static! { + static ref IDT: Idt = { + let mut idt = Idt::new(); + + // set up CPU exceptions + idt.breakpoint.set_handler_fn(exception::breakpoint); + idt.debug.set_handler_fn(exception::debug); + idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable); + idt.breakpoint.set_handler_fn(exception::breakpoint); + idt.overflow.set_handler_fn(exception::overflow); + idt.bound_range_exceeded.set_handler_fn(exception::bound_range); + idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); + idt.device_not_available.set_handler_fn(exception::device_not_available); + idt.double_fault.set_handler_fn(exception::double_fault); + idt.segment_not_present.set_handler_fn(exception::segment_not_present); + idt.stack_segment_fault.set_handler_fn(exception::stack_segment); + idt.general_protection_fault.set_handler_fn(exception::general_protection); + idt.page_fault.set_handler_fn(exception::page_fault); + idt.x87_floating_point.set_handler_fn(exception::x87_fpu); + idt.alignment_check.set_handler_fn(exception::alignment_check); + idt.machine_check.set_handler_fn(exception::machine_check); + idt.simd_floating_point.set_handler_fn(exception::simd); + idt.virtualization.set_handler_fn(exception::virtualization); + + // set up IRQs + idt[32].set_handler_fn(irq::pit); + idt[33].set_handler_fn(irq::keyboard); + idt[34].set_handler_fn(irq::cascade); + idt[35].set_handler_fn(irq::com2); + idt[36].set_handler_fn(irq::com1); + idt[37].set_handler_fn(irq::lpt2); + idt[38].set_handler_fn(irq::floppy); + idt[39].set_handler_fn(irq::lpt1); + idt[40].set_handler_fn(irq::rtc); + idt[41].set_handler_fn(irq::pci1); + idt[42].set_handler_fn(irq::pci2); + idt[43].set_handler_fn(irq::pci3); + idt[44].set_handler_fn(irq::mouse); + idt[45].set_handler_fn(irq::fpu); + idt[46].set_handler_fn(irq::ata1); + idt[47].set_handler_fn(irq::ata2); + + idt + }; +} + +// pub fn init(memory_controller: &mut ::memory::MemoryController) { +pub fn init() { + // let double_fault_stack = memory_controller.alloc_stack(1) + // .expect("could not allocate double fault stack"); + // println!("DF stack: {:#?}", double_fault_stack); + // flush!(); + IDT.load(); +} diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 3460f22d..cb94f379 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -1,6 +1,51 @@ use x86::structures::idt::*; +use arch::x86::device::pic; + +pub unsafe fn trigger(irq: u8) { + if irq < 16 { + if irq >= 8 { + pic::SLAVE.mask_set(irq - 8); + pic::MASTER.ack(); + pic::SLAVE.ack(); + } else { + pic::MASTER.mask_set(irq); + pic::MASTER.ack(); + } + } +} + +pub unsafe fn acknowledge(irq: usize) { + if irq < 16 { + if irq >= 8 { + pic::SLAVE.mask_clear(irq as u8 - 8); + } else { + pic::MASTER.mask_clear(irq as u8); + } + } +} + +interrupt!(pit, {}); interrupt!(keyboard, { - println!("key pressed!"); + unsafe { trigger(1); } + + println!("IT WOOOOOOOOOORKS WOUHOU!!!!!!"); flush!(); + + unsafe { acknowledge(1); } }); + +interrupt!(cascade, {}); +interrupt!(com2, {}); +interrupt!(com1, {}); +interrupt!(lpt2, {}); +interrupt!(floppy, {}); +interrupt!(lpt1, {}); +interrupt!(rtc, {}); +interrupt!(pci1, {}); +interrupt!(pci2, {}); +interrupt!(pci3, {}); +interrupt!(mouse, {}); +interrupt!(fpu, {}); +interrupt!(ata1, {}); +interrupt!(ata2, {}); diff --git a/kernel-rs/src/arch/x86/interrupt/mod.rs b/kernel-rs/src/arch/x86/interrupt/mod.rs index 770d0f0c..81c73a70 100644 --- a/kernel-rs/src/arch/x86/interrupt/mod.rs +++ b/kernel-rs/src/arch/x86/interrupt/mod.rs @@ -1,44 +1,2 @@ -use x86::structures::idt::*; - #[macro_use] pub mod exception; #[macro_use] pub mod irq; - - -lazy_static! { - static ref IDT: Idt = { - let mut idt = Idt::new(); - - // set up CPU exceptions - idt.breakpoint.set_handler_fn(exception::breakpoint); - idt.debug.set_handler_fn(exception::debug); - idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable); - idt.breakpoint.set_handler_fn(exception::breakpoint); - idt.overflow.set_handler_fn(exception::overflow); - idt.bound_range_exceeded.set_handler_fn(exception::bound_range); - idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); - idt.device_not_available.set_handler_fn(exception::device_not_available); - idt.double_fault.set_handler_fn(exception::double_fault); - idt.segment_not_present.set_handler_fn(exception::segment_not_present); - idt.stack_segment_fault.set_handler_fn(exception::stack_segment); - idt.general_protection_fault.set_handler_fn(exception::general_protection); - idt.page_fault.set_handler_fn(exception::page_fault); - idt.x87_floating_point.set_handler_fn(exception::x87_fpu); - idt.alignment_check.set_handler_fn(exception::alignment_check); - idt.machine_check.set_handler_fn(exception::machine_check); - idt.simd_floating_point.set_handler_fn(exception::simd); - idt.virtualization.set_handler_fn(exception::virtualization); - - // set up IRQs - idt[33].set_handler_fn(irq::keyboard); - idt - }; -} - -// pub fn init(memory_controller: &mut ::memory::MemoryController) { -pub fn init() { - // let double_fault_stack = memory_controller.alloc_stack(1) - // .expect("could not allocate double fault stack"); - // println!("DF stack: {:#?}", double_fault_stack); - // flush!(); - IDT.load(); -} diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index bef3cee1..1cb4f2c7 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -5,9 +5,11 @@ pub mod macros; pub mod paging; pub mod interrupt; pub mod device; +pub mod idt; use multiboot2; use acpi; +use raw_cpuid::CpuId; #[no_mangle] pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { @@ -23,21 +25,20 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { acpi::init().expect("ACPI failed"); } + // set up interrupts + idt::init(); + // set up physical allocator ::memory::init(&boot_info); - - // set up interrupts - self::interrupt::init(); - // set up virtual mapping - let mut active_table = self::paging::init(&boot_info); + let mut active_table = paging::init(&boot_info); // set up heap ::allocator::init(&mut active_table); - // pic - self::device::init(); + // set up pic & apic + device::init(&mut active_table); // after core has loaded ::memory::init_noncore(); diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 57575a17..15788763 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -45,3 +45,10 @@ pub fn halt() -> ! { unsafe {asm!("hlt" : : : : "volatile")}; } } + +/// wait for an io operation to complete +pub fn io_wait() { + unsafe { asm!("jmp 1f\n\t + 1:jmp 2f\n\t + 2:" : : : : "volatile")} +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index c13360d4..c29217a8 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -77,8 +77,6 @@ fn check_key_state(key: u8) -> (bool, usize) { } pub fn kbd_callback() { - println!("kbd callback called"); - flush!(); static mut SHIFT: bool = false; static mut CTRL: bool = false; static mut ALT: bool = false; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index f4dc049a..4a63e890 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -19,6 +19,7 @@ extern crate rlibc; extern crate spin; extern crate multiboot2; extern crate slab_allocator; +extern crate raw_cpuid; // used by arch/x86, need conditional compilation here extern crate x86; @@ -44,11 +45,8 @@ pub mod arch; /// kernel entry point. arch module is responsible for calling this pub fn kmain() -> ! { - // vga is specific to chipset not cpu - vga::init(); - // x86::instructions::interrupts::disable(); - // x86::instructions::interrupts::int3(); + x86::instructions::interrupts::int3(); // x86::instructions::interrupts::enable(); // fn stack_overflow() { stack_overflow(); } @@ -58,6 +56,10 @@ pub fn kmain() -> ! { // *(0xdead as *mut u32) = 42; // }; + // vga is specific to chipset not cpu + vga::init(); + + // loop { keyboard::kbd_callback(); } loop {} } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index b773b4ff..979c5939 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -199,21 +199,21 @@ impl fmt::Write for Writer { pub fn init() { set_color!(White, Cyan); - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); + // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + // format_args!("{: ^80}", r#" ,--, "#), + // format_args!("{: ^80}", r#" ,--.'| ,----, "#), + // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + // format_args!("{: ^80}", r#" ' ; |./__; : "#), + // format_args!("{: ^80}", r#" | : ;| : .' "#), + // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + // format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); unsafe { VGA.prompt(); } unsafe { VGA.flush(); } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index ea8512f4..5c33fe13 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit ea8512f4c21c6c84578e04eff1f0b4662f089cd9 +Subproject commit 5c33fe133431bb85b86deeff4ec12f17f7ee96cd From 4885defefa8c45c58039a269ef63b48d8047547a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 5 Apr 2018 13:16:04 +0200 Subject: [PATCH 101/151] keyboard now works with interrupts, cool --- kernel-rs/src/arch/x86/device/cpu.rs | 2 +- kernel-rs/src/arch/x86/device/pic.rs | 11 +-- kernel-rs/src/arch/x86/interrupt/exception.rs | 75 ++++++++++++++----- kernel-rs/src/arch/x86/interrupt/irq.rs | 57 ++++++++------ kernel-rs/src/arch/x86/macros.rs | 36 --------- kernel-rs/src/arch/x86/mod.rs | 3 +- kernel-rs/src/lib.rs | 7 +- 7 files changed, 101 insertions(+), 90 deletions(-) delete mode 100644 kernel-rs/src/arch/x86/macros.rs diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/x86/device/cpu.rs index cf7e3fbb..83051d5d 100644 --- a/kernel-rs/src/arch/x86/device/cpu.rs +++ b/kernel-rs/src/arch/x86/device/cpu.rs @@ -28,7 +28,7 @@ pub fn cpu_info() -> Result { } if let Some(info) = cpuid.get_feature_info() { - print!("Features:"); + print!("CPU Features:"); if info.has_fpu() { print!(" fpu") }; if info.has_vme() { print!(", vme") }; if info.has_de() { print!(", de") }; diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs index 48738772..c36e8ee8 100644 --- a/kernel-rs/src/arch/x86/device/pic.rs +++ b/kernel-rs/src/arch/x86/device/pic.rs @@ -36,13 +36,14 @@ pub unsafe fn init() { MASTER.data.write(master_mask); wait(); SLAVE.data.write(slave_mask); wait(); - println!("master={:#b}", MASTER.data.read()); - println!("slave ={:#b}", SLAVE.data.read()); + println!("master={:#x}", MASTER.data.read()); + println!("slave ={:#x}", SLAVE.data.read()); - unsafe { ::arch::x86::interrupt::irq::trigger(1); } + MASTER.mask_set(0); + MASTER.mask_clear(1); - println!("master={:#b}", MASTER.data.read()); - println!("slave ={:#b}", SLAVE.data.read()); + // asm!("sti"); + ::x86::instructions::interrupts::enable(); } pub struct Pic { diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 489c4011..e6baaff8 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -1,24 +1,59 @@ // https://wiki.osdev.org/Exceptions +macro_rules! exception { + ($name:ident, $func:block) => { + pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) + { + println!("Exception: {}", stringify!($name)); + println!("{:#?}", stack_frame); + flush!(); + + #[allow(unused_variables)] + fn inner(stack: &mut ExceptionStackFrame) { + $func + } + inner(stack_frame); + } + } +} + +macro_rules! exception_err { + ($name:ident, $func:block) => { + pub extern "x86-interrupt" fn $name( + stack_frame: &mut ExceptionStackFrame, _error_code: u32) + { + println!("Exception: {}", stringify!($name)); + println!("{:#?}", stack_frame); + flush!(); + + #[allow(unused_variables)] + fn inner(stack: &mut ExceptionStackFrame) { + $func + } + inner(stack_frame); + } + } +} + use x86::structures::idt::*; -interrupt!(divide_by_zero, {}); -interrupt!(debug, {}); -interrupt!(non_maskable, {}); -interrupt!(breakpoint, { +exception!(divide_by_zero, {}); +exception!(debug, {}); +exception!(non_maskable, {}); +exception!(breakpoint, { println!("testing here dont mind me"); flush!(); }); -interrupt!(overflow, {}); -interrupt!(bound_range, {}); -interrupt!(invalid_opcode, {}); -interrupt!(device_not_available, {}); -interrupt_err!(double_fault, {}); -interrupt!(coprocessor_segment_overrun, {}); -interrupt_err!(invalid_tss, {}); -interrupt_err!(segment_not_present, {}); -interrupt_err!(stack_segment, {}); -interrupt_err!(general_protection, {}); +exception!(overflow, {}); +exception!(bound_range, {}); +exception!(invalid_opcode, {}); +exception!(device_not_available, {}); +exception_err!(double_fault, {}); +exception!(coprocessor_segment_overrun, {}); +exception_err!(invalid_tss, {}); +exception_err!(segment_not_present, {}); +exception_err!(stack_segment, {}); +exception_err!(general_protection, {}); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode) @@ -29,9 +64,9 @@ pub extern "x86-interrupt" fn page_fault( flush!(); } -interrupt!(x87_fpu, {}); -interrupt_err!(alignment_check, {}); -interrupt!(machine_check, {}); -interrupt!(simd, {}); -interrupt!(virtualization, {}); -interrupt_err!(security, {}); +exception!(x87_fpu, {}); +exception_err!(alignment_check, {}); +exception!(machine_check, {}); +exception!(simd, {}); +exception!(virtualization, {}); +exception_err!(security, {}); diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index cb94f379..46d2d6e2 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -1,6 +1,22 @@ use x86::structures::idt::*; use arch::x86::device::pic; +#[macro_export] +macro_rules! interrupt { + ($i:expr, $name:ident, $func:block) => { + pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) + { + unsafe { trigger(1); } + #[allow(unused_variables)] + fn inner(stack: &mut ExceptionStackFrame) { + $func + } + inner(stack_frame); + unsafe { acknowledge(1); } + } + } +} + pub unsafe fn trigger(irq: u8) { if irq < 16 { if irq >= 8 { @@ -18,34 +34,31 @@ pub unsafe fn acknowledge(irq: usize) { if irq < 16 { if irq >= 8 { pic::SLAVE.mask_clear(irq as u8 - 8); + pic::SLAVE.ack(); } else { pic::MASTER.mask_clear(irq as u8); + pic::MASTER.ack(); } } } -interrupt!(pit, {}); +interrupt!(0, pit, {}); -interrupt!(keyboard, { - unsafe { trigger(1); } - - println!("IT WOOOOOOOOOORKS WOUHOU!!!!!!"); - flush!(); - - unsafe { acknowledge(1); } +interrupt!(1, keyboard, { + ::keyboard::kbd_callback(); }); -interrupt!(cascade, {}); -interrupt!(com2, {}); -interrupt!(com1, {}); -interrupt!(lpt2, {}); -interrupt!(floppy, {}); -interrupt!(lpt1, {}); -interrupt!(rtc, {}); -interrupt!(pci1, {}); -interrupt!(pci2, {}); -interrupt!(pci3, {}); -interrupt!(mouse, {}); -interrupt!(fpu, {}); -interrupt!(ata1, {}); -interrupt!(ata2, {}); +interrupt!(2, cascade, {}); +interrupt!(3, com2, {}); +interrupt!(4, com1, {}); +interrupt!(5, lpt2, {}); +interrupt!(6, floppy, {}); +interrupt!(7, lpt1, {}); +interrupt!(8, rtc, {}); +interrupt!(9, pci1, {}); +interrupt!(10, pci2, {}); +interrupt!(11, pci3, {}); +interrupt!(12, mouse, {}); +interrupt!(13, fpu, {}); +interrupt!(14, ata1, {}); +interrupt!(15, ata2, {}); diff --git a/kernel-rs/src/arch/x86/macros.rs b/kernel-rs/src/arch/x86/macros.rs deleted file mode 100644 index 94b41202..00000000 --- a/kernel-rs/src/arch/x86/macros.rs +++ /dev/null @@ -1,36 +0,0 @@ -#[macro_export] -macro_rules! interrupt { - ($name:ident, $func:block) => { - pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) - { - println!("Exception: {}", stringify!($name)); - println!("{:#?}", stack_frame); - flush!(); - - #[allow(unused_variables)] - fn inner(stack: &mut ExceptionStackFrame) { - $func - } - inner(stack_frame); - } - } -} - -#[macro_export] -macro_rules! interrupt_err { - ($name:ident, $func:block) => { - pub extern "x86-interrupt" fn $name( - stack_frame: &mut ExceptionStackFrame, _error_code: u32) - { - println!("Exception: {}", stringify!($name)); - println!("{:#?}", stack_frame); - flush!(); - - #[allow(unused_variables)] - fn inner(stack: &mut ExceptionStackFrame) { - $func - } - inner(stack_frame); - } - } -} diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 1cb4f2c7..45f657b7 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -1,15 +1,14 @@ extern crate x86; #[macro_use] -pub mod macros; pub mod paging; pub mod interrupt; pub mod device; + pub mod idt; use multiboot2; use acpi; -use raw_cpuid::CpuId; #[no_mangle] pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 4a63e890..1acdefc8 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -14,7 +14,8 @@ #![feature(abi_x86_interrupt)] extern crate rlibc; -#[macro_use] extern crate alloc; +// #[macro_use] +extern crate alloc; #[macro_use] extern crate lazy_static; extern crate spin; extern crate multiboot2; @@ -45,9 +46,7 @@ pub mod arch; /// kernel entry point. arch module is responsible for calling this pub fn kmain() -> ! { - // x86::instructions::interrupts::disable(); - x86::instructions::interrupts::int3(); - // x86::instructions::interrupts::enable(); + // x86::instructions::interrupts::int3(); // fn stack_overflow() { stack_overflow(); } // stack_overflow(); From 24fa39d45cb3c3aeac34d2df74e3fdbb01786b6f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 5 Apr 2018 13:49:47 +0200 Subject: [PATCH 102/151] cpu as a console command --- kernel-rs/src/arch/x86/device/cpu.rs | 17 ++++++------ kernel-rs/src/arch/x86/device/local_apic.rs | 6 ++--- kernel-rs/src/arch/x86/device/mod.rs | 1 - kernel-rs/src/arch/x86/device/pic.rs | 11 ++++---- kernel-rs/src/arch/x86/interrupt/irq.rs | 6 +++-- kernel-rs/src/arch/x86/mod.rs | 1 - kernel-rs/src/console.rs | 14 +++++++--- kernel-rs/src/vga/mod.rs | 30 ++++++++++----------- 8 files changed, 46 insertions(+), 40 deletions(-) diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/x86/device/cpu.rs index 83051d5d..eaadb10b 100644 --- a/kernel-rs/src/arch/x86/device/cpu.rs +++ b/kernel-rs/src/arch/x86/device/cpu.rs @@ -8,27 +8,27 @@ pub fn cpu_info() -> Result { let cpuid = CpuId::new(); if let Some(info) = cpuid.get_vendor_info() { - println!("CPU Vendor: {}", info.as_string()); + println!("Vendor: {}", info.as_string()); } if let Some(info) = cpuid.get_extended_function_info() { if let Some(brand) = info.processor_brand_string() { - println!("CPU Model: {}", brand); + println!("Model: {}", brand); } } if let Some(info) = cpuid.get_processor_frequency_info() { - println!("CPU Base MHz: {}", info.processor_base_frequency()); - println!("CPU Max MHz: {}", info.processor_max_frequency()); + println!("Base MHz: {}", info.processor_base_frequency()); + println!("Max MHz: {}", info.processor_max_frequency()); println!("Bus MHz: {}", info.bus_frequency()); } else { set_color!(Red); - println!("couldn't retrieve CPU frequency info"); + println!("Couldn't retrieve cpu frequency info"); set_color!(); } if let Some(info) = cpuid.get_feature_info() { - print!("CPU Features:"); + print!("Features:"); if info.has_fpu() { print!(" fpu") }; if info.has_vme() { print!(", vme") }; if info.has_de() { print!(", de") }; @@ -97,7 +97,7 @@ pub fn cpu_info() -> Result { } if let Some(info) = cpuid.get_extended_function_info() { - print!("CPU extended function:"); + print!("Extended function:"); if info.has_64bit_mode() { print!(" lm") }; if info.has_rdtscp() { print!(", rdtscp") }; if info.has_1gib_pages() { print!(", pdpe1gb") }; @@ -111,7 +111,7 @@ pub fn cpu_info() -> Result { } if let Some(info) = cpuid.get_extended_feature_info() { - print!("CPU extended features:"); + print!("Extended features:"); if info.has_fsgsbase() { print!(" fsgsbase") }; if info.has_tsc_adjust_msr() { print!(", tsc_adjust") }; if info.has_bmi1() { print!(", bmi1") }; @@ -128,6 +128,5 @@ pub fn cpu_info() -> Result { println!(""); } - Ok(()) } diff --git a/kernel-rs/src/arch/x86/device/local_apic.rs b/kernel-rs/src/arch/x86/device/local_apic.rs index dea9cd2b..3a4e79c6 100644 --- a/kernel-rs/src/arch/x86/device/local_apic.rs +++ b/kernel-rs/src/arch/x86/device/local_apic.rs @@ -15,9 +15,7 @@ pub struct LocalApic { } impl LocalApic { - unsafe fn init(&mut self, active_table: &mut ActivePageTable) { - // let efer = Efer::read(); - // println!("efer = {:?}", efer); - // flush!(); + unsafe fn init(&mut self, _active_table: &mut ActivePageTable) { + // ??? } } diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index d9b91aa5..dc1eac30 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -6,5 +6,4 @@ pub mod cpu; pub unsafe fn init(active_table: &mut ActivePageTable) { pic::init(); local_apic::init(active_table); - cpu::cpu_info().expect("cpuid not available"); } diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs index c36e8ee8..00b5ab21 100644 --- a/kernel-rs/src/arch/x86/device/pic.rs +++ b/kernel-rs/src/arch/x86/device/pic.rs @@ -36,11 +36,12 @@ pub unsafe fn init() { MASTER.data.write(master_mask); wait(); SLAVE.data.write(slave_mask); wait(); - println!("master={:#x}", MASTER.data.read()); - println!("slave ={:#x}", SLAVE.data.read()); - - MASTER.mask_set(0); - MASTER.mask_clear(1); + // disable all irqs + MASTER.data.write(!0); wait(); + SLAVE.data.write(!0); wait(); + + // keyboard active + MASTER.mask_clear(1); wait(); // asm!("sti"); ::x86::instructions::interrupts::enable(); diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 46d2d6e2..04a64b83 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -6,13 +6,15 @@ macro_rules! interrupt { ($i:expr, $name:ident, $func:block) => { pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) { - unsafe { trigger(1); } + unsafe { trigger($i); } + #[allow(unused_variables)] fn inner(stack: &mut ExceptionStackFrame) { $func } inner(stack_frame); - unsafe { acknowledge(1); } + + unsafe { acknowledge($i); } } } } diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 45f657b7..ddf17a1c 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -42,7 +42,6 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // after core has loaded ::memory::init_noncore(); - // primary CPU entry point ::kmain(); } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 73a307bc..6dc8f781 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -23,6 +23,7 @@ fn dispatch(command: &str) -> Result <(), &'static str> { // others "stack" => self::print_stack(), "regs" => self::regs(), + "cpu" => self::cpu(), _ => Err("Command unknown. (h|help for help)"), } @@ -48,6 +49,7 @@ fn help() -> Result <(), &'static str> { println!("shutdown | halt | q => Kill a kitten, then shutdown"); println!("stack => Print kernel stack in a fancy way"); println!("regs => Print controle register"); + println!("cpu => Print cpu information"); flush!(); Ok(()) } @@ -177,11 +179,17 @@ pub fn acpi_info() -> Result <(), &'static str> { } pub fn regs() -> Result <(), &'static str> { - use x86::registers::control::*; + use ::x86::registers::control::*; println!("cr0={:#b}", Cr0::read()); println!("cr3={:?}", Cr3::read()); + println!("cr4={:?}", Cr4::read()); + flush!(); + Ok(()) +} + +pub fn cpu() -> Result <(), &'static str> { + use ::arch::x86::device::cpu; + cpu::cpu_info().expect("cpu info not available"); flush!(); - // TODO implement cr4 flags in `x86` module - // println!("cr4={:#b}", Cr4::read()); Ok(()) } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 979c5939..b773b4ff 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -199,21 +199,21 @@ impl fmt::Write for Writer { pub fn init() { set_color!(White, Cyan); - // print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - // format_args!("{: ^80}", r#" ,--, "#), - // format_args!("{: ^80}", r#" ,--.'| ,----, "#), - // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - // format_args!("{: ^80}", r#" ' ; |./__; : "#), - // format_args!("{: ^80}", r#" | : ;| : .' "#), - // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - // format_args!("{: ^80}", r#" '--' `---' "#)); + print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#)); set_color!(); unsafe { VGA.prompt(); } unsafe { VGA.flush(); } From b7855ae56cca9ae2f475faf9c49a50abfebf00e8 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 5 Apr 2018 19:04:05 +0200 Subject: [PATCH 103/151] @gz merged rust-cpuid PR so i can get rid of my fork --- kernel-rs/.gitmodules | 3 --- kernel-rs/Cargo.toml | 8 +++++--- kernel-rs/rust-cpuid | 1 - kernel-rs/src/arch/mod.rs | 2 ++ kernel-rs/src/arch/x86/interrupt/exception.rs | 16 +++++++++++----- kernel-rs/src/arch/x86/mod.rs | 1 + kernel-rs/src/console.rs | 15 ++++++++------- kernel-rs/src/keyboard.rs | 5 ----- kernel-rs/src/lib.rs | 10 ++++++---- 9 files changed, 33 insertions(+), 28 deletions(-) delete mode 160000 kernel-rs/rust-cpuid diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules index 782f58ec..820f6043 100644 --- a/kernel-rs/.gitmodules +++ b/kernel-rs/.gitmodules @@ -4,6 +4,3 @@ [submodule "x86"] path = x86 url = https://github.com/jzck/x86.git -[submodule "rust-cpuid"] - path = rust-cpuid - url = https://github.com/jzck/rust-cpuid diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 1c8920b7..217b03ac 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -13,10 +13,12 @@ spin = "0.4" slab_allocator = "0.3.1" multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag x86 = { path = "x86" } # forked for IA32 -raw-cpuid = { path = "rust-cpuid" } # forked for IA32 + +[dependencies.raw-cpuid] +# need to use github/master because of features not yet on crates.io +git = "https://github.com/gz/rust-cpuid" +features = ["nightly"] [dependencies.lazy_static] version = "1.0.0" features = ["spin_no_std"] - - diff --git a/kernel-rs/rust-cpuid b/kernel-rs/rust-cpuid deleted file mode 160000 index 07299b93..00000000 --- a/kernel-rs/rust-cpuid +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 07299b93df57fcee2b6aec61502a5135b99967f8 diff --git a/kernel-rs/src/arch/mod.rs b/kernel-rs/src/arch/mod.rs index aebe1682..06b8ef64 100644 --- a/kernel-rs/src/arch/mod.rs +++ b/kernel-rs/src/arch/mod.rs @@ -1 +1,3 @@ +// we only support a single architecture at the moment +// more specifically IA-32 (aka i386) but we name it x86 here. pub mod x86; diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index e6baaff8..9a75ef24 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -1,9 +1,13 @@ // https://wiki.osdev.org/Exceptions +use ::arch::x86::pti; + macro_rules! exception { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) { + // unsafe { pti::map(); } + println!("Exception: {}", stringify!($name)); println!("{:#?}", stack_frame); flush!(); @@ -13,6 +17,8 @@ macro_rules! exception { $func } inner(stack_frame); + + // unsafe { pti::unmap(); } } } } @@ -37,13 +43,13 @@ macro_rules! exception_err { use x86::structures::idt::*; -exception!(divide_by_zero, {}); +exception!(divide_by_zero, { + panic!("CPU exception: division by zero"); +}); + exception!(debug, {}); exception!(non_maskable, {}); -exception!(breakpoint, { - println!("testing here dont mind me"); - flush!(); -}); +exception!(breakpoint, {}); exception!(overflow, {}); exception!(bound_range, {}); exception!(invalid_opcode, {}); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index ddf17a1c..f00125a2 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -4,6 +4,7 @@ extern crate x86; pub mod paging; pub mod interrupt; pub mod device; +pub mod pti; pub mod idt; diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 6dc8f781..29a8f583 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -20,7 +20,7 @@ fn dispatch(command: &str) -> Result <(), &'static str> { "reboot" => self::reboot(), "shutdown" | "halt" | "q" => self::shutdown(), - // others + // x86 specific "stack" => self::print_stack(), "regs" => self::regs(), "cpu" => self::cpu(), @@ -117,7 +117,6 @@ fn print_line(line: &[u8], address: usize) { } /// Print the kernel stack -/// fn print_stack() -> Result <(), &'static str> { let esp: usize; let ebp: usize; @@ -130,7 +129,7 @@ fn print_stack() -> Result <(), &'static str> { } // fn mb2_memory() -> Result <(), &'static str> { -// let boot_info = context::boot_info(); +// let boot_info = ::multiboot2::boot_info(); // let memory_map_tag = boot_info.memory_map_tag() // .expect("Memory map tag required"); @@ -144,7 +143,7 @@ fn print_stack() -> Result <(), &'static str> { // } // fn mb2_sections() -> Result <(), &'static str> { -// let boot_info = context::boot_info(); +// let boot_info = ::multiboot2::boot_info(); // let elf_sections_tag = boot_info.elf_sections_tag() // .expect("Elf-sections tag required"); @@ -178,15 +177,17 @@ pub fn acpi_info() -> Result <(), &'static str> { Ok(()) } +/// Dump control registers pub fn regs() -> Result <(), &'static str> { use ::x86::registers::control::*; - println!("cr0={:#b}", Cr0::read()); - println!("cr3={:?}", Cr3::read()); - println!("cr4={:?}", Cr4::read()); + println!("cr0 = {:?}", Cr0::read()); + println!("cr3 = {:?}", Cr3::read()); + println!("cr4 = {:?}", Cr4::read()); flush!(); Ok(()) } +/// Dump cpu info, should add power management info pub fn cpu() -> Result <(), &'static str> { use ::arch::x86::device::cpu; cpu::cpu_info().expect("cpu info not available"); diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index c29217a8..c456d45f 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -91,11 +91,6 @@ pub fn kbd_callback() { 0x2A | 0x36 => {SHIFT = !is_release}, 0x38 => {ALT = !is_release}, 0x1D => {CTRL = !is_release}, - // terminal switching - // 0x0F if !is_release => { - // context::switch_term(); - // context::current_term().flush(); - // }, 0x0E if !is_release => { vga::VGA.backspace(); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 1acdefc8..509d3d71 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -1,23 +1,25 @@ //! project hosted on [github](https://github.com/jzck/kernel) -//! exclusively x86 -//! + +// nightly stuff we need #![no_std] #![feature(lang_items)] #![feature(const_fn)] #![feature(ptr_internals)] #![feature(asm)] +#![feature(thread_local)] +// home made heap #![feature(alloc)] #![feature(allocator_api)] #![feature(global_allocator)] +// x86 specific #![feature(abi_x86_interrupt)] extern crate rlibc; -// #[macro_use] extern crate alloc; -#[macro_use] extern crate lazy_static; extern crate spin; +#[macro_use] extern crate lazy_static; extern crate multiboot2; extern crate slab_allocator; extern crate raw_cpuid; From 1b7ddd12d9bb22548c1be2a4c465624a1c1f320a Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 5 Apr 2018 19:04:44 +0200 Subject: [PATCH 104/151] pti file, doesnt work yet --- kernel-rs/src/arch/x86/pti.rs | 68 +++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 kernel-rs/src/arch/x86/pti.rs diff --git a/kernel-rs/src/arch/x86/pti.rs b/kernel-rs/src/arch/x86/pti.rs new file mode 100644 index 00000000..7ed277cb --- /dev/null +++ b/kernel-rs/src/arch/x86/pti.rs @@ -0,0 +1,68 @@ +use core::ptr; + +use super::paging::ActivePageTable; +// use super::paging::entry::EntryFlags; + +#[thread_local] +pub static mut PTI_CPU_STACK: [u8; 256] = [0; 256]; + +#[thread_local] +pub static mut PTI_CONTEXT_STACK: usize = 0; + +#[inline(always)] +unsafe fn switch_stack(old: usize, new: usize) { + let old_esp: usize; + asm!("" : "={esp}"(old_esp) : : : "intel", "volatile"); + + let offset_esp = old - old_esp; + + let new_esp = new - offset_esp; + + ptr::copy_nonoverlapping( + old_esp as *const u8, + new_esp as *mut u8, + offset_esp + ); + + asm!("" : : "{esp}"(new_esp) : : "intel", "volatile"); +} + +#[inline(always)] +pub unsafe fn map() { + // { + // let mut active_table = unsafe { ActivePageTable::new() }; + // + // // Map kernel heap + // let address = active_table.p4()[::KERNEL_HEAP_PML4].address(); + // let frame = Frame::containing_address(address); + // let mut flags = active_table.p4()[::KERNEL_HEAP_PML4].flags(); + // flags.remove(EntryFlags::PRESENT); + // active_table.p4_mut()[::KERNEL_HEAP_PML4].set(frame, flags); + // + // // Reload page tables + // active_table.flush_all(); + // } + + // Switch to per-context stack + switch_stack(PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), PTI_CONTEXT_STACK); +} + +#[inline(always)] +pub unsafe fn unmap() { + // Switch to per-CPU stack + switch_stack(PTI_CONTEXT_STACK, PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()); + + // { + // let mut active_table = unsafe { ActivePageTable::new() }; + // + // // Unmap kernel heap + // let address = active_table.p4()[::KERNEL_HEAP_PML4].address(); + // let frame = Frame::containing_address(address); + // let mut flags = active_table.p4()[::KERNEL_HEAP_PML4].flags(); + // flags.insert(EntryFlags::PRESENT); + // active_table.p4_mut()[::KERNEL_HEAP_PML4].set(frame, flags); + // + // // Reload page tables + // active_table.flush_all(); + // } +} From bea6a729fe3effa88f77f59c9fd6956b510b45a0 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 6 Apr 2018 17:43:58 +0200 Subject: [PATCH 105/151] gdt in place but triple faults because of spin::Once for now --- kernel-rs/Cargo.toml | 9 +++++---- kernel-rs/src/arch/x86/gdt.rs | 34 ++++++++++++++++++++++++++++++++++ kernel-rs/src/arch/x86/mod.rs | 13 +++++++------ kernel-rs/src/arch/x86/pti.rs | 3 +++ kernel-rs/src/lib.rs | 2 ++ kernel-rs/src/memory/mod.rs | 2 +- 6 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 kernel-rs/src/arch/x86/gdt.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 217b03ac..d2b8779f 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -13,11 +13,12 @@ spin = "0.4" slab_allocator = "0.3.1" multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag x86 = { path = "x86" } # forked for IA32 +raw-cpuid = { path = "rust-cpuid" } -[dependencies.raw-cpuid] -# need to use github/master because of features not yet on crates.io -git = "https://github.com/gz/rust-cpuid" -features = ["nightly"] +# [dependencies.raw-cpuid] +# # need to use github/master because of features not yet on crates.io +# git = "https://github.com/gz/rust-cpuid" +# features = ["nightly"] [dependencies.lazy_static] version = "1.0.0" diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs new file mode 100644 index 00000000..0fed6425 --- /dev/null +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -0,0 +1,34 @@ +use x86::structures::gdt; +use x86::structures::tss; +use x86::instructions::segmentation::set_cs; +use x86::instructions::tables::load_tss; +use spin::Once; + +static GDT: Once = Once::new(); +static TSS: Once = Once::new(); + +pub fn init() { + // let tss = tss::TaskStateSegment::new(); + let tss = TSS.call_once(|| { + let mut tss = tss::TaskStateSegment::new(); + tss + }); + + // let mut code_selector = gdt::SegmentSelector(0); + // let mut tss_selector = gdt::SegmentSelector(0); + + // let gdt = GDT.call_once(|| { + // let mut gdt = gdt::Gdt::new(); + // code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); + // tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); + // gdt + // }); + + // gdt.load(); + // unsafe { + // // reload code segment register + // set_cs(code_selector); + // // load TSS + // load_tss(tss_selector); + // } +} diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index f00125a2..74572557 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -6,6 +6,7 @@ pub mod interrupt; pub mod device; pub mod pti; +pub mod gdt; pub mod idt; use multiboot2; @@ -25,9 +26,6 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { acpi::init().expect("ACPI failed"); } - // set up interrupts - idt::init(); - // set up physical allocator ::memory::init(&boot_info); @@ -37,12 +35,15 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { // set up heap ::allocator::init(&mut active_table); + // set up memory segmentation + // gdt::init(); + + // set up interrupts + idt::init(); + // set up pic & apic device::init(&mut active_table); - // after core has loaded - ::memory::init_noncore(); - // primary CPU entry point ::kmain(); } diff --git a/kernel-rs/src/arch/x86/pti.rs b/kernel-rs/src/arch/x86/pti.rs index 7ed277cb..7942d611 100644 --- a/kernel-rs/src/arch/x86/pti.rs +++ b/kernel-rs/src/arch/x86/pti.rs @@ -12,6 +12,8 @@ pub static mut PTI_CONTEXT_STACK: usize = 0; #[inline(always)] unsafe fn switch_stack(old: usize, new: usize) { let old_esp: usize; + + // save the old esp asm!("" : "={esp}"(old_esp) : : : "intel", "volatile"); let offset_esp = old - old_esp; @@ -24,6 +26,7 @@ unsafe fn switch_stack(old: usize, new: usize) { offset_esp ); + // switch the esp with the new one asm!("" : : "{esp}"(new_esp) : : "intel", "volatile"); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 509d3d71..8db6c338 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -47,6 +47,8 @@ pub mod arch; /// kernel entry point. arch module is responsible for calling this pub fn kmain() -> ! { + // core is loaded now + memory::init_noncore(); // x86::instructions::interrupts::int3(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 01514299..a8c28ed5 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -72,7 +72,7 @@ pub fn deallocate_frames(frame: PhysFrame, count: usize) { /// Init memory module after core /// Must be called once, and only once, -pub unsafe fn init_noncore() { +pub fn init_noncore() { if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { controler.frame_allocator.set_core(true); } else { From a0ad3689f31bc90ebefe116b74bba7845386af8e Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 13:33:16 +0200 Subject: [PATCH 106/151] code doesnt work anymore but i'm commiting anyway, shoot me --- kernel-rs/Cargo.toml | 10 +- kernel-rs/src/acpi/dsdt.rs | 56 +-- kernel-rs/src/acpi/fadt.rs | 80 ++--- kernel-rs/src/acpi/mod.rs | 63 ++-- kernel-rs/src/acpi/rsdp.rs | 30 +- kernel-rs/src/acpi/rsdt.rs | 10 +- kernel-rs/src/acpi/xsdt.rs | 10 +- kernel-rs/src/allocator/mod.rs | 6 +- kernel-rs/src/arch/x86/device/cpu.rs | 318 +++++++++++++----- kernel-rs/src/arch/x86/device/local_apic.rs | 6 +- kernel-rs/src/arch/x86/device/mod.rs | 2 +- kernel-rs/src/arch/x86/device/pic.rs | 57 ++-- kernel-rs/src/arch/x86/gdt.rs | 12 +- kernel-rs/src/arch/x86/interrupt/exception.rs | 7 +- kernel-rs/src/arch/x86/interrupt/mod.rs | 6 +- kernel-rs/src/arch/x86/mod.rs | 20 +- kernel-rs/src/arch/x86/paging/mapper.rs | 17 +- kernel-rs/src/arch/x86/paging/mod.rs | 115 ++++--- kernel-rs/src/arch/x86/paging/table.rs | 31 +- .../src/arch/x86/paging/temporary_page.rs | 40 +-- kernel-rs/src/arch/x86/pti.rs | 16 +- kernel-rs/src/console.rs | 46 +-- kernel-rs/src/cpuio.rs | 22 +- kernel-rs/src/io/mod.rs | 8 +- kernel-rs/src/keyboard.rs | 27 +- kernel-rs/src/lib.rs | 30 +- kernel-rs/src/memory/bump.rs | 69 ++-- kernel-rs/src/memory/mod.rs | 21 +- kernel-rs/src/memory/recycle.rs | 4 +- kernel-rs/src/vga/mod.rs | 62 ++-- 30 files changed, 725 insertions(+), 476 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index d2b8779f..efc5451c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -13,12 +13,12 @@ spin = "0.4" slab_allocator = "0.3.1" multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag x86 = { path = "x86" } # forked for IA32 -raw-cpuid = { path = "rust-cpuid" } +# raw-cpuid = { path = "rust-cpuid" } -# [dependencies.raw-cpuid] -# # need to use github/master because of features not yet on crates.io -# git = "https://github.com/gz/rust-cpuid" -# features = ["nightly"] +[dependencies.raw-cpuid] +# need to use github/master because of features not yet on crates.io +git = "https://github.com/gz/rust-cpuid" +features = ["nightly"] [dependencies.lazy_static] version = "1.0.0" diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index aa3456e2..32309cf1 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -1,4 +1,4 @@ -use super::{check_signature,ACPISDTHeader}; +use super::{check_signature, ACPISDTHeader}; use core::mem; use cpuio; @@ -7,7 +7,7 @@ static mut DSDT: DSDT = DSDT { dsdt: None, s5_ptr: 0, slp_typ_a: 0, - slp_typ_b: 0 + slp_typ_b: 0, }; struct DSDT { @@ -15,24 +15,26 @@ struct DSDT { dsdt: Option<&'static ACPISDTHeader>, s5_ptr: u32, slp_typ_a: u16, - slp_typ_b: u16 + slp_typ_b: u16, } impl DSDT { - fn init(&mut self, addr: u32) -> Result <(), &'static str> { - self.dsdt = Some(unsafe{ &(*(addr as *const ACPISDTHeader)) }); + fn init(&mut self, addr: u32) -> Result<(), &'static str> { + self.dsdt = Some(unsafe { &(*(addr as *const ACPISDTHeader)) }); self.s5_ptr = self.find_s5(addr)?; self.parse_s5(); self.valid = true; Ok(()) } - fn find_s5(&self, addr: u32) -> Result { + fn find_s5(&self, addr: u32) -> Result { let dsdt_start = addr + mem::size_of::() as u32; let dsdt_end = dsdt_start + self.dsdt.unwrap().length; for addr in dsdt_start..dsdt_end { if check_signature(addr, "_S5_") { - if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) && check_signature(addr + 4, "\x12") { + if (check_signature(addr - 1, "\x08") || check_signature(addr - 2, "\x08\\")) + && check_signature(addr + 4, "\x12") + { return Ok(addr); } } @@ -42,43 +44,51 @@ impl DSDT { fn parse_s5(&mut self) { let ptr = self.s5_ptr + 5; - let ptr = ((unsafe{*(ptr as *const u8)} & 0xC0) >> 6) + 2; - let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix - self.slp_typ_a = (unsafe {*(ptr as *const u8)} as u16) << 10; + let ptr = ((unsafe { *(ptr as *const u8) } & 0xC0) >> 6) + 2; + let ptr = if unsafe { *(ptr as *const u8) } == 0x0A { + ptr + 1 + } else { + ptr + }; // Skip bytePrefix + self.slp_typ_a = (unsafe { *(ptr as *const u8) } as u16) << 10; let ptr = ptr + 1; - let ptr = if unsafe{*(ptr as *const u8)} == 0x0A { ptr + 1 } else { ptr };// Skip bytePrefix - self.slp_typ_b = (unsafe {*(ptr as *const u8)} as u16) << 10; + let ptr = if unsafe { *(ptr as *const u8) } == 0x0A { + ptr + 1 + } else { + ptr + }; // Skip bytePrefix + self.slp_typ_b = (unsafe { *(ptr as *const u8) } as u16) << 10; } } -fn is_init() -> Result <(), &'static str> { - match unsafe {DSDT.valid} { +fn is_init() -> Result<(), &'static str> { + match unsafe { DSDT.valid } { true => Ok(()), - false => match unsafe {DSDT.dsdt} { + false => match unsafe { DSDT.dsdt } { Some(_) => Err("Differentiated System Description Pointer (DSDP) is not valid"), - None => Err("Differentiated System Description Pointer (DSDP) is not initialized") - } + None => Err("Differentiated System Description Pointer (DSDP) is not initialized"), + }, } } /// ## Initialize Differentiated System Description Table (DSDT) /// input param addr is contain in FADT -pub fn init(addr: u32) -> Result <(), &'static str> { +pub fn init(addr: u32) -> Result<(), &'static str> { if ACPISDTHeader::valid(addr, "DSDT") { - return unsafe {DSDT.init(addr)}; + return unsafe { DSDT.init(addr) }; } return Err("Can not find Differentiated System Description Table (DSDT)."); } /// NOT COMPATIBLE WITH VIRTUALBOX /// Send shutdown signal -/// outw(PM1a_CNT_BLK, SLP_TYPx | SLP_EN) -pub fn shutdown(pm1_cnt: [u16; 2]) -> Result <(), &'static str> { +/// outw(PM1a_CNT_BLK, SLP_TYPx | SLP_EN) +pub fn shutdown(pm1_cnt: [u16; 2]) -> Result<(), &'static str> { is_init()?; - let slp_typ = unsafe{ DSDT.slp_typ_a } | (1 << 13); + let slp_typ = unsafe { DSDT.slp_typ_a } | (1 << 13); cpuio::outw(pm1_cnt[0], slp_typ); if pm1_cnt[1] != 0 { - let slp_typ = unsafe{ DSDT.slp_typ_b } | (1 << 13); + let slp_typ = unsafe { DSDT.slp_typ_b } | (1 << 13); cpuio::outw(pm1_cnt[1], slp_typ); } Ok(()) diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index ed5da011..edbdcbd2 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -1,4 +1,4 @@ -use super::{ACPISDTHeader,ACPISDTIter}; +use super::{ACPISDTHeader, ACPISDTIter}; use cpuio; #[repr(C)] @@ -9,13 +9,12 @@ struct GenericAddressStructure { bitoffset: u8, accesssize: u8, noused: u32, - address: u64 + address: u64, } #[repr(C)] #[derive(Debug, Clone)] -struct FADT -{ +struct FADT { header: ACPISDTHeader, firmwarectrl: u32, dsdt: u32, @@ -28,33 +27,33 @@ struct FADT smi_commandport: u32, acpi_enable: u8, acpidisable: u8, - s4bios_req: u8, //no use - pstate_control: u8, //no use + s4bios_req: u8, //no use + pstate_control: u8, //no use pm1aeventblock: u32, //no use pm1beventblock: u32, //no use pm1acontrolblock: u32, pm1bcontrolblock: u32, pm2controlblock: u32, //no use - pmtimerblock: u32, //no use - gpe0block: u32, //no use - gpe1block: u32, //no use - pm1eventlength: u8, //no use + pmtimerblock: u32, //no use + gpe0block: u32, //no use + gpe1block: u32, //no use + pm1eventlength: u8, //no use pm1controllength: u8, pm2controllength: u8, //no use - pmtimerlength: u8, //no use - gpe0length: u8, //no use - gpe1length: u8, //no use - gpe1base: u8, //no use - cstatecontrol: u8, //no use - worstc2latency: u16, //no use - worstc3latency: u16, //no use - flushsize: u16, //no use - flushstride: u16, //no use - dutyoffset: u8, //no use - dutywidth: u8, //no use - dayalarm: u8, //no use - monthalarm: u8, //no use - century: u8, //no use + pmtimerlength: u8, //no use + gpe0length: u8, //no use + gpe1length: u8, //no use + gpe1base: u8, //no use + cstatecontrol: u8, //no use + worstc2latency: u16, //no use + worstc3latency: u16, //no use + flushsize: u16, //no use + flushstride: u16, //no use + dutyoffset: u8, //no use + dutywidth: u8, //no use + dayalarm: u8, //no use + monthalarm: u8, //no use + century: u8, //no use // reserved in acpi 1.0; used since acpi 2.0+ bootarchitectureflags: u16, @@ -80,19 +79,20 @@ struct FADT x_pmtimerblock: GenericAddressStructure, x_gpe0block: GenericAddressStructure, x_gpe1block: GenericAddressStructure, - } static mut FADT: Option = None; /// ## Initialize Fixed ACPI Description Table (FADT) /// input param addr is contain in other ptr of rsdt -pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { +pub fn init(sdt_iter: ACPISDTIter) -> Result<(), &'static str> { for sdt_ptr in sdt_iter { - if ACPISDTHeader::valid(sdt_ptr, "FACP") { // Where is "FADT"? Shut up is magic - let fadt_tmp: FADT = unsafe{ (*(sdt_ptr as *const FADT)).clone() }; - unsafe {FADT = Some(fadt_tmp.clone())}; - if !is_enable()? { // TODO do i have to check if enabled before init ??? + if ACPISDTHeader::valid(sdt_ptr, "FACP") { + // Where is "FADT"? Shut up is magic + let fadt_tmp: FADT = unsafe { (*(sdt_ptr as *const FADT)).clone() }; + unsafe { FADT = Some(fadt_tmp.clone()) }; + if !is_enable()? { + // TODO do i have to check if enabled before init ??? let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST let acpi_enable = fadt_tmp.acpi_enable; cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command @@ -103,16 +103,16 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result <(), &'static str> { return Err("Can not find Fixed ACPI Description Table (FADT)."); } -fn is_init() -> Result { - match unsafe {FADT.clone()} { - Some(fadt) => Ok(fadt), - None => Err("Fixed ACPI Description Table (FADT) is not initialized") +fn is_init() -> Result { + match unsafe { FADT.clone() } { + Some(fadt) => Ok(fadt), + None => Err("Fixed ACPI Description Table (FADT) is not initialized"), } } /// Return Dsdt address /// FADT must have been initialized first -pub fn dsdtaddr() -> Result { +pub fn dsdtaddr() -> Result { let fadt = is_init()?; return Ok(fadt.dsdt); } @@ -122,7 +122,7 @@ fn get_cnt(fadt: FADT) -> [u16; 2] { } /// Return true/false depending of acpi is enable -pub fn is_enable() -> Result { +pub fn is_enable() -> Result { let fadt = is_init()?; let pm1_cnt = get_cnt(fadt); if pm1_cnt[1] == 0 { @@ -134,13 +134,13 @@ pub fn is_enable() -> Result { /// Return a array with [pm1a, pm1b] /// FADT must have been initialized first -pub fn get_controlblock() -> Result <[u16; 2], &'static str> { +pub fn get_controlblock() -> Result<[u16; 2], &'static str> { if !is_enable()? { Err("ACPI is not enabled") } else { - // println!("HALT"); - // flush!(); - // cpuio::halt(); + // println!("HALT"); + // flush!(); + // cpuio::halt(); Ok(get_cnt(is_init()?)) // TODO redondant call to is_init } } diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 35b9f2f0..3b0544a8 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -26,7 +26,7 @@ impl ACPISDTHeader { pub fn valid(addr: u32, signature: &str) -> bool { if check_signature(addr, signature) { let ptr_tmp = addr as *const ACPISDTHeader; - if check_checksum(addr, unsafe {(*ptr_tmp).length} as usize) { + if check_checksum(addr, unsafe { (*ptr_tmp).length } as usize) { return true; } } @@ -36,16 +36,16 @@ impl ACPISDTHeader { static mut ACPI: Acpi = Acpi { valid: false, - v2: false + v2: false, }; struct Acpi { valid: bool, - v2: bool + v2: bool, } impl Acpi { - fn common_init(&mut self) -> Result <(), &'static str> { + fn common_init(&mut self) -> Result<(), &'static str> { if self.v2 { // Xsdt Address: // 64-bit physical address of the XSDT table. If you detect ACPI Version 2.0 you should use this table instead of RSDT even on x86, casting the address to uint32_t. @@ -58,20 +58,21 @@ impl Acpi { dsdt::init(fadt::dsdtaddr()?)?; self.valid = true; Ok(()) - } - fn init(&mut self) -> Result <(), &'static str> { + fn init(&mut self) -> Result<(), &'static str> { self.v2 = rsdp::init()?; self.common_init() } - fn load(&mut self, rsdp_addr: u32) -> Result <(), &'static str> { + fn load(&mut self, rsdp_addr: u32) -> Result<(), &'static str> { self.v2 = rsdp::load(rsdp_addr)?; self.common_init() } } fn check_signature(addr: u32, id: &str) -> bool { - let signature = match core::str::from_utf8(unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, id.len())}) { + let signature = match core::str::from_utf8(unsafe { + core::slice::from_raw_parts_mut(addr as *mut u8, id.len()) + }) { Ok(y) => y, Err(_) => return false, }; @@ -79,7 +80,7 @@ fn check_signature(addr: u32, id: &str) -> bool { } fn check_checksum(addr: u32, len: usize) -> bool { - let byte_array = unsafe {core::slice::from_raw_parts_mut(addr as *mut u8, len)}; + let byte_array = unsafe { core::slice::from_raw_parts_mut(addr as *mut u8, len) }; let mut sum: u32 = 0; for byte in byte_array { sum += *byte as u32; @@ -91,19 +92,23 @@ pub struct ACPISDTIter { pos: usize, width: usize, sdt: u32, - len: usize + len: usize, } impl ACPISDTIter { - fn new(acpi_sdt: Option<*const ACPISDTHeader>, ptr_len: usize) -> Result { + fn new( + acpi_sdt: Option<*const ACPISDTHeader>, + ptr_len: usize, + ) -> Result { match acpi_sdt { - None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."), - Some(ptr) => Ok(ACPISDTIter { + None => Err("There is no ACPI System Description Table (ACPISDTHeader) to iter on."), + Some(ptr) => Ok(ACPISDTIter { pos: 0, width: ptr_len, sdt: ptr as u32 + mem::size_of::() as u32, - len: (unsafe {(*ptr).length} as usize - mem::size_of::()) / ptr_len - }) + len: (unsafe { (*ptr).length } as usize - mem::size_of::()) + / ptr_len, + }), } } } @@ -116,47 +121,53 @@ impl Iterator for ACPISDTIter { if self.pos > self.len { return None; } - let ret = Some(unsafe {*(self.sdt as *const u32)}); + let ret = Some(unsafe { *(self.sdt as *const u32) }); self.sdt += self.width as u32; return ret; } } -fn is_init() -> Result <(), &'static str> { - if unsafe {ACPI.valid} { +fn is_init() -> Result<(), &'static str> { + if unsafe { ACPI.valid } { Ok(()) } else { Err("ACPI is not initialized") } } - /// Initalized the ACPI module -pub fn init() -> Result <(), &'static str> { +pub fn init() -> Result<(), &'static str> { if let Ok(()) = is_init() { return Ok(()); } - unsafe {ACPI.init()} + unsafe { ACPI.init() } } /// Load the ACPI module, addr given is a ptr to RSDP -pub fn load(rsdp_addr: u32) -> Result <(), &'static str> { +pub fn load(rsdp_addr: u32) -> Result<(), &'static str> { if let Ok(()) = is_init() { return Ok(()); } - unsafe {ACPI.load(rsdp_addr)} + unsafe { ACPI.load(rsdp_addr) } } /// Proceed to ACPI shutdown /// This function doesn't work with Virtual Box yet -pub fn shutdown() -> Result <(), &'static str> { +pub fn shutdown() -> Result<(), &'static str> { is_init()?; dsdt::shutdown(fadt::get_controlblock()?) } /// Display state of ACPI -pub fn info() -> Result <(), &'static str> { +pub fn info() -> Result<(), &'static str> { is_init()?; - println!("ACPI STATE:\n {}", if fadt::is_enable()? {"ENABLED"} else {"DISABLED"}); + println!( + "ACPI STATE:\n {}", + if fadt::is_enable()? { + "ENABLED" + } else { + "DISABLED" + } + ); Ok(()) } diff --git a/kernel-rs/src/acpi/rsdp.rs b/kernel-rs/src/acpi/rsdp.rs index 02ff4914..028f1451 100644 --- a/kernel-rs/src/acpi/rsdp.rs +++ b/kernel-rs/src/acpi/rsdp.rs @@ -1,4 +1,4 @@ -use super::{check_signature,check_checksum}; +use super::{check_checksum, check_signature}; use core::mem; #[repr(C)] @@ -27,39 +27,41 @@ static mut RSDPTR: Option = None; /// Return a bool /// true => RSDP is V2 /// false => RSDP is V1 -pub fn load(addr: u32) -> Result { +pub fn load(addr: u32) -> Result { if check_signature(addr, "RSD PTR ") { - let rsdp_tmp: RSDP20 = unsafe{ (*(addr as *const RSDP20)).clone() }; + let rsdp_tmp: RSDP20 = unsafe { (*(addr as *const RSDP20)).clone() }; let revision = rsdp_tmp.rsdp.revision; - if (revision == 0 && check_checksum(addr, mem::size_of::())) || (revision == 2 && check_checksum(addr, mem::size_of::())) { - unsafe {RSDPTR = Some(rsdp_tmp)}; + if (revision == 0 && check_checksum(addr, mem::size_of::())) + || (revision == 2 && check_checksum(addr, mem::size_of::())) + { + unsafe { RSDPTR = Some(rsdp_tmp) }; return Ok(revision == 2); } } Err("Not a valid RSD ptr") } -fn memory_finding() -> Result { +fn memory_finding() -> Result { let mut i = 0; while i < 0x1000000 { i += 8; if let Ok(result) = load(i) { - return Ok(result) + return Ok(result); } } Err("Can not find Root System Description Pointer (RSDP).") } -fn is_init() -> Result { - match unsafe {RSDPTR.clone()} { - Some(rsdptr) => Ok(rsdptr), - None => Err("Root System Description Pointer (RSDP) is not initialized") +fn is_init() -> Result { + match unsafe { RSDPTR.clone() } { + Some(rsdptr) => Ok(rsdptr), + None => Err("Root System Description Pointer (RSDP) is not initialized"), } } /// Return a ptr on xsdt /// RSDP must have been initialized first -pub fn xsdtaddr() -> Result { +pub fn xsdtaddr() -> Result { let rsdptr = is_init()?; let revision = rsdptr.rsdp.revision; if revision != 2 { @@ -70,7 +72,7 @@ pub fn xsdtaddr() -> Result { /// Return a ptr on rsdt /// RSDP must have been initialized first -pub fn rsdtaddr() -> Result { +pub fn rsdtaddr() -> Result { let rsdptr = is_init()?; return Ok(rsdptr.rsdp.rsdtaddr); } @@ -78,6 +80,6 @@ pub fn rsdtaddr() -> Result { /// RSDP init will iter on addr in [0x0 - 0x1000000] to find "RSDP PTR " /// if you already know the location, you should prefer to use load function /// return an Error if there is no RSDP in memory, or return the value of load function -pub fn init() -> Result { +pub fn init() -> Result { memory_finding() } diff --git a/kernel-rs/src/acpi/rsdt.rs b/kernel-rs/src/acpi/rsdt.rs index dd2cb047..59ed0fb0 100644 --- a/kernel-rs/src/acpi/rsdt.rs +++ b/kernel-rs/src/acpi/rsdt.rs @@ -1,13 +1,13 @@ -use super::{ACPISDTHeader,ACPISDTIter}; +use super::{ACPISDTHeader, ACPISDTIter}; //TODO this can work only if pagging is disabled static mut RSDT: Option<*const ACPISDTHeader> = None; /// ## Initialize Root System Description Table (RSDT) /// input param addr is contain in RSDP -pub fn init(addr: u32) -> Result <(), &'static str> { +pub fn init(addr: u32) -> Result<(), &'static str> { if ACPISDTHeader::valid(addr, "RSDT") { - unsafe {RSDT = Some(addr as *const ACPISDTHeader)}; + unsafe { RSDT = Some(addr as *const ACPISDTHeader) }; return Ok(()); } return Err("Can not find Root System Description Table (RSDT)."); @@ -15,6 +15,6 @@ pub fn init(addr: u32) -> Result <(), &'static str> { /// Return a iterable of ptr contained in RSDT /// RSDT must have been initialized first -pub fn iter() -> Result { - ACPISDTIter::new(unsafe {RSDT}, 4) +pub fn iter() -> Result { + ACPISDTIter::new(unsafe { RSDT }, 4) } diff --git a/kernel-rs/src/acpi/xsdt.rs b/kernel-rs/src/acpi/xsdt.rs index 06ae29bd..eb05c1ae 100644 --- a/kernel-rs/src/acpi/xsdt.rs +++ b/kernel-rs/src/acpi/xsdt.rs @@ -1,15 +1,15 @@ -use super::{ACPISDTHeader,ACPISDTIter}; +use super::{ACPISDTHeader, ACPISDTIter}; //TODO this can work only if pagging is disabled static mut XSDT: Option<*const ACPISDTHeader> = None; /// ## Initialize Root System Description Table (XSDT) /// input param addr is contain in RSDP -pub fn init(addr: u64) -> Result <(), &'static str> { +pub fn init(addr: u64) -> Result<(), &'static str> { assert!((addr as u32) as u64 == addr); let addr: u32 = addr as u32; if ACPISDTHeader::valid(addr, "XSDT") { - unsafe {XSDT = Some(addr as *const ACPISDTHeader)}; + unsafe { XSDT = Some(addr as *const ACPISDTHeader) }; return Ok(()); } return Err("Can not find eXtended System Descriptor Table (XSDT)."); @@ -17,6 +17,6 @@ pub fn init(addr: u64) -> Result <(), &'static str> { /// Return a iterable of ptr contained in XSDT /// XSDT must have been initialized first -pub fn iter() -> Result { - ACPISDTIter::new(unsafe {XSDT}, 8) +pub fn iter() -> Result { + ACPISDTIter::new(unsafe { XSDT }, 8) } diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index 2a4ca765..9707bd8a 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -5,11 +5,9 @@ use x86::*; use x86::structures::paging::*; use arch::x86::paging::*; -fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) -{ +fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) { let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32)); - let heap_end_page = Page::containing_address(VirtAddr::new( - offset as u32 + size as u32 - 1)); + let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1)); for page in heap_start_page..heap_end_page + 1 { active_table.map(page, PageTableFlags::WRITABLE); diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/x86/device/cpu.rs index eaadb10b..35c56a7c 100644 --- a/kernel-rs/src/arch/x86/device/cpu.rs +++ b/kernel-rs/src/arch/x86/device/cpu.rs @@ -1,6 +1,6 @@ extern crate raw_cpuid; -use core::fmt::{Result}; +use core::fmt::Result; use self::raw_cpuid::CpuId; @@ -29,102 +29,260 @@ pub fn cpu_info() -> Result { if let Some(info) = cpuid.get_feature_info() { print!("Features:"); - if info.has_fpu() { print!(" fpu") }; - if info.has_vme() { print!(", vme") }; - if info.has_de() { print!(", de") }; - if info.has_pse() { print!(", pse") }; - if info.has_tsc() { print!(", tsc") }; - if info.has_msr() { print!(", msr") }; - if info.has_pae() { print!(", pae") }; - if info.has_mce() { print!(", mce") }; + if info.has_fpu() { + print!(" fpu") + }; + if info.has_vme() { + print!(", vme") + }; + if info.has_de() { + print!(", de") + }; + if info.has_pse() { + print!(", pse") + }; + if info.has_tsc() { + print!(", tsc") + }; + if info.has_msr() { + print!(", msr") + }; + if info.has_pae() { + print!(", pae") + }; + if info.has_mce() { + print!(", mce") + }; - if info.has_cmpxchg8b() { print!(", cx8") }; - if info.has_apic() { print!(", apic") }; - if info.has_sysenter_sysexit() { print!(", sep") }; - if info.has_mtrr() { print!(", mtrr") }; - if info.has_pge() { print!(", pge") }; - if info.has_mca() { print!(", mca") }; - if info.has_cmov() { print!(", cmov") }; - if info.has_pat() { print!(", pat") }; + if info.has_cmpxchg8b() { + print!(", cx8") + }; + if info.has_apic() { + print!(", apic") + }; + if info.has_sysenter_sysexit() { + print!(", sep") + }; + if info.has_mtrr() { + print!(", mtrr") + }; + if info.has_pge() { + print!(", pge") + }; + if info.has_mca() { + print!(", mca") + }; + if info.has_cmov() { + print!(", cmov") + }; + if info.has_pat() { + print!(", pat") + }; - if info.has_pse36() { print!(", pse36") }; - if info.has_psn() { print!(", psn") }; - if info.has_clflush() { print!(", clflush") }; - if info.has_ds() { print!(", ds") }; - if info.has_acpi() { print!(", acpi") }; - if info.has_mmx() { print!(", mmx") }; - if info.has_fxsave_fxstor() { print!(", fxsr") }; - if info.has_sse() { print!(", sse") }; + if info.has_pse36() { + print!(", pse36") + }; + if info.has_psn() { + print!(", psn") + }; + if info.has_clflush() { + print!(", clflush") + }; + if info.has_ds() { + print!(", ds") + }; + if info.has_acpi() { + print!(", acpi") + }; + if info.has_mmx() { + print!(", mmx") + }; + if info.has_fxsave_fxstor() { + print!(", fxsr") + }; + if info.has_sse() { + print!(", sse") + }; - if info.has_sse2() { print!(", sse2") }; - if info.has_ss() { print!(", ss") }; - if info.has_htt() { print!(", ht") }; - if info.has_tm() { print!(", tm") }; - if info.has_pbe() { print!(", pbe") }; + if info.has_sse2() { + print!(", sse2") + }; + if info.has_ss() { + print!(", ss") + }; + if info.has_htt() { + print!(", ht") + }; + if info.has_tm() { + print!(", tm") + }; + if info.has_pbe() { + print!(", pbe") + }; - if info.has_sse3() { print!(", sse3") }; - if info.has_pclmulqdq() { print!(", pclmulqdq") }; - if info.has_ds_area() { print!(", dtes64") }; - if info.has_monitor_mwait() { print!(", monitor") }; - if info.has_cpl() { print!(", ds_cpl") }; - if info.has_vmx() { print!(", vmx") }; - if info.has_smx() { print!(", smx") }; - if info.has_eist() { print!(", est") }; + if info.has_sse3() { + print!(", sse3") + }; + if info.has_pclmulqdq() { + print!(", pclmulqdq") + }; + if info.has_ds_area() { + print!(", dtes64") + }; + if info.has_monitor_mwait() { + print!(", monitor") + }; + if info.has_cpl() { + print!(", ds_cpl") + }; + if info.has_vmx() { + print!(", vmx") + }; + if info.has_smx() { + print!(", smx") + }; + if info.has_eist() { + print!(", est") + }; - if info.has_tm2() { print!(", tm2") }; - if info.has_ssse3() { print!(", ssse3") }; - if info.has_cnxtid() { print!(", cnxtid") }; - if info.has_fma() { print!(", fma") }; - if info.has_cmpxchg16b() { print!(", cx16") }; - if info.has_pdcm() { print!(", pdcm") }; - if info.has_pcid() { print!(", pcid") }; - if info.has_dca() { print!(", dca") }; + if info.has_tm2() { + print!(", tm2") + }; + if info.has_ssse3() { + print!(", ssse3") + }; + if info.has_cnxtid() { + print!(", cnxtid") + }; + if info.has_fma() { + print!(", fma") + }; + if info.has_cmpxchg16b() { + print!(", cx16") + }; + if info.has_pdcm() { + print!(", pdcm") + }; + if info.has_pcid() { + print!(", pcid") + }; + if info.has_dca() { + print!(", dca") + }; - if info.has_sse41() { print!(", sse4_1") }; - if info.has_sse42() { print!(", sse4_2") }; - if info.has_x2apic() { print!(", x2apic") }; - if info.has_movbe() { print!(", movbe") }; - if info.has_popcnt() { print!(", popcnt") }; - if info.has_tsc_deadline() { print!(", tsc_deadline_timer") }; - if info.has_aesni() { print!(", aes") }; - if info.has_xsave() { print!(", xsave") }; + if info.has_sse41() { + print!(", sse4_1") + }; + if info.has_sse42() { + print!(", sse4_2") + }; + if info.has_x2apic() { + print!(", x2apic") + }; + if info.has_movbe() { + print!(", movbe") + }; + if info.has_popcnt() { + print!(", popcnt") + }; + if info.has_tsc_deadline() { + print!(", tsc_deadline_timer") + }; + if info.has_aesni() { + print!(", aes") + }; + if info.has_xsave() { + print!(", xsave") + }; - if info.has_oxsave() { print!(", xsaveopt") }; - if info.has_avx() { print!(", avx") }; - if info.has_f16c() { print!(", f16c") }; - if info.has_rdrand() { print!(", rdrand") }; + if info.has_oxsave() { + print!(", xsaveopt") + }; + if info.has_avx() { + print!(", avx") + }; + if info.has_f16c() { + print!(", f16c") + }; + if info.has_rdrand() { + print!(", rdrand") + }; println!(""); } if let Some(info) = cpuid.get_extended_function_info() { print!("Extended function:"); - if info.has_64bit_mode() { print!(" lm") }; - if info.has_rdtscp() { print!(", rdtscp") }; - if info.has_1gib_pages() { print!(", pdpe1gb") }; - if info.has_execute_disable() { print!(", nx") }; - if info.has_syscall_sysret() { print!(", syscall") }; - if info.has_prefetchw() { print!(", prefetchw") }; - if info.has_lzcnt() { print!(", lzcnt") }; - if info.has_lahf_sahf() { print!(", lahf_lm") }; - if info.has_invariant_tsc() { print!(", constant_tsc") }; + if info.has_64bit_mode() { + print!(" lm") + }; + if info.has_rdtscp() { + print!(", rdtscp") + }; + if info.has_1gib_pages() { + print!(", pdpe1gb") + }; + if info.has_execute_disable() { + print!(", nx") + }; + if info.has_syscall_sysret() { + print!(", syscall") + }; + if info.has_prefetchw() { + print!(", prefetchw") + }; + if info.has_lzcnt() { + print!(", lzcnt") + }; + if info.has_lahf_sahf() { + print!(", lahf_lm") + }; + if info.has_invariant_tsc() { + print!(", constant_tsc") + }; println!(""); } if let Some(info) = cpuid.get_extended_feature_info() { print!("Extended features:"); - if info.has_fsgsbase() { print!(" fsgsbase") }; - if info.has_tsc_adjust_msr() { print!(", tsc_adjust") }; - if info.has_bmi1() { print!(", bmi1") }; - if info.has_hle() { print!(", hle") }; - if info.has_avx2() { print!(", avx2") }; - if info.has_smep() { print!(", smep") }; - if info.has_bmi2() { print!(", bmi2") }; - if info.has_rep_movsb_stosb() { print!(", erms") }; - if info.has_invpcid() { print!(", invpcid") }; - if info.has_rtm() { print!(", rtm") }; - if info.has_qm() { print!(", qm") }; - if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") }; - if info.has_mpx() { print!(", mpx") }; + if info.has_fsgsbase() { + print!(" fsgsbase") + }; + if info.has_tsc_adjust_msr() { + print!(", tsc_adjust") + }; + if info.has_bmi1() { + print!(", bmi1") + }; + if info.has_hle() { + print!(", hle") + }; + if info.has_avx2() { + print!(", avx2") + }; + if info.has_smep() { + print!(", smep") + }; + if info.has_bmi2() { + print!(", bmi2") + }; + if info.has_rep_movsb_stosb() { + print!(", erms") + }; + if info.has_invpcid() { + print!(", invpcid") + }; + if info.has_rtm() { + print!(", rtm") + }; + if info.has_qm() { + print!(", qm") + }; + if info.has_fpu_cs_ds_deprecated() { + print!(", fpu_seg") + }; + if info.has_mpx() { + print!(", mpx") + }; println!(""); } diff --git a/kernel-rs/src/arch/x86/device/local_apic.rs b/kernel-rs/src/arch/x86/device/local_apic.rs index 3a4e79c6..058be3fd 100644 --- a/kernel-rs/src/arch/x86/device/local_apic.rs +++ b/kernel-rs/src/arch/x86/device/local_apic.rs @@ -1,8 +1,8 @@ -use ::arch::x86::paging::ActivePageTable; +use arch::x86::paging::ActivePageTable; pub static mut LOCAL_APIC: LocalApic = LocalApic { address: 0, - x2: false + x2: false, }; pub unsafe fn init(active_table: &mut ActivePageTable) { @@ -11,7 +11,7 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { pub struct LocalApic { pub address: usize, - pub x2: bool + pub x2: bool, } impl LocalApic { diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index dc1eac30..1a0a08a9 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -1,4 +1,4 @@ -use ::arch::x86::paging::ActivePageTable; +use arch::x86::paging::ActivePageTable; pub mod pic; pub mod local_apic; pub mod cpu; diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs index 00b5ab21..39a4f2f7 100644 --- a/kernel-rs/src/arch/x86/device/pic.rs +++ b/kernel-rs/src/arch/x86/device/pic.rs @@ -1,47 +1,64 @@ -use ::io::{Io, Pio}; +use io::{Io, Pio}; pub static mut MASTER: Pic = Pic::new(0x20); pub static mut SLAVE: Pic = Pic::new(0xA0); pub static mut WAIT_PORT: Pio = Pio::new(0x80); pub unsafe fn init() { - let wait = || {WAIT_PORT.write(0)}; + let wait = || WAIT_PORT.write(0); let master_mask = MASTER.data.read(); let slave_mask = SLAVE.data.read(); // Start initialization - MASTER.cmd.write(0x11); wait(); - SLAVE.cmd.write(0x11); wait(); + MASTER.cmd.write(0x11); + wait(); + SLAVE.cmd.write(0x11); + wait(); // Set offsets - MASTER.data.write(0x20); wait(); - SLAVE.data.write(0x28); wait(); + MASTER.data.write(0x20); + wait(); + SLAVE.data.write(0x28); + wait(); // Set up cascade - MASTER.data.write(4); wait(); - SLAVE.data.write(2); wait(); + MASTER.data.write(4); + wait(); + SLAVE.data.write(2); + wait(); // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) - MASTER.data.write(1); wait(); - SLAVE.data.write(1); wait(); + MASTER.data.write(1); + wait(); + SLAVE.data.write(1); + wait(); // Unmask interrupts - MASTER.data.write(0); wait(); - SLAVE.data.write(0); wait(); + MASTER.data.write(0); + wait(); + SLAVE.data.write(0); + wait(); // Ack remaining interrupts - MASTER.ack(); wait(); - SLAVE.ack(); wait(); + MASTER.ack(); + wait(); + SLAVE.ack(); + wait(); - MASTER.data.write(master_mask); wait(); - SLAVE.data.write(slave_mask); wait(); + MASTER.data.write(master_mask); + wait(); + SLAVE.data.write(slave_mask); + wait(); // disable all irqs - MASTER.data.write(!0); wait(); - SLAVE.data.write(!0); wait(); - + MASTER.data.write(!0); + wait(); + SLAVE.data.write(!0); + wait(); + // keyboard active - MASTER.mask_clear(1); wait(); + MASTER.mask_clear(1); + wait(); // asm!("sti"); ::x86::instructions::interrupts::enable(); diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 0fed6425..ff682cba 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -4,15 +4,15 @@ use x86::instructions::segmentation::set_cs; use x86::instructions::tables::load_tss; use spin::Once; -static GDT: Once = Once::new(); -static TSS: Once = Once::new(); +// static GDT: Once = Once::new(); +// static TSS: Once = Once::new(); pub fn init() { // let tss = tss::TaskStateSegment::new(); - let tss = TSS.call_once(|| { - let mut tss = tss::TaskStateSegment::new(); - tss - }); + // let tss = TSS.call_once(|| { + // let mut tss = tss::TaskStateSegment::new(); + // tss + // }); // let mut code_selector = gdt::SegmentSelector(0); // let mut tss_selector = gdt::SegmentSelector(0); diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 9a75ef24..88bd80c5 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -1,6 +1,6 @@ // https://wiki.osdev.org/Exceptions -use ::arch::x86::pti; +use arch::x86::pti; macro_rules! exception { ($name:ident, $func:block) => { @@ -62,8 +62,9 @@ exception_err!(stack_segment, {}); exception_err!(general_protection, {}); pub extern "x86-interrupt" fn page_fault( - stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode) -{ + stack_frame: &mut ExceptionStackFrame, + code: PageFaultErrorCode, +) { println!("Exception: page_fault"); println!("Error code: {:#b}", code); println!("{:#?}", stack_frame); diff --git a/kernel-rs/src/arch/x86/interrupt/mod.rs b/kernel-rs/src/arch/x86/interrupt/mod.rs index 81c73a70..c8a97f14 100644 --- a/kernel-rs/src/arch/x86/interrupt/mod.rs +++ b/kernel-rs/src/arch/x86/interrupt/mod.rs @@ -1,2 +1,4 @@ -#[macro_use] pub mod exception; -#[macro_use] pub mod irq; +#[macro_use] +pub mod exception; +#[macro_use] +pub mod irq; diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 74572557..9f32c21d 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -6,14 +6,14 @@ pub mod interrupt; pub mod device; pub mod pti; -pub mod gdt; +// pub mod gdt; pub mod idt; use multiboot2; use acpi; #[no_mangle] -pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { +pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // parse multiboot2 info let boot_info = multiboot2::load(multiboot_info_addr); @@ -26,24 +26,26 @@ pub unsafe extern fn x86_rust_start(multiboot_info_addr: usize) { acpi::init().expect("ACPI failed"); } + // fill and load idt (exceptions + irqs) + idt::init(); + // set up physical allocator - ::memory::init(&boot_info); + ::memory::init(&boot_info); // set up virtual mapping let mut active_table = paging::init(&boot_info); + asm!("hlt"); + // set up heap ::allocator::init(&mut active_table); - // set up memory segmentation - // gdt::init(); - - // set up interrupts - idt::init(); - // set up pic & apic device::init(&mut active_table); + // fill and load gdt + // gdt::init(); + // primary CPU entry point ::kmain(); } diff --git a/kernel-rs/src/arch/x86/paging/mapper.rs b/kernel-rs/src/arch/x86/paging/mapper.rs index 128e82be..56ba3517 100644 --- a/kernel-rs/src/arch/x86/paging/mapper.rs +++ b/kernel-rs/src/arch/x86/paging/mapper.rs @@ -31,8 +31,7 @@ impl Mapper { } /// virtual addr to physical addr translation - pub fn translate(&self, virtual_address: VirtAddr) -> Option - { + pub fn translate(&self, virtual_address: VirtAddr) -> Option { let offset = virtual_address.as_u32() % PAGE_SIZE as u32; self.translate_page(Page::containing_address(virtual_address)) .map(|frame| frame.start_address() + offset) @@ -54,33 +53,29 @@ impl Mapper { }; p1.and_then(|p1| p1[page.p1_index()].pointed_frame()) - .or_else(huge_page) + .or_else(huge_page) } /// map a virtual page to a physical frame in the page tables - pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags) - { + pub fn map_to(&mut self, page: Page, frame: PhysFrame, flags: PageTableFlags) { let p2 = self.p2_mut(); let p1 = p2.next_table_create(usize_from(u32::from(page.p2_index()))); assert!(p1[page.p1_index()].is_unused()); p1[page.p1_index()].set(frame, flags | PageTableFlags::PRESENT); } - pub fn map(&mut self, page: Page, flags: PageTableFlags) - { + pub fn map(&mut self, page: Page, flags: PageTableFlags) { let frame = ::memory::allocate_frames(1).expect("out of frames"); self.map_to(page, frame, flags) } - pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags) - { + pub fn identity_map(&mut self, frame: PhysFrame, flags: PageTableFlags) { let virt_addr = VirtAddr::new(frame.start_address().as_u32()); let page = Page::containing_address(virt_addr); self.map_to(page, frame, flags); } - pub fn unmap(&mut self, page: Page) - { + pub fn unmap(&mut self, page: Page) { assert!(self.translate(page.start_address()).is_some()); let p1 = self.p2_mut() diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs index 1a4db1c7..39e87944 100644 --- a/kernel-rs/src/arch/x86/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -51,34 +51,40 @@ impl ActivePageTable { } } - pub fn with(&mut self, - table: &mut InactivePageTable, - temporary_page: &mut temporary_page::TemporaryPage, - f: F) - where F: FnOnce(&mut Mapper) - { - let (cr3_back, _cr3flags_back) = Cr3::read(); + pub fn with( + &mut self, + table: &mut InactivePageTable, + temporary_page: &mut temporary_page::TemporaryPage, + f: F, + ) where + F: FnOnce(&mut Mapper), + { + let (cr3_back, _cr3flags_back) = Cr3::read(); - // map temp page to current p2 - let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); + // map temp page to current p2 + let p2_table = temporary_page.map_table_frame(cr3_back.clone(), self); - // overwrite recursive map - self.p2_mut()[1023].set(table.p2_frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - tlb::flush_all(); + // overwrite recursive map + self.p2_mut()[1023].set( + table.p2_frame.clone(), + PageTableFlags::PRESENT | PageTableFlags::WRITABLE, + ); + tlb::flush_all(); - // execute f in the new context - f(self); + // execute f in the new context + f(self); - // restore recursive mapping to original p2 table - p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - } + // restore recursive mapping to original p2 table + p2_table[1023].set(cr3_back, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); + } pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable { - let (p2_frame, cr3_flags) = Cr3::read(); let old_table = InactivePageTable { p2_frame }; - unsafe { Cr3::write(new_table.p2_frame, cr3_flags); } + unsafe { + Cr3::write(new_table.p2_frame, cr3_flags); + } old_table } @@ -89,39 +95,44 @@ pub struct InactivePageTable { } impl InactivePageTable { - pub fn new(frame: PhysFrame, - active_table: &mut ActivePageTable, - temporary_page: &mut TemporaryPage) - -> InactivePageTable { - { - let table = temporary_page.map_table_frame(frame.clone(), active_table); + pub fn new( + frame: PhysFrame, + active_table: &mut ActivePageTable, + temporary_page: &mut TemporaryPage, + ) -> InactivePageTable { + { + let table = temporary_page.map_table_frame(frame.clone(), active_table); - table.zero(); - // set up recursive mapping for the table - table[1023].set(frame.clone(), PageTableFlags::PRESENT | PageTableFlags::WRITABLE) - } - temporary_page.unmap(active_table); - InactivePageTable { p2_frame: frame } + table.zero(); + // set up recursive mapping for the table + table[1023].set( + frame.clone(), + PageTableFlags::PRESENT | PageTableFlags::WRITABLE, + ) } + temporary_page.unmap(active_table); + InactivePageTable { p2_frame: frame } + } } -pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable -{ - let mut temporary_page = TemporaryPage::new(Page{number: 0xcafe}); +pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable { + let mut temporary_page = TemporaryPage::new(Page { number: 0xcafe }); let mut active_table = unsafe { ActivePageTable::new() }; let mut new_table = { let frame = ::memory::allocate_frames(1).expect("no more frames"); InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; - + unsafe { + asm!("hlt"); + } active_table.with(&mut new_table, &mut temporary_page, |mapper| { - // id map vga buffer let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); mapper.identity_map(vga_buffer_frame, PageTableFlags::WRITABLE); - let elf_sections_tag = boot_info.elf_sections_tag() + let elf_sections_tag = boot_info + .elf_sections_tag() .expect("Memory map tag required"); // id map kernel sections @@ -129,24 +140,26 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable if !section.is_allocated() { continue; } - assert!(section.start_address() % PAGE_SIZE as u64 == 0, - "sections need to be page aligned"); + assert!( + section.start_address() % PAGE_SIZE as u64 == 0, + "sections need to be page aligned" + ); let flags = elf_to_pagetable_flags(§ion.flags()); - let start_frame = PhysFrame::containing_address( - PhysAddr::new(section.start_address() as u32)); - let end_frame = PhysFrame::containing_address( - PhysAddr::new(section.end_address() as u32 - 1)); + let start_frame = + PhysFrame::containing_address(PhysAddr::new(section.start_address() as u32)); + let end_frame = + PhysFrame::containing_address(PhysAddr::new(section.end_address() as u32 - 1)); for frame in start_frame..end_frame + 1 { mapper.identity_map(frame, flags); } } // id map multiboot - let multiboot_start = PhysFrame::containing_address( - PhysAddr::new(boot_info.start_address() as u32)); - let multiboot_end = PhysFrame::containing_address( - PhysAddr::new(boot_info.end_address() as u32 - 1)); + let multiboot_start = + PhysFrame::containing_address(PhysAddr::new(boot_info.start_address() as u32)); + let multiboot_end = + PhysFrame::containing_address(PhysAddr::new(boot_info.end_address() as u32 - 1)); for frame in multiboot_start..multiboot_end + 1 { mapper.identity_map(frame, PageTableFlags::PRESENT); } @@ -154,17 +167,15 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable let old_table = active_table.switch(new_table); - let old_p2_page = Page::containing_address( - VirtAddr::new(old_table.p2_frame.start_address().as_u32())); + let old_p2_page = + Page::containing_address(VirtAddr::new(old_table.p2_frame.start_address().as_u32())); active_table.unmap(old_p2_page); active_table } -fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) - -> PageTableFlags -{ +fn elf_to_pagetable_flags(elf_flags: &multiboot2::ElfSectionFlags) -> PageTableFlags { use multiboot2::ElfSectionFlags; let mut flags = PageTableFlags::empty(); diff --git a/kernel-rs/src/arch/x86/paging/table.rs b/kernel-rs/src/arch/x86/paging/table.rs index 41eec7e0..3b774172 100644 --- a/kernel-rs/src/arch/x86/paging/table.rs +++ b/kernel-rs/src/arch/x86/paging/table.rs @@ -1,20 +1,18 @@ use x86::structures::paging::*; -pub trait RecTable -{ +pub trait RecTable { fn next_table_address(&self, index: usize) -> Option; fn next_table(&self, index: usize) -> Option<&PageTable>; fn next_table_mut(&mut self, index: usize) -> Option<&mut PageTable>; - fn next_table_create(&mut self, - index: usize) - -> &mut PageTable; + fn next_table_create(&mut self, index: usize) -> &mut PageTable; } -impl RecTable for PageTable -{ +impl RecTable for PageTable { fn next_table_address(&self, index: usize) -> Option { let entry_flags = self[index].flags(); - if entry_flags.contains(PageTableFlags::PRESENT) && !entry_flags.contains(PageTableFlags::HUGE_PAGE) { + if entry_flags.contains(PageTableFlags::PRESENT) + && !entry_flags.contains(PageTableFlags::HUGE_PAGE) + { let table_address = self as *const _ as usize; Some((table_address << 10 | index << 12) as u32) } else { @@ -32,16 +30,17 @@ impl RecTable for PageTable .map(|address| unsafe { &mut *(address as *mut _) }) } - fn next_table_create(&mut self, - index: usize) -> &mut PageTable - { + fn next_table_create(&mut self, index: usize) -> &mut PageTable { if self.next_table(index).is_none() { - assert!(!self[index].flags().contains(PageTableFlags::HUGE_PAGE), - "mapping code does not support huge pages"); - let frame = ::memory::allocate_frames(1) - .expect("out of memory"); + assert!( + !self[index].flags().contains(PageTableFlags::HUGE_PAGE), + "mapping code does not support huge pages" + ); + let frame = ::memory::allocate_frames(1).expect("out of memory"); self[index].set(frame, PageTableFlags::PRESENT | PageTableFlags::WRITABLE); - self.next_table_mut(index).expect("next_table_mut gave None").zero() + self.next_table_mut(index) + .expect("next_table_mut gave None") + .zero() } self.next_table_mut(index).expect("no next table 2") } diff --git a/kernel-rs/src/arch/x86/paging/temporary_page.rs b/kernel-rs/src/arch/x86/paging/temporary_page.rs index becdb0fc..b712fcfb 100644 --- a/kernel-rs/src/arch/x86/paging/temporary_page.rs +++ b/kernel-rs/src/arch/x86/paging/temporary_page.rs @@ -7,24 +7,25 @@ pub struct TemporaryPage { } impl TemporaryPage { - pub fn new(page: Page) -> TemporaryPage - { + pub fn new(page: Page) -> TemporaryPage { TemporaryPage { page: page } } /// Maps the temporary page to the given frame in the active table. /// Returns the start address of the temporary page. - pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) - -> VirtAddr - { - assert!(active_table.translate_page(self.page).is_none(), - "temporary page is already mapped"); - active_table.map_to(self.page, frame, PageTableFlags::WRITABLE); - // this kind of check should be done in a test routine - assert!(active_table.translate_page(self.page).is_some(), - "temporary page was not mapped"); - self.page.start_address() - } + pub fn map(&mut self, frame: PhysFrame, active_table: &mut ActivePageTable) -> VirtAddr { + assert!( + active_table.translate_page(self.page).is_none(), + "temporary page is already mapped" + ); + active_table.map_to(self.page, frame, PageTableFlags::WRITABLE); + // this kind of check should be done in a test routine + assert!( + active_table.translate_page(self.page).is_some(), + "temporary page was not mapped" + ); + self.page.start_address() + } /// Unmaps the temporary page in the active table. pub fn unmap(&mut self, active_table: &mut ActivePageTable) { @@ -33,10 +34,11 @@ impl TemporaryPage { /// Maps the temporary page to the given page table frame in the active /// table. Returns a reference to the now mapped table. - pub fn map_table_frame(&mut self, - frame: PhysFrame, - active_table: &mut ActivePageTable) - -> &mut PageTable { - unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } - } + pub fn map_table_frame( + &mut self, + frame: PhysFrame, + active_table: &mut ActivePageTable, + ) -> &mut PageTable { + unsafe { &mut *(self.map(frame, active_table).as_u32() as *mut PageTable) } + } } diff --git a/kernel-rs/src/arch/x86/pti.rs b/kernel-rs/src/arch/x86/pti.rs index 7942d611..91f488c1 100644 --- a/kernel-rs/src/arch/x86/pti.rs +++ b/kernel-rs/src/arch/x86/pti.rs @@ -20,11 +20,7 @@ unsafe fn switch_stack(old: usize, new: usize) { let new_esp = new - offset_esp; - ptr::copy_nonoverlapping( - old_esp as *const u8, - new_esp as *mut u8, - offset_esp - ); + ptr::copy_nonoverlapping(old_esp as *const u8, new_esp as *mut u8, offset_esp); // switch the esp with the new one asm!("" : : "{esp}"(new_esp) : : "intel", "volatile"); @@ -47,13 +43,19 @@ pub unsafe fn map() { // } // Switch to per-context stack - switch_stack(PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), PTI_CONTEXT_STACK); + switch_stack( + PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), + PTI_CONTEXT_STACK, + ); } #[inline(always)] pub unsafe fn unmap() { // Switch to per-CPU stack - switch_stack(PTI_CONTEXT_STACK, PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len()); + switch_stack( + PTI_CONTEXT_STACK, + PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), + ); // { // let mut active_table = unsafe { ActivePageTable::new() }; diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 29a8f583..0e1eff02 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -6,9 +6,9 @@ use cpuio; use core::char; use vga::*; -fn dispatch(command: &str) -> Result <(), &'static str> { +fn dispatch(command: &str) -> Result<(), &'static str> { match command { - "help" | "h" => self::help(), + "help" | "h" => self::help(), // multiboot // "memory" => self::mb2_memory(), @@ -16,20 +16,20 @@ fn dispatch(command: &str) -> Result <(), &'static str> { // "sections" => self::mb2_sections(), // ACPI - "acpi" => self::acpi_info(), - "reboot" => self::reboot(), - "shutdown" | "halt" | "q" => self::shutdown(), + "acpi" => self::acpi_info(), + "reboot" => self::reboot(), + "shutdown" | "halt" | "q" => self::shutdown(), // x86 specific - "stack" => self::print_stack(), - "regs" => self::regs(), - "cpu" => self::cpu(), + "stack" => self::print_stack(), + "regs" => self::regs(), + "cpu" => self::cpu(), - _ => Err("Command unknown. (h|help for help)"), + _ => Err("Command unknown. (h|help for help)"), } } -pub fn exec(cli: &Writer) -> Result <(), &'static str> { +pub fn exec(cli: &Writer) -> Result<(), &'static str> { let command = cli.get_command()?; if let Err(msg) = self::dispatch(command) { set_color!(Red); @@ -39,7 +39,7 @@ pub fn exec(cli: &Writer) -> Result <(), &'static str> { Ok(()) } -fn help() -> Result <(), &'static str> { +fn help() -> Result<(), &'static str> { println!("acpi => Return acpi state (ENABLED|DISABLE)"); println!("help | h => Print this help"); // println!("memory => Print memory areas"); @@ -59,14 +59,14 @@ fn help() -> Result <(), &'static str> { /// If reboot failed, will loop on a halt cmd /// fn reboot() -> ! { - unsafe {asm!("cli")}; //TODO volatile ????? - // I will now clear the keyboard buffer + unsafe { asm!("cli") }; //TODO volatile ????? + // I will now clear the keyboard buffer let mut buffer: u8 = 0x02; while buffer & 0x02 != 0 { cpuio::inb(0x60); buffer = cpuio::inb(0x64); } - cpuio::outb(0x64, 0xFE);//Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot + cpuio::outb(0x64, 0xFE); //Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot println!("Unable to perform reboot. Kernel will be halted"); cpuio::halt(); } @@ -76,7 +76,7 @@ fn reboot() -> ! { /// If shutdown is performed but failed, will loop on a halt cmd /// If shutdown cannot be called, return a Err(&str) /// -fn shutdown() -> Result <(), &'static str> { +fn shutdown() -> Result<(), &'static str> { acpi::shutdown()?; println!("Unable to perform ACPI shutdown. Kernel will be halted"); cpuio::halt(); @@ -102,14 +102,14 @@ fn print_line(line: &[u8], address: usize) { for byte in line { print!("{:02x} ", *byte); } - let length : usize = 16 - line.len(); + let length: usize = 16 - line.len(); for _ in 0..length { print!(" "); } print!("|"); for byte in line { match is_control(*byte as char) { - true => print!("."), + true => print!("."), false => print!("{}", *byte as char), }; } @@ -117,7 +117,7 @@ fn print_line(line: &[u8], address: usize) { } /// Print the kernel stack -fn print_stack() -> Result <(), &'static str> { +fn print_stack() -> Result<(), &'static str> { let esp: usize; let ebp: usize; unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; @@ -172,14 +172,14 @@ fn print_stack() -> Result <(), &'static str> { // Ok(()) // } -pub fn acpi_info() -> Result <(), &'static str> { +pub fn acpi_info() -> Result<(), &'static str> { acpi::info()?; Ok(()) } /// Dump control registers -pub fn regs() -> Result <(), &'static str> { - use ::x86::registers::control::*; +pub fn regs() -> Result<(), &'static str> { + use x86::registers::control::*; println!("cr0 = {:?}", Cr0::read()); println!("cr3 = {:?}", Cr3::read()); println!("cr4 = {:?}", Cr4::read()); @@ -188,8 +188,8 @@ pub fn regs() -> Result <(), &'static str> { } /// Dump cpu info, should add power management info -pub fn cpu() -> Result <(), &'static str> { - use ::arch::x86::device::cpu; +pub fn cpu() -> Result<(), &'static str> { + use arch::x86::device::cpu; cpu::cpu_info().expect("cpu info not available"); flush!(); Ok(()) diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 15788763..1343789d 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -5,50 +5,52 @@ pub fn inb(port: u16) -> u8 { // The registers for the `in` and `out` instructions are always the // same: `a` for value, and `d` for the port address. let result: u8; - unsafe {asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile")}; + unsafe { asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile") }; result } /// Write a `u8`-sized `value` to `port`. pub fn outb(port: u16, value: u8) { - unsafe {asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile")}; + unsafe { asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile") }; } /// Read a `u16`-sized value from `port`. pub fn inw(port: u16) -> u16 { let result: u16; - unsafe {asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile")}; + unsafe { asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile") }; result } /// Write a `u8`-sized `value` to `port`. pub fn outw(port: u16, value: u16) { - unsafe {asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile")}; + unsafe { asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile") }; } /// Read a `u32`-sized value from `port`. pub fn inl(port: u16) -> u32 { let result: u32; - unsafe {asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile")}; + unsafe { asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile") }; result } /// Write a `u32`-sized `value` to `port`. pub fn outl(port: u16, value: u32) { - unsafe {asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile")}; + unsafe { asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile") }; } /// Halt system pub fn halt() -> ! { - unsafe {asm!("cli" : : : : "volatile")}; + unsafe { asm!("cli" : : : : "volatile") }; loop { - unsafe {asm!("hlt" : : : : "volatile")}; + unsafe { asm!("hlt" : : : : "volatile") }; } } /// wait for an io operation to complete pub fn io_wait() { - unsafe { asm!("jmp 1f\n\t + unsafe { + asm!("jmp 1f\n\t 1:jmp 2f\n\t - 2:" : : : : "volatile")} + 2:" : : : : "volatile") + } } diff --git a/kernel-rs/src/io/mod.rs b/kernel-rs/src/io/mod.rs index 3bb33f5f..0382a50a 100644 --- a/kernel-rs/src/io/mod.rs +++ b/kernel-rs/src/io/mod.rs @@ -5,13 +5,17 @@ pub use self::pio::*; use core::ops::{BitAnd, BitOr, Not}; pub trait Io { - type Value: Copy + PartialEq + BitAnd + BitOr + Not; + type Value: Copy + + PartialEq + + BitAnd + + BitOr + + Not; fn read(&self) -> Self::Value; fn write(&mut self, value: Self::Value); #[inline(always)] - fn readf(&self, flags: Self::Value) -> bool { + fn readf(&self, flags: Self::Value) -> bool { (self.read() & flags) as Self::Value == flags } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index c456d45f..d7c4a16a 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -4,7 +4,7 @@ use cpuio; use vga; const MAX_KEYS: usize = 59; -const KEYMAP_US: [[u8;2]; MAX_KEYS] = [ +const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ *b"\0\0", *b"\0\0",//escape *b"1!", @@ -84,25 +84,24 @@ pub fn kbd_callback() { if (control & 1) == 1 { let scancode = cpuio::inb(0x60); let (is_release, scancode) = check_key_state(scancode); - unsafe {//TODO remove unsafe + unsafe { + //TODO remove unsafe match self::KEYMAP_US.get(scancode as usize) { - Some(b"\0\0") => { - match scancode { - 0x2A | 0x36 => {SHIFT = !is_release}, - 0x38 => {ALT = !is_release}, - 0x1D => {CTRL = !is_release}, - 0x0E if !is_release => { - vga::VGA.backspace(); - } - _ => {} + Some(b"\0\0") => match scancode { + 0x2A | 0x36 => SHIFT = !is_release, + 0x38 => ALT = !is_release, + 0x1D => CTRL = !is_release, + 0x0E if !is_release => { + vga::VGA.backspace(); } + _ => {} }, Some(ascii) if !is_release => { let sym = if SHIFT { ascii[1] } else { ascii[0] }; vga::VGA.keypress(sym); - }, - Some(_) => {}, - None =>{}, + } + Some(_) => {} + None => {} } } } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 8db6c338..9d542d82 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -7,28 +7,28 @@ #![feature(ptr_internals)] #![feature(asm)] #![feature(thread_local)] - // home made heap #![feature(alloc)] #![feature(allocator_api)] #![feature(global_allocator)] - // x86 specific #![feature(abi_x86_interrupt)] -extern crate rlibc; extern crate alloc; -extern crate spin; -#[macro_use] extern crate lazy_static; +#[macro_use] +extern crate lazy_static; extern crate multiboot2; -extern crate slab_allocator; extern crate raw_cpuid; +extern crate rlibc; +extern crate slab_allocator; +extern crate spin; // used by arch/x86, need conditional compilation here extern crate x86; /// 80x25 terminal driver -#[macro_use] pub mod vga; +#[macro_use] +pub mod vga; /// PS/2 detection and processing pub mod keyboard; /// simplisitc kernel commands @@ -45,9 +45,10 @@ pub mod memory; /// arch specific entry points pub mod arch; -/// kernel entry point. arch module is responsible for calling this +/// kernel entry point. arch module is responsible for +/// calling this once the core has loaded pub fn kmain() -> ! { - // core is loaded now + // heap avalaible for tracking free'd frames memory::init_noncore(); // x86::instructions::interrupts::int3(); @@ -66,12 +67,13 @@ pub fn kmain() -> ! { loop {} } -#[lang = "eh_personality"] #[no_mangle] -pub extern fn eh_personality() {} +#[lang = "eh_personality"] +#[no_mangle] +pub extern "C" fn eh_personality() {} -#[lang = "panic_fmt"] #[no_mangle] -pub extern fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) --> ! { +#[lang = "panic_fmt"] +#[no_mangle] +pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { println!("PANIC: {}", fmt); println!("FILE: {}", file); println!("LINE: {}", line); diff --git a/kernel-rs/src/memory/bump.rs b/kernel-rs/src/memory/bump.rs index d45e595c..4e62a672 100644 --- a/kernel-rs/src/memory/bump.rs +++ b/kernel-rs/src/memory/bump.rs @@ -1,4 +1,4 @@ -use multiboot2::{MemoryAreaIter, MemoryArea}; +use multiboot2::{MemoryArea, MemoryAreaIter}; use x86::*; use x86::structures::paging::PhysFrame; use super::FrameAllocator; @@ -14,21 +14,21 @@ pub struct BumpFrameAllocator { } impl BumpFrameAllocator { - pub fn new(kernel_start: usize, kernel_end: usize, - multiboot_start: usize, multiboot_end: usize, - memory_areas: MemoryAreaIter) -> BumpFrameAllocator { + pub fn new( + kernel_start: usize, + kernel_end: usize, + multiboot_start: usize, + multiboot_end: usize, + memory_areas: MemoryAreaIter, + ) -> BumpFrameAllocator { let mut allocator = BumpFrameAllocator { next_free_frame: PhysFrame { number: 0 }, current_area: None, areas: memory_areas, - kernel_start: PhysFrame::containing_address( - PhysAddr::new(kernel_start as u32)), - kernel_end: PhysFrame::containing_address( - PhysAddr::new(kernel_end as u32)), - multiboot_start: PhysFrame::containing_address( - PhysAddr::new(multiboot_start as u32)), - multiboot_end: PhysFrame::containing_address( - PhysAddr::new(multiboot_end as u32)), + kernel_start: PhysFrame::containing_address(PhysAddr::new(kernel_start as u32)), + kernel_end: PhysFrame::containing_address(PhysAddr::new(kernel_end as u32)), + multiboot_start: PhysFrame::containing_address(PhysAddr::new(multiboot_start as u32)), + multiboot_end: PhysFrame::containing_address(PhysAddr::new(multiboot_end as u32)), }; allocator.choose_next_area(); allocator @@ -36,13 +36,16 @@ impl BumpFrameAllocator { fn choose_next_area(&mut self) { // get next area with free frames - self.current_area = self.areas.clone().filter(|area| { - area.end_address() >= self.next_free_frame.start_address().as_u32() as usize - }).min_by_key(|area| area.start_address()); + self.current_area = self.areas + .clone() + .filter(|area| { + area.end_address() >= self.next_free_frame.start_address().as_u32() as usize + }) + .min_by_key(|area| area.start_address()); if let Some(area) = self.current_area { - let start_frame = PhysFrame::containing_address( - PhysAddr::new(area.start_address() as u32)); + let start_frame = + PhysFrame::containing_address(PhysAddr::new(area.start_address() as u32)); if self.next_free_frame < start_frame { self.next_free_frame = start_frame; } @@ -52,22 +55,32 @@ impl BumpFrameAllocator { impl FrameAllocator for BumpFrameAllocator { fn allocate_frames(&mut self, count: usize) -> Option { - if count == 0 { return None }; + if count == 0 { + return None; + }; if let Some(area) = self.current_area { - let start_frame = PhysFrame { number: self.next_free_frame.number }; - let end_frame = PhysFrame { number: self.next_free_frame.number + count as u32 - 1 }; + let start_frame = PhysFrame { + number: self.next_free_frame.number, + }; + let end_frame = PhysFrame { + number: self.next_free_frame.number + count as u32 - 1, + }; - let current_area_last_frame = PhysFrame::containing_address( - PhysAddr::new(area.end_address() as u32)); + let current_area_last_frame = + PhysFrame::containing_address(PhysAddr::new(area.end_address() as u32)); if end_frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); - } else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) { + } else if (start_frame >= self.kernel_start && start_frame <= self.kernel_end) + || (end_frame >= self.kernel_start && end_frame <= self.kernel_end) + { // frame used by kernel self.next_free_frame = PhysFrame { number: self.kernel_end.number + 1, }; - } else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end) || (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end) { + } else if (start_frame >= self.multiboot_start && start_frame <= self.multiboot_end) + || (end_frame >= self.multiboot_start && end_frame <= self.multiboot_end) + { // frame used by multiboot self.next_free_frame = PhysFrame { number: self.multiboot_end.number + 1, @@ -79,13 +92,17 @@ impl FrameAllocator for BumpFrameAllocator { // try again with next_free_frame self.allocate_frames(count) } else { - None + None } } fn deallocate_frames(&mut self, frame: PhysFrame, count: usize) { // bump doesnt deallocate, must be used inside of a recycler - println!("lost frames {:#x} ({})", frame.start_address().as_u32(), count); + println!( + "lost frames {:#x} ({})", + frame.start_address().as_u32(), + count + ); // unimplemented!(); } } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index a8c28ed5..7d9de270 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -24,20 +24,27 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); let memory_map_tag = boot_info.memory_map_tag().unwrap(); - let kernel_start = elf_sections_tag.sections() + let kernel_start = elf_sections_tag + .sections() .filter(|s| s.is_allocated()) .map(|s| s.start_address()) - .min().unwrap(); + .min() + .unwrap(); - let kernel_end = elf_sections_tag.sections() + let kernel_end = elf_sections_tag + .sections() .filter(|s| s.is_allocated()) .map(|s| s.start_address() + s.size()) - .max().unwrap(); + .max() + .unwrap(); let bump_allocator = BumpFrameAllocator::new( - kernel_start as usize, kernel_end as usize, - boot_info.start_address(), boot_info.end_address(), - memory_map_tag.memory_areas()); + kernel_start as usize, + kernel_end as usize, + boot_info.start_address(), + boot_info.end_address(), + memory_map_tag.memory_areas(), + ); let frame_allocator = RecycleAllocator::new(bump_allocator); diff --git a/kernel-rs/src/memory/recycle.rs b/kernel-rs/src/memory/recycle.rs index 6cebe2b4..69373d5c 100644 --- a/kernel-rs/src/memory/recycle.rs +++ b/kernel-rs/src/memory/recycle.rs @@ -26,7 +26,7 @@ impl RecycleAllocator { } fn merge(&mut self, address: usize, count: usize) -> bool { - for i in 0 .. self.free.len() { + for i in 0..self.free.len() { let changed = { let free = &mut self.free[i]; if address + count * 4096 == free.0 { @@ -97,7 +97,7 @@ impl FrameAllocator for RecycleAllocator { self.inner.deallocate_frames(frame, count); } else { let address = frame.start_address().as_u32() as usize; - if ! self.merge(address, count) { + if !self.merge(address, count) { self.free.push((address, count)); } } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index b773b4ff..ba38317b 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -40,7 +40,9 @@ macro_rules! set_color { pub fn print(args: fmt::Arguments) { use core::fmt::Write; - unsafe { self::VGA.write_fmt(args).unwrap(); } + unsafe { + self::VGA.write_fmt(args).unwrap(); + } } extern crate core; @@ -51,7 +53,8 @@ const BUFFER_COLS: usize = 80 * 2; pub struct Writer { pub buffer_pos: usize, pub color_code: ColorCode, - buffer: [u8; BUFFER_ROWS * BUFFER_COLS], command: [u8; 10], + buffer: [u8; BUFFER_ROWS * BUFFER_COLS], + command: [u8; 10], command_len: usize, } @@ -80,13 +83,11 @@ impl Writer { } } - pub fn get_command(&self) -> Result <&str, &'static str> { - + pub fn get_command(&self) -> Result<&str, &'static str> { match core::str::from_utf8(&self.command) { Ok(y) => Ok(&y[..self.command_len]), - Err(_) => Err("Command is not utf8 char") + Err(_) => Err("Command is not utf8 char"), } - } pub fn keypress(&mut self, ascii: u8) { @@ -106,9 +107,11 @@ impl Writer { self.prompt(); } _ if self.command_len >= 10 => (), - byte if self.command_len == 0 && byte == b' ' => (), + byte if self.command_len == 0 && byte == b' ' => (), byte => { - if self.command_len >= 10 { return }; + if self.command_len >= 10 { + return; + }; self.command[self.command_len] = byte; self.write_byte(byte); self.command_len += 1; @@ -130,7 +133,6 @@ impl Writer { let i = self.buffer_pos; match byte { - b'\n' => { let current_line = self.buffer_pos / (BUFFER_COLS); self.buffer_pos = (current_line + 1) * BUFFER_COLS; @@ -178,7 +180,7 @@ impl Writer { } } - for col in 0..BUFFER_COLS/2 { + for col in 0..BUFFER_COLS / 2 { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; } @@ -199,22 +201,28 @@ impl fmt::Write for Writer { pub fn init() { set_color!(White, Cyan); - print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#)); + print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + format_args!("{: ^80}", r#" ,--, "#), + format_args!("{: ^80}", r#" ,--.'| ,----, "#), + format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + format_args!("{: ^80}", r#" ' ; |./__; : "#), + format_args!("{: ^80}", r#" | : ;| : .' "#), + format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + format_args!("{: ^80}", r#" '--' `---' "#) + ); set_color!(); - unsafe { VGA.prompt(); } - unsafe { VGA.flush(); } + unsafe { + VGA.prompt(); + } + unsafe { + VGA.flush(); + } } From 7fb7d9d460bea679ff87403144280d5b81f9f633 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 13:34:02 +0200 Subject: [PATCH 107/151] x86 updated for gdt --- kernel-rs/x86 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 5c33fe13..b61535ec 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 5c33fe133431bb85b86deeff4ec12f17f7ee96cd +Subproject commit b61535ecda89a6588a2c092dfa3bfbcc7f841575 From b51fe947f08232e15178d05a3cccd850860551ae Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 14:55:06 +0200 Subject: [PATCH 108/151] asm --- kernel-rs/src/arch/x86/boot.asm | 6 +++--- kernel-rs/src/arch/x86/gdt.rs | 2 +- kernel-rs/src/arch/x86/paging/mod.rs | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index f2fab7b6..4da50748 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -31,9 +31,9 @@ set_up_page_tables: or eax, 0b11 ; present + writable mov [p2_table + 1023 * 4], eax - ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx + ; identity map first P2 entry to a huge page mov eax, 0b10000011 ; huge + present + writable - mov [p2_table], eax ; map ecx-th entry + mov [p2_table], eax ; map first entry mov eax, p2_table mov cr3, eax @@ -54,7 +54,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 8 + resb 4096 * 16 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index ff682cba..2aae8e3c 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -2,7 +2,7 @@ use x86::structures::gdt; use x86::structures::tss; use x86::instructions::segmentation::set_cs; use x86::instructions::tables::load_tss; -use spin::Once; +// use spin::Once; // static GDT: Once = Once::new(); // static TSS: Once = Once::new(); diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs index 39e87944..3f4809cb 100644 --- a/kernel-rs/src/arch/x86/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -122,6 +122,7 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable { let frame = ::memory::allocate_frames(1).expect("no more frames"); InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; + unsafe { asm!("hlt"); } From 9f1c31f298bdc79c012ccfd6047c0a1644a192e4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 17:11:46 +0200 Subject: [PATCH 109/151] this commit should work but there's something VERY broken with the stack atm, all focus on this until understood better --- kernel-rs/src/arch/x86/boot.asm | 2 +- kernel-rs/src/arch/x86/interrupt/exception.rs | 2 +- kernel-rs/src/arch/x86/mod.rs | 2 -- kernel-rs/src/arch/x86/paging/mod.rs | 4 ---- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 4da50748..2f0402b6 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -54,7 +54,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 16 + resb 4096 * 4 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 88bd80c5..48bc6028 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -64,7 +64,7 @@ exception_err!(general_protection, {}); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode, -) { + ) { println!("Exception: page_fault"); println!("Error code: {:#b}", code); println!("{:#?}", stack_frame); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 9f32c21d..6fb594eb 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -35,8 +35,6 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // set up virtual mapping let mut active_table = paging::init(&boot_info); - asm!("hlt"); - // set up heap ::allocator::init(&mut active_table); diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs index 3f4809cb..698d2cf9 100644 --- a/kernel-rs/src/arch/x86/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -123,10 +123,6 @@ pub fn remap_the_kernel(boot_info: &BootInformation) -> ActivePageTable { InactivePageTable::new(frame, &mut active_table, &mut temporary_page) }; - unsafe { - asm!("hlt"); - } - active_table.with(&mut new_table, &mut temporary_page, |mapper| { // id map vga buffer let vga_buffer_frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); From 93e48044f57ae2f9fb2cd48913a338dddb2ffb68 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 20:26:45 +0200 Subject: [PATCH 110/151] makefile refactor --- kernel-rs/Makefile | 47 +++++++------------ kernel-rs/mk/grub.mk | 9 ++++ kernel-rs/mk/qemu.mk | 4 +- kernel-rs/src/arch/x86/boot.asm | 3 +- kernel-rs/src/arch/x86/interrupt/exception.rs | 4 +- 5 files changed, 33 insertions(+), 34 deletions(-) create mode 100644 kernel-rs/mk/grub.mk diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 7a9ed66b..ebafd3f1 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -2,49 +2,38 @@ SHELL := /bin/bash ARCH := x86 OS := bluesnow -target ?= $(ARCH)-$(OS) +TARGET ?= $(ARCH)-$(OS) -NASM := /usr/bin/nasm -f elf -g -LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections -MKDIR := mkdir -p - -kernel := build/$(OS) -iso := $(kernel).iso -DIRISO := build/isofiles - -rust_os := target/$(target)/debug/lib$(OS).a - -linker_script := src/arch/$(ARCH)/linker.ld -grub.cfg := src/arch/$(ARCH)/grub.cfg +## COMPILE ASM (nasm) asm_source := $(wildcard src/arch/$(ARCH)/*.asm) asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source)) - -all: $(kernel) - +NASM := /usr/bin/nasm -f elf -g build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile - @$(MKDIR) $(shell dirname $@) + @mkdir -p $(shell dirname $@) $(NASM) $< -o $@ +## COMPILE RUST (xargo) +rust_os := target/$(TARGET)/debug/lib$(OS).a +$(rust_os): $(TARGET).json Makefile + @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) + +## LINKAGE +kernel := build/$(OS) +linker_script := src/arch/$(ARCH)/linker.ld +LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) -$(iso): $(kernel) $(grub.cfg) Makefile - @$(MKDIR) $(DIRISO)/boot/grub - @cp $(grub.cfg) $(DIRISO)/boot/grub - @cp $(kernel) $(DIRISO)/boot/$(OS) - @grub-mkrescue -o $@ $(DIRISO) 2>/dev/null - clean: @xargo clean @rm -rf build -$(rust_os): $(target).json Makefile - @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(target) - -kernel: $(rust_os) -iso: $(iso) - .PHONY: clean kernel iso $(rust_os) # Emulation recipes include mk/qemu.mk + +# Bootloader recipes +include mk/grub.mk +iso: $(grub-iso) + diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk new file mode 100644 index 00000000..28d9c17c --- /dev/null +++ b/kernel-rs/mk/grub.mk @@ -0,0 +1,9 @@ +grub-iso := $(kernel).iso +grub-cfg := src/arch/$(ARCH)/grub.cfg +isodir := build/isofiles + +$(grub-iso): $(kernel) $(grub-cfg) Makefile + @mkdir -p $(isodir)/boot/grub + @cp $(grub-cfg) $(isodir)/boot/grub + @cp $(kernel) $(isodir)/boot/$(OS) + @grub-mkrescue -o $@ $(isodir) 2>/dev/null diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 0ac107ab..7fc3b264 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -7,7 +7,7 @@ else endif QEMU := qemu-system-x86_64 -QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom +QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom build/$(kernel).iso MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ @@ -21,5 +21,5 @@ GDB := gdb -q\ qemu: @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } - @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU) $(QEMUFLAGS) $(iso)' + @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU) $(QEMUFLAGS)' diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 2f0402b6..87e1410a 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -6,6 +6,7 @@ bits 32 start: ; our stack, located in bss, linker.ld puts bss at the end of the binary mov esp, stack_top + ; multiboot information pointer push ebx @@ -54,7 +55,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 4 + resb 4096 * 3 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 48bc6028..fa1682dc 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -64,9 +64,9 @@ exception_err!(general_protection, {}); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode, - ) { +) { println!("Exception: page_fault"); - println!("Error code: {:#b}", code); + println!("Error code: {:?}", code); println!("{:#?}", stack_frame); flush!(); } From 1744c523d7eb044a9c7dca223db5e278ee70903b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 20:45:28 +0200 Subject: [PATCH 111/151] makefile refactor --- kernel-rs/src/arch/x86/boot.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 87e1410a..170d2591 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -55,7 +55,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 3 + resb 4096 * 4 stack_top: section .gdt From d382b623a4bd88c5f465f47d38c508b9007ace92 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 9 Apr 2018 20:46:42 +0200 Subject: [PATCH 112/151] nope --- kernel-rs/mk/qemu.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 7fc3b264..366a12f5 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -7,7 +7,7 @@ else endif QEMU := qemu-system-x86_64 -QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom build/$(kernel).iso +QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom build/bluesnow.iso MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ From 1c606561a130fa8fdb24bbc50f7f061bfbbe6b3d Mon Sep 17 00:00:00 2001 From: wescande Date: Tue, 10 Apr 2018 21:43:40 +0200 Subject: [PATCH 113/151] keyboard input is now in irq compliant mode --- kernel-rs/mk/grub.mk | 1 + kernel-rs/src/keyboard.rs | 60 ++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk index 28d9c17c..1444d67a 100644 --- a/kernel-rs/mk/grub.mk +++ b/kernel-rs/mk/grub.mk @@ -7,3 +7,4 @@ $(grub-iso): $(kernel) $(grub-cfg) Makefile @cp $(grub-cfg) $(isodir)/boot/grub @cp $(kernel) $(isodir)/boot/$(OS) @grub-mkrescue -o $@ $(isodir) 2>/dev/null + @printf "\r\033[38;5;117m✓ GRUB ==> $(grub-iso)\033[0m\033[K\n" diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index d7c4a16a..fddb2992 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -76,33 +76,41 @@ fn check_key_state(key: u8) -> (bool, usize) { } } -pub fn kbd_callback() { - static mut SHIFT: bool = false; - static mut CTRL: bool = false; - static mut ALT: bool = false; - let control = cpuio::inb(0x64); - if (control & 1) == 1 { - let scancode = cpuio::inb(0x60); - let (is_release, scancode) = check_key_state(scancode); - unsafe { - //TODO remove unsafe - match self::KEYMAP_US.get(scancode as usize) { - Some(b"\0\0") => match scancode { - 0x2A | 0x36 => SHIFT = !is_release, - 0x38 => ALT = !is_release, - 0x1D => CTRL = !is_release, - 0x0E if !is_release => { - vga::VGA.backspace(); - } - _ => {} - }, - Some(ascii) if !is_release => { - let sym = if SHIFT { ascii[1] } else { ascii[0] }; - vga::VGA.keypress(sym); - } - Some(_) => {} - None => {} +fn get_scancode() -> u8 { + let mut scancode = 0; + loop { + if cpuio::inb(0x60) != scancode { + scancode = cpuio::inb(0x60); + if scancode > 0 { + return scancode; } } } } + +pub fn kbd_callback() { + static mut SHIFT: bool = false; + static mut CTRL: bool = false; + static mut ALT: bool = false; + let scancode = get_scancode(); + let (is_release, scancode) = check_key_state(scancode); + unsafe { + //TODO remove unsafe + match self::KEYMAP_US.get(scancode as usize) { + Some(b"\0\0") => match scancode { + 0x2A | 0x36 => SHIFT = !is_release, + 0x38 => ALT = !is_release, + 0x1D => CTRL = !is_release, + 0x0E if !is_release => { + vga::VGA.backspace(); + } + _ => {} + }, + Some(ascii) if !is_release => { + let sym = if SHIFT { ascii[1] } else { ascii[0] }; + vga::VGA.keypress(sym); + } + _ => {} + } + } +} From ae7c97a77d59cacb18df80461041c5ee4eb5ccf2 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 14:27:41 +0200 Subject: [PATCH 114/151] massive memory problem averted: we were just being stupid like usual --- kernel-rs/src/arch/x86/boot.asm | 7 ++++-- kernel-rs/src/arch/x86/idt.rs | 1 + kernel-rs/src/arch/x86/interrupt/exception.rs | 3 +++ kernel-rs/src/arch/x86/linker.ld | 12 ++++----- kernel-rs/src/arch/x86/mod.rs | 25 ++++++++++++++++--- kernel-rs/src/arch/x86/paging/mapper.rs | 2 +- kernel-rs/src/arch/x86/paging/mod.rs | 6 +++++ kernel-rs/src/console.rs | 2 +- kernel-rs/src/lib.rs | 2 +- kernel-rs/src/memory/bump.rs | 7 ++++++ kernel-rs/src/memory/mod.rs | 14 +++++++++++ kernel-rs/x86 | 2 +- 12 files changed, 67 insertions(+), 16 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 170d2591..72d057d8 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -11,7 +11,6 @@ start: push ebx call check_multiboot - call set_up_page_tables ; load the new gdt @@ -36,6 +35,10 @@ set_up_page_tables: mov eax, 0b10000011 ; huge + present + writable mov [p2_table], eax ; map first entry + mov eax, 0b10000011 ; huge + present + writable + or eax, 0x400000 ; 4MB + mov [p2_table + 4], eax ; map second entry + mov eax, p2_table mov cr3, eax ret @@ -55,7 +58,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 4 + resb 4096 * 3 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs index 2b645697..4a511522 100644 --- a/kernel-rs/src/arch/x86/idt.rs +++ b/kernel-rs/src/arch/x86/idt.rs @@ -53,5 +53,6 @@ pub fn init() { // .expect("could not allocate double fault stack"); // println!("DF stack: {:#?}", double_fault_stack); // flush!(); + IDT.load(); } diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index fa1682dc..06c6cdf4 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -69,6 +69,9 @@ pub extern "x86-interrupt" fn page_fault( println!("Error code: {:?}", code); println!("{:#?}", stack_frame); flush!(); + unsafe { + asm!("hlt"); + } } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index d02b7510..2dc25860 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -43,12 +43,6 @@ SECTIONS { . = ALIGN(4K); } - .bss : - { - *(.bss .bss.*) - . = ALIGN(4K); - } - .gdt : { *(.gdt) @@ -66,4 +60,10 @@ SECTIONS { *(.got.plt) . = ALIGN(4K); } + + .bss : + { + *(.bss .bss.*) + . = ALIGN(4K); + } } diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 6fb594eb..8cee6b38 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -17,6 +17,10 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // parse multiboot2 info let boot_info = multiboot2::load(multiboot_info_addr); + // println!("{:?}", boot_info); + // flush!(); + // asm!("hlt"); + // ACPI must be intialized BEFORE paging is active if let Some(rsdp) = boot_info.rsdp_v2_tag() { acpi::load(rsdp).expect("ACPI failed"); @@ -26,15 +30,28 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { acpi::init().expect("ACPI failed"); } - // fill and load idt (exceptions + irqs) - idt::init(); - // set up physical allocator ::memory::init(&boot_info); - // set up virtual mapping + // let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required"); + // println!("memory areas:"); + // for area in memory_map_tag.memory_areas() { + // println!( + // " start: {:#x}, end: {:#x} length: {:#x}", + // area.start_address(), + // area.end_address(), + // area.size() + // ); + // } + // flush!(); + // asm!("hlt"); + + // set up virtual addressing (paging) let mut active_table = paging::init(&boot_info); + // fill and load idt (exceptions + irqs) + idt::init(); + // set up heap ::allocator::init(&mut active_table); diff --git a/kernel-rs/src/arch/x86/paging/mapper.rs b/kernel-rs/src/arch/x86/paging/mapper.rs index 56ba3517..c3d8115d 100644 --- a/kernel-rs/src/arch/x86/paging/mapper.rs +++ b/kernel-rs/src/arch/x86/paging/mapper.rs @@ -11,7 +11,7 @@ use super::table::RecTable; pub const P2: *mut PageTable = 0xffff_f000 as *mut _; pub struct Mapper { - p2: Unique, + pub p2: Unique, } impl Mapper { diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs index 698d2cf9..58fac763 100644 --- a/kernel-rs/src/arch/x86/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -101,6 +101,12 @@ impl InactivePageTable { temporary_page: &mut TemporaryPage, ) -> InactivePageTable { { + println!("mapping temp page:"); + println!("frame: {:?}", frame); + flush!(); + // unsafe { + // asm!("hlt"); + // } let table = temporary_page.map_table_frame(frame.clone(), active_table); table.zero(); diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 0e1eff02..7b24dc20 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -117,7 +117,7 @@ fn print_line(line: &[u8], address: usize) { } /// Print the kernel stack -fn print_stack() -> Result<(), &'static str> { +pub fn print_stack() -> Result<(), &'static str> { let esp: usize; let ebp: usize; unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 9d542d82..020db3d2 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -81,7 +81,7 @@ pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: loop {} } -pub const HEAP_START: usize = (1 << 22); //first entry of p2 +pub const HEAP_START: usize = (2 << 22); //third entry of p2 pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB #[global_allocator] diff --git a/kernel-rs/src/memory/bump.rs b/kernel-rs/src/memory/bump.rs index 4e62a672..fce35247 100644 --- a/kernel-rs/src/memory/bump.rs +++ b/kernel-rs/src/memory/bump.rs @@ -58,6 +58,12 @@ impl FrameAllocator for BumpFrameAllocator { if count == 0 { return None; }; + // println!("allocate {}", count); + // println!("kstart {:?}", self.kernel_start); + // println!("kend {:?}", self.kernel_end); + // println!("multiboot start {:?}", self.multiboot_start); + // println!("multiboot end {:?}", self.multiboot_end); + // flush!(); if let Some(area) = self.current_area { let start_frame = PhysFrame { number: self.next_free_frame.number, @@ -68,6 +74,7 @@ impl FrameAllocator for BumpFrameAllocator { let current_area_last_frame = PhysFrame::containing_address(PhysAddr::new(area.end_address() as u32)); + if end_frame > current_area_last_frame { // all frames are taken in this area self.choose_next_area(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 7d9de270..5bcadcdd 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -46,6 +46,20 @@ pub fn init(boot_info: &multiboot2::BootInformation) { memory_map_tag.memory_areas(), ); + println!("memory areas from the f allocator:"); + for area in memory_map_tag.memory_areas() { + println!( + " start: {:#x}, end: {:#x} length: {:#x}", + area.start_address(), + area.end_address(), + area.size() + ); + } + flush!(); + // unsafe { + // asm!("hlt"); + // } + let frame_allocator = RecycleAllocator::new(bump_allocator); // let stack_allocator = { diff --git a/kernel-rs/x86 b/kernel-rs/x86 index b61535ec..ae98bfcd 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit b61535ecda89a6588a2c092dfa3bfbcc7f841575 +Subproject commit ae98bfcd4f30217a4bfe944549d222bb07f81deb From ee5f2780e5430841bc12940dc9bbcac2e8c9d0c1 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 14:31:58 +0200 Subject: [PATCH 115/151] multiboot crate update --- kernel-rs/multiboot2-elf64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/multiboot2-elf64 b/kernel-rs/multiboot2-elf64 index 73530c41..32552947 160000 --- a/kernel-rs/multiboot2-elf64 +++ b/kernel-rs/multiboot2-elf64 @@ -1 +1 @@ -Subproject commit 73530c41902a6991ca54ad6f12d05519d4870403 +Subproject commit 32552947aa30414a96d9a8e291aceaf18320b3ef From 5f40aeeae56458cfbcb1c4c86fb11722c7f54de7 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 14:49:52 +0200 Subject: [PATCH 116/151] grub.mk mdr --- kernel-rs/mk/grub.mk | 3 +-- kernel-rs/src/arch/x86/boot.asm | 2 +- kernel-rs/src/arch/x86/mod.rs | 15 +-------------- kernel-rs/src/lib.rs | 5 ++--- 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk index 1444d67a..cb44a41e 100644 --- a/kernel-rs/mk/grub.mk +++ b/kernel-rs/mk/grub.mk @@ -6,5 +6,4 @@ $(grub-iso): $(kernel) $(grub-cfg) Makefile @mkdir -p $(isodir)/boot/grub @cp $(grub-cfg) $(isodir)/boot/grub @cp $(kernel) $(isodir)/boot/$(OS) - @grub-mkrescue -o $@ $(isodir) 2>/dev/null - @printf "\r\033[38;5;117m✓ GRUB ==> $(grub-iso)\033[0m\033[K\n" + grub-mkrescue -o $@ $(isodir) 2>/dev/null diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 72d057d8..ef54d30f 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -58,7 +58,7 @@ align 4096 p2_table: resb 4096 stack_bottom: - resb 4096 * 3 + resb 4096 * 4 stack_top: section .gdt diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 8cee6b38..6b68f857 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -33,23 +33,10 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // set up physical allocator ::memory::init(&boot_info); - // let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required"); - // println!("memory areas:"); - // for area in memory_map_tag.memory_areas() { - // println!( - // " start: {:#x}, end: {:#x} length: {:#x}", - // area.start_address(), - // area.end_address(), - // area.size() - // ); - // } - // flush!(); - // asm!("hlt"); - // set up virtual addressing (paging) let mut active_table = paging::init(&boot_info); - // fill and load idt (exceptions + irqs) + // load idt (exceptions + irqs) idt::init(); // set up heap diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 020db3d2..c79a30fb 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -60,10 +60,9 @@ pub fn kmain() -> ! { // *(0xdead as *mut u32) = 42; // }; - // vga is specific to chipset not cpu + // vga is *not* cpu specific, chipset specific? vga::init(); - // loop { keyboard::kbd_callback(); } loop {} } @@ -81,7 +80,7 @@ pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: loop {} } -pub const HEAP_START: usize = (2 << 22); //third entry of p2 +pub const HEAP_START: usize = (1 << 22 + 2); //third entry of p2 pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB #[global_allocator] From 0849f24628dfa301bd338010af5b5e161d336396 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 15:12:35 +0200 Subject: [PATCH 117/151] close #2 --- kernel-rs/src/lib.rs | 2 +- kernel-rs/src/vga/mod.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index c79a30fb..b1471098 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -51,7 +51,7 @@ pub fn kmain() -> ! { // heap avalaible for tracking free'd frames memory::init_noncore(); - // x86::instructions::interrupts::int3(); + x86::instructions::interrupts::int3(); // fn stack_overflow() { stack_overflow(); } // stack_overflow(); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index ba38317b..9b5c780e 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -180,8 +180,10 @@ impl Writer { } } - for col in 0..BUFFER_COLS / 2 { - self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col * 2)] = b' '; + for col in (0..BUFFER_COLS / 2).map(|x| x * 2) { + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' '; + self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = + ColorCode::new(Color::White, Color::Black).0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; @@ -200,7 +202,7 @@ impl fmt::Write for Writer { } pub fn init() { - set_color!(White, Cyan); + set_color!(Yellow, Red); print!( "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", format_args!("{: ^80}", r#" ,--, "#), @@ -218,7 +220,6 @@ pub fn init() { format_args!("{: ^80}", r#" ' ,/ ; | .' "#), format_args!("{: ^80}", r#" '--' `---' "#) ); - set_color!(); unsafe { VGA.prompt(); } From b0548384e7ffbf78d7150da2799f894a510911f1 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 15:32:11 +0200 Subject: [PATCH 118/151] context gone --- kernel-rs/src/arch/x86/gdt.rs | 32 +++++++++---------- kernel-rs/src/arch/x86/interrupt/exception.rs | 3 -- kernel-rs/src/arch/x86/mod.rs | 8 ++--- kernel-rs/src/context.rs | 26 --------------- kernel-rs/src/lib.rs | 6 ++-- 5 files changed, 23 insertions(+), 52 deletions(-) delete mode 100644 kernel-rs/src/context.rs diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 2aae8e3c..f9c46046 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -2,27 +2,27 @@ use x86::structures::gdt; use x86::structures::tss; use x86::instructions::segmentation::set_cs; use x86::instructions::tables::load_tss; -// use spin::Once; +use spin::Once; -// static GDT: Once = Once::new(); -// static TSS: Once = Once::new(); +static GDT: Once = Once::new(); +static TSS: Once = Once::new(); pub fn init() { - // let tss = tss::TaskStateSegment::new(); - // let tss = TSS.call_once(|| { - // let mut tss = tss::TaskStateSegment::new(); - // tss - // }); + let tss = tss::TaskStateSegment::new(); + let tss = TSS.call_once(|| { + let mut tss = tss::TaskStateSegment::new(); + tss + }); - // let mut code_selector = gdt::SegmentSelector(0); - // let mut tss_selector = gdt::SegmentSelector(0); + let mut code_selector = gdt::SegmentSelector(0); + let mut tss_selector = gdt::SegmentSelector(0); - // let gdt = GDT.call_once(|| { - // let mut gdt = gdt::Gdt::new(); - // code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); - // tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); - // gdt - // }); + let gdt = GDT.call_once(|| { + let mut gdt = gdt::Gdt::new(); + code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); + tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); + gdt + }); // gdt.load(); // unsafe { diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 06c6cdf4..fa1682dc 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -69,9 +69,6 @@ pub extern "x86-interrupt" fn page_fault( println!("Error code: {:?}", code); println!("{:#?}", stack_frame); flush!(); - unsafe { - asm!("hlt"); - } } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 6b68f857..2110ffae 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -6,7 +6,7 @@ pub mod interrupt; pub mod device; pub mod pti; -// pub mod gdt; +pub mod gdt; pub mod idt; use multiboot2; @@ -39,15 +39,15 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // load idt (exceptions + irqs) idt::init(); + // fill and load gdt + gdt::init(); + // set up heap ::allocator::init(&mut active_table); // set up pic & apic device::init(&mut active_table); - // fill and load gdt - // gdt::init(); - // primary CPU entry point ::kmain(); } diff --git a/kernel-rs/src/context.rs b/kernel-rs/src/context.rs deleted file mode 100644 index 81b76627..00000000 --- a/kernel-rs/src/context.rs +++ /dev/null @@ -1,26 +0,0 @@ -use multiboot2; -use memory; -use vga; - -pub static mut CONTEXT: Option = None; - -pub struct Context { - pub current_term: u8, - pub vga1: vga::Writer, - pub vga2: vga::Writer, -} - -impl Context -{ - pub fn new(multiboot_start: usize) -> Context { - - - Context { - current_term: 0, - boot_info, - vga1, - vga2, - } - } -} - diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b1471098..04c00217 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -48,10 +48,10 @@ pub mod arch; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded pub fn kmain() -> ! { - // heap avalaible for tracking free'd frames + // heap avalaible for tracking freed frames memory::init_noncore(); - x86::instructions::interrupts::int3(); + // x86::instructions::interrupts::int3(); // fn stack_overflow() { stack_overflow(); } // stack_overflow(); @@ -60,7 +60,7 @@ pub fn kmain() -> ! { // *(0xdead as *mut u32) = 42; // }; - // vga is *not* cpu specific, chipset specific? + // vga is *not* cpu specific vga::init(); loop {} From 8a3e3a2324fd59039c7a4ad4a21062048f10853b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 15:49:37 +0200 Subject: [PATCH 119/151] cursor.rs, no more cpuio in vga --- kernel-rs/src/vga/cursor.rs | 30 ++++++++++++++++++++++++++++++ kernel-rs/src/vga/mod.rs | 13 +++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 kernel-rs/src/vga/cursor.rs diff --git a/kernel-rs/src/vga/cursor.rs b/kernel-rs/src/vga/cursor.rs new file mode 100644 index 00000000..850c45cc --- /dev/null +++ b/kernel-rs/src/vga/cursor.rs @@ -0,0 +1,30 @@ +// https://wiki.osdev.org/Text_Mode_Cursor +// Protected mode cursor abstraction + +use io::{Io, Pio}; + +pub static mut CURSOR: Cursor = Cursor::new(0x3D4); + +pub struct Cursor { + cmd: Pio, + data: Pio, +} + +impl Cursor { + pub const fn new(port: u16) -> Cursor { + Cursor { + cmd: Pio::new(port), + data: Pio::new(port + 1), + } + } + + pub fn flush(&mut self, position: usize) { + // 14 awaits the rightmost 8bits + self.cmd.write(14); + self.data.write((position >> 8) as u8 & 0xff); + + // 15 awaits the leftmost 8bits + self.cmd.write(15); + self.data.write((position >> 0) as u8 & 0xff); + } +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 9b5c780e..1a2dedc8 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,8 +1,9 @@ pub mod color; +pub mod cursor; pub use self::color::{Color, ColorCode}; +use self::cursor::CURSOR; -use cpuio; use console; pub static mut VGA: Writer = self::Writer::new(); @@ -156,13 +157,9 @@ impl Writer { } fn flush_cursor(&self) { - let cursor_position = self.buffer_pos / 2; - // 14 awaits the rightmost 8bits - cpuio::outb(0x3D4, 14); - cpuio::outb(0x3D5, (cursor_position >> 8) as u8); - // 15 awaits the leftmost 8bits - cpuio::outb(0x3D4, 15); - cpuio::outb(0x3D5, (cursor_position >> 0) as u8 & 0x00ff); + unsafe { + CURSOR.flush(self.buffer_pos / 2); + } } pub fn flush(&mut self) { From f138d77e4da0e392c13d937ce865b641f13960dc Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 17:59:14 +0200 Subject: [PATCH 120/151] gdt support in rust --- kernel-rs/src/arch/x86/gdt.rs | 27 +++++++++++++++++++-------- kernel-rs/src/arch/x86/paging/mod.rs | 6 ------ kernel-rs/src/memory/mod.rs | 14 -------------- kernel-rs/x86 | 2 +- 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index f9c46046..8d720bf9 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -10,7 +10,7 @@ static TSS: Once = Once::new(); pub fn init() { let tss = tss::TaskStateSegment::new(); let tss = TSS.call_once(|| { - let mut tss = tss::TaskStateSegment::new(); + let tss = tss::TaskStateSegment::new(); tss }); @@ -21,14 +21,25 @@ pub fn init() { let mut gdt = gdt::Gdt::new(); code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); + println!("cs: {:?}", code_selector); gdt }); - // gdt.load(); - // unsafe { - // // reload code segment register - // set_cs(code_selector); - // // load TSS - // load_tss(tss_selector); - // } + println!("0 upper: {:#x}", gdt.table[0] as u32); + println!("0 lower: {:#x}", gdt.table[0] >> 32 as u32); + println!("1 upper: {:#x}", gdt.table[1] as u32); + println!("1 lower: {:#x}", gdt.table[1] >> 32 as u32); + println!("2 upper: {:#x}", gdt.table[2] as u32); + println!("2 lower: {:#x}", gdt.table[2] >> 32 as u32); + println!("3 upper: {:#x}", gdt.table[3] as u32); + println!("3 lower: {:#x}", gdt.table[3] >> 32 as u32); + flush!(); + + gdt.load(); + unsafe { + // reload code segment register + set_cs(code_selector); + // load TSS + load_tss(tss_selector); + } } diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs index 58fac763..698d2cf9 100644 --- a/kernel-rs/src/arch/x86/paging/mod.rs +++ b/kernel-rs/src/arch/x86/paging/mod.rs @@ -101,12 +101,6 @@ impl InactivePageTable { temporary_page: &mut TemporaryPage, ) -> InactivePageTable { { - println!("mapping temp page:"); - println!("frame: {:?}", frame); - flush!(); - // unsafe { - // asm!("hlt"); - // } let table = temporary_page.map_table_frame(frame.clone(), active_table); table.zero(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 5bcadcdd..7d9de270 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -46,20 +46,6 @@ pub fn init(boot_info: &multiboot2::BootInformation) { memory_map_tag.memory_areas(), ); - println!("memory areas from the f allocator:"); - for area in memory_map_tag.memory_areas() { - println!( - " start: {:#x}, end: {:#x} length: {:#x}", - area.start_address(), - area.end_address(), - area.size() - ); - } - flush!(); - // unsafe { - // asm!("hlt"); - // } - let frame_allocator = RecycleAllocator::new(bump_allocator); // let stack_allocator = { diff --git a/kernel-rs/x86 b/kernel-rs/x86 index ae98bfcd..f5e4cb87 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit ae98bfcd4f30217a4bfe944549d222bb07f81deb +Subproject commit f5e4cb879953ebbeba28a1eaa28bf531424e6824 From fd0915048d92314da2dfff31cc2c3d667302dc6b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 18:01:13 +0200 Subject: [PATCH 121/151] removed unused segments selectors in assembly --- kernel-rs/src/arch/x86/boot.asm | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index ef54d30f..8355baf6 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -82,38 +82,6 @@ GDTR: DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] DB 0x0 ; Base ( bits 24 -31 ) -.gdt_ss: equ $ - .gdt_top; the stack segment Aka KERNEL STACK - DW 0x0 ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0x96 ; [ Access Flags: 0x96=10010110b = (present)|(Privilege Ring 0=00b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) - -.gdt_es: equ $ - .gdt_top; the extra segment Aka USER CODE - DW 0xffff ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0xFE ; [ Access Flags: 0xFE=11111110b = (present)|(Privilege Ring 3=11b)|(1)|(code => 1)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) - -.gdt_fs: equ $ - .gdt_top; the other segment Aka USER DATA - DW 0xffff ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0xF2 ; [ Access Flags: 0xF2=11110010b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand down => 0)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) - -.gdt_gs: equ $ - .gdt_top; the other segment Aka USER STACK - DW 0x0 ; Limit ( bits 0 -15 ) - DW 0x0 ; Base ( bits 0 -15 ) - DB 0x0 ; Base ( bits 16 -23 ) - DB 0xF6 ; [ Access Flags: 0xF2=11110110b = (present)|(Privilege Ring 3=11b)|(1)|(data => 0)|(expand up => 1)|(readable)|(0) ] - DB 0xCF ; [ Flags: C=1100b = (granularity)|(32bit)|(!64bit)|(0) ] / [ Limits: (bits 16-19): F=1111b ] - DB 0x0 ; Base ( bits 24 -31 ) - .gdt_bottom: .ptr: DW .gdt_bottom - .gdt_top - 1 ; length of the structure minus 1 From ffcb85dd5b670ce6a66f510e29d3315991ab96b4 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 12 Apr 2018 18:06:50 +0200 Subject: [PATCH 122/151] prettier asm --- kernel-rs/src/arch/x86/boot.asm | 15 ++++++++++----- kernel-rs/src/arch/x86/gdt.rs | 17 ++++++++--------- kernel-rs/src/arch/x86/start.asm | 2 -- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 8355baf6..9737350d 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -25,6 +25,8 @@ check_multiboot: mov al, "0" jmp error +; minimal page tables (first 8MB identity mapped) +; core page tables will be loaded in rust set_up_page_tables: ; map P2 table recursively mov eax, p2_table @@ -32,12 +34,13 @@ set_up_page_tables: mov [p2_table + 1023 * 4], eax ; identity map first P2 entry to a huge page - mov eax, 0b10000011 ; huge + present + writable - mov [p2_table], eax ; map first entry + mov eax, 0x0 ; 0MB -> 4MB (first page) + or eax, 0b10000011 ; huge + present + writable + mov [p2_table], eax - mov eax, 0b10000011 ; huge + present + writable - or eax, 0x400000 ; 4MB - mov [p2_table + 4], eax ; map second entry + mov eax, 0x400000 ; 4MB -> 8Mb (second page) + or eax, 0b10000011 ; huge + present + writable + mov [p2_table + 4], eax mov eax, p2_table mov cr3, eax @@ -61,6 +64,8 @@ stack_bottom: resb 4096 * 4 stack_top: +; minimal boot gdt (cs & ds) +; core gdt will be loaded in rust section .gdt GDTR: ; http://tuttlem.github.io/2014/07/11/a-gdt-primer.html diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 8d720bf9..974c8a9b 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -21,18 +21,17 @@ pub fn init() { let mut gdt = gdt::Gdt::new(); code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); - println!("cs: {:?}", code_selector); gdt }); - println!("0 upper: {:#x}", gdt.table[0] as u32); - println!("0 lower: {:#x}", gdt.table[0] >> 32 as u32); - println!("1 upper: {:#x}", gdt.table[1] as u32); - println!("1 lower: {:#x}", gdt.table[1] >> 32 as u32); - println!("2 upper: {:#x}", gdt.table[2] as u32); - println!("2 lower: {:#x}", gdt.table[2] >> 32 as u32); - println!("3 upper: {:#x}", gdt.table[3] as u32); - println!("3 lower: {:#x}", gdt.table[3] >> 32 as u32); + println!("gdt 0 upper: {:#x}", gdt.table[0] as u32); + println!("gdt 0 lower: {:#x}", gdt.table[0] >> 32 as u32); + println!("gdt 1 upper: {:#x}", gdt.table[1] as u32); + println!("gdt 1 lower: {:#x}", gdt.table[1] >> 32 as u32); + println!("gdt 2 upper: {:#x}", gdt.table[2] as u32); + println!("gdt 2 lower: {:#x}", gdt.table[2] >> 32 as u32); + println!("gdt 3 upper: {:#x}", gdt.table[3] as u32); + println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); flush!(); gdt.load(); diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index 45ec32c2..ea3fe179 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -12,8 +12,6 @@ x86_start: mov gs, ax call x86_rust_start - - cli ; clear interrupt HALT: hlt jmp HALT From cdf09f9869428ee81dd0db7b1bdc0995ffba5234 Mon Sep 17 00:00:00 2001 From: wescande Date: Thu, 12 Apr 2018 19:37:43 +0200 Subject: [PATCH 123/151] keyboard use Pio --- kernel-rs/src/console.rs | 14 ++++------ kernel-rs/src/cpuio.rs | 7 ++++- kernel-rs/src/keyboard.rs | 59 ++++++++++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 7b24dc20..3d5ca557 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -2,6 +2,7 @@ extern crate core; // extern crate multiboot2; use acpi; +use keyboard::PS2; use cpuio; use core::char; use vga::*; @@ -59,15 +60,10 @@ fn help() -> Result<(), &'static str> { /// If reboot failed, will loop on a halt cmd /// fn reboot() -> ! { - unsafe { asm!("cli") }; //TODO volatile ????? - // I will now clear the keyboard buffer - let mut buffer: u8 = 0x02; - while buffer & 0x02 != 0 { - cpuio::inb(0x60); - buffer = cpuio::inb(0x64); - } - cpuio::outb(0x64, 0xFE); //Send reset value to CPU //TODO doesn't work in QEMU ==> it seems that qemu cannot reboot - println!("Unable to perform reboot. Kernel will be halted"); + // acpi::reboot()?; + // println!("Unable to perform ACPI reboot."); + unsafe {PS2.ps2_8042_reset()};// TODO unsafe + println!("Unable to perform 8042 reboot. Kernel will be halted"); cpuio::halt(); } diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs index 1343789d..50793228 100644 --- a/kernel-rs/src/cpuio.rs +++ b/kernel-rs/src/cpuio.rs @@ -38,9 +38,14 @@ pub fn outl(port: u16, value: u32) { unsafe { asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile") }; } +/// Disable interruption +pub fn cli() { + unsafe { asm!("cli" : : : : "volatile") }; +} + /// Halt system pub fn halt() -> ! { - unsafe { asm!("cli" : : : : "volatile") }; + cli(); loop { unsafe { asm!("hlt" : : : : "volatile") }; } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index fddb2992..64daa163 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -2,6 +2,8 @@ extern crate core; use cpuio; use vga; +use io::Pio; +use io::Io; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ @@ -66,6 +68,49 @@ const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ *b"\0\0",//capslock ]; + +pub static mut PS2: Ps2 = Ps2::new(); + +pub struct Ps2 { + status: Pio, + data: Pio, +} + +impl Ps2 { + pub const fn new() -> Ps2 { + Ps2 { + status: Pio::new(0x64), + data: Pio::new(0x60), + } + } + + pub fn clear_buffer(&self) { + let mut buffer: u8 = 0x02; + while buffer & 0x02 != 0 { + self.data.read(); + buffer = self.status.read(); + } + } + + pub fn ps2_8042_reset(&mut self) { + cpuio::cli(); + self.clear_buffer(); + self.status.write(0xFE); + } + + pub fn get_scancode(&self) -> u8 { + let mut scancode = 0; + loop { + if self.data.read() != scancode { + scancode = self.data.read(); + if scancode > 0 { + return scancode; + } + } + } + } +} + const TOUCH_RELEASE: u8 = 1 << 7; fn check_key_state(key: u8) -> (bool, usize) { @@ -76,23 +121,11 @@ fn check_key_state(key: u8) -> (bool, usize) { } } -fn get_scancode() -> u8 { - let mut scancode = 0; - loop { - if cpuio::inb(0x60) != scancode { - scancode = cpuio::inb(0x60); - if scancode > 0 { - return scancode; - } - } - } -} - pub fn kbd_callback() { static mut SHIFT: bool = false; static mut CTRL: bool = false; static mut ALT: bool = false; - let scancode = get_scancode(); + let scancode = unsafe { PS2.get_scancode() }; let (is_release, scancode) = check_key_state(scancode); unsafe { //TODO remove unsafe From d15fa664f2dd4af2c0cbe262da920e5135f8e0ea Mon Sep 17 00:00:00 2001 From: wescande Date: Sun, 15 Apr 2018 11:31:40 +0200 Subject: [PATCH 124/151] No more cpuio, juste pio in io module. (change in acpi for that => need refactor) --- kernel-rs/src/acpi/dsdt.rs | 9 ++++-- kernel-rs/src/acpi/fadt.rs | 30 ++++++++++++++----- kernel-rs/src/acpi/mod.rs | 12 +++++++- kernel-rs/src/console.rs | 24 ++++++++++----- kernel-rs/src/cpuio.rs | 61 -------------------------------------- kernel-rs/src/io/mod.rs | 11 +++++++ kernel-rs/src/keyboard.rs | 6 ++-- kernel-rs/src/lib.rs | 3 +- 8 files changed, 70 insertions(+), 86 deletions(-) delete mode 100644 kernel-rs/src/cpuio.rs diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index 32309cf1..e20cd3d8 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -1,6 +1,6 @@ use super::{check_signature, ACPISDTHeader}; use core::mem; -use cpuio; +use io::{Pio,Io}; static mut DSDT: DSDT = DSDT { valid: false, @@ -86,10 +86,13 @@ pub fn init(addr: u32) -> Result<(), &'static str> { pub fn shutdown(pm1_cnt: [u16; 2]) -> Result<(), &'static str> { is_init()?; let slp_typ = unsafe { DSDT.slp_typ_a } | (1 << 13); - cpuio::outw(pm1_cnt[0], slp_typ); + let mut pin: Pio = Pio::new(pm1_cnt[0]); + pin.write(slp_typ); if pm1_cnt[1] != 0 { let slp_typ = unsafe { DSDT.slp_typ_b } | (1 << 13); - cpuio::outw(pm1_cnt[1], slp_typ); + let mut pin: Pio = Pio::new(pm1_cnt[1]); + pin.write(slp_typ); + // cpuio::outw(pm1_cnt[1], slp_typ); } Ok(()) } diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index edbdcbd2..94105bcb 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -1,5 +1,5 @@ use super::{ACPISDTHeader, ACPISDTIter}; -use cpuio; +use io::{Io,Pio}; #[repr(C)] #[derive(Debug, Clone)] @@ -95,7 +95,10 @@ pub fn init(sdt_iter: ACPISDTIter) -> Result<(), &'static str> { // TODO do i have to check if enabled before init ??? let smi_cmd = fadt_tmp.smi_commandport as u16; // TODO WHY DO I NEED THIS FUCKING CAST let acpi_enable = fadt_tmp.acpi_enable; - cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command + //TODO not sexy it ! + let mut pin: Pio = Pio::new(smi_cmd); + pin.write(acpi_enable); + // cpuio::outb(smi_cmd, acpi_enable); // send acpi enable command } return Ok(()); } @@ -125,10 +128,14 @@ fn get_cnt(fadt: FADT) -> [u16; 2] { pub fn is_enable() -> Result { let fadt = is_init()?; let pm1_cnt = get_cnt(fadt); + let pin: Pio = Pio::new(pm1_cnt[0]); if pm1_cnt[1] == 0 { - Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) + Ok(pin.read() & 0x1 == 0x1) + // Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) } else { - Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1 || cpuio::inw(pm1_cnt[1]) & 0x1 == 0x1) + let pin2: Pio = Pio::new(pm1_cnt[1]); + Ok(pin.read() & 0x1 == 0x1 || pin2.read() & 0x1 == 0x1) + // Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1 || cpuio::inw(pm1_cnt[1]) & 0x1 == 0x1) } } @@ -138,9 +145,18 @@ pub fn get_controlblock() -> Result<[u16; 2], &'static str> { if !is_enable()? { Err("ACPI is not enabled") } else { - // println!("HALT"); - // flush!(); - // cpuio::halt(); Ok(get_cnt(is_init()?)) // TODO redondant call to is_init } } +pub fn reboot() -> Result<(), &'static str> { + if !is_enable()? { + Err("ACPI is not enabled") + } else { + let fadt = is_init()?; + println!("fadt on {} ({}), value is {}", fadt.resetreg.address as u32, fadt.resetreg.address as u16, fadt.resetvalue); + let mut pin: Pio = Pio::new(fadt.resetreg.address as u16); + pin.write(fadt.resetvalue); + // cpuio::outb(fadt.resetreg.address as u16, fadt.resetvalue); //TODO do it work + Ok(()) + } +} diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 3b0544a8..b1ab85ca 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -6,7 +6,6 @@ mod dsdt; use core; use core::mem; -// use cpuio; #[repr(C)] #[derive(Debug, Clone, Copy)] @@ -158,6 +157,17 @@ pub fn shutdown() -> Result<(), &'static str> { dsdt::shutdown(fadt::get_controlblock()?) } +/// Proceed to ACPI reboot +/// This function need ACPI in v2 +pub fn reboot() -> Result<(), &'static str> { + is_init()?; + if unsafe {ACPI.v2} { + fadt::reboot() + } else { + Err("ACPI reboot only available in ACPI v2+") + } +} + /// Display state of ACPI pub fn info() -> Result<(), &'static str> { is_init()?; diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 3d5ca557..f44b444e 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -3,7 +3,7 @@ extern crate core; use acpi; use keyboard::PS2; -use cpuio; +use io; use core::char; use vga::*; @@ -60,11 +60,15 @@ fn help() -> Result<(), &'static str> { /// If reboot failed, will loop on a halt cmd /// fn reboot() -> ! { - // acpi::reboot()?; - // println!("Unable to perform ACPI reboot."); + match acpi::reboot() { + Err(msg) => println!("{}", msg), + _ => println!("Unable to perform ACPI reboot."), + } + flush!(); unsafe {PS2.ps2_8042_reset()};// TODO unsafe println!("Unable to perform 8042 reboot. Kernel will be halted"); - cpuio::halt(); + flush!(); + io::halt(); } /// Shutdown the kernel @@ -72,10 +76,13 @@ fn reboot() -> ! { /// If shutdown is performed but failed, will loop on a halt cmd /// If shutdown cannot be called, return a Err(&str) /// -fn shutdown() -> Result<(), &'static str> { - acpi::shutdown()?; - println!("Unable to perform ACPI shutdown. Kernel will be halted"); - cpuio::halt(); +fn shutdown() -> ! { + match acpi::shutdown() { + Err(msg) => println!("{}", msg), + _ => println!("Unable to perform ACPI shutdown. Kernel will be halted"), + } + flush!(); + io::halt(); } fn hexdump(start: usize, end: usize) { @@ -121,6 +128,7 @@ pub fn print_stack() -> Result<(), &'static str> { println!("ebp = {:#x}", ebp); println!("size = {:#X} bytes", ebp - esp); hexdump(esp, ebp); + flush!(); Ok(()) } diff --git a/kernel-rs/src/cpuio.rs b/kernel-rs/src/cpuio.rs deleted file mode 100644 index 50793228..00000000 --- a/kernel-rs/src/cpuio.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![allow(dead_code)] - -/// Read a `u8`-sized value from `port`. -pub fn inb(port: u16) -> u8 { - // The registers for the `in` and `out` instructions are always the - // same: `a` for value, and `d` for the port address. - let result: u8; - unsafe { asm!("inb %dx, %al" : "={al}"(result) : "{dx}"(port) :: "volatile") }; - result -} - -/// Write a `u8`-sized `value` to `port`. -pub fn outb(port: u16, value: u8) { - unsafe { asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(value) :: "volatile") }; -} - -/// Read a `u16`-sized value from `port`. -pub fn inw(port: u16) -> u16 { - let result: u16; - unsafe { asm!("inw %dx, %ax" : "={ax}"(result) : "{dx}"(port) :: "volatile") }; - result -} - -/// Write a `u8`-sized `value` to `port`. -pub fn outw(port: u16, value: u16) { - unsafe { asm!("outw %ax, %dx" :: "{dx}"(port), "{ax}"(value) :: "volatile") }; -} - -/// Read a `u32`-sized value from `port`. -pub fn inl(port: u16) -> u32 { - let result: u32; - unsafe { asm!("inl %dx, %eax" : "={eax}"(result) : "{dx}"(port) :: "volatile") }; - result -} - -/// Write a `u32`-sized `value` to `port`. -pub fn outl(port: u16, value: u32) { - unsafe { asm!("outl %eax, %dx" :: "{dx}"(port), "{eax}"(value) :: "volatile") }; -} - -/// Disable interruption -pub fn cli() { - unsafe { asm!("cli" : : : : "volatile") }; -} - -/// Halt system -pub fn halt() -> ! { - cli(); - loop { - unsafe { asm!("hlt" : : : : "volatile") }; - } -} - -/// wait for an io operation to complete -pub fn io_wait() { - unsafe { - asm!("jmp 1f\n\t - 1:jmp 2f\n\t - 2:" : : : : "volatile") - } -} diff --git a/kernel-rs/src/io/mod.rs b/kernel-rs/src/io/mod.rs index 0382a50a..8c4c4543 100644 --- a/kernel-rs/src/io/mod.rs +++ b/kernel-rs/src/io/mod.rs @@ -28,3 +28,14 @@ pub trait Io { self.write(tmp); } } + +pub fn cli() { + unsafe { asm!("cli" : : : : "volatile") }; +} + +pub fn halt() -> ! { + cli(); + loop { + unsafe { asm!("hlt" : : : : "volatile") }; + } +} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 64daa163..8151114b 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,9 +1,7 @@ extern crate core; -use cpuio; use vga; -use io::Pio; -use io::Io; +use io::{self,Pio,Io}; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ @@ -93,7 +91,7 @@ impl Ps2 { } pub fn ps2_8042_reset(&mut self) { - cpuio::cli(); + io::cli(); self.clear_buffer(); self.status.write(0xFE); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 04c00217..20f23d2a 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -33,8 +33,7 @@ pub mod vga; pub mod keyboard; /// simplisitc kernel commands pub mod console; -/// rust wrappers around cpu I/O instructions., cpuio.rs needs to go in favour of io module -pub mod cpuio; +/// rust wrappers around cpu I/O instructions. pub mod io; /// ACPI self contained module pub mod acpi; From d64c01d2b199826cf4b576293de83a874393f117 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 15 Apr 2018 11:48:51 +0200 Subject: [PATCH 125/151] nothing important --- kernel-rs/Cargo.toml | 8 +++--- kernel-rs/src/arch/x86/gdt.rs | 2 +- kernel-rs/src/arch/x86/interrupt/exception.rs | 2 +- kernel-rs/src/lib.rs | 6 ++++- kernel-rs/src/memory/mod.rs | 2 ++ kernel-rs/src/memory/stack_allocator.rs | 27 ++++++++++--------- 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index efc5451c..b44f28a4 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -11,15 +11,17 @@ rlibc = "1.0" bitflags = "1.0.1" spin = "0.4" slab_allocator = "0.3.1" -multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag -x86 = { path = "x86" } # forked for IA32 -# raw-cpuid = { path = "rust-cpuid" } +multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag [dependencies.raw-cpuid] # need to use github/master because of features not yet on crates.io git = "https://github.com/gz/rust-cpuid" features = ["nightly"] +[dependencies.x86] +# forked for IA32 compat +path = "x86" + [dependencies.lazy_static] version = "1.0.0" features = ["spin_no_std"] diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 974c8a9b..cea7e214 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -8,7 +8,6 @@ static GDT: Once = Once::new(); static TSS: Once = Once::new(); pub fn init() { - let tss = tss::TaskStateSegment::new(); let tss = TSS.call_once(|| { let tss = tss::TaskStateSegment::new(); tss @@ -39,6 +38,7 @@ pub fn init() { // reload code segment register set_cs(code_selector); // load TSS + println!("loading tss {:?}", tss_selector); load_tss(tss_selector); } } diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index fa1682dc..b8994281 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -54,7 +54,7 @@ exception!(overflow, {}); exception!(bound_range, {}); exception!(invalid_opcode, {}); exception!(device_not_available, {}); -exception_err!(double_fault, {}); +exception_err!(double_fault, { panic!("double fault non recoverable") }); exception!(coprocessor_segment_overrun, {}); exception_err!(invalid_tss, {}); exception_err!(segment_not_present, {}); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 04c00217..a7467976 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -53,13 +53,17 @@ pub fn kmain() -> ! { // x86::instructions::interrupts::int3(); - // fn stack_overflow() { stack_overflow(); } + // fn stack_overflow() { + // stack_overflow(); + // } // stack_overflow(); // unsafe { // *(0xdead as *mut u32) = 42; // }; + println!("tss: {:?}"); + // vga is *not* cpu specific vga::init(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 7d9de270..0ee34685 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,5 +1,6 @@ mod bump; mod recycle; +// mod stack_allocator; use multiboot2; use x86::structures::paging::*; @@ -7,6 +8,7 @@ use spin::Mutex; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; +// use self::stack_allocator::StackAllocator; pub trait FrameAllocator { fn allocate_frames(&mut self, size: usize) -> Option; diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs index 3bce908e..fb756ce4 100644 --- a/kernel-rs/src/memory/stack_allocator.rs +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -1,5 +1,5 @@ use x86::structures::paging::*; -use memory::paging::{ActivePageTable}; +use memory::paging::ActivePageTable; use memory::*; use core::ops::Range; @@ -10,12 +10,9 @@ pub struct Stack { } impl Stack { - fn new (top: usize, bottom: usize) -> Stack { + fn new(top: usize, bottom: usize) -> Stack { assert!(top > bottom); - Stack { - top, - bottom, - } + Stack { top, bottom } } pub fn top(&self) -> usize { @@ -29,7 +26,7 @@ impl Stack { #[derive(Debug)] pub struct StackAllocator { - range: Range + range: Range, } impl StackAllocator { @@ -37,10 +34,12 @@ impl StackAllocator { StackAllocator { range } } - pub fn alloc_stack(&mut self, - active_table: &mut ActivePageTable, - frame_allocator: &mut FA, - size_in_pages: usize) -> Option { + pub fn alloc_stack( + &mut self, + active_table: &mut ActivePageTable, + frame_allocator: &mut FA, + size_in_pages: usize, + ) -> Option { if size_in_pages == 0 { return None; /* a zero sized stack makes no sense */ } @@ -71,8 +70,10 @@ impl StackAllocator { // create a new stack let top_of_stack = end.start_address().as_u32() + PAGE_SIZE as u32; - Some(Stack::new(top_of_stack as usize, - start.start_address().as_u32() as usize)) + Some(Stack::new( + top_of_stack as usize, + start.start_address().as_u32() as usize, + )) } _ => None, /* not enough pages */ } From 700b8a4e00346638a6f7d241bf374a0e0b69fae3 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 15 Apr 2018 11:50:13 +0200 Subject: [PATCH 126/151] rustfmt --- kernel-rs/src/acpi/dsdt.rs | 2 +- kernel-rs/src/acpi/fadt.rs | 9 ++++++--- kernel-rs/src/acpi/mod.rs | 2 +- kernel-rs/src/console.rs | 10 +++++----- kernel-rs/src/keyboard.rs | 3 +-- kernel-rs/src/lib.rs | 2 -- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index e20cd3d8..d0612519 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -1,6 +1,6 @@ use super::{check_signature, ACPISDTHeader}; use core::mem; -use io::{Pio,Io}; +use io::{Io, Pio}; static mut DSDT: DSDT = DSDT { valid: false, diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index 94105bcb..22135d29 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -1,5 +1,5 @@ use super::{ACPISDTHeader, ACPISDTIter}; -use io::{Io,Pio}; +use io::{Io, Pio}; #[repr(C)] #[derive(Debug, Clone)] @@ -131,7 +131,7 @@ pub fn is_enable() -> Result { let pin: Pio = Pio::new(pm1_cnt[0]); if pm1_cnt[1] == 0 { Ok(pin.read() & 0x1 == 0x1) - // Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) + // Ok(cpuio::inw(pm1_cnt[0]) & 0x1 == 0x1) } else { let pin2: Pio = Pio::new(pm1_cnt[1]); Ok(pin.read() & 0x1 == 0x1 || pin2.read() & 0x1 == 0x1) @@ -153,7 +153,10 @@ pub fn reboot() -> Result<(), &'static str> { Err("ACPI is not enabled") } else { let fadt = is_init()?; - println!("fadt on {} ({}), value is {}", fadt.resetreg.address as u32, fadt.resetreg.address as u16, fadt.resetvalue); + println!( + "fadt on {} ({}), value is {}", + fadt.resetreg.address as u32, fadt.resetreg.address as u16, fadt.resetvalue + ); let mut pin: Pio = Pio::new(fadt.resetreg.address as u16); pin.write(fadt.resetvalue); // cpuio::outb(fadt.resetreg.address as u16, fadt.resetvalue); //TODO do it work diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index b1ab85ca..55f86984 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -161,7 +161,7 @@ pub fn shutdown() -> Result<(), &'static str> { /// This function need ACPI in v2 pub fn reboot() -> Result<(), &'static str> { is_init()?; - if unsafe {ACPI.v2} { + if unsafe { ACPI.v2 } { fadt::reboot() } else { Err("ACPI reboot only available in ACPI v2+") diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index f44b444e..9ec181d7 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -61,11 +61,11 @@ fn help() -> Result<(), &'static str> { /// fn reboot() -> ! { match acpi::reboot() { - Err(msg) => println!("{}", msg), - _ => println!("Unable to perform ACPI reboot."), + Err(msg) => println!("{}", msg), + _ => println!("Unable to perform ACPI reboot."), } flush!(); - unsafe {PS2.ps2_8042_reset()};// TODO unsafe + unsafe { PS2.ps2_8042_reset() }; // TODO unsafe println!("Unable to perform 8042 reboot. Kernel will be halted"); flush!(); io::halt(); @@ -78,8 +78,8 @@ fn reboot() -> ! { /// fn shutdown() -> ! { match acpi::shutdown() { - Err(msg) => println!("{}", msg), - _ => println!("Unable to perform ACPI shutdown. Kernel will be halted"), + Err(msg) => println!("{}", msg), + _ => println!("Unable to perform ACPI shutdown. Kernel will be halted"), } flush!(); io::halt(); diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 8151114b..d4b77828 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use vga; -use io::{self,Pio,Io}; +use io::{self, Io, Pio}; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ @@ -66,7 +66,6 @@ const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ *b"\0\0",//capslock ]; - pub static mut PS2: Ps2 = Ps2::new(); pub struct Ps2 { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 9995b3b4..9fe8e091 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -61,8 +61,6 @@ pub fn kmain() -> ! { // *(0xdead as *mut u32) = 42; // }; - println!("tss: {:?}"); - // vga is *not* cpu specific vga::init(); From e1f8c3f9caddf5ad4cf11336d0e5c760f7e9d85f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 15 Apr 2018 18:12:51 +0200 Subject: [PATCH 127/151] stack stuff for willy wonka --- kernel-rs/src/memory/mod.rs | 32 +++++++++++++++++-------- kernel-rs/src/memory/stack_allocator.rs | 2 +- kernel-rs/x86 | 2 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 0ee34685..314b2dbc 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,14 +1,15 @@ mod bump; mod recycle; -// mod stack_allocator; +mod stack_allocator; use multiboot2; use x86::structures::paging::*; +use x86::*; use spin::Mutex; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; -// use self::stack_allocator::StackAllocator; +use self::stack_allocator::StackAllocator; pub trait FrameAllocator { fn allocate_frames(&mut self, size: usize) -> Option; @@ -17,7 +18,7 @@ pub trait FrameAllocator { pub struct MemoryControler { frame_allocator: RecycleAllocator, - // stack_allocator: StackAllocator, + stack_allocator: StackAllocator, } static MEMORY_CONTROLER: Mutex> = Mutex::new(None); @@ -50,16 +51,19 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let frame_allocator = RecycleAllocator::new(bump_allocator); - // let stack_allocator = { - // let stack_alloc_start = heap_end_page + 1; - // let stack_alloc_end = stack_alloc_start + 100; - // let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; - // StackAllocator::new(stack_alloc_range) - // }; + let heap_end_page = + Page::containing_address(VirtAddr::new(::HEAP_START as u32 + ::HEAP_SIZE as u32 - 1)); + + let stack_allocator = { + let stack_alloc_start = heap_end_page + 1; + let stack_alloc_end = stack_alloc_start + 100; + let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; + StackAllocator::new(stack_alloc_range) + }; *MEMORY_CONTROLER.lock() = Some(MemoryControler { frame_allocator, - // stack_allocator, + stack_allocator, }); } @@ -79,6 +83,14 @@ pub fn deallocate_frames(frame: PhysFrame, count: usize) { } } +pub fn allocate_stack() { + if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { + controler.stack_allocator.allocate_stack() + } else { + panic!("frame allocator not initialized!"); + } +} + /// Init memory module after core /// Must be called once, and only once, pub fn init_noncore() { diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs index fb756ce4..ddf17a06 100644 --- a/kernel-rs/src/memory/stack_allocator.rs +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -34,7 +34,7 @@ impl StackAllocator { StackAllocator { range } } - pub fn alloc_stack( + pub fn allocate_stack( &mut self, active_table: &mut ActivePageTable, frame_allocator: &mut FA, diff --git a/kernel-rs/x86 b/kernel-rs/x86 index f5e4cb87..2a8416d0 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit f5e4cb879953ebbeba28a1eaa28bf531424e6824 +Subproject commit 2a8416d0af403786d082695d13a0f74cd2b7f216 From b3a1c5194a3c8a27fefcc61075a740dc1eb762df Mon Sep 17 00:00:00 2001 From: wescande Date: Sun, 15 Apr 2018 21:00:53 +0200 Subject: [PATCH 128/151] add some --- kernel-rs/Makefile | 2 +- kernel-rs/src/arch/x86/gdt.rs | 16 ++++- kernel-rs/src/arch/x86/idt.rs | 2 + kernel-rs/src/arch/x86/interrupt/exception.rs | 1 + kernel-rs/src/arch/x86/mod.rs | 2 +- kernel-rs/src/io/mod.rs | 2 + kernel-rs/src/lib.rs | 15 ++++- kernel-rs/src/memory/mod.rs | 62 +++++++++++-------- kernel-rs/src/memory/stack_allocator.rs | 18 +++--- kernel-rs/x86 | 2 +- 10 files changed, 80 insertions(+), 42 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index ebafd3f1..5f339951 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -15,7 +15,7 @@ build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile ## COMPILE RUST (xargo) rust_os := target/$(TARGET)/debug/lib$(OS).a $(rust_os): $(TARGET).json Makefile - @RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) + @TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) ## LINKAGE kernel := build/$(OS) diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index cea7e214..a5cb7ab7 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -2,14 +2,25 @@ use x86::structures::gdt; use x86::structures::tss; use x86::instructions::segmentation::set_cs; use x86::instructions::tables::load_tss; +use arch::x86::paging::ActivePageTable; use spin::Once; +// use io; static GDT: Once = Once::new(); static TSS: Once = Once::new(); -pub fn init() { +pub fn init(mut active_table: &mut ActivePageTable) { + // let tss = tss::TaskStateSegment::new(); let tss = TSS.call_once(|| { - let tss = tss::TaskStateSegment::new(); + let mut tss = tss::TaskStateSegment::new(); +match ::memory::allocate_stack(&mut active_table) { + Some(stack) => {tss.esp0 = stack.top; tss.ss = 0x18}, + // Some(stack) => {tss.esp = stack.top; tss.ebp = stack.bottom }, + _ => panic!("There is no stack available for tss"), + }; + // tss.esp = tss.esp0; + // tss.ebp = tss.esp; + // println!("tss on {:#x}", tss.esp0);flush!(); tss }); @@ -33,6 +44,7 @@ pub fn init() { println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); flush!(); + // io::halt(); gdt.load(); unsafe { // reload code segment register diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs index 4a511522..7407f2c0 100644 --- a/kernel-rs/src/arch/x86/idt.rs +++ b/kernel-rs/src/arch/x86/idt.rs @@ -15,10 +15,12 @@ lazy_static! { idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); idt.device_not_available.set_handler_fn(exception::device_not_available); idt.double_fault.set_handler_fn(exception::double_fault); + idt.double_fault.set_gate_type(GateType::TaskGate32); idt.segment_not_present.set_handler_fn(exception::segment_not_present); idt.stack_segment_fault.set_handler_fn(exception::stack_segment); idt.general_protection_fault.set_handler_fn(exception::general_protection); idt.page_fault.set_handler_fn(exception::page_fault); + idt.page_fault.set_gate_type(GateType::TaskGate32); idt.x87_floating_point.set_handler_fn(exception::x87_fpu); idt.alignment_check.set_handler_fn(exception::alignment_check); idt.machine_check.set_handler_fn(exception::machine_check); diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index b8994281..1eead757 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -1,6 +1,7 @@ // https://wiki.osdev.org/Exceptions use arch::x86::pti; +use io; macro_rules! exception { ($name:ident, $func:block) => { diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 2110ffae..fb606873 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -40,7 +40,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { idt::init(); // fill and load gdt - gdt::init(); + gdt::init(&mut active_table); // set up heap ::allocator::init(&mut active_table); diff --git a/kernel-rs/src/io/mod.rs b/kernel-rs/src/io/mod.rs index 8c4c4543..2bfb053a 100644 --- a/kernel-rs/src/io/mod.rs +++ b/kernel-rs/src/io/mod.rs @@ -29,10 +29,12 @@ pub trait Io { } } +#[inline(always)] pub fn cli() { unsafe { asm!("cli" : : : : "volatile") }; } +#[inline(always)] pub fn halt() -> ! { cli(); loop { diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 9fe8e091..143320a0 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -44,6 +44,8 @@ pub mod memory; /// arch specific entry points pub mod arch; +// use core::mem; +// use x86::structures::idt::*; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded pub fn kmain() -> ! { @@ -51,15 +53,22 @@ pub fn kmain() -> ! { memory::init_noncore(); // x86::instructions::interrupts::int3(); + // println!("size of idt entry: {}", mem::size_of::>()); + // println!("size of i32 {}", mem::size_of::()); + // flush!(); + // unsafe {asm!("hlt");} + // let x = 0; + // let y = 5 /x; + // println!("x {} y {}", x, y); // fn stack_overflow() { // stack_overflow(); // } // stack_overflow(); - // unsafe { - // *(0xdead as *mut u32) = 42; - // }; + unsafe { + *(0xdead as *mut u32) = 42; + }; // vga is *not* cpu specific vga::init(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 314b2dbc..d27633d8 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -4,12 +4,14 @@ mod stack_allocator; use multiboot2; use x86::structures::paging::*; +use arch::x86::paging::ActivePageTable; use x86::*; -use spin::Mutex; +// use spin::Mutex; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; -use self::stack_allocator::StackAllocator; +use self::stack_allocator::{Stack,StackAllocator}; + pub trait FrameAllocator { fn allocate_frames(&mut self, size: usize) -> Option; @@ -21,7 +23,7 @@ pub struct MemoryControler { stack_allocator: StackAllocator, } -static MEMORY_CONTROLER: Mutex> = Mutex::new(None); +static mut MEMORY_CONTROLER: Option = None; pub fn init(boot_info: &multiboot2::BootInformation) { let elf_sections_tag = boot_info.elf_sections_tag().unwrap(); @@ -47,7 +49,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) { boot_info.start_address(), boot_info.end_address(), memory_map_tag.memory_areas(), - ); + ); let frame_allocator = RecycleAllocator::new(bump_allocator); @@ -61,42 +63,52 @@ pub fn init(boot_info: &multiboot2::BootInformation) { StackAllocator::new(stack_alloc_range) }; - *MEMORY_CONTROLER.lock() = Some(MemoryControler { - frame_allocator, - stack_allocator, - }); + unsafe { + MEMORY_CONTROLER = Some(MemoryControler { + frame_allocator, + stack_allocator, + }); + } } pub fn allocate_frames(count: usize) -> Option { - if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { - controler.frame_allocator.allocate_frames(count) - } else { - panic!("frame allocator not initialized!"); + unsafe { + if let Some(ref mut controler) = MEMORY_CONTROLER { + controler.frame_allocator.allocate_frames(count) + } else { + panic!("frame allocator not initialized!"); + } } } pub fn deallocate_frames(frame: PhysFrame, count: usize) { - if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { - controler.frame_allocator.deallocate_frames(frame, count) - } else { - panic!("frame allocator not initialized!"); + unsafe { + if let Some(ref mut controler) = MEMORY_CONTROLER { + controler.frame_allocator.deallocate_frames(frame, count) + } else { + panic!("frame allocator not initialized!"); + } } } -pub fn allocate_stack() { - if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { - controler.stack_allocator.allocate_stack() - } else { - panic!("frame allocator not initialized!"); +pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option { + unsafe { + if let Some(ref mut controler) = MEMORY_CONTROLER { + controler.stack_allocator.allocate_stack(&mut active_table, &mut controler.frame_allocator, 5) + } else { + panic!("frame allocator not initialized!"); + } } } /// Init memory module after core /// Must be called once, and only once, pub fn init_noncore() { - if let Some(ref mut controler) = *MEMORY_CONTROLER.lock() { - controler.frame_allocator.set_core(true); - } else { - panic!("frame allocator not initialized"); + unsafe { + if let Some(ref mut controler) = MEMORY_CONTROLER { + controler.frame_allocator.set_core(true); + } else { + panic!("frame allocator not initialized"); + } } } diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs index ddf17a06..f9aa0ed0 100644 --- a/kernel-rs/src/memory/stack_allocator.rs +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -1,25 +1,25 @@ use x86::structures::paging::*; -use memory::paging::ActivePageTable; +use arch::x86::paging::ActivePageTable; use memory::*; use core::ops::Range; #[derive(Debug)] pub struct Stack { - top: usize, - bottom: usize, + pub top: u32, + pub bottom: u32, } impl Stack { - fn new(top: usize, bottom: usize) -> Stack { + fn new(top: u32, bottom: u32) -> Stack { assert!(top > bottom); Stack { top, bottom } } - pub fn top(&self) -> usize { + pub fn top(&self) -> u32 { self.top } - pub fn bottom(&self) -> usize { + pub fn bottom(&self) -> u32 { self.bottom } } @@ -65,14 +65,14 @@ impl StackAllocator { // map stack pages to physical frames for page in range { - active_table.map(page, PageTableFlags::WRITABLE, frame_allocator); + active_table.map(page, PageTableFlags::WRITABLE); } // create a new stack let top_of_stack = end.start_address().as_u32() + PAGE_SIZE as u32; Some(Stack::new( - top_of_stack as usize, - start.start_address().as_u32() as usize, + top_of_stack, + start.start_address().as_u32(), )) } _ => None, /* not enough pages */ diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 2a8416d0..c6636434 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 2a8416d0af403786d082695d13a0f74cd2b7f216 +Subproject commit c6636434cb64916c303c17c243c0e93830882248 From 7e150e081b785a19a8dee56b085f83380b20532b Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Mon, 16 Apr 2018 16:34:20 +0200 Subject: [PATCH 129/151] now we have 2 tss's, still doesnt work properly --- kernel-rs/src/arch/x86/gdt.rs | 70 +++++++++++++------ kernel-rs/src/arch/x86/idt.rs | 9 ++- kernel-rs/src/arch/x86/interrupt/exception.rs | 20 +++--- kernel-rs/src/console.rs | 16 +++++ kernel-rs/src/lib.rs | 13 +--- kernel-rs/src/memory/mod.rs | 9 +-- kernel-rs/src/memory/stack_allocator.rs | 8 +-- kernel-rs/x86 | 2 +- 8 files changed, 93 insertions(+), 54 deletions(-) diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index a5cb7ab7..cad1b356 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -2,55 +2,79 @@ use x86::structures::gdt; use x86::structures::tss; use x86::instructions::segmentation::set_cs; use x86::instructions::tables::load_tss; +use x86::registers::control; use arch::x86::paging::ActivePageTable; use spin::Once; // use io; static GDT: Once = Once::new(); -static TSS: Once = Once::new(); +static TSS_MAIN: Once = Once::new(); +static TSS_INT: Once = Once::new(); pub fn init(mut active_table: &mut ActivePageTable) { - // let tss = tss::TaskStateSegment::new(); - let tss = TSS.call_once(|| { + let tss_main = TSS_MAIN.call_once(|| { let mut tss = tss::TaskStateSegment::new(); -match ::memory::allocate_stack(&mut active_table) { - Some(stack) => {tss.esp0 = stack.top; tss.ss = 0x18}, - // Some(stack) => {tss.esp = stack.top; tss.ebp = stack.bottom }, - _ => panic!("There is no stack available for tss"), + // tss.esp0 = stack.top; + tss.ss0 = 0x8; + tss.cr3 = control::Cr3::read_u32(); + tss.reserved_iopb = 1; //T debug bit + tss + }); + + let tss_int = TSS_INT.call_once(|| { + let mut tss = tss::TaskStateSegment::new(); + match ::memory::allocate_stack(&mut active_table) { + Some(stack) => { + println!("int tss stack at {:#x}", stack.top); + tss.esp0 = stack.top; + tss.ss0 = 0x8; + tss.cr3 = control::Cr3::read_u32(); + // tss.esp = stack.top; + // tss.es = 0x8; + // tss.cs = 0x8; + // tss.ss = 0x8; + // tss.ds = 0x8; + // tss.fs = 0x8; + // tss.gs = 0x8; + // tss.link = 0x10; //main tss + tss.reserved_iopb = 1; //T debug bit + } + _ => panic!("There is no stack available for tss"), }; - // tss.esp = tss.esp0; - // tss.ebp = tss.esp; - // println!("tss on {:#x}", tss.esp0);flush!(); tss }); let mut code_selector = gdt::SegmentSelector(0); - let mut tss_selector = gdt::SegmentSelector(0); + let mut tss_main_selector = gdt::SegmentSelector(0); + let mut tss_int_selector = gdt::SegmentSelector(0); let gdt = GDT.call_once(|| { let mut gdt = gdt::Gdt::new(); code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); - tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); + tss_main_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_main)); + tss_int_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_int)); gdt }); - println!("gdt 0 upper: {:#x}", gdt.table[0] as u32); - println!("gdt 0 lower: {:#x}", gdt.table[0] >> 32 as u32); - println!("gdt 1 upper: {:#x}", gdt.table[1] as u32); - println!("gdt 1 lower: {:#x}", gdt.table[1] >> 32 as u32); - println!("gdt 2 upper: {:#x}", gdt.table[2] as u32); - println!("gdt 2 lower: {:#x}", gdt.table[2] >> 32 as u32); - println!("gdt 3 upper: {:#x}", gdt.table[3] as u32); - println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); + // println!("gdt 0 upper: {:#x}", gdt.table[0] as u32); + // println!("gdt 0 lower: {:#x}", gdt.table[0] >> 32 as u32); + // println!("gdt 1 upper: {:#x}", gdt.table[1] as u32); + // println!("gdt 1 lower: {:#x}", gdt.table[1] >> 32 as u32); + // println!("gdt 2 upper: {:#x}", gdt.table[2] as u32); + // println!("gdt 2 lower: {:#x}", gdt.table[2] >> 32 as u32); + // println!("gdt 3 upper: {:#x}", gdt.table[3] as u32); + // println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); + // println!("gdt 4 upper: {:#x}", gdt.table[4] as u32); + // println!("gdt 4 lower: {:#x}", gdt.table[4] >> 32 as u32); flush!(); - // io::halt(); gdt.load(); unsafe { // reload code segment register + println!("set_cs({:#x})", code_selector.0); set_cs(code_selector); // load TSS - println!("loading tss {:?}", tss_selector); - load_tss(tss_selector); + println!("loading tss {:?}", tss_main_selector); + load_tss(tss_main_selector); } } diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs index 7407f2c0..48ce7dd8 100644 --- a/kernel-rs/src/arch/x86/idt.rs +++ b/kernel-rs/src/arch/x86/idt.rs @@ -10,17 +10,24 @@ lazy_static! { idt.debug.set_handler_fn(exception::debug); idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable); idt.breakpoint.set_handler_fn(exception::breakpoint); + idt.breakpoint.set_gate_type(GateType::TaskGate32); + idt.breakpoint.set_selector(0x18); + idt.overflow.set_handler_fn(exception::overflow); idt.bound_range_exceeded.set_handler_fn(exception::bound_range); idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); idt.device_not_available.set_handler_fn(exception::device_not_available); idt.double_fault.set_handler_fn(exception::double_fault); - idt.double_fault.set_gate_type(GateType::TaskGate32); + // idt.double_fault.set_gate_type(GateType::TaskGate32); + // idt.double_fault.set_selector(0x18); + idt.segment_not_present.set_handler_fn(exception::segment_not_present); idt.stack_segment_fault.set_handler_fn(exception::stack_segment); idt.general_protection_fault.set_handler_fn(exception::general_protection); idt.page_fault.set_handler_fn(exception::page_fault); idt.page_fault.set_gate_type(GateType::TaskGate32); + idt.page_fault.set_selector(0x18); + idt.x87_floating_point.set_handler_fn(exception::x87_fpu); idt.alignment_check.set_handler_fn(exception::alignment_check); idt.machine_check.set_handler_fn(exception::machine_check); diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 1eead757..a61d1642 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -1,14 +1,9 @@ // https://wiki.osdev.org/Exceptions -use arch::x86::pti; -use io; - macro_rules! exception { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) { - // unsafe { pti::map(); } - println!("Exception: {}", stringify!($name)); println!("{:#?}", stack_frame); flush!(); @@ -18,8 +13,6 @@ macro_rules! exception { $func } inner(stack_frame); - - // unsafe { pti::unmap(); } } } } @@ -50,7 +43,11 @@ exception!(divide_by_zero, { exception!(debug, {}); exception!(non_maskable, {}); -exception!(breakpoint, {}); +exception!(breakpoint, { + // unsafe { + // asm!("hlt"); + // } +}); exception!(overflow, {}); exception!(bound_range, {}); exception!(invalid_opcode, {}); @@ -60,7 +57,9 @@ exception!(coprocessor_segment_overrun, {}); exception_err!(invalid_tss, {}); exception_err!(segment_not_present, {}); exception_err!(stack_segment, {}); -exception_err!(general_protection, {}); +exception_err!(general_protection, { + panic!("general protection fault (#GP) can not recover"); +}); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, @@ -70,6 +69,9 @@ pub extern "x86-interrupt" fn page_fault( println!("Error code: {:?}", code); println!("{:#?}", stack_frame); flush!(); + unsafe { + asm!("hlt"); + } } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 9ec181d7..ae067a53 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -25,6 +25,8 @@ fn dispatch(command: &str) -> Result<(), &'static str> { "stack" => self::print_stack(), "regs" => self::regs(), "cpu" => self::cpu(), + "int3" => self::int3(), + "overflow" => self::overflow(), _ => Err("Command unknown. (h|help for help)"), } @@ -198,3 +200,17 @@ pub fn cpu() -> Result<(), &'static str> { flush!(); Ok(()) } + +pub fn int3() -> Result<(), &'static str> { + use x86; + x86::instructions::interrupts::int3(); + Ok(()) +} + +pub fn overflow() -> Result<(), &'static str> { + fn stack_overflow() { + stack_overflow(); + } + stack_overflow(); + Ok(()) +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 143320a0..b513ed0a 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -52,14 +52,8 @@ pub fn kmain() -> ! { // heap avalaible for tracking freed frames memory::init_noncore(); - // x86::instructions::interrupts::int3(); - // println!("size of idt entry: {}", mem::size_of::>()); - // println!("size of i32 {}", mem::size_of::()); - // flush!(); - // unsafe {asm!("hlt");} - // let x = 0; - // let y = 5 /x; - // println!("x {} y {}", x, y); + // vga is *not* cpu specific + vga::init(); // fn stack_overflow() { // stack_overflow(); @@ -70,8 +64,7 @@ pub fn kmain() -> ! { *(0xdead as *mut u32) = 42; }; - // vga is *not* cpu specific - vga::init(); + // x86::instructions::interrupts::int3(); loop {} } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index d27633d8..017f86e6 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -10,8 +10,7 @@ use x86::*; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; -use self::stack_allocator::{Stack,StackAllocator}; - +use self::stack_allocator::{Stack, StackAllocator}; pub trait FrameAllocator { fn allocate_frames(&mut self, size: usize) -> Option; @@ -49,7 +48,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) { boot_info.start_address(), boot_info.end_address(), memory_map_tag.memory_areas(), - ); + ); let frame_allocator = RecycleAllocator::new(bump_allocator); @@ -94,7 +93,9 @@ pub fn deallocate_frames(frame: PhysFrame, count: usize) { pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option { unsafe { if let Some(ref mut controler) = MEMORY_CONTROLER { - controler.stack_allocator.allocate_stack(&mut active_table, &mut controler.frame_allocator, 5) + controler + .stack_allocator + .allocate_stack(&mut active_table, 4) } else { panic!("frame allocator not initialized!"); } diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs index f9aa0ed0..710932d9 100644 --- a/kernel-rs/src/memory/stack_allocator.rs +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -34,10 +34,9 @@ impl StackAllocator { StackAllocator { range } } - pub fn allocate_stack( + pub fn allocate_stack( &mut self, active_table: &mut ActivePageTable, - frame_allocator: &mut FA, size_in_pages: usize, ) -> Option { if size_in_pages == 0 { @@ -70,10 +69,7 @@ impl StackAllocator { // create a new stack let top_of_stack = end.start_address().as_u32() + PAGE_SIZE as u32; - Some(Stack::new( - top_of_stack, - start.start_address().as_u32(), - )) + Some(Stack::new(top_of_stack, start.start_address().as_u32())) } _ => None, /* not enough pages */ } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index c6636434..b50a1f4f 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit c6636434cb64916c303c17c243c0e93830882248 +Subproject commit b50a1f4f875be1ccd8a89cf0ae23e292630d414e From 203ddd9780483d4db2e54dbb8c4b38b4e36715fb Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 17 Apr 2018 12:26:47 +0200 Subject: [PATCH 130/151] cleanup up for handing in --- kernel-rs/src/arch/x86/gdt.rs | 36 ++++--------------- kernel-rs/src/arch/x86/idt.rs | 9 ----- kernel-rs/src/arch/x86/interrupt/exception.rs | 12 +++---- kernel-rs/src/lib.rs | 6 ++-- 4 files changed, 14 insertions(+), 49 deletions(-) diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index cad1b356..74ebeb04 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -5,7 +5,6 @@ use x86::instructions::tables::load_tss; use x86::registers::control; use arch::x86::paging::ActivePageTable; use spin::Once; -// use io; static GDT: Once = Once::new(); static TSS_MAIN: Once = Once::new(); @@ -15,44 +14,19 @@ pub fn init(mut active_table: &mut ActivePageTable) { let tss_main = TSS_MAIN.call_once(|| { let mut tss = tss::TaskStateSegment::new(); // tss.esp0 = stack.top; - tss.ss0 = 0x8; + // tss.ss = 0x8; tss.cr3 = control::Cr3::read_u32(); tss.reserved_iopb = 1; //T debug bit tss }); - let tss_int = TSS_INT.call_once(|| { - let mut tss = tss::TaskStateSegment::new(); - match ::memory::allocate_stack(&mut active_table) { - Some(stack) => { - println!("int tss stack at {:#x}", stack.top); - tss.esp0 = stack.top; - tss.ss0 = 0x8; - tss.cr3 = control::Cr3::read_u32(); - // tss.esp = stack.top; - // tss.es = 0x8; - // tss.cs = 0x8; - // tss.ss = 0x8; - // tss.ds = 0x8; - // tss.fs = 0x8; - // tss.gs = 0x8; - // tss.link = 0x10; //main tss - tss.reserved_iopb = 1; //T debug bit - } - _ => panic!("There is no stack available for tss"), - }; - tss - }); - let mut code_selector = gdt::SegmentSelector(0); let mut tss_main_selector = gdt::SegmentSelector(0); - let mut tss_int_selector = gdt::SegmentSelector(0); let gdt = GDT.call_once(|| { let mut gdt = gdt::Gdt::new(); code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); tss_main_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_main)); - tss_int_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_int)); gdt }); @@ -64,17 +38,19 @@ pub fn init(mut active_table: &mut ActivePageTable) { // println!("gdt 2 lower: {:#x}", gdt.table[2] >> 32 as u32); // println!("gdt 3 upper: {:#x}", gdt.table[3] as u32); // println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); + // println!("gdt 3 limit: {}", (gdt.table[3] & 0x00ff) as u32); + // println!("gdt 3 base : {}", (gdt.table[3] & 0xff00) as u32); // println!("gdt 4 upper: {:#x}", gdt.table[4] as u32); // println!("gdt 4 lower: {:#x}", gdt.table[4] >> 32 as u32); - flush!(); + // flush!(); gdt.load(); unsafe { // reload code segment register - println!("set_cs({:#x})", code_selector.0); + // println!("set_cs({:#x})", code_selector.0); set_cs(code_selector); // load TSS - println!("loading tss {:?}", tss_main_selector); + // println!("loading tss {:?}", tss_main_selector); load_tss(tss_main_selector); } } diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs index 48ce7dd8..4a511522 100644 --- a/kernel-rs/src/arch/x86/idt.rs +++ b/kernel-rs/src/arch/x86/idt.rs @@ -10,24 +10,15 @@ lazy_static! { idt.debug.set_handler_fn(exception::debug); idt.non_maskable_interrupt.set_handler_fn(exception::non_maskable); idt.breakpoint.set_handler_fn(exception::breakpoint); - idt.breakpoint.set_gate_type(GateType::TaskGate32); - idt.breakpoint.set_selector(0x18); - idt.overflow.set_handler_fn(exception::overflow); idt.bound_range_exceeded.set_handler_fn(exception::bound_range); idt.invalid_opcode.set_handler_fn(exception::invalid_opcode); idt.device_not_available.set_handler_fn(exception::device_not_available); idt.double_fault.set_handler_fn(exception::double_fault); - // idt.double_fault.set_gate_type(GateType::TaskGate32); - // idt.double_fault.set_selector(0x18); - idt.segment_not_present.set_handler_fn(exception::segment_not_present); idt.stack_segment_fault.set_handler_fn(exception::stack_segment); idt.general_protection_fault.set_handler_fn(exception::general_protection); idt.page_fault.set_handler_fn(exception::page_fault); - idt.page_fault.set_gate_type(GateType::TaskGate32); - idt.page_fault.set_selector(0x18); - idt.x87_floating_point.set_handler_fn(exception::x87_fpu); idt.alignment_check.set_handler_fn(exception::alignment_check); idt.machine_check.set_handler_fn(exception::machine_check); diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index a61d1642..adb17268 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -44,15 +44,16 @@ exception!(divide_by_zero, { exception!(debug, {}); exception!(non_maskable, {}); exception!(breakpoint, { - // unsafe { - // asm!("hlt"); - // } + println!("breakpoint inner function"); + flush!(); }); exception!(overflow, {}); exception!(bound_range, {}); exception!(invalid_opcode, {}); exception!(device_not_available, {}); -exception_err!(double_fault, { panic!("double fault non recoverable") }); +exception_err!(double_fault, { + panic!("double fault non recoverable"); +}); exception!(coprocessor_segment_overrun, {}); exception_err!(invalid_tss, {}); exception_err!(segment_not_present, {}); @@ -69,9 +70,6 @@ pub extern "x86-interrupt" fn page_fault( println!("Error code: {:?}", code); println!("{:#?}", stack_frame); flush!(); - unsafe { - asm!("hlt"); - } } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b513ed0a..23b0c5cf 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -60,9 +60,9 @@ pub fn kmain() -> ! { // } // stack_overflow(); - unsafe { - *(0xdead as *mut u32) = 42; - }; + // unsafe { + // *(0xdead as *mut u32) = 42; + // }; // x86::instructions::interrupts::int3(); From 4a13eb1c15f80f9bf08654a2f29d0ee556d3cdc3 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 17 Apr 2018 12:28:04 +0200 Subject: [PATCH 131/151] bp doesnt block --- kernel-rs/src/arch/x86/interrupt/exception.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index adb17268..2f6a858d 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -38,15 +38,12 @@ macro_rules! exception_err { use x86::structures::idt::*; exception!(divide_by_zero, { - panic!("CPU exception: division by zero"); + panic!("CPU exception: division by zero") }); exception!(debug, {}); exception!(non_maskable, {}); -exception!(breakpoint, { - println!("breakpoint inner function"); - flush!(); -}); +exception!(breakpoint, {}); exception!(overflow, {}); exception!(bound_range, {}); exception!(invalid_opcode, {}); From d3eb0e51381d74e5ad28fa7023d59f1b23947363 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 25 Apr 2018 21:37:58 +0200 Subject: [PATCH 132/151] gdt stuff --- kernel-rs/src/arch/x86/gdt.rs | 19 ++++++------------- kernel-rs/x86 | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 74ebeb04..65873b55 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -30,19 +30,12 @@ pub fn init(mut active_table: &mut ActivePageTable) { gdt }); - // println!("gdt 0 upper: {:#x}", gdt.table[0] as u32); - // println!("gdt 0 lower: {:#x}", gdt.table[0] >> 32 as u32); - // println!("gdt 1 upper: {:#x}", gdt.table[1] as u32); - // println!("gdt 1 lower: {:#x}", gdt.table[1] >> 32 as u32); - // println!("gdt 2 upper: {:#x}", gdt.table[2] as u32); - // println!("gdt 2 lower: {:#x}", gdt.table[2] >> 32 as u32); - // println!("gdt 3 upper: {:#x}", gdt.table[3] as u32); - // println!("gdt 3 lower: {:#x}", gdt.table[3] >> 32 as u32); - // println!("gdt 3 limit: {}", (gdt.table[3] & 0x00ff) as u32); - // println!("gdt 3 base : {}", (gdt.table[3] & 0xff00) as u32); - // println!("gdt 4 upper: {:#x}", gdt.table[4] as u32); - // println!("gdt 4 lower: {:#x}", gdt.table[4] >> 32 as u32); - // flush!(); + println!("gdt[0]={:#?}", gdt::Descriptor(gdt.table[0])); + println!("gdt[1]={:#?}", gdt::Descriptor(gdt.table[1])); + println!("gdt[2]={:#?}", gdt::Descriptor(gdt.table[2])); + println!("gdt[3]={:#?}", gdt::Descriptor(gdt.table[3])); + println!("gdt[4]={:#?}", gdt::Descriptor(gdt.table[4])); + flush!(); gdt.load(); unsafe { diff --git a/kernel-rs/x86 b/kernel-rs/x86 index b50a1f4f..830c0b77 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit b50a1f4f875be1ccd8a89cf0ae23e292630d414e +Subproject commit 830c0b770873e8f96b0fbdab484579e15cfd8b73 From 0aae87eda3cb44f8da042b17a5523c92e003918f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 3 May 2018 20:27:52 +0200 Subject: [PATCH 133/151] i'm just trying to figure out this mess.. fml --- kernel-rs/src/allocator/mod.rs | 13 ++-- kernel-rs/src/arch/x86/consts.rs | 31 +++++++++ kernel-rs/src/arch/x86/gdt.rs | 67 ++++++++----------- kernel-rs/src/arch/x86/interrupt/exception.rs | 6 +- kernel-rs/src/arch/x86/mod.rs | 38 ++++++++++- kernel-rs/src/arch/x86/start.asm | 3 +- kernel-rs/src/console.rs | 16 +++++ kernel-rs/src/lib.rs | 4 +- kernel-rs/src/memory/mod.rs | 2 +- kernel-rs/src/vga/mod.rs | 36 +++++----- kernel-rs/x86 | 2 +- 11 files changed, 144 insertions(+), 74 deletions(-) create mode 100644 kernel-rs/src/arch/x86/consts.rs diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index 9707bd8a..5837c638 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -5,21 +5,22 @@ use x86::*; use x86::structures::paging::*; use arch::x86::paging::*; -fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) { - let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32)); - let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1)); +fn map_heap(active_table: &mut ActivePageTable, offset: u32, size: u32) { + let heap_start_page = Page::containing_address(VirtAddr::new(offset)); + let heap_end_page = Page::containing_address(VirtAddr::new(offset + size - 1)); for page in heap_start_page..heap_end_page + 1 { + //we really should only map 1 huge page instead of 1024 small pages active_table.map(page, PageTableFlags::WRITABLE); } } /// should be called only once pub unsafe fn init(active_table: &mut ActivePageTable) { - let offset = ::HEAP_START; - let size = ::HEAP_SIZE; + let offset = ::KERNEL_HEAP_OFFSET; + let size = ::KERNEL_HEAP_SIZE; map_heap(active_table, offset, size); - Allocator::init(offset, size); + Allocator::init(offset as usize, size as usize); } diff --git a/kernel-rs/src/arch/x86/consts.rs b/kernel-rs/src/arch/x86/consts.rs new file mode 100644 index 00000000..9d41c545 --- /dev/null +++ b/kernel-rs/src/arch/x86/consts.rs @@ -0,0 +1,31 @@ +//layout looks like this: +// [kernel 0->4MiB] +// [kernel 4->8MiB] +// [user stack] +// [start of userheap] +// . +// . +// . +// [end of userheap] +// [kernel heap] +// [recursive map] points to first entry +// +// which makes userheap = 4GiB - 4*4MiB (~= 4GiB) +macro_rules! p2 { ($i:expr) => {($i & P2_MASK) / P1_SIZE}} +pub const P2_MASK: u32 = 0xFFC0_0000; //top 10 bits +pub const P1_SIZE: u32 = 0x0040_0000; //4MiB (2**22) + +pub const RECURSIVE_PAGE_OFFSET: u32 = (-(P1_SIZE as isize)) as u32; +///1023 +pub const RECURSIVE_PAGE_P2: u32 = p2!(RECURSIVE_PAGE_OFFSET); + +pub const KERNEL_HEAP_OFFSET: u32 = RECURSIVE_PAGE_OFFSET - P1_SIZE; +///1022 +pub const KERNEL_HEAP_P2: u32 = p2!(KERNEL_HEAP_OFFSET); +pub const KERNEL_HEAP_SIZE: u32 = 4 * 1024 * 1024; //4MiB (1 huge page) + +pub const USER_OFFSET: u32 = 0x00a0_0000; //3rd page (kernel takes 2 first pages) +pub const USER_P2: u32 = p2!(USER_OFFSET); + +pub const USER_STACK_OFFSET: u32 = USER_OFFSET + P1_SIZE; +pub const USER_STACK_2: u32 = p2!(USER_STACK_OFFSET); diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 65873b55..3744733f 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -1,49 +1,38 @@ use x86::structures::gdt; use x86::structures::tss; -use x86::instructions::segmentation::set_cs; +use x86::instructions::segmentation::*; use x86::instructions::tables::load_tss; -use x86::registers::control; -use arch::x86::paging::ActivePageTable; +use x86::*; use spin::Once; -static GDT: Once = Once::new(); -static TSS_MAIN: Once = Once::new(); -static TSS_INT: Once = Once::new(); +pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); +pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); -pub fn init(mut active_table: &mut ActivePageTable) { - let tss_main = TSS_MAIN.call_once(|| { - let mut tss = tss::TaskStateSegment::new(); - // tss.esp0 = stack.top; - // tss.ss = 0x8; - tss.cr3 = control::Cr3::read_u32(); - tss.reserved_iopb = 1; //T debug bit - tss - }); +pub static GDT_KERNEL_CODE: u16 = 1; +pub static GDT_KERNEL_DATA: u16 = 1; +pub static GDT_USER_CODE: u16 = 2; +pub static GDT_USER_DATA: u16 = 3; - let mut code_selector = gdt::SegmentSelector(0); - let mut tss_main_selector = gdt::SegmentSelector(0); +pub unsafe fn init() { + TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; + asm!("mov %ebp, $0" : "=r" (TSS.esp0)); - let gdt = GDT.call_once(|| { - let mut gdt = gdt::Gdt::new(); - code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); - tss_main_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_main)); - gdt - }); + // the following order is important + let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); + let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); + let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); + //I read that the tss should be twice as long + //fuck knows why... + //also this doesnt work if the tss is after 3rd spot + //once again: fuck knows why... + GDT.add_entry(gdt::Descriptor(0)); + let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); + let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); - println!("gdt[0]={:#?}", gdt::Descriptor(gdt.table[0])); - println!("gdt[1]={:#?}", gdt::Descriptor(gdt.table[1])); - println!("gdt[2]={:#?}", gdt::Descriptor(gdt.table[2])); - println!("gdt[3]={:#?}", gdt::Descriptor(gdt.table[3])); - println!("gdt[4]={:#?}", gdt::Descriptor(gdt.table[4])); - flush!(); - - gdt.load(); - unsafe { - // reload code segment register - // println!("set_cs({:#x})", code_selector.0); - set_cs(code_selector); - // load TSS - // println!("loading tss {:?}", tss_main_selector); - load_tss(tss_main_selector); - } + GDT.load(); + set_cs(kcode_selector); + load_ds(kdata_selector); + load_es(kdata_selector); + load_ss(kdata_selector); + load_tss(tss_selector); } diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 2f6a858d..d9b034d2 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -4,7 +4,7 @@ macro_rules! exception { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) { - println!("Exception: {}", stringify!($name)); + println!("#{}", stringify!($name)); println!("{:#?}", stack_frame); flush!(); @@ -20,9 +20,9 @@ macro_rules! exception { macro_rules! exception_err { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name( - stack_frame: &mut ExceptionStackFrame, _error_code: u32) + stack_frame: &mut ExceptionStackFrame, error_code: u32) { - println!("Exception: {}", stringify!($name)); + println!("#{}({})", stringify!($name), error_code); println!("{:#?}", stack_frame); flush!(); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index fb606873..89080806 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -4,7 +4,7 @@ extern crate x86; pub mod paging; pub mod interrupt; pub mod device; -pub mod pti; +pub mod consts; pub mod gdt; pub mod idt; @@ -40,7 +40,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { idt::init(); // fill and load gdt - gdt::init(&mut active_table); + gdt::init(); // set up heap ::allocator::init(&mut active_table); @@ -51,3 +51,37 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // primary CPU entry point ::kmain(); } + +pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { + asm!("push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + " + : //no output + : "{r10}"(gdt::GDT_USER_DATA << 3 | 3), + "{r11}"(sp), + "{r12}"(1 << 9) // interrupt enable flag + "{r13}"(gdt::GDT_USER_CODE << 3 | 3), + "{r14}"(ip), + "{r15}"(arg) + : //no clobbers + : "intel", "volatile" + ); + + asm!("mov ds, r14d + mov es, r14d + mov fs, r15d + mov gs, r14d + fninit + iret" + : //no output (never returns) + : "{r14}"(gdt::GDT_USER_DATA << 3 | 3), + "{r15}"(gdt::GDT_USER_CODE << 3 | 3) + : //no clobbers (never returns) + : "intel", "volatile" + ); + unreachable!(); +} diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index ea3fe179..fc0fc608 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -4,10 +4,11 @@ extern x86_rust_start section .text bits 32 x86_start: - mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) + mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) mov ds, ax mov ss, ax mov es, ax + mov ax, 0x0 ; fuck fs & gs, fuck them. mov fs, ax mov gs, ax diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index ae067a53..e3b45690 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -186,9 +186,25 @@ pub fn acpi_info() -> Result<(), &'static str> { /// Dump control registers pub fn regs() -> Result<(), &'static str> { use x86::registers::control::*; + use x86::instructions::tables::tr; + use x86::instructions::segmentation::*; + use x86::structures::gdt; println!("cr0 = {:?}", Cr0::read()); println!("cr3 = {:?}", Cr3::read()); println!("cr4 = {:?}", Cr4::read()); + println!("tr = {:?}", tr()); + println!("ss = {:?}", ss()); + println!("cs = {:?}", cs()); + println!("ds = {:?}", ds()); + println!("es = {:?}", es()); + println!("fs = {:?}", fs()); + println!("gs = {:?}", gs()); + unsafe { + println!( + "tss = {:#?}", + gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize]) + ); + } flush!(); Ok(()) } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 23b0c5cf..6c65b86f 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -43,6 +43,7 @@ pub mod allocator; pub mod memory; /// arch specific entry points pub mod arch; +pub use arch::x86::consts::*; // use core::mem; // use x86::structures::idt::*; @@ -83,8 +84,5 @@ pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: loop {} } -pub const HEAP_START: usize = (1 << 22 + 2); //third entry of p2 -pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB - #[global_allocator] static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator; diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 017f86e6..3fba610d 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -53,7 +53,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let frame_allocator = RecycleAllocator::new(bump_allocator); let heap_end_page = - Page::containing_address(VirtAddr::new(::HEAP_START as u32 + ::HEAP_SIZE as u32 - 1)); + Page::containing_address(VirtAddr::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE - 1)); let stack_allocator = { let stack_alloc_start = heap_end_page + 1; diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 1a2dedc8..27be530c 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -199,24 +199,24 @@ impl fmt::Write for Writer { } pub fn init() { - set_color!(Yellow, Red); - print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#) - ); + // set_color!(Yellow, Red); + // print!( + // "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + // format_args!("{: ^80}", r#" ,--, "#), + // format_args!("{: ^80}", r#" ,--.'| ,----, "#), + // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + // format_args!("{: ^80}", r#" ' ; |./__; : "#), + // format_args!("{: ^80}", r#" | : ;| : .' "#), + // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + // format_args!("{: ^80}", r#" '--' `---' "#) + // ); unsafe { VGA.prompt(); } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 830c0b77..73a83239 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 830c0b770873e8f96b0fbdab484579e15cfd8b73 +Subproject commit 73a83239073de4acb5b18bacad049553a086ce3f From e2cf54877e2612647f3a6a49f176c729f74f0d93 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 17 May 2018 13:17:39 +0200 Subject: [PATCH 134/151] some stuff --- kernel-rs/.gdbinit | 2 + kernel-rs/Cargo.toml | 2 +- kernel-rs/Makefile | 14 ++++-- kernel-rs/mk/grub.mk | 2 +- kernel-rs/mk/qemu.mk | 18 +++---- kernel-rs/src/allocator/mod.rs | 14 +++--- kernel-rs/src/arch/x86/boot.asm | 4 ++ kernel-rs/src/arch/x86/consts.rs | 63 ++++++++++++++++--------- kernel-rs/src/arch/x86/gdt.rs | 33 ++++++++----- kernel-rs/src/arch/x86/linker.ld | 12 +++++ kernel-rs/src/arch/x86/mod.rs | 54 +++++++++++---------- kernel-rs/src/arch/x86/paging/mapper.rs | 1 - kernel-rs/src/console.rs | 22 +++++---- kernel-rs/src/lib.rs | 21 +++++++++ kernel-rs/src/memory/mod.rs | 38 ++++++--------- kernel-rs/x86 | 2 +- 16 files changed, 186 insertions(+), 116 deletions(-) create mode 100644 kernel-rs/.gdbinit diff --git a/kernel-rs/.gdbinit b/kernel-rs/.gdbinit new file mode 100644 index 00000000..12181178 --- /dev/null +++ b/kernel-rs/.gdbinit @@ -0,0 +1,2 @@ +set arch i386:x86-64 +symbol-file build/bluesnow-x86.bin diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index b44f28a4..45bb02ea 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bluesnow" version = "0.1.0" -authors = ["Jack Halford ", "William Escande "] +authors = ["Jack Halford ", "William Escande "] [lib] crate-type = ["staticlib"] diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 5f339951..67f3aee6 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -4,6 +4,11 @@ ARCH := x86 OS := bluesnow TARGET ?= $(ARCH)-$(OS) +all: + @printf "make kernel\t# build kernel binary\n" + @printf "make iso\t# build iso cdrom with grub\n" + @printf "make qemu\t# run qemu+gdb in tmux window\n" + ## COMPILE ASM (nasm) asm_source := $(wildcard src/arch/$(ARCH)/*.asm) asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source)) @@ -15,18 +20,18 @@ build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile ## COMPILE RUST (xargo) rust_os := target/$(TARGET)/debug/lib$(OS).a $(rust_os): $(TARGET).json Makefile - @TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) + TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) ## LINKAGE -kernel := build/$(OS) +kernel := build/$(OS)-$(ARCH).bin linker_script := src/arch/$(ARCH)/linker.ld LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections $(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) clean: - @xargo clean - @rm -rf build + xargo clean + rm -rf build .PHONY: clean kernel iso $(rust_os) @@ -37,3 +42,4 @@ include mk/qemu.mk include mk/grub.mk iso: $(grub-iso) +kernel: $(kernel) diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk index cb44a41e..80d40dfa 100644 --- a/kernel-rs/mk/grub.mk +++ b/kernel-rs/mk/grub.mk @@ -1,4 +1,4 @@ -grub-iso := $(kernel).iso +grub-iso := $(kernel:.bin=.iso) grub-cfg := src/arch/$(ARCH)/grub.cfg isodir := build/isofiles diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 366a12f5..4ff0c2c3 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -1,4 +1,4 @@ -ifeq ($(shell whoami), william) +ifeq ($(shell whoami), jack) PORT := 4242 PORTG := 4244 else @@ -6,20 +6,22 @@ else PORTG := 4344 endif -QEMU := qemu-system-x86_64 -QEMUFLAGS := -gdb tcp::$(PORTG) -enable-kvm -monitor telnet:127.0.0.1:$(PORT),server,nowait -curses -cdrom build/bluesnow.iso +QEMU := qemu-system-x86_64\ + -gdb tcp::$(PORTG)\ + -S\ + -enable-kvm\ + -monitor telnet:127.0.0.1:$(PORT),server,nowait\ + -curses\ + -cdrom build/bluesnow-x86.iso MONITOR := sleep 0.5;\ telnet 127.0.0.1 $(PORT);\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` GDB := gdb -q\ - -ex \"set arch i386:x86-64\"\ - -ex \"file $(kernel)\"\ - -ex \"target remote :$(PORTG)\"\ - -ex \"continue\" + -ex \"target remote :$(PORTG)\" qemu: @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } - @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU) $(QEMUFLAGS)' + @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)' diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index 5837c638..1aa4c172 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -5,12 +5,9 @@ use x86::*; use x86::structures::paging::*; use arch::x86::paging::*; -fn map_heap(active_table: &mut ActivePageTable, offset: u32, size: u32) { - let heap_start_page = Page::containing_address(VirtAddr::new(offset)); - let heap_end_page = Page::containing_address(VirtAddr::new(offset + size - 1)); - - for page in heap_start_page..heap_end_page + 1 { - //we really should only map 1 huge page instead of 1024 small pages +fn map_heap(active_table: &mut ActivePageTable) { + //zone for heap is predefines in `consts.rs` + for page in ::KERNEL_HEAP_RANGE { active_table.map(page, PageTableFlags::WRITABLE); } } @@ -20,7 +17,8 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { let offset = ::KERNEL_HEAP_OFFSET; let size = ::KERNEL_HEAP_SIZE; - map_heap(active_table, offset, size); + map_heap(active_table); - Allocator::init(offset as usize, size as usize); + //slab allocator + Allocator::init(offset.as_u32() as usize, size as usize); } diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 9737350d..3c24d67d 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -42,6 +42,10 @@ set_up_page_tables: or eax, 0b10000011 ; huge + present + writable mov [p2_table + 4], eax + mov eax, 0x800000 ; 8MB -> 12Mb (second page) + or eax, 0b10000011 ; huge + present + writable + mov [p2_table + 8], eax + mov eax, p2_table mov cr3, eax ret diff --git a/kernel-rs/src/arch/x86/consts.rs b/kernel-rs/src/arch/x86/consts.rs index 9d41c545..d1fb4a29 100644 --- a/kernel-rs/src/arch/x86/consts.rs +++ b/kernel-rs/src/arch/x86/consts.rs @@ -1,31 +1,52 @@ -//layout looks like this: +// p2 layout looks like this: // [kernel 0->4MiB] // [kernel 4->8MiB] +// [start of no man's land] +// . +// . +// . +// [end of no man's land] // [user stack] -// [start of userheap] -// . -// . -// . -// [end of userheap] // [kernel heap] // [recursive map] points to first entry // -// which makes userheap = 4GiB - 4*4MiB (~= 4GiB) -macro_rules! p2 { ($i:expr) => {($i & P2_MASK) / P1_SIZE}} -pub const P2_MASK: u32 = 0xFFC0_0000; //top 10 bits -pub const P1_SIZE: u32 = 0x0040_0000; //4MiB (2**22) +// no man's land should be used in the future for mmap() I guess +// the kernel right now takes up 2 pages with debug symbols, +// if it gets to 3 pages everything will crash and i'll have +// to hardcode the third page here and in `boot.asm` also! +// +// TODO +// kernel is mapped identically (start of memory) but in +// the future it should be higher-half mapped so that +// user memory starts at 0 -pub const RECURSIVE_PAGE_OFFSET: u32 = (-(P1_SIZE as isize)) as u32; -///1023 -pub const RECURSIVE_PAGE_P2: u32 = p2!(RECURSIVE_PAGE_OFFSET); +use x86::structures::paging::*; +use x86::*; +use core::ops::Range; -pub const KERNEL_HEAP_OFFSET: u32 = RECURSIVE_PAGE_OFFSET - P1_SIZE; -///1022 -pub const KERNEL_HEAP_P2: u32 = p2!(KERNEL_HEAP_OFFSET); -pub const KERNEL_HEAP_SIZE: u32 = 4 * 1024 * 1024; //4MiB (1 huge page) +// macro_rules! prange { ($i:expr, $s:expr) => {$i..$i+$s+1}} -pub const USER_OFFSET: u32 = 0x00a0_0000; //3rd page (kernel takes 2 first pages) -pub const USER_P2: u32 = p2!(USER_OFFSET); +// all of this is fucking contrived +// the rust compiler should be able to evaluate const expressions +// by using the impl for my structs, what i'm doing here is obvious +// to me but not to the compiler -pub const USER_STACK_OFFSET: u32 = USER_OFFSET + P1_SIZE; -pub const USER_STACK_2: u32 = p2!(USER_STACK_OFFSET); +pub const RECURSIVE_PAGE_OFFSET: VirtAddr = VirtAddr(0xffc0_000); // first 10 bits +pub const RECURSIVE_PAGE: Page = Page::containing_address(RECURSIVE_PAGE_OFFSET); +pub const RECURSIVE_PAGE_SIZE: u32 = 0x0040_0000; // the whole p2 entry + +pub const KERNEL_HEAP_OFFSET: VirtAddr = VirtAddr(RECURSIVE_PAGE_OFFSET.0 - RECURSIVE_PAGE_SIZE); +// should be +// pub const KERNEL_HEAP_OFFSET: VirtAddr = RECURSIVE_PAGE_OFFSET - RECURSIVE_PAGE_SIZE); +pub const KERNEL_HEAP_SIZE: u32 = 0x0040_0000; //4MiB (1 huge page) +pub const KERNEL_HEAP_START: Page = Page::containing_address(KERNEL_HEAP_OFFSET); +pub const KERNEL_HEAP_END: Page = + Page::containing_address(VirtAddr(KERNEL_HEAP_OFFSET.0 + KERNEL_HEAP_SIZE)); +pub const KERNEL_HEAP_RANGE: Range = KERNEL_HEAP_START..KERNEL_HEAP_END; + +pub const USER_STACK_OFFSET: VirtAddr = VirtAddr(KERNEL_HEAP_OFFSET.0 - KERNEL_HEAP_SIZE); +pub const USER_STACK_START: Page = Page::containing_address(USER_STACK_OFFSET); +pub const USER_STACK_SIZE: u32 = 0x0040_0000; //4MiB (1 huge page) +pub const USER_STACK_END: Page = + Page::containing_address(VirtAddr(USER_STACK_OFFSET.0 + USER_STACK_SIZE)); +pub const USER_STACK_RANGE: Range = USER_STACK_START..USER_STACK_END; diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 3744733f..cdfc540d 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -1,33 +1,41 @@ use x86::structures::gdt; use x86::structures::tss; +use x86::structures::gdt::{Descriptor, SegmentSelector}; use x86::instructions::segmentation::*; use x86::instructions::tables::load_tss; +use x86::PrivilegeLevel::{Ring0, Ring3}; use x86::*; -use spin::Once; pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); pub static GDT_KERNEL_CODE: u16 = 1; -pub static GDT_KERNEL_DATA: u16 = 1; -pub static GDT_USER_CODE: u16 = 2; -pub static GDT_USER_DATA: u16 = 3; +pub static GDT_KERNEL_DATA: u16 = 2; +pub static GDT_USER_CODE: u16 = 3; +pub static GDT_USER_DATA: u16 = 4; +// tss takes 2 spots; +pub static GDT_TSS: u16 = 5; pub unsafe fn init() { TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; - asm!("mov %ebp, $0" : "=r" (TSS.esp0)); + asm!("mov %esp, $0" : "=r" (TSS.esp0)); - // the following order is important + // the following *order* is important let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); - let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); - //I read that the tss should be twice as long - //fuck knows why... - //also this doesnt work if the tss is after 3rd spot - //once again: fuck knows why... - GDT.add_entry(gdt::Descriptor(0)); let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); + //I read that the tss should be twice as long + //fuck knows why... + let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); + GDT.add_entry(gdt::Descriptor(0)); + + // println!( + // "tr({:#x}):\n {:#?}", + // tss_selector.0, + // gdt::Descriptor(GDT.table[tss_selector.index() as usize]) + // ); + // flush!(); GDT.load(); set_cs(kcode_selector); @@ -35,4 +43,5 @@ pub unsafe fn init() { load_es(kdata_selector); load_ss(kdata_selector); load_tss(tss_selector); + // unreachable!(); } diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 2dc25860..df7fd06a 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -66,4 +66,16 @@ SECTIONS { *(.bss .bss.*) . = ALIGN(4K); } + + .stab : + { + *(.stab) + . = ALIGN(4K); + } + + .stabstr : + { + *(.stabstr) + . = ALIGN(4K); + } } diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 89080806..4355d810 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -53,35 +53,39 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { } pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { - asm!("push r10 - push r11 - push r12 - push r13 - push r14 - push r15 - " + use x86::structures::gdt::{Descriptor, SegmentSelector}; + use x86::instructions::segmentation::*; + use x86::PrivilegeLevel::{Ring0, Ring3}; + + x86::instructions::interrupts::disable(); + + // println!("sp: {:#x}", sp); + // println!("ip: {:#x}", ip); + + let udata_selector = SegmentSelector::new(gdt::GDT_USER_DATA, Ring0); + let ucode_selector = SegmentSelector::new(gdt::GDT_USER_CODE, Ring3); + load_ds(udata_selector); + load_es(udata_selector); + load_fs(udata_selector); + load_gs(udata_selector); + + asm!(" + push $0; \ + push $1; \ + push $2; \ + push $3; \ + push $4" : //no output - : "{r10}"(gdt::GDT_USER_DATA << 3 | 3), - "{r11}"(sp), - "{r12}"(1 << 9) // interrupt enable flag - "{r13}"(gdt::GDT_USER_CODE << 3 | 3), - "{r14}"(ip), - "{r15}"(arg) + : "r"(udata_selector), + "r"(sp), + "r"(1 << 9) // interrupt enable flag + "r"(ucode_selector), + "r"(ip) : //no clobbers : "intel", "volatile" ); - asm!("mov ds, r14d - mov es, r14d - mov fs, r15d - mov gs, r14d - fninit - iret" - : //no output (never returns) - : "{r14}"(gdt::GDT_USER_DATA << 3 | 3), - "{r15}"(gdt::GDT_USER_CODE << 3 | 3) - : //no clobbers (never returns) - : "intel", "volatile" - ); + asm!("iret"); + unreachable!(); } diff --git a/kernel-rs/src/arch/x86/paging/mapper.rs b/kernel-rs/src/arch/x86/paging/mapper.rs index c3d8115d..cf8ce6b5 100644 --- a/kernel-rs/src/arch/x86/paging/mapper.rs +++ b/kernel-rs/src/arch/x86/paging/mapper.rs @@ -84,7 +84,6 @@ impl Mapper { let frame = p1[page.p1_index()].pointed_frame().unwrap(); p1[page.p1_index()].set_unused(); tlb::flush(page.start_address()); - // TODO ::memory::deallocate_frames(frame, 1); } } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index e3b45690..5cbf1196 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -188,17 +188,19 @@ pub fn regs() -> Result<(), &'static str> { use x86::registers::control::*; use x86::instructions::tables::tr; use x86::instructions::segmentation::*; + use x86::registers::flags::*; use x86::structures::gdt; - println!("cr0 = {:?}", Cr0::read()); - println!("cr3 = {:?}", Cr3::read()); - println!("cr4 = {:?}", Cr4::read()); - println!("tr = {:?}", tr()); - println!("ss = {:?}", ss()); - println!("cs = {:?}", cs()); - println!("ds = {:?}", ds()); - println!("es = {:?}", es()); - println!("fs = {:?}", fs()); - println!("gs = {:?}", gs()); + println!("cr0 = {:?}", Cr0::read()); + println!("cr3 = {:?}", Cr3::read()); + println!("cr4 = {:?}", Cr4::read()); + println!("flags= {:?}", flags()); + println!("tr = {:?}", tr()); + println!("ss = {:?}", ss()); + println!("cs = {:?}", cs()); + println!("ds = {:?}", ds()); + println!("es = {:?}", es()); + println!("fs = {:?}", fs()); + println!("gs = {:?}", gs()); unsafe { println!( "tss = {:#?}", diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 6c65b86f..afe88457 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -3,6 +3,7 @@ // nightly stuff we need #![no_std] #![feature(lang_items)] +#![feature(naked_functions)] #![feature(const_fn)] #![feature(ptr_internals)] #![feature(asm)] @@ -67,6 +68,26 @@ pub fn kmain() -> ! { // x86::instructions::interrupts::int3(); + // println!("flags: {:?}", x86::registers::flags::flags()); + // flush!(); + + let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); + // let sp: u32; + // unsafe { + // asm!("mov %ebp, $0" : "=r" (sp)); + // } + let ip = self::init as *const () as u32; + + unsafe { + arch::x86::usermode(ip, sp, 0); + } + unreachable!() + // loop {} +} + +pub fn init() { + println!("inside init function!!!!!"); + flush!(); loop {} } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 3fba610d..d747acd5 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -6,7 +6,6 @@ use multiboot2; use x86::structures::paging::*; use arch::x86::paging::ActivePageTable; use x86::*; -// use spin::Mutex; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; @@ -19,7 +18,7 @@ pub trait FrameAllocator { pub struct MemoryControler { frame_allocator: RecycleAllocator, - stack_allocator: StackAllocator, + // stack_allocator: StackAllocator, } static mut MEMORY_CONTROLER: Option = None; @@ -51,21 +50,12 @@ pub fn init(boot_info: &multiboot2::BootInformation) { ); let frame_allocator = RecycleAllocator::new(bump_allocator); - - let heap_end_page = - Page::containing_address(VirtAddr::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE - 1)); - - let stack_allocator = { - let stack_alloc_start = heap_end_page + 1; - let stack_alloc_end = stack_alloc_start + 100; - let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; - StackAllocator::new(stack_alloc_range) - }; + // let stack_allocator = StackAllocator::new(::USER_STACK_RANGE); unsafe { MEMORY_CONTROLER = Some(MemoryControler { frame_allocator, - stack_allocator, + // stack_allocator, }); } } @@ -90,17 +80,17 @@ pub fn deallocate_frames(frame: PhysFrame, count: usize) { } } -pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option { - unsafe { - if let Some(ref mut controler) = MEMORY_CONTROLER { - controler - .stack_allocator - .allocate_stack(&mut active_table, 4) - } else { - panic!("frame allocator not initialized!"); - } - } -} +// pub fn allocate_stack(mut active_table: &mut ActivePageTable) -> Option { +// unsafe { +// if let Some(ref mut controler) = MEMORY_CONTROLER { +// controler +// .stack_allocator +// .allocate_stack(&mut active_table, 4) +// } else { +// panic!("frame allocator not initialized!"); +// } +// } +// } /// Init memory module after core /// Must be called once, and only once, diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 73a83239..3a6ff64c 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 73a83239073de4acb5b18bacad049553a086ce3f +Subproject commit 3a6ff64c5fb9a4bdeb8b6b4c83328278c551dbad From 91d6d126e8ff503b80716c40c46d342de58c9fdf Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 17 May 2018 16:46:02 +0200 Subject: [PATCH 135/151] switched qemu to qemu-system-i386, even though it doesnt change anything useful --- kernel-rs/.gdbinit | 4 ++-- kernel-rs/Cargo.toml | 4 ++++ kernel-rs/Makefile | 2 +- kernel-rs/mk/qemu.mk | 2 +- kernel-rs/src/arch/x86/boot.asm | 2 +- kernel-rs/src/arch/x86/linker.ld | 31 +++++++++++-------------------- kernel-rs/src/lib.rs | 12 +++++------- kernel-rs/x86-bluesnow.json | 6 +++--- 8 files changed, 28 insertions(+), 35 deletions(-) diff --git a/kernel-rs/.gdbinit b/kernel-rs/.gdbinit index 12181178..77d679cf 100644 --- a/kernel-rs/.gdbinit +++ b/kernel-rs/.gdbinit @@ -1,2 +1,2 @@ -set arch i386:x86-64 -symbol-file build/bluesnow-x86.bin +set arch i386 +file build/bluesnow-x86.bin diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 45bb02ea..824d95b2 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -25,3 +25,7 @@ path = "x86" [dependencies.lazy_static] version = "1.0.0" features = ["spin_no_std"] + +[dependencies.compiler_builtins] +#I'm waiting for somebody to port i386/udivdi3.S ... :((( +git = "https://github.com/rust-lang-nursery/compiler-builtins" diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 67f3aee6..5a421239 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -12,7 +12,7 @@ all: ## COMPILE ASM (nasm) asm_source := $(wildcard src/arch/$(ARCH)/*.asm) asm_object := $(patsubst src/arch/$(ARCH)/%.asm, build/arch/$(ARCH)/%.o, $(asm_source)) -NASM := /usr/bin/nasm -f elf -g +NASM := /usr/bin/nasm -f elf -gdwarf build/arch/$(ARCH)/%.o: src/arch/$(ARCH)/%.asm Makefile @mkdir -p $(shell dirname $@) $(NASM) $< -o $@ diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 4ff0c2c3..db0f170c 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -6,7 +6,7 @@ else PORTG := 4344 endif -QEMU := qemu-system-x86_64\ +QEMU := qemu-system-i386\ -gdb tcp::$(PORTG)\ -S\ -enable-kvm\ diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 3c24d67d..045dc35a 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -42,7 +42,7 @@ set_up_page_tables: or eax, 0b10000011 ; huge + present + writable mov [p2_table + 4], eax - mov eax, 0x800000 ; 8MB -> 12Mb (second page) + mov eax, 0x800000 ; 8MB -> 12Mb (third page) or eax, 0b10000011 ; huge + present + writable mov [p2_table + 8], eax diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index df7fd06a..4b3004c1 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -2,10 +2,6 @@ ENTRY(start) OUTPUT_FORMAT(elf32-i386) SECTIONS { - /* GDT for the win */ - /* . = 0x800; */ - /* .gdt : {KEEP(*(.gdt))} */ - /* VGA, cannot use section for this */ VGA_PTR = 0xb8000; . = 0xb8000; @@ -15,6 +11,7 @@ SECTIONS { /* ensure that the multiboot header is at the beginning */ .multiboot : { + /* KEEP otherwise it gets garbage collected by linker */ KEEP(*(.multiboot)) . = ALIGN(4K); } @@ -37,12 +34,6 @@ SECTIONS { . = ALIGN(4K); } - .debug : - { - *(.debug_*) - . = ALIGN(4K); - } - .gdt : { *(.gdt) @@ -67,15 +58,15 @@ SECTIONS { . = ALIGN(4K); } - .stab : - { - *(.stab) - . = ALIGN(4K); - } + /* .stab : */ + /* { */ + /* KEEP(*(.stab)) */ + /* . = ALIGN(4K); */ + /* } */ - .stabstr : - { - *(.stabstr) - . = ALIGN(4K); - } + /* .stabstr : */ + /* { */ + /* KEEP(*(.stabstr)) */ + /* . = ALIGN(4K); */ + /* } */ } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index afe88457..b9686b90 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -46,8 +46,6 @@ pub mod memory; pub mod arch; pub use arch::x86::consts::*; -// use core::mem; -// use x86::structures::idt::*; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded pub fn kmain() -> ! { @@ -78,11 +76,11 @@ pub fn kmain() -> ! { // } let ip = self::init as *const () as u32; - unsafe { - arch::x86::usermode(ip, sp, 0); - } - unreachable!() - // loop {} + // unsafe { + // arch::x86::usermode(ip, sp, 0); + // } + // unreachable!() + loop {} } pub fn init() { diff --git a/kernel-rs/x86-bluesnow.json b/kernel-rs/x86-bluesnow.json index 22f12e60..36bdde97 100644 --- a/kernel-rs/x86-bluesnow.json +++ b/kernel-rs/x86-bluesnow.json @@ -4,14 +4,14 @@ "_comment": "http://llvm.org/docs/LangRef.html#data-layout", "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", - "llvm-target": "i686-unknown-none", + "llvm-target": "i386-unknown-none", "linker-flavor": "gcc", - "no-compiler-rt": true, - "os": "bluesnow", + "os": "none", "target-endian": "little", "target-pointer-width": "32", "target-c-int-width": "32", "features": "-mmx,-fxsr,-sse,-sse2,+soft-float", "eliminate-frame-pointer": false, + "disable-redzone": true, "panic-strategy": "abort" } From 02d0ddaf02e950c04dea9688c871fdb9dc885504 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 17 May 2018 16:48:47 +0200 Subject: [PATCH 136/151] changed name x86 to i386 --- kernel-rs/Makefile | 2 +- kernel-rs/mk/qemu.mk | 2 +- kernel-rs/src/arch/{x86 => i386}/boot.asm | 0 kernel-rs/src/arch/{x86 => i386}/consts.rs | 0 kernel-rs/src/arch/{x86 => i386}/device/cpu.rs | 0 kernel-rs/src/arch/{x86 => i386}/device/local_apic.rs | 0 kernel-rs/src/arch/{x86 => i386}/device/mod.rs | 0 kernel-rs/src/arch/{x86 => i386}/device/pic.rs | 0 kernel-rs/src/arch/{x86 => i386}/gdt.rs | 0 kernel-rs/src/arch/{x86 => i386}/grub.cfg | 0 kernel-rs/src/arch/{x86 => i386}/idt.rs | 0 kernel-rs/src/arch/{x86 => i386}/interrupt/exception.rs | 0 kernel-rs/src/arch/{x86 => i386}/interrupt/irq.rs | 0 kernel-rs/src/arch/{x86 => i386}/interrupt/mod.rs | 0 kernel-rs/src/arch/{x86 => i386}/linker.ld | 0 kernel-rs/src/arch/{x86 => i386}/mod.rs | 0 kernel-rs/src/arch/{x86 => i386}/multiboot_header.asm | 0 kernel-rs/src/arch/{x86 => i386}/paging/mapper.rs | 0 kernel-rs/src/arch/{x86 => i386}/paging/mod.rs | 0 kernel-rs/src/arch/{x86 => i386}/paging/table.rs | 0 kernel-rs/src/arch/{x86 => i386}/paging/temporary_page.rs | 0 kernel-rs/src/arch/{x86 => i386}/pti.rs | 0 kernel-rs/src/arch/{x86 => i386}/start.asm | 0 kernel-rs/src/arch/mod.rs | 5 +++-- 24 files changed, 5 insertions(+), 4 deletions(-) rename kernel-rs/src/arch/{x86 => i386}/boot.asm (100%) rename kernel-rs/src/arch/{x86 => i386}/consts.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/device/cpu.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/device/local_apic.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/device/mod.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/device/pic.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/gdt.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/grub.cfg (100%) rename kernel-rs/src/arch/{x86 => i386}/idt.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/interrupt/exception.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/interrupt/irq.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/interrupt/mod.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/linker.ld (100%) rename kernel-rs/src/arch/{x86 => i386}/mod.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/multiboot_header.asm (100%) rename kernel-rs/src/arch/{x86 => i386}/paging/mapper.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/paging/mod.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/paging/table.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/paging/temporary_page.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/pti.rs (100%) rename kernel-rs/src/arch/{x86 => i386}/start.asm (100%) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 5a421239..913bdab6 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,6 +1,6 @@ SHELL := /bin/bash -ARCH := x86 +ARCH := i386 OS := bluesnow TARGET ?= $(ARCH)-$(OS) diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index db0f170c..44fce0d2 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -6,7 +6,7 @@ else PORTG := 4344 endif -QEMU := qemu-system-i386\ +QEMU := qemu-system-$(ARCH)\ -gdb tcp::$(PORTG)\ -S\ -enable-kvm\ diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/i386/boot.asm similarity index 100% rename from kernel-rs/src/arch/x86/boot.asm rename to kernel-rs/src/arch/i386/boot.asm diff --git a/kernel-rs/src/arch/x86/consts.rs b/kernel-rs/src/arch/i386/consts.rs similarity index 100% rename from kernel-rs/src/arch/x86/consts.rs rename to kernel-rs/src/arch/i386/consts.rs diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/i386/device/cpu.rs similarity index 100% rename from kernel-rs/src/arch/x86/device/cpu.rs rename to kernel-rs/src/arch/i386/device/cpu.rs diff --git a/kernel-rs/src/arch/x86/device/local_apic.rs b/kernel-rs/src/arch/i386/device/local_apic.rs similarity index 100% rename from kernel-rs/src/arch/x86/device/local_apic.rs rename to kernel-rs/src/arch/i386/device/local_apic.rs diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/i386/device/mod.rs similarity index 100% rename from kernel-rs/src/arch/x86/device/mod.rs rename to kernel-rs/src/arch/i386/device/mod.rs diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/i386/device/pic.rs similarity index 100% rename from kernel-rs/src/arch/x86/device/pic.rs rename to kernel-rs/src/arch/i386/device/pic.rs diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/i386/gdt.rs similarity index 100% rename from kernel-rs/src/arch/x86/gdt.rs rename to kernel-rs/src/arch/i386/gdt.rs diff --git a/kernel-rs/src/arch/x86/grub.cfg b/kernel-rs/src/arch/i386/grub.cfg similarity index 100% rename from kernel-rs/src/arch/x86/grub.cfg rename to kernel-rs/src/arch/i386/grub.cfg diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/i386/idt.rs similarity index 100% rename from kernel-rs/src/arch/x86/idt.rs rename to kernel-rs/src/arch/i386/idt.rs diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/i386/interrupt/exception.rs similarity index 100% rename from kernel-rs/src/arch/x86/interrupt/exception.rs rename to kernel-rs/src/arch/i386/interrupt/exception.rs diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/i386/interrupt/irq.rs similarity index 100% rename from kernel-rs/src/arch/x86/interrupt/irq.rs rename to kernel-rs/src/arch/i386/interrupt/irq.rs diff --git a/kernel-rs/src/arch/x86/interrupt/mod.rs b/kernel-rs/src/arch/i386/interrupt/mod.rs similarity index 100% rename from kernel-rs/src/arch/x86/interrupt/mod.rs rename to kernel-rs/src/arch/i386/interrupt/mod.rs diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/i386/linker.ld similarity index 100% rename from kernel-rs/src/arch/x86/linker.ld rename to kernel-rs/src/arch/i386/linker.ld diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/i386/mod.rs similarity index 100% rename from kernel-rs/src/arch/x86/mod.rs rename to kernel-rs/src/arch/i386/mod.rs diff --git a/kernel-rs/src/arch/x86/multiboot_header.asm b/kernel-rs/src/arch/i386/multiboot_header.asm similarity index 100% rename from kernel-rs/src/arch/x86/multiboot_header.asm rename to kernel-rs/src/arch/i386/multiboot_header.asm diff --git a/kernel-rs/src/arch/x86/paging/mapper.rs b/kernel-rs/src/arch/i386/paging/mapper.rs similarity index 100% rename from kernel-rs/src/arch/x86/paging/mapper.rs rename to kernel-rs/src/arch/i386/paging/mapper.rs diff --git a/kernel-rs/src/arch/x86/paging/mod.rs b/kernel-rs/src/arch/i386/paging/mod.rs similarity index 100% rename from kernel-rs/src/arch/x86/paging/mod.rs rename to kernel-rs/src/arch/i386/paging/mod.rs diff --git a/kernel-rs/src/arch/x86/paging/table.rs b/kernel-rs/src/arch/i386/paging/table.rs similarity index 100% rename from kernel-rs/src/arch/x86/paging/table.rs rename to kernel-rs/src/arch/i386/paging/table.rs diff --git a/kernel-rs/src/arch/x86/paging/temporary_page.rs b/kernel-rs/src/arch/i386/paging/temporary_page.rs similarity index 100% rename from kernel-rs/src/arch/x86/paging/temporary_page.rs rename to kernel-rs/src/arch/i386/paging/temporary_page.rs diff --git a/kernel-rs/src/arch/x86/pti.rs b/kernel-rs/src/arch/i386/pti.rs similarity index 100% rename from kernel-rs/src/arch/x86/pti.rs rename to kernel-rs/src/arch/i386/pti.rs diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/i386/start.asm similarity index 100% rename from kernel-rs/src/arch/x86/start.asm rename to kernel-rs/src/arch/i386/start.asm diff --git a/kernel-rs/src/arch/mod.rs b/kernel-rs/src/arch/mod.rs index 06b8ef64..b03878a5 100644 --- a/kernel-rs/src/arch/mod.rs +++ b/kernel-rs/src/arch/mod.rs @@ -1,3 +1,4 @@ // we only support a single architecture at the moment -// more specifically IA-32 (aka i386) but we name it x86 here. -pub mod x86; +// we called it i386 but we generally support all 32bit +// intel architectures (IA-32) such as i[3456]86 +pub mod i386; From df163a43490fca4710c47c8539f583ff0ccbb7f8 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 17 May 2018 16:54:42 +0200 Subject: [PATCH 137/151] reverted back --- kernel-rs/Makefile | 2 +- kernel-rs/src/arch/mod.rs | 4 ++-- kernel-rs/src/arch/{i386 => x86}/boot.asm | 0 kernel-rs/src/arch/{i386 => x86}/consts.rs | 0 kernel-rs/src/arch/{i386 => x86}/device/cpu.rs | 0 kernel-rs/src/arch/{i386 => x86}/device/local_apic.rs | 0 kernel-rs/src/arch/{i386 => x86}/device/mod.rs | 0 kernel-rs/src/arch/{i386 => x86}/device/pic.rs | 0 kernel-rs/src/arch/{i386 => x86}/gdt.rs | 0 kernel-rs/src/arch/{i386 => x86}/grub.cfg | 0 kernel-rs/src/arch/{i386 => x86}/idt.rs | 0 kernel-rs/src/arch/{i386 => x86}/interrupt/exception.rs | 0 kernel-rs/src/arch/{i386 => x86}/interrupt/irq.rs | 0 kernel-rs/src/arch/{i386 => x86}/interrupt/mod.rs | 0 kernel-rs/src/arch/{i386 => x86}/linker.ld | 0 kernel-rs/src/arch/{i386 => x86}/mod.rs | 0 kernel-rs/src/arch/{i386 => x86}/multiboot_header.asm | 0 kernel-rs/src/arch/{i386 => x86}/paging/mapper.rs | 0 kernel-rs/src/arch/{i386 => x86}/paging/mod.rs | 0 kernel-rs/src/arch/{i386 => x86}/paging/table.rs | 0 kernel-rs/src/arch/{i386 => x86}/paging/temporary_page.rs | 0 kernel-rs/src/arch/{i386 => x86}/pti.rs | 0 kernel-rs/src/arch/{i386 => x86}/start.asm | 0 23 files changed, 3 insertions(+), 3 deletions(-) rename kernel-rs/src/arch/{i386 => x86}/boot.asm (100%) rename kernel-rs/src/arch/{i386 => x86}/consts.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/device/cpu.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/device/local_apic.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/device/mod.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/device/pic.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/gdt.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/grub.cfg (100%) rename kernel-rs/src/arch/{i386 => x86}/idt.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/interrupt/exception.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/interrupt/irq.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/interrupt/mod.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/linker.ld (100%) rename kernel-rs/src/arch/{i386 => x86}/mod.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/multiboot_header.asm (100%) rename kernel-rs/src/arch/{i386 => x86}/paging/mapper.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/paging/mod.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/paging/table.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/paging/temporary_page.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/pti.rs (100%) rename kernel-rs/src/arch/{i386 => x86}/start.asm (100%) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 913bdab6..5a421239 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,6 +1,6 @@ SHELL := /bin/bash -ARCH := i386 +ARCH := x86 OS := bluesnow TARGET ?= $(ARCH)-$(OS) diff --git a/kernel-rs/src/arch/mod.rs b/kernel-rs/src/arch/mod.rs index b03878a5..baf9581d 100644 --- a/kernel-rs/src/arch/mod.rs +++ b/kernel-rs/src/arch/mod.rs @@ -1,4 +1,4 @@ // we only support a single architecture at the moment -// we called it i386 but we generally support all 32bit +// we call it x86 but we only support all 32bit // intel architectures (IA-32) such as i[3456]86 -pub mod i386; +pub mod x86; diff --git a/kernel-rs/src/arch/i386/boot.asm b/kernel-rs/src/arch/x86/boot.asm similarity index 100% rename from kernel-rs/src/arch/i386/boot.asm rename to kernel-rs/src/arch/x86/boot.asm diff --git a/kernel-rs/src/arch/i386/consts.rs b/kernel-rs/src/arch/x86/consts.rs similarity index 100% rename from kernel-rs/src/arch/i386/consts.rs rename to kernel-rs/src/arch/x86/consts.rs diff --git a/kernel-rs/src/arch/i386/device/cpu.rs b/kernel-rs/src/arch/x86/device/cpu.rs similarity index 100% rename from kernel-rs/src/arch/i386/device/cpu.rs rename to kernel-rs/src/arch/x86/device/cpu.rs diff --git a/kernel-rs/src/arch/i386/device/local_apic.rs b/kernel-rs/src/arch/x86/device/local_apic.rs similarity index 100% rename from kernel-rs/src/arch/i386/device/local_apic.rs rename to kernel-rs/src/arch/x86/device/local_apic.rs diff --git a/kernel-rs/src/arch/i386/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs similarity index 100% rename from kernel-rs/src/arch/i386/device/mod.rs rename to kernel-rs/src/arch/x86/device/mod.rs diff --git a/kernel-rs/src/arch/i386/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs similarity index 100% rename from kernel-rs/src/arch/i386/device/pic.rs rename to kernel-rs/src/arch/x86/device/pic.rs diff --git a/kernel-rs/src/arch/i386/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs similarity index 100% rename from kernel-rs/src/arch/i386/gdt.rs rename to kernel-rs/src/arch/x86/gdt.rs diff --git a/kernel-rs/src/arch/i386/grub.cfg b/kernel-rs/src/arch/x86/grub.cfg similarity index 100% rename from kernel-rs/src/arch/i386/grub.cfg rename to kernel-rs/src/arch/x86/grub.cfg diff --git a/kernel-rs/src/arch/i386/idt.rs b/kernel-rs/src/arch/x86/idt.rs similarity index 100% rename from kernel-rs/src/arch/i386/idt.rs rename to kernel-rs/src/arch/x86/idt.rs diff --git a/kernel-rs/src/arch/i386/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs similarity index 100% rename from kernel-rs/src/arch/i386/interrupt/exception.rs rename to kernel-rs/src/arch/x86/interrupt/exception.rs diff --git a/kernel-rs/src/arch/i386/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs similarity index 100% rename from kernel-rs/src/arch/i386/interrupt/irq.rs rename to kernel-rs/src/arch/x86/interrupt/irq.rs diff --git a/kernel-rs/src/arch/i386/interrupt/mod.rs b/kernel-rs/src/arch/x86/interrupt/mod.rs similarity index 100% rename from kernel-rs/src/arch/i386/interrupt/mod.rs rename to kernel-rs/src/arch/x86/interrupt/mod.rs diff --git a/kernel-rs/src/arch/i386/linker.ld b/kernel-rs/src/arch/x86/linker.ld similarity index 100% rename from kernel-rs/src/arch/i386/linker.ld rename to kernel-rs/src/arch/x86/linker.ld diff --git a/kernel-rs/src/arch/i386/mod.rs b/kernel-rs/src/arch/x86/mod.rs similarity index 100% rename from kernel-rs/src/arch/i386/mod.rs rename to kernel-rs/src/arch/x86/mod.rs diff --git a/kernel-rs/src/arch/i386/multiboot_header.asm b/kernel-rs/src/arch/x86/multiboot_header.asm similarity index 100% rename from kernel-rs/src/arch/i386/multiboot_header.asm rename to kernel-rs/src/arch/x86/multiboot_header.asm diff --git a/kernel-rs/src/arch/i386/paging/mapper.rs b/kernel-rs/src/arch/x86/paging/mapper.rs similarity index 100% rename from kernel-rs/src/arch/i386/paging/mapper.rs rename to kernel-rs/src/arch/x86/paging/mapper.rs diff --git a/kernel-rs/src/arch/i386/paging/mod.rs b/kernel-rs/src/arch/x86/paging/mod.rs similarity index 100% rename from kernel-rs/src/arch/i386/paging/mod.rs rename to kernel-rs/src/arch/x86/paging/mod.rs diff --git a/kernel-rs/src/arch/i386/paging/table.rs b/kernel-rs/src/arch/x86/paging/table.rs similarity index 100% rename from kernel-rs/src/arch/i386/paging/table.rs rename to kernel-rs/src/arch/x86/paging/table.rs diff --git a/kernel-rs/src/arch/i386/paging/temporary_page.rs b/kernel-rs/src/arch/x86/paging/temporary_page.rs similarity index 100% rename from kernel-rs/src/arch/i386/paging/temporary_page.rs rename to kernel-rs/src/arch/x86/paging/temporary_page.rs diff --git a/kernel-rs/src/arch/i386/pti.rs b/kernel-rs/src/arch/x86/pti.rs similarity index 100% rename from kernel-rs/src/arch/i386/pti.rs rename to kernel-rs/src/arch/x86/pti.rs diff --git a/kernel-rs/src/arch/i386/start.asm b/kernel-rs/src/arch/x86/start.asm similarity index 100% rename from kernel-rs/src/arch/i386/start.asm rename to kernel-rs/src/arch/x86/start.asm From 983c5d6e276f7ecaa400b8c1d9cd08deef03e818 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 17 May 2018 17:07:15 +0200 Subject: [PATCH 138/151] qemu i386 hardcoded --- kernel-rs/mk/qemu.mk | 2 +- kernel-rs/src/arch/x86/linker.ld | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 44fce0d2..db0f170c 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -6,7 +6,7 @@ else PORTG := 4344 endif -QEMU := qemu-system-$(ARCH)\ +QEMU := qemu-system-i386\ -gdb tcp::$(PORTG)\ -S\ -enable-kvm\ diff --git a/kernel-rs/src/arch/x86/linker.ld b/kernel-rs/src/arch/x86/linker.ld index 4b3004c1..96419d19 100644 --- a/kernel-rs/src/arch/x86/linker.ld +++ b/kernel-rs/src/arch/x86/linker.ld @@ -34,6 +34,14 @@ SECTIONS { . = ALIGN(4K); } + /* NOT A GOOD IDEA TO GROUP debug_* SYMBOLS ! */ + /* .debug : */ + /* { */ + /* /1* KEEP(*(.debug_*)) *1/ */ + /* *(.debug_*) */ + /* . = ALIGN(4K); */ + /* } */ + .gdt : { *(.gdt) From e48c3fc680e1ffd328d1e610a58ee24077a26fc6 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 31 May 2018 18:32:52 +0200 Subject: [PATCH 139/151] Does it compile? no. Do I know what Im doing? maybe. Am I making progress? Yes. --- kernel-rs/.gdbinit | 2 - kernel-rs/mk/qemu.mk | 34 ++++++---- kernel-rs/src/arch/x86/boot.asm | 1 + kernel-rs/src/arch/x86/device/mod.rs | 2 +- kernel-rs/src/arch/x86/gdt.rs | 35 +++++++--- kernel-rs/src/arch/x86/interrupt/exception.rs | 5 +- kernel-rs/src/arch/x86/mod.rs | 45 ++++++++++--- kernel-rs/src/lib.rs | 14 ++-- kernel-rs/src/process/fifo.rs | 27 ++++++++ kernel-rs/src/process/mod.rs | 64 +++++++++++++++++++ kernel-rs/src/vga/mod.rs | 10 +-- kernel-rs/x86 | 2 +- 12 files changed, 192 insertions(+), 49 deletions(-) delete mode 100644 kernel-rs/.gdbinit create mode 100644 kernel-rs/src/process/fifo.rs create mode 100644 kernel-rs/src/process/mod.rs diff --git a/kernel-rs/.gdbinit b/kernel-rs/.gdbinit deleted file mode 100644 index 77d679cf..00000000 --- a/kernel-rs/.gdbinit +++ /dev/null @@ -1,2 +0,0 @@ -set arch i386 -file build/bluesnow-x86.bin diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index db0f170c..c99cce58 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -1,27 +1,35 @@ ifeq ($(shell whoami), jack) - PORT := 4242 - PORTG := 4244 + PORT_MONIT := 4242 + PORT_GDB := 4244 else - PORT := 4342 - PORTG := 4344 + PORT_MONIT := 4342 + PORT_GDB := 4344 endif QEMU := qemu-system-i386\ - -gdb tcp::$(PORTG)\ + -cdrom build/bluesnow-x86.iso\ -S\ -enable-kvm\ - -monitor telnet:127.0.0.1:$(PORT),server,nowait\ -curses\ - -cdrom build/bluesnow-x86.iso + -gdb tcp::$(PORT_GDB)\ + -monitor telnet:127.0.0.1:$(PORT_MONIT),server,nowait +qemu: + $(QEMU) -MONITOR := sleep 0.5;\ - telnet 127.0.0.1 $(PORT);\ +GDB := gdb -q\ + -symbols "$(kernel)" \ + -ex "target remote :$(PORT_GDB)"\ + -ex "set arch i386" +gdb: + $(GDB) + +MONITOR := telnet 127.0.0.1 $(PORT_MONIT);\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` -GDB := gdb -q\ - -ex \"target remote :$(PORTG)\" +monitor: + telnet 127.0.0.1 $(PORT_MONIT) -qemu: +#not using this anymore +william: @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)' - diff --git a/kernel-rs/src/arch/x86/boot.asm b/kernel-rs/src/arch/x86/boot.asm index 045dc35a..892fc549 100644 --- a/kernel-rs/src/arch/x86/boot.asm +++ b/kernel-rs/src/arch/x86/boot.asm @@ -4,6 +4,7 @@ extern x86_start section .text bits 32 start: + ; our stack, located in bss, linker.ld puts bss at the end of the binary mov esp, stack_top diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index 1a0a08a9..be0549aa 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -5,5 +5,5 @@ pub mod cpu; pub unsafe fn init(active_table: &mut ActivePageTable) { pic::init(); - local_apic::init(active_table); + // local_apic::init(active_table); } diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index cdfc540d..5510b81f 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -8,28 +8,40 @@ use x86::*; pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); +pub static mut TASK_TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); -pub static GDT_KERNEL_CODE: u16 = 1; -pub static GDT_KERNEL_DATA: u16 = 2; -pub static GDT_USER_CODE: u16 = 3; -pub static GDT_USER_DATA: u16 = 4; -// tss takes 2 spots; -pub static GDT_TSS: u16 = 5; +pub static GDT_KERNEL_CODE: SegmentSelector = SegmentSelector::new(1, Ring0); +pub static GDT_KERNEL_DATA: SegmentSelector = SegmentSelector::new(2, Ring0); +pub static GDT_USER_CODE: SegmentSelector = SegmentSelector::new(3, Ring3); +pub static GDT_USER_DATA: SegmentSelector = SegmentSelector::new(4, Ring3); +pub static GDT_TSS: SegmentSelector = SegmentSelector::new(5, Ring3); +pub static GDT_TASK_TSS: SegmentSelector = SegmentSelector::new(7, Ring3); pub unsafe fn init() { - TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; - asm!("mov %esp, $0" : "=r" (TSS.esp0)); - // the following *order* is important let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); + //I read that the tss should be twice as long //fuck knows why... + TSS.ss0 = GDT_KERNEL_CODE.0; + asm!("mov %esp, $0" : "=r" (TSS.esp0)); let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); GDT.add_entry(gdt::Descriptor(0)); + TASK_TSS.eip = self::test_task as *const () as u32; + let task_tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TASK_TSS)); + GDT.add_entry(gdt::Descriptor(0)); + + assert_eq!(kcode_selector, GDT_KERNEL_CODE); + assert_eq!(kdata_selector, GDT_KERNEL_DATA); + assert_eq!(ucode_selector, GDT_USER_CODE); + assert_eq!(udata_selector, GDT_USER_DATA); + assert_eq!(tss_selector, GDT_TSS); + assert_eq!(task_tss_selector, GDT_TASK_TSS); + // println!( // "tr({:#x}):\n {:#?}", // tss_selector.0, @@ -45,3 +57,8 @@ pub unsafe fn init() { load_tss(tss_selector); // unreachable!(); } + +pub fn test_task() { + println!("inside test task omg we did it !!!"); + flush!(); +} diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index d9b034d2..4f86fca8 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -56,17 +56,20 @@ exception_err!(invalid_tss, {}); exception_err!(segment_not_present, {}); exception_err!(stack_segment, {}); exception_err!(general_protection, { - panic!("general protection fault (#GP) can not recover"); + panic!("cannot recover from #GP"); }); pub extern "x86-interrupt" fn page_fault( stack_frame: &mut ExceptionStackFrame, code: PageFaultErrorCode, ) { + use x86::registers::control::Cr2; println!("Exception: page_fault"); println!("Error code: {:?}", code); + println!("PFLA: {:?}", Cr2::read()); println!("{:#?}", stack_frame); flush!(); + panic!("cannot recover from #PF") } exception!(x87_fpu, {}); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 4355d810..d22592ca 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -45,6 +45,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // set up heap ::allocator::init(&mut active_table); + // set up user stack + use x86::structures::paging::*; + // for page in ::USER_STACK_RANGE { + // active_table.map(page, PageTableFlags::WRITABLE); + // } + // set up pic & apic device::init(&mut active_table); @@ -52,7 +58,12 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { ::kmain(); } -pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { +pub unsafe fn switch(ip: u32) -> ! { + asm!("push $0; ret" :: "r"(ip) :: "volatile", "intel"); + unreachable!(); +} + +pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! { use x86::structures::gdt::{Descriptor, SegmentSelector}; use x86::instructions::segmentation::*; use x86::PrivilegeLevel::{Ring0, Ring3}; @@ -62,12 +73,26 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { // println!("sp: {:#x}", sp); // println!("ip: {:#x}", ip); - let udata_selector = SegmentSelector::new(gdt::GDT_USER_DATA, Ring0); - let ucode_selector = SegmentSelector::new(gdt::GDT_USER_CODE, Ring3); - load_ds(udata_selector); - load_es(udata_selector); - load_fs(udata_selector); - load_gs(udata_selector); + // load_ds(udata_selector); + // asm!("mov $0, %ds" :: "r"(gdt::GDT_USER_DATA << 3 | 3)); + + // loop {} + + // load_es(udata_selector); + // load_fs(udata_selector); + // load_gs(udata_selector); + + use x86::registers::flags; + flags::set_flags(flags::Flags::NT); + + asm!("mov %esp, $0" : "=r" (sp)); + + println!("{:#x}", gdt::GDT_KERNEL_DATA.0); + println!("{:#x}", sp); + println!("{:#x}", 1 << 9); + println!("{:#x}", gdt::GDT_KERNEL_CODE.0); + println!("{:#x}", ip); + flush!(); asm!(" push $0; \ @@ -76,15 +101,17 @@ pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { push $3; \ push $4" : //no output - : "r"(udata_selector), + : "r"(gdt::GDT_USER_DATA.0), "r"(sp), "r"(1 << 9) // interrupt enable flag - "r"(ucode_selector), + "r"(gdt::GDT_USER_CODE.0), "r"(ip) : //no clobbers : "intel", "volatile" ); + // loop {} + asm!("iret"); unreachable!(); diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index b9686b90..5d4bbfee 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -45,6 +45,8 @@ pub mod memory; /// arch specific entry points pub mod arch; pub use arch::x86::consts::*; +/// process scheduling +pub mod process; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded @@ -69,24 +71,20 @@ pub fn kmain() -> ! { // println!("flags: {:?}", x86::registers::flags::flags()); // flush!(); - let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); + // let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); // let sp: u32; // unsafe { // asm!("mov %ebp, $0" : "=r" (sp)); // } - let ip = self::init as *const () as u32; // unsafe { // arch::x86::usermode(ip, sp, 0); // } // unreachable!() - loop {} -} -pub fn init() { - println!("inside init function!!!!!"); - flush!(); - loop {} + process::ploop(); + + unreachable!(); } #[lang = "eh_personality"] diff --git a/kernel-rs/src/process/fifo.rs b/kernel-rs/src/process/fifo.rs new file mode 100644 index 00000000..c0889fb3 --- /dev/null +++ b/kernel-rs/src/process/fifo.rs @@ -0,0 +1,27 @@ +use spin::Mutex; +use alloc::VecDeque; + +use super::*; + +pub struct Fifo { + list: VecDeque, +} + +impl Fifo { + pub fn new() -> Fifo { + Fifo { + list: VecDeque::new(), + } + } +} + +impl Scheduler for Fifo { + fn add_process(&mut self, ip: u32) { + let p = Process::new(ip); + self.list.push_back(p); + } + + fn next(&mut self) -> Option { + self.list.pop_front() + } +} diff --git a/kernel-rs/src/process/mod.rs b/kernel-rs/src/process/mod.rs new file mode 100644 index 00000000..5f7ffd14 --- /dev/null +++ b/kernel-rs/src/process/mod.rs @@ -0,0 +1,64 @@ +mod fifo; + +lazy_static! { + static ref SCHEDULER: fifo::Fifo = fifo::Fifo::new(); +} + +// lazy_static! { +// static ref SCHEDULER: self::Scheduler = self::Scheduler { +// list: Mutex::new(VecDeque::new()) +// }; +// } + +#[derive(Debug)] +pub struct Process { + // this is eip right now + // this will be an elf blob later + ip: u32, +} + +impl Process { + pub fn new(ip: u32) -> Process { + Process { ip } + } + + pub unsafe fn execute(&mut self) { + asm!("push $0; ret" :: "r"(self.ip) :: "volatile", "intel"); + } +} + +pub trait Scheduler { + fn add_process(&mut self, ip: u32); + fn next(&mut self) -> Option; +} + +pub fn ploop() { + let ip = self::init as *const () as u32; + unsafe { + SCHEDULER.add_process(ip); + } + loop { + if let Some(mut p) = unsafe { SCHEDULER.next() } { + print!("{:?}", p); + unsafe { + p.execute(); + } + } + } +} + +pub fn fork() -> i32 { + let ip; + unsafe { + asm!("" : "={eip}"(ip) ::: "volatile"); + SCHEDULER.add_process(ip); + } + 0 +} + +pub fn init() -> ! { + let i = self::fork(); + println!("inside fork_print() function!!!!!, fork={}", i); + flush!(); + loop {} +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 27be530c..8a3cfbef 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -32,9 +32,9 @@ macro_rules! flush { macro_rules! set_color { () => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} ); + $crate::vga::ColorCode::new($crate::vga::Color::Black, $crate::vga::Color::Yellow)} ); ($fg:ident) => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} ); + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Yellow)} ); ($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code = $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} ); } @@ -63,7 +63,7 @@ impl Writer { pub const fn new() -> Writer { Writer { buffer_pos: 0, - color_code: ColorCode::new(Color::White, Color::Black), + color_code: ColorCode::new(Color::Black, Color::Yellow), buffer: [0; BUFFER_ROWS * BUFFER_COLS], command: [b'\0'; 10], command_len: 0, @@ -100,7 +100,7 @@ impl Writer { b'\n' => { self.write_byte(b'\n'); if let Err(msg) = console::exec(&self) { - set_color!(Red, Black); + set_color!(Red, Yellow); println!("Something wrong: {}", msg); set_color!(); } @@ -180,7 +180,7 @@ impl Writer { for col in (0..BUFFER_COLS / 2).map(|x| x * 2) { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' '; self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = - ColorCode::new(Color::White, Color::Black).0; + ColorCode::new(Color::Black, Color::Yellow).0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 3a6ff64c..d81e8a36 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 3a6ff64c5fb9a4bdeb8b6b4c83328278c551dbad +Subproject commit d81e8a3690f3cd2dc64f0d6ebabceeb8e5583c97 From 15a7f53bc2e64d06da77bb77bf155b097129bf2f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 5 Jun 2018 18:05:18 +0200 Subject: [PATCH 140/151] no more warnings! --- kernel-rs/src/acpi/dsdt.rs | 2 +- kernel-rs/src/acpi/fadt.rs | 2 +- kernel-rs/src/arch/x86/device/local_apic.rs | 21 ----- kernel-rs/src/arch/x86/device/mod.rs | 9 +- kernel-rs/src/arch/x86/device/pic.rs | 99 --------------------- kernel-rs/src/arch/x86/gdt.rs | 4 +- kernel-rs/src/arch/x86/interrupt/irq.rs | 6 +- kernel-rs/src/arch/x86/mod.rs | 16 ++-- kernel-rs/src/console.rs | 7 +- kernel-rs/src/io/mod.rs | 43 --------- kernel-rs/src/io/pio.rs | 89 ------------------ kernel-rs/src/keyboard.rs | 5 +- kernel-rs/src/lib.rs | 10 +-- kernel-rs/src/memory/mod.rs | 6 +- kernel-rs/src/process/fifo.rs | 6 +- kernel-rs/src/process/mod.rs | 49 ++++++---- kernel-rs/src/vga/cursor.rs | 2 +- kernel-rs/src/vga/mod.rs | 24 ++++- kernel-rs/x86 | 2 +- 19 files changed, 88 insertions(+), 314 deletions(-) delete mode 100644 kernel-rs/src/arch/x86/device/local_apic.rs delete mode 100644 kernel-rs/src/arch/x86/device/pic.rs delete mode 100644 kernel-rs/src/io/mod.rs delete mode 100644 kernel-rs/src/io/pio.rs diff --git a/kernel-rs/src/acpi/dsdt.rs b/kernel-rs/src/acpi/dsdt.rs index d0612519..b93d407e 100644 --- a/kernel-rs/src/acpi/dsdt.rs +++ b/kernel-rs/src/acpi/dsdt.rs @@ -1,6 +1,6 @@ use super::{check_signature, ACPISDTHeader}; use core::mem; -use io::{Io, Pio}; +use x86::devices::io::{Io, Pio}; static mut DSDT: DSDT = DSDT { valid: false, diff --git a/kernel-rs/src/acpi/fadt.rs b/kernel-rs/src/acpi/fadt.rs index 22135d29..95f7c244 100644 --- a/kernel-rs/src/acpi/fadt.rs +++ b/kernel-rs/src/acpi/fadt.rs @@ -1,5 +1,5 @@ use super::{ACPISDTHeader, ACPISDTIter}; -use io::{Io, Pio}; +use x86::devices::io::{Io, Pio}; #[repr(C)] #[derive(Debug, Clone)] diff --git a/kernel-rs/src/arch/x86/device/local_apic.rs b/kernel-rs/src/arch/x86/device/local_apic.rs deleted file mode 100644 index 058be3fd..00000000 --- a/kernel-rs/src/arch/x86/device/local_apic.rs +++ /dev/null @@ -1,21 +0,0 @@ -use arch::x86::paging::ActivePageTable; - -pub static mut LOCAL_APIC: LocalApic = LocalApic { - address: 0, - x2: false, -}; - -pub unsafe fn init(active_table: &mut ActivePageTable) { - LOCAL_APIC.init(active_table); -} - -pub struct LocalApic { - pub address: usize, - pub x2: bool, -} - -impl LocalApic { - unsafe fn init(&mut self, _active_table: &mut ActivePageTable) { - // ??? - } -} diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs index be0549aa..70b5b2e6 100644 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ b/kernel-rs/src/arch/x86/device/mod.rs @@ -1,9 +1,8 @@ -use arch::x86::paging::ActivePageTable; -pub mod pic; -pub mod local_apic; +use x86::devices::pit; +use x86::devices::pic; pub mod cpu; -pub unsafe fn init(active_table: &mut ActivePageTable) { +pub unsafe fn init() { pic::init(); - // local_apic::init(active_table); + pit::init(); } diff --git a/kernel-rs/src/arch/x86/device/pic.rs b/kernel-rs/src/arch/x86/device/pic.rs deleted file mode 100644 index 39a4f2f7..00000000 --- a/kernel-rs/src/arch/x86/device/pic.rs +++ /dev/null @@ -1,99 +0,0 @@ -use io::{Io, Pio}; - -pub static mut MASTER: Pic = Pic::new(0x20); -pub static mut SLAVE: Pic = Pic::new(0xA0); -pub static mut WAIT_PORT: Pio = Pio::new(0x80); - -pub unsafe fn init() { - let wait = || WAIT_PORT.write(0); - let master_mask = MASTER.data.read(); - let slave_mask = SLAVE.data.read(); - - // Start initialization - MASTER.cmd.write(0x11); - wait(); - SLAVE.cmd.write(0x11); - wait(); - - // Set offsets - MASTER.data.write(0x20); - wait(); - SLAVE.data.write(0x28); - wait(); - - // Set up cascade - MASTER.data.write(4); - wait(); - SLAVE.data.write(2); - wait(); - - // Set up interrupt mode (1 is 8086/88 mode, 2 is auto EOI) - MASTER.data.write(1); - wait(); - SLAVE.data.write(1); - wait(); - - // Unmask interrupts - MASTER.data.write(0); - wait(); - SLAVE.data.write(0); - wait(); - - // Ack remaining interrupts - MASTER.ack(); - wait(); - SLAVE.ack(); - wait(); - - MASTER.data.write(master_mask); - wait(); - SLAVE.data.write(slave_mask); - wait(); - - // disable all irqs - MASTER.data.write(!0); - wait(); - SLAVE.data.write(!0); - wait(); - - // keyboard active - MASTER.mask_clear(1); - wait(); - - // asm!("sti"); - ::x86::instructions::interrupts::enable(); -} - -pub struct Pic { - cmd: Pio, - data: Pio, -} - -impl Pic { - pub const fn new(port: u16) -> Pic { - Pic { - cmd: Pio::new(port), - data: Pio::new(port + 1), - } - } - - pub fn ack(&mut self) { - self.cmd.write(0x20); - } - - pub fn mask_set(&mut self, irq: u8) { - assert!(irq < 8); - - let mut mask = self.data.read(); - mask |= 1 << irq; - self.data.write(mask); - } - - pub fn mask_clear(&mut self, irq: u8) { - assert!(irq < 8); - - let mut mask = self.data.read(); - mask &= !(1 << irq); - self.data.write(mask); - } -} diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 5510b81f..1ed14506 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -1,10 +1,9 @@ use x86::structures::gdt; use x86::structures::tss; -use x86::structures::gdt::{Descriptor, SegmentSelector}; +use x86::structures::gdt::SegmentSelector; use x86::instructions::segmentation::*; use x86::instructions::tables::load_tss; use x86::PrivilegeLevel::{Ring0, Ring3}; -use x86::*; pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); @@ -42,6 +41,7 @@ pub unsafe fn init() { assert_eq!(tss_selector, GDT_TSS); assert_eq!(task_tss_selector, GDT_TASK_TSS); + // use x86::structures::gdt::Descriptor; // println!( // "tr({:#x}):\n {:#?}", // tss_selector.0, diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 04a64b83..2e5f553a 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -1,5 +1,5 @@ use x86::structures::idt::*; -use arch::x86::device::pic; +use x86::devices::pic; #[macro_export] macro_rules! interrupt { @@ -44,7 +44,9 @@ pub unsafe fn acknowledge(irq: usize) { } } -interrupt!(0, pit, {}); +interrupt!(0, pit, { + fprintln!("got pit (irq0)"); +}); interrupt!(1, keyboard, { ::keyboard::kbd_callback(); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index d22592ca..496103c5 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -46,13 +46,13 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { ::allocator::init(&mut active_table); // set up user stack - use x86::structures::paging::*; + // use x86::structures::paging::*; // for page in ::USER_STACK_RANGE { // active_table.map(page, PageTableFlags::WRITABLE); // } - // set up pic & apic - device::init(&mut active_table); + // set up pic, pit + device::init(); // primary CPU entry point ::kmain(); @@ -63,10 +63,10 @@ pub unsafe fn switch(ip: u32) -> ! { unreachable!(); } -pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! { - use x86::structures::gdt::{Descriptor, SegmentSelector}; - use x86::instructions::segmentation::*; - use x86::PrivilegeLevel::{Ring0, Ring3}; +pub unsafe fn usermode(ip: u32, sp: u32) -> ! { + // use x86::structures::gdt::{Descriptor, SegmentSelector}; + // use x86::instructions::segmentation::*; + // use x86::PrivilegeLevel::{Ring0, Ring3}; x86::instructions::interrupts::disable(); @@ -85,7 +85,7 @@ pub unsafe fn usermode(ip: u32, mut sp: u32, arg: u32) -> ! { use x86::registers::flags; flags::set_flags(flags::Flags::NT); - asm!("mov %esp, $0" : "=r" (sp)); + // asm!("mov %esp, $0" : "=r" (sp)); println!("{:#x}", gdt::GDT_KERNEL_DATA.0); println!("{:#x}", sp); diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 5cbf1196..377257e0 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -3,7 +3,6 @@ extern crate core; use acpi; use keyboard::PS2; -use io; use core::char; use vga::*; @@ -57,6 +56,7 @@ fn help() -> Result<(), &'static str> { Ok(()) } +use x86::instructions::halt; /// Reboot the kernel /// /// If reboot failed, will loop on a halt cmd @@ -70,7 +70,7 @@ fn reboot() -> ! { unsafe { PS2.ps2_8042_reset() }; // TODO unsafe println!("Unable to perform 8042 reboot. Kernel will be halted"); flush!(); - io::halt(); + halt(); } /// Shutdown the kernel @@ -84,7 +84,7 @@ fn shutdown() -> ! { _ => println!("Unable to perform ACPI shutdown. Kernel will be halted"), } flush!(); - io::halt(); + halt(); } fn hexdump(start: usize, end: usize) { @@ -225,6 +225,7 @@ pub fn int3() -> Result<(), &'static str> { Ok(()) } +#[allow(unconditional_recursion)] pub fn overflow() -> Result<(), &'static str> { fn stack_overflow() { stack_overflow(); diff --git a/kernel-rs/src/io/mod.rs b/kernel-rs/src/io/mod.rs deleted file mode 100644 index 2bfb053a..00000000 --- a/kernel-rs/src/io/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -mod pio; - -pub use self::pio::*; - -use core::ops::{BitAnd, BitOr, Not}; - -pub trait Io { - type Value: Copy - + PartialEq - + BitAnd - + BitOr - + Not; - - fn read(&self) -> Self::Value; - fn write(&mut self, value: Self::Value); - - #[inline(always)] - fn readf(&self, flags: Self::Value) -> bool { - (self.read() & flags) as Self::Value == flags - } - - #[inline(always)] - fn writef(&mut self, flags: Self::Value, value: bool) { - let tmp: Self::Value = match value { - true => self.read() | flags, - false => self.read() & !flags, - }; - self.write(tmp); - } -} - -#[inline(always)] -pub fn cli() { - unsafe { asm!("cli" : : : : "volatile") }; -} - -#[inline(always)] -pub fn halt() -> ! { - cli(); - loop { - unsafe { asm!("hlt" : : : : "volatile") }; - } -} diff --git a/kernel-rs/src/io/pio.rs b/kernel-rs/src/io/pio.rs deleted file mode 100644 index 2582066d..00000000 --- a/kernel-rs/src/io/pio.rs +++ /dev/null @@ -1,89 +0,0 @@ -use core::marker::PhantomData; - -use super::*; - -/// Generic PIO -#[derive(Copy, Clone)] -pub struct Pio { - port: u16, - value: PhantomData, -} - -impl Pio { - /// Create a PIO from a given port - pub const fn new(port: u16) -> Self { - Pio:: { - port: port, - value: PhantomData, - } - } -} - -/// Read/Write for byte PIO -impl Io for Pio { - type Value = u8; - - /// Read - #[inline(always)] - fn read(&self) -> u8 { - let value: u8; - unsafe { - asm!("in $0, $1" : "={al}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u8) { - unsafe { - asm!("out $1, $0" : : "{al}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} - -/// Read/Write for word PIO -impl Io for Pio { - type Value = u16; - - /// Read - #[inline(always)] - fn read(&self) -> u16 { - let value: u16; - unsafe { - asm!("in $0, $1" : "={ax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u16) { - unsafe { - asm!("out $1, $0" : : "{ax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} - -/// Read/Write for doubleword PIO -impl Io for Pio { - type Value = u32; - - /// Read - #[inline(always)] - fn read(&self) -> u32 { - let value: u32; - unsafe { - asm!("in $0, $1" : "={eax}"(value) : "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - value - } - - /// Write - #[inline(always)] - fn write(&mut self, value: u32) { - unsafe { - asm!("out $1, $0" : : "{eax}"(value), "{dx}"(self.port) : "memory" : "intel", "volatile"); - } - } -} diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index d4b77828..67458433 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,7 +1,7 @@ extern crate core; use vga; -use io::{self, Io, Pio}; +use x86::devices::io::{Io, Pio}; const MAX_KEYS: usize = 59; const KEYMAP_US: [[u8; 2]; MAX_KEYS] = [ @@ -90,7 +90,8 @@ impl Ps2 { } pub fn ps2_8042_reset(&mut self) { - io::cli(); + use x86::instructions::interrupts; + interrupts::disable(); self.clear_buffer(); self.status.write(0xFE); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 5d4bbfee..39d31462 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -34,8 +34,6 @@ pub mod vga; pub mod keyboard; /// simplisitc kernel commands pub mod console; -/// rust wrappers around cpu I/O instructions. -pub mod io; /// ACPI self contained module pub mod acpi; /// Heap allocators @@ -57,11 +55,6 @@ pub fn kmain() -> ! { // vga is *not* cpu specific vga::init(); - // fn stack_overflow() { - // stack_overflow(); - // } - // stack_overflow(); - // unsafe { // *(0xdead as *mut u32) = 42; // }; @@ -82,8 +75,7 @@ pub fn kmain() -> ! { // } // unreachable!() - process::ploop(); - + process::schedule(); unreachable!(); } diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index d747acd5..a2af86a5 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,15 +1,13 @@ mod bump; mod recycle; -mod stack_allocator; +// mod stack_allocator; use multiboot2; use x86::structures::paging::*; -use arch::x86::paging::ActivePageTable; -use x86::*; use self::bump::BumpFrameAllocator; use self::recycle::RecycleAllocator; -use self::stack_allocator::{Stack, StackAllocator}; +// use self::stack_allocator::{Stack, StackAllocator}; pub trait FrameAllocator { fn allocate_frames(&mut self, size: usize) -> Option; diff --git a/kernel-rs/src/process/fifo.rs b/kernel-rs/src/process/fifo.rs index c0889fb3..c5be7b85 100644 --- a/kernel-rs/src/process/fifo.rs +++ b/kernel-rs/src/process/fifo.rs @@ -1,24 +1,26 @@ -use spin::Mutex; use alloc::VecDeque; use super::*; pub struct Fifo { list: VecDeque, + next_pid: i32, } impl Fifo { pub fn new() -> Fifo { Fifo { list: VecDeque::new(), + next_pid: 1, } } } impl Scheduler for Fifo { fn add_process(&mut self, ip: u32) { - let p = Process::new(ip); + let p = Process::new(self.next_pid, ip); self.list.push_back(p); + self.next_pid += 1; } fn next(&mut self) -> Option { diff --git a/kernel-rs/src/process/mod.rs b/kernel-rs/src/process/mod.rs index 5f7ffd14..e381568d 100644 --- a/kernel-rs/src/process/mod.rs +++ b/kernel-rs/src/process/mod.rs @@ -1,7 +1,13 @@ mod fifo; +use spin::Mutex; lazy_static! { - static ref SCHEDULER: fifo::Fifo = fifo::Fifo::new(); + pub static ref SCHEDULER: Mutex = Mutex::new({ + let init_process: u32 = self::init as *const () as u32; + let mut f = fifo::Fifo::new(); + f.add_process(init_process); + f + }); } // lazy_static! { @@ -14,16 +20,19 @@ lazy_static! { pub struct Process { // this is eip right now // this will be an elf blob later + pid: i32, ip: u32, } impl Process { - pub fn new(ip: u32) -> Process { - Process { ip } + pub fn new(pid: i32, ip: u32) -> Process { + Process { pid, ip } } pub unsafe fn execute(&mut self) { - asm!("push $0; ret" :: "r"(self.ip) :: "volatile", "intel"); + let scheduler_loop = schedule as *const () as u32; + asm!("push $0; push $1; ret" :: "r"(scheduler_loop) ,"r"(self.ip) :: "volatile", "intel"); + unreachable!(); } } @@ -32,33 +41,35 @@ pub trait Scheduler { fn next(&mut self) -> Option; } -pub fn ploop() { - let ip = self::init as *const () as u32; - unsafe { - SCHEDULER.add_process(ip); - } +pub fn schedule() { loop { - if let Some(mut p) = unsafe { SCHEDULER.next() } { - print!("{:?}", p); + if let Some(mut p) = SCHEDULER.lock().next() { + println!("executing {:#x}", p.ip); + flush!(); unsafe { + SCHEDULER.force_unlock(); p.execute(); } + unreachable!(); } } } pub fn fork() -> i32 { let ip; - unsafe { - asm!("" : "={eip}"(ip) ::: "volatile"); - SCHEDULER.add_process(ip); - } + unsafe { asm!("pop $0" : "=r"(ip) ::: "intel") }; + println!("ip = {:#x}", ip); + flush!(); + unsafe { asm!("push $0" :: "r"(ip) :: "intel") }; + SCHEDULER.lock().add_process(ip); 0 } -pub fn init() -> ! { - let i = self::fork(); - println!("inside fork_print() function!!!!!, fork={}", i); +pub fn init() { + println!("init first line"); + flush!(); + // let i = self::fork(); + // println!("fork={}", i); + println!("init last line"); flush!(); - loop {} } diff --git a/kernel-rs/src/vga/cursor.rs b/kernel-rs/src/vga/cursor.rs index 850c45cc..575e467f 100644 --- a/kernel-rs/src/vga/cursor.rs +++ b/kernel-rs/src/vga/cursor.rs @@ -1,7 +1,7 @@ // https://wiki.osdev.org/Text_Mode_Cursor // Protected mode cursor abstraction -use io::{Io, Pio}; +use x86::devices::io::{Io, Pio}; pub static mut CURSOR: Cursor = Cursor::new(0x3D4); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 8a3cfbef..b4a54fc3 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused_macros)] + pub mod color; pub mod cursor; @@ -15,19 +17,37 @@ struct ScreenChar { color_code: ColorCode, } +// print wrapper macro around vga macro_rules! print { ($($arg:tt)*) => ({ $crate::vga::print(format_args!($($arg)*)); }); } +// flushed print +macro_rules! fprint { + ($($arg:tt)*) => ({ + print!($($arg)*); + flush!(); + }); +} + +// print with a line feed macro_rules! println { ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } +// flushed println +macro_rules! fprintln { + ($($arg:tt)*) => ({ + println!($($arg)*); + flush!(); + }); +} + macro_rules! flush { - () => (unsafe { $crate::vga::VGA.flush() }); + () => (#[allow(unused_unsafe)] unsafe { $crate::vga::VGA.flush() }); } macro_rules! set_color { @@ -125,7 +145,7 @@ impl Writer { self.buffer_pos -= 2; let i = self.buffer_pos; self.buffer[i] = b' '; - self.buffer[i + 1] = 0; + self.buffer[i + 1] = self.color_code.0; self.flush(); // flush!(); } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index d81e8a36..0da7a6b2 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit d81e8a3690f3cd2dc64f0d6ebabceeb8e5583c97 +Subproject commit 0da7a6b2bfafec479a990bb0dac8f4bd58b9fd79 From b75d97b11e1dcf0845dbd7c06c52f0e1ab87195f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 6 Jun 2018 16:59:16 +0200 Subject: [PATCH 141/151] timer done --- kernel-rs/src/arch/x86/device/mod.rs | 8 -- .../src/arch/x86/{device => devices}/cpu.rs | 0 kernel-rs/src/arch/x86/devices/mod.rs | 15 ++++ kernel-rs/src/arch/x86/idt.rs | 6 -- kernel-rs/src/arch/x86/interrupt/irq.rs | 17 ++++- kernel-rs/src/arch/x86/mod.rs | 4 +- kernel-rs/src/arch/x86/pti.rs | 73 ------------------- kernel-rs/src/console.rs | 14 +++- kernel-rs/src/lib.rs | 26 +------ kernel-rs/src/process/mod.rs | 6 +- kernel-rs/src/time.rs | 17 +++++ kernel-rs/x86 | 2 +- 12 files changed, 69 insertions(+), 119 deletions(-) delete mode 100644 kernel-rs/src/arch/x86/device/mod.rs rename kernel-rs/src/arch/x86/{device => devices}/cpu.rs (100%) create mode 100644 kernel-rs/src/arch/x86/devices/mod.rs delete mode 100644 kernel-rs/src/arch/x86/pti.rs create mode 100644 kernel-rs/src/time.rs diff --git a/kernel-rs/src/arch/x86/device/mod.rs b/kernel-rs/src/arch/x86/device/mod.rs deleted file mode 100644 index 70b5b2e6..00000000 --- a/kernel-rs/src/arch/x86/device/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -use x86::devices::pit; -use x86::devices::pic; -pub mod cpu; - -pub unsafe fn init() { - pic::init(); - pit::init(); -} diff --git a/kernel-rs/src/arch/x86/device/cpu.rs b/kernel-rs/src/arch/x86/devices/cpu.rs similarity index 100% rename from kernel-rs/src/arch/x86/device/cpu.rs rename to kernel-rs/src/arch/x86/devices/cpu.rs diff --git a/kernel-rs/src/arch/x86/devices/mod.rs b/kernel-rs/src/arch/x86/devices/mod.rs new file mode 100644 index 00000000..212805fd --- /dev/null +++ b/kernel-rs/src/arch/x86/devices/mod.rs @@ -0,0 +1,15 @@ +use x86::devices::pit; +use x86::devices::pic; +pub mod cpu; +use x86::instructions::interrupts; + +static CHAN0_DIVISOR: u16 = 2685; + +pub unsafe fn init() { + pic::init_cascade(); + pic::disable_irqs(); + pic::enable_irq(0); + pic::enable_irq(1); + pit::CHAN0.set_divisor(CHAN0_DIVISOR); + interrupts::enable(); +} diff --git a/kernel-rs/src/arch/x86/idt.rs b/kernel-rs/src/arch/x86/idt.rs index 4a511522..ec5ca5e4 100644 --- a/kernel-rs/src/arch/x86/idt.rs +++ b/kernel-rs/src/arch/x86/idt.rs @@ -47,12 +47,6 @@ lazy_static! { }; } -// pub fn init(memory_controller: &mut ::memory::MemoryController) { pub fn init() { - // let double_fault_stack = memory_controller.alloc_stack(1) - // .expect("could not allocate double fault stack"); - // println!("DF stack: {:#?}", double_fault_stack); - // flush!(); - IDT.load(); } diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 2e5f553a..81817b7b 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -1,5 +1,6 @@ use x86::structures::idt::*; use x86::devices::pic; +use time; #[macro_export] macro_rules! interrupt { @@ -45,7 +46,21 @@ pub unsafe fn acknowledge(irq: usize) { } interrupt!(0, pit, { - fprintln!("got pit (irq0)"); + /// t = 1/f + /// pit freq = 1.193182 MHz + /// chan0 divisor = 2685 + /// PIT_RATE in us + const PIT_RATE: u32 = 2_251; + { + let mut offset = time::OFFSET.lock(); + let sum = offset.1 + PIT_RATE; + offset.1 = sum % 1_000_000; + offset.0 += sum / 1_000_000; + if sum > 1_000_000 { + fprintln!("uptime: {}s", offset.0); + } + } + unsafe { pic::MASTER.ack() }; }); interrupt!(1, keyboard, { diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 496103c5..59b7f073 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -3,7 +3,7 @@ extern crate x86; #[macro_use] pub mod paging; pub mod interrupt; -pub mod device; +pub mod devices; pub mod consts; pub mod gdt; @@ -52,7 +52,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // } // set up pic, pit - device::init(); + devices::init(); // primary CPU entry point ::kmain(); diff --git a/kernel-rs/src/arch/x86/pti.rs b/kernel-rs/src/arch/x86/pti.rs deleted file mode 100644 index 91f488c1..00000000 --- a/kernel-rs/src/arch/x86/pti.rs +++ /dev/null @@ -1,73 +0,0 @@ -use core::ptr; - -use super::paging::ActivePageTable; -// use super::paging::entry::EntryFlags; - -#[thread_local] -pub static mut PTI_CPU_STACK: [u8; 256] = [0; 256]; - -#[thread_local] -pub static mut PTI_CONTEXT_STACK: usize = 0; - -#[inline(always)] -unsafe fn switch_stack(old: usize, new: usize) { - let old_esp: usize; - - // save the old esp - asm!("" : "={esp}"(old_esp) : : : "intel", "volatile"); - - let offset_esp = old - old_esp; - - let new_esp = new - offset_esp; - - ptr::copy_nonoverlapping(old_esp as *const u8, new_esp as *mut u8, offset_esp); - - // switch the esp with the new one - asm!("" : : "{esp}"(new_esp) : : "intel", "volatile"); -} - -#[inline(always)] -pub unsafe fn map() { - // { - // let mut active_table = unsafe { ActivePageTable::new() }; - // - // // Map kernel heap - // let address = active_table.p4()[::KERNEL_HEAP_PML4].address(); - // let frame = Frame::containing_address(address); - // let mut flags = active_table.p4()[::KERNEL_HEAP_PML4].flags(); - // flags.remove(EntryFlags::PRESENT); - // active_table.p4_mut()[::KERNEL_HEAP_PML4].set(frame, flags); - // - // // Reload page tables - // active_table.flush_all(); - // } - - // Switch to per-context stack - switch_stack( - PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), - PTI_CONTEXT_STACK, - ); -} - -#[inline(always)] -pub unsafe fn unmap() { - // Switch to per-CPU stack - switch_stack( - PTI_CONTEXT_STACK, - PTI_CPU_STACK.as_ptr() as usize + PTI_CPU_STACK.len(), - ); - - // { - // let mut active_table = unsafe { ActivePageTable::new() }; - // - // // Unmap kernel heap - // let address = active_table.p4()[::KERNEL_HEAP_PML4].address(); - // let frame = Frame::containing_address(address); - // let mut flags = active_table.p4()[::KERNEL_HEAP_PML4].flags(); - // flags.insert(EntryFlags::PRESENT); - // active_table.p4_mut()[::KERNEL_HEAP_PML4].set(frame, flags); - // - // // Reload page tables - // active_table.flush_all(); - // } -} diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 377257e0..e7e0d974 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -26,6 +26,7 @@ fn dispatch(command: &str) -> Result<(), &'static str> { "cpu" => self::cpu(), "int3" => self::int3(), "overflow" => self::overflow(), + "page_fault" => self::page_fault(), _ => Err("Command unknown. (h|help for help)"), } @@ -46,12 +47,14 @@ fn help() -> Result<(), &'static str> { println!("help | h => Print this help"); // println!("memory => Print memory areas"); // println!("multiboot => Print multiboot information"); - println!("reboot => Reboot"); // println!("sections => Print elf sections"); + println!("reboot => Reboot"); println!("shutdown | halt | q => Kill a kitten, then shutdown"); println!("stack => Print kernel stack in a fancy way"); println!("regs => Print controle register"); println!("cpu => Print cpu information"); + println!("overflow => triggers a stack overflow"); + println!("page_fault => triggers a page fault on 0xdead"); flush!(); Ok(()) } @@ -213,7 +216,7 @@ pub fn regs() -> Result<(), &'static str> { /// Dump cpu info, should add power management info pub fn cpu() -> Result<(), &'static str> { - use arch::x86::device::cpu; + use arch::x86::devices::cpu; cpu::cpu_info().expect("cpu info not available"); flush!(); Ok(()) @@ -233,3 +236,10 @@ pub fn overflow() -> Result<(), &'static str> { stack_overflow(); Ok(()) } + +pub fn page_fault() -> Result<(), &'static str> { + unsafe { + *(0xdead as *mut u32) = 42; + }; + Ok(()) +} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 39d31462..19039bac 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -45,36 +45,18 @@ pub mod arch; pub use arch::x86::consts::*; /// process scheduling pub mod process; +/// uptime counting +pub mod time; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded pub fn kmain() -> ! { - // heap avalaible for tracking freed frames + // memory init after heap is available memory::init_noncore(); - // vga is *not* cpu specific + // vga is *not* cpu specific I think vga::init(); - // unsafe { - // *(0xdead as *mut u32) = 42; - // }; - - // x86::instructions::interrupts::int3(); - - // println!("flags: {:?}", x86::registers::flags::flags()); - // flush!(); - - // let sp = (::USER_STACK_OFFSET + ::USER_STACK_SIZE).as_u32(); - // let sp: u32; - // unsafe { - // asm!("mov %ebp, $0" : "=r" (sp)); - // } - - // unsafe { - // arch::x86::usermode(ip, sp, 0); - // } - // unreachable!() - process::schedule(); unreachable!(); } diff --git a/kernel-rs/src/process/mod.rs b/kernel-rs/src/process/mod.rs index e381568d..af270b35 100644 --- a/kernel-rs/src/process/mod.rs +++ b/kernel-rs/src/process/mod.rs @@ -66,10 +66,8 @@ pub fn fork() -> i32 { } pub fn init() { - println!("init first line"); - flush!(); + fprintln!("init first line"); // let i = self::fork(); // println!("fork={}", i); - println!("init last line"); - flush!(); + fprintln!("init last line"); } diff --git a/kernel-rs/src/time.rs b/kernel-rs/src/time.rs new file mode 100644 index 00000000..70d1819c --- /dev/null +++ b/kernel-rs/src/time.rs @@ -0,0 +1,17 @@ +use spin::Mutex; + +/// Kernel start time, measured in (seconds, microseconds) since Unix epoch +pub static START: Mutex<(u32, u32)> = Mutex::new((0, 0)); +/// Kernel up time, measured in (seconds, microseconds) since `START_TIME` +pub static OFFSET: Mutex<(u32, u32)> = Mutex::new((0, 0)); + +pub fn monotonic() -> (u32, u32) { + *OFFSET.lock() +} + +pub fn realtime() -> (u32, u32) { + let offset = monotonic(); + let start = *START.lock(); + let sum = start.1 + offset.1; + (start.0 + offset.0 + sum / 1_000_000, sum % 1_000_000) +} diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 0da7a6b2..229c4acb 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 0da7a6b2bfafec479a990bb0dac8f4bd58b9fd79 +Subproject commit 229c4acbbe81bf4837bd05714b99614ada9dd2b3 From ba108d9e3e92188cc07215cb45ff75a86063f65d Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 6 Jun 2018 18:16:50 +0200 Subject: [PATCH 142/151] scheduling --- kernel-rs/src/arch/x86/devices/cpu.rs | 6 +-- kernel-rs/src/arch/x86/interrupt/irq.rs | 2 +- kernel-rs/src/lib.rs | 6 +-- kernel-rs/src/{process => scheduling}/fifo.rs | 9 ++++- kernel-rs/src/{process => scheduling}/mod.rs | 39 +++++-------------- kernel-rs/src/scheduling/process.rs | 33 ++++++++++++++++ kernel-rs/src/scheduling/sleep.rs | 6 +++ 7 files changed, 63 insertions(+), 38 deletions(-) rename kernel-rs/src/{process => scheduling}/fifo.rs (61%) rename kernel-rs/src/{process => scheduling}/mod.rs (54%) create mode 100644 kernel-rs/src/scheduling/process.rs create mode 100644 kernel-rs/src/scheduling/sleep.rs diff --git a/kernel-rs/src/arch/x86/devices/cpu.rs b/kernel-rs/src/arch/x86/devices/cpu.rs index 35c56a7c..079db7d5 100644 --- a/kernel-rs/src/arch/x86/devices/cpu.rs +++ b/kernel-rs/src/arch/x86/devices/cpu.rs @@ -274,9 +274,9 @@ pub fn cpu_info() -> Result { if info.has_rtm() { print!(", rtm") }; - if info.has_qm() { - print!(", qm") - }; + // if info.has_qm() { + // print!(", qm") + // }; if info.has_fpu_cs_ds_deprecated() { print!(", fpu_seg") }; diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 81817b7b..7385a455 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -57,7 +57,7 @@ interrupt!(0, pit, { offset.1 = sum % 1_000_000; offset.0 += sum / 1_000_000; if sum > 1_000_000 { - fprintln!("uptime: {}s", offset.0); + // fprintln!("uptime: {}s", offset.0); } } unsafe { pic::MASTER.ack() }; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 19039bac..f323022c 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -43,8 +43,8 @@ pub mod memory; /// arch specific entry points pub mod arch; pub use arch::x86::consts::*; -/// process scheduling -pub mod process; +/// concurrency management +pub mod scheduling; /// uptime counting pub mod time; @@ -57,7 +57,7 @@ pub fn kmain() -> ! { // vga is *not* cpu specific I think vga::init(); - process::schedule(); + scheduling::schedule(); unreachable!(); } diff --git a/kernel-rs/src/process/fifo.rs b/kernel-rs/src/scheduling/fifo.rs similarity index 61% rename from kernel-rs/src/process/fifo.rs rename to kernel-rs/src/scheduling/fifo.rs index c5be7b85..5f64228f 100644 --- a/kernel-rs/src/process/fifo.rs +++ b/kernel-rs/src/scheduling/fifo.rs @@ -1,6 +1,13 @@ +//! simple first come first serve scheduling algorithm +//! unsound for everyday use, a process can decide to +//! hijack the cpu, also it only allows for terminating +//! processes... +//! however it's stupid simple to implement! + use alloc::VecDeque; use super::*; +// use super::process::*; pub struct Fifo { list: VecDeque, @@ -17,7 +24,7 @@ impl Fifo { } impl Scheduler for Fifo { - fn add_process(&mut self, ip: u32) { + fn add_task(&mut self, ip: u32) { let p = Process::new(self.next_pid, ip); self.list.push_back(p); self.next_pid += 1; diff --git a/kernel-rs/src/process/mod.rs b/kernel-rs/src/scheduling/mod.rs similarity index 54% rename from kernel-rs/src/process/mod.rs rename to kernel-rs/src/scheduling/mod.rs index af270b35..e1708787 100644 --- a/kernel-rs/src/process/mod.rs +++ b/kernel-rs/src/scheduling/mod.rs @@ -1,50 +1,27 @@ +mod process; mod fifo; + use spin::Mutex; +pub use self::process::*; lazy_static! { pub static ref SCHEDULER: Mutex = Mutex::new({ let init_process: u32 = self::init as *const () as u32; let mut f = fifo::Fifo::new(); - f.add_process(init_process); + f.add_task(init_process); f }); } -// lazy_static! { -// static ref SCHEDULER: self::Scheduler = self::Scheduler { -// list: Mutex::new(VecDeque::new()) -// }; -// } - -#[derive(Debug)] -pub struct Process { - // this is eip right now - // this will be an elf blob later - pid: i32, - ip: u32, -} - -impl Process { - pub fn new(pid: i32, ip: u32) -> Process { - Process { pid, ip } - } - - pub unsafe fn execute(&mut self) { - let scheduler_loop = schedule as *const () as u32; - asm!("push $0; push $1; ret" :: "r"(scheduler_loop) ,"r"(self.ip) :: "volatile", "intel"); - unreachable!(); - } -} - pub trait Scheduler { - fn add_process(&mut self, ip: u32); + fn add_task(&mut self, ip: u32); fn next(&mut self) -> Option; } pub fn schedule() { loop { if let Some(mut p) = SCHEDULER.lock().next() { - println!("executing {:#x}", p.ip); + println!("executing {:#?}", p); flush!(); unsafe { SCHEDULER.force_unlock(); @@ -61,10 +38,12 @@ pub fn fork() -> i32 { println!("ip = {:#x}", ip); flush!(); unsafe { asm!("push $0" :: "r"(ip) :: "intel") }; - SCHEDULER.lock().add_process(ip); + SCHEDULER.lock().add_task(ip); 0 } +pub fn sleep() {} + pub fn init() { fprintln!("init first line"); // let i = self::fork(); diff --git a/kernel-rs/src/scheduling/process.rs b/kernel-rs/src/scheduling/process.rs new file mode 100644 index 00000000..e09ac959 --- /dev/null +++ b/kernel-rs/src/scheduling/process.rs @@ -0,0 +1,33 @@ +#[derive(Debug)] +pub enum State { + Running, + Ready, + Sleeping(u32), + Blocked(), +} + +#[derive(Debug)] +pub struct Process { + pid: i32, + // this is eip right now + // this will be an elf blob later + ip: u32, + state: State, +} + +impl Process { + pub fn new(pid: i32, ip: u32) -> Process { + Process { + pid, + ip, + state: State::Ready, + } + } + + pub unsafe fn execute(&mut self) { + use super::schedule; + let scheduler_loop = schedule as *const () as u32; + asm!("push $0; push $1; ret" :: "r"(scheduler_loop) ,"r"(self.ip) :: "volatile", "intel"); + unreachable!(); + } +} diff --git a/kernel-rs/src/scheduling/sleep.rs b/kernel-rs/src/scheduling/sleep.rs new file mode 100644 index 00000000..ceb57610 --- /dev/null +++ b/kernel-rs/src/scheduling/sleep.rs @@ -0,0 +1,6 @@ +//! sleeping processing are stored in a delta queue +//! separate from other scheduling structures: this +//! way the scheduling algorithms don't have to worry about +//! managing these +//! +//! inspired from https://wiki.osdev.org/Blocking_Process From 8e1927dc7decad9224daeab7fde3a74b7a4855d2 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Fri, 24 Aug 2018 23:53:00 +0200 Subject: [PATCH 143/151] modules https --- kernel-rs/.gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel-rs/.gitmodules b/kernel-rs/.gitmodules index 820f6043..6b9b26f1 100644 --- a/kernel-rs/.gitmodules +++ b/kernel-rs/.gitmodules @@ -1,6 +1,6 @@ [submodule "multiboot2-elf64"] path = multiboot2-elf64 - url = git@github.com:jzck/multiboot2-elf64.git + url = https://github.com/jzck/multiboot2-elf64.git [submodule "x86"] path = x86 url = https://github.com/jzck/x86.git From f02df6577e65f47cf439d4c197643659ceb54c06 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Nov 2018 23:21:48 +0100 Subject: [PATCH 144/151] some stuff --- kernel-rs/Makefile | 13 ++++--- kernel-rs/mk/grub.mk | 3 +- kernel-rs/mk/qemu.mk | 51 ++++++++++--------------- kernel-rs/src/arch/x86/interrupt/irq.rs | 3 -- kernel-rs/src/console.rs | 11 ++++++ kernel-rs/src/lib.rs | 5 ++- kernel-rs/src/scheduling/mod.rs | 10 +++-- kernel-rs/src/scheduling/sleep.rs | 35 +++++++++++++++++ 8 files changed, 84 insertions(+), 47 deletions(-) diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 5a421239..7bc433c7 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -6,8 +6,8 @@ TARGET ?= $(ARCH)-$(OS) all: @printf "make kernel\t# build kernel binary\n" - @printf "make iso\t# build iso cdrom with grub\n" - @printf "make qemu\t# run qemu+gdb in tmux window\n" + @printf "make iso\t# build iso cdrom\n" + @printf "make qemu\t# run iso in qemu\n" ## COMPILE ASM (nasm) asm_source := $(wildcard src/arch/$(ARCH)/*.asm) @@ -35,11 +35,12 @@ clean: .PHONY: clean kernel iso $(rust_os) +# Bootloader recipes +ISO := $(kernel:.bin=.iso) +iso: $(ISO) +include mk/grub.mk + # Emulation recipes include mk/qemu.mk -# Bootloader recipes -include mk/grub.mk -iso: $(grub-iso) - kernel: $(kernel) diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk index 80d40dfa..2cd521b8 100644 --- a/kernel-rs/mk/grub.mk +++ b/kernel-rs/mk/grub.mk @@ -1,8 +1,7 @@ -grub-iso := $(kernel:.bin=.iso) grub-cfg := src/arch/$(ARCH)/grub.cfg isodir := build/isofiles -$(grub-iso): $(kernel) $(grub-cfg) Makefile +$(ISO): $(kernel) $(grub-cfg) Makefile @mkdir -p $(isodir)/boot/grub @cp $(grub-cfg) $(isodir)/boot/grub @cp $(kernel) $(isodir)/boot/$(OS) diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index c99cce58..7dd71894 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -1,35 +1,24 @@ -ifeq ($(shell whoami), jack) - PORT_MONIT := 4242 - PORT_GDB := 4244 -else - PORT_MONIT := 4342 - PORT_GDB := 4344 -endif +QEMU_SOCKET := /tmp/qemu.sock +QEMU_MONITOR := socat - unix-connect:$(QEMU_SOCKET) +QEMU_GDB_PORT := 4242 -QEMU := qemu-system-i386\ - -cdrom build/bluesnow-x86.iso\ - -S\ - -enable-kvm\ - -curses\ - -gdb tcp::$(PORT_GDB)\ - -monitor telnet:127.0.0.1:$(PORT_MONIT),server,nowait qemu: - $(QEMU) + qemu-system-i386\ + -cdrom $(ISO)\ + -S\ + -enable-kvm\ + -curses\ + -gdb tcp::$(QEMU_GDB_PORT)\ + -monitor unix:${QEMU_SOCKET},server,nowait -GDB := gdb -q\ - -symbols "$(kernel)" \ - -ex "target remote :$(PORT_GDB)"\ - -ex "set arch i386" -gdb: - $(GDB) +qemu-gdb: + gdb -q\ + -symbols "$(kernel)" \ + -ex "target remote :$(QEMU_GDB_PORT)"\ + -ex "set arch i386" -MONITOR := telnet 127.0.0.1 $(PORT_MONIT);\ - kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 1 \`;\ - kill \`ps -x | grep \"[g]db -q\" | cut -d \ -f 2 \` -monitor: - telnet 127.0.0.1 $(PORT_MONIT) - -#not using this anymore -william: - @tmux info >&- || { echo -e "\033[38;5;16mPlease run inside a tmux session\033[0m" ; exit 1; } - @tmux new-window 'tmux split-window -h "$(MONITOR)"; tmux split-window -fv "$(GDB)"; tmux select-pane -t 1; tmux resize-pane -x 80 -y 25; $(QEMU)' +qemu-monitor: + $(QEMU_MONITOR) +qemu-reload: + echo "change ide1-cd0 $(ISO)" | $(QEMU_MONITOR) &>- + echo "system_reset" | $(QEMU_MONITOR) &>- diff --git a/kernel-rs/src/arch/x86/interrupt/irq.rs b/kernel-rs/src/arch/x86/interrupt/irq.rs index 7385a455..0a6e349c 100644 --- a/kernel-rs/src/arch/x86/interrupt/irq.rs +++ b/kernel-rs/src/arch/x86/interrupt/irq.rs @@ -56,9 +56,6 @@ interrupt!(0, pit, { let sum = offset.1 + PIT_RATE; offset.1 = sum % 1_000_000; offset.0 += sum / 1_000_000; - if sum > 1_000_000 { - // fprintln!("uptime: {}s", offset.0); - } } unsafe { pic::MASTER.ack() }; }); diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index e7e0d974..59f981ec 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -2,6 +2,7 @@ extern crate core; // extern crate multiboot2; use acpi; +use time; use keyboard::PS2; use core::char; use vga::*; @@ -28,6 +29,9 @@ fn dispatch(command: &str) -> Result<(), &'static str> { "overflow" => self::overflow(), "page_fault" => self::page_fault(), + // time + "uptime" => self::uptime(), + _ => Err("Command unknown. (h|help for help)"), } } @@ -59,6 +63,13 @@ fn help() -> Result<(), &'static str> { Ok(()) } +fn uptime() -> Result<(), &'static str> { + let mut offset = time::OFFSET.lock(); + fprintln!("{}s", offset.0 + offset.1 / 1_000_000); + flush!(); + Ok(()) +} + use x86::instructions::halt; /// Reboot the kernel /// diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index f323022c..4d4b3fbe 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -54,10 +54,11 @@ pub fn kmain() -> ! { // memory init after heap is available memory::init_noncore(); - // vga is *not* cpu specific I think + // load vga after core because is *not* cpu specific I think vga::init(); - scheduling::schedule(); + // scheduler WIP + // scheduling::schedule(); unreachable!(); } diff --git a/kernel-rs/src/scheduling/mod.rs b/kernel-rs/src/scheduling/mod.rs index e1708787..0c05f51e 100644 --- a/kernel-rs/src/scheduling/mod.rs +++ b/kernel-rs/src/scheduling/mod.rs @@ -1,9 +1,10 @@ mod process; +mod sleep; + mod fifo; use spin::Mutex; -pub use self::process::*; - +pub use self::process::*; lazy_static! { pub static ref SCHEDULER: Mutex = Mutex::new({ let init_process: u32 = self::init as *const () as u32; @@ -13,6 +14,7 @@ lazy_static! { }); } +/// Scheduler algorithm needs to implement this pub trait Scheduler { fn add_task(&mut self, ip: u32); fn next(&mut self) -> Option; @@ -42,7 +44,9 @@ pub fn fork() -> i32 { 0 } -pub fn sleep() {} +pub fn sleep() { + +} pub fn init() { fprintln!("init first line"); diff --git a/kernel-rs/src/scheduling/sleep.rs b/kernel-rs/src/scheduling/sleep.rs index ceb57610..ff4c75d7 100644 --- a/kernel-rs/src/scheduling/sleep.rs +++ b/kernel-rs/src/scheduling/sleep.rs @@ -4,3 +4,38 @@ //! managing these //! //! inspired from https://wiki.osdev.org/Blocking_Process + +use alloc::VecDeque; +use super::*; + +struct Sleeper { + process: Process, + // ms + ticks: u32, +} + +/// osdev calls this a delta queue but google doesnt know +struct DeltaQueue { + queue: VecDeque, +} + +impl DeltaQueue { + pub fn insert(&mut self, process: Process, ticks: u32) { + let sleeper = Sleeper { process, ticks }; + } + + /// decreases timer on the list and returns the number + /// of finished sleepers + pub fn tick(&mut self) -> u32 { + let mut i: u32 = 0; + while let Some(link) = self.queue.get_mut(i as usize) { + // find how many links have 0 ticks left + if link.ticks > 0 { + link.ticks -= 1; + break; + } + i += 1; + } + i + } +} From 911d9c8ae24930df576e8b5b6c678ed84140ce78 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 28 Nov 2018 23:26:28 +0100 Subject: [PATCH 145/151] readme --- kernel-rs/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 6f7bfaf4..47f4d9ee 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -2,18 +2,17 @@ Kernel from scratch (KFS) series of projects at Ecole 42 ! ### [documentation](https://jzck.github.io/kernel/bluesnow/index.html) -### dependencies +# building - `nasm` compiles the bootcode - `ld` links the bootcode and rust binary - `grub-mkrescue` builds the iso - `xargo` builds rust code - - `qemu` runs the iso See `.travis.yml` to get an ubuntu environment ready on archlinux `pacman -S rustup make grub xorriso mtools binutils gcc qemu` -### rust setup +#### rust setup ``` rustup override add nightly @@ -21,17 +20,17 @@ rustup component add rust-src cargo install xargo ``` -### running +# running -`make iso` generate the iso -`make qemu` runs the OS in a tmux window with `qemu` + `gdb` + - `make iso` builds a bootable iso with grub + - `make qemu` runs the iso, `make qemu-reload` after a re-build -### todo +# todo - remove assembly for a pure rust entry point - replace grub with something lighter -### inspiration +# inspiration - [wiki.osdev.org](https://wiki.osdev.org) is a fucking goldmine - [Phil Opperman's "Writing an OS in rust"](https://os.phil-opp.com/) From 3e49ec75d3a876a386457460c60acee920b085bd Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Tue, 15 Jan 2019 23:16:36 +0100 Subject: [PATCH 146/151] it compiles, update for rust 2018 --- kernel-rs/Cargo.toml | 15 +++++------ kernel-rs/Makefile | 10 +++---- kernel-rs/README.md | 19 ++++++++++---- kernel-rs/mk/grub.mk | 4 +-- kernel-rs/mk/qemu.mk | 2 +- kernel-rs/src/allocator/mod.rs | 13 ++++++---- kernel-rs/src/allocator/slab.rs | 43 ------------------------------- kernel-rs/src/arch/x86/mod.rs | 2 +- kernel-rs/src/lib.rs | 22 +++++----------- kernel-rs/src/memory/recycle.rs | 2 +- kernel-rs/src/scheduling/fifo.rs | 2 +- kernel-rs/src/scheduling/sleep.rs | 2 +- 12 files changed, 46 insertions(+), 90 deletions(-) delete mode 100644 kernel-rs/src/allocator/slab.rs diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index 824d95b2..293bdd48 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -10,22 +10,19 @@ crate-type = ["staticlib"] rlibc = "1.0" bitflags = "1.0.1" spin = "0.4" -slab_allocator = "0.3.1" -multiboot2 = { path = "multiboot2-elf64" } # added rsdp tag +slab_allocator = "0.3.5" +x86 = { path = "x86" } # forked for IA-32 compat +multiboot2 = { path = "multiboot2-elf64" } # forked to add rsdp tag [dependencies.raw-cpuid] # need to use github/master because of features not yet on crates.io git = "https://github.com/gz/rust-cpuid" features = ["nightly"] -[dependencies.x86] -# forked for IA32 compat -path = "x86" - [dependencies.lazy_static] version = "1.0.0" features = ["spin_no_std"] -[dependencies.compiler_builtins] -#I'm waiting for somebody to port i386/udivdi3.S ... :((( -git = "https://github.com/rust-lang-nursery/compiler-builtins" +#[dependencies.compiler_builtins] +##I'm waiting for somebody to port i386/udivdi3.S ... :((( +#git = "https://github.com/rust-lang-nursery/compiler-builtins" diff --git a/kernel-rs/Makefile b/kernel-rs/Makefile index 7bc433c7..cf398440 100644 --- a/kernel-rs/Makefile +++ b/kernel-rs/Makefile @@ -1,7 +1,7 @@ SHELL := /bin/bash ARCH := x86 -OS := bluesnow +OS := bluesnow TARGET ?= $(ARCH)-$(OS) all: @@ -23,10 +23,10 @@ $(rust_os): $(TARGET).json Makefile TERM=xterm RUST_TARGET_PATH="$(shell pwd)" xargo build --target $(TARGET) ## LINKAGE -kernel := build/$(OS)-$(ARCH).bin +KERNEL := build/$(OS)-$(ARCH).bin linker_script := src/arch/$(ARCH)/linker.ld LD := /usr/bin/ld -m elf_i386 -L ./ -n --gc-sections -$(kernel): $(rust_os) $(asm_object) $(linker_script) Makefile +$(KERNEL): $(rust_os) $(asm_object) $(linker_script) Makefile $(LD) -o $@ -T $(linker_script) $(asm_object) $(rust_os) clean: @@ -36,11 +36,11 @@ clean: .PHONY: clean kernel iso $(rust_os) # Bootloader recipes -ISO := $(kernel:.bin=.iso) +ISO := $(KERNEL:.bin=.iso) iso: $(ISO) include mk/grub.mk # Emulation recipes include mk/qemu.mk -kernel: $(kernel) +kernel: $(KERNEL) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index 47f4d9ee..c27a0f95 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -4,31 +4,40 @@ Kernel from scratch (KFS) series of projects at Ecole 42 ! # building +`git submodule udpate --init` + - `nasm` compiles the bootcode - `ld` links the bootcode and rust binary - - `grub-mkrescue` builds the iso + - `grub-mkrescue` builds the iso (need xorriso and mtools) - `xargo` builds rust code See `.travis.yml` to get an ubuntu environment ready -on archlinux `pacman -S rustup make grub xorriso mtools binutils gcc qemu` +on archlinux `pacman -S rustup make grub xorriso mtools binutils gcc qemu` +on voidlinux `xbps-install -S rustup make grub xorriso mtools binutils gcc qemu nasm` + #### rust setup +We build on nightly channel because of some cool features not yet in stable. +We need the rust sources to build with xargo for cross-compiling to custom platform. + ``` -rustup override add nightly rustup component add rust-src +rustup override add nightly +rustup default nightly cargo install xargo ``` # running - `make iso` builds a bootable iso with grub - - `make qemu` runs the iso, `make qemu-reload` after a re-build + - `make qemu` runs the iso, + - `make qemu-reload` reloads the CD # todo - remove assembly for a pure rust entry point - - replace grub with something lighter + - replace grub with something lighter (no bootloader at all with `qemu -kernel` ?) # inspiration diff --git a/kernel-rs/mk/grub.mk b/kernel-rs/mk/grub.mk index 2cd521b8..78240426 100644 --- a/kernel-rs/mk/grub.mk +++ b/kernel-rs/mk/grub.mk @@ -1,8 +1,8 @@ grub-cfg := src/arch/$(ARCH)/grub.cfg isodir := build/isofiles -$(ISO): $(kernel) $(grub-cfg) Makefile +$(ISO): $(KERNEL) $(grub-cfg) Makefile @mkdir -p $(isodir)/boot/grub @cp $(grub-cfg) $(isodir)/boot/grub - @cp $(kernel) $(isodir)/boot/$(OS) + @cp $(KERNEL) $(isodir)/boot/$(OS) grub-mkrescue -o $@ $(isodir) 2>/dev/null diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 7dd71894..e5f89e2d 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -13,7 +13,7 @@ qemu: qemu-gdb: gdb -q\ - -symbols "$(kernel)" \ + -symbols "$(KERNEL)" \ -ex "target remote :$(QEMU_GDB_PORT)"\ -ex "set arch i386" diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index 1aa4c172..baa5135f 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -1,12 +1,10 @@ -pub use self::slab::Allocator; -mod slab; +// pub use self::ALLOCATOR; -use x86::*; use x86::structures::paging::*; use arch::x86::paging::*; fn map_heap(active_table: &mut ActivePageTable) { - //zone for heap is predefines in `consts.rs` + //zone for heap is predefined in `consts.rs` for page in ::KERNEL_HEAP_RANGE { active_table.map(page, PageTableFlags::WRITABLE); } @@ -20,5 +18,10 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { map_heap(active_table); //slab allocator - Allocator::init(offset.as_u32() as usize, size as usize); + super::ALLOCATOR.init(offset.as_u32() as usize, size as usize); +} + +#[alloc_error_handler] +fn foo(_: core::alloc::Layout) -> ! { + panic!(); } diff --git a/kernel-rs/src/allocator/slab.rs b/kernel-rs/src/allocator/slab.rs deleted file mode 100644 index ddc50501..00000000 --- a/kernel-rs/src/allocator/slab.rs +++ /dev/null @@ -1,43 +0,0 @@ -use alloc::heap::{Alloc, AllocErr, Layout}; -use spin::Mutex; -use slab_allocator::Heap; - -static HEAP: Mutex> = Mutex::new(None); - -pub struct Allocator; - -impl Allocator { - pub unsafe fn init(offset: usize, size: usize) { - *HEAP.lock() = Some(Heap::new(offset, size)); - } -} - -unsafe impl<'a> Alloc for &'a Allocator { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - if let Some(ref mut heap) = *HEAP.lock() { - heap.allocate(layout) - } else { - panic!("__rust_allocate: heap not initialized"); - } - } - - unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { - if let Some(ref mut heap) = *HEAP.lock() { - heap.deallocate(ptr, layout) - } else { - panic!("__rust_deallocate: heap not initialized"); - } - } - - fn oom(&mut self, error: AllocErr) -> ! { - panic!("Out of memory: {:?}", error); - } - - fn usable_size(&self, layout: &Layout) -> (usize, usize) { - if let Some(ref mut heap) = *HEAP.lock() { - heap.usable_size(layout) - } else { - panic!("__rust_usable_size: heap not initialized"); - } - } -} diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 59b7f073..73ae5e38 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -54,7 +54,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // set up pic, pit devices::init(); - // primary CPU entry point + // primary CPU entry point, architutecture independant now. ::kmain(); } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 4d4b3fbe..0156eff5 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -10,8 +10,8 @@ #![feature(thread_local)] // home made heap #![feature(alloc)] +#![feature(alloc_error_handler)] #![feature(allocator_api)] -#![feature(global_allocator)] // x86 specific #![feature(abi_x86_interrupt)] @@ -27,25 +27,16 @@ extern crate spin; // used by arch/x86, need conditional compilation here extern crate x86; -/// 80x25 terminal driver #[macro_use] pub mod vga; -/// PS/2 detection and processing pub mod keyboard; -/// simplisitc kernel commands pub mod console; -/// ACPI self contained module pub mod acpi; -/// Heap allocators pub mod allocator; -/// Memory management pub mod memory; -/// arch specific entry points pub mod arch; pub use arch::x86::consts::*; -/// concurrency management pub mod scheduling; -/// uptime counting pub mod time; /// kernel entry point. arch module is responsible for @@ -66,15 +57,14 @@ pub fn kmain() -> ! { #[no_mangle] pub extern "C" fn eh_personality() {} -#[lang = "panic_fmt"] +#[panic_handler] #[no_mangle] -pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! { - println!("PANIC: {}", fmt); - println!("FILE: {}", file); - println!("LINE: {}", line); +pub extern "C" fn panic_fmt(info: &core::panic::PanicInfo) -> ! { + println!("{}", info); flush!(); loop {} } #[global_allocator] -static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator; +// pub static ALLOCATOR: slab_allocator::LockedHeap = allocator::ALLOCATOR; +pub static ALLOCATOR: slab_allocator::LockedHeap = slab_allocator::LockedHeap::empty(); diff --git a/kernel-rs/src/memory/recycle.rs b/kernel-rs/src/memory/recycle.rs index 69373d5c..4772addb 100644 --- a/kernel-rs/src/memory/recycle.rs +++ b/kernel-rs/src/memory/recycle.rs @@ -1,7 +1,7 @@ //! Recycle allocator //! Uses freed frames if possible, then uses inner allocator -use alloc::Vec; +use alloc::vec::Vec; use x86::*; use x86::structures::paging::*; use super::*; diff --git a/kernel-rs/src/scheduling/fifo.rs b/kernel-rs/src/scheduling/fifo.rs index 5f64228f..aea1e4bb 100644 --- a/kernel-rs/src/scheduling/fifo.rs +++ b/kernel-rs/src/scheduling/fifo.rs @@ -4,7 +4,7 @@ //! processes... //! however it's stupid simple to implement! -use alloc::VecDeque; +use alloc::collections::vec_deque::VecDeque; use super::*; // use super::process::*; diff --git a/kernel-rs/src/scheduling/sleep.rs b/kernel-rs/src/scheduling/sleep.rs index ff4c75d7..af69d146 100644 --- a/kernel-rs/src/scheduling/sleep.rs +++ b/kernel-rs/src/scheduling/sleep.rs @@ -5,7 +5,7 @@ //! //! inspired from https://wiki.osdev.org/Blocking_Process -use alloc::VecDeque; +use alloc::collections::vec_deque::VecDeque; use super::*; struct Sleeper { From 381b86d5e024dcb3597340c887472e4a1d301a3f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 16 Jan 2019 20:53:40 +0100 Subject: [PATCH 147/151] console moved out of vga --- kernel-rs/src/console.rs | 150 ++++++++++++++++++++++++++++---------- kernel-rs/src/keyboard.rs | 6 +- kernel-rs/src/lib.rs | 6 +- kernel-rs/src/vga/mod.rs | 82 ++------------------- 4 files changed, 122 insertions(+), 122 deletions(-) diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 59f981ec..963d37ac 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -7,56 +7,126 @@ use keyboard::PS2; use core::char; use vga::*; -fn dispatch(command: &str) -> Result<(), &'static str> { - match command { - "help" | "h" => self::help(), +pub static mut CONSOLE: Console = self::Console::new(); - // multiboot - // "memory" => self::mb2_memory(), - // "multiboot" => self::mb2_info(), - // "sections" => self::mb2_sections(), - - // ACPI - "acpi" => self::acpi_info(), - "reboot" => self::reboot(), - "shutdown" | "halt" | "q" => self::shutdown(), - - // x86 specific - "stack" => self::print_stack(), - "regs" => self::regs(), - "cpu" => self::cpu(), - "int3" => self::int3(), - "overflow" => self::overflow(), - "page_fault" => self::page_fault(), - - // time - "uptime" => self::uptime(), - - _ => Err("Command unknown. (h|help for help)"), - } +pub struct Console { + command: [u8; 10], + command_len: usize, } -pub fn exec(cli: &Writer) -> Result<(), &'static str> { - let command = cli.get_command()?; - if let Err(msg) = self::dispatch(command) { - set_color!(Red); - println!("`{}`: {}", command, msg); - set_color!(); +impl Console { + pub const fn new() -> Console { + Console { + command: [b'\0'; 10], + command_len: 0, + } + } + + pub fn init(&self) { + set_color!(); + // print!("{}", format_args!("{: ^4000}", r#" "#)); + unsafe { + // VGA.buffer_pos = 0; + self.prompt(); + VGA.flush(); + } + } + + pub fn backspace(&mut self) { + if self.command_len > 0 { + self.command_len -= 1; + unsafe { VGA.erase_byte(); } + } + } + + pub fn prompt(&self) { + set_color!(Blue); + unsafe { VGA.write_str("> "); } + set_color!(); + flush!(); + } + + pub fn keypress(&mut self, ascii: u8) { + match ascii { + b'\n' if self.command_len == 0 => { + unsafe { VGA.write_byte(b'\n'); } + self.prompt(); + } + b'\n' => { + unsafe { VGA.write_byte(b'\n'); } + self.exec(); + self.command_len = 0; + self.prompt(); + } + // _ if self.command_len >= 10 => (), + // byte if self.command_len == 0 && byte == b' ' => (), + byte => { + if self.command_len >= 10 { + return; + }; + self.command[self.command_len] = byte; + unsafe { VGA.write_byte(byte); } + self.command_len += 1; + } + } + flush!(); + } + + + fn get_command(&self) -> Result<&str, &'static str> { + match core::str::from_utf8(&self.command) { + Ok(y) => Ok(&y[..self.command_len]), + Err(_) => Err("Command is not utf8"), + } + } + + pub fn exec(&self) -> core::result::Result<(), &'static str> { + let command = self.get_command(); + if let Err(msg) = command { + set_color!(Red); + println!("{}", msg); + set_color!(); + } + match command.unwrap() { + "help" | "h" => self::help(), + + // multiboot + // "memory" => self::mb2_memory(), + // "multiboot" => self::mb2_info(), + // "sections" => self::mb2_sections(), + + // ACPI + "acpi" => self::acpi_info(), + "reboot" => self::reboot(), + "shutdown" | "halt" | "q" => self::shutdown(), + + // x86 specific + "stack" => self::print_stack(), + "regs" => self::regs(), + "cpu" => self::cpu(), + "int3" => self::int3(), + "overflow" => self::overflow(), + "page_fault" => self::page_fault(), + + // time + "uptime" => self::uptime(), + + _ => Err("Command unknown. (try help)"), + } } - Ok(()) } fn help() -> Result<(), &'static str> { - println!("acpi => Return acpi state (ENABLED|DISABLE)"); - println!("help | h => Print this help"); + println!("help | h => print this help"); // println!("memory => Print memory areas"); // println!("multiboot => Print multiboot information"); // println!("sections => Print elf sections"); - println!("reboot => Reboot"); - println!("shutdown | halt | q => Kill a kitten, then shutdown"); - println!("stack => Print kernel stack in a fancy way"); - println!("regs => Print controle register"); - println!("cpu => Print cpu information"); + println!("reboot => reboot"); + println!("shutdown | halt | q => acpi shutdown"); + println!("acpi => acpi state"); + println!("stack => print kernel stack in a fancy way"); + println!("regs => print controle register"); + println!("cpu => print cpu information"); println!("overflow => triggers a stack overflow"); println!("page_fault => triggers a page fault on 0xdead"); flush!(); diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index 67458433..ec4e8766 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,6 +1,6 @@ extern crate core; -use vga; +use console; use x86::devices::io::{Io, Pio}; const MAX_KEYS: usize = 59; @@ -133,13 +133,13 @@ pub fn kbd_callback() { 0x38 => ALT = !is_release, 0x1D => CTRL = !is_release, 0x0E if !is_release => { - vga::VGA.backspace(); + console::CONSOLE.backspace(); } _ => {} }, Some(ascii) if !is_release => { let sym = if SHIFT { ascii[1] } else { ascii[0] }; - vga::VGA.keypress(sym); + console::CONSOLE.keypress(sym); } _ => {} } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 0156eff5..c29bcad3 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -38,6 +38,7 @@ pub mod arch; pub use arch::x86::consts::*; pub mod scheduling; pub mod time; +pub mod pci; /// kernel entry point. arch module is responsible for /// calling this once the core has loaded @@ -45,9 +46,10 @@ pub fn kmain() -> ! { // memory init after heap is available memory::init_noncore(); - // load vga after core because is *not* cpu specific I think - vga::init(); + // unsafe VGA + unsafe { console::CONSOLE.init(); } + pci::lspci(); // scheduler WIP // scheduling::schedule(); unreachable!(); diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index b4a54fc3..e6df8adc 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -1,5 +1,3 @@ -#![allow(unused_macros)] - pub mod color; pub mod cursor; @@ -52,9 +50,9 @@ macro_rules! flush { macro_rules! set_color { () => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::Black, $crate::vga::Color::Yellow)} ); + $crate::vga::ColorCode::new($crate::vga::Color::White, $crate::vga::Color::Black)} ); ($fg:ident) => (unsafe { $crate::vga::VGA.color_code = - $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Yellow)} ); + $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::Black)} ); ($fg:ident, $bg:ident) => (unsafe { $crate::vga::VGA.color_code = $crate::vga::ColorCode::new($crate::vga::Color::$fg, $crate::vga::Color::$bg)} ); } @@ -83,27 +81,13 @@ impl Writer { pub const fn new() -> Writer { Writer { buffer_pos: 0, - color_code: ColorCode::new(Color::Black, Color::Yellow), + color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], command: [b'\0'; 10], command_len: 0, } } - pub fn prompt(&mut self) { - set_color!(Blue); - self.write_str("> "); - set_color!(); - flush!(); - } - - pub fn backspace(&mut self) { - if self.command_len > 0 { - self.command_len -= 1; - self.erase_byte(); - } - } - pub fn get_command(&self) -> Result<&str, &'static str> { match core::str::from_utf8(&self.command) { Ok(y) => Ok(&y[..self.command_len]), @@ -111,35 +95,6 @@ impl Writer { } } - pub fn keypress(&mut self, ascii: u8) { - match ascii { - b'\n' if self.command_len == 0 => { - self.write_byte(b'\n'); - self.prompt(); - } - b'\n' => { - self.write_byte(b'\n'); - if let Err(msg) = console::exec(&self) { - set_color!(Red, Yellow); - println!("Something wrong: {}", msg); - set_color!(); - } - self.command_len = 0; - self.prompt(); - } - _ if self.command_len >= 10 => (), - byte if self.command_len == 0 && byte == b' ' => (), - byte => { - if self.command_len >= 10 { - return; - }; - self.command[self.command_len] = byte; - self.write_byte(byte); - self.command_len += 1; - } - } - self.flush(); - } pub fn erase_byte(&mut self) { self.buffer_pos -= 2; @@ -170,7 +125,7 @@ impl Writer { } } - fn write_str(&mut self, s: &str) { + pub fn write_str(&mut self, s: &str) { for byte in s.bytes() { self.write_byte(byte) } @@ -200,7 +155,7 @@ impl Writer { for col in (0..BUFFER_COLS / 2).map(|x| x * 2) { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col)] = b' '; self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = - ColorCode::new(Color::Black, Color::Yellow).0; + ColorCode::new(Color::White, Color::Black).0; } self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; @@ -217,30 +172,3 @@ impl fmt::Write for Writer { Ok(()) } } - -pub fn init() { - // set_color!(Yellow, Red); - // print!( - // "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - // format_args!("{: ^80}", r#" ,--, "#), - // format_args!("{: ^80}", r#" ,--.'| ,----, "#), - // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - // format_args!("{: ^80}", r#" ' ; |./__; : "#), - // format_args!("{: ^80}", r#" | : ;| : .' "#), - // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - // format_args!("{: ^80}", r#" '--' `---' "#) - // ); - unsafe { - VGA.prompt(); - } - unsafe { - VGA.flush(); - } -} From 85afa2b4377db079494b7c8a829f9c8086965097 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Wed, 16 Jan 2019 22:30:06 +0100 Subject: [PATCH 148/151] pci first commit --- kernel-rs/mk/qemu.mk | 8 +++++--- kernel-rs/src/console.rs | 10 ++++++---- kernel-rs/src/lib.rs | 5 +++-- kernel-rs/src/pci/mod.rs | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 kernel-rs/src/pci/mod.rs diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index e5f89e2d..99fbe143 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -12,7 +12,8 @@ qemu: -monitor unix:${QEMU_SOCKET},server,nowait qemu-gdb: - gdb -q\ + gdb\ + -q\ -symbols "$(KERNEL)" \ -ex "target remote :$(QEMU_GDB_PORT)"\ -ex "set arch i386" @@ -20,5 +21,6 @@ qemu-gdb: qemu-monitor: $(QEMU_MONITOR) qemu-reload: - echo "change ide1-cd0 $(ISO)" | $(QEMU_MONITOR) &>- - echo "system_reset" | $(QEMU_MONITOR) &>- + echo "stop" | $(QEMU_MONITOR) &>/dev/null + echo "change ide1-cd0 $(ISO)" | $(QEMU_MONITOR) &>/dev/null + echo "system_reset" | $(QEMU_MONITOR) &>/dev/null diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index 963d37ac..b0d7e09a 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -54,7 +54,11 @@ impl Console { } b'\n' => { unsafe { VGA.write_byte(b'\n'); } - self.exec(); + if let Err(msg) = self.exec() { + set_color!(Red); + println!("{}", msg); + set_color!(); + } self.command_len = 0; self.prompt(); } @@ -83,9 +87,7 @@ impl Console { pub fn exec(&self) -> core::result::Result<(), &'static str> { let command = self.get_command(); if let Err(msg) = command { - set_color!(Red); - println!("{}", msg); - set_color!(); + return Err(msg) } match command.unwrap() { "help" | "h" => self::help(), diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index c29bcad3..c58b1d51 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -24,6 +24,8 @@ extern crate rlibc; extern crate slab_allocator; extern crate spin; +extern crate bitflags; + // used by arch/x86, need conditional compilation here extern crate x86; @@ -44,7 +46,7 @@ pub mod pci; /// calling this once the core has loaded pub fn kmain() -> ! { // memory init after heap is available - memory::init_noncore(); + // memory::init_noncore(); // unsafe VGA unsafe { console::CONSOLE.init(); } @@ -68,5 +70,4 @@ pub extern "C" fn panic_fmt(info: &core::panic::PanicInfo) -> ! { } #[global_allocator] -// pub static ALLOCATOR: slab_allocator::LockedHeap = allocator::ALLOCATOR; pub static ALLOCATOR: slab_allocator::LockedHeap = slab_allocator::LockedHeap::empty(); diff --git a/kernel-rs/src/pci/mod.rs b/kernel-rs/src/pci/mod.rs new file mode 100644 index 00000000..2440fe82 --- /dev/null +++ b/kernel-rs/src/pci/mod.rs @@ -0,0 +1,22 @@ +// https://wiki.osdev.org/PCI + +use x86::devices::io::{Pio}; + +pub static mut PCI_CONFIG_ADDRESS: Pio = Pio::new(0xCF8); +pub static mut PCI_CONFIG_DATA: Pio = Pio::new(0xCFC); + +pub fn lspci() { + pci_config_read_word(1, 1, 1, 2); +} + +pub fn pci_config_read_word(bus: u32, slot: u32, func: u32, offset: u32) { + // let address: u64 = (bus as u32) << 16 + // | (slot as u32) << 11 + // | (func as u32) << 8 + // | (offset as u32) & 0xfc + // | 0x80000000; + let address: u64 = 0x80000000; + println!("{} {} {} {}", bus, slot, func, offset); + println!("{:#x}", address); + println!("{:#b}", address); +} From c9ad4e9e5810fa11e10446aa7e1aee95636a2562 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sun, 20 Jan 2019 22:11:14 +0100 Subject: [PATCH 149/151] lspci, console refactor --- kernel-rs/src/acpi/mod.rs | 46 ++-- kernel-rs/src/allocator/mod.rs | 2 +- kernel-rs/src/arch/x86/devices/cpu.rs | 6 +- kernel-rs/src/arch/x86/mod.rs | 31 ++- kernel-rs/src/console.rs | 304 +++++--------------------- kernel-rs/src/lib.rs | 4 +- kernel-rs/src/memory/mod.rs | 60 +++++ kernel-rs/src/pci/mod.rs | 85 +++++-- kernel-rs/src/time.rs | 5 + kernel-rs/src/vga/mod.rs | 34 +-- 10 files changed, 250 insertions(+), 327 deletions(-) diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 55f86984..6a2f1f4b 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -126,17 +126,9 @@ impl Iterator for ACPISDTIter { } } -fn is_init() -> Result<(), &'static str> { - if unsafe { ACPI.valid } { - Ok(()) - } else { - Err("ACPI is not initialized") - } -} - /// Initalized the ACPI module pub fn init() -> Result<(), &'static str> { - if let Ok(()) = is_init() { + if unsafe{ACPI.valid} { return Ok(()); } unsafe { ACPI.init() } @@ -144,7 +136,7 @@ pub fn init() -> Result<(), &'static str> { /// Load the ACPI module, addr given is a ptr to RSDP pub fn load(rsdp_addr: u32) -> Result<(), &'static str> { - if let Ok(()) = is_init() { + if unsafe{ACPI.valid} { return Ok(()); } unsafe { ACPI.load(rsdp_addr) } @@ -152,32 +144,30 @@ pub fn load(rsdp_addr: u32) -> Result<(), &'static str> { /// Proceed to ACPI shutdown /// This function doesn't work with Virtual Box yet -pub fn shutdown() -> Result<(), &'static str> { - is_init()?; - dsdt::shutdown(fadt::get_controlblock()?) +pub fn shutdown() { + if unsafe{ACPI.valid} { return } + dsdt::shutdown(fadt::get_controlblock().unwrap()); } /// Proceed to ACPI reboot /// This function need ACPI in v2 -pub fn reboot() -> Result<(), &'static str> { - is_init()?; +pub fn reboot() { + if unsafe {!ACPI.valid} { + println!("ACPI not initialized"); + } if unsafe { ACPI.v2 } { - fadt::reboot() + fadt::reboot().unwrap() } else { - Err("ACPI reboot only available in ACPI v2+") + println!("ACPI reboot only available in ACPI v2+"); } } /// Display state of ACPI -pub fn info() -> Result<(), &'static str> { - is_init()?; - println!( - "ACPI STATE:\n {}", - if fadt::is_enable()? { - "ENABLED" - } else { - "DISABLED" - } - ); - Ok(()) +pub fn info() { + if unsafe { !ACPI.valid } { println!("ACPI not initialized"); return } + match fadt::is_enable() { + Ok(True) => println!("ACPI is disabled"), + Ok(False) => println!("ACPI is disabled"), + Err(msg) => println!("error while checking ACPI") + } } diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index baa5135f..6c5fb136 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -23,5 +23,5 @@ pub unsafe fn init(active_table: &mut ActivePageTable) { #[alloc_error_handler] fn foo(_: core::alloc::Layout) -> ! { - panic!(); + panic!("alloc_error_handler"); } diff --git a/kernel-rs/src/arch/x86/devices/cpu.rs b/kernel-rs/src/arch/x86/devices/cpu.rs index 079db7d5..111ba009 100644 --- a/kernel-rs/src/arch/x86/devices/cpu.rs +++ b/kernel-rs/src/arch/x86/devices/cpu.rs @@ -1,10 +1,8 @@ extern crate raw_cpuid; -use core::fmt::Result; - use self::raw_cpuid::CpuId; -pub fn cpu_info() -> Result { +pub fn cpu_info() { let cpuid = CpuId::new(); if let Some(info) = cpuid.get_vendor_info() { @@ -285,6 +283,4 @@ pub fn cpu_info() -> Result { }; println!(""); } - - Ok(()) } diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index 73ae5e38..14cd6855 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -17,10 +17,6 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // parse multiboot2 info let boot_info = multiboot2::load(multiboot_info_addr); - // println!("{:?}", boot_info); - // flush!(); - // asm!("hlt"); - // ACPI must be intialized BEFORE paging is active if let Some(rsdp) = boot_info.rsdp_v2_tag() { acpi::load(rsdp).expect("ACPI failed"); @@ -116,3 +112,30 @@ pub unsafe fn usermode(ip: u32, sp: u32) -> ! { unreachable!(); } + +/// Dump control registers +pub fn regs() { + use x86::registers::control::*; + use x86::instructions::tables::tr; + use x86::instructions::segmentation::*; + use x86::registers::flags::*; + use x86::structures::gdt; + println!("cr0 = {:?}", Cr0::read()); + println!("cr3 = {:?}", Cr3::read()); + println!("cr4 = {:?}", Cr4::read()); + println!("flags= {:?}", flags()); + println!("tr = {:?}", tr()); + println!("ss = {:?}", ss()); + println!("cs = {:?}", cs()); + println!("ds = {:?}", ds()); + println!("es = {:?}", es()); + println!("fs = {:?}", fs()); + println!("gs = {:?}", gs()); + unsafe { + println!( + "tss = {:#?}", + gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize]) + ); + } + flush!(); +} diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index b0d7e09a..f5c00bca 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,14 +1,49 @@ extern crate core; // extern crate multiboot2; -use acpi; -use time; -use keyboard::PS2; -use core::char; use vga::*; +use alloc::collections::BTreeMap; pub static mut CONSOLE: Console = self::Console::new(); +lazy_static! { + static ref COMMANDS: BTreeMap<&'static str, fn()> = { + let mut commands = BTreeMap::new(); + commands.insert("help", self::help as fn()); + + // ACPI + commands.insert("acpi", ::acpi::info as fn()); + commands.insert("reboot", ::acpi::reboot as fn()); + commands.insert("shutdown", ::acpi::shutdown as fn()); + + // time + commands.insert("uptime", ::time::uptime as fn()); + + // cpu + use arch::x86; + commands.insert("cpu", x86::devices::cpu::cpu_info as fn()); + commands.insert("regs", x86::regs as fn()); + commands.insert("int3", ::x86::instructions::interrupts::int3 as fn()); + + //memory + commands.insert("stack", ::memory::print_stack as fn()); + commands.insert("page_fault", ::memory::page_fault as fn()); + commands.insert("overflow", ::memory::overflow as fn()); + commands.insert("overflow", ::memory::overflow as fn()); + + //pci + commands.insert("lspci", ::pci::lspci as fn()); + commands + }; +} + +fn help() { + println!("The following commands are available:"); + for (key, val) in COMMANDS.iter() { + println!("{}", key); + } +} + pub struct Console { command: [u8; 10], command_len: usize, @@ -54,11 +89,7 @@ impl Console { } b'\n' => { unsafe { VGA.write_byte(b'\n'); } - if let Err(msg) = self.exec() { - set_color!(Red); - println!("{}", msg); - set_color!(); - } + self.exec(); self.command_len = 0; self.prompt(); } @@ -73,256 +104,27 @@ impl Console { self.command_len += 1; } } - flush!(); + unsafe { VGA.flush(); } } - - fn get_command(&self) -> Result<&str, &'static str> { + fn get_command(&self) -> Result { match core::str::from_utf8(&self.command) { - Ok(y) => Ok(&y[..self.command_len]), + Ok(y) => { + if let Some(command) = COMMANDS.get(&y[..self.command_len]) { + Ok(*command) + } else { + Err("Command not found, try help") + } + }, Err(_) => Err("Command is not utf8"), } } - pub fn exec(&self) -> core::result::Result<(), &'static str> { + pub fn exec(&self) { let command = self.get_command(); - if let Err(msg) = command { - return Err(msg) - } - match command.unwrap() { - "help" | "h" => self::help(), - - // multiboot - // "memory" => self::mb2_memory(), - // "multiboot" => self::mb2_info(), - // "sections" => self::mb2_sections(), - - // ACPI - "acpi" => self::acpi_info(), - "reboot" => self::reboot(), - "shutdown" | "halt" | "q" => self::shutdown(), - - // x86 specific - "stack" => self::print_stack(), - "regs" => self::regs(), - "cpu" => self::cpu(), - "int3" => self::int3(), - "overflow" => self::overflow(), - "page_fault" => self::page_fault(), - - // time - "uptime" => self::uptime(), - - _ => Err("Command unknown. (try help)"), + match command { + Err(msg) => println!("{}", msg), + Ok(func) => (func)(), } } } - -fn help() -> Result<(), &'static str> { - println!("help | h => print this help"); - // println!("memory => Print memory areas"); - // println!("multiboot => Print multiboot information"); - // println!("sections => Print elf sections"); - println!("reboot => reboot"); - println!("shutdown | halt | q => acpi shutdown"); - println!("acpi => acpi state"); - println!("stack => print kernel stack in a fancy way"); - println!("regs => print controle register"); - println!("cpu => print cpu information"); - println!("overflow => triggers a stack overflow"); - println!("page_fault => triggers a page fault on 0xdead"); - flush!(); - Ok(()) -} - -fn uptime() -> Result<(), &'static str> { - let mut offset = time::OFFSET.lock(); - fprintln!("{}s", offset.0 + offset.1 / 1_000_000); - flush!(); - Ok(()) -} - -use x86::instructions::halt; -/// Reboot the kernel -/// -/// If reboot failed, will loop on a halt cmd -/// -fn reboot() -> ! { - match acpi::reboot() { - Err(msg) => println!("{}", msg), - _ => println!("Unable to perform ACPI reboot."), - } - flush!(); - unsafe { PS2.ps2_8042_reset() }; // TODO unsafe - println!("Unable to perform 8042 reboot. Kernel will be halted"); - flush!(); - halt(); -} - -/// Shutdown the kernel -/// -/// If shutdown is performed but failed, will loop on a halt cmd -/// If shutdown cannot be called, return a Err(&str) -/// -fn shutdown() -> ! { - match acpi::shutdown() { - Err(msg) => println!("{}", msg), - _ => println!("Unable to perform ACPI shutdown. Kernel will be halted"), - } - flush!(); - halt(); -} - -fn hexdump(start: usize, end: usize) { - let mut address = 0; - let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) }; - while address <= data.len() { - let next_end = core::cmp::min(address + 16, data.len()); - print_line(&data[address..next_end], address + start); - address = address + 16; - } - println!(""); -} - -fn is_control(c: char) -> bool { - !(c >= ' ' && c <= '~') -} - -fn print_line(line: &[u8], address: usize) { - print!("\n{:#08x}: ", address); - for byte in line { - print!("{:02x} ", *byte); - } - let length: usize = 16 - line.len(); - for _ in 0..length { - print!(" "); - } - print!("|"); - for byte in line { - match is_control(*byte as char) { - true => print!("."), - false => print!("{}", *byte as char), - }; - } - print!("|"); -} - -/// Print the kernel stack -pub fn print_stack() -> Result<(), &'static str> { - let esp: usize; - let ebp: usize; - unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; - println!("esp = {:#x}", esp); - println!("ebp = {:#x}", ebp); - println!("size = {:#X} bytes", ebp - esp); - hexdump(esp, ebp); - flush!(); - Ok(()) -} - -// fn mb2_memory() -> Result <(), &'static str> { -// let boot_info = ::multiboot2::boot_info(); - -// let memory_map_tag = boot_info.memory_map_tag() -// .expect("Memory map tag required"); - -// println!("memory areas:"); -// for area in memory_map_tag.memory_areas() { -// println!(" start: 0x{:x}, length: 0x{:x}", -// area.start_address(), area.size()); -// } -// Ok(()) -// } - -// fn mb2_sections() -> Result <(), &'static str> { -// let boot_info = ::multiboot2::boot_info(); - -// let elf_sections_tag = boot_info.elf_sections_tag() -// .expect("Elf-sections tag required"); - -// println!("kernel sections:"); -// for section in elf_sections_tag.sections() { -// println!(" {: <10} {:#x}, size: {:#x}, flags: {:#X}", -// section.name(), section.start_address(), section.size(), section.flags()); -// } -// Ok(()) -// } - -// fn mb2_info() -> Result <(), &'static str> { -// let boot_info = context::boot_info(); - -// let command_line_tag = boot_info.command_line_tag() -// .expect("Elf-sections tag required"); - -// let bootloader_tag = boot_info.boot_loader_name_tag() -// .expect("Elf-sections tag required"); - -// println!("bootloader: {}", bootloader_tag.name()); -// if command_line_tag.command_line().len() != 0 { -// println!("command line: {}", command_line_tag.command_line()); -// } -// Ok(()) -// } - -pub fn acpi_info() -> Result<(), &'static str> { - acpi::info()?; - Ok(()) -} - -/// Dump control registers -pub fn regs() -> Result<(), &'static str> { - use x86::registers::control::*; - use x86::instructions::tables::tr; - use x86::instructions::segmentation::*; - use x86::registers::flags::*; - use x86::structures::gdt; - println!("cr0 = {:?}", Cr0::read()); - println!("cr3 = {:?}", Cr3::read()); - println!("cr4 = {:?}", Cr4::read()); - println!("flags= {:?}", flags()); - println!("tr = {:?}", tr()); - println!("ss = {:?}", ss()); - println!("cs = {:?}", cs()); - println!("ds = {:?}", ds()); - println!("es = {:?}", es()); - println!("fs = {:?}", fs()); - println!("gs = {:?}", gs()); - unsafe { - println!( - "tss = {:#?}", - gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize]) - ); - } - flush!(); - Ok(()) -} - -/// Dump cpu info, should add power management info -pub fn cpu() -> Result<(), &'static str> { - use arch::x86::devices::cpu; - cpu::cpu_info().expect("cpu info not available"); - flush!(); - Ok(()) -} - -pub fn int3() -> Result<(), &'static str> { - use x86; - x86::instructions::interrupts::int3(); - Ok(()) -} - -#[allow(unconditional_recursion)] -pub fn overflow() -> Result<(), &'static str> { - fn stack_overflow() { - stack_overflow(); - } - stack_overflow(); - Ok(()) -} - -pub fn page_fault() -> Result<(), &'static str> { - unsafe { - *(0xdead as *mut u32) = 42; - }; - Ok(()) -} diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index c58b1d51..a9ebbbb9 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -51,7 +51,9 @@ pub fn kmain() -> ! { // unsafe VGA unsafe { console::CONSOLE.init(); } - pci::lspci(); + if let Ok(slot) = pci::get_ide1() { + println!("found IDE at slot {}", slot); + } // scheduler WIP // scheduling::schedule(); unreachable!(); diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index a2af86a5..2279c3e8 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -101,3 +101,63 @@ pub fn init_noncore() { } } } + + +/// for console +#[allow(unconditional_recursion)] +pub fn overflow() { + overflow(); +} + +/// for console +pub fn page_fault() { + unsafe { + *(0xdead as *mut u32) = 42; + }; +} + +/// Print the kernel stack +pub fn print_stack() { + fn hexdump(start: usize, end: usize) { + let mut address = 0; + let data = unsafe { core::slice::from_raw_parts_mut(start as *mut u8, end - start) }; + while address <= data.len() { + let next_end = core::cmp::min(address + 16, data.len()); + print_line(&data[address..next_end], address + start); + address = address + 16; + } + println!(""); + } + + fn is_control(c: char) -> bool { + !(c >= ' ' && c <= '~') + } + + fn print_line(line: &[u8], address: usize) { + print!("\n{:#08x}: ", address); + for byte in line { + print!("{:02x} ", *byte); + } + let length: usize = 16 - line.len(); + for _ in 0..length { + print!(" "); + } + print!("|"); + for byte in line { + match is_control(*byte as char) { + true => print!("."), + false => print!("{}", *byte as char), + }; + } + print!("|"); + } + + let esp: usize; + let ebp: usize; + unsafe { asm!("" : "={esp}"(esp), "={ebp}"(ebp):::) }; + println!("esp = {:#x}", esp); + println!("ebp = {:#x}", ebp); + println!("size = {:#X} bytes", ebp - esp); + hexdump(esp, ebp); + flush!(); +} diff --git a/kernel-rs/src/pci/mod.rs b/kernel-rs/src/pci/mod.rs index 2440fe82..827ffb77 100644 --- a/kernel-rs/src/pci/mod.rs +++ b/kernel-rs/src/pci/mod.rs @@ -1,22 +1,79 @@ // https://wiki.osdev.org/PCI -use x86::devices::io::{Pio}; +use x86::devices::io::{Pio, Io}; -pub static mut PCI_CONFIG_ADDRESS: Pio = Pio::new(0xCF8); -pub static mut PCI_CONFIG_DATA: Pio = Pio::new(0xCFC); +pub static mut PCI_CONFIG_ADDRESS: Pio = Pio::new(0xCF8); +pub static mut PCI_CONFIG_DATA: Pio = Pio::new(0xCFC); + +pub fn get_ide1() -> Result { + let bus = 0; + + for slot in 0..31 { + let vendor = pci_config_read_word(bus, slot, 0, 0); + if vendor == 0xffff { + continue; + } + let class = pci_config_read_byte(bus, slot, 0, 11); + let subclass = pci_config_read_byte(bus, slot, 0, 10); + if class == 0x01 && subclass == 0x01 { + return Ok(slot); + } + } + Err(()) +} pub fn lspci() { - pci_config_read_word(1, 1, 1, 2); + let bus = 0; + + for slot in 0..31 { + let vendor = pci_config_read_word(bus, slot, 0, 0); + if vendor == 0xffff { + continue; + } + let header_type = pci_config_read_byte(bus, slot, 0, 14) ; + if header_type & 0x80 != 0 { + // device has multiple functions + for function in 0..0x7 { + let vendor = pci_config_read_word(bus, slot, function, 0); + if vendor != 0xffff { + pci_display(bus, slot, function); + } + } + } else { + pci_display(bus, slot, 0); + } + } } -pub fn pci_config_read_word(bus: u32, slot: u32, func: u32, offset: u32) { - // let address: u64 = (bus as u32) << 16 - // | (slot as u32) << 11 - // | (func as u32) << 8 - // | (offset as u32) & 0xfc - // | 0x80000000; - let address: u64 = 0x80000000; - println!("{} {} {} {}", bus, slot, func, offset); - println!("{:#x}", address); - println!("{:#b}", address); +pub fn pci_display(bus: u32, slot: u32, function: u32) { + let vendor = pci_config_read_word(bus, slot, function, 0); + let device = pci_config_read_word(bus, slot, function, 2); + let class = pci_config_read_byte(bus, slot, function, 11); + let subclass = pci_config_read_byte(bus, slot, function, 10); + println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}", + bus, slot, function, class, subclass, vendor, device); +} + +pub fn pci_access(bus: u32, slot: u32, func: u32, offset: u32) { + let address = (bus as u32) << 16 + | (slot as u32) << 11 + | (func as u32) << 8 + | (offset as u32) & 0xfc + | 0x80000000; + unsafe { PCI_CONFIG_ADDRESS.write(address); } +} + +pub fn pci_config_read_doubleword(bus: u32, slot: u32, func: u32, offset: u32) -> u32 { + pci_access(bus, slot, func, offset); + unsafe { PCI_CONFIG_DATA.read() } +} + +pub fn pci_config_read_word(bus: u32, slot: u32, func: u32, offset: u32) -> u16 { + pci_access(bus, slot, func, offset); + unsafe { (PCI_CONFIG_DATA.read() >> ((offset & 2) * 8)) as u16 } +} + +pub fn pci_config_read_byte(bus: u32, slot: u32, func: u32, offset: u32) -> u8 { + pci_access(bus, slot, func, offset); + unsafe { (PCI_CONFIG_DATA.read() >> ((offset & 3) * 8)) as u8 } } diff --git a/kernel-rs/src/time.rs b/kernel-rs/src/time.rs index 70d1819c..0d29eecf 100644 --- a/kernel-rs/src/time.rs +++ b/kernel-rs/src/time.rs @@ -15,3 +15,8 @@ pub fn realtime() -> (u32, u32) { let sum = start.1 + offset.1; (start.0 + offset.0 + sum / 1_000_000, sum % 1_000_000) } + +pub fn uptime() { + let mut offset = self::OFFSET.lock(); + println!("{}s", offset.0 + offset.1 / 1_000_000); +} diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index e6df8adc..e4ded8b6 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -4,8 +4,6 @@ pub mod cursor; pub use self::color::{Color, ColorCode}; use self::cursor::CURSOR; -use console; - pub static mut VGA: Writer = self::Writer::new(); #[derive(Debug, Clone, Copy)] @@ -16,6 +14,7 @@ struct ScreenChar { } // print wrapper macro around vga +#[allow(unused_macros)] macro_rules! print { ($($arg:tt)*) => ({ $crate::vga::print(format_args!($($arg)*)); @@ -23,6 +22,7 @@ macro_rules! print { } // flushed print +#[allow(unused_macros)] macro_rules! fprint { ($($arg:tt)*) => ({ print!($($arg)*); @@ -31,12 +31,15 @@ macro_rules! fprint { } // print with a line feed +#[allow(unused_macros)] macro_rules! println { + () => ({print!("\n")}); ($fmt:expr) => (print!(concat!($fmt, "\n"))); ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); } // flushed println +#[allow(unused_macros)] macro_rules! fprintln { ($($arg:tt)*) => ({ println!($($arg)*); @@ -73,8 +76,6 @@ pub struct Writer { pub buffer_pos: usize, pub color_code: ColorCode, buffer: [u8; BUFFER_ROWS * BUFFER_COLS], - command: [u8; 10], - command_len: usize, } impl Writer { @@ -83,46 +84,36 @@ impl Writer { buffer_pos: 0, color_code: ColorCode::new(Color::White, Color::Black), buffer: [0; BUFFER_ROWS * BUFFER_COLS], - command: [b'\0'; 10], - command_len: 0, } } - pub fn get_command(&self) -> Result<&str, &'static str> { - match core::str::from_utf8(&self.command) { - Ok(y) => Ok(&y[..self.command_len]), - Err(_) => Err("Command is not utf8 char"), - } - } - - pub fn erase_byte(&mut self) { self.buffer_pos -= 2; let i = self.buffer_pos; self.buffer[i] = b' '; self.buffer[i + 1] = self.color_code.0; self.flush(); - // flush!(); } pub fn write_byte(&mut self, byte: u8) { - let i = self.buffer_pos; - match byte { b'\n' => { let current_line = self.buffer_pos / (BUFFER_COLS); self.buffer_pos = (current_line + 1) * BUFFER_COLS; } byte => { - self.buffer[i] = byte; - self.buffer[i + 1] = self.color_code.0; + self.buffer[self.buffer_pos] = byte; + self.buffer[self.buffer_pos + 1] = self.color_code.0; self.buffer_pos += 2; } } if self.buffer_pos >= self.buffer.len() { self.scroll(); + self.flush(); } + // flushing here is correct but slow + // self.flush(); } pub fn write_str(&mut self, s: &str) { @@ -132,9 +123,7 @@ impl Writer { } fn flush_cursor(&self) { - unsafe { - CURSOR.flush(self.buffer_pos / 2); - } + unsafe { CURSOR.flush(self.buffer_pos / 2); } } pub fn flush(&mut self) { @@ -157,7 +146,6 @@ impl Writer { self.buffer[((BUFFER_ROWS - 1) * BUFFER_COLS) + (col + 1)] = ColorCode::new(Color::White, Color::Black).0; } - self.buffer_pos = (BUFFER_ROWS - 1) * BUFFER_COLS; } } From 3d167f26d5a0f0c68ef2b3a0f63c3f02713d8a26 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 2 Feb 2019 18:46:41 +0100 Subject: [PATCH 150/151] pci, ide stuff --- kernel-rs/mk/qemu.mk | 3 +- kernel-rs/src/acpi/mod.rs | 22 ++--- kernel-rs/src/console.rs | 6 +- kernel-rs/src/keyboard.rs | 2 - kernel-rs/src/lib.rs | 12 ++- kernel-rs/src/pci/ide.rs | 4 + kernel-rs/src/pci/mod.rs | 131 ++++++++++++++++++++---------- kernel-rs/src/scheduling/sleep.rs | 2 +- kernel-rs/src/time.rs | 2 +- kernel-rs/src/vga/mod.rs | 4 +- 10 files changed, 115 insertions(+), 73 deletions(-) create mode 100644 kernel-rs/src/pci/ide.rs diff --git a/kernel-rs/mk/qemu.mk b/kernel-rs/mk/qemu.mk index 99fbe143..014477be 100644 --- a/kernel-rs/mk/qemu.mk +++ b/kernel-rs/mk/qemu.mk @@ -9,7 +9,8 @@ qemu: -enable-kvm\ -curses\ -gdb tcp::$(QEMU_GDB_PORT)\ - -monitor unix:${QEMU_SOCKET},server,nowait + -monitor unix:${QEMU_SOCKET},server,nowait\ + -drive file=disk,if=ide,index=1 qemu-gdb: gdb\ diff --git a/kernel-rs/src/acpi/mod.rs b/kernel-rs/src/acpi/mod.rs index 6a2f1f4b..58882099 100644 --- a/kernel-rs/src/acpi/mod.rs +++ b/kernel-rs/src/acpi/mod.rs @@ -128,33 +128,27 @@ impl Iterator for ACPISDTIter { /// Initalized the ACPI module pub fn init() -> Result<(), &'static str> { - if unsafe{ACPI.valid} { - return Ok(()); - } + if unsafe{ACPI.valid} { return Ok(()); } unsafe { ACPI.init() } } /// Load the ACPI module, addr given is a ptr to RSDP pub fn load(rsdp_addr: u32) -> Result<(), &'static str> { - if unsafe{ACPI.valid} { - return Ok(()); - } + if unsafe{!ACPI.valid} { return Ok(()); } unsafe { ACPI.load(rsdp_addr) } } /// Proceed to ACPI shutdown /// This function doesn't work with Virtual Box yet pub fn shutdown() { - if unsafe{ACPI.valid} { return } - dsdt::shutdown(fadt::get_controlblock().unwrap()); + if unsafe{!ACPI.valid} { return; } + dsdt::shutdown(fadt::get_controlblock().unwrap()).unwrap(); } /// Proceed to ACPI reboot /// This function need ACPI in v2 pub fn reboot() { - if unsafe {!ACPI.valid} { - println!("ACPI not initialized"); - } + if unsafe {!ACPI.valid} { println!("ACPI not initialized"); } if unsafe { ACPI.v2 } { fadt::reboot().unwrap() } else { @@ -166,8 +160,8 @@ pub fn reboot() { pub fn info() { if unsafe { !ACPI.valid } { println!("ACPI not initialized"); return } match fadt::is_enable() { - Ok(True) => println!("ACPI is disabled"), - Ok(False) => println!("ACPI is disabled"), - Err(msg) => println!("error while checking ACPI") + Ok(true) => println!("ACPI is disabled"), + Ok(false) => println!("ACPI is disabled"), + Err(msg) => println!("error while checking ACPI: {}", msg) } } diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index f5c00bca..fa6b5fa5 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -1,6 +1,3 @@ -extern crate core; -// extern crate multiboot2; - use vga::*; use alloc::collections::BTreeMap; @@ -29,7 +26,6 @@ lazy_static! { commands.insert("stack", ::memory::print_stack as fn()); commands.insert("page_fault", ::memory::page_fault as fn()); commands.insert("overflow", ::memory::overflow as fn()); - commands.insert("overflow", ::memory::overflow as fn()); //pci commands.insert("lspci", ::pci::lspci as fn()); @@ -39,7 +35,7 @@ lazy_static! { fn help() { println!("The following commands are available:"); - for (key, val) in COMMANDS.iter() { + for (key, _val) in COMMANDS.iter() { println!("{}", key); } } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index ec4e8766..75787813 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,5 +1,3 @@ -extern crate core; - use console; use x86::devices::io::{Io, Pio}; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index a9ebbbb9..c363c8a5 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -15,6 +15,7 @@ // x86 specific #![feature(abi_x86_interrupt)] +// extern crate core; extern crate alloc; #[macro_use] extern crate lazy_static; @@ -39,11 +40,12 @@ pub mod memory; pub mod arch; pub use arch::x86::consts::*; pub mod scheduling; +#[allow(dead_code)] pub mod time; pub mod pci; -/// kernel entry point. arch module is responsible for -/// calling this once the core has loaded +/// kernel entry point. +/// ::arch is responsible for calling this once the core has loaded. pub fn kmain() -> ! { // memory init after heap is available // memory::init_noncore(); @@ -51,9 +53,11 @@ pub fn kmain() -> ! { // unsafe VGA unsafe { console::CONSOLE.init(); } - if let Ok(slot) = pci::get_ide1() { - println!("found IDE at slot {}", slot); + if let Some(ide) = pci::get_first(0x1, 0x1) { + println!("found IDE at slot {}", ide.slot); + pci::ide::init(ide); } + // scheduler WIP // scheduling::schedule(); unreachable!(); diff --git a/kernel-rs/src/pci/ide.rs b/kernel-rs/src/pci/ide.rs new file mode 100644 index 00000000..f817db3e --- /dev/null +++ b/kernel-rs/src/pci/ide.rs @@ -0,0 +1,4 @@ +use super::*; + +pub fn init(drive: Pci) { +} diff --git a/kernel-rs/src/pci/mod.rs b/kernel-rs/src/pci/mod.rs index 827ffb77..20652210 100644 --- a/kernel-rs/src/pci/mod.rs +++ b/kernel-rs/src/pci/mod.rs @@ -1,59 +1,106 @@ // https://wiki.osdev.org/PCI - use x86::devices::io::{Pio, Io}; +use alloc::vec::*; + +pub mod ide; pub static mut PCI_CONFIG_ADDRESS: Pio = Pio::new(0xCF8); pub static mut PCI_CONFIG_DATA: Pio = Pio::new(0xCFC); -pub fn get_ide1() -> Result { - let bus = 0; - - for slot in 0..31 { - let vendor = pci_config_read_word(bus, slot, 0, 0); - if vendor == 0xffff { - continue; - } - let class = pci_config_read_byte(bus, slot, 0, 11); - let subclass = pci_config_read_byte(bus, slot, 0, 10); - if class == 0x01 && subclass == 0x01 { - return Ok(slot); - } - } - Err(()) +pub struct Pci { + pub bus: u32, + pub slot: u32, + pub func: u32, + pub device: u16, + pub vendor: u16, + pub class: u8, + pub subclass: u8, + pub header_type: u8, } pub fn lspci() { - let bus = 0; - - for slot in 0..31 { - let vendor = pci_config_read_word(bus, slot, 0, 0); - if vendor == 0xffff { - continue; - } - let header_type = pci_config_read_byte(bus, slot, 0, 14) ; - if header_type & 0x80 != 0 { - // device has multiple functions - for function in 0..0x7 { - let vendor = pci_config_read_word(bus, slot, function, 0); - if vendor != 0xffff { - pci_display(bus, slot, function); - } - } - } else { - pci_display(bus, slot, 0); - } + for pci in self::get_all() { + println!("{}", pci); } } -pub fn pci_display(bus: u32, slot: u32, function: u32) { - let vendor = pci_config_read_word(bus, slot, function, 0); - let device = pci_config_read_word(bus, slot, function, 2); - let class = pci_config_read_byte(bus, slot, function, 11); - let subclass = pci_config_read_byte(bus, slot, function, 10); - println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}", - bus, slot, function, class, subclass, vendor, device); +pub fn get_all() -> Vec { + let bus = 0; + let mut slot = 0; + let mut pcis: Vec = Vec::new(); + + while let Some(pci)= pci_get(bus, slot, 0) { + if pci.header_type & 0x80 != 0 { + let mut func = 0; + while let Some(pci)= pci_get(bus, slot, func) { + // device has multiple functions + pcis.push(pci); + func += 1; + if func == 7 {break;} + } + } + pcis.push(pci); + slot += 1; + if slot == 32 {break;} + } + pcis } +pub fn get_first(class: u8, subclass: u8) -> Option { + let bus = 0; + let mut slot = 0; + + while let Some(pci)= pci_get(bus, slot, 0) { + if pci.class == class && pci.subclass == subclass { + return Some(pci); + } + if pci.header_type & 0x80 != 0 { + let mut func = 0; + while let Some(pci)= pci_get(bus, slot, func) { + // device has multiple functions + if pci.class == class && pci.subclass == subclass { + return Some(pci); + } + func += 1; + if func == 7 {break;} + } + } + slot += 1; + if slot == 32 {break;} + } + None +} + +pub fn pci_get(bus: u32, slot: u32, func: u32) -> Option { + let vendor = pci_config_read_word(bus, slot, func, 0); + if vendor == 0xffff { return None } + let pci = Pci {bus, slot, func, vendor, + device: pci_config_read_word(bus, slot, func, 2), + subclass: pci_config_read_byte(bus, slot, func, 10), + class: pci_config_read_byte(bus, slot, func, 11), + header_type: pci_config_read_byte(bus, slot, func, 14), + }; + Some(pci) +} + +use core::fmt; +impl fmt::Display for Pci { + fn fmt(&self, f: &mut core::fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}.{} {:#x},{:#x} {:#x} {:#x}", + self.bus, self.slot, self.func, + self.class, self.subclass, + self.vendor, self.device); + Ok(()) + } +} + +// pub fn pci_display(bus: u32, slot: u32, function: u32) { +// let vendor = pci_config_read_word(bus, slot, function, 0); +// let device = pci_config_read_word(bus, slot, function, 2); +// println!("{}:{}.{} {:#x},{:#x}: {:#x} {:#x}", +// bus, slot, function, class, subclass, vendor, device); +// } + pub fn pci_access(bus: u32, slot: u32, func: u32, offset: u32) { let address = (bus as u32) << 16 | (slot as u32) << 11 diff --git a/kernel-rs/src/scheduling/sleep.rs b/kernel-rs/src/scheduling/sleep.rs index af69d146..ca453133 100644 --- a/kernel-rs/src/scheduling/sleep.rs +++ b/kernel-rs/src/scheduling/sleep.rs @@ -3,7 +3,7 @@ //! way the scheduling algorithms don't have to worry about //! managing these //! -//! inspired from https://wiki.osdev.org/Blocking_Process +//! https://wiki.osdev.org/Blocking_Process use alloc::collections::vec_deque::VecDeque; use super::*; diff --git a/kernel-rs/src/time.rs b/kernel-rs/src/time.rs index 0d29eecf..ce8cc0aa 100644 --- a/kernel-rs/src/time.rs +++ b/kernel-rs/src/time.rs @@ -17,6 +17,6 @@ pub fn realtime() -> (u32, u32) { } pub fn uptime() { - let mut offset = self::OFFSET.lock(); + let offset = self::OFFSET.lock(); println!("{}s", offset.0 + offset.1 / 1_000_000); } diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index e4ded8b6..2d8834ab 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -67,8 +67,6 @@ pub fn print(args: fmt::Arguments) { } } -extern crate core; - const BUFFER_ROWS: usize = 25; const BUFFER_COLS: usize = 80 * 2; @@ -153,7 +151,7 @@ impl Writer { // trait needed by formatting macros use core::fmt; impl fmt::Write for Writer { - fn write_str(&mut self, s: &str) -> ::core::fmt::Result { + fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { self.write_byte(byte) } From 26093882f5793998d535c3d040192a3538ea5384 Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Sat, 17 Aug 2019 02:24:41 +0200 Subject: [PATCH 151/151] new repo --- kernel-rs/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-rs/README.md b/kernel-rs/README.md index c27a0f95..cb0340cc 100644 --- a/kernel-rs/README.md +++ b/kernel-rs/README.md @@ -1,3 +1,5 @@ +# !! Switched to ziglang -> [new repo here](https://github.com/jzck/kernel-zig) !! + Kernel from scratch (KFS) series of projects at Ecole 42 ! ### [documentation](https://jzck.github.io/kernel/bluesnow/index.html)