|
|
<!DOCTYPE HTML>
|
|
|
<html lang="cn" class="sidebar-visible no-js light">
|
|
|
<head>
|
|
|
<!-- Book generated using mdBook -->
|
|
|
<meta charset="UTF-8">
|
|
|
<title>🚧 虚拟内存:VMAR 对象 - 简明 zCore 教程</title>
|
|
|
|
|
|
|
|
|
<!-- Custom HTML head -->
|
|
|
|
|
|
|
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
|
<meta name="description" content="">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
<meta name="theme-color" content="#ffffff" />
|
|
|
|
|
|
<link rel="icon" href="favicon.svg">
|
|
|
<link rel="shortcut icon" href="favicon.png">
|
|
|
<link rel="stylesheet" href="css/variables.css">
|
|
|
<link rel="stylesheet" href="css/general.css">
|
|
|
<link rel="stylesheet" href="css/chrome.css">
|
|
|
<link rel="stylesheet" href="css/print.css" media="print">
|
|
|
|
|
|
<!-- Fonts -->
|
|
|
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
|
|
<link rel="stylesheet" href="fonts/fonts.css">
|
|
|
|
|
|
<!-- Highlight.js Stylesheets -->
|
|
|
<link rel="stylesheet" href="highlight.css">
|
|
|
<link rel="stylesheet" href="tomorrow-night.css">
|
|
|
<link rel="stylesheet" href="ayu-highlight.css">
|
|
|
|
|
|
<!-- Custom theme stylesheets -->
|
|
|
|
|
|
</head>
|
|
|
<body>
|
|
|
<!-- Provide site root to javascript -->
|
|
|
<script type="text/javascript">
|
|
|
var path_to_root = "";
|
|
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
|
|
|
</script>
|
|
|
|
|
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
|
|
<script type="text/javascript">
|
|
|
try {
|
|
|
var theme = localStorage.getItem('mdbook-theme');
|
|
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
|
|
|
|
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
|
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
|
|
}
|
|
|
|
|
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
|
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
|
|
}
|
|
|
} catch (e) { }
|
|
|
</script>
|
|
|
|
|
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
|
|
<script type="text/javascript">
|
|
|
var theme;
|
|
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
|
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
|
|
var html = document.querySelector('html');
|
|
|
html.classList.remove('no-js')
|
|
|
html.classList.remove('light')
|
|
|
html.classList.add(theme);
|
|
|
html.classList.add('js');
|
|
|
</script>
|
|
|
|
|
|
<!-- Hide / unhide sidebar before it is displayed -->
|
|
|
<script type="text/javascript">
|
|
|
var html = document.querySelector('html');
|
|
|
var sidebar = 'hidden';
|
|
|
if (document.body.clientWidth >= 1080) {
|
|
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
|
|
sidebar = sidebar || 'visible';
|
|
|
}
|
|
|
html.classList.remove('sidebar-visible');
|
|
|
html.classList.add("sidebar-" + sidebar);
|
|
|
</script>
|
|
|
|
|
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
|
|
<div class="sidebar-scrollbox">
|
|
|
<ol class="chapter"><li class="chapter-item expanded affix "><a href="index.html">简明 zCore 教程</a></li><li class="chapter-item expanded affix "><a href="zcore-intro.html">🚧 zCore 整体结构和设计模式</a></li><li class="chapter-item expanded affix "><a href="fuchsia.html">🚧 Fuchsia OS 和 Zircon 微内核</a></li><li class="chapter-item expanded "><a href="ch01-00-object.html"><strong aria-hidden="true">1.</strong> 内核对象</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch01-01-kernel-object.html"><strong aria-hidden="true">1.1.</strong> ✅ 初识内核对象</a></li><li class="chapter-item expanded "><a href="ch01-02-process-object.html"><strong aria-hidden="true">1.2.</strong> 🚧 对象管理器:Process 对象</a></li><li class="chapter-item expanded "><a href="ch01-03-channel-object.html"><strong aria-hidden="true">1.3.</strong> 🚧 对象传送器:Channel 对象</a></li></ol></li><li class="chapter-item expanded "><a href="ch02-00-task.html"><strong aria-hidden="true">2.</strong> 任务管理</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch02-01-zircon-task.html"><strong aria-hidden="true">2.1.</strong> 🚧 Zircon 任务管理体系</a></li><li class="chapter-item expanded "><a href="ch02-02-process-job-object.html"><strong aria-hidden="true">2.2.</strong> 🚧 进程管理:Process 与 Job 对象</a></li><li class="chapter-item expanded "><a href="ch02-03-thread-object.html"><strong aria-hidden="true">2.3.</strong> 🚧 线程管理:Thread 对象</a></li></ol></li><li class="chapter-item expanded "><a href="ch03-00-memory.html"><strong aria-hidden="true">3.</strong> 内存管理</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch03-01-zircon-memory.html"><strong aria-hidden="true">3.1.</strong> 🚧 Zircon 内存管理模型</a></li><li class="chapter-item expanded "><a href="ch03-02-vmo.html"><strong aria-hidden="true">3.2.</strong> 🚧 物理内存:VMO 对象</a></li><li class="chapter-item expanded "><a href="ch03-03-vmo-paged.html"><strong aria-hidden="true">3.3.</strong> 🚧 物理内存:按页分配的 VMO</a></li><li class="chapter-item expanded "><a href="ch03-04-vmar.html" class="active"><strong aria-hidden="true">3.4.</strong> 🚧 虚拟内存:VMAR 对象</a></li></ol></li><li class="chapter-item expanded "><a href="ch04-00-userspace.html"><strong aria-hidden="true">4.</strong> 用户程序</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch04-01-user-program.html"><strong aria-hidden="true">4.1.</strong> 🚧 Zircon 用户程序</a></li><li class="chapter-item expanded "><a href="ch04-02-context-switch.html"><strong aria-hidden="true">4.2.</strong> 🚧 上下文切换</a></li><li class="chapter-item expanded "><a href="ch04-03-syscall.html"><strong aria-hidden="true">4.3.</strong> 🚧 系统调用</a></li></ol></li><li class="chapter-item expanded "><a href="ch05-00-signal-and-waiting.html"><strong aria-hidden="true">5.</strong> 信号和等待</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch05-01-wait-signal.html"><strong aria-hidden="true">5.1.</strong> 🚧 等待内核对象的信号</a></li><li class="chapter-item expanded "><a href="ch05-02-port-object.html"><strong aria-hidden="true">5.2.</strong> 🚧 同时等待多个信号:Port 对象</a></li><li class="chapter-item expanded "><a href="ch05-03-more-signal-objects.html"><strong aria-hidden="true">5.3.</strong> 🚧 实现更多:EventPair, Timer 对象</a></li><li class="chapter-item expanded "><a href="ch05-04-futex-object.html"><strong aria-hidden="true">5.4.</strong> 🚧 用户态同步互斥:Futex 对象</a></li></ol></li><li class="chapter-item expanded "><a href="ch06-00-hal.html"><strong aria-hidden="true">6.</strong> 硬件抽象层</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="ch06-01-zcore-hal-unix.html"><strong aria-hidden="true">6.1.</strong> ✅ UNIX硬件抽象层</a></li></ol></li></ol> </div>
|
|
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
|
|
</nav>
|
|
|
|
|
|
<div id="page-wrapper" class="page-wrapper">
|
|
|
|
|
|
<div class="page">
|
|
|
|
|
|
<div id="menu-bar-hover-placeholder"></div>
|
|
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
|
|
<div class="left-buttons">
|
|
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
|
|
<i class="fa fa-bars"></i>
|
|
|
</button>
|
|
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
|
|
<i class="fa fa-paint-brush"></i>
|
|
|
</button>
|
|
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
|
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
|
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
|
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
|
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
|
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
|
|
</ul>
|
|
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
|
|
<i class="fa fa-search"></i>
|
|
|
</button>
|
|
|
</div>
|
|
|
|
|
|
<h1 class="menu-title">简明 zCore 教程</h1>
|
|
|
|
|
|
<div class="right-buttons">
|
|
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
|
|
<i id="print-button" class="fa fa-print"></i>
|
|
|
</a>
|
|
|
<a href="https://github.com/rcore-os/zCore-Tutorial" title="Git repository" aria-label="Git repository">
|
|
|
<i id="git-repository-button" class="fa fa-github"></i>
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div id="search-wrapper" class="hidden">
|
|
|
<form id="searchbar-outer" class="searchbar-outer">
|
|
|
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
|
|
</form>
|
|
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
|
|
<div id="searchresults-header" class="searchresults-header"></div>
|
|
|
<ul id="searchresults">
|
|
|
</ul>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
|
|
<script type="text/javascript">
|
|
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
|
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
|
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
|
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<div id="content" class="content">
|
|
|
<main>
|
|
|
<h1 id="虚拟内存vmar-对象"><a class="header" href="#虚拟内存vmar-对象">虚拟内存:VMAR 对象</a></h1>
|
|
|
<h2 id="vmar-简介"><a class="header" href="#vmar-简介">VMAR 简介</a></h2>
|
|
|
<p>虚拟内存地址区域(Virtual Memory Address Regions ,VMARs)为管理进程的地址空间提供了一种抽象。在进程创建时,将Root VMAR 的句柄提供给进程创建者。该句柄指的是跨越整个地址空间的 VMAR。这个空间可以通过<a href="https://fuchsia.dev/docs/reference/syscalls/vmar_map"><code>zx_vmar_map()</code></a>和 <a href="https://fuchsia.dev/docs/reference/syscalls/vmar_allocate"><code>zx_vmar_allocate()</code></a>接口来划分 。 <a href="https://fuchsia.dev/docs/reference/syscalls/vmar_allocate"><code>zx_vmar_allocate()</code></a>可用于生成新的 VMAR(称为子区域或子区域),可用于将地址空间的各个部分组合在一起。</p>
|
|
|
<h2 id="实现-vmar-对象框架"><a class="header" href="#实现-vmar-对象框架">实现 VMAR 对象框架</a></h2>
|
|
|
<blockquote>
|
|
|
<p>定义 VmAddressRange,VmMapping</p>
|
|
|
<p>实现 create_child, map, unmap, destroy 函数,并做单元测试验证地址空间分配</p>
|
|
|
</blockquote>
|
|
|
<h3 id="vmaddressregion"><a class="header" href="#vmaddressregion">VmAddressRegion</a></h3>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>pub struct VmAddressRegion {
|
|
|
flags: VmarFlags,
|
|
|
base: KObjectBase,
|
|
|
addr: VirtAddr,
|
|
|
size: usize,
|
|
|
parent: Option<Arc<VmAddressRegion>>,
|
|
|
page_table: Arc<Mutex<dyn PageTableTrait>>,
|
|
|
/// If inner is None, this region is destroyed, all operations are invalid.
|
|
|
inner: Mutex<Option<VmarInner>>,
|
|
|
}
|
|
|
|
|
|
#[derive(Default)]
|
|
|
struct VmarInner {
|
|
|
children: Vec<Arc<VmAddressRegion>>,
|
|
|
mappings: Vec<Arc<VmMapping>>,
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<p>构造一个根节点 VMAR,这个 VMAR 是每个进程都拥有的。</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>impl VmAddressRegion {
|
|
|
/// Create a new root VMAR.
|
|
|
pub fn new_root() -> Arc<Self> {
|
|
|
let (addr, size) = {
|
|
|
use core::sync::atomic::*;
|
|
|
static VMAR_ID: AtomicUsize = AtomicUsize::new(0);
|
|
|
let i = VMAR_ID.fetch_add(1, Ordering::SeqCst);
|
|
|
(0x2_0000_0000 + 0x100_0000_0000 * i, 0x100_0000_0000)
|
|
|
};
|
|
|
Arc::new(VmAddressRegion {
|
|
|
flags: VmarFlags::ROOT_FLAGS,
|
|
|
base: KObjectBase::new(),
|
|
|
addr,
|
|
|
size,
|
|
|
parent: None,
|
|
|
page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())), //hal PageTable
|
|
|
inner: Mutex::new(Some(VmarInner::default())),
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<p>我们的内核同样需要一个根 VMAR</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>/// The base of kernel address space
|
|
|
/// In x86 fuchsia this is 0xffff_ff80_0000_0000 instead
|
|
|
pub const KERNEL_ASPACE_BASE: u64 = 0xffff_ff02_0000_0000;
|
|
|
/// The size of kernel address space
|
|
|
pub const KERNEL_ASPACE_SIZE: u64 = 0x0000_0080_0000_0000;
|
|
|
/// The base of user address space
|
|
|
pub const USER_ASPACE_BASE: u64 = 0;
|
|
|
// pub const USER_ASPACE_BASE: u64 = 0x0000_0000_0100_0000;
|
|
|
/// The size of user address space
|
|
|
pub const USER_ASPACE_SIZE: u64 = (1u64 << 47) - 4096 - USER_ASPACE_BASE;
|
|
|
|
|
|
impl VmAddressRegion {
|
|
|
/// Create a kernel root VMAR.
|
|
|
pub fn new_kernel() -> Arc<Self> {
|
|
|
let kernel_vmar_base = KERNEL_ASPACE_BASE as usize;
|
|
|
let kernel_vmar_size = KERNEL_ASPACE_SIZE as usize;
|
|
|
Arc::new(VmAddressRegion {
|
|
|
flags: VmarFlags::ROOT_FLAGS,
|
|
|
base: KObjectBase::new(),
|
|
|
addr: kernel_vmar_base,
|
|
|
size: kernel_vmar_size,
|
|
|
parent: None,
|
|
|
page_table: Arc::new(Mutex::new(kernel_hal::PageTable::new())),
|
|
|
inner: Mutex::new(Some(VmarInner::default())),
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<h3 id="vmaddressmapping"><a class="header" href="#vmaddressmapping">VmAddressMapping</a></h3>
|
|
|
<p>VmAddressMapping 用于建立 VMO 和 VMAR 之间的映射。</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>/// Virtual Memory Mapping
|
|
|
pub struct VmMapping {
|
|
|
/// The permission limitation of the vmar
|
|
|
permissions: MMUFlags,
|
|
|
vmo: Arc<VmObject>,
|
|
|
page_table: Arc<Mutex<dyn PageTableTrait>>,
|
|
|
inner: Mutex<VmMappingInner>,
|
|
|
}
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
struct VmMappingInner {
|
|
|
/// The actual flags used in the mapping of each page
|
|
|
flags: Vec<MMUFlags>,
|
|
|
addr: VirtAddr,
|
|
|
size: usize,
|
|
|
vmo_offset: usize,
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<p>map 和 unmap 实现内存映射和解映射</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>impl VmMapping {
|
|
|
/// Map range and commit.
|
|
|
/// Commit pages to vmo, and map those to frames in page_table.
|
|
|
/// Temporarily used for development. A standard procedure for
|
|
|
/// vmo is: create_vmo, op_range(commit), map
|
|
|
fn map(self: &Arc<Self>) -> ZxResult {
|
|
|
self.vmo.commit_pages_with(&mut |commit| {
|
|
|
let inner = self.inner.lock();
|
|
|
let mut page_table = self.page_table.lock();
|
|
|
let page_num = inner.size / PAGE_SIZE;
|
|
|
let vmo_offset = inner.vmo_offset / PAGE_SIZE;
|
|
|
for i in 0..page_num {
|
|
|
let paddr = commit(vmo_offset + i, inner.flags[i])?;
|
|
|
//通过 PageTableTrait 的 hal_pt_map 进行页表映射
|
|
|
//调用 kernel-hal的方法进行映射
|
|
|
}
|
|
|
Ok(())
|
|
|
})
|
|
|
}
|
|
|
|
|
|
fn unmap(&self) {
|
|
|
let inner = self.inner.lock();
|
|
|
let pages = inner.size / PAGE_SIZE;
|
|
|
// TODO inner.vmo_offset unused?
|
|
|
// 调用 kernel-hal的方法进行解映射
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<h2 id="hal用-mmap-模拟页表"><a class="header" href="#hal用-mmap-模拟页表">HAL:用 mmap 模拟页表</a></h2>
|
|
|
<blockquote>
|
|
|
<p>实现页表接口 map, unmap, protect</p>
|
|
|
</blockquote>
|
|
|
<p>在 kernel-hal 中定义了一个页表和这个页表具有的方法。</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>/// Page Table
|
|
|
#[repr(C)]
|
|
|
pub struct PageTable {
|
|
|
table_phys: PhysAddr,
|
|
|
}
|
|
|
|
|
|
impl PageTable {
|
|
|
/// Get current page table
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_current"]
|
|
|
pub fn current() -> Self {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
|
|
|
/// Create a new `PageTable`.
|
|
|
#[allow(clippy::new_without_default)]
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_new"]
|
|
|
pub fn new() -> Self {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
impl PageTableTrait for PageTable {
|
|
|
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_map"]
|
|
|
fn map(&mut self, _vaddr: VirtAddr, _paddr: PhysAddr, _flags: MMUFlags) -> Result<()> {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
/// Unmap the page of `vaddr`.
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_unmap"]
|
|
|
fn unmap(&mut self, _vaddr: VirtAddr) -> Result<()> {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
/// Change the `flags` of the page of `vaddr`.
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_protect"]
|
|
|
fn protect(&mut self, _vaddr: VirtAddr, _flags: MMUFlags) -> Result<()> {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
/// Query the physical address which the page of `vaddr` maps to.
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_query"]
|
|
|
fn query(&mut self, _vaddr: VirtAddr) -> Result<PhysAddr> {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
/// Get the physical address of root page table.
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_table_phys"]
|
|
|
fn table_phys(&self) -> PhysAddr {
|
|
|
self.table_phys
|
|
|
}
|
|
|
|
|
|
/// Activate this page table
|
|
|
#[cfg(target_arch = "riscv64")]
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_activate"]
|
|
|
fn activate(&self) {
|
|
|
unimplemented!()
|
|
|
}
|
|
|
|
|
|
#[linkage = "weak"]
|
|
|
#[export_name = "hal_pt_unmap_cont"]
|
|
|
fn unmap_cont(&mut self, vaddr: VirtAddr, pages: usize) -> Result<()> {
|
|
|
for i in 0..pages {
|
|
|
self.unmap(vaddr + i * PAGE_SIZE)?;
|
|
|
}
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<p>在 kernel-hal-unix 中实现了 PageTableTrait,在 map 中调用了 mmap。</p>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>impl PageTableTrait for PageTable {
|
|
|
/// Map the page of `vaddr` to the frame of `paddr` with `flags`.
|
|
|
#[export_name = "hal_pt_map"]
|
|
|
fn map(&mut self, vaddr: VirtAddr, paddr: PhysAddr, flags: MMUFlags) -> Result<()> {
|
|
|
debug_assert!(page_aligned(vaddr));
|
|
|
debug_assert!(page_aligned(paddr));
|
|
|
let prot = flags.to_mmap_prot();
|
|
|
mmap(FRAME_FILE.as_raw_fd(), paddr, PAGE_SIZE, vaddr, prot);
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
/// Unmap the page of `vaddr`.
|
|
|
#[export_name = "hal_pt_unmap"]
|
|
|
fn unmap(&mut self, vaddr: VirtAddr) -> Result<()> {
|
|
|
self.unmap_cont(vaddr, 1)
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
<h2 id="实现内存映射"><a class="header" href="#实现内存映射">实现内存映射</a></h2>
|
|
|
<blockquote>
|
|
|
<p>用 HAL 实现上面 VMAR 留空的部分,并做单元测试验证内存映射</p>
|
|
|
</blockquote>
|
|
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
|
|
<span class="boring">#![allow(unused)]
|
|
|
</span><span class="boring">fn main() {
|
|
|
</span>impl VmMapping {
|
|
|
/// Map range and commit.
|
|
|
/// Commit pages to vmo, and map those to frames in page_table.
|
|
|
/// Temporarily used for development. A standard procedure for
|
|
|
/// vmo is: create_vmo, op_range(commit), map
|
|
|
fn map(self: &Arc<Self>) -> ZxResult {
|
|
|
self.vmo.commit_pages_with(&mut |commit| {
|
|
|
let inner = self.inner.lock();
|
|
|
let mut page_table = self.page_table.lock();
|
|
|
let page_num = inner.size / PAGE_SIZE;
|
|
|
let vmo_offset = inner.vmo_offset / PAGE_SIZE;
|
|
|
for i in 0..page_num {
|
|
|
let paddr = commit(vmo_offset + i, inner.flags[i])?;
|
|
|
//通过 PageTableTrait 的 hal_pt_map 进行页表映射
|
|
|
page_table
|
|
|
.map(inner.addr + i * PAGE_SIZE, paddr, inner.flags[i])
|
|
|
.expect("failed to map");
|
|
|
}
|
|
|
Ok(())
|
|
|
})
|
|
|
}
|
|
|
|
|
|
fn unmap(&self) {
|
|
|
let inner = self.inner.lock();
|
|
|
let pages = inner.size / PAGE_SIZE;
|
|
|
// TODO inner.vmo_offset unused?
|
|
|
self.page_table
|
|
|
.lock()
|
|
|
.unmap_cont(inner.addr, pages)
|
|
|
.expect("failed to unmap")
|
|
|
}
|
|
|
}
|
|
|
<span class="boring">}
|
|
|
</span></code></pre></pre>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
|
|
<!-- Mobile navigation buttons -->
|
|
|
<a rel="prev" href="ch03-03-vmo-paged.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
|
<i class="fa fa-angle-left"></i>
|
|
|
</a>
|
|
|
|
|
|
<a rel="next" href="ch04-00-userspace.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
|
<i class="fa fa-angle-right"></i>
|
|
|
</a>
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
|
</nav>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
|
|
<a rel="prev" href="ch03-03-vmo-paged.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
|
|
<i class="fa fa-angle-left"></i>
|
|
|
</a>
|
|
|
|
|
|
<a rel="next" href="ch04-00-userspace.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
|
|
<i class="fa fa-angle-right"></i>
|
|
|
</a>
|
|
|
</nav>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
window.playground_copyable = true;
|
|
|
</script>
|
|
|
|
|
|
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
|
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
|
|
<!-- Custom JS scripts -->
|
|
|
|
|
|
|
|
|
</body>
|
|
|
</html>
|