mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 20:40:28 +00:00
Merge pull request #4357 from beaumccartney/mach-vm-apis
bindings, types, and constants for some mach vm apis
This commit is contained in:
@@ -1,29 +1,525 @@
|
||||
package darwin
|
||||
|
||||
foreign import pthread "system:System.framework"
|
||||
foreign import mach "system:System.framework"
|
||||
|
||||
import "core:c"
|
||||
import "base:intrinsics"
|
||||
|
||||
// NOTE(tetra): Unclear whether these should be aligned 16 or not.
|
||||
// However all other sync primitives are aligned for robustness.
|
||||
// I cannot currently align these though.
|
||||
// See core/sys/unix/pthread_linux.odin/pthread_t.
|
||||
task_t :: distinct u64
|
||||
semaphore_t :: distinct u64
|
||||
kern_return_t :: distinct c.int
|
||||
|
||||
kern_return_t :: distinct u64
|
||||
thread_act_t :: distinct u64
|
||||
mach_port_t :: distinct c.uint
|
||||
vm_map_t :: mach_port_t
|
||||
mem_entry_name_port_t :: mach_port_t
|
||||
ipc_space_t :: mach_port_t
|
||||
thread_t :: mach_port_t
|
||||
task_t :: mach_port_t
|
||||
semaphore_t :: mach_port_t
|
||||
|
||||
vm_size_t :: distinct c.uintptr_t
|
||||
|
||||
vm_address_t :: vm_offset_t
|
||||
vm_offset_t :: distinct c.uintptr_t
|
||||
|
||||
// NOTE(beau): typedefed to int in the original headers
|
||||
boolean_t :: b32
|
||||
|
||||
vm_prot_t :: distinct c.int
|
||||
|
||||
vm_inherit_t :: distinct c.uint
|
||||
|
||||
mach_port_name_t :: distinct c.uint
|
||||
|
||||
sync_policy_t :: distinct c.int
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign pthread {
|
||||
mach_task_self :: proc() -> task_t ---
|
||||
foreign mach {
|
||||
mach_task_self :: proc() -> mach_port_t ---
|
||||
|
||||
semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy, value: c.int) -> kern_return_t ---
|
||||
semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> kern_return_t ---
|
||||
semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return ---
|
||||
semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return ---
|
||||
|
||||
semaphore_signal :: proc(semaphore: semaphore_t) -> kern_return_t ---
|
||||
semaphore_signal_all :: proc(semaphore: semaphore_t) -> kern_return_t ---
|
||||
semaphore_signal_thread :: proc(semaphore: semaphore_t, thread: thread_act_t) -> kern_return_t ---
|
||||
|
||||
semaphore_wait :: proc(semaphore: semaphore_t) -> kern_return_t ---
|
||||
semaphore_signal :: proc(semaphore: semaphore_t) -> Kern_Return ---
|
||||
semaphore_signal_all :: proc(semaphore: semaphore_t) -> Kern_Return ---
|
||||
semaphore_signal_thread :: proc(semaphore: semaphore_t, thread: thread_t) -> Kern_Return ---
|
||||
|
||||
semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return ---
|
||||
|
||||
vm_allocate :: proc (target_task : vm_map_t, address: ^vm_address_t, size: vm_size_t, flags: VM_Flags) -> Kern_Return ---
|
||||
|
||||
vm_deallocate :: proc(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) -> Kern_Return ---
|
||||
|
||||
vm_map :: proc(
|
||||
target_task: vm_map_t,
|
||||
address: ^vm_address_t,
|
||||
size: vm_size_t,
|
||||
mask: vm_address_t,
|
||||
flags: VM_Flags,
|
||||
object: mem_entry_name_port_t,
|
||||
offset: vm_offset_t,
|
||||
copy: boolean_t,
|
||||
cur_protection,
|
||||
max_protection: VM_Prot_Flags,
|
||||
inheritance: VM_Inherit,
|
||||
) -> Kern_Return ---
|
||||
|
||||
mach_make_memory_entry :: proc(
|
||||
target_task: vm_map_t,
|
||||
size: ^vm_size_t,
|
||||
offset: vm_offset_t,
|
||||
permission: VM_Prot_Flags,
|
||||
object_handle: ^mem_entry_name_port_t,
|
||||
parent_entry: mem_entry_name_port_t,
|
||||
) -> Kern_Return ---
|
||||
|
||||
mach_port_deallocate :: proc(
|
||||
task: ipc_space_t,
|
||||
name: mach_port_name_t,
|
||||
) -> Kern_Return ---
|
||||
|
||||
vm_page_size: vm_size_t
|
||||
}
|
||||
|
||||
Kern_Return :: enum kern_return_t {
|
||||
Success,
|
||||
|
||||
/* Specified address is not currently valid.
|
||||
*/
|
||||
Invalid_Address,
|
||||
|
||||
/* Specified memory is valid, but does not permit the
|
||||
* required forms of access.
|
||||
*/
|
||||
Protection_Failure,
|
||||
|
||||
/* The address range specified is already in use, or
|
||||
* no address range of the size specified could be
|
||||
* found.
|
||||
*/
|
||||
No_Space,
|
||||
|
||||
/* The function requested was not applicable to this
|
||||
* type of argument, or an argument is invalid
|
||||
*/
|
||||
Invalid_Argument,
|
||||
|
||||
/* The function could not be performed. A catch-all.
|
||||
*/
|
||||
Failure,
|
||||
|
||||
/* A system resource could not be allocated to fulfill
|
||||
* this request. This failure may not be permanent.
|
||||
*/
|
||||
Resource_Shortage,
|
||||
|
||||
/* The task in question does not hold receive rights
|
||||
* for the port argument.
|
||||
*/
|
||||
Not_Receiver,
|
||||
|
||||
/* Bogus access restriction.
|
||||
*/
|
||||
No_Access,
|
||||
|
||||
/* During a page fault, the target address refers to a
|
||||
* memory object that has been destroyed. This
|
||||
* failure is permanent.
|
||||
*/
|
||||
Memory_Failure,
|
||||
|
||||
/* During a page fault, the memory object indicated
|
||||
* that the data could not be returned. This failure
|
||||
* may be temporary; future attempts to access this
|
||||
* same data may succeed, as defined by the memory
|
||||
* object.
|
||||
*/
|
||||
Memory_Error,
|
||||
|
||||
/* The receive right is already a member of the portset.
|
||||
*/
|
||||
Already_In_Set,
|
||||
|
||||
/* The receive right is not a member of a port set.
|
||||
*/
|
||||
Not_In_Set,
|
||||
|
||||
/* The name already denotes a right in the task.
|
||||
*/
|
||||
Name_Exists,
|
||||
|
||||
/* The operation was aborted. Ipc code will
|
||||
* catch this and reflect it as a message error.
|
||||
*/
|
||||
Aborted,
|
||||
|
||||
/* The name doesn't denote a right in the task.
|
||||
*/
|
||||
Invalid_Name,
|
||||
|
||||
/* Target task isn't an active task.
|
||||
*/
|
||||
Invalid_Task,
|
||||
|
||||
/* The name denotes a right, but not an appropriate right.
|
||||
*/
|
||||
Invalid_Right,
|
||||
|
||||
/* A blatant range error.
|
||||
*/
|
||||
Invalid_Value,
|
||||
|
||||
/* Operation would overflow limit on user-references.
|
||||
*/
|
||||
URefs_Overflow,
|
||||
|
||||
/* The supplied (port) capability is improper.
|
||||
*/
|
||||
Invalid_Capability,
|
||||
|
||||
/* The task already has send or receive rights
|
||||
* for the port under another name.
|
||||
*/
|
||||
Right_Exists,
|
||||
|
||||
/* Target host isn't actually a host.
|
||||
*/
|
||||
Invalid_Host,
|
||||
|
||||
/* An attempt was made to supply "precious" data
|
||||
* for memory that is already present in a
|
||||
* memory object.
|
||||
*/
|
||||
Memory_Present,
|
||||
|
||||
/* A page was requested of a memory manager via
|
||||
* memory_object_data_request for an object using
|
||||
* a MEMORY_OBJECT_COPY_CALL strategy, with the
|
||||
* VM_PROT_WANTS_COPY flag being used to specify
|
||||
* that the page desired is for a copy of the
|
||||
* object, and the memory manager has detected
|
||||
* the page was pushed into a copy of the object
|
||||
* while the kernel was walking the shadow chain
|
||||
* from the copy to the object. This error code
|
||||
* is delivered via memory_object_data_error
|
||||
* and is handled by the kernel (it forces the
|
||||
* kernel to restart the fault). It will not be
|
||||
* seen by users.
|
||||
*/
|
||||
Memory_Data_Moved,
|
||||
|
||||
/* A strategic copy was attempted of an object
|
||||
* upon which a quicker copy is now possible.
|
||||
* The caller should retry the copy using
|
||||
* vm_object_copy_quickly. This error code
|
||||
* is seen only by the kernel.
|
||||
*/
|
||||
Memory_Restart_Copy,
|
||||
|
||||
/* An argument applied to assert processor set privilege
|
||||
* was not a processor set control port.
|
||||
*/
|
||||
Invalid_Processor_Set,
|
||||
|
||||
/* The specified scheduling attributes exceed the thread's
|
||||
* limits.
|
||||
*/
|
||||
Policy_Limit,
|
||||
|
||||
/* The specified scheduling policy is not currently
|
||||
* enabled for the processor set.
|
||||
*/
|
||||
Invalid_Policy,
|
||||
|
||||
/* The external memory manager failed to initialize the
|
||||
* memory object.
|
||||
*/
|
||||
Invalid_Object,
|
||||
|
||||
/* A thread is attempting to wait for an event for which
|
||||
* there is already a waiting thread.
|
||||
*/
|
||||
Already_Waiting,
|
||||
|
||||
/* An attempt was made to destroy the default processor
|
||||
* set.
|
||||
*/
|
||||
Default_Set,
|
||||
|
||||
/* An attempt was made to fetch an exception port that is
|
||||
* protected, or to abort a thread while processing a
|
||||
* protected exception.
|
||||
*/
|
||||
Exception_Protected,
|
||||
|
||||
/* A ledger was required but not supplied.
|
||||
*/
|
||||
Invalid_Ledger,
|
||||
|
||||
/* The port was not a memory cache control port.
|
||||
*/
|
||||
Invalid_Memory_Control,
|
||||
|
||||
/* An argument supplied to assert security privilege
|
||||
* was not a host security port.
|
||||
*/
|
||||
Invalid_Security,
|
||||
|
||||
/* thread_depress_abort was called on a thread which
|
||||
* was not currently depressed.
|
||||
*/
|
||||
Not_Depressed,
|
||||
|
||||
/* Object has been terminated and is no longer available
|
||||
*/
|
||||
Terminated,
|
||||
|
||||
/* Lock set has been destroyed and is no longer available.
|
||||
*/
|
||||
Lock_Set_Destroyed,
|
||||
|
||||
/* The thread holding the lock terminated before releasing
|
||||
* the lock
|
||||
*/
|
||||
Lock_Unstable,
|
||||
|
||||
/* The lock is already owned by another thread
|
||||
*/
|
||||
Lock_Owned,
|
||||
|
||||
/* The lock is already owned by the calling thread
|
||||
*/
|
||||
Lock_Owned_Self,
|
||||
|
||||
/* Semaphore has been destroyed and is no longer available.
|
||||
*/
|
||||
Semaphore_Destroyed,
|
||||
|
||||
/* Return from RPC indicating the target server was
|
||||
* terminated before it successfully replied
|
||||
*/
|
||||
Rpc_Server_Terminated,
|
||||
|
||||
/* Terminate an orphaned activation.
|
||||
*/
|
||||
RPC_Terminate_Orphan,
|
||||
|
||||
/* Allow an orphaned activation to continue executing.
|
||||
*/
|
||||
RPC_Continue_Orphan,
|
||||
|
||||
/* Empty thread activation (No thread linked to it)
|
||||
*/
|
||||
Not_Supported,
|
||||
|
||||
/* Remote node down or inaccessible.
|
||||
*/
|
||||
Node_Down,
|
||||
|
||||
/* A signalled thread was not actually waiting. */
|
||||
Not_Waiting,
|
||||
|
||||
/* Some thread-oriented operation (semaphore_wait) timed out
|
||||
*/
|
||||
Operation_Timed_Out,
|
||||
|
||||
/* During a page fault, indicates that the page was rejected
|
||||
* as a result of a signature check.
|
||||
*/
|
||||
Codesign_Error,
|
||||
|
||||
/* The requested property cannot be changed at this time.
|
||||
*/
|
||||
Policy_Static,
|
||||
|
||||
/* The provided buffer is of insufficient size for the requested data.
|
||||
*/
|
||||
Insufficient_Buffer_Size,
|
||||
|
||||
/* Denied by security policy
|
||||
*/
|
||||
Denied,
|
||||
|
||||
/* The KC on which the function is operating is missing
|
||||
*/
|
||||
Missing_KC,
|
||||
|
||||
/* The KC on which the function is operating is invalid
|
||||
*/
|
||||
Invalid_KC,
|
||||
|
||||
/* A search or query operation did not return a result
|
||||
*/
|
||||
Not_Found,
|
||||
|
||||
/* Maximum return value allowable
|
||||
*/
|
||||
Return_Max = 0x100,
|
||||
}
|
||||
|
||||
/*
|
||||
* VM allocation flags:
|
||||
*
|
||||
* VM_FLAGS_FIXED
|
||||
* (really the absence of VM_FLAGS_ANYWHERE)
|
||||
* Allocate new VM region at the specified virtual address, if possible.
|
||||
*
|
||||
* VM_FLAGS_ANYWHERE
|
||||
* Allocate new VM region anywhere it would fit in the address space.
|
||||
*
|
||||
* VM_FLAGS_PURGABLE
|
||||
* Create a purgable VM object for that new VM region.
|
||||
*
|
||||
* VM_FLAGS_4GB_CHUNK
|
||||
* The new VM region will be chunked up into 4GB sized pieces.
|
||||
*
|
||||
* VM_FLAGS_NO_PMAP_CHECK
|
||||
* (for DEBUG kernel config only, ignored for other configs)
|
||||
* Do not check that there is no stale pmap mapping for the new VM region.
|
||||
* This is useful for kernel memory allocations at bootstrap when building
|
||||
* the initial kernel address space while some memory is already in use.
|
||||
*
|
||||
* VM_FLAGS_OVERWRITE
|
||||
* The new VM region can replace existing VM regions if necessary
|
||||
* (to be used in combination with VM_FLAGS_FIXED).
|
||||
*
|
||||
* VM_FLAGS_NO_CACHE
|
||||
* Pages brought in to this VM region are placed on the speculative
|
||||
* queue instead of the active queue. In other words, they are not
|
||||
* cached so that they will be stolen first if memory runs low.
|
||||
*/
|
||||
|
||||
@(private="file")
|
||||
LOG2 :: intrinsics.constant_log2
|
||||
|
||||
VM_Flag :: enum c.int {
|
||||
Anywhere,
|
||||
Purgable,
|
||||
_4GB_Chunk,
|
||||
Random_Addr,
|
||||
No_Cache,
|
||||
Resilient_Codesign,
|
||||
Resilient_Media,
|
||||
Permanent,
|
||||
|
||||
// NOTE(beau): log 2 of the bit we want in the bit set so we get that bit in
|
||||
// the bit set
|
||||
|
||||
TPRO = LOG2(0x1000),
|
||||
Overwrite = LOG2(0x4000),/* delete any existing mappings first */
|
||||
|
||||
Superpage_Size_Any = LOG2(0x10000),
|
||||
Superpage_Size_2MB = LOG2(0x20000),
|
||||
__Superpage3 = LOG2(0x40000),
|
||||
|
||||
Return_Data_Addr = LOG2(0x100000),
|
||||
Return_4K_Data_Addr = LOG2(0x800000),
|
||||
|
||||
Alias_Mask1 = 24,
|
||||
Alias_Mask2,
|
||||
Alias_Mask3,
|
||||
Alias_Mask4,
|
||||
Alias_Mask5,
|
||||
Alias_Mask6,
|
||||
Alias_Mask7,
|
||||
Alias_Mask8,
|
||||
}
|
||||
|
||||
VM_Flags :: distinct bit_set[VM_Flag; c.int]
|
||||
VM_FLAGS_FIXED :: VM_Flags{}
|
||||
|
||||
/*
|
||||
* VM_FLAGS_SUPERPAGE_MASK
|
||||
* 3 bits that specify whether large pages should be used instead of
|
||||
* base pages (!=0), as well as the requested page size.
|
||||
*/
|
||||
VM_FLAGS_SUPERPAGE_MASK :: VM_Flags {
|
||||
.Superpage_Size_Any,
|
||||
.Superpage_Size_2MB,
|
||||
.__Superpage3,
|
||||
}
|
||||
|
||||
// 0xFF000000
|
||||
VM_FLAGS_ALIAS_MASK :: VM_Flags {
|
||||
.Alias_Mask1,
|
||||
.Alias_Mask2,
|
||||
.Alias_Mask3,
|
||||
.Alias_Mask4,
|
||||
.Alias_Mask5,
|
||||
.Alias_Mask6,
|
||||
.Alias_Mask7,
|
||||
.Alias_Mask8,
|
||||
}
|
||||
|
||||
VM_GET_FLAGS_ALIAS :: proc(flags: VM_Flags) -> c.int {
|
||||
return transmute(c.int)(flags & VM_FLAGS_ALIAS_MASK) >> 24
|
||||
}
|
||||
// NOTE(beau): no need for VM_SET_FLAGS_ALIAS, just mask in things from
|
||||
// VM_Flag.Alias_Mask*
|
||||
|
||||
VM_FLAG_HW :: VM_Flag.TPRO
|
||||
VM_FLAGS_HW :: VM_Flags{VM_FLAG_HW}
|
||||
|
||||
/* These are the flags that we accept from user-space */
|
||||
VM_FLAGS_USER_ALLOCATE :: VM_Flags {
|
||||
.Anywhere,
|
||||
.Purgable,
|
||||
._4GB_Chunk,
|
||||
.Random_Addr,
|
||||
.No_Cache,
|
||||
.Permanent,
|
||||
.Overwrite,
|
||||
} | VM_FLAGS_FIXED | VM_FLAGS_SUPERPAGE_MASK | VM_FLAGS_ALIAS_MASK | VM_FLAGS_HW
|
||||
|
||||
VM_FLAGS_USER_MAP :: VM_Flags {
|
||||
.Return_4K_Data_Addr,
|
||||
.Return_Data_Addr,
|
||||
} | VM_FLAGS_USER_ALLOCATE
|
||||
|
||||
VM_FLAGS_USER_REMAP :: VM_Flags {
|
||||
.Anywhere,
|
||||
.Random_Addr,
|
||||
.Overwrite,
|
||||
.Return_Data_Addr,
|
||||
.Resilient_Codesign,
|
||||
.Resilient_Media,
|
||||
} | VM_FLAGS_FIXED
|
||||
|
||||
VM_FLAGS_SUPERPAGE_NONE :: VM_Flags{} /* no superpages, if all bits are 0 */
|
||||
|
||||
/*
|
||||
* Protection values, defined as bits within the vm_prot_t type
|
||||
*/
|
||||
|
||||
VM_Prot :: enum vm_prot_t {
|
||||
Read,
|
||||
Write,
|
||||
Execute,
|
||||
}
|
||||
|
||||
VM_Prot_Flags :: distinct bit_set[VM_Prot; vm_prot_t]
|
||||
|
||||
VM_PROT_NONE :: VM_Prot_Flags{}
|
||||
VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write}
|
||||
VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute}
|
||||
|
||||
/*
|
||||
* Enumeration of valid values for vm_inherit_t.
|
||||
*/
|
||||
|
||||
VM_Inherit :: enum vm_inherit_t {
|
||||
Share,
|
||||
Copy,
|
||||
None,
|
||||
Donate_Copy,
|
||||
}
|
||||
|
||||
VM_INHERIT_DEFAULT :: VM_Inherit.Copy
|
||||
VM_INHERIT_LAST_VALID :: VM_Inherit.None
|
||||
|
||||
Sync_Policy :: enum sync_policy_t {
|
||||
Fifo,
|
||||
Fixed_Priority,
|
||||
Reversed,
|
||||
Order_Mask,
|
||||
}
|
||||
|
||||
SYNC_POLICY_LIFO :: Sync_Policy.Fifo | Sync_Policy.Reversed
|
||||
|
||||
Reference in New Issue
Block a user