CORESRV
Presentation
Coresrv is the main and central service of LSE/OS. It manages:
Note the following particularities of LSE/OS:
LSE/OS only manages elementary task and memory operations and guarantee the security for it.
The Task Control Block
The TCB is the structure that represent a task. It is not only a logical view of the reality but a hardware view: if you pay attention to the t_tcb_export strcture, you notice that the t_tss structure is defined first because it is a requirement for calling a taskgate. The iomapbase field is the offset to the optional t_iomap that defines ISA ioport permissions.
Class | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|
t_ucred | Store credentials of the process | ||||||||
t_ustat | Store statistics of the process | ||||||||
t_tcb_export | The portable portion of the TCB | ||||||||
t_tss | The HW structure of a taskgate context | ||||||||
t_sigctx | The context binded to a signal handler | ||||||||
t_usig | The optional structure needed by a signalable task | ||||||||
iomap | The optional HW IO map of authorized ioports for the task | ||||||||
t_tcb_full | The TCB as it is viewed in coresrv, especially it contains fields for storing the task in the linked lists of the system
|
Address Spaces
An address space is a virtual memory set (t_area_set). For each address space there is a page directory and some page tables according to the x86 requirements. Altough tasks need at least one address space as a support for execution, address spaces are managed totaly separately from tasks. Many tasks can share the same address space and one task can use have many address spaces.
Class | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|
t_aspace_export | The portable portion of the address space
| ||||||||
t_aspace_full | The address space structure that is viewed inside coresrv: especially it contains the fields required for beeing stored in the linked lists of the system, etc
| ||||||||
t_area_set | Described in the memory management section. |
Item | Description |
---|---|
sys0_set | Physical pages < pstart |
sys1_set | Physical pages > 0xd0000000 (memory mapped registers) |
phys_set | Physical pages (RAM) excepted sys0 and sys1 |
kern_set | Kernel virtual pages |
asn_set | Area sets of address spaces. Note they all contains kernel page tables |
Please have a look in x86 manual for understanding page directory mechanism.
Dynamic View
Step | Description |
---|---|
1 | The creator queries the size (in page) requested for the specic options it needs for the new task: especially the TCB size may vary if the task is signalable: signal context (t_sigctx) structures are present in the TCB, or the task accesses ioports so it must contains a iomap in it. |
2 | The creator allocates the needed physical pages for the TCB |
3 | Since the TCB virtual pages must be kernel addresses, the creator allocates kernel pages for it. It is easy to implement a quota mechanism for a user to allocate only a limited number of kernel pages. |
4 | The creator make the kernel pages mapping on the previously allocated pages. |
5 | The creator registers the newly created TCB and gets a 64bit pid |
6 | The creator binds the task to the address space. |
7 | The creator loads the name of the new task |
8 | The creator loads the class of the new task (TCBC_UNDEF, TCBC_SCHED, TCBC_SERVICE, TCBC_REALTIME, TCBC_KERNEL) |
9 | The creator loads the registers of the new tasks: the full set with ltss() and only the entry points with lep() |
10 | The creator sets the task in run queue. The task could then be scheduled. |
The following diagram illustrates the 3 use cases actions that have to be managed by the context switcher:
Step | Description |
---|---|
1 | Cswitch calls runq() to get the next action to perform |
Use Case 1 | A Task is beeing elected |
2 | Cswitch restores the FPU state of the task (because it is not done automatically) |
3 | Cswitch unlocks the task in the GDT: It can be called then in assembly |
4 | Cswitch calls the taskgate in assembly |
5 | Cswitch locks the task again: it cannot be called by anybody |
6 | Cswitch saves the FPU context of the task |
Use Case 2 | An address space has to be destroyed: an aspace is destroyed when no more task use it (refcnt) |
7 | Cswitch needs the full definition of the address space |
8 | Cswitch releases the address space: asrele() is not a syscall but a convenience function that retrieves all the memory areas used by the address space with memdef() and call prele(), krele() and vrele() according to the type of each area. |
9 | Cswitch unregisters the address space: it removes it from the hash table |
10 | Cswitch unmap the aspace page from the TLB |
11 | Cswitch removes all the pages tables from the page directory corresponding to the address space |
12 | Flush of the TLB cache to update the processor |
13 | Free the page directory of the address space |
14 | Free the physical page of the address space |
15 | Free the kernel page of the address space |
Use Case 3 | A TCB is beeing destroyed |
16 | Cswitch get the full definition of the TCB |
17 | Cswitch unregisters the TCB: remove task from hash table and process list |
18 | Cswitch unmaps the TCB from TLB |
19 | Cswitch releases the physical pages of the TCB |
20 | Cswitch releases the kernel pages of the TCB |
Coresrv API overview
Links refer to Doxygen generated prototypes of functions:
Syscall | Description | Debug |
---|---|---|
__sfullas() | Get the full definition of the address space (kernel dependent) | |
__sfulllink() | Get the full definition of the caller task (kernel dependent) | |
__sfulltcb2() | Get the full definition of a task (kernel dependent) | |
aggdef() | Get the definition of some physical pages marked as non coalescible | |
ascopy() | Copy memory from an address space to one another | |
asop() | Perform some address space operations (address space switching, etc) | |
aspgdir() | Get the page directory of the specified address space | |
asreg() | Register an address space | |
assert() | Declare one assertion (for kernel only) | Yes |
asunreg() | Unregister an address space | |
check() | Launch a sanity check | Yes |
clearbsy() | Clear the BSY bit of a task in GDT (unlock the task from processor) | |
collect() | Collect information on dead tasks | |
copy() | Copy memory from one task to one another | |
dump() | Dumps some debug information of the system | Yes |
dwrite() | Prints a message on console | |
_exit() | Kill current task with an error code | |
getegid() | Get the effective group id of the task | |
geteuid() | Get the effective uid of the task | |
getgid() | Get the group id of the task | |
getgroups() | Get all the groups of the task | |
getsel() | Get the selector associated to a pid | |
getuid() | Get current uid of the task | |
ioacquire() | Acquire the rights on a ioport | |
iorele() | Release the rights on a ioport | |
kdef() | Get information on kernel pages | |
kill() | Send a signal to a task | |
krele() | Release kernel pages | |
krsv() | Reserve kernel pages | |
lasep() | Load entry points of an address space (if it is an executable) | |
lasprotect() | Protect the current address space | |
lclass() | Modify the class of a task | |
lep() | Load entry points of the task | |
lfpu() | Load the FPU state into the task | |
_lidt() | Store records to IDT | |
llinkret() | Modify the return codes of a task | |
lname() | Change the name of a task | |
lstatus() | Change the status of a task (TCBS_IDLE, TCBS_RUN, TCBS_SLEEP, TCBS_STOP, TCBS_ZOMBIE, TCBS_STOP) | |
ltrace() | Trace a process (syscalls, traps, pgflts, etc) and print debug message on console | Yes |
ltss() | Load the TSS (task x86 registers) into a task | |
memdef() | Get information on physical, kernel and user pages of an address space id | |
memdump() | Dump address spaces informations on console | Yes |
nicepid() | Change the priority of the task | |
notify() | Declare the task as the notify manager | |
paggregate() | Mark physical pages as non coalescible | |
pdef() | Get information on physical pages | |
pgive() | Give some physical pages to an another address space | |
prele() | Release physical pages | |
procdef() | Get information on tasks in the system | |
prsv() | Reserve physical pages | |
pshare() | Mark physical pages as shareable | |
ptrace() | Like the Unix equivalent, cause the task to be stopped when it has to be signaled, the parent process receives a SIGCHLD | |
_rcr3() | Get the current page directory of the task | |
reboot() | Reboot the system | |
remrunq() | Remove a task from run queue | |
remrunq2() | Remove a task from run queue (by pid) | |
reparent() | More generic form of yield() that allows to yield in another context | |
runq() | Get the next task to run according to a round robin algorithm and if signals have to be posted | |
sas() | Get an address space record | |
sasid() | Get the current address space id | |
sclass() | Get the class of the task | |
scred() | Get the credentials of a task | |
secmgr() | Declare current task as security manager | |
setasuid() | Set the owner of the address space | |
setbsy() | Set the BSY bit of a task in GDT | |
setegid() | Set the effective group id of the task | |
seteuid() | Set the effective uid of the task | |
setgid() | Set the group id of the task | |
setgroups() | Set all the groups of the task | |
setpgid() | Set process group id | |
setrunq() | Set a task in run queue (by pid) | |
setrunq2() | Set a task in run queue | |
setuid() | Set the uid of the task | |
sfpu() | Get the FPU state of a task | |
_sgdt() | Get records from GDT (Global Descriptor Table) | |
_sidt() | Get records from IDT (Interrupt Descriptor Table) | |
sigaction2 | More generic form of the sigaction() unix call | |
sigprocmask() | Same as in Unix | |
sigreturn() | Return from a signal handler | |
sigsuspend() | Same as in Unix | |
sinfo() | Get system info such as GDT address and limit | |
slink() | Get the tcb of caller (e.g. for syscalls) | |
spgid() | Get the process group id of a task | |
spgid2() | Get the process group of the task (by pid) | |
spid() | Get the current pid (64bits) | |
sppid() | Get the parent process id of a task | |
sppid2() | Get the parent process id of task (by pid) | |
sq_gate() | To be documented | |
ssig() | Get info for pending signals of a task | |
stcb() | Get properties of a task (Task Control Block) | |
stcb2() | Same as stcb() but take a pid instead of a selector in parameter | |
tcbreg() | Register a new TCB | |
tcbsizepg() | Get the size in page needed by a tcb according to task options | |
tcbunreg() | Unregister a TCB | |
vdef() | Get information on virtual pages | |
vm86() | Perform a VM86 call | |
vmap() | Map virtual pages to physical pages | |
vrele() | Release virtual pages | |
vrsv() | Reserve virtual pages in an address space | |
vunmap() | Unmap virtual pages from physical pages | |
wait4() | Same as in Unix | |
wire() | Wire pages into physical TLB |