Compare commits

...

2 Commits

9 changed files with 75 additions and 133 deletions

View File

@ -5,44 +5,6 @@ use crate::zion;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::ffi::c_void; use core::ffi::c_void;
pub type ThreadEntry = fn(*const c_void) -> ();
#[no_mangle]
extern "C" fn internal_entry_point(thread_ptr: *const Thread, arg1: *const c_void) -> ! {
let thread: &Thread = unsafe { thread_ptr.as_ref().expect("Failed to unwrap thread ref") };
(thread.entry)(arg1);
syscall::thread_exit()
}
// TODO: Add a Drop implementation that kills this thread and drops its capability.
pub struct Thread {
cap: Capability,
// This field only exists to ensure that the entry reference will outlive the thread object
// itself.
entry: ThreadEntry,
}
impl Thread {
pub fn spawn(entry: ThreadEntry, arg1: *const c_void) -> Result<Box<Self>, zion::ZError> {
let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP })?;
let cap = syscall::thread_create(&proc_cap)?;
let thread = Box::new(Self { cap, entry });
syscall::thread_start(
&thread.cap,
internal_entry_point as u64,
thread.as_ref() as *const Thread as u64,
arg1 as u64,
)?;
Ok(thread)
}
pub fn join(&self) -> Result<(), zion::ZError> {
syscall::thread_wait(&self.cap)
}
}
pub struct JoinHandle { pub struct JoinHandle {
cap: Capability, cap: Capability,
} }

View File

@ -2,6 +2,8 @@ use crate::buffer::ByteBuffer;
use alloc::vec::Vec; use alloc::vec::Vec;
use mammoth::cap::Capability; use mammoth::cap::Capability;
use mammoth::syscall; use mammoth::syscall;
use mammoth::thread;
use mammoth::thread::JoinHandle;
use mammoth::zion::z_cap_t; use mammoth::zion::z_cap_t;
use mammoth::zion::ZError; use mammoth::zion::ZError;
@ -50,3 +52,10 @@ pub trait YunqServer {
cap_buffer: &mut Vec<z_cap_t>, cap_buffer: &mut Vec<z_cap_t>,
) -> Result<usize, ZError>; ) -> Result<usize, ZError>;
} }
pub fn spawn_server_thread<T>(mut server: T) -> JoinHandle
where
T: YunqServer + Send + 'static,
{
thread::spawn(move || server.server_loop())
}

View File

@ -1,8 +1,8 @@
use alloc::boxed::Box; use alloc::sync::Arc;
use alloc::rc::Rc; use mammoth::sync::Mutex;
use core::ffi::c_void; use mammoth::thread;
use mammoth::{mem::MemoryRegion, thread::Thread, zion::ZError}; use mammoth::{mem::MemoryRegion, zion::ZError};
use crate::ahci::command::FisType; use crate::ahci::command::FisType;
use crate::ahci::port::{ use crate::ahci::port::{
@ -48,8 +48,6 @@ pub struct PciDeviceHeader {
pub struct AhciController { pub struct AhciController {
pci_memory: MemoryRegion, pci_memory: MemoryRegion,
hba_memory: MemoryRegion, hba_memory: MemoryRegion,
irq_port: Option<mammoth::port::PortServer>,
irq_thread: Option<Box<Thread>>,
ports: [Option<PortController<'static>>; 32], ports: [Option<PortController<'static>>; 32],
} }
@ -68,18 +66,12 @@ impl AhciController {
let mut controller = Self { let mut controller = Self {
pci_memory, pci_memory,
hba_memory, hba_memory,
irq_port: None,
irq_thread: None,
ports: [const { None }; 32], ports: [const { None }; 32],
}; };
controller.init(); controller.init();
controller controller
} }
pub fn join(&self) -> Result<(), ZError> {
self.irq_thread.as_ref().unwrap().join()
}
fn init(&mut self) { fn init(&mut self) {
self.ahci_hba().global_host_control.set_hba_reset(true); self.ahci_hba().global_host_control.set_hba_reset(true);
@ -95,28 +87,11 @@ impl AhciController {
mammoth::syscall::thread_sleep(50).unwrap(); mammoth::syscall::thread_sleep(50).unwrap();
self.register_irq();
self.init_ports().unwrap(); self.init_ports().unwrap();
} }
fn run_server(&self) -> Result<Box<Thread>, ZError> { fn irq_num(&self) -> u64 {
let thread_entry = |server_ptr: *const c_void| { match self.pci_header().interrupt_pin {
let server = unsafe {
(server_ptr as *mut Self)
.as_mut()
.expect("Failed to convert to server")
};
server.irq_loop();
};
Thread::spawn(
thread_entry,
self as *const Self as *const core::ffi::c_void,
)
}
fn register_irq(&mut self) {
let irq_num = match self.pci_header().interrupt_pin {
1 => mammoth::zion::kZIrqPci1, 1 => mammoth::zion::kZIrqPci1,
2 => mammoth::zion::kZIrqPci2, 2 => mammoth::zion::kZIrqPci2,
3 => mammoth::zion::kZIrqPci3, 3 => mammoth::zion::kZIrqPci3,
@ -125,29 +100,16 @@ impl AhciController {
"Unrecognized pci interrupt pin {}", "Unrecognized pci interrupt pin {}",
self.pci_header().interrupt_pin self.pci_header().interrupt_pin
), ),
}; }
self.irq_port = Some(mammoth::port::PortServer::from_cap(
mammoth::syscall::register_irq(irq_num).unwrap(),
));
self.irq_thread = Some(self.run_server().unwrap());
self.ahci_hba()
.global_host_control
.set_interrupt_enable(true);
} }
fn irq_loop(&mut self) { fn handle_irq(&mut self) {
loop { for i in 0..self.ahci_hba().capabilities.num_ports() {
self.irq_port.as_ref().unwrap().recv_null().unwrap(); let int_offset = 1 << i;
if (self.ahci_hba().interrupt_status & int_offset) == int_offset {
for i in 0..self.ahci_hba().capabilities.num_ports() { if let Some(port) = &mut self.ports[i as usize] {
let int_offset = 1 << i; port.handle_interrupt();
if (self.ahci_hba().interrupt_status & int_offset) == int_offset { self.ahci_hba().interrupt_status &= !int_offset;
if let Some(port) = &mut self.ports[i as usize] {
port.handle_interrupt();
self.ahci_hba().interrupt_status &= !int_offset;
}
} }
} }
} }
@ -214,6 +176,24 @@ impl AhciController {
} }
} }
pub fn spawn_irq_thread(controller: Arc<Mutex<AhciController>>) -> thread::JoinHandle {
let irq_thread = move || {
let irq_num = controller.lock().irq_num();
let irq_port =
mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap());
controller
.lock()
.ahci_hba()
.global_host_control
.set_interrupt_enable(true);
loop {
irq_port.recv_null().unwrap();
controller.lock().handle_irq();
}
};
thread::spawn(irq_thread)
}
struct Command { struct Command {
command: SataCommand, command: SataCommand,
lba: u64, lba: u64,
@ -253,7 +233,7 @@ impl From<&Command> for HostToDeviceRegisterFis {
struct PortController<'a> { struct PortController<'a> {
ahci_port_hba: &'a mut AhciPortHba, ahci_port_hba: &'a mut AhciPortHba,
command_slots: [Option<Rc<Command>>; 32], command_slots: [Option<Arc<Command>>; 32],
command_structures: MemoryRegion, command_structures: MemoryRegion,
} }
@ -316,7 +296,7 @@ impl<'a> PortController<'a> {
mammoth::debug!("Sector size: {:#0x}", sector_size); mammoth::debug!("Sector size: {:#0x}", sector_size);
mammoth::debug!("LBA Count: {:#0x}", lba_count); mammoth::debug!("LBA Count: {:#0x}", lba_count);
}; };
self.issue_command(Rc::from(Command::identify(callback)?))?; self.issue_command(Arc::from(Command::identify(callback)?))?;
} else { } else {
let sig = self.ahci_port_hba.signature; let sig = self.ahci_port_hba.signature;
mammoth::debug!("Skipping non-sata sig: {:#0x}", sig); mammoth::debug!("Skipping non-sata sig: {:#0x}", sig);
@ -324,7 +304,7 @@ impl<'a> PortController<'a> {
Ok(()) Ok(())
} }
fn issue_command(&mut self, command: Rc<Command>) -> Result<(), ZError> { fn issue_command(&mut self, command: Arc<Command>) -> Result<(), ZError> {
let slot = self.select_slot()?; let slot = self.select_slot()?;
self.command_slots[slot] = Some(command.clone()); self.command_slots[slot] = Some(command.clone());

View File

@ -3,4 +3,5 @@ mod controller;
mod hba; mod hba;
mod port; mod port;
pub use controller::spawn_irq_thread;
pub use controller::AhciController; pub use controller::AhciController;

View File

@ -3,9 +3,10 @@
extern crate alloc; extern crate alloc;
use mammoth::{define_entry, zion::z_err_t}; use alloc::sync::Arc;
use mammoth::{define_entry, sync::Mutex, zion::z_err_t};
use denali::ahci::AhciController; use denali::ahci::{spawn_irq_thread, AhciController};
define_entry!(); define_entry!();
@ -19,12 +20,13 @@ extern "C" fn main() -> z_err_t {
.get_ahci_info() .get_ahci_info()
.expect("Failed to get ahci info"); .expect("Failed to get ahci info");
let ahci_controller = AhciController::new( let ahci_controller = Arc::new(Mutex::new(AhciController::new(
mammoth::mem::MemoryRegion::from_cap(mammoth::cap::Capability::take(ahci_info.ahci_region)) mammoth::mem::MemoryRegion::from_cap(mammoth::cap::Capability::take(ahci_info.ahci_region))
.unwrap(), .unwrap(),
); )));
ahci_controller.join().unwrap(); let thread = spawn_irq_thread(ahci_controller.clone());
thread.join();
0 0
} }

View File

@ -3,16 +3,16 @@
extern crate alloc; extern crate alloc;
use alloc::{string::ToString, vec::Vec}; use alloc::{string::ToString, sync::Arc, vec::Vec};
use mammoth::{ use mammoth::{
cap::Capability, cap::Capability,
define_entry, elf, define_entry, elf,
init::{BOOT_FRAMEBUFFER_INFO_VMMO, BOOT_PCI_VMMO}, init::{BOOT_FRAMEBUFFER_INFO_VMMO, BOOT_PCI_VMMO},
mem::MemoryRegion, mem::MemoryRegion,
zion::{z_cap_t, z_err_t, ZError}, zion::{kZionPerm_All, z_cap_t, z_err_t, ZError},
}; };
use yellowstone_yunq::YellowstoneServer; use yellowstone_yunq::YellowstoneServer;
use yunq::server::YunqServer; use yunq::server::{spawn_server_thread, YunqServer};
mod gpt; mod gpt;
mod pci; mod pci;
@ -40,20 +40,19 @@ extern "C" fn main() -> z_err_t {
.expect("Failed to create PCI region"); .expect("Failed to create PCI region");
let fb_region = MemoryRegion::from_cap(Capability::take(unsafe { BOOT_FRAMEBUFFER_INFO_VMMO })) let fb_region = MemoryRegion::from_cap(Capability::take(unsafe { BOOT_FRAMEBUFFER_INFO_VMMO }))
.expect("Failed to create Framebuffer region"); .expect("Failed to create Framebuffer region");
let context = alloc::rc::Rc::new( let context = Arc::new(
server::YellowstoneServerContext::new(pci_region, fb_region) server::YellowstoneServerContext::new(pci_region, fb_region)
.expect("Failed to create yellowstone context"), .expect("Failed to create yellowstone context"),
); );
let handler = server::YellowstoneServerImpl::new(context.clone()); let handler = server::YellowstoneServerImpl::new(context.clone());
let server = YellowstoneServer::new(handler).expect("Couldn't create yellowstone server"); let server = YellowstoneServer::new(handler).expect("Couldn't create yellowstone server");
let server_thread = server.run_server().expect("Failed to run server"); let client_cap = server.create_client_cap().unwrap();
let server_thread = spawn_server_thread(server);
spawn_from_vmmo( spawn_from_vmmo(
unsafe { mammoth::init::BOOT_DENALI_VMMO }, unsafe { mammoth::init::BOOT_DENALI_VMMO },
server client_cap.duplicate(kZionPerm_All).unwrap(),
.create_client_cap()
.expect("Failed to create client cap for denali"),
) )
.expect("Failed to spawn denali"); .expect("Failed to spawn denali");
@ -62,7 +61,7 @@ extern "C" fn main() -> z_err_t {
spawn_from_vmmo( spawn_from_vmmo(
unsafe { mammoth::init::BOOT_VICTORIA_FALLS_VMMO }, unsafe { mammoth::init::BOOT_VICTORIA_FALLS_VMMO },
server.create_client_cap().unwrap(), client_cap.duplicate(kZionPerm_All).unwrap(),
) )
.expect("Failed to spawn victoriafalls"); .expect("Failed to spawn victoriafalls");
@ -87,7 +86,11 @@ extern "C" fn main() -> z_err_t {
let path = "/bin/".to_string() + bin_name; let path = "/bin/".to_string() + bin_name;
let bin_file = victoriafalls::file::File::open(&path).unwrap(); let bin_file = victoriafalls::file::File::open(&path).unwrap();
spawn_from_mem_region(bin_file.memory(), server.create_client_cap().unwrap()).unwrap(); spawn_from_mem_region(
bin_file.memory(),
client_cap.duplicate(kZionPerm_All).unwrap(),
)
.unwrap();
} }
server_thread.join().expect("Failed to join thread"); server_thread.join().expect("Failed to join thread");

View File

@ -1,7 +1,9 @@
use core::cell::RefCell; use core::cell::RefCell;
use alloc::rc::Rc; use alloc::rc::Rc;
use alloc::sync::Arc;
use alloc::{collections::BTreeMap, string::String}; use alloc::{collections::BTreeMap, string::String};
use mammoth::sync::Mutex;
use mammoth::{cap::Capability, mem::MemoryRegion, zion::ZError}; use mammoth::{cap::Capability, mem::MemoryRegion, zion::ZError};
use victoriafalls::VFSClient; use victoriafalls::VFSClient;
use yellowstone_yunq::{ use yellowstone_yunq::{
@ -15,7 +17,7 @@ pub struct YellowstoneServerContext {
registration_semaphore: mammoth::sync::Semaphore, registration_semaphore: mammoth::sync::Semaphore,
pci_reader: PciReader, pci_reader: PciReader,
framebuffer_info_region: MemoryRegion, framebuffer_info_region: MemoryRegion,
service_map: RefCell<BTreeMap<String, Capability>>, service_map: Mutex<BTreeMap<String, Capability>>,
} }
impl YellowstoneServerContext { impl YellowstoneServerContext {
@ -52,13 +54,13 @@ impl YellowstoneServerContext {
registration_semaphore: mammoth::sync::Semaphore::new()?, registration_semaphore: mammoth::sync::Semaphore::new()?,
pci_reader: PciReader::new(pci_region), pci_reader: PciReader::new(pci_region),
framebuffer_info_region: fb_region, framebuffer_info_region: fb_region,
service_map: BTreeMap::new().into(), service_map: Mutex::new(BTreeMap::new()),
}) })
} }
pub fn wait(&self, service: &str) -> Result<(), ZError> { pub fn wait(&self, service: &str) -> Result<(), ZError> {
loop { loop {
match self.service_map.borrow().get(service) { match self.service_map.lock().get(service) {
Some(_) => return Ok(()), Some(_) => return Ok(()),
None => {} None => {}
} }
@ -68,11 +70,11 @@ impl YellowstoneServerContext {
} }
pub struct YellowstoneServerImpl { pub struct YellowstoneServerImpl {
context: Rc<YellowstoneServerContext>, context: Arc<YellowstoneServerContext>,
} }
impl YellowstoneServerImpl { impl YellowstoneServerImpl {
pub fn new(context: Rc<YellowstoneServerContext>) -> Self { pub fn new(context: Arc<YellowstoneServerContext>) -> Self {
Self { context } Self { context }
} }
} }
@ -87,7 +89,7 @@ impl YellowstoneServerHandler for YellowstoneServerImpl {
self.context self.context
.service_map .service_map
.borrow_mut() .lock()
.insert(req.endpoint_name, Capability::take(req.endpoint_capability)); .insert(req.endpoint_name, Capability::take(req.endpoint_capability));
self.context.registration_semaphore.signal()?; self.context.registration_semaphore.signal()?;
@ -95,7 +97,7 @@ impl YellowstoneServerHandler for YellowstoneServerImpl {
} }
fn get_endpoint(&mut self, req: GetEndpointRequest) -> Result<Endpoint, ZError> { fn get_endpoint(&mut self, req: GetEndpointRequest) -> Result<Endpoint, ZError> {
match self.context.service_map.borrow().get(&req.endpoint_name) { match self.context.service_map.lock().get(&req.endpoint_name) {
Some(cap) => Ok(Endpoint { Some(cap) => Ok(Endpoint {
endpoint: cap.duplicate(Capability::PERMS_ALL)?.release(), endpoint: cap.duplicate(Capability::PERMS_ALL)?.release(),
}), }),
@ -122,7 +124,7 @@ impl YellowstoneServerHandler for YellowstoneServerImpl {
} }
fn get_denali(&mut self) -> Result<DenaliInfo, ZError> { fn get_denali(&mut self) -> Result<DenaliInfo, ZError> {
match self.context.service_map.borrow().get("denali") { match self.context.service_map.lock().get("denali") {
Some(ep_cap) => crate::gpt::read_gpt(denali::DenaliClient::new( Some(ep_cap) => crate::gpt::read_gpt(denali::DenaliClient::new(
ep_cap.duplicate(Capability::PERMS_ALL).unwrap(), ep_cap.duplicate(Capability::PERMS_ALL).unwrap(),
)) ))

View File

@ -37,12 +37,6 @@ pub extern "C" fn main() -> z_err_t {
let b = Box::new(1); let b = Box::new(1);
debug!("Addrs: {:p} {:p}", a, b); debug!("Addrs: {:p} {:p}", a, b);
let e: thread::ThreadEntry = |_| {
debug!("Testing 1 2 3");
};
let t = thread::Thread::spawn(e, core::ptr::null()).expect("Failed to spawn thread");
t.join().expect("Failed to wait.");
let x = Box::new(|| 1); let x = Box::new(|| 1);
debug!("Addr: {:p}", x); debug!("Addr: {:p}", x);
debug!("Addr: {:p}", &x); debug!("Addr: {:p}", &x);

View File

@ -369,17 +369,6 @@ fn generate_server(interface: &Interface) -> TokenStream {
handler, handler,
}) })
} }
pub fn run_server(&self) -> Result<Box<thread::Thread>, ZError> {
let thread_entry = |server_ptr: *const c_void| {
let server = unsafe { (server_ptr as *mut #server_name<T>).as_mut().expect("Failed to convert to server") };
server.server_loop();
};
thread::Thread::spawn(
thread_entry,
self as *const Self as *const core::ffi::c_void,
)
}
} }
impl<T: #server_trait> yunq::server::YunqServer for #server_name<T> { impl<T: #server_trait> yunq::server::YunqServer for #server_name<T> {