Page 1 of 1

Ring buffers for syscall in mikrokernell.

Posted: Wed Apr 10, 2024 5:41 am
by JustVic
I have a few questions about a system like io_using on Linux, but very simplified. It uses ring buffers to transfer kernel system calls. This is what I want to build. I think it might be useful for a microkernel.

My construction is something like this:

Code: Select all

struct ring_sqe {
   enum sqe_op    opcode;   
   uint8_t    flags;          
   uint32_t   fd;             
   int64_t *argptr;
};
struct ring_cqe {
  uint64_t     user_data; 
  uint32_t     res;        
  uint32_t     flags;
};

struct ring_sq {
  struct ring_sqe *sqes;
  uint64_t sqe_head;
  uint64_t sqe_tail;
  size_t ring_sz;
  //void *ring_ptr;
};

struct ring_cq {
  struct ring_cqe *cqes;
  uint64_t cqe_head;
  uint64_t cqe_tail;
  size_t ring_sz;
//  void *ring_ptr;
};

struct rings {
  struct ring_sq sq;
  struct ring_cq cq;
  unsigned flags;
//  int rings_fd;
};

1 - Is it good strategy for all or most syscalls in microkernell?

2 - How to pass syscalls with variable args/parameters of different types through ring buffer to kernel?
-----One way I can thik is:

Code: Select all

            typedef struct {
    int syscall_num;
    int param_count;
    size_t param_sizes[MAX_PARAMS];
    void *params[MAX_PARAMS];
} syscall_t;

//Pack the System Call Parameters
void pack_syscall_args(syscall_t *syscall, void *buffer) {
    size_t offset = 0;
    
    for (int i = 0; i < syscall->param_count; i++) {
        memcpy(buffer + offset, syscall->params[i], syscall->param_sizes[i]);
        offset += syscall->param_sizes[i];
    }
}
But wouldn't it be too slow for system calls?
--------Other way is to pack in to array:

Code: Select all

struct ring_sqe {
   enum sqe_op    opcode;   
   uint8_t    flags;          
   uint32_t   fd;             
   int64_t *argptr;
};
...
	int64_t mass[200];

	char g = 'g';
	char s[4] = "asdf\0";
	int z = 2;
	bool b = false;
	mass[0] = g;
	mass[1] = z;
	mass[2] = b;
	mass[3] = s;

	Sqe.opcode = 6;
	Sqe.argptr = mass; 

     	ring_set(&RingsM, &Sqe);
---------Maybe somehow to use va_list args...

3 - And how can I check on the kernel side that the parameters with the correct types were sent from the user space?

If you have any ideas on how to build such a system in a very simplified way, it would be nice to hear them. :roll:

Re: Ring buffers for syscall in mikrokernell.

Posted: Thu Apr 11, 2024 4:22 pm
by kashimoto
I do not have too much experience with these ring buffers, these are just my ideas after 1year of kernel hobby os work.

1. I cannot really help with this.
Probably it is worth for very specific situations, i do not know what exactly your needs there.
But i would guess that these syscalls are heavily IO specific so, in my OS that is not such a trouble haha.

2.
Regarding the size of the packages: I think when you initialise your queue from the user-space side,
you could have a parameter to define the request/response package sizes?
In this case the caller needs to know the max size they are willing.

Packing:
The nicest would be (IMO) if all syscall has their own struct, so you could just memcpy their content into the ring buffer.

Also you can go with the max param count yes,
Or also just store the number of parameters in a numeric field,
then with pointer-magic you just read it from-to the correct region.
struct {
int param_count;
int params[];
// and the content can even contain the length of the param and then the actual param's value,
// so you can even put an integer field, then a char array, in a single package
}

3. You need to validate them manually based on the given syscall that was requested.
Whether they have the correct value range, modes, etc.
Validate the output buffer, whether the kernel has correct read/write access to it, whether it is long enough to read/write the requested amount of data from/into it.
The same if your parameter is being a pointer to a struct,you need to follow the pointer and check that struct for validity.

I hope you can find some useful stuff in it :D

Re: Ring buffers for syscall in mikrokernell.

Posted: Fri Apr 12, 2024 11:07 am
by JustVic
Thanks for your answer kashimoto. I will try to do it as you say one struct for each syscall. I think it's convenient.