Norost IPC packets format - version 1
This is technically the third IPC packet format I came up with. However, the first one was never used much and I consider the second to be v0 since it was still a rather quick & hacky implementation that happened to work well enough at first.
The text below is what I typed in “notes.txt” while also sketching on paper. I don’t intend to upload the sketches as I don’t have a scanner.
Revision 2
fields (32/64 bit):
( 4/ 8) data: ptr
( 4/ 8) name: ptr
( 8/ .) data_offset: u64
( 4/ .) data_length: u32
( 4/ .) address: u32
( 2/ .) flags_kernel: u16
( 2/ .) flags_user: u16
( 2/ .) name_length: u16
( 2/ .) id: u16
total:
(32/40) packed
(../..) padded
flags_kernel (used by kernel):
( 2) 0- 1: Page size (4 levels: 4k/2M/1G/0.5T. More is likely (hopefully) not needed)
( 2) 2- 3: Data type (copy/share/move/inline)
( 2) 4- 5: Name type (copy/share/move/inline)
( 3) 6- 8: RWX flag data mapping
...
flags_user (ignored by kernel);
( 1) 0- 0: name (0) vs slot (1) name
( 1) 1- 1: byte (0) vs page (1) offset
( 1) 2- 2: ok (0) or err (1) (kernel-agnostic)
...
( 5) 11-15: Opcode (-16 to 15 ]signed (+request, -response))
opcodes:
request:
0: OPEN (make server allocate slot->object mapping)
1: CLOSE (remove slot->object mapping)
2: MAP (map page)
3: FLUSH (flush modified mapped data)
4: STAT (get object info)
5: LIST (list child objects)
6: CREATE (create object)
7: DESTROY (destroy object)
response:
-1: OK (operation successful)
-2: EXISTS (object already exist)
-3: NOPERM (insufficient permissions)
-4: UNAVAIL (object could or can not be created)
transfer:
with ASID: just context switch, it's cheap
without ASID: map IPC pages inside kernel to avoid switch
copy:
copy directly to userspace
userspace buffer: linked list of free blocks.
each block is 2^n bytes large
can be split into 2^(n-1), 2^(n-2), ... 16
16 bytes min seems reasonable?
256 bytes max seems reasonable too.
if 2^m blocks not available, split in 2^(m-1)
use one half, put other in list
recursive
max 2^16 free blocks of each size.
more blocks can't be used in one go anyways.
move/share:
map PPN[0] of self with A
map PPN[1]
map PPN[2]
...
map PPN[0] of other page with B
map PPN[1]
map PPN[2]
...
no context switch!
can be even faster with idempotent mapping
Revision 1
fields (32/64 bit):
( 4/ 8) address: usize
( 4/ 8) name: ptr
( 4/ 8) data: ptr
( 6/ .) data_offset: u48
( 2/ .) name_length: u16
( 4/ .) data_length: u32
( 2/ .) flags: u16
( 2/ .) id: u16
total:
(28/40) packed
(../..) padded
flags:
( 2) 0- 1: Page size (4 levels: 4k/2M/1G/0.5T.
More is likely (hopefully) not needed).
( 2) 2- 3: Data type (copy/share/move/inline)
( 2) 4- 5: Name type (copy/share/move/inline)
( 2) 6- 7: R/RW/RX/RWX flag data mapping
( 1) 8- 8: name (0) vs slot (1) name (kernel-agnostic)
( 1) 9- 9: byte (0) vs page (1) offset (kernel-agnostic)
( 1) 10-10: ok (0) or err (1) (kernel-agnostic)
( 5) 11-15: Opcode (32 kernel-agnostic, signed (+request, -response))
opcodes:
request:
0: OPEN (make server allocate slot->object mapping)
1: CLOSE (remove slot->object mapping)
2: MAP (map page)
3: FLUSH (flush modified mapped data)
4: STAT (get object info)
5: LIST (list child objects)
6: CREATE (create object)
7: DESTROY (destroy object)
response:
-1: OK (operation successful)
-2: EXISTS (object already exist)
-3: NOPERM (insufficient permissions)
-4: UNAVAIL (object could or can not be created)
transfer:
with ASID: just context switch, it's cheap
without ASID: map IPC pages inside kernel to avoid switch
copy:
copy directly to userspace
userspace buffer: linked list of free blocks.
each block is 2^n bytes large
can be split into 2^(n-1), 2^(n-2), ... 16
16 bytes min seems reasonable?
256 bytes max seems reasonable too.
if 2^m blocks not available, split in 2^(m-1)
use one half, put other in list
recursive
max 2^16 free blocks of each size.
more blocks can't be used in one go anyways.
move/share:
map PPN[0] of self with A
map PPN[1]
map PPN[2]
...
map PPN[0] of other page with B
map PPN[1]
map PPN[2]
...
no context switch!
can be even faster with idempotent mapping