xref: /titanic_51/usr/src/uts/common/xen/public/xen.h (revision ad09f8b827db90c9a0093f0b6382803fa64a5fd1)
1843e1988Sjohnlev /******************************************************************************
2843e1988Sjohnlev  * xen.h
3843e1988Sjohnlev  *
4843e1988Sjohnlev  * Guest OS interface to Xen.
5843e1988Sjohnlev  *
6843e1988Sjohnlev  * Permission is hereby granted, free of charge, to any person obtaining a copy
7843e1988Sjohnlev  * of this software and associated documentation files (the "Software"), to
8843e1988Sjohnlev  * deal in the Software without restriction, including without limitation the
9843e1988Sjohnlev  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10843e1988Sjohnlev  * sell copies of the Software, and to permit persons to whom the Software is
11843e1988Sjohnlev  * furnished to do so, subject to the following conditions:
12843e1988Sjohnlev  *
13843e1988Sjohnlev  * The above copyright notice and this permission notice shall be included in
14843e1988Sjohnlev  * all copies or substantial portions of the Software.
15843e1988Sjohnlev  *
16843e1988Sjohnlev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17843e1988Sjohnlev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18843e1988Sjohnlev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19843e1988Sjohnlev  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20843e1988Sjohnlev  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21843e1988Sjohnlev  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22843e1988Sjohnlev  * DEALINGS IN THE SOFTWARE.
23843e1988Sjohnlev  *
24843e1988Sjohnlev  * Copyright (c) 2004, K A Fraser
25843e1988Sjohnlev  */
26843e1988Sjohnlev 
27843e1988Sjohnlev #ifndef __XEN_PUBLIC_XEN_H__
28843e1988Sjohnlev #define __XEN_PUBLIC_XEN_H__
29843e1988Sjohnlev 
30843e1988Sjohnlev #include "xen-compat.h"
31843e1988Sjohnlev 
32843e1988Sjohnlev #if defined(__i386) && !defined(__i386__)
33a576ab5bSrab #define __i386__ /* foo */
34843e1988Sjohnlev #endif
35843e1988Sjohnlev 
36843e1988Sjohnlev #if defined(__amd64) && !defined(__x86_64__)
37843e1988Sjohnlev #define __x86_64__
38843e1988Sjohnlev #endif
39843e1988Sjohnlev 
40843e1988Sjohnlev #if defined(_ASM) && !defined(__ASSEMBLY__)
41843e1988Sjohnlev #define __ASSEMBLY__
42843e1988Sjohnlev #endif
43843e1988Sjohnlev 
44843e1988Sjohnlev #if defined(__i386__) || defined(__x86_64__)
45843e1988Sjohnlev #include "arch-x86/xen.h"
46843e1988Sjohnlev #elif defined(__ia64__)
47843e1988Sjohnlev #include "arch-ia64.h"
48843e1988Sjohnlev #else
49843e1988Sjohnlev #error "Unsupported architecture"
50843e1988Sjohnlev #endif
51843e1988Sjohnlev 
52349b53ddSStuart Maybee #ifndef __ASSEMBLY__
53349b53ddSStuart Maybee /* Guest handles for primitive C types. */
54349b53ddSStuart Maybee DEFINE_XEN_GUEST_HANDLE(char);
55349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
56349b53ddSStuart Maybee DEFINE_XEN_GUEST_HANDLE(int);
57349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uint,  unsigned int);
58349b53ddSStuart Maybee DEFINE_XEN_GUEST_HANDLE(long);
59349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
60349b53ddSStuart Maybee DEFINE_XEN_GUEST_HANDLE(void);
61349b53ddSStuart Maybee 
62349b53ddSStuart Maybee DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
63349b53ddSStuart Maybee #endif
64349b53ddSStuart Maybee 
65843e1988Sjohnlev /*
66843e1988Sjohnlev  * HYPERCALLS
67843e1988Sjohnlev  */
68843e1988Sjohnlev 
69843e1988Sjohnlev #define __HYPERVISOR_set_trap_table        0
70843e1988Sjohnlev #define __HYPERVISOR_mmu_update            1
71843e1988Sjohnlev #define __HYPERVISOR_set_gdt               2
72843e1988Sjohnlev #define __HYPERVISOR_stack_switch          3
73843e1988Sjohnlev #define __HYPERVISOR_set_callbacks         4
74843e1988Sjohnlev #define __HYPERVISOR_fpu_taskswitch        5
75843e1988Sjohnlev #define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
76843e1988Sjohnlev #define __HYPERVISOR_platform_op           7
77843e1988Sjohnlev #define __HYPERVISOR_set_debugreg          8
78843e1988Sjohnlev #define __HYPERVISOR_get_debugreg          9
79843e1988Sjohnlev #define __HYPERVISOR_update_descriptor    10
80843e1988Sjohnlev #define __HYPERVISOR_memory_op            12
81843e1988Sjohnlev #define __HYPERVISOR_multicall            13
82843e1988Sjohnlev #define __HYPERVISOR_update_va_mapping    14
83843e1988Sjohnlev #define __HYPERVISOR_set_timer_op         15
84843e1988Sjohnlev #define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
85843e1988Sjohnlev #define __HYPERVISOR_xen_version          17
86843e1988Sjohnlev #define __HYPERVISOR_console_io           18
87843e1988Sjohnlev #define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
88843e1988Sjohnlev #define __HYPERVISOR_grant_table_op       20
89843e1988Sjohnlev #define __HYPERVISOR_vm_assist            21
90843e1988Sjohnlev #define __HYPERVISOR_update_va_mapping_otherdomain 22
91843e1988Sjohnlev #define __HYPERVISOR_iret                 23 /* x86 only */
92843e1988Sjohnlev #define __HYPERVISOR_vcpu_op              24
93843e1988Sjohnlev #define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
94843e1988Sjohnlev #define __HYPERVISOR_mmuext_op            26
95349b53ddSStuart Maybee #define __HYPERVISOR_xsm_op               27
96843e1988Sjohnlev #define __HYPERVISOR_nmi_op               28
97843e1988Sjohnlev #define __HYPERVISOR_sched_op             29
98843e1988Sjohnlev #define __HYPERVISOR_callback_op          30
99843e1988Sjohnlev #define __HYPERVISOR_xenoprof_op          31
100843e1988Sjohnlev #define __HYPERVISOR_event_channel_op     32
101843e1988Sjohnlev #define __HYPERVISOR_physdev_op           33
102843e1988Sjohnlev #define __HYPERVISOR_hvm_op               34
103843e1988Sjohnlev #define __HYPERVISOR_sysctl               35
104843e1988Sjohnlev #define __HYPERVISOR_domctl               36
105843e1988Sjohnlev #define __HYPERVISOR_kexec_op             37
106843e1988Sjohnlev 
107843e1988Sjohnlev /* Architecture-specific hypercall definitions. */
108843e1988Sjohnlev #define __HYPERVISOR_arch_0               48
109843e1988Sjohnlev #define __HYPERVISOR_arch_1               49
110843e1988Sjohnlev #define __HYPERVISOR_arch_2               50
111843e1988Sjohnlev #define __HYPERVISOR_arch_3               51
112843e1988Sjohnlev #define __HYPERVISOR_arch_4               52
113843e1988Sjohnlev #define __HYPERVISOR_arch_5               53
114843e1988Sjohnlev #define __HYPERVISOR_arch_6               54
115843e1988Sjohnlev #define __HYPERVISOR_arch_7               55
116843e1988Sjohnlev 
117843e1988Sjohnlev /*
118843e1988Sjohnlev  * HYPERCALL COMPATIBILITY.
119843e1988Sjohnlev  */
120843e1988Sjohnlev 
121843e1988Sjohnlev /* New sched_op hypercall introduced in 0x00030101. */
122843e1988Sjohnlev #if __XEN_INTERFACE_VERSION__ < 0x00030101
123843e1988Sjohnlev #undef __HYPERVISOR_sched_op
124843e1988Sjohnlev #define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
125843e1988Sjohnlev #endif
126843e1988Sjohnlev 
127843e1988Sjohnlev /* New event-channel and physdev hypercalls introduced in 0x00030202. */
128843e1988Sjohnlev #if __XEN_INTERFACE_VERSION__ < 0x00030202
129843e1988Sjohnlev #undef __HYPERVISOR_event_channel_op
130843e1988Sjohnlev #define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
131843e1988Sjohnlev #undef __HYPERVISOR_physdev_op
132843e1988Sjohnlev #define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
133843e1988Sjohnlev #endif
134843e1988Sjohnlev 
135843e1988Sjohnlev /* New platform_op hypercall introduced in 0x00030204. */
136843e1988Sjohnlev #if __XEN_INTERFACE_VERSION__ < 0x00030204
137843e1988Sjohnlev #define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
138843e1988Sjohnlev #endif
139843e1988Sjohnlev 
140843e1988Sjohnlev /*
141843e1988Sjohnlev  * VIRTUAL INTERRUPTS
142843e1988Sjohnlev  *
143843e1988Sjohnlev  * Virtual interrupts that a guest OS may receive from Xen.
144843e1988Sjohnlev  *
145843e1988Sjohnlev  * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
146843e1988Sjohnlev  * global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
147843e1988Sjohnlev  * The latter can be allocated only once per guest: they must initially be
148843e1988Sjohnlev  * allocated to VCPU0 but can subsequently be re-bound.
149843e1988Sjohnlev  */
150843e1988Sjohnlev #define VIRQ_TIMER      0  /* V. Timebase update, and/or requested timeout.  */
151843e1988Sjohnlev #define VIRQ_DEBUG      1  /* V. Request guest to dump debug info.           */
152843e1988Sjohnlev #define VIRQ_CONSOLE    2  /* G. (DOM0) Bytes received on emergency console. */
153843e1988Sjohnlev #define VIRQ_DOM_EXC    3  /* G. (DOM0) Exceptional event for some domain.   */
154843e1988Sjohnlev #define VIRQ_TBUF       4  /* G. (DOM0) Trace buffer has records available.  */
155843e1988Sjohnlev #define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
156843e1988Sjohnlev #define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
157a576ab5bSrab #define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
158843e1988Sjohnlev 
159843e1988Sjohnlev /* Architecture-specific VIRQ definitions. */
160843e1988Sjohnlev #define VIRQ_ARCH_0    16
161843e1988Sjohnlev #define VIRQ_ARCH_1    17
162843e1988Sjohnlev #define VIRQ_ARCH_2    18
163843e1988Sjohnlev #define VIRQ_ARCH_3    19
164843e1988Sjohnlev #define VIRQ_ARCH_4    20
165843e1988Sjohnlev #define VIRQ_ARCH_5    21
166843e1988Sjohnlev #define VIRQ_ARCH_6    22
167843e1988Sjohnlev #define VIRQ_ARCH_7    23
168843e1988Sjohnlev 
169843e1988Sjohnlev #define NR_VIRQS       24
170843e1988Sjohnlev 
171843e1988Sjohnlev /*
172843e1988Sjohnlev  * MMU-UPDATE REQUESTS
173843e1988Sjohnlev  *
174843e1988Sjohnlev  * HYPERVISOR_mmu_update() accepts a list of (ptr, val) pairs.
175843e1988Sjohnlev  * A foreigndom (FD) can be specified (or DOMID_SELF for none).
176843e1988Sjohnlev  * Where the FD has some effect, it is described below.
177843e1988Sjohnlev  * ptr[1:0] specifies the appropriate MMU_* command.
178843e1988Sjohnlev  *
179843e1988Sjohnlev  * ptr[1:0] == MMU_NORMAL_PT_UPDATE:
180843e1988Sjohnlev  * Updates an entry in a page table. If updating an L1 table, and the new
181843e1988Sjohnlev  * table entry is valid/present, the mapped frame must belong to the FD, if
182843e1988Sjohnlev  * an FD has been specified. If attempting to map an I/O page then the
183843e1988Sjohnlev  * caller assumes the privilege of the FD.
184843e1988Sjohnlev  * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
185843e1988Sjohnlev  * FD == DOMID_XEN: Map restricted areas of Xen's heap space.
186843e1988Sjohnlev  * ptr[:2]  -- Machine address of the page-table entry to modify.
187843e1988Sjohnlev  * val      -- Value to write.
188843e1988Sjohnlev  *
189843e1988Sjohnlev  * ptr[1:0] == MMU_MACHPHYS_UPDATE:
190843e1988Sjohnlev  * Updates an entry in the machine->pseudo-physical mapping table.
191843e1988Sjohnlev  * ptr[:2]  -- Machine address within the frame whose mapping to modify.
192843e1988Sjohnlev  *             The frame must belong to the FD, if one is specified.
193843e1988Sjohnlev  * val      -- Value to write into the mapping entry.
194349b53ddSStuart Maybee  *
195349b53ddSStuart Maybee  * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
196349b53ddSStuart Maybee  * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
197349b53ddSStuart Maybee  * with those in @val.
198843e1988Sjohnlev  */
199843e1988Sjohnlev #define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.      */
200843e1988Sjohnlev #define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for */
201349b53ddSStuart Maybee #define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
202843e1988Sjohnlev 
203843e1988Sjohnlev /*
204843e1988Sjohnlev  * MMU EXTENDED OPERATIONS
205843e1988Sjohnlev  *
206843e1988Sjohnlev  * HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
207843e1988Sjohnlev  * A foreigndom (FD) can be specified (or DOMID_SELF for none).
208843e1988Sjohnlev  * Where the FD has some effect, it is described below.
209843e1988Sjohnlev  *
210843e1988Sjohnlev  * cmd: MMUEXT_(UN)PIN_*_TABLE
211843e1988Sjohnlev  * mfn: Machine frame number to be (un)pinned as a p.t. page.
212843e1988Sjohnlev  *      The frame must belong to the FD, if one is specified.
213843e1988Sjohnlev  *
214843e1988Sjohnlev  * cmd: MMUEXT_NEW_BASEPTR
215843e1988Sjohnlev  * mfn: Machine frame number of new page-table base to install in MMU.
216843e1988Sjohnlev  *
217843e1988Sjohnlev  * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
218843e1988Sjohnlev  * mfn: Machine frame number of new page-table base to install in MMU
219843e1988Sjohnlev  *      when in user space.
220843e1988Sjohnlev  *
221843e1988Sjohnlev  * cmd: MMUEXT_TLB_FLUSH_LOCAL
222843e1988Sjohnlev  * No additional arguments. Flushes local TLB.
223843e1988Sjohnlev  *
224843e1988Sjohnlev  * cmd: MMUEXT_INVLPG_LOCAL
225843e1988Sjohnlev  * linear_addr: Linear address to be flushed from the local TLB.
226843e1988Sjohnlev  *
227843e1988Sjohnlev  * cmd: MMUEXT_TLB_FLUSH_MULTI
228843e1988Sjohnlev  * vcpumask: Pointer to bitmap of VCPUs to be flushed.
229843e1988Sjohnlev  *
230843e1988Sjohnlev  * cmd: MMUEXT_INVLPG_MULTI
231843e1988Sjohnlev  * linear_addr: Linear address to be flushed.
232843e1988Sjohnlev  * vcpumask: Pointer to bitmap of VCPUs to be flushed.
233843e1988Sjohnlev  *
234843e1988Sjohnlev  * cmd: MMUEXT_TLB_FLUSH_ALL
235843e1988Sjohnlev  * No additional arguments. Flushes all VCPUs' TLBs.
236843e1988Sjohnlev  *
237843e1988Sjohnlev  * cmd: MMUEXT_INVLPG_ALL
238843e1988Sjohnlev  * linear_addr: Linear address to be flushed from all VCPUs' TLBs.
239843e1988Sjohnlev  *
240843e1988Sjohnlev  * cmd: MMUEXT_FLUSH_CACHE
241843e1988Sjohnlev  * No additional arguments. Writes back and flushes cache contents.
242843e1988Sjohnlev  *
243843e1988Sjohnlev  * cmd: MMUEXT_SET_LDT
244843e1988Sjohnlev  * linear_addr: Linear address of LDT base (NB. must be page-aligned).
245843e1988Sjohnlev  * nr_ents: Number of entries in LDT.
246*ad09f8b8SMark Johnson  *
247*ad09f8b8SMark Johnson  * cmd: MMUEXT_CLEAR_PAGE
248*ad09f8b8SMark Johnson  * mfn: Machine frame number to be cleared.
249*ad09f8b8SMark Johnson  *
250*ad09f8b8SMark Johnson  * cmd: MMUEXT_COPY_PAGE
251*ad09f8b8SMark Johnson  * mfn: Machine frame number of the destination page.
252*ad09f8b8SMark Johnson  * src_mfn: Machine frame number of the source page.
253843e1988Sjohnlev  */
254843e1988Sjohnlev #define MMUEXT_PIN_L1_TABLE      0
255843e1988Sjohnlev #define MMUEXT_PIN_L2_TABLE      1
256843e1988Sjohnlev #define MMUEXT_PIN_L3_TABLE      2
257843e1988Sjohnlev #define MMUEXT_PIN_L4_TABLE      3
258843e1988Sjohnlev #define MMUEXT_UNPIN_TABLE       4
259843e1988Sjohnlev #define MMUEXT_NEW_BASEPTR       5
260843e1988Sjohnlev #define MMUEXT_TLB_FLUSH_LOCAL   6
261843e1988Sjohnlev #define MMUEXT_INVLPG_LOCAL      7
262843e1988Sjohnlev #define MMUEXT_TLB_FLUSH_MULTI   8
263843e1988Sjohnlev #define MMUEXT_INVLPG_MULTI      9
264843e1988Sjohnlev #define MMUEXT_TLB_FLUSH_ALL    10
265843e1988Sjohnlev #define MMUEXT_INVLPG_ALL       11
266843e1988Sjohnlev #define MMUEXT_FLUSH_CACHE      12
267843e1988Sjohnlev #define MMUEXT_SET_LDT          13
268843e1988Sjohnlev #define MMUEXT_NEW_USER_BASEPTR 15
269*ad09f8b8SMark Johnson #define MMUEXT_CLEAR_PAGE       16
270*ad09f8b8SMark Johnson #define MMUEXT_COPY_PAGE        17
271843e1988Sjohnlev 
272843e1988Sjohnlev #ifndef __ASSEMBLY__
273843e1988Sjohnlev struct mmuext_op {
274843e1988Sjohnlev     unsigned int cmd;
275843e1988Sjohnlev     union {
276*ad09f8b8SMark Johnson         /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
277*ad09f8b8SMark Johnson          * CLEAR_PAGE, COPY_PAGE */
278843e1988Sjohnlev         xen_pfn_t     mfn;
279843e1988Sjohnlev         /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
280843e1988Sjohnlev         unsigned long linear_addr;
281843e1988Sjohnlev     } arg1;
282843e1988Sjohnlev     union {
283843e1988Sjohnlev         /* SET_LDT */
284843e1988Sjohnlev         unsigned int nr_ents;
285843e1988Sjohnlev         /* TLB_FLUSH_MULTI, INVLPG_MULTI */
286349b53ddSStuart Maybee #if __XEN_INTERFACE_VERSION__ >= 0x00030205
287*ad09f8b8SMark Johnson         XEN_GUEST_HANDLE(const_void) vcpumask;
288349b53ddSStuart Maybee #else
289*ad09f8b8SMark Johnson         const void *vcpumask;
290349b53ddSStuart Maybee #endif
291*ad09f8b8SMark Johnson         /* COPY_PAGE */
292*ad09f8b8SMark Johnson         xen_pfn_t src_mfn;
293843e1988Sjohnlev     } arg2;
294843e1988Sjohnlev };
295843e1988Sjohnlev typedef struct mmuext_op mmuext_op_t;
296843e1988Sjohnlev DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
297843e1988Sjohnlev #endif
298843e1988Sjohnlev 
299843e1988Sjohnlev /* These are passed as 'flags' to update_va_mapping. They can be ORed. */
300843e1988Sjohnlev /* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap.   */
301843e1988Sjohnlev /* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer.         */
302843e1988Sjohnlev #define UVMF_NONE               (0UL<<0) /* No flushing at all.   */
303843e1988Sjohnlev #define UVMF_TLB_FLUSH          (1UL<<0) /* Flush entire TLB(s).  */
304843e1988Sjohnlev #define UVMF_INVLPG             (2UL<<0) /* Flush only one entry. */
305843e1988Sjohnlev #define UVMF_FLUSHTYPE_MASK     (3UL<<0)
306843e1988Sjohnlev #define UVMF_MULTI              (0UL<<2) /* Flush subset of TLBs. */
307843e1988Sjohnlev #define UVMF_LOCAL              (0UL<<2) /* Flush local TLB.      */
308843e1988Sjohnlev #define UVMF_ALL                (1UL<<2) /* Flush all TLBs.       */
309843e1988Sjohnlev 
310843e1988Sjohnlev /*
311843e1988Sjohnlev  * Commands to HYPERVISOR_console_io().
312843e1988Sjohnlev  */
313843e1988Sjohnlev #define CONSOLEIO_write         0
314843e1988Sjohnlev #define CONSOLEIO_read          1
315843e1988Sjohnlev #define CONSOLEIO_get_device   32
316843e1988Sjohnlev 
317843e1988Sjohnlev /*
318843e1988Sjohnlev  * Commands to HYPERVISOR_vm_assist().
319843e1988Sjohnlev  */
320843e1988Sjohnlev #define VMASST_CMD_enable                0
321843e1988Sjohnlev #define VMASST_CMD_disable               1
322843e1988Sjohnlev 
323843e1988Sjohnlev /* x86/32 guests: simulate full 4GB segment limits. */
324843e1988Sjohnlev #define VMASST_TYPE_4gb_segments         0
325843e1988Sjohnlev 
326843e1988Sjohnlev /* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
327843e1988Sjohnlev #define VMASST_TYPE_4gb_segments_notify  1
328843e1988Sjohnlev 
329843e1988Sjohnlev /*
330843e1988Sjohnlev  * x86 guests: support writes to bottom-level PTEs.
331843e1988Sjohnlev  * NB1. Page-directory entries cannot be written.
332843e1988Sjohnlev  * NB2. Guest must continue to remove all writable mappings of PTEs.
333843e1988Sjohnlev  */
334843e1988Sjohnlev #define VMASST_TYPE_writable_pagetables  2
335843e1988Sjohnlev 
336843e1988Sjohnlev /* x86/PAE guests: support PDPTs above 4GB. */
337843e1988Sjohnlev #define VMASST_TYPE_pae_extended_cr3     3
338843e1988Sjohnlev 
339843e1988Sjohnlev #define MAX_VMASST_TYPE                  3
340843e1988Sjohnlev 
341843e1988Sjohnlev #ifndef __ASSEMBLY__
342843e1988Sjohnlev 
343843e1988Sjohnlev typedef uint16_t domid_t;
344843e1988Sjohnlev 
345843e1988Sjohnlev /* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
346843e1988Sjohnlev #define DOMID_FIRST_RESERVED (0x7FF0U)
347843e1988Sjohnlev 
348843e1988Sjohnlev /* DOMID_SELF is used in certain contexts to refer to oneself. */
349843e1988Sjohnlev #define DOMID_SELF (0x7FF0U)
350843e1988Sjohnlev 
351843e1988Sjohnlev /*
352843e1988Sjohnlev  * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
353843e1988Sjohnlev  * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
354843e1988Sjohnlev  * is useful to ensure that no mappings to the OS's own heap are accidentally
355843e1988Sjohnlev  * installed. (e.g., in Linux this could cause havoc as reference counts
356843e1988Sjohnlev  * aren't adjusted on the I/O-mapping code path).
357843e1988Sjohnlev  * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
358843e1988Sjohnlev  * be specified by any calling domain.
359843e1988Sjohnlev  */
360843e1988Sjohnlev #define DOMID_IO   (0x7FF1U)
361843e1988Sjohnlev 
362843e1988Sjohnlev /*
363843e1988Sjohnlev  * DOMID_XEN is used to allow privileged domains to map restricted parts of
364843e1988Sjohnlev  * Xen's heap space (e.g., the machine_to_phys table).
365843e1988Sjohnlev  * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
366843e1988Sjohnlev  * the caller is privileged.
367843e1988Sjohnlev  */
368843e1988Sjohnlev #define DOMID_XEN  (0x7FF2U)
369843e1988Sjohnlev 
370*ad09f8b8SMark Johnson /* DOMID_INVALID is used to identity invalid domid */
371*ad09f8b8SMark Johnson #define DOMID_INVALID (0x7FFFU)
372*ad09f8b8SMark Johnson 
373843e1988Sjohnlev /*
374843e1988Sjohnlev  * Send an array of these to HYPERVISOR_mmu_update().
375843e1988Sjohnlev  * NB. The fields are natural pointer/address size for this architecture.
376843e1988Sjohnlev  */
377843e1988Sjohnlev struct mmu_update {
378843e1988Sjohnlev     uint64_t ptr;       /* Machine address of PTE. */
379843e1988Sjohnlev     uint64_t val;       /* New contents of PTE.    */
380843e1988Sjohnlev };
381843e1988Sjohnlev typedef struct mmu_update mmu_update_t;
382843e1988Sjohnlev DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
383843e1988Sjohnlev 
384843e1988Sjohnlev /*
385843e1988Sjohnlev  * Send an array of these to HYPERVISOR_multicall().
386843e1988Sjohnlev  * NB. The fields are natural register size for this architecture.
387843e1988Sjohnlev  */
388843e1988Sjohnlev struct multicall_entry {
389843e1988Sjohnlev     unsigned long op, result;
390843e1988Sjohnlev     unsigned long args[6];
391843e1988Sjohnlev };
392843e1988Sjohnlev typedef struct multicall_entry multicall_entry_t;
393843e1988Sjohnlev DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
394843e1988Sjohnlev 
395843e1988Sjohnlev /*
396843e1988Sjohnlev  * Event channel endpoints per domain:
397843e1988Sjohnlev  *  1024 if a long is 32 bits; 4096 if a long is 64 bits.
398843e1988Sjohnlev  */
399843e1988Sjohnlev #define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
400843e1988Sjohnlev 
401843e1988Sjohnlev struct vcpu_time_info {
402843e1988Sjohnlev     /*
403843e1988Sjohnlev      * Updates to the following values are preceded and followed by an
404843e1988Sjohnlev      * increment of 'version'. The guest can therefore detect updates by
405843e1988Sjohnlev      * looking for changes to 'version'. If the least-significant bit of
406843e1988Sjohnlev      * the version number is set then an update is in progress and the guest
407843e1988Sjohnlev      * must wait to read a consistent set of values.
408843e1988Sjohnlev      * The correct way to interact with the version number is similar to
409843e1988Sjohnlev      * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
410843e1988Sjohnlev      */
411843e1988Sjohnlev     uint32_t version;
412843e1988Sjohnlev     uint32_t pad0;
413843e1988Sjohnlev     uint64_t tsc_timestamp;   /* TSC at last update of time vals.  */
414843e1988Sjohnlev     uint64_t system_time;     /* Time, in nanosecs, since boot.    */
415843e1988Sjohnlev     /*
416843e1988Sjohnlev      * Current system time:
417843e1988Sjohnlev      *   system_time +
418843e1988Sjohnlev      *   ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
419843e1988Sjohnlev      * CPU frequency (Hz):
420843e1988Sjohnlev      *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
421843e1988Sjohnlev      */
422843e1988Sjohnlev     uint32_t tsc_to_system_mul;
423843e1988Sjohnlev     int8_t   tsc_shift;
424843e1988Sjohnlev     int8_t   pad1[3];
425843e1988Sjohnlev }; /* 32 bytes */
426843e1988Sjohnlev typedef struct vcpu_time_info vcpu_time_info_t;
427843e1988Sjohnlev 
428843e1988Sjohnlev struct vcpu_info {
429843e1988Sjohnlev     /*
430843e1988Sjohnlev      * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
431843e1988Sjohnlev      * a pending notification for a particular VCPU. It is then cleared
432843e1988Sjohnlev      * by the guest OS /before/ checking for pending work, thus avoiding
433843e1988Sjohnlev      * a set-and-check race. Note that the mask is only accessed by Xen
434843e1988Sjohnlev      * on the CPU that is currently hosting the VCPU. This means that the
435843e1988Sjohnlev      * pending and mask flags can be updated by the guest without special
436843e1988Sjohnlev      * synchronisation (i.e., no need for the x86 LOCK prefix).
437843e1988Sjohnlev      * This may seem suboptimal because if the pending flag is set by
438843e1988Sjohnlev      * a different CPU then an IPI may be scheduled even when the mask
439843e1988Sjohnlev      * is set. However, note:
440843e1988Sjohnlev      *  1. The task of 'interrupt holdoff' is covered by the per-event-
441843e1988Sjohnlev      *     channel mask bits. A 'noisy' event that is continually being
442843e1988Sjohnlev      *     triggered can be masked at source at this very precise
443843e1988Sjohnlev      *     granularity.
444843e1988Sjohnlev      *  2. The main purpose of the per-VCPU mask is therefore to restrict
445843e1988Sjohnlev      *     reentrant execution: whether for concurrency control, or to
446843e1988Sjohnlev      *     prevent unbounded stack usage. Whatever the purpose, we expect
447843e1988Sjohnlev      *     that the mask will be asserted only for short periods at a time,
448843e1988Sjohnlev      *     and so the likelihood of a 'spurious' IPI is suitably small.
449843e1988Sjohnlev      * The mask is read before making an event upcall to the guest: a
450843e1988Sjohnlev      * non-zero mask therefore guarantees that the VCPU will not receive
451843e1988Sjohnlev      * an upcall activation. The mask is cleared when the VCPU requests
452843e1988Sjohnlev      * to block: this avoids wakeup-waiting races.
453843e1988Sjohnlev      */
454843e1988Sjohnlev     uint8_t evtchn_upcall_pending;
455843e1988Sjohnlev     uint8_t evtchn_upcall_mask;
456843e1988Sjohnlev     unsigned long evtchn_pending_sel;
457843e1988Sjohnlev     struct arch_vcpu_info arch;
458843e1988Sjohnlev     struct vcpu_time_info time;
459843e1988Sjohnlev }; /* 64 bytes (x86) */
460a576ab5bSrab #ifndef __XEN__
461843e1988Sjohnlev typedef struct vcpu_info vcpu_info_t;
462a576ab5bSrab #endif
463843e1988Sjohnlev 
464843e1988Sjohnlev /*
465843e1988Sjohnlev  * Xen/kernel shared data -- pointer provided in start_info.
466843e1988Sjohnlev  *
467843e1988Sjohnlev  * This structure is defined to be both smaller than a page, and the
468843e1988Sjohnlev  * only data on the shared page, but may vary in actual size even within
469843e1988Sjohnlev  * compatible Xen versions; guests should not rely on the size
470843e1988Sjohnlev  * of this structure remaining constant.
471843e1988Sjohnlev  */
472843e1988Sjohnlev struct shared_info {
473843e1988Sjohnlev     struct vcpu_info vcpu_info[MAX_VIRT_CPUS];
474843e1988Sjohnlev 
475843e1988Sjohnlev     /*
476843e1988Sjohnlev      * A domain can create "event channels" on which it can send and receive
477843e1988Sjohnlev      * asynchronous event notifications. There are three classes of event that
478843e1988Sjohnlev      * are delivered by this mechanism:
479843e1988Sjohnlev      *  1. Bi-directional inter- and intra-domain connections. Domains must
480843e1988Sjohnlev      *     arrange out-of-band to set up a connection (usually by allocating
481843e1988Sjohnlev      *     an unbound 'listener' port and avertising that via a storage service
482843e1988Sjohnlev      *     such as xenstore).
483843e1988Sjohnlev      *  2. Physical interrupts. A domain with suitable hardware-access
484843e1988Sjohnlev      *     privileges can bind an event-channel port to a physical interrupt
485843e1988Sjohnlev      *     source.
486843e1988Sjohnlev      *  3. Virtual interrupts ('events'). A domain can bind an event-channel
487843e1988Sjohnlev      *     port to a virtual interrupt source, such as the virtual-timer
488843e1988Sjohnlev      *     device or the emergency console.
489843e1988Sjohnlev      *
490843e1988Sjohnlev      * Event channels are addressed by a "port index". Each channel is
491843e1988Sjohnlev      * associated with two bits of information:
492843e1988Sjohnlev      *  1. PENDING -- notifies the domain that there is a pending notification
493843e1988Sjohnlev      *     to be processed. This bit is cleared by the guest.
494843e1988Sjohnlev      *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
495843e1988Sjohnlev      *     will cause an asynchronous upcall to be scheduled. This bit is only
496843e1988Sjohnlev      *     updated by the guest. It is read-only within Xen. If a channel
497843e1988Sjohnlev      *     becomes pending while the channel is masked then the 'edge' is lost
498843e1988Sjohnlev      *     (i.e., when the channel is unmasked, the guest must manually handle
499843e1988Sjohnlev      *     pending notifications as no upcall will be scheduled by Xen).
500843e1988Sjohnlev      *
501843e1988Sjohnlev      * To expedite scanning of pending notifications, any 0->1 pending
502843e1988Sjohnlev      * transition on an unmasked channel causes a corresponding bit in a
503843e1988Sjohnlev      * per-vcpu selector word to be set. Each bit in the selector covers a
504843e1988Sjohnlev      * 'C long' in the PENDING bitfield array.
505843e1988Sjohnlev      */
506843e1988Sjohnlev     unsigned long evtchn_pending[sizeof(unsigned long) * 8];
507843e1988Sjohnlev     unsigned long evtchn_mask[sizeof(unsigned long) * 8];
508843e1988Sjohnlev 
509843e1988Sjohnlev     /*
510843e1988Sjohnlev      * Wallclock time: updated only by control software. Guests should base
511843e1988Sjohnlev      * their gettimeofday() syscall on this wallclock-base value.
512843e1988Sjohnlev      */
513843e1988Sjohnlev     uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */
514843e1988Sjohnlev     uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
515843e1988Sjohnlev     uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
516843e1988Sjohnlev 
517843e1988Sjohnlev     struct arch_shared_info arch;
518843e1988Sjohnlev 
519843e1988Sjohnlev };
520a576ab5bSrab #ifndef __XEN__
521843e1988Sjohnlev typedef struct shared_info shared_info_t;
522a576ab5bSrab #endif
523843e1988Sjohnlev 
524843e1988Sjohnlev /*
525a576ab5bSrab  * Start-of-day memory layout:
526843e1988Sjohnlev  *  1. The domain is started within contiguous virtual-memory region.
527a576ab5bSrab  *  2. The contiguous region ends on an aligned 4MB boundary.
528a576ab5bSrab  *  3. This the order of bootstrap elements in the initial virtual region:
529843e1988Sjohnlev  *      a. relocated kernel image
530843e1988Sjohnlev  *      b. initial ram disk              [mod_start, mod_len]
531843e1988Sjohnlev  *      c. list of allocated page frames [mfn_list, nr_pages]
532*ad09f8b8SMark Johnson  *         (unless relocated due to XEN_ELFNOTE_INIT_P2M)
533843e1988Sjohnlev  *      d. start_info_t structure        [register ESI (x86)]
534843e1988Sjohnlev  *      e. bootstrap page tables         [pt_base, CR3 (x86)]
535843e1988Sjohnlev  *      f. bootstrap stack               [register ESP (x86)]
536a576ab5bSrab  *  4. Bootstrap elements are packed together, but each is 4kB-aligned.
537a576ab5bSrab  *  5. The initial ram disk may be omitted.
538a576ab5bSrab  *  6. The list of page frames forms a contiguous 'pseudo-physical' memory
539843e1988Sjohnlev  *     layout for the domain. In particular, the bootstrap virtual-memory
540843e1988Sjohnlev  *     region is a 1:1 mapping to the first section of the pseudo-physical map.
541a576ab5bSrab  *  7. All bootstrap elements are mapped read-writable for the guest OS. The
542843e1988Sjohnlev  *     only exception is the bootstrap page table, which is mapped read-only.
543a576ab5bSrab  *  8. There is guaranteed to be at least 512kB padding after the final
544843e1988Sjohnlev  *     bootstrap element. If necessary, the bootstrap virtual region is
545843e1988Sjohnlev  *     extended by an extra 4MB to ensure this.
546843e1988Sjohnlev  */
547843e1988Sjohnlev 
548843e1988Sjohnlev #define MAX_GUEST_CMDLINE 1024
549843e1988Sjohnlev struct start_info {
550843e1988Sjohnlev     /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME.    */
551843e1988Sjohnlev     char magic[32];             /* "xen-<version>-<platform>".            */
552843e1988Sjohnlev     unsigned long nr_pages;     /* Total pages allocated to this domain.  */
553843e1988Sjohnlev     unsigned long shared_info;  /* MACHINE address of shared info struct. */
554843e1988Sjohnlev     uint32_t flags;             /* SIF_xxx flags.                         */
555843e1988Sjohnlev     xen_pfn_t store_mfn;        /* MACHINE page number of shared page.    */
556843e1988Sjohnlev     uint32_t store_evtchn;      /* Event channel for store communication. */
557843e1988Sjohnlev     union {
558843e1988Sjohnlev         struct {
559843e1988Sjohnlev             xen_pfn_t mfn;      /* MACHINE page number of console page.   */
560843e1988Sjohnlev             uint32_t  evtchn;   /* Event channel for console page.        */
561843e1988Sjohnlev         } domU;
562843e1988Sjohnlev         struct {
563843e1988Sjohnlev             uint32_t info_off;  /* Offset of console_info struct.         */
564843e1988Sjohnlev             uint32_t info_size; /* Size of console_info struct from start.*/
565843e1988Sjohnlev         } dom0;
566843e1988Sjohnlev     } console;
567843e1988Sjohnlev     /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME).     */
568843e1988Sjohnlev     unsigned long pt_base;      /* VIRTUAL address of page directory.     */
569843e1988Sjohnlev     unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames.       */
570843e1988Sjohnlev     unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
571843e1988Sjohnlev     unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
572843e1988Sjohnlev     unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
573843e1988Sjohnlev     int8_t cmd_line[MAX_GUEST_CMDLINE];
574*ad09f8b8SMark Johnson     /* The pfn range here covers both page table and p->m table frames.   */
575*ad09f8b8SMark Johnson     unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table.    */
576*ad09f8b8SMark Johnson     unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table.  */
577843e1988Sjohnlev };
578843e1988Sjohnlev typedef struct start_info start_info_t;
579843e1988Sjohnlev 
580843e1988Sjohnlev /* New console union for dom0 introduced in 0x00030203. */
581843e1988Sjohnlev #if __XEN_INTERFACE_VERSION__ < 0x00030203
582843e1988Sjohnlev #define console_mfn    console.domU.mfn
583843e1988Sjohnlev #define console_evtchn console.domU.evtchn
584843e1988Sjohnlev #endif
585843e1988Sjohnlev 
586843e1988Sjohnlev /* These flags are passed in the 'flags' field of start_info_t. */
587843e1988Sjohnlev #define SIF_PRIVILEGED    (1<<0)  /* Is the domain privileged? */
588843e1988Sjohnlev #define SIF_INITDOMAIN    (1<<1)  /* Is this the initial control domain? */
589349b53ddSStuart Maybee #define SIF_PM_MASK       (0xFF<<8) /* reserve 1 byte for xen-pm options */
590843e1988Sjohnlev 
591843e1988Sjohnlev #define XEN_CONSOLE_INVALID   -1
592843e1988Sjohnlev #define XEN_CONSOLE_COM1       0
593843e1988Sjohnlev #define XEN_CONSOLE_COM2       1
594843e1988Sjohnlev #define XEN_CONSOLE_VGA        2
595843e1988Sjohnlev 
596843e1988Sjohnlev typedef struct dom0_vga_console_info {
597843e1988Sjohnlev     uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
598843e1988Sjohnlev #define XEN_VGATYPE_TEXT_MODE_3 0x03
599843e1988Sjohnlev #define XEN_VGATYPE_VESA_LFB    0x23
600843e1988Sjohnlev 
601843e1988Sjohnlev     union {
602843e1988Sjohnlev         struct {
603843e1988Sjohnlev             /* Font height, in pixels. */
604843e1988Sjohnlev             uint16_t font_height;
605843e1988Sjohnlev             /* Cursor location (column, row). */
606843e1988Sjohnlev             uint16_t cursor_x, cursor_y;
607843e1988Sjohnlev             /* Number of rows and columns (dimensions in characters). */
608843e1988Sjohnlev             uint16_t rows, columns;
609843e1988Sjohnlev         } text_mode_3;
610843e1988Sjohnlev 
611843e1988Sjohnlev         struct {
612843e1988Sjohnlev             /* Width and height, in pixels. */
613843e1988Sjohnlev             uint16_t width, height;
614843e1988Sjohnlev             /* Bytes per scan line. */
615843e1988Sjohnlev             uint16_t bytes_per_line;
616843e1988Sjohnlev             /* Bits per pixel. */
617843e1988Sjohnlev             uint16_t bits_per_pixel;
618843e1988Sjohnlev             /* LFB physical address, and size (in units of 64kB). */
619843e1988Sjohnlev             uint32_t lfb_base;
620843e1988Sjohnlev             uint32_t lfb_size;
621843e1988Sjohnlev             /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
622843e1988Sjohnlev             uint8_t  red_pos, red_size;
623843e1988Sjohnlev             uint8_t  green_pos, green_size;
624843e1988Sjohnlev             uint8_t  blue_pos, blue_size;
625843e1988Sjohnlev             uint8_t  rsvd_pos, rsvd_size;
626349b53ddSStuart Maybee #if __XEN_INTERFACE_VERSION__ >= 0x00030206
627349b53ddSStuart Maybee             /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
628349b53ddSStuart Maybee             uint32_t gbl_caps;
629349b53ddSStuart Maybee             /* Mode attributes (offset 0x0, VESA command 0x4f01). */
630349b53ddSStuart Maybee             uint16_t mode_attrs;
631349b53ddSStuart Maybee #endif
632843e1988Sjohnlev         } vesa_lfb;
633843e1988Sjohnlev     } u;
634843e1988Sjohnlev } dom0_vga_console_info_t;
635a576ab5bSrab #define xen_vga_console_info dom0_vga_console_info
636a576ab5bSrab #define xen_vga_console_info_t dom0_vga_console_info_t
637843e1988Sjohnlev 
638843e1988Sjohnlev typedef uint8_t xen_domain_handle_t[16];
639843e1988Sjohnlev 
640843e1988Sjohnlev /* Turn a plain number into a C unsigned long constant. */
641843e1988Sjohnlev #define __mk_unsigned_long(x) x ## UL
642843e1988Sjohnlev #define mk_unsigned_long(x) __mk_unsigned_long(x)
643843e1988Sjohnlev 
644349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uint8,  uint8_t);
645349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
646349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
647349b53ddSStuart Maybee __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
648843e1988Sjohnlev 
649843e1988Sjohnlev #else /* __ASSEMBLY__ */
650843e1988Sjohnlev 
651843e1988Sjohnlev /* In assembly code we cannot use C numeric constant suffixes. */
652843e1988Sjohnlev #define mk_unsigned_long(x) x
653843e1988Sjohnlev 
654843e1988Sjohnlev #endif /* !__ASSEMBLY__ */
655843e1988Sjohnlev 
656a576ab5bSrab /* Default definitions for macros used by domctl/sysctl. */
657a576ab5bSrab #if defined(__XEN__) || defined(__XEN_TOOLS__)
658a576ab5bSrab #ifndef uint64_aligned_t
659a576ab5bSrab #define uint64_aligned_t uint64_t
660a576ab5bSrab #endif
661a576ab5bSrab #ifndef XEN_GUEST_HANDLE_64
662a576ab5bSrab #define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
663a576ab5bSrab #endif
664a576ab5bSrab #endif
665a576ab5bSrab 
666843e1988Sjohnlev #endif /* __XEN_PUBLIC_XEN_H__ */
667843e1988Sjohnlev 
668843e1988Sjohnlev /*
669843e1988Sjohnlev  * Local variables:
670843e1988Sjohnlev  * mode: C
671843e1988Sjohnlev  * c-set-style: "BSD"
672843e1988Sjohnlev  * c-basic-offset: 4
673843e1988Sjohnlev  * tab-width: 4
674843e1988Sjohnlev  * indent-tabs-mode: nil
675843e1988Sjohnlev  * End:
676843e1988Sjohnlev  */
677