diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-07-06 10:46:29 +0000 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-07-06 10:46:29 +0000 |
commit | b7d34829a343a9fcc9e5d6a64d6138bc6ce0d160 (patch) | |
tree | 55fdbbc8a6878bbfcbc00826dce1138f17d721e2 /extras/mini-os | |
parent | 3f54e6d5ece9b20caa0fd77d2c8342c69c6733b2 (diff) | |
download | xen-b7d34829a343a9fcc9e5d6a64d6138bc6ce0d160.tar.gz xen-b7d34829a343a9fcc9e5d6a64d6138bc6ce0d160.tar.bz2 xen-b7d34829a343a9fcc9e5d6a64d6138bc6ce0d160.zip |
Mini-os updates from Grzegorz Milos.
Diffstat (limited to 'extras/mini-os')
-rw-r--r-- | extras/mini-os/Makefile | 26 | ||||
-rw-r--r-- | extras/mini-os/events.c | 81 | ||||
-rw-r--r-- | extras/mini-os/hypervisor.c | 95 | ||||
-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.h | 41 | ||||
-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.c | 58 | ||||
-rw-r--r-- | extras/mini-os/time.c | 108 | ||||
-rw-r--r-- | extras/mini-os/traps.c | 105 | ||||
-rw-r--r-- | extras/mini-os/x86_32.S | 74 |
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) (®s->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) |