70 |
MOD_NUMBER. */ |
MOD_NUMBER. */ |
71 |
unsigned int mods_count; |
unsigned int mods_count; |
72 |
|
|
73 |
/* The physical memory server master control capability for the root |
/* The physical memory and task server master control capabilities for |
74 |
filesystem. */ |
the root filesystem. */ |
75 |
hurd_cap_handle_t physmem_master; |
hurd_cap_handle_t physmem_master; |
76 |
|
hurd_cap_handle_t task_master; |
77 |
|
|
78 |
|
/* The wortel task capability object handle. */ |
79 |
|
hurd_cap_handle_t task_wortel; |
80 |
|
|
81 |
|
/* The first free thread number. */ |
82 |
|
l4_word_t first_free_thread_no; |
83 |
|
|
84 |
|
|
85 |
/* The maximum number of tasks allowed to use the rootserver. */ |
/* The maximum number of tasks allowed to use the rootserver. */ |
274 |
|
|
275 |
mods[i].task_id = task_id; |
mods[i].task_id = task_id; |
276 |
} |
} |
277 |
|
|
278 |
|
/* Initialize the first free thread number. */ |
279 |
|
first_free_thread_no = thread_no; |
280 |
} |
} |
281 |
|
|
282 |
|
|
629 |
+ i * elf->e_phentsize); |
+ i * elf->e_phentsize); |
630 |
if (ph->p_type == PT_LOAD) |
if (ph->p_type == PT_LOAD) |
631 |
{ |
{ |
632 |
|
l4_word_t page_offset = l4_page_trunc (ph->p_offset); |
633 |
|
l4_word_t byte_offset = ph->p_offset - page_offset; |
634 |
|
|
635 |
/* We add first the extra allocated memory map item |
/* We add first the extra allocated memory map item |
636 |
because the array is built up in the reversed |
because the array is built up in the reversed |
637 |
order. */ |
order. */ |
638 |
if (ph->p_memsz > ph->p_filesz) |
if (ph->p_memsz > ph->p_filesz) |
639 |
{ |
{ |
640 |
/* The file may need some extra memory allocated. */ |
/* The file may need some extra memory allocated. */ |
641 |
l4_word_t memsz = l4_page_round (ph->p_memsz); |
l4_word_t memsz = l4_page_round (byte_offset + ph->p_memsz); |
642 |
l4_word_t filesz = l4_page_round (ph->p_filesz); |
l4_word_t filesz = l4_page_round (byte_offset + ph->p_filesz); |
643 |
|
|
644 |
if (memsz > filesz) |
if (memsz > filesz) |
645 |
{ |
{ |
648 |
phys_mapv = (struct hurd_startup_map *) |
phys_mapv = (struct hurd_startup_map *) |
649 |
STARTUP_TO_PHYS (mapv); |
STARTUP_TO_PHYS (mapv); |
650 |
|
|
651 |
|
/* We need to clear out the BSS section that is on |
652 |
|
the rest of the page where the filesz ends. |
653 |
|
Normally, we would have to do this via COW, but |
654 |
|
in this case we know its safe to just clear out |
655 |
|
the actual module page. The only thing we |
656 |
|
delete this way is the ELF section headers. */ |
657 |
|
memset ((void *) (mods[MOD_TASK].start |
658 |
|
+ ph->p_offset + ph->p_filesz), 0, |
659 |
|
filesz - (byte_offset + ph->p_filesz)); |
660 |
|
|
661 |
/* FIXME When we have physical mem containers for |
/* FIXME When we have physical mem containers for |
662 |
allocation, use them. */ |
allocation, use them. */ |
663 |
phys_mapv->cont.server = mods[MOD_PHYSMEM].server_thread; |
phys_mapv->cont.server = mods[MOD_PHYSMEM].server_thread; |
664 |
phys_mapv->cont.cap_id = mods[MOD_TASK].mem_cont; |
phys_mapv->cont.cap_handle = mods[MOD_TASK].mem_cont; |
665 |
phys_mapv->size = memsz - filesz; |
phys_mapv->size = memsz - filesz; |
666 |
/* The dirty hack here causes physmem to allocate |
/* The dirty hack here causes physmem to allocate |
667 |
anonymous memory. */ |
anonymous memory. */ |
684 |
/* FIXME When we have physical mem containers for |
/* FIXME When we have physical mem containers for |
685 |
allocation, use them. */ |
allocation, use them. */ |
686 |
phys_mapv->cont.server = mods[MOD_PHYSMEM].server_thread; |
phys_mapv->cont.server = mods[MOD_PHYSMEM].server_thread; |
687 |
phys_mapv->cont.cap_id = mods[MOD_TASK].mem_cont; |
phys_mapv->cont.cap_handle = mods[MOD_TASK].mem_cont; |
688 |
phys_mapv->size = l4_page_round (ph->p_filesz);; |
phys_mapv->size = l4_page_round (ph->p_filesz);; |
689 |
phys_mapv->offset = l4_page_trunc (ph->p_offset) |
phys_mapv->offset = l4_page_trunc (ph->p_offset) |
690 |
| ((ph->p_flags & PF_X) ? L4_FPAGE_EXECUTABLE : 0) |
| ((ph->p_flags & PF_X) ? L4_FPAGE_EXECUTABLE : 0) |
702 |
/* Fill the startup structure. */ |
/* Fill the startup structure. */ |
703 |
phys_startup->version_major = HURD_STARTUP_VERSION_MAJOR; |
phys_startup->version_major = HURD_STARTUP_VERSION_MAJOR; |
704 |
phys_startup->version_minor = HURD_STARTUP_VERSION_MINOR; |
phys_startup->version_minor = HURD_STARTUP_VERSION_MINOR; |
705 |
|
/* See below. */ |
706 |
|
phys_startup->utcb_area = l4_fpage_log2 (((l4_word_t) HURD_STARTUP_ADDR) |
707 |
|
+ HURD_STARTUP_SIZE |
708 |
|
+ l4_kip_area_size (), |
709 |
|
l4_utcb_area_size_log2 ()); |
710 |
phys_startup->argz = argz_len ? STARTUP_TO_VIRT (argz) : NULL; |
phys_startup->argz = argz_len ? STARTUP_TO_VIRT (argz) : NULL; |
711 |
phys_startup->argz_len = argz_len; |
phys_startup->argz_len = argz_len; |
712 |
phys_startup->wortel.server = l4_my_global_id (); |
phys_startup->wortel.server = l4_my_global_id (); |
713 |
phys_startup->wortel.cap_id = wortel_add_user (mods[MOD_TASK].task_id); |
phys_startup->wortel.cap_handle = wortel_add_user (mods[MOD_TASK].task_id); |
714 |
phys_startup->image.server = mods[MOD_PHYSMEM].server_thread; |
phys_startup->image.server = mods[MOD_PHYSMEM].server_thread; |
715 |
phys_startup->image.cap_id = mods[MOD_TASK].mem_cont; |
phys_startup->image.cap_handle = mods[MOD_TASK].mem_cont; |
716 |
phys_startup->mapc = mapc; |
phys_startup->mapc = mapc; |
717 |
phys_startup->mapv = (struct hurd_startup_map *) STARTUP_TO_VIRT (mapv); |
phys_startup->mapv = (struct hurd_startup_map *) STARTUP_TO_VIRT (mapv); |
718 |
/* The program header is already a virtual address for the task. */ |
/* The program header is already a virtual address for the task. */ |
720 |
phys_startup->phdr_len = mods[MOD_TASK].header_size; |
phys_startup->phdr_len = mods[MOD_TASK].header_size; |
721 |
phys_startup->entry_point = (void *) task_entry_point; |
phys_startup->entry_point = (void *) task_entry_point; |
722 |
phys_startup->startup.server = mods[MOD_PHYSMEM].server_thread; |
phys_startup->startup.server = mods[MOD_PHYSMEM].server_thread; |
723 |
phys_startup->startup.cap_id = mods[MOD_TASK].startup_cont; |
phys_startup->startup.cap_handle = mods[MOD_TASK].startup_cont; |
724 |
|
|
725 |
/* The stack layout is in accordance to the following startup prototype: |
/* The stack layout is in accordance to the following startup prototype: |
726 |
void start (struct hurd_startup_data *startup_data). */ |
void start (struct hurd_startup_data *startup_data). */ |
759 |
below code makes assumptions about page alignedness that are |
below code makes assumptions about page alignedness that are |
760 |
architecture specific. And it does not assert that we do not |
architecture specific. And it does not assert that we do not |
761 |
accidently exceed the wortel end address. */ |
accidently exceed the wortel end address. */ |
|
/* FIXME: In any case, we have to pass the UTCB area size (and |
|
|
location) to task. */ |
|
762 |
ret = l4_space_control (task, 0, |
ret = l4_space_control (task, 0, |
763 |
l4_fpage_log2 (((l4_word_t) HURD_STARTUP_ADDR) |
l4_fpage_log2 (((l4_word_t) HURD_STARTUP_ADDR) |
764 |
+ HURD_STARTUP_SIZE, |
+ HURD_STARTUP_SIZE, |
765 |
l4_kip_area_size_log2 ()), |
l4_kip_area_size_log2 ()), |
766 |
l4_fpage_log2 (((l4_word_t) HURD_STARTUP_ADDR) |
phys_startup->utcb_area, |
|
+ HURD_STARTUP_SIZE |
|
|
+ l4_kip_area_size (), |
|
|
l4_utcb_area_size_log2 ()), |
|
767 |
l4_anythread, &control); |
l4_anythread, &control); |
768 |
if (!ret) |
if (!ret) |
769 |
panic ("could not create task address space: %s", |
panic ("could not create task address space: %s", |
853 |
/* This is the physmem thread that sent us the GET_TASK_CAP RPC. */ |
/* This is the physmem thread that sent us the GET_TASK_CAP RPC. */ |
854 |
l4_thread_id_t physmem; |
l4_thread_id_t physmem; |
855 |
|
|
856 |
|
/* This is to keep information about created task caps. */ |
857 |
|
unsigned int cur_task = (unsigned int) -1; |
858 |
|
|
859 |
/* Make a list of all the containers we want. */ |
/* Make a list of all the containers we want. */ |
860 |
for (i = 0; i < mods_count; i++) |
for (i = 0; i < mods_count; i++) |
861 |
{ |
{ |
882 |
container[nr_cont].cont = &mods[i].mem_cont; |
container[nr_cont].cont = &mods[i].mem_cont; |
883 |
|
|
884 |
{ |
{ |
885 |
/* We zero out the unused bytes on the last page, because they |
/* We zero out the unused bytes on the last page, for security |
886 |
may be part of a .bss section. This could be somewhere |
reasons, and because they may be part of a .bss section. |
887 |
else, of course, but this place is just as good as any |
This should probably be in physmem, but this place is just |
888 |
other. */ |
as good as any other. */ |
889 |
l4_word_t start = container[nr_cont].end; |
l4_word_t start = container[nr_cont].end; |
890 |
l4_word_t end = start | (l4_min_page_size () - 1); |
l4_word_t end = start | (l4_min_page_size () - 1); |
891 |
|
|
896 |
|
|
897 |
} |
} |
898 |
|
|
|
|
|
899 |
/* If a conventinal page with address 0 exists in the memory |
/* If a conventinal page with address 0 exists in the memory |
900 |
descriptors, allocate it because we don't want to bother anybody |
descriptors, allocate it because we don't want to bother anybody |
901 |
with that silly page. FIXME: We should eventually remap it to a |
with that silly page. FIXME: We should eventually remap it to a |
922 |
if (l4_ipc_failed (tag)) |
if (l4_ipc_failed (tag)) |
923 |
panic ("Receiving message failed: %u", (l4_error_code () >> 1) & 0x7); |
panic ("Receiving message failed: %u", (l4_error_code () >> 1) & 0x7); |
924 |
|
|
925 |
|
l4_msg_store (tag, msg); |
926 |
|
|
927 |
/* FIXME: Remove when not debugging. */ |
/* FIXME: Remove when not debugging. */ |
928 |
if ((l4_label (tag) >> 4) == 0xffe) |
if ((l4_label (tag) >> 4) == 0xffe) |
929 |
{ |
{ |
930 |
if (l4_untyped_words (tag) != 2 || l4_typed_words (tag) != 0) |
if (l4_untyped_words (tag) != 2 || l4_typed_words (tag) != 0) |
931 |
panic ("Invalid format of page fault message"); |
panic ("Invalid format of page fault message"); |
932 |
|
|
933 |
panic ("Unexpected page fault from 0x%x at address 0x%x (IP 0x%x)", |
panic ("Unexpected page fault from 0x%x at address 0x%x (IP 0x%x)", |
934 |
from, l4_msg_word (msg, 0), l4_msg_word (msg, 1)); |
from, l4_msg_word (msg, 0), l4_msg_word (msg, 1)); |
935 |
} |
} |
944 |
from, cap_id); |
from, cap_id); |
945 |
#endif |
#endif |
946 |
|
|
|
l4_msg_store (tag, msg); |
|
|
|
|
947 |
if (label == WORTEL_MSG_PUTCHAR) |
if (label == WORTEL_MSG_PUTCHAR) |
948 |
{ |
{ |
949 |
int chr; |
int chr; |
1003 |
else if (label == WORTEL_MSG_GET_CAP_REQUEST) |
else if (label == WORTEL_MSG_GET_CAP_REQUEST) |
1004 |
{ |
{ |
1005 |
if (cur_cont > nr_cont) |
if (cur_cont > nr_cont) |
1006 |
panic ("physmem does not stop requesting capabilities"); |
panic ("physmem does not stop requesting capability requests"); |
1007 |
else if (cur_cont == nr_cont) |
else if (cur_cont == nr_cont) |
1008 |
{ |
{ |
1009 |
/* Request the global control capability now. */ |
/* Request the global control capability now. */ |
1025 |
|
|
1026 |
/* We can not pass more than 31 map items in our |
/* We can not pass more than 31 map items in our |
1027 |
message, because there are only 64 message registers, |
message, because there are only 64 message registers, |
1028 |
we need 1 for the task ID, and each map item takes up |
we need 2 for the tag and the task ID, and each map |
1029 |
two message registers. */ |
item takes up two message registers. */ |
1030 |
if (nr_fpages > 31) |
if (nr_fpages > (L4_NUM_MRS - 2) / 2) |
1031 |
panic ("%s: Module %s is too large and has an " |
panic ("%s: Module %s is too large and has an " |
1032 |
"unfortunate alignment", __func__, |
"unfortunate alignment", __func__, |
1033 |
mods[container[cur_cont].module].name); |
mods[container[cur_cont].module].name); |
1082 |
/* Start up the task server and continue serving RPCs. */ |
/* Start up the task server and continue serving RPCs. */ |
1083 |
start_task (); |
start_task (); |
1084 |
} |
} |
1085 |
|
else if (label == WORTEL_MSG_GET_FIRST_FREE_THREAD_NO) |
1086 |
|
{ |
1087 |
|
/* This RPC is used by wortel to determine the first free |
1088 |
|
thread ID for thread allocation. */ |
1089 |
|
l4_msg_clear (msg); |
1090 |
|
l4_msg_append_word (msg, first_free_thread_no); |
1091 |
|
l4_msg_load (msg); |
1092 |
|
l4_reply (from); |
1093 |
|
} |
1094 |
|
else if (label == WORTEL_MSG_THREAD_CONTROL) |
1095 |
|
{ |
1096 |
|
if (l4_untyped_words (tag) != 5 || l4_typed_words (tag) != 0) |
1097 |
|
panic ("Invalid format of thread control msg"); |
1098 |
|
|
1099 |
|
l4_thread_id_t dest = l4_msg_word (msg, 0); |
1100 |
|
l4_thread_id_t space = l4_msg_word (msg, 1); |
1101 |
|
l4_thread_id_t scheduler = l4_msg_word (msg, 2); |
1102 |
|
l4_thread_id_t pager = l4_msg_word (msg, 3); |
1103 |
|
void *utcb = (void *) l4_msg_word (msg, 4); |
1104 |
|
l4_word_t ret; |
1105 |
|
|
1106 |
|
ret = l4_thread_control (dest, space, scheduler, pager, utcb); |
1107 |
|
|
1108 |
|
l4_msg_clear (msg); |
1109 |
|
l4_msg_append_word (msg, ret ? 0 : l4_error_code ()); |
1110 |
|
l4_msg_load (msg); |
1111 |
|
l4_reply (from); |
1112 |
|
} |
1113 |
|
else if (label == WORTEL_MSG_GET_TASK_CAP_REQUEST) |
1114 |
|
{ |
1115 |
|
if (cur_task == (unsigned int) -1) |
1116 |
|
{ |
1117 |
|
hurd_task_id_t wortel_task_id = l4_version (l4_my_global_id ()); |
1118 |
|
l4_word_t thread_no = l4_thread_no (l4_my_global_id ()); |
1119 |
|
|
1120 |
|
/* Give out the wortel task information. */ |
1121 |
|
l4_msg_clear (msg); |
1122 |
|
l4_set_msg_label (msg, 0); |
1123 |
|
l4_msg_append_word (msg, wortel_task_id); |
1124 |
|
l4_msg_append_word (msg, l4_my_global_id ()); |
1125 |
|
for (i = 1; i < WORTEL_THREADS; i++) |
1126 |
|
l4_msg_append_word |
1127 |
|
(msg, l4_global_id (thread_no + i, wortel_task_id)); |
1128 |
|
l4_msg_load (msg); |
1129 |
|
l4_reply (from); |
1130 |
|
} |
1131 |
|
else if (cur_task > mods_count) |
1132 |
|
panic ("task does not stop requesting capability requests"); |
1133 |
|
else if (cur_task == mods_count) |
1134 |
|
{ |
1135 |
|
/* Request the global control capability now. */ |
1136 |
|
l4_msg_clear (msg); |
1137 |
|
l4_msg_append_word |
1138 |
|
(msg, l4_version (mods[MOD_ROOT_FS].server_thread)); |
1139 |
|
l4_msg_load (msg); |
1140 |
|
l4_reply (from); |
1141 |
|
} |
1142 |
|
else |
1143 |
|
{ |
1144 |
|
/* We are allowed to make a capability request now. */ |
1145 |
|
|
1146 |
|
l4_word_t thread_no |
1147 |
|
= l4_thread_no (mods[cur_task].server_thread); |
1148 |
|
|
1149 |
|
/* We have one MR for the tag, one for the task ID, and |
1150 |
|
one for the main thread. */ |
1151 |
|
if (mods[cur_task].nr_extra_threads > L4_NUM_MRS - 3) |
1152 |
|
panic ("%s: Module %s has too many threads", __func__, |
1153 |
|
mods[container[cur_cont].module].name); |
1154 |
|
|
1155 |
|
l4_msg_clear (msg); |
1156 |
|
l4_set_msg_label (msg, 0); |
1157 |
|
l4_msg_append_word (msg, mods[cur_task].task_id); |
1158 |
|
l4_msg_append_word (msg, mods[cur_task].server_thread); |
1159 |
|
for (i = 1; i <= mods[cur_task].nr_extra_threads; i++) |
1160 |
|
l4_msg_append_word |
1161 |
|
(msg, l4_global_id (thread_no + i, |
1162 |
|
mods[cur_task].task_id)); |
1163 |
|
l4_msg_load (msg); |
1164 |
|
l4_reply (from); |
1165 |
|
} |
1166 |
|
} |
1167 |
|
else if (label == WORTEL_MSG_GET_TASK_CAP_REPLY) |
1168 |
|
{ |
1169 |
|
if (l4_untyped_words (tag) != 1 || l4_typed_words (tag) != 0) |
1170 |
|
panic ("Invalid format of get task cap reply msg"); |
1171 |
|
|
1172 |
|
if (cur_task == (unsigned int) -1) |
1173 |
|
task_wortel = l4_msg_word (msg, 0); |
1174 |
|
else if (cur_task > mods_count) |
1175 |
|
panic ("Invalid get task cap reply message"); |
1176 |
|
else if (cur_task == mods_count) |
1177 |
|
task_master = l4_msg_word (msg, 0); |
1178 |
|
else |
1179 |
|
mods[cur_task].task_ctrl = l4_msg_word (msg, 0); |
1180 |
|
|
1181 |
|
do |
1182 |
|
cur_task++; |
1183 |
|
while (cur_task < mods_count && !MOD_IS_TASK (cur_task)); |
1184 |
|
|
1185 |
|
l4_msg_clear (msg); |
1186 |
|
l4_msg_load (msg); |
1187 |
|
l4_reply (from); |
1188 |
|
} |
1189 |
else |
else |
1190 |
panic ("Invalid message with tag 0x%x", tag); |
panic ("Invalid message with tag 0x%x", tag); |
1191 |
} |
} |