mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-29 15:15:08 +00:00
846 lines
20 KiB
Odin
846 lines
20 KiB
Odin
package darwin
|
|
|
|
foreign import mach "system:System"
|
|
|
|
import "core:c"
|
|
import "base:intrinsics"
|
|
|
|
mach_port_t :: distinct c.uint
|
|
task_t :: mach_port_t
|
|
|
|
semaphore_t :: distinct u64
|
|
|
|
kern_return_t :: distinct c.int
|
|
thread_act_t :: distinct u32
|
|
thread_state_t :: distinct ^u32
|
|
thread_list_t :: [^]thread_act_t
|
|
vm_region_recurse_info_t :: distinct ^i32
|
|
task_info_t :: distinct ^i32
|
|
|
|
MACH_PORT_NULL :: 0
|
|
MACH_PORT_DEAD :: ~mach_port_t(0)
|
|
|
|
MACH_MSG_PORT_DESCRIPTOR :: 0
|
|
|
|
X86_THREAD_STATE32 :: 1
|
|
X86_THREAD_STATE64 :: 4
|
|
ARM_THREAD_STATE64 :: 6
|
|
|
|
mach_msg_option_t :: distinct i32
|
|
name_t :: distinct cstring
|
|
|
|
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
|
|
|
|
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
|
|
|
|
mach_port_right_t :: distinct c.uint
|
|
|
|
sync_policy_t :: distinct c.int
|
|
|
|
mach_msg_port_descriptor_t :: struct {
|
|
name: mach_port_t,
|
|
_: u32,
|
|
using _: bit_field u32 {
|
|
_: u32 | 16,
|
|
disposition: u32 | 8,
|
|
type: u32 | 8,
|
|
},
|
|
}
|
|
|
|
Task_Port_Type :: enum u32 {
|
|
Kernel = 1,
|
|
Host,
|
|
Name,
|
|
Bootstrap,
|
|
Seatbelt = 7,
|
|
Access = 9,
|
|
}
|
|
|
|
Bootstrap_Error :: enum u32 {
|
|
Success,
|
|
Not_Privileged = 1100,
|
|
Name_In_Use = 1101,
|
|
Unknown_Service = 1102,
|
|
Service_Active = 1103,
|
|
Bad_Count = 1104,
|
|
No_Memory = 1105,
|
|
No_Children = 1106,
|
|
}
|
|
|
|
Msg_Type :: enum u32 {
|
|
Unstructured = 0,
|
|
Bit = 0,
|
|
Boolean = 0,
|
|
Integer_16 = 1,
|
|
Integer_32 = 2,
|
|
Char = 8,
|
|
Byte = 9,
|
|
Integer_8 = 9,
|
|
Real = 10,
|
|
Integer_64 = 11,
|
|
String = 12,
|
|
String_C = 12,
|
|
|
|
Port_Name = 15,
|
|
|
|
Move_Receive = 16,
|
|
Port_Receive = 16,
|
|
Move_Send = 17,
|
|
Port_Send = 17,
|
|
Move_Send_Once = 18,
|
|
Port_Send_Once = 18,
|
|
Copy_Send = 19,
|
|
Make_Send = 20,
|
|
Make_Send_Once = 21,
|
|
}
|
|
|
|
Msg_Header_Bits :: enum u32 {
|
|
Zero = 0,
|
|
Remote_Mask = 0xff,
|
|
Local_Mask = 0xff00,
|
|
Migrated = 0x08000000,
|
|
Unused = 0x07ff0000,
|
|
Complex_Data = 0x10000000,
|
|
Complex_Ports = 0x20000000,
|
|
Circular = 0x40000000,
|
|
Complex = 0x80000000,
|
|
}
|
|
|
|
mach_msg_type_t :: struct {
|
|
using _: bit_field u32 {
|
|
name: u32 | 8,
|
|
size: u32 | 8,
|
|
number: u32 | 12,
|
|
inline: u32 | 1,
|
|
longform: u32 | 1,
|
|
deallocate: u32 | 1,
|
|
unused: u32 | 1,
|
|
},
|
|
}
|
|
|
|
mach_msg_header_t :: struct {
|
|
msgh_bits: u32,
|
|
msgh_size: u32,
|
|
msgh_remote_port: mach_port_t,
|
|
msgh_local_port: mach_port_t,
|
|
msgh_voucher_port: u32,
|
|
msgh_id: i32,
|
|
}
|
|
|
|
mach_msg_body_t :: struct {
|
|
msgh_descriptor_count: u32,
|
|
}
|
|
|
|
mach_msg_trailer_t :: struct {
|
|
msgh_trailer_type: u32,
|
|
msgh_trailer_size: u32,
|
|
}
|
|
|
|
x86_thread_state32_t :: struct {
|
|
eax: u32,
|
|
ebx: u32,
|
|
ecx: u32,
|
|
edx: u32,
|
|
edi: u32,
|
|
esi: u32,
|
|
ebp: u32,
|
|
esp: u32,
|
|
ss: u32,
|
|
eflags: u32,
|
|
eip: u32,
|
|
cs: u32,
|
|
ds: u32,
|
|
es: u32,
|
|
fs: u32,
|
|
gs: u32,
|
|
}
|
|
X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32)
|
|
|
|
x86_thread_state64_t :: struct #packed {
|
|
rax: u64,
|
|
rbx: u64,
|
|
rcx: u64,
|
|
rdx: u64,
|
|
rdi: u64,
|
|
rsi: u64,
|
|
rbp: u64,
|
|
rsp: u64,
|
|
r8: u64,
|
|
r9: u64,
|
|
r10: u64,
|
|
r11: u64,
|
|
r12: u64,
|
|
r13: u64,
|
|
r14: u64,
|
|
r15: u64,
|
|
rip: u64,
|
|
rflags: u64,
|
|
cs: u64,
|
|
fs: u64,
|
|
gs: u64,
|
|
}
|
|
X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32)
|
|
|
|
arm_thread_state64_t :: struct #packed {
|
|
x: [29]u64,
|
|
fp: u64,
|
|
lr: u64,
|
|
sp: u64,
|
|
pc: u64,
|
|
cpsr: u32,
|
|
pad: u32,
|
|
}
|
|
ARM_THREAD_STATE64_COUNT :: size_of(arm_thread_state64_t) / size_of(u32)
|
|
|
|
THREAD_IDENTIFIER_INFO :: 4
|
|
thread_identifier_info :: struct {
|
|
thread_id: u64,
|
|
thread_handler: u64,
|
|
dispatch_qaddr: u64,
|
|
}
|
|
THREAD_IDENTIFIER_INFO_COUNT :: size_of(thread_identifier_info) / size_of(u32)
|
|
|
|
vm_region_submap_info_64 :: struct {
|
|
protection: u32,
|
|
max_protection: u32,
|
|
inheritance: u32,
|
|
offset: u64,
|
|
user_tag: u32,
|
|
pages_residept: u32,
|
|
pages_shared_now_private: u32,
|
|
pages_swapped_out: u32,
|
|
pages_dirtied: u32,
|
|
ref_count: u32,
|
|
shadow_depth: u16,
|
|
external_pager: u8,
|
|
share_mode: u8,
|
|
is_submap: b32,
|
|
behavior: i32,
|
|
object_id: u32,
|
|
user_wired_count: u16,
|
|
pages_reusable: u32,
|
|
}
|
|
VM_REGION_SUBMAP_INFO_COUNT_64 :: size_of(vm_region_submap_info_64) / size_of(u32)
|
|
|
|
TASK_DYLD_INFO :: 17
|
|
task_dyld_info :: struct {
|
|
all_image_info_addr: u64,
|
|
all_image_info_size: u64,
|
|
all_image_info_format: i32,
|
|
}
|
|
TASK_DYLD_INFO_COUNT :: size_of(task_dyld_info) / size_of(u32)
|
|
|
|
dyld_image_info :: struct {
|
|
image_load_addr: u64,
|
|
image_file_path: cstring,
|
|
image_file_mod_date: u64,
|
|
}
|
|
|
|
dyld_uuid_info :: struct {
|
|
image_load_addr: u64,
|
|
image_uuid: [16]u8,
|
|
}
|
|
|
|
dyld_all_image_infos :: struct {
|
|
version: u32,
|
|
info_array_count: u32,
|
|
info_array: rawptr,
|
|
notification: rawptr,
|
|
process_detached_from_shared_region: b32,
|
|
libSystem_initialized: b32,
|
|
dyld_image_load_addr: u64,
|
|
jit_info: rawptr,
|
|
dyld_version: cstring,
|
|
error_message: cstring,
|
|
termination_flags: u64,
|
|
core_symbolication_shm_page: rawptr,
|
|
system_order_flag: u64,
|
|
uuid_array_count: u64,
|
|
uuid_array: rawptr,
|
|
dyld_all_image_infos_addr: u64,
|
|
initial_image_count: u64,
|
|
error_kind: u64,
|
|
error_client_of_dylib_path: cstring,
|
|
error_target_dylib_path: cstring,
|
|
error_symbol: cstring,
|
|
shared_cache_slide: u64,
|
|
shared_cache_uuid: [16]u8,
|
|
shared_cache_base_addr: u64,
|
|
info_array_change_timestamp: u64,
|
|
dyld_path: cstring,
|
|
notify_ports: [8]mach_port_t,
|
|
reserved: [7]u64,
|
|
shared_cache_fsid: u64,
|
|
shared_cache_fsobjid: u64,
|
|
compact_dyld_image_info_addr: u64,
|
|
compact_dyld_image_info_size: u64,
|
|
platform: u32,
|
|
aot_info_count: u32,
|
|
aot_info_array: rawptr,
|
|
aot_info_array_change_timestamp: u64,
|
|
aot_shared_cache_base_address: u64,
|
|
aot_shared_cache_uuid: [16]u8,
|
|
}
|
|
|
|
|
|
@(default_calling_convention="c")
|
|
foreign mach {
|
|
mach_task_self :: proc() -> mach_port_t ---
|
|
mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> Kern_Return ---
|
|
mach_msg_send :: proc(header: rawptr) -> Kern_Return ---
|
|
mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> Kern_Return ---
|
|
mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> Kern_Return ---
|
|
mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> Kern_Return ---
|
|
mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> Kern_Return ---
|
|
vm_page_size: u64
|
|
vm_page_mask: u64
|
|
vm_page_shift: i32
|
|
|
|
mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> Kern_Return ---
|
|
mach_port_deallocate :: proc(task: task_t, name: u32) -> Kern_Return ---
|
|
mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> Kern_Return ---
|
|
|
|
task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> Kern_Return ---
|
|
task_suspend :: proc(task: task_t) -> Kern_Return ---
|
|
task_resume :: proc(task: task_t) -> Kern_Return ---
|
|
task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> Kern_Return ---
|
|
task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> Kern_Return ---
|
|
task_terminate :: proc(task: task_t) -> Kern_Return ---
|
|
|
|
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 ---
|
|
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 ---
|
|
|
|
thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> Kern_Return ---
|
|
thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> Kern_Return ---
|
|
|
|
bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> Kern_Return ---
|
|
bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_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 ---
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
HW = TPRO,
|
|
}
|
|
|
|
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*
|
|
|
|
/* 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_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}
|
|
|
|
/*
|
|
* Mach msg options, defined as bits within the mach_msg_option_t type
|
|
*/
|
|
|
|
Msg_Option :: enum mach_msg_option_t {
|
|
Send_Msg,
|
|
Receive_Msg,
|
|
|
|
Send_Timeout = LOG2(0x10),
|
|
Send_Notify = LOG2(0x20),
|
|
Send_Interrupt = LOG2(0x40),
|
|
Send_Cancel = LOG2(0x80),
|
|
Receive_Timeout = LOG2(0x100),
|
|
Receive_Notify = LOG2(0x200),
|
|
Receive_Interrupt = LOG2(0x400),
|
|
Receive_Large = LOG2(0x800),
|
|
Send_Always = LOG2(0x10000),
|
|
}
|
|
|
|
Msg_Option_Flags :: distinct bit_set[Msg_Option; mach_msg_option_t]
|
|
|
|
/*
|
|
* Enumeration of valid values for mach_port_right_t
|
|
*/
|
|
|
|
Port_Right :: enum mach_port_right_t {
|
|
Send,
|
|
Receive,
|
|
Send_Once,
|
|
Port_Set,
|
|
Dead_Name,
|
|
}
|
|
|
|
/*
|
|
* Enumeration of valid values for vm_inherit_t.
|
|
*/
|
|
|
|
VM_Inherit :: enum vm_inherit_t {
|
|
Share,
|
|
Copy,
|
|
None,
|
|
Donate_Copy,
|
|
|
|
Default = Copy,
|
|
Last_Valid = None,
|
|
}
|
|
|
|
Sync_Policy :: enum sync_policy_t {
|
|
Fifo,
|
|
Fixed_Priority,
|
|
Reversed,
|
|
Order_Mask,
|
|
|
|
Lifo = Fifo | Reversed,
|
|
}
|
|
|
|
mach_vm_trunc_page :: proc(v: u64) -> u64 {
|
|
return v & ~vm_page_mask
|
|
}
|