mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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.
This commit is contained in:
1 parent
2eef9a8f52
commit
5cf5933f37
4 files changed
+99
-75
No files matched your search
@@ -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__ */
|
||||
@@ -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
|
||||
+17
-6
@@ -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();
|
||||
|
||||
+64
-66
@@ -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;
|
||||
static u32 st_scale_f; /* convert ticks -> usecs */
|
||||
static u32 st_scale_i; /* convert ticks -> usecs */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
/* 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;
|
||||
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 );
|
||||
}
|
||||
|
||||
/* 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;
|
||||
#define TIME_VALUES_UP_TO_DATE \
|
||||
(shadow_time_version == HYPERVISOR_shared_info->time_version2)
|
||||
|
||||
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();
|
||||
}
|
||||
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;
|
||||
struct timeval _tv;
|
||||
|
||||
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++;
|
||||
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);
|
||||
|
||||
|
||||