You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'for-linus-4.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from David Vrabel: "Xen features and fixes for 4.5-rc0: - Stolen ticks and PV wallclock support for arm/arm64 - Add grant copy ioctl to gntdev device" * tag 'for-linus-4.5-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen/gntdev: add ioctl for grant copy x86/xen: don't reset vcpu_info on a cancelled suspend xen/gntdev: constify mmu_notifier_ops structures xen/grant-table: constify gnttab_ops structure xen/time: use READ_ONCE xen/x86: convert remaining timespec to timespec64 in xen_pvclock_gtod_notify xen/x86: support XENPF_settime64 xen/arm: set the system time in Xen via the XENPF_settime64 hypercall xen/arm: introduce xen_read_wallclock arm: extend pvclock_wall_clock with sec_hi xen: introduce XENPF_settime64 xen/arm: introduce HYPERVISOR_platform_op on arm and arm64 xen: rename dom0_op to platform_op xen/arm: account for stolen ticks arm64: introduce CONFIG_PARAVIRT, PARAVIRT_TIME_ACCOUNTING and pv_time_ops arm: introduce CONFIG_PARAVIRT, PARAVIRT_TIME_ACCOUNTING and pv_time_ops missing include asm/paravirt.h in cputime.c xen: move xen_setup_runstate_info and get_runstate_snapshot to drivers/xen/time.c
This commit is contained in:
@@ -1824,6 +1824,25 @@ config SWIOTLB
|
||||
config IOMMU_HELPER
|
||||
def_bool SWIOTLB
|
||||
|
||||
config PARAVIRT
|
||||
bool "Enable paravirtualization code"
|
||||
help
|
||||
This changes the kernel so it can modify itself when it is run
|
||||
under a hypervisor, potentially improving performance significantly
|
||||
over full virtualization.
|
||||
|
||||
config PARAVIRT_TIME_ACCOUNTING
|
||||
bool "Paravirtual steal time accounting"
|
||||
select PARAVIRT
|
||||
default n
|
||||
help
|
||||
Select this option to enable fine granularity task steal time
|
||||
accounting. Time spent executing other tasks in parallel with
|
||||
the current vCPU is discounted from the vCPU power. To account for
|
||||
that, there can be a small performance impact.
|
||||
|
||||
If in doubt, say N here.
|
||||
|
||||
config XEN_DOM0
|
||||
def_bool y
|
||||
depends on XEN
|
||||
@@ -1837,6 +1856,7 @@ config XEN
|
||||
select ARCH_DMA_ADDR_T_64BIT
|
||||
select ARM_PSCI
|
||||
select SWIOTLB_XEN
|
||||
select PARAVIRT
|
||||
help
|
||||
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _ASM_ARM_PARAVIRT_H
|
||||
#define _ASM_ARM_PARAVIRT_H
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
struct static_key;
|
||||
extern struct static_key paravirt_steal_enabled;
|
||||
extern struct static_key paravirt_steal_rq_enabled;
|
||||
|
||||
struct pv_time_ops {
|
||||
unsigned long long (*steal_clock)(int cpu);
|
||||
};
|
||||
extern struct pv_time_ops pv_time_ops;
|
||||
|
||||
static inline u64 paravirt_steal_clock(int cpu)
|
||||
{
|
||||
return pv_time_ops.steal_clock(cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/interface/platform.h>
|
||||
|
||||
long privcmd_call(unsigned call, unsigned long a1,
|
||||
unsigned long a2, unsigned long a3,
|
||||
@@ -49,6 +50,12 @@ int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
|
||||
int HYPERVISOR_physdev_op(int cmd, void *arg);
|
||||
int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
|
||||
int HYPERVISOR_tmem_op(void *arg);
|
||||
int HYPERVISOR_platform_op_raw(void *arg);
|
||||
static inline int HYPERVISOR_platform_op(struct xen_platform_op *op)
|
||||
{
|
||||
op->interface_version = XENPF_INTERFACE_VERSION;
|
||||
return HYPERVISOR_platform_op_raw(op);
|
||||
}
|
||||
int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
|
||||
|
||||
static inline int
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
(hnd).p = val; \
|
||||
} while (0)
|
||||
|
||||
#define __HYPERVISOR_platform_op_raw __HYPERVISOR_platform_op
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/* Explicitly size integers that represent pfns in the interface with
|
||||
* Xen so that we can have one ABI that works for 32 and 64 bit guests.
|
||||
@@ -76,6 +78,7 @@ struct pvclock_wall_clock {
|
||||
u32 version;
|
||||
u32 sec;
|
||||
u32 nsec;
|
||||
u32 sec_hi;
|
||||
} __attribute__((__packed__));
|
||||
#endif
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ obj-$(CONFIG_EFI) += efi.o
|
||||
ifneq ($(CONFIG_ARCH_EBSA110),y)
|
||||
obj-y += io.o
|
||||
endif
|
||||
obj-$(CONFIG_PARAVIRT) += paravirt.o
|
||||
|
||||
head-y := head$(MMUEXT).o
|
||||
obj-$(CONFIG_DEBUG_LL) += debug.o
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2013 Citrix Systems
|
||||
*
|
||||
* Author: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/paravirt.h>
|
||||
|
||||
struct static_key paravirt_steal_enabled;
|
||||
struct static_key paravirt_steal_rq_enabled;
|
||||
|
||||
struct pv_time_ops pv_time_ops;
|
||||
EXPORT_SYMBOL_GPL(pv_time_ops);
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <xen/page.h>
|
||||
#include <xen/interface/sched.h>
|
||||
#include <xen/xen-ops.h>
|
||||
#include <asm/paravirt.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
#include <asm/xen/hypercall.h>
|
||||
#include <asm/system_misc.h>
|
||||
@@ -25,6 +26,10 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/pvclock_gtod.h>
|
||||
#include <linux/time64.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
||||
@@ -79,6 +84,83 @@ int xen_unmap_domain_gfn_range(struct vm_area_struct *vma,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range);
|
||||
|
||||
static unsigned long long xen_stolen_accounting(int cpu)
|
||||
{
|
||||
struct vcpu_runstate_info state;
|
||||
|
||||
BUG_ON(cpu != smp_processor_id());
|
||||
|
||||
xen_get_runstate_snapshot(&state);
|
||||
|
||||
WARN_ON(state.state != RUNSTATE_running);
|
||||
|
||||
return state.time[RUNSTATE_runnable] + state.time[RUNSTATE_offline];
|
||||
}
|
||||
|
||||
static void xen_read_wallclock(struct timespec64 *ts)
|
||||
{
|
||||
u32 version;
|
||||
struct timespec64 now, ts_monotonic;
|
||||
struct shared_info *s = HYPERVISOR_shared_info;
|
||||
struct pvclock_wall_clock *wall_clock = &(s->wc);
|
||||
|
||||
/* get wallclock at system boot */
|
||||
do {
|
||||
version = wall_clock->version;
|
||||
rmb(); /* fetch version before time */
|
||||
now.tv_sec = ((uint64_t)wall_clock->sec_hi << 32) | wall_clock->sec;
|
||||
now.tv_nsec = wall_clock->nsec;
|
||||
rmb(); /* fetch time before checking version */
|
||||
} while ((wall_clock->version & 1) || (version != wall_clock->version));
|
||||
|
||||
/* time since system boot */
|
||||
ktime_get_ts64(&ts_monotonic);
|
||||
*ts = timespec64_add(now, ts_monotonic);
|
||||
}
|
||||
|
||||
static int xen_pvclock_gtod_notify(struct notifier_block *nb,
|
||||
unsigned long was_set, void *priv)
|
||||
{
|
||||
/* Protected by the calling core code serialization */
|
||||
static struct timespec64 next_sync;
|
||||
|
||||
struct xen_platform_op op;
|
||||
struct timespec64 now, system_time;
|
||||
struct timekeeper *tk = priv;
|
||||
|
||||
now.tv_sec = tk->xtime_sec;
|
||||
now.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
|
||||
system_time = timespec64_add(now, tk->wall_to_monotonic);
|
||||
|
||||
/*
|
||||
* We only take the expensive HV call when the clock was set
|
||||
* or when the 11 minutes RTC synchronization time elapsed.
|
||||
*/
|
||||
if (!was_set && timespec64_compare(&now, &next_sync) < 0)
|
||||
return NOTIFY_OK;
|
||||
|
||||
op.cmd = XENPF_settime64;
|
||||
op.u.settime64.mbz = 0;
|
||||
op.u.settime64.secs = now.tv_sec;
|
||||
op.u.settime64.nsecs = now.tv_nsec;
|
||||
op.u.settime64.system_time = timespec64_to_ns(&system_time);
|
||||
(void)HYPERVISOR_platform_op(&op);
|
||||
|
||||
/*
|
||||
* Move the next drift compensation time 11 minutes
|
||||
* ahead. That's emulating the sync_cmos_clock() update for
|
||||
* the hardware RTC.
|
||||
*/
|
||||
next_sync = now;
|
||||
next_sync.tv_sec += 11 * 60;
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block xen_pvclock_gtod_notifier = {
|
||||
.notifier_call = xen_pvclock_gtod_notify,
|
||||
};
|
||||
|
||||
static void xen_percpu_init(void)
|
||||
{
|
||||
struct vcpu_register_vcpu_info info;
|
||||
@@ -104,6 +186,8 @@ static void xen_percpu_init(void)
|
||||
BUG_ON(err);
|
||||
per_cpu(xen_vcpu, cpu) = vcpup;
|
||||
|
||||
xen_setup_runstate_info(cpu);
|
||||
|
||||
after_register_vcpu_info:
|
||||
enable_percpu_irq(xen_events_irq, 0);
|
||||
put_cpu();
|
||||
@@ -271,6 +355,11 @@ static int __init xen_guest_init(void)
|
||||
|
||||
register_cpu_notifier(&xen_cpu_notifier);
|
||||
|
||||
pv_time_ops.steal_clock = xen_stolen_accounting;
|
||||
static_key_slow_inc(¶virt_steal_enabled);
|
||||
if (xen_initial_domain())
|
||||
pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(xen_guest_init);
|
||||
@@ -282,6 +371,11 @@ static int __init xen_pm_init(void)
|
||||
|
||||
pm_power_off = xen_power_off;
|
||||
arm_pm_restart = xen_restart;
|
||||
if (!xen_initial_domain()) {
|
||||
struct timespec64 ts;
|
||||
xen_read_wallclock(&ts);
|
||||
do_settimeofday64(&ts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -307,5 +401,6 @@ EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
|
||||
EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
|
||||
EXPORT_SYMBOL_GPL(HYPERVISOR_vcpu_op);
|
||||
EXPORT_SYMBOL_GPL(HYPERVISOR_tmem_op);
|
||||
EXPORT_SYMBOL_GPL(HYPERVISOR_platform_op);
|
||||
EXPORT_SYMBOL_GPL(HYPERVISOR_multicall);
|
||||
EXPORT_SYMBOL_GPL(privcmd_call);
|
||||
|
||||
@@ -89,6 +89,7 @@ HYPERCALL2(memory_op);
|
||||
HYPERCALL2(physdev_op);
|
||||
HYPERCALL3(vcpu_op);
|
||||
HYPERCALL1(tmem_op);
|
||||
HYPERCALL1(platform_op_raw);
|
||||
HYPERCALL2(multicall);
|
||||
|
||||
ENTRY(privcmd_call)
|
||||
|
||||
@@ -555,6 +555,25 @@ config SECCOMP
|
||||
and the task is only allowed to execute a few safe syscalls
|
||||
defined by each seccomp mode.
|
||||
|
||||
config PARAVIRT
|
||||
bool "Enable paravirtualization code"
|
||||
help
|
||||
This changes the kernel so it can modify itself when it is run
|
||||
under a hypervisor, potentially improving performance significantly
|
||||
over full virtualization.
|
||||
|
||||
config PARAVIRT_TIME_ACCOUNTING
|
||||
bool "Paravirtual steal time accounting"
|
||||
select PARAVIRT
|
||||
default n
|
||||
help
|
||||
Select this option to enable fine granularity task steal time
|
||||
accounting. Time spent executing other tasks in parallel with
|
||||
the current vCPU is discounted from the vCPU power. To account for
|
||||
that, there can be a small performance impact.
|
||||
|
||||
If in doubt, say N here.
|
||||
|
||||
config XEN_DOM0
|
||||
def_bool y
|
||||
depends on XEN
|
||||
@@ -563,6 +582,7 @@ config XEN
|
||||
bool "Xen guest support on ARM64"
|
||||
depends on ARM64 && OF
|
||||
select SWIOTLB_XEN
|
||||
select PARAVIRT
|
||||
help
|
||||
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64.
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _ASM_ARM64_PARAVIRT_H
|
||||
#define _ASM_ARM64_PARAVIRT_H
|
||||
|
||||
#ifdef CONFIG_PARAVIRT
|
||||
struct static_key;
|
||||
extern struct static_key paravirt_steal_enabled;
|
||||
extern struct static_key paravirt_steal_rq_enabled;
|
||||
|
||||
struct pv_time_ops {
|
||||
unsigned long long (*steal_clock)(int cpu);
|
||||
};
|
||||
extern struct pv_time_ops pv_time_ops;
|
||||
|
||||
static inline u64 paravirt_steal_clock(int cpu)
|
||||
{
|
||||
return pv_time_ops.steal_clock(cpu);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -41,6 +41,7 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o
|
||||
arm64-obj-$(CONFIG_PCI) += pci.o
|
||||
arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
|
||||
arm64-obj-$(CONFIG_ACPI) += acpi.o
|
||||
arm64-obj-$(CONFIG_PARAVIRT) += paravirt.o
|
||||
|
||||
obj-y += $(arm64-obj-y) vdso/
|
||||
obj-m += $(arm64-obj-m)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2013 Citrix Systems
|
||||
*
|
||||
* Author: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/paravirt.h>
|
||||
|
||||
struct static_key paravirt_steal_enabled;
|
||||
struct static_key paravirt_steal_rq_enabled;
|
||||
|
||||
struct pv_time_ops pv_time_ops;
|
||||
EXPORT_SYMBOL_GPL(pv_time_ops);
|
||||
@@ -80,6 +80,7 @@ HYPERCALL2(memory_op);
|
||||
HYPERCALL2(physdev_op);
|
||||
HYPERCALL3(vcpu_op);
|
||||
HYPERCALL1(tmem_op);
|
||||
HYPERCALL1(platform_op_raw);
|
||||
HYPERCALL2(multicall);
|
||||
|
||||
ENTRY(privcmd_call)
|
||||
|
||||
@@ -310,10 +310,10 @@ HYPERVISOR_mca(struct xen_mc *mc_op)
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_dom0_op(struct xen_platform_op *platform_op)
|
||||
HYPERVISOR_platform_op(struct xen_platform_op *op)
|
||||
{
|
||||
platform_op->interface_version = XENPF_INTERFACE_VERSION;
|
||||
return _hypercall1(int, dom0_op, platform_op);
|
||||
op->interface_version = XENPF_INTERFACE_VERSION;
|
||||
return _hypercall1(int, platform_op, op);
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ static u32 xen_apic_read(u32 reg)
|
||||
if (reg != APIC_ID)
|
||||
return 0;
|
||||
|
||||
ret = HYPERVISOR_dom0_op(&op);
|
||||
ret = HYPERVISOR_platform_op(&op);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ static bool __init xen_check_mwait(void)
|
||||
|
||||
set_xen_guest_handle(op.u.set_pminfo.pdc, buf);
|
||||
|
||||
if ((HYPERVISOR_dom0_op(&op) == 0) &&
|
||||
if ((HYPERVISOR_platform_op(&op) == 0) &&
|
||||
(buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) {
|
||||
cpuid_leaf5_ecx_val = cx;
|
||||
cpuid_leaf5_edx_val = dx;
|
||||
@@ -1365,7 +1365,7 @@ static void __init xen_boot_params_init_edd(void)
|
||||
info->params.length = sizeof(info->params);
|
||||
set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
|
||||
&info->params);
|
||||
ret = HYPERVISOR_dom0_op(&op);
|
||||
ret = HYPERVISOR_platform_op(&op);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
@@ -1383,7 +1383,7 @@ static void __init xen_boot_params_init_edd(void)
|
||||
op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
|
||||
for (nr = 0; nr < EDD_MBR_SIG_MAX; nr++) {
|
||||
op.u.firmware_info.index = nr;
|
||||
ret = HYPERVISOR_dom0_op(&op);
|
||||
ret = HYPERVISOR_platform_op(&op);
|
||||
if (ret)
|
||||
break;
|
||||
mbr_signature[nr] = op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
|
||||
@@ -1690,7 +1690,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
|
||||
xen_start_info->console.domU.mfn = 0;
|
||||
xen_start_info->console.domU.evtchn = 0;
|
||||
|
||||
if (HYPERVISOR_dom0_op(&op) == 0)
|
||||
if (HYPERVISOR_platform_op(&op) == 0)
|
||||
boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags;
|
||||
|
||||
/* Make sure ACS will be enabled */
|
||||
|
||||
@@ -34,7 +34,8 @@ static void xen_hvm_post_suspend(int suspend_cancelled)
|
||||
{
|
||||
#ifdef CONFIG_XEN_PVHVM
|
||||
int cpu;
|
||||
xen_hvm_init_shared_info();
|
||||
if (!suspend_cancelled)
|
||||
xen_hvm_init_shared_info();
|
||||
xen_callback_vector();
|
||||
xen_unplug_emulated_devices();
|
||||
if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
|
||||
|
||||
+31
-84
@@ -16,6 +16,7 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pvclock_gtod.h>
|
||||
#include <linux/timekeeper_internal.h>
|
||||
|
||||
#include <asm/pvclock.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
@@ -32,86 +33,12 @@
|
||||
#define TIMER_SLOP 100000
|
||||
#define NS_PER_TICK (1000000000LL / HZ)
|
||||
|
||||
/* runstate info updated by Xen */
|
||||
static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate);
|
||||
|
||||
/* snapshots of runstate info */
|
||||
static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot);
|
||||
|
||||
/* unused ns of stolen time */
|
||||
static DEFINE_PER_CPU(u64, xen_residual_stolen);
|
||||
|
||||
/* return an consistent snapshot of 64-bit time/counter value */
|
||||
static u64 get64(const u64 *p)
|
||||
{
|
||||
u64 ret;
|
||||
|
||||
if (BITS_PER_LONG < 64) {
|
||||
u32 *p32 = (u32 *)p;
|
||||
u32 h, l;
|
||||
|
||||
/*
|
||||
* Read high then low, and then make sure high is
|
||||
* still the same; this will only loop if low wraps
|
||||
* and carries into high.
|
||||
* XXX some clean way to make this endian-proof?
|
||||
*/
|
||||
do {
|
||||
h = p32[1];
|
||||
barrier();
|
||||
l = p32[0];
|
||||
barrier();
|
||||
} while (p32[1] != h);
|
||||
|
||||
ret = (((u64)h) << 32) | l;
|
||||
} else
|
||||
ret = *p;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runstate accounting
|
||||
*/
|
||||
static void get_runstate_snapshot(struct vcpu_runstate_info *res)
|
||||
{
|
||||
u64 state_time;
|
||||
struct vcpu_runstate_info *state;
|
||||
|
||||
BUG_ON(preemptible());
|
||||
|
||||
state = this_cpu_ptr(&xen_runstate);
|
||||
|
||||
/*
|
||||
* The runstate info is always updated by the hypervisor on
|
||||
* the current CPU, so there's no need to use anything
|
||||
* stronger than a compiler barrier when fetching it.
|
||||
*/
|
||||
do {
|
||||
state_time = get64(&state->state_entry_time);
|
||||
barrier();
|
||||
*res = *state;
|
||||
barrier();
|
||||
} while (get64(&state->state_entry_time) != state_time);
|
||||
}
|
||||
|
||||
/* return true when a vcpu could run but has no real cpu to run on */
|
||||
bool xen_vcpu_stolen(int vcpu)
|
||||
{
|
||||
return per_cpu(xen_runstate, vcpu).state == RUNSTATE_runnable;
|
||||
}
|
||||
|
||||
void xen_setup_runstate_info(int cpu)
|
||||
{
|
||||
struct vcpu_register_runstate_memory_area area;
|
||||
|
||||
area.addr.v = &per_cpu(xen_runstate, cpu);
|
||||
|
||||
if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area,
|
||||
cpu, &area))
|
||||
BUG();
|
||||
}
|
||||
|
||||
static void do_stolen_accounting(void)
|
||||
{
|
||||
struct vcpu_runstate_info state;
|
||||
@@ -119,7 +46,7 @@ static void do_stolen_accounting(void)
|
||||
s64 runnable, offline, stolen;
|
||||
cputime_t ticks;
|
||||
|
||||
get_runstate_snapshot(&state);
|
||||
xen_get_runstate_snapshot(&state);
|
||||
|
||||
WARN_ON(state.state != RUNSTATE_running);
|
||||
|
||||
@@ -194,26 +121,46 @@ static int xen_pvclock_gtod_notify(struct notifier_block *nb,
|
||||
unsigned long was_set, void *priv)
|
||||
{
|
||||
/* Protected by the calling core code serialization */
|
||||
static struct timespec next_sync;
|
||||
static struct timespec64 next_sync;
|
||||
|
||||
struct xen_platform_op op;
|
||||
struct timespec now;
|
||||
struct timespec64 now;
|
||||
struct timekeeper *tk = priv;
|
||||
static bool settime64_supported = true;
|
||||
int ret;
|
||||
|
||||
now = __current_kernel_time();
|
||||
now.tv_sec = tk->xtime_sec;
|
||||
now.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
|
||||
|
||||
/*
|
||||
* We only take the expensive HV call when the clock was set
|
||||
* or when the 11 minutes RTC synchronization time elapsed.
|
||||
*/
|
||||
if (!was_set && timespec_compare(&now, &next_sync) < 0)
|
||||
if (!was_set && timespec64_compare(&now, &next_sync) < 0)
|
||||
return NOTIFY_OK;
|
||||
|
||||
op.cmd = XENPF_settime;
|
||||
op.u.settime.secs = now.tv_sec;
|
||||
op.u.settime.nsecs = now.tv_nsec;
|
||||
op.u.settime.system_time = xen_clocksource_read();
|
||||
again:
|
||||
if (settime64_supported) {
|
||||
op.cmd = XENPF_settime64;
|
||||
op.u.settime64.mbz = 0;
|
||||
op.u.settime64.secs = now.tv_sec;
|
||||
op.u.settime64.nsecs = now.tv_nsec;
|
||||
op.u.settime64.system_time = xen_clocksource_read();
|
||||
} else {
|
||||
op.cmd = XENPF_settime32;
|
||||
op.u.settime32.secs = now.tv_sec;
|
||||
op.u.settime32.nsecs = now.tv_nsec;
|
||||
op.u.settime32.system_time = xen_clocksource_read();
|
||||
}
|
||||
|
||||
(void)HYPERVISOR_dom0_op(&op);
|
||||
ret = HYPERVISOR_platform_op(&op);
|
||||
|
||||
if (ret == -ENOSYS && settime64_supported) {
|
||||
settime64_supported = false;
|
||||
goto again;
|
||||
}
|
||||
if (ret < 0)
|
||||
return NOTIFY_BAD;
|
||||
|
||||
/*
|
||||
* Move the next drift compensation time 11 minutes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
|
||||
obj-$(CONFIG_X86) += fallback.o
|
||||
obj-y += grant-table.o features.o balloon.o manage.o preempt.o
|
||||
obj-y += grant-table.o features.o balloon.o manage.o preempt.o time.o
|
||||
obj-y += events/
|
||||
obj-y += xenbus/
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ static int xen_acpi_notify_hypervisor_state(u8 sleep_state,
|
||||
bits, val_a, val_b))
|
||||
return -1;
|
||||
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
HYPERVISOR_platform_op(&op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user