1/**
2 * \file
3 * \brief Essential capability definitions.
4 */
5
6/*
7 * Copyright (c) 2007-2012, 2016, ETH Zurich.
8 * Copyright (c) 2015, 2016 Hewlett Packard Enterprise Development LP.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#ifndef BARRELFISH_CAPABILITIES_H
17#define BARRELFISH_CAPABILITIES_H
18
19/* FIXME: OBJBITS and OBJSIZE defines must match sizes in Hamlet's capabilities/caps.hl */
20
21// Size of CNode entry
22#define OBJBITS_CTE             6
23
24/// Number of entries in L2 CNode in bits
25#define L2_CNODE_BITS           8
26/// Number of entries in L2 CNode
27#define L2_CNODE_SLOTS          (1UL << L2_CNODE_BITS)
28
29#ifndef __ASSEMBLER__
30
31#include <assert.h>
32#include <stdbool.h>
33#include <barrelfish_kpi/types.h>
34
35#define CAPRIGHTS_READ          (1 << 0)
36#define CAPRIGHTS_WRITE         (1 << 1)
37#define CAPRIGHTS_EXECUTE       (1 << 2)
38#define CAPRIGHTS_GRANT         (1 << 3)
39#define CAPRIGHTS_IDENTIFY      (1 << 4)
40#define CAPRIGHTS_NUM           5
41
42#define CAPRIGHTS_ALLRIGHTS     ((1 << CAPRIGHTS_NUM) - 1)
43#define CAPRIGHTS_READ_WRITE    (CAPRIGHTS_READ | CAPRIGHTS_WRITE)
44#define CAPRIGHTS_NORIGHTS      0
45
46typedef uint8_t         CapRights;
47#define PRIuCAPRIGHTS PRIu8
48#define PRIxCAPRIGHTS PRIx8
49
50struct dcb;
51
52// capbits needs CapRights and dcb;
53#include <barrelfish_kpi/capbits.h>
54
55STATIC_ASSERT((L2_CNODE_SLOTS  * (1UL << OBJBITS_CTE)) == OBJSIZE_L2CNODE,
56        "l2 cnode size doesn't match cte size");
57
58static inline bool type_is_vnode(enum objtype type)
59{
60    STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
61
62    return (type == ObjType_VNode_x86_64_pml4 ||
63            type == ObjType_VNode_x86_64_pdpt ||
64            type == ObjType_VNode_x86_64_pdir ||
65            type == ObjType_VNode_x86_64_ptable ||
66            type == ObjType_VNode_x86_32_pdpt ||
67            type == ObjType_VNode_x86_32_pdir ||
68            type == ObjType_VNode_x86_32_ptable ||
69            type == ObjType_VNode_AARCH64_l3 ||
70            type == ObjType_VNode_AARCH64_l2 ||
71            type == ObjType_VNode_AARCH64_l1 ||
72            type == ObjType_VNode_AARCH64_l0 ||
73            type == ObjType_VNode_ARM_l2 ||
74            type == ObjType_VNode_ARM_l1
75           );
76}
77
78static inline bool type_is_vroot(enum objtype type)
79{
80    STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
81
82    return (type == ObjType_VNode_x86_64_pml4 ||
83#ifdef CONFIG_PAE
84            type == ObjType_VNode_x86_32_pdpt ||
85#else
86            type == ObjType_VNode_x86_32_pdir ||
87#endif
88            type == ObjType_VNode_AARCH64_l0 ||
89            type == ObjType_VNode_ARM_l1
90           );
91}
92/**
93 * Return size of vnode in bits. This is the size of a page table page.
94 *
95 * @param type Object type.
96 *
97 * @return Number of bits a VNode object occupies.
98 */
99static inline size_t vnode_objbits(enum objtype type)
100{
101    // This function should be emitted by hamlet or somesuch.
102    STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
103
104    if (type == ObjType_VNode_x86_64_pml4 ||
105        type == ObjType_VNode_x86_64_pdpt ||
106        type == ObjType_VNode_x86_64_pdir ||
107        type == ObjType_VNode_x86_64_ptable ||
108        type == ObjType_VNode_x86_32_pdpt ||
109        type == ObjType_VNode_x86_32_pdir ||
110        type == ObjType_VNode_x86_32_ptable)
111    {
112        return 12;
113    }
114    else if (type == ObjType_VNode_AARCH64_l0 ||
115             type == ObjType_VNode_AARCH64_l1 ||
116             type == ObjType_VNode_AARCH64_l2 ||
117             type == ObjType_VNode_AARCH64_l3)
118    {
119        return 12;
120    }
121    else if (type == ObjType_VNode_ARM_l1)
122    {
123        return 14;
124    }
125    else if (type == ObjType_VNode_ARM_l2)
126    {
127        return 10;
128    }
129
130    assert(0 && !"Page table size unknown.");
131    return 0;
132}
133
134/**
135 * Return size of vnode in bytes. This is the size of a page table page.
136 *
137 * @param type Object type.
138 *
139 * @return Size of a VNode in bytes.
140 *
141 * XXX: this should probably just do 1UL << vnode_objbits(type) for vnode
142 * objtypes -SG, 2016-07-06.
143 */
144static inline size_t vnode_objsize(enum objtype type)
145{
146    // This function should be emitted by hamlet or somesuch.
147    STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
148
149    if (type == ObjType_VNode_x86_64_pml4 ||
150        type == ObjType_VNode_x86_64_pdpt ||
151        type == ObjType_VNode_x86_64_pdir ||
152        type == ObjType_VNode_x86_64_ptable ||
153        type == ObjType_VNode_x86_32_pdpt ||
154        type == ObjType_VNode_x86_32_pdir ||
155        type == ObjType_VNode_x86_32_ptable)
156    {
157        // XXX: cannot use BASE_PAGE_SIZE here because asmoffsets does not
158        // include the right files
159        return 4096; // BASE_PAGE_SIZE
160    }
161    else if (type == ObjType_VNode_AARCH64_l0 ||
162             type == ObjType_VNode_AARCH64_l1 ||
163             type == ObjType_VNode_AARCH64_l2 ||
164             type == ObjType_VNode_AARCH64_l3)
165    {
166        return 4096;
167    }
168    else if (type == ObjType_VNode_ARM_l1)
169    {
170        // ARMv7 L1 page table is 16kB.
171        return 16384;
172    }
173    else if (type == ObjType_VNode_ARM_l2)
174    {
175        return 1024;
176    }
177
178    assert(0 && !"Page table size unknown.");
179    return 0;
180}
181
182/**
183 * Return number of page table entries for vnode in bits.
184 * @param type Object type.
185 * @return Number of page table entries in bits
186 */
187static inline size_t vnode_entry_bits(enum objtype type) {
188    // This function should be emitted by hamlet or somesuch.
189    STATIC_ASSERT(50 == ObjType_Num, "Check VNode definitions");
190
191    if (type == ObjType_VNode_x86_64_pml4 ||
192        type == ObjType_VNode_x86_64_pdpt ||
193        type == ObjType_VNode_x86_64_pdir ||
194        type == ObjType_VNode_x86_64_ptable)
195    {
196        return 9;      // log2(X86_64_PTABLE_SIZE)
197    }
198#ifdef CONFIG_PAE
199    if (type == ObjType_VNode_x86_32_pdpt)
200    {
201        return 2;       // log2(X86_32_PDPTE_SIZE)
202    }
203    else if (type == ObjType_VNode_x86_32_pdir ||
204             type == ObjType_VNode_x86_32_ptable)
205    {
206        return 9;       // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
207    }
208#else
209    if (type == ObjType_VNode_x86_32_pdir ||
210        type == ObjType_VNode_x86_32_ptable)
211    {
212        return 10;      // log2(X86_32_PTABLE_SIZE) == log2(X86_32_PDIR_SIZE)
213    }
214#endif
215
216    if (type == ObjType_VNode_AARCH64_l0 ||
217        type == ObjType_VNode_AARCH64_l1 ||
218        type == ObjType_VNode_AARCH64_l2 ||
219        type == ObjType_VNode_AARCH64_l3)
220    {
221        return 9;       // log2(ARM_MAX_ENTRIES)
222    }
223
224    if (type == ObjType_VNode_ARM_l2)
225    {
226        return 9;       // log2(ARM_L2_MAX_ENTRIES)
227    }
228    else if (type == ObjType_VNode_ARM_l1)
229    {
230        return 12;      // log2(ARM_L1_MAX_ENTRIES)
231    }
232
233    assert(!"unknown page table type");
234    return 0;
235}
236
237/**
238 * Return number of slots for cnode in bits.
239 * @param type Object type.
240 * @return Number of page table entries in bits
241 */
242static inline size_t cnode_get_slots(struct capability *cnode) {
243    STATIC_ASSERT(50 == ObjType_Num, "Check CNode definitions");
244
245    switch (cnode->type) {
246        case ObjType_L1CNode:
247            return cnode->u.l1cnode.allocated_bytes / (1UL << OBJBITS_CTE);
248        case ObjType_L2CNode:
249            return L2_CNODE_SLOTS;
250        default:
251            assert(!"not a cnode");
252            return 0;
253    }
254}
255
256static inline enum objtype get_mapping_type(enum objtype captype)
257{
258    STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mapping types");
259
260    switch (captype) {
261        case ObjType_Frame:
262            return ObjType_Frame_Mapping;
263        case ObjType_DevFrame:
264            return ObjType_DevFrame_Mapping;
265        case ObjType_VNode_x86_64_pml4:
266            return ObjType_VNode_x86_64_pml4_Mapping;
267        case ObjType_VNode_x86_64_pdpt:
268            return ObjType_VNode_x86_64_pdpt_Mapping;
269        case ObjType_VNode_x86_64_pdir:
270            return ObjType_VNode_x86_64_pdir_Mapping;
271        case ObjType_VNode_x86_64_ptable:
272            return ObjType_VNode_x86_64_ptable_Mapping;
273        case ObjType_VNode_x86_32_pdpt:
274            return ObjType_VNode_x86_32_pdpt_Mapping;
275        case ObjType_VNode_x86_32_pdir:
276            return ObjType_VNode_x86_32_pdir_Mapping;
277        case ObjType_VNode_x86_32_ptable:
278            return ObjType_VNode_x86_32_ptable_Mapping;
279        case ObjType_VNode_ARM_l1:
280            return ObjType_VNode_ARM_l1_Mapping;
281        case ObjType_VNode_ARM_l2:
282            return ObjType_VNode_ARM_l2_Mapping;
283        case ObjType_VNode_AARCH64_l0:
284            return ObjType_VNode_AARCH64_l0_Mapping;
285        case ObjType_VNode_AARCH64_l1:
286            return ObjType_VNode_AARCH64_l1_Mapping;
287        case ObjType_VNode_AARCH64_l2:
288            return ObjType_VNode_AARCH64_l2_Mapping;
289        case ObjType_VNode_AARCH64_l3:
290            return ObjType_VNode_AARCH64_l3_Mapping;
291        /* all other types are not mappable */
292        default:
293            return ObjType_Null;
294    }
295}
296
297static inline bool type_is_mapping(enum objtype type)
298{
299    STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mapping types");
300
301    switch (type) {
302        case ObjType_Frame_Mapping:
303        case ObjType_DevFrame_Mapping:
304        case ObjType_VNode_x86_64_pml4_Mapping:
305        case ObjType_VNode_x86_64_pdpt_Mapping:
306        case ObjType_VNode_x86_64_pdir_Mapping:
307        case ObjType_VNode_x86_64_ptable_Mapping:
308        case ObjType_VNode_x86_32_pdpt_Mapping:
309        case ObjType_VNode_x86_32_pdir_Mapping:
310        case ObjType_VNode_x86_32_ptable_Mapping:
311        case ObjType_VNode_ARM_l1_Mapping:
312        case ObjType_VNode_ARM_l2_Mapping:
313        case ObjType_VNode_AARCH64_l0_Mapping:
314        case ObjType_VNode_AARCH64_l1_Mapping:
315        case ObjType_VNode_AARCH64_l2_Mapping:
316        case ObjType_VNode_AARCH64_l3_Mapping:
317            return true;
318
319        /* all other types are not mapping types */
320        default:
321            return false;
322    }
323}
324
325static inline bool type_is_mappable(enum objtype type)
326{
327    STATIC_ASSERT(50 == ObjType_Num, "Knowledge of all mappable types");
328
329    switch (type) {
330        case ObjType_Frame:
331        case ObjType_DevFrame:
332        case ObjType_VNode_x86_64_pml4:
333        case ObjType_VNode_x86_64_pdpt:
334        case ObjType_VNode_x86_64_pdir:
335        case ObjType_VNode_x86_64_ptable:
336        case ObjType_VNode_x86_32_pdpt:
337        case ObjType_VNode_x86_32_pdir:
338        case ObjType_VNode_x86_32_ptable:
339        case ObjType_VNode_ARM_l1:
340        case ObjType_VNode_ARM_l2:
341        case ObjType_VNode_AARCH64_l0:
342        case ObjType_VNode_AARCH64_l1:
343        case ObjType_VNode_AARCH64_l2:
344        case ObjType_VNode_AARCH64_l3:
345            return true;
346
347        /* all other types are not mappable */
348        default:
349            return false;
350    }
351}
352
353/**
354 * CNode capability commands.
355 */
356enum cnode_cmd {
357    CNodeCmd_Copy,      ///< Copy capability
358    CNodeCmd_Mint,      ///< Mint capability
359    CNodeCmd_Retype,    ///< Retype capability
360    CNodeCmd_Delete,    ///< Delete capability
361    CNodeCmd_Revoke,    ///< Revoke capability
362    CNodeCmd_Create,    ///< Create capability
363    CNodeCmd_GetState,  ///< Get distcap state for capability
364    CNodeCmd_GetSize,   ///< Get Size of CNode, only applicable for L1 Cnode
365    CNodeCmd_Resize,    ///< Resize CNode, only applicable for L1 Cnode
366};
367
368enum vnode_cmd {
369    VNodeCmd_Map,
370    VNodeCmd_Unmap,
371    VNodeCmd_Identify,   ///< Return the physical address of the VNode
372    VNodeCmd_ModifyFlags,
373};
374
375/**
376 * Mapping commands
377 */
378enum mapping_cmd {
379    MappingCmd_Modify,
380    MappingCmd_Destroy,
381};
382
383/**
384 * Kernel capabilities commands.
385 * Monitor's invocations of capability operations
386 * which the kernel will not subject to cross core checks
387 */
388enum kernel_cmd {
389    KernelCmd_Spawn_core,         ///< Spawn a new kernel
390    KernelCmd_Identify_cap,       ///< Return the meta data of a capability
391    KernelCmd_Identify_domains_cap, ///< Return the meta data of another domain's capability
392    KernelCmd_Remote_relations,   ///< Set capability as being remote
393    KernelCmd_Cap_has_relations,      ///< Return presence of local relations
394    KernelCmd_Create_cap,         ///< Create a new capability
395    KernelCmd_Copy_existing,
396    KernelCmd_Get_core_id,        ///< Returns the id of the core the domain is on
397    KernelCmd_Get_arch_id,        ///< Returns arch id of caller's core
398    KernelCmd_Nullify_cap,        ///< Set the capability to NULL allowed it to be reused
399    KernelCmd_Setup_trace,        ///< Set up trace buffer
400    KernelCmd_Register,           ///< Register monitor notify endpoint
401    KernelCmd_Domain_Id,          ///< Set domain ID of dispatcher
402    KernelCmd_Get_cap_owner,
403    KernelCmd_Set_cap_owner,
404    KernelCmd_Lock_cap,
405    KernelCmd_Unlock_cap,
406    KernelCmd_Delete_last,
407    KernelCmd_Delete_foreigns,
408    KernelCmd_Revoke_mark_target,
409    KernelCmd_Revoke_mark_relations,
410    KernelCmd_Delete_step,
411    KernelCmd_Clear_step,
412    KernelCmd_Retype,
413    KernelCmd_Has_descendants,
414    KernelCmd_Is_retypeable,
415    KernelCmd_Sync_timer,
416    KernelCmd_IPI_Register,
417    KernelCmd_IPI_Delete,
418    KernelCmd_GetGlobalPhys,
419    KernelCmd_Add_kcb,            ///< add extra kcb to be scheduled
420    KernelCmd_Remove_kcb,         ///< remove kcb from scheduling ring
421    KernelCmd_Suspend_kcb_sched,  ///< suspend/resume kcb scheduler
422    KernelCmd_Get_platform,       ///< Get architecture platform
423    KernelCmd_Count
424};
425
426/**
427 * Specific commands for dispatcher capabilities.
428 */
429enum dispatcher_cmd {
430    DispatcherCmd_Setup,            ///< Set dispatcher parameters
431    DispatcherCmd_Properties,       ///< Set dispatcher properties
432    DispatcherCmd_PerfMon,          ///< Performance monitoring
433    DispatcherCmd_SetupGuest,       ///< Set up the DCB of a guest domain
434    DispatcherCmd_DumpPTables,      ///< Dump hw page tables of dispatcher
435    DispatcherCmd_DumpCapabilities, ///< Dump capabilities of dispatcher
436    DispatcherCmd_Vmread,           ///< Execute vmread on the current and active VMCS
437    DispatcherCmd_Vmwrite,          ///< Execute vmwrite on the current and active VMCS
438    DispatcherCmd_Vmptrld,          ///< Make VMCS clear and inactive
439    DispatcherCmd_Vmclear,          ///< Make VMCS current and active
440};
441
442/**
443 * Frame capability commands.
444 */
445enum frame_cmd {
446    FrameCmd_Identify,      ///< Return physical address of frame
447};
448
449/**
450 * Kernel control block commands.
451 */
452enum kcb_cmd {
453    KCBCmd_Clone = FrameCmd_Identify+1, ///< Duplicate core_data
454};
455
456/**
457 * RAM capability commands
458 */
459enum ram_cmd {
460    RAMCmd_Identify,      ///< Return physical address of frame
461};
462
463/**
464 * IRQ Table capability commands.
465 */
466enum irqtable_cmd {
467    IRQTableCmd_Alloc,  ///< Allocate new vector (XXX: HACK: this is x86 specific)
468    IRQTableCmd_AllocDestCap,  ///< Allocate new dest capability (XXX: HACK: this is x86 specific)
469    IRQTableCmd_Set,    ///< Set endpoint for IRQ# notifications
470    IRQTableCmd_Delete  ///< Remove notification endpoint for IRQ#
471};
472
473/**
474 * IRQ Vector commands.
475 */
476
477enum irqdest_cmd {
478	IRQDestCmd_Connect,	///< Connect this capability to a messaging channel
479	IRQDestCmd_GetVector, ///< Return the local interrupt vector
480	IRQDestCmd_GetCpu ///< Return the local interrupt vector
481};
482
483/**
484 * IRQ Vector commands.
485 */
486
487enum irqsrc_cmd {
488    IRQSrcCmd_GetVecStart,   ///< Return vector range start
489    IRQSrcCmd_GetVecEnd   ///< Return vector range high
490};
491
492
493/**
494 * IO capability commands.
495 */
496enum io_cmd {
497    IOCmd_Outb,         ///< Output byte to port
498    IOCmd_Outw,         ///< Output word to port
499    IOCmd_Outd,         ///< Output double word to port
500    IOCmd_Inb,          ///< Input byte from port
501    IOCmd_Inw,          ///< Input word from port
502    IOCmd_Ind           ///< Input double word from port
503};
504
505/**
506 * Notify capability commands.
507 */
508enum notify_cmd {
509    NotifyCmd_Send
510};
511
512
513/**
514 * Performance monitoring commands.
515 * Seems to be already included in the Dispatcher capability.
516 */
517enum perfmon_cmd {
518    PerfmonCmd_Activate,    ///< Activate performance counters
519    PerfmonCmd_Deactivate,  ///< Deactivate performance counters
520    PerfmonCmd_Write        ///< Read current performance counter values
521};
522
523
524/**
525 * ID capability commands.
526 */
527enum id_cmd {
528    IDCmd_Identify  ///< Return system-wide unique ID
529};
530
531/**
532 * IPI capability commands
533 */
534
535enum ipi_cmd {
536    IPICmd_Send_Start,     ///< Send Startup IPI to a destination core
537    IPICmd_Send_Init,      ///< Send Init IPI to a destination core
538};
539/**
540 * Maximum command ordinal.
541 */
542#define CAP_MAX_CMD KernelCmd_Count
543
544/**
545 * \brief Values returned from frame identify invocation
546 */
547struct frame_identity {
548    genpaddr_t base;   ///< Physical base address of frame
549    gensize_t  bytes;  ///< Size of frame, in bytes
550};
551
552/**
553 * \brief Values returned from the VNode identify invocation
554 */
555struct vnode_identity {
556    genpaddr_t base;   ///< Physical base address of the VNode
557    uint8_t type;      ///< Type of VNode
558};
559
560#endif // __ASSEMBLER__
561
562#endif // BARRELFISH_CAPABILITIES_H
563