push of spinor changes to validate l2cache

This commit is contained in:
bunnie 2021-07-05 00:08:58 +08:00
parent 79ce51c32c
commit 1b5d4bd79b
9 changed files with 259 additions and 11 deletions

8
Cargo.lock generated
View file

@ -1237,18 +1237,18 @@ dependencies = [
[[package]]
name = "ptr_meta"
version = "0.1.1"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aad980f4bb4053abd4733b1680024a8c71ffde345f6e584c6af9eb6f0067a198"
checksum = "7424255320182a46c403331afed6f95e0259a7c578f9da54a27e262ef3b60118"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bcd6232fa7d7fcd15703da5c07c9f10d203ee4fdf6ecf6d7ac5056db78089a3"
checksum = "53005b9863728f508d3f23ae37e03d60986a01b65f7ae8397dcebaa1d5e54e10"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",

View file

@ -28,6 +28,7 @@ default-members = [
"services/engine-25519",
"services/aes",
"services/test-stub",
#"services/spinor",
]
members = [
"xous-ipc",
@ -69,6 +70,7 @@ members = [
"services/engine-25519",
"services/aes",
"services/test-stub",
#"services/spinor",
]
resolver = "2"

View file

@ -3,7 +3,7 @@
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" >
<vendor>litex</vendor>
<name>SOC</name>
<description><![CDATA[Litex SoC 2021-07-03 18:21:53]]></description>
<description><![CDATA[Litex SoC 2021-07-04 02:16:46]]></description>
<addressUnitBits>8</addressUnitBits>
<width>32</width>
@ -1222,10 +1222,10 @@ register to disable individual events.]]></description>
<register>
<name>GIT_GITREV</name>
<description><![CDATA[First 32-bits of the git revision. This documentation was built from git rev
``977355ba``, so this value is 2540918202, which should be enough to check out
``27ddfe4b``, so this value is 668859979, which should be enough to check out
the exact git version used to build this firmware.]]></description>
<addressOffset>0x0014</addressOffset>
<resetValue>0x977355ba</resetValue>
<resetValue>0x27ddfe4b</resetValue>
<size>32</size>
<fields>
<field>
@ -1242,7 +1242,7 @@ the exact git version used to build this firmware.]]></description>
is ``1``, then the repository this was built from has one additional commit
beyond the tag indicated in `MAJOR`, `MINOR`, and `REVISION`.]]></description>
<addressOffset>0x0018</addressOffset>
<resetValue>0x26</resetValue>
<resetValue>0x28</resetValue>
<size>32</size>
<fields>
<field>
@ -3467,7 +3467,7 @@ inject too fast.]]></description>
<name>SEED1</name>
<description><![CDATA[Bits 32-63 of `SEED_SEED`. Seed used for the build]]></description>
<addressOffset>0x0000</addressOffset>
<resetValue>0x698bb704</resetValue>
<resetValue>0x6a034505</resetValue>
<size>32</size>
<fields>
<field>
@ -3482,7 +3482,7 @@ inject too fast.]]></description>
<name>SEED0</name>
<description><![CDATA[Bits 0-31 of `SEED_SEED`.]]></description>
<addressOffset>0x0004</addressOffset>
<resetValue>0x5d2ea7df</resetValue>
<resetValue>0x6ebb0afe</resetValue>
<size>32</size>
<fields>
<field>
@ -3535,10 +3535,40 @@ inject too fast.]]></description>
</field>
</fields>
</register>
<register>
<name>LOCKADDR</name>
<description><![CDATA[address of the word to lock. Address locked on write, and cannot be undone.]]></description>
<addressOffset>0x0008</addressOffset>
<resetValue>0x00</resetValue>
<size>32</size>
<fields>
<field>
<name>lockaddr</name>
<msb>7</msb>
<bitRange>[7:0]</bitRange>
<lsb>0</lsb>
</field>
</fields>
</register>
<register>
<name>LOCKSTAT</name>
<description><![CDATA[If set, the requested address word is locked and will always return 0.]]></description>
<addressOffset>0x000c</addressOffset>
<resetValue>0x00</resetValue>
<size>32</size>
<fields>
<field>
<name>lockstat</name>
<msb>0</msb>
<bitRange>[0:0]</bitRange>
<lsb>0</lsb>
</field>
</fields>
</register>
</registers>
<addressBlock>
<offset>0</offset>
<size>0x8</size>
<size>0x10</size>
<usage>registers</usage>
</addressBlock>
</peripheral>

Binary file not shown.

View file

@ -0,0 +1,23 @@
[package]
name = "spinor"
version = "0.1.0"
authors = ["bunnie <bunnie@kosagi.com>"]
edition = "2018"
description = "SPINOR ROM operations server"
[dependencies]
xous = { path = "../../xous-rs" }
log-server = { path = "../log-server" }
ticktimer-server = { path = "../ticktimer-server" }
xous-names = { path = "../xous-names" }
log = "0.4"
num-derive = {version = "0.3", default-features = false}
num-traits = {version = "0.2", default-features = false}
susres = {path = "../susres"}
rkyv = {version = "0.6.7", default-features = false, features = ["const_generics"]}
[target.'cfg(not(any(windows,unix)))'.dependencies]
utralib = { path = "../../utralib"}
[features]
default = []

View file

@ -0,0 +1,32 @@
pub(crate) const SERVER_NAME_SPINOR: &str = "_SPINOR Hardware Interface Server_";
#[allow(dead_code)]
#[derive(num_derive::FromPrimitive, num_derive::ToPrimitive, Debug)]
pub(crate) enum Opcode {
/// erase a region
EraseRegion,
/// program a region
WriteRegion,
/// Suspend/resume callback
SuspendResume,
}
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Clone, Copy)]
pub struct EraseRegion {
/// start location for the erase
pub start: u32,
/// length of the region to erase
pub len: u32,
}
#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Clone, Copy)]
pub struct WriteRegion<const N: usize> { // wait...can we do const generics with rkyv??
/// start location for the write
pub start: u32,
/// if true, erase the region to write if not already erased; otherwise, if not erased, the routine will error out
pub autoerase: bool,
/// data to write
pub sector: [u8; N],
}

View file

@ -0,0 +1,33 @@
#![cfg_attr(target_os = "none", no_std)]
pub mod api;
use xous::{CID, send_message};
use num_traits::ToPrimitive;
pub struct Spinor {
conn: CID,
}
impl Spinor {
pub fn new(xns: &xous_names::XousNames) -> Result<Self, xous::Error> {
REFCOUNT.store(REFCOUNT.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
let conn = xns.request_connection_blocking(api::SERVER_NAME_SPINOR).expect("Can't connect to Spinor server");
Ok(Spinor {
conn
})
}
}
use core::sync::atomic::{AtomicU32, Ordering};
static REFCOUNT: AtomicU32 = AtomicU32::new(0);
impl Drop for Spinor {
fn drop(&mut self) {
// the connection to the server side must be reference counted, so that multiple instances of this object within
// a single process do not end up de-allocating the CID on other threads before they go out of scope.
// Note to future me: you want this. Don't get rid of it because you think, "nah, nobody will ever make more than one copy of this object".
if REFCOUNT.load(Ordering::Relaxed) == 0 {
unsafe{xous::disconnect(self.conn).unwrap();}
}
// if there was object-specific state (such as a one-time use server for async callbacks, specific to the object instance),
// de-allocate those items here. They don't need a reference count because they are object-specific
}
}

127
services/spinor/src/main.rs Normal file
View file

@ -0,0 +1,127 @@
#![cfg_attr(target_os = "none", no_std)]
#![cfg_attr(target_os = "none", no_main)]
mod api;
use num_traits::FromPrimitive;
use log::info;
#[cfg(target_os = "none")]
mod implementation {
use utralib::generated::*;
// use crate::api::*;
use log::info;
use susres::{RegManager, RegOrField, SuspendResume};
pub struct Spinor {
csr: utralib::CSR<u32>,
fifo: xous::MemoryRange,
susres_manager: RegManager::<{utra::audio::AUDIO_NUMREGS}>,
}
impl Spinor {
pub fn new() -> Spinor {
let csr = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::audio::HW_AUDIO_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map Audio CSR range");
let fifo = xous::syscall::map_memory(
xous::MemoryAddress::new(utralib::HW_AUDIO_MEM),
None,
utralib::HW_AUDIO_MEM_LEN,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map Audio CSR range");
let mut spinor = Spinor {
csr: CSR::new(csr.as_mut_ptr() as *mut u32),
susres_manager: RegManager::new(csr.as_mut_ptr() as *mut u32),
fifo,
};
spinor
}
pub fn suspend(&mut self) {
self.susres_manager.suspend();
}
pub fn resume(&mut self) {
self.susres_manager.resume();
}
}
}
// a stub to try to avoid breaking hosted mode for as long as possible.
#[cfg(not(target_os = "none"))]
mod implementation {
use log::info;
pub struct Spinor {
}
impl Spinor {
pub fn new() -> Spinor {
Spinor {
}
}
pub fn suspend(&self) {
}
pub fn resume(&self) {
}
}
}
#[xous::xous_main]
fn xmain() -> ! {
use crate::implementation::Spinor;
log_server::init_wait().unwrap();
log::set_max_level(log::LevelFilter::Info);
info!("my PID is {}", xous::process::id());
let xns = xous_names::XousNames::new().unwrap();
/*
Very important to track who has access to the SPINOR server, and limit access. Access to this server is essential for persistent rootkits.
Here is the list of servers allowed to access, and why:
- shellchat (for testing ONLY, remove once done)
- PDDB (not yet written)
- keystore (not yet written)
*/
let spinor_sid = xns.register_name(api::SERVER_NAME_SPINOR, Some(1)).expect("can't register server");
log::trace!("registered with NS -- {:?}", spinor_sid);
let mut spinor = Spinor::new();
log::trace!("ready to accept requests");
// register a suspend/resume listener
let sr_cid = xous::connect(spinor_sid).expect("couldn't create suspend callback connection");
let mut susres = susres::Susres::new(&xns, api::Opcode::SuspendResume as u32, sr_cid).expect("couldn't create suspend/resume object");
loop {
let msg = xous::receive_message(spinor_sid).unwrap();
match FromPrimitive::from_usize(msg.body.id()) {
Some(api::Opcode::SuspendResume) => xous::msg_scalar_unpack!(msg, token, _, _, _, {
spinor.suspend();
susres.suspend_until_resume(token).expect("couldn't execute suspend/resume");
spinor.resume();
}),
None => {
log::error!("couldn't convert opcode");
break
}
}
}
// clean up our program
log::trace!("main loop exit, destroying servers");
xns.unregister_server(spinor_sid).unwrap();
xous::destroy_server(spinor_sid).unwrap();
log::trace!("quitting");
xous::terminate_process(0)
}

View file

@ -55,6 +55,7 @@ fn try_main() -> Result<(), DynError> {
"codec",
"engine-sha512",
"engine-25519",
//"spinor",
];
let benchmark_pkgs = [
"benchmark",