| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 
|  | 2 | #ifndef _XEN_MULTICALLS_H | 
|  | 3 | #define _XEN_MULTICALLS_H | 
|  | 4 |  | 
|  | 5 | #include <trace/events/xen.h> | 
|  | 6 |  | 
|  | 7 | #include "xen-ops.h" | 
|  | 8 |  | 
|  | 9 | /* Multicalls */ | 
|  | 10 | struct multicall_space | 
|  | 11 | { | 
|  | 12 | struct multicall_entry *mc; | 
|  | 13 | void *args; | 
|  | 14 | }; | 
|  | 15 |  | 
|  | 16 | /* Allocate room for a multicall and its args */ | 
|  | 17 | struct multicall_space __xen_mc_entry(size_t args); | 
|  | 18 |  | 
|  | 19 | DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags); | 
|  | 20 |  | 
|  | 21 | /* Call to start a batch of multiple __xen_mc_entry()s.  Must be | 
|  | 22 | paired with xen_mc_issue() */ | 
|  | 23 | static inline void xen_mc_batch(void) | 
|  | 24 | { | 
|  | 25 | unsigned long flags; | 
|  | 26 |  | 
|  | 27 | /* need to disable interrupts until this entry is complete */ | 
|  | 28 | local_irq_save(flags); | 
|  | 29 | trace_xen_mc_batch(paravirt_get_lazy_mode()); | 
|  | 30 | __this_cpu_write(xen_mc_irq_flags, flags); | 
|  | 31 | } | 
|  | 32 |  | 
|  | 33 | static inline struct multicall_space xen_mc_entry(size_t args) | 
|  | 34 | { | 
|  | 35 | xen_mc_batch(); | 
|  | 36 | return __xen_mc_entry(args); | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | /* Flush all pending multicalls */ | 
|  | 40 | void xen_mc_flush(void); | 
|  | 41 |  | 
|  | 42 | /* Issue a multicall if we're not in a lazy mode */ | 
|  | 43 | static inline void xen_mc_issue(unsigned mode) | 
|  | 44 | { | 
|  | 45 | trace_xen_mc_issue(mode); | 
|  | 46 |  | 
|  | 47 | if ((paravirt_get_lazy_mode() & mode) == 0) | 
|  | 48 | xen_mc_flush(); | 
|  | 49 |  | 
|  | 50 | /* restore flags saved in xen_mc_batch */ | 
|  | 51 | local_irq_restore(this_cpu_read(xen_mc_irq_flags)); | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | /* Set up a callback to be called when the current batch is flushed */ | 
|  | 55 | void xen_mc_callback(void (*fn)(void *), void *data); | 
|  | 56 |  | 
|  | 57 | /* | 
|  | 58 | * Try to extend the arguments of the previous multicall command.  The | 
|  | 59 | * previous command's op must match.  If it does, then it attempts to | 
|  | 60 | * extend the argument space allocated to the multicall entry by | 
|  | 61 | * arg_size bytes. | 
|  | 62 | * | 
|  | 63 | * The returned multicall_space will return with mc pointing to the | 
|  | 64 | * command on success, or NULL on failure, and args pointing to the | 
|  | 65 | * newly allocated space. | 
|  | 66 | */ | 
|  | 67 | struct multicall_space xen_mc_extend_args(unsigned long op, size_t arg_size); | 
|  | 68 |  | 
|  | 69 | #endif /* _XEN_MULTICALLS_H */ |