blob: 7c85dd816dca1ae0244ae40ade0f31f2bf2c1e61 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Linux-specific definitions for managing interactions with Microsoft's
* Hyper-V hypervisor. The definitions in this file are specific to
* the ARM64 architecture. See include/asm-generic/mshyperv.h for
* definitions are that architecture independent.
*
* Definitions that are specified in the Hyper-V Top Level Functional
* Spec (TLFS) should not go in this file, but should instead go in
* hyperv-tlfs.h.
*
* Copyright (C) 2019, Microsoft, Inc.
*
* Author : Michael Kelley <mikelley@microsoft.com>
*/
#ifndef _ASM_MSHYPERV_H
#define _ASM_MSHYPERV_H
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/clocksource.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <asm/hyperv-tlfs.h>
/*
* Define the IRQ numbers/vectors used by Hyper-V VMbus interrupts
* and by STIMER0 Direct Mode interrupts. Hyper-V should be supplying
* these values through ACPI, but there are no other interrupting
* devices in a Hyper-V VM on ARM64, so it's OK to hard code for now.
* The "CALLBACK_VECTOR" terminology is a left-over from the x86/x64
* world that is used in architecture independent Hyper-V code.
*/
#define HYPERVISOR_CALLBACK_VECTOR 16
#define HV_STIMER0_IRQNR 17
extern u64 hv_do_hvc(u64 control, ...);
extern u64 hv_do_hvc_fast_get(u64 control, u64 input1, u64 input2, u64 input3,
struct hv_get_vp_register_output *output);
/*
* Declare calls to get and set Hyper-V VP register values on ARM64, which
* requires a hypercall.
*/
extern void hv_set_vpreg(u32 reg, u64 value);
extern u64 hv_get_vpreg(u32 reg);
extern void hv_get_vpreg_128(u32 reg, struct hv_get_vp_register_output *result);
/*
* Use the Hyper-V provided stimer0 as the timer that is made
* available to the architecture independent Hyper-V drivers.
*/
#define hv_init_timer(timer, tick) \
hv_set_vpreg(HV_REGISTER_STIMER0_COUNT + (2*timer), tick)
#define hv_init_timer_config(timer, val) \
hv_set_vpreg(HV_REGISTER_STIMER0_CONFIG + (2*timer), val)
#define hv_get_current_tick(tick) \
(tick = hv_get_vpreg(HV_REGISTER_TIME_REFCOUNT))
#define hv_get_simp(val) (val = hv_get_vpreg(HV_REGISTER_SIPP))
#define hv_set_simp(val) hv_set_vpreg(HV_REGISTER_SIPP, val)
#define hv_get_siefp(val) (val = hv_get_vpreg(HV_REGISTER_SIFP))
#define hv_set_siefp(val) hv_set_vpreg(HV_REGISTER_SIFP, val)
#define hv_get_synic_state(val) (val = hv_get_vpreg(HV_REGISTER_SCONTROL))
#define hv_set_synic_state(val) hv_set_vpreg(HV_REGISTER_SCONTROL, val)
#define hv_get_vp_index(index) (index = hv_get_vpreg(HV_REGISTER_VPINDEX))
#define hv_signal_eom() hv_set_vpreg(HV_REGISTER_EOM, 0)
/*
* Hyper-V SINT registers are numbered sequentially, so we can just
* add the SINT number to the register number of SINT0
*/
#define hv_get_synint_state(sint_num, val) \
(val = hv_get_vpreg(HV_REGISTER_SINT0 + sint_num))
#define hv_set_synint_state(sint_num, val) \
hv_set_vpreg(HV_REGISTER_SINT0 + sint_num, val)
#define hv_get_crash_ctl(val) \
(val = hv_get_vpreg(HV_REGISTER_CRASH_CTL))
#define hv_get_time_ref_count(val) \
(val = hv_get_vpreg(HV_REGISTER_TIME_REFCOUNT))
#define hv_get_reference_tsc(val) \
(val = hv_get_vpreg(HV_REGISTER_REFERENCE_TSC))
#define hv_set_reference_tsc(val) \
hv_set_vpreg(HV_REGISTER_REFERENCE_TSC, val)
#define hv_set_clocksource_vdso(val) \
((val).archdata.vclock_mode = VCLOCK_HVCLOCK)
#if IS_ENABLED(CONFIG_HYPERV)
#define hv_enable_stimer0_percpu_irq(irq) enable_percpu_irq(irq, 0)
#define hv_disable_stimer0_percpu_irq(irq) disable_percpu_irq(irq)
#endif
/*
* ARM64 specific code to read the hardware clock.
*
* This could be used in both kernel space and userspace (vDSO), so make it
* possible for a previous definition to override the default one.
*/
#ifndef hv_get_raw_timer
#define hv_get_raw_timer() arch_timer_read_counter()
#endif
#include <asm-generic/mshyperv.h>
#endif