Compare commits

...

468 Commits

Author SHA1 Message Date
Philipp Oppermann
87d95dbf0d Update to latest bit_field version
(cherry picked from commit 46100ba24b)
2017-01-25 13:53:10 +01:00
Philipp Oppermann
91672e3cac The ReadWrite flag isn't needed for code segments (#279)
(cherry picked from commit fce85e68ee)
2017-01-18 13:13:59 +01:00
Philipp Oppermann
a91322017e Load null selectors to all data registers
This is required for some instructions such as iretq (ss must be valid or 0).

(cherry picked from commit 8f8b46a9b6)
2017-01-15 14:18:35 +01:00
Philipp Oppermann
f0df9fb937 Data segments aren't needed for 64-bit mode
(cherry picked from commit e179dadf70)
2017-01-15 14:14:47 +01:00
Philipp Oppermann
135d8891f3 Make panic_fmt public to fix private_no_mangle_fns warning
(cherry picked from commit 1be2f42791)
2017-01-04 16:24:35 +01:00
Philipp Oppermann
58de55a2d4 Mark panic_fmt as no_mangle to work around rust-lang/rust#38281
(cherry picked from commit 081105bbb6)
(cherry picked from commit 1acc1ff5806f2fa101f726644d258eb4e4543540)
2017-01-04 16:10:32 +01:00
Philipp Oppermann
94d4f8df8e Update x86 crate to version 0.8.0 (#266)
(cherry picked from commit 02697891e2)
2016-12-21 15:09:45 +01:00
Philipp Oppermann
d5c84a860a Remove cargo workspace (#265)
(cherry picked from commit fcd453ac29)
2016-12-21 14:47:40 +01:00
Philipp Oppermann
ce6b43cc9b Fix panic_fmt arguments: file is a &'static str
(cherry picked from commit e9735738f7)
2016-11-26 12:29:31 +01:00
Philipp Oppermann
090e0785ff Use references for the ExceptionStackFrame argument
We require/assume that these pointers are correct. Using references is cleaner than blindly dereferencing raw pointers.

Important: The Rust book guarantees that: “At runtime, a raw pointer * and a reference pointing to the same piece of data have an identical representation.”
(cherry picked from commit 15feb9a120)
2016-11-01 18:01:24 +01:00
Philipp Oppermann
5ce6655aa1 Remove print_error and use normal println in exception handlers
(cherry picked from commit 9b83b2853e)
2016-10-31 01:32:53 +01:00
Philipp Oppermann
e8d1f96b76 Create a new print function and use it in the print macro
This fixes the deadlock problem, because the format_args is now evaluated before locking the screen writer. So `println!("{:?}", {println!("");})` no longer triggers a deadlock.

(cherry picked from commit d96df500a7)
2016-10-31 01:22:52 +01:00
Philipp Oppermann
e09df45b9b Use volatile operations for accessing the VGA buffer
(cherry picked from commit d7a445b1bb)
2016-10-08 15:55:28 +02:00
Philipp Oppermann
7f80db6fb4 Add missing license headers and update copyright year (#232)
(cherry picked from commit a04924955a)
2016-10-02 18:31:20 +02:00
Philipp Oppermann
c764e6bb43 Add missing license headers (#233)
(cherry picked from commit 0f4d1ce303)
2016-10-02 18:29:52 +02:00
Philipp Oppermann
0ec126fc7d Use crates.io version of multiboot2
(cherry picked from commit c6b1346956)
2016-09-27 13:56:43 +02:00
Calvin Lee
258a7d1aba Fixes #220: BumpAllocator overflow
I also fixed a spelling error and replaced a tab with a space
in the blog post where `allocate()` was created.

(cherry picked from commit 54e02fd6b5)
(cherry picked from commit 3a2f0b33297164ebbfab92ee76881b6c06c4914d)
2016-09-27 13:41:01 +02:00
Philipp Oppermann
6e20fe17db Update bit_field to 0.5.0 and use new API
(cherry picked from commit 6eba03dd58)
2016-09-27 13:38:15 +02:00
Philipp Oppermann
2aeeaecf86 Create a cargo workspace for subcrates
(cherry picked from commit 488a3c16f0)
2016-08-05 11:29:19 +02:00
Philipp Oppermann
e63dda6953 Add missing rsi clobber in code as well
(cherry picked from commit 46d41d9c3d)
2016-08-04 01:13:34 +02:00
Philipp Oppermann
af8578ec78 Fix .travis.yml for tag build 2016-08-03 16:54:27 +02:00
Philipp Oppermann
4c9f7cfbee Update README for better_exception_messages tag 2016-08-03 16:53:44 +02:00
Philipp Oppermann
c26fb53547 Remove blog and scripts subdirs 2016-08-03 16:51:58 +02:00
Philipp Oppermann
7871e4008a Fix github tag link 2016-08-03 16:48:02 +02:00
Philipp Oppermann
e1a90fe3ab Final improvements 2016-08-03 16:42:47 +02:00
Philipp Oppermann
e17fd2d0de Run rustfmt 2016-08-03 16:41:49 +02:00
Philipp Oppermann
2df8517816 Translate error code and print cr2 register 2016-08-03 16:39:38 +02:00
Philipp Oppermann
550a99cfd4 Add and test a handler_with_error_code macro and a page fault handler 2016-08-03 16:36:58 +02:00
Philipp Oppermann
86a757cb61 Add and test an invalid opcode handler function 2016-08-03 16:26:22 +02:00
Philipp Oppermann
bf72618647 Add a handler macro that creates wrapper functions 2016-08-03 16:24:43 +02:00
Philipp Oppermann
308b033ea9 Add a wrapper function and print the exception stack frame 2016-08-03 16:22:59 +02:00
Philipp Oppermann
07bef978ad Silence dead code warnings 2016-08-03 16:00:04 +02:00
Philipp Oppermann
ee48ec5e29 Reset src to master to be able to follow step-by-step 2016-08-03 16:00:04 +02:00
Philipp Oppermann
6590531a41 Provoke a page fault 2016-08-03 16:00:04 +02:00
Philipp Oppermann
df99382cda Print cr2 in page_fault_handler 2016-08-03 16:00:04 +02:00
Philipp Oppermann
979663acda Rename to better-exception-messages 2016-08-03 16:00:04 +02:00
Philipp Oppermann
8bb46c6b62 Finish exceptions diagnostics post 2016-08-03 16:00:03 +02:00
Philipp Oppermann
4eda7993a2 Add handler! macros 2016-08-03 16:00:03 +02:00
Philipp Oppermann
b949fba62f Next section: Debug the failure on real hardware 2016-08-03 14:44:52 +02:00
Philipp Oppermann
83978e8417 Add a ToC 2016-08-03 14:44:52 +02:00
Philipp Oppermann
9113a63f5e Test the two-stage exception handler in code 2016-08-03 14:44:52 +02:00
Philipp Oppermann
9e45cf65bc Describe the two-stage exception handler 2016-08-03 14:44:52 +02:00
Philipp Oppermann
06fb4d6596 WIP code for upcoming post 2016-08-03 14:44:52 +02:00
Philipp Oppermann
95c0452bcb Begin new post 2016-08-03 14:44:52 +02:00
Philipp Oppermann
68e2495d9c Rename modifying-page-tables.md to page-tables.md 2016-08-03 14:43:01 +02:00
Philipp Oppermann
9469dc5891 Remove coarse class from ToCs
We will add it dynamically via javascript when the Toc is higher than the viewport.
2016-07-28 19:42:37 +02:00
Anton Strömkvist
6b2f1281ae Fix hex constant (#193)
I assume these were in the wrong order since all the others looked this way :)
2016-07-28 18:01:42 +02:00
Philipp Oppermann
826e303ed0 Merge pull request #192 from phil-opp/post-toc
Add tables of contents to all blog posts
2016-07-17 17:14:50 +02:00
Philipp Oppermann
d4e82b0aa4 Improve heading levels 2016-07-17 17:10:42 +02:00
Philipp Oppermann
bc6f496eb5 Add tables of contents to all blog posts 2016-07-17 17:10:23 +02:00
Philipp Oppermann
62dd13b2e7 Merge pull request #190 from phil-opp/p1
Add aligned .got and .got.plt sections to linker script
2016-07-16 17:22:25 +02:00
Philipp Oppermann
68c1e42356 Update linker script in post (add .got and .got.plt) 2016-07-14 18:11:58 +02:00
Philipp Oppermann
2445b47661 Add aligned .got and .got.plt sections to linker script 2016-07-14 18:07:26 +02:00
Philipp Oppermann
d64e4ba2fc Update x86 crate to 0.7.1 (#189) 2016-07-14 11:21:04 +02:00
Aaron Hill
48e7faa521 Add ENTRY(start) to 'Allocating Frames' blog post linker script (#188) 2016-06-29 09:19:08 +02:00
Philipp Oppermann
f8c5bc5dec Merge pull request #187 from phil-opp/divide_by_zero
Catch divide error instead of page fault
2016-06-25 17:13:29 +02:00
Philipp Oppermann
ca438d9740 Revise plans for the upcoming post 2016-06-25 17:12:04 +02:00
Philipp Oppermann
702e49eaf7 Catch divide-by-zero errors and introduce inline assembly
This commit updates the “Catching Exceptions” post to catch divide-by-zero errors instead of page faults. The reason is a subtle stack alignment bug, which is somehow caused by the additional error code on a page fault. This commit also adds a short introduction to inline assembly.
2016-06-25 17:12:04 +02:00
Philipp Oppermann
e8b3a1fff1 Catch divide error instead of page fault
The divide error pushes no error code. Thus we avoid stack misalignment (see #184).
2016-06-25 17:12:04 +02:00
Philipp Oppermann
c9d8afe434 Run rustfmt 2016-06-25 17:08:26 +02:00
Philipp Oppermann
2f9e6cc0d0 Minor improvements to catching exceptions post 2016-06-25 17:06:57 +02:00
Philipp Oppermann
84ba085a0a The section will be only about exceptions (#186) 2016-06-24 13:59:17 +02:00
Philipp Oppermann
b7a47ee001 Add gitter badge (#183) 2016-06-24 13:54:35 +02:00
Philipp Oppermann
e4cc5b84f1 Merge pull request #185 from phil-opp/unwind_resume
Create dummy _Unwind_Resume function to fix libcore linker errors
2016-06-24 13:44:54 +02:00
Philipp Oppermann
f00360d553 Add and explain dummy _Unwind_Resume function in “Set Up Rust” post 2016-06-24 13:37:03 +02:00
Philipp Oppermann
952f7ed5e3 Create dummy _Unwind_Resume function to fix libcore linker errors 2016-06-24 13:37:02 +02:00
Philipp Oppermann
76b83c623e Revert "Remove unneeded gcc_except_table section" (#180) 2016-06-13 18:36:01 +02:00
Philipp Oppermann
20d9037740 Merge pull request #178 from phil-opp/patch5
Remove unneeded gcc_except_table section
2016-06-12 16:36:00 +02:00
Philipp Oppermann
1fb6369f61 Remove unneeded gcc_except_table section from blog post 2016-06-12 16:33:55 +02:00
Philipp Oppermann
1083ac9bac Remove unneeded gcc_except_table section 2016-06-12 16:32:34 +02:00
Ryan Campbell
793eeebfb3 Add missing open brace (#177) 2016-06-10 20:36:33 +02:00
Steve Klabnik
1183f5d1e1 Update section header to reflect changes in the text (#176) 2016-06-07 21:48:54 +02:00
Philipp Oppermann
bddf35f365 Add missing link to bit_field crate (#174) 2016-06-01 01:21:16 +02:00
Jordan Danford
bf0e70746d Change 'boot load' to 'boot loop' in 'Remap the Kernel' section (#173) 2016-05-31 09:11:14 +02:00
Homu
c22e1e8bb1 Auto merge of #172 - phil-opp:phil-opp-patch-1, r=phil-opp
Recommend rustup instead of multirust
2016-05-30 23:58:02 +09:00
Philipp Oppermann
4fae6e4731 Recommend rustup instead of multirust 2016-05-30 16:57:28 +02:00
Philipp Oppermann
c2336ceece Make cross-compile-* and set-up-gdb pages additional resourses 2016-05-29 19:58:44 +02:00
Philipp Oppermann
2f0a3459ad Merge pull request #170 from phil-opp/cargo-panic-abort
Use the `panic=abort` option instead of `-Z no-landing-pads`
2016-05-29 18:49:30 +02:00
Philipp Oppermann
0f5ec6f129 Update “Kernel Heap”: The _Unwind_Resume linker error shouldn't occur anymore 2016-05-29 18:47:38 +02:00
Philipp Oppermann
5d13ff7c3a Add update note 2016-05-29 18:38:14 +02:00
Philipp Oppermann
d7b05bc6b4 Update “Set Up Rust” post to use the cargo panic option 2016-05-29 18:35:16 +02:00
Philipp Oppermann
f4eb589f19 We don't need _Unwind_Resume anymore 2016-05-29 18:00:58 +02:00
Philipp Oppermann
725c452157 Use the panic=abort option instead of -Z no-landing-pads 2016-05-29 18:00:29 +02:00
Philipp Oppermann
01f9f1056c Merge pull request #169 from phil-opp/missing-pub
Make methods of EntryOptions public
2016-05-29 17:26:48 +02:00
Philipp Oppermann
9ea7ee6f57 Make methods of EntryOptions public in post 2016-05-29 17:25:11 +02:00
Philipp Oppermann
480265872d Make methods of EntryOptions public 2016-05-29 17:24:21 +02:00
Philipp Oppermann
165bf096a7 Merge pull request #164 from phil-opp/catching-exceptions
Add new post about “Catching Exceptions”
2016-05-28 16:00:31 +02:00
Philipp Oppermann
f58a6fe185 Add a print_error function, which works for exceptions inside println 2016-05-28 15:47:34 +02:00
Philipp Oppermann
c1df1d3354 Initialize the IDT and provoke a page fault 2016-05-28 15:47:34 +02:00
Philipp Oppermann
2d15a7bdb1 Make HandlerFunc public, because it is part of a public interface 2016-05-28 15:47:34 +02:00
Philipp Oppermann
c65b16f42d Create a static IDT with a page fault handler function 2016-05-28 15:47:34 +02:00
Philipp Oppermann
b84c5822df Create interrupt module with IDT submodule 2016-05-28 15:47:34 +02:00
Philipp Oppermann
245125cb4a Minor improvements to post 2016-05-28 15:47:33 +02:00
Philipp Oppermann
e2b45d3971 Fix minor errors in code snippets 2016-05-28 15:46:47 +02:00
Philipp Oppermann
865e74bfad We don't overhaul our build system yet 2016-05-28 14:37:19 +02:00
Philipp Oppermann
745b1f6a0b Improve _Unwind_Resume description and remove claim about the “next post” 2016-05-28 14:36:23 +02:00
Philipp Oppermann
3b71e9e5a0 Add “Catching Exceptions” post to README 2016-05-28 14:15:20 +02:00
Philipp Oppermann
e4b42b106f Reset source code to master again 2016-05-28 14:09:45 +02:00
Philipp Oppermann
08540eb602 Remove unneeded unsafe 2016-05-28 14:09:17 +02:00
Philipp Oppermann
4633f84af6 Finish catching-exceptions post 2016-05-28 14:09:17 +02:00
Philipp Oppermann
5054e48c9a Remove unneeded pubs 2016-05-28 14:09:17 +02:00
Philipp Oppermann
13e94de7b4 Make the load function safe 2016-05-28 14:09:17 +02:00
Philipp Oppermann
8540d3844b Use new x86::segmentation::cs function and merge set_handler and options
We avoid inline assembly and increase safety (it is no longer possible to set the non-present initilization entries to present).
2016-05-28 14:09:17 +02:00
Philipp Oppermann
968ae00de7 Update blog post 2016-05-28 14:09:17 +02:00
Philipp Oppermann
cbe034f3a5 wip 2016-05-28 14:09:17 +02:00
Philipp Oppermann
c961fdc32b wip 2016-05-28 14:09:17 +02:00
Philipp Oppermann
59382699d0 wip 2016-05-28 14:09:17 +02:00
Philipp Oppermann
74f33c0f44 Use own Itd entry type 2016-05-28 14:09:17 +02:00
Philipp Oppermann
78655d6bef Add bit_field dependency 2016-05-28 14:09:17 +02:00
Philipp Oppermann
431bb39fdb Begin work for exceptions post 2016-05-28 14:09:17 +02:00
Philipp Oppermann
7c565abba8 Fix: hole_list_allocator instead of linked_list_allocator (#161)
Reported by @simonlovgren in #160
2016-05-17 14:35:53 +02:00
Philipp Oppermann
a59f51766a Merge pull request #159 from phil-opp/update_bitflags
Update bitflags to 0.7.0
2016-05-15 12:32:22 +02:00
Philipp Oppermann
e383a9235a Update post to use bitflags 0.7.0 2016-05-15 12:29:29 +02:00
Philipp Oppermann
1703827da2 Update to bitflags 0.7.0 2016-05-15 12:27:43 +02:00
Philipp Oppermann
a39c59801b Use upstream lazy static as it has a spin_no_std feature now (#158) 2016-05-14 16:25:15 +02:00
Philipp Oppermann
7170c658a7 Add missing mut (#156) 2016-05-07 15:01:39 +02:00
William Orr
07d534e4b4 Add missing use statements in printing-to-screen (#154) 2016-05-03 09:14:34 +02:00
William Orr
a9f41d7303 Replace movaps with movups
objdump on my system and code snippet in blog agree - problem is caused
by `movups` not `movaps`. Fix surrounding text and doc link to reflect
this.
2016-05-02 20:18:15 +02:00
Philipp Oppermann
301859a4b9 Merge pull request #153 from phil-opp/patch5
The no-landing-pads snippet already generates SSE instructions
2016-05-02 17:02:31 +02:00
Philipp Oppermann
088e87b23a The no-landing-pads snippet already generates SSE instructions 2016-05-02 16:58:49 +02:00
Philipp Oppermann
0d210e554f Fix: pass the commit hash instead of the variable name 2016-05-02 16:16:24 +02:00
Philipp Oppermann
622c4f0797 Pass commit hash for update commit message 2016-05-02 16:09:15 +02:00
Philipp Oppermann
b633b29b6c Fix rendering of repr(C)
Fixes #151
2016-05-02 15:47:41 +02:00
Philipp Oppermann
f1c68fd6dc Remove installation of pygments
We don't deploy on this branch, so syntax highlighting is not needed.
2016-05-02 15:44:36 +02:00
Philipp Oppermann
d056a41154 Trigger rebuild of hugo branch instead of deploying ourselves 2016-05-02 15:32:10 +02:00
Philipp Oppermann
2cecc5abeb Copy all files (inclusive the hidden .nojekyll) 2016-05-01 15:20:17 +02:00
Philipp Oppermann
e95710c66e Merge pull request #150 from phil-opp/travis_hugo
Build hugo blog using travis
2016-05-01 15:12:58 +02:00
Philipp Oppermann
1e69a0c627 Build hugo blog using travis 2016-05-01 15:07:07 +02:00
Philipp Oppermann
40170d0039 Add contact page 2016-04-30 13:27:30 +02:00
Philipp Oppermann
192780e219 Merge pull request #148 from phil-opp/convert-posts-for-hugo
Convert posts for hugo
2016-04-30 13:22:49 +02:00
Philipp Oppermann
568e95605b Add more redirects for old url formats 2016-04-25 23:25:59 +02:00
Philipp Oppermann
0fc63576e7 fix link 2016-04-25 22:44:33 +02:00
Philipp Oppermann
fe9b742978 Improve presentation of code snippets 2016-04-25 22:44:33 +02:00
Philipp Oppermann
aeb3100ee4 Don't link to src subdir 2016-04-25 22:44:33 +02:00
Philipp Oppermann
ed1b23a386 Improve wording and mention possibility of disabling SSE 2016-04-25 22:44:33 +02:00
Philipp Oppermann
bbb77e2f9b Link to a specific github revision (so that the line number won't change anymore) 2016-04-25 22:44:33 +02:00
Philipp Oppermann
7b2d40d3f0 Improve indentation, line length, and syntax highlighting 2016-04-25 22:44:33 +02:00
Philipp Oppermann
7b2bdf5c3c Convert links to hugo format and insert more breaks 2016-04-25 22:44:33 +02:00
Philipp Oppermann
cdc0b0748b Convert front matters to hugo's toml-based format 2016-04-25 22:44:33 +02:00
Philipp Oppermann
814fc5c3c0 Reorganize posts and pages inside a blog directory 2016-04-25 21:44:08 +02:00
Philipp Oppermann
8651fafb2c Prepare hugo migration: Disable automatic blog update 2016-04-25 19:29:01 +02:00
Philipp Oppermann
0d539a6dae Remove wrong claims about the linux allocator (#147) 2016-04-25 16:51:51 +02:00
Philipp Oppermann
9e74969732 Merge pull request #143 from phil-opp/kernel-heap-final
Add new post about creating a kernel heap
2016-04-12 09:44:00 +02:00
Philipp Oppermann
a365d19c46 Fix whitespace in rustc error message 2016-04-12 09:41:23 +02:00
Philipp Oppermann
43e73ff050 Add kernel heap post to readme 2016-04-12 00:47:05 +02:00
Philipp Oppermann
6839321233 Formatting: Run rustfmt 2016-04-12 00:47:05 +02:00
Philipp Oppermann
f2f2568e26 Formatting: Use same format as cargo-edit 2016-04-12 00:47:05 +02:00
Philipp Oppermann
2b85f38b41 Use new hole_list_allocator instead of bump_allocator 2016-04-12 00:47:05 +02:00
Philipp Oppermann
6a45b29560 Create hole_list_allocator crate 2016-04-12 00:47:05 +02:00
Philipp Oppermann
eac60162ad Fix page fault by mapping the complete heap 2016-04-12 00:47:05 +02:00
Philipp Oppermann
fbc1c60164 Ensure that memory::init is only called once 2016-04-12 00:47:05 +02:00
Philipp Oppermann
cea73b3ab9 Move memory intialization to memory::init function 2016-04-12 00:47:05 +02:00
Philipp Oppermann
9e46fb21c7 Try to allocate something (causes a page fault) 2016-04-12 00:47:05 +02:00
Philipp Oppermann
f25cb599c2 Link bump_allocator and alloc and collections crates 2016-04-12 00:47:05 +02:00
Philipp Oppermann
c6981c2f24 Create bump_allocator crate 2016-04-12 00:47:05 +02:00
Philipp Oppermann
5f84061469 Add new post about creating a kernel heap 2016-04-12 00:47:04 +02:00
Philipp Oppermann
05f76f525c Merge pull request #141 from phil-opp/patch1
Fix bug in frame iteration
2016-03-06 15:03:51 +01:00
Philipp Oppermann
1d8a36a14b Rewrite remap_the_kernel post to use range_inclusive instead of step_by 2016-03-06 15:01:48 +01:00
Philipp Oppermann
03ed3ce9a0 Replace buggy range.step_by with a Frame::range_inclusive function 2016-03-06 13:42:31 +01:00
Philipp Oppermann
23df363136 Update to changes introduced in 4fcb4b3424 2016-02-24 17:35:47 +01:00
Philipp Oppermann
4fcb4b3424 Make some more types public since they are part of the public interface 2016-02-24 17:34:36 +01:00
Philipp Oppermann
c145f9f1d1 Use function in post as well 2016-02-24 17:18:59 +01:00
Philipp Oppermann
941b1fab1c Use new section.is_allocated function 2016-02-24 17:14:39 +01:00
Philipp Oppermann
3b7638bb1d Merge pull request #131 from phil-opp/remap-the-kernel-update
Identity map the multiboot structure to fix the frame allocator
2016-02-24 17:02:47 +01:00
Philipp Oppermann
6734417e0f Add update note 2016-02-24 17:00:09 +01:00
Philipp Oppermann
0aa9b27f9b Add `Fixing the FrameAllocator section
Document changes from e3021d17d542e10328985ae5d0e0e373897835b3
2016-02-24 16:53:47 +01:00
Philipp Oppermann
5ee21d43f7 Use new linker script in post as well
New linker script from 86a59723bc0ead07497b0ea84d9543761a9f4430
2016-02-24 16:53:47 +01:00
Philipp Oppermann
635f7d3f9d Align section size instead of section start due to #126
This fixes the problem that GRUB sometimes puts the multiboot info struct between kernel sections if the hole is big enough. This leads to problems since we would try to map the same page twice in that case.
2016-02-24 16:52:19 +01:00
Philipp Oppermann
4142cff3e6 Identity map the multiboot info structure 2016-02-24 16:52:19 +01:00
Philipp Oppermann
75aa669cdb Merge pull request #135 from phil-opp/phil-opp-patch-1
Add `#[allow(dead_code)]` to Color enum
2016-02-22 07:30:54 +01:00
Philipp Oppermann
8b2ec752b7 Add #[allow(dead_code)] to Color enum 2016-02-22 07:28:58 +01:00
Philipp Oppermann
aea5054cf3 Change email of travis update bot 2016-02-18 17:56:16 +01:00
Philipp Oppermann
ac9044bd96 Some improvements to remap-the-kernel and allocating-frames 2016-02-13 22:44:09 +01:00
Philipp Oppermann
d321982755 Merge pull request #130 from phil-opp/phil-opp-patch-1
Improve introduction for frame allocation and explain what a frame is
2016-02-05 10:52:41 +01:00
Philipp Oppermann
2795b33fd6 Improve introduction for frame allocation and explain what a frame is 2016-02-04 20:05:25 +01:00
Philipp Oppermann
75bd3c8785 Merge pull request #129 from phil-opp/phil-opp-patch-1
Improve Printing to Screen post
2016-02-04 17:10:32 +01:00
Philipp Oppermann
d421bac590 Remove mention of byte strings as they are not compatible to write_str 2016-02-04 16:41:58 +01:00
Philipp Oppermann
b092e79495 Better document changes required for unstable feature & extern crate 2016-02-04 16:40:18 +01:00
Philipp Oppermann
aaffb32bbd Make clear in which file the code fragments go 2016-02-03 18:01:58 +01:00
Philipp Oppermann
937224a2c7 Merge pull request #127 from phil-opp/phil-opp-patch-1
Add/extend explanations in Entering Longmode
2016-02-02 23:13:14 +01:00
Philipp Oppermann
de2305038a Improve comments in code as well 2016-02-02 23:11:19 +01:00
Philipp Oppermann
bb4d64dc99 Extend explanation for long mode test and improve code comments 2016-02-02 23:09:44 +01:00
Philipp Oppermann
d6efe62c80 Add some explanation for the long mode check 2016-02-01 23:57:09 +01:00
Philipp Oppermann
c2c863c7f3 Use cmp and je instead of xor and jz 2016-02-01 23:42:09 +01:00
Philipp Oppermann
b9c94baaaa Explain the CPUID check 2016-02-01 23:40:45 +01:00
Philipp Oppermann
cbf4534eca Explain cmp, jmp and jne instructions more detailed 2016-02-01 19:28:18 +01:00
Philipp Oppermann
7b16d80d98 Merge pull request #125 from phil-opp/phil-opp-patch-1
Link travis build and note that the code works for the newest nightly
2016-01-27 17:42:09 +01:00
Philipp Oppermann
1a886fed5d Link travis build and note that the code should work for the newest nightly 2016-01-27 17:38:07 +01:00
Philipp Oppermann
df72565933 Merge pull request #123 from FreeFull/patch-1
Fix type name: `Entry` instead of `EntryFlags`
2016-01-20 14:40:37 +01:00
Filip Szczepański
cb8c438820 Fix type name: Entry instead of EntryFlags
Fix for #120
2016-01-20 13:34:15 +00:00
Philipp Oppermann
954ec78a44 Merge pull request #122 from phil-opp/update-x86-crate
Update x86 crate to version 0.6 and disable performance counter
2016-01-20 00:13:15 +01:00
Philipp Oppermann
865dd9cd72 Update x86 crate to version 0.6 and disable performance counter 2016-01-20 00:06:46 +01:00
Philipp Oppermann
23ee000f70 Split large command block 2016-01-19 23:24:07 +01:00
Philipp Oppermann
49b78f59e2 Merge pull request #121 from phil-opp/grub-troubleshooting
Add grub-mkrescue troubleshooting steps
2016-01-19 23:23:31 +01:00
Philipp Oppermann
4beecbe138 Add grub-mkrescue troubleshooting steps 2016-01-19 23:07:23 +01:00
Philipp Oppermann
86d27933ff Merge pull request #120 from phil-opp/phil-opp-patch-1
Fix type name: `EntryFlags` instead of `TableEntryFlags`
2016-01-19 13:07:38 +01:00
Philipp Oppermann
1bd054d718 Fix type name: EntryFlags instead of TableEntryFlags 2016-01-19 13:04:27 +01:00
Philipp Oppermann
5bc31e7c46 Mention xorriso in Readme
See #104
2016-01-18 23:16:17 +01:00
Philipp Oppermann
a6632af0b6 Remove call to non-existent Writer::new
The creation of a `Writer` is the same as before, so we omit it.

Fixes #118
2016-01-17 13:24:16 +01:00
Philipp Oppermann
1284ea3657 Merge pull request #115 from mhlopko/patch-2
Add missing brackets
2016-01-14 14:55:33 +01:00
Marcel Hlopko
db9e6c5739 Add missing brackets 2016-01-14 14:52:02 +01:00
Philipp Oppermann
0c45cf1b97 Merge pull request #114 from mhlopko/patch-1
Add missing semicolon
2016-01-14 14:43:56 +01:00
Marcel Hlopko
59d9a08aea Add missing semicolon 2016-01-14 14:33:33 +01:00
Philipp Oppermann
16eef8e945 Merge pull request #112 from phil-opp/official-bitflags
Use official bitflags crate
2016-01-14 09:36:35 +01:00
Philipp Oppermann
9ed358c54c Use official bitflags 2016-01-14 09:21:15 +01:00
Philipp Oppermann
e320e4d1d9 Merge pull request #107 from jonfk/master
Added missing `unsafe` in printing-to-screen post
2016-01-09 13:15:41 +01:00
Jonathan Fok kan
cd9441fe13 Fixed small error in printing-to-screen post 2016-01-09 13:15:06 +01:00
Philipp Oppermann
555096c953 Merge pull request #106 from phil-opp/phil-opp-patch-1
Add building instructions and links to posts and source code in README
2016-01-09 13:05:15 +01:00
Philipp Oppermann
519bb2b385 Merge pull request #108 from jonfk/fixed/alloc-frames
Fixed typos in post Allocating Frames
2016-01-09 12:57:58 +01:00
Jonathan Fok kan
376ab13f1a Fixed typos in post Allocating Frames 2016-01-09 01:30:06 -05:00
Philipp Oppermann
73673f759d Add building instructions and links to posts and source code 2016-01-06 19:01:43 +01:00
Philipp Oppermann
43a86e7b86 Merge pull request #105 from heathtechnical/master
Fixed typo in 'CPUID check' heading
2016-01-05 00:13:17 +01:00
Dan Heath
3828ba8830 Fixed typo in 'CPUID check' heading 2016-01-04 22:38:49 +00:00
Philipp Oppermann
a338bf5d98 Merge pull request #103 from phil-opp/qemu-cdrom
Use `-cdrom` instead of `-drive` as it's shorter
2016-01-02 16:35:01 +01:00
Philipp Oppermann
be251361fa Use -cdrom instead of -drive as it's shorter
Right now, it does not matter whether we boot from a drive or a cdrom. Therefore we use the shorter `-cdrom`.
2016-01-02 16:28:09 +01:00
Philipp Oppermann
d57657ac29 Merge pull request #102 from phil-opp/cpuid-comments
Improve comments for CPUID check
2016-01-02 16:10:01 +01:00
Philipp Oppermann
157b3b208d Improve comments for CPUID check 2016-01-02 16:01:42 +01:00
Philipp Oppermann
980c94202f Merge pull request #100 from phil-opp/remap-the-kernel
New post about remapping the kernel
2016-01-01 18:34:29 +01:00
Philipp Oppermann
cfe03f612d Remove printing of memory areas and elf sections 2016-01-01 18:05:16 +01:00
Philipp Oppermann
ac6c1af84f Remove test_paging function 2016-01-01 18:05:16 +01:00
Philipp Oppermann
1c2e6fca64 Remove unused imports 2016-01-01 18:05:16 +01:00
Philipp Oppermann
db928db0b5 Unmap the old P4 page to create a basic guard page for the kernel stack 2016-01-01 18:05:16 +01:00
Philipp Oppermann
e2b99ac8c1 Set the NXE and the WP bit 2016-01-01 18:05:16 +01:00
Philipp Oppermann
76d1c41e96 Use correct section flags (causes a page fault) 2016-01-01 18:05:16 +01:00
Philipp Oppermann
b64f980c34 Identity map the vga text buffer 2016-01-01 18:05:16 +01:00
Philipp Oppermann
051596d8f9 Try to switch tables, causes boot loop 2016-01-01 18:05:16 +01:00
Philipp Oppermann
33322ec49b Test it 2016-01-01 18:05:16 +01:00
Philipp Oppermann
8e65034643 Align sections in linker script 2016-01-01 18:05:16 +01:00
Philipp Oppermann
dd51bde9f9 Add remap_the_kernel function 2016-01-01 18:05:16 +01:00
Philipp Oppermann
fe8c81a531 Backup and restore original recursive mapping in with 2016-01-01 18:05:16 +01:00
Philipp Oppermann
c16b3059cf Add ActivePageTable::with draft 2016-01-01 18:05:16 +01:00
Philipp Oppermann
a100d5f63f Split mapping functions of ActivePageTable into mapper subtype 2016-01-01 18:05:16 +01:00
Philipp Oppermann
716e3f7359 Zero and recursive map inactive table on creation 2016-01-01 18:05:16 +01:00
Philipp Oppermann
7ce86b3a80 Add temporary_page submodule 2016-01-01 18:05:16 +01:00
Philipp Oppermann
a7000e537c Add InactivePageTableSkeleton 2016-01-01 18:05:16 +01:00
Philipp Oppermann
2198d09695 Add clone methods to Page(public) and Frame(private) 2016-01-01 18:05:16 +01:00
Philipp Oppermann
f378e6aed3 Set up GDB 2016-01-01 18:05:16 +01:00
Philipp Oppermann
295ae7ba89 Add new post about remapping the kernel 2016-01-01 18:05:16 +01:00
Philipp Oppermann
9bad9020f6 Make Page::containing address public in post
This brings it in line with the code
2015-12-31 00:00:41 +01:00
Philipp Oppermann
b11ed7bd46 Merge pull request #97 from phil-opp/gdb-update
Update the gdb overview
2015-12-30 02:21:39 +01:00
Philipp Oppermann
5c6630fa97 Add tui commands 2015-12-30 02:18:54 +01:00
Philipp Oppermann
b58bca6fe9 Link Beej's Quick guide
Recommended by Julia Evans on hackernews: https://news.ycombinator.com/item?id=10808362
2015-12-30 02:18:25 +01:00
Philipp Oppermann
350069fd44 Merge pull request #96 from phil-opp/dual-license
Dual license the code
2015-12-29 12:35:57 +01:00
Philipp Oppermann
a9e5b7fd28 Update license headers 2015-12-29 12:31:25 +01:00
Philipp Oppermann
543f202412 Dual license code under apache2/mit 2015-12-29 12:21:29 +01:00
Philipp Oppermann
6f3daa8a2a Merge pull request #91 from phil-opp/patch1
Use new example code to cause SSE failure
2015-12-26 13:41:01 +01:00
Philipp Oppermann
36cf22895a Use new example code to cause SSE failure 2015-12-26 13:38:27 +01:00
Philipp Oppermann
97d381198b Merge pull request #90 from phil-opp/update-page-tables-post
Explain lifetime elision in `next_table` methods
2015-12-26 04:36:45 +01:00
Philipp Oppermann
049fc4d74d Explain lifetime elision in next_table methods
Also, improve headings and the ActivePageTable section a bit.
2015-12-26 04:33:02 +01:00
Philipp Oppermann
65d2f7e013 Merge pull request #88 from phil-opp/patch1
Rename RecursivePageTable to ActivePageTable
2015-12-25 13:17:49 +01:00
Philipp Oppermann
b39bb643dd Rename RecursivePageTable to ActivePageTable 2015-12-25 13:14:14 +01:00
Philipp Oppermann
d28548fa10 Link next post 2015-12-24 03:15:09 +01:00
Philipp Oppermann
d9eff3e50a Merge pull request #86 from phil-opp/gdb-support
Add page about GDB support
2015-12-24 03:06:18 +01:00
Philipp Oppermann
6470e2f56d Add page about GDB support 2015-12-24 03:02:58 +01:00
Philipp Oppermann
ad8e9da766 Merge pull request #85 from alicemaz/master
Add missing unsafe to Unique::new
2015-12-23 12:50:15 +01:00
Alice Maz
4aec3b3d78 Add unsafe to Unique::new
previously compile would fail with E0133
2015-12-23 01:35:53 -05:00
Philipp Oppermann
c19d176aa0 Merge pull request #81 from 'rafalmiel-master'
Fix HierachicalLevel typo
2015-12-20 15:58:54 +01:00
Rafal Mielniczuk
337799599a Fix HierachicalLevel typo 2015-12-20 15:52:14 +01:00
Philipp Oppermann
74e84c7ea4 The core_str_ext feature is no longer needed 2015-12-20 15:47:51 +01:00
Philipp Oppermann
14166b3a35 Remove old features 2015-12-20 15:40:43 +01:00
Philipp Oppermann
dced423588 Improve tag update script 2015-12-20 15:32:26 +01:00
Philipp Oppermann
60eb7ed4a7 Merge pull request #79 from phil-opp/rustfmt
Run rustfmt
2015-12-20 15:09:39 +01:00
Philipp Oppermann
165e6ebff8 Run rustfmt 2015-12-20 15:05:08 +01:00
Philipp Oppermann
52f239e5b4 Add a link to the x86 crate
Also, fix some formatting.
2015-12-16 14:01:13 +01:00
Philipp Oppermann
f00366d09f Merge pull request #75 from phil-opp/rename-paging-post
Change title to `Page Tables`
2015-12-16 12:35:58 +01:00
Philipp Oppermann
de50b37443 Change title to Page Tables 2015-12-16 12:26:53 +01:00
Philipp Oppermann
bb0bd73584 Merge pull request #72 from phil-opp/fix-1
Rename `test_*` functions to `check_*` again
2015-12-14 01:08:28 +01:00
Philipp Oppermann
6e60552e87 Rename test_* functions to check_* 2015-12-14 01:03:55 +01:00
Philipp Oppermann
3c6057dd76 Merge pull request #71 from phil-opp/rename-min_by
The `Iterator::min_by` was renamed to `min_by_key`
2015-12-14 00:14:13 +01:00
Philipp Oppermann
7e83931746 The Iterator::min_by was renamed to min_by_key 2015-12-14 00:08:54 +01:00
Philipp Oppermann
7675a08ebe Merge pull request #70 from phil-opp/stable-no_std
The `no_std` attribute is stable now
2015-12-14 00:08:30 +01:00
Philipp Oppermann
22014eb38d The no_std attribute is stable now 2015-12-14 00:03:55 +01:00
Philipp Oppermann
87b8fc6a29 Merge pull request #68 from phil-opp/update_tag
Rename tag to `modifying_page_tables`
2015-12-14 00:03:03 +01:00
Philipp Oppermann
ce5c4b970a Rename tag to modifying_page_tables 2015-12-14 00:00:32 +01:00
Philipp Oppermann
807e8110be Merge pull request #67 from phil-opp/grammar-set_up
Fix grammar: `set up` instead of `setup`
2015-12-13 19:36:00 +01:00
Philipp Oppermann
c0439cf194 Fix Grammar
`set up` not `setup`
2015-12-13 18:53:15 +01:00
Philipp Oppermann
26fc76fbda Merge pull request #65 from phil-opp/move-setup-SSE
Move `setup_SSE` to boot.asm
2015-12-12 15:03:13 +01:00
Philipp Oppermann
953704f103 Move setup_SSE to boot.asm 2015-12-12 15:00:14 +01:00
Philipp Oppermann
e272cc9257 Merge pull request #62 from phil-opp/fix-1
Use a more expressive variable name
2015-12-10 16:59:18 +01:00
Philipp Oppermann
617c92d017 Use a more expressive variable name 2015-12-10 16:55:54 +01:00
Philipp Oppermann
5cc6f9ec4b Merge pull request #61 from phil-opp/paging-module
New post about accessing and modifying page tables
2015-12-09 16:23:27 +01:00
Philipp Oppermann
3a82ca32cd Publish Accessing and Modifying Page Tables post 2015-12-09 16:18:16 +01:00
Philipp Oppermann
9366db272c Finish introduction and other TODOs 2015-12-09 16:14:25 +01:00
Philipp Oppermann
b3cb09ba8d Add short conclusion 2015-12-09 15:46:15 +01:00
Philipp Oppermann
329a64c9a1 Some small improvements 2015-12-09 15:46:15 +01:00
Philipp Oppermann
75264e7cac Fix unmap function by flushing the TLB 2015-12-09 15:46:15 +01:00
Philipp Oppermann
8bb09f47f8 Test unmap function 2015-12-09 15:46:15 +01:00
Philipp Oppermann
cf5ea7664e Test map_to function 2015-12-09 15:46:15 +01:00
Philipp Oppermann
5b4e457439 Double stack size to avoid stack overflow 2015-12-09 15:46:14 +01:00
Philipp Oppermann
786e1d5cab Test translate function 2015-12-09 15:46:14 +01:00
Philipp Oppermann
d8c6b6f5b7 Add and call test_paging function 2015-12-09 15:46:14 +01:00
Philipp Oppermann
4fd8891aff Add (buggy) unmap function 2015-12-09 15:46:14 +01:00
Philipp Oppermann
d52c79b106 Add map and identity_map functions 2015-12-09 15:46:14 +01:00
Philipp Oppermann
86d8e99271 Make translate and map_to safe by making them RecursivePageTable methods 2015-12-09 15:46:14 +01:00
Philipp Oppermann
fb7d2d22b6 Add RecursivePageTable as an owner for the P4 table 2015-12-09 15:46:14 +01:00
Philipp Oppermann
46b93e0650 Add unsafe map_to function and make translate unsafe, too
These functions are unsafe because it's possible to get aliased &mut references.
2015-12-09 15:46:14 +01:00
Philipp Oppermann
e84344f59a Add function to translate virtual to physical address 2015-12-09 15:46:14 +01:00
Philipp Oppermann
d267ac1c98 Define the next_table methods only for P4, P3, and P2 tables 2015-12-09 15:46:14 +01:00
Philipp Oppermann
e5a4114262 Add unsafe next_table methods 2015-12-09 15:46:14 +01:00
Philipp Oppermann
e071c24680 Recursive map the P4 table 2015-12-09 15:46:14 +01:00
Philipp Oppermann
96b0dc0c66 Model page tables 2015-12-09 15:46:14 +01:00
Philipp Oppermann
14384fb27f Model page table entries 2015-12-09 15:46:14 +01:00
Philipp Oppermann
d827f51bb6 Create basic paging module 2015-12-09 15:46:14 +01:00
Philipp Oppermann
dabef43db9 Reset src to master to be able to follow step-by-stp 2015-12-09 15:46:14 +01:00
Philipp Oppermann
9019309d40 Many wording improvements 2015-12-09 15:46:14 +01:00
Philipp Oppermann
9f509aec80 Improve post and rewrite recursive mapping section 2015-12-09 15:46:14 +01:00
Philipp Oppermann
fd42d634ad Change title and add some incomplete introduction variants 2015-12-09 15:44:17 +01:00
Philipp Oppermann
2b8838459c Add image sources 2015-12-09 15:42:45 +01:00
Philipp Oppermann
bf6bcdcc82 Add paging introduction 2015-12-09 15:42:45 +01:00
Philipp Oppermann
fac58a003a Describe unwrap function 2015-12-09 15:42:45 +01:00
Philipp Oppermann
57fbd2efc5 Specify some imports 2015-12-09 15:42:45 +01:00
Philipp Oppermann
bd00921dac Use expect instead of unwrap 2015-12-09 15:42:45 +01:00
Philipp Oppermann
67b30314c4 Use relative links for images 2015-12-09 15:42:45 +01:00
Philipp Oppermann
e331a6610b Describe p*_index functions 2015-12-09 15:42:45 +01:00
Philipp Oppermann
15427b363a Take page by value in mapping functions
(there is no reason to borrow it at the moment)
2015-12-09 15:42:45 +01:00
Philipp Oppermann
b314d4827f Move Frame::start_address to memory/mod.rs and use it in identity_map() 2015-12-09 15:42:44 +01:00
Philipp Oppermann
6ed376112d PAGE_SIZE is already defined in memory/mod.rs 2015-12-09 15:42:44 +01:00
Philipp Oppermann
a279609c26 Add images, TODOs, RecursivePageTable::new, and many improvements 2015-12-09 15:42:44 +01:00
Philipp Oppermann
557738e705 Add a RecursivePageTable::new function 2015-12-09 15:42:44 +01:00
Philipp Oppermann
92194d8354 Remove unused feature and import 2015-12-09 15:42:44 +01:00
Philipp Oppermann
05873d9dae Improve next_table_create 2015-12-09 15:42:44 +01:00
Philipp Oppermann
c5fac2647e Merge lock.rs into mod.rs 2015-12-09 15:42:44 +01:00
Philipp Oppermann
5113fce8f7 Big update and many new sections... 2015-12-09 15:42:44 +01:00
Philipp Oppermann
f912dfa506 Improve huge_page closure 2015-12-09 15:42:44 +01:00
Philipp Oppermann
4aeda180a1 Remove old content and add skeletons for new sections 2015-12-09 15:42:36 +01:00
Philipp Oppermann
cdaad86a06 Change semantics of start_address and containing_address
The page numbers now respect the memory hole between higher and lower half.
2015-12-09 15:38:46 +01:00
Philipp Oppermann
c52f58cc4c Rename and use is_unused() 2015-12-09 15:38:46 +01:00
Philipp Oppermann
bd05aa7715 Add section about type system magic 2015-12-09 15:38:46 +01:00
Philipp Oppermann
b1a2c8caad Rename PhantomData field 2015-12-09 15:38:46 +01:00
Philipp Oppermann
7005cd7819 Start rewriting post for new design 2015-12-09 15:38:46 +01:00
Philipp Oppermann
e88de41914 Calculate next_table_address through directly through addresses 2015-12-09 15:38:46 +01:00
Philipp Oppermann
4a54a24145 Reorganize imports 2015-12-09 15:38:46 +01:00
Philipp Oppermann
799067f8b1 Add Frame::start_address 2015-12-09 15:38:46 +01:00
Philipp Oppermann
51f83717d6 Use Frame::containing_address 2015-12-09 15:38:46 +01:00
Philipp Oppermann
7e5da6c897 Modify pointed_frame to return an Option 2015-12-09 15:38:46 +01:00
Philipp Oppermann
2d9b619587 Begin updating post 2015-12-09 15:38:46 +01:00
Philipp Oppermann
6535aa017d Add lock module (name is temporary) 2015-12-09 15:38:46 +01:00
Philipp Oppermann
6c5b932fbc Split translate into translate_page and rest 2015-12-09 15:38:46 +01:00
Philipp Oppermann
44fd5f682d Some new test printlns 2015-12-09 15:38:46 +01:00
Philipp Oppermann
a8df7b2e4d Finish basics of new paging module 2015-12-09 15:38:46 +01:00
Philipp Oppermann
562221d725 Add some unstable features and some printing tests 2015-12-09 15:38:46 +01:00
Philipp Oppermann
b7debed3b7 Increase stack size to 4096*2 2015-12-09 15:38:46 +01:00
Philipp Oppermann
204a9d9c9d Add some sections (now outdated) 2015-12-09 15:38:46 +01:00
Philipp Oppermann
c7fe1348f0 Old attempts for a new design 2015-12-09 15:38:46 +01:00
Philipp Oppermann
ace53fad91 Updates for the old paging code 2015-12-09 15:38:46 +01:00
Philipp Oppermann
ae49ab5072 Add alternative paging module with new design 2015-12-09 15:38:45 +01:00
Philipp Oppermann
540c398ec3 Alternative, more advanced design 2015-12-09 15:38:45 +01:00
Philipp Oppermann
907f51bb5b Add section about modifying table entries 2015-12-09 15:38:45 +01:00
Philipp Oppermann
882af6f14e Make p{1,2,3}_table functions unsafe 2015-12-09 15:38:45 +01:00
Philipp Oppermann
cf5e2715ae Add section about translating virtual addresses 2015-12-09 15:38:45 +01:00
Philipp Oppermann
08a9743caa Describle implementation of recursive mapping 2015-12-09 15:38:45 +01:00
Philipp Oppermann
90dba32898 Add “Mapping Page Tables” section and extract page table entry flags 2015-12-09 15:38:45 +01:00
Philipp Oppermann
6462a3263c Add basic module and corresponding documentation 2015-12-09 15:38:33 +01:00
Philipp Oppermann
6b72dd8223 Remove Lock structure again as we changed design 2015-12-08 22:20:19 +01:00
Philipp Oppermann
f917bd67a1 Begin paging module 2015-12-08 22:20:19 +01:00
Philipp Oppermann
0e574426c5 Add recursive mapping and start describing it 2015-12-08 22:20:19 +01:00
Philipp Oppermann
38849516a1 Add preliminary outline for next post 2015-12-08 22:20:19 +01:00
Philipp Oppermann
f1f1e66dce Improve wording (frame instead of page) 2015-12-03 18:41:51 +01:00
Philipp Oppermann
0cfb38ee6e Merge pull request #59 from phil-opp/mac-os-note
Add a note about Mac OS and virtual machines
2015-11-28 18:06:41 +01:00
Philipp Oppermann
2d069d636f Add a note about Mac OS and virtual machines 2015-11-28 18:04:37 +01:00
Philipp Oppermann
0a6a174e54 Fix broken markdown link 2015-11-24 00:18:32 +01:00
Philipp Oppermann
9b6bb7f895 Merge pull request #56 from phil-opp/qemu-warning
Specify `raw` ISO format explicitely to avoid QEMU warning
2015-11-24 00:10:04 +01:00
Philipp Oppermann
e52d8bcfd2 Specify raw ISO format explicitely to avoid QEMU warning 2015-11-24 00:08:34 +01:00
Philipp Oppermann
43924afbbf Make internal links relative 2015-11-23 23:42:35 +01:00
Philipp Oppermann
5137ad103a Merge pull request #54 from phil-opp/phil-opp-patch-1-1
Recommend `multirust override nighly`
2015-11-22 23:07:02 +01:00
Philipp Oppermann
84813d9b08 Recommend multirust override nighly
Resolves #53
2015-11-22 23:04:32 +01:00
Philipp Oppermann
cefe95dc88 Merge pull request #52 from phil-opp/remove_copy_for_frame
Don't derive Copy/Clone for Frame so we can be sure that it's free
2015-11-19 19:57:29 +01:00
Philipp Oppermann
a8600a00b6 Don't derive Copy/Clone for Frame so we can be sure that it's free
If a Frame would be clonable or even Copy, the frame could be freed (e.g. passed to deallocate_frame) and used thereafter. Or it could be freed multiple times.
2015-11-19 19:56:22 +01:00
Philipp Oppermann
c71981947b Update URL 2015-11-19 16:07:01 +01:00
Philipp Oppermann
4e0071cf3d Merge pull request #50 from phil-opp/fix-2
Don't set `write protect` bit when enabling paging
2015-11-19 15:29:26 +01:00
Philipp Oppermann
88eb0636f3 Don't set write protect bit as we don't need it now 2015-11-19 15:26:58 +01:00
Philipp Oppermann
f4c61f7634 Merge pull request #49 from phil-opp/fix-1
VGA buffer: `bit` instead of `byte`
2015-11-19 15:24:35 +01:00
Philipp Oppermann
0e31d4a221 Fix #48 2015-11-19 15:23:25 +01:00
Philipp Oppermann
25122bc05c Correct the reason for using clone 2015-11-16 15:01:39 +01:00
Philipp Oppermann
fc856a55a6 Merge pull request #44 from alevy/patch-1
Small grammar nit in "Entering Longmode" post
2015-11-15 20:18:45 +01:00
Amit Levy
fc55d6dc06 Small grammar nit in "Entering Longmode" post
'a' vs 'an'
2015-11-15 14:17:27 -05:00
Philipp Oppermann
eb93c94d6d Merge pull request #43 from alevy/patch-1
Fix typo in "Entering long mode"
2015-11-15 20:13:52 +01:00
Amit Levy
a1d744cf5a Fix typo in "Entering long mode"
I think there is a typo in the section describing how the P2 mapping is set up. The corresponding code sets _P2_'s third entry.
2015-11-15 13:55:58 -05:00
Philipp Oppermann
f08b2cb340 Merge pull request #42 from phil-opp/allocating-frames-motivation
Discuss alternative frame stack designs
2015-11-15 17:17:08 +01:00
Philipp Oppermann
ced6edbdd1 Discuss alternative frame stack designs 2015-11-15 17:13:20 +01:00
Philipp Oppermann
e380129fde Merge pull request #40 from phil-opp/allocating-frames
New post about allocating frames
2015-11-15 12:03:11 +01:00
Philipp Oppermann
f997f1f0f0 Small wording improvement 2015-11-15 12:00:03 +01:00
Philipp Oppermann
96cee9ab2b Link github repository 2015-11-15 12:00:03 +01:00
Philipp Oppermann
5de4255fca Add a conclusion to the allocating frames post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
78c2fd6acc Many small improvements 2015-11-15 12:00:03 +01:00
Philipp Oppermann
28c56f2c06 Publish Allocating Frames post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
18d397b48d Some improvements to the allocating frames post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
a8580ad3a2 Fix: next_free_frame must be increased to the start of the current area 2015-11-15 12:00:03 +01:00
Philipp Oppermann
6ce34f5e2b Add introduction 2015-11-15 12:00:03 +01:00
Philipp Oppermann
d0cf5e7c61 Link from Printing to Screen 2015-11-15 12:00:03 +01:00
Philipp Oppermann
ca07527ede Add What's next? text 2015-11-15 12:00:03 +01:00
Philipp Oppermann
cf835e19ae Recommend Eric Kidd's Bare Metal Rust series 2015-11-15 12:00:03 +01:00
Philipp Oppermann
939d33efce Many improvements to allocating frames post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
16078431db Add basic description for frame allocator methods 2015-11-15 12:00:03 +01:00
Philipp Oppermann
8304439c82 Add a FrameAllocator trait 2015-11-15 12:00:03 +01:00
Philipp Oppermann
75988f1324 Test: allocate all frames 2015-11-15 12:00:03 +01:00
Philipp Oppermann
a2047bc70a Add an AreaFrameAllocator 2015-11-15 12:00:03 +01:00
Philipp Oppermann
6f8a21eba6 Create a memory module with a Frame struct 2015-11-15 12:00:03 +01:00
Philipp Oppermann
ccaa2ed645 Add section about start and end of kernel/multiboot 2015-11-15 12:00:03 +01:00
Philipp Oppermann
718db100cd Add let bindings for tags 2015-11-15 12:00:03 +01:00
Philipp Oppermann
f2b91d3d61 Improve panic handler 2015-11-15 12:00:03 +01:00
Philipp Oppermann
fc389c9e9e Increase stack size to 4096 2015-11-15 12:00:03 +01:00
Philipp Oppermann
2d1c801c72 Rename post to Allocating Frames 2015-11-15 12:00:03 +01:00
Philipp Oppermann
895d40cd13 Add section about kernel elf sections 2015-11-15 12:00:03 +01:00
Philipp Oppermann
33fdbce530 Print available memory areas using multiboot info 2015-11-15 12:00:03 +01:00
Philipp Oppermann
73aa41e25e Pass multiboot pointer as argument to rust_main 2015-11-15 12:00:03 +01:00
Philipp Oppermann
d07530d660 Rename new post to Remapping the Kernel 2015-11-15 12:00:03 +01:00
Philipp Oppermann
a54b2d8f47 Remove detailed description of multiboot structures
Instead, we will use the external crate `multiboot2-elf64` at https://github.com/phil-opp/multiboot2-elf64 . The removed parts were added to its README for documentation
2015-11-15 12:00:03 +01:00
Philipp Oppermann
c064de5190 Add description of info struct and elf tag 2015-11-15 12:00:03 +01:00
Philipp Oppermann
1f074264c0 Rename and restructure multiboot info post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
4d59d7350c Add skeleton for next post 2015-11-15 12:00:03 +01:00
Philipp Oppermann
b8d1dfd84d Merge pull request #41 from phil-opp/mention-no-redzone
Mention `-C no-redzone` in the `Setup Rust` post
2015-11-15 10:59:45 +01:00
Philipp Oppermann
65b4b4f027 Mention -C no-redzone in the Setup Rust post 2015-11-15 10:58:01 +01:00
Philipp Oppermann
340e1ff670 Merge pull request #39 from phil-opp/tools
Add script to cherry-pick commits to tags
2015-11-13 18:15:08 +01:00
Philipp Oppermann
d082f802f4 Move scripts to scripts folder 2015-11-13 18:13:01 +01:00
Philipp Oppermann
2a83b3440e Split script to allow switching branches & simplify code 2015-11-13 18:13:01 +01:00
Philipp Oppermann
79bd6873fb Added script to cherry-pick a commit to multiple tags 2015-11-13 18:13:01 +01:00
Philipp Oppermann
86d1ff145d Merge pull request #38 from phil-opp/replace_wildcard_dependecies
Replace wildcards in dependencies with a lower bound
2015-11-13 18:06:42 +01:00
Philipp Oppermann
6d05d4513c Replace wildcards in dependencies with a lower bound 2015-11-13 18:05:03 +01:00
Philipp Oppermann
b9a35036e3 Fix redirects 2015-11-07 01:12:33 +01:00
Philipp Oppermann
e8b6947555 Travis bugfix 2015-11-07 00:38:47 +01:00
Philipp Oppermann
6646326fb0 One more cosmetical thing 2015-11-07 00:34:16 +01:00
Philipp Oppermann
8dfc8531e4 Some cosmetical improvements for the blog update commits 2015-11-07 00:28:47 +01:00
Philipp Oppermann
91f7c70194 Last final travis fix: there is no _pages folder 2015-11-07 00:22:32 +01:00
Philipp Oppermann
2691f2b5d7 Final travis fix: add -r flag to copy 2015-11-07 00:19:09 +01:00
Philipp Oppermann
5978234f15 Fix: travis needs to clone it again because it needs gh-pages 2015-11-07 00:10:53 +01:00
Philipp Oppermann
753c8d4aea Fix ssh key name 2015-11-07 00:02:22 +01:00
Philipp Oppermann
5a49d761d9 Remove wrong include 2015-11-06 23:59:09 +01:00
Philipp Oppermann
1b2ff0f66e Merge pull request #28 from phil-opp/travis_blog_update
Use travis to update blog on master push
2015-11-06 23:56:10 +01:00
Philipp Oppermann
7e5dad2277 Update blog on push to master through travis 2015-11-06 23:55:00 +01:00
Philipp Oppermann
6e93a7d528 Add redirects again 2015-11-06 22:57:06 +01:00
Philipp Oppermann
e759a6826c Merge pull request #26 from phil-opp/merge_posts_pr
Move blog posts/pages into code repository
2015-11-06 22:50:07 +01:00
Philipp Oppermann
885168bea4 Move blog posts/pages into code repository
For history see the `rust_os_posts` tag in the phil-opp/phil-opp.github.io repository.
2015-11-06 22:47:39 +01:00
Philipp Oppermann
fa78bd82a8 Add missing license header 2015-11-03 19:53:28 +01:00
Homu
9986ee22d4 Auto merge of #23 - phil-opp:phil-opp-patch-1, r=phil-opp
Add travis badge to README
2015-11-02 06:39:20 +09:00
Philipp Oppermann
2b075af068 Add travis badge 2015-11-01 19:53:25 +01:00
Homu
77373d59b2 Auto merge of #22 - phil-opp:phil-opp-patch-1, r=phil-opp
Link the blog in README
2015-11-02 03:35:33 +09:00
Philipp Oppermann
fa96486353 Add link to blog 2015-11-01 18:59:45 +01:00
Philipp Oppermann
e582b37f19 Merge pull request #21 from phil-opp/imul_mul
Use unsigned `mul` instead of signed `imul`
2015-10-31 13:50:46 +01:00
Philipp Oppermann
8789fa8531 Use unsigned mul instead of signed imul 2015-10-31 13:48:58 +01:00
Philipp Oppermann
1e7236caf5 Merge pull request #18 from phil-opp/2mib_pages
Use 2MiB pages instead of one 1GiB page
2015-10-29 18:20:58 +01:00
Philipp Oppermann
2a35ec19b6 Use 2MiB pages instead of one 1GiB page 2015-10-29 17:47:21 +01:00
Philipp Oppermann
dfabc0ff32 Merge pull request #15 from phil-opp/printing_to_screen_improvements
Add the clear_screen function from the blog post
2015-10-27 20:50:08 +01:00
Philipp Oppermann
e439e9eb5d Use a byte char instead of casting 2015-10-27 20:48:14 +01:00
Philipp Oppermann
c36a3d19d2 Add and use a clear_screen function 2015-10-27 20:47:58 +01:00
Philipp Oppermann
54b47aaac1 Merge pull request #14 from phil-opp/multiboot_header_section_name
Rename `multiboot` section to `multiboot_header`
2015-10-27 18:47:03 +01:00
Philipp Oppermann
7b0428b07a Rename multiboot section to multiboot_header 2015-10-27 18:42:28 +01:00
Philipp Oppermann
8640091bc6 Merge pull request #12 from phil-opp/a_minimal_kernel_fixes
Makefile fixes
2015-10-26 23:02:34 +01:00
Philipp Oppermann
5e5374cd7d Update grub.cfg to use renamed kernel file
Renaming occurred in 37b576e to be in line with the blog posts.
2015-10-26 16:54:45 +01:00
Jacob Krall
37b576eb3c Explicitly rename copied kernel to kernel.bin
Otherwise your `grub.cfg` from earlier in the article will be out of date (we're producing `kernel-x86_64.bin`, but grub expects `kernel.bin`).
2015-10-26 15:45:46 +01:00
Jacob Krall
9ecaf0fe0c make iso depends on grub.cfg
This way, if you fix a typo in grub.cfg, you don't have to `make clean` to get `make iso` to pick it up.
2015-10-26 15:45:19 +01:00
Philipp Oppermann
1e90a1e78d Merge pull request #8 from phil-opp/printing_to_screen_repr_c
Add #[repr(C)] to ScreenChar
2015-10-25 15:53:45 +01:00
Philipp Oppermann
34dd42a6fc Add #[repr(C)] to ScreenChar 2015-10-25 15:38:08 +01:00
Philipp Oppermann
68c0ab0d59 Merge pull request #7 from phil-opp/fix_long_mode_test
Fix long mode test
2015-10-25 01:51:43 +02:00
Philipp Oppermann
f670e330f5 Fix long mode test (fixes #6) 2015-10-25 01:49:42 +02:00
Philipp Oppermann
a39a611629 Wording: replace check with test 2015-10-25 01:48:57 +02:00
Philipp Oppermann
9cd9ec25db Merge pull request #5 from phil-opp/rust-target
Specify rust target
2015-10-24 16:25:50 +02:00
Philipp Oppermann
3d94304bbb Specify rust target 2015-10-24 16:20:46 +02:00
Philipp Oppermann
95028c0f5d Merge pull request #3 from phil-opp/vga_buffer
Add a VGA buffer module
2015-10-23 12:47:44 +02:00
Philipp Oppermann
5b1f2361f2 Use println! to print the `Hello World! 2015-10-23 01:45:10 +02:00
Philipp Oppermann
4d29482952 Add custom print and println macros 2015-10-23 01:45:10 +02:00
Philipp Oppermann
e4a8c4c9fa Silence dead code warnings for unused colors 2015-10-23 01:45:10 +02:00
Philipp Oppermann
c547b128e5 Implement fmt::Write trait for Writer 2015-10-23 01:45:10 +02:00
Philipp Oppermann
4668acb09e Add a public static writer
Since `unsafe const` aren't allowed yet, we temorary add a custom version of Unique to make `Unique::new` const (instead of unsafe).
2015-10-23 01:45:10 +02:00
Philipp Oppermann
ab464b107d Add a basic writer type to print single bytes
It prints always to the last line and shifts lines up on newline or line wrap. To easily shift lines up, we make the ColorCode and ScreenChar types Copy.
2015-10-23 01:45:10 +02:00
Philipp Oppermann
49fd8926a5 Add a VGA buffer module skeleton
It contains basic types for colors, screen characters, and the buffer itself.
2015-10-23 01:45:10 +02:00
Philipp Oppermann
3e7fd1b433 Merge pull request #4 from phil-opp/better_hello_world
Improve `Hello World!` code
2015-10-03 17:40:14 +02:00
Philipp Oppermann
5bcd6d2c2d Improve Hello World! code
Avoid special core features and complicated iterator chaining to make the code simpler overall.
2015-10-03 17:38:41 +02:00
28 changed files with 1740 additions and 187 deletions

View File

@@ -15,5 +15,4 @@ addons:
packages:
- nasm
script:
- make
script: make

View File

@@ -1,10 +1,29 @@
[package]
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
name = "blog_os"
version = "0.1.0"
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
[dependencies]
bit_field = "0.7.0"
bitflags = "0.7.0"
multiboot2 = "0.1.0"
once = "0.2.1"
rlibc = "0.1.4"
spin = "0.3.4"
volatile = "0.1.0"
[dependencies.hole_list_allocator]
path = "libs/hole_list_allocator"
[dependencies.x86]
default-features = false
version = "0.8.0"
[lib]
crate-type = ["staticlib"]
[dependencies]
rlibc = "*"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

9
LICENSE-MIT Normal file
View File

@@ -0,0 +1,9 @@
The MIT License (MIT)
Copyright (c) 2015 Philipp Oppermann
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,29 +1,25 @@
# Copyright 2015 Philipp Oppermann
# 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 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
arch ?= x86_64
target ?= $(arch)-unknown-linux-gnu
kernel := build/kernel-$(arch).bin
iso := build/os-$(arch).iso
rust_os := target/debug/libblog_os.a
rust_os := target/$(target)/debug/libblog_os.a
linker_script := src/arch/$(arch)/linker.ld
grub_cfg := src/arch/$(arch)/grub.cfg
assembly_source_files := $(wildcard src/arch/$(arch)/*.asm)
assembly_object_files := $(patsubst src/arch/$(arch)/%.asm, \
build/arch/$(arch)/%.o, $(assembly_source_files))
.PHONY: all clean run iso cargo
.PHONY: all clean run debug iso cargo gdb
all: $(kernel)
@@ -32,13 +28,19 @@ clean:
@rm -rf build
run: $(iso)
@qemu-system-x86_64 -hda $(iso)
@qemu-system-x86_64 -cdrom $(iso) -s
debug: $(iso)
@qemu-system-x86_64 -cdrom $(iso) -s -S
gdb:
@rust-os-gdb/bin/rust-gdb "build/kernel-x86_64.bin" -ex "target remote :1234"
iso: $(iso)
$(iso): $(kernel)
$(iso): $(kernel) $(grub_cfg)
@mkdir -p build/isofiles/boot/grub
@cp $(kernel) build/isofiles/boot/
@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
@@ -47,7 +49,7 @@ $(kernel): cargo $(rust_os) $(assembly_object_files) $(linker_script)
@ld -n --gc-sections -T $(linker_script) -o $(kernel) $(assembly_object_files) $(rust_os)
cargo:
@cargo rustc -- -Z no-landing-pads
@cargo build --target $(target)
# compile assembly files
build/arch/$(arch)/%.o: src/arch/$(arch)/%.asm

View File

@@ -1 +1,14 @@
# blogOS
# Blog OS (Better Exception Messages)
[![Build Status](https://travis-ci.org/phil-opp/blog_os.svg?branch=better_exception_messages)](https://travis-ci.org/phil-opp/blog_os/branches)
This repository contains the source code for the [Better Exception Messages](http://os.phil-opp.com/better-exception-messages.html) post of the [Writing an OS in Rust](http://os.phil-opp.com) series.
**Check out the [master branch](https://github.com/phil-opp/blog_os) for more information.**
## Building
You need to have `nasm`, `grub-mkrescue`, `xorriso`, `qemu`, and a nightly Rust compiler installed. Then you can run it using `make run`.
Please file an issue if you have any problems.
## License
The source code is dual-licensed under MIT or the Apache License (Version 2.0).

2
libs/bump_allocator/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Generated by Cargo
/target/

View File

@@ -0,0 +1,7 @@
[package]
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
name = "bump_allocator"
version = "0.1.0"
[dependencies]
spin = "0.3.5"

View File

@@ -0,0 +1,114 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(const_fn)]
#![feature(allocator)]
#![allocator]
#![no_std]
use spin::Mutex;
extern crate spin;
pub const HEAP_START: usize = 0o_000_001_000_000_0000;
pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB
static BUMP_ALLOCATOR: Mutex<BumpAllocator> = Mutex::new(
BumpAllocator::new(HEAP_START, HEAP_SIZE));
#[derive(Debug)]
struct BumpAllocator {
heap_start: usize,
heap_size: usize,
next: usize,
}
impl BumpAllocator {
/// Create a new allocator, which uses the memory in the
/// range [heap_start, heap_start + heap_size).
const fn new(heap_start: usize, heap_size: usize) -> BumpAllocator {
BumpAllocator {
heap_start: heap_start,
heap_size: heap_size,
next: heap_start,
}
}
/// Allocates a block of memory with the given size and alignment.
fn allocate(&mut self, size: usize, align: usize) -> Option<*mut u8> {
let alloc_start = align_up(self.next, align);
let alloc_end = alloc_start.saturating_add(size);
if alloc_end <= self.heap_start + self.heap_size {
self.next = alloc_end;
Some(alloc_start as *mut u8)
} else {
None
}
}
}
/// 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)
}
#[no_mangle]
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
BUMP_ALLOCATOR.lock().allocate(size, align).expect("out of memory")
}
#[no_mangle]
pub extern fn __rust_deallocate(_ptr: *mut u8, _size: usize,
_align: usize)
{
// just leak it
}
#[no_mangle]
pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
size
}
#[no_mangle]
pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, size: usize,
_new_size: usize, _align: usize) -> usize
{
size
}
#[no_mangle]
pub extern fn __rust_reallocate(ptr: *mut u8, size: usize, new_size: usize,
align: usize) -> *mut u8 {
use core::{ptr, cmp};
// from: https://github.com/rust-lang/rust/blob/
// c66d2380a810c9a2b3dbb4f93a830b101ee49cc2/
// src/liballoc_system/lib.rs#L98-L101
let new_ptr = __rust_allocate(new_size, align);
unsafe { ptr::copy(ptr, new_ptr, cmp::min(size, new_size)) };
__rust_deallocate(ptr, size, align);
new_ptr
}

2
libs/hole_list_allocator/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Generated by Cargo
/target/

View File

@@ -0,0 +1,12 @@
[package]
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
name = "hole_list_allocator"
version = "0.1.0"
[dependencies]
linked_list_allocator = "0.2.0"
spin = "0.3.5"
[dependencies.lazy_static]
version = "0.2.1"
features = ["spin_no_std"]

View File

@@ -0,0 +1,68 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(allocator)]
#![feature(const_fn)]
#![allocator]
#![no_std]
use spin::Mutex;
use linked_list_allocator::Heap;
extern crate spin;
extern crate linked_list_allocator;
#[macro_use]
extern crate lazy_static;
pub const HEAP_START: usize = 0o_000_001_000_000_0000;
pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB
lazy_static! {
static ref HEAP: Mutex<Heap> = Mutex::new(unsafe {
Heap::new(HEAP_START, HEAP_SIZE)
});
}
#[no_mangle]
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
HEAP.lock().allocate_first_fit(size, align).expect("out of memory")
}
#[no_mangle]
pub extern fn __rust_deallocate(ptr: *mut u8, size: usize, align: usize) {
unsafe { HEAP.lock().deallocate(ptr, size, align) };
}
#[no_mangle]
pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
size
}
#[no_mangle]
pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, size: usize,
_new_size: usize, _align: usize) -> usize
{
size
}
#[no_mangle]
pub extern fn __rust_reallocate(ptr: *mut u8, size: usize, new_size: usize,
align: usize) -> *mut u8 {
use core::{ptr, cmp};
// from: https://github.com/rust-lang/rust/blob/
// c66d2380a810c9a2b3dbb4f93a830b101ee49cc2/
// src/liballoc_system/lib.rs#L98-L101
let new_ptr = __rust_allocate(new_size, align);
unsafe { ptr::copy(ptr, new_ptr, cmp::min(size, new_size)) };
__rust_deallocate(ptr, size, align);
new_ptr
}

View File

@@ -1,16 +1,11 @@
; Copyright 2015 Philipp Oppermann
; 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 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
; Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
; http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
; <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
; option. This file may not be copied, modified, or distributed
; except according to those terms.
global start
extern long_mode_start
@@ -19,33 +14,51 @@ section .text
bits 32
start:
mov esp, stack_top
; Move Multiboot info pointer to edi to pass it to the kernel. We must not
; modify the `edi` register until the kernel it called.
mov edi, ebx
call check_multiboot
call check_cpuid
call check_long_mode
call setup_page_tables
call set_up_page_tables
call enable_paging
call set_up_SSE
; load the 64-bit GDT
lgdt [gdt64.pointer]
; update selectors
mov ax, gdt64.data
mov ss, ax
mov ds, ax
mov es, ax
jmp gdt64.code:long_mode_start
setup_page_tables:
set_up_page_tables:
; recursive map 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 a huge page that starts at address 0
mov dword [p3_table], 0b10000011 ; present + writable + huge
; map first P3 entry to P2 table
mov eax, p2_table
or eax, 0b11 ; present + writable
mov [p3_table], 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
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, 512 ; if counter == 512, the whole P2 table is mapped
jne .map_p2_table ; else map the next entry
ret
@@ -68,7 +81,6 @@ enable_paging:
; enable paging in the cr0 register
mov eax, cr0
or eax, 1 << 31
or eax, 1 << 16
mov cr0, eax
ret
@@ -93,55 +105,98 @@ check_multiboot:
; Throw error 1 if the CPU doesn't support the CPUID command.
check_cpuid:
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
mov ecx, eax ; Set the C-register to the A-register.
xor eax, 1 << 21 ; Flip the ID-bit, which is bit 21.
push eax ; Store the A-register.
popfd ; Restore the FLAGS-register.
pushfd ; Store the FLAGS-register.
pop eax ; Restore the A-register.
push ecx ; Store the C-register.
popfd ; Restore the FLAGS-register.
xor eax, ecx ; Do a XOR-operation on the A-register and the C-register.
jz .no_cpuid ; The zero flag is set, no CPUID.
ret ; CPUID is available for use.
; 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
; Throw error 2 if the CPU doesn't support Long Mode.
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.
; 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
; Check for SSE and enable it. If it's not supported throw error "a".
set_up_SSE:
; check for SSE
mov eax, 0x1
cpuid
test edx, 1<<25
jz .no_SSE
; enable SSE
mov eax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
ret
.no_SSE:
mov al, "a"
jmp error
section .bss
align 4096
p4_table:
resb 4096
p3_table:
resb 4096
p2_table:
resb 4096
stack_bottom:
resb 64
resb 4096 * 2
stack_top:
section .rodata
gdt64:
dq 0 ; zero entry
.code: equ $ - gdt64 ; new
dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment
.data: equ $ - gdt64 ; new
dq (1<<44) | (1<<47) | (1<<41) ; data segment
dq (1<<44) | (1<<47) | (1<<43) | (1<<53) ; code segment
.pointer:
dw $ - gdt64 - 1
dq gdt64

View File

@@ -1,21 +1,16 @@
# Copyright 2015 Philipp Oppermann
# 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 (the "License")
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
set timeout=0
set default=0
menuentry "my os" {
multiboot2 /boot/kernel-x86_64.bin
multiboot2 /boot/kernel.bin
boot
}

View File

@@ -1,17 +1,12 @@
/*
Copyright 2015 Philipp Oppermann
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 (the "License")
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
option. This file may not be copied, modified, or distributed
except according to those terms.
*/
ENTRY(start)
@@ -19,14 +14,51 @@ ENTRY(start)
SECTIONS {
. = 1M;
.boot :
.rodata :
{
/* ensure that the multiboot header is at the beginning */
KEEP(*(.multiboot))
KEEP(*(.multiboot_header))
*(.rodata .rodata.*)
. = ALIGN(4K);
}
.text :
{
*(.text)
*(.text .text.*)
. = ALIGN(4K);
}
.data :
{
*(.data .data.*)
. = ALIGN(4K);
}
.bss :
{
*(.bss .bss.*)
. = ALIGN(4K);
}
.got :
{
*(.got)
. = ALIGN(4K);
}
.got.plt :
{
*(.got.plt)
. = ALIGN(4K);
}
.data.rel.ro : ALIGN(4K) {
*(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)
. = ALIGN(4K);
}
.gcc_except_table : ALIGN(4K) {
*(.gcc_except_table)
. = ALIGN(4K);
}
}

View File

@@ -1,16 +1,11 @@
; Copyright 2015 Philipp Oppermann
; 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 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
; Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
; http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
; <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
; option. This file may not be copied, modified, or distributed
; except according to those terms.
global long_mode_start
extern rust_main
@@ -18,9 +13,15 @@ extern rust_main
section .text
bits 64
long_mode_start:
call setup_SSE
; 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
; call rust main
; call rust main (with multiboot pointer in rdi)
call rust_main
.os_returned:
; rust main returned, print `OS returned!`
@@ -31,36 +32,3 @@ long_mode_start:
mov rax, 0x4f214f644f654f6e
mov [0xb8010], rax
hlt
; Check for SSE and enable it. If it's not supported throw error "a".
setup_SSE:
; check for SSE
mov rax, 0x1
cpuid
test edx, 1<<25
jz .no_SSE
; enable SSE
mov rax, cr0
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, rax
mov rax, cr4
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, rax
ret
.no_SSE:
mov al, "a"
jmp error
; Prints `ERROR: ` and the given error code to screen and hangs.
; parameter: error code (in ascii) in al
error:
mov rbx, 0x4f4f4f524f524f45
mov [0xb8000], rbx
mov rbx, 0x4f204f204f3a4f52
mov [0xb8008], rbx
mov byte [0xb800e], al
hlt
jmp error

View File

@@ -1,18 +1,13 @@
; Copyright 2015 Philipp Oppermann
; 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 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
; Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
; http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
; <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
; option. This file may not be copied, modified, or distributed
; except according to those terms.
section .multiboot
section .multiboot_header
header_start:
dd 0xe85250d6 ; magic number (multiboot 2)
dd 0 ; architecture 0 (protected mode i386)

115
src/interrupts/idt.rs Normal file
View File

@@ -0,0 +1,115 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use x86::shared::segmentation::{self, SegmentSelector};
use x86::shared::PrivilegeLevel;
pub struct Idt([Entry; 16]);
impl Idt {
pub fn new() -> Idt {
Idt([Entry::missing(); 16])
}
pub fn set_handler(&mut self, entry: u8, handler: HandlerFunc) -> &mut EntryOptions {
self.0[entry as usize] = Entry::new(segmentation::cs(), handler);
&mut self.0[entry as usize].options
}
pub fn load(&'static self) {
use x86::shared::dtables::{DescriptorTablePointer, lidt};
use core::mem::size_of;
let ptr = DescriptorTablePointer {
base: self as *const _ as *const ::x86::bits64::irq::IdtEntry,
limit: (size_of::<Self>() - 1) as u16,
};
unsafe { lidt(&ptr) };
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C, packed)]
pub struct Entry {
pointer_low: u16,
gdt_selector: SegmentSelector,
options: EntryOptions,
pointer_middle: u16,
pointer_high: u32,
reserved: u32,
}
pub type HandlerFunc = extern "C" fn() -> !;
impl Entry {
fn new(gdt_selector: SegmentSelector, handler: HandlerFunc) -> Self {
let pointer = handler as u64;
Entry {
gdt_selector: gdt_selector,
pointer_low: pointer as u16,
pointer_middle: (pointer >> 16) as u16,
pointer_high: (pointer >> 32) as u32,
options: EntryOptions::new(),
reserved: 0,
}
}
fn missing() -> Self {
Entry {
gdt_selector: SegmentSelector::new(0, PrivilegeLevel::Ring0),
pointer_low: 0,
pointer_middle: 0,
pointer_high: 0,
options: EntryOptions::minimal(),
reserved: 0,
}
}
}
use bit_field::BitField;
#[derive(Debug, Clone, Copy)]
pub struct EntryOptions(u16);
impl EntryOptions {
fn minimal() -> Self {
let mut options = 0;
options.set_bits(9..12, 0b111); // 'must-be-one' bits
EntryOptions(options)
}
fn new() -> Self {
let mut options = Self::minimal();
options.set_present(true).disable_interrupts(true);
options
}
pub fn set_present(&mut self, present: bool) -> &mut Self {
self.0.set_bit(15, present);
self
}
pub fn disable_interrupts(&mut self, disable: bool) -> &mut Self {
self.0.set_bit(8, !disable);
self
}
#[allow(dead_code)]
pub fn set_privilege_level(&mut self, dpl: u16) -> &mut Self {
self.0.set_bits(13..15, dpl);
self
}
#[allow(dead_code)]
pub fn set_stack_index(&mut self, index: u16) -> &mut Self {
self.0.set_bits(0..3, index);
self
}
}

105
src/interrupts/mod.rs Normal file
View File

@@ -0,0 +1,105 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod idt;
macro_rules! handler {
($name: ident) => {{
#[naked]
extern "C" fn wrapper() -> ! {
unsafe {
asm!("mov rdi, rsp
sub rsp, 8 // align the stack pointer
call $0"
:: "i"($name as extern "C" fn(
&ExceptionStackFrame) -> !)
: "rdi" : "intel");
::core::intrinsics::unreachable();
}
}
wrapper
}}
}
macro_rules! handler_with_error_code {
($name: ident) => {{
#[naked]
extern "C" fn wrapper() -> ! {
unsafe {
asm!("pop rsi // pop error code into rsi
mov rdi, rsp
sub rsp, 8 // align the stack pointer
call $0"
:: "i"($name as extern "C" fn(
&ExceptionStackFrame, u64) -> !)
: "rdi","rsi" : "intel");
::core::intrinsics::unreachable();
}
}
wrapper
}}
}
lazy_static! {
static ref IDT: idt::Idt = {
let mut idt = idt::Idt::new();
idt.set_handler(0, handler!(divide_by_zero_handler));
idt.set_handler(6, handler!(invalid_opcode_handler));
idt.set_handler(14, handler_with_error_code!(page_fault_handler));
idt
};
}
pub fn init() {
IDT.load();
}
#[derive(Debug)]
#[repr(C)]
struct ExceptionStackFrame {
instruction_pointer: u64,
code_segment: u64,
cpu_flags: u64,
stack_pointer: u64,
stack_segment: u64,
}
extern "C" fn divide_by_zero_handler(stack_frame: &ExceptionStackFrame) -> ! {
println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
loop {}
}
extern "C" fn invalid_opcode_handler(stack_frame: &ExceptionStackFrame) -> ! {
println!("\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}",
stack_frame.instruction_pointer,
stack_frame);
loop {}
}
bitflags! {
flags PageFaultErrorCode: u64 {
const PROTECTION_VIOLATION = 1 << 0,
const CAUSED_BY_WRITE = 1 << 1,
const USER_MODE = 1 << 2,
const MALFORMED_TABLE = 1 << 3,
const INSTRUCTION_FETCH = 1 << 4,
}
}
extern "C" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: u64) -> ! {
use x86::shared::control_regs;
println!("\nEXCEPTION: PAGE FAULT while accessing {:#x}\nerror code: \
{:?}\n{:#?}",
unsafe { control_regs::cr2() },
PageFaultErrorCode::from_bits(error_code).unwrap(),
stack_frame);
loop {}
}

View File

@@ -1,46 +1,97 @@
// Copyright 2015 Philipp Oppermann
// 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 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(no_std, lang_items)]
#![feature(core_slice_ext, core_str_ext, core_intrinsics)]
#![feature(lang_items)]
#![feature(const_fn, unique)]
#![feature(alloc, collections)]
#![feature(asm)]
#![feature(naked_functions)]
#![feature(core_intrinsics)]
#![no_std]
extern crate rlibc;
extern crate volatile;
extern crate spin;
extern crate multiboot2;
#[macro_use]
extern crate bitflags;
extern crate x86;
#[macro_use]
extern crate once;
extern crate bit_field;
use core::intrinsics::offset;
extern crate hole_list_allocator;
extern crate alloc;
#[macro_use]
extern crate collections;
#[macro_use]
mod vga_buffer;
mod memory;
mod interrupts;
#[no_mangle]
pub extern fn rust_main() {
pub extern "C" fn rust_main(multiboot_information_address: usize) {
// ATTENTION: we have a very small stack and no guard page
let x = ["Hello", " ", "World", "!"];
let screen_pointer = 0xb8000 as *const u16;
vga_buffer::clear_screen();
println!("Hello World{}", "!");
for (byte, i) in x.iter().flat_map(|s| s.bytes()).zip(0..) {
let c = 0x1f00 | (byte as u16);
unsafe {
let screen_char = offset(screen_pointer, i) as *mut u16;
*screen_char = c
}
}
let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
enable_nxe_bit();
enable_write_protect_bit();
// set up guard page and map the heap pages
memory::init(boot_info);
// initialize our IDT
interrupts::init();
// provoke a page fault
unsafe { *(0xdeadbeaf as *mut u64) = 42 };
println!("It did not crash!");
loop {}
}
fn enable_nxe_bit() {
use x86::shared::msr::{IA32_EFER, rdmsr, wrmsr};
let nxe_bit = 1 << 11;
unsafe {
let efer = rdmsr(IA32_EFER);
wrmsr(IA32_EFER, efer | nxe_bit);
}
}
fn enable_write_protect_bit() {
use x86::shared::control_regs::{cr0, cr0_write, CR0_WRITE_PROTECT};
unsafe { cr0_write(cr0() | CR0_WRITE_PROTECT) };
}
#[cfg(not(test))]
#[lang = "eh_personality"]
extern fn eh_personality() {}
extern "C" fn eh_personality() {}
#[cfg(not(test))]
#[lang = "panic_fmt"]
extern fn panic_fmt() -> ! {loop{}}
#[no_mangle]
pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: u32) -> ! {
println!("\n\nPANIC in {} at line {}:", file, line);
println!(" {}", fmt);
loop {}
}
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn _Unwind_Resume() -> ! {
loop {}
}

View File

@@ -0,0 +1,103 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use memory::{Frame, FrameAllocator};
use multiboot2::{MemoryAreaIter, MemoryArea};
/// A frame allocator that uses the memory areas from the multiboot information structure as
/// source. The {kernel, multiboot}_{start, end} fields are used to avoid returning memory that is
/// already in use.
///
/// `kernel_end` and `multiboot_end` are _inclusive_ bounds.
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<Frame> {
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!()
}
}

111
src/memory/mod.rs Normal file
View File

@@ -0,0 +1,111 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::area_frame_allocator::AreaFrameAllocator;
pub use self::paging::remap_the_kernel;
use self::paging::PhysicalAddress;
use multiboot2::BootInformation;
mod area_frame_allocator;
mod paging;
pub const PAGE_SIZE: usize = 4096;
pub fn init(boot_info: &BootInformation) {
assert_has_not_been_called!("memory::init must be called only once");
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");
let kernel_start = elf_sections_tag.sections()
.filter(|s| s.is_allocated())
.map(|s| s.addr)
.min()
.unwrap();
let kernel_end = elf_sections_tag.sections()
.filter(|s| s.is_allocated())
.map(|s| s.addr + s.size)
.max()
.unwrap();
println!("kernel start: {:#x}, kernel end: {:#x}",
kernel_start,
kernel_end);
println!("multiboot start: {:#x}, multiboot end: {:#x}",
boot_info.start_address(),
boot_info.end_address());
let mut frame_allocator = AreaFrameAllocator::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 self::paging::Page;
use hole_list_allocator::{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::WRITABLE, &mut frame_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 }
}
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: start,
end: end,
}
}
}
struct FrameIter {
start: Frame,
end: Frame,
}
impl Iterator for FrameIter {
type Item = Frame;
fn next(&mut self) -> Option<Frame> {
if self.start <= self.end {
let frame = self.start.clone();
self.start.number += 1;
Some(frame)
} else {
None
}
}
}
pub trait FrameAllocator {
fn allocate_frame(&mut self) -> Option<Frame>;
fn deallocate_frame(&mut self, frame: Frame);
}

View File

@@ -0,0 +1,76 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use memory::Frame;
use multiboot2::ElfSection;
pub struct Entry(u64);
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<Frame> {
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();
}
}
bitflags! {
pub flags 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 EntryFlags {
pub fn from_elf_section_flags(section: &ElfSection) -> EntryFlags {
use multiboot2::{ELF_SECTION_ALLOCATED, ELF_SECTION_WRITABLE, ELF_SECTION_EXECUTABLE};
let mut flags = EntryFlags::empty();
if section.flags().contains(ELF_SECTION_ALLOCATED) {
// section is loaded to memory
flags = flags | PRESENT;
}
if section.flags().contains(ELF_SECTION_WRITABLE) {
flags = flags | WRITABLE;
}
if !section.flags().contains(ELF_SECTION_EXECUTABLE) {
flags = flags | NO_EXECUTE;
}
flags
}
}

118
src/memory/paging/mapper.rs Normal file
View File

@@ -0,0 +1,118 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::{VirtualAddress, PhysicalAddress, Page, ENTRY_COUNT};
use super::entry::*;
use super::table::{self, Table, Level4};
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use core::ptr::Unique;
pub struct Mapper {
p4: Unique<Table<Level4>>,
}
impl Mapper {
pub unsafe fn new() -> Mapper {
Mapper { p4: Unique::new(table::P4) }
}
pub fn p4(&self) -> &Table<Level4> {
unsafe { self.p4.get() }
}
pub fn p4_mut(&mut self) -> &mut Table<Level4> {
unsafe { self.p4.get_mut() }
}
pub fn translate(&self, virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
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<Frame> {
let p3 = self.p4().next_table(page.p4_index());
let huge_page = || {
p3.and_then(|p3| {
let p3_entry = &p3[page.p3_index()];
// 1GiB page?
if let Some(start_frame) = p3_entry.pointed_frame() {
if p3_entry.flags().contains(HUGE_PAGE) {
// address must be 1GiB aligned
assert!(start_frame.number % (ENTRY_COUNT * ENTRY_COUNT) == 0);
return Some(Frame {
number: start_frame.number + page.p2_index() * ENTRY_COUNT +
page.p1_index(),
});
}
}
if let Some(p2) = p3.next_table(page.p3_index()) {
let p2_entry = &p2[page.p2_index()];
// 2MiB page?
if let Some(start_frame) = p2_entry.pointed_frame() {
if p2_entry.flags().contains(HUGE_PAGE) {
// address must be 2MiB aligned
assert!(start_frame.number % ENTRY_COUNT == 0);
return Some(Frame { number: start_frame.number + page.p1_index() });
}
}
}
None
})
};
p3.and_then(|p3| p3.next_table(page.p3_index()))
.and_then(|p2| p2.next_table(page.p2_index()))
.and_then(|p1| p1[page.p1_index()].pointed_frame())
.or_else(huge_page)
}
pub fn map_to<A>(&mut self, page: Page, frame: Frame, flags: EntryFlags, allocator: &mut A)
where A: FrameAllocator
{
let mut p3 = self.p4_mut().next_table_create(page.p4_index(), allocator);
let mut p2 = p3.next_table_create(page.p3_index(), allocator);
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 | PRESENT);
}
pub fn map<A>(&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<A>(&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<A>(&mut self, page: Page, allocator: &mut A)
where A: FrameAllocator
{
assert!(self.translate(page.start_address()).is_some());
let p1 = self.p4_mut()
.next_table_mut(page.p4_index())
.and_then(|p3| p3.next_table_mut(page.p3_index()))
.and_then(|p2| p2.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();
unsafe { ::x86::shared::tlb::flush(page.start_address()) };
// TODO free p(1,2,3) table if empty
// allocator.deallocate_frame(frame);
}
}

227
src/memory/paging/mod.rs Normal file
View File

@@ -0,0 +1,227 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::entry::*;
use memory::{PAGE_SIZE, Frame, FrameAllocator};
use self::temporary_page::TemporaryPage;
pub use self::mapper::Mapper;
use core::ops::{Deref, DerefMut};
use multiboot2::BootInformation;
mod entry;
mod table;
mod temporary_page;
mod mapper;
const ENTRY_COUNT: usize = 512;
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 address: 0x{:x}",
address);
Page { number: address / PAGE_SIZE }
}
fn start_address(&self) -> usize {
self.number * PAGE_SIZE
}
fn p4_index(&self) -> usize {
(self.number >> 27) & 0o777
}
fn p3_index(&self) -> usize {
(self.number >> 18) & 0o777
}
fn p2_index(&self) -> usize {
(self.number >> 9) & 0o777
}
fn p1_index(&self) -> usize {
(self.number >> 0) & 0o777
}
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
PageIter {
start: start,
end: end,
}
}
}
pub struct PageIter {
start: Page,
end: Page,
}
impl Iterator for PageIter {
type Item = Page;
fn next(&mut self) -> Option<Page> {
if self.start <= self.end {
let page = self.start;
self.start.number += 1;
Some(page)
} else {
None
}
}
}
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 {
unsafe fn new() -> ActivePageTable {
ActivePageTable { mapper: Mapper::new() }
}
pub fn with<F>(&mut self,
table: &mut InactivePageTable,
temporary_page: &mut temporary_page::TemporaryPage, // new
f: F)
where F: FnOnce(&mut Mapper)
{
use x86::shared::{control_regs, tlb};
let flush_tlb = || unsafe { tlb::flush_all() };
{
let backup = Frame::containing_address(unsafe { control_regs::cr3() } as usize);
// map temporary_page to current p4 table
let p4_table = temporary_page.map_table_frame(backup.clone(), self);
// overwrite recursive mapping
self.p4_mut()[511].set(table.p4_frame.clone(), PRESENT | WRITABLE);
flush_tlb();
// execute f in the new context
f(self);
// restore recursive mapping to original p4 table
p4_table[511].set(backup, PRESENT | WRITABLE);
flush_tlb();
}
temporary_page.unmap(self);
}
pub fn switch(&mut self, new_table: InactivePageTable) -> InactivePageTable {
use x86::shared::control_regs;
let old_table = InactivePageTable {
p4_frame: Frame::containing_address(unsafe { control_regs::cr3() } as usize),
};
unsafe {
control_regs::cr3_write(new_table.p4_frame.start_address());
}
old_table
}
}
pub struct InactivePageTable {
p4_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();
table[511].set(frame.clone(), PRESENT | WRITABLE);
}
temporary_page.unmap(active_table);
InactivePageTable { p4_frame: frame }
}
}
pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> ActivePageTable
where A: FrameAllocator
{
let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe }, 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");
// identity map the allocated kernel sections
for section in elf_sections_tag.sections() {
if !section.is_allocated() {
// section is not loaded to memory
continue;
}
assert!(section.addr as usize % PAGE_SIZE == 0,
"sections need to be page aligned");
println!("mapping section at addr: {:#x}, size: {:#x}",
section.addr,
section.size);
let flags = EntryFlags::from_elf_section_flags(section);
let start_frame = Frame::containing_address(section.start_address());
let end_frame = Frame::containing_address(section.end_address() - 1);
for frame in Frame::range_inclusive(start_frame, end_frame) {
mapper.identity_map(frame, flags, allocator);
}
}
// identity map the VGA text buffer
let vga_buffer_frame = Frame::containing_address(0xb8000);
mapper.identity_map(vga_buffer_frame, WRITABLE, allocator);
// identity map the multiboot info structure
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, PRESENT, allocator);
}
});
let old_table = active_table.switch(new_table);
println!("NEW TABLE!!!");
let old_p4_page = Page::containing_address(old_table.p4_frame.start_address());
active_table.unmap(old_p4_page, allocator);
println!("guard page at {:#x}", old_p4_page.start_address());
active_table
}

119
src/memory/paging/table.rs Normal file
View File

@@ -0,0 +1,119 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::FrameAllocator;
use core::ops::{Index, IndexMut};
use core::marker::PhantomData;
pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;
pub struct Table<L: TableLevel> {
entries: [Entry; ENTRY_COUNT],
level: PhantomData<L>,
}
impl<L> Table<L>
where L: TableLevel
{
pub fn zero(&mut self) {
for entry in self.entries.iter_mut() {
entry.set_unused();
}
}
}
impl<L> Table<L>
where L: HierarchicalLevel
{
fn next_table_address(&self, index: usize) -> Option<usize> {
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
}
}
pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
self.next_table_address(index)
.map(|address| unsafe { &*(address as *const _) })
}
pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
self.next_table_address(index)
.map(|address| unsafe { &mut *(address as *mut _) })
}
pub fn next_table_create<A>(&mut self,
index: usize,
allocator: &mut A)
-> &mut Table<L::NextLevel>
where A: FrameAllocator
{
if self.next_table(index).is_none() {
assert!(!self.entries[index].flags().contains(HUGE_PAGE),
"mapping code does not support huge pages");
let frame = allocator.allocate_frame().expect("no frames available");
self.entries[index].set(frame, PRESENT | WRITABLE);
self.next_table_mut(index).unwrap().zero();
}
self.next_table_mut(index).unwrap()
}
}
impl<L> Index<usize> for Table<L>
where L: TableLevel
{
type Output = Entry;
fn index(&self, index: usize) -> &Entry {
&self.entries[index]
}
}
impl<L> IndexMut<usize> for Table<L>
where L: TableLevel
{
fn index_mut(&mut self, index: usize) -> &mut Entry {
&mut self.entries[index]
}
}
pub trait TableLevel {}
pub enum Level4 {}
#[allow(dead_code)]
pub enum Level3 {}
#[allow(dead_code)]
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;
}

View File

@@ -0,0 +1,86 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
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<A>(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::WRITABLE;
assert!(active_table.translate_page(self.page).is_none(),
"temporary page is already mapped");
active_table.map_to(self.page, frame, WRITABLE, &mut self.allocator);
self.page.start_address()
}
/// 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<Level1> {
unsafe { &mut *(self.map(frame, active_table) as *mut Table<Level1>) }
}
/// 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)
}
}
struct TinyAllocator([Option<Frame>; 3]);
impl TinyAllocator {
fn new<A>(allocator: &mut A) -> TinyAllocator
where A: FrameAllocator
{
let mut f = || allocator.allocate_frame();
let frames = [f(), f(), f()];
TinyAllocator(frames)
}
}
impl FrameAllocator for TinyAllocator {
fn allocate_frame(&mut self) -> Option<Frame> {
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 allocator can hold only 3 frames.");
}
}

150
src/vga_buffer.rs Normal file
View File

@@ -0,0 +1,150 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Writer> = Mutex::new(Writer {
column_position: 0,
color_code: ColorCode::new(Color::LightGreen, Color::Black),
buffer: unsafe { Unique::new(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();
}
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,
buffer: Unique<Buffer>,
}
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;
}
}
}
fn buffer(&mut self) -> &mut Buffer {
unsafe { self.buffer.get_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);
}
}
}
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,
}
struct Buffer {
chars: [[Volatile<ScreenChar>; BUFFER_WIDTH]; BUFFER_HEIGHT],
}