1// vim:set ft=cpp: -*- Mode: C++ -*-
2/*!
3 * \file
4 * L4::Kip class, memory descriptors.
5 *
6 * \author Alexander Warg <alexander.warg@os.inf.tu-dresden.de>
7 * \ingroup l4_api
8 *
9 */
10/*
11 * (c) 2008-2009 Author(s)
12 *     economic rights: Technische Universität Dresden (Germany)
13 *
14 * This file is part of TUD:OS and distributed under the terms of the
15 * GNU General Public License 2.
16 * Please see the COPYING-GPL-2 file for details.
17 *
18 * As a special exception, you may use this file as part of a free software
19 * library without restriction.  Specifically, if other files instantiate
20 * templates or use macros or inline functions from this file, or you compile
21 * this file and link it with other files to produce an executable, this
22 * file does not by itself cause the resulting executable to be covered by
23 * the GNU General Public License.  This exception does not however
24 * invalidate any other reasons why the executable file might be covered by
25 * the GNU General Public License.
26 */
27#ifndef L4_SYS_KIP_H__
28#define L4_SYS_KIP_H__
29
30#include <l4/cxx/static_vector>
31
32/* C++ version of memory descriptors */
33
34/**
35 * \defgroup l4_kip_api Kernel Interface Page
36 * \ingroup l4_api
37 * Kernel Interface Page.
38 *
39 * C++ interface for the Kernel Interface Page:<br>
40 * \includefile{l4/sys/kip}
41 */
42
43namespace L4
44{
45  namespace Kip
46  {
47    /**
48     * Memory descriptors stored in the kernel interface page.
49     * \ingroup l4_kip_api
50     *
51     * \includefile{l4/sys/kip}
52     */
53    class Mem_desc
54    {
55    public:
56      /**
57       * Memory types.
58       */
59      enum Mem_type
60      {
61        Undefined    = 0x0,  ///< Undefined memory
62        Conventional = 0x1,  ///< Conventional memory
63        Reserved     = 0x2,  ///< Reserved region, do not use this memory
64        Dedicated    = 0x3,  ///< Dedicated
65        Shared       = 0x4,  ///< Shared
66
67        Info         = 0xd,  ///< Info by boot loader
68        Bootloader   = 0xe,  ///< Memory belongs to the boot loader
69        Arch         = 0xf   ///< Architecture specific memory
70      };
71
72      /**
73       * Memory sub types for the Mem_type::Info type
74       */
75      enum Info_sub_type
76      {
77        Info_acpi_rsdp = 0  ///< Physical address of the ACPI root pointer.
78      };
79
80    private:
81      unsigned long _l, _h;
82
83      static unsigned long &memory_info(void *kip) noexcept
84      { return *((unsigned long *)kip + 21); }
85
86      static unsigned long memory_info(void const *kip) noexcept
87      { return *((unsigned long const *)kip + 21); }
88
89    public:
90      /**
91       * Get first memory descriptor.
92       *
93       * \param kip  Pointer to the kernel info page
94       *
95       * \return First memory descriptor stored in the kernel info page
96       */
97      static Mem_desc *first(void *kip) noexcept
98      {
99        return (Mem_desc *)((char *)kip
100               + (memory_info(kip) >> ((sizeof(unsigned long) / 2) * 8)));
101      }
102
103      static Mem_desc const *first(void const *kip) noexcept
104      {
105        return (Mem_desc const *)((char const *)kip
106               + (memory_info(kip) >> ((sizeof(unsigned long) / 2) * 8)));
107      }
108
109      /**
110       * Return number of memory descriptors stored in the kernel info page.
111       *
112       * \param kip  Pointer to the kernel info page
113       *
114       * \return Number of memory descriptors in the kernel info page.
115       */
116      static unsigned long count(void const *kip) noexcept
117      {
118        return memory_info(kip)
119               & ((1UL << ((sizeof(unsigned long) / 2) * 8)) - 1);
120      }
121
122      /**
123       * Set number of memory descriptors.
124       *
125       * \param kip    Pointer to the kernel info page
126       * \param count  Number of memory descriptors
127       */
128      static void count(void *kip, unsigned count) noexcept
129      {
130        unsigned long &mi = memory_info(kip);
131        mi = (mi & ~((1UL << ((sizeof(unsigned long) / 2) * 8)) - 1)) | count;
132      }
133
134      /**
135       * Return enumerable list of memory descriptors
136       *
137       * \param kip  Pointer to the kernel info page.
138       */
139      static inline cxx::static_vector<Mem_desc const> all(void const *kip)
140      {
141        return cxx::static_vector<Mem_desc const>(Mem_desc::first(kip),
142                                                  Mem_desc::count(kip));
143      }
144
145      /**
146       * Return enumerable list of memory descriptors
147       *
148       * \param kip  Pointer to the kernel info page.
149       */
150      static inline cxx::static_vector<Mem_desc> all(void *kip)
151      {
152        return cxx::static_vector<Mem_desc>(Mem_desc::first(kip),
153                                            Mem_desc::count(kip));
154      }
155
156      /**
157       * Initialize memory descriptor.
158       *
159       * \param start  Start address
160       * \param end    End address
161       * \param t      Memory type
162       * \param st     Memory subtype, defaults to 0
163       * \param virt   True for virtual memory, false for physical memory,
164       *               defaults to physical
165       */
166      Mem_desc(unsigned long start, unsigned long end,
167               Mem_type t, unsigned char st = 0, bool virt = false) noexcept
168      : _l((start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0)
169           | (virt ? 0x0200 : 0x0)), _h(end | 0x3ffUL)
170      {}
171
172      /**
173       * Return start address of memory descriptor.
174       *
175       * \return Start address of memory descriptor
176       */
177      unsigned long start() const noexcept { return _l & ~0x3ffUL; }
178
179      /**
180       * Return end address of memory descriptor.
181       *
182       * \return End address of memory descriptor
183       */
184      unsigned long end() const noexcept { return _h | 0x3ffUL; }
185
186      /**
187       * Return size of region described by the memory descriptor.
188       *
189       * \return Size of the region described by the memory descriptor
190       */
191      unsigned long size() const noexcept { return end() + 1 - start(); }
192
193      /**
194       * Return type of the memory descriptor.
195       *
196       * \return Type of the memory descriptor
197       */
198      Mem_type type() const noexcept { return (Mem_type)(_l & 0x0f); }
199
200      /**
201       * Return sub-type of the memory descriptor.
202       *
203       * \return Sub-type of the memory descriptor
204       */
205      unsigned char sub_type() const noexcept { return (_l >> 4) & 0x0f; }
206
207      /**
208       * Return whether the memory descriptor describes a virtual or
209       * physical region.
210       *
211       * \return True for virtual region, false for physical region.
212       */
213      unsigned is_virtual() const noexcept { return _l & 0x200; }
214
215      /**
216       * Set values of a memory descriptor.
217       *
218       * \param start  Start address
219       * \param end    End address
220       * \param t      Memory type
221       * \param st     Sub-type, defaults to 0
222       * \param virt   Virtual or physical memory region, defaults to physical
223       */
224      void set(unsigned long start, unsigned long end,
225               Mem_type t, unsigned char st = 0, bool virt = false) noexcept
226      {
227        _l = (start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0)
228             | (virt?0x0200:0x0);
229
230        _h = end | 0x3ffUL;
231      }
232
233    };
234  };
235};
236
237#endif
238