diff options
-rw-r--r-- | arch/x86/lguest/boot.c | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index e6023b86f31d..92c56117eae5 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
@@ -93,27 +93,7 @@ struct lguest_data lguest_data = { | |||
93 | }; | 93 | }; |
94 | static cycle_t clock_base; | 94 | static cycle_t clock_base; |
95 | 95 | ||
96 | /*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first | 96 | /*G:037 async_hcall() is pretty simple: I'm quite proud of it really. We have a |
97 | * real optimization trick! | ||
98 | * | ||
99 | * When lazy_mode is set, it means we're allowed to defer all hypercalls and do | ||
100 | * them as a batch when lazy_mode is eventually turned off. Because hypercalls | ||
101 | * are reasonably expensive, batching them up makes sense. For example, a | ||
102 | * large munmap might update dozens of page table entries: that code calls | ||
103 | * paravirt_enter_lazy_mmu(), does the dozen updates, then calls | ||
104 | * lguest_leave_lazy_mode(). | ||
105 | * | ||
106 | * So, when we're in lazy mode, we call async_hypercall() to store the call for | ||
107 | * future processing. When lazy mode is turned off we issue a hypercall to | ||
108 | * flush the stored calls. | ||
109 | */ | ||
110 | static void lguest_leave_lazy_mode(void) | ||
111 | { | ||
112 | paravirt_leave_lazy(paravirt_get_lazy_mode()); | ||
113 | hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0); | ||
114 | } | ||
115 | |||
116 | /* async_hcall() is pretty simple: I'm quite proud of it really. We have a | ||
117 | * ring buffer of stored hypercalls which the Host will run though next time we | 97 | * ring buffer of stored hypercalls which the Host will run though next time we |
118 | * do a normal hypercall. Each entry in the ring has 4 slots for the hypercall | 98 | * do a normal hypercall. Each entry in the ring has 4 slots for the hypercall |
119 | * arguments, and a "hcall_status" word which is 0 if the call is ready to go, | 99 | * arguments, and a "hcall_status" word which is 0 if the call is ready to go, |
@@ -151,6 +131,18 @@ static void async_hcall(unsigned long call, unsigned long arg1, | |||
151 | local_irq_restore(flags); | 131 | local_irq_restore(flags); |
152 | } | 132 | } |
153 | 133 | ||
134 | /*G:035 Notice the lazy_hcall() above, rather than hcall(). This is our first | ||
135 | * real optimization trick! | ||
136 | * | ||
137 | * When lazy_mode is set, it means we're allowed to defer all hypercalls and do | ||
138 | * them as a batch when lazy_mode is eventually turned off. Because hypercalls | ||
139 | * are reasonably expensive, batching them up makes sense. For example, a | ||
140 | * large munmap might update dozens of page table entries: that code calls | ||
141 | * paravirt_enter_lazy_mmu(), does the dozen updates, then calls | ||
142 | * lguest_leave_lazy_mode(). | ||
143 | * | ||
144 | * So, when we're in lazy mode, we call async_hcall() to store the call for | ||
145 | * future processing. */ | ||
154 | static void lazy_hcall(unsigned long call, | 146 | static void lazy_hcall(unsigned long call, |
155 | unsigned long arg1, | 147 | unsigned long arg1, |
156 | unsigned long arg2, | 148 | unsigned long arg2, |
@@ -161,7 +153,14 @@ static void lazy_hcall(unsigned long call, | |||
161 | else | 153 | else |
162 | async_hcall(call, arg1, arg2, arg3); | 154 | async_hcall(call, arg1, arg2, arg3); |
163 | } | 155 | } |
164 | /*:*/ | 156 | |
157 | /* When lazy mode is turned off reset the per-cpu lazy mode variable and then | ||
158 | * issue a hypercall to flush any stored calls. */ | ||
159 | static void lguest_leave_lazy_mode(void) | ||
160 | { | ||
161 | paravirt_leave_lazy(paravirt_get_lazy_mode()); | ||
162 | hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0); | ||
163 | } | ||
165 | 164 | ||
166 | /*G:033 | 165 | /*G:033 |
167 | * After that diversion we return to our first native-instruction | 166 | * After that diversion we return to our first native-instruction |