Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion bootloader/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion kernel/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 16 additions & 3 deletions kernel/src/arch/syscall/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,25 @@ pub(super) fn sys_device_reg(handle: RawHandle, offset: u64, width: u64, value:
/// Mints a device claim, gated on a `SysCap` carrying [`Rights::DEVICE`].
///
/// `selector` says which device where the class alone does not — a PCI
/// function's vendor and device id — and is ignored by every class that names
/// at most one device on the machine.
pub(super) fn sys_device_claim(syscap: RawHandle, class: u64, selector: u64) -> u64 {
/// function's vendor and device id, a partition's GUID — and a word the class
/// does not read is refused, never dropped: whoever set it meant a device this
/// claim would not name.
pub(super) fn sys_device_claim(syscap: RawHandle, class: u64, selector: [u64; 2]) -> u64 {
let Some(class) = device::DeviceType::from_raw(class) else {
return SyscallError::InvalidArgument.to_u64();
};
let read = match class {
device::DeviceType::Keyboard
| device::DeviceType::Mouse
| device::DeviceType::Framebuffer
| device::DeviceType::HdaAudio
| device::DeviceType::VirtioSound => 0,
device::DeviceType::PciFunction => 1,
device::DeviceType::Partition => 2,
};
if selector[read..].iter().any(|&word| word != 0) {
return SyscallError::InvalidArgument.to_u64();
}
if let Err(e) = demand_syscap(syscap, Rights::DEVICE) {
return e.refuse();
}
Expand Down
7 changes: 6 additions & 1 deletion kernel/src/arch/syscall/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,12 @@ pub(super) fn syscall_dispatch(num: u64, a1: u64, a2: u64, a3: u64, a4: u64) ->
let Some(mut buf) = ctx.user_bytes_mut(UserAddr::new(a1), a2) else { return bad_addr };
sys_endowments(&mut buf)
}
SYS_DEVICE_CLAIM => sys_device_claim(RawHandle(a1 as u32), a2, a3),
SYS_DEVICE_CLAIM => sys_device_claim(RawHandle(a1 as u32), a2, [a3, a4]),
// Numbered in the ABI and not yet served: a caller is told which call it made.
SYS_PARTITION_READ | SYS_PARTITION_WRITE => {
crate::log!("syscall {num} (a partition transfer) is not implemented in this kernel");
SyscallError::NotSupported.to_u64()
}
SYS_RT_ENTER => sys_rt_enter(RawHandle(a1 as u32)),
SYS_LOG_READ => {
// checked_mul before mapping: a product that doesn't fit is a bad argument,
Expand Down
13 changes: 9 additions & 4 deletions kernel/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,10 @@ pub enum ClaimError {
/// `Claim` lives on this stack frame until the returned object takes it, so a
/// failure after `acquire` cannot leave a device held by nobody.
///
/// `selector` says *which* device where the class alone does not — today that
/// is a PCI function's vendor and device id, and every other class ignores it.
pub fn try_claim(class: DeviceType, selector: u64) -> Result<Arc<DeviceClaim>, ClaimError> {
/// `selector` says *which* device where the class alone does not — a PCI
/// function's vendor and device id in its first word, a partition's GUID in
/// both — and the syscall has refused a word the class does not read.
pub fn try_claim(class: DeviceType, selector: [u64; 2]) -> Result<Arc<DeviceClaim>, ClaimError> {
// Availability is checked before acquiring, so an absent device reports `Absent`, not `Owned`.
match class {
DeviceType::Keyboard => {
Expand Down Expand Up @@ -143,14 +144,18 @@ pub fn try_claim(class: DeviceType, selector: u64) -> Result<Arc<DeviceClaim>, C
Ok(DeviceClaim::new(class, framebuffer_info(screen), claim))
}
DeviceType::PciFunction => {
let id = toyos_abi::syscall::PciId::from_wire(selector)
let id = toyos_abi::syscall::PciId::from_wire(selector[0])
.ok_or(ClaimError::Absent)?;
// The slot's own guard, taken inside: a PCI claim's exclusivity is
// per function rather than per class, so there is no flag here to
// acquire first.
let (info, slot, claim) = crate::pcidev::claim(id)?;
Ok(DeviceClaim::new(class, DeviceInfo::PciFunction(info, slot), claim))
}
DeviceType::Partition => {
log!("partclaim: this kernel does not hand out partition claims yet");
Err(ClaimError::Unusable)
}
DeviceType::HdaAudio => {
let (info, pcm) = crate::drivers::hda::info().ok_or(ClaimError::Absent)?;
let claim = Claim::acquire(class)?;
Expand Down
7 changes: 7 additions & 0 deletions kernel/src/object/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ pub fn read_source(object: &KObjectRef) -> Option<Source> {
device_registry::DeviceType::HdaAudio => Some(Source::Hda),
device_registry::DeviceType::VirtioSound => Some(Source::VirtioSound),
device_registry::DeviceType::Framebuffer => None,
// A partition answers its description and has nothing to wait for.
device_registry::DeviceType::Partition => None,
},
// Named unconditionally: the source alone cannot enforce rights.
KObjectRef::SysCap(_) => Some(Source::Log),
Expand Down Expand Up @@ -332,6 +334,9 @@ pub fn read_device(
}
}
device_registry::DeviceType::Framebuffer => Some(claim.describe(table, buf)),
// Every read is the description: a partition's bytes move through
// `SYS_PARTITION_READ`, never through a read of the claim.
device_registry::DeviceType::Partition => Some(claim.describe(table, buf)),
// The description first and interrupts after, the shape the HDA stub
// has: a driver reads what it is driving once, and everything it reads
// afterwards is what its device has been doing.
Expand Down Expand Up @@ -543,6 +548,7 @@ pub fn fstat(object: &KObjectRef) -> Stat {
device_registry::DeviceType::PciFunction => FileType::Unknown,
device_registry::DeviceType::HdaAudio
| device_registry::DeviceType::VirtioSound => FileType::Unknown,
device_registry::DeviceType::Partition => FileType::Unknown,
}),
}
}
Expand Down Expand Up @@ -662,6 +668,7 @@ pub fn has_data(object: &KObjectRef) -> bool {
!d.info_read() || d.pci_slot().is_some_and(crate::pcidev::has_irq)
}
device_registry::DeviceType::Framebuffer => true,
device_registry::DeviceType::Partition => true,
device_registry::DeviceType::HdaAudio => {
!d.info_read() || crate::drivers::hda::has_pending()
}
Expand Down
16 changes: 8 additions & 8 deletions tests/toyos-rust-tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion toyos-abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "toyos-abi"
version = "0.6.0"
version = "0.7.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "The ToyOS kernel ABI: syscall numbers, struct layouts and typed syscall wrappers."
Expand Down
1 change: 1 addition & 0 deletions toyos-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub mod hda;
pub mod inbox;
pub mod input;
pub mod log;
pub mod part;
pub mod pci;
pub mod ring;
pub mod syscall;
Expand Down
Loading
Loading