Reworked the ethernet driver to use kmalloc properly. Fixed up kmalloc.
authorPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 18 Jun 2009 19:42:01 +0000 (12:42 -0700)
committerKevin Klues <klueska@eecs.berkeley.edu>
Wed, 1 Jul 2009 20:33:12 +0000 (13:33 -0700)
Fixed some issues with my kmalloc ethernet port. It now works and compiles correctly. I also fixed some
issues with pages in kmalloc. Made needed changes to newlib backend to support the new kmalloc.

include/rl8168.h
kern/src/env.c
kern/src/kmalloc.c
kern/src/rl8168.c
kern/src/smp.c
kern/src/syscall.c
user/parlib/src/newlib_backend.c

index ead2f17..9fc731a 100644 (file)
@@ -5,9 +5,9 @@
 #include <trap.h>
 #include <pmap.h>
 
-#define nic_debug(...)  cprintf(__VA_ARGS__)  
-#define nic_interrupt_debug(...)  cprintf(__VA_ARGS__)  
-#define nic_frame_debug(...)  cprintf(__VA_ARGS__)  
+#define nic_debug(...)  //cprintf(__VA_ARGS__)  
+#define nic_interrupt_debug(...) // cprintf(__VA_ARGS__)  
+#define nic_frame_debug(...)  //cprintf(__VA_ARGS__)  
 
 // Macro for formatting PCI Configuration Address queries
 #define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
 #define MAX_FRAME_SIZE         ETHERNET_ENCAP_SIZE + MTU       
        
 // Realtek Descriptor Related Sizing
-#define NUM_TX_DESCRIPTORS     1024 * 16
-#define NUM_RX_DESCRIPTORS     1024 * 16
+#define NUM_TX_DESCRIPTORS     1024
+#define NUM_RX_DESCRIPTORS     1024
 
 // !!!!!!!!! need to verify the 128byte nature of this field. Spec says it could be 32 for some chips.
 
index f0d09e5..34dd908 100644 (file)
@@ -554,8 +554,8 @@ env_destroy(env_t *e)
         * and not from where we left off the last time we called manager.  That
         * would require us to save some context (and a stack to work on) here.
         */
-       manager();
-       assert(0); // never get here
+       //manager();
+       //assert(0); // never get here
 
        // ugly, but for now just linearly search through all possible
        // environments for a runnable one.
index f832c31..0412a42 100644 (file)
@@ -10,7 +10,7 @@
 #include <pmap.h>
 #include <kmalloc.h>
 
-#define kmallocdebug(args...)  printk(args)
+#define kmallocdebug(args...)  //printk(args)
 
 static page_list_t pages_list; //List of physical pages used by kmalloc
 extern size_t naddrpage;
@@ -40,11 +40,24 @@ void* kmalloc(size_t size, int flags) {
        //If we couldn't find them, return NULL
        if( first == -1 )
                return NULL;
-       
+       /*
+       cprintf("Starting page check.\n");
+       for (int i = 0; i < naddrpage; i++) {
+               page_t* page = ppn2page(i);
+               if (((page->pp_link.le_next != NULL) && (page->pp_ref != 0)) || ((page->pp_link.le_next == NULL) && (page->pp_ref == 0))) {
+                       cprintf("Out of sync on page: %u\n", i);
+                       cprintf("-->pp_link: %p\n", page->pp_link);
+                       cprintf("-->pp_ref: %p\n", page->pp_ref);
+               }
+       }
+       cprintf("Ending page check.\n");
+       */
+               
        //Otherwise go ahead and allocate them to ourselves now
        for(int i=0; i<npages; i++) {
                page_t* page;
                page_alloc_specific(&page, first+i);
+               page->pp_ref++; // Kevin doesnt like this.
                page->num_cons_links = npages-i;
                LIST_INSERT_HEAD(&pages_list, page, pp_link);
                kmallocdebug("mallocing page: %u\n", first+i);
@@ -61,7 +74,7 @@ void kfree(void *addr) {
        for(int i=0; i<num_links; i++) {
                page_t* p = ppn2page((page2ppn(page) + i));
                LIST_REMOVE(p, pp_link);
-               page_free(p);
+               page_decref(p);
                kmallocdebug("freeing page: %d\n", page2ppn(p));
        }
 }
\ No newline at end of file
index 4713786..d3c0903 100644 (file)
@@ -14,6 +14,7 @@
 #include <string.h>
 #include <rl8168.h>
 #include <trap.h>
+#include <kmalloc.h>
 
 #include <pmap.h>
 
  *
  * This is an ongoing work in progress. Main thing is we need a kernel interface for PCI
  * devices and network devices, that we can hook into, instead of providing arbitary functions
- *
- * One of the big things we need to change is the page allocation. Right now we use a page as the max
- * size of a packet. This needs to change. We do it this way right now because that is really our only 
- * allocation mechnism. I don't want to write some sort of kalloc just for the net driver, so until
- * that exists, I'll use a page per packet buffer.
  * 
  * TODO: Remove hacky syscall hack stuff (once we get a real stack).
  * TODO: Jumbo frame support
@@ -221,22 +217,19 @@ void setup_descriptors() {
 void setup_descriptors() {
        
        nic_debug("-->Setting up tx/rx descriptors.\n");
-       
-       page_t *rx_des_page = NULL, *tx_des_page = NULL;
                        
        // Allocate room for the buffers. Include an extra ALIGN space.
        // Buffers need to be on 256 byte boundries.
-       rx_des_kva = kalloc(NUM_RX_DESCRIPTORS * sizeof(struct Descriptor) + RL_DES_ALIGN, NULL);
-       tx_des_kva = kalloc(NUM_TX_DESCRIPTORS * sizeof(struct Descriptor) + RL_DES_ALIGN, NULL);
+       // Note: Buffers are alligned by kmalloc automatically to powers of 2 less than the size requested
+       // We request more than 256, thus they are aligned on 256 byte boundries
+       rx_des_kva = kmalloc(NUM_RX_DESCRIPTORS * sizeof(struct Descriptor), 0);
+       tx_des_kva = kmalloc(NUM_TX_DESCRIPTORS * sizeof(struct Descriptor), 0);
        
        if (rx_des_kva == NULL) panic("Can't allocate page for RX Ring");
        if (tx_des_kva == NULL) panic("Can't allocate page for TX Ring");
        
-       rx_des_kva = ROUNDUP(rx_des_kva, RL_DES_ALIGN);
-       tx_des_kva = ROUNDUP(tx_des_kva, RL_DES_ALIGN);
-       
-       rx_des_pa = (struct Descriptor *)PADDR(rx_des_page);
-       tx_des_pa = (struct Descriptor *)PADDR(tx_des_page);
+       rx_des_pa = (struct Descriptor *)PADDR(rx_des_kva);
+       tx_des_pa = (struct Descriptor *)PADDR(tx_des_kva);
        
     for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
                set_rx_descriptor(i, TRUE); // Allocate memory for the descriptor
@@ -257,10 +250,10 @@ void set_rx_descriptor(uint32_t des_num, uint8_t reset_buffer) {
                rx_des_kva[des_num].command = rx_des_kva[des_num].command | DES_EOR_MASK;
        
        if (reset_buffer) {
-               char *rx_buffer = kalloc(RL_RX_MAX_BUFFER_SIZE + RL_BUF_ALIGN);
+               // Must be aligned on 8 byte boundries. Taken care of by kmalloc.
+               char *rx_buffer = kmalloc(RL_RX_MAX_BUFFER_SIZE, 0);
        
                if (rx_buffer == NULL) panic ("Can't allocate page for RX Buffer");
-               rx_buffer = ROUNDUP(rx_buffer, RL_BUF_ALIGN);
 
                rx_des_kva[des_num].low_buf = PADDR(rx_buffer);
                //.high_buf used if we do 64bit.
@@ -278,7 +271,7 @@ void set_tx_descriptor(uint32_t des_num) {
        if (des_num == (NUM_TX_DESCRIPTORS - 1))
                tx_des_kva[des_num].command = DES_EOR_MASK;     
                
-       char *tx_buffer = kalloc(RL_TX_MAX_BUFFER_SIZE);
+       char *tx_buffer = kmalloc(RL_TX_MAX_BUFFER_SIZE, 0);
 
        if (tx_buffer == NULL) panic ("Can't allocate page for TX Buffer");
 
@@ -451,13 +444,11 @@ void nic_handle_rx_packet() {
        uint32_t fragment_size = 0;
        uint32_t num_frags = 0;
        
-       char *rx_buffer = kalloc(MAX_FRAME_SIZE);
+       char *rx_buffer = kmalloc(MAX_FRAME_SIZE, 0);
        
        if (rx_buffer == NULL) panic ("Can't allocate page for incoming packet.");
        
        do {
-               num_frags++;
-               
                current_command =  rx_des_kva[rx_des_loop_cur].command;
                fragment_size = rx_des_kva[rx_des_loop_cur].command & DES_RX_SIZE_MASK;
                
@@ -472,6 +463,9 @@ void nic_handle_rx_packet() {
                        panic("RX Descriptor Ring out of sync.");
                }
                
+               num_frags++;
+               
+               
                // Make sure we own the current packet. Kernel ownership is denoted by a 0. Nic by a 1.
                if (current_command & DES_OWN_MASK) {
                        nic_frame_debug("-->ERR: Current RX descriptor not owned by kernel. Panic!");
@@ -511,8 +505,6 @@ void nic_handle_rx_packet() {
                
        } while (!(current_command & DES_LS_MASK));
        
-
-       
        // Hack for UDP syscall hack. 
        // This is a quick hack to let us deal with where to put packets coming in. This is not concurrency friendly
        // In the event that we get 2 incoming frames for our syscall test (shouldnt happen)
@@ -540,6 +532,8 @@ void nic_handle_rx_packet() {
                
                process_frame(rx_buffer, frame_size, current_command);
                
+               rx_des_cur = rx_des_loop_cur;
+               
                return;
        }
        
@@ -547,6 +541,8 @@ void nic_handle_rx_packet() {
        
        // Chew on the frame data. Command bits should be the same for all frags.
        process_frame(rx_buffer, frame_size, current_command);
+
+       rx_des_cur = rx_des_loop_cur;
        
        kfree(rx_buffer);
        
@@ -617,7 +613,7 @@ void process_frame(char *frame_buffer, uint32_t frame_size, uint32_t command) {
 // This seems like the stacks responsibility. Leave this for now. may in future
 // Remove the max size cap and generate multiple packets.
 int send_frame(const char *data, size_t len) {
-       
+
        if (data == NULL)
                return -1;
        if (len == 0)
@@ -633,7 +629,7 @@ int send_frame(const char *data, size_t len) {
                return -1;
        }
        
-       memcpy((char*)tx_des_kva[tx_des_cur].low_buf, data, len);
+       memcpy(KADDR(tx_des_kva[tx_des_cur].low_buf), data, len);
 
        tx_des_kva[tx_des_cur].command = tx_des_kva[tx_des_cur].command | len | DES_OWN_MASK | DES_FS_MASK | DES_LS_MASK;
 
@@ -706,7 +702,7 @@ const char *packet_wrap(const char* data, size_t len) {
                return NULL;
        }
        
-       char* wrap_buffer = kalloc(MAX_PACKET_SIZE);
+       char* wrap_buffer = kmalloc(MAX_PACKET_SIZE, 0);
        
        if (wrap_buffer == NULL) {
                nic_frame_debug("Can't allocate page for packet wrapping");
index 0932120..91c4cee 100644 (file)
@@ -122,6 +122,8 @@ void smp_boot(void)
        pagetable_remove(boot_pgdir, (void*)trampoline_pg);
        // Dealloc the temp shared stack
        page_decref(smp_stack);
+       smp_stack->pp_ref++;
+       
 
        // Set up the generic remote function call facility
        init_smp_call_function();
@@ -159,6 +161,7 @@ uint32_t smp_main(void)
        if (page_alloc(&my_stack))
                panic("Unable to alloc a per-core stack!");
        my_stack->pp_ref++;
+
        memset(page2kva(my_stack), 0, PGSIZE);
 
        // Set up a gdt / gdt_pd for this core, stored at the top of the stack
index cb852f6..99cc333 100644 (file)
@@ -17,6 +17,7 @@
 #include <pmap.h>
 #include <trap.h>
 #include <syscall.h>
+#include <kmalloc.h>
 
 void syscall_wrapper(struct Trapframe *tf)
 {
index 3ac487e..784d1db 100644 (file)
@@ -14,7 +14,7 @@
 #include <stdio.h>
 #include <debug.h>
 
-#define debug_in_out(...) // debug(__VA_ARGS__)  
+#define debug_in_out(...)  //debug(__VA_ARGS__)  
 #define debug_write_check(fmt, ...) // debug(fmt, __VA_ARGS__)
 
 /* environ