Giter Site home page Giter Site logo

phil-opp / blog_os Goto Github PK

View Code? Open in Web Editor NEW
14.0K 283.0 1.0K 17.5 MB

Writing an OS in Rust

Home Page: http://os.phil-opp.com

License: Apache License 2.0

Shell 0.09% Python 0.21% HTML 96.51% CSS 1.22% JavaScript 0.37% Dockerfile 0.07% SCSS 1.52%
kernel rust operating-system x86-64

blog_os's Introduction

Blog OS

This repository contains the source code for the Writing an OS in Rust series at os.phil-opp.com.

If you have questions, open an issue or chat with us on Gitter.

Where is the code?

The code for each post lives in a separate git branch. This makes it possible to see the intermediate state after each post.

The code for the latest post is available here.

You can find the branch for each post by following the (source code) link in the post list below. The branches are named post-XX where XX is the post number, for example post-03 for the VGA Text Mode post or post-07 for the Hardware Interrupts post. For build instructions, see the Readme of the respective branch.

You can check out a branch in a subdirectory using git worktree:

git worktree add code post-10

The above command creates a subdirectory named code that contains the code for the 10th post ("Heap Allocation").

Posts

The goal of this project is to provide step-by-step tutorials in individual blog posts. We currently have the following set of posts:

Bare Bones:

Interrupts:

Memory Management:

Multitasking:

First Edition Posts

The current version of the blog is already the second edition. The first edition is outdated and no longer maintained, but might still be useful. The posts of the first edition are:

Click to expand

Bare Bones:

Memory Management:

Exceptions:

Additional Resources:

License

This project, with exception of the blog/content folder, is licensed under either of

at your option.

For licensing of the blog/content folder, see the blog/content/README.md.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

blog_os's People

Contributors

acheronfail avatar acyanbird avatar alaincao avatar alexandremarcq avatar alexxroche avatar asami-okina avatar bors[bot] avatar briankung avatar connortsui20 avatar delta1 avatar donald-pinckney avatar drprofesq avatar firenezz avatar foo-x avatar hamidrezakp avatar hecatia-elegua avatar hi-rustin avatar inpermutation avatar joe1994 avatar johntitor avatar karbonitekream avatar maximevaillancourt avatar mhbahrampour avatar phil-opp avatar robert-w-gries avatar skierpage avatar steveklabnik avatar swnakamura avatar themimicodes avatar toothbrush7777777 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog_os's Issues

Nasm warning on checksum calculation on Mac OS

dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))

produces the warning:

multiboot_header.asm:7: warning: numeric constant 0x100000000 does not fit in 32 bits

The following version compiles without warnings (but causes a warning on Linux):

dd - (0xe85250d6 + 0 + (header_end - header_start))

See comment from Georgiy Slobodenyuk.

Table of Contents

Most of the posts are pretty long, so a table of contents might be a good idea.

Fix warnings

Currently the compiler issues the following warnings:

src/memory/paging/table.rs:90:1: 90:15 warning: enum is never used: `Level3`, #[warn(dead_code)] on by default
src/memory/paging/table.rs:90 enum Level3 {}
                              ^~~~~~~~~~~~~~
src/memory/paging/table.rs:91:1: 91:15 warning: enum is never used: `Level2`, #[warn(dead_code)] on by default
src/memory/paging/table.rs:91 enum Level2 {}
                              ^~~~~~~~~~~~~~
src/memory/paging/table.rs:32:27: 32:44 warning: private trait in public interface (error E0445), #[warn(private_in_public)] on by default
src/memory/paging/table.rs:32 impl<L> Table<L> where L: HierarchicalLevel
                                                        ^~~~~~~~~~~~~~~~~
src/memory/paging/table.rs:32:27: 32:44 warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

src/memory/paging/mapper.rs:88:5: 93:6 warning: method is never used: `map`, #[warn(dead_code)] on by default
src/memory/paging/mapper.rs:88     pub fn map<A>(&mut self, page: Page, flags: EntryFlags, allocator: &mut A)
src/memory/paging/mapper.rs:89         where A: FrameAllocator
src/memory/paging/mapper.rs:90     {
src/memory/paging/mapper.rs:91         let frame = allocator.allocate_frame().expect("out of memory");
src/memory/paging/mapper.rs:92         self.map_to(page, frame, flags, allocator)
src/memory/paging/mapper.rs:93     }
src/memory/paging/mapper.rs:102:44: 102:53 warning: unused variable: `allocator`, #[warn(unused_variables)] on by default
src/memory/paging/mapper.rs:102     pub fn unmap<A>(&mut self, page: Page, allocator: &mut A)
                                                                           ^~~~~~~~~
src/memory/paging/mapper.rs:112:13: 112:18 warning: unused variable: `frame`, #[warn(unused_variables)] on by default
src/memory/paging/mapper.rs:112         let frame = p1[page.p1_index()].pointed_frame().unwrap();
                                            ^~~~~

The warnings in mapper.rs are ok (we don't use these values yet), but the table.rs warnings need to get fixed.

  • make HierachicalLevel, Level3, and Level2 public
  • fix the dead code warnings for Level3 and Level2 (why is it even dead code?)

Migrate to kramdown

Currenly we use redcarpet, which won't be available after May 1st.

Alternative: switch to hugo.

Mac OS support

Some Mac OS users seem to have tool problems in the first post. So it might be a good idea to create a separate page that lists all needed extra steps (such as updating nasm).

Unfortunately, I have zero Mac experience and can only copy instructions from the post's comments. So if someone got it working, I would really appreciate a list of required commands!

Flush tlb also on `map_to` for exotic CPUs

Because Intel CPUs don't remember "not present" pages, documentation from Intel may say that you don't need to invalidate when changing a page from "not present" to "present". Intel's documentation is only correct for Intel CPUs. It is not correct for all 80x86 CPUs. Some CPUs (mostly Cyrix) do remember when a page was "not present" and because of those CPUs you do have to invalidate when changing a page from "not present" to "present".

From this stackoverflow answer: http://stackoverflow.com/a/28384866/866447

Extend some explanations

Some issues that were brought up by rylev on IRC:

  • "CPUID check" too fast
  • more assembly explanations, especially cmp and jmp

Update: below @mtnygard mentioned some issues with Printing to Screen:

  • too quick
  • unclear code fragments (which file? function or impl method?)
  • better document the lib.rs and Cargo.toml changes required for Unique and spin
  • type conflict: byte strings vs definition of write_str

VGA colors: 'variant is never used'

Rust complains that most of the VGA colour constants are dead code. This creates a big pile of compiler warnings to wade through; perhaps this enum should have the #[allow(dead_code)] attribute?

What is a frame?

Your blog series is normally easy to follow, but I got a bit lost when I started reading "Frame Allocation" because you leapt straight in without saying what a frame is. Could you dedicate a paragraph or two to this so the reader knows where they're standing?

Long mode test is wrong

Should be:

test_long_mode:
    mov eax, 0x80000000    ; Set the A-register to 0x80000000.
    cpuid                  ; CPU identification.
    cmp eax, 0x80000001    ; Compare the A-register with 0x80000001.
    jb .no_long_mode       ; It is less, there is no long mode.
    mov eax, 0x80000001    ; Set the A-register to 0x80000001.
    cpuid                  ; CPU identification.
    test edx, 1 << 29      ; Test if the LM-bit, which is bit 29, is set in the D-register.
    jz .no_long_mode       ; They aren't, there is no long mode.
    ret

But is:

check_long_mode:
    mov eax, 0x80000000    ; Set the A-register to 0x80000000.
    cpuid                  ; CPU identification.
    cmp eax, 0x80000001    ; Compare the A-register with 0x80000001.
    jb .no_long_mode       ; It is less, there is no long mode.
    mov eax, 0x80000000    ; Set the A-register to 0x80000000.
    cpuid                  ; CPU identification.
    cmp eax, 0x80000001    ; Compare the A-register with 0x80000001.
    jb .no_long_mode       ; It is less, there is no long mode.
    ret

Add some notes regarding problems with `grub-mkrescue`

It seems like grub-mkrescue causes some issues. See this comment.

Update: We should add some notes regarding

  • the different naming of grub-mkrescue in some distros (grub2-mkrescue)
  • the need for mtools (to create an EFI image) or -d /usr/lib/grub/i386-pc (to avoid EFI) on EFI systems
  • that xorriso is contained in libisoburn for some distros

PhysicalAddress and VirtualAddress types probably shouldn't be interoperable

At the moment you define PhysicalAddress and VirtualAddress as synonyms via the type keyword, but this has the sideeffect that either can be passed to functions that take the other since they're both usize. It might be worth defining them via the newtype pattern (struct PhysicalAddress(usize);) instead.

[Page Tables] Do we need atomics for `Entry`?

Right now an Entry is just an u64. Maybe it should be an AtomicUsize instead.

The reason is that we're modifying the tables through recursive mapping and thus have some magic addresses. The compiler and the CPU don't know this and could maybe reorder instructions in a wrong way.

For example, it would be bad if the following is reordered (pseudo code):

create_p3_table(p4[0x42]);
modify 0xffffffffffe42000; // the magic address to the created table

If some optimizer would cause modification of the magic address before the p3 is created, it would cause a page fault.

The question is: Is it possible that an optimizer does such things?

Add short introduction on the front page

It would be nice to have some kind of introduction on the front page, which describes the scope of the project and provides some links (e.g. to the github repo). Then we could also remove the ugly Latest Post banner.

vga_buffer.rs: `Unique<>` is unstable

src/vga_buffer.rs:1:5: 1:22 error: use of unstable library feature 'unique': needs an RFC to flesh out design (see issue #27730)
src/vga_buffer.rs:1 use core::ptr::Unique;
                        ^~~~~~~~~~~~~~~~~
src/vga_buffer.rs:1:5: 1:22 help: add #![feature(unique)] to the crate attributes to enable

grub-mkrescue needs xorriso

For post 1, Would be nice to point out that grub-mkrescue needs xorriso installed. The command throws a cryptic error about xorriso version otherwise. Would be nice to save a (albeit quick) Google search.

AreaFrameAllocator no longer safe to use after remapping the kernel

The AreaFrameAllocator is unsafe to use after kernel remapping because it references the multiboot information structure, which is not remapped. I'm not sure what your next steps are (it's possible this is by design) but this took me a hot second to debug once I got through your last post and started off on my own adventures. If other people are having similar problems you have a couple choices:

  • Stop using the AreaFrameAllocator and us some other FrameAllocator after the kernel remap
  • Remap the multiboot header in remap_the_kernel, like you did the VGA buffer

You already have a reference to the boot_info object in remap_the_kernel, so you can use that for the remap. It's a bit ghetto, but here's a quick implementation of the latter option:

let boot_info_frame = Frame::containing_address(boot_info as *const _ as usize);
mapper.identity_map(boot_info_frame, PRESENT, allocator);

Compiling and running the blog_os

image

Is this what the start up is supposed to look like when you download and do make run?

It is complaining there is no bootable device.

fatal: unrecognised output format 'elf64' on OS X

➜  os-rust  nasm -f elf64 multiboot_header.asm
nasm: fatal: unrecognised output format 'elf64' - use -hf for a list

This is the error I get when going through part one of your tutorial when trying to specify elf64 as the format for the linked executable.

nasm -hf lists:

valid output formats for -f are (`*' denotes default):
  * bin       flat-form binary files (e.g. DOS .COM, .SYS)
    aout      Linux a.out object files
    aoutb     NetBSD/FreeBSD a.out object files
    coff      COFF (i386) object files (e.g. DJGPP for DOS)
    elf       ELF32 (i386) object files (e.g. Linux)
    as86      Linux as86 (bin86 version 0.3) object files
    obj       MS-DOS 16-bit/32-bit OMF object files
    win32     Microsoft Win32 (i386) object files
    rdf       Relocatable Dynamic Object File Format v2.0
    ieee      IEEE-695 (LADsoft variant) object file format
    macho     NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files

Setting unneeded `write protect` bit when enabling paging

Ahmed Charles noted in a comment that we set the write protect bit when enabling paging. It's bit 16 in the CR0 register, Wikipedia describes it like this:

When set, the CPU can't write to read-only pages when privilege level is 0

The question is wether we should keep it (and add an explaining comment) or remove it (since it's not required for the switch to long mode).

I think it's reasonable to set it but maybe it's better to do it in a later post when it's required. When we remove it, it must not cause problems for people with the old version.

Any opinions are appreciated :).

Compare / contrast my VGA driver

Hey Phil,

Thanks again for a rad tutorial. I've been trying to do stuff on my own, while sort of peeking back at your stuff for hints. Given that 'print to the screen' is mostly Just Rust, I tried doing it myself. I figured opening an issue might be a decent way to discuss the differences, I'm not sure it's the right thing, let me know if I should have emailed you. 😄

Here's where I'm at: https://github.com/steveklabnik/nucleus/blob/cec875df64d988d707537c8058aa4862a532ef36/vga/src/lib.rs

The big difference, looking back, is in the way we built the buffer: I made mine a single, long buffer, and did calculations to get the x/y going. I also wrote a flush() that ends up doing the writing of the buffer to the screen, which is just a copy, since the buffer now has the same representation as the VGA memory itself.

Your code also handles long lines correctly; I'll have to fix mine to take this into account. I also don't need Unique, due to flush() handling it.

And I think I spotted another bug, I'm making the arrays twice as long as they need to be, now that they hold the struct rather than the bytes they did before...

Anyway. Would be interested in hearing your thoughts, or if I've done something else silly somewhere.

might be good to remind users to override rust to nightly

in ubuntu 14.04 after installing multirust and running the command multirust update nightly I ran into the following error:

 #[feature] may not be used on the stable release channel

which suggested I was still using stable. running multirust override nightly did the trick, may be worth throwing into your document for other newbie readers such as myself.

Thanks for making a really excellent tutorial by the way!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.