]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/examples/sys/vm-tz/main.cc
ec7200fc03eca3c253b985027b7dc5f62329c539
[l4.git] / l4 / pkg / examples / sys / vm-tz / main.cc
1 /*
2  * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>,
4  *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
5  *     economic rights: Technische Universität Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  */
11 #include <l4/re/env>
12 #include <l4/re/util/env_ns>
13 #include <l4/re/c/namespace.h>
14 #include <l4/re/dataspace>
15 #include <l4/re/c/rm.h>
16 #include <l4/re/c/util/cap_alloc.h>
17 #include <l4/sys/factory.h>
18 #include <l4/sys/ipc.h>
19 #include <l4/sys/types.h>
20 #include <l4/sys/vm.h>
21 #include <l4/sigma0/sigma0.h>
22 #include <l4/util/util.h>
23
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27
28 /*
29  * This is a simple example to demonstrate how to
30  * startup a Linux in Vm.
31  *
32  * This example has some prerequisites:
33  *
34  * 1. The Linux image name: 'rom/vm-linux-image'
35  *
36  * 2. The Linux image link/start address: 0x9000000
37  *
38  * 3. The Linux RAM disk name: 'rom/linux-initrd'
39  *
40  * 4. The VM physical memory: 0x8000000 - 0xc000000
41  */
42
43 static void error(const char *str)
44 {
45   printf("%s", str);
46   exit(-1);
47 }
48
49 static void dump_vm_state(l4_vm_state *state)
50 {
51   printf("pc:%08lx cpsr:%08lx\n",
52       state->pc, state->cpsr);
53   printf("r0:%08lx r1:%08lx r2:%08lx r3:%08lx\n",
54       state->r[0], state->r[1], state->r[2], state->r[3]);
55   printf("r4:%08lx r5:%08lx r6:%08lx r7:%08lx\n",
56       state->r[4], state->r[5], state->r[6], state->r[7]);
57   printf("r8:%08lx r9:%08lx r10:%08lx r11:%08lx\n",
58       state->r[8], state->r[9], state->r[10], state->r[11]);
59   printf("r12:%08lx\n",
60       state->r[12]);
61   printf("lr_svc:%08lx sp_svc:%08lx spsr_svc:%08lx\n",
62       state->lr_svc, state->sp_svc, state->spsr_svc);
63 }
64
65
66 enum {
67     Ram_base = 0x8000000, // 128 MB
68     Ram_size = 0x4000000, // 128 MB
69     Start_addr = Ram_base + 0x1000000, // +1MB
70     Atag_addr = 0x8000000,
71     Initrd_addr = Ram_base + 0x2000000, // +2MB
72 };
73
74 #define ATAG_NONE       0x00000000
75 #define ATAG_CORE       0x54410001
76 #define ATAG_MEM        0x54410002
77 #define ATAG_INITRD2    0x54420005
78 #define ATAG_CMDLINE    0x54410009
79
80 #define tag_size(type)  ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
81
82 struct tag_header
83 {
84   l4_uint32_t size;
85   l4_uint32_t tag;
86 };
87
88 struct tag_core
89 {
90   l4_uint32_t flags;
91   l4_uint32_t pagesize;
92   l4_uint32_t rootdev;
93 };
94
95 struct tag_mem
96 {
97   l4_uint32_t   size;
98   l4_uint32_t   start;
99 };
100
101 struct tag_cmdline
102 {
103   char    cmdline[128];
104 };
105
106 struct tag_initrd
107 {
108   l4_uint32_t start;
109   l4_uint32_t size;
110 };
111
112 static struct init_tags
113 {
114   struct tag_header hdr1;
115   struct tag_core   core;
116   struct tag_header hdr2;
117   struct tag_mem    mem;
118   struct tag_header hdr3;
119   struct tag_cmdline cmdline;
120   struct tag_header hdr4;
121   struct tag_initrd initrd;
122   struct tag_header hdr5;
123 } init_tags = {
124         { tag_size(tag_core), ATAG_CORE },
125         { 1, L4_PAGESIZE, 0xff },
126         { tag_size(tag_mem), ATAG_MEM },
127         { Ram_size, Ram_base },
128         { tag_size(tag_cmdline), ATAG_CMDLINE },
129         { "root=/dev/ram0 earlyprintk=serial console=ttyAMA0 init=/bin/sh" },
130         { tag_size(tag_initrd), ATAG_INITRD2 },
131         { Initrd_addr, 0 },
132         { 0, ATAG_NONE }
133 };
134
135 int main()
136 {
137   L4::Cap<void> sigma0_cap;
138   l4_cap_idx_t vm_cap = l4re_util_cap_alloc();
139   L4::Cap<L4Re::Dataspace> vm_ds_cap;
140   L4::Cap<L4Re::Dataspace> initrd_cap;
141   l4_addr_t vm_image_addr = 0;
142   l4_size_t vm_image_size = 0;
143   l4_addr_t initrd_addr = 0;
144   l4_size_t initrd_size = 0;
145
146   printf("Vmm started\n");
147
148   if (l4_ipc_error(l4_factory_create_vm(l4re_env()->factory, vm_cap), l4_utcb()))
149     error("Cannot create vm\n");
150
151   if (!(sigma0_cap = L4Re::Env::env()->get_cap<void>("sigma0")))
152     error("Cannot query sigma0 cap\n");
153
154   if (l4sigma0_map_iomem(sigma0_cap.cap(), Ram_base, Ram_base, Ram_size, 1))
155     error("Cannot map nonsecure memory\n");
156
157   L4Re::Util::Env_ns ns;
158   if (!(vm_ds_cap = ns.query<L4Re::Dataspace>("rom/vm-linux-image-tz")))
159     error("Cannot query vm image\n");
160
161   vm_image_size = vm_ds_cap->size();
162
163   if (l4re_rm_attach((void**)&vm_image_addr, l4_round_page(vm_image_size),
164                 L4RE_RM_SEARCH_ADDR | L4RE_RM_READ_ONLY, vm_ds_cap.cap(), 0, 0))
165     error("Cannot attach vm image\n");
166
167   if (!(initrd_cap = ns.query<L4Re::Dataspace>("rom/linux-initrd")))
168       error("Cannot query initrd image\n");
169
170   initrd_size = initrd_cap->size();
171   
172   if (l4re_rm_attach((void**)&initrd_addr, l4_round_page(initrd_size),
173                 L4RE_RM_SEARCH_ADDR | L4RE_RM_READ_ONLY, initrd_cap.cap(), 0, 0))
174     error("Cannot attach initrd image\n");
175
176   // fixup Initrd size in ATAG structure
177   init_tags.initrd.size = initrd_size;
178
179   memcpy((void*)Start_addr, (void*)vm_image_addr, vm_image_size);
180   memcpy((void*)Initrd_addr, (void*)initrd_addr, initrd_size);
181   memcpy((void*)Atag_addr, (void*)&init_tags, sizeof(init_tags));
182
183   // Initialize Vm state according to Linux's requirements
184   l4_vm_state *state;
185   posix_memalign((void**)&state, L4_PAGESIZE, sizeof(l4_vm_state));
186   state->pc = Start_addr;
187   state->cpsr = 0x13;
188   state->r[0] = 0;              // R0=0 according to the spec
189   state->r[1] = 827;            // R1=1 Realview machine architecture
190   state->r[2] = Atag_addr;      // R2=2 ATAG pointer
191   
192   while (1)
193     {
194       printf("VM run\n");
195       l4_umword_t label = 0;
196       int ret = l4_error_u(l4_vm_run(vm_cap, l4_fpage((unsigned long)state, 12, 0), &label), l4_utcb());
197       if (ret < 0)
198         {
199           printf("VM run failed with %d\n", ret);
200           return -1;
201         }
202       else
203         printf("VM exit\n");
204
205       // do nothing but dump the state and sleep a second
206       dump_vm_state((l4_vm_state *)l4_utcb_mr_u(l4_utcb()));
207       l4_sleep(1000);
208     }
209
210   return 0;
211 }