1 /* 2 * Support for executing code in new tasks and threads. 3 * 4 * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/re/env.h> 23 #include <l4/sys/err.h> 24 #include <l4/util/util.h> 25 26 #include <exec/elf.h> 27 #include <exec/memory.h> 28 #include <exec/external_pager.h> 29 #include <exec/process.h> 30 #include <ipc/server.h> 31 32 #include <stdio.h> 33 34 #include <pthread-l4.h> 35 #include <pthread.h> 36 37 #include "pager_object_server.h" 38 39 40 41 static ExternalPager exec_pager; 42 43 44 45 int main(int argc, char *argv[]) 46 { 47 long err; 48 49 if (argc < 2) 50 { 51 printf("Need a program to run.\n"); 52 return 1; 53 } 54 55 /* Initialise the memory of the new task. */ 56 57 offset_t initial_stack_size = 16 * L4_PAGESIZE; 58 ExplicitSegment stack(Utcb_area_start - initial_stack_size, initial_stack_size, L4_FPAGE_RW); 59 Payload *payload; 60 61 if (exec_get_payload(argv[1], &payload, true)) 62 { 63 printf("Could not initialise program.\n"); 64 return 1; 65 } 66 67 if (stack.allocate(true)) 68 { 69 printf("Could not allocate stack.\n"); 70 return 1; 71 } 72 73 /* Initialise pager regions. */ 74 75 for (unsigned int i = 0; i < payload->segments(); i++) 76 { 77 if (payload->segment(i)->loadable()) 78 exec_pager.add(payload->segment(i)->region()); 79 } 80 81 exec_pager.add(stack.region()); 82 83 /* Start the pager. */ 84 85 pthread_t pager_thread; 86 pthread_attr_t attr; 87 88 pthread_attr_init(&attr); 89 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 90 91 ipc_server_config_type config; 92 ipc_server_init_for(&config, PagerObject, &exec_pager); 93 94 err = pthread_create(&pager_thread, &attr, ipc_server_start_mainloop, &config); 95 96 if (err) 97 { 98 printf("Could not start pager thread.\n"); 99 return 1; 100 } 101 102 printf("Starting pager thread...\n"); 103 err = ipc_server_start_config_thread(&config, pthread_l4_cap(pager_thread)); 104 105 if (err) 106 { 107 printf("Could not start pager.\n"); 108 return 1; 109 } 110 111 /* Configure the environment for the task, specifying the pager (and exception 112 handler plus region mapper). */ 113 114 Process process; 115 116 err = process.configure_task(); 117 118 if (err) 119 { 120 printf("Could not configure task.\n"); 121 return 1; 122 } 123 124 err = process.configure_thread(config.server); 125 126 if (err) 127 { 128 printf("Could not configure thread.\n"); 129 return 1; 130 } 131 132 /* Populate a thread stack with argument and environment details. */ 133 134 Stack st(stack); 135 136 /* NOTE: Environment vector is currently not defined. */ 137 138 char *envp[] = {NULL}; 139 140 st.populate(argc - 1, argv + 1, envp); 141 142 /* Start the new thread in the given stack. */ 143 144 printf("Run thread...\n"); 145 146 err = process.thread_start(payload->entry_point(), st); 147 148 if (err) 149 { 150 printf("Could not run thread.\n"); 151 return 1; 152 } 153 154 printf("Finished.\n"); 155 while (1); 156 157 return 0; 158 } 159 160 /* vim: tabstop=2 expandtab shiftwidth=2 161 */