chore: auto-commit after execute-task

GSD-Unit: M003/S03/T01
This commit is contained in:
John Doe
2026-05-04 12:33:55 -04:00
parent daa42391cc
commit 9ee840ccc4
2 changed files with 116 additions and 25 deletions
+71 -6
View File
@@ -3,6 +3,7 @@ use std::rc::Rc;
use unicorn_engine::{Arch, Mode, Prot, RegisterARM64, Unicorn};
use crate::mmio::MmioBus;
use crate::security::efuse::{EFUSE_BASE, EFUSE_SIZE};
use super::exception::ExceptionModule;
use crate::mmio::gic::GicDistributor;
@@ -73,6 +74,30 @@ impl UnicornCPU {
})
.ok()?;
// Register EFUSE MMIO hooks at the real hardware address
// (0x7000F800). This is a second, dedicated mmio_map so that
// ARM64 LDR/STR instructions targeting EFUSE_BASE trigger
// MMIO hooks through the same MmioBus. Resolves MEM054.
emu.mmio_map(
EFUSE_BASE,
EFUSE_SIZE,
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize| {
let bus = uc.get_data_mut();
let addr = EFUSE_BASE + offset;
bus.borrow().read(addr, size as u32)
}),
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize, value: u64| {
let bus = uc.get_data_mut();
let addr = EFUSE_BASE + offset;
bus.borrow_mut().write(addr, size as u32, value);
}),
)
.map_err(|e| {
eprintln!("Failed to map EFUSE MMIO region: {e:?}");
e
})
.ok()?;
// Initialize stack pointer
let _ = emu.reg_write(RegisterARM64::SP, (8 * 1024 * 1024) - 0x1000);
@@ -135,15 +160,55 @@ impl UnicornCPU {
})
.ok()?;
// Part 2: MMIO_BASE+MMIO_SIZE..memory_size (shared memory after MMIO region)
// Part 2: split around the EFUSE region (0x7000F8000x7000FC00) so
// that ARM64 LDR targeting EFUSE_BASE reaches the real hardware
// address through dedicated mmio_map hooks (MEM054).
let mmio_end = MMIO_BASE + MMIO_SIZE;
if mmio_end < memory_size {
// Part 2a: mmio_end..EFUSE_BASE (shared memory between MMIO and eFuse)
if mmio_end < EFUSE_BASE {
unsafe {
let part2_ptr = memory_ptr.add(mmio_end as usize);
let part2_size = memory_size - mmio_end;
emu.mem_map_ptr(mmio_end, part2_size, Prot::ALL, part2_ptr as *mut std::ffi::c_void)
let part2a_ptr = memory_ptr.add(mmio_end as usize);
let part2a_size = EFUSE_BASE - mmio_end;
emu.mem_map_ptr(mmio_end, part2a_size, Prot::ALL, part2a_ptr as *mut std::ffi::c_void)
.map_err(|e| {
eprintln!("Failed to map shared memory (high) for core {}: {:?}", core_id, e);
eprintln!("Failed to map shared memory (part2a) for core {}: {:?}", core_id, e);
e
})
.ok()?;
}
}
// EFUSE MMIO hooks at real hardware address (0x7000F800)
emu.mmio_map(
EFUSE_BASE,
EFUSE_SIZE,
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize| {
let bus = uc.get_data_mut();
let addr = EFUSE_BASE + offset;
bus.borrow().read(addr, size as u32)
}),
Some(move |uc: &mut Unicorn<'_, Rc<RefCell<MmioBus>>>, offset: u64, size: usize, value: u64| {
let bus = uc.get_data_mut();
let addr = EFUSE_BASE + offset;
bus.borrow_mut().write(addr, size as u32, value);
}),
)
.map_err(|e| {
eprintln!("Failed to map EFUSE MMIO region for core {}: {:?}", core_id, e);
e
})
.ok()?;
// Part 2b: EFUSE_BASE + EFUSE_SIZE..memory_size (shared memory after eFuse)
let efuse_end = EFUSE_BASE + EFUSE_SIZE;
if efuse_end < memory_size {
unsafe {
let part2b_ptr = memory_ptr.add(efuse_end as usize);
let part2b_size = memory_size - efuse_end;
emu.mem_map_ptr(efuse_end, part2b_size, Prot::ALL, part2b_ptr as *mut std::ffi::c_void)
.map_err(|e| {
eprintln!("Failed to map shared memory (part2b) for core {}: {:?}", core_id, e);
e
})
.ok()?;
+45 -19
View File
@@ -4,7 +4,6 @@
//! These tests exercise the full MMIO path: register device → encode ARM64
//! instructions → run emulation → read register values back.
use crate::cpu::unicorn_interface::MMIO_BASE;
use crate::cpu::UnicornCPU;
use crate::security::efuse::{EfuseArray, EFUSE_BASE, EFUSE_SIZE};
@@ -52,11 +51,25 @@ fn encode_movz(d: u32, imm16: u32, hw: u32) -> u32 {
0xD280_0000 | (hw << 21) | (imm16 << 5) | d
}
/// Encode `MOVK Xd, #imm16, LSL #(hw*16)`.
fn encode_movk(d: u32, imm16: u32, hw: u32) -> u32 {
0xF280_0000 | (hw << 21) | (imm16 << 5) | d
}
/// Encode `BRK #0` — halts emulation.
fn encode_brk() -> u32 {
0xD420_0000
}
/// Write MOVZ+MOVK pair to load EFUSE_BASE (0x7000F800) into Xd.
/// Returns two instructions: `[MOVZ, MOVK]`.
fn encode_load_efuse_base_into(d: u32) -> [u32; 2] {
[
encode_movz(d, 0xF800, 0), // MOVZ Xd, #0xF800
encode_movk(d, 0x7000, 1), // MOVK Xd, #0x7000, LSL #16 → Xd = 0x7000F800
]
}
/// Write a sequence of 32-bit instructions into the UnicornCPU memory.
fn write_code(cpu: &UnicornCPU, addr: u64, insns: &[u32]) {
for (i, insn) in insns.iter().enumerate() {
@@ -98,20 +111,24 @@ fn test_efuse_registers_on_mmio_bus() {
fn test_efuse_read_chip_id_via_ldr() {
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
// Register eFuse at MMIO_BASE so Unicorn's mmio_map hooks intercept LDR
// Register eFuse at EFUSE_BASE (0x7000F800) — the dedicated mmio_map
// hook in UnicornCPU intercepts ARM64 LDR targeting this address.
cpu.mmio_bus_mut()
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
// Code at 0x1000:
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE (0x10000000)
// MOVZ X1, #0xF800 ; X1 = 0xF800
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE (0x7000F800)
// LDR W0, [X1] ; load 32-bit chip ID → W0 (X0 low 32b)
// BRK #0
let code_addr = 0x1000u64;
let [movz, movk] = encode_load_efuse_base_into(1);
write_code(
&cpu,
code_addr,
&[
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
movz, // MOVZ X1, #0xF800
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
encode_ldr_w0_x1(), // LDR W0, [X1] → reads offset 0 (chip ID)
encode_brk(),
],
@@ -133,19 +150,22 @@ fn test_efuse_read_vendor_code_via_ldr() {
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
cpu.mmio_bus_mut()
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
// Code at 0x1000:
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
// MOVZ X1, #0xF800 ; X1 = 0xF800
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
// LDR W0, [X1, #4] ; load 32-bit from offset 4 → vendor code
// BRK #0
let code_addr = 0x1000u64;
let [movz, movk] = encode_load_efuse_base_into(1);
write_code(
&cpu,
code_addr,
&[
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
encode_ldr_w_offset(0, 1, 4), // LDR W0, [X1, #4]
movz, // MOVZ X1, #0xF800
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
encode_ldr_w_offset(0, 1, 4), // LDR W0, [X1, #4]
encode_brk(),
],
);
@@ -165,23 +185,26 @@ fn test_efuse_read_dram_config_via_ldr() {
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
cpu.mmio_bus_mut()
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
// DRAM config is at offset 0x100 — word 0 of Reserved_ODM4.
// Value: 0x00000004 (DRAM size = 4 GB).
// Code:
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
// MOVZ X1, #0xF800 ; X1 = 0xF800
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
// MOVZ X2, #0x100 ; X2 = 0x100 (offset for DRAM config)
// ADD X1, X1, X2 ; X1 = MMIO_BASE + 0x100
// ADD X1, X1, X2 ; X1 = EFUSE_BASE + 0x100
// LDR W0, [X1] ; load DRAM config word
// BRK #0
let code_addr = 0x1000u64;
let [movz, movk] = encode_load_efuse_base_into(1);
write_code(
&cpu,
code_addr,
&[
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
encode_movz(2, 0x100, 0), // X2 = 0x100
movz, // MOVZ X1, #0xF800
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
encode_movz(2, 0x100, 0), // MOVZ X2, #0x100
0x8B02_0021, // ADD X1, X1, X2
encode_ldr_w0_x1(), // LDR W0, [X1]
encode_brk(),
@@ -203,23 +226,26 @@ fn test_efuse_read_security_flags_via_ldr() {
let mut cpu = UnicornCPU::new().expect("Failed to create UnicornCPU");
cpu.mmio_bus_mut()
.register_device("efuse", MMIO_BASE, EFUSE_SIZE, EfuseArray::new_t210());
.register_device("efuse", EFUSE_BASE, EFUSE_SIZE, EfuseArray::new_t210());
// Security flags at offset 0x108 (word 2 of Reserved_ODM4).
// Value: 0x00000001 (secure boot enabled).
// Code:
// MOVZ X1, #0x1000, LSL #16 ; X1 = MMIO_BASE
// MOVZ X1, #0xF800 ; X1 = 0xF800
// MOVK X1, #0x7000, LSL #16 ; X1 = EFUSE_BASE
// MOVZ X2, #0x108 ; X2 = 0x108
// ADD X1, X1, X2 ; X1 = MMIO_BASE + 0x108
// ADD X1, X1, X2 ; X1 = EFUSE_BASE + 0x108
// LDR W0, [X1] ; load security flags
// BRK #0
let code_addr = 0x1000u64;
let [movz, movk] = encode_load_efuse_base_into(1);
write_code(
&cpu,
code_addr,
&[
encode_movz(1, 0x1000, 1), // X1 = 0x10000000
encode_movz(2, 0x108, 0), // X2 = 0x108
movz, // MOVZ X1, #0xF800
movk, // MOVK X1, #0x7000, LSL #16 → X1 = EFUSE_BASE
encode_movz(2, 0x108, 0), // MOVZ X2, #0x108
0x8B02_0021, // ADD X1, X1, X2
encode_ldr_w0_x1(), // LDR W0, [X1]
encode_brk(),