Skip to content

Commit 44518b2

Browse files
committed
[feat] support smc proxy, add dtb in vcpu_create_cfg
1 parent 63fbc02 commit 44518b2

File tree

4 files changed

+74
-17
lines changed

4 files changed

+74
-17
lines changed

src/exception.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ core::arch::global_asm!(
7070
///
7171
pub fn handle_exception_sync(ctx: &mut TrapFrame) -> AxResult<AxVCpuExitReason> {
7272
match exception_class() {
73-
Some(ESR_EL2::EC::Value::DataAbortLowerEL) => handle_data_abort(ctx),
73+
Some(ESR_EL2::EC::Value::DataAbortLowerEL) => {
74+
let elr = ctx.exception_pc();
75+
let val = elr + exception_next_instruction_step();
76+
ctx.set_exception_pc(val);
77+
handle_data_abort(ctx)
78+
}
7479
Some(ESR_EL2::EC::Value::HVC64) => {
7580
// The `#imm`` argument when triggering a hvc call, currently not used.
7681
let _hvc_arg_imm16 = ESR_EL2.read(ESR_EL2::ISS);
@@ -94,6 +99,22 @@ pub fn handle_exception_sync(ctx: &mut TrapFrame) -> AxResult<AxVCpuExitReason>
9499
],
95100
})
96101
}
102+
Some(ESR_EL2::EC::Value::SMC64) => {
103+
let elr = ctx.exception_pc();
104+
let val = elr + exception_next_instruction_step();
105+
ctx.set_exception_pc(val);
106+
107+
// Is this a psci call?
108+
if let Some(result) = handle_psci_call(ctx) {
109+
return result;
110+
} else {
111+
// We just forward the SMC call to the ATF directly.
112+
// The args are from lower EL, so it is safe to call the ATF.
113+
(ctx.gpr[0], ctx.gpr[1], ctx.gpr[2], ctx.gpr[3]) =
114+
unsafe { crate::smc::smc_call(ctx.gpr[0], ctx.gpr[1], ctx.gpr[2], ctx.gpr[3]) };
115+
Ok(AxVCpuExitReason::Nothing)
116+
}
117+
}
97118
_ => {
98119
panic!(
99120
"handler not presents for EC_{} @ipa 0x{:x}, @pc 0x{:x}, @esr 0x{:x},
@@ -114,17 +135,18 @@ pub fn handle_exception_sync(ctx: &mut TrapFrame) -> AxResult<AxVCpuExitReason>
114135

115136
fn handle_data_abort(context_frame: &mut TrapFrame) -> AxResult<AxVCpuExitReason> {
116137
let addr = exception_fault_addr()?;
117-
debug!("data fault addr {:?}, esr: 0x{:x}", addr, exception_esr());
118-
119138
let access_width = exception_data_abort_access_width();
120139
let is_write = exception_data_abort_access_is_write();
121140
//let sign_ext = exception_data_abort_access_is_sign_ext();
122141
let reg = exception_data_abort_access_reg();
123142
let reg_width = exception_data_abort_access_reg_width();
124143

125-
let elr = context_frame.exception_pc();
126-
let val = elr + exception_next_instruction_step();
127-
context_frame.set_exception_pc(val);
144+
trace!(
145+
"Data fault @{:?}, ELR {:#x}, esr: 0x{:x}",
146+
addr,
147+
context_frame.exception_pc(),
148+
exception_esr(),
149+
);
128150

129151
let width = match AccessWidth::try_from(access_width) {
130152
Ok(access_width) => access_width,
@@ -178,12 +200,14 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
178200
const PSCI_FN_RANGE_32: core::ops::RangeInclusive<u64> = 0x8400_0000..=0x8400_001F;
179201
const PSCI_FN_RANGE_64: core::ops::RangeInclusive<u64> = 0xC400_0000..=0xC400_001F;
180202

203+
const PSCI_FN_VERSION: u64 = 0x0;
181204
const _PSCI_FN_CPU_SUSPEND: u64 = 0x1;
182205
const PSCI_FN_CPU_OFF: u64 = 0x2;
183206
const PSCI_FN_CPU_ON: u64 = 0x3;
184207
const _PSCI_FN_MIGRATE: u64 = 0x5;
185208
const PSCI_FN_SYSTEM_OFF: u64 = 0x8;
186209
const _PSCI_FN_SYSTEM_RESET: u64 = 0x9;
210+
const PSCI_FN_END: u64 = 0x1f;
187211

188212
let fn_ = ctx.gpr[0];
189213
let fn_offset = if PSCI_FN_RANGE_32.contains(&fn_) {
@@ -194,16 +218,18 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
194218
None
195219
};
196220

197-
fn_offset.map(|fn_offset| match fn_offset {
198-
PSCI_FN_CPU_OFF => Ok(AxVCpuExitReason::CpuDown { _state: ctx.gpr[1] }),
199-
PSCI_FN_CPU_ON => Ok(AxVCpuExitReason::CpuUp {
221+
match fn_offset {
222+
Some(PSCI_FN_CPU_OFF) => Some(Ok(AxVCpuExitReason::CpuDown { _state: ctx.gpr[1] })),
223+
Some(PSCI_FN_CPU_ON) => Some(Ok(AxVCpuExitReason::CpuUp {
200224
target_cpu: ctx.gpr[1],
201225
entry_point: GuestPhysAddr::from(ctx.gpr[2] as usize),
202226
arg: ctx.gpr[3],
203-
}),
204-
PSCI_FN_SYSTEM_OFF => Ok(AxVCpuExitReason::SystemDown),
205-
_ => Err(AxError::Unsupported),
206-
})
227+
})),
228+
Some(PSCI_FN_SYSTEM_OFF) => Some(Ok(AxVCpuExitReason::SystemDown)),
229+
// We just forward these request to the ATF directly.
230+
Some(PSCI_FN_VERSION..PSCI_FN_END) => None,
231+
_ => None,
232+
}
207233
}
208234

209235
/// Dispatches IRQs to the appropriate handler provided by the underlying host OS,

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(naked_functions)]
33
#![feature(doc_cfg)]
44
#![feature(asm_const)]
5+
#![feature(exclusive_range_pattern)]
56
#![doc = include_str!("../README.md")]
67

78
#[macro_use]
@@ -13,6 +14,7 @@ mod exception_utils;
1314
mod exception;
1415
mod pcpu;
1516
mod vcpu;
17+
mod smc;
1618

1719
pub use self::pcpu::Aarch64PerCpu;
1820
pub use self::vcpu::{Aarch64VCpu, Aarch64VCpuCreateConfig};

src/smc.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use core::arch::asm;
2+
3+
#[inline(never)]
4+
/// invoke a secure monitor call
5+
/// # Safety:
6+
/// It is unsafe to call this function directly.
7+
/// The caller must ensure that
8+
/// x0 is defined as the SMC function number referenced in the SMC Calling Convention
9+
/// than the args later must be valid for the specified SMC function.
10+
pub unsafe fn smc_call(x0: u64, x1: u64, x2: u64, x3: u64) -> (u64, u64, u64, u64) {
11+
let r0;
12+
let r1;
13+
let r2;
14+
let r3;
15+
asm!(
16+
"smc #0",
17+
inout("x0") x0 => r0,
18+
inout("x1") x1 => r1,
19+
inout("x2") x2 => r2,
20+
inout("x3") x3 => r3,
21+
options(nomem, nostack)
22+
);
23+
(r0, r1, r2, r3)
24+
}

src/vcpu.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ pub struct Aarch64VCpuCreateConfig {
7575
/// which is used to identify the CPU in a multiprocessor system.
7676
/// Note: mind CPU cluster.
7777
pub mpidr_el1: u64,
78+
/// The address of the device tree blob.
79+
pub dtb_addr: usize,
7880
}
7981

8082
impl<H: AxVCpuHal> axvcpu::AxArchVCpu for Aarch64VCpu<H> {
@@ -83,8 +85,11 @@ impl<H: AxVCpuHal> axvcpu::AxArchVCpu for Aarch64VCpu<H> {
8385
type SetupConfig = ();
8486

8587
fn new(config: Self::CreateConfig) -> AxResult<Self> {
88+
let mut ctx = TrapFrame::default();
89+
ctx.set_argument(config.dtb_addr);
90+
8691
Ok(Self {
87-
ctx: TrapFrame::default(),
92+
ctx,
8893
host_stack_top: 0,
8994
guest_system_regs: GuestSystemRegisters::default(),
9095
mpidr: config.mpidr_el1,
@@ -168,11 +173,11 @@ impl<H: AxVCpuHal> Aarch64VCpu<H> {
168173
+ VTCR_EL2::SL0.val(0b01)
169174
+ VTCR_EL2::T0SZ.val(64 - 39))
170175
.into();
171-
self.guest_system_regs.hcr_el2 = (HCR_EL2::VM::Enable + HCR_EL2::RW::EL1IsAarch64).into();
176+
self.guest_system_regs.hcr_el2 =
177+
(HCR_EL2::VM::Enable + HCR_EL2::RW::EL1IsAarch64 + HCR_EL2::TSC::EnableTrapEl1SmcToEl2)
178+
.into();
172179
// self.system_regs.hcr_el2 |= 1<<27;
173180
// + HCR_EL2::IMO::EnableVirtualIRQ).into();
174-
// trap el1 smc to el2
175-
// self.system_regs.hcr_el2 |= HCR_TSC_TRAP as u64;
176181

177182
// Set VMPIDR_EL2, which provides the value of the Virtualization Multiprocessor ID.
178183
// This is the value returned by Non-secure EL1 reads of MPIDR.

0 commit comments

Comments
 (0)