GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - GabGP/MultiprogrammingOS: A lightweight multiprogramming kernel for ARM architectures (VersatilePB & BeagleBone Black).

BranchesTags
Open more actions menu
 
 

Latest commit

 

History

132 Commits
132 Commits

Folders and files

NameName
Last commit message
Last commit date
.vscode
.vscode
 
 
build
build
 
 
docs/media
docs/media
 
 
src
src
 
 
.gitignore
.gitignore
 
 
Makefile
Makefile
 
 
README.md
README.md
 
 

Repository files navigation

Multiprogramming OS for ARM

A small operating system kernel, written from scratch, that runs several programs at once on an ARM processor.
It boots on a real BeagleBone Black board or in the QEMU emulator, takes turns between programs on a timer, keeps them out of each other's memory, and survives when one of them crashes.

Serial console replay: the kernel boots, sets up memory protection, the timer and interrupts, then switches between the OS process, which prints letters, and two user programs; the first checks that the kernel rejects bad requests and counts ticks, the second deliberately causes an alignment fault, and the kernel ends it and carries on

A real boot in QEMU. Blue lines come from the OS process, green from the user programs, grey lines are the kernel logging every switch, and orange is a program crashing on purpose while the rest keep running.


Highlights

  • Several programs, one processor. A timer interrupts the running program at a fixed interval and the kernel hands the processor to the next one in line (round-robin scheduling). A program can also give up its turn early.
  • Programs can't touch each other. Each one lives in its own 1 MB slice of memory, and the processor's memory-protection unit blocks any access outside it.
  • A controlled way in. Programs ask the kernel for things (write text, give up the CPU, exit) through system calls, and the kernel checks every request: a bad file number or a pointer outside the program's memory is refused, not obeyed.
  • Crashes stay contained. If a program faults, for example by reading memory at a misaligned address, the kernel records why, ends that program, and keeps running the others.
  • Two targets. The same code builds for a VersatilePB board emulated by QEMU and for the real BeagleBone Black board (ARM Cortex-A8).
  • Everything is logged. Every switch between a program and the kernel is printed with the reason, so you can watch the scheduler work.

What runs on it

Process What it does
Kernel Boots, sets up memory protection, the timer and interrupts, then schedules everyone else.
OS process Prints the alphabet, one letter at a time (----From OS: A, B, ...). Runs whenever no one else needs the CPU.
Process 1 Tries two bad requests to prove the kernel rejects them ([A] Protections Verified!), then prints [B] tick 0 to [B] tick 19, giving up its turn after each one.
Process 2 Deliberately breaks a rule to test fault handling. By default it reads memory at a misaligned address; set TEST in src/user/p2/process_2.c to try a permission fault, privilege escalation or a debug event instead.

How it works

  1. Boot. The kernel starts in privileged mode, sets up the memory protection, turns off the board's watchdog, starts a hardware timer and enables interrupts.
  2. Launch. It loads the OS process and the two user programs, each into its own memory slice, and switches to the first one in unprivileged user mode.
  3. Take turns. Every timer tick drops back into the kernel, which saves the running program's registers, picks the next ready program, restores its registers and jumps back. To each program it looks like it never stopped.
  4. Serve requests. When a program makes a system call, the kernel checks the arguments, does the work and returns a result code.
  5. Handle crashes. When the processor reports a fault, the kernel identifies the kind of fault, marks that program as terminated, and moves on to the next one.

Run it

You need Linux, make, the ARM cross-compiler gcc-arm-none-eabi (13.2.1 tested) and qemu-system-arm. Tested on Ubuntu and Fedora.

make qemu         # build and boot in QEMU (VersatilePB)
make qemu-debug   # same, waiting for a debugger on port 3333
make bbb          # build for the BeagleBone Black
make clean

On a BeagleBone Black

Connect to the board's serial console at 115200 baud (with CoolTerm, minicom or similar), then in U-Boot:

loady 0x82000000

Send build/bin/os.bin over YMODEM, then start it with go 0x82000000.

Debugging

After make qemu-debug, in another terminal:

gdb-multiarch build/bin/os.elf
(gdb) target remote localhost:3333

Useful commands: layout regs, break <function>, continue.


Credits

Made by Carlos Alvarez (@23004004) and Gabriel Garcia (@GabGP). This is a fork of 23004004/001Multiprogramming.


Technical reference

Kernel Log Reference

Output Event
! Kernel Panic
. Yield Scheduling
... Normal Scheduling
MODE_SWITCH KERNEL_TO_USER pid=<first> reason=initial_launch Initial Boot Path (Kernel → User)
MODE_SWITCH USER_TO_KERNEL pid=<n> reason=timer_irq Interrupt Path (User → Kernel)
MODE_SWITCH KERNEL_TO_USER pid=<m> reason=dispatch Interrupt Path (Kernel → User)
MODE_SWITCH USER_TO_KERNEL pid=<n> reason=syscall id=<id> Syscall Path (User → Kernel)
MODE_SWITCH KERNEL_TO_USER pid=<m> reason=syscall_return id=<id> rc=<rc> Syscall Path (Kernel → User)
MODE_SWITCH USER_TO_KERNEL pid=<n> reason=fault type=<type> Exception Path (User → Kernel)
MODE_SWITCH KERNEL_TO_USER pid=<m> reason=fault_recovery Exception Path (Kernel → User)

Scheduler Behaviour

The scheduler enforces a Round-Robin scheduling policy. It manages CPU time allocation by monitoring a quantum and handling process transitions based on three main triggers:

  1. Quantum Expiry: When the quantum reaches zero, the current process is preempted to allow another process to run.
  2. Process Termination: If the current process enters the PROCESS_TERMINATED state, a new process is immediately scheduled.
  3. Voluntary Yield: A process can choose to give up its remaining time via the SYS_YIELD system call.

If any of these conditions are met, the scheduler moves to the next process in the ready queue and resets the quantum. When idling, the OS process will continue running.

Process Memory Map

Each process is allocated a dedicated memory region starting at a base address determined by the platform and its PID. The entry point for each process is at the beginning of its allocated 1MB region.

PID Process Name Memory Start Address (VersatilePB) Memory Start Address (BeagleBone Black)
0 Kernel 0x00000000 0x82000000
1 OS Process 0x00100000 0x82100000
2 User Process 1 0x00200000 0x82200000
3 User Process 2 0x00300000 0x82300000
... ... ... ...

Process Control Block (PCB)

The PCB stores the context and metadata for each process, ensuring that the system can save and restore its state during context switches.

Variable Description
pid Unique numeric identifier for the process.
state Current lifecycle state (e.g., READY, RUNNING, WAITING).
regs[13] Array storing the general-purpose registers (R0 to R12).
pc Program Counter; the address of the next instruction to be executed.
sp Stack Pointer; points to the top of the process's private stack.
lr Link Register; stores the return address for function calls and exceptions.
spsr Saved Processor Status Register; used to restore the CPU mode and flags.
syscall_id Stores the ID of the current or most recent system call.
fault_type Records the type of hardware exception encountered by the process.
termination_reason Indicates why a process ended (Normal exit, Syscall, or Fault).
exit_code The status code returned to the kernel upon termination.

Process States

The kernel manages the lifecycle of each task through a set of defined states stored in the PCB.

State Value Description
PROCESS_NEW 0 The process is being created and its PCB is being initialized.
PROCESS_READY 1 The process is waiting in the ready_queue to be assigned to the CPU.
PROCESS_RUNNING 2 The process instructions are currently being executed by the processor.
PROCESS_WAITING 3 The process is waiting for an event to occur.
PROCESS_SUSPENDED 4 The process execution is paused but the context is preserved in memory.
PROCESS_TERMINATED 5 The process has completed execution or has been aborted due to a fault.

Syscall ABI

The system uses registers R0-R3 for system call interfacing. R0 is used to pass the Syscall ID and also stores the return code upon completion.

Syscall Name ID (R0) Arg 1 (R1) Arg 2 (R2) Arg 3 (R3) Return Code (R0) Description
SYS_YIELD 1 - - - RC_SUCCES Voluntarily yield CPU to the next process.
SYS_EXIT 2 Exit Code - - Exit Code Terminate the current process with an exit code.
SYS_WRITE 3 File Descriptor Buffer Length Bytes / Error Write string to UART (FD 1 supported).

Return and Error Codes

Return Code Value Description
RC_SUCCESS 0 Operation completed successfully.
RC_INVALID_SYSCALL -1 The requested Syscall ID is not recognized.
RC_INVALID_ARGUMENT -2 Provided arguments are invalid. (FD != 1or 0 > Length > 256)
RC_INVALID_USR_PTR -3 Memory access violation (Buffer outside process boundary).
RC_INVALID_ORIGIN -4 Invalid syscall origin (Triggered by kernel).

Unknown Syscall Behavior

If a process requests an unknown Syscall ID, the kernel will immediately transition the process to the PROCESS_TERMINATED state, set the return register to RC_INVALID_SYSCALL, and trigger the scheduler to pick the next available task.

Invalid Syscall Origin Behavior

If a process triggers a syscall while on kernel mode, then the same procedure as unknown system behavior follows, except that the return code is set to RC_INVALID_ORIGIN. This is because syscalls are meant to be triggered while on user mode, and if someone with kernel privileges triggers it, then it means something went wrong.

Fault Handling Policy

When a hardware exception or processor fault occurs, the fault_dispatcher categorizes the error and enforces a system safety policy.

Fault Classification / Type Value Outcome Comment
FAULT_NONE 0 - Default Value
FAULT_ALIGNMENT_ERROR 1 Terminate MMU
FAULT_ACCESS_FLAG 2 Terminate MMU
FAULT_INVALID_MAPPING 3 Terminate Translation Fault / MMU
FAULT_PRIV_VIOLATION 4 Terminate Domain Fault / MMU
FAULT_PERMISSION 5 Terminate MMU
FAULT_SYNC_EXT_ABORT 6 Terminate Synchronous External Abort
FAULT_ASYNC_EXT_ABORT 7 Terminate Asynchronous External Abort
FAULT_TTB_WALK_SEA 8 Terminate Translation Table Walk (Sync External Abort)
FAULT_TTB_WALK_SPE 9 Terminate Translation Table Walk (Sync Parity Error)
FAULT_MEM_ACCESS_SPE 10 Terminate Memory Access (Synchronous Parity Error)
FAULT_MEM_ACCESS_APE 11 Terminate Memory Access (Asynchronous Parity Error)
FAULT_DEBUG_EVENT 12 Terminate -
FAULT_INST_CACHE_MAINT 13 Terminate Instruction Cache Maintenance
FAULT_IMP_DEF_LD 14 Terminate Implementation Defined (Lockdown)
FAULT_IMP_DEF_CA 15 Terminate Implementation Defined (Coprocessor Abort)
FAULT_UNKNOWN -1 Terminate -
FAULT_UND_INST -2 Terminate Undefined Instruction

Recovery Strategy

The current kernel policy is Fail-Stop for individual processes. If any fault is detected:

  1. The current process is marked as PROCESS_TERMINATED.
  2. The fault_type and termination_reason are recorded in the process's PCB.
  3. The scheduler swaps out the current process and selects the next PROCESS_READY process.
  4. The system continues running other processes.

Notes:

  • Test on BeagleBone Black, otherwise the exceptions might not trigger on qemu.
  • MMU faults require the MMU to be enabled and set up.

Termination Reason

Termination Reason Value Description
EXIT_NORMAL 0 Process terminated normally. Default Value.
EXIT_SYSCALL 1 Process terminated after a syscall (Successful or Failed).
EXIT_FAULT 2 Process terminated after a fault.

About

A lightweight multiprogramming kernel for ARM architectures (VersatilePB & BeagleBone Black).

Topics

armv7kernellinux

Resources

Readme
Activity

Stars

0 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.