]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/vmm/server/src/ram_ds.cc
Update
[l4.git] / l4 / pkg / vmm / server / src / ram_ds.cc
1 /*
2  * Copyright (C) 2015 Kernkonzept GmbH.
3  * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
4  *
5  * This file is distributed under the terms of the GNU General Public
6  * License, version 2.  Please see the COPYING-GPL-2 file for details.
7  */
8
9 #include <l4/re/env>
10 #include <l4/re/error_helper>
11 #include <l4/l4re_vfs/backend>
12
13 #include "debug.h"
14 #include "ram_ds.h"
15
16 namespace Vmm {
17
18 Ram_ds::Ram_ds(L4::Cap<L4Re::Dataspace> ram, l4_addr_t vm_base)
19 : _ram(ram),
20   _dma(L4Re::chkcap(L4Re::Util::cap_alloc.alloc<L4Re::Dma_space>()))
21 {
22   Dbg info(Dbg::Info);
23
24   _vm_start = vm_base;
25   _size = ram->size();
26
27   auto *env = L4Re::Env::env();
28
29   int err = l4_error(env->user_factory()->create(_dma.get()));
30
31   if (err >= 0)
32     err = _dma->associate(L4::Ipc::Cap<L4::Task>(L4::Cap<void>::Invalid),
33                           L4Re::Dma_space::Phys_space);
34
35   if (err < 0)
36     _dma = L4::Cap<L4Re::Dma_space>::Invalid;
37
38   l4_size_t phys_size = _size;
39   L4Re::Dma_space::Dma_addr phys_ram = 0;
40
41   if (err >= 0)
42     err = _dma->map(L4::Ipc::make_cap(ram, L4_CAP_FPAGE_RW),
43                     0, &phys_size,
44                     L4Re::Dma_space::Attributes::None,
45                     L4Re::Dma_space::Bidirectional, &phys_ram);
46   else
47     phys_size = 0;
48
49   if (err < 0 || phys_size < _size)
50     {
51       info.printf("RAM dataspace not contiguous, should not use DMA w/o IOMMU\n");
52       if (err >= 0 && _vm_start == ~0UL)
53         {
54           _vm_start = phys_ram;
55           _ident = true;
56         }
57     }
58   else
59     {
60       _cont = true;
61       if (_vm_start == ~0UL)
62         {
63           _vm_start = phys_ram;
64           _ident = true;
65         }
66     }
67
68   info.printf("RAM: @ %lx size=%x (%c%c)\n",
69               _vm_start, (unsigned) _size, _cont ? 'c' : '-', _ident ? 'i' : '-');
70
71   _local_start = 0;
72   L4Re::chksys(env->rm()->attach(&_local_start, _size,
73                                  L4Re::Rm::Search_addr | L4Re::Rm::Eager_map,
74                                  L4::Ipc::make_cap_rw(ram), 0,
75                                  L4_SUPERPAGESHIFT));
76   _local_end = _local_start + _size;
77   info.printf("RAM: VMM mapping @ %lx size=%x\n", _local_start, (unsigned)_size);
78   if (_vm_start != ~0UL)
79     {
80       _offset = _local_start - _vm_start;
81       info.printf("RAM: VM offset=%lx\n", _offset);
82     }
83 }
84
85
86 L4virtio::Ptr<void>
87 Ram_ds::load_file(char const *name, l4_addr_t offset, l4_size_t *_size)
88 {
89   Dbg info(Dbg::Info, "file");
90
91   info.printf("load: %s -> %lx\n", name, offset);
92   int fd = open(name, O_RDONLY);
93   if (fd < 0)
94     {
95       Err().printf("could not open file: %s:", name);
96       L4Re::chksys(-L4_EINVAL);
97     }
98
99   cxx::Ref_ptr<L4Re::Vfs::File> file = L4Re::Vfs::vfs_ops->get_file(fd);
100   if (!file)
101     {
102       Err().printf("bad file descriptor: %s\n", name);
103       errno = EBADF;
104       L4Re::chksys(-L4_EINVAL);
105     }
106
107   L4::Cap<L4Re::Dataspace> f = file->data_space();
108   if (!f)
109     {
110       Err().printf("could not get data space for %s\n", name);
111       errno = EINVAL;
112       L4Re::chksys(-L4_EINVAL);
113     }
114
115   l4_size_t size = f->size();
116   info.printf("copy in: %s -> %lx-%lx\n", name, offset, offset + size);
117
118   L4Re::chksys(_ram->copy_in(offset, f, 0, size), "copy in");
119   close(fd);
120   if (_size)
121     *_size = size;
122
123   return L4virtio::Ptr<void>(offset + vm_start());
124 }
125
126
127 } // namespace