xref: /netbsd-src/sys/rump/share/man/man3/rumpuser.3 (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1.\"     $NetBSD: rumpuser.3,v 1.1 2014/11/09 17:39:38 pooka Exp $
2.\"
3.\" Copyright (c) 2013 Antti Kantee.  All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\"    notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\"    notice, this list of conditions and the following disclaimer in the
12.\"    documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE.
25.\"
26.Dd August 24, 2014
27.Dt RUMPUSER 3
28.Os
29.Sh NAME
30.Nm rumpuser
31.Nd rump kernel hypercall interface
32.Sh LIBRARY
33rump User Library (librumpuser, \-lrumpuser)
34.Sh SYNOPSIS
35.In rump/rumpuser.h
36.Sh DESCRIPTION
37The
38.Nm
39hypercall interfaces allow a rump kernel to access host resources.
40A hypervisor implementation must implement the routines described in
41this document to allow a rump kernel to run on the host.
42The implementation included in
43.Nx
44is for POSIX-like hosts (*BSD, Linux, etc.).
45This document is divided into sections based on the functionality
46group of each hypercall.
47.Pp
48Since the hypercall interface is a C function interface, both the
49rump kernel and the hypervisor must conform to the same ABI.
50The interface itself attempts to assume as little as possible from
51the type systems, and for example
52.Vt off_t
53is passed as
54.Vt int64_t
55and enums are passed as ints.
56It is recommended that the hypervisor converts these to the native
57types before starting to process the hypercall, for example by
58assigning the ints back to enums.
59.Sh UPCALLS AND RUMP KERNEL CONTEXT
60A hypercall is always entered with the calling thread scheduled in
61the rump kernel.
62In case the hypercall intends to block while waiting for an event,
63the hypervisor must first release the rump kernel scheduling context.
64In other words, the rump kernel context is a resource and holding
65on to it while waiting for a rump kernel event/resource may lead
66to a deadlock.
67Even when there is no possibility of deadlock in the strict sense
68of the term, holding on to the rump kernel context while performing
69a slow hypercall such as reading a device will prevent other threads
70(including the clock interrupt) from using that rump kernel context.
71.Pp
72Releasing the context is done by calling the
73.Fn hyp_backend_unschedule
74upcall which the hypervisor received from rump kernel as a parameter
75for
76.Fn rumpuser_init .
77Before a hypercall returns back to the rump kernel, the returning thread
78must carry a rump kernel context.
79In case the hypercall unscheduled itself, it must reschedule itself
80by calling
81.Fn hyp_backend_schedule .
82.Sh HYPERCALL INTERFACES
83.Ss Initialization
84.Ft int
85.Fn rumpuser_init "int version" "struct rump_hyperup *hyp"
86.Pp
87Initialize the hypervisor.
88.Bl -tag -width "xenum_rumpclock"
89.It Fa version
90hypercall interface version number that the kernel expects to be used.
91In case the hypervisor cannot provide an exact match, this routine must
92return a non-zero value.
93.It Fa hyp
94pointer to a set of upcalls the hypervisor can make into the rump kernel
95.El
96.Ss Memory allocation
97.Ft int
98.Fn rumpuser_malloc "size_t len" "int alignment" "void **memp"
99.Bl -tag -width "xenum_rumpclock"
100.It Fa len
101amount of memory to allocate
102.It Fa alignment
103size the returned memory must be aligned to.
104For example, if the value passed is 4096, the returned memory
105must be aligned to a 4k boundary.
106.It Fa memp
107return pointer for allocated memory
108.El
109.Pp
110.Ft void
111.Fn rumpuser_free "void *mem" "size_t len"
112.Bl -tag -width "xenum_rumpclock"
113.It Fa mem
114memory to free
115.It Fa len
116length of allocation.
117This is always equal to the amount the caller requested from the
118.Fn rumpuser_malloc
119which returned
120.Fa mem .
121.El
122.Ss Files and I/O
123.Ft int
124.Fn rumpuser_open "const char *name" "int mode" "int *fdp"
125.Pp
126Open
127.Fa name
128for I/O and associate a file descriptor with it.
129Notably, there needs to be no mapping between
130.Fa name
131and the host's file system namespace.
132For example, it is possible to associate the file descriptor with
133device I/O registers for special values of
134.Fa name .
135.Bl -tag -width "xenum_rumpclock"
136.It Fa name
137the identifier of the file to open for I/O
138.It Fa mode
139combination of the following:
140.Bl -tag -width "XRUMPUSER_OPEN_CREATE"
141.It Dv RUMPUSER_OPEN_RDONLY
142open only for reading
143.It Dv RUMPUSER_OPEN_WRONLY
144open only for writing
145.It Dv RUMPUSER_OPEN_RDWR
146open for reading and writing
147.It Dv RUMPUSER_OPEN_CREATE
148do not treat missing
149.Fa name
150as an error
151.It Dv RUMPUSER_OPEN_EXCL
152combined with
153.Dv RUMPUSER_OPEN_CREATE ,
154flag an error if
155.Fa name
156already exists
157.It Dv RUMPUSER_OPEN_BIO
158the caller will use this file for block I/O, usually used in
159conjunction with accessing file system media.
160The hypervisor should treat this flag as advisory and possibly
161enable some optimizations for
162.Fa *fdp
163based on it.
164.El
165Notably, the permissions of the created file are left up to the
166hypervisor implementation.
167.It Fa fdp
168An integer value denoting the open file is returned here.
169.El
170.Pp
171.Ft int
172.Fn rumpuser_close "int fd"
173.Pp
174Close a previously opened file descriptor.
175.Pp
176.Ft int
177.Fn rumpuser_getfileinfo "const char *name" "uint64_t *size" "int *type"
178.Bl -tag -width "xenum_rumpclock"
179.It Fa name
180file for which information is returned.
181The namespace is equal to that of
182.Fn rumpuser_open .
183.It Fa size
184If
185.Pf non- Dv NULL ,
186size of the file is returned here.
187.It Fa type
188If
189.Pf non- Dv NULL ,
190type of the file is returned here.
191The options are
192.Dv RUMPUSER_FT_DIR ,
193.Dv RUMPUSER_FT_REG ,
194.Dv RUMPUSER_FT_BLK ,
195.Dv RUMPUSER_FT_CHR ,
196or
197.Dv RUMPUSER_FT_OTHER
198for directory, regular file, block device, character device or unknown,
199respectively.
200.El
201.Pp
202.Ft void
203.Fo rumpuser_bio
204.Fa "int fd" "int op" "void *data" "size_t dlen" "int64_t off"
205.Fa "rump_biodone_fn biodone" "void *donearg"
206.Fc
207.Pp
208Initiate block I/O and return immediately.
209.Bl -tag -width "xenum_rumpclock"
210.It Fa fd
211perform I/O on this file descriptor.
212The file descriptor must have been opened with
213.Dv RUMPUSER_OPEN_BIO .
214.It Fa op
215Transfer data from the file descriptor with
216.Dv RUMPUSER_BIO_READ
217and transfer data to the file descriptor with
218.Dv RUMPUSER_BIO_WRITE .
219Unless
220.Dv RUMPUSER_BIO_SYNC
221is specified, the hypervisor may cache a write instead of
222committing it to permanent storage.
223.It Fa data
224memory address to transfer data to/from
225.It Fa dlen
226length of I/O.
227The length is guaranteed to be a multiple of 512.
228.It Fa off
229offset into
230.Fa fd
231where I/O is performed
232.It Fa biodone
233To be called when the I/O is complete.
234Accessing
235.Fa data
236is not legal after the call is made.
237.It Fa donearg
238opaque arg that must be passed to
239.Fa biodone .
240.El
241.Pp
242.Ft int
243.Fo rumpuser_iovread
244.Fa "int fd" "struct rumpuser_iovec *ruiov" "size_t iovlen"
245.Fa "int64_t off" "size_t *retv"
246.Fc
247.Pp
248.Ft int
249.Fo rumpuser_iovwrite
250.Fa "int fd" "struct rumpuser_iovec *ruiov" "size_t iovlen"
251.Fa "int64_t off" "size_t *retv"
252.Fc
253.Pp
254These routines perform scatter-gather I/O which is not
255block I/O by nature and therefore cannot be handled by
256.Fn rumpuser_bio .
257.Pp
258.Bl -tag -width "xenum_rumpclock"
259.It Fa fd
260file descriptor to perform I/O on
261.It Fa ruiov
262an array of I/O descriptors.
263It is defined as follows:
264.Bd -literal -offset indent -compact
265struct rumpuser_iovec {
266	void *iov_base;
267	size_t iov_len;
268};
269.Ed
270.It Fa iovlen
271number of elements in
272.Fa ruiov
273.It Fa off
274offset of
275.Fa fd
276to perform I/O on.
277This can either be a non-negative value or
278.Dv RUMPUSER_IOV_NOSEEK .
279The latter denotes that no attempt to change the underlying objects
280offset should be made.
281Using both types of offsets on a single instance of
282.Fa fd
283results in undefined behavior.
284.It Fa retv
285number of bytes successfully transferred is returned here
286.El
287.Pp
288.Ft int
289.Fo rumpuser_syncfd
290.Fa "int fd" "int flags" "uint64_t start" "uint64_t len"
291.Fc
292.Pp
293Synchronizes
294.Fa fd
295with respect to backing storage.
296The other arguments are:
297.Pp
298.Bl -tag -width "xenum_rumpclock"
299.It Fa flags
300controls how synchronization happens.
301It must contain one of the following:
302.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER"
303.It Dv RUMPUSER_SYNCFD_READ
304Make sure that the next read sees writes from all other parties.
305This is useful for example in the case that
306.Fa fd
307represents memory to write a DMA read is being performed.
308.It Dv RUMPUSER_SYNCFD_WRITE
309Flush cached writes.
310.El
311.Pp
312The following additional parameters may be passed in
313.Fa flags :
314.Pp
315.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER"
316.It Dv RUMPUSER_SYNCFD_BARRIER
317Issue a barrier.
318Outstanding I/O operations which were started before the barrier
319complete before any operations after the barrier are performed.
320.It Dv RUMPUSER_SYNCFD_SYNC
321Wait for the synchronization operation to fully complete before
322returning.
323For example, this could mean that the data to be written to a disk
324has hit either the disk or non-volatile memory.
325.El
326.It Fa start
327offset into the object.
328.It Fa len
329the number of bytes to synchronize.
330The value 0 denotes until the end of the object.
331.El
332.Ss Clocks
333The hypervisor should support two clocks, one for wall time and one
334for monotonically increasing time, the latter of which may be based
335on some arbitrary time (e.g. system boot time).
336If this is not possible, the hypervisor must make a reasonable effort to
337retain semantics.
338.Pp
339.Ft int
340.Fn rumpuser_clock_gettime "int enum_rumpclock" "int64_t *sec" "long *nsec"
341.Pp
342.Bl -tag -width "xenum_rumpclock"
343.It Fa enum_rumpclock
344specifies the clock type.
345In case of
346.Dv RUMPUSER_CLOCK_RELWALL
347the wall time should be returned.
348In case of
349.Dv RUMPUSER_CLOCK_ABSMONO
350the time of a monotonic clock should be returned.
351.It Fa sec
352return value for seconds
353.It Fa nsec
354return value for nanoseconds
355.El
356.Pp
357.Ft int
358.Fn rumpuser_clock_sleep "int enum_rumpclock" "int64_t sec" "long nsec"
359.Bl -tag -width "xenum_rumpclock"
360.It Fa enum_rumpclock
361In case of
362.Dv RUMPUSER_CLOCK_RELWALL ,
363the sleep should last at least as long as specified.
364In case of
365.Dv RUMPUSER_CLOCK_ABSMONO ,
366the sleep should last until the hypervisor monotonic clock hits
367the specified absolute time.
368.It Fa sec
369sleep duration, seconds.
370exact semantics depend on
371.Fa clk .
372.It Fa nsec
373sleep duration, nanoseconds.
374exact semantics depend on
375.Fa clk .
376.El
377.Ss Parameter retrieval
378.Ft int
379.Fn rumpuser_getparam "const char *name" "void *buf" "size_t buflen"
380.Pp
381Retrieve a configuration parameter from the hypervisor.
382It is up to the hypervisor to decide how the parameters can be set.
383.Bl -tag -width "xenum_rumpclock"
384.It Fa name
385name of the parameter.
386If the name starts with an underscore, it means a mandatory parameter.
387The mandatory parameters are
388.Dv RUMPUSER_PARAM_NCPU
389which specifies the amount of virtual CPUs bootstrapped by the
390rump kernel and
391.Dv RUMPUSER_PARAM_HOSTNAME
392which returns a preferably unique instance name for the rump kernel.
393.It Fa buf
394buffer to return the data in as a string
395.It Fa buflen
396length of buffer
397.El
398.Ss Termination
399.Ft void
400.Fn rumpuser_exit "int value"
401.Pp
402Terminate the rump kernel with exit value
403.Fa value .
404If
405.Fa value
406is
407.Dv RUMPUSER_PANIC
408the hypervisor should attempt to provide something akin to a core dump.
409.Ss Console output
410Console output is divided into two routines: a per-character
411one and printf-like one.
412The former is used e.g. by the rump kernel's internal printf
413routine.
414The latter can be used for direct debug prints e.g. very early
415on in the rump kernel's bootstrap or when using the in-kernel
416routine causes too much skew in the debug print results
417(the hypercall runs outside of the rump kernel and therefore does not
418cause any locking or scheduling events inside the rump kernel).
419.Pp
420.Ft void
421.Fn rumpuser_putchar "int ch"
422.Pp
423Output
424.Fa ch
425on the console.
426.Pp
427.Ft void
428.Fn rumpuser_dprintf "const char *fmt" "..."
429.Pp
430Do output based on printf-like parameters.
431.Ss Signals
432.Pp
433A rump kernel should be able to send signals to client programs
434due to some standard interfaces including signal delivery in their
435specifications.
436Examples of these interfaces include
437.Xr setitimer 2
438and
439.Xr write 2 .
440The
441.Fn rumpuser_kill
442function advises the hypercall implementation to raise a signal for the
443process containing the rump kernel.
444.Pp
445.Ft int
446.Fn rumpuser_kill "int64_t pid" "int sig"
447.Pp
448.Bl -tag -width "xenum_rumpclock"
449.It Fa pid
450The pid of the rump kernel process that the signal is directed to.
451This value may be used as the hypervisor as a hint on how to deliver
452the signal.
453The value
454.Dv RUMPUSER_PID_SELF
455may also be specified to indicate no hint.
456This value will be removed in a future version of the hypercall interface.
457.It Fa sig
458Number of signal to raise.
459The value is in NetBSD signal number namespace.
460In case the host has a native representation for signals, the
461value should be translated before the signal is raised.
462In case there is no mapping between
463.Fa sig
464and native signals (if any), the behavior is implementation-defined.
465.El
466.Pp
467A rump kernel will ignore the return value of this hypercall.
468The only implication of not implementing
469.Fn rumpuser_kill
470is that some application programs may not experience expected behavior
471for standard interfaces.
472.Pp
473As an aside,the
474.Xr rump_sp 7
475protocol provides equivalent functionality for remote clients.
476.Ss Random pool
477.Ft int
478.Fn rumpuser_getrandom "void *buf" "size_t buflen" "int flags" "size_t *retp"
479.Pp
480.Bl -tag -width "xenum_rumpclock"
481.It Fa buf
482buffer that the randomness is written to
483.It Fa buflen
484number of bytes of randomness requested
485.It Fa flags
486The value 0 or a combination of
487.Dv RUMPUSER_RANDOM_HARD
488(return true randomness instead of something from a PRNG)
489and
490.Dv RUMPUSER_RANDOM_NOWAIT
491(do not block in case the requested amount of bytes is not available).
492.It Fa retp
493The number of random bytes written into
494.Fa buf .
495.El
496.Ss Threads
497.Ft int
498.Fo rumpuser_thread_create
499.Fa "void *(*fun)(void *)" "void *arg" "const char *thrname" "int mustjoin"
500.Fa "int priority" "int cpuidx" "void **cookie"
501.Fc
502.Pp
503Create a schedulable host thread context.
504The rump kernel will call this interface when it creates a kernel thread.
505The scheduling policy for the new thread is defined by the hypervisor.
506In case the hypervisor wants to optimize the scheduling of the
507threads, it can perform heuristics on the
508.Fa thrname ,
509.Fa priority
510and
511.Fa cpuidx
512parameters.
513.Bl -tag -width "xenum_rumpclock"
514.It Fa fun
515function that the new thread must call.
516This call will never return.
517.It Fa arg
518argument to be passed to
519.Fa fun
520.It Fa thrname
521Name of the new thread.
522.It Fa mustjoin
523If 1, the thread will be waited for by
524.Fn rumpuser_thread_join
525when the thread exits.
526.It Fa priority
527The priority that the kernel requested the thread to be created at.
528Higher values mean higher priority.
529The exact kernel semantics for each value are not available through
530this interface.
531.It Fa cpuidx
532The index of the virtual CPU that the thread is bound to, or \-1
533if the thread is not bound.
534The mapping between the virtual CPUs and physical CPUs, if any,
535is hypervisor implementation specific.
536.It Fa cookie
537In case
538.Fa mustjoin
539is set, the value returned in
540.Fa cookie
541will be passed to
542.Fn rumpuser_thread_join .
543.El
544.Pp
545.Ft void
546.Fn rumpuser_thread_exit "void"
547.Pp
548Called when a thread created with
549.Fn rumpuser_thread_create
550exits.
551.Pp
552.Ft int
553.Fn rumpuser_thread_join "void *cookie"
554.Pp
555Wait for a joinable thread to exit.
556The cookie matches the value from
557.Fn rumpuser_thread_create .
558.Pp
559.Ft void
560.Fn rumpuser_curlwpop "int enum_rumplwpop" "struct lwp *l"
561.Pp
562Manipulate the hypervisor's thread context database.
563The possible operations are create, destroy, and set as specified by
564.Fa enum_rumplwpop :
565.Bl -tag -width "XRUMPUSER_LWP_DESTROY"
566.It Dv RUMPUSER_LWP_CREATE
567Inform the hypervisor that
568.Fa l
569is now a valid thread context which may be set.
570A currently valid value of
571.Fa l
572may not be specified.
573This operation is informational and does not mandate any action
574from the hypervisor.
575.It Dv RUMPUSER_LWP_DESTROY
576Inform the hypervisor that
577.Fa l
578is no longer a valid thread context.
579This means that it may no longer be set as the current context.
580A currently set context or an invalid one may not be destroyed.
581This operation is informational and does not mandate any action
582from the hypervisor.
583.It Dv RUMPUSER_LWP_SET
584Set
585.Fa l
586as the current host thread's rump kernel context.
587A previous context must not exist.
588.It Dv RUMPUSER_LWP_CLEAR
589Clear the context previous set by
590.Dv RUMPUSER_LWP_SET .
591The value passed in
592.Fa l
593is the current thread and is never
594.Dv NULL .
595.El
596.Pp
597.Ft struct lwp *
598.Fn rumpuser_curlwp "void"
599.Pp
600Retrieve the rump kernel thread context associated with the current host
601thread, as set by
602.Fn rumpuser_curlwpop .
603This routine may be called when a context is not set and
604the routine must return
605.Dv NULL
606in that case.
607This interface is expected to be called very often.
608Any optimizations pertaining to the execution speed of this routine
609should be done in
610.Fn rumpuser_curlwpop .
611.Pp
612.Ft void
613.Fn rumpuser_seterrno "int errno"
614.Pp
615Set an errno value in the calling thread's TLS.
616Note: this is used only if rump kernel clients make rump system calls.
617.Ss Mutexes, rwlocks and condition variables
618The locking interfaces have standard semantics, so we will not
619discuss each one in detail.
620The data types
621.Vt struct rumpuser_mtx ,
622.Vt struct rumpuser_rw
623and
624.Vt struct rumpuser_cv
625used by these interfaces are opaque to the rump kernel, i.e. the
626hypervisor has complete freedom over them.
627.Pp
628Most of these interfaces will (and must) relinquish the rump kernel
629CPU context in case they block (or intend to block).
630The exceptions are the "nowrap" variants of the interfaces which
631may not relinquish rump kernel context.
632.Pp
633.Ft void
634.Fn rumpuser_mutex_init "struct rumpuser_mtx **mtxp" "int flags"
635.Pp
636.Ft void
637.Fn rumpuser_mutex_enter "struct rumpuser_mtx *mtx"
638.Pp
639.Ft void
640.Fn rumpuser_mutex_enter_nowrap "struct rumpuser_mtx *mtx"
641.Pp
642.Ft int
643.Fn rumpuser_mutex_tryenter "struct rumpuser_mtx *mtx"
644.Pp
645.Ft void
646.Fn rumpuser_mutex_exit "struct rumpuser_mtx *mtx"
647.Pp
648.Ft void
649.Fn rumpuser_mutex_destroy "struct rumpuser_mtx *mtx"
650.Pp
651.Ft void
652.Fn rumpuser_mutex_owner "struct rumpuser_mtx *mtx" "struct lwp **lp"
653.Pp
654Mutexes provide mutually exclusive locking.
655The flags, of which at least one must be given, are as follows:
656.Bl -tag -width "XRUMPUSER_MTX_KMUTEX"
657.It Dv RUMPUSER_MTX_SPIN
658Create a spin mutex.
659Locking this type of mutex must not relinquish rump kernel context
660even when
661.Fn rumpuser_mutex_enter
662is used.
663.It Dv RUMPUSER_MTX_KMUTEX
664The mutex must track and be able to return the rump kernel thread
665that owns the mutex (if any).
666If this flag is not specified,
667.Fn rumpuser_mutex_owner
668will never be called for that particular mutex.
669.El
670.Pp
671.Ft void
672.Fn rumpuser_rw_init "struct rumpuser_rw **rwp"
673.Pp
674.Ft void
675.Fn rumpuser_rw_enter "int enum_rumprwlock" "struct rumpuser_rw *rw"
676.Pp
677.Ft int
678.Fn rumpuser_rw_tryenter "int enum_rumprwlock" "struct rumpuser_rw *rw"
679.Pp
680.Ft int
681.Fn rumpuser_rw_tryupgrade "struct rumpuser_rw *rw"
682.Pp
683.Ft void
684.Fn rumpuser_rw_downgrade "struct rumpuser_rw *rw"
685.Pp
686.Ft void
687.Fn rumpuser_rw_exit "struct rumpuser_rw *rw"
688.Pp
689.Ft void
690.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw"
691.Pp
692.Ft void
693.Fo rumpuser_rw_held
694.Fa "int enum_rumprwlock" "struct rumpuser_rw *rw" "int *heldp"
695.Fc
696.Pp
697Read/write locks provide either shared or exclusive locking.
698The possible values for
699.Fa lk
700are
701.Dv RUMPUSER_RW_READER
702and
703.Dv RUMPUSER_RW_WRITER .
704Upgrading means trying to migrate from an already owned shared
705lock to an exclusive lock and downgrading means migrating from
706an already owned exclusive lock to a shared lock.
707.Pp
708.Ft void
709.Fn rumpuser_cv_init "struct rumpuser_cv **cvp"
710.Pp
711.Ft void
712.Fn rumpuser_cv_destroy "struct rumpuser_cv *cv"
713.Pp
714.Ft void
715.Fn rumpuser_cv_wait "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
716.Pp
717.Ft void
718.Fn rumpuser_cv_wait_nowrap "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
719.Pp
720.Ft int
721.Fo rumpuser_cv_timedwait
722.Fa "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx"
723.Fa "int64_t sec" "int64_t nsec"
724.Fc
725.Pp
726.Ft void
727.Fn rumpuser_cv_signal "struct rumpuser_cv *cv"
728.Pp
729.Ft void
730.Fn rumpuser_cv_broadcast "struct rumpuser_cv *cv"
731.Pp
732.Ft void
733.Fn rumpuser_cv_has_waiters "struct rumpuser_cv *cv" "int *waitersp"
734.Pp
735Condition variables wait for an event.
736The
737.Fa mtx
738interlock eliminates a race between checking the predicate and
739sleeping on the condition variable; the mutex should be released
740for the duration of the sleep in the normal atomic manner.
741The timedwait variant takes a specifier indicating a relative
742sleep duration after which the routine will return with
743.Er ETIMEDOUT .
744If a timedwait is signaled before the timeout expires, the
745routine will return 0.
746.Pp
747The order in which the hypervisor
748reacquires the rump kernel context and interlock mutex before
749returning into the rump kernel is as follows.
750In case the interlock mutex was initialized with both
751.Dv RUMPUSER_MTX_SPIN
752and
753.Dv RUMPUSER_MTX_KMUTEX ,
754the rump kernel context is scheduled before the mutex is reacquired.
755In case of a purely
756.Dv RUMPUSER_MTX_SPIN
757mutex, the mutex is acquired first.
758In the final case the order is implementation-defined.
759.Sh RETURN VALUES
760All routines which return an integer return an errno value.
761The hypervisor must translate the value to the the native errno
762namespace used by the rump kernel.
763Routines which do not return an integer may never fail.
764.Sh SEE ALSO
765.Xr rump 3
766.Rs
767.%A Antti Kantee
768.%D 2012
769.%J Aalto University Doctoral Dissertations
770.%T Flexible Operating System Internals: The Design and Implementation of the Anykernel and Rump Kernels
771.%O Section 2.3.2: The Hypercall Interface
772.Re
773.Pp
774For a list of all known implementations of the
775.Nm
776interface, see
777.Lk http://wiki.rumpkernel.org/Platforms .
778.Sh HISTORY
779The rump kernel hypercall API was first introduced in
780.Nx 5.0 .
781The API described above first appeared in
782.Nx 7.0 .
783