# Makefile for GeekOS kernel, userspace, and tools
# Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.69 $
+# $Revision: 1.70 $
# This is free software. You are permitted to use,
# redistribute, and modify it as specified in the file "COPYING".
endif
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DTEST_NE2K
+#DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DTEST_NE2K
ifeq ($(DEBUG),1)
JRLDEBUG= -DSERIAL_PRINT_DEBUG=1 -DSERIAL_PRINT_DEBUG_LEVEL=10 -DSERIAL_PRINT=1 -DVMM_DEBUG=1 -DVMM_INFO=1 -DVMM_TRACE=1 $(DEBUG_SECTIONS)
serial.c reboot.c \
paging.c \
debug.c vmm_stubs.c vm.c pci.c\
- queue.c socket.c ring_buffer.c \
+ queue.c ring_buffer.c \
main.c
+ #socket.c
# Kernel object files built from C source files
KERNEL_C_OBJS := $(KERNEL_C_SRCS:%.c=geekos/%.o)
/*
* GeekOS timer interrupt support
* Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "COPYING".
extern volatile ulong_t g_numTicks;
+typedef void (*timerCallback)(int);
+
void Init_Timer(void);
void Micro_Delay(int us);
+typedef struct {
+ int ticks; /* timer code decrements this */
+ int id; /* unqiue id for this timer even */
+ timerCallback callBack; /* Queue to wakeup on timer expire */
+ int origTicks;
+} timerEvent;
+
+int Start_Timer(int ticks, timerCallback);
+int Get_Remaing_Timer_Ticks(int id);
+int Cancel_Timer(int id);
+
+
void Micro_Delay(int us);
#endif /* GEEKOS_TIMER_H */
vm_operating_mode_t run_state;
void * vmm_data;
+
+ /* TEMP */
+ //ullong_t exit_tsc;
+
};
#ifndef DEBUG_PIC
#undef PrintDebug
#define PrintDebug(fmt, args...)
-#define PrintPicTrace(_f, _a...) PrintTrace("\n8259a.c(%d) "_f, __LINE__, ## _a)
+//#define PrintPicTrace(_f, _a...) PrintTrace("\n8259a.c(%d) "_f, __LINE__, ## _a)
#endif
struct pic_internal *state = (struct pic_internal*)private_data;
- PrintPicTrace("[pic_lower_intr] IRQ line %d now low\n", (unsigned) irq_no);
+ PrintDebug("[pic_lower_intr] IRQ line %d now low\n", (unsigned) irq_no);
if (irq_no <= 7) {
state->master_irr &= ~(1 << irq_no);
if ((state->master_irr & ~(state->master_imr)) == 0) {
- PrintPicTrace("\t\tFIXME: Master maybe should do sth\n");
+ PrintDebug("\t\tFIXME: Master maybe should do sth\n");
}
} else if ((irq_no > 7) && (irq_no <= 15)) {
state->slave_irr &= ~(1 << (irq_no - 8));
if ((state->slave_irr & (~(state->slave_imr))) == 0) {
- PrintPicTrace("\t\tFIXME: Slave maybe should do sth\n");
+ PrintDebug("\t\tFIXME: Slave maybe should do sth\n");
}
}
return 0;
* Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
* Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
* Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
- * $Revision: 1.45 $
+ * $Revision: 1.46 $
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "COPYING".
Init_Stubs();
-
-#ifdef TEST_NE2K
+#if 0
{
init_network();
uchar_t local_addr[4];
local_addr[0] = 10;
local_addr[1] = 0;
local_addr[2] = 2;
- local_addr[3] = 20;
+ local_addr[3] = 21;
set_ip_addr(local_addr);
remote_addr[0] = 10;
remote_addr[1] = 0;
remote_addr[2] = 2;
- remote_addr[3] = 21;
+ remote_addr[3] = 20;
connect(remote_addr, 4301);
}
#endif
-#if !TEST_NE2K
+
{
RunVMM(bootInfo);
}
-#endif
SerialPrint("RunVMM returned, spinning\n");
static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
{
+
Begin_IRQ(state);
PrintBoth("NIC Interrupt Occured!\n");
uchar_t isr_content = In_Byte(NE2K_ISR);
#include <uip/uip_arp.h>
#include <geekos/vmm_stubs.h>
#include <geekos/debug.h>
-
+#include <geekos/timer.h>
#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
struct socket sockets[MAX_SOCKS];
+void socket_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL socket_appcall
+#endif /* UIP_APPCALL */
+
+
-int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
+static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
+static void periodic_caller(int timer_id);
void init_network() {
int i = 0;
+ bool iflag;
+
for (i = 0; i < MAX_SOCKS; i++) {
sockets[i].in_use = 0;
}
+
//initiate uIP
uip_init();
uip_arp_init();
//setup device driver
Init_Ne2k(&Packet_Received);
-
+ iflag = Begin_Int_Atomic();
+ Start_Timer(2, periodic_caller);
+ End_Int_Atomic(iflag);
}
}
+
+static void periodic_caller(int timer_id) {
+ int i;
+ //handle the periodic calls of uIP
+
+ //PrintBoth("Timer CALLBACK handler\n");
+
+ for(i = 0; i < UIP_CONNS; ++i) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ //devicedriver_send();
+ PrintBoth("Sending Packet\n");
+ NE2K_Transmit(uip_len);
+ }
+ }
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ //devicedriver_send();
+ NE2K_Transmit(uip_len);
+ }
+ }
+}
+
+
int connect(const uchar_t ip_addr[4], ushort_t port) {
int sockfd = -1;
sockfd = allocate_socket_fd();
- uip_ipaddr_t ipaddr;
+ static uip_ipaddr_t ipaddr;
if (sockfd == -1) {
return -1;
}
uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
-
- sockets[sockfd].state = WAITING;
- sockets[sockfd].con = uip_connect((uip_ipaddr_t *)&ip_addr, htons(port));
+ sockets[sockfd].con = uip_connect(&ipaddr, htons(port));
if (sockets[sockfd].con == NULL){
PrintBoth("Connection start\n");
-
- while(sockets[sockfd].state == WAITING) {
- timer_int_handler(NULL);
- }
-
+ Wait(&(sock->recv_wait_queue));
+
PrintBoth("Connected\n");
- if (sockets[sockfd].state != ESTABLISHED) {
- release_socket_fd(sockfd);
- return -1;
- }
+
return sockfd;
return recvlen;
}
-void timer_int_Handler(struct Interrupt_State * state){
- int i;
- //handle the periodic calls of uIP
- for(i = 0; i < UIP_CONNS; ++i) {
- uip_periodic(i);
- if(uip_len > 0) {
- //devicedriver_send();
- NE2K_Transmit(uip_len);
- }
- }
- for(i = 0; i < UIP_UDP_CONNS; i++) {
- uip_udp_periodic(i);
- if(uip_len > 0) {
- //devicedriver_send();
- NE2K_Transmit(uip_len);
- }
- }
-}
+
// a series of utilities to handle conncetion states
static void connected(int sockfd) {
-int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
+static int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
//int i;
-
uip_len = info->size;
// for (i = 0; i < info->size; i++) {
// uip_buf[i] = *(pkt + i);
//}
+ PrintBoth("Packet REceived\n");
+
memcpy(uip_buf, pkt, uip_len);
Free(pkt);
if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
+ PrintBoth("ARP PACKET\n");
+
uip_arp_arpin();
+
if (uip_len > 0) {
+ PrintBoth("Transmitting\n");
NE2K_Transmit(uip_len);
- }
+ }
+
} else {
-
+ PrintBoth("Data PACKET\n");
uip_arp_ipin();
uip_input();
+
if (uip_len > 0) {
+ PrintBoth("Transmitting\n");
uip_arp_out();
NE2K_Transmit(uip_len);
}
+
}
-
- return 0;
+ return 0;
}
* GeekOS timer interrupt support
* Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
* Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
- * $Revision: 1.10 $
+ * $Revision: 1.11 $
*
* This is free software. You are permitted to use,
* redistribute, and modify it as specified in the file "COPYING".
#include <geekos/serial.h>
#include <geekos/debug.h>
+#include <geekos/io_crap.h>
/* PAD this currently is in nvram.c */
extern void deliver_timer_interrupt_to_vmm(uint_t period_us);
uint_t cpu_khz_freq;
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#ifdef REALLY_SLOW_IO
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
-#else
-#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
-#endif
-
-
-
-#define __OUT1(s,x) \
-static inline void out##s(unsigned x value, unsigned short port) {
-
-#define __OUT2(s,s1,s2) \
-__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
-
-#define __OUT(s,s1,x) \
-__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
-__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
-
-
-#define __IN1(s) \
-static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
-
-#define __IN2(s,s1,s2) \
-__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
-
-#define __IN(s,s1,i...) \
-__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
-
-
-#define RETURN_TYPE unsigned char
-__IN(b,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned short
-__IN(w,"")
-#undef RETURN_TYPE
-#define RETURN_TYPE unsigned int
-__IN(l,"")
-#undef RETURN_TYPE
-__OUT(b,"b",char)
-__OUT(w,"w",short)
-
+#define MAX_TIMER_EVENTS 100
+
+static int timerDebug = 0;
+static int timeEventCount;
+static int nextEventID;
+timerEvent pendingTimerEvents[MAX_TIMER_EVENTS];
+
/*
static void Timer_Interrupt_Handler(struct Interrupt_State* state)
{
- struct Kernel_Thread* current = g_currentThread;
-
- Begin_IRQ(state);
-
-
+ int i;
+ struct Kernel_Thread* current = g_currentThread;
-#if 0
-#define STACK_LEN 256
+ Begin_IRQ(state);
- SerialPrint("Host Timer Interrupt Handler running\n");
- SerialPrint("Timer====\n");
- Dump_Interrupt_State(state);
- // SerialMemDump((unsigned char*)(¤t),STACK_LEN);
- SerialPrint("Timer done===\n");
-
-#endif
- /* Update global and per-thread number of ticks */
- ++g_numTicks;
- ++current->numTicks;
+ /* Update global and per-thread number of ticks */
+ ++g_numTicks;
+ ++current->numTicks;
+
+ /* update timer events */
+ for (i=0; i < timeEventCount; i++) {
+ if (pendingTimerEvents[i].ticks == 0) {
+ if (timerDebug) Print("timer: event %d expired (%d ticks)\n",
+ pendingTimerEvents[i].id, pendingTimerEvents[i].origTicks);
+ (pendingTimerEvents[i].callBack)(pendingTimerEvents[i].id);
+ pendingTimerEvents[i].ticks = pendingTimerEvents[i].origTicks;
+ } else {
+ pendingTimerEvents[i].ticks--;
+ }
+ }
+
+ /*
+ * If thread has been running for an entire quantum,
+ * inform the interrupt return code that we want
+ * to choose a new thread.
+ */
+ if (current->numTicks >= g_Quantum) {
+ g_needReschedule = true;
/*
- * If thread has been running for an entire quantum,
- * inform the interrupt return code that we want
- * to choose a new thread.
+ * The current process is moved to a lower priority queue,
+ * since it consumed a full quantum.
*/
- if (current->numTicks >= g_Quantum) {
- g_needReschedule = true;
- }
-
-
- deliver_timer_interrupt_to_vmm(1000000/HZ);
-
- End_IRQ(state);
+ //if (current->currentReadyQueue < (MAX_QUEUE_LEVEL - 1)) {
+ /*Print("process %d moved to ready queue %d\n", current->pid, current->currentReadyQueue); */
+ //current->currentReadyQueue++;
+ //}
+
+ }
+
+
+ deliver_timer_interrupt_to_vmm(1000000/HZ);
+
+ End_IRQ(state);
}
/*
}
+int Start_Timer(int ticks, timerCallback cb)
+{
+ int ret;
+
+ KASSERT(!Interrupts_Enabled());
+
+ if (timeEventCount == MAX_TIMER_EVENTS) {
+ return -1;
+ } else {
+ ret = nextEventID++;
+ pendingTimerEvents[timeEventCount].id = ret;
+ pendingTimerEvents[timeEventCount].callBack = cb;
+ pendingTimerEvents[timeEventCount].ticks = ticks;
+ pendingTimerEvents[timeEventCount].origTicks = ticks;
+ timeEventCount++;
+
+ return ret;
+ }
+}
+
+int Get_Remaing_Timer_Ticks(int id)
+{
+ int i;
+
+ KASSERT(!Interrupts_Enabled());
+ for (i=0; i < timeEventCount; i++) {
+ if (pendingTimerEvents[i].id == id) {
+ return pendingTimerEvents[i].ticks;
+ }
+ }
+
+ return -1;
+}
+
+int Cancel_Timer(int id)
+{
+ int i;
+ KASSERT(!Interrupts_Enabled());
+ for (i=0; i < timeEventCount; i++) {
+ if (pendingTimerEvents[i].id == id) {
+ pendingTimerEvents[i] = pendingTimerEvents[timeEventCount-1];
+ timeEventCount--;
+ return 0;
+ }
+ }
+
+ Print("timer: unable to find timer id %d to cancel it\n", id);
+ return -1;
+}
+
+
#define US_PER_TICK (HZ * 1000000)
/*
}
+
// can we start a kernel thread here...
-static int start_svm_guest(struct guest_info *info) {
+ int start_svm_guest(struct guest_info *info) {
vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
uint_t num_exits = 0;
+
/* Checks machine SVM capability */
/* Implemented from: AMD Arch Manual 3, sect 15.4 */
int is_svm_capable() {
return -1;
}
} else {
+ /*
+ ulong_t tsc_spread = 0;
+ ullong_t exit_tsc = 0;
+
+ ulong_t rax = (ulong_t)info->vm_regs.rbx;
+ ulong_t rdx = (ulong_t)info->vm_regs.rcx;
+
+ *(ulong_t *)(&exit_tsc) = rax;
+ *(((ulong_t *)(&exit_tsc)) + 1) = rdx;
+
+ tsc_spread = info->exit_tsc - exit_tsc;
+
+ PrintError("VMMCALL tsc diff = %lu\n",tsc_spread);
+ info->rip += 3;
+ */
PrintError("VMMCALL with not emulator...\n");
return -1;
}
}
+/*static int IO_Read(ushort_t port, void * dst, uint_t length, void * priv_data) {
+
+ struct guest_info * info = priv_data;
+ ulong_t tsc_spread = 0;
+ ullong_t exit_tsc = 0;
+
+
+ *(ulong_t *)(&exit_tsc) = info->vm_regs.rbx;
+ *(ulong_t *)((&exit_tsc) + 4) = info->vm_regs.rcx;
+ tsc_spread = info->exit_tsc - exit_tsc;
+
+ PrintError("IOREAD tsc diff = %lu\n",tsc_spread);
+ info->rip += 3;
+
+
+ return 1;
+}
+*/
int config_guest(struct guest_info * info, void * config_ptr) {
#endif
+ //v3_hook_io_port(info, 1234, &IO_Read, NULL, info);
+
info->rip = 0xfff0;
info->vm_regs.rsp = 0x0;
v3_hook_io_port(&vm_info, 0x61, &IO_Read, &IO_Write, NULL);
v3_hook_io_port(&vm_info, 0x05, &IO_Read, &IO_Write_to_Serial, NULL);
+
+
/*
vm_info.cr0 = 0;
vm_info.cs.base=0xf000;
#ifndef DEBUG_INTERRUPTS
#undef PrintDebug
#define PrintDebug(fmt, args...)
-#else
-#undef PrintDebug
-#define PrintDebug(fmt, args...) PrintTrace("\nvmm_intr.c(%d) "_f, __LINE__, ## _a)
#endif