时间虚拟化

init_platform_timer

xen\arch\x86\setup.c

void __init __start_xen(unsigned long mbi_p)

{

    init_xen_time();

 

xen\arch\x86\time.c

int __init init_xen_time(void)

{

init_platform_timer();

 

xen\arch\x86\time.c

static void __init init_platform_timer(void)

{

    init_timer(&plt_overflow_timer,plt_overflow, NULL, 0);

 

xen\arch\x86\time.c

static void plt_overflow(void *unused)

{

    count = plt_src.read_counter();

    plt_stamp64 += (count - plt_stamp) & plt_mask;

    plt_stamp = count;

xen\arch\x86\time.c

read_platform_stime

platform_time_calibration

resume_platform_timer

rtc的时间获得

tools\ioemu-qemu-xen\hw\ mc146818rtc.c

RTCState *rtc_init(int base, qemu_irq irq, int base_year)

{

    s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;

    qemu_mod_timer(s->second_timer2, s->next_second_time);

 

tools\ioemu-qemu-xen\qemu-tool.c ?

int64_t qemu_get_clock(QEMUClock *clock)

{

    qemu_timeval tv;

    qemu_gettimeofday(&tv);

    return (tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000)) / 1000000;

}

tools\ioemu-qemu-xen\vl.c

int64_t qemu_get_clock(QEMUClock *clock)

{

    switch(clock->type) {

    case QEMU_TIMER_REALTIME:

        return get_clock() / 1000000;

    default:

    case QEMU_TIMER_VIRTUAL:

        if (use_icount) {

            return cpu_get_icount();

        } else {

            return cpu_get_clock();

        }

    }

}

 

tools\ioemu-qemu-xen\vl.c

static void init_timers(void)

{

    init_get_clock();

    ticks_per_sec = QEMU_TIMER_BASE;

    rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);

    vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);

}

 

tools\ioemu-qemu-xen\vl.c中main函数

use_icount?

 

tools\ioemu-qemu-xen\vl.c

/* return the host CPU monotonic timer and handle stop/restart */

static int64_t cpu_get_clock(void)

{

    int64_t ti;

    if (!cpu_ticks_enabled) {

        return cpu_clock_offset;

    } else {

        ti = get_clock();

        return ti + cpu_clock_offset;

    }

}

 

tools\ioemu-qemu-xen\vl.c

static int64_t get_clock(void)

{

    LARGE_INTEGER ti;

    QueryPerformanceCounter(&ti);

    return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq);

}

 

结论:qemu通过dom0获取rtc时间。

tools\ioemu-qemu-xen\hw\ mc146818rtc.c

static void rtc_copy_date(RTCState *s)

{

    const struct tm *tm = &s->current_tm;

    int year;

 

    s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);

    s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);

 

tools\ioemu-qemu-xen\hw\ mc146818rtc.c

void rtc_set_date(RTCState *s, const struct tm *tm)

{

    s->current_tm = *tm;

    rtc_copy_date(s);

}

 

rtc_init ->rtc_set_date_from_host –> rtc_set_date

 

tools\ioemu-qemu-xen\hw\ mc146818rtc.c

static void rtc_set_date_from_host(RTCState *s)

{

    struct tm tm;

    int val;

 

    /* set the CMOS date */

    qemu_get_timedate(&tm, 0);

    rtc_set_date(s, &tm);

 

走下面哪条路径?

tools\ioemu-qemu-xen\vl.c

/***********************************************************/

/* host time/date access */

void qemu_get_timedate(struct tm *tm, int offset)

{

    time_t ti;

    struct tm *ret;

 

    time(&ti);

    ti += offset;

    if (rtc_date_offset == -1) {

        if (rtc_utc)

            ret = gmtime(&ti); //参数类型??

        else

            ret = localtime(&ti);

    } else {

        ti -= rtc_date_offset;

        ret = gmtime(&ti);

    }

 

    memcpy(tm, ret, sizeof(struct tm));

}

 

xen\common\time.c中gmtime作用就是将时间格式化到一个结构体中,并将其返回。

read_platform_stime

 

xen\arch\x86\time.c

void cstate_restore_tsc(void)

{

    stime_delta = read_platform_stime() - t->stime_master_stamp;

 

TSC 是时间戳计数器的缩写

static void time_calibration_tsc_rendezvous(void *_r)

{

    for ( i = 4; i >= 0; i-- )

    {

        if ( smp_processor_id() == 0 )

        {

            while ( atomic_read(&r->semaphore) != (total_cpus - 1) )

                mb();

 

            if ( r->master_stime == 0 )

            {

                r->master_stime =read_platform_stime();

 

 

/* Ordinary rendezvous function which does not modify TSC values. */

static void time_calibration_std_rendezvous(void *_r)

{

    if ( smp_processor_id() == 0 )

    {

        while ( atomic_read(&r->semaphore) != (total_cpus - 1) )

            cpu_relax();

        r->master_stime = read_platform_stime();

 

void init_percpu_time(void)

{

    struct cpu_time *t = &this_cpu(cpu_time);

    unsigned long flags;

    s_time_t now;

 

    local_irq_save(flags);

    rdtscll(t->local_tsc_stamp);

    now = read_platform_stime();

 

 

/* Late init function (after all CPUs are booted). */

int __init init_xen_time(void)

{

        /* If TSCs are not marked as 'reliable', re-sync during rendezvous. */

        if ( !boot_cpu_has(X86_FEATURE_TSC_RELIABLE) )

            time_calibration_rendezvous_fn =time_calibration_tsc_rendezvous;

 

static void time_calibration(void *unused)

{

    struct calibration_rendezvous r = {

        .cpu_calibration_map = cpu_online_map,

        .semaphore = ATOMIC_INIT(0)

    };

 

    /* @wait=1 because we must wait for all cpus before freeing @r. */

    on_selected_cpus(&r.cpu_calibration_map,

                     time_calibration_rendezvous_fn,

                     &r, 1);

}

 

xen\arch\x86\time.c

static void (*time_calibration_rendezvous_fn)(void *) =

    time_calibration_std_rendezvous;

 

platform_time_calibration

cpu_frequency_change-> platform_time_calibration

local_time_calibration-> platform_time_calibration

time_suspend-> platform_time_calibration

int __init init_xen_time(void)

{

    open_softirq(TIME_CALIBRATE_SOFTIRQ,local_time_calibration);

resume_platform_timer

 

int time_resume(void)

{

    /*u64 tmp = */init_pit_and_calibrate_tsc();

 

    /* Disable this while calibrate_tsc_ap() also is skipped. */

    /*set_time_scale(&this_cpu(cpu_time).tsc_scale, tmp);*/

 

    resume_platform_timer();

 

device_power_up-> time_resume

结论

xen通过init_platform_timer来初始化时间源供Dom0使用。

 

DomU则通过rtc_init来从Dom0获取时间。

 

因此,时间虚拟化的路径应该如下:

 

xen->Dom0->DomU

 

2013年5月23日上传

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值