diff options
author | Michael Kelly <mike@weatherwax.co.uk> | 2025-08-31 23:21:54 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-08-31 23:21:54 +0200 |
commit | fdfca0e86009c5a7b188fa39e939de800a73391d (patch) | |
tree | d590b5ebe43d1ed21fd5dbae75240031e99b34a8 | |
parent | eec7037c885f6e54bf8f22d421d6abc55a2cd667 (diff) |
Add mach_port_set_ktype RPC to set ktype of a user port
For now, we only allow a newly-introduced MACH_PORT_KTYPE_USER_DEVICE type
that makes ipc_kmsg_copyin_body use page lists, which keep them in a busy
state that prevents them from being paged out.
-rw-r--r-- | include/mach/mach_port.defs | 18 | ||||
-rw-r--r-- | include/mach/port.h | 6 | ||||
-rw-r--r-- | ipc/ipc_object.c | 1 | ||||
-rw-r--r-- | ipc/mach_port.c | 39 | ||||
-rw-r--r-- | kern/ipc_kobject.h | 9 |
5 files changed, 70 insertions, 3 deletions
diff --git a/include/mach/mach_port.defs b/include/mach/mach_port.defs index 3823bb14..3f2aed14 100644 --- a/include/mach/mach_port.defs +++ b/include/mach/mach_port.defs @@ -358,3 +358,21 @@ routine mach_port_set_protected_payload( routine mach_port_clear_protected_payload( task : ipc_space_t; name : mach_port_name_t); + +/* + * Set the kernel port type for specific kernel behaviour. + * ktype must be one of: + * MACH_PORT_KTYPE_NONE + * MACH_PORT_KTYPE_USER_DEVICE + * The named port must not be currently associated with any + * other kernel port type. + */ + +type mach_port_ktype_t = unsigned; + +routine mach_port_set_ktype( + host : host_priv_t; + task : ipc_space_t; + name : mach_port_name_t; + right : mach_port_right_t; + ktype : mach_port_ktype_t); diff --git a/include/mach/port.h b/include/mach/port.h index c9bbcf17..488d2c9e 100644 --- a/include/mach/port.h +++ b/include/mach/port.h @@ -156,4 +156,10 @@ typedef struct mach_port_status { #define MACH_PORT_QLIMIT_DEFAULT ((mach_port_msgcount_t) 5) #define MACH_PORT_QLIMIT_MAX ((mach_port_msgcount_t) 16) +typedef unsigned int mach_port_ktype_t; + +/* Constants for calls to mach_port_set_ktype() */ +#define MACH_PORT_KTYPE_NONE 0 +#define MACH_PORT_KTYPE_USER_DEVICE 28 + #endif /* _MACH_PORT_H_ */ diff --git a/ipc/ipc_object.c b/ipc/ipc_object.c index 1074fb2c..d6c332e6 100644 --- a/ipc/ipc_object.c +++ b/ipc/ipc_object.c @@ -944,6 +944,7 @@ char *ikot_print_array[IKOT_MAX_TYPE] = { "(CLOCK) ", "(CLOCK_CTRL) ", "(PAGER_PROXY) ", /* 27 */ + "(USER_DEVICE) ", /* 28 */ /* << new entries here */ "(UNKNOWN) " /* magic catchall */ }; /* Please keep in sync with kern/ipc_kobject.h */ diff --git a/ipc/mach_port.c b/ipc/mach_port.c index d8696e23..eed3e725 100644 --- a/ipc/mach_port.c +++ b/ipc/mach_port.c @@ -1567,6 +1567,45 @@ mach_port_clear_protected_payload( return KERN_SUCCESS; } +kern_return_t +mach_port_set_ktype( + host_t host_priv, + ipc_space_t space, + mach_port_name_t name, + mach_port_right_t right, + mach_port_ktype_t ktype) +{ + ipc_port_t port; + kern_return_t kr; + + if (host_priv == HOST_NULL) + return KERN_INVALID_HOST; + + if (space == IS_NULL) + return KERN_INVALID_TASK; + + if (ktype != MACH_PORT_KTYPE_NONE + && ktype != MACH_PORT_KTYPE_USER_DEVICE) + return KERN_INVALID_ARGUMENT; + + kr = ipc_object_translate(space, name, right, (ipc_object_t *)&port); + if (kr != KERN_SUCCESS) + return kr; + + /* port is locked and active */ + if (ip_kotype(port) == IKOT_NONE || ip_kotype(port) == IKOT_USER_DEVICE) + ipc_kobject_set(port, IKO_NULL, + ktype == MACH_PORT_KTYPE_NONE + ? IKOT_NONE + : IKOT_USER_DEVICE); + else + kr = KERN_INVALID_ARGUMENT; + + ip_unlock(port); + + return kr; +} + #if MACH_KDB void diff --git a/kern/ipc_kobject.h b/kern/ipc_kobject.h index 606a66a9..63ad87c5 100644 --- a/kern/ipc_kobject.h +++ b/kern/ipc_kobject.h @@ -77,9 +77,10 @@ typedef unsigned int ipc_kobject_type_t; #define IKOT_CLOCK 25 #define IKOT_CLOCK_CTRL 26 #define IKOT_PAGER_PROXY 27 +#define IKOT_USER_DEVICE 28 /* << new entries here */ -#define IKOT_UNKNOWN 28 /* magic catchall */ -#define IKOT_MAX_TYPE 29 /* # of IKOT_ types */ +#define IKOT_UNKNOWN 29 /* magic catchall */ +#define IKOT_MAX_TYPE 30 /* # of IKOT_ types */ /* Please keep ipc/ipc_object.c:ikot_print_array up to date */ #define is_ipc_kobject(ikot) (ikot != IKOT_NONE) @@ -90,7 +91,9 @@ typedef unsigned int ipc_kobject_type_t; */ #define ipc_kobject_vm_page_list(ikot) \ - ((ikot == IKOT_PAGING_REQUEST) || (ikot == IKOT_DEVICE)) + ((ikot == IKOT_PAGING_REQUEST) || \ + (ikot == IKOT_DEVICE) || \ + (ikot == IKOT_USER_DEVICE)) #define ipc_kobject_vm_page_steal(ikot) (ikot == IKOT_PAGING_REQUEST) |