18c2ecf20Sopenharmony_ci================= 28c2ecf20Sopenharmony_ciKVM VCPU Requests 38c2ecf20Sopenharmony_ci================= 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciOverview 68c2ecf20Sopenharmony_ci======== 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ciKVM supports an internal API enabling threads to request a VCPU thread to 98c2ecf20Sopenharmony_ciperform some activity. For example, a thread may request a VCPU to flush 108c2ecf20Sopenharmony_ciits TLB with a VCPU request. The API consists of the following functions:: 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci /* Check if any requests are pending for VCPU @vcpu. */ 138c2ecf20Sopenharmony_ci bool kvm_request_pending(struct kvm_vcpu *vcpu); 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci /* Check if VCPU @vcpu has request @req pending. */ 168c2ecf20Sopenharmony_ci bool kvm_test_request(int req, struct kvm_vcpu *vcpu); 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci /* Clear request @req for VCPU @vcpu. */ 198c2ecf20Sopenharmony_ci void kvm_clear_request(int req, struct kvm_vcpu *vcpu); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci /* 228c2ecf20Sopenharmony_ci * Check if VCPU @vcpu has request @req pending. When the request is 238c2ecf20Sopenharmony_ci * pending it will be cleared and a memory barrier, which pairs with 248c2ecf20Sopenharmony_ci * another in kvm_make_request(), will be issued. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci bool kvm_check_request(int req, struct kvm_vcpu *vcpu); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci /* 298c2ecf20Sopenharmony_ci * Make request @req of VCPU @vcpu. Issues a memory barrier, which pairs 308c2ecf20Sopenharmony_ci * with another in kvm_check_request(), prior to setting the request. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci void kvm_make_request(int req, struct kvm_vcpu *vcpu); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci /* Make request @req of all VCPUs of the VM with struct kvm @kvm. */ 358c2ecf20Sopenharmony_ci bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciTypically a requester wants the VCPU to perform the activity as soon 388c2ecf20Sopenharmony_cias possible after making the request. This means most requests 398c2ecf20Sopenharmony_ci(kvm_make_request() calls) are followed by a call to kvm_vcpu_kick(), 408c2ecf20Sopenharmony_ciand kvm_make_all_cpus_request() has the kicking of all VCPUs built 418c2ecf20Sopenharmony_ciinto it. 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciVCPU Kicks 448c2ecf20Sopenharmony_ci---------- 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ciThe goal of a VCPU kick is to bring a VCPU thread out of guest mode in 478c2ecf20Sopenharmony_ciorder to perform some KVM maintenance. To do so, an IPI is sent, forcing 488c2ecf20Sopenharmony_cia guest mode exit. However, a VCPU thread may not be in guest mode at the 498c2ecf20Sopenharmony_citime of the kick. Therefore, depending on the mode and state of the VCPU 508c2ecf20Sopenharmony_cithread, there are two other actions a kick may take. All three actions 518c2ecf20Sopenharmony_ciare listed below: 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci1) Send an IPI. This forces a guest mode exit. 548c2ecf20Sopenharmony_ci2) Waking a sleeping VCPU. Sleeping VCPUs are VCPU threads outside guest 558c2ecf20Sopenharmony_ci mode that wait on waitqueues. Waking them removes the threads from 568c2ecf20Sopenharmony_ci the waitqueues, allowing the threads to run again. This behavior 578c2ecf20Sopenharmony_ci may be suppressed, see KVM_REQUEST_NO_WAKEUP below. 588c2ecf20Sopenharmony_ci3) Nothing. When the VCPU is not in guest mode and the VCPU thread is not 598c2ecf20Sopenharmony_ci sleeping, then there is nothing to do. 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciVCPU Mode 628c2ecf20Sopenharmony_ci--------- 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciVCPUs have a mode state, ``vcpu->mode``, that is used to track whether the 658c2ecf20Sopenharmony_ciguest is running in guest mode or not, as well as some specific 668c2ecf20Sopenharmony_cioutside guest mode states. The architecture may use ``vcpu->mode`` to 678c2ecf20Sopenharmony_ciensure VCPU requests are seen by VCPUs (see "Ensuring Requests Are Seen"), 688c2ecf20Sopenharmony_cias well as to avoid sending unnecessary IPIs (see "IPI Reduction"), and 698c2ecf20Sopenharmony_cieven to ensure IPI acknowledgements are waited upon (see "Waiting for 708c2ecf20Sopenharmony_ciAcknowledgements"). The following modes are defined: 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ciOUTSIDE_GUEST_MODE 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci The VCPU thread is outside guest mode. 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciIN_GUEST_MODE 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci The VCPU thread is in guest mode. 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ciEXITING_GUEST_MODE 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci The VCPU thread is transitioning from IN_GUEST_MODE to 838c2ecf20Sopenharmony_ci OUTSIDE_GUEST_MODE. 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciREADING_SHADOW_PAGE_TABLES 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci The VCPU thread is outside guest mode, but it wants the sender of 888c2ecf20Sopenharmony_ci certain VCPU requests, namely KVM_REQ_TLB_FLUSH, to wait until the VCPU 898c2ecf20Sopenharmony_ci thread is done reading the page tables. 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ciVCPU Request Internals 928c2ecf20Sopenharmony_ci====================== 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciVCPU requests are simply bit indices of the ``vcpu->requests`` bitmap. 958c2ecf20Sopenharmony_ciThis means general bitops, like those documented in [atomic-ops]_ could 968c2ecf20Sopenharmony_cialso be used, e.g. :: 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci clear_bit(KVM_REQ_UNHALT & KVM_REQUEST_MASK, &vcpu->requests); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ciHowever, VCPU request users should refrain from doing so, as it would 1018c2ecf20Sopenharmony_cibreak the abstraction. The first 8 bits are reserved for architecture 1028c2ecf20Sopenharmony_ciindependent requests, all additional bits are available for architecture 1038c2ecf20Sopenharmony_cidependent requests. 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciArchitecture Independent Requests 1068c2ecf20Sopenharmony_ci--------------------------------- 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciKVM_REQ_TLB_FLUSH 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci KVM's common MMU notifier may need to flush all of a guest's TLB 1118c2ecf20Sopenharmony_ci entries, calling kvm_flush_remote_tlbs() to do so. Architectures that 1128c2ecf20Sopenharmony_ci choose to use the common kvm_flush_remote_tlbs() implementation will 1138c2ecf20Sopenharmony_ci need to handle this VCPU request. 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciKVM_REQ_MMU_RELOAD 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci When shadow page tables are used and memory slots are removed it's 1188c2ecf20Sopenharmony_ci necessary to inform each VCPU to completely refresh the tables. This 1198c2ecf20Sopenharmony_ci request is used for that. 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciKVM_REQ_PENDING_TIMER 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci This request may be made from a timer handler run on the host on behalf 1248c2ecf20Sopenharmony_ci of a VCPU. It informs the VCPU thread to inject a timer interrupt. 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ciKVM_REQ_UNHALT 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci This request may be made from the KVM common function kvm_vcpu_block(), 1298c2ecf20Sopenharmony_ci which is used to emulate an instruction that causes a CPU to halt until 1308c2ecf20Sopenharmony_ci one of an architectural specific set of events and/or interrupts is 1318c2ecf20Sopenharmony_ci received (determined by checking kvm_arch_vcpu_runnable()). When that 1328c2ecf20Sopenharmony_ci event or interrupt arrives kvm_vcpu_block() makes the request. This is 1338c2ecf20Sopenharmony_ci in contrast to when kvm_vcpu_block() returns due to any other reason, 1348c2ecf20Sopenharmony_ci such as a pending signal, which does not indicate the VCPU's halt 1358c2ecf20Sopenharmony_ci emulation should stop, and therefore does not make the request. 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciKVM_REQUEST_MASK 1388c2ecf20Sopenharmony_ci---------------- 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ciVCPU requests should be masked by KVM_REQUEST_MASK before using them with 1418c2ecf20Sopenharmony_cibitops. This is because only the lower 8 bits are used to represent the 1428c2ecf20Sopenharmony_cirequest's number. The upper bits are used as flags. Currently only two 1438c2ecf20Sopenharmony_ciflags are defined. 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ciVCPU Request Flags 1468c2ecf20Sopenharmony_ci------------------ 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ciKVM_REQUEST_NO_WAKEUP 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci This flag is applied to requests that only need immediate attention 1518c2ecf20Sopenharmony_ci from VCPUs running in guest mode. That is, sleeping VCPUs do not need 1528c2ecf20Sopenharmony_ci to be awaken for these requests. Sleeping VCPUs will handle the 1538c2ecf20Sopenharmony_ci requests when they are awaken later for some other reason. 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ciKVM_REQUEST_WAIT 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci When requests with this flag are made with kvm_make_all_cpus_request(), 1588c2ecf20Sopenharmony_ci then the caller will wait for each VCPU to acknowledge its IPI before 1598c2ecf20Sopenharmony_ci proceeding. This flag only applies to VCPUs that would receive IPIs. 1608c2ecf20Sopenharmony_ci If, for example, the VCPU is sleeping, so no IPI is necessary, then 1618c2ecf20Sopenharmony_ci the requesting thread does not wait. This means that this flag may be 1628c2ecf20Sopenharmony_ci safely combined with KVM_REQUEST_NO_WAKEUP. See "Waiting for 1638c2ecf20Sopenharmony_ci Acknowledgements" for more information about requests with 1648c2ecf20Sopenharmony_ci KVM_REQUEST_WAIT. 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ciVCPU Requests with Associated State 1678c2ecf20Sopenharmony_ci=================================== 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciRequesters that want the receiving VCPU to handle new state need to ensure 1708c2ecf20Sopenharmony_cithe newly written state is observable to the receiving VCPU thread's CPU 1718c2ecf20Sopenharmony_ciby the time it observes the request. This means a write memory barrier 1728c2ecf20Sopenharmony_cimust be inserted after writing the new state and before setting the VCPU 1738c2ecf20Sopenharmony_cirequest bit. Additionally, on the receiving VCPU thread's side, a 1748c2ecf20Sopenharmony_cicorresponding read barrier must be inserted after reading the request bit 1758c2ecf20Sopenharmony_ciand before proceeding to read the new state associated with it. See 1768c2ecf20Sopenharmony_ciscenario 3, Message and Flag, of [lwn-mb]_ and the kernel documentation 1778c2ecf20Sopenharmony_ci[memory-barriers]_. 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ciThe pair of functions, kvm_check_request() and kvm_make_request(), provide 1808c2ecf20Sopenharmony_cithe memory barriers, allowing this requirement to be handled internally by 1818c2ecf20Sopenharmony_cithe API. 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciEnsuring Requests Are Seen 1848c2ecf20Sopenharmony_ci========================== 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ciWhen making requests to VCPUs, we want to avoid the receiving VCPU 1878c2ecf20Sopenharmony_ciexecuting in guest mode for an arbitrary long time without handling the 1888c2ecf20Sopenharmony_cirequest. We can be sure this won't happen as long as we ensure the VCPU 1898c2ecf20Sopenharmony_cithread checks kvm_request_pending() before entering guest mode and that a 1908c2ecf20Sopenharmony_cikick will send an IPI to force an exit from guest mode when necessary. 1918c2ecf20Sopenharmony_ciExtra care must be taken to cover the period after the VCPU thread's last 1928c2ecf20Sopenharmony_cikvm_request_pending() check and before it has entered guest mode, as kick 1938c2ecf20Sopenharmony_ciIPIs will only trigger guest mode exits for VCPU threads that are in guest 1948c2ecf20Sopenharmony_cimode or at least have already disabled interrupts in order to prepare to 1958c2ecf20Sopenharmony_cienter guest mode. This means that an optimized implementation (see "IPI 1968c2ecf20Sopenharmony_ciReduction") must be certain when it's safe to not send the IPI. One 1978c2ecf20Sopenharmony_cisolution, which all architectures except s390 apply, is to: 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci- set ``vcpu->mode`` to IN_GUEST_MODE between disabling the interrupts and 2008c2ecf20Sopenharmony_ci the last kvm_request_pending() check; 2018c2ecf20Sopenharmony_ci- enable interrupts atomically when entering the guest. 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ciThis solution also requires memory barriers to be placed carefully in both 2048c2ecf20Sopenharmony_cithe requesting thread and the receiving VCPU. With the memory barriers we 2058c2ecf20Sopenharmony_cican exclude the possibility of a VCPU thread observing 2068c2ecf20Sopenharmony_ci!kvm_request_pending() on its last check and then not receiving an IPI for 2078c2ecf20Sopenharmony_cithe next request made of it, even if the request is made immediately after 2088c2ecf20Sopenharmony_cithe check. This is done by way of the Dekker memory barrier pattern 2098c2ecf20Sopenharmony_ci(scenario 10 of [lwn-mb]_). As the Dekker pattern requires two variables, 2108c2ecf20Sopenharmony_cithis solution pairs ``vcpu->mode`` with ``vcpu->requests``. Substituting 2118c2ecf20Sopenharmony_cithem into the pattern gives:: 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci CPU1 CPU2 2148c2ecf20Sopenharmony_ci ================= ================= 2158c2ecf20Sopenharmony_ci local_irq_disable(); 2168c2ecf20Sopenharmony_ci WRITE_ONCE(vcpu->mode, IN_GUEST_MODE); kvm_make_request(REQ, vcpu); 2178c2ecf20Sopenharmony_ci smp_mb(); smp_mb(); 2188c2ecf20Sopenharmony_ci if (kvm_request_pending(vcpu)) { if (READ_ONCE(vcpu->mode) == 2198c2ecf20Sopenharmony_ci IN_GUEST_MODE) { 2208c2ecf20Sopenharmony_ci ...abort guest entry... ...send IPI... 2218c2ecf20Sopenharmony_ci } } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciAs stated above, the IPI is only useful for VCPU threads in guest mode or 2248c2ecf20Sopenharmony_cithat have already disabled interrupts. This is why this specific case of 2258c2ecf20Sopenharmony_cithe Dekker pattern has been extended to disable interrupts before setting 2268c2ecf20Sopenharmony_ci``vcpu->mode`` to IN_GUEST_MODE. WRITE_ONCE() and READ_ONCE() are used to 2278c2ecf20Sopenharmony_cipedantically implement the memory barrier pattern, guaranteeing the 2288c2ecf20Sopenharmony_cicompiler doesn't interfere with ``vcpu->mode``'s carefully planned 2298c2ecf20Sopenharmony_ciaccesses. 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciIPI Reduction 2328c2ecf20Sopenharmony_ci------------- 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ciAs only one IPI is needed to get a VCPU to check for any/all requests, 2358c2ecf20Sopenharmony_cithen they may be coalesced. This is easily done by having the first IPI 2368c2ecf20Sopenharmony_cisending kick also change the VCPU mode to something !IN_GUEST_MODE. The 2378c2ecf20Sopenharmony_citransitional state, EXITING_GUEST_MODE, is used for this purpose. 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ciWaiting for Acknowledgements 2408c2ecf20Sopenharmony_ci---------------------------- 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ciSome requests, those with the KVM_REQUEST_WAIT flag set, require IPIs to 2438c2ecf20Sopenharmony_cibe sent, and the acknowledgements to be waited upon, even when the target 2448c2ecf20Sopenharmony_ciVCPU threads are in modes other than IN_GUEST_MODE. For example, one case 2458c2ecf20Sopenharmony_ciis when a target VCPU thread is in READING_SHADOW_PAGE_TABLES mode, which 2468c2ecf20Sopenharmony_ciis set after disabling interrupts. To support these cases, the 2478c2ecf20Sopenharmony_ciKVM_REQUEST_WAIT flag changes the condition for sending an IPI from 2488c2ecf20Sopenharmony_cichecking that the VCPU is IN_GUEST_MODE to checking that it is not 2498c2ecf20Sopenharmony_ciOUTSIDE_GUEST_MODE. 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ciRequest-less VCPU Kicks 2528c2ecf20Sopenharmony_ci----------------------- 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ciAs the determination of whether or not to send an IPI depends on the 2558c2ecf20Sopenharmony_citwo-variable Dekker memory barrier pattern, then it's clear that 2568c2ecf20Sopenharmony_cirequest-less VCPU kicks are almost never correct. Without the assurance 2578c2ecf20Sopenharmony_cithat a non-IPI generating kick will still result in an action by the 2588c2ecf20Sopenharmony_cireceiving VCPU, as the final kvm_request_pending() check does for 2598c2ecf20Sopenharmony_cirequest-accompanying kicks, then the kick may not do anything useful at 2608c2ecf20Sopenharmony_ciall. If, for instance, a request-less kick was made to a VCPU that was 2618c2ecf20Sopenharmony_cijust about to set its mode to IN_GUEST_MODE, meaning no IPI is sent, then 2628c2ecf20Sopenharmony_cithe VCPU thread may continue its entry without actually having done 2638c2ecf20Sopenharmony_ciwhatever it was the kick was meant to initiate. 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciOne exception is x86's posted interrupt mechanism. In this case, however, 2668c2ecf20Sopenharmony_cieven the request-less VCPU kick is coupled with the same 2678c2ecf20Sopenharmony_cilocal_irq_disable() + smp_mb() pattern described above; the ON bit 2688c2ecf20Sopenharmony_ci(Outstanding Notification) in the posted interrupt descriptor takes the 2698c2ecf20Sopenharmony_cirole of ``vcpu->requests``. When sending a posted interrupt, PIR.ON is 2708c2ecf20Sopenharmony_ciset before reading ``vcpu->mode``; dually, in the VCPU thread, 2718c2ecf20Sopenharmony_civmx_sync_pir_to_irr() reads PIR after setting ``vcpu->mode`` to 2728c2ecf20Sopenharmony_ciIN_GUEST_MODE. 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciAdditional Considerations 2758c2ecf20Sopenharmony_ci========================= 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ciSleeping VCPUs 2788c2ecf20Sopenharmony_ci-------------- 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ciVCPU threads may need to consider requests before and/or after calling 2818c2ecf20Sopenharmony_cifunctions that may put them to sleep, e.g. kvm_vcpu_block(). Whether they 2828c2ecf20Sopenharmony_cido or not, and, if they do, which requests need consideration, is 2838c2ecf20Sopenharmony_ciarchitecture dependent. kvm_vcpu_block() calls kvm_arch_vcpu_runnable() 2848c2ecf20Sopenharmony_cito check if it should awaken. One reason to do so is to provide 2858c2ecf20Sopenharmony_ciarchitectures a function where requests may be checked if necessary. 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ciClearing Requests 2888c2ecf20Sopenharmony_ci----------------- 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ciGenerally it only makes sense for the receiving VCPU thread to clear a 2918c2ecf20Sopenharmony_cirequest. However, in some circumstances, such as when the requesting 2928c2ecf20Sopenharmony_cithread and the receiving VCPU thread are executed serially, such as when 2938c2ecf20Sopenharmony_cithey are the same thread, or when they are using some form of concurrency 2948c2ecf20Sopenharmony_cicontrol to temporarily execute synchronously, then it's possible to know 2958c2ecf20Sopenharmony_cithat the request may be cleared immediately, rather than waiting for the 2968c2ecf20Sopenharmony_cireceiving VCPU thread to handle the request in VCPU RUN. The only current 2978c2ecf20Sopenharmony_ciexamples of this are kvm_vcpu_block() calls made by VCPUs to block 2988c2ecf20Sopenharmony_cithemselves. A possible side-effect of that call is to make the 2998c2ecf20Sopenharmony_ciKVM_REQ_UNHALT request, which may then be cleared immediately when the 3008c2ecf20Sopenharmony_ciVCPU returns from the call. 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ciReferences 3038c2ecf20Sopenharmony_ci========== 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci.. [atomic-ops] Documentation/core-api/atomic_ops.rst 3068c2ecf20Sopenharmony_ci.. [memory-barriers] Documentation/memory-barriers.txt 3078c2ecf20Sopenharmony_ci.. [lwn-mb] https://lwn.net/Articles/573436/ 308