Merge branch 'master' into net-dev
authorKevin Klues <klueska@eecs.berkeley.edu>
Sat, 1 Aug 2009 18:41:47 +0000 (11:41 -0700)
committerKevin Klues <klueska@eecs.berkeley.edu>
Sat, 1 Aug 2009 18:41:47 +0000 (11:41 -0700)
Conflicts:
.gitignore
kern/boot
kern/include/ros/syscall.h
kern/src/Makefrag
kern/src/init.c
kern/src/smp.c
kern/src/syscall.c
kern/src/testing.c
user/parlib/inc/parlib.h
user/parlib/src/newlib_backend.c
user/parlib/src/syscall.c

21 files changed:
1  2 
kern/arch/i386/apic.c
kern/arch/i386/apic.h
kern/arch/i386/ioapic.h
kern/arch/i386/trap.c
kern/include/mptables.h
kern/include/pci.h
kern/include/rl8168.h
kern/include/ros/syscall.h
kern/include/testing.h
kern/src/Makefrag
kern/src/env.c
kern/src/init.c
kern/src/ioapic.c
kern/src/monitor.c
kern/src/smp.c
kern/src/syscall.c
kern/src/testing.c
user/apps/parlib/Makefrag
user/parlib/inc/parlib.h
user/parlib/src/newlib_backend.c
user/parlib/src/syscall.c

index 0000000,ee4817e..9ba0f50
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,220 +1,219 @@@
 -
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
+ #include <arch/mmu.h>
+ #include <arch/x86.h>
+ #include <arch/arch.h>
+ #include <arch/apic.h>
+ #include <ros/timer.h>
+ #include <assert.h>
+ system_timing_t system_timing = {0, 0, 0xffff, 0};
+ /*
+  * Remaps the Programmable Interrupt Controller to use IRQs 32-47
+  * http://wiki.osdev.org/PIC
+  * Not 100% on this stuff, after looking over 
+  * http://bochs.sourceforge.net/techspec/PORTS.LST  The cascading and other 
+  * stuff might need to be in one command, and after that all we are doing
+  * is toggling masks.
+  */
+ void pic_remap() 
+ {
+       // start initialization
+       outb(PIC1_CMD, 0x11);
+       outb(PIC2_CMD, 0x11);
+       // set new offsets
+       outb(PIC1_DATA, PIC1_OFFSET);
+       outb(PIC2_DATA, PIC2_OFFSET);
+       // set up cascading
+       outb(PIC1_DATA, 0x04);
+       outb(PIC2_DATA, 0x02);
+       // other stuff (put in 8086/88 mode, or whatever)
+       outb(PIC1_DATA, 0x01);
+       outb(PIC2_DATA, 0x01);
+       // set masks, defaulting to all masked for now
+       outb(PIC1_DATA, 0xff);
+       outb(PIC2_DATA, 0xff);
+ }
+ void pic_mask_irq(uint8_t irq)
+ {
+       if (irq > 7)
+               outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8)));
+       else
+               outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq));
+ }
+ void pic_unmask_irq(uint8_t irq)
+ {
+       if (irq > 7) {
+               outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8)));
+               outb(PIC1_DATA, inb(PIC1_DATA) & 0xfb); // make sure irq2 is unmasked
+       } else
+               outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
+ }
+ /*
+  * Sets the LAPIC timer to go off after a certain number of ticks.  The primary
+  * clock freq is actually the bus clock, which we figure out during timer_init
+  * Unmasking is implied.  Ref SDM, 3A, 9.6.4
+  */
+ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div)
+ {
+       // clears bottom bit and then set divider
+       write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) |
+                     (div & 0xf));
+       // set LVT with interrupt handling information
+       write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17));
+       write_mmreg32(LAPIC_TIMER_INIT, ticks);
+       // For debugging when we expand this
+       //cprintf("LAPIC LVT Timer: 0x%08x\n", read_mmreg32(LAPIC_LVT_TIMER));
+       //cprintf("LAPIC Init Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_INIT));
+       //cprintf("LAPIC Current Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_CURRENT));
+ }
+ void lapic_set_timer(uint32_t usec, bool periodic)
+ {
+       // divide the bus clock by 128, which is the max.
+       uint32_t ticks = (usec * system_timing.bus_freq / 128) / 1000000;
+       __lapic_set_timer(ticks, LAPIC_TIMER_DEFAULT_VECTOR, periodic,
+                         LAPIC_TIMER_DEFAULT_DIVISOR);
+ }
+ uint32_t lapic_get_default_id(void)
+ {
+       uint32_t ebx;
+       cpuid(1, 0, &ebx, 0, 0);
+       // p6 family only uses 4 bits here, and 0xf is reserved for the IOAPIC
+       return (ebx & 0xFF000000) >> 24;
+ }
+ // timer init calibrates both tsc timer and lapic timer using PIT
+ void timer_init(void){
+       uint64_t tscval[2];
+       long timercount[2];
+       pit_set_timer(0xffff, TIMER_RATEGEN);
+       // assume tsc exist
+       tscval[0] = read_tsc();
+       udelay_pit(1000000);
+       tscval[1] = read_tsc();
+       system_timing.tsc_freq = tscval[1] - tscval[0];
+       
+       cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
+       __lapic_set_timer(0xffffffff, LAPIC_TIMER_DEFAULT_VECTOR, FALSE,
+                         LAPIC_TIMER_DEFAULT_DIVISOR);
+       // Mask the LAPIC Timer, so we never receive this interrupt (minor race)
+       mask_lapic_lvt(LAPIC_LVT_TIMER);
+       timercount[0] = read_mmreg32(LAPIC_TIMER_CURRENT);
+       udelay_pit(1000000);
+       timercount[1] = read_mmreg32(LAPIC_TIMER_CURRENT);
+       system_timing.bus_freq = (timercount[0] - timercount[1])*128;
+               
+       cprintf("Bus Frequency: %llu\n", system_timing.bus_freq);
+ }
+ void pit_set_timer(uint32_t divisor, uint32_t mode)
+ {
+       if (divisor & 0xffff0000)
+               warn("Divisor too large!");
+       mode = TIMER_SEL0|TIMER_16BIT|mode;
+       outb(TIMER_MODE, mode); 
+       outb(TIMER_CNTR0, divisor & 0xff);
+       outb(TIMER_CNTR0, (divisor >> 8) );
+       system_timing.pit_mode = mode;
+       system_timing.pit_divisor = divisor;
+       // cprintf("timer mode set to %d, divisor %d\n",mode, divisor);
+ }
+ static int getpit()
+ {
+     int high, low;
+       // TODO: need a lock to protect access to PIT
+     /* Select timer0 and latch counter value. */
+     outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+     
+     low = inb(TIMER_CNTR0);
+     high = inb(TIMER_CNTR0);
+     return ((high << 8) | low);
+ }
+ // forces cpu to relax for usec miliseconds
+ void udelay(uint64_t usec)
+ {
+       #if !defined(__BOCHS__)
+       if (system_timing.tsc_freq != 0)
+       {
+               uint64_t start, end, now;
+               start = read_tsc();
+         end = start + (system_timing.tsc_freq * usec) / 1000000;
+         //cprintf("start %llu, end %llu\n", start, end);
+               if (end == 0) cprintf("This is terribly wrong \n");
+               do {
+             cpu_relax();
+             now = read_tsc();
+                       //cprintf("now %llu\n", now);
+               } while (now < end || (now > start && end < start));
+         return;
+       } else
+       #endif
+       {
+               udelay_pit(usec);
+       }
+ }
+ void udelay_pit(uint64_t usec)
+ {
+       
+       int64_t delta, prev_tick, tick, ticks_left;
+       prev_tick = getpit();
+       /*
+        * Calculate (n * (i8254_freq / 1e6)) without using floating point
+        * and without any avoidable overflows.
+        */
+       if (usec <= 0)
+               ticks_left = 0;
+       // some optimization from bsd code
+       else if (usec < 256)
+               /*
+                * Use fixed point to avoid a slow division by 1000000.
+                * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
+                * 2^15 is the first power of 2 that gives exact results
+                * for n between 0 and 256.
+                */
+               ticks_left = ((uint64_t)usec * 39099 + (1 << 15) - 1) >> 15;
+       else
+               // round up the ticks left
+               ticks_left = ((uint64_t)usec * (long long)PIT_FREQ+ 999999)
+                            / 1000000; 
+       while (ticks_left > 0) {
+               tick = getpit();
+               delta = prev_tick - tick;
+               prev_tick = tick;
+               if (delta < 0) {
+                       // counter looped around during the delta time period
+                       delta += system_timing.pit_divisor; // maximum count 
+                       if (delta < 0)
+                               delta = 0;
+               }
+               ticks_left -= delta;
+       }
+ }
+ uint64_t gettimer(void)
+ {
+       return read_tsc();      
+ }
+ uint64_t getfreq(void)
+ {
+       return system_timing.tsc_freq;
+ }
index 0000000,1df0369..6d7c087
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,229 +1,227 @@@
 -// IOAPIC
 -#define IOAPIC_BASE                                   0xfec00000 // this is the default, can be changed
 -
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
+ #ifndef ROS_KERN_APIC_H
+ #define ROS_KERN_APIC_H
+ /* 
+  * Functions and definitions for dealing with the APIC and PIC, specific to
+  * Intel.  Does not handle an x2APIC.
+  */
+ #include <arch/mmu.h>
+ #include <arch/x86.h>
++#include <arch/ioapic.h>
+ // PIC
+ #define PIC1_CMD                                      0x20
+ #define PIC1_DATA                                     0x21
+ #define PIC2_CMD                                      0xA0
+ #define PIC2_DATA                                     0xA1
+ // These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
+ #define PIC1_OFFSET                                   0x20
+ #define PIC2_OFFSET                                   0x28
+ #define PIC_EOI                                               0x20
+ // Local APIC
+ #define LAPIC_BASE                                    0xfee00000 // this is the default, can be changed
+ #define LAPIC_EOI                                     (LAPIC_BASE + 0x0b0)
+ #define LAPIC_SPURIOUS                                (LAPIC_BASE + 0x0f0)
+ #define LAPIC_VERSION                         (LAPIC_BASE + 0x030)
+ #define LAPIC_ERROR                                   (LAPIC_BASE + 0x280)
+ #define LAPIC_ID                                      (LAPIC_BASE + 0x020)
+ #define LAPIC_LOGICAL_ID                      (LAPIC_BASE + 0x0d0)
+ // LAPIC Local Vector Table
+ #define LAPIC_LVT_TIMER                               (LAPIC_BASE + 0x320)
+ #define LAPIC_LVT_LINT0                               (LAPIC_BASE + 0x350)
+ #define LAPIC_LVT_LINT1                               (LAPIC_BASE + 0x360)
+ #define LAPIC_LVT_ERROR                               (LAPIC_BASE + 0x370)
+ #define LAPIC_LVT_PERFMON                     (LAPIC_BASE + 0x340)
+ #define LAPIC_LVT_THERMAL                     (LAPIC_BASE + 0x330)
+ #define LAPIC_LVT_MASK                                0x00010000
+ // LAPIC Timer
+ #define LAPIC_TIMER_INIT                      (LAPIC_BASE + 0x380)
+ #define LAPIC_TIMER_CURRENT                   (LAPIC_BASE + 0x390)
+ #define LAPIC_TIMER_DIVIDE                    (LAPIC_BASE + 0x3e0)
+ #define LAPIC_TIMER_DEFAULT_VECTOR    0xeb
+ #define LAPIC_TIMER_DEFAULT_DIVISOR   0xa // This is 128.  Ref SDM 3.a 9.6.4
+ // IPI Interrupt Command Register
+ #define LAPIC_IPI_ICR_LOWER                   (LAPIC_BASE + 0x300)
+ #define LAPIC_IPI_ICR_UPPER                   (LAPIC_BASE + 0x310)
+ // PIT (Programmable Interval Timer)
+ #define       TIMER_REG_CNTR0 0       /* timer 0 counter port */
+ #define       TIMER_REG_CNTR1 1       /* timer 1 counter port */
+ #define       TIMER_REG_CNTR2 2       /* timer 2 counter port */
+ #define       TIMER_REG_MODE  3       /* timer mode port */
+ #define       TIMER_SEL0      0x00    /* select counter 0 */
+ #define       TIMER_SEL1      0x40    /* select counter 1 */
+ #define       TIMER_SEL2      0x80    /* select counter 2 */
+ #define       TIMER_INTTC     0x00    /* mode 0, intr on terminal cnt */
+ #define       TIMER_ONESHOT   0x02    /* mode 1, one shot */
+ #define       TIMER_RATEGEN   0x04    /* mode 2, rate generator */
+ #define       TIMER_SQWAVE    0x06    /* mode 3, square wave */
+ #define       TIMER_SWSTROBE  0x08    /* mode 4, s/w triggered strobe */
+ #define       TIMER_HWSTROBE  0x0a    /* mode 5, h/w triggered strobe */
+ #define       TIMER_LATCH     0x00    /* latch counter for reading */
+ #define       TIMER_LSB       0x10    /* r/w counter LSB */
+ #define       TIMER_MSB       0x20    /* r/w counter MSB */
+ #define       TIMER_16BIT     0x30    /* r/w counter 16 bits, LSB first */
+ #define       TIMER_BCD       0x01    /* count in BCD */
+ #define PIT_FREQ                                      1193182
+ #define IO_TIMER1   0x40        /* 8253 Timer #1 */
+ #define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
+ #define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
+ #define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
+ #define TIMER_MODE  (IO_TIMER1 + TIMER_REG_MODE)
+ typedef struct system_timing {
+       uint64_t tsc_freq;
+       uint64_t bus_freq;
+       uint16_t pit_divisor;
+       uint8_t pit_mode;
+ } system_timing_t;
+ extern system_timing_t system_timing;
+ void pic_remap(void);
+ void pic_mask_irq(uint8_t irq);
+ void pic_unmask_irq(uint8_t irq);
+ void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
+ void lapic_set_timer(uint32_t usec, bool periodic);
+ uint32_t lapic_get_default_id(void);
+ // PIT related
+ void pit_set_timer(uint32_t freq, uint32_t mode);
+ void timer_init(void);
+ void udelay(uint64_t usec);
+ void udelay_pit(uint64_t usec);
+ // TODO: right now timer defaults to TSC
+ uint64_t gettimer(void);
+ uint64_t inline getfreq(void);
+ static inline void pic_send_eoi(uint32_t irq);
+ static inline void lapic_send_eoi(void);
+ static inline uint32_t lapic_get_version(void);
+ static inline uint32_t lapic_get_error(void);
+ static inline uint32_t lapic_get_id(void);
+ static inline uint8_t lapic_get_logid(void);
+ static inline void lapic_set_logid(uint8_t id);
+ static inline void lapic_disable(void);
+ static inline void lapic_enable(void);
+ static inline void lapic_wait_to_send(void);
+ static inline void send_init_ipi(void);
+ static inline void send_startup_ipi(uint8_t vector);
+ static inline void send_self_ipi(uint8_t vector);
+ static inline void send_broadcast_ipi(uint8_t vector);
+ static inline void send_all_others_ipi(uint8_t vector);
+ static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector);
+ #define mask_lapic_lvt(entry) \
+       write_mmreg32(entry, read_mmreg32(entry) | LAPIC_LVT_MASK)
+ #define unmask_lapic_lvt(entry) \
+       write_mmreg32(entry, read_mmreg32(entry) & ~LAPIC_LVT_MASK)
+ static inline void pic_send_eoi(uint32_t irq)
+ {
+       // all irqs beyond the first seven need to be chained to the slave
+       if (irq > 7)
+               outb(PIC2_CMD, PIC_EOI);
+       outb(PIC1_CMD, PIC_EOI);
+ }
+ static inline void lapic_send_eoi(void)
+ {
+       write_mmreg32(LAPIC_EOI, 0);
+ }
+ static inline uint32_t lapic_get_version(void)
+ {
+       return read_mmreg32(LAPIC_VERSION);     
+ }
+ static inline uint32_t lapic_get_error(void)
+ {
+       write_mmreg32(LAPIC_ERROR, 0xdeadbeef);
+       return read_mmreg32(LAPIC_ERROR);
+ }
+ static inline uint32_t lapic_get_id(void)
+ {
+       return read_mmreg32(LAPIC_ID) >> 24;
+ }
+ static inline uint8_t lapic_get_logid(void)
+ {
+       return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
+ }
+ static inline void lapic_set_logid(uint8_t id)
+ {
+       write_mmreg32(LAPIC_LOGICAL_ID, id << 24);
+ }
+ /* There are a couple ways to do it.  The MSR route doesn't seem to work
+  * in KVM.  It's also a somewhat permanent thing
+  */
+ static inline void lapic_disable(void)
+ {
+       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) & 0xffffefff);
+       //write_msr(IA32_APIC_BASE, read_msr(IA32_APIC_BASE) & ~MSR_APIC_ENABLE);
+ }
+ /* Spins until previous IPIs are delivered.  Not sure if we want it inlined
+  * Also not sure when we really need to do this. 
+  */
+ static inline void lapic_wait_to_send(void)
+ {
+       static inline void cpu_relax(void);
+       while(read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
+               cpu_relax();
+ }
+ static inline void lapic_enable(void)
+ {
+       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) | 0x00000100);
+ }
+ static inline void send_init_ipi(void)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4500);
+ }
+ static inline void send_startup_ipi(uint8_t vector)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4600 | vector);
+ }
+ static inline void send_self_ipi(uint8_t vector)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00044000 | vector);
+ }
+ static inline void send_broadcast_ipi(uint8_t vector)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00084000 | vector);
+ }
+ static inline void send_all_others_ipi(uint8_t vector)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4000 | vector);
+ }
+ static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector)
+ {
+       write_mmreg32(LAPIC_IPI_ICR_UPPER, dest << 24);
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004000 | (logical_mode << 11) | vector);
+ }
+ /* To change the LAPIC Base (not recommended):
+       msr_val = read_msr(IA32_APIC_BASE);
+       msr_val = msr_val & ~MSR_APIC_BASE_ADDRESS | 0xfaa00000;
+       write_msr(IA32_APIC_BASE, msr_val);
+ */
+ #endif /* ROS_KERN_APIC_H */
index 0000000,0000000..5033041
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,35 @@@
++/*
++ * Copyright (c) 2009 The Regents of the University of California
++ * See LICENSE for details.
++ */
++
++#ifndef ROS_KERN_IOAPIC_H
++#define ROS_KERN_IOAPIC_H
++
++#include <arch/mmu.h>
++#include <arch/x86.h>
++#include <arch/apic.h>
++
++// IOAPIC
++// Paul wants this next constant to go away. its only still used
++//  for the top of memory calculations
++#define IOAPIC_BASE                                   0xfec00000 // this is the default, can be changed
++
++// These are things like level sensitive, edge triggered, fixed, nmi, extint, etc
++// I should elaborate upon these.
++#define IOAPIC_PCI_FLAGS                      0xa0
++#define IOAPIC_ISA_FLAGS                      0x00
++#define IOAPIC_PIC_FLAGS                      0x07 // Not used. 
++#define IOAPIC_BROKEN_PCI_FLAGS               IOAPIC_ISA_FLAGS // No idea if this is correct, or it should be pci.
++
++#define IOAPIC_MAX_ID                         256
++
++#define IOAPIC_UNROUTE_LOW                    0x00000000
++#define IOAPIC_UNROUTE_HIGH                   0x00000001
++
++
++void ioapic_init();
++void ioapic_route_irq(uint8_t irq, uint8_t dest);
++void ioapic_unroute_irq(uint8_t irq);
++
++#endif /* ROS_KERN_IOAPIC_H */
index 0000000,498022f..0efd4ed
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,361 +1,367 @@@
 -      //      cprintf("Incoming IRQ, ISR: %d on core %d\n", tf->tf_trapno, lapic_get_id());
+ #ifdef __DEPUTY__
+ #pragma noasync
+ #endif
+ #include <arch/mmu.h>
+ #include <arch/x86.h>
+ #include <arch/arch.h>
+ #include <arch/console.h>
+ #include <arch/apic.h>
+ #include <smp.h>
+ #include <assert.h>
+ #include <pmap.h>
+ #include <trap.h>
+ #include <monitor.h>
+ #include <env.h>
+ #include <syscall.h>
+ taskstate_t ts;
+ /* Interrupt descriptor table.  (Must be built at run time because
+  * shifted function addresses can't be represented in relocation records.)
+  */
+ // Aligned on an 8 byte boundary (SDM V3A 5-13)
+ gatedesc_t __attribute__ ((aligned (8))) idt[256] = { { 0 } };
+ pseudodesc_t idt_pd = {
+       sizeof(idt) - 1, (uint32_t) idt
+ };
+ /* global handler table, used by core0 (for now).  allows the registration
+  * of functions to be called when servicing an interrupt.  other cores
+  * can set up their own later.
+  */
+ handler_t interrupt_handlers[256];
+ static const char *NTS (IN_HANDLER trapname)(int trapno)
+ {
+     // zra: excnames is NORACE because Ivy doesn't trust const
+       static const char *NT const (NORACE excnames)[] = {
+               "Divide error",
+               "Debug",
+               "Non-Maskable Interrupt",
+               "Breakpoint",
+               "Overflow",
+               "BOUND Range Exceeded",
+               "Invalid Opcode",
+               "Device Not Available",
+               "Double Fault",
+               "Coprocessor Segment Overrun",
+               "Invalid TSS",
+               "Segment Not Present",
+               "Stack Fault",
+               "General Protection",
+               "Page Fault",
+               "(unknown trap)",
+               "x87 FPU Floating-Point Error",
+               "Alignment Check",
+               "Machine-Check",
+               "SIMD Floating-Point Exception"
+       };
+       if (trapno < sizeof(excnames)/sizeof(excnames[0]))
+               return excnames[trapno];
+       if (trapno == T_SYSCALL)
+               return "System call";
+       return "(unknown trap)";
+ }
+ void
+ idt_init(void)
+ {
+       extern segdesc_t gdt[];
+       // This table is made in trapentry.S by each macro in that file.
+       // It is layed out such that the ith entry is the ith's traphandler's
+       // (uint32_t) trap addr, then (uint32_t) trap number
+       struct trapinfo { uint32_t trapaddr; uint32_t trapnumber; };
+       extern struct trapinfo (BND(__this,trap_tbl_end) trap_tbl)[];
+       extern struct trapinfo (SNT trap_tbl_end)[];
+       int i, trap_tbl_size = trap_tbl_end - trap_tbl;
+       extern void ISR_default(void);
+       // set all to default, to catch everything
+       for(i = 0; i < 256; i++)
+               SETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
+       // set all entries that have real trap handlers
+       // we need to stop short of the last one, since the last is the default
+       // handler with a fake interrupt number (500) that is out of bounds of
+       // the idt[]
+       // if we set these to trap gates, be sure to handle the IRQs separately
+       // and we might need to break our pretty tables
+       for(i = 0; i < trap_tbl_size - 1; i++)
+               SETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
+       // turn on syscall handling and other user-accessible ints
+       // DPL 3 means this can be triggered by the int instruction
+       // STS_TG32 sets the IDT type to a Trap Gate (interrupts enabled)
+       idt[T_SYSCALL].gd_dpl = 3;
+       idt[T_SYSCALL].gd_type = STS_TG32;
+       idt[T_BRKPT].gd_dpl = 3;
+       // Setup a TSS so that we get the right stack
+       // when we trap to the kernel.
+       ts.ts_esp0 = KSTACKTOP;
+       ts.ts_ss0 = GD_KD;
+       // Initialize the TSS field of the gdt.
+       gdt[GD_TSS >> 3] = SEG16(STS_T32A, (uint32_t) (&ts),
+                                       sizeof(taskstate_t), 0);
+       gdt[GD_TSS >> 3].sd_s = 0;
+       // Load the TSS
+       ltr(GD_TSS);
+       // Load the IDT
+       asm volatile("lidt idt_pd");
+       // This will go away when we start using the IOAPIC properly
+       pic_remap();
+       // set LINT0 to receive ExtINTs (KVM's default).  At reset they are 0x1000.
+       write_mmreg32(LAPIC_LVT_LINT0, 0x700);
+       // mask it to shut it up for now
+       mask_lapic_lvt(LAPIC_LVT_LINT0);
+       // and turn it on
+       lapic_enable();
+ }
+ void
+ (IN_HANDLER print_regs)(push_regs_t *regs)
+ {
+       cprintf("  edi  0x%08x\n", regs->reg_edi);
+       cprintf("  esi  0x%08x\n", regs->reg_esi);
+       cprintf("  ebp  0x%08x\n", regs->reg_ebp);
+       cprintf("  oesp 0x%08x\n", regs->reg_oesp);
+       cprintf("  ebx  0x%08x\n", regs->reg_ebx);
+       cprintf("  edx  0x%08x\n", regs->reg_edx);
+       cprintf("  ecx  0x%08x\n", regs->reg_ecx);
+       cprintf("  eax  0x%08x\n", regs->reg_eax);
+ }
+ void
+ (IN_HANDLER print_trapframe)(trapframe_t *tf)
+ {
+       cprintf("TRAP frame at %p on core %d\n", tf, lapic_get_id());
+       print_regs(&tf->tf_regs);
+       cprintf("  es   0x----%04x\n", tf->tf_es);
+       cprintf("  ds   0x----%04x\n", tf->tf_ds);
+       cprintf("  trap 0x%08x %s\n", tf->tf_trapno, trapname(tf->tf_trapno));
+       cprintf("  err  0x%08x\n", tf->tf_err);
+       cprintf("  eip  0x%08x\n", tf->tf_eip);
+       cprintf("  cs   0x----%04x\n", tf->tf_cs);
+       cprintf("  flag 0x%08x\n", tf->tf_eflags);
+       cprintf("  esp  0x%08x\n", tf->tf_esp);
+       cprintf("  ss   0x----%04x\n", tf->tf_ss);
+ }
+ static void
+ (IN_HANDLER trap_dispatch)(trapframe_t *tf)
+ {
+       env_t* curenv = curenvs[core_id()];
+       // Handle processor exceptions.
+       switch(tf->tf_trapno) {
+               case T_BRKPT:
+                       while (1)
+                               monitor(tf);
+                       // never get to this
+                       assert(0);
+               case T_PGFLT:
+                       page_fault_handler(tf);
+                       break;
+               case T_SYSCALL:
+                       // check for userspace, for now
+                       assert(tf->tf_cs != GD_KT);
+                       tf->tf_regs.reg_eax =
+                               syscall(curenv, tf->tf_regs.reg_eax, tf->tf_regs.reg_edx,
+                                       tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx,
+                                       tf->tf_regs.reg_edi, tf->tf_regs.reg_esi);
+                       env_run(curenv);
+                       break;
+               default:
+                       // Unexpected trap: The user process or the kernel has a bug.
+                       print_trapframe(tf);
+                       if (tf->tf_cs == GD_KT)
+                               panic("Damn Damn!  Unhandled trap in the kernel!");
+                       else {
+                               warn("Unexpected trap from userspace");
+                               env_destroy(curenv);
+                               return;
+                       }
+       }
+       return;
+ }
+ void
+ (IN_HANDLER env_push_ancillary_state)(env_t* e)
+ {
+       // Here's where you'll save FP/MMX/XMM regs
+ }
+ void
+ (IN_HANDLER env_pop_ancillary_state)(env_t* e)
+ {
+       // Here's where you'll restore FP/MMX/XMM regs
+ }
+ void
+ (IN_HANDLER trap)(trapframe_t *tf)
+ {
+       //cprintf("Incoming TRAP frame at %p\n", tf);
+       env_t* curenv = curenvs[lapic_get_id()];
+       env_push_ancillary_state(curenv);
+       if ((tf->tf_cs & ~3) != GD_UT && (tf->tf_cs & ~3) != GD_KT) {
+               print_trapframe(tf);
+               panic("Trapframe with invalid CS!");
+       }
+       if ((tf->tf_cs & 3) == 3) {
+               // Trapped from user mode.
+               // TODO: this will change when an env has more than one context
+               // Copy trap frame (which is currently on the stack)
+               // into 'curenv->env_tf', so that running the environment
+               // will restart at the trap point.
+               assert(curenv);
+               curenv->env_tf = *tf;
+               // The trapframe on the stack should be ignored from here on.
+               tf = &curenv->env_tf;
+       }
+       // Dispatch based on what type of trap occurred
+       trap_dispatch(tf);
+       // should this be if == 3?  Sort out later when we handle traps.
+       // so far we never get here
+       assert(0);
+         // Return to the current environment, which should be runnable.
+         assert(curenv && curenv->env_status == ENV_RUNNABLE);
+         env_run(curenv);
+ }
+ void
+ (IN_HANDLER irq_handler)(trapframe_t *tf)
+ {
+       //if (lapic_get_id())
 -              pic_send_eoi(tf->tf_trapno - PIC1_OFFSET);
++      //      cprintf("Incoming IRQ, ISR: %d on core %d\n", tf->tf_trapno, lapic_get_id());           
+       // merge this with alltraps?  other than the EOI... or do the same in all traps
+       extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
+       // determine the interrupt handler table to use.  for now, pick the global
+       handler_t* handler_tbl = interrupt_handlers;
+       if (handler_tbl[tf->tf_trapno].isr != 0)
+               handler_tbl[tf->tf_trapno].isr(tf, handler_tbl[tf->tf_trapno].data);
+       // if we're a general purpose IPI function call, down the cpu_list
+       if ((0xf0 <= tf->tf_trapno) && (tf->tf_trapno < 0xf0 +NUM_HANDLER_WRAPPERS))
+               down_checklist(handler_wrappers[tf->tf_trapno & 0x0f].cpu_list);
+       // Send EOI.  might want to do this in assembly, and possibly earlier
+       // This is set up to work with an old PIC for now
+       // Convention is that all IRQs between 32 and 47 are for the PIC.
+       // All others are LAPIC (timer, IPIs, perf, non-ExtINT LINTS, etc)
+       // For now, only 235-255 are available
+       assert(tf->tf_trapno >= 32); // slows us down, but we should never have this
++      
++      lapic_send_eoi();
++      
++/*    Old PIC relatd code. Should be gone for good, but leaving it just incase.
+       if (tf->tf_trapno < 48)
++              //pic_send_eoi(tf->tf_trapno - PIC1_OFFSET);
++              ioapic_send_eoi(tf->tf_trapno); // Quick hack. Fix.
+       else
+               lapic_send_eoi();
++*/
+ }
+ void
+ register_interrupt_handler(handler_t table[], uint8_t int_num, isr_t handler,
+                            void* data)
+ {
+       table[int_num].isr = handler;
+       table[int_num].data = data;
+ }
+ void
+ page_fault_handler(trapframe_t *tf)
+ {
+       uint32_t fault_va;
+       // Read processor's CR2 register to find the faulting address
+       fault_va = rcr2();
+       // Handle kernel-mode page faults.
+       // TODO - one day, we'll want to handle this.
+       if ((tf->tf_cs & 3) == 0) {
+               print_trapframe(tf);
+               panic("Page Fault in the Kernel at 0x%08x!", fault_va);
+       }
+       // We've already handled kernel-mode exceptions, so if we get here,
+       // the page fault happened in user mode.
+       // Call the environment's page fault upcall, if one exists.  Set up a
+       // page fault stack frame on the user exception stack (below
+       // UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
+       //
+       // The page fault upcall might cause another page fault, in which case
+       // we branch to the page fault upcall recursively, pushing another
+       // page fault stack frame on top of the user exception stack.
+       //
+       // The trap handler needs one word of scratch space at the top of the
+       // trap-time stack in order to return.  In the non-recursive case, we
+       // don't have to worry about this because the top of the regular user
+       // stack is free.  In the recursive case, this means we have to leave
+       // an extra word between the current top of the exception stack and
+       // the new stack frame because the exception stack _is_ the trap-time
+       // stack.
+       //
+       // If there's no page fault upcall, the environment didn't allocate a
+       // page for its exception stack, or the exception stack overflows,
+       // then destroy the environment that caused the fault.
+       //
+       // Hints:
+       //   user_mem_assert() and env_run() are useful here.
+       //   To change what the user environment runs, modify 'curenv->env_tf'
+       //   (the 'tf' variable points at 'curenv->env_tf').
+       // LAB 4: Your code here.
+       // Destroy the environment that caused the fault.
+       env_t* curenv = curenvs[lapic_get_id()];
+       cprintf("[%08x] user fault va %08x ip %08x from core %d\n",
+               curenv->env_id, fault_va, tf->tf_eip, lapic_get_id());
+       print_trapframe(tf);
+       env_destroy(curenv);
+ }
+ void sysenter_init(void)
+ {
+       write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
+       write_msr(MSR_IA32_SYSENTER_ESP, ts.ts_esp0);
+       write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
+ }
+ /* This is called from sysenter's asm, with the tf on the kernel stack. */
+ void sysenter_callwrapper(struct Trapframe *tf)
+ {
+       env_t* curenv = curenvs[lapic_get_id()];
+       curenv->env_tf = *tf;
+       
+       // The trapframe on the stack should be ignored from here on.
+       tf = &curenv->env_tf;
+       tf->tf_regs.reg_eax = (intreg_t) syscall(curenv,
+                                                tf->tf_regs.reg_eax,
+                                                tf->tf_regs.reg_edx,
+                                                tf->tf_regs.reg_ecx,
+                                                tf->tf_regs.reg_ebx,
+                                                tf->tf_regs.reg_edi,
+                                                0);
+       env_run(curenv);
+ }
index 0000000,0000000..f9a8e69
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,174 @@@
++#ifndef ROS_INC_MPTABLES_H
++#define ROS_INC_MPTABLES_H
++
++#include <arch/types.h>
++#include <trap.h>
++#include <pmap.h>
++
++#define mptables_info(...)  cprintf(__VA_ARGS__)  
++#define mptables_dump(...)  //cprintf(__VA_ARGS__)  
++
++
++#define MP_SIG                        0x5f504d5f      /* _MP_ */
++
++#define BIOS_ROM_BASE 0xf0000
++#define BIOS_ROM_BOUND  0xffff0 // Inclusive.
++
++#define EBDA_POINTER  0x040e // Bound is dynamic. In first KB
++#define EBDA_SIZE             1024
++
++#define TOPOFMEM_POINTER      0x0413          /* BIOS: base memory size */
++#define IMCRP_MASK            0x80
++
++#define NUM_ENTRY_TYPES 5
++
++enum interrupt_modes {
++      PIC, // PIC Mode (Bocsh, KVM)
++      VW,  // Virtural Wire Mode (Dev Boxes)
++      SIO  // Once we fix up the ioapic, shift to this mode, sym io.
++};
++
++enum entry_types {
++      PROC =          0,
++      BUS  =          1,
++      IOAPIC =        2,
++      INT =           3,
++      LINT =          4
++};
++
++enum busTypes {
++    CBUS = 1,
++    CBUSII = 2,
++    EISA = 3,
++    ISA = 6,
++    PCI = 13,
++    XPRESS = 18,
++    MAX_BUSTYPE = 18,
++    UNKNOWN_BUSTYPE = 0xff
++};
++
++typedef struct BUSTYPENAME {
++    uint8_t   type;
++    char      name[ 7 ];
++} busTypeName;
++
++static busTypeName busTypeTable[] =
++{
++    { CBUS,           "CBUS"   },
++    { CBUSII,         "CBUSII" },
++    { EISA,           "EISA"   },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { ISA,            "ISA"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { PCI,            "PCI"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    },
++    { UNKNOWN_BUSTYPE,        "---"    }
++};
++
++typedef struct TABLE_ENTRY {
++    uint8_t   type;
++    uint8_t   length;
++    char      name[ 32 ];
++} tableEntry;
++
++/* MP Floating Pointer Structure */
++typedef struct MPFPS {
++    char      signature[ 4 ];
++    void*     pap;
++    uint8_t   length;
++    uint8_t   spec_rev;
++    uint8_t   checksum;
++    uint8_t   mpfb1;
++    uint8_t   mpfb2;
++    uint8_t   mpfb3;
++    uint8_t   mpfb4;
++    uint8_t   mpfb5;
++} mpfps_t;
++
++
++/* MP Configuration Table Header */
++typedef struct MPCTH {
++    char      signature[ 4 ];
++    uint16_t  base_table_length;
++    uint8_t           spec_rev;
++    uint8_t           checksum;
++    uint8_t           oem_id[ 8 ];
++    uint8_t           product_id[ 12 ];
++    void*             oem_table_pointer;
++    uint16_t  oem_table_size;
++    uint16_t  entry_count;
++    void*             apic_address;
++    uint16_t  extended_table_length;
++    uint8_t           extended_table_checksum;
++    uint8_t           reserved;
++} mpcth_t;
++
++
++typedef struct PROCENTRY {
++    uint8_t           type;
++    uint8_t           apicID;
++    uint8_t           apicVersion;
++    uint8_t           cpuFlags;
++    uint32_t  cpuSignature;
++    uint32_t  featureFlags;
++    uint32_t  reserved1;
++    uint32_t  reserved2;
++} proc_entry;
++
++typedef struct BUSENTRY {
++    uint8_t   type;
++    uint8_t   busID;
++    char      busType[ 6 ];
++} bus_entry;
++
++typedef struct IOAPICENTRY {
++    uint8_t   type;
++    uint8_t   apicID;
++    uint8_t   apicVersion;
++    uint8_t   apicFlags;
++    void*     apicAddress;
++} ioapic_entry;
++
++typedef struct INTENTRY {
++    uint8_t           type;
++    uint8_t           intType;
++    uint16_t  intFlags;
++    uint8_t           srcBusID;
++    uint8_t           srcBusIRQ;
++    uint8_t           dstApicID;
++    uint8_t           dstApicINT;
++} int_entry;
++
++typedef struct PCIINTENTRY {
++    uint16_t          dstApicID; // A value of 256 or greater means not valid.
++    uint8_t           dstApicINT;
++} pci_int_entry;
++
++typedef pci_int_entry isa_int_entry;
++
++typedef struct PCIINTGROUP {
++      pci_int_entry intn[4];
++} pci_int_group;
++
++void mptables_parse();
++mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound);
++bool checksum(physaddr_t addr, uint32_t len);
++void configuration_parse(physaddr_t conf_addr);
++
++void proc_parse(proc_entry* entry, uint32_t count);
++void bus_parse(bus_entry* entry, uint32_t count);
++void ioapic_parse(ioapic_entry* entry, uint32_t count);
++void int_parse(int_entry* entry, uint32_t count);
++void lint_parse(int_entry* entry, uint32_t count);
++
++#endif /* !ROS_INC_MPTABLES_H */
index 0000000,0000000..17e995c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++#ifndef ROS_INC_PCI_H
++#define ROS_INC_PCI_H
++
++#include <arch/types.h>
++#include <trap.h>
++#include <pmap.h>
++
++#define pci_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) | \
++                                                             (FUNC << 8) | REG  | \
++                                                             ((uint32_t)0x80000000))
++
++// General PCI Constants
++#define PCI_CONFIG_ADDR     0xCF8
++#define PCI_CONFIG_DATA     0xCFC
++#define INVALID_VENDOR_ID   0xFFFF
++
++#define INVALID_IRQ                   0xFFFF
++#define INVALID_BUS                   0xFFFF
++
++#define INVALID_INTN          0x0000
++
++
++#define PCI_IO_MASK         0xFFF8
++#define PCI_MEM_MASK        0xFFFFFFF0
++#define PCI_IRQ_MASK          0xFF
++#define PCI_INTN_MASK         0xFF00
++#define PCI_INTN_SHFT         0x8
++#define PCI_VENDOR_MASK               0xFFFF
++#define PCI_DEVICE_OFFSET     0x10
++#define PCI_IRQ_REG                   0x3c
++
++#define PCI_MAX_BUS                   256
++#define PCI_MAX_DEV                   32
++#define PCI_MAX_FUNC          8
++#define PCI_BAR_IO_MASK               0x1
++#define NUM_IRQS                      256
++
++// Offset used for indexing IRQs
++#define KERNEL_IRQ_OFFSET     32
++
++typedef struct PCIIRQENTRY {
++      uint16_t bus; // Bus larger than 255 denotes invalid entry.
++                                // This is why bus is 16 bits not 8.
++      uint8_t dev;
++      uint8_t func;
++      uint8_t intn;
++} pci_irq_entry;
++
++typedef struct PCIDEVENTRY {
++      uint16_t dev_id; 
++      uint16_t ven_id;
++} pci_dev_entry;
++
++void pci_init();
++
++
++#endif /* !ROS_INC_PCI_H */
index 0000000,0000000..c5d9a63
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,147 @@@
++#ifndef ROS_INC_REALTEK_H
++#define ROS_INC_REALTEK_H
++
++#include <arch/types.h>
++#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_IRQ_CPU                   5
++
++// Macro for formatting PCI Configuration Address queries
++#define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
++                                                             (FUNC << 8) | REG  | \
++                                                             ((uint32_t)0x80000000))
++#define REALTEK_VENDOR_ID   0x10ec
++#define REALTEK_DEV_ID      0x8168
++
++// Realtek Offsets
++#define RL_HWREV_REG          0x40
++#define RL_MAC_OFFSET         0x00
++#define RL_CTRL_REG         0x37
++#define RL_IM_REG                     0x3c
++#define RL_IS_REG                     0x3E
++#define RL_EP_CTRL_REG                0x50
++#define RL_RX_CFG_REG                 0x44
++#define RL_TX_CFG_REG         0x40
++#define RL_RX_MXPKT_REG     0xDA
++#define RL_TX_MXPKT_REG     0xEC
++#define RL_RX_DES_REG       0xE4
++#define RL_TX_DES_REG       0x20
++#define RL_TX_CTRL_REG                0x38    
++#define RL_CP_CTRL_REG                0xE0            
++
++// Realtek masks
++#define RL_HWREV_MASK         0x7C800000
++#define RL_CTRL_RXTX_MASK     0x0C
++#define RL_CTRL_RESET_MASK  0x10
++
++#define RL_EP_CTRL_UL_MASK    0xC0
++#define RL_EP_CTRL_L_MASK     0x00
++#define RL_TX_SEND_MASK               0x40
++#define RL_CP_MAGIC_MASK      0x002B // Magic bits pulled from the BSD driver.
++                                                                 // Are listed as needed for TX/RX checksumming
++
++// NOTE: THESE SHOULD BE BROKEN DOWN INTO A SERIES OF BITS TO REPERSENT THE VARIOUS OPTIONS
++// AND THEN THE MASK SHOULD BE DEFINED TO BE AN OR OF THOSE BITS. THIS IS A QUICK HACK JOB.
++// See interrupts below for how this should be done
++#define RL_RX_CFG_MASK                0x0000E70F  // RXFTH: unlimited, MXDMA: unlimited, AAP: set (promisc. mode set)
++#define RL_TX_CFG_MASK                0x3000700  // IFG: normal, MXDMA: unlimited.  crc appended
++
++// Realtek interrupt bits
++#define RL_INT_SERR                   0x8000
++#define RL_INT_TIMEOUT                0x4000
++#define RL_INT_SWINT          0x0100
++#define RL_INT_TDU                    0x0080
++#define RL_INT_FOVW                   0x0040
++#define RL_INT_LINKCHG                0x0020
++#define RL_INT_RDU                    0x0010
++#define RL_INT_TERR                   0x0008
++#define RL_INT_TOK                    0x0004
++#define RL_INT_RERR                   0x0002
++#define RL_INT_ROK                    0x0001
++
++#define RL_INTERRUPT_MASK     RL_INT_LINKCHG | RL_INT_TOK | RL_INT_ROK | RL_INT_SWINT
++#define RL_INTRRUPT_CLEAR     0xFFFF
++
++// Realtek descriptor command bits
++#define DES_OWN_MASK          0x80000000
++#define DES_EOR_MASK          0x40000000
++#define DES_RX_SIZE_MASK      0x3FFF
++#define DES_FS_MASK                   0x20000000
++#define DES_LS_MASK                   0x10000000
++#define DES_MAR_MASK          0x08000000
++#define DES_PAM_MASK          0x04000000
++#define DES_BAR_MASK          0x02000000
++
++// TFor some reaosn the bits are in an undocumented position for our NIC
++// They should be part of the command field, at the commented addrs below. instead
++// they are part of the vlan field as stated below.
++//#define DES_TX_IP_CHK_MASK  0x40000
++//#define DES_TX_UDP_CHK_MASK 0x20000
++//#define DES_TX_TCP_CHK_MASK 0x10000
++#define DES_TX_IP_CHK_MASK  0x20000000
++#define DES_TX_UDP_CHK_MASK 0x80000000
++#define DES_TX_TCP_CHK_MASK 0x40000000
++
++// Offset used for indexing IRQs
++#define KERNEL_IRQ_OFFSET     32
++
++// Basic packet sizing
++// TODO handle jumbo packets
++#define ETHERNET_ENCAP_SIZE   18
++#define MTU                                   1500    
++#define MAX_FRAME_SIZE                ETHERNET_ENCAP_SIZE + MTU       
++      
++// Realtek Descriptor Related Sizing
++#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.
++
++#define RL_TX_MAX_BUFFER_SIZE  ROUNDUP(MAX_FRAME_SIZE, 128)
++#define RL_RX_MAX_BUFFER_SIZE  ROUNDUP(MAX_FRAME_SIZE, 8)    // Might be able to be 4 less. Does it strip out the crc flag?
++
++#define RL_TX_MAX_SIZE                RL_TX_MAX_BUFFER_SIZE / 128
++#define RL_RX_MAX_SIZE                RL_RX_MAX_BUFFER_SIZE
++
++#define RL_DES_ALIGN  256
++#define RL_BUF_ALIGN  8
++
++// ^----- Good line ------^
++
++// v----- Evil line ------v
++// Hacky stuff for syscalls go away.
++
++#define MINIMUM_PACKET_SIZE 14 // kinda evil. probably evil.
++#define MAX_PACKET_SIZE               MTU
++
++#define PACKET_HEADER_SIZE  20 + 8 + 14 //IP UDP ETH
++#define MAX_PACKET_DATA               MAX_FRAME_SIZE - PACKET_HEADER_SIZE
++// This number needs verification! Also, this is a huge hack, as the driver shouldnt care about UDP/IP etc.
++
++// ^----- Evil line ------^
++
++// v----- Good line ------v
++
++
++void nic_init(void);
++void reset_nic(void);
++void nic_interrupt_handler(trapframe_t *tf, void* data);
++int scan_pci(void);
++void read_mac(void);
++void setup_interrupts(void);
++void setup_descriptors(void);
++void configure_nic(void);
++void nic_handle_rx_packet(void);
++void set_rx_descriptor(uint32_t des_num, uint8_t reset_buffer);
++void set_tx_descriptor(uint32_t des_num);
++void process_frame(char *frame_buffer, uint32_t frame_size, uint32_t command);
++int send_frame(const char *data, size_t len);
++const char *packet_wrap(const char* data, size_t len);
++
++
++#endif /* !ROS_INC_REALTEK_H */
index 0000000,128ff43..8dca5cd
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,55 +1,58 @@@
+ #ifndef ROS_INCLUDE_SYSCALL_H
+ #define ROS_INCLUDE_SYSCALL_H
+ #include <arch/types.h>
+ #include <ros/ring_buffer.h>
+ /* system call numbers */
+ enum
+ {
+       SYS_begofcalls, //Should always be first
+       SYS_null,
+       SYS_cache_buster,
+       SYS_cache_invalidate,
+       SYS_cputs,
+       SYS_cgetc,
+       SYS_getcpuid,
+       SYS_serial_write,
+       SYS_serial_read,
++      SYS_eth_read,
++      SYS_eth_write,
++      SYS_run_binary,
+       SYS_shared_page_alloc,
+       SYS_shared_page_free,
+       SYS_getenvid,
+       SYS_env_destroy,
+       SYS_yield,
+       SYS_proc_create,
+       SYS_proc_run,
+       SYS_endofcalls //Should always be last
+ };
+ #define NSYSCALLS (SYS_endofcalls -1)
+ // syscall number starts at 1 and goes up to NSYSCALLS, without holes.
+ #define INVALID_SYSCALL(syscallno) ((syscallno) > NSYSCALLS)
+ /* For Buster Measurement Flags */
+ #define BUSTER_SHARED                 0x0001
+ #define BUSTER_STRIDED                        0x0002
+ #define BUSTER_LOCKED                 0x0004
+ #define BUSTER_PRINT_TICKS            0x0008
+ #define BUSTER_JUST_LOCKS             0x0010 // unimplemented
+ #define NUM_SYSCALL_ARGS 6
+ typedef struct syscall_req {
+       uint32_t num;
+       uint32_t flags;
+       uint32_t args[NUM_SYSCALL_ARGS];
+ } syscall_req_t;
+ typedef struct syscall_rsp {
+       int32_t retval;
+ } syscall_rsp_t;
+ // Generic Syscall Ring Buffer
+ DEFINE_RING_TYPES(syscall, syscall_req_t, syscall_rsp_t);
+ #endif /* !ROS_INCLUDE_SYSCALL_H */
index 0000000,7c58d27..89ba6ed
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,29 +1,30 @@@
+ #ifndef ROS_INC_TESTING_H
+ #define ROS_INC_TESTING_H
+ /* This is just a dumping ground for old code used for testing.
+  * Someone should go through old commits and bring back other relevant tests.
+  * Someone else should actually make these useful on their own
+  */
+ #include <arch/types.h>
+ void test_ipi_sending(void);
+ void test_pic_reception(void);
++void test_ioapic_pic_reroute(void);
+ void test_print_info(void);
+ void test_barrier(void);
+ void test_interrupts_irqsave(void);
+ void test_bitmasks(void);
+ void test_checklists(void);
+ void test_pit(void);
+ void test_smp_call_functions(void);
+ void test_lapic_status_bit(void);
+ void test_run_measurements(uint32_t job_num);
+ struct trapframe_t;
+ void test_hello_world_handler(trapframe_t *tf, void* data);
+ void test_print_info_handler(trapframe_t *tf, void* data);
+ void test_barrier_handler(trapframe_t *tf, void* data);
+ #endif /* !ROS_INC_TESTING_H */
@@@ -11,45 -11,35 +11,45 @@@ OBJDIRS += $(KERN_SRC_DIR
  #
  # We also snatch the use of a couple handy source files
  # from the lib directory, to avoid gratuitous code duplication.
- KERN_SRCFILES := $(KERN_SRC_DIR)/entry.S \
-                  $(KERN_SRC_DIR)/smp_entry.S \
+ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
                   $(KERN_SRC_DIR)/init.c \
-                  $(KERN_SRC_DIR)/console.c \
                   $(KERN_SRC_DIR)/monitor.c \
-                  $(KERN_SRC_DIR)/pmap.c \
-                  $(KERN_SRC_DIR)/env.c \
-                  $(KERN_SRC_DIR)/kclock.c \
-                  $(KERN_SRC_DIR)/picirq.c \
                   $(KERN_SRC_DIR)/printf.c \
-                  $(KERN_SRC_DIR)/syscall.c \
 +                 $(KERN_SRC_DIR)/trap.c \
 +                 $(KERN_SRC_DIR)/trapentry.S \
 +                 $(KERN_SRC_DIR)/sched.c \
-                  $(KERN_SRC_DIR)/testing.c \
-                  $(KERN_SRC_DIR)/workqueue.c \
-                  $(KERN_SRC_DIR)/manager.c \
 +                 $(KERN_SRC_DIR)/kdebug.c \
 +                 $(KERN_SRC_DIR)/apic.c \
-                  $(KERN_SRC_DIR)/atomic.c \
-                  $(KERN_SRC_DIR)/smp.c \
 +                 $(KERN_SRC_DIR)/mptables.c \
 +                 $(KERN_SRC_DIR)/pci.c \
 +                 $(KERN_SRC_DIR)/ioapic.c \
                   $(KERN_SRC_DIR)/printfmt.c \
+                  $(KERN_SRC_DIR)/smp.c \
+                  $(KERN_SRC_DIR)/multiboot.c \
                   $(KERN_SRC_DIR)/readline.c \
                   $(KERN_SRC_DIR)/string.c \
+                  $(KERN_SRC_DIR)/atomic.c \
+                  $(KERN_SRC_DIR)/workqueue.c \
+                  $(KERN_SRC_DIR)/pmap.c \
+                  $(KERN_SRC_DIR)/env.c \
+                  $(KERN_SRC_DIR)/manager.c \
+                  $(KERN_SRC_DIR)/syscall.c \
                   $(KERN_SRC_DIR)/timer.c \
                   $(KERN_SRC_DIR)/kmalloc.c \
-                  $(KERN_SRC_DIR)/rl8168.c
++                 $(KERN_SRC_DIR)/rl8168.c \
+                  $(KERN_SRC_DIR)/testing.c
  
  # Only build files if they exist.
  KERN_SRCFILES := $(wildcard $(KERN_SRCFILES))
  
- KERN_APPFILES :=    $(USER_APPS_PARLIB_DIR)/matrix \
+ KERN_APPFILES := \
+                     $(USER_APPS_ROSLIB_DIR)/proctests \
+                     $(USER_APPS_ROSLIB_DIR)/fptest \
                      $(USER_APPS_ROSLIB_DIR)/null \
                      $(USER_APPS_ROSLIB_DIR)/hello \
-                     $(USER_APPS_ROSLIB_DIR)/proctests \
 +                    $(USER_APPS_PARLIB_DIR)/draw_nanwan_standalone \
+                     $(USER_APPS_PARLIB_DIR)/channel_test_client \
+                     $(USER_APPS_PARLIB_DIR)/channel_test_server \
                      $(USER_APPS_ROSLIB_DIR)/measurements
  #                    $(USER_APPS_PARLIB_DIR)/draw_nanwan
  #                    $(USER_APPS_PARLIB_DIR)/open_read \
diff --cc kern/src/env.c
Simple merge
diff --cc kern/src/init.c
  #include <kclock.h>
  #include <manager.h>
  
- static void print_cpuinfo(void);
 +#include <rl8168.h>
 +#include <mptables.h>
 +#include <pci.h>
 +#include <arch/ioapic.h>
 +
  void kernel_init(multiboot_info_t *mboot_info)
  {
        extern char (BND(__this, end) edata)[], (SNT end)[];
        idt_init();
        sysenter_init();
        timer_init();
 +      mptables_parse();
 +      pci_init();
 +      ioapic_init(); // MUST BE AFTER PCI/ISA INIT!
 +      // this returns when all other cores are done and ready to receive IPIs
 +      smp_boot();
 +      
 +      nic_init();             
 +      /*
+       // this returns when all other cores are done and ready to receive IPIs
+       smp_boot();
        test_smp_call_functions();
        test_checklists();
        test_barrier();
index 773f750,0000000..b4218c8
mode 100644,000000..100644
--- /dev/null
@@@ -1,155 -1,0 +1,154 @@@
- #include <arch/timer.h>
 +/*
 + * Copyright (c) 2009 The Regents of the University of California
 + * See LICENSE for details.
 + */
 +
 +#include <arch/mmu.h>
 +#include <arch/x86.h>
 +#include <arch/apic.h>
 +#include <assert.h>
 +#include <mptables.h>
 +#include <pci.h>
 +
 +/* IOAPIC ?Driver?
 + *
 + * Written by Paul Pearce.
 + *
 + * Insight into functionality goes here
 + *
 + * TODO: Clean up array bounds checking (leaving it to ivy is lame, no offense to ivy, its just not good practice)
 + */
 +
 +typedef struct IOAPICREDIRECT {
 +    void*                     ioapic_address; // NULL means invalid (duh)
 +      uint8_t                 ioapic_flags;
 +      uint8_t                 ioapic_int;
 +} ioapic_redirect;
 +
 +ioapic_redirect ioapic_redirects[NUM_IRQS];
 +
 +void ioapic_init() {
 +      // Set all entires invalid.
 +      memset(ioapic_redirects, 0x0, sizeof(ioapic_redirects));
 +      
 +      extern uint8_t num_cpus;
 +      uint32_t inconsistent_pci_mappings = 0;  // Set high if we find inconsistent mappings between
 +                                                                                       //  mptables and the pci bus.
 +      
 +      // Pull in all the stuff we need from mptables and the pci parsing
 +      extern pci_irq_entry irq_pci_map[NUM_IRQS];
 +      extern pci_int_group pci_int_groups[PCI_MAX_BUS][PCI_MAX_DEV];
 +      extern ioapic_entry ioapic_entries[IOAPIC_MAX_ID];
 +      extern isa_int_entry isa_int_entries[NUM_IRQS];
 +      
 +      // Setup the PCI entries
 +      for (int i = 0; i < NUM_IRQS; i++) {
 +              uint16_t bus = irq_pci_map[i].bus;
 +              uint8_t dev = irq_pci_map[i].dev;
 +              uint8_t intn = irq_pci_map[i].intn;
 +              
 +              if (bus == INVALID_BUS)
 +                      continue;
 +
 +              uint16_t dstApicID = pci_int_groups[bus][dev].intn[intn].dstApicID;
 +              uint8_t dstApicINT = pci_int_groups[bus][dev].intn[intn].dstApicINT;
 +              
 +              // MP Tables uses 8 bits to store the apic id. If our value is larger, is invalid entry
 +              // If we have a valid bus in the irq->pci map, and the pic->int entry doesnt exist, we have a major problem
 +              if (dstApicID == 0xFFFF) {
 +                      if (!inconsistent_pci_mappings)
 +                              cprintf("WARNING: INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS. Trying to cope...\n");
 +                      inconsistent_pci_mappings++;
 +                      continue;
 +              }
 +              
 +              // If the lowest bit of the apic flags is set to 0, it means the ioapic is not usable.
 +              // We also use this to denote non-existent ioapics in our map
 +              if ((ioapic_entries[dstApicID].apicFlags & 0x1) == 0) 
 +                      panic("IRQ SAYS ITS GOING TO AN IOAPIC LISTED AS INVALID, THATS BAD.");
 +                                      
 +              ioapic_redirects[i].ioapic_address = ioapic_entries[dstApicID].apicAddress;
 +              ioapic_redirects[i].ioapic_int = dstApicINT;
 +              ioapic_redirects[i].ioapic_flags = IOAPIC_PCI_FLAGS;
 +      }
 +      
 +      // Setup the ISA entries
 +      for (int i = 0; i < NUM_IRQS; i++) {
 +              
 +              uint16_t dstApicID = isa_int_entries[i].dstApicID;
 +              uint8_t dstApicINT = isa_int_entries[i].dstApicINT;
 +              
 +              
 +              // Skip invalid entries
 +              if (dstApicID == 0xFFFF)
 +                      continue;
 +                      
 +              if (ioapic_redirects[i].ioapic_address != NULL) {
 +                      // We could handle this so long as they would route to the same place. But we will say we cant
 +                      //  because this shouldnt really happen
 +                      panic("BOTH PCI AND ISA CLAIM TO SHARE AN IRQ. BAD");
 +              }
 +              
 +              // Code to check if this isa irq entry claims to be pci
 +              uint16_t pci_bus = irq_pci_map[i].bus;
 +              if (pci_bus != INVALID_BUS) {
 +                      // PCI bus had an entry for this irq, but we didn't set it during our pci run
 +                      //  This means it is likely a broken mptable implimentation. this happens on bochs and kvm
 +                      //  lets just set the flags as if its broken, and move on. Hopefully it will work out.
 +                      ioapic_redirects[i].ioapic_flags = IOAPIC_BROKEN_PCI_FLAGS;
 +                      inconsistent_pci_mappings--;
 +              }
 +              else {
 +                      ioapic_redirects[i].ioapic_flags = IOAPIC_ISA_FLAGS;
 +              }
 +              
 +
 +              ioapic_redirects[i].ioapic_address = ioapic_entries[dstApicID].apicAddress;
 +              ioapic_redirects[i].ioapic_int = dstApicINT;
 +      }
 +      
 +      // Things didn't balance out when we scanned the isa bus for the missing pci devices. Die.
 +      if (inconsistent_pci_mappings != 0) 
 +              panic("FAILED TO COPE WITH INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS!");
 +      
 +      // Support for other type of IRQ's goes here.
 +}
 +
 +// MUST NOT BE CALLED BEFORE THE MPTABLES ARE PARSED
 +// INPUT IS NON-KERNEL-OFFSETTED. IE IRQ0 is Pit, not divide by 0.
 +void ioapic_route_irq(uint8_t irq, uint8_t dest) {
 +      
 +      if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
 +              panic("TRYING TO REROUTE AN INVALID IRQ!");
 +      }
 +
 +      // THIS IS A TEMP CHECK. IF WE USE LOGICAL PARTITIONS THIS MUST BE REMOVED
 +      if (dest >= num_cpus)
 +              panic("TRYING TO REROUTE TO AN INVALID DESTINATION!");
 +      
 +      // This is ugly. Fix it. I just gave up because i need sleep and I wanted it working so I can commit.
 +      uint32_t redirect_low = KERNEL_IRQ_OFFSET + irq;
 +      redirect_low = redirect_low | (ioapic_redirects[irq].ioapic_flags << 8);
 +      uint32_t redirect_high = dest << 24;
 +      
 +      // YOU MUST MUST MUST MUST MUST MUST MUST write the high bits first. Ask Paul about that afternoon of his life.
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int + 1);
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, redirect_high);
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int);
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, redirect_low);
 +}
 +
 +void ioapic_unroute_irq(uint8_t irq) {
 +
 +      if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
 +              panic("TRYING TO REROUTE AN INVALID IRQ!");
 +      }
 +      
 +      // Must write low first, else we will reroute to a wrong core before turning off
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int);
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, IOAPIC_UNROUTE_LOW);
 +      
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int + 1);
 +      write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, IOAPIC_UNROUTE_HIGH);
 +
 +}
Simple merge
diff --cc kern/src/smp.c
  #pragma nodeputy
  #endif
  
- #include <arch/x86.h>
- #include <arch/smp.h>
- #include <arch/console.h>
- #include <arch/apic.h>
+ #include <arch/arch.h>
  #include <atomic.h>
- #include <ros/error.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #include <pmap.h>
- #include <env.h>
- #include <trap.h>
- volatile uint8_t num_cpus = 0xee;
- uintptr_t smp_stack_top;
- per_cpu_info_t per_cpu_info[MAX_NUM_CPUS];
+ #include <smp.h>
  
- /*************************** IPI Wrapper Stuff ********************************/
- // checklists to protect the global interrupt_handlers for 0xf0, f1, f2, f3, f4
- // need to be global, since there is no function that will always exist for them
- handler_wrapper_t             handler_wrappers[NUM_HANDLER_WRAPPERS];
  // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
- uint32_t outstanding_calls = 0; 
- #define DECLARE_HANDLER_CHECKLISTS(vector)                          \
-       INIT_CHECKLIST(f##vector##_cpu_list, MAX_NUM_CPUS);
- #define INIT_HANDLER_WRAPPER(v)                                     \
- {                                                                   \
-       handler_wrappers[(v)].vector = 0xf##v;                          \
-       handler_wrappers[(v)].cpu_list = &f##v##_cpu_list;              \
-       handler_wrappers[(v)].cpu_list->mask.size = num_cpus;           \
- }
- DECLARE_HANDLER_CHECKLISTS(0);
- DECLARE_HANDLER_CHECKLISTS(1);
- DECLARE_HANDLER_CHECKLISTS(2);
- DECLARE_HANDLER_CHECKLISTS(3);
- DECLARE_HANDLER_CHECKLISTS(4);
- static void init_smp_call_function(void)
- {
-       INIT_HANDLER_WRAPPER(0);
-       INIT_HANDLER_WRAPPER(1);
-       INIT_HANDLER_WRAPPER(2);
-       INIT_HANDLER_WRAPPER(3);
-       INIT_HANDLER_WRAPPER(4);
- }
- /******************************************************************************/
- static void smp_mtrr_handler(trapframe_t *tf, void* data)
- {
-       setup_default_mtrrs((barrier_t*)data);
- }
- void smp_boot(void)
- {
-       // this needs to be set in smp_entry too...
-       #define trampoline_pg 0x00001000
-       page_t *smp_stack;
-       // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
-       // page1 (2nd page) is reserved, hardcoded in pmap.c
-       extern smp_entry(), smp_entry_end(), smp_boot_lock(), smp_semaphore();
-       memset(KADDR(trampoline_pg), 0, PGSIZE);
-       memcpy(KADDR(trampoline_pg), &smp_entry, &smp_entry_end - &smp_entry);
-       // This mapping allows access to the trampoline with paging on and off
-       // via trampoline_pg
-       page_insert(boot_pgdir, pa2page(trampoline_pg), (void*)trampoline_pg, PTE_W);
-       // Allocate a stack for the cores starting up.  One for all, must share
-       if (page_alloc(&smp_stack))
-               panic("No memory for SMP boot stack!");
-       smp_stack->pp_ref++;
-       smp_stack_top = (uintptr_t)(page2kva(smp_stack) + PGSIZE);
-       // Start the IPI process (INIT, wait, SIPI, wait, SIPI, wait)
-       send_init_ipi();
-       // SDM 3A is a little wonky wrt the proper delays.  These are my best guess.
-       udelay(10000);
-       // first SIPI
-       send_startup_ipi(0x01);
-       /* BOCHS does not like this second SIPI.
-       // second SIPI
-       udelay(200);
-       send_startup_ipi(0x01);
-       */
-       udelay(100000);
-       // Each core will also increment smp_semaphore, and decrement when it is done,
-       // all in smp_entry.  It's purpose is to keep Core0 from competing for the
-       // smp_boot_lock.  So long as one AP increments the sem before the final
-       // LAPIC timer goes off, all available cores will be initialized.
-       while(*(volatile uint32_t*)(&smp_semaphore - &smp_entry + trampoline_pg));
-       // From here on, no other cores are coming up.  Grab the lock to ensure it.
-       // Another core could be in it's prelock phase and be trying to grab the lock
-       // forever....
-       // The lock exists on the trampoline, so it can be grabbed right away in
-       // real mode.  If core0 wins the race and blocks other CPUs from coming up
-       // it can crash the machine if the other cores are allowed to proceed with
-       // booting.  Specifically, it's when they turn on paging and have that temp
-       // mapping pulled out from under them.  Now, if a core loses, it will spin
-       // on the trampoline (which we must be careful to not deallocate)
-       spin_lock((uint32_t*)(&smp_boot_lock - &smp_entry + trampoline_pg));
-       cprintf("Num_Cpus Detected: %d\n", num_cpus);
-       // Remove the mapping of the page used by the trampoline
-       page_remove(boot_pgdir, (void*)trampoline_pg);
-       // It had a refcount of 2 earlier, so we need to dec once more to free it
-       // but only if all cores are in (or we reset / reinit those that failed)
-       // TODO after we parse ACPI tables
-       if (num_cpus == 8) // TODO - ghetto coded for our 8 way SMPs
-               page_decref(pa2page(trampoline_pg));
-       // Remove the page table used for that mapping
-       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();
-       // Set up all cores to use the proper MTRRs
-       barrier_t generic_barrier;
-       init_barrier(&generic_barrier, num_cpus); // barrier used by smp_mtrr_handler
-       smp_call_function_all(smp_mtrr_handler, &generic_barrier, 0);
-       // Should probably flush everyone's TLB at this point, to get rid of
-       // temp mappings that were removed.  TODO
- }
- /*
-  * This is called from smp_entry by each core to finish the core bootstrapping.
-  * There is a spinlock around this entire function in smp_entry, for a few reasons,
-  * the most important being that all cores use the same stack when entering here.
-  */
- uint32_t smp_main(void)
- {
-       /*
-       // Print some diagnostics.  Uncomment if there're issues.
-       cprintf("Good morning Vietnam!\n");
-       cprintf("This core's Default APIC ID: 0x%08x\n", lapic_get_default_id());
-       cprintf("This core's Current APIC ID: 0x%08x\n", lapic_get_id());
-       if (read_msr(IA32_APIC_BASE) & 0x00000100)
-               cprintf("I am the Boot Strap Processor\n");
-       else
-               cprintf("I am an Application Processor\n");
-       cprintf("Num_Cpus: %d\n\n", num_cpus);
-       */
-       // Get a per-core kernel stack
-       page_t *my_stack;
-       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
-       // This is necessary, eagle-eyed readers know why
-       // GDT should be 4-byte aligned.  TS isn't aligned.  Not sure if it matters.
-       pseudodesc_t *my_gdt_pd = page2kva(my_stack) + PGSIZE -
-               sizeof(pseudodesc_t) - sizeof(segdesc_t)*SEG_COUNT;
-       segdesc_t *my_gdt = page2kva(my_stack) + PGSIZE -
-               sizeof(segdesc_t)*SEG_COUNT;
-       // TS also needs to be permanent
-       taskstate_t *my_ts = page2kva(my_stack) + PGSIZE -
-               sizeof(pseudodesc_t) - sizeof(segdesc_t)*SEG_COUNT -
-               sizeof(taskstate_t);
-       // Usable portion of the KSTACK grows down from here
-       // Won't actually start using this stack til our first interrupt
-       // (issues with changing the stack pointer and then trying to "return")
-       uintptr_t my_stack_top = (uintptr_t)my_ts;
-       
-       // Set up MSR for SYSENTER 
-       write_msr(MSR_IA32_SYSENTER_CS, GD_KT);
-       write_msr(MSR_IA32_SYSENTER_ESP, my_stack_top);
-       write_msr(MSR_IA32_SYSENTER_EIP, (uint32_t) &sysenter_handler);
-       // Build and load the gdt / gdt_pd
-       memcpy(my_gdt, gdt, sizeof(segdesc_t)*SEG_COUNT);
-       *my_gdt_pd = (pseudodesc_t) {
-               sizeof(segdesc_t)*SEG_COUNT - 1, (uintptr_t) my_gdt };
-       asm volatile("lgdt %0" : : "m"(*my_gdt_pd));
-       // Need to set the TSS so we know where to trap on this core
-       my_ts->ts_esp0 = my_stack_top;
-       my_ts->ts_ss0 = GD_KD;
-       // Initialize the TSS field of my_gdt.
-       my_gdt[GD_TSS >> 3] = SEG16(STS_T32A, (uint32_t) (my_ts), sizeof(taskstate_t), 0);
-       my_gdt[GD_TSS >> 3].sd_s = 0;
-       // Load the TSS
-       ltr(GD_TSS);
-       // Loads the same IDT used by the other cores
-       asm volatile("lidt idt_pd");
-       // APIC setup
-       // set LINT0 to receive ExtINTs (KVM's default).  At reset they are 0x1000.
-       write_mmreg32(LAPIC_LVT_LINT0, 0x700);
-       // mask it to shut it up for now.  Doesn't seem to matter yet, since both
-       // KVM and Bochs seem to only route the PIC to core0.
-       mask_lapic_lvt(LAPIC_LVT_LINT0);
-       // and then turn it on
-       lapic_enable();
-       // set a default logical id for now
-       lapic_set_logid(lapic_get_id());
-       return my_stack_top; // will be loaded in smp_entry.S
- }
+ atomic_t outstanding_calls = 0;
 -
+ per_cpu_info_t per_cpu_info[MAX_NUM_CPUS];
  
  /* All non-zero cores call this at the end of their boot process.  They halt,
   * and wake up when interrupted, do any work on their work queue, then halt
@@@ -4,40 -4,19 +4,21 @@@
  #endif
  
  #include <arch/types.h>
- #include <arch/x86.h>
+ #include <arch/arch.h>
  #include <arch/mmu.h>
  #include <arch/console.h>
- #include <arch/apic.h>
- #include <arch/timer.h>
+ #include <ros/timer.h>
  #include <ros/error.h>
  
 +#include <rl8168.h>
  #include <string.h>
  #include <assert.h>
  #include <env.h>
  #include <pmap.h>
  #include <trap.h>
  #include <syscall.h>
 +#include <kmalloc.h>
  
- /* This is called from sysenter's asm, with the tf on the kernel stack. */
- void sysenter_callwrapper(struct Trapframe *tf)
- {
-       env_t* curenv = curenvs[lapic_get_id()];
-       curenv->env_tf = *tf;
-       
-       // The trapframe on the stack should be ignored from here on.
-       tf = &curenv->env_tf;
-       tf->tf_regs.reg_eax = (intreg_t) syscall(curenv,
-                                                tf->tf_regs.reg_eax,
-                                                tf->tf_regs.reg_edx,
-                                                tf->tf_regs.reg_ecx,
-                                                tf->tf_regs.reg_ebx,
-                                                tf->tf_regs.reg_edi,
-                                                0);
-       env_run(curenv);
- }
  //Do absolutely nothing.  Used for profiling.
  static void sys_null(void)
  {
@@@ -74,99 -53,38 +55,131 @@@ static ssize_t sys_serial_read(env_t* e
        #endif
  }
  
 +static ssize_t sys_run_binary(env_t* e, void* binary_buf, void* arg, size_t len) {
 +      uint8_t* new_binary = kmalloc(len, 0);
 +      if(new_binary == NULL)
 +              return -ENOMEM;
 +      memcpy(new_binary, binary_buf, len);
 +
 +      env_t* env = env_create((uint8_t*)new_binary, len);
 +      kfree(new_binary);
 +      
 +      e->env_status = ENV_RUNNABLE;
 +      env_run(env);
 +      return 0;
 +}
 +
 +// 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;
 +              
 +      }
 +      else
 +              return -EINVAL;
 +}
 +/*
 +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 -EINVAL;
 +}
 +*/
 +
 +
 +// 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 -EINVAL;
 +}
 +
+ static ssize_t sys_shared_page_alloc(env_t* p1, 
+                                      void** addr, envid_t p2_id, 
+                                      int p1_flags, int p2_flags
+                                     ) 
+ {
+       if (!VALID_USER_PERMS(p1_flags)) return -EPERM;
+       if (!VALID_USER_PERMS(p2_flags)) return -EPERM;
+       page_t* page;
+       env_t* p2 = &(envs[ENVX(p2_id)]);
+       error_t e = page_alloc(&page);
+       if(e < 0) return e;
+       
+       void* p2_addr = page_insert_in_range(p2->env_pgdir, page, 
+                                            (void*)UTEXT, (void*)UTOP, p2_flags);
+       if(p2_addr == NULL) 
+               return -EFAIL;
+               
+       void* p1_addr = page_insert_in_range(p1->env_pgdir, page, 
+                                           (void*)UTEXT, (void*)UTOP, p1_flags);
+       if(p1_addr == NULL) {
+               page_remove(p2->env_pgdir, p2_addr);
+               return -EFAIL;
+       }
+       *addr = p1_addr;
+       return ESUCCESS;
+ }
+ static void sys_shared_page_free(env_t* p1, void* addr, envid_t p2)
+ {
+ }
  // Invalidate the cache of this core
  static void sys_cache_invalidate(void)
  {
@@@ -340,14 -263,7 +358,14 @@@ intreg_t syscall(env_t* e, uint32_t sys
        switch (syscallno) {
                case SYS_null:
                        sys_null();
-                       return 0;
+                       return ESUCCESS;
 +              case SYS_run_binary:
 +                      return sys_run_binary(e, (char *DANGEROUS)a1, 
 +                                            (char* DANGEROUS)a2, (size_t)a3);
 +              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_buster:
                        sys_cache_buster(e, a1, a2, a3);
                        return 0;
  #include <env.h>
  #include <syscall.h>
  
 +#include <pmap.h>
 +
  #define test_vector 0xeb
  
+ #if 0
  void test_ipi_sending(void)
  {
        extern handler_t interrupt_handlers[];
@@@ -74,23 -73,9 +75,25 @@@ void test_pic_reception(void
        enable_irq();
        while(1);
  }
 -
+ #endif
  
 +void test_ioapic_pic_reroute(void) 
 +{
++      extern handler_t interrupt_handlers[];
 +      register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, 0);
 +      ioapic_route_irq(0, 3); 
 +
 +      cprintf("Starting pit on core 3....\n");
 +      udelay(3000000);
 +      pit_set_timer(100000,TIMER_RATEGEN); // totally arbitrary time
 +      
 +      udelay(3000000);
 +      ioapic_unroute_irq(0);
 +      udelay(300000);
 +      cprintf("Masked pit. Waiting before return...\n");
 +      udelay(30000000);
 +}
 +
  void test_print_info(void)
  {
        cprintf("\nCORE 0 asking all cores to print info:\n");
Simple merge
@@@ -24,9 -33,9 +33,12 @@@ ssize_t     sys_cputs(const uint8_t *s
  uint16_t    sys_cgetc(void);
  ssize_t     sys_serial_write(void* buf, size_t len); 
  ssize_t     sys_serial_read(void* buf, size_t len);
 +ssize_t     sys_eth_write(void* buf, size_t len); 
 +ssize_t     sys_eth_read(void* buf, size_t len);
 +ssize_t     sys_run_binary(void* binary_buf, void* arg, size_t len);
+ ssize_t     sys_shared_page_alloc(void *COUNT(PGSIZE) *addr, envid_t p2, 
+                                   int p1_flags, int p2_flags);
+ ssize_t     sys_shared_page_free(void *COUNT(PGSIZE) addr, envid_t p2);
  envid_t     sys_getenvid(void);
  envid_t     sys_getcpuid(void);
  void        sys_env_destroy(envid_t);
Simple merge
Simple merge