diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-10-30 17:33:14 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-10-30 17:33:14 +0000 |
commit | 5cf5933f37cfba4c99aea8d70cca2d89da0344bb (patch) | |
tree | 2ca0c4f737197ee1f9b61534c660c69d6c9a5e27 /extras | |
parent | 2eef9a8f5271d12c3a484fc49a573e206369bacd (diff) | |
download | xen-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.h | 12 | ||||
-rw-r--r-- | extras/mini-os/head.S | 9 | ||||
-rw-r--r-- | extras/mini-os/kernel.c | 23 | ||||
-rw-r--r-- | extras/mini-os/time.c | 142 |
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); |