/* * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define HERMIT_PORT 0x494E #define HEMRIT_MAGIC 0x7E317 static struct netif mmnif_netif; static const int sobufsize = 131072; /* * Note that linker symbols are not variables, they have no memory allocated for * maintaining a value, rather their address is their value. */ extern const void kernel_start; extern const void kernel_end; extern const void hbss_start; extern const void tls_start; extern const void tls_end; extern const void __bss_start; extern const void percore_start; extern const void percore_end0; extern const void percore_end; extern char __BUILD_DATE; /* Page frame counters */ extern atomic_int64_t total_pages; extern atomic_int64_t total_allocated_pages; extern atomic_int64_t total_available_pages; extern atomic_int32_t cpu_online; extern atomic_int32_t possible_cpus; extern int32_t isle; extern int32_t possible_isles; extern uint32_t boot_processor; extern int libc_sd; uint32_t idle_poll = 1; islelock_t* rcce_lock = NULL; rcce_mpb_t* rcce_mpb = NULL; #if 0 static int foo(void* arg) { int i; for(i=0; i<5; i++) { kprintf("hello from %s\n", (char*) arg); sleep(1); } return 0; } #endif static int hermit_init(void) { uint32_t i; size_t sz = (size_t) &percore_end0 - (size_t) &percore_start; // initialize .kbss sections memset((void*)&hbss_start, 0x00, ((size_t) &kernel_end - (size_t) &hbss_start)); // initialize .percore section => copy first section to all other sections for(i=1; iid); sys_sem_signal(sem); } static int init_netifs(void) { struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; err_t err; sys_sem_t sem; if(sys_sem_new(&sem, 0) != ERR_OK) LWIP_ASSERT("Failed to create semaphore", 0); tcpip_init(tcpip_init_done, &sem); sys_sem_wait(&sem); kprintf("TCP/IP initialized.\n"); sys_sem_free(&sem); /* Set network address variables */ IP4_ADDR(&gw, 192,168,28,1); IP4_ADDR(&ipaddr, 192,168,28,isle+2); IP4_ADDR(&netmask, 255,255,255,0); /* register our Memory Mapped Virtual IP interface in the lwip stack * and tell him how to use the interface: * - mmnif_dev : the device data storage * - ipaddr : the ip address wich should be used * - gw : the gateway wicht should be used * - mmnif_init : the initialization which has to be done in order to use our interface * - ip_input : tells him that he should use ip_input */ #if LWIP_TCPIP_CORE_LOCKING_INPUT if ((err = netifapi_netif_add(&mmnif_netif, &ipaddr, &netmask, &gw, NULL, mmnif_init, tcpip_input)) != ERR_OK) #else /* * Note: Our drivers guarantee that the input function will be called in the context of the tcpip thread. * => Therefore, we are able to use ip_input instead of tcpip_input */ if ((err = netifapi_netif_add(&mmnif_netif, &ipaddr, &netmask, &gw, NULL, mmnif_init, ip_input)) != ERR_OK) #endif { kprintf("Unable to add the intra network interface: err = %d\n", err); return -ENODEV; } /* tell lwip all initialization is done and we want to set it up */ netifapi_netif_set_default(&mmnif_netif); netifapi_netif_set_up(&mmnif_netif); return 0; } int network_shutdown(void) { kputs("Shutdown LwIP\n"); if (libc_sd > 0) lwip_close(libc_sd); mmnif_shutdown(); netifapi_netif_set_down(&mmnif_netif); //stats_display(); return 0; } #if MAX_CORES > 1 int smp_main(void) { int32_t cpu = atomic_int32_inc(&cpu_online); #ifdef DYNAMIC_TICKS enable_dynticks(); #endif /* wait for the other cpus */ while(atomic_int32_read(&cpu_online) < atomic_int32_read(&possible_cpus)) PAUSE; print_status(); //create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO); while(1) { check_workqueues(); if (idle_poll) PAUSE; else HALT; } return 0; } #endif static int init_rcce(void) { size_t addr; addr = vma_alloc(PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); if (BUILTIN_EXPECT(!addr, 0)) return -ENOMEM; if (page_map(addr, phy_rcce_internals, 1, PG_GLOBAL|PG_RW)) { vma_free(addr, addr + PAGE_SIZE); return -ENOMEM; } rcce_lock = (islelock_t*) addr; rcce_mpb = (rcce_mpb_t*) (addr + CACHE_LINE*(RCCE_MAXNP+1)); kprintf("Map rcce_lock at %p and rcce_mpb at %p\n", rcce_lock, rcce_mpb); return 0; } int libc_start(int argc, char** argv, char** env); // init task => creates all other tasks an initialize the LwIP static int initd(void* arg) { int s = -1, c = -1; int i, j, flag = 1; int len, err; int magic; struct sockaddr_in server, client; task_t* curr_task = per_core(current_task); size_t heap = 0x80000000; int argc, envc; char** argv = NULL; char **environ = NULL; kputs("Initd is running\n"); // setup heap if (!curr_task->heap) curr_task->heap = (vma_t*) kmalloc(sizeof(vma_t)); if (BUILTIN_EXPECT(!curr_task->heap, 0)) { kprintf("load_task: heap is missing!\n"); return -ENOMEM; } curr_task->heap->flags = VMA_HEAP|VMA_USER; curr_task->heap->start = PAGE_FLOOR(heap); curr_task->heap->end = PAGE_FLOOR(heap); //create_kernel_task(NULL, foo, "foo1", NORMAL_PRIO); //create_kernel_task(NULL, foo, "foo2", NORMAL_PRIO); // initialize network init_netifs(); // initialize iRCCE init_rcce(); s = lwip_socket(PF_INET , SOCK_STREAM , 0); if (s < 0) { kprintf("socket failed: %d\n", server); return -1; } // prepare the sockaddr_in structure memset((char *) &server, 0x00, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(HERMIT_PORT); if ((err = lwip_bind(s, (struct sockaddr *) &server, sizeof(server))) < 0) { kprintf("bind failed: %d\n", errno); lwip_close(s); return -1; } if ((err = lwip_listen(s, 2)) < 0) { kprintf("listen failed: %d\n", errno); lwip_close(s); return -1; } len = sizeof(struct sockaddr_in); kputs("TCP server listening.\n"); if ((c = lwip_accept(s, (struct sockaddr *)&client, (socklen_t*)&len)) < 0) { kprintf("accept faild: %d\n", errno); lwip_close(s); return -1; } kputs("Establish IP connection\n"); lwip_setsockopt(c, SOL_SOCKET, SO_RCVBUF, (char *) &sobufsize, sizeof(sobufsize)); lwip_setsockopt(c, SOL_SOCKET, SO_SNDBUF, (char *) &sobufsize, sizeof(sobufsize)); lwip_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(flag)); flag = 0; lwip_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(flag)); lwip_read(c, &magic, sizeof(magic)); if (magic != HEMRIT_MAGIC) { kprintf("Invalid magic number %d\n", magic); lwip_close(c); return -1; } err = lwip_read(c, &argc, sizeof(argc)); if (err != sizeof(argc)) goto out; argv = kmalloc((argc+1)*sizeof(char*)); if (!argv) goto out; memset(argv, 0x00, (argc+1)*sizeof(char*)); for(i=0; i 0) lwip_close(c); libc_sd = -1; if (s > 0) lwip_close(s); return 0; } int hermit_main(void) { hermit_init(); system_calibration(); // enables also interrupts atomic_int32_inc(&cpu_online); kprintf("This is Hermit %s, build date %u\n", VERSION, &__DATE__); kprintf("Isle %d of %d possible isles\n", isle, possible_isles); kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end); kprintf("TLS image starts at %p and ends at %p\n", &tls_start, &tls_end); kprintf("Kernel BBS starts at %p and ends at %p\n", &hbss_start, &kernel_end); kprintf("Per core data starts at %p and ends at %p\n", &percore_start, &percore_end); kprintf("Per core size 0x%zd\n", (size_t) &percore_end0 - (size_t) &percore_start); kprintf("Processor frequency: %u MHz\n", get_cpu_frequency()); kprintf("Total memory: %zd MiB\n", atomic_int64_read(&total_pages) * PAGE_SIZE / (1024ULL*1024ULL)); kprintf("Current allocated memory: %zd KiB\n", atomic_int64_read(&total_allocated_pages) * PAGE_SIZE / 1024ULL); kprintf("Current available memory: %zd MiB\n", atomic_int64_read(&total_available_pages) * PAGE_SIZE / (1024ULL*1024ULL)); #if 0 print_pci_adapters(); #endif #ifdef DYNAMIC_TICKS enable_dynticks(); #endif /* wait for the other cpus */ while(atomic_int32_read(&cpu_online) < atomic_int32_read(&possible_cpus)) PAUSE; print_status(); create_kernel_task_on_core(NULL, initd, NULL, NORMAL_PRIO, boot_processor); while(1) { check_workqueues(); if (idle_poll) PAUSE; else HALT; } return 0; }