Fixed a bug in apic.c for irq's > 7. Rewrote/organized nic driver to use kalloc
[akaros.git] / kern / src / syscall.c
index 784b4c2..cb852f6 100644 (file)
@@ -7,7 +7,10 @@
 #include <arch/x86.h>
 #include <arch/console.h>
 #include <arch/apic.h>
+#include <arch/timer.h>
 #include <ros/error.h>
+
+#include <rl8168.h>
 #include <string.h>
 #include <assert.h>
 #include <env.h>
@@ -19,7 +22,10 @@ void syscall_wrapper(struct Trapframe *tf)
 {
        env_t* curenv = curenvs[lapic_get_id()];
     curenv->env_tf = *tf;
-    tf->tf_regs.reg_eax =
+       //Re enable interrupts. sysenter disables them.
+       enable_irq();
+       
+       curenv->env_tf.tf_regs.reg_eax =
            (intreg_t) syscall(curenv,
                               tf->tf_regs.reg_eax,
                               tf->tf_regs.reg_edx,
@@ -27,7 +33,7 @@ void syscall_wrapper(struct Trapframe *tf)
                               tf->tf_regs.reg_ebx,
                               tf->tf_regs.reg_edi,
                               0);
-    return;
+       env_run(curenv);
 }
 
 //Do absolutely nothing.  Used for profiling.
@@ -39,23 +45,110 @@ static void sys_null(void)
 //Write a buffer over the serial port
 static ssize_t sys_serial_write(env_t* e, const char *DANGEROUS buf, size_t len) 
 {
-       char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
-       for(int i =0; i<len; i++)
-               serial_send_byte(buf[i]);       
-       return (ssize_t)len;
+       #ifdef SERIAL_IO
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               for(int i =0; i<len; i++)
+                       serial_send_byte(buf[i]);       
+               return (ssize_t)len;
+       #else
+               return -E_INVAL;
+       #endif
 }
 
 //Read a buffer over the serial port
 static ssize_t sys_serial_read(env_t* e, char *DANGEROUS buf, size_t len) 
 {
-    char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
-       size_t bytes_read = 0;
-       int c;
-       while((c = serial_read_byte()) != -1) {
-               buf[bytes_read++] = (uint8_t)c;
-               if(bytes_read == len) break;
+       #ifdef SERIAL_IO
+           char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               size_t bytes_read = 0;
+               int c;
+               while((c = serial_read_byte()) != -1) {
+                       buf[bytes_read++] = (uint8_t)c;
+                       if(bytes_read == len) break;
+               }
+               return (ssize_t)bytes_read;
+       #else
+               return -E_INVAL;
+       #endif
+}
+
+// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
+{ 
+       extern int eth_up;
+       
+       if (eth_up) {
+               
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               int total_sent = 0;
+               int just_sent = 0;
+               int cur_packet_len = 0;
+               while (total_sent != len) {
+                       cur_packet_len = ((len - total_sent) > MAX_PACKET_DATA) ? MAX_PACKET_DATA : (len - total_sent);
+                       char* wrap_buffer = packet_wrap(buf + total_sent, cur_packet_len);
+                       just_sent = send_frame(wrap_buffer, cur_packet_len + PACKET_HEADER_SIZE);
+                       
+                       if (just_sent < 0)
+                               return 0; // This should be an error code of its own
+                               
+                       if (wrap_buffer)
+                               kfree(wrap_buffer);
+                               
+                       total_sent += cur_packet_len;
+               }
+               
+               return (ssize_t)len;
+               
        }
-       return (ssize_t)bytes_read;
+       else
+               return -E_INVAL;
+}
+/*
+static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
+{ 
+       extern int eth_up;
+       
+       if (eth_up) {
+               
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               
+               return(send_frame(buf, len));
+       }
+       return -E_INVAL;
+}
+*/
+
+
+// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf, size_t len) 
+{
+       extern int eth_up;
+       
+       if (eth_up) {
+               extern int packet_waiting;
+               extern int packet_buffer_size;
+               extern char* packet_buffer;
+               extern char* packet_buffer_orig;
+               extern int packet_buffer_pos;
+                       
+               if (packet_waiting == 0)
+                       return 0;
+                       
+               int read_len = ((packet_buffer_pos + len) > packet_buffer_size) ? packet_buffer_size - packet_buffer_pos : len;
+
+               memcpy(buf, packet_buffer + packet_buffer_pos, read_len);
+       
+               packet_buffer_pos = packet_buffer_pos + read_len;
+       
+               if (packet_buffer_pos == packet_buffer_size) {
+                       kfree(packet_buffer_orig);
+                       packet_waiting = 0;
+               }
+       
+               return read_len;
+       }
+       else
+               return -E_INVAL;
 }
 
 // Invalidate the cache of this core
@@ -69,17 +162,72 @@ static void sys_cache_invalidate(void)
 // address space.  It's just #defined to be some random 4MB chunk (which ought
 // to be boot_alloced or something).  Meant to grab exclusive access to cache
 // lines, to simulate doing something useful.
-static void sys_cache_buster(env_t* e, uint32_t num_writes, uint32_t val)
+static void sys_cache_buster(env_t* e, uint32_t num_writes, uint32_t num_pages,
+                             uint32_t flags)
 {
-       #define BUSTER_ADDR 0xd0000000
-       #define MAX_WRITES 1048576
+       #define BUSTER_ADDR             0xd0000000  // around 512 MB deep
+       #define MAX_WRITES              1048576*8
+       #define MAX_PAGES               32
+       #define INSERT_ADDR     (UINFO + 2*PGSIZE) // should be free for these tests
        uint32_t* buster = (uint32_t*)BUSTER_ADDR;
        static uint32_t buster_lock = 0;
+       uint64_t ticks;
+       page_t* a_page[MAX_PAGES];
+
+       /* Strided Accesses or Not (adjust to step by cachelines) */
+       uint32_t stride = 1;
+       if (flags & BUSTER_STRIDED) {
+               stride = 16;
+               num_writes *= 16;
+       }
+       
+       /* Shared Accesses or Not (adjust to use per-core regions)
+        * Careful, since this gives 8MB to each core, starting around 512MB.
+        * Also, doesn't separate memory for core 0 if it's an async call.
+        */
+       if (!(flags & BUSTER_SHARED))
+               buster = (uint32_t*)(BUSTER_ADDR + lapic_get_id() * 0x00800000);
+
+       /* Start the timer, if we're asked to print this info*/
+       if (flags & BUSTER_PRINT_TICKS)
+               ticks = start_timing();
 
-       spin_lock(&buster_lock);
-       for (int i = 0; i < MIN(num_writes, MAX_WRITES); i++)
-               buster[i] = val;
-       spin_unlock(&buster_lock);
+       /* Allocate num_pages (up to MAX_PAGES), to simulate doing some more
+        * realistic work.  Note we don't write to these pages, even if we pick
+        * unshared.  Mostly due to the inconvenience of having to match up the
+        * number of pages with the number of writes.  And it's unnecessary.
+        */
+       if (num_pages) {
+               spin_lock(&buster_lock);
+               for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
+                       page_alloc(&a_page[i]);
+                       page_insert(e->env_pgdir, a_page[i], (void*)INSERT_ADDR + PGSIZE*i,
+                                   PTE_U | PTE_W);
+               }
+               spin_unlock(&buster_lock);
+       }
+
+       if (flags & BUSTER_LOCKED)
+               spin_lock(&buster_lock);
+       for (int i = 0; i < MIN(num_writes, MAX_WRITES); i=i+stride)
+               buster[i] = 0xdeadbeef;
+       if (flags & BUSTER_LOCKED)
+               spin_unlock(&buster_lock);
+
+       if (num_pages) {
+               spin_lock(&buster_lock);
+               for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
+                       page_remove(e->env_pgdir, (void*)(INSERT_ADDR + PGSIZE * i));
+                       page_decref(a_page[i]);
+               }
+               spin_unlock(&buster_lock);
+       }
+
+       /* Print info */
+       if (flags & BUSTER_PRINT_TICKS) {
+               ticks = stop_timing(ticks);
+               printk("%llu,", ticks);
+       }
        return;
 }
 
@@ -170,11 +318,15 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                        return sys_serial_write(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(e, (char *DANGEROUS)a1, (size_t)a2);
+               case SYS_eth_write:
+                       return sys_eth_write(e, (char *DANGEROUS)a1, (size_t)a2);
+               case SYS_eth_read:
+                       return sys_eth_read(e, (char *DANGEROUS)a1, (size_t)a2);        
                case SYS_cache_invalidate:
                        sys_cache_invalidate();
                        return 0;
                case SYS_cache_buster:
-                       sys_cache_buster(e, a1, a2);
+                       sys_cache_buster(e, a1, a2, a3);
                        return 0;
                case SYS_cputs:
                        return sys_cputs(e, (char *DANGEROUS)a1, (size_t)a2);