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)
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.
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>
29 * This is a simple example to demonstrate how to
30 * startup a Linux in Vm.
32 * This example has some prerequisites:
34 * 1. The Linux image name: 'rom/vm-linux-image'
36 * 2. The Linux image link/start address: 0x9000000
38 * 3. The Linux RAM disk name: 'rom/linux-initrd'
40 * 4. The VM physical memory: 0x8000000 - 0xc000000
43 static void error(const char *str)
49 static void dump_vm_state(l4_vm_state *state)
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]);
61 printf("lr_svc:%08lx sp_svc:%08lx spsr_svc:%08lx\n",
62 state->lr_svc, state->sp_svc, state->spsr_svc);
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
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
80 #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
112 static struct init_tags
114 struct tag_header hdr1;
115 struct tag_core core;
116 struct tag_header hdr2;
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;
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 },
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;
146 printf("Vmm started\n");
148 if (l4_ipc_error(l4_factory_create_vm(l4re_env()->factory, vm_cap), l4_utcb()))
149 error("Cannot create vm\n");
151 if (!(sigma0_cap = L4Re::Env::env()->get_cap<void>("sigma0")))
152 error("Cannot query sigma0 cap\n");
154 if (l4sigma0_map_iomem(sigma0_cap.cap(), Ram_base, Ram_base, Ram_size, 1))
155 error("Cannot map nonsecure memory\n");
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");
161 vm_image_size = vm_ds_cap->size();
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");
167 if (!(initrd_cap = ns.query<L4Re::Dataspace>("rom/linux-initrd")))
168 error("Cannot query initrd image\n");
170 initrd_size = initrd_cap->size();
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");
176 // fixup Initrd size in ATAG structure
177 init_tags.initrd.size = initrd_size;
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));
183 // Initialize Vm state according to Linux's requirements
185 posix_memalign((void**)&state, L4_PAGESIZE, sizeof(l4_vm_state));
186 state->pc = Start_addr;
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
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());
199 printf("VM run failed with %d\n", ret);
205 // do nothing but dump the state and sleep a second
206 dump_vm_state((l4_vm_state *)l4_utcb_mr_u(l4_utcb()));