blob: 0c6b70e26fd5f59b36875b7189c059a49ae5d322 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#pragma once
#include <zircon/compiler.h>
#include <zircon/types.h>
static constexpr uint32_t kKvmSystemTimeMsrOld = 0x12;
static constexpr uint32_t kKvmSystemTimeMsr = 0x4b564d01;
static constexpr uint32_t kKvmBootTimeOld = 0x11;
static constexpr uint32_t kKvmBootTime = 0x4b564d00;
static constexpr uint32_t kKvmFeatureClockSourceOld = 1u << 0;
static constexpr uint32_t kKvmFeatureClockSource = 1u << 3;
static constexpr uint8_t kKvmSystemTimeStable = 1u << 0;
// Both structures below are part of the ABI used by Xen and KVM, this ABI is not
// defined by use we just follow it. For more detail please refer to the
// documentation (https://www.kernel.org/doc/Documentation/virtual/kvm/msr.txt).
struct pvclock_boot_time {
// With multiple VCPUs it is possible that one VCPU can try to read boot time
// while we are updating it because another VCPU asked for the update. In this
// case odd version value serves as an indicator for the guest that update is
// in progress. Therefore we need to update version before we write anything
// else and after, also we need to user proper memory barriers. The same logic
// applies to system time version below, even though system time is per VCPU
// others VCPUs still can access system times of other VCPUs (Linux however
// never does that).
uint32_t version;
uint32_t seconds;
uint32_t nseconds;
} __PACKED;
static_assert(sizeof(struct pvclock_boot_time) == 12, "sizeof(pvclock_boot_time) should be 12");
struct pvclock_system_time {
uint32_t version;
uint32_t pad0;
uint64_t tsc_timestamp;
uint64_t system_time;
uint32_t tsc_mul;
int8_t tsc_shift;
uint8_t flags;
uint8_t pad1[2];
} __PACKED;
static_assert(sizeof(struct pvclock_system_time) == 32, "sizeof(pvclock_system_time) should be 32");
zx_status_t pvclock_init();
bool pvclock_is_present();
bool pvclock_is_stable();
uint64_t pvclock_get_tsc_freq();