ia64/xen-unstable
changeset 870:09bebb539c8c
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.
time.c, hypervisor.h, kernel.c, head.S:
Fix minios to work with revised Xen 1.2 interface.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Thu Oct 30 17:33:14 2003 +0000 (2003-10-30) |
parents | d5ad00b29735 |
children | b147d210dca8 |
files | extras/mini-os/h/hypervisor.h extras/mini-os/head.S extras/mini-os/kernel.c extras/mini-os/time.c |
line diff
1.1 --- a/extras/mini-os/h/hypervisor.h Wed Oct 29 17:30:14 2003 +0000 1.2 +++ b/extras/mini-os/h/hypervisor.h Thu Oct 30 17:33:14 2003 +0000 1.3 @@ -255,4 +255,16 @@ static inline long HYPERVISOR_kbd_op(uns 1.4 return ret; 1.5 } 1.6 1.7 +static inline int HYPERVISOR_update_va_mapping( 1.8 + unsigned long page_nr, unsigned long new_val, unsigned long flags) 1.9 +{ 1.10 + int ret; 1.11 + __asm__ __volatile__ ( 1.12 + TRAP_INSTR 1.13 + : "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping), 1.14 + "b" (page_nr), "c" (new_val), "d" (flags) ); 1.15 + 1.16 + return ret; 1.17 +} 1.18 + 1.19 #endif /* __HYPERVISOR_H__ */
2.1 --- a/extras/mini-os/head.S Wed Oct 29 17:30:14 2003 +0000 2.2 +++ b/extras/mini-os/head.S Thu Oct 30 17:33:14 2003 +0000 2.3 @@ -4,9 +4,8 @@ 2.4 #define MOD_START 4 2.5 #define MOD_LEN 8 2.6 2.7 -#define ENTRY(X) .globl X ; X : 2.8 - 2.9 -.globl _start 2.10 +.globl _start, shared_info 2.11 + 2.12 _start: 2.13 cld 2.14 2.15 @@ -43,3 +42,7 @@ stack_start: 2.16 .long stack+8192, __KERNEL_DS 2.17 2.18 2.19 + /* Unpleasant -- we actually use this PTE to map shared_info :-) */ 2.20 + .org 0x1000 2.21 +shared_info: 2.22 + .org 0x2000
3.1 --- a/extras/mini-os/kernel.c Wed Oct 29 17:30:14 2003 +0000 3.2 +++ b/extras/mini-os/kernel.c Thu Oct 30 17:33:14 2003 +0000 3.3 @@ -61,6 +61,19 @@ static void exit_handler(int ev, struct 3.4 static void debug_handler(int ev, struct pt_regs *regs); 3.5 3.6 3.7 +static shared_info_t *map_shared_info(unsigned long pa) 3.8 +{ 3.9 + extern char shared_info[PAGE_SIZE]; 3.10 + if ( HYPERVISOR_update_va_mapping((unsigned long)shared_info >> PAGE_SHIFT, 3.11 + pa | 3, UVMF_INVLPG) ) 3.12 + { 3.13 + printk("Failed to map shared_info!!\n"); 3.14 + *(int*)0=0; 3.15 + } 3.16 + return (shared_info_t *)shared_info; 3.17 +} 3.18 + 3.19 + 3.20 /* 3.21 * INITIAL C ENTRY POINT. 3.22 */ 3.23 @@ -72,25 +85,23 @@ void start_kernel(start_info_t *si) 3.24 memcpy(&start_info, si, sizeof(*si)); 3.25 3.26 /* Grab the shared_info pointer and put it in a safe place. */ 3.27 - HYPERVISOR_shared_info = start_info.shared_info; 3.28 + HYPERVISOR_shared_info = map_shared_info(start_info.shared_info); 3.29 3.30 /* Set up event and failsafe callback addresses. */ 3.31 HYPERVISOR_set_callbacks( 3.32 __KERNEL_CS, (unsigned long)hypervisor_callback, 3.33 __KERNEL_CS, (unsigned long)failsafe_callback); 3.34 3.35 - 3.36 trap_init(); 3.37 3.38 - 3.39 /* ENABLE EVENT DELIVERY. This is disabled at start of day. */ 3.40 __sti(); 3.41 3.42 /* print out some useful information */ 3.43 printk("Xeno Minimal OS!\n"); 3.44 printk("start_info: %p\n", si); 3.45 - printk(" nr_pages: %lu", si->nr_pages); 3.46 - printk(" shared_inf: %p\n", si->shared_info); 3.47 + printk(" nr_pages: %lu", si->nr_pages); 3.48 + printk(" shared_inf: %08lx\n", si->shared_info); 3.49 printk(" pt_base: %p", (void *)si->pt_base); 3.50 printk(" mod_start: 0x%lx\n", si->mod_start); 3.51 printk(" mod_len: %lu\n", si->mod_len); 3.52 @@ -142,7 +153,7 @@ void start_kernel(start_info_t *si) 3.53 void do_exit(void) 3.54 { 3.55 printk("do_exit called!\n"); 3.56 - for ( ;; ) ; 3.57 + for ( ;; ) HYPERVISOR_exit(); 3.58 } 3.59 static void exit_handler(int ev, struct pt_regs *regs) { 3.60 do_exit();
4.1 --- a/extras/mini-os/time.c Wed Oct 29 17:30:14 2003 +0000 4.2 +++ b/extras/mini-os/time.c Thu Oct 30 17:33:14 2003 +0000 4.3 @@ -47,102 +47,91 @@ 4.4 *************************************************************************/ 4.5 4.6 static unsigned int rdtsc_bitshift; 4.7 -static u32 st_scale_f; 4.8 -static u32 st_scale_i; 4.9 -static u32 shadow_st_pcc; 4.10 -static s_time_t shadow_st; 4.11 -static u32 shadow_wc_version=0; 4.12 -static long shadow_tv_sec; 4.13 -static long shadow_tv_usec; 4.14 -static s_time_t shadow_wc_timestamp; 4.15 +static u32 st_scale_f; /* convert ticks -> usecs */ 4.16 +static u32 st_scale_i; /* convert ticks -> usecs */ 4.17 + 4.18 +/* These are peridically updated in shared_info, and then copied here. */ 4.19 +static u32 shadow_tsc_stamp; 4.20 +static s64 shadow_system_time; 4.21 +static u32 shadow_time_version; 4.22 +static struct timeval shadow_tv; 4.23 4.24 -/* 4.25 - * System time. 4.26 - * We need to read the values from the shared info page "atomically" 4.27 - * and use the cycle counter value as the "version" number. Clashes 4.28 - * should be very rare. 4.29 - */ 4.30 -inline s_time_t get_s_time(void) 4.31 -{ 4.32 - s32 delta_tsc; 4.33 - u32 low; 4.34 - u64 delta, tsc; 4.35 - u32 version; 4.36 - u64 cpu_freq, scale; 4.37 +#ifndef rmb 4.38 +#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") 4.39 +#endif 4.40 + 4.41 +#define HANDLE_USEC_OVERFLOW(_tv) \ 4.42 + do { \ 4.43 + while ( (_tv).tv_usec >= 1000000 ) \ 4.44 + { \ 4.45 + (_tv).tv_usec -= 1000000; \ 4.46 + (_tv).tv_sec++; \ 4.47 + } \ 4.48 + } while ( 0 ) 4.49 4.50 - /* check if our values are still up-to-date */ 4.51 - while ( (version = HYPERVISOR_shared_info->wc_version) != 4.52 - shadow_wc_version ) 4.53 - { 4.54 - barrier(); 4.55 +static void get_time_values_from_xen(void) 4.56 +{ 4.57 + do { 4.58 + shadow_time_version = HYPERVISOR_shared_info->time_version2; 4.59 + rmb(); 4.60 + shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec; 4.61 + shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec; 4.62 + shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp; 4.63 + shadow_system_time = HYPERVISOR_shared_info->system_time; 4.64 + rmb(); 4.65 + } 4.66 + while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 ); 4.67 +} 4.68 4.69 - shadow_wc_version = version; 4.70 - shadow_tv_sec = HYPERVISOR_shared_info->tv_sec; 4.71 - shadow_tv_usec = HYPERVISOR_shared_info->tv_usec; 4.72 - shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp; 4.73 - shadow_st_pcc = HYPERVISOR_shared_info->st_timestamp; 4.74 - shadow_st = HYPERVISOR_shared_info->system_time; 4.75 + 4.76 +#define TIME_VALUES_UP_TO_DATE \ 4.77 + (shadow_time_version == HYPERVISOR_shared_info->time_version2) 4.78 + 4.79 4.80 - rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift; 4.81 - cpu_freq = HYPERVISOR_shared_info->cpu_freq; 4.82 - 4.83 - /* XXX cpu_freq as u32 limits it to 4.29 GHz. Get a better do_div! */ 4.84 - scale = 1000000000LL << (32 + rdtsc_bitshift); 4.85 - scale /= cpu_freq; 4.86 - st_scale_f = scale & 0xffffffff; 4.87 - st_scale_i = scale >> 32; 4.88 - 4.89 - barrier(); 4.90 - } 4.91 +static inline unsigned long get_time_delta_usecs(void) 4.92 +{ 4.93 + s32 delta_tsc; 4.94 + u32 low; 4.95 + u64 delta, tsc; 4.96 4.97 rdtscll(tsc); 4.98 low = (u32)(tsc >> rdtsc_bitshift); 4.99 - delta_tsc = (s32)(low - shadow_st_pcc); 4.100 + delta_tsc = (s32)(low - shadow_tsc_stamp); 4.101 if ( unlikely(delta_tsc < 0) ) delta_tsc = 0; 4.102 delta = ((u64)delta_tsc * st_scale_f); 4.103 delta >>= 32; 4.104 delta += ((u64)delta_tsc * st_scale_i); 4.105 4.106 - return shadow_st + delta; 4.107 + return (unsigned long)delta; 4.108 } 4.109 4.110 4.111 -/* 4.112 - * Wallclock time. 4.113 - * Based on what the hypervisor tells us, extrapolated using system time. 4.114 - * Again need to read a number of values from the shared page "atomically". 4.115 - * this time using a version number. 4.116 - */ 4.117 void gettimeofday(struct timeval *tv) 4.118 { 4.119 - long usec, sec; 4.120 - u64 now; 4.121 - 4.122 - now = get_s_time(); 4.123 - usec = ((unsigned long)(now-shadow_wc_timestamp))/1000; 4.124 - sec = shadow_tv_sec; 4.125 - usec += shadow_tv_usec; 4.126 + struct timeval _tv; 4.127 4.128 - while ( usec >= 1000000 ) 4.129 - { 4.130 - usec -= 1000000; 4.131 - sec++; 4.132 + do { 4.133 + get_time_values_from_xen(); 4.134 + _tv.tv_usec = get_time_delta_usecs(); 4.135 + _tv.tv_sec = shadow_tv.tv_sec; 4.136 + _tv.tv_usec += shadow_tv.tv_usec; 4.137 } 4.138 + while ( unlikely(!TIME_VALUES_UP_TO_DATE) ); 4.139 4.140 - tv->tv_sec = sec; 4.141 - tv->tv_usec = usec; 4.142 + HANDLE_USEC_OVERFLOW(_tv); 4.143 + *tv = _tv; 4.144 } 4.145 4.146 4.147 static void timer_handler(int ev, struct pt_regs *regs) 4.148 { 4.149 static int i; 4.150 - s_time_t now; 4.151 + struct timeval tv; 4.152 4.153 i++; 4.154 if (i >= 1000) { 4.155 - now = get_s_time(); 4.156 - printf("T(%lld)\n", now); 4.157 + gettimeofday(&tv); 4.158 + printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec); 4.159 i = 0; 4.160 } 4.161 } 4.162 @@ -150,12 +139,21 @@ static void timer_handler(int ev, struct 4.163 4.164 void init_time(void) 4.165 { 4.166 - u64 __cpu_khz; 4.167 + u64 __cpu_khz, cpu_freq, scale; 4.168 unsigned long cpu_khz; 4.169 4.170 __cpu_khz = HYPERVISOR_shared_info->cpu_freq; 4.171 cpu_khz = (u32) (__cpu_khz/1000); 4.172 4.173 + rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift; 4.174 + cpu_freq = HYPERVISOR_shared_info->cpu_freq; 4.175 + 4.176 + scale = 1000000LL << (32 + rdtsc_bitshift); 4.177 + scale /= cpu_freq; 4.178 + 4.179 + st_scale_f = scale & 0xffffffff; 4.180 + st_scale_i = scale >> 32; 4.181 + 4.182 printk("Xen reported: %lu.%03lu MHz processor.\n", 4.183 cpu_khz / 1000, cpu_khz % 1000); 4.184