1#
2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3#
4# SPDX-License-Identifier: BSD-2-Clause
5#
6
7from __future__ import absolute_import, division, print_function, \
8    unicode_literals
9
10from capdl.Object import Object, Frame, CNode, Endpoint, Notification, SchedControl
11
12
13class Cap(object):
14    """
15    A capability to a kernel object.
16    """
17
18    def __init__(self, referent, **kwargs):
19        assert isinstance(referent, Object)
20        self.referent = referent
21        self.read = False
22        self.write = False
23        self.grant = False
24        self.grantreply = False
25        self.guard = 0
26        self.guard_size = 0
27        self.badge = None
28        self.cached = True
29        self.ports = None
30        self.mapping_container = None
31        self.mapping_slot = None
32        self.mapping_deferred = False
33        for (k, v) in kwargs.items():
34            if hasattr(self, k):
35                setattr(self, k, v)
36
37    def set_guard(self, guard):
38        assert isinstance(self.referent, CNode)
39        assert isinstance(guard, int)
40        assert guard % 2**18 == guard, 'guards can be a maximum of 18 bits'
41        self.guard = guard
42
43    def set_guard_size(self, guard_size):
44        assert isinstance(self.referent, CNode)
45        assert isinstance(guard_size, int)
46        self.guard_size = guard_size
47
48    def set_badge(self, badge):
49        # Only endpoint caps can be badged.
50        assert isinstance(self.referent, Endpoint) or \
51            isinstance(self.referent, Notification)
52        assert badge % 2**28 == badge, 'badges can be a maximum of 28 bits'
53        self.badge = badge
54
55    def set_cached(self, cached):
56        assert isinstance(self.referent, Frame)
57        self.cached = cached
58
59    def set_mapping(self, container, slot):
60        """
61        @brief      For a frame cap in a cspace, ensure that this is the
62                    cap used for a mapping into a mapping object specified by
63                    container and slot.
64
65        @param      self       A frame cap that is inside a CNode.
66        @param      container  The mapping object the frame is mapped into.
67        @param      slot       The index of the mapping object
68        """
69        assert isinstance(self.referent, Frame)
70        self.mapping_container = container
71        self.mapping_slot = slot
72
73    def set_mapping_deferred(self):
74        """
75        @brief      Indicate that this cap is a mapping cap, but the container
76                    and slot values are to be set later.
77        """
78        assert isinstance(self.referent, Frame)
79        self.mapping_deferred = True
80
81    def __repr__(self):
82        extra = []
83
84        if isinstance(self.referent, SchedControl):
85            return "sched_control (core: %d)" % self.referent.core
86
87        if isinstance(self.referent,
88                      (Frame, Endpoint, Notification)):
89            is_frame = isinstance(self.referent, Frame)
90            rights = [sym for sym, flag in
91                      [('R', self.read),
92                       ('W', self.write),
93                       ('X', is_frame and self.grant),
94                       ('G', not is_frame and self.grant),
95                       ('P', self.grantreply)]
96                      if flag]
97            extra.append(''.join(rights))
98
99        if isinstance(self.referent, Frame) and not self.cached:
100            extra.append('uncached')
101        if isinstance(self.referent, Frame) and \
102                self.mapping_container is not None:
103            extra.append('mapping: (%s, %d)' % (self.mapping_container.name, self.mapping_slot))
104        if isinstance(self.referent, (Endpoint, Notification)) and \
105           self.badge is not None:
106            extra.append('badge: %d' % self.badge)
107        if isinstance(self.referent, CNode):
108            extra.append('guard: %s' % self.guard)
109            extra.append('guard_size: %s' % self.guard_size)
110
111        extra = [x for x in extra if x != '']
112
113        return '%s%s' % (self.referent.name,
114                         (' (%s)' % ', '.join(extra)) if extra else '')
115