1// -*- Mode: C++ -*-
2// vim:ft=cpp
3/*
4 * Copyright (C) 2017 Kernkonzept GmbH.
5 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
6 *
7 * This file is distributed under the terms of the GNU General Public
8 * License, version 2.  Please see the COPYING-GPL-2 file for details.
9 */
10#pragma once
11
12#include <l4/re/protocols.h>
13#include <l4/sys/capability>
14#include <l4/sys/cxx/ipc_types>
15#include <l4/sys/cxx/ipc_iface>
16
17namespace L4Re
18{
19
20/**
21 * Interface for memory-like address space accessible via IPC.
22 *
23 * This interface defines methods for indirect access to MMIO regions.
24 *
25 * Memory mapped IO (MMIO) is used by device drivers to control hardware
26 * devices. Access to MMIO regions is assigned to user-level device drivers
27 * via mappings of memory pages.
28 *
29 * However, there are hardware platforms where MMIO regions for different
30 * devices share the same memory page.  With respect to security and safety,
31 * it is often not allowed to map a memory page to multiple device drivers
32 * because the driver of one device could then influence operation of another
33 * device, which violates security boundaries.
34 *
35 * A solution to that problem is to implement a third (trusted) component that
36 * gets exclusive access to the shared memory page, and that drivers can
37 * access via IPC with the Mmio_space protocol. This proxy-component can then
38 * enforce an access policy.
39 *
40 * \includefile{l4/re/mmio_space}
41 */
42struct L4_EXPORT Mmio_space
43: public L4::Kobject_t<Mmio_space, L4::Kobject, L4RE_PROTO_MMIO_SPACE>
44{
45  /// Actual size of the value to read or write.
46  enum Access_width
47  {
48    Wd_8bit = 0,  ///< Value is a byte.
49    Wd_16bit = 1, ///< Value is a 2-byte word.
50    Wd_32bit = 2, ///< Value is a 4-byte word.
51    Wd_64bit = 3  ///< Value is a 8-byte word.
52  };
53
54  /// Device address.
55  typedef l4_uint64_t Addr;
56
57  /**
58   * Read a value from the given address.
59   *
60   * \param      addr   Device virtual address to read from. The address
61   *                    must be aligned relative to the access width.
62   * \param      width  Access width of value to be read, see #Access_width.
63   * \param[out] value  Return value. If width is smaller than 64 bit,the
64   *                    upper bits are guaranteed to be 0.
65   *
66   * \retval #L4_EOK       Success.
67   * \retval -L4_EPERM   Insufficient read rights.
68   * \retval -L4_EINVAL  Address does not exist or cannot be accessed
69   *                     with the given width.
70   */
71  L4_INLINE_RPC(long, mmio_read, (Addr addr, char width, l4_uint64_t *value));
72
73  /**
74   * Write a value to the given address.
75   *
76   * \param addr   Device virtual address to write to. The address
77   *               must be aligned relative to the access width.
78   * \param width  Access width of value to write, see #Access_width.
79   * \param value  Value to write. If width is smaller than 64 bit,
80   *               the upper bits are ignored.
81   *
82   * \retval #L4_EOK       Success.
83   * \retval -L4_EPERM   Insufficient write rights.
84   * \retval -L4_EINVAL  Address does not exist or cannot be accessed
85   *                     with the given width.
86   */
87  L4_INLINE_RPC(long, mmio_write, (Addr addr, char width, l4_uint64_t value));
88
89  typedef L4::Typeid::Rpcs<mmio_read_t, mmio_write_t> Rpcs;
90};
91
92}
93