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.
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 -
    4.16 -/*
    4.17 - * System time.
    4.18 - * We need to read the values from the shared info page "atomically" 
    4.19 - * and use the cycle counter value as the "version" number. Clashes
    4.20 - * should be very rare.
    4.21 - */
    4.22 -inline s_time_t get_s_time(void)
    4.23 -{
    4.24 -    s32 delta_tsc;
    4.25 -    u32 low;
    4.26 -    u64 delta, tsc;
    4.27 -    u32	version;
    4.28 -    u64 cpu_freq, scale;
    4.29 +static u32 st_scale_f; /* convert ticks -> usecs */
    4.30 +static u32 st_scale_i; /* convert ticks -> usecs */
    4.31  
    4.32 -    /* check if our values are still up-to-date */
    4.33 -    while ( (version = HYPERVISOR_shared_info->wc_version) != 
    4.34 -            shadow_wc_version )
    4.35 -    {
    4.36 -        barrier();
    4.37 +/* These are peridically updated in shared_info, and then copied here. */
    4.38 +static u32 shadow_tsc_stamp;
    4.39 +static s64 shadow_system_time;
    4.40 +static u32 shadow_time_version;
    4.41 +static struct timeval shadow_tv;
    4.42  
    4.43 -        shadow_wc_version   = version;
    4.44 -        shadow_tv_sec       = HYPERVISOR_shared_info->tv_sec;
    4.45 -        shadow_tv_usec      = HYPERVISOR_shared_info->tv_usec;
    4.46 -        shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp;
    4.47 -        shadow_st_pcc       = HYPERVISOR_shared_info->st_timestamp;
    4.48 -        shadow_st           = HYPERVISOR_shared_info->system_time;
    4.49 +#ifndef rmb
    4.50 +#define rmb()  __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
    4.51 +#endif
    4.52  
    4.53 -        rdtsc_bitshift      = HYPERVISOR_shared_info->rdtsc_bitshift;
    4.54 -        cpu_freq            = HYPERVISOR_shared_info->cpu_freq;
    4.55 +#define HANDLE_USEC_OVERFLOW(_tv)          \
    4.56 +    do {                                   \
    4.57 +        while ( (_tv).tv_usec >= 1000000 ) \
    4.58 +        {                                  \
    4.59 +            (_tv).tv_usec -= 1000000;      \
    4.60 +            (_tv).tv_sec++;                \
    4.61 +        }                                  \
    4.62 +    } while ( 0 )
    4.63  
    4.64 -        /* XXX cpu_freq as u32 limits it to 4.29 GHz. Get a better do_div! */
    4.65 -        scale = 1000000000LL << (32 + rdtsc_bitshift);
    4.66 -        scale /= cpu_freq;
    4.67 -        st_scale_f = scale & 0xffffffff;
    4.68 -        st_scale_i = scale >> 32;
    4.69 +static void get_time_values_from_xen(void)
    4.70 +{
    4.71 +    do {
    4.72 +        shadow_time_version = HYPERVISOR_shared_info->time_version2;
    4.73 +        rmb();
    4.74 +        shadow_tv.tv_sec    = HYPERVISOR_shared_info->wc_sec;
    4.75 +        shadow_tv.tv_usec   = HYPERVISOR_shared_info->wc_usec;
    4.76 +        shadow_tsc_stamp    = HYPERVISOR_shared_info->tsc_timestamp;
    4.77 +        shadow_system_time  = HYPERVISOR_shared_info->system_time;
    4.78 +        rmb();
    4.79 +    }
    4.80 +    while ( shadow_time_version != HYPERVISOR_shared_info->time_version1 );
    4.81 +}
    4.82  
    4.83 -        barrier();
    4.84 -	}
    4.85 +
    4.86 +#define TIME_VALUES_UP_TO_DATE \
    4.87 +    (shadow_time_version == HYPERVISOR_shared_info->time_version2)
    4.88 +
    4.89 +
    4.90 +static inline unsigned long get_time_delta_usecs(void)
    4.91 +{
    4.92 +    s32      delta_tsc;
    4.93 +    u32      low;
    4.94 +    u64      delta, tsc;
    4.95  
    4.96      rdtscll(tsc);
    4.97      low = (u32)(tsc >> rdtsc_bitshift);
    4.98 -    delta_tsc = (s32)(low - shadow_st_pcc);
    4.99 +    delta_tsc = (s32)(low - shadow_tsc_stamp);
   4.100      if ( unlikely(delta_tsc < 0) ) delta_tsc = 0;
   4.101      delta = ((u64)delta_tsc * st_scale_f);
   4.102      delta >>= 32;
   4.103      delta += ((u64)delta_tsc * st_scale_i);
   4.104  
   4.105 -    return shadow_st + delta;
   4.106 +    return (unsigned long)delta;
   4.107  }
   4.108  
   4.109  
   4.110 -/*
   4.111 - * Wallclock time.
   4.112 - * Based on what the hypervisor tells us, extrapolated using system time.
   4.113 - * Again need to read a number of values from the shared page "atomically".
   4.114 - * this time using a version number.
   4.115 - */
   4.116  void gettimeofday(struct timeval *tv)
   4.117  {
   4.118 -    long          usec, sec;
   4.119 -    u64           now;
   4.120 -
   4.121 -    now   = get_s_time();
   4.122 -    usec  = ((unsigned long)(now-shadow_wc_timestamp))/1000;
   4.123 -    sec   = shadow_tv_sec;
   4.124 -    usec += shadow_tv_usec;
   4.125 +    struct timeval _tv;
   4.126  
   4.127 -    while ( usec >= 1000000 ) 
   4.128 -    {
   4.129 -        usec -= 1000000;
   4.130 -        sec++;
   4.131 +    do {
   4.132 +        get_time_values_from_xen();
   4.133 +        _tv.tv_usec = get_time_delta_usecs();
   4.134 +        _tv.tv_sec   = shadow_tv.tv_sec;
   4.135 +        _tv.tv_usec += shadow_tv.tv_usec;
   4.136      }
   4.137 +    while ( unlikely(!TIME_VALUES_UP_TO_DATE) );
   4.138  
   4.139 -    tv->tv_sec = sec;
   4.140 -    tv->tv_usec = usec;
   4.141 +    HANDLE_USEC_OVERFLOW(_tv);
   4.142 +    *tv = _tv;
   4.143  }
   4.144  
   4.145  
   4.146  static void timer_handler(int ev, struct pt_regs *regs)
   4.147  {
   4.148      static int i;
   4.149 -    s_time_t now;
   4.150 +    struct timeval tv;
   4.151  
   4.152      i++;
   4.153      if (i >= 1000) {
   4.154 -        now = get_s_time();
   4.155 -        printf("T(%lld)\n", now);
   4.156 +        gettimeofday(&tv);
   4.157 +        printf("T(s=%ld us=%ld)\n", tv.tv_sec, tv.tv_usec);
   4.158          i = 0;
   4.159      }
   4.160  }
   4.161 @@ -150,12 +139,21 @@ static void timer_handler(int ev, struct
   4.162  
   4.163  void init_time(void)
   4.164  {
   4.165 -    u64         __cpu_khz;
   4.166 +    u64         __cpu_khz, cpu_freq, scale;
   4.167      unsigned long cpu_khz;
   4.168  
   4.169      __cpu_khz = HYPERVISOR_shared_info->cpu_freq;
   4.170      cpu_khz = (u32) (__cpu_khz/1000);
   4.171  
   4.172 +    rdtsc_bitshift = HYPERVISOR_shared_info->rdtsc_bitshift;
   4.173 +    cpu_freq       = HYPERVISOR_shared_info->cpu_freq;
   4.174 +
   4.175 +    scale = 1000000LL << (32 + rdtsc_bitshift);
   4.176 +    scale /= cpu_freq;
   4.177 +
   4.178 +    st_scale_f = scale & 0xffffffff;
   4.179 +    st_scale_i = scale >> 32;
   4.180 +
   4.181      printk("Xen reported: %lu.%03lu MHz processor.\n", 
   4.182             cpu_khz / 1000, cpu_khz % 1000);
   4.183