- axvcpu 提供 CPU 虚拟化支持
- 高度依赖于架构
- 存储不同架构的异常上下文框架
- 基本调度项
- 特定架构的 vCPU 实现需要被分离到独立的 crate 中:
#![allow(unused)]
fn main() {
/// A trait for architecture-specific vcpu.
///
/// This trait is an abstraction for virtual CPUs of different architectures.
pub trait AxArchVCpu: Sized {
/// The configuration for creating a new [`AxArchVCpu`]. Used by [`AxArchVCpu::new`].
type CreateConfig;
/// The configuration for setting up a created [`AxArchVCpu`]. Used by [`AxArchVCpu::setup`].
type SetupConfig;
/// Create a new `AxArchVCpu`.
fn new(config: Self::CreateConfig) -> AxResult<Self>;
/// Set the entry point of the vcpu.
///
/// It's guaranteed that this function is called only once, before [`AxArchVCpu::setup`] being called.
fn set_entry(&mut self, entry: GuestPhysAddr) -> AxResult;
/// Set the EPT root of the vcpu.
///
/// It's guaranteed that this function is called only once, before [`AxArchVCpu::setup`] being called.
fn set_ept_root(&mut self, ept_root: HostPhysAddr) -> AxResult;
/// Setup the vcpu.
///
/// It's guaranteed that this function is called only once, after [`AxArchVCpu::set_entry`] and [`AxArchVCpu::set_ept_root`] being called.
fn setup(&mut self, config: Self::SetupConfig) -> AxResult;
/// Run the vcpu until a vm-exit occurs.
fn run(&mut self) -> AxResult<AxVCpuExitReason>;
/// Bind the vcpu to the current physical CPU.
fn bind(&mut self) -> AxResult;
/// Unbind the vcpu from the current physical CPU.
fn unbind(&mut self) -> AxResult;
/// Set the value of a general-purpose register according to the given index.
fn set_gpr(&mut self, reg: usize, val: usize);
}
```<style>
.scroll-to-top {
font-size: 2.5rem;
width: 3.2rem;
height: 3.2rem;
display: none;
align-items: center;
justify-content: center;
position: fixed;
padding: 0.75rem;
bottom: 4rem;
right: calc(1.25rem + 90px + var(--page-padding));
z-index: 999;
cursor: pointer;
border: none;
color: var(--bg);
background: var(--fg);
border-radius: 50%;
}
.scroll-to-top.hidden {
display: none;
}
.scroll-to-top i {
transform: translateY(-2px);
}
@media (min-width: 1080px) {
.scroll-to-top {
display: flex;
}
}
</style>
<button type="button" aria-label="scroll-to-top" class="scroll-to-top hidden" onclick="scrollToTop()">
<i class="fa fa-angle-up"></i>
</button>
<script>
const scrollToTop = () => window.scroll({ top: 0, behavior: "smooth" });
window.addEventListener("scroll", () => {
const button = document.querySelector(".scroll-to-top");
button.classList.toggle("hidden", window.scrollY < 200);
});
</script>
<style>
.announcement-banner {
z-index: 150;
color: var(--fg);
position: relative;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0;
padding: 1rem 3.5rem;
background: repeating-linear-gradient(
45deg,
var(--site-announcement-bar-stripe-color1),
var(--site-announcement-bar-stripe-color1) 20px,
var(--site-announcement-bar-stripe-color2) 10px,
var(--site-announcement-bar-stripe-color2) 40px
);
}
.announcement-banner {
--site-announcement-bar-stripe-color1: #e5e7eb;
--site-announcement-bar-stripe-color2: #d1d5db;
}
.announcement-banner[data-theme="ocean"] {
--site-announcement-bar-stripe-color1: #86b2f9;
--site-announcement-bar-stripe-color2: #7298ea;
}
.announcement-banner[data-theme="forest"] {
--site-announcement-bar-stripe-color1: #97f5d6;
--site-announcement-bar-stripe-color2: #6de0bf;
}
.announcement-banner[data-theme="lava"] {
--site-announcement-bar-stripe-color1: #fea3a3;
--site-announcement-bar-stripe-color2: #e57e7e;
}
html:is(.navy, .coal, .ayu) .announcement-banner {
--site-announcement-bar-stripe-color1: #1f2937;
--site-announcement-bar-stripe-color2: #111827;
}
html:is(.navy, .coal, .ayu) .announcement-banner[data-theme="ocean"] {
--site-announcement-bar-stripe-color1: #2563eb;
--site-announcement-bar-stripe-color2: #1d4ed8;
}
html:is(.navy, .coal, .ayu) .announcement-banner[data-theme="forest"] {
--site-announcement-bar-stripe-color1: #22d3a5;
--site-announcement-bar-stripe-color2: #0fbf8f;
}
html:is(.navy, .coal, .ayu) .announcement-banner[data-theme="lava"] {
--site-announcement-bar-stripe-color1: #f87171;
--site-announcement-bar-stripe-color2: #ef4444;
}
.announcement-banner p {
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
text-align: center;
white-space: nowrap;
text-overflow: ellipsis;
text-wrap: balance;
}
.announcement-banner button {
top: 50%;
right: 1rem;
position: absolute;
transform: translateY(-50%);
width: 3rem;
height: 3rem;
cursor: pointer !important;
border: none;
font-weight: 900;
border-radius: 50%;
background-color: transparent;
}
</style>
<div style="display: none" data-id="0.2.11" class="announcement-banner" data-theme="default">
<p><em>正在逐步完善中。。。</em></p>
<button type="button">X</button>
</div>
<script>
(() => {
const banner = document.querySelector(".announcement-banner");
const id = banner.getAttribute("data-id");
const message = banner.querySelector("p").textContent;
const localData = JSON.parse(localStorage.getItem("mdbook-announcement-banner"));
if (!localData || localData.id !== id || localData.hide !== true) {
banner.style.display = "flex";
const page = document.querySelector(".page");
page.parentNode.insertBefore(banner, page);
banner.querySelector("button").addEventListener("click", () => {
banner.remove();
localStorage.setItem("mdbook-announcement-banner", JSON.stringify({ id, hide: true, message }));
});
}
})();
</script>
<style>
.giscus {
margin-top: 6rem;
}
</style>
<script
src="https://giscus.app/client.js"
data-repo="arceos-hypervisor/doc"
data-repo-id="R_kgDOLMHfvQ"
data-category="Comments"
data-category-id="DIC_kwDOLMHfvc4CoqAB"
data-mapping="title"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="light"
data-lang="zh-CN"
data-loading="eager"
crossorigin="anonymous"
async
></script>
<script>
(() => {
const giscusScript = document.querySelector("script[data-repo][data-repo-id]");
if (giscusScript?.getAttribute("data-theme") !== "book") return;
const mapTheme = (theme) => (theme === "light" || theme === "rust" ? "light" : "dark");
const bookTheme = localStorage.getItem("mdbook-theme") || html.getAttribute("class");
giscusScript.setAttribute("data-theme", mapTheme(bookTheme));
document.querySelectorAll("button[role='menuitem'].theme").forEach((btn) => {
btn.addEventListener("click", (event) => {
theme = mapTheme(event.target.id);
const iframe = document.querySelector("iframe.giscus-frame");
if (iframe) iframe.contentWindow.postMessage({ giscus: { setConfig: { theme } } }, "*");
});
});
})();
</script>
<style>
footer {
text-align: center;
text-wrap: balance;
margin-top: 5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
footer p {
margin: 0;
}
</style>
<footer><p>Copyright © 2025 • Created by ArceOS Team</p>
</footer>
}