# Tutorial 14 - Virtual Memory Part 2: MMIO Remap
## tl;dr
- We introduce a first set of changes which is eventually needed for separating `kernel` and `user`
address spaces.
- The memory mapping strategy gets more sophisticated as we do away with `identity mapping` the
whole of the board's address space.
- Instead, only ranges that are actually needed are mapped:
- The `kernel binary` stays `identity mapped` for now.
- Device `MMIO regions` are remapped lazily (to a special reserved virtual address region).
## Table of Contents
- [Introduction](#introduction)
- [Implementation](#implementation)
- [A New Mapping API in `src/memory/mmu.rs`](#a-new-mapping-api-in-srcmemorymmutranslationtablers)
- [The new APIs in action](#the-new-apis-in-action)
- [MMIO Virtual Address Allocation](#mmio-virtual-address-allocation)
- [Supporting Changes](#supporting-changes)
- [Test it](#test-it)
- [Diff to previous](#diff-to-previous)
## Introduction
This tutorial is a first step of many needed for enabling `userspace applications` (which we
hopefully will have some day in the very distant future).
For this, one of the features we want is a clean separation of `kernel` and `user` address spaces.
Fortunately, `ARMv8` has convenient architecture support to realize this. The following text and
pictue gives some more motivation and technical information. It is quoted from the _[ARM Cortex-A
Series Programmer’s Guide for ARMv8-A], Chapter 12.2, Separation of kernel and application Virtual
Address spaces_:
> Operating systems typically have a number of applications or tasks running concurrently. Each of
> these has its own unique set of translation tables and the kernel switches from one to another as
> part of the process of switching context between one task and another. However, much of the memory
> system is used only by the kernel and has fixed virtual to Physical Address mappings where the
> translation table entries rarely change. The ARMv8 architecture provides a number of features to
> efficiently handle this requirement.
>
> The table base addresses are specified in the Translation Table Base Registers `TTBR0_EL1` and
> `TTBR1_EL1`. The translation table pointed to by `TTBR0` is selected when the upper bits of the VA
> are all 0. `TTBR1` is selected when the upper bits of the VA are all set to 1. [...]
>
> Figure 12-4 shows how the kernel space can be mapped to the most significant area of memory and
> the Virtual Address space associated with each application mapped to the least significant area of
> memory. However, both of these are mapped to a much smaller Physical Address space.
<p align="center">
<img src="../doc/15_kernel_user_address_space_partitioning.png" height="500" align="center">
</p>
This approach is also sometimes called a "[higher half kernel]". To eventually achieve this
separation, this tutorial makes a start by changing the following things:
1. Instead of bulk-`identity mapping` the whole of the board's address space, only the particular
parts that are needed will be mapped.
1. For now, the `kernel binary` stays identity mapped. This will be changed in the coming tutorials
as it is a quite difficult and peculiar exercise to remap the kernel.
1. Device `MMIO regions` are lazily remapped during device driver bringup (using the new
`DriverManage` function `instantiate_drivers()`).
1. A dedicated region of virtual addresses that we reserve using `BSP` code and the `linker
script` is used for this.
1. We keep using `TTBR0` for the kernel translation tables for now. This will be changed when we
remap the `kernel binary` in the coming tutorials.
[ARM Cortex-A Series Programmer’s Guide for ARMv8-A]: https://developer.arm.com/documentation/den0024/latest/
[higher half kernel]: https://wiki.osdev.org/Higher_Half_Kernel
## Implementation
Until now, the whole address space of the board was identity mapped at once. The **architecture**
(`src/_arch/_/memory/**`) and **bsp** (`src/bsp/_/memory/**`) parts of the kernel worked
together directly while setting up the translation tables, without any indirection through **generic
kernel code** (`src/memory/**`).
The way it worked was that the `architectural MMU code` would query the `bsp code` about the start
and end of the physical address space, and any special regions in this space that need a mapping
that _is not_ normal chacheable DRAM. It would then go ahead and map the whole address space at once
and never touch the translation tables again during runtime.
Changing in this tutorial, **architecture** and **bsp** code will no longer autonomously create the
virtual memory mappings. Instead, this is now orchestrated by the kernel's **generic MMU subsystem
code**.
### A New Mapping API in `src/memory/mmu/translation_table.rs`
First, we define an interface for operating on `translation tables`:
```rust
/// Translation table operations.
pub trait TranslationTable {
/// Anything that needs to run before any of the other provided functions can be used.
///
/// # Safety
///
/// - Implementor must ensure that this function can run only once or is harmless if invoked
/// multiple times.
fn init(&mut self);
/// The translation table's base address to be used for programming the MMU.
fn phys_base_address(&self) -> Address<Physical>;
/// Map the given virtual memory region to the given physical memory region.
unsafe fn map_at(
&mut self,
virt_region: &MemoryRegion<Virtual>,
phys_region: &MemoryRegion<Physical>,
attr: &AttributeFields,
) -> Result<(), &'static str>;
}
```
In order to enable the generic kernel code to manipulate the kernel's translation tables, they must
first be made accessible. Until now, they were just a "hidden" struct in the `architectural` MMU
driver (`src/arch/.../memory/mmu.rs`). This made sense because the MMU driver code was the only code
that needed to be concerned with the table data structure, so having it accessible locally
simplified things.
Since the tables need to be exposed to the rest of the kernel code now, it makes sense to move them
to `BSP` code. Because ultimately, it is the `BSP` that is defining the translation table's
properties, such as the size of the virtual address space that the tables need to cover.
They are now defined in the global instances region of `src/bsp/.../memory/mmu.rs`. To control
access, they are guarded by an `InitStateLock`.
```rust
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
/// The kernel translation tables.
static KERNEL_TABLES: InitStateLock<KernelTranslationTable> =
InitStateLock::new(KernelTranslationTable::new());
```
The struct `KernelTranslationTable` is a type alias defined in the same file, which in turn gets its
definition from an associated type of type `KernelVirtAddrSpace`, which itself is a type alias of
`memory::mmu::AddressSpace`. I know this sounds horribly complicated, but in the end this is just
some layers of `const generics` whose implementation is scattered between `generic` and `arch` code.
This is done to (1) ensure a sane compile-time definition of the translation table struct (by doing
various bounds checks), and (2) to separate concerns between generic `MMU` code and specializations
that come from the `architectural` part.
In the end, these tables can be accessed by calling `bsp::memory::mmu::kernel_translation_tables()`:
```rust
/// Return a reference to the kernel's translation tables.
pub fn kernel_translation_tables() -> &'static InitStateLock<KernelTranslationTable> {
&KERNEL_TABLES
}
```
Finally, the generic kernel code (`src/memory/mmu.rs`) now provides a couple of memory mapping
functions that access and manipulate this instance. They are exported for the rest of the kernel to
use:
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
### 使用 Rust 实现一个基于树莓派的操作系统 #### 资源概述 本资源包提供了一套详细的指南和完整的源码,用于使用 Rust 编程语言在树莓派上实现一个简单的操作系统。该资源包旨在帮助开发者深入了解操作系统的基本原理和实现方法,同时掌握 Rust 在系统编程中的应用。内容包括开题报告、开发指南、源码实现和配置说明,非常适合对系统编程和嵌入式开发感兴趣的学生和开发者。 #### 内容介绍 1. **项目背景** - 介绍树莓派硬件的基本特点及其在嵌入式开发中的应用。 - 解释选择 Rust 语言进行操作系统开发的优势,如安全性、性能和并发性。 2. **开题报告** - **项目目标**:明确操作系统的开发目标,包括支持的硬件平台(树莓派型号)、实现的基本功能(如内核启动、进程管理、内存管理、设备驱动等)。 - **技术方案**:说明项目的整体技术方案,包括系统架构设计、关键技术选型、模块划分等。 - **开发计划**:详细的项目开发计划,分阶段描述各功能模块的实现时间表和里程碑。 - **风险分析**:分析项目可能遇到的技术难题和
资源推荐
资源详情
资源评论
收起资源包目录
使用 Rust 实现一个基于 树莓派的操作系统.zip (1214个子文件)
auto 76B
diff_tut_folders.bash 815B
devtool_completion.bash 220B
rpi4.cfg 1KB
rpi3.cfg 1KB
devtool 16B
Dockerfile 5KB
14_header.drawio 2KB
14_BCM_driver.drawio 2KB
14_GICv2_driver.drawio 2KB
.editorconfig 429B
wiring.fzz 60KB
09_wiring_jtag.fzz 47KB
Gemfile 234B
09_demo.gif 3.65MB
12_demo.gif 219KB
minipush_demo_frontpage.gif 203KB
.gitignore 101B
jtag_boot_rpi3.img 10KB
demo_payload_rpi3.img 9KB
demo_payload_rpi4.img 9KB
jtag_boot_rpi4.img 9KB
header.jpg 693KB
09_image_jtag_connected.jpg 235KB
.prettierrc.json 942B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 373B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
settings.json 364B
kernel.ld 5KB
kernel.ld 5KB
kernel.ld 4KB
kernel.ld 4KB
kernel.ld 4KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 3KB
kernel.ld 738B
kernel_symbols.ld 310B
kernel_symbols.ld 305B
kernel_symbols.ld 305B
kernel_symbols.ld 305B
kernel_virt_addr_space_size.ld 51B
kernel_virt_addr_space_size.ld 51B
kernel_virt_addr_space_size.ld 51B
kernel_virt_addr_space_size.ld 51B
kernel_virt_addr_space_size.ld 51B
kernel_virt_addr_space_size.ld 51B
LICENSE-APACHE 11KB
LICENSE-MIT 1KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 2KB
Cargo.lock 635B
Cargo.lock 635B
Cargo.lock 634B
Cargo.lock 634B
Cargo.lock 634B
Cargo.lock 634B
Cargo.lock 634B
Cargo.lock 634B
Cargo.lock 615B
Cargo.lock 615B
Cargo.lock 615B
共 1214 条
- 1
- 2
- 3
- 4
- 5
- 6
- 13
资源评论
编程资源宝库
- 粉丝: 3118
- 资源: 188
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功