1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
/* This file contains code for initialization of protected mode, to initialize
* code and data segment descriptors, and to initialize global descriptors
* for local descriptors in the process table.
*/
#include <assert.h>
#include <string.h>
#include <machine/multiboot.h>
#include "kernel/kernel.h"
#include "archconst.h"
#include "arch_proto.h"
#include <sys/exec.h>
#include <libexec.h>
struct tss_s tss[CONFIG_MAX_CPUS];
extern int exc_vector_table;
int prot_init_done = 0;
phys_bytes vir2phys(void *vir)
{
/* defined in kernel.lds */
extern char _kern_vir_base, _kern_phys_base;
u32_t offset = (vir_bytes) &_kern_vir_base -
(vir_bytes) &_kern_phys_base;
return (phys_bytes)vir - offset;
}
int tss_init(unsigned cpu, void * kernel_stack)
{
struct tss_s * t = &tss[cpu];
/*
* make space for process pointer and cpu id and point to the first
* usable word
*/
t->sp0 = ((unsigned) kernel_stack) - ARM_STACK_TOP_RESERVED;
/*
* set the cpu id at the top of the stack so we know on which cpu is
* this stack in use when we trap to kernel
*/
*((reg_t *)(t->sp0 + 1 * sizeof(reg_t))) = cpu;
return 0;
}
multiboot_module_t *bootmod(int pnr)
{
int i;
assert(pnr >= 0);
/* Search for desired process in boot process
* list. The first NR_TASKS ones do not correspond
* to a module, however, so we don't search those.
*/
for(i = NR_TASKS; i < NR_BOOT_PROCS; i++) {
int p;
p = i - NR_TASKS;
if(image[i].proc_nr == pnr) {
assert(p < MULTIBOOT_MAX_MODS);
assert(p < kinfo.mbi.mi_mods_count);
return &kinfo.module_list[p];
}
}
panic("boot module %d not found", pnr);
}
int booting_cpu = 0;
void prot_init(void)
{
/* tell the HW where we stored our vector table */
write_vbar((reg_t)&exc_vector_table);
/* Set up a new post-relocate bootstrap pagetable so that
* we can map in VM, and we no longer rely on pre-relocated
* data.
*/
pg_clear();
pg_identity(&kinfo); /* Still need 1:1 for device memory . */
pg_mapkernel();
pg_load();
prot_init_done = 1;
}
static int alloc_for_vm = 0;
void arch_post_init(void)
{
/* Let memory mapping code know what's going on at bootstrap time */
struct proc *vm;
vm = proc_addr(VM_PROC_NR);
get_cpulocal_var(ptproc) = vm;
pg_info(&vm->p_seg.p_ttbr, &vm->p_seg.p_ttbr_v);
}
static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo);
pg_load();
memset((char *) vaddr, 0, len);
alloc_for_vm += len;
return OK;
}
void arch_boot_proc(struct boot_image *ip, struct proc *rp)
{
multiboot_module_t *mod;
struct ps_strings *psp;
char *sp;
if(rp->p_nr < 0) return;
mod = bootmod(rp->p_nr);
/* Important special case: we put VM in the bootstrap pagetable
* so it can run.
*/
if(rp->p_nr == VM_PROC_NR) {
struct exec_info execi;
memset(&execi, 0, sizeof(execi));
/* exec parameters */
execi.stack_high = kinfo.user_sp;
execi.stack_size = 64 * 1024; /* not too crazy as it must be preallocated */
execi.proc_e = ip->endpoint;
execi.hdr = (char *) mod->mod_start; /* phys mem direct */
execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
execi.frame_len = 0;
/* callbacks for use in the kernel */
execi.copymem = libexec_copy_memcpy;
execi.clearmem = libexec_clear_memset;
execi.allocmem_prealloc_junk = libexec_pg_alloc;
execi.allocmem_prealloc_cleared = libexec_pg_alloc;
execi.allocmem_ondemand = libexec_pg_alloc;
execi.clearproc = NULL;
/* parse VM ELF binary and alloc/map it into bootstrap pagetable */
if(libexec_load_elf(&execi) != OK)
panic("VM loading failed");
/* Setup a ps_strings struct on the stack, pointing to the
* following argv, envp. */
sp = (char *)execi.stack_high;
sp -= sizeof(struct ps_strings);
psp = (struct ps_strings *) sp;
/* Take the stack pointer down three words to give startup code
* something to use as "argc", "argv" and "envp".
*/
sp -= (sizeof(void *) + sizeof(void *) + sizeof(int));
// linear address space, so it is available.
psp->ps_argvstr = (char **)(sp + sizeof(int));
psp->ps_nargvstr = 0;
psp->ps_envstr = psp->ps_argvstr + sizeof(void *);
psp->ps_nenvstr = 0;
arch_proc_init(rp, execi.pc, (vir_bytes)sp,
execi.stack_high - sizeof(struct ps_strings),
ip->proc_name);
/* Free VM blob that was just copied into existence. */
add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start);
mod->mod_end = mod->mod_start = 0;
/* Remember them */
kinfo.vm_allocated_bytes = alloc_for_vm;
}
}
|