Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions common/src/buddy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ static BUDDY: LazyLock<BuddyAllocatorImpl> = LazyLock::new(|| {
}
});

pub const MEM_BASE: u64 = 0x1_0000_0000;

#[cfg(feature = "std")]
pub fn init(size: usize) {
LazyLock::set(&BUDDY, BuddyAllocatorImpl::new(size))
Expand Down Expand Up @@ -936,6 +938,10 @@ pub struct BuddyAllocator;
// Rust requires explicit guarantee that clones of custom memory allocator for Arc can free memory allocated by each other
unsafe impl AllocatorClone for BuddyAllocator {}

pub fn ioaddr() -> u64 {
MEM_BASE + BuddyAllocator.len() as u64
}

impl BuddyAllocator {
pub const MIN_ALLOCATION: usize = BuddyAllocatorImpl::MIN_ALLOCATION;
}
Expand Down
3 changes: 0 additions & 3 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ pub mod hypercall {
pub const MEMSET: u64 = 3;
pub const MEMCLR: u64 = 4;

pub const NOTIFY_READ: u64 = 16;
pub const NOTIFY_WRITE: u64 = 17;

#[derive(Debug, Default)]
pub struct TcpInfo {
pub ip: u32,
Expand Down
2 changes: 2 additions & 0 deletions common/src/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod bi;
mod doorbell;
mod error;
mod uni;

pub use bi::{pipe, Pipe};
pub use doorbell::DoorBell;
pub use error::{Error, Result};
pub use uni::{channel, Reader, Writer};
88 changes: 77 additions & 11 deletions common/src/pipe/bi.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,118 @@
use super::doorbell::DoorBell;
use super::error::Result;
use super::uni::{channel, Reader, Writer};

#[derive(Debug)]
pub struct Pipe {
pub struct Pipe<D: DoorBell> {
rx: Reader,
tx: Writer,
rx_avail: D,
tx_avail: D,
}

pub fn pipe(len: usize) -> (Pipe, Pipe) {
pub fn pipe<D0: DoorBell, D1: DoorBell>(
len: usize,
rx_avail0: D0,
tx_avail0: D0,
rx_avail1: D1,
tx_avail1: D1,
) -> (Pipe<D0>, Pipe<D1>) {
let (r0, w0) = channel(len);
let (r1, w1) = channel(len);
(Pipe { rx: r0, tx: w1 }, Pipe { rx: r1, tx: w0 })
(
Pipe {
rx: r0,
tx: w1,
rx_avail: rx_avail0,
tx_avail: tx_avail0,
},
Pipe {
rx: r1,
tx: w0,
rx_avail: rx_avail1,
tx_avail: tx_avail1,
},
)
}

impl Pipe {
impl<D: DoorBell> Pipe<D> {
pub fn read(&mut self, data: &mut [u8]) -> Result<usize> {
self.rx.read(data)
let res = self.rx.read(data);
if let Ok(s) = res {
if s > 0 {
self.tx_avail.ring();
}
}
res
}

pub fn can_read(&self) -> bool {
!self.rx.is_empty()
}

pub fn write(&mut self, data: &[u8]) -> Result<usize> {
self.tx.write(data)
let res = self.tx.write(data);
if let Ok(s) = res {
if s > 0 {
self.rx_avail.ring();
}
}
res
}

pub fn can_write(&self) -> bool {
!self.tx.is_empty()
}

pub fn into_inner(self) -> (Reader, Writer) {
(self.rx, self.tx)
pub fn into_inner(self) -> (Reader, Writer, D, D) {
(self.rx, self.tx, self.rx_avail, self.tx_avail)
}

/// # Safety
/// The reader and writer must correspond to the two halves of a pipe, as previously returned
/// from into_inner.
pub unsafe fn from_inner(rx: Reader, tx: Writer) -> Self {
Pipe { rx, tx }
pub unsafe fn from_inner(rx: Reader, tx: Writer, rx_avail: D, tx_avail: D) -> Self {
Pipe {
rx,
tx,
rx_avail,
tx_avail,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use core::sync::atomic::{AtomicUsize, Ordering};

pub struct TestDoorBell {
count: AtomicUsize,
}

impl DoorBell for TestDoorBell {
fn ring(&self) {
self.count.fetch_add(1, Ordering::Release);
}
}

impl TestDoorBell {
pub fn new() -> Self {
Self {
count: AtomicUsize::new(0),
}
}
}

#[test]
pub fn test_ping_pong() {
let (mut p, mut q) = super::pipe(1024);
let (mut p, mut q) = super::pipe(
1024,
TestDoorBell::new(),
TestDoorBell::new(),
TestDoorBell::new(),
TestDoorBell::new(),
);
std::thread::spawn(move || loop {
let mut buf = [0; 8];
loop {
Expand Down
6 changes: 6 additions & 0 deletions common/src/pipe/doorbell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// Notify the waiter on newly available event (readable/writable)
///
/// ring blocks until it's possible to ring
pub trait DoorBell {
fn ring(&self);
}
7 changes: 7 additions & 0 deletions common/src/protocol/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,19 @@ impl From<std::io::ErrorKind> for IoErrorKind {
}
}

#[derive(Debug, Serialize, Deserialize)]
pub struct VMToHostDoorBellData {
pub datamatch: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PipeData {
pub rx_ptr: usize,
pub rx_len: usize,
pub tx_ptr: usize,
pub tx_len: usize,
pub rx_avail: VMToHostDoorBellData,
pub tx_avail: VMToHostDoorBellData,
}

#[derive(Debug, Default, Serialize, Deserialize)]
Expand Down
37 changes: 37 additions & 0 deletions kernel/src/doorbell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::vm;
use common::{buddy::ioaddr, pipe::DoorBell, protocol::control::VMToHostDoorBellData};

#[derive(Debug)]
struct SendPtr(*mut u64);

/// #Safety
///
/// The ptr remains valid during the lifetime of SendPtr
unsafe impl Send for SendPtr {}

#[derive(Debug)]
pub struct VMToHostDoorBell {
addr: SendPtr,
datamatch: u64,
}

impl VMToHostDoorBell {
/// #Safety
///
/// raw must corresponds to a into_inner call on the vmm side on a VMToHostDoorBell
pub unsafe fn from_raw_parts(raw: VMToHostDoorBellData) -> Self {
let addr: *mut u64 = vm::pa2ka(ioaddr() as usize);
Self {
addr: SendPtr(addr),
datamatch: raw.datamatch,
}
}
}

impl DoorBell for VMToHostDoorBell {
fn ring(&self) {
unsafe {
core::ptr::write_volatile(self.addr.0, self.datamatch);
}
}
}
6 changes: 4 additions & 2 deletions kernel/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::prelude::*;
use crate::{doorbell::VMToHostDoorBell, prelude::*};

use alloc::format;
use common::hypercall;
Expand Down Expand Up @@ -115,7 +115,9 @@ unsafe fn get_pipe(data: common::protocol::control::PipeData) -> HostPipe {
let rx = Reader::from_inner(rx);
let tx = Arc::from_raw_in(core::ptr::from_raw_parts(txp, data.tx_len), BuddyAllocator);
let tx = Writer::from_inner(tx);
let pipe = Pipe::from_inner(rx, tx);
let rx_avail = VMToHostDoorBell::from_raw_parts(data.rx_avail);
let tx_avail = VMToHostDoorBell::from_raw_parts(data.tx_avail);
let pipe = Pipe::from_inner(rx, tx, rx_avail, tx_avail);
HostPipe::new(pipe)
}

Expand Down
5 changes: 5 additions & 0 deletions kernel/src/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ unsafe extern "C" fn isr_entry(registers: &mut IsrRegisterFile) {
crate::lapic::LAPIC.borrow_mut().clear_interrupt();
return;
}
if registers.isr == 0x32 {
INTERRUPTED.store(true, Ordering::Release);
crate::lapic::LAPIC.borrow_mut().clear_interrupt();
return;
}
if registers.cs & 0b11 == 0b11 {
if registers.isr == 0x20 {
INTERRUPTED.store(true, Ordering::Relaxed);
Expand Down
6 changes: 6 additions & 0 deletions kernel/src/lapic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,10 @@ pub unsafe fn init() {
win.write_volatile(0x31);
regsel.write_volatile(0x13); // redirection entry 0-hi
win.write_volatile(0x00);

// GSI 2 -> INT 0x32
regsel.write_volatile(0x14); // redirection entry 0-lo
win.write_volatile(0x32);
regsel.write_volatile(0x15); // redirection entry 0-hi
win.write_volatile(0x00);
}
1 change: 1 addition & 0 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub mod tsc;
pub mod types;
pub mod vm;

mod doorbell;
mod gdt;
mod idt;
mod interrupts;
Expand Down
17 changes: 6 additions & 11 deletions kernel/src/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::doorbell::VMToHostDoorBell;
use crate::kthread;
use crate::prelude::*;
use common::pipe::Pipe as RawPipe;
Expand All @@ -9,18 +10,17 @@ pub static HOST: KMutex<OnceCell<ControlPipe>> = KMutex::new(OnceCell::new());

#[derive(Debug)]
pub struct HostPipe {
inner: RawPipe,
inner: RawPipe<VMToHostDoorBell>,
}

impl HostPipe {
pub fn new(pipe: RawPipe) -> Self {
pub fn new(pipe: RawPipe<VMToHostDoorBell>) -> Self {
Self { inner: pipe }
}

pub fn read(&mut self, bytes: &mut [u8]) -> PipeResult<usize> {
while !self.inner.can_read() {
// kthread::wfi();
kthread::yield_now();
kthread::wfi();
}
self.inner.read(bytes)
}
Expand All @@ -41,14 +41,9 @@ impl HostPipe {

pub fn write(&mut self, bytes: &[u8]) -> PipeResult<usize> {
while !self.inner.can_write() {
// kthread::wfi();
kthread::yield_now();
kthread::wfi();
}
let n = self.inner.write(bytes);
// unsafe {
// crate::io::hypercall0(crate::hypercall::NOTIFY_READ);
// }
n
self.inner.write(bytes)
}

pub fn write_exact(&mut self, mut bytes: &[u8]) -> PipeResult<()> {
Expand Down
13 changes: 10 additions & 3 deletions kernel/src/rsstart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use log::LevelFilter;

use crate::{
debugcon::DEBUG,
doorbell::VMToHostDoorBell,
gdt::{GdtDescriptor, PrivilegeLevel},
host::HOST,
idt::{GateType, Idt, IdtDescriptor, IdtEntry},
Expand All @@ -18,7 +19,11 @@ use crate::{
vm,
};

use common::{buddy::BuddyAllocatorRawData, BuddyAllocator};
use common::{
buddy::{BuddyAllocatorRawData, MEM_BASE},
protocol::control::VMToHostDoorBellData,
BuddyAllocator,
};

extern "C" {
fn kmain();
Expand Down Expand Up @@ -98,7 +103,7 @@ unsafe extern "C" fn _start(
}
let ptr: *mut BuddyAllocatorRawData = vm::pa2ka(allocator_data_ptr + 0x1_0000_0000);
let mut raw = *ptr;
raw.base = vm::pa2ka(0x1_0000_0000);
raw.base = vm::pa2ka(MEM_BASE as usize);
common::buddy::import(raw);
BuddyAllocator.set_caching(false);

Expand Down Expand Up @@ -147,7 +152,9 @@ unsafe extern "C" fn _start(
let rx = Reader::from_inner(rx);
let tx = Arc::from_raw_in(core::ptr::from_raw_parts(txp, txn), BuddyAllocator);
let tx = Writer::from_inner(tx);
let pipe = RawPipe::from_inner(rx, tx);
let rx_avail = VMToHostDoorBell::from_raw_parts(VMToHostDoorBellData { datamatch: 0 });
let tx_avail = VMToHostDoorBell::from_raw_parts(VMToHostDoorBellData { datamatch: 1 });
let pipe = RawPipe::from_inner(rx, tx, rx_avail, tx_avail);
let pipe = HostPipe::new(pipe);
let host = crate::pipe::HOST.lock();
host.set(ControlPipe::new(pipe)).unwrap();
Expand Down
Loading
Loading