From e6fb99beb42af4b7536774276b6a8380ca50ee6b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 1 Sep 2011 13:31:41 -0700 Subject: [PATCH 01/24] add inline assembler functions to determine the MSB and LSB --- arch/x86/include/asm/processor.h | 30 +++++++++++++++++++++++++----- kernel/tasks.c | 15 +++++---------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ad962757..ad9e9f36 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -272,22 +272,42 @@ static inline uint32_t read_eflags(void) return result; } -/** @brief search the first bit, which is set +/** @brief search the first most significant bit * * @param i source operand - * @return first bit, which is set in the source operand + * @return + * - first bit, which is set in the source operand + * - invalid value, if not bit ist set */ -static inline uint32_t last_set(uint32_t i) +static inline size_t msb(size_t i) { - uint32_t ret; + size_t ret; if (!i) - return 0; + return (sizeof(size_t)*8); asm volatile ("bsr %1, %0" : "=r"(ret) : "r"(i) : "cc"); return ret; } +/** @brief search the least significant bit + * + * @param i source operand + * @return + * - first bit, which is set in the source operand + * - invalid value, if not bit ist set + */ +static inline size_t lsb(size_t i) +{ + size_t ret; + + if (!i) + return (sizeof(size_t)*8); + asm volatile ("bsf %1, %0" : "=r"(ret) : "r"(i) : "cc"); + + return ret; +} + /** @brief Read extended instruction pointer * @return The EIP's value */ diff --git a/kernel/tasks.c b/kernel/tasks.c index bc037aad..0689d401 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -69,7 +69,7 @@ task_t* get_current_task(void) { } uint32_t get_highest_priority(uint32_t core_id) { - return last_set(runqueues[core_id].prio_bitmap); + return msb(runqueues[core_id].prio_bitmap); } int multitasking_init(void) { @@ -1228,20 +1228,15 @@ void scheduler(void) } runqueues[core_id].old_task = NULL; // reset old task - prio = last_set(runqueues[core_id].prio_bitmap); // determines highest priority + prio = msb(runqueues[core_id].prio_bitmap); // determines highest priority #if MAX_CORES > 1 - if (!prio) { + if (prio >= sizeof(size_t)*8) { load_balancing(); - prio = last_set(runqueues[core_id].prio_bitmap); // retry... + prio = msb(runqueues[core_id].prio_bitmap); // retry... } #endif - if (BUILTIN_EXPECT(prio > MAX_PRIO, 0)) { - kprintf("Invalid priority %u by bitmap 0x%x\n", prio, runqueues[core_id].prio_bitmap); - prio = 0; - } - - if (!prio) { + if (prio >= sizeof(size_t)*8) { if ((curr_task->status == TASK_RUNNING) || (curr_task->status == TASK_IDLE)) goto get_task_out; curr_task = per_core(current_task) = runqueues[core_id].idle; From 591e1624609fe04605edc6e38a9b028a967e877b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 12:44:47 -0700 Subject: [PATCH 02/24] switch back to the "original" test cases --- kernel/tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/tests.c b/kernel/tests.c index 58df28fa..8d3b1631 100644 --- a/kernel/tests.c +++ b/kernel/tests.c @@ -432,8 +432,8 @@ int test_init(void) //create_kernel_task(NULL, mail_ping, NULL, NORMAL_PRIO); //create_kernel_task(NULL, mail_noise, NULL, NORMAL_PRIO); //create_kernel_task(NULL, svm_test, NULL, NORMAL_PRIO); - create_user_task(NULL, "/bin/hello", argv); - //create_user_task(NULL, "/bin/tests", argv); + //create_user_task(NULL, "/bin/hello", argv); + create_user_task(NULL, "/bin/tests", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/jacobi", argv); //create_user_task(NULL, "/bin/server", server_argv); From b67e9bb88f2a2b50193c8a979e1b3be3175556f4 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 13:24:53 -0700 Subject: [PATCH 03/24] move initrd to 0x01000000 ATTENTION: By the creation of scc_bootinfo.asm, you have to use this new default value (see Makfile) --- tools/Makefile | 2 +- tools/load.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index baf8febe..b47cc898 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -36,7 +36,7 @@ reset_vector.bin: reset_vector.o ld --oformat binary -Ttext 0 -melf_i386 -o $@ $< scc_bootinfo.asm: bootinfo.sh - ./bootinfo.sh 0x00400000 initrd.img 1 533 0 > scc_bootinfo.asm + ./bootinfo.sh 0x01000000 initrd.img 1 533 0 > scc_bootinfo.asm scc_bootinfo.bin: scc_bootinfo.asm $(NASM) $(NASMFLAGS) -o $@ $< diff --git a/tools/load.map b/tools/load.map index 6263ab88..ef05bd83 100644 --- a/tools/load.map +++ b/tools/load.map @@ -1,5 +1,5 @@ 0x00080000 scc_bootinfo.bin 0x00090200 scc_setup.bin 0x00100000 metalsvm.bin -0x00400000 initrd.img +0x01000000 initrd.img 0xfffff000 reset_vector.bin From f198c2685182bce0d3d4023a4645bbcb9b549983 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 13:35:22 -0700 Subject: [PATCH 04/24] add nicer output messages --- arch/x86/mm/page.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index cecbab61..cc767a43 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -801,8 +801,9 @@ int arch_paging_init(void) npages = bootinfo->size >> PAGE_SHIFT; if (bootinfo->size & (PAGE_SIZE-1)) npages++; - bootinfo->addr = map_region(0, bootinfo->addr, npages, MAP_KERNEL_SPACE); - kprintf("Map initrd at 0x%x (size %u bytes)\n", bootinfo->addr, bootinfo->size); + viraddr = map_region(0, bootinfo->addr, npages, MAP_KERNEL_SPACE); + kprintf("Map initrd from 0x%x to 0x%x (size %u bytes)\n", bootinfo->addr, viraddr, bootinfo->size); + bootinfo->addr = viraddr; #endif /* From 751dda8f1e2778155c572b7618bad46d4bf15d79 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 13:51:29 -0700 Subject: [PATCH 05/24] add helper function to determine, if the interrupt flag is set --- arch/x86/include/asm/irqflags.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index 81e3dd4c..093fb61f 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -75,6 +75,21 @@ inline static void irq_nested_enable(uint32_t flags) { irq_enable(); } +/** @brief Determines, if the interrupt flags (IF) is ser + * + * @return + * - 1 interrupt flag is set + * - 0 interrupt flag is cleared + */ +inline static uint32_t is_irq_enabled(void) +{ + uint32_t flags; + asm volatile("pushf; popl %0": "=r"(flags) : : "memory"); + if (flags & (1 << 9)) + return 1; + return 0; +} + #ifdef __cplusplus } #endif From 41dc03235a91f24ed17a2670dcb2be60c8dd20ff Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 13:52:42 -0700 Subject: [PATCH 06/24] use get_cpu_frequency instead of the static number 533 --- arch/x86/scc/icc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/scc/icc.c b/arch/x86/scc/icc.c index 2bd5141f..065c086f 100644 --- a/arch/x86/scc/icc.c +++ b/arch/x86/scc/icc.c @@ -257,7 +257,7 @@ int icc_halt(void) return 0; } -#define ROUNDS 100000 +#define ROUNDS 1000 #define CORE_A 0 // sender #define CORE_B 1 // receiver @@ -425,7 +425,7 @@ int icc_mail_ping_irq(void) kprintf( "timer = %d\n", timer ); kprintf( "mail_pingpong needs in average %d nsec (%d ticks)!\n", - timer*1000/(2*ROUNDS*533), timer/(2*ROUNDS) ); + timer*1000/(2*ROUNDS*get_cpu_frequency()), timer/(2*ROUNDS) ); irq_nested_enable(flags); From 27e652f81d9c6dfde32ee64cd6e84143a013aa0f Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 13:57:11 -0700 Subject: [PATCH 07/24] if a task exists with a higher priority, we start a rescheduling in check_workqueues. --- arch/x86/mm/svm.c | 2 +- include/metalsvm/tasks.h | 8 +++----- kernel/main.c | 7 ++----- kernel/syscall.c | 2 +- kernel/tasks.c | 7 +++++-- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/arch/x86/mm/svm.c b/arch/x86/mm/svm.c index f0b772d4..588618bd 100644 --- a/arch/x86/mm/svm.c +++ b/arch/x86/mm/svm.c @@ -132,7 +132,7 @@ int svm_access_request(size_t addr) icc_mail_check(0); while (page_owner[pageid] != my_ue) { - check_workqueues_rem_irq(); + check_workqueues(); } return change_page_permissions(addr, addr+PAGE_SIZE, VMA_READ|VMA_WRITE|VMA_CACHEABLE); diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index 7f3c7221..8dd950f8 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -176,12 +176,9 @@ size_t get_idle_task(uint32_t id); */ int sys_execve(const char* fname, char** argv, char** env); -/** @brief determines the highest priority of all ready tasks on core core_id - * - * @param core_id core id - * @return highest priority +/** @brief if a task exists with higher priority, MetalSVM switch to it. */ -uint32_t get_highest_priority(uint32_t core_id); +void check_scheduling(void); /** @brief Call to rescheduling * @@ -194,6 +191,7 @@ static inline void check_workqueues(void) #ifdef CONFIG_ROCKCREEK icc_mail_check(0); #endif + check_scheduling(); } static inline void check_workqueues_rem_irq(void) diff --git a/kernel/main.c b/kernel/main.c index 6a18cdc8..c458c3aa 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -94,12 +94,9 @@ int main(void) create_kernel_task(NULL, initd, NULL, NORMAL_PRIO); reschedule(); - while(1) { -#ifdef CONFIG_ROCKCREEK - //icc_halt(); -#else + while(1) { + check_workqueues(); HALT; -#endif } return 0; diff --git a/kernel/syscall.c b/kernel/syscall.c index 8f52a2d2..6eaecd28 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -91,7 +91,7 @@ int syscall_handler(uint32_t sys_nr, ...) int ret = -EINVAL; va_list vl; - check_workqueues_rem_irq(); + check_workqueues(); va_start(vl, sys_nr); diff --git a/kernel/tasks.c b/kernel/tasks.c index 0689d401..910a0605 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -68,8 +68,11 @@ task_t* get_current_task(void) { return per_core(current_task); } -uint32_t get_highest_priority(uint32_t core_id) { - return msb(runqueues[core_id].prio_bitmap); +void check_scheduling(void) { + if (!is_irq_enabled()) + return; + if (msb(runqueues[CORE_ID].prio_bitmap) > per_core(current_task)->prio) + reschedule(); } int multitasking_init(void) { From 6b8d635c3b671aa9873d768d89e131087484c130 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 2 Sep 2011 14:20:43 -0700 Subject: [PATCH 08/24] minor optimizations in the LwIP settings --- lwip/src/include/lwipopts.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 0e1b40c7..68ae046b 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -171,6 +171,12 @@ */ #define MEMP_NUM_TCPIP_MSG_INPKT 0x40 +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#define MEMP_NUM_TCP_SEG 32 + /* DEBUG options */ #define LWIP_DEBUG 1 #define DHCP_DEBUG LWIP_DBG_OFF From 62070aa3a9222dd5d82048ba65e0301e3f4e6460 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 3 Sep 2011 13:25:49 -0700 Subject: [PATCH 09/24] add the support of (explicit) write through caching --- arch/x86/mm/page.c | 3 +++ include/metalsvm/stdlib.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/page.c b/arch/x86/mm/page.c index cc767a43..b2cfaad4 100644 --- a/arch/x86/mm/page.c +++ b/arch/x86/mm/page.c @@ -367,6 +367,9 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag if (flags & MAP_NO_ACCESS) pgt->entries[index] &= ~PG_PRESENT; + if (flags & MAP_WT) + pgt->entries[index] |= PG_PWT; + if (flags & MAP_USER_SPACE) atomic_int32_inc(&task->user_usage); diff --git a/include/metalsvm/stdlib.h b/include/metalsvm/stdlib.h index 15d0961e..0a568204 100644 --- a/include/metalsvm/stdlib.h +++ b/include/metalsvm/stdlib.h @@ -41,7 +41,7 @@ extern "C" { #define MAP_USER_SPACE (1 << 1) #define MAP_PAGE_TABLE (1 << 2) #define MAP_NO_CACHE (1 << 3) -//#define MAP_STACK (1 << 4) +#define MAP_WT (1 << 5) //#define MAP_HEAP (1 << 5) #define MAP_CODE (1 << 6) #define MAP_READONLY (1 << 7) From be766af0fbc223a0c575636e114c0bb9f1c8438c Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 3 Sep 2011 13:27:25 -0700 Subject: [PATCH 10/24] LwIP fine tuning --- lwip/src/include/arch/cc.h | 2 +- lwip/src/include/lwipopts.h | 44 +++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/lwip/src/include/arch/cc.h b/lwip/src/include/arch/cc.h index 3474f573..392132bb 100644 --- a/lwip/src/include/arch/cc.h +++ b/lwip/src/include/arch/cc.h @@ -70,7 +70,7 @@ typedef size_t mem_ptr_t; #define MEM_ALIGNMENT 4 #define ETH_PAD_SIZE 2 -#define LWIP_CHKSUM_ALGORITHM 2 +#define LWIP_CHKSUM_ALGORITHM 3 /* prototypes for printf() and abort() */ #include diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 68ae046b..34d12975 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -3,6 +3,8 @@ #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H_ +#include + /** * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain * critical regions during buffer allocation, deallocation and memory @@ -59,10 +61,19 @@ */ #define LWIP_TCP 1 +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#define TCP_MSS 1460 + /** * TCP_SND_BUF: TCP sender buffer space (bytes). */ -#define TCP_SND_BUF (16*1024) +#define TCP_SND_BUF (16*TCP_WND) /** * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) @@ -118,15 +129,6 @@ */ #define DEFAULT_THREAD_PRIO NORMAL_PRIO -/** - * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, - * you might want to increase this.) - * For the receive side, this MSS is advertised to the remote side - * when opening a connection. For the transmit size, this MSS sets - * an upper limit on the MSS advertised by the remote host. - */ -#define TCP_MSS 2048 - /** * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ @@ -175,7 +177,25 @@ * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. * (requires the LWIP_TCP option) */ -#define MEMP_NUM_TCP_SEG 32 +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN + +// On the SCC, we have not to check incoming messages +#ifdef CONFIG_ROCKCREEK +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#define CHECKSUM_CHECK_IP 0 + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#define CHECKSUM_CHECK_UDP 0 + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#define CHECKSUM_CHECK_TCP 0 +#endif /* DEBUG options */ #define LWIP_DEBUG 1 @@ -187,7 +207,7 @@ #define MEM_DEBUG LWIP_DBG_OFF #define IP_DEBUG LWIP_DBG_OFF #define INET_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_ON +#define NETIF_DEBUG LWIP_DBG_OFF #define TIMERS_DEBUG LWIP_DBG_OFF #define SOCKETS_DEBUG LWIP_DBG_OFF #define PBUF_DEBUG LWIP_DBG_OFF From 710523582ee5e0160531e5dda3c274bdbbe415dd Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 3 Sep 2011 13:28:02 -0700 Subject: [PATCH 11/24] increase the performance of the eMAC device by enabling write combining --- drivers/net/rckemac.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 69f4bdba..97f65226 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -101,9 +101,6 @@ #define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK) #define CLINE_PACKETS(_x) (CLINE_ALIGN(_x) >> CLINE_SHIFT) -/* Flush */ -#define CL1FLUSH __asm__ volatile (".byte 0x0F; .byte 0x0A;\n") - /* Read 16bit from buffer */ #define U16(_addr) (256 * (*((uint8_t*) (_addr + 1))) + (*((uint8_t*)(_addr)))) @@ -113,6 +110,26 @@ static struct netif* mynetif; +#if 0 +inline static void *memcpy_noprefetching(void* dest, const void *src, size_t count) +{ + int32_t i, j, k; + + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + + asm volatile ( + "cld; rep movsl\n\t" + "movl %4, %%ecx\n\t" + "andl $3, %%ecx\n\t" + "rep movsb\n\t" + : "=&c"(i), "=&D"(j), "=&S"(k) + : "0"(count/4), "g"(count), "1"(dest), "2"(src) : "memory","cc"); + + return dest; +} +#endif + static int read_emac(int num_emac, int offset, int core) { int ret; @@ -246,6 +263,9 @@ again: *((volatile int*) rckemacif->tx_buffer) = 2; + // flush write combining buffers + *(int *)RCCE_fool_write_combine_buffer = 1; + /* set new write offset */ //LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset)); write_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_WRITE_OFFSET, rckemacif->core, rckemacif->tx_write_offset); @@ -439,7 +459,6 @@ static void rckemacif_handler(struct state* s) nexttry: /* check for updated write offset */ - CL1FLUSH; write_offset = *((volatile unsigned int*) (rckemacif->rx_buffer)) & 0xFFFF; //write_offset = read_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, rckemacif->core); if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) { @@ -500,7 +519,7 @@ err_t rckemacif_init(struct netif* netif) rckemacif->rx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1; /* allocate the send buffers */ - rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE); + rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE|MAP_WT|MAP_MPE); if (!(rckemacif->tx_buffer)) { LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n")); kfree(rckemacif->rx_buffer, BUFFER_SIZE); @@ -762,6 +781,9 @@ err_t rckemacif_init(struct netif* netif) rckemacif->ethaddr = (struct eth_addr *)netif->hwaddr; + // flush write combining buffers + *(int *)RCCE_fool_write_combine_buffer = 1; + tcpip_callback(netif_set_link_up, netif); return ERR_OK; From 9b442bfd118bbf5d49a032cc82beea4b0b3830e6 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sat, 3 Sep 2011 13:29:33 -0700 Subject: [PATCH 12/24] add a free netio server --- kernel/netio.c | 349 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 328 insertions(+), 21 deletions(-) diff --git a/kernel/netio.c b/kernel/netio.c index 166bbc18..96ee53aa 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -1,50 +1,356 @@ -/* - * this example is derived from the netio example of the contrib-1.4.0 +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. * - * see http://download.savannah.gnu.org/releases/lwip/ */ - #include -#include #if defined(CONFIG_LWIP) #include + +#if LWIP_TCP #include +/* + * This implements a netio server. + * The client sends a command word (4 bytes) then a data length word (4 bytes). + * If the command is "receive", the server is to consume "data length" bytes into + * a circular buffer until the first byte is non-zero, then it is to consume + * another command/data pair. + * If the command is "send", the server is to send "data length" bytes from a circular + * buffer with the first byte being zero, until "some time" (6 seconds in the + * current netio126.zip download) has passed and then send one final buffer with + * the first byte being non-zero. Then it is to consume another command/data pair. + */ + /* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ -#if LWIP_TCP -static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +/* implementation options */ +#define NETIO_BUF_SIZE (4 * 1024) +#define NETIO_USE_STATIC_BUF 0 + +/* NetIO server state definition */ +#define NETIO_STATE_WAIT_FOR_CMD 0 +#define NETIO_STATE_RECV_DATA 1 +#define NETIO_STATE_SEND_DATA 2 +#define NETIO_STATE_SEND_DATA_LAST 3 +#define NETIO_STATE_DONE 4 + +struct netio_state { + u32_t state; + u32_t cmd; + u32_t data_len; + u32_t cntr; + u8_t * buf_ptr; + u32_t buf_pos; + u32_t first_byte; + u32_t time_stamp; +}; + +/* NetIO command protocol definition */ +#define NETIO_CMD_QUIT 0 +#define NETIO_CMD_C2S 1 +#define NETIO_CMD_S2C 2 +#define NETIO_CMD_RES 3 + +static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); + +static void +netio_close(void *arg, struct tcp_pcb *pcb) { + err_t err; - LWIP_UNUSED_ARG(arg); + struct netio_state *ns = arg; + ns->state = NETIO_STATE_DONE; + tcp_recv(pcb, NULL); + err = tcp_close(pcb); - if (err == ERR_OK && p != NULL) { - tcp_recved(pcb, p->tot_len); - pbuf_free(p); + if (err != ERR_OK) { + /* closing failed, try again later */ + tcp_recv(pcb, netio_recv); } else { - pbuf_free(p); + /* closing succeeded */ +#if NETIO_USE_STATIC_BUF != 1 + if(ns->buf_ptr != NULL){ + mem_free(ns->buf_ptr); + } +#endif + tcp_arg(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_sent(pcb, NULL); + if (arg != NULL) { + mem_free(arg); + } + } +} + +static err_t +netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netio_state *ns = arg; + u8_t * data_ptr; + u32_t data_cntr; + struct pbuf *q = p; + u16_t len; + + if (p != NULL) { + tcp_recved(pcb, p->tot_len); } - if (err == ERR_OK && p == NULL) { - tcp_arg(pcb, NULL); - tcp_sent(pcb, NULL); - tcp_recv(pcb, NULL); - tcp_close(pcb); + if (err == ERR_OK && q != NULL) { + + while (q != NULL) { + data_cntr = q->len; + data_ptr = q->payload; + while (data_cntr--) { + if (ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + break; + } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { + if (ns->cntr < 4) { + /* build up the CMD field */ + ns->cmd <<= 8; + ns->cmd |= *data_ptr++; + ns->cntr++; + } else if (ns->cntr < 8) { + /* build up the DATA field */ + ns->data_len <<= 8; + ns->data_len |= *data_ptr++; + ns->cntr++; + + if (ns->cntr == 8) { + /* now we have full command and data words */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + if (ns->cmd == NETIO_CMD_C2S) { + ns->state = NETIO_STATE_RECV_DATA; + } else if (ns->cmd == NETIO_CMD_S2C) { + ns->state = NETIO_STATE_SEND_DATA; + /* start timer */ + ns->time_stamp = get_clock_tick(); + /* send first round of data */ + + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + ns->cntr += len; + + } else { + /* unrecognized command, punt */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + netio_close(ns, pcb); + break; + } + } + } else { + /* in trouble... shouldn't be in this state! */ + kputs("netio is in trouble\n"); + } + + } else if (ns->state == NETIO_STATE_RECV_DATA) { + + if(ns->cntr == 0){ + /* save the first byte of this new round of data + * this will not match ns->buf_ptr[0] in the case that + * NETIO_BUF_SIZE is less than ns->data_len. + */ + ns->first_byte = *data_ptr; + } + + ns->buf_ptr[ns->buf_pos++] = *data_ptr++; + ns->cntr++; + + if (ns->buf_pos == NETIO_BUF_SIZE) { + /* circularize the buffer */ + ns->buf_pos = 0; + } + + if(ns->cntr == ns->data_len){ + ns->cntr = 0; + if (ns->first_byte != 0) { + /* if this last round did not start with 0, + * go look for another command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ + } else { + /* stay here and wait on more data */ + } + } + + } else if (ns->state == NETIO_STATE_SEND_DATA + || ns->state == NETIO_STATE_SEND_DATA_LAST) { + /* I don't think this should happen... */ + kputs("I don't think this should happen...\n"); + } else { + /* done / quit */ + netio_close(ns, pcb); + break; + } /* end of ns->state condition */ + } /* end of while data still in this pbuf */ + + q = q->next; + } + + pbuf_free(p); + + } else { + + /* error or closed by other side */ + if (p != NULL) { + pbuf_free(p); + } + + /* close the connection */ + netio_close(ns, pcb); + + } + return ERR_OK; + +} + +static err_t +netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netio_state *ns = arg; + err_t err = ERR_OK; + + if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { + /* done with this round of sending */ + ns->buf_pos = 0; + ns->cntr = 0; + + /* check if timer expired */ + if (get_clock_tick() - ns->time_stamp > 600) { + ns->buf_ptr[0] = 1; + ns->state = NETIO_STATE_SEND_DATA_LAST; + } else { + ns->buf_ptr[0] = 0; + } + } + + if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + + if(ns->cntr < ns->data_len){ + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + if(ns->buf_pos >= NETIO_BUF_SIZE){ + ns->buf_pos = 0; + } + + ns->cntr += len; + } + } + + if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ + /* we have buffered up all our data to send this last round, go look for a command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->cntr = 0; + /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ } return ERR_OK; } -static err_t netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) +static err_t +netio_poll(void *arg, struct tcp_pcb *pcb) { - LWIP_UNUSED_ARG(arg); + struct netio_state * ns = arg; + + if(ns->state == NETIO_STATE_SEND_DATA) { + + } else if(ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + } + + return ERR_OK; + +} + +#if NETIO_USE_STATIC_BUF == 1 +static u8_t netio_buf[NETIO_BUF_SIZE]; +#endif + +static err_t +netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netio_state * ns; + LWIP_UNUSED_ARG(err); - tcp_arg(pcb, NULL); - tcp_sent(pcb, NULL); + ns = mem_malloc(sizeof(struct netio_state)); + + if(ns == NULL){ + return ERR_MEM; + } + + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + ns->cntr = 0; + ns->buf_pos = 0; +#if NETIO_USE_STATIC_BUF == 1 + ns->buf_ptr = netio_buf; +#else + ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE); + + if(ns->buf_ptr == NULL){ + mem_free(ns); + return ERR_MEM; + } +#endif + + ns->buf_ptr[0] = 0; + + tcp_arg(pcb, ns); + tcp_sent(pcb, netio_sent); tcp_recv(pcb, netio_recv); + tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ + //tcp_nagle_disable(pcb); return ERR_OK; } @@ -57,6 +363,7 @@ void netio_init(void) pcb = tcp_listen(pcb); tcp_accept(pcb, netio_accept); } + #endif /* LWIP_TCP */ #endif From 3ff872ac311eb2917c502177465f8d880cee85df Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Sun, 4 Sep 2011 01:55:55 -0700 Subject: [PATCH 13/24] fine tuning... --- kernel/netio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/netio.c b/kernel/netio.c index 96ee53aa..35a707e3 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -344,7 +344,8 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) } #endif - ns->buf_ptr[0] = 0; + memset(ns->buf_ptr, 0x00, NETIO_BUF_SIZE); + //ns->buf_ptr[0] = 0; tcp_arg(pcb, ns); tcp_sent(pcb, netio_sent); From c6339bfd2d700cd042407be8371f1caacbe7a92a Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 6 Sep 2011 06:46:52 -0700 Subject: [PATCH 14/24] by leaving the interrupt handler, we check if an urgent task is ready if yes, the kernel switchs to this task --- arch/x86/kernel/irq.c | 5 +++-- include/metalsvm/tasks.h | 8 ++++++++ kernel/tasks.c | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index d93b2a55..f0f7d130 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -237,8 +237,7 @@ void irq_handler(struct state *s) // evaluate only irq status register if int_no = 124 if( s->int_no == 124 ) { check_workqueues_rem_irq(); - } - else { + } else { check_workqueues(); } @@ -283,4 +282,6 @@ leave_handler: // timer interrupt? if ((s->int_no == 32) || (s->int_no == 123)) scheduler(); // switch to a new task + else if ((s->int_no >= 32) && (get_highest_priority() > per_core(current_task)->prio)) + scheduler(); } diff --git a/include/metalsvm/tasks.h b/include/metalsvm/tasks.h index 8dd950f8..3f4589cb 100644 --- a/include/metalsvm/tasks.h +++ b/include/metalsvm/tasks.h @@ -180,6 +180,14 @@ int sys_execve(const char* fname, char** argv, char** env); */ void check_scheduling(void); +/** @brief determine the highest priority of all tasks, which are ready + * + * @return + * - return highest priority + * - if no task is ready, the function returns an invalid value (> MAX_PRIO) + */ +uint32_t get_highest_priority(void); + /** @brief Call to rescheduling * * This is a purely assembled procedure for rescheduling diff --git a/kernel/tasks.c b/kernel/tasks.c index 910a0605..10f4a50a 100644 --- a/kernel/tasks.c +++ b/kernel/tasks.c @@ -75,6 +75,11 @@ void check_scheduling(void) { reschedule(); } +uint32_t get_highest_priority(void) +{ + return msb(runqueues[CORE_ID].prio_bitmap); +} + int multitasking_init(void) { if (BUILTIN_EXPECT(task_table[0].status != TASK_IDLE, 0)) { kputs("Task 0 is not an idle task\n"); From 3fad9accbdac0b9295310e89314cba2c554444c3 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 6 Sep 2011 07:11:23 -0700 Subject: [PATCH 15/24] remove obsolete timer --- kernel/netio.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/kernel/netio.c b/kernel/netio.c index 35a707e3..37a7ccda 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -24,7 +24,7 @@ * This file is part of the lwIP TCP/IP stack. * */ -#include +#include #if defined(CONFIG_LWIP) @@ -40,8 +40,7 @@ * a circular buffer until the first byte is non-zero, then it is to consume * another command/data pair. * If the command is "send", the server is to send "data length" bytes from a circular - * buffer with the first byte being zero, until "some time" (6 seconds in the - * current netio126.zip download) has passed and then send one final buffer with + * buffer with the first byte being zero, until "some time" and then send one final buffer with * the first byte being non-zero. Then it is to consume another command/data pair. */ @@ -156,7 +155,9 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) len = tcp_sndbuf(pcb); len = LWIP_MIN(len, ns->data_len - ns->cntr); len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + //kprintf("data length: %d, len: %d\n", ns->data_len, len); + ns->buf_ptr[0] = 0; do { err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); if (err == ERR_MEM) { @@ -216,7 +217,6 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) } else if (ns->state == NETIO_STATE_SEND_DATA || ns->state == NETIO_STATE_SEND_DATA_LAST) { /* I don't think this should happen... */ - kputs("I don't think this should happen...\n"); } else { /* done / quit */ netio_close(ns, pcb); @@ -256,12 +256,8 @@ netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) ns->cntr = 0; /* check if timer expired */ - if (get_clock_tick() - ns->time_stamp > 600) { - ns->buf_ptr[0] = 1; - ns->state = NETIO_STATE_SEND_DATA_LAST; - } else { - ns->buf_ptr[0] = 0; - } + ns->buf_ptr[0] = 1; + ns->state = NETIO_STATE_SEND_DATA_LAST; } if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ @@ -291,6 +287,7 @@ netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) ns->state = NETIO_STATE_WAIT_FOR_CMD; ns->cntr = 0; /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ + //kprintf("consumed ticks: %d", get_clock_tick() - ns->time_stamp); } return ERR_OK; @@ -345,7 +342,6 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) #endif memset(ns->buf_ptr, 0x00, NETIO_BUF_SIZE); - //ns->buf_ptr[0] = 0; tcp_arg(pcb, ns); tcp_sent(pcb, netio_sent); From bbf4706c5065b5b8f7bcd7a72e6aca63ae46a2e7 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 6 Sep 2011 07:15:26 -0700 Subject: [PATCH 16/24] LwIP fine tuning --- lwip/src/arch/sys_arch.c | 4 ++-- lwip/src/include/arch/cc.h | 2 +- lwip/src/include/lwipopts.h | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lwip/src/arch/sys_arch.c b/lwip/src/arch/sys_arch.c index 88b9e26b..5b90bf66 100644 --- a/lwip/src/arch/sys_arch.c +++ b/lwip/src/arch/sys_arch.c @@ -167,7 +167,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t * mbox, void **msg, u32_t timeout) int err; err = mailbox_ptr_fetch(&mbox->mailbox, msg, timeout); - LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: %d\n", err)); + //LWIP_DEBUGF(SYS_DEBUG, ("sys_arch_mbox_fetch: %d\n", err)); if (!err) return 0; @@ -216,7 +216,7 @@ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) int err; err = mailbox_ptr_trypost(&mbox->mailbox, msg); - LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: %d"\n, err)); + //LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: %d"\n, err)); return err; } diff --git a/lwip/src/include/arch/cc.h b/lwip/src/include/arch/cc.h index 392132bb..f34c3e51 100644 --- a/lwip/src/include/arch/cc.h +++ b/lwip/src/include/arch/cc.h @@ -70,7 +70,7 @@ typedef size_t mem_ptr_t; #define MEM_ALIGNMENT 4 #define ETH_PAD_SIZE 2 -#define LWIP_CHKSUM_ALGORITHM 3 +#define LWIP_CHKSUM_ALGORITHM 2 /* prototypes for printf() and abort() */ #include diff --git a/lwip/src/include/lwipopts.h b/lwip/src/include/lwipopts.h index 34d12975..d21fe32c 100644 --- a/lwip/src/include/lwipopts.h +++ b/lwip/src/include/lwipopts.h @@ -179,7 +179,7 @@ */ #define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN -// On the SCC, we have not to check incoming messages +// On the SCC, we have not to check incoming messages from the trusted MCPC #ifdef CONFIG_ROCKCREEK /** * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. @@ -202,12 +202,12 @@ #define DHCP_DEBUG LWIP_DBG_OFF #define ETHARP_DEBUG LWIP_DBG_OFF #define TCPIP_DEBUG LWIP_DBG_OFF -#define SYS_DEBUG LWIP_DBG_OFF +#define SYS_DEBUG LWIP_DBG_ON #define RAW_DEBUG LWIP_DBG_OFF #define MEM_DEBUG LWIP_DBG_OFF #define IP_DEBUG LWIP_DBG_OFF #define INET_DEBUG LWIP_DBG_OFF -#define NETIF_DEBUG LWIP_DBG_OFF +#define NETIF_DEBUG LWIP_DBG_ON #define TIMERS_DEBUG LWIP_DBG_OFF #define SOCKETS_DEBUG LWIP_DBG_OFF #define PBUF_DEBUG LWIP_DBG_OFF From a79f47d3651bdd9a80d0e5619b563ba8235f66f4 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 6 Sep 2011 08:09:33 -0700 Subject: [PATCH 17/24] remove wrong comment --- kernel/netio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/netio.c b/kernel/netio.c index 37a7ccda..aeef965e 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -254,8 +254,6 @@ netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) /* done with this round of sending */ ns->buf_pos = 0; ns->cntr = 0; - - /* check if timer expired */ ns->buf_ptr[0] = 1; ns->state = NETIO_STATE_SEND_DATA_LAST; } From 24ea129456ec993e625800d74f426a77e18c5d03 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Tue, 6 Sep 2011 08:58:03 -0700 Subject: [PATCH 18/24] use optimized memcpy function to increase the performance --- drivers/net/rckemac.c | 121 +++++++++++++++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 25 deletions(-) diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index 97f65226..d3188e66 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -108,15 +108,67 @@ #define MAC_HI(_x) ((((_x) >> 32)) & 0xFFFF) #define MAC_LO(_x) (((_x) ) & 0xFFFFFFFF) +#define MIN(a, b) (a) < (b) ? (a) : (b) + static struct netif* mynetif; -#if 0 -inline static void *memcpy_noprefetching(void* dest, const void *src, size_t count) +inline static void* memcpy_from_nc(void *dest, const void *src, size_t count) { - int32_t i, j, k; +#if 0 + size_t i; - if (BUILTIN_EXPECT(!dest || !src, 0)) - return dest; + for(i=0; inext) { - memcpy(((uint8_t*)addr) + 2 + i, q->payload, q->len); + memcpy_to_nc(((uint8_t*)addr) + 2 + i, q->payload, q->len); i += q->len; } @@ -224,12 +276,12 @@ again: if (bytes_left < bytes_to_copy) bytes_to_copy = bytes_left; - LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy)); + //LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy)); q = p; i = 0; while ((q != 0) && (i < bytes_to_copy)) { sz = q->len > bytes_to_copy-i ? bytes_to_copy-i : q->len; - memcpy(((uint8_t*) addr) + 2 + i, q->payload, sz); + memcpy_to_nc(((uint8_t*) addr) + 2 + i, q->payload, sz); bytes_left -= sz; i += sz; if (i < bytes_to_copy) @@ -239,16 +291,16 @@ again: if (bytes_left != 0) { rckemacif->tx_write_offset = 1; addr = rckemacif->tx_buffer + 32; - LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left)); + //LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left)); i = 0; if (sz < q->len) { - memcpy((uint8_t*) addr, q->payload + sz, q->len - sz); + memcpy_to_nc((uint8_t*) addr, q->payload + sz, q->len - sz); bytes_left -= (q->len - sz); i = q->len - sz; } for(q=q->next; (q != 0); q = q->next) { - memcpy(((uint8_t*) addr) + i, q->payload, q->len); + memcpy_to_nc(((uint8_t*) addr) + i, q->payload, q->len); i += q->len; } @@ -256,7 +308,7 @@ again: if (rest != 0) rest = 32 - rest; - LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest)); + //LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest)); rckemacif->tx_write_offset += CLINE_PACKETS(bytes_left + rest) - 1; } } @@ -312,7 +364,7 @@ static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset) { rckemacif_t* rckemacif = netif->state; unsigned short read_offset = rckemacif->rx_read_offset; - unsigned int counter; + //unsigned int counter; volatile void *addr = NULL; uint16_t i, length = 0; uint32_t packets = 0; @@ -373,7 +425,7 @@ again: if (read_offset < write_offset) { for (q=p, i/*counter=0*/; q!=NULL; q=q->next) { - memcpy((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len); + memcpy_from_nc((uint8_t*) q->payload, (uint8_t*)addr + 2, q->len); //for(i=0; ilen; i++, counter++) { // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; //} @@ -384,33 +436,52 @@ again: int rest; int bytesLeft = length; int bytesToCopy = length; + int counter = 0; /* rest to the end of buffer - 2 bytes length information */ rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2; if (length > rest) bytesToCopy = rest; - LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft)); + //LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft)); - for (q=p, counter=0; q!=NULL; q=q->next) { - for(i=0; ilen; i++, counter++) { + q = p; + i = /*counter =*/ 0; + while ((q != NULL) && (counter < bytesToCopy)) { + i = MIN(q->len, bytesToCopy - counter); + memcpy_from_nc(q->payload, (uint8_t*) addr + 2 + counter, i); + counter += i; + if (counter >= bytesToCopy) + goto out; + else + q = q->next; + /*for(i=0; ilen; i++, counter++) { if (counter < bytesToCopy) ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter]; else goto out; - } + }*/ } out: bytesLeft -= bytesToCopy; if (bytesLeft != 0) { addr = rckemacif->rx_buffer + 0x20; - LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0])); - for(counter=0; (ilen) && (counter < bytesLeft); i++, counter++) - ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + counter = 0; + //LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0])); + + if (i < q->len) { + counter = MIN(q->len - i, bytesLeft); + memcpy_from_nc((uint8_t*)q->payload + i, (uint8_t*) addr, counter); + } + //for(counter=0; (ilen) && (counter < bytesLeft); i++, counter++) + // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) { - for(i=0; (ilen) && (counter < bytesLeft); i++, counter++) { - ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; - } + i = MIN(q->len, bytesLeft - counter); + memcpy_from_nc((uint8_t*)q->payload, (uint8_t*)addr + counter, i); + counter += i; + //for(i=0; (ilen) && (counter < bytesLeft); i++, counter++) { + // ((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter]; + //} } read_offset = CLINE_PACKETS(bytesLeft); } else { From 4f5e5e244982f470078f6f40599885d42dc65995 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 7 Sep 2011 10:07:22 +0200 Subject: [PATCH 19/24] switch back to RAW interface and some cosmetic changes --- kernel/ping.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/kernel/ping.c b/kernel/ping.c index 7d81500f..af661b79 100644 --- a/kernel/ping.c +++ b/kernel/ping.c @@ -55,7 +55,7 @@ #include #if LWIP_SOCKET -#define PING_USE_SOCKETS 1 +#define PING_USE_SOCKETS 0 #endif #if PING_USE_SOCKETS @@ -102,7 +102,7 @@ #endif /* ping variables */ -static u16_t ping_seq_num; +static u16_t ping_seq_num = 0; static u32_t ping_time; #if !PING_USE_SOCKETS static struct raw_pcb *ping_pcb; @@ -216,7 +216,7 @@ ping_thread(void *arg) ping_target = PING_TARGET; if (ping_send(s, &ping_target) == ERR_OK) { - LWIP_DEBUGF( PING_DEBUG, ("ping: send on core %d to " , CORE_ID)); + LWIP_DEBUGF( PING_DEBUG, ("ping: send to ")); ip_addr_debug_print(PING_DEBUG, &ping_target); LWIP_DEBUGF( PING_DEBUG, ("\n")); @@ -293,6 +293,7 @@ ping_send(struct raw_pcb *raw, ip_addr_t *addr) static void ping_timeout(void *arg) { + static unsigned counter = 0; struct raw_pcb *pcb = (struct raw_pcb*)arg; ip_addr_t ping_target = PING_TARGET; @@ -300,7 +301,9 @@ ping_timeout(void *arg) ping_send(pcb, &ping_target); - sys_timeout(PING_DELAY, ping_timeout, pcb); + counter++; + if (counter < 5) + sys_timeout(PING_DELAY, ping_timeout, pcb); } static void @@ -314,13 +317,15 @@ ping_raw_init(void) sys_timeout(PING_DELAY, ping_timeout, ping_pcb); } +#if 0 void -ping_send_now() +ping_send_now(void) { ip_addr_t ping_target = PING_TARGET; LWIP_ASSERT("ping_pcb != NULL", ping_pcb != NULL); ping_send(ping_pcb, &ping_target); } +#endif #endif /* PING_USE_SOCKETS */ From 8aadb9a4262b02a4a230061604ebba8ca9e6dc82 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 7 Sep 2011 10:09:47 +0200 Subject: [PATCH 20/24] to solve some DHCP issues, we use same procedure to initialize LwIP like the LwIP examples --- include/metalsvm/init.h | 7 +- kernel/init.c | 147 ++++++++++++++++++++++++---------------- 2 files changed, 90 insertions(+), 64 deletions(-) diff --git a/include/metalsvm/init.h b/include/metalsvm/init.h index 02f97091..8ca4a89a 100644 --- a/include/metalsvm/init.h +++ b/include/metalsvm/init.h @@ -36,11 +36,8 @@ extern "C" { * initialize the VGA output. If configured.*/ int lowlevel_init(void); -/** @brief Initialize LWIP stack and start a networking task. */ -int network_init(void); - -/** @brief Shutdown the networking subsystem. */ -int network_shutdown(void); +/** @brief Shutdown the system */ +int shutdown(void); /** @brief Entry point of the init task */ int initd(void* arg); diff --git a/kernel/init.c b/kernel/init.c index ac1653a8..cbb9c32e 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -72,30 +72,14 @@ int lowlevel_init(void) #if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) static struct netif* default_netif = NULL; -static volatile uint32_t lwip_initialized = 0; -static void tcp_init_ok(void* e) +static int init_netifs(void) { - kputs("TCP/IP init COMPLETE!!\n"); - lwip_initialized = 1; -} -#endif - -int network_init(void) -{ -#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) struct ip_addr ipaddr; struct ip_addr netmask; struct ip_addr gw; - kputs("Initialize network...\n"); - - // Initialize lwIP modules - tcpip_init(tcp_init_ok, NULL); - - while(!lwip_initialized) { - reschedule(); - } + kputs("Initialize NICs...\n"); // Set up the lwIP network interface // Allocate and configure netif @@ -115,6 +99,14 @@ int network_init(void) /* Bring up the network interface */ if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rckemacif_init, tcpip_input)) { + kputs("Unable to add network interface\n"); + return -ENODEV; + } + + netif_set_default(default_netif); + netif_set_up(default_netif); + + //mmnif_open(); #else /* Clear network address because we use DHCP to get an ip address */ IP4_ADDR(&gw, 0,0,0,0); @@ -123,64 +115,63 @@ int network_init(void) /* Bring up the network interface */ if (!netif_add(default_netif, &ipaddr, &netmask, &gw, NULL, rtl8139if_init, tcpip_input)) { -#endif kputs("Unable to add network interface\n"); return -ENODEV; } netif_set_default(default_netif); - netif_set_up(default_netif); - /* test if interface is really up */ - if (!netif_is_up(default_netif)) { - kputs("network interface is not up\n"); - return -ENODEV; - } - -#ifndef CONFIG_ROCKCREEK kprintf("Starting DHCPCD...\n"); dhcp_start(default_netif); - - int mscnt = 0; - /* wait for ip address */ - while(!default_netif->ip_addr.addr) { - sys_msleep(DHCP_FINE_TIMER_MSECS); - dhcp_fine_tmr(); - mscnt += DHCP_FINE_TIMER_MSECS; - if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { - dhcp_coarse_tmr(); - mscnt = 0; - } - } -#else - //mmnif_open(); -#endif - - // start echo and ping server - echo_init(); - //ping_init(); - netio_init(); #endif return 0; } - -int network_shutdown(void) -{ -#ifdef CONFIG_LWIP -#ifdef CONFIG_ROCKCREEK - //mmnif_close(); -#elif defined(CONFIG_PCI) - dhcp_release(default_netif); - dhcp_stop(default_netif); #endif - mem_free(default_netif); - default_netif = NULL; +#ifdef CONFIG_LWIP +static void tcpip_init_done(void* arg) +{ + sys_sem_t* sem = (sys_sem_t*)arg; + +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) + init_netifs(); +#endif + sys_sem_signal(sem); +} +#endif + +#ifdef CONFIG_LWIP +static int network_shutdown(void) +{ +#ifdef CONFIG_ROCKCREEK + if (default_netif) { + netif_set_link_down(default_netif); + mem_free(default_netif); + default_netif = NULL; + } + //mmnif_close(); +#elif defined(CONFIG_PCI) + if (default_netif) { + dhcp_release(default_netif); + dhcp_stop(default_netif); + mem_free(default_netif); + default_netif = NULL; + } #endif return 0; } +#endif + +int shutdown(void) +{ +#ifdef CONFIG_LWIP + return network_shutdown(); +#else + return 0; +#endif +} static void list_fs(vfs_node_t* node, uint32_t depth) { @@ -217,7 +208,45 @@ static void list_root(void) { int initd(void* arg) { - network_init(); +#ifdef CONFIG_LWIP + sys_sem_t sem; + + // Initialize lwIP modules + 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); + +#if defined(CONFIG_LWIP) && (defined(CONFIG_PCI) || defined(CONFIG_ROCKCREEK)) + /* test if interface is really up */ + if (!netif_is_up(default_netif)) { + kputs("network interface is not up\n"); + return -ENODEV; + } +#endif + +#ifndef CONFIG_ROCKCREEK + int mscnt = 0; + /* wait for ip address */ + while(default_netif && !default_netif->ip_addr.addr) { + sys_msleep(DHCP_FINE_TIMER_MSECS); + dhcp_fine_tmr(); + mscnt += DHCP_FINE_TIMER_MSECS; + if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) { + dhcp_coarse_tmr(); + mscnt = 0; + } + } +#endif + + // start echo and ping server + echo_init(); + //ping_init(); + netio_init(); +#endif + list_root(); test_init(); From 308f9b136f62f85f9d33857c8c65929856568767 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 7 Sep 2011 10:11:16 +0200 Subject: [PATCH 21/24] remove tcpip_callback(netif_set_link_up, netif) => the initd will set the link up --- drivers/net/rckemac.c | 2 -- drivers/net/rtl8139.c | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/rckemac.c b/drivers/net/rckemac.c index d3188e66..a7188f2a 100644 --- a/drivers/net/rckemac.c +++ b/drivers/net/rckemac.c @@ -855,8 +855,6 @@ err_t rckemacif_init(struct netif* netif) // flush write combining buffers *(int *)RCCE_fool_write_combine_buffer = 1; - tcpip_callback(netif_set_link_up, netif); - return ERR_OK; } #endif diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index cc3ab28d..df5d7ce6 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -441,14 +441,12 @@ err_t rtl8139if_init(struct netif* netif) /* maximum transfer unit */ netif->mtu = 1500; /* broadcast capability */ - netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; /* hardware address length */ netif->hwaddr_len = 6; rtl8139if->ethaddr = (struct eth_addr *)netif->hwaddr; - tcpip_callback(netif_set_link_up, netif); - return ERR_OK; } #endif From 42ee9a2a6a95cfd1393a201b362014f6f8726149 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 7 Sep 2011 01:41:17 -0700 Subject: [PATCH 22/24] now, we use on all SCCs the same IP (192.168.28.(COREID+1)) --- kernel/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/init.c b/kernel/init.c index cbb9c32e..d17fbe9c 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -93,8 +93,8 @@ static int init_netifs(void) memset(default_netif, 0x00, sizeof(struct netif)); #ifdef CONFIG_ROCKCREEK /* Set network address variables */ - IP4_ADDR(&gw, 192,168,4,254); - IP4_ADDR(&ipaddr, 192,168,4,RCCE_ue()+1); + IP4_ADDR(&gw, 192,168,28,254); + IP4_ADDR(&ipaddr, 192,168,28,RCCE_ue()+1); IP4_ADDR(&netmask, 255,255,255,0); /* Bring up the network interface */ From 58b46d6c08e92195ee46b693f7d0a139732e04de Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 7 Sep 2011 03:12:38 -0700 Subject: [PATCH 23/24] on the server side, we determines also the bandwidth --- kernel/netio.c | 21 ++++++++++++--------- lwip/src/include/arch/cc.h | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/kernel/netio.c b/kernel/netio.c index aeef965e..e6c55ef8 100644 --- a/kernel/netio.c +++ b/kernel/netio.c @@ -25,6 +25,7 @@ * */ #include +#include #if defined(CONFIG_LWIP) @@ -65,7 +66,7 @@ struct netio_state { u8_t * buf_ptr; u32_t buf_pos; u32_t first_byte; - u32_t time_stamp; + u64_t time_stamp; }; /* NetIO command protocol definition */ @@ -114,10 +115,6 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) struct pbuf *q = p; u16_t len; - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - } - if (err == ERR_OK && q != NULL) { while (q != NULL) { @@ -149,7 +146,7 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) } else if (ns->cmd == NETIO_CMD_S2C) { ns->state = NETIO_STATE_SEND_DATA; /* start timer */ - ns->time_stamp = get_clock_tick(); + ns->time_stamp = rdtsc(); /* send first round of data */ len = tcp_sndbuf(pcb); @@ -157,7 +154,6 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); //kprintf("data length: %d, len: %d\n", ns->data_len, len); - ns->buf_ptr[0] = 0; do { err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); if (err == ERR_MEM) { @@ -227,12 +223,14 @@ netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) q = q->next; } + tcp_recved(pcb, p->tot_len); pbuf_free(p); } else { /* error or closed by other side */ if (p != NULL) { + tcp_recved(pcb, p->tot_len); pbuf_free(p); } @@ -251,11 +249,17 @@ netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) err_t err = ERR_OK; if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { + u64_t now = rdtsc(); + u64_t time = (now - ns->time_stamp) / get_cpu_frequency(); + /* done with this round of sending */ ns->buf_pos = 0; ns->cntr = 0; ns->buf_ptr[0] = 1; ns->state = NETIO_STATE_SEND_DATA_LAST; + + kprintf("consumed time: %llu usec (%llu ticks)\n", time, now - ns->time_stamp); + kprintf("throughput: %llu KByte/s\n", (ns->data_len * 1000000ULL) / (time*1024)); } if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ @@ -284,8 +288,7 @@ netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) /* we have buffered up all our data to send this last round, go look for a command */ ns->state = NETIO_STATE_WAIT_FOR_CMD; ns->cntr = 0; - /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ - //kprintf("consumed ticks: %d", get_clock_tick() - ns->time_stamp); + ns->buf_ptr[0] = 0; } return ERR_OK; diff --git a/lwip/src/include/arch/cc.h b/lwip/src/include/arch/cc.h index f34c3e51..d4b637cc 100644 --- a/lwip/src/include/arch/cc.h +++ b/lwip/src/include/arch/cc.h @@ -48,6 +48,8 @@ typedef uint16_t u16_t; typedef int16_t s16_t; typedef uint32_t u32_t; typedef int32_t s32_t; +typedef uint64_t u64_t; +typedef int64_t s64_t; typedef size_t mem_ptr_t; From 4d57419e22811d9673853f2505792d4944cf9d14 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Thu, 8 Sep 2011 04:43:35 -0700 Subject: [PATCH 24/24] increasing the support of user-level BSD sockets --- newlib/net/Makefile | 3 +- newlib/net/gethostbyname.c | 56 +++++++++++++++++++++++++++++++ newlib/net/getsockopt.c | 56 +++++++++++++++++++++++++++++++ newlib/net/inet.h | 2 +- newlib/net/netdb.h | 67 ++++++++++++++++++++++++++++++++++++++ newlib/net/select.c | 58 +++++++++++++++++++++++++++++++++ newlib/net/sendto.c | 58 +++++++++++++++++++++++++++++++++ newlib/net/setsockopt.c | 57 ++++++++++++++++++++++++++++++++ newlib/net/socket.h | 4 +-- newlib/net/syscall.h | 6 ++++ 10 files changed, 363 insertions(+), 4 deletions(-) create mode 100644 newlib/net/gethostbyname.c create mode 100644 newlib/net/getsockopt.c create mode 100644 newlib/net/netdb.h create mode 100644 newlib/net/select.c create mode 100644 newlib/net/sendto.c create mode 100644 newlib/net/setsockopt.c diff --git a/newlib/net/Makefile b/newlib/net/Makefile index 4d8e4bce..9a0ea2e6 100644 --- a/newlib/net/Makefile +++ b/newlib/net/Makefile @@ -7,7 +7,7 @@ LDFLAGS = LIBNAME = libsocket.a ARFLAGS = ruv CP = cp -OBJS = accept.o bind.o closesocket.o connect.o listen.o recv.o send.o socket.o ip_addr.o +OBJS = accept.o bind.o closesocket.o connect.o listen.o recv.o send.o socket.o ip_addr.o gethostbyname.o #setsockopt.o getsockopt.o sendto.o select.o # other implicit rules %.o : %.c @@ -23,6 +23,7 @@ $(LIBNAME): $(OBJS) socket.h $(CP) socket.h $(NEWLIB)/include/sys $(CP) in.h $(NEWLIB)/include/netinet $(CP) inet.h $(NEWLIB)/include/arpa + $(CP) netdb.h $(NEWLIB)/include clean: $(RM) $(LIBNAME) *.o *~ diff --git a/newlib/net/gethostbyname.c b/newlib/net/gethostbyname.c new file mode 100644 index 00000000..a42e4037 --- /dev/null +++ b/newlib/net/gethostbyname.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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 "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +struct hostent; + +struct hostent* +_DEFUN (gethostbyname, (name), + const char *name) +{ + struct hostent* ret; + + ret = (struct hostent*) SYSCALL1(__NR_gethostbyname, name); + //if (ret == NULL) + // errno = -EINVAL; + + return ret; +} diff --git a/newlib/net/getsockopt.c b/newlib/net/getsockopt.c new file mode 100644 index 00000000..2684ecc0 --- /dev/null +++ b/newlib/net/getsockopt.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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 "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +int +_DEFUN (getsockopt, (s, level, optname, optval, optlen), + int s _AND int level _AND int optname _AND void *optval _AND uint32_t optlen) +{ + int ret; + + ret = SYSCALL6(__NR_getsockopt, s, level, optname, optval, optlen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/inet.h b/newlib/net/inet.h index 39bbc745..8d2cbf42 100644 --- a/newlib/net/inet.h +++ b/newlib/net/inet.h @@ -106,4 +106,4 @@ char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); } #endif -#endif /* __NETINET_IN_H__ */ +#endif /* __ARPA_INET_H__ */ diff --git a/newlib/net/netdb.h b/newlib/net/netdb.h new file mode 100644 index 00000000..d4086a07 --- /dev/null +++ b/newlib/net/netdb.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, Stefan Lankes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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. + */ + +/* + * The kernel of MetalSVM uses LwIP as lightweight TCP/IP stack. + * This header defines only a small wrapper to use LwIP functions + * from user space. + */ + +#ifndef __NETDB_H__ +#define __NETDB_H__ + +#include +#include + +#ifdef __cplusplus +{ +#endif + +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct hostent *gethostbyname(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETDB_H__ */ diff --git a/newlib/net/select.c b/newlib/net/select.c new file mode 100644 index 00000000..862cd467 --- /dev/null +++ b/newlib/net/select.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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 "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (select, (maxfdp1, readset, writeset, exceptset, timeout), + int maxfdp1 _AND fd_set *readset _AND fd_set *writeset _AND fd_set *exceptset _AND struct timeval *timeout) +{ + int ret; + + ret = SYSCALL6(__NR_select, maxfdp1, readset, writeset, exceptset, timeout); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/sendto.c b/newlib/net/sendto.c new file mode 100644 index 00000000..a4730cbc --- /dev/null +++ b/newlib/net/sendto.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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 "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + +struct sockaddr; + +int +_DEFUN (sendto, (s, dataptr, size, flags, to, tolen), + int s _AND const void *dataptr _AND size_t size _AND int flags _AND const struct sockaddr *to _AND uint32_t tolen) +{ + int ret; + + ret = SYSCALL7(__NR_sendto, s, dataptr, size, flags, to, tolen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/setsockopt.c b/newlib/net/setsockopt.c new file mode 100644 index 00000000..b650da0a --- /dev/null +++ b/newlib/net/setsockopt.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011, Stefan Lanes, Chair for Operating Systems, + * 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Chair for Operating Systems, + * RWTH Aachen University. + * 4. Neither the name of the Chair for Operating Systems, RWTH Aachen 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 ''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 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 "config.h" +#include <_ansi.h> +#include <_syslist.h> +#include +#undef errno +extern int errno; +#include "warning.h" +#include "syscall.h" + + +int +_DEFUN (setsockopt, (s, level, optname, optval, optlen), + int s _AND int level _AND int optname _AND const void *optval _AND uint32_t optlen) +{ + int ret; + + ret = SYSCALL6(__NR_setsockopt, s, level, optname, optval, optlen); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} diff --git a/newlib/net/socket.h b/newlib/net/socket.h index 92d9ad0f..da6b1d11 100644 --- a/newlib/net/socket.h +++ b/newlib/net/socket.h @@ -311,8 +311,8 @@ int send(int s, const void *dataptr, size_t size, int flags); int sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); int socket(int domain, int type, int protocol); -//int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, -// struct timeval *timeout); +int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); //int ioctl(int s, long cmd, void *argp); //int fcntl(int s, int cmd, int val); diff --git a/newlib/net/syscall.h b/newlib/net/syscall.h index 5bd58118..26acb507 100644 --- a/newlib/net/syscall.h +++ b/newlib/net/syscall.h @@ -63,6 +63,12 @@ extern "C" { #define __NR_recv 21 #define __NR_send 22 #define __NR_socket 23 +#define __NR_getsockopt 24 +#define __NR_setsockopt 25 +#define __NR_gethostbyname 26 +#define __NR_sendto 27 +#define __NR_recvfrom 28 +#define __NR_select 29 #define _STR(token) #token #define _SYSCALLSTR(x) "int $" _STR(x) " "