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];
}
}
--------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);
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.