12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022 |
- /*
- * Mach Operating System
- * Copyright (c) 1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- #include <glue/gnulinux.h>
- #include <linux/printk.h>
- #include <linux/uaccess.h>
- #include <mach/boolean.h>
- #include <mach/port.h>
- #include <mach/message.h>
- #include <mach/thread_status.h>
- #include <kern/ast.h>
- #include <kern/debug.h>
- #include <kern/ipc_tt.h>
- #include <kern/syscall_subr.h>
- #include <kern/thread.h>
- #include <kern/task.h>
- #include <kern/ipc_kobject.h>
- #include <kern/ipc_tt.h>
- #include <kern/ipc_mig.h>
- #include <vm/vm_map.h>
- #include <vm/vm_user.h>
- #include <ipc/port.h>
- #include <ipc/ipc_kmsg.h>
- #include <ipc/ipc_entry.h>
- #include <ipc/ipc_object.h>
- #include <ipc/ipc_mqueue.h>
- #include <ipc/ipc_space.h>
- #include <ipc/ipc_port.h>
- #include <ipc/ipc_pset.h>
- #include <ipc/ipc_thread.h>
- #include <ipc/mach_port.h>
- #include <device/dev_hdr.h>
- #include <device/device_types.h>
- #include <device/ds_routines.h>
- #if 0
- /*
- * Routine: mach_msg_send_from_kernel
- * Purpose:
- * Send a message from the kernel.
- *
- * This is used by the client side of KernelUser interfaces
- * to implement SimpleRoutines. Currently, this includes
- * device_reply and memory_object messages.
- * Conditions:
- * Nothing locked.
- * Returns:
- * MACH_MSG_SUCCESS Sent the message.
- * MACH_SEND_INVALID_DATA Bad destination port.
- */
- mach_msg_return_t
- mach_msg_send_from_kernel(
- mach_msg_header_t *msg,
- mach_msg_size_t send_size)
- {
- ipc_kmsg_t kmsg;
- mach_msg_return_t mr;
- if (!MACH_PORT_VALID(msg->msgh_remote_port))
- return MACH_SEND_INVALID_DEST;
- mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
- if (mr != MACH_MSG_SUCCESS)
- panic("mach_msg_send_from_kernel");
- ipc_kmsg_copyin_from_kernel(kmsg);
- ipc_mqueue_send_always(kmsg);
- return MACH_MSG_SUCCESS;
- }
- mach_msg_return_t
- mach_msg_rpc_from_kernel(msg, send_size, reply_size)
- const mach_msg_header_t *msg;
- mach_msg_size_t send_size;
- mach_msg_size_t reply_size;
- {
- panic("mach_msg_rpc_from_kernel"); /*XXX*/
- }
- /*
- * Routine: mach_msg_abort_rpc
- * Purpose:
- * Destroy the thread's ith_rpc_reply port.
- * This will interrupt a mach_msg_rpc_from_kernel
- * with a MACH_RCV_PORT_DIED return code.
- * Conditions:
- * Nothing locked.
- */
- void
- mach_msg_abort_rpc(ipc_thread_t thread)
- {
- ipc_port_t reply = IP_NULL;
- ith_lock(thread);
- if (thread->ith_self != IP_NULL) {
- reply = thread->ith_rpc_reply;
- thread->ith_rpc_reply = IP_NULL;
- }
- ith_unlock(thread);
- if (reply != IP_NULL)
- ipc_port_dealloc_reply(reply);
- }
- /*
- * Routine: mach_msg
- * Purpose:
- * Like mach_msg_trap except that message buffers
- * live in kernel space. Doesn't handle any options.
- *
- * This is used by in-kernel server threads to make
- * kernel calls, to receive request messages, and
- * to send reply messages.
- * Conditions:
- * Nothing locked.
- * Returns:
- */
- mach_msg_return_t
- mach_msg(
- mach_msg_header_t *msg,
- mach_msg_option_t option,
- mach_msg_size_t send_size,
- mach_msg_size_t rcv_size,
- mach_port_t rcv_name,
- mach_msg_timeout_t time_out,
- mach_port_t notify)
- {
- ipc_space_t space = current_space();
- vm_map_t map = current_map();
- ipc_kmsg_t kmsg;
- mach_port_seqno_t seqno;
- mach_msg_return_t mr;
- if (option & MACH_SEND_MSG) {
- mr = ipc_kmsg_get_from_kernel(msg, send_size, &kmsg);
- if (mr != MACH_MSG_SUCCESS)
- panic("mach_msg");
- mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
- if (mr != MACH_MSG_SUCCESS) {
- ikm_free(kmsg);
- return mr;
- }
- do
- mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
- MACH_MSG_TIMEOUT_NONE);
- while (mr == MACH_SEND_INTERRUPTED);
- assert(mr == MACH_MSG_SUCCESS);
- }
- if (option & MACH_RCV_MSG) {
- do {
- ipc_object_t object;
- ipc_mqueue_t mqueue;
- mr = ipc_mqueue_copyin(space, rcv_name,
- &mqueue, &object);
- if (mr != MACH_MSG_SUCCESS)
- return mr;
- /* hold ref for object; mqueue is locked */
- mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
- MACH_MSG_SIZE_MAX,
- MACH_MSG_TIMEOUT_NONE,
- FALSE, IMQ_NULL_CONTINUE,
- &kmsg, &seqno);
- /* mqueue is unlocked */
- ipc_object_release(object);
- } while (mr == MACH_RCV_INTERRUPTED);
- if (mr != MACH_MSG_SUCCESS)
- return mr;
- kmsg->ikm_header.msgh_seqno = seqno;
- if (rcv_size < kmsg->ikm_header.msgh_size) {
- ipc_kmsg_copyout_dest(kmsg, space);
- ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
- return MACH_RCV_TOO_LARGE;
- }
- mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
- if (mr != MACH_MSG_SUCCESS) {
- if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
- ipc_kmsg_put_to_kernel(msg, kmsg,
- kmsg->ikm_header.msgh_size);
- } else {
- ipc_kmsg_copyout_dest(kmsg, space);
- ipc_kmsg_put_to_kernel(msg, kmsg, sizeof *msg);
- }
- return mr;
- }
- ipc_kmsg_put_to_kernel(msg, kmsg, kmsg->ikm_header.msgh_size);
- }
- return MACH_MSG_SUCCESS;
- }
- /*
- * Routine: mig_get_reply_port
- * Purpose:
- * Called by client side interfaces living in the kernel
- * to get a reply port. This port is used for
- * mach_msg() calls which are kernel calls.
- */
- mach_port_t
- mig_get_reply_port(void)
- {
- ipc_thread_t self = current_thread();
- if (self->ith_mig_reply == MACH_PORT_NULL)
- self->ith_mig_reply = mach_reply_port();
- return self->ith_mig_reply;
- }
- /*
- * Routine: mig_dealloc_reply_port
- * Purpose:
- * Called by client side interfaces to get rid of a reply port.
- * Shouldn't ever be called inside the kernel, because
- * kernel calls shouldn't prompt Mig to call it.
- */
- void
- mig_dealloc_reply_port(
- mach_port_t reply_port)
- {
- panic("mig_dealloc_reply_port");
- }
- /*
- * Routine: mig_put_reply_port
- * Purpose:
- * Called by client side interfaces after each RPC to
- * let the client recycle the reply port if it wishes.
- */
- void
- mig_put_reply_port(
- mach_port_t reply_port)
- {
- }
- /*
- * mig_strncpy.c - by Joshua Block
- *
- * mig_strncpy -- Bounded string copy. Does what the library routine
- * strncpy does: Copies the (null terminated) string in src into dest,
- * a buffer of length len. Returns the length of the destination
- * string excluding the terminating null.
- *
- * Parameters:
- *
- * dest - Pointer to destination buffer.
- *
- * src - Pointer to source string.
- *
- * len - Length of destination buffer.
- */
- vm_size_t
- mig_strncpy(dest, src, len)
- char *dest;
- const char *src;
- int len;
- {
- char *dest_ = dest;
- int i;
- if (len <= 0)
- return 0;
- for (i = 0; i < len; i++) {
- if (! (*dest = *src))
- break;
- dest++;
- src++;
- }
- return dest - dest_;
- }
- #define fast_send_right_lookup(name, port, abort) \
- MACRO_BEGIN \
- ipc_space_t space = current_space(); \
- ipc_entry_t entry; \
- \
- is_read_lock(space); \
- assert(space->is_active); \
- \
- entry = ipc_entry_lookup (space, name); \
- if (entry == IE_NULL) { \
- is_read_unlock (space); \
- abort; \
- } \
- \
- if (IE_BITS_TYPE (entry->ie_bits) != MACH_PORT_TYPE_SEND) { \
- is_read_unlock (space); \
- abort; \
- } \
- \
- port = (ipc_port_t) entry->ie_object; \
- assert(port != IP_NULL); \
- \
- ip_lock(port); \
- /* can safely unlock space now that port is locked */ \
- is_read_unlock(space); \
- MACRO_END
- device_t
- port_name_to_device(mach_port_t name)
- {
- ipc_port_t port;
- device_t device;
- fast_send_right_lookup(name, port, goto abort);
- /* port is locked */
- /*
- * Now map the port object to a device object.
- * This is an inline version of dev_port_lookup().
- */
- if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
- device = (device_t) port->ip_kobject;
- device_reference(device);
- ip_unlock(port);
- return device;
- }
- ip_unlock(port);
- return DEVICE_NULL;
- /*
- * The slow case. The port wasn't easily accessible.
- */
- abort: {
- ipc_port_t kern_port;
- kern_return_t kr;
- kr = ipc_object_copyin(current_space(), name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &kern_port);
- if (kr != KERN_SUCCESS)
- return DEVICE_NULL;
- device = dev_port_lookup(kern_port);
- if (IP_VALID(kern_port))
- ipc_port_release_send(kern_port);
- return device;
- }
- }
- thread_t
- port_name_to_thread(mach_port_t name)
- {
- ipc_port_t port;
- fast_send_right_lookup(name, port, goto abort);
- /* port is locked */
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_THREAD)) {
- thread_t thread;
- thread = (thread_t) port->ip_kobject;
- assert(thread != THREAD_NULL);
- /* thread referencing is a bit complicated,
- so don't bother to expand inline */
- thread_reference(thread);
- ip_unlock(port);
- return thread;
- }
- ip_unlock(port);
- return THREAD_NULL;
- abort: {
- thread_t thread;
- ipc_port_t kern_port;
- kern_return_t kr;
- kr = ipc_object_copyin(current_space(), name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &kern_port);
- if (kr != KERN_SUCCESS)
- return THREAD_NULL;
- thread = convert_port_to_thread(kern_port);
- if (IP_VALID(kern_port))
- ipc_port_release_send(kern_port);
- return thread;
- }
- }
- task_t
- port_name_to_task(mach_port_t name)
- {
- ipc_port_t port;
- fast_send_right_lookup(name, port, goto abort);
- /* port is locked */
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- task_t task;
- task = (task_t) port->ip_kobject;
- assert(task != TASK_NULL);
- task_lock(task);
- /* can safely unlock port now that task is locked */
- ip_unlock(port);
- task->ref_count++;
- task_unlock(task);
- return task;
- }
- ip_unlock(port);
- return TASK_NULL;
- abort: {
- task_t task;
- ipc_port_t kern_port;
- kern_return_t kr;
- kr = ipc_object_copyin(current_space(), name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &kern_port);
- if (kr != KERN_SUCCESS)
- return TASK_NULL;
- task = convert_port_to_task(kern_port);
- if (IP_VALID(kern_port))
- ipc_port_release_send(kern_port);
- return task;
- }
- }
- vm_map_t
- port_name_to_map(
- mach_port_t name)
- {
- ipc_port_t port;
- fast_send_right_lookup(name, port, goto abort);
- /* port is locked */
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- vm_map_t map;
- map = ((task_t) port->ip_kobject)->map;
- assert(map != VM_MAP_NULL);
- simple_lock(&map->ref_lock);
- /* can safely unlock port now that map is locked */
- ip_unlock(port);
- map->ref_count++;
- simple_unlock(&map->ref_lock);
- return map;
- }
- ip_unlock(port);
- return VM_MAP_NULL;
- abort: {
- vm_map_t map;
- ipc_port_t kern_port;
- kern_return_t kr;
- kr = ipc_object_copyin(current_space(), name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &kern_port);
- if (kr != KERN_SUCCESS)
- return VM_MAP_NULL;
- map = convert_port_to_map(kern_port);
- if (IP_VALID(kern_port))
- ipc_port_release_send(kern_port);
- return map;
- }
- }
- ipc_space_t
- port_name_to_space(mach_port_t name)
- {
- ipc_port_t port;
- fast_send_right_lookup(name, port, goto abort);
- /* port is locked */
- if (ip_active(port) &&
- (ip_kotype(port) == IKOT_TASK)) {
- ipc_space_t space;
- space = ((task_t) port->ip_kobject)->itk_space;
- assert(space != IS_NULL);
- simple_lock(&space->is_ref_lock_data);
- /* can safely unlock port now that space is locked */
- ip_unlock(port);
- space->is_references++;
- simple_unlock(&space->is_ref_lock_data);
- return space;
- }
- ip_unlock(port);
- return IS_NULL;
- abort: {
- ipc_space_t space;
- ipc_port_t kern_port;
- kern_return_t kr;
- kr = ipc_object_copyin(current_space(), name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &kern_port);
- if (kr != KERN_SUCCESS)
- return IS_NULL;
- space = convert_port_to_space(kern_port);
- if (IP_VALID(kern_port))
- ipc_port_release_send(kern_port);
- return space;
- }
- }
- /*
- * Hack to translate a thread port to a thread pointer for calling
- * thread_get_state and thread_set_state. This is only necessary
- * because the IPC message for these two operations overflows the
- * kernel stack.
- *
- * AARGH!
- */
- kern_return_t thread_get_state_KERNEL(
- mach_port_t thread_port, /* port right for thread */
- int flavor,
- thread_state_t old_state, /* pointer to OUT array */
- natural_t *old_state_count) /* IN/OUT */
- {
- thread_t thread;
- kern_return_t result;
- thread = port_name_to_thread(thread_port);
- result = thread_get_state(thread, flavor, old_state, old_state_count);
- thread_deallocate(thread);
- return result;
- }
- kern_return_t thread_set_state_KERNEL(
- mach_port_t thread_port, /* port right for thread */
- int flavor,
- thread_state_t new_state,
- natural_t new_state_count)
- {
- thread_t thread;
- kern_return_t result;
- thread = port_name_to_thread(thread_port);
- result = thread_set_state(thread, flavor, new_state, new_state_count);
- thread_deallocate(thread);
- return result;
- }
- /*
- * Things to keep in mind:
- *
- * The idea here is to duplicate the semantics of the true kernel RPC.
- * The destination port/object should be checked first, before anything
- * that the user might notice (like ipc_object_copyin). Return
- * MACH_SEND_INTERRUPTED if it isn't correct, so that the user stub
- * knows to fall back on an RPC. For other return values, it won't
- * retry with an RPC. The retry might get a different (incorrect) rc.
- * Return values are only set (and should only be set, with copyout)
- * on successful calls.
- */
- kern_return_t
- syscall_vm_map(
- mach_port_t target_map,
- vm_offset_t *address,
- vm_size_t size,
- vm_offset_t mask,
- boolean_t anywhere,
- mach_port_t memory_object,
- vm_offset_t offset,
- boolean_t copy,
- vm_prot_t cur_protection,
- vm_prot_t max_protection,
- vm_inherit_t inheritance)
- {
- vm_map_t map;
- ipc_port_t port;
- vm_offset_t addr;
- kern_return_t result;
- map = port_name_to_map(target_map);
- if (map == VM_MAP_NULL)
- return MACH_SEND_INTERRUPTED;
- if (MACH_PORT_VALID(memory_object)) {
- result = ipc_object_copyin(current_space(), memory_object,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &port);
- if (result != KERN_SUCCESS) {
- vm_map_deallocate(map);
- return result;
- }
- } else
- port = (ipc_port_t) memory_object;
- copyin(address, &addr, sizeof(vm_offset_t));
- result = vm_map(map, &addr, size, mask, anywhere,
- port, offset, copy,
- cur_protection, max_protection, inheritance);
- if (result == KERN_SUCCESS)
- copyout(&addr, address, sizeof(vm_offset_t));
- if (IP_VALID(port))
- ipc_port_release_send(port);
- vm_map_deallocate(map);
- return result;
- }
- kern_return_t syscall_vm_allocate(
- mach_port_t target_map,
- vm_offset_t *address,
- vm_size_t size,
- boolean_t anywhere)
- {
- vm_map_t map;
- vm_offset_t addr;
- kern_return_t result;
- map = port_name_to_map(target_map);
- if (map == VM_MAP_NULL)
- return MACH_SEND_INTERRUPTED;
- copyin(address, &addr, sizeof(vm_offset_t));
- result = vm_allocate(map, &addr, size, anywhere);
- if (result == KERN_SUCCESS)
- copyout(&addr, address, sizeof(vm_offset_t));
- vm_map_deallocate(map);
- return result;
- }
- kern_return_t syscall_vm_deallocate(
- mach_port_t target_map,
- vm_offset_t start,
- vm_size_t size)
- {
- vm_map_t map;
- kern_return_t result;
- map = port_name_to_map(target_map);
- if (map == VM_MAP_NULL)
- return MACH_SEND_INTERRUPTED;
- result = vm_deallocate(map, start, size);
- vm_map_deallocate(map);
- return result;
- }
- kern_return_t syscall_task_create(
- mach_port_t parent_task,
- boolean_t inherit_memory,
- mach_port_t *child_task) /* OUT */
- {
- task_t t, c;
- ipc_port_t port;
- mach_port_t name;
- kern_return_t result;
- t = port_name_to_task(parent_task);
- if (t == TASK_NULL)
- return MACH_SEND_INTERRUPTED;
- result = task_create(t, inherit_memory, &c);
- if (result == KERN_SUCCESS) {
- port = (ipc_port_t) convert_task_to_port(c);
- /* always returns a name, even for non-success return codes */
- (void) ipc_kmsg_copyout_object(current_space(),
- (ipc_object_t) port,
- MACH_MSG_TYPE_PORT_SEND, &name);
- copyout(&name, child_task,
- sizeof(mach_port_t));
- }
- task_deallocate(t);
- return result;
- }
- kern_return_t syscall_task_terminate(mach_port_t task)
- {
- task_t t;
- kern_return_t result;
- t = port_name_to_task(task);
- if (t == TASK_NULL)
- return MACH_SEND_INTERRUPTED;
- result = task_terminate(t);
- task_deallocate(t);
- return result;
- }
- kern_return_t syscall_task_suspend(mach_port_t task)
- {
- task_t t;
- kern_return_t result;
- t = port_name_to_task(task);
- if (t == TASK_NULL)
- return MACH_SEND_INTERRUPTED;
- result = task_suspend(t);
- task_deallocate(t);
- return result;
- }
- kern_return_t syscall_task_set_special_port(
- mach_port_t task,
- int which_port,
- mach_port_t port_name)
- {
- task_t t;
- ipc_port_t port;
- kern_return_t result;
- t = port_name_to_task(task);
- if (t == TASK_NULL)
- return MACH_SEND_INTERRUPTED;
- if (MACH_PORT_VALID(port_name)) {
- result = ipc_object_copyin(current_space(), port_name,
- MACH_MSG_TYPE_COPY_SEND,
- (ipc_object_t *) &port);
- if (result != KERN_SUCCESS) {
- task_deallocate(t);
- return result;
- }
- } else
- port = (ipc_port_t) port_name;
- result = task_set_special_port(t, which_port, port);
- if ((result != KERN_SUCCESS) && IP_VALID(port))
- ipc_port_release_send(port);
- task_deallocate(t);
- return result;
- }
- kern_return_t
- syscall_mach_port_allocate(
- mach_port_t task,
- mach_port_right_t right,
- mach_port_t *namep)
- {
- ipc_space_t space;
- mach_port_t name;
- kern_return_t kr;
- space = port_name_to_space(task);
- if (space == IS_NULL)
- return MACH_SEND_INTERRUPTED;
- kr = mach_port_allocate(space, right, &name);
- if (kr == KERN_SUCCESS)
- copyout(&name, namep, sizeof(mach_port_t));
- is_release(space);
- return kr;
- }
- kern_return_t
- syscall_mach_port_allocate_name(
- mach_port_t task,
- mach_port_right_t right,
- mach_port_t name)
- {
- ipc_space_t space;
- kern_return_t kr;
- space = port_name_to_space(task);
- if (space == IS_NULL)
- return MACH_SEND_INTERRUPTED;
- kr = mach_port_allocate_name(space, right, name);
- is_release(space);
- return kr;
- }
- kern_return_t
- syscall_mach_port_deallocate(
- mach_port_t task,
- mach_port_t name)
- {
- ipc_space_t space;
- kern_return_t kr;
- space = port_name_to_space(task);
- if (space == IS_NULL)
- return MACH_SEND_INTERRUPTED;
- kr = mach_port_deallocate(space, name);
- is_release(space);
- return kr;
- }
- kern_return_t
- syscall_mach_port_insert_right(
- mach_port_t task,
- mach_port_t name,
- mach_port_t right,
- mach_msg_type_name_t rightType)
- {
- ipc_space_t space;
- ipc_object_t object;
- mach_msg_type_name_t newtype;
- kern_return_t kr;
- space = port_name_to_space(task);
- if (space == IS_NULL)
- return MACH_SEND_INTERRUPTED;
- if (!MACH_MSG_TYPE_PORT_ANY(rightType)) {
- is_release(space);
- return KERN_INVALID_VALUE;
- }
- if (MACH_PORT_VALID(right)) {
- kr = ipc_object_copyin(current_space(), right, rightType,
- &object);
- if (kr != KERN_SUCCESS) {
- is_release(space);
- return kr;
- }
- } else
- object = (ipc_object_t) right;
- newtype = ipc_object_copyin_type(rightType);
- kr = mach_port_insert_right(space, name, (ipc_port_t) object, newtype);
- if ((kr != KERN_SUCCESS) && IO_VALID(object))
- ipc_object_destroy(object, newtype);
- is_release(space);
- return kr;
- }
- kern_return_t syscall_thread_depress_abort(mach_port_t thread)
- {
- thread_t t;
- kern_return_t result;
- t = port_name_to_thread(thread);
- if (t == THREAD_NULL)
- return MACH_SEND_INTERRUPTED;
- result = thread_depress_abort(t);
- thread_deallocate(t);
- return result;
- }
- /*
- * Device traps -- these are way experimental.
- */
- io_return_t
- syscall_device_write_request(mach_port_t device_name,
- mach_port_t reply_name,
- dev_mode_t mode,
- recnum_t recnum,
- vm_offset_t data,
- vm_size_t data_count)
- {
- device_t dev;
- /*ipc_port_t reply_port;*/
- io_return_t res;
- /*
- * First try to translate the device name.
- *
- * If this fails, return KERN_INVALID_CAPABILITY.
- * Caller knows that this most likely means that
- * device is not local to node and IPC should be used.
- *
- * If kernel doesn't do device traps, kern_invalid()
- * will be called instead of this function which will
- * return KERN_INVALID_ARGUMENT.
- */
- dev = port_name_to_device(device_name);
- if (dev == DEVICE_NULL)
- return KERN_INVALID_CAPABILITY;
- /*
- * Translate reply port.
- */
- /*if (reply_name == MACH_PORT_NULL)
- reply_port = IP_NULL;
- */
- if (reply_name != MACH_PORT_NULL) {
- /* Homey don't play that. */
- device_deallocate(dev);
- return KERN_INVALID_RIGHT;
- }
- /* note: doesn't take reply_port arg yet. */
- res = ds_device_write_trap(dev, /*reply_port,*/
- mode, recnum,
- data, data_count);
- /*
- * Give up reference from port_name_to_device.
- */
- device_deallocate(dev);
- return res;
- }
- io_return_t
- syscall_device_writev_request(mach_port_t device_name,
- mach_port_t reply_name,
- dev_mode_t mode,
- recnum_t recnum,
- io_buf_vec_t *iovec,
- vm_size_t iocount)
- {
- device_t dev;
- /*ipc_port_t reply_port;*/
- io_return_t res;
- /*
- * First try to translate the device name.
- *
- * If this fails, return KERN_INVALID_CAPABILITY.
- * Caller knows that this most likely means that
- * device is not local to node and IPC should be used.
- *
- * If kernel doesn't do device traps, kern_invalid()
- * will be called instead of this function which will
- * return KERN_INVALID_ARGUMENT.
- */
- dev = port_name_to_device(device_name);
- if (dev == DEVICE_NULL)
- return KERN_INVALID_CAPABILITY;
- /*
- * Translate reply port.
- */
- /*if (reply_name == MACH_PORT_NULL)
- reply_port = IP_NULL;
- */
- if (reply_name != MACH_PORT_NULL) {
- /* Homey don't play that. */
- device_deallocate(dev);
- return KERN_INVALID_RIGHT;
- }
- /* note: doesn't take reply_port arg yet. */
- res = ds_device_writev_trap(dev, /*reply_port,*/
- mode, recnum,
- iovec, iocount);
- /*
- * Give up reference from port_name_to_device.
- */
- device_deallocate(dev);
- return res;
- }
- #endif
|