feat: room for many apps: qemu 512M, pool sized from RAM (448M, 114688 frames), user VA 32M -> 1G, display 8 windows (buffers at 0x1000_0000, stack 14 pages), pm app budget 24 MiB, init 16 children (notif bits moved)

This commit is contained in:
2026-10-28 15:31:30 +01:00
parent 8c518b84aa
commit c3eb70191b
11 changed files with 30 additions and 23 deletions

View File

@@ -1,13 +1,14 @@
pub const RAM_BASE: usize = 0x80000000;
pub const RAM_SIZE: usize = 128 * 1024 * 1024;
/// What the Makefile and scripts give QEMU (`-m 512M`).
pub const RAM_SIZE: usize = 512 * 1024 * 1024;
pub const UART_BASE: usize = 0x10000000;
pub const VIRTIO_BASE: usize = 0x10001000;
pub const VIRTIO_SIZE: usize = 0x8000;
pub const PLIC_BASE: usize = 0x0C000000;
pub const CLINT_BASE: usize = 0x02000000;
pub const USER_POOL_BASE: usize = 0x84000000;
/// 64 MiB, up to the end of RAM (QEMU virt's default 128 MiB).
pub const USER_POOL_PAGES: usize = 16384;
/// The rest of RAM, from `USER_POOL_BASE` (448 MiB).
pub const USER_POOL_PAGES: usize = (RAM_BASE + RAM_SIZE - USER_POOL_BASE) / 4096;
pub const TICK_INTERVAL: u64 = 10_000_000;
/// QEMU virt's PLIC lines.

View File

@@ -1,9 +1,10 @@
use super::pte::{PAGE_SIZE, PageTable, PageTableEntry, Sv39Flags, table_at, vpn};
use platform::{FrameSource, MapError};
/// User mappings live in root slot 0, in a private L1 per address space.
/// User mappings live in root slot 0, in a private L1 per address space:
/// all of its 1 GiB (leaf tables are made as pages are mapped).
pub const USER_VA_START: usize = 0x1000;
pub const USER_VA_END: usize = 0x0200_0000;
pub const USER_VA_END: usize = 0x4000_0000;
fn fresh_table(frames: &mut dyn FrameSource) -> Result<usize, MapError> {
let pa = frames

View File

@@ -12,7 +12,7 @@ const INPUT: CapSlot = CapSlot::const_new(1);
/// `themes/`, read-only.
const THEMES: CapSlot = CapSlot::const_new(2);
/// Where storage's buffer is mapped while the themes are read.
const STORAGE_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x0180_0000);
const STORAGE_BUF_VA: types::address::VirtualAddress = types::address::VirtualAddress::from_raw(0x1800_0000);
/// The longest theme file read.
const THEME_BYTES: usize = 4096;

View File

@@ -19,7 +19,7 @@ mod proofs;
pub const PAGE_SIZE: usize = 4096;
/// Frames the kernel can track. The board's user pool must fit.
pub const MAX_FRAMES: usize = if cfg!(kani) { 6 } else { 16384 };
pub const MAX_FRAMES: usize = if cfg!(kani) { 6 } else { 114_688 };
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrameUse {

View File

@@ -115,11 +115,12 @@ pub const SERVERS: &[Program] = &[
storage: &[disk(b"themes", false)],
// Its clients subscribe and take focus.
restarts_clients: true,
// Its windows' state (input queues among it) is KiBs.
stack_pages: 8,
// Its windows' state (input queues among it) is ~10 KiB, and the
// server is built on the stack.
stack_pages: 14,
// The framebuffer is ~1000 pages at 1280x800, and so is each of
// the (at most 4) windows' pixel buffers, which it owns.
..server("display", b"bin/display", Limits { pages: 5200, regions: 9, ..SMALL })
// the (at most 8) windows' pixel buffers, which it owns.
..server("display", b"bin/display", Limits { pages: 9300, regions: 13, ..SMALL })
},
// Text on the display, lines from the keyboard (it takes input focus).
// Its clients wait on lines and Ctrl+C. It draws its own text now,
@@ -149,8 +150,8 @@ pub const GATEKEEPER: Program = Program {
pub const SESSION: &[Program] = &[Program {
uses: &["terminal", "display"],
storage: &[users(b"", true), disk(b"apps", false)],
// Room for a few apps at a time.
spawns: Some(Limits { pages: 2048, endpoints: 8, notifications: 8, regions: 8 }),
// Room for several apps at a time (24 MiB between them).
spawns: Some(Limits { pages: 6144, endpoints: 12, notifications: 12, regions: 12 }),
// The shell holds handles to the apps it ran, which die with it.
restarts_clients: true,
session: Session::PassOn,

View File

@@ -16,7 +16,7 @@ use crate::load;
pub(crate) const MAX_CLIENTS: usize = 4;
/// Death signals carry the child's index as a bit.
const MAX_CHILDREN: usize = 8;
pub(crate) const MAX_CHILDREN: usize = 16;
struct Child {
client: usize,

View File

@@ -25,8 +25,11 @@ use crate::watchdog;
pub(crate) const MAX_SUPERVISED: usize = 12;
/// Init's death notification: spawned children below, storage, then a bit
/// per supervised program, and the timer on top.
const FIRST_BIT: usize = 16;
const STORAGE_BIT: usize = 1 << 15;
const FIRST_BIT: usize = 17;
const STORAGE_BIT: usize = 1 << 16;
// Spawned children take the bits below storage's; supervised programs
// those above it, clear of the timer's.
const _: () = assert!(crate::spawn::MAX_CHILDREN <= 16 && FIRST_BIT + MAX_SUPERVISED < 62);
pub(crate) const TIMER_BIT: usize = 1 << 62;
/// Where boot left storage's process.
const STORAGE_PROCESS: CapSlot = CapSlot::const_new(1);

View File

@@ -13,8 +13,9 @@ use crate::server::Host;
use crate::windows::MAX_WINDOWS;
/// Where slot `i`'s buffer is mapped in the display: 4 MiB apart, room for
/// a 1280x800 window.
const BUFFERS_VA: usize = 0x0080_0000;
/// a 1280x800 window; high, clear of the GPU's mappings and of the heap,
/// which grows from the bottom.
const BUFFERS_VA: usize = 0x1000_0000;
const BUFFER_SPAN: usize = 0x0040_0000;
const PAGE: usize = 4096;

View File

@@ -6,7 +6,7 @@
use types::display::window::{BADGE, NAME_BYTES};
pub const MAX_WINDOWS: usize = 4;
pub const MAX_WINDOWS: usize = 8;
/// Events received and not yet polled by the window in front.
const QUEUED: usize = 32;