commit to journal of bad ideas issue #243: a misguided attempt at a PDDB API.

This commit is contained in:
bunnie 2021-10-31 22:58:20 +08:00
parent 21e320a905
commit 46f1f60cda
6 changed files with 206 additions and 80 deletions

View file

@ -7,72 +7,3 @@ pub(crate) enum Opcode {
/// Suspend/resume callback
SuspendResume,
}
// this is an intenal structure for managing the overall PDDB
pub(crate) struct PddbManager {
}
impl PddbManager {
// return a list of open bases
fn list_basis();
}
// this is an internal struct for managing a basis
pub(crate) struct PddbBasis {
}
impl PddbBasis {
// opening and closing basis will side-effect PddbDicts and PddbKeys
fn open(); // will result in a password box being triggered to open a basis
fn close();
}
// this structure can be shared on the user side?
pub struct PddbDict {
contents: Hashmap,
}
impl PddbDict {
// opens a dictionary only if it exists
pub fn open(dict_name: &str) -> Option<PddbDict>;
// creates a dictionary only if it does not already exist
pub fn create(dict_name: &str) -> Option<PddbDict>;
// returns a key only if it exists
pub fn get(&mut self, key_name: &str, key_changed_cb: CB) -> Result<PddbKey>;
// updates an existing key's value. mainly used by write().
pub fn update(&mut self, key: PddbKey) -> Result<Option<PddbKey>>;
// creates a key or overwrites it
pub fn insert(&mut self, key: PddbKey) -> Option<PddbKey>; // may return the displaced key
// deletes a key within the dictionary
pub fn remove(&mut self, key: PddbKey) -> Result<()>;
// deletes the entire dictionary
pub fn delete(&mut self);
}
/// PddbKey is somewhat isomorphic to a File in Rust, in that it provides slices of [u8] that
/// can be `read()`, `write()` and `seek()`.
/// this is definitely a user-facing structure
pub struct PddbKey<CB>
where CB: FnMut(), {
// dictionary to search for the key within
dict: PddbDict,
// a copy of my name
name: String,
// called when the key changes (basis or is modified otherwise)
key_changed_cb: CB,
// mapped memory for the plaintext contexts, typically not all resident
mem: MemoryRange,
}
impl PddbKey<'a, CB> {
// reads are transparent and "just happen"
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
// writes will call update() on the dictionary
pub fn write(&mut self, buf: &[u8]) -> Result<usize>;
// provided for compatibility with Rust API
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
}
pub struct PddbBasis {
}

View file

@ -0,0 +1,2 @@
pub mod pddbkey;
pub use pddbkey::*;

View file

@ -0,0 +1,44 @@
use std::io::{Error, ErrorKind, Result};
use xous::MemoryRange;
use std::io::SeekFrom;
use crate::PddbDict;
/// PddbKey is somewhat isomorphic to a File in Rust, in that it provides slices of [u8] that
/// can be `read()`, `write()` and `seek()`.
/// this is definitely a user-facing structure
pub struct PddbKey<'a> {
// dictionary to search for the key within
dict: PddbDict<'a>,
// a copy of my name
name: String,
// called when the key changes (basis or is modified otherwise)
key_changed_cb: Box<dyn FnMut() + 'a>,
// mapped memory for the plaintext contexts, typically not all resident
mem: MemoryRange,
}
impl<'a> PddbKey<'a> {
pub fn set_callback(&mut self, key_changed_cb: impl FnMut() + 'a) {
self.key_changed_cb = Box::new(key_changed_cb);
}
pub fn new() {
let mem = xous::syscall::map_memory(
None,
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
).expect("couldn't map initial memory page");
}
/* these get moved to traits */
/*
// reads are transparent and "just happen"
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> { Ok(0) }
// writes will call update() on the dictionary
pub fn write(&mut self, buf: &[u8]) -> Result<usize> { Ok(0) }
// provided for compatibility with Rust API
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64> { Ok(0) }
*/
}

View file

@ -1,22 +1,99 @@
#![cfg_attr(target_os = "none", no_std)]
pub mod api;
pub use api::*;
pub mod frontend;
pub use frontend::*;
use xous::{CID, send_message};
use num_traits::*;
/// This constant maps onto a region that's "unused" by Xous, and claimable by user
/// processes.
const PDDB_BACKING_BASE: usize = 0x8000_0000;
/// This designates the largest contiguous extent that we could allocate for a file.
/// The backing isn't allocated -- it is merely reserved. Accesses to the backing trigger
/// page faults that are handled by the PDDB, and just the pages actively being dereferenced is
/// swapped into physical memory on demand. This does put a pretty hard upper limit on file sizes
/// on a 32-bit system, but PDDB is coded such that we could extend to a 64-bit system and
/// increase this limit my changing the constants here.
const PDDB_BACKING_SIZE: usize = 0x4000_0000;
fn handle_exception(exception: xous::Exception) -> isize {
use xous::Exception::*;
match exception {
IllegalInstruction(epc, instruction) => {
println!(
"Caught illegal instruction {:08x} at {:08x}, just skipping it...",
epc, instruction
);
4
}
InstructionAddressMisaligned(epc, addr) => {
println!(
"Misaligned instruction at {:08x} ({:08x}), trying to nudge forward a bit",
epc, addr
);
1
}
InstructionAccessFault(epc, addr)
| LoadAccessFault(epc, addr)
| StoreAccessFault(epc, addr) => {
panic!(
"Access fault of some sort: ({:08x} {:08x}): {:?}",
epc, addr, epc
);
}
LoadAddressMisaligned(epc, addr) | StoreAddressMisaligned(epc, addr) => {
println!(
"Load was misaligned ({:08x} @ {:08x}). Just skipping the instruction and hoping nobody notices.", epc, addr
);
4
}
InstructionPageFault(epc, addr) | LoadPageFault(epc, addr) | StorePageFault(epc, addr) => {
println!("Memory access fault at address 0x{:08x} (pc is at 0x{:08x}), allocating a new page", addr, epc);
let base = addr & !4095;
let size = 4096;
xous::map_memory(
None,
xous::MemoryAddress::new(base),
size,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map memory");
// Retry the instruction
0
}
Unknown(a1, a2, a3) => panic!("unknown exception: {:08x} {:08x} {:08x}", a1, a2, a3),
}
}
pub struct Pddb {
conn: CID,
backing: MemoryRange,
}
impl Pddb {
pub fn new(xns: &xous_names::XousNames) -> Result<Self, xous::Error> {
pub fn new(xns: &xous_names::XousNames) -> core::result::Result<Self, xous::Error> {
REFCOUNT.store(REFCOUNT.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
let conn = xns.request_connection_blocking(api::SERVER_NAME_CODEC).expect("Can't connect to Pddb server");
let conn = xns.request_connection_blocking(api::SERVER_NAME_PDDB).expect("Can't connect to Pddb server");
xous::syscall::set_exception_handler(handle_exception).unwrap();
let backing = unsafe {MemoryRange::new(
0x8000_0000,
0x1000_0000,
).expect("couldn't reserve pages for file backing region") };
Ok(Pddb {
conn
conn,
backing
})
}
pub(crate) fn conn(&self) -> CID {
self.conn
}
}
use core::sync::atomic::{AtomicU32, Ordering};
@ -32,4 +109,59 @@ impl Drop for Pddb {
// 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
}
}
}
use xous::MemoryRange;
use std::collections::HashMap;
use std::io::SeekFrom;
use std::io::{Error, ErrorKind, Result};
// this is an intenal structure for managing the overall PDDB
pub(crate) struct PddbManager {
}
impl PddbManager {
// return a list of open bases
fn list_basis() {}
}
// this is an internal struct for managing a basis
pub(crate) struct PddbBasis {
}
impl PddbBasis {
// opening and closing basis will side-effect PddbDicts and PddbKeys
fn open() {} // will result in a password box being triggered to open a basis
fn close() {}
}
// this structure can be shared on the user side?
pub struct PddbDict<'a> {
contents: HashMap<PddbKey<'a>, &'a [u8]>,
callback: Box<dyn FnMut() + 'a>,
}
impl<'a> PddbDict<'a> {
// opens a dictionary only if it exists
pub fn open(dict_name: &str) -> Option<PddbDict> { None }
// creates a dictionary only if it does not already exist
pub fn create(dict_name: &str) -> Option<PddbDict> { None }
// returns a key only if it exists
pub fn get(&mut self, key_name: &str, key_changed_cb: impl FnMut() + 'a) -> Result<Option<PddbKey>> {
self.callback = Box::new(key_changed_cb);
Ok(None)
}
// updates an existing key's value. mainly used by write().
pub fn update(&mut self, key: PddbKey) -> Result<Option<PddbKey>> { Ok(None) }
// creates a key or overwrites it
pub fn insert(&mut self, key: PddbKey) -> Option<PddbKey> { None } // may return the displaced key
// deletes a key within the dictionary
pub fn remove(&mut self, key: PddbKey) -> Result<()> { Ok(()) }
// deletes the entire dictionary
pub fn delete(&mut self) {}
}

View file

@ -7,8 +7,6 @@ use num_traits::*;
#[xous::xous_main]
fn xmain() -> ! {
use crate::implementation::Pddb;
log_server::init_wait().unwrap();
log::set_max_level(log::LevelFilter::Info);
log::info!("my PID is {}", xous::process::id());
@ -17,8 +15,6 @@ fn xmain() -> ! {
let pddb_sid = xns.register_name(api::SERVER_NAME_PDDB, None).expect("can't register server");
log::trace!("registered with NS -- {:?}", pddb_sid);
let mut pddb = Pddb::new();
log::trace!("ready to accept requests");
// register a suspend/resume listener
@ -29,9 +25,9 @@ fn xmain() -> ! {
let msg = xous::receive_message(pddb_sid).unwrap();
match FromPrimitive::from_usize(msg.body.id()) {
Some(api::Opcode::SuspendResume) => xous::msg_scalar_unpack!(msg, token, _, _, _, {
pddb.suspend();
/* pddb.suspend();
susres.suspend_until_resume(token).expect("couldn't execute suspend/resume");
pddb.resume();
pddb.resume(); */
}),
None => {
log::error!("couldn't convert opcode");

View file

@ -113,6 +113,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
"com",
"susres",
];
let pddb_dev_pkgs = [
"ticktimer-server",
"log-server",
"susres",
"xous-names",
"trng",
"pddb",
];
let aestest_pkgs = ["ticktimer-server", "log-server", "aes-test"];
let mut args = env::args();
let task = args.nth(1);
@ -138,6 +147,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Some("hw-image") => {
build_hw_image(false, env::args().nth(2), &hw_pkgs, lkey, kkey, None, &[])?
}
Some("pddb-dev") => build_hw_image(
false,
env::args().nth(2),
&pddb_dev_pkgs,
lkey,
kkey,
None,
&[],
)?,
Some("pddb-hosted") => run(false, &pddb_dev_pkgs)?,
Some("benchmark") => build_hw_image(
false,
env::args().nth(2),
@ -231,6 +250,8 @@ burn-soc invoke the `usb_update.py` utility to stage the SoC gate
nuke-soc 'Factory reset' - invoke the `usb_update.py` utility to burn the SoC gateware, erasing most secrets. For developers.
generate-locales only generate the locales include for the language selected in xous-rs/src/locale.rs
wycheproof-import generate binary test vectors for engine-25519 from whycheproof-import/x25519.json
pddb-dev PDDB testing only for live hardware
pddb-hosted PDDB testing in a hosted environment
Please refer to tools/README_UPDATE.md for instructions on how to set up `usb_update.py`
"