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