param result 0 reset all attributes to their defaults 1 set bold 2 set half-bright (simulated with color on a color display) 3 set italic (since Linux 2.6.22; simulated with color on a color display) 4 set underscore (simulated with color on a color display) (the colors used to simulate dim or underline are set using ESC ] ...) 5 set blink 7 set reverse video 10 reset selected mapping, display control flag, and toggle meta flag (ECMA-48 says "primary font"). 11 select null mapping, set display control flag, reset toggle meta flag (ECMA-48 says "first alternate font"). 12 select null mapping, set display control flag, set toggle meta flag (ECMA-48 says "second alternate font"). The toggle meta flag causes the high bit of a byte to be toggled before the mapping table translation is done. 21 set underline; before Linux 4.17, this value set normal intensity (as is done in many other terminals) 22 set normal intensity 23 italic off (since Linux 2.6.22) 24 underline off 25 blink off 27 reverse video off 30 set black foreground 31 set red foreground 32 set green foreground 33 set brown foreground 34 set blue foreground 35 set magenta foreground 36 set cyan foreground 37 set white foreground 38 256/24-bit foreground color follows, shoehorned into 16 basic colors (before Linux 3.16: set underscore on, set default foreground color) 39 set default foreground color (before Linux 3.16: set underscore off, set default foreground color) 40 set black background 41 set red background 42 set green background 43 set brown background 44 set blue background 45 set magenta background 46 set cyan background 47 set white background 48 256/24-bit background color follows, shoehorned into 8 basic colors 49 set default background color 90..97 set foreground to bright versions of 30..37 100..107 set background, same as 40..47 (bright not supported)
Commands 38 and 48 require further arguments: ;5;x 256 color: values 0..15 are IBGR (black, red, green, ... white), 16..231 a 6x6x6 color cube, 232..255 a grayscale ramp ;2;r;g;b 24-bit color, r/g/b components are in the range 0..255
The critical key to the Component-based design is the Feature. This can be configured in the Cargo.toml file and in the Makefile environment variable, which can decide which content to compile and link. It feels like a advanced #if - #endif switch option.
Unikernel
We use 3 stages to express the system advancing from bare-metal program to a component-based system.
Bare-metal program
Hardfirm + Bootloader
Initialize the special registers
Initialize MMU (for Paging)
Initialize Stack
Initialize Interrupt Vector
Initialize Peripherals / Devices
Transfer to main program
Layer / Hierarchy
Hardfirm + Bootloader (Layer)
Hardware Initialization(Layer): the special registers 、MMU(for Paging)、STACK、Interrupt Vector
voidReset_Handler(void){ __asm__ volatile( ".code 32 \n" "CPSID if \n"// Mask interrupts /* Put any cores other than 0 to sleep */ "MRC p15, 0, R0, c0, c0, 5 \n"/* Read MPIDR */ "ANDS R0, R0, #3 \n" "goToSleep: \n" "ITT NE \n"/* Needed when in Thumb mode for following WFINE instruction */ "WFINE \n" "BNE goToSleep \n" /* Reset SCTLR Settings */ "MRC p15, 0, R0, c1, c0, 0 \n"/* Read CP15 System Control register */ "BIC R0, R0, #(0x1 << 12) \n"/* Clear I bit 12 to disable I Cache */ "BIC R0, R0, #(0x1 << 2) \n"/* Clear C bit 2 to disable D Cache */ "BIC R0, R0, #0x1 \n"/* Clear M bit 0 to disable MMU */ "BIC R0, R0, #(0x1 << 11) \n"/* Clear Z bit 11 to disable branch prediction */ "BIC R0, R0, #(0x1 << 13) \n"/* Clear V bit 13 to disable hivecs */ "BIC R0, R0, #(0x1 << 29) \n"/* Clear AFE bit 29 to enable the full range of access permissions */ "ORR R0, R0, #(0x1 << 30) \n"/* Set TE bit to take exceptions in Thumb mode */ "MCR p15, 0, R0, c1, c0, 0 \n"/* Write value back to CP15 System Control register */ "ISB \n" /* Configure ACTLR */ "MRC p15, 0, r0, c1, c0, 1 \n"/* Read CP15 Auxiliary Control Register */ "ORR r0, r0, #(1 << 1) \n"/* Enable L2 prefetch hint (UNK/WI since r4p1) */ "MCR p15, 0, r0, c1, c0, 1 \n"/* Write CP15 Auxiliary Control Register */ /* Set Vector Base Address Register (VBAR) to point to this application's vector table */ "LDR R0, =Vectors \n" "MCR p15, 0, R0, c12, c0, 0 \n" "ISB \n" ... "CPSIE if \n"// Unmask interrupts "BL __libc_init_array \n" "BL main \n" ...) }
The above code selected from the HAL Code of STM32MP13, as the initialization and reset handler code, which will help initialize STACK, Interrupt-Vector and critical registers, and end up transferring to main program. The code is followed similar logic as the rCore, and can help us have a better understanding of the MCU, MPU and CPU.
Like rCore, We need to provide implementation for the memory interfaces about heap operations, to avoid memory leaks and memory fragmentation. This can help us manage memory more efficiently, and provide convenience for future expansion.
There are 2 kinds of Memory Allocation Functions: One is based on Page (palloc), and the other is based on Byte (balloc), where the “ByteAlloc” is based on “PageAlloc”.
If we take “PageAlloc” based on “ByteAlloc”, it will be difficult to align.
Algorithm for Memory Allocation
TLSF, Two-Level Segregated Fit
Buddy
Slab
Bump
How to enable paging mechanism:
Early in the kernel startup, use the ruled identity mapping part of memory
Note that some address-related registers, such as SP, need to be changed to linear addresses
Then if paging feature specified, rebuild the complete paging reflect.
Task switching: Swaps the task currently being executed with a task in the ready queue. For Single-core CPU, the form of multitasking can only be concurrent, but not parallel.
State of Task
Running
The number is equal to the number of processor cores
SWITCH-TO: Ready or Blocked or Exited
Ready
Is ready to be scheduled at any time
SWITCH-TO: Running
Blocked
Waiting for an event or resource satisfying a condition
SWITCH-TO: Ready
Exited
The task is finished and waiting to be recycled
Task switching: Firsty, save the context of the current task. Then, restore the context of the new task. Finally, trandfer to switch tasks. Note that the interrupt enable state of the processor switching the task, should be off during the switching process (CLI). If neccessary, the Spinlock and Mutex are required to be used to avoid race conditions (SMP?).
There are usual preemption conditions: One is the time slice of the task is exhausted, and the other is the interrupt source, such as the clock (Timer). The privilege level may be used to determine the nested or re-entry of the traps.
Algorithm of Scheduling
Collaborative scheduling algorithm (FIFO, fair)
Preemptive scheduling algorithm (Privileged)
ROUND_ROBIN
CFS (Completely Fair Scheduler)
The DEVICEs are usually in the kinds of net, block, display and so on.
How to discover and initialize devices
(axruntime at startup) discovers the device and initializes it with the appropriate driver
axdriver Indicates the process of discovering and initializing devices
2-stage cyclic detection discovers the device
Level 1: traverses all virtio_mmio address ranges, determined by the platform physical memory layout, and performs transition page mapping
Level 2: Enumerate devices with the for_each_drivers macro, and then probe each virtio device probe_mmio
probe discovers devices based on the bus, matches drivers one by one, and initializes them
Bus connecting with devices
PCI
MMIO
A File System is a mechanism used in an operating system to manage files and data on computer storage devices such as hard disks, SSDS, flash memory, etc. (In Linux, every device will also exist as one or more files)
File System
RAMFS: A memory-based virtual file system
For temporary data storage that is fast but easy to lose.
DEVFS: Device file system
For managing and accessing hardware devices, simplifying the development and access of device drivers.
ProcFS: process file system
Provides system process and status information for system monitoring and management.
SysFS: System file system
Exports kernel objects and properties for viewing and managing hardware devices and drivers.
Macro kernel
More than before:
Privilege Level
Address space
So we need
Map user/kernel space (address space)
Usual method
The high end of the page table is used as kernel space
The low end is used as user application space, because user programs mostly start from low addresses
Kernel space is shared and user space is used independently
Add system call (cross-privilege + address space)
The user applications toggle between two privilege levels:
Task Context : User Level, execute application logic
Trap Context : Kernel Level, handle system calls and exceptions
Address space Area mapping Back-end Backend maps specific areas in a space
Linear
case The target physical address space area already exists, and the mapping relationship is directly established
It can be used for MMIO area mapping and special shared address area mapping
Corresponding physical page frames must be consecutive
Alloc (Lazy)
case Use missing page exception (亡羊补牢)
Mapped by page, the corresponding physical page frames are usually discontinuous
To compatible with Linux applications, we should implement the compatible system calls, file systems and other system resources. This asks us to follow the POSIX standard.
POSIX allows developers to write applications using a standard set of apis without worrying about differences in the underlying operating system.
Except Windows, many modern operating systems, such as Linux, macOS (based on Unix), and many embedded systems (RtOS ?) , are partially or fully POSIX compliant. This allows applications developed on these systems to run seamlessly on different platforms.
When loading the ELF-formatted application, the VirtAddr and MemSiz are used to place the segment in the target virtual memory location. Beware that some segments like .bss are all zeros, so the actual data is not stored in the ELF file, but rather dynamically allocated space is requested.
The important support to do is to implemwnt hosted-standing environment main function. We should provide:
Parameter information (argc and argv): parameter number, parameter string pointer array
Environment information (envv): environment variable string pointer array
Hypervisor
Each virtual machine has its own independent virtual machine hardware, based on the physical computer. Each virtual machine runs its own operating system, and the operating system believes that it is alone in the execution environment, and cannot distinguish whether the environment is a physical machine or a virtual machine. (ideal state)
This is similar to virtualization software, like VMware ?
Is the virtual 8086 mode on x86 the same or similar principle?
The difference between a Hypervisor and an Emulator is whether the architecture of the virtual running environment is the same as that of the physical running environment that supports it.
It Seems to have something to do with emulation KVM acceleration.
Layers of resource objects supported by the Hypervisor:
VM: manages the address space.
vCPU: indicates the virtualization of computing resources and the flow of execution on VMS
vMem: Memory virtualization based on the physical space layout of VMS
vDevice: indicates device virtualization, including direct mapping and emulation
vUtilities: interrupts virtualization and bus device operation
Usually use below items to implement a Hypervisor:
run_guest is responsible for entering Guest environment
guest_exit is responsible for exiting Guest environment