What does your kernel API look like ?
What does your kernel API look like ?
We have a thread which allows people to show off what their OS looks like. I guess some of us are developing Posix systems and perhaps our APIs look a little like the Posix interface. But others have also given hints and glimpses at what they are doing and it seems a little different. Is there anyone who would like to show off their kernel API ?
I have nothing to show at the moment. Part of the reason I'm asking is because I can't settle on anything so I guess I'm looking for inspiration.
I have nothing to show at the moment. Part of the reason I'm asking is because I can't settle on anything so I guess I'm looking for inspiration.
If a trainstation is where trains stop, what is a workstation ?
Re: What does your kernel API look like ?
Hi gerry,
http://h71000.www7.hp.com/doc/732final/ ... tents.html . You may get inspired by the OpenVMS Api , it is not posixy .
One of the things i like about the api is that it enforces secure coding to some extent , VMS systems support call by descriptor , in which you always specify the pointer and the length all the time.
--Thomas
http://h71000.www7.hp.com/doc/732final/ ... tents.html . You may get inspired by the OpenVMS Api , it is not posixy .
One of the things i like about the api is that it enforces secure coding to some extent , VMS systems support call by descriptor , in which you always specify the pointer and the length all the time.
--Thomas
Re: What does your kernel API look like ?
I have two group of API:
1. driver development kit: this explose some kernel function to driver module by the linker during relocation.
2. application development: I have not design my own yet but POSIX wrapper interface is on my agenda.
I guess the naming of function is not that important at this moment, but I go for something like google code style, for example:
1. driver development kit: this explose some kernel function to driver module by the linker during relocation.
2. application development: I have not design my own yet but POSIX wrapper interface is on my agenda.
I guess the naming of function is not that important at this moment, but I go for something like google code style, for example:
Code: Select all
int syscall_is_computer_up(void);
Last edited by bluemoon on Sun Apr 29, 2012 6:19 am, edited 1 time in total.
- xenos
- Member
- Posts: 1121
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: What does your kernel API look like ?
My kernel API is not quite finished as well, but here's a glimpse of it:
Since I'm working on a microkernel, the low level kernel API is rather small. Further, it is rather different from POSIX in a number of ways. For example, there is no such thing as fork and exec, but rather things like CreateThread (which creates a new thread within the same address space) and CreateProcess (which executes some program in a new address space), similar to the Windows API. The most important (family of) system call(s) concerns IPC. I plan to implement synchronous IPC only, to avoid the necessity of message queues in the kernel. Finally there are a few support function to query system time, time consumption for threads and processes and so on.
Besides that, I'm thinking about an exokernel approach for the high level interface, although this concept is still a bit new to me...
Since I'm working on a microkernel, the low level kernel API is rather small. Further, it is rather different from POSIX in a number of ways. For example, there is no such thing as fork and exec, but rather things like CreateThread (which creates a new thread within the same address space) and CreateProcess (which executes some program in a new address space), similar to the Windows API. The most important (family of) system call(s) concerns IPC. I plan to implement synchronous IPC only, to avoid the necessity of message queues in the kernel. Finally there are a few support function to query system time, time consumption for threads and processes and so on.
Besides that, I'm thinking about an exokernel approach for the high level interface, although this concept is still a bit new to me...
- AndrewAPrice
- Member
- Posts: 2303
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: What does your kernel API look like ?
My kernel API and application API are somewhat intermixed because my entire OS is a platform for running high level bytecode. The closest thing to a "syscall" is calls to methods such as "new System.Threading.Thread" being intercepted during the JIT process. In that way my kernel/application API has been inspired by .Net and Java.
Its hard for someone to be able to run a C program on my platform. Not impossible (my bye code is just another target) but you'll face the same problems as compiling C programs for the JVM.
Its hard for someone to be able to run a C program on my platform. Not impossible (my bye code is just another target) but you'll face the same problems as compiling C programs for the JVM.
My OS is Perception.
- AndrewAPrice
- Member
- Posts: 2303
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: What does your kernel API look like ?
My kernel API and application API are somewhat intermixed because my entire OS is a platform for running high level bytecode. The closest thing to a "syscall" is calls to methods such as "new System.Threading.Thread" being intercepted during the JIT process. In that way my kernel/application API has been inspired by .Net and Java.
I have no IPC. If two programs reference the same library then only one instance of the library will be loaded. My OS is unconventional but that's why we're doing it!
Its hard for someone to be able to run a C program on my platform. Not impossible (my byte code is just another target) but you'll face the same problems as compiling C programs for the JVM.
I have no IPC. If two programs reference the same library then only one instance of the library will be loaded. My OS is unconventional but that's why we're doing it!
Its hard for someone to be able to run a C program on my platform. Not impossible (my byte code is just another target) but you'll face the same problems as compiling C programs for the JVM.
Last edited by AndrewAPrice on Sun Apr 29, 2012 10:57 am, edited 3 times in total.
My OS is Perception.
Re: What does your kernel API look like ?
I've got like two APIs, one for syscalls for userspace programs and one for kernel modules.
Userspace syscalls:
They are implemented in the simplest way possible like this:
For the kernel modules I've got only a few functions that drivers are able to utilize after they've been relocated. This list will get shorter later on when I will be moving more stuff to userspace.
That's it =)
Userspace syscalls:
Code: Select all
unsigned int call_open(char *path);
void call_close(unsigned int fd);
unsigned int call_read(unsigned int fd, unsigned int offset, unsigned int count, void *buffer);
unsigned int call_write(unsigned int fd, unsigned int offset, unsigned int count, void *buffer);
unsigned int call_execute(char *path, unsigned int argc, char **argv); // will change this to call_execute(char *path); eventually
unsigned int call_load(char *path); // load module
unsigned int call_unload(char *path);
unsigned int call_exit();
unsigned int call_wait(); // exit without giving up the resource
unsigned int call_attach(int index, void (*routine)()); // attach an event. often used before wait()
unsigned int call_detach(int index);
void call_halt();
void call_reboot();
Code: Select all
.intel_syntax noprefix
[...]
.global call_open
call_open:
mov eax, 0x04
int 0x80
ret
[...]
Code: Select all
irq_register_routine
irq_unregister_routine
mmu_map_kernel_memory
mmu_reload_memory
modules_bus_init
modules_device_init
modules_driver_init
modules_filesystem_init
modules_get_driver
modules_get_filesystem
modules_register_bus
modules_register_device
modules_register_driver
modules_register_filesystem
modules_unregister_bus
modules_unregister_device
modules_unregister_driver
modules_unregister_filesystem
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: What does your kernel API look like ?
I have two types of APIs: kernel API and application API.
Unlike many other systems, the kernel and device-drivers are not linked together, but reside in separately compiled modules. This is what the kernel API does. It allows device-drivers to expose their APIs, and to use APIs only be refering to their gate number.
The first step is API exposure, which is done at device-driver initialization time:
The next step is some device-driver using the function:
The user of the code basically loads the parameters into registers and then executes a far call to 0002:gate_nr.
The final step is a kernel function intercepting the protection fault that a call to selector 2 causes, and patching the code to either a far call or a push cs / near call.
The application API is similar, but a little more complex. It allows applications running in V86 mode, 16-bit protected mode and 32-bit protected or flat mode to use the same gate server code.
Below is how the gate exposure looks like.
The simplest interface, which can only be used if the same registers are used from both 16 and 32 bit mode:
This interface is used when different entry points for 16 and 32 bit code are required:
This interface is used when a module supports the sysenter / sysexit interface, and 16 bit and 32 bit code has the same register usage:
This interface is used when a module supports the sysenter / sysexit interface, and 16 bit and 32 bit code has different register usage:
Even if there are several ways of setting up the server part of application syscalls, there is only one way to use them:
If the application is 16-bit it will use a far call to 0001:gate_nr, and if it is 32-bit it will use a far call to 0003:gate_nr. The protection fault handler would then know which destination entry-point to use. Since application calls cannot directly be patched with far calls, the server in kernel will either create a call gate and patch the call to a call gate instead, or if the sysenter interface is supported and the API has registered a sysenter handler, it will patch the code to a call near stub in application space that would load some registers and do a sysenter.
Application calls can also be used from kernel and / or device-drivers. When this is the case, they are patched to far or near calls.
Kernel API (for assembly): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Kernel API (for C): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Application API (for assembly): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Application API (for C): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Calls from V86 mode are special. They use an invalid instruction, which is intercepted, and then the function is carried out in kernel, and iretd is issued to re-execute code after the invalid instruction. However, this interface no longer is maintained, and thus is not working at the moment.
Unlike many other systems, the kernel and device-drivers are not linked together, but reside in separately compiled modules. This is what the kernel API does. It allows device-drivers to expose their APIs, and to use APIs only be refering to their gate number.
The first step is API exposure, which is done at device-driver initialization time:
Code: Select all
; AX Gate number
; DS:ESI Gate entry point
; ES:EDI Gate name
RegisterOsGate MACRO
OsGate register_osgate_nr
ENDM
Code: Select all
OsGate16 MACRO gate_nr
db 67h
db 66h
db 9Ah
dd gate_nr
dw 2
ENDM
OsGate32 MACRO gate_nr
db 3Eh
db 67h
db 9Ah
dd gate_nr
dw 2
ENDM
OsGate MACRO gate_nr
IF (size $) EQ 0FF02h
OsGate16 gate_nr
ELSE
OsGate32 gate_nr
ENDIF
ENDM
The final step is a kernel function intercepting the protection fault that a call to selector 2 causes, and patching the code to either a far call or a push cs / near call.
The application API is similar, but a little more complex. It allows applications running in V86 mode, 16-bit protected mode and 32-bit protected or flat mode to use the same gate server code.
Below is how the gate exposure looks like.
The simplest interface, which can only be used if the same registers are used from both 16 and 32 bit mode:
Code: Select all
; AX Gate number
; DX Segment registers to transfer between V86 and protected mode
; DS:ESI Gate entry point
; ES:EDI Gate name
RegisterBimodalUserGate MACRO
OsGate register_bimodal_usergate_nr
ENDM
Code: Select all
; AX Gate number
; DX Segment registers to transfer between V86 and protected mode
; DS:EBX 16 bit entry point
; DS:ESI 32 bit entry point
; ES:EDI Gate name
RegisterUserGate MACRO
OsGate register_usergate_nr
ENDM
Code: Select all
; AX Gate number
; DX Segment transfer
; DS:ESI Far call address
; DS:EBP Near call address
; ES:EDI Gate name
RegisterBimodalSyscall MACRO
OsGate register_bimodal_syscall_nr
ENDM
Code: Select all
; AX Gate number
; DX Segment transfer
; DS:EBX 16-bit far call address
; DS:ESI 32-bit far call address
; DS:EBP 32-bit near call address
; ES:EDI Gate name
RegisterSyscall MACRO
OsGate register_syscall_nr
ENDM
Code: Select all
UserGate16 MACRO gate_nr
db 67h
db 66h
db 9Ah
dd gate_nr
dw 1
ENDM
UserGate32 MACRO gate_nr
db 3Eh
db 67h
db 9Ah
dd gate_nr
dw 3
ENDM
UserGate MACRO gate_nr
IF (size $) EQ 0FF02h
UserGate16 gate_nr
ELSE
UserGate32 gate_nr
ENDIF
ENDM
Application calls can also be used from kernel and / or device-drivers. When this is the case, they are patched to far or near calls.
Kernel API (for assembly): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Kernel API (for C): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Application API (for assembly): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Application API (for C): http://rdos.net/vc/viewvc.cgi/trunk/ker ... iew=markup
Calls from V86 mode are special. They use an invalid instruction, which is intercepted, and then the function is carried out in kernel, and iretd is issued to re-execute code after the invalid instruction. However, this interface no longer is maintained, and thus is not working at the moment.
Re: What does your kernel API look like ?
What about create/remove?Jezze wrote: Userspace syscalls:
Code: Select all
unsigned int call_open(char *path); void call_close(unsigned int fd); unsigned int call_read(unsigned int fd, unsigned int offset, unsigned int count, void *buffer); unsigned int call_write(unsigned int fd, unsigned int offset, unsigned int count, void *buffer); unsigned int call_execute(char *path, unsigned int argc, char **argv); // will change this to call_execute(char *path); eventually unsigned int call_load(char *path); // load module unsigned int call_unload(char *path); unsigned int call_exit(); unsigned int call_wait(); // exit without giving up the resource unsigned int call_attach(int index, void (*routine)()); // attach an event. often used before wait() unsigned int call_detach(int index); void call_halt(); void call_reboot();
- AndrewAPrice
- Member
- Posts: 2303
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: What does your kernel API look like ?
@rdos: That is a nice clean self-describing API that could be used with very little to no documentation. Well done.
My OS is Perception.
Re: What does your kernel API look like ?
my new syscall interface reuse the AMD ABI on x86_64:
syscall parameters and return values are on rdi, rsi, rcx, etc which are exactly match with the ABI, and only registers needed to be preserve are preserved.
In kernel the stub looks like this:
Code: Select all
; int _exit ();
_exit:
mov eax, 1
syscall
ret
; int open ( const char * file, int flags, int mode );
open:
mov eax, 2
mov r10, rcx ; rcx is used by syscall
syscall
ret
In kernel the stub looks like this:
Code: Select all
_syscall_stub:
mov r12, rcx ; ring3 rip
mov r13, r11 ; rflags
mov rcx, r10
; call handler[eax]
mov rcx, r12
mov r11, r13
sysret