aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/mini-os/Makefile26
-rw-r--r--extras/mini-os/events.c81
-rw-r--r--extras/mini-os/hypervisor.c95
-rw-r--r--extras/mini-os/include/events.h (renamed from extras/mini-os/h/events.h)25
-rw-r--r--extras/mini-os/include/hypervisor.h (renamed from extras/mini-os/h/hypervisor.h)61
-rw-r--r--extras/mini-os/include/lib.h (renamed from extras/mini-os/h/lib.h)0
-rw-r--r--extras/mini-os/include/mm.h (renamed from extras/mini-os/h/mm.h)0
-rw-r--r--extras/mini-os/include/os.h (renamed from extras/mini-os/h/os.h)58
-rw-r--r--extras/mini-os/include/time.h (renamed from extras/mini-os/h/time.h)8
-rw-r--r--extras/mini-os/include/traps.h41
-rw-r--r--extras/mini-os/include/types.h (renamed from extras/mini-os/h/types.h)0
-rw-r--r--extras/mini-os/kernel.c58
-rw-r--r--extras/mini-os/time.c108
-rw-r--r--extras/mini-os/traps.c105
-rw-r--r--extras/mini-os/x86_32.S74
15 files changed, 455 insertions, 285 deletions
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 56bc7f9e5f..60e598207d 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -1,11 +1,12 @@
+debug ?= y
-CC := gcc
-LD := ld
+include $(CURDIR)/../../Config.mk
-TARGET_ARCH := $(shell uname -m | sed -e s/i.86/x86_32/)
+# Set TARGET_ARCH
+override TARGET_ARCH := $(XEN_TARGET_ARCH)
# NB. '-Wcast-qual' is nasty, so I omitted it.
-CFLAGS := -fno-builtin -O3 -Wall -Ih/ -Wredundant-decls -Wno-format
+CFLAGS := -fno-builtin -Wall -Werror -Iinclude/ -Wredundant-decls -Wno-format
CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
ifeq ($(TARGET_ARCH),x86_32)
@@ -19,23 +20,25 @@ CFLAGS += -fno-asynchronous-unwind-tables
LDFLAGS := -m elf_x86_64
endif
+ifeq ($(debug),y)
+CFLAGS += -g
+else
+CFLAGS += -O3
+endif
+
TARGET := mini-os
OBJS := $(TARGET_ARCH).o
OBJS += $(patsubst %.c,%.o,$(wildcard *.c))
OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
-OBJS := $(subst events.o,,$(OBJS))
-OBJS := $(subst hypervisor.o,,$(OBJS))
-OBJS := $(subst time.o,,$(OBJS))
-
-HDRS := $(wildcard h/*.h)
-HDRS += $(wildcard h/xen-public/*.h)
+HDRS := $(wildcard include/*.h)
+HDRS += $(wildcard include/xen/*.h)
default: $(TARGET)
xen-public:
- [ -e h/xen-public ] || ln -sf ../../../xen/include/public h/xen-public
+ [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
$(TARGET): xen-public $(OBJS)
$(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf
@@ -51,3 +54,4 @@ clean:
%.o: %.S $(HDRS) Makefile
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $@
+
diff --git a/extras/mini-os/events.c b/extras/mini-os/events.c
index 8603fa4c37..8ca49d284b 100644
--- a/extras/mini-os/events.c
+++ b/extras/mini-os/events.c
@@ -1,20 +1,19 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
****************************************************************************
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
****************************************************************************
*
* File: events.c
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
*
- * Date: Jul 2003
+ * Date: Jul 2003, changes Jun 2005
*
* Environment: Xen Minimal OS
- * Description: Deal with events
+ * Description: Deals with events recieved on event channels
*
****************************************************************************
- * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
- ****************************************************************************
*/
#include <os.h>
@@ -22,25 +21,25 @@
#include <events.h>
#include <lib.h>
+#include <xen/event_channel.h>
static ev_action_t ev_actions[NR_EVS];
-void default_handler(int ev, struct pt_regs *regs);
+void default_handler(u32 port, struct pt_regs *regs);
/*
- * demux events to different handlers
+ * Demux events to different handlers.
*/
-unsigned int do_event(int ev, struct pt_regs *regs)
+int do_event(u32 port, struct pt_regs *regs)
{
ev_action_t *action;
- if (ev >= NR_EVS) {
- printk("Large event number %d\n", ev);
+ if (port >= NR_EVS) {
+ printk("Port number too large: %d\n", port);
return 0;
}
- action = &ev_actions[ev];
+ action = &ev_actions[port];
action->count++;
- ack_hypervisor_event(ev);
if (!action->handler)
goto out;
@@ -49,45 +48,49 @@ unsigned int do_event(int ev, struct pt_regs *regs)
goto out;
/* call the handler */
- action->handler(ev, regs);
+ action->handler(port, regs);
+
+ clear_evtchn(port);
out:
return 1;
}
-/*
- * add a handler
- */
-unsigned int add_ev_action( int ev, void (*handler)(int, struct pt_regs *) )
+int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
{
- if (ev_actions[ev].handler) {
- printk ("event[%d] already handled by %p", ev, ev_actions[ev].handler);
- return 0;
- }
+ evtchn_op_t op;
+ int ret = 0;
+ u32 port;
- ev_actions[ev].handler = handler;
- return 1;
-}
+ /* Try to bind the virq to a port */
+ op.cmd = EVTCHNOP_bind_virq;
+ op.u.bind_virq.virq = virq;
-unsigned int enable_ev_action( int ev )
-{
- if (!ev_actions[ev].handler) {
- printk ("enable event[%d], no handler installed", ev);
- return 0;
+ if ( HYPERVISOR_event_channel_op(&op) != 0 )
+ {
+ ret = 1;
+ printk("Failed to bind virtual IRQ %d\n", virq);
+ goto out;
}
- ev_actions[ev].status &= ~EVS_DISABLED;
- return 1;
-}
-unsigned int disable_ev_action( int ev )
-{
- ev_actions[ev].status |= EVS_DISABLED;
- return 1;
+ port = op.u.bind_virq.port;
+
+ if(ev_actions[port].handler)
+ printk("WARN: Handler for port %d already registered, replacing\n",
+ port);
+
+ ev_actions[port].handler = handler;
+ ev_actions[port].status &= ~EVS_DISABLED;
+
+ /* Finally unmask the port */
+ unmask_evtchn(port);
+out:
+ return ret;
}
/*
- * initially all events are without a handler and disabled
+ * Initially all events are without a handler and disabled
*/
void init_events(void)
{
@@ -101,6 +104,6 @@ void init_events(void)
}
}
-void default_handler(int ev, struct pt_regs *regs) {
- printk("X[%d] ", ev);
+void default_handler(u32 port, struct pt_regs *regs) {
+ printk("[Port %d] - event received\n", port);
}
diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c
index ee7d475b1c..53321b2a7d 100644
--- a/extras/mini-os/hypervisor.c
+++ b/extras/mini-os/hypervisor.c
@@ -4,6 +4,7 @@
* Communication to/from hypervisor.
*
* Copyright (c) 2002-2003, K A Fraser
+ * Copyright (c) 2005, Grzegorz Milos, gm281@cam.ac.uk,Intel Research Cambridge
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -26,65 +27,69 @@
#include <os.h>
#include <hypervisor.h>
+#include <events.h>
-static unsigned long event_mask = 0;
-static unsigned long ev_err_count;
+#define active_evtchns(cpu,sh,idx) \
+ ((sh)->evtchn_pending[idx] & \
+ ~(sh)->evtchn_mask[idx])
void do_hypervisor_callback(struct pt_regs *regs)
{
- unsigned long events, flags;
- shared_info_t *shared = HYPERVISOR_shared_info;
+ u32 l1, l2;
+ unsigned int l1i, l2i, port;
+ int cpu = 0;
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_data[cpu];
- do {
- /* Specialised local_irq_save(). */
- flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT,
- &shared->events_mask);
- barrier();
+ vcpu_info->evtchn_upcall_pending = 0;
+
+ /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
+ l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
+ while ( l1 != 0 )
+ {
+ l1i = __ffs(l1);
+ l1 &= ~(1 << l1i);
+
+ while ( (l2 = active_evtchns(cpu, s, l1i)) != 0 )
+ {
+ l2i = __ffs(l2);
+ l2 &= ~(1 << l2i);
- events = xchg(&shared->events, 0);
- events &= event_mask;
-
- /* 'events' now contains some pending events to handle. */
- __asm__ __volatile__ (
- " push %1 ;"
- " sub $4,%%esp ;"
- " jmp 2f ;"
- "1: btrl %%eax,%0 ;" /* clear bit */
- " mov %%eax,(%%esp) ;"
- " call do_event ;" /* do_event(event) */
- "2: bsfl %0,%%eax ;" /* %eax == bit # */
- " jnz 1b ;"
- " add $8,%%esp ;"
- /* we use %ebx because it is callee-saved */
- : : "b" (events), "r" (regs)
- /* clobbered by callback function calls */
- : "eax", "ecx", "edx", "memory" );
-
- /* Specialised local_irq_restore(). */
- if ( flags ) set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask);
- barrier();
+ port = (l1i << 5) + l2i;
+ do_event(port, regs);
+ }
}
- while ( shared->events );
}
-void enable_hypervisor_event(unsigned int ev)
+
+inline void mask_evtchn(u32 port)
{
- set_bit(ev, &event_mask);
- set_bit(ev, &HYPERVISOR_shared_info->events_mask);
- if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
- &HYPERVISOR_shared_info->events_mask) )
- do_hypervisor_callback(NULL);
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_set_bit(port, &s->evtchn_mask[0]);
}
-void disable_hypervisor_event(unsigned int ev)
+inline void unmask_evtchn(u32 port)
{
- clear_bit(ev, &event_mask);
- clear_bit(ev, &HYPERVISOR_shared_info->events_mask);
+ shared_info_t *s = HYPERVISOR_shared_info;
+ vcpu_info_t *vcpu_info = &s->vcpu_data[smp_processor_id()];
+
+ synch_clear_bit(port, &s->evtchn_mask[0]);
+
+ /*
+ * The following is basically the equivalent of 'hw_resend_irq'. Just like
+ * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
+ */
+ if ( synch_test_bit (port, &s->evtchn_pending[0]) &&
+ !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel) )
+ {
+ vcpu_info->evtchn_upcall_pending = 1;
+ if ( !vcpu_info->evtchn_upcall_mask )
+ force_evtchn_callback();
+ }
}
-void ack_hypervisor_event(unsigned int ev)
+inline void clear_evtchn(u32 port)
{
- if ( !(event_mask & (1<<ev)) )
- atomic_inc((atomic_t *)&ev_err_count);
- set_bit(ev, &HYPERVISOR_shared_info->events_mask);
+ shared_info_t *s = HYPERVISOR_shared_info;
+ synch_clear_bit(port, &s->evtchn_pending[0]);
}
diff --git a/extras/mini-os/h/events.h b/extras/mini-os/include/events.h
index c8f696ae90..7825650c57 100644
--- a/extras/mini-os/h/events.h
+++ b/extras/mini-os/include/events.h
@@ -1,34 +1,27 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
****************************************************************************
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
****************************************************************************
*
* File: events.h
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
*
- * Date: Jul 2003
+ * Date: Jul 2003, changes Jun 2005
*
* Environment: Xen Minimal OS
- * Description: deal with events
+ * Description: Deals with events on the event channels
*
****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
*/
#ifndef _EVENTS_H_
#define _EVENTS_H_
-/* _EVENT_* are defined in xen-public/xen.h */
-#define EV_BLKDEV _EVENT_BLKDEV
-#define EV_TIMER _EVENT_TIMER
-#define EV_DIE _EVENT_DIE
-#define EV_DEBUG _EVENT_DEBUG
-#define EV_NET _EVENT_NET
-#define EV_PS2 _EVENT_PS2
+#include<traps.h>
-#define NR_EVS (sizeof(HYPERVISOR_shared_info->events) * 8)
+#define NR_EVS 1024
/* ev handler status */
#define EVS_INPROGRESS 1 /* Event handler active - do not enter! */
@@ -44,10 +37,8 @@ typedef struct _ev_action_t {
} ev_action_t;
/* prototypes */
-unsigned int do_event(int ev, struct pt_regs *regs);
-unsigned int add_ev_action( int ev, void (*handler)(int, struct pt_regs *) );
-unsigned int enable_ev_action( int ev );
-unsigned int disable_ev_action( int ev );
+int do_event(u32 port, struct pt_regs *regs);
+int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
void init_events(void);
#endif /* _EVENTS_H_ */
diff --git a/extras/mini-os/h/hypervisor.h b/extras/mini-os/include/hypervisor.h
index c167850d55..f0467bb9e2 100644
--- a/extras/mini-os/h/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -1,9 +1,12 @@
/******************************************************************************
* hypervisor.h
*
- * Linux-specific hypervisor handling.
+ * Hypervisor handling.
*
+ * TODO - x86_64 broken!
+ *
* Copyright (c) 2002, K A Fraser
+ * Copyright (c) 2005, Grzegorz Milos
*/
#ifndef _HYPERVISOR_H_
@@ -11,8 +14,10 @@
#include <types.h>
-#include <xen-public/xen.h>
-#include <xen-public/io/domain_controller.h>
+#include <xen/xen.h>
+#include <xen/io/domain_controller.h>
+
+
/*
* a placeholder for the start of day information passed up from the hypervisor
@@ -27,10 +32,10 @@ extern union start_info_union start_info_union;
/* hypervisor.c */
-void do_hypervisor_callback(struct pt_regs *regs);
-void enable_hypervisor_event(unsigned int ev);
-void disable_hypervisor_event(unsigned int ev);
-void ack_hypervisor_event(unsigned int ev);
+//void do_hypervisor_callback(struct pt_regs *regs);
+void mask_evtchn(u32 port);
+void unmask_evtchn(u32 port);
+void clear_evtchn(u32 port);
/*
* Assembler stubs for hyper-calls.
@@ -48,6 +53,20 @@ void ack_hypervisor_event(unsigned int ev);
#define _a4 "b"
#endif
+static __inline__ int HYPERVISOR_event_channel_op(
+ void *op)
+{
+ int ret;
+ unsigned long ignore;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ignore)
+ : "0" (__HYPERVISOR_event_channel_op), "1" (op)
+ : "memory" );
+
+ return ret;
+}
+
static __inline__ int HYPERVISOR_set_trap_table(trap_info_t *table)
{
int ret;
@@ -201,16 +220,38 @@ static __inline__ int HYPERVISOR_suspend(unsigned long srec)
return ret;
}
-static __inline__ long HYPERVISOR_set_timer_op(void *timer_arg)
+#ifdef __i386__
+static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
{
int ret;
+ unsigned long timeout_hi = (unsigned long)(timeout>>32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ unsigned long ign1, ign2;
+
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_timer_op),
- _a1 (timer_arg) : "memory" );
+ : "=a" (ret), "=b" (ign1), "=c" (ign2)
+ : "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
+ : "memory");
return ret;
}
+#else
+static __inline__ long HYPERVISOR_set_timer_op( u64 timeout )
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret)
+ : "0" ((unsigned long)__HYPERVISOR_set_timer_op),
+ "D" (timeout)
+ : __syscall_clobber );
+
+ return ret;
+}
+#endif
+
static __inline__ int HYPERVISOR_dom0_op(void *dom0_op)
{
diff --git a/extras/mini-os/h/lib.h b/extras/mini-os/include/lib.h
index 0b405ee006..0b405ee006 100644
--- a/extras/mini-os/h/lib.h
+++ b/extras/mini-os/include/lib.h
diff --git a/extras/mini-os/h/mm.h b/extras/mini-os/include/mm.h
index c5f6ad4788..c5f6ad4788 100644
--- a/extras/mini-os/h/mm.h
+++ b/extras/mini-os/include/mm.h
diff --git a/extras/mini-os/h/os.h b/extras/mini-os/include/os.h
index 434dd992f6..490abc9839 100644
--- a/extras/mini-os/h/os.h
+++ b/extras/mini-os/include/os.h
@@ -23,7 +23,7 @@
#ifndef __ASSEMBLY__
#include <types.h>
#endif
-#include <xen-public/xen.h>
+#include <xen/xen.h>
#define __KERNEL_CS FLAT_KERNEL_CS
#define __KERNEL_DS FLAT_KERNEL_DS
@@ -57,7 +57,6 @@
#define pt_regs xen_regs
void trap_init(void);
-void dump_regs(struct pt_regs *regs);
/*
* The use of 'barrier' in the following reflects their use as local-lock
@@ -274,7 +273,62 @@ static __inline__ void atomic_inc(atomic_t *v)
#define rdtscll(val) \
__asm__ __volatile__("rdtsc" : "=A" (val))
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+ __asm__("bsfl %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
+#define ADDR (*(volatile long *) addr)
+
+static __inline__ void synch_set_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__ (
+ "lock btsl %1,%0"
+ : "=m" (ADDR) : "Ir" (nr) : "memory" );
+}
+static __inline__ void synch_clear_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__ (
+ "lock btrl %1,%0"
+ : "=m" (ADDR) : "Ir" (nr) : "memory" );
+}
+
+static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "lock btsl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit), "=m" (ADDR) : "Ir" (nr) : "memory");
+ return oldbit;
+}
+
+
+static __inline__ int synch_const_test_bit(int nr, const volatile void * addr)
+{
+ return ((1UL << (nr & 31)) &
+ (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+ __asm__ __volatile__ (
+ "btl %2,%1\n\tsbbl %0,%0"
+ : "=r" (oldbit) : "m" (ADDR), "Ir" (nr) );
+ return oldbit;
+}
+
+#define synch_test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ synch_const_test_bit((nr),(addr)) : \
+ synch_var_test_bit((nr),(addr)))
#endif /* !__ASSEMBLY__ */
+#define rdtsc(low,high) \
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
#endif /* _OS_H_ */
diff --git a/extras/mini-os/h/time.h b/extras/mini-os/include/time.h
index 06fa97d68d..40b4c212fa 100644
--- a/extras/mini-os/h/time.h
+++ b/extras/mini-os/include/time.h
@@ -1,20 +1,19 @@
/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
****************************************************************************
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
****************************************************************************
*
* File: time.h
* Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
- * Changes:
+ * Changes: Grzegorz Milos (gm281@cam.ac.uk)
*
- * Date: Jul 2003
+ * Date: Jul 2003, changesJun 2005
*
* Environment: Xen Minimal OS
* Description: Time and timer functions
*
****************************************************************************
- * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $
- ****************************************************************************
*/
#ifndef _TIME_H_
@@ -53,5 +52,6 @@ void init_time(void);
s_time_t get_s_time(void);
s_time_t get_v_time(void);
void gettimeofday(struct timeval *tv);
+void block(u32 millisecs);
#endif /* _TIME_H_ */
diff --git a/extras/mini-os/include/traps.h b/extras/mini-os/include/traps.h
new file mode 100644
index 0000000000..258ae819f9
--- /dev/null
+++ b/extras/mini-os/include/traps.h
@@ -0,0 +1,41 @@
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Reseach Cambridge
+ ****************************************************************************
+ *
+ * File: traps.h
+ * Author: Grzegorz Milos (gm281@cam.ac.uk)
+ *
+ * Date: Jun 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: Deals with traps
+ *
+ ****************************************************************************
+ */
+
+#ifndef _TRAPS_H_
+#define _TRAPS_H_
+
+struct pt_regs {
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long eax;
+ int xds;
+ int xes;
+ long orig_eax;
+ long eip;
+ int xcs;
+ long eflags;
+ long esp;
+ int xss;
+};
+
+
+void dump_regs(struct pt_regs *regs);
+
+#endif /* _TRAPS_H_ */
diff --git a/extras/mini-os/h/types.h b/extras/mini-os/include/types.h
index 7bf103ab9c..7bf103ab9c 100644
--- a/extras/mini-os/h/types.h
+++ b/extras/mini-os/include/types.h
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index b6f89b8bbb..85b55f1ab0 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -5,6 +5,7 @@
* from head.S.
*
* Copyright (c) 2002-2003, K A Fraser & R Neugebauer
+ * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -56,10 +57,6 @@ char stack[8192];
void hypervisor_callback(void);
void failsafe_callback(void);
-/* default event handlers */
-static void exit_handler(int ev, struct pt_regs *regs);
-static void debug_handler(int ev, struct pt_regs *regs);
-
extern char shared_info[PAGE_SIZE];
static shared_info_t *map_shared_info(unsigned long pa)
@@ -80,6 +77,7 @@ static shared_info_t *map_shared_info(unsigned long pa)
void start_kernel(start_info_t *si)
{
static char hello[] = "Bootstrapping...\n";
+ int i;
(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
/* Copy the start_info struct to a globally-accessible area. */
@@ -126,28 +124,32 @@ void start_kernel(start_info_t *si)
init_mm();
/* set up events */
-// init_events();
-
- /*
- * These need to be replaced with event-channel/control-interface
- * equivalents.
- */
-#if 0
- /* Install some handlers. */
- add_ev_action(EV_DIE, &exit_handler);
- enable_ev_action(EV_DIE);
- enable_hypervisor_event(EV_DIE);
-
- add_ev_action(EV_DEBUG, &debug_handler);
- enable_ev_action(EV_DEBUG);
- enable_hypervisor_event(EV_DEBUG);
-#endif
-
+ init_events();
/* init time and timers */
-// init_time();
+ init_time();
/* do nothing */
- for ( ; ; ) HYPERVISOR_yield();
+ i = 0;
+ for ( ; ; )
+ {
+ if(i >= 1000)
+ {
+ {
+ unsigned long saved;
+ __asm__ ("movl %%esp, %0"
+ :"=r"(saved) /* y is output operand */
+ /* x is input operand */);
+// :"a"); /* %eax is clobbered register */
+ printk("ESP=0x%lx\n", saved);
+ }
+
+ printk("1000 bloks\n");
+ i=0;
+ }
+// HYPERVISOR_yield();
+ block(1);
+ i++;
+ }
}
@@ -163,13 +165,3 @@ void do_exit(void)
printk("do_exit called!\n");
for ( ;; ) HYPERVISOR_shutdown();
}
-static void exit_handler(int ev, struct pt_regs *regs) {
- do_exit();
-}
-
-/*
- * a debug handler to print out some state from the guest
- */
-static void debug_handler(int ev, struct pt_regs *regs) {
- dump_regs(regs);
-}
diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c
index df3a62e4dd..ca48a6ae1d 100644
--- a/extras/mini-os/time.c
+++ b/extras/mini-os/time.c
@@ -2,10 +2,12 @@
****************************************************************************
* (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
* (C) 2002-2003 - Keir Fraser - University of Cambridge
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
****************************************************************************
*
* File: time.c
* Author: Rolf Neugebauer and Keir Fraser
+ * Changes: Grzegorz Milos
*
* Description: Simple time and timer functions
*
@@ -30,6 +32,7 @@
#include <os.h>
+#include <traps.h>
#include <types.h>
#include <hypervisor.h>
#include <events.h>
@@ -40,9 +43,13 @@
* Time functions
*************************************************************************/
-static unsigned int rdtsc_bitshift;
-static u32 st_scale_f; /* convert ticks -> usecs */
-static u32 st_scale_i; /* convert ticks -> usecs */
+/* Cached *multiplier* to convert TSC counts to microseconds.
+ * (see the equation below).
+ * Equal to 2^32 * (1 / (clocks per usec) ).
+ * Initialized in time_init.
+ */
+static unsigned long fast_gettimeoffset_quotient;
+
/* These are peridically updated in shared_info, and then copied here. */
static u32 shadow_tsc_stamp;
@@ -70,7 +77,7 @@ static void get_time_values_from_xen(void)
rmb();
shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec;
shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec;
- shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp.tsc_bits;
+ shadow_tsc_stamp = (u32)HYPERVISOR_shared_info->tsc_timestamp;
shadow_system_time = HYPERVISOR_shared_info->system_time;
rmb();
}
@@ -81,22 +88,33 @@ static void get_time_values_from_xen(void)
#define TIME_VALUES_UP_TO_DATE \
(shadow_time_version == HYPERVISOR_shared_info->time_version2)
-
-static __inline__ unsigned long get_time_delta_usecs(void)
+static u32 get_time_delta_usecs(void)
{
- s32 delta_tsc;
- u32 low;
- u64 delta, tsc;
-
- rdtscll(tsc);
- low = (u32)(tsc >> rdtsc_bitshift);
- delta_tsc = (s32)(low - shadow_tsc_stamp);
- if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
- delta = ((u64)delta_tsc * st_scale_f);
- delta >>= 32;
- delta += ((u64)delta_tsc * st_scale_i);
-
- return (unsigned long)delta;
+ register unsigned long eax, edx;
+
+ /* Read the Time Stamp Counter */
+
+ rdtsc(eax,edx);
+
+ /* .. relative to previous jiffy (32 bits is enough) */
+ eax -= shadow_tsc_stamp;
+
+ /*
+ * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
+ * = (tsc_low delta) * (usecs_per_clock)
+ * = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
+ *
+ * Using a mull instead of a divl saves up to 31 clock cycles
+ * in the critical path.
+ */
+
+ __asm__("mull %2"
+ :"=a" (eax), "=d" (edx)
+ :"rm" (fast_gettimeoffset_quotient),
+ "0" (eax));
+
+ /* our adjusted time offset in microseconds */
+ return edx;
}
s64 get_s_time (void)
@@ -139,6 +157,25 @@ void gettimeofday(struct timeval *tv)
*tv = _tv;
}
+static void print_current_time(void)
+{
+ struct timeval tv;
+
+ get_time_values_from_xen();
+
+ gettimeofday(&tv);
+ printk("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
+}
+
+void block(u32 millisecs)
+{
+ struct timeval tv;
+ gettimeofday(&tv);
+ //printk("tv.tv_sec=%ld, tv.tv_usec=%ld, shadow_system_time=%lld\n", tv.tv_sec, tv.tv_usec, shadow_system_time );
+ HYPERVISOR_set_timer_op(get_s_time() + 1000000LL * (s64) millisecs);
+ HYPERVISOR_block();
+}
+
/*
* Just a dummy
@@ -146,41 +183,38 @@ void gettimeofday(struct timeval *tv)
static void timer_handler(int ev, struct pt_regs *regs)
{
static int i;
- struct timeval tv;
get_time_values_from_xen();
i++;
if (i >= 1000) {
- gettimeofday(&tv);
- printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
+ print_current_time();
i = 0;
}
}
+
void init_time(void)
{
- u64 __cpu_khz, cpu_freq, scale;
+ u64 __cpu_khz;
unsigned long cpu_khz;
__cpu_khz = HYPERVISOR_shared_info->cpu_freq;
- cpu_khz = (u32) (__cpu_khz/1000);
-
- rdtsc_bitshift = HYPERVISOR_shared_info->tsc_timestamp.tsc_bitshift;
- cpu_freq = HYPERVISOR_shared_info->cpu_freq;
-
- scale = 1000000LL << (32 + rdtsc_bitshift);
- scale /= cpu_freq;
- st_scale_f = scale & 0xffffffff;
- st_scale_i = scale >> 32;
+ cpu_khz = (u32) (__cpu_khz/1000);
printk("Xen reported: %lu.%03lu MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
-
- add_ev_action(EV_TIMER, &timer_handler);
- enable_ev_action(EV_TIMER);
- enable_hypervisor_event(EV_TIMER);
-
+ /* (10^6 * 2^32) / cpu_hz = (10^3 * 2^32) / cpu_khz =
+ (2^32 * 1 / (clocks/us)) */
+ {
+ unsigned long eax=0, edx=1000;
+ __asm__("divl %2"
+ :"=a" (fast_gettimeoffset_quotient), "=d" (edx)
+ :"r" (cpu_khz),
+ "0" (eax), "1" (edx));
+ }
+
+ bind_virq(VIRQ_TIMER, &timer_handler);
}
diff --git a/extras/mini-os/traps.c b/extras/mini-os/traps.c
index 7000128230..2bbca77f54 100644
--- a/extras/mini-os/traps.c
+++ b/extras/mini-os/traps.c
@@ -1,5 +1,6 @@
#include <os.h>
+#include <traps.h>
#include <hypervisor.h>
#include <mm.h>
#include <lib.h>
@@ -37,21 +38,22 @@ void dump_regs(struct pt_regs *regs)
#ifdef __x86_64__
esp = regs->rsp;
- ss = regs->ss;
+ ss = regs->xss;
#else
esp = (unsigned long) (&regs->esp);
ss = __KERNEL_DS;
- if (regs->cs & 2) {
+ if (regs->xcs & 2) {
+printk("CS is true, esp is %x\n", regs->esp);
esp = regs->esp;
- ss = regs->ss & 0xffff;
+ ss = regs->xss & 0xffff;
}
#endif
- printf("EIP: %04x:[<%p>] %08x\n",
- 0xffff & regs->cs , regs->eip, regs->error_code);
+ printf("EIP: %04x:[<%p>]\n",
+ 0xffff & regs->xcs , regs->eip);
printf("EFLAGS: %p\n",regs->eflags);
- printf("eax: %p ebx: %p ecx: %p edx: %p\n",
+ printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
- printf("esi: %p edi: %p ebp: %p esp: %p\n",
+ printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, esp);
#ifdef __x86_64__
printf("r8 : %p r9 : %p r10: %p r11: %p\n",
@@ -60,40 +62,28 @@ void dump_regs(struct pt_regs *regs)
regs->r12, regs->r13, regs->r14, regs->r15);
#endif
printf("ds: %04x es: %04x ss: %04x\n",
- regs->ds & 0xffff, regs->es & 0xffff, ss);
+ regs->xds & 0xffff, regs->xes & 0xffff, ss);
}
-static __inline__ void dump_code(unsigned long eip)
+static void do_trap(int trapnr, char *str, struct pt_regs * regs, unsigned long error_code)
{
- unsigned char *ptr = (unsigned char *)eip;
- int x;
-
- printk("Bytes at eip: ");
- for ( x = -4; x < 5; x++ )
- printf("%02x ", ptr[x]);
- printk("\n");
-}
-
-static void __inline__ do_trap(int trapnr, char *str,
- struct pt_regs * regs)
-{
- printk("FATAL: Unhandled Trap %d (%s)\n", trapnr, str);
+ printk("FATAL: Unhandled Trap %d (%s), error code=0x%lx\n", trapnr, str, error_code);
+ printk("Regs address %p\n", regs);
dump_regs(regs);
- dump_code(regs->eip);
do_exit();
}
#define DO_ERROR(trapnr, str, name) \
-void do_##name(struct pt_regs * regs) \
+void do_##name(struct pt_regs * regs, unsigned long error_code) \
{ \
- do_trap(trapnr, str, regs); \
+ do_trap(trapnr, str, regs, error_code); \
}
#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
-void do_##name(struct pt_regs * regs) \
+void do_##name(struct pt_regs * regs, unsigned long error_code) \
{ \
- do_trap(trapnr, str, regs); \
+ do_trap(trapnr, str, regs, error_code); \
}
DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
@@ -109,13 +99,11 @@ DO_ERROR(12, "stack segment", stack_segment)
DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
DO_ERROR(18, "machine check", machine_check)
-extern unsigned long virt_cr2;
-void do_page_fault(struct pt_regs *regs)
+void do_page_fault(struct pt_regs *regs, unsigned long error_code,
+ unsigned long addr)
{
- unsigned long addr = virt_cr2;
printk("Page fault at linear address %p\n", addr);
dump_regs(regs);
- dump_code(regs->eip);
#ifdef __x86_64__
{
unsigned long *tab = (unsigned long *)start_info.pt_base;
@@ -126,35 +114,33 @@ void do_page_fault(struct pt_regs *regs)
page = tab[l4_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L4 = %p (%p)\n", page, tab);
- if ( !(page & _PAGE_PRESENT) )
+ if ( !(page & AGERESENT) )
goto out;
page = tab[l3_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L3 = %p (%p)\n", page, tab);
- if ( !(page & _PAGE_PRESENT) )
+ if ( !(page & AGERESENT) )
goto out;
page = tab[l2_table_offset(addr)];
tab = __va(mfn_to_pfn(pte_to_mfn(page)) << PAGE_SHIFT);
printk(" L2 = %p (%p) %s\n", page, tab,
- (page & _PAGE_PSE) ? "(2MB)" : "");
- if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) )
+ (page & AGESE) ? "(2MB)" : "");
+ if ( !(page & AGERESENT) || (page & AGESE) )
goto out;
page = tab[l1_table_offset(addr)];
printk(" L1 = %p\n", page);
}
#endif
- out:
do_exit();
}
-void do_general_protection(struct pt_regs *regs)
+void do_general_protection(struct pt_regs *regs, long error_code)
{
- printk("GPF\n");
+ printk("GPF %p, error_code=%lx\n", regs, error_code);
dump_regs(regs);
- dump_code(regs->eip);
do_exit();
}
@@ -172,7 +158,6 @@ void do_coprocessor_error(struct pt_regs * regs)
{
printk("Copro error\n");
dump_regs(regs);
- dump_code(regs->eip);
do_exit();
}
@@ -196,28 +181,25 @@ void do_spurious_interrupt_bug(struct pt_regs * regs)
* The 'privilege ring' field specifies the least-privileged ring that
* can trap to that vector using a software-interrupt instruction (INT).
*/
-#ifdef __x86_64__
-#define _P 0,
-#endif
static trap_info_t trap_table[] = {
- { 0, 0, __KERNEL_CS, _P (unsigned long)divide_error },
- { 1, 0, __KERNEL_CS, _P (unsigned long)debug },
- { 3, 3, __KERNEL_CS, _P (unsigned long)int3 },
- { 4, 3, __KERNEL_CS, _P (unsigned long)overflow },
- { 5, 3, __KERNEL_CS, _P (unsigned long)bounds },
- { 6, 0, __KERNEL_CS, _P (unsigned long)invalid_op },
- { 7, 0, __KERNEL_CS, _P (unsigned long)device_not_available },
- { 9, 0, __KERNEL_CS, _P (unsigned long)coprocessor_segment_overrun },
- { 10, 0, __KERNEL_CS, _P (unsigned long)invalid_TSS },
- { 11, 0, __KERNEL_CS, _P (unsigned long)segment_not_present },
- { 12, 0, __KERNEL_CS, _P (unsigned long)stack_segment },
- { 13, 0, __KERNEL_CS, _P (unsigned long)general_protection },
- { 14, 0, __KERNEL_CS, _P (unsigned long)page_fault },
- { 15, 0, __KERNEL_CS, _P (unsigned long)spurious_interrupt_bug },
- { 16, 0, __KERNEL_CS, _P (unsigned long)coprocessor_error },
- { 17, 0, __KERNEL_CS, _P (unsigned long)alignment_check },
- { 18, 0, __KERNEL_CS, _P (unsigned long)machine_check },
- { 19, 0, __KERNEL_CS, _P (unsigned long)simd_coprocessor_error },
+ { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
+ { 1, 0, __KERNEL_CS, (unsigned long)debug },
+ { 3, 3, __KERNEL_CS, (unsigned long)int3 },
+ { 4, 3, __KERNEL_CS, (unsigned long)overflow },
+ { 5, 3, __KERNEL_CS, (unsigned long)bounds },
+ { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
+ { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
+ { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+ { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
+ { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
+ { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
+ { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
+ { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
+ { 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
+ { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
+ { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
+ { 18, 0, __KERNEL_CS, (unsigned long)machine_check },
+ { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
{ 0, 0, 0, 0 }
};
@@ -227,3 +209,4 @@ void trap_init(void)
{
HYPERVISOR_set_trap_table(trap_table);
}
+
diff --git a/extras/mini-os/x86_32.S b/extras/mini-os/x86_32.S
index c02048f9a0..3daeb2167d 100644
--- a/extras/mini-os/x86_32.S
+++ b/extras/mini-os/x86_32.S
@@ -1,4 +1,6 @@
#include <os.h>
+#include <xen/arch-x86_32.h>
+
.section __xen_guest
.asciz "XEN_VER=3.0,LOADER=generic,PT_MODE_WRITABLE"
@@ -21,6 +23,7 @@ stack_start:
shared_info:
.org 0x2000
+
ES = 0x20
ORIG_EAX = 0x24
EIP = 0x28
@@ -62,6 +65,31 @@ ENTRY(divide_error)
do_exception:
pushl %ds
pushl %eax
+ xorl %eax, %eax
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ decl %eax # eax = -1
+ pushl %ecx
+ pushl %ebx
+ cld
+ movl %es, %ecx
+ movl ES(%esp), %edi # get the function address
+ movl ORIG_EAX(%esp), %edx # get the error code
+ movl %eax, ORIG_EAX(%esp)
+ movl %ecx, ES(%esp)
+ movl $(__KERNEL_DS), %ecx
+ movl %ecx, %ds
+ movl %ecx, %es
+ movl %esp,%eax # pt_regs pointer
+ pushl %edx
+ pushl %eax
+ call *%edi
+ addl $8,%esp
+
+/* pushl %ds
+ pushl %eax
xorl %eax,%eax
pushl %ebp
pushl %edi
@@ -83,7 +111,7 @@ do_exception:
movl %edx,%ds
movl %edx,%es
call *%edi
- addl $8,%esp
+ addl $8,%esp */
ret_from_exception:
@@ -112,19 +140,19 @@ ENTRY(hypervisor_callback)
cmpl $ecrit,%eax
jb critical_region_fixup
11: push %esp
-# call do_hypervisor_callback
+ call do_hypervisor_callback
add $4,%esp
movl HYPERVISOR_shared_info,%esi
xorl %eax,%eax
movb CS(%esp),%cl
test $2,%cl # slow return to ring 2 or 3
jne safesti
-safesti:btsl $31,4(%esi) # reenable event callbacks
+safesti:movb $0,1(%esi) # reenable event callbacks
scrit: /**** START OF CRITICAL REGION ****/
- cmpl %eax,(%esi)
- jne 14f # process more events if necessary...
+ testb $0xFF,(%esi)
+ jnz 14f # process more events if necessary...
RESTORE_ALL
-14: btrl %eax,4(%esi)
+14: movb $1,1(%esi)
jmp 11b
ecrit: /**** END OF CRITICAL REGION ****/
# [How we do the fixup]. We want to merge the current stack frame with the
@@ -153,7 +181,7 @@ critical_region_fixup:
jmp 11b
critical_fixup_table:
- .byte 0x00,0x00 # cmpl %eax,(%esi)
+ .byte 0x00,0x00,0x00 # testb $0xff,(%esi)
.byte 0x00,0x00 # jne 14f
.byte 0x00 # pop %ebx
.byte 0x04 # pop %ecx
@@ -166,7 +194,7 @@ critical_fixup_table:
.byte 0x20 # pop %es
.byte 0x24,0x24,0x24 # add $4,%esp
.byte 0x28 # iret
- .byte 0x00,0x00,0x00,0x00,0x00 # btrl $31,4(%esi)
+ .byte 0x00,0x00,0x00,0x00 # movb $1,1(%esi)
.byte 0x00,0x00 # jmp 11b
# Hypervisor uses this for application faults while it executes.
@@ -220,10 +248,6 @@ ENTRY(coprocessor_segment_overrun)
pushl $do_coprocessor_segment_overrun
jmp do_exception
-ENTRY(double_fault)
- pushl $do_double_fault
- jmp do_exception
-
ENTRY(invalid_TSS)
pushl $do_invalid_TSS
jmp do_exception
@@ -246,32 +270,30 @@ ENTRY(alignment_check)
# This handler is special, because it gets an extra value on its stack,
# which is the linear faulting address.
+# fastcall register usage: %eax = pt_regs, %edx = error code,
+# %ecx = fault address
ENTRY(page_fault)
pushl %ds
pushl %eax
- xorl %eax,%eax
+ xorl %eax, %eax
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
- decl %eax # eax = -1
+ decl %eax /* eax = -1 */
pushl %ecx
pushl %ebx
cld
- movl %es,%ecx
- movl ORIG_EAX(%esp), %esi # get the error code
- movl ES(%esp), %edi # get the faulting address
+ movl %es,%edi
+ movl ES(%esp), %ecx /* get the faulting address */
+ movl ORIG_EAX(%esp), %edx /* get the error code */
movl %eax, ORIG_EAX(%esp)
- movl %ecx, ES(%esp)
- movl %esp,%edx
- pushl %edi # push the faulting address
- pushl %esi # push the error code
- pushl %edx # push the pt_regs pointer
- movl $(__KERNEL_DS),%edx
- movl %edx,%ds
- movl %edx,%es
+ movl %edi, ES(%esp)
+ movl $(__KERNEL_DS),%eax
+ movl %eax, %ds
+ movl %eax, %es
+ movl %esp,%eax /* pt_regs pointer */
call do_page_fault
- addl $12,%esp
jmp ret_from_exception
ENTRY(machine_check)