Commit ae6adf99 authored by kaf24's avatar kaf24

Mini-os updates from Grzegorz Milos.

parent ad4b8954
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 $@
/* -*- 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);
}
......@@ -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]);
}
/* -*- 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_ */
/******************************************************************************
* 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)
{
......
......@@ -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_ */
/* -*- 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_ */
/*
****************************************************************************
* (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_ */
......@@ -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);
}
......@@ -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 */