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 |