1.\" $NetBSD: rumpuser.3,v 1.4 2023/07/14 23:21:53 lukem 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 July 15, 2023 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.Bl -tag -width "xenum_rumpclock" 258.It Fa fd 259file descriptor to perform I/O on 260.It Fa ruiov 261an array of I/O descriptors. 262It is defined as follows: 263.Bd -literal -offset indent -compact 264struct rumpuser_iovec { 265 void *iov_base; 266 size_t iov_len; 267}; 268.Ed 269.It Fa iovlen 270number of elements in 271.Fa ruiov 272.It Fa off 273offset of 274.Fa fd 275to perform I/O on. 276This can either be a non-negative value or 277.Dv RUMPUSER_IOV_NOSEEK . 278The latter denotes that no attempt to change the underlying objects 279offset should be made. 280Using both types of offsets on a single instance of 281.Fa fd 282results in undefined behavior. 283.It Fa retv 284number of bytes successfully transferred is returned here 285.El 286.Pp 287.Ft int 288.Fo rumpuser_syncfd 289.Fa "int fd" "int flags" "uint64_t start" "uint64_t len" 290.Fc 291.Pp 292Synchronizes 293.Fa fd 294with respect to backing storage. 295The other arguments are: 296.Bl -tag -width "xenum_rumpclock" 297.It Fa flags 298controls how synchronization happens. 299It must contain one of the following: 300.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER" 301.It Dv RUMPUSER_SYNCFD_READ 302Make sure that the next read sees writes from all other parties. 303This is useful for example in the case that 304.Fa fd 305represents memory to write a DMA read is being performed. 306.It Dv RUMPUSER_SYNCFD_WRITE 307Flush cached writes. 308.El 309.Pp 310The following additional parameters may be passed in 311.Fa flags : 312.Bl -tag -width "XRUMPUSER_SYNCFD_BARRIER" 313.It Dv RUMPUSER_SYNCFD_BARRIER 314Issue a barrier. 315Outstanding I/O operations which were started before the barrier 316complete before any operations after the barrier are performed. 317.It Dv RUMPUSER_SYNCFD_SYNC 318Wait for the synchronization operation to fully complete before 319returning. 320For example, this could mean that the data to be written to a disk 321has hit either the disk or non-volatile memory. 322.El 323.It Fa start 324offset into the object. 325.It Fa len 326the number of bytes to synchronize. 327The value 0 denotes until the end of the object. 328.El 329.Ss Clocks 330The hypervisor should support two clocks, one for wall time and one 331for monotonically increasing time, the latter of which may be based 332on some arbitrary time (e.g. system boot time). 333If this is not possible, the hypervisor must make a reasonable effort to 334retain semantics. 335.Pp 336.Ft int 337.Fn rumpuser_clock_gettime "int enum_rumpclock" "int64_t *sec" "long *nsec" 338.Bl -tag -width "xenum_rumpclock" 339.It Fa enum_rumpclock 340specifies the clock type. 341In case of 342.Dv RUMPUSER_CLOCK_RELWALL 343the wall time should be returned. 344In case of 345.Dv RUMPUSER_CLOCK_ABSMONO 346the time of a monotonic clock should be returned. 347.It Fa sec 348return value for seconds 349.It Fa nsec 350return value for nanoseconds 351.El 352.Pp 353.Ft int 354.Fn rumpuser_clock_sleep "int enum_rumpclock" "int64_t sec" "long nsec" 355.Bl -tag -width "xenum_rumpclock" 356.It Fa enum_rumpclock 357In case of 358.Dv RUMPUSER_CLOCK_RELWALL , 359the sleep should last at least as long as specified. 360In case of 361.Dv RUMPUSER_CLOCK_ABSMONO , 362the sleep should last until the hypervisor monotonic clock hits 363the specified absolute time. 364.It Fa sec 365sleep duration, seconds. 366exact semantics depend on 367.Fa clk . 368.It Fa nsec 369sleep duration, nanoseconds. 370exact semantics depend on 371.Fa clk . 372.El 373.Ss Parameter retrieval 374.Ft int 375.Fn rumpuser_getparam "const char *name" "void *buf" "size_t buflen" 376.Pp 377Retrieve a configuration parameter from the hypervisor. 378It is up to the hypervisor to decide how the parameters can be set. 379.Bl -tag -width "xenum_rumpclock" 380.It Fa name 381name of the parameter. 382If the name starts with an underscore, it means a mandatory parameter. 383The mandatory parameters are 384.Dv RUMPUSER_PARAM_NCPU 385which specifies the amount of virtual CPUs bootstrapped by the 386rump kernel and 387.Dv RUMPUSER_PARAM_HOSTNAME 388which returns a preferably unique instance name for the rump kernel. 389.It Fa buf 390buffer to return the data in as a string 391.It Fa buflen 392length of buffer 393.El 394.Ss Termination 395.Ft void 396.Fn rumpuser_exit "int value" 397.Pp 398Terminate the rump kernel with exit value 399.Fa value . 400If 401.Fa value 402is 403.Dv RUMPUSER_PANIC 404the hypervisor should attempt to provide something akin to a core dump. 405.Ss Console output 406Console output is divided into two routines: a per-character 407one and printf-like one. 408The former is used e.g. by the rump kernel's internal printf 409routine. 410The latter can be used for direct debug prints e.g. very early 411on in the rump kernel's bootstrap or when using the in-kernel 412routine causes too much skew in the debug print results 413(the hypercall runs outside of the rump kernel and therefore does not 414cause any locking or scheduling events inside the rump kernel). 415.Pp 416.Ft void 417.Fn rumpuser_putchar "int ch" 418.Pp 419Output 420.Fa ch 421on the console. 422.Pp 423.Ft void 424.Fn rumpuser_dprintf "const char *fmt" "..." 425.Pp 426Do output based on printf-like parameters. 427.Ss Signals 428A rump kernel should be able to send signals to client programs 429due to some standard interfaces including signal delivery in their 430specifications. 431Examples of these interfaces include 432.Xr setitimer 2 433and 434.Xr write 2 . 435The 436.Fn rumpuser_kill 437function advises the hypercall implementation to raise a signal for the 438process containing the rump kernel. 439.Pp 440.Ft int 441.Fn rumpuser_kill "int64_t pid" "int sig" 442.Bl -tag -width "xenum_rumpclock" 443.It Fa pid 444The pid of the rump kernel process that the signal is directed to. 445This value may be used as the hypervisor as a hint on how to deliver 446the signal. 447The value 448.Dv RUMPUSER_PID_SELF 449may also be specified to indicate no hint. 450This value will be removed in a future version of the hypercall interface. 451.It Fa sig 452Number of signal to raise. 453The value is in 454.Nx 455signal number namespace. 456In case the host has a native representation for signals, the 457value should be translated before the signal is raised. 458In case there is no mapping between 459.Fa sig 460and native signals (if any), the behavior is implementation-defined. 461.El 462.Pp 463A rump kernel will ignore the return value of this hypercall. 464The only implication of not implementing 465.Fn rumpuser_kill 466is that some application programs may not experience expected behavior 467for standard interfaces. 468.Pp 469As an aside,the 470.Xr rump_sp 7 471protocol provides equivalent functionality for remote clients. 472.Ss Random pool 473.Ft int 474.Fn rumpuser_getrandom "void *buf" "size_t buflen" "int flags" "size_t *retp" 475.Bl -tag -width "xenum_rumpclock" 476.It Fa buf 477buffer that the randomness is written to 478.It Fa buflen 479number of bytes of randomness requested 480.It Fa flags 481The value 0 or a combination of 482.Dv RUMPUSER_RANDOM_HARD 483(return true randomness instead of something from a PRNG) 484and 485.Dv RUMPUSER_RANDOM_NOWAIT 486(do not block in case the requested amount of bytes is not available). 487.It Fa retp 488The number of random bytes written into 489.Fa buf . 490.El 491.Ss Threads 492.Ft int 493.Fo rumpuser_thread_create 494.Fa "void *(*fun)(void *)" "void *arg" "const char *thrname" "int mustjoin" 495.Fa "int priority" "int cpuidx" "void **cookie" 496.Fc 497.Pp 498Create a schedulable host thread context. 499The rump kernel will call this interface when it creates a kernel thread. 500The scheduling policy for the new thread is defined by the hypervisor. 501In case the hypervisor wants to optimize the scheduling of the 502threads, it can perform heuristics on the 503.Fa thrname , 504.Fa priority 505and 506.Fa cpuidx 507parameters. 508.Bl -tag -width "xenum_rumpclock" 509.It Fa fun 510function that the new thread must call. 511This call will never return. 512.It Fa arg 513argument to be passed to 514.Fa fun 515.It Fa thrname 516Name of the new thread. 517.It Fa mustjoin 518If 1, the thread will be waited for by 519.Fn rumpuser_thread_join 520when the thread exits. 521.It Fa priority 522The priority that the kernel requested the thread to be created at. 523Higher values mean higher priority. 524The exact kernel semantics for each value are not available through 525this interface. 526.It Fa cpuidx 527The index of the virtual CPU that the thread is bound to, or \-1 528if the thread is not bound. 529The mapping between the virtual CPUs and physical CPUs, if any, 530is hypervisor implementation specific. 531.It Fa cookie 532In case 533.Fa mustjoin 534is set, the value returned in 535.Fa cookie 536will be passed to 537.Fn rumpuser_thread_join . 538.El 539.Pp 540.Ft void 541.Fn rumpuser_thread_exit "void" 542.Pp 543Called when a thread created with 544.Fn rumpuser_thread_create 545exits. 546.Pp 547.Ft int 548.Fn rumpuser_thread_join "void *cookie" 549.Pp 550Wait for a joinable thread to exit. 551The cookie matches the value from 552.Fn rumpuser_thread_create . 553.Pp 554.Ft void 555.Fn rumpuser_curlwpop "int enum_rumplwpop" "struct lwp *l" 556.Pp 557Manipulate the hypervisor's thread context database. 558The possible operations are create, destroy, and set as specified by 559.Fa enum_rumplwpop : 560.Bl -tag -width "XRUMPUSER_LWP_DESTROY" 561.It Dv RUMPUSER_LWP_CREATE 562Inform the hypervisor that 563.Fa l 564is now a valid thread context which may be set. 565A currently valid value of 566.Fa l 567may not be specified. 568This operation is informational and does not mandate any action 569from the hypervisor. 570.It Dv RUMPUSER_LWP_DESTROY 571Inform the hypervisor that 572.Fa l 573is no longer a valid thread context. 574This means that it may no longer be set as the current context. 575A currently set context or an invalid one may not be destroyed. 576This operation is informational and does not mandate any action 577from the hypervisor. 578.It Dv RUMPUSER_LWP_SET 579Set 580.Fa l 581as the current host thread's rump kernel context. 582A previous context must not exist. 583.It Dv RUMPUSER_LWP_CLEAR 584Clear the context previous set by 585.Dv RUMPUSER_LWP_SET . 586The value passed in 587.Fa l 588is the current thread and is never 589.Dv NULL . 590.El 591.Pp 592.Ft struct lwp * 593.Fn rumpuser_curlwp "void" 594.Pp 595Retrieve the rump kernel thread context associated with the current host 596thread, as set by 597.Fn rumpuser_curlwpop . 598This routine may be called when a context is not set and 599the routine must return 600.Dv NULL 601in that case. 602This interface is expected to be called very often. 603Any optimizations pertaining to the execution speed of this routine 604should be done in 605.Fn rumpuser_curlwpop . 606.Pp 607.Ft void 608.Fn rumpuser_seterrno "int errno" 609.Pp 610Set an errno value in the calling thread's TLS. 611Note: this is used only if rump kernel clients make rump system calls. 612.Ss Mutexes, rwlocks and condition variables 613The locking interfaces have standard semantics, so we will not 614discuss each one in detail. 615The data types 616.Vt struct rumpuser_mtx , 617.Vt struct rumpuser_rw 618and 619.Vt struct rumpuser_cv 620used by these interfaces are opaque to the rump kernel, i.e. the 621hypervisor has complete freedom over them. 622.Pp 623Most of these interfaces will (and must) relinquish the rump kernel 624CPU context in case they block (or intend to block). 625The exceptions are the "nowrap" variants of the interfaces which 626may not relinquish rump kernel context. 627.Pp 628.Ft void 629.Fn rumpuser_mutex_init "struct rumpuser_mtx **mtxp" "int flags" 630.Pp 631.Ft void 632.Fn rumpuser_mutex_enter "struct rumpuser_mtx *mtx" 633.Pp 634.Ft void 635.Fn rumpuser_mutex_enter_nowrap "struct rumpuser_mtx *mtx" 636.Pp 637.Ft int 638.Fn rumpuser_mutex_tryenter "struct rumpuser_mtx *mtx" 639.Pp 640.Ft void 641.Fn rumpuser_mutex_exit "struct rumpuser_mtx *mtx" 642.Pp 643.Ft void 644.Fn rumpuser_mutex_destroy "struct rumpuser_mtx *mtx" 645.Pp 646.Ft void 647.Fn rumpuser_mutex_owner "struct rumpuser_mtx *mtx" "struct lwp **lp" 648.Pp 649Mutexes provide mutually exclusive locking. 650The flags, of which at least one must be given, are as follows: 651.Bl -tag -width "XRUMPUSER_MTX_KMUTEX" 652.It Dv RUMPUSER_MTX_SPIN 653Create a spin mutex. 654Locking this type of mutex must not relinquish rump kernel context 655even when 656.Fn rumpuser_mutex_enter 657is used. 658.It Dv RUMPUSER_MTX_KMUTEX 659The mutex must track and be able to return the rump kernel thread 660that owns the mutex (if any). 661If this flag is not specified, 662.Fn rumpuser_mutex_owner 663will never be called for that particular mutex. 664.El 665.Pp 666.Ft void 667.Fn rumpuser_rw_init "struct rumpuser_rw **rwp" 668.Pp 669.Ft void 670.Fn rumpuser_rw_enter "int enum_rumprwlock" "struct rumpuser_rw *rw" 671.Pp 672.Ft int 673.Fn rumpuser_rw_tryenter "int enum_rumprwlock" "struct rumpuser_rw *rw" 674.Pp 675.Ft int 676.Fn rumpuser_rw_tryupgrade "struct rumpuser_rw *rw" 677.Pp 678.Ft void 679.Fn rumpuser_rw_downgrade "struct rumpuser_rw *rw" 680.Pp 681.Ft void 682.Fn rumpuser_rw_exit "struct rumpuser_rw *rw" 683.Pp 684.Ft void 685.Fn rumpuser_rw_destroy "struct rumpuser_rw *rw" 686.Pp 687.Ft void 688.Fo rumpuser_rw_held 689.Fa "int enum_rumprwlock" "struct rumpuser_rw *rw" "int *heldp" 690.Fc 691.Pp 692Read/write locks provide either shared or exclusive locking. 693The possible values for 694.Fa lk 695are 696.Dv RUMPUSER_RW_READER 697and 698.Dv RUMPUSER_RW_WRITER . 699Upgrading means trying to migrate from an already owned shared 700lock to an exclusive lock and downgrading means migrating from 701an already owned exclusive lock to a shared lock. 702.Pp 703.Ft void 704.Fn rumpuser_cv_init "struct rumpuser_cv **cvp" 705.Pp 706.Ft void 707.Fn rumpuser_cv_destroy "struct rumpuser_cv *cv" 708.Pp 709.Ft void 710.Fn rumpuser_cv_wait "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx" 711.Pp 712.Ft void 713.Fn rumpuser_cv_wait_nowrap "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx" 714.Pp 715.Ft int 716.Fo rumpuser_cv_timedwait 717.Fa "struct rumpuser_cv *cv" "struct rumpuser_mtx *mtx" 718.Fa "int64_t sec" "int64_t nsec" 719.Fc 720.Pp 721.Ft void 722.Fn rumpuser_cv_signal "struct rumpuser_cv *cv" 723.Pp 724.Ft void 725.Fn rumpuser_cv_broadcast "struct rumpuser_cv *cv" 726.Pp 727.Ft void 728.Fn rumpuser_cv_has_waiters "struct rumpuser_cv *cv" "int *waitersp" 729.Pp 730Condition variables wait for an event. 731The 732.Fa mtx 733interlock eliminates a race between checking the predicate and 734sleeping on the condition variable; the mutex should be released 735for the duration of the sleep in the normal atomic manner. 736The timedwait variant takes a specifier indicating a relative 737sleep duration after which the routine will return with 738.Er ETIMEDOUT . 739If a timedwait is signaled before the timeout expires, the 740routine will return 0. 741.Pp 742The order in which the hypervisor 743reacquires the rump kernel context and interlock mutex before 744returning into the rump kernel is as follows. 745In case the interlock mutex was initialized with both 746.Dv RUMPUSER_MTX_SPIN 747and 748.Dv RUMPUSER_MTX_KMUTEX , 749the rump kernel context is scheduled before the mutex is reacquired. 750In case of a purely 751.Dv RUMPUSER_MTX_SPIN 752mutex, the mutex is acquired first. 753In the final case the order is implementation-defined. 754.Sh RETURN VALUES 755All routines which return an integer return an errno value. 756The hypervisor must translate the value to the native errno 757namespace used by the rump kernel. 758Routines which do not return an integer may never fail. 759.Sh SEE ALSO 760.Xr rump 3 761.Rs 762.%A Antti Kantee 763.%D 2012 764.%J Aalto University Doctoral Dissertations 765.%T Flexible Operating System Internals: The Design and Implementation of the Anykernel and Rump Kernels 766.%O Section 2.3.2: The Hypercall Interface 767.Re 768.Pp 769For a list of all known implementations of the 770.Nm 771interface, see 772.Lk https://github.com/rumpkernel/wiki/wiki/Platforms . 773.Sh HISTORY 774The rump kernel hypercall API was first introduced in 775.Nx 5.0 . 776The API described above first appeared in 777.Nx 7.0 . 778