forked from OpenXT/xc-windows
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xsapi.h
1285 lines (1195 loc) · 53.1 KB
/
xsapi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 2010 Citrix Systems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* All of the supported APIs exported by xevtchn.sys in one convenient
* place. There are a bunch of others which are special-case hooks
* for xenvbd and xennet, but they shouldn't be used by anyone
* else. */
#ifndef XSAPI_H__
#define XSAPI_H__
#include "wrapper_types.h"
#include "types.h"
#include "specstrings.h"
#ifndef XSAPI
#define XSAPI DECLSPEC_IMPORT
#endif
/* Described later, under ``suspend handlers''. */
MAKE_WRAPPER_PUB(SUSPEND_TOKEN)
/* The state of either end of the Xenbus, i.e. the current communication
status of initialisation across the bus. States here imply nothing about
the state of the connection between the driver and the kernel's device
layers. */
MAKE_WRAPPER_PUB(XENBUS_STATE)
MAKE_WRAPPER_PRIV(XENBUS_STATE, int)
#define _XENBUS_STATE_INITIALISING 1
#define XENBUS_STATE_INITIALISING wrap_XENBUS_STATE(_XENBUS_STATE_INITIALISING)
/* Finished early initialisation, but waiting for information from the
peer or hotplug scripts. */
#define _XENBUS_STATE_INITWAIT 2
#define XENBUS_STATE_INITWAIT wrap_XENBUS_STATE(_XENBUS_STATE_INITWAIT)
/* Initialised and waiting for a connection from the peer. */
#define _XENBUS_STATE_INITIALISED 3
#define XENBUS_STATE_INITIALISED wrap_XENBUS_STATE(_XENBUS_STATE_INITIALISED)
#define _XENBUS_STATE_CONNECTED 4
#define XENBUS_STATE_CONNECTED wrap_XENBUS_STATE(_XENBUS_STATE_CONNECTED)
/* The device is being closed due to an error or an unplug event. */
#define _XENBUS_STATE_CLOSING 5
#define XENBUS_STATE_CLOSING wrap_XENBUS_STATE(_XENBUS_STATE_CLOSING)
#define _XENBUS_STATE_CLOSED 6
#define XENBUS_STATE_CLOSED wrap_XENBUS_STATE(_XENBUS_STATE_CLOSED)
/* Compare two XENBUS_STATEs. Returns TRUE if @a and @b represent
* the same xenbus state, or if they're both null, and FALSE otherwise.
*
* Can be called at any IRQL holding any combination of locks.
*/
static __inline BOOLEAN
same_XENBUS_STATE(XENBUS_STATE a, XENBUS_STATE b)
{
if (unwrap_XENBUS_STATE(a) == unwrap_XENBUS_STATE(b))
return TRUE;
else
return FALSE;
}
/* ----------------------- Initialisation -------------------------- */
/* Wait for the PV drivers to finish initialisation. Returns TRUE
* if the drivers are now available, or FALSE if initialisation
* failed.
*
* Clients should wait for initialisation when they first load and
* after recovering from hibernation. They do not have to wait
* following dom0-driven suspend/resume.
*
* Clients should not call any other APIs defined in this header until
* this has returned TRUE.
*
* Call at PASSIVE_LEVEL.
*/
XSAPI BOOLEAN xenbus_await_initialisation(void);
/* ----------------------- Domain ID type -------------------------- */
/* A special type for domain IDs. The aim here is to make it obvious
* if someone's assumed that backends are always in dom0. */
MAKE_WRAPPER_PUB(DOMAIN_ID)
__MAKE_WRAPPER_PRIV(DOMAIN_ID, int)
/* Take an int and turn it into a DOMAIN_ID. The 0xf001 is to make
* uninitialised domain ids obvious. I specifically don't want an
* uninitialised id to show up as 0, since that's almost, but not
* quite, always the right answer, so is unlikely to get spotted. */
static __inline DOMAIN_ID wrap_DOMAIN_ID(int x)
{
return __wrap_DOMAIN_ID(x ^ 0xf001);
}
/* Given a DOMAIN_ID, return the integer domain id */
static __inline int unwrap_DOMAIN_ID(DOMAIN_ID x)
{
return __unwrap_DOMAIN_ID(x) ^ 0xf001;
}
/* Construct a DOMAIN_ID for dom0. */
#define DOMAIN_ID_0() wrap_DOMAIN_ID(0)
/* --------------------------- Xenbus ------------------------------ */
/* All xenbus operations can, at present, be invoked at IRQL <=
* DISPATCH_LEVEL. I'd be happier if I could restrict that to
* PASSIVE_LEVEL, though. */
/* Any operations performed inside a transaction will be exposed to
* other domains atomically when the transaction ends (assuming it was
* successful). If any operation inside a transaction fails, the
* whole transaction fails with the same error code. These are not
* the semantics which most people expect, and they are not those
* exposed by the Linux equivalents of this API, but they do
* drastically simplify error handling logic in most callers of it.
*
* xenbus_read() and xenbus_ls() operations performed inside a
* transaction can, sometimes, invent results which have never
* appeared in the store. If this happens, the transaction will
* always fail to commit, returning either STATUS_RETRY if no other
* error occurs or an appropriate error value if one does.
*
* Most operations can be performed with a null transaction, including
* xenbus_transaction_end(), in which case they return
* STATUS_INSUFFICIENT_RESOURCES.
*/
MAKE_WRAPPER_PUB(xenbus_transaction_t)
struct xenbus_transaction;
__MAKE_WRAPPER_PRIV(xenbus_transaction_t, struct xenbus_transaction *)
/* The nil transaction. Operations performed in this transaction are
* exposed immediately and do not need an explicit transaction_end.
* They are still atomic, however.
*
* Note that this is *not* the null transaction, which is reserved
* for error situations.
*/
#define XBT_NIL __wrap_xenbus_transaction_t((struct xenbus_transaction *)1)
/* Check whether a transaction is XBT_NIL. Returns TRUE if @xbt is
* XBT_NIL, and FALSE otherwise.
*
* @xbt can be null, nil, or a valid transaction.
*
* Added in XE 4.1.
*/
static __inline BOOLEAN
is_nil_xenbus_transaction_t(xenbus_transaction_t xbt)
{
if (__unwrap_xenbus_transaction_t(xbt) ==
(struct xenbus_transaction *)1)
return TRUE;
else
return FALSE;
}
/* Start a new transaction. Returns the new transaction at *@Res.
* This function always succeeds, and the returned transaction must
* always be finished by xenbus_transaction_end().
*
#ifdef XSAPI_LEGACY_XENBUS_TRANSACTION_START_RETURNS_NTSTATUS
* The return value is somewhat subtle. xenbus_transaction_start()
* will always open a new transaction, and must therefore always be
* followed by a call to xenbus_transaction_end(). However,
* xenbus_transaction_start() may sometimes be able to detect that the
* transaction is in some sense doomed to fail, and in that case it
* will return a non-NT_SUCCESS() value which is the expected result
* of trying to call xenbus_transaction_end() and committing the
* transaction. This is intended to allow the caller to optimise by
* avoiding any time-consuming actions which will then be discarded
* when the transaction aborts. The caller is never required to look
* at the return value of this function to achieve simple
* correctness.
#endif
*/
XSAPI NTSTATUS __xenbus_transaction_start_ntstatus(__out xenbus_transaction_t *Res);
XSAPI VOID __xenbus_transaction_start_void(__in const char *caller, __out xenbus_transaction_t *Res);
#ifdef XSAPI_LEGACY_XENBUS_TRANSACTION_START_RETURNS_NTSTATUS
#define xenbus_transaction_start(_xbt) __xenbus_transaction_start_ntstatus(_xbt)
#else
#define xenbus_transaction_start(_xbt) __xenbus_transaction_start_void(__FUNCTION__, (_xbt))
#endif
/* End a transaction. If @abort is 0, the transaction is committed;
* otherwise, it is aborted, and no operations performed under it
* will be visible to other users of the store. This can return
* STATUS_RETRY if some other domain made a conflicting update to
* the store, in which case the caller should try the transaction
* again.
*
* Even when this returns failure, the transaction is still finished,
* and should not be used again.
*
* @t can be null but not nil.
*/
__checkReturn XSAPI NTSTATUS __xenbus_transaction_end_anonymous(xenbus_transaction_t t, int abort);
__checkReturn XSAPI NTSTATUS __xenbus_transaction_end(const char *caller,
xenbus_transaction_t t,
int abort);
#define xenbus_transaction_end(_xbt, _abort) \
__xenbus_transaction_end(__FUNCTION__, (_xbt), (_abort))
/* XXX These should take a prefix and a node, rather than just a
path. */
/* Write the nul-terminated string @data to @path as part of transaction
* @xbt.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_write(xenbus_transaction_t xbt, PCSTR path, PCSTR data);
/* Write @size bytes from @data to @path/@node as part of transaction
* @xbt.
*
* @path, @node, and @data must point at valid globally-mapped
* non-pageable memory.
*
* @data can contain arbitrary binary data, including embedded nuls.
*
* @xbt can be null, nil, or a valid transaction.
*
* Added in XE 4.1
*/
XSAPI NTSTATUS xenbus_write_bin(xenbus_transaction_t xbt, PCSTR path,
PCSTR node, const void *data, size_t size);
/* Read a nul-terminated string from @path under transaction @xbt.
* The result is returned as a nul-terminated string at *@Res, and
* should be freed with XmFreeMemory() when you're finished with
* it.
*
* @path must point at valid globally-mapped non-pageable memory. The
* buffer returned through *@Res will be non-pageable and globally
* mapped.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_read(xenbus_transaction_t xbt, PCSTR path,
__out PSTR *Res);
/* Read arbitrary data from @path/@node under transaction @xbt. The
* result is returned as a newly-allocated buffer at *@Res, and should
* be freed with XmFreeMemory() when you're finished with it. The
* length of the buffer is returned in *@size.
*
* Note that *@Res is not guaranteed to be nul-terminated, and can
* contain embedded nuls. This is different from xenbus_read().
*
* @path and @node must point at valid globally-mapped non-pageable
* memory. The buffer returned through *@Res will be non-pageable and
* globally mapped.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_read_bin(xenbus_transaction_t xbt, PCSTR path,
PCSTR node, __out void **Res,
__out size_t *size);
/* List the sub-nodes of node @path under transaction @xbt. The
* result is returned as a NULL-terminated array of nul-terminated
* strings at *@Res. Both the array and the strings referred to
* should be released with XmFreeMemory().
*
* @path must point at valid globally-mapped non-pageable memory. The
* buffer returned through *@Res will be globally-mapped and
* non-pageable, as will all of the strings referenced by it.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_ls(xenbus_transaction_t xbt, PCSTR path,
__out PSTR **Res);
/* Interprets @fmt as a printf-style format string, processes it as
* for sprintf(), and writes the result to @prefix/@node under the
* transaction @xbt.
*
* @prefix, @node, @fmt, and any pointers in the argument list which
* must be dereferenced to interpret @fmt must point at valid
* globally-mapped non-pageable memory.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_printf(xenbus_transaction_t xbt, PCSTR prefix,
PCSTR node, PCSTR fmt, ...);
/* Read a decimal integer from @prefix/@node under transaction @xbt.
* The transaction is considered to have failed if this function
* encounters any errors, including errors parsing @prefix/@node.
*
* @prefix, @node, and @res must all point at valid globally-mapped
* non-pageable memory.
*
* @xbt can be null, nil, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_read_int(xenbus_transaction_t xbt, PCSTR prefix,
PCSTR node, ULONG64 *res);
/* Wait for a backend to leave state @state. @backend_path is the
* path to the backend area, and @timeout specifies a timeout with the
* same semantics as KeWaitForSingleObject. Returns the last observed
* backend state, or null_XENBUS_STATE() on error. Note that the
* return value could be @state if the wait times out.
*
* The caller must provide a suspend token, since the backend path is
* likely to change during dom0 suspend/resume.
*
* @backend_path must point at valid globally-mapped non-pageable
* memory. If @timeout is non-NULL, it must also point at
* non-pageable memory.
*
* Must be invoked at PASSIVE_LEVEL if the timeout is non-zero, and at
* IRQL <= DISPATCH_LEVEL otherwise.
*/
XSAPI XENBUS_STATE __XenbusWaitForBackendStateChangeAnonymous(PCSTR backend_path,
XENBUS_STATE state,
PLARGE_INTEGER timeout,
SUSPEND_TOKEN token);
XSAPI XENBUS_STATE __XenbusWaitForBackendStateChange(PCSTR caller,
PCSTR backend_path,
XENBUS_STATE state,
PLARGE_INTEGER timeout,
SUSPEND_TOKEN token);
#define XenbusWaitForBackendStateChange(_backend_path, _state, _timeout, _token) \
__XenbusWaitForBackendStateChange(__FUNCTION__, (_backend_path), (_state), (_timeout), (_token))
struct xenbus_watch_handler;
/* Register a watch on @path in xenstore. When @path changes, @cb
* will be invoked from the xenbus thread with arguments @path and
* @data. The watch infrastructure takes a copy of @path, and so the
* caller is free to release the storage used by its copy. Returns a
* pointer to a new watch handler structure on success, or NULL on
* error.
*
* It is guaranteed that the watch will fire shortly after any change
* to the node, barring errors. It is not guaranteed that it fire
* exactly once for every time the node is changed, or that it will
* only fire when the node changes.
*
* Watches are preserved across dom0-driven save/restore.
*
* Watch callbacks are run at PASSIVE_LEVEL from a system thread. Any
* single watch handler will only be invoked from one thread at a
* time.
*
* Implementation detail: At present, watch handlers are always run
* from the same thread. This means that only one handler can be
* active at any time. It is not guaranteed that this behaviour will
* be preserved in future versions.
*
* Returns NULL on error.
*
* NOTE: __xenbus_watch_path_anonymous() is defined for ABI compatibility.
* New code should use the xenbus_watch_path() macro.
*/
XSAPI __checkReturn struct xenbus_watch_handler *__xenbus_watch_path_anonymous(PCSTR path,
void (*cb)(void *data),
void *data);
XSAPI __checkReturn struct xenbus_watch_handler *__xenbus_watch_path(PCSTR path,
const char *cb_name,
void (*cb)(void *data),
void *data);
#define xenbus_watch_path(_path, _cb, _data) \
__xenbus_watch_path((_path), #_cb, (_cb), (_data));
/* Register a watch on @path in xenstore, and arrange that
* @evt is set whenever @path changes. No priority increment is
* applied.
*
* @path must point at valid non-pageable memory.
*
* @evt should usually be a notification event, rather than
* synchronisation. If a synchronisation event is used, note that
* rapid changes will sometimes only signal the event once. The event
* can be signalled when path is unchanged, although this should be
* rare. @evt should remain valid until the watch is release with
* xenbus_unregister_watch(). It is the caller's responsibility to
* release the memory occupied by the event at that time.
*
* Watches are preserved across dom0 save/restore.
*
* Returns NULL on error.
*/
XSAPI __checkReturn struct xenbus_watch_handler *xenbus_watch_path_event(PCSTR path,
struct _KEVENT *evt);
/* Re-direct a registered watch @wh so that it points at a new
* location @path
*
* Returns STATUS_SUCCESS on success, or something else on error. The
* watch continues to use the old path on error.
*
* Note that this function does not wait for the watch to complete
* before redirecting it, and so the watch can continue to fire on the
* old location after xenbus_redirect_watch() completes.
*
* Call at IRQL < DISPATCH_LEVEL.
*/
XSAPI __checkReturn NTSTATUS xenbus_redirect_watch(struct xenbus_watch_handler *wh,
PCSTR path);
/* Release a watch allocated by xenbus_watch_path. When this returns,
* it is guaranteed that the final invocation of the callback due to
* this watch has finished.
*
* This can be used to release watches allocated with either
* xenbus_watch_path() or xenbus_watch_path_event().
*
* Be careful when unregistering watches from a late suspend handler
* if the watch handler ever allocates a suspend token. Allocating a
* suspend token effectively waits for all suspend handlers to
* complete, and before unregistering a watch you must wait for the
* watch handler to complete, and so this can lead to deadlocks if the
* watch handler is in its very early stages when the suspend starts.
*
* @wh must not be null.
*
* Must be invoked at PASSIVE_LEVEL.
*/
XSAPI void xenbus_unregister_watch(struct xenbus_watch_handler *wh);
/* Read a XENBUS_STATE from the store at @prefix/@node under the
* transaction @xbt. Returns STATUS_DATA_ERROR and fails the
* transaction if @prefix/@node is readable but does not contain a
* valid XENBUS_STATE.
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* @xbt may be nil, null, or a valid transaction. @state should not
* be NULL.
*
* On error, *@state will be set to null_XENBUS_STATE().
*
* Must be invoked at IRQL <= DISPATCH_LEVEL.
*/
XSAPI NTSTATUS xenbus_read_state(xenbus_transaction_t xbt,
PCSTR prefix,
PCSTR node,
XENBUS_STATE *state);
/* Write the XENBUS_STATE @state to the store at @prefix/@node under
* the transaction @xbt, provided @prefix/@node already exists. If
* @prefix/@node does not exist, return STATUS_OBJECT_NAME_NOT_FOUND
* and fail the transaction.
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* @xbt may be nil, null, or a valid transaction. @state should not
* be null.
*
* Must be invoked at IRQL <= DISPATCH_LEVEL.
*/
XSAPI NTSTATUS xenbus_change_state(xenbus_transaction_t xbt,
PCSTR prefix,
PCSTR node,
XENBUS_STATE state);
/* Cause the watch @wh to fire soon in its normal context.
* @wh is triggered as if the thing which it is watching was modified.
*
* @wh must not be null.
*
* Must be invoked at PASSIVE_LEVEL.
*/
XSAPI void xenbus_trigger_watch(struct xenbus_watch_handler *wh);
/* Read a feature flag from the store at @prefix/@node, under the
* transaction @xbt. Sets @res to TRUE if the feature is available,
* and FALSE otherwise. The feature is considered unavailable if the
* node does not exist or if it exists and has the value 0. It is
* available if it exists and has the value 1. Anything else is
* considered an error.
*
* The transaction will not be aborted simply because the node is not
* present (unlike XenbusReadInteger or xenbus_read). It will be
* aborted as normal if there is any other error reading the node, or
* if the node does not have the value "0" or the value "1".
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* *@res is set to FALSE on failure.
*
* @xbt may be nil, null, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_read_feature_flag(xenbus_transaction_t xbt,
PCSTR prefix, PCSTR node,
BOOLEAN *res);
/* Set a flag in the store. Sets @prefix/@node to 1 if @res is TRUE
* and 0 if it is FALSE.
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* @xbt may be nil, null, or a valid transaction.
*/
XSAPI NTSTATUS xenbus_write_feature_flag(xenbus_transaction_t xbt,
PCSTR prefix, PCSTR node,
BOOLEAN res);
/* Read a domain ID from the store at @prefix/@node, under the
* transaction @xbt. Sets @res to the resulting domain ID, or
* null_DOMAIN_ID() on error.
*
* Domain IDs are represented in the store by base-10 integers between
* 0 and DOMID_FIRST_RESERVED-1, inclusive; if the value in the store
* cannot be parsed as such, or if it is out of range, the call fails,
* and so does the transaction.
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* @xbt may be nil, null, or a valid transaction.
*
* Added in XE 5.0.
*/
XSAPI NTSTATUS xenbus_read_domain_id(xenbus_transaction_t xbt,
PCSTR prefix, PCSTR node,
DOMAIN_ID *res);
/* ------------------ Xenbus enumerated devices -------------------- */
/* The xenbus driver enumerates devices in the device area of xenstore
* and presents them to the Windows PnP manager, which will then load
* suitable devices.
*
* For every directory ``device/${class}/${id}'', the bus driver will
* create a PDO as a child of itself. The PDO has instance ID ${id},
* hardware ID XEN\${class}, and a single device ID which is also
* XEN\${class}. For example, the PDO for device ``device/vfb/12''
* will have instance ID 12, and hardware and device IDs XEN\vfb.
* Clients can install drivers for these IDs via the usual Windows PnP
* mechanisms.
*
* Note that the vbd class is handled specially. Users of this
* library should not attempt to attach drivers to class vbd.
*
* The bus driver assumes that the frontend area will contain an entry
* called ``backend'' which contains the path to the backend area for
* the device, and that the backend area contains an entry called
* ``state'' which gives the current state of the backend device. The
* bus driver will send an EJECT PNP IRP to the device stack when the
* backend state changes to CLOSING, indicating that the frontend
* should close and unload. The PDO is still created if these xenbus
* nodes are not present, but hot-remove will not be supported.
*
* The frontend path for a given PDO can be extracted with
* xenbus_find_frontend(), and the backend with xenbus_find_backend().
* These must be invoked on the PDO *only*, or they will bugcheck.
*/
/* Given a Xenbus PDO, determine the frontend path for the device.
* Returns a newly-allocated nul-terminated string which should
* be release with XmFreeMemory(), or NULL on error.
*
* @device must be a xenbus PDO. Anything else will cause a bugcheck.
* The caller is responsible for ensuring that the PDO remains valid
* while this function is running, but there is no requirement for it
* to remain valid once it has returned. The returned string remains
* valid until explicitly released.
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI PSTR xenbus_find_frontend(PDEVICE_OBJECT device);
/* Given a Xenbus PDO, determine the backend path for the device.
* Returns a newly-allocated nul-terminated string which should be
* released with XmFreeMemory(), or NULL on error.
*
* @device must be a xenbus PDO. Anything else will cause a bugcheck.
* The caller is responsible for ensuring that the PDO remains valid
* while this function is running, but there is no requirement for it
* to remain valid once it has returned. The returned string remains
* valid until explicitly released.
*
* Note that the backend path is likely to change across dom0
* suspend/resume. The caller is therefore required to provide
* a suspend token when calling xenbus_find_backend().
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI PSTR xenbus_find_backend(PDEVICE_OBJECT device, SUSPEND_TOKEN token);
/* Read the feature flag @node from the xenstore backend area for the
* device represented by @pdo, under the transaction @xbt. Sets @res
* to TRUE if the feature is available, and FALSE otherwise. The
* feature is considered unavailable if the node does not exist or if
* it exists and has the value 0. It is available if it exists and
* has the value 1. Anything else is considered an error.
*
* The transaction will not be aborted simply because the node is not
* present (unlike XenbusReadInteger() or xenbus_read()). It will be
* aborted as normal if there is any other error reading the node, or
* if the node does not have the value "0" or the value "1".
*
* @node must point at valid globally-mapped non-pageable memory.
*
* *@res is set to FALSE on failure.
*
* @xbt may be nil, null, or a valid transaction.
*
* Call from IRQL < DISPATCH_LEVEL.
*/
XSAPI NTSTATUS xenbus_read_backend_feature_flag(xenbus_transaction_t xbt,
PDEVICE_OBJECT pdo,
PCSTR node,
BOOLEAN *res);
/* Read arbitrary data from the xenstore key @node in the backend area
* corresponding to the device @pdo, under transaction @xbt. The
* result is returned as a newly-allocated buffer at *@Res, and should
* be freed with XmFreeMemory() when you're finished with it. The
* length of the buffer is returned in *@size.
*
* Note that *@Res is not guaranteed to be nul-terminated, and can
* contain embedded nuls. This is different from xenbus_read().
*
* @node must point at valid globally-mapped non-pageable memory. The
* buffer returned at *@res will be globally-mapped and non-pageable.
*
* @xbt can be null, nil, or a valid transaction.
*
* Call from IRQL < DISPATCH_LEVEL.
*/
XSAPI NTSTATUS xenbus_read_backend_bin(xenbus_transaction_t xbt,
PDEVICE_OBJECT pdo,
PCSTR node,
void **res,
size_t *size);
/* Read a nul-terminated string from the xenstore key @node in the
* backend area corresponding the device @pdo, under transaction @xbt.
* The result is returned as a nul-terminated string at *@Res, and
* should be freed with XmFreeMemory() when you're finished with it.
*
* @node must point at valid globally-mapped non-pageable memory. The
* buffer returned at *@res will be globally-mapped and non-pageable.
*
* @xbt can be null, nil, or a valid transaction.
*
* @pdo must be a xenbus device physical device object.
*
* Call from IRQL < DISPATCH_LEVEL.
*/
XSAPI NTSTATUS xenbus_read_backend(xenbus_transaction_t xbt,
PDEVICE_OBJECT pdo,
PCSTR node,
PSTR *res);
/* ----------------------- Event channels -------------------------- */
/* Event channels are one of the primary Xen-provided inter-domain
* communication mechanisms. The only kind supported by xevtchn.sys
* is an inter-domain event channel. These have two ends in separate
* domains and are, once established, basically symmetrical. Either
* end can notify over the event channel, which will cause a bit in
* the other end's hypervisor shared info to be set and an interrupt
* to be raised. It is then up to the recipient domain to process the
* event in a suitable fashion.
*
* Events can be temporarily masked by setting suitable bits in the
* shared info structure. This will prevent an interrupt being raised
* for that event channel, but will not prevent the pending bit being
* set. Note that masking an event channel only prevents the local
* event handler from being run; it is still possible to notify the
* remote domain over the channel, and the remote event channel
* handler will be invoked immediately (subject to masking in the
* remote domain).
*
* If an event is raised several times before the recipient domain is
* able to process it, the events will be combined and only delivered
* once.
*
* EVTCHN_PORT structures remain valid across dom0-driven
* save/restore, hibernation, and migration, but will not be
* automatically communicated to device backends etc. The Xen-side
* event channel port number may change, but that should be invisible
* to users of this API.
*/
MAKE_WRAPPER_PUB(EVTCHN_PORT)
/* Allocate a new Xen event channel and return an EVTCHN_PORT
* describing it. The domain @domid will be able to connect to this
* port so that it can send and receive notifications over the event
* channel. When this port is notified by the remote domain, @cb will
* be invoked with the single argument @context. This callback will
* be invoked directly from the event channel interrupt handler; it
* must therefore be quick. The callback can be invoked even when the
* associated event has not been raised, although this should be rare.
* Returns a null port on failure.
*
* The port should be released with EvtchnClose() when it is no longer
* needed.
*
* Invoke from PASSIVE_LEVEL.
*/
typedef void EVTCHN_HANDLER_CB(void *Context);
typedef EVTCHN_HANDLER_CB *PEVTCHN_HANDLER_CB;
XSAPI EVTCHN_PORT EvtchnAllocUnbound(DOMAIN_ID domid, PEVTCHN_HANDLER_CB cb,
void *context);
/* EvtchnAllocUnboundDpc() is analogous to EvtchnAllocUnbound(),
* except that the callback is run from a DPC rather than directly
* from the event channel interrupt handler. The port can be raised
* and notified as normal.
*
* There is no way to directly access a DPC port's DPC. Several ports
* may share a single Windows DPC; this should be transparent to
* clients. It is guaranteed that the callback will not be
* simultaneously invoked on multiple CPUs.
*
* DPC ports cannot be masked and unmasked. It is an error to call
* EvtchnPortMask() or EvtchnPortUnmask() on such a port.
*
* Call from PASSIVE_LEVEL.
*
* Introduced in Orlando.
*/
XSAPI EVTCHN_PORT EvtchnAllocUnboundDpc(DOMAIN_ID domid,
PEVTCHN_HANDLER_CB cb,
void *context);
/* Close the event channel port @port, unregistering the handler.
* When this returns, it is guaranteed that the last invocation of the
* callback assigned with EvtchnAllocUnbound() or
* EvtchnAllocUnboundDpc() has completed.
*
* It is not necessary to stop the port before closing it.
*
* @port may not be null.
*
* @port is invalid after this has been called.
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI void EvtchnClose(EVTCHN_PORT port);
/* Prevent any further invocations of the handler associated with @port,
* and wait for any existing invocations to finish.
*
* It is not possible to re-start a port which has been stopped. The
* port must be closed with EvtchnClose() and re-created.
*
* EvtchnNotifyRemote(), EvtchnPortMask(), EvtchnPortUnmask(), and
* EvtchnRaiseLocally() are all no-ops on a stopped port.
* xenbus_write_evtchn_port() on a stopped port will return an error
* and fail any transaction.
*
* @port may not be null.
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI void EvtchnPortStop(EVTCHN_PORT port);
/* Notify the remote domain connected to the event channel @port,
* previously returned by EvtchnAllocUnbound(). The notification will
* be discarded if there is no domain currently attached to the other
* end of the event channel.
*
* @port may not be null.
*
* Can be invoked from any IRQL, holding any combination of locks.
*/
XSAPI void EvtchnNotifyRemote(__in EVTCHN_PORT port);
/* Cause an event channel to be raised locally. Shortly after this is
* called, the callback defined for the event will be invoked in its
* usual context, exactly as if it had been raised in the remote
* domain
*
* @port may not be null.
*
* Can be invoked from IRQL <= DISPATCH_LEVEL, holding any combination
* of locks.
*/
XSAPI void EvtchnRaiseLocally(__in EVTCHN_PORT port);
/* Write the event channel port number @port to xenstore at
* @prefix/@node under the transaction @xbt. Users should not attempt
* to interpret the contents of the EVTCHN_PORT structure
* themselves.
*
* xenbus_write_evtchn_port() will fail the transaction and return an
* error if @port was previously been passed to EvtchnPortStop().
*
* @prefix and @node must point at valid globally-mapped non-pageable
* memory.
*
* @port must not be null. @xbt may be nil, null, or a valid
* transaction.
*/
XSAPI NTSTATUS xenbus_write_evtchn_port(xenbus_transaction_t xbt,
PCSTR prefix, PCSTR node,
EVTCHN_PORT port);
/* ----------------------- Debug callbacks ------------------------- */
MAKE_WRAPPER_PUB(EVTCHN_DEBUG_CALLBACK)
/* Register a handler for VIRQ_DEBUG. When VIRQ_DEBUG is raised
* against the current domain, @cb will be invoked with parameter @d.
* This is usually used to dump debugging information to XenTrace.
* The returned handle should be released with
* EvtchnReleaseDebugCallback(). Returns null_EVTCHN_DEBUG_CALLBACK()
* on error.
*
* The callback is invoked from the same context as an event channel
* handler registered with EvtchnAllocUnbound().
*
* Debug callbacks may also be invoked immediately before the guest
* bugchecks. If so, they are invoked from the same context as a
* KeRegisterBugCheckCallback() callback, and with XenTrace configured
* to send every message to every available message consumer. Debug
* callbacks are not guaranteed to be invoked after every possible
* crash.
*
* Note that the number of debug callbacks which can be registered is
* quite limited. They should not be allocated gratuitously, and
* drivers must operate correctly when they are unable to allocate a
* callback.
*
* VIRQ_DEBUG is automatically raised against all domains by
* xen-bugtool, shortly before collecting the domain 0 logs. This is,
* however, no synchronisation between bugtool and the in-guest tools,
* and so if a debug callback takes more than a few seconds the
* collected logs may be truncated.
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI EVTCHN_DEBUG_CALLBACK __EvtchnSetupDebugCallbackAnonymous(VOID (*cb)(PVOID),
PVOID d);
XSAPI EVTCHN_DEBUG_CALLBACK __EvtchnSetupDebugCallback(const CHAR *module,
const CHAR *name,
VOID (*cb)(PVOID),
PVOID d);
#define EvtchnSetupDebugCallback(_cb, _d) \
__EvtchnSetupDebugCallback(XENTARGET, #_cb, (_cb), (_d))
/* Release the debug callback handle previously returned by
* EvtchnSetupDebugCallback(). @handle can be
* null_EVTCHN_DEBUG_CALLBACK(); in that case, this is a no-op.
*
* Invoke from PASSIVE_LEVEL.
*/
XSAPI void EvtchnReleaseDebugCallback(EVTCHN_DEBUG_CALLBACK handle);
/* ------------------------- Grant tables -------------------------- */
/* Grant tables provide a mechanism by which domains can grant other
* domains access to their memory in a controlled fashion. Each grant
* reference grants a particular foreign domain access to a particular
* frame of physical memory in the local domain. They can be either
* read-only or read-write.
*
* We use a wrapper type, GRANT_REF, around the underlying
* xen_grant_ref_t. This has a couple of advantages:
*
* a) invalid grant references have an all-zero representation in
* memory, so initialisation becomes much easier,
* b) we can steal a few bits out of the bottom for flags, which
* can then be used for checking that e.g. they're release back
* to the right cache.
* c) you get as much type safety as C can offer.
*
* GRANT_REFs are preserved across dom0-driver save/restore, and have
* the same xen_grant_ref_t after recovery as they had before.
*/
/* Xen grant references are integers greater than or equal to 0.
* GRANT_REFs are (grant_ref_t+1)<<10. This makes sure that null
* references are recognisable as such, and allows us to shove some
* flags in the bottom few bits (mostly for debugging). */
/* As far as clients are concerned, the only operations on GRANT_REFs
* are null_GRANT_REF, is_null_GRANT_REF, and xen_GRANT_REF. They
* cannot assume anything about the flags part of the reference. */
MAKE_WRAPPER_PUB(GRANT_REF)
__MAKE_WRAPPER_PRIV(GRANT_REF, ULONG_PTR)
typedef uint32_t xen_grant_ref_t;
/* Given a GRANT_REF, return the Xen grant_ref_t. This is what needs
* to be communicated to backends. */
static __inline xen_grant_ref_t xen_GRANT_REF(GRANT_REF g)
{
ULONG_PTR res = __unwrap_GRANT_REF(g);
return (xen_grant_ref_t)((res >> 10) - 1);
}
/* Make a GRANT_REF for a given Xen grant_ref_t, cache id,
* and the current suspend count. Cache id should be set to
* 0 for external callers */
static __inline GRANT_REF wrap_GRANT_REF(xen_grant_ref_t x, int cache)
{
return __wrap_GRANT_REF(((x + 1) << 10) |
(cache & 3));
}
/* Grants have two possible modes: read-only or read-write. */
MAKE_WRAPPER_PUB(GRANT_MODE)
MAKE_WRAPPER_PRIV(GRANT_MODE, int)
#define GRANT_MODE_RW wrap_GRANT_MODE(0)
#define GRANT_MODE_RO wrap_GRANT_MODE(1)
/* Return a raw grant ref for situations where the client wants
* to manage its own grant ref list.
*
* Can be called at any IRQL holding any combinations of locks.
*/
XSAPI GRANT_REF GnttabGetGrantRef(VOID);
/* See GnttabGrantForeignAccess but with a grant ref. See the
* comments for that routine. The @ref parameter is acquired
* using GnttabGetGrantRef().
*
* Can be invoked at any IRQL holding any combination of locks.
*/
XSAPI void GnttabGrantForeignAccessRef(DOMAIN_ID domid,
PFN_NUMBER frame,
GRANT_MODE mode,
GRANT_REF ref);
/* Grants domain @domid access to physical frame @frame of our memory.
* The domain is able to map the frame into its own address space, and
* can also use it as the target or source of grant copy operations.
* The grant can be either read-only or read-write, according to
* @mode. The grant reference should be released by calling
* GnttabEndForeignAccess() when it is no longer needed.
*
* Can be invoked at any IRQL holding any combination of locks.
*/
XSAPI GRANT_REF GnttabGrantForeignAccess(DOMAIN_ID domid,
PFN_NUMBER frame,
GRANT_MODE mode);
/* Undo the effects of GnttabGrantForeignAccess(): Stop any further
* accesses through the reference @ref, and return it to the pool of
* free grant references. This can fail if the grant is still in use
* in the other domain; in that case, it returns STATUS_DEVICE_BUSY.
* The grant reference is not released. The caller may try again
* later, but there is no way to release the reference if the granted
* domain refuses to unmap it.
*
* @ref must not be null, since this is likely to be the only place
* where we can check that the caller hasn't done something stupid
* like accidentally pushing a null reference over a ring to a backend.
*
* Can be called at any IRQL holding any combinations of locks.
*/
XSAPI NTSTATUS GnttabEndForeignAccess(GRANT_REF ref);
/* ------------------------- Grant caches -------------------------- */
/* The largest component of the cost of GnttabGrantForeignAccess() is
* the synchronisation around the pool of free grant references. This
* can be mitigated using grant caches, which allocate batches of
* grant references from the main pool and then return them without
* performing any additional synchronisation. The caller is expected
* to ensure that a single grant cache is never used on multiple CPUs
* at the same time.
*
* The cache infrastructure is responsible for moving references
* between the cache and the main pool when necessary.
*
*/
struct grant_cache;
/* Allocate a new grant cache. Returns a pointer to the new cache on
* success or NULL on failure. The cache should be released with
* GnttabFreeCache() when no longer needed.
*
* If this succeeds, it is guaranteed that at least @min_population
* grant references can be allocated from the cache without an error.
* References returned to the cache with GnttabEndForeignAccessCache()
* are returned to this pool, so that it is possible to allocate
* up to the limit, release n entries, and then allocate another n,
* and be guaranteed to succeed.
*
*
* Call at PASSIVE_LEVEL.
*/
XSAPI struct grant_cache *GnttabAllocCache(ULONG min_population);
/* Release the grant cache @gc which was previously allocated with
* GnttabInitCache(). All references which were allocated with
* GnttabGrantForeignAccessCache() should have been released with
* GnttabEndForeignAccessCache() before releasing the grant_cache.