aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-10-30 17:33:14 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-10-30 17:33:14 +0000
commit5cf5933f37cfba4c99aea8d70cca2d89da0344bb (patch)
tree2ca0c4f737197ee1f9b61534c660c69d6c9a5e27 /extras
parent2eef9a8f5271d12c3a484fc49a573e206369bacd (diff)
downloadxen-5cf5933f37cfba4c99aea8d70cca2d89da0344bb.tar.gz
xen-5cf5933f37cfba4c99aea8d70cca2d89da0344bb.tar.bz2
xen-5cf5933f37cfba4c99aea8d70cca2d89da0344bb.zip
bitkeeper revision 1.541.1.1 (3fa14b5aVZfwzFArgab1vhsTUV0TOA)
time.c, hypervisor.h, kernel.c, head.S: Fix minios to work with revised Xen 1.2 interface.
Diffstat (limited to 'extras')
-rw-r--r--extras/mini-os/h/hypervisor.h12
-rw-r--r--extras/mini-os/head.S9
-rw-r--r--extras/mini-os/kernel.c23
-rw-r--r--extras/mini-os/time.c142
4 files changed, 105 insertions, 81 deletions
diff --git a/extras/mini-os/h/hypervisor.h b/extras/mini-os/h/hypervisor.h
index 23c39134f3..4c4d752615 100644
--- a/extras/mini-os/h/hypervisor.h
+++ b/extras/mini-os/h/hypervisor.h
@@ -255,4 +255,16 @@ static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val)
return ret;
}
+static inline int HYPERVISOR_update_va_mapping(
+ unsigned long page_nr, unsigned long new_val, unsigned long flags)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping),
+ "b" (page_nr), "c" (new_val), "d" (flags) );
+
+ return ret;
+}
+
#endif /* __HYPERVISOR_H__ */
diff --git a/extras/mini-os/head.S b/extras/mini-os/head.S
index d5cb19f574..4a2ccbbe1e 100644
--- a/extras/mini-os/head.S
+++ b/extras/mini-os/head.S
@@ -4,9 +4,8 @@
#define MOD_START 4
#define MOD_LEN 8
-#define ENTRY(X) .globl X ; X :
-
-.globl _start
+.globl _start, shared_info
+
_start:
cld
@@ -43,3 +42,7 @@ stack_start:
.long stack+8192, __KERNEL_DS
+ /* Unpleasant -- we actually use this PTE to map shared_info :-) */
+ .org 0x1000
+shared_info:
+ .org 0x2000
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 12d36f1347..0ead3f18d3 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -61,6 +61,19 @@ static void exit_handler(int ev, struct pt_regs *regs);
static void debug_handler(int ev, struct pt_regs *regs);
+static shared_info_t *map_shared_info(unsigned long pa)
+{
+ extern char shared_info[PAGE_SIZE];
+ if ( HYPERVISOR_update_va_mapping((unsigned long)shared_info >> PAGE_SHIFT,
+ pa | 3, UVMF_INVLPG) )
+ {
+ printk("Failed to map shared_info!!\n");
+ *(int*)0=0;
+ }
+ return (shared_info_t *)shared_info;
+}
+
+
/*
* INITIAL C ENTRY POINT.
*/
@@ -72,25 +85,23 @@ void start_kernel(start_info_t *si)
memcpy(&start_info, si, sizeof(*si));
/* Grab the shared_info pointer and put it in a safe place. */
- HYPERVISOR_shared_info = start_info.shared_info;
+ HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
/* Set up event and failsafe callback addresses. */
HYPERVISOR_set_callbacks(
__KERNEL_CS, (unsigned long)hypervisor_callback,
__KERNEL_CS, (unsigned long)failsafe_callback);
-
trap_init();
-
/* ENABLE EVENT DELIVERY. This is disabled at start of day. */
__sti();
/* print out some useful information */
printk("Xeno Minimal OS!\n");
printk("start_info: %p\n", si);
- printk(" nr_pages: %lu", si->nr_pages);
- printk(" shared_inf: %p\n", si->shared_info);
+ printk(" nr_pages: %lu", si->nr_pages);
+ printk(" shared_inf: %08lx\n", si->shared_info);
printk(" pt_base: %p", (void *)si->pt_base);
printk(" mod_start: 0x%lx\n", si->mod_start);
printk(" mod_len: %lu\n", si->mod_len);
@@ -142,7 +153,7 @@ void start_kernel(start_info_t *si)
void do_exit(void)
{
printk("do_exit called!\n");
- for ( ;; ) ;
+ for ( ;; ) HYPERVISOR_exit();
}
static void exit_handler(int ev, struct pt_regs *regs) {
do_exit();
diff --git a/extras/mini-os/time.c b/extras/mini-os/time.c
index 8e7de4e20d..23b31794ba 100644
--- a/extras/mini-os/time.c
+++ b/extras/mini-os/time.c
@@ -47,102 +47,91 @@
*************************************************************************/
static unsigned int rdtsc_bitshift;
-static u32 st_scale_f;
-static u32 st_scale_i;
-static u32 shadow_st_pcc;
-static s_time_t shadow_st;
-static u32 shadow_wc_version=0;
-static long shadow_tv_sec;
-static long shadow_tv_usec;
-static s_time_t shadow_wc_timestamp;
-
-/*
- * System time.
- * We need to read the values from the shared info page "atomically"
- * and use the cycle counter value as the "version" number. Clashes
- * should be very rare.
- */
-inline s_time_t get_s_time(void)
+static u32 st_scale_f; /* convert ticks -> usecs */
+static u32 st_scale_i; /* convert ticks -> usecs */
+
+/* These are peridically updated in shared_info, and then copied here. */
+static u32 shadow_tsc_stamp;
+static s64 shadow_system_time;
+static u32 shadow_time_version;
+static struct timeval shadow_tv;
+
+#ifndef rmb
+#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+#endif
+
+#define HANDLE_USEC_OVERFLOW(_tv) \
+ do { \
+ while ( (_tv).tv_usec >= 1000000 ) \
+ { \
+ (_tv).tv_usec -= 1000000; \
+ (_tv).tv_sec++; \
+ } \
+ } while ( 0 )
+
+static void get_time_values_from_xen(void)
{
- s32 delta_tsc;
- u32 low;
- u64 delta, tsc;
- u32 version;
- u64 cpu_freq, scale;
-
- /* check if our values are still up-to-date */
- while ( (version = HYPERVISOR_shared_info->wc_version) !=
- shadow_wc_version )
- {
- barrier();
-
- shadow_wc_version = version;
- shadow_tv_sec = HYPERVISOR_shared_info->tv_sec;
- shadow_tv_usec = HYPERVISOR_shared_info->tv_usec;
- shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp;
- shadow_st_pcc = HYPERVISOR_shared_info->st_timestamp;
- shadow_st = HYPERVISOR_shared_info->system_time;
-
- rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift;
- cpu_freq = HYPERVISOR_shared_info->cpu_freq;
-
- /* XXX cpu_freq as u32 limits it to 4.29 GHz. Get a better do_div! */
- scale = 1000000000LL << (32 + rdtsc_bitshift);
- scale /= cpu_freq;
- st_scale_f = scale & 0xffffffff;
- st_scale_i = scale >> 32;
-
- barrier();
- }
+ do {
+ shadow_time_version = HYPERVISOR_shared_info->time_version2;
+ 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;
+ shadow_system_time = HYPERVISOR_shared_info->system_time;
+ rmb();
+ }
+ while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
+}
+
+
+#define TIME_VALUES_UP_TO_DATE \
+ (shadow_time_version == HYPERVISOR_shared_info->time_version2)
+
+
+static inline unsigned long 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_st_pcc);
+ 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 shadow_st + delta;
+ return (unsigned long)delta;
}
-/*
- * Wallclock time.
- * Based on what the hypervisor tells us, extrapolated using system time.
- * Again need to read a number of values from the shared page "atomically".
- * this time using a version number.
- */
void gettimeofday(struct timeval *tv)
{
- long usec, sec;
- u64 now;
-
- now = get_s_time();
- usec = ((unsigned long)(now-shadow_wc_timestamp))/1000;
- sec = shadow_tv_sec;
- usec += shadow_tv_usec;
-
- while ( usec >= 1000000 )
- {
- usec -= 1000000;
- sec++;
+ struct timeval _tv;
+
+ do {
+ get_time_values_from_xen();
+ _tv.tv_usec = get_time_delta_usecs();
+ _tv.tv_sec = shadow_tv.tv_sec;
+ _tv.tv_usec += shadow_tv.tv_usec;
}
+ while ( unlikely(!TIME_VALUES_UP_TO_DATE) );
- tv->tv_sec = sec;
- tv->tv_usec = usec;
+ HANDLE_USEC_OVERFLOW(_tv);
+ *tv = _tv;
}
static void timer_handler(int ev, struct pt_regs *regs)
{
static int i;
- s_time_t now;
+ struct timeval tv;
i++;
if (i >= 1000) {
- now = get_s_time();
- printf("T(%lld)\n", now);
+ gettimeofday(&tv);
+ printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
i = 0;
}
}
@@ -150,12 +139,21 @@ static void timer_handler(int ev, struct pt_regs *regs)
void init_time(void)
{
- u64 __cpu_khz;
+ u64 __cpu_khz, cpu_freq, scale;
unsigned long cpu_khz;
__cpu_khz = HYPERVISOR_shared_info->cpu_freq;
cpu_khz = (u32) (__cpu_khz/1000);
+ rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_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;
+
printk("Xen reported: %lu.%03lu MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);