* Re: [PATCH v4 2/5] x86/hyper-v: Add synthetic debugger definitions
From: Jon Doron @ 2020-03-12 19:34 UTC (permalink / raw)
To: Michael Kelley
Cc: vkuznets, Wei Liu, kvm@vger.kernel.org,
linux-hyperv@vger.kernel.org
In-Reply-To: <MW2PR2101MB1052572531F218BF7DAFBA2AD7FD0@MW2PR2101MB1052.namprd21.prod.outlook.com>
Sure thing
On Thu, Mar 12, 2020 at 9:32 PM Michael Kelley <mikelley@microsoft.com> wrote:
>
> From: Jon Doron <arilou@gmail.com> Sent: Thursday, March 12, 2020 12:12 PM
> >
> > On 12/03/2020, Michael Kelley wrote:
> > >From: Vitaly Kuznetsov <vkuznets@redhat.com> Sent: Thursday, March 12, 2020 6:51 AM
> > >>
> > >> Michael Kelley <mikelley@microsoft.com> writes:
> > >>
> > >> > I'm flexible, and trying to not be a pain-in-the-neck. :-) What would
> > >> > the KVM guys think about putting the definitions in a KVM specific
> > >> > #include file, and clearly marking them as deprecated, mostly
> > >> > undocumented, and used only to support debugging old Windows
> > >> > versions?
> > >>
> > >> I *think* we should do the following: defines which *are* present in
> > >> TLFS doc (e.g. HV_FEATURE_DEBUG_MSRS_AVAILABLE,
> > >> HV_STATUS_OPERATION_DENIED, ...) go to asm/hyperv-tlfs.h, the rest
> > >> (syndbg) stuff goes to kvm-specific include (I'd suggest we just use
> > >> hyperv.h we already have).
> > >>
> > >> What do you think?
> > >>
> > >
> > >I could live with this proposal, since they *are* in the TLFS v6.0 as it
> > >exists today. However, v6.0 seems inconsistent in what parts of this
> > >debugging functionality it exposes, probably just because someone
> > >hasn't thought comprehensively about the topic across the whole
> > >document. I'll make sure that it gets looked at in the next revision
> > >(which should be a lot sooner that the 2+ years it took to get the v6.0
> > >revision done). But I won't be surprised if the remaining vestiges are
> > >removed at that time, in which case we would want to move the
> > >definitions from hyperv-tlfs.h to KVM's hyper.h.
> > >
> > >Michael
> >
> > Hi guys, just a quick note I went over the old HyperV TLFS and it seems
> > like all the Syndbg MSRs are documented (under Appendix F: Hypervisor
> > Synthetic MSRs, from v5.0b).
> >
> > It seems like the undocumented stuff is HV_X64_MSR_SYNDBG_OPTIONS which
> > seems kinda odd because that's how you enable the hypercalls debugging
> > interface which is documented.
> >
> > And the syndbg CPUID leafs are not documented as well.
> >
> > So would you like me to put all the MSRs in the tlfs omitting the
> > HV_X64_MSR_SYNDBG_OPTIONS.
> >
> > So in hyperv.h we will have HV_X64_MSR_SYNDBG_OPTIONS and the CPUID
> > leafs.
> >
>
> Could you make the decision based on the new v6.0 of the Hyper-V TLFS?
> See https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
> to get a copy. I think some of the synthetic debugger stuff has been dropped
> from the v6.0 version compared with the earlier v5.0 versions, and I'd like the
> updates to hyperv-tlfs.h to reflect that newest version.
>
> Michael
^ permalink raw reply
* [PATCH v5 0/5] x86/kvm/hyper-v: add support for synthetic debugger
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
Add support for the synthetic debugger interface of hyper-v, the
synthetic debugger has 2 modes.
1. Use a set of MSRs to send/recv information (undocumented so it's not
going to the hyperv-tlfs.h)
2. Use hypercalls
The first mode is based the following MSRs:
1. Control/Status MSRs which either asks for a send/recv .
2. Send/Recv MSRs each holds GPA where the send/recv buffers are.
3. Pending MSR, holds a GPA to a PAGE that simply has a boolean that
indicates if there is data pending to issue a recv VMEXIT.
The first mode implementation is to simply exit to user-space when
either the control MSR or the pending MSR are being set.
Then it's up-to userspace to implement the rest of the logic of sending/recving.
In the second mode instead of using MSRs KNet will simply issue
Hypercalls with the information to send/recv, in this mode the data
being transferred is UDP encapsulated, unlike in the previous mode in
which you get just the data to send.
The new hypercalls will exit to userspace which will be incharge of
re-encapsulating if needed the UDP packets to be sent.
There is an issue though in which KDNet does not respect the hypercall
page and simply issues vmcall/vmmcall instructions depending on the cpu
type expecting them to be handled as it a real hypercall was issued.
Jon Doron (5):
x86/kvm/hyper-v: Explicitly align hcall param for kvm_hyperv_exit
x86/hyper-v: Add synthetic debugger definitions
x86/kvm/hyper-v: Add support for synthetic debugger capability
x86/kvm/hyper-v: enable hypercalls regardless of hypercall page
x86/kvm/hyper-v: Add support for synthetic debugger via hypercalls
Documentation/virt/kvm/api.rst | 18 ++++
arch/x86/include/asm/hyperv-tlfs.h | 6 ++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/hyperv.c | 162 ++++++++++++++++++++++++++++-
arch/x86/kvm/hyperv.h | 27 +++++
arch/x86/kvm/trace.h | 51 +++++++++
arch/x86/kvm/x86.c | 9 ++
include/uapi/linux/kvm.h | 13 +++
8 files changed, 297 insertions(+), 2 deletions(-)
--
2.24.1
^ permalink raw reply
* [PATCH v5 1/5] x86/kvm/hyper-v: Explicitly align hcall param for kvm_hyperv_exit
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
In-Reply-To: <20200313132034.132315-1-arilou@gmail.com>
Signed-off-by: Jon Doron <arilou@gmail.com>
---
Documentation/virt/kvm/api.rst | 2 ++
include/uapi/linux/kvm.h | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index ebd383fba939..4872c47bbcff 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5025,9 +5025,11 @@ EOI was received.
#define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
__u32 type;
+ __u32 pad1;
union {
struct {
__u32 msr;
+ __u32 pad2;
__u64 control;
__u64 evt_page;
__u64 msg_page;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 4b95f9a31a2f..7ee0ddc4c457 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -189,9 +189,11 @@ struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
__u32 type;
+ __u32 pad1;
union {
struct {
__u32 msr;
+ __u32 pad2;
__u64 control;
__u64 evt_page;
__u64 msg_page;
--
2.24.1
^ permalink raw reply related
* [PATCH v5 2/5] x86/hyper-v: Add synthetic debugger definitions
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
In-Reply-To: <20200313132034.132315-1-arilou@gmail.com>
Hyper-V synthetic debugger has two modes, one that uses MSRs and
the other that use Hypercalls.
Add all the required definitions to both types of synthetic debugger
interface.
Some of the required new CPUIDs and MSRs are not documented in the TLFS
so they are in hyperv.h instead.
Signed-off-by: Jon Doron <arilou@gmail.com>
---
arch/x86/include/asm/hyperv-tlfs.h | 6 ++++++
arch/x86/kvm/hyperv.h | 22 ++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index 92abc1e42bfc..671ce2a39d4b 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -131,6 +131,8 @@
#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE BIT(8)
/* Crash MSR available */
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(10)
+/* Support for debug MSRs available */
+#define HV_FEATURE_DEBUG_MSRS_AVAILABLE BIT(11)
/* stimer Direct Mode is available */
#define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(19)
@@ -376,6 +378,9 @@ struct hv_tsc_emulation_status {
#define HVCALL_SEND_IPI_EX 0x0015
#define HVCALL_POST_MESSAGE 0x005c
#define HVCALL_SIGNAL_EVENT 0x005d
+#define HVCALL_POST_DEBUG_DATA 0x0069
+#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
+#define HVCALL_RESET_DEBUG_SESSION 0x006b
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
@@ -419,6 +424,7 @@ enum HV_GENERIC_SET_FORMAT {
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
#define HV_STATUS_INVALID_ALIGNMENT 4
#define HV_STATUS_INVALID_PARAMETER 5
+#define HV_STATUS_OPERATION_DENIED 8
#define HV_STATUS_INSUFFICIENT_MEMORY 11
#define HV_STATUS_INVALID_PORT_ID 17
#define HV_STATUS_INVALID_CONNECTION_ID 18
diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
index 757cb578101c..56bc3416b62f 100644
--- a/arch/x86/kvm/hyperv.h
+++ b/arch/x86/kvm/hyperv.h
@@ -23,6 +23,28 @@
#include <linux/kvm_host.h>
+/* These defines are required by KDNet and they are not part of Hyper-V TLFS */
+#define HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080
+#define HYPERV_CPUID_SYNDBG_INTERFACE 0x40000081
+#define HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082
+
+/*
+ * Hyper-V synthetic debugger platform capabilities
+ * These are HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits.
+ */
+#define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING BIT(1)
+
+/* Hyper-V Synthetic debug options MSR */
+#define HV_X64_MSR_SYNDBG_CONTROL 0x400000F1
+#define HV_X64_MSR_SYNDBG_STATUS 0x400000F2
+#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x400000F3
+#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x400000F4
+#define HV_X64_MSR_SYNDBG_PENDING_BUFFER 0x400000F5
+#define HV_X64_MSR_SYNDBG_OPTIONS 0x400000FF
+
+/* Hyper-V HV_X64_MSR_SYNDBG_OPTIONS bits */
+#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2)
+
static inline struct kvm_vcpu_hv *vcpu_to_hv_vcpu(struct kvm_vcpu *vcpu)
{
return &vcpu->arch.hyperv;
--
2.24.1
^ permalink raw reply related
* [PATCH v5 3/5] x86/kvm/hyper-v: Add support for synthetic debugger capability
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
In-Reply-To: <20200313132034.132315-1-arilou@gmail.com>
Add support for Hyper-V synthetic debugger (syndbg) interface.
The syndbg interface is using MSRs to emulate a way to send/recv packets
data.
The debug transport dll (kdvm/kdnet) will identify if Hyper-V is enabled
and if it supports the synthetic debugger interface it will attempt to
use it, instead of trying to initialize a network adapter.
Signed-off-by: Jon Doron <arilou@gmail.com>
---
Documentation/virt/kvm/api.rst | 16 ++++
arch/x86/include/asm/kvm_host.h | 13 +++
arch/x86/kvm/hyperv.c | 135 +++++++++++++++++++++++++++++++-
arch/x86/kvm/hyperv.h | 5 ++
arch/x86/kvm/trace.h | 51 ++++++++++++
arch/x86/kvm/x86.c | 9 +++
include/uapi/linux/kvm.h | 11 +++
7 files changed, 239 insertions(+), 1 deletion(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 4872c47bbcff..fe992dcf4f93 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5024,6 +5024,7 @@ EOI was received.
struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
+ #define KVM_EXIT_HYPERV_SYNDBG 3
__u32 type;
__u32 pad1;
union {
@@ -5039,6 +5040,15 @@ EOI was received.
__u64 result;
__u64 params[2];
} hcall;
+ struct {
+ __u32 msr;
+ __u32 pad2;
+ __u64 control;
+ __u64 status;
+ __u64 send_page;
+ __u64 recv_page;
+ __u64 pending_page;
+ } syndbg;
} u;
};
/* KVM_EXIT_HYPERV */
@@ -5055,6 +5065,12 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
event/message pages and to enable/disable SynIC messages/events processing
in userspace.
+ - KVM_EXIT_HYPERV_SYNDBG -- synchronously notify user-space about
+
+Hyper-V Synthetic debugger state change. Notification is used to either update
+the pending_page location or to send a control command (send the buffer located
+in send_page or recv a buffer to recv_page).
+
::
/* KVM_EXIT_ARM_NISV */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 98959e8cd448..f8e58e8866bb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -854,6 +854,18 @@ struct kvm_apic_map {
struct kvm_lapic *phys_map[];
};
+/* Hyper-V synthetic debugger (SynDbg)*/
+struct kvm_hv_syndbg {
+ struct {
+ u64 control;
+ u64 status;
+ u64 send_page;
+ u64 recv_page;
+ u64 pending_page;
+ } control;
+ u64 options;
+};
+
/* Hyper-V emulation context */
struct kvm_hv {
struct mutex hv_lock;
@@ -877,6 +889,7 @@ struct kvm_hv {
atomic_t num_mismatched_vp_indexes;
struct hv_partition_assist_pg *hv_pa_pg;
+ struct kvm_hv_syndbg hv_syndbg;
};
enum kvm_irqchip_mode {
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index a86fda7a1d03..b6a97abe2bc9 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -266,6 +266,107 @@ static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
return ret;
}
+static int kvm_hv_syndbg_complete_userspace(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_hv *hv = &kvm->arch.hyperv;
+
+ if (vcpu->run->hyperv.u.syndbg.msr == HV_X64_MSR_SYNDBG_CONTROL)
+ hv->hv_syndbg.control.status =
+ vcpu->run->hyperv.u.syndbg.status;
+ return 1;
+}
+
+static void syndbg_exit(struct kvm_vcpu *vcpu, u32 msr)
+{
+ struct kvm_hv_syndbg *syndbg = vcpu_to_hv_syndbg(vcpu);
+ struct kvm_vcpu_hv *hv_vcpu = &vcpu->arch.hyperv;
+
+ hv_vcpu->exit.type = KVM_EXIT_HYPERV_SYNDBG;
+ hv_vcpu->exit.u.syndbg.msr = msr;
+ hv_vcpu->exit.u.syndbg.control = syndbg->control.control;
+ hv_vcpu->exit.u.syndbg.send_page = syndbg->control.send_page;
+ hv_vcpu->exit.u.syndbg.recv_page = syndbg->control.recv_page;
+ hv_vcpu->exit.u.syndbg.pending_page = syndbg->control.pending_page;
+ vcpu->arch.complete_userspace_io =
+ kvm_hv_syndbg_complete_userspace;
+
+ kvm_make_request(KVM_REQ_HV_EXIT, vcpu);
+}
+
+static int syndbg_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+ struct kvm_hv_syndbg *syndbg = vcpu_to_hv_syndbg(vcpu);
+ int ret;
+
+ trace_kvm_hv_syndbg_set_msr(vcpu->vcpu_id,
+ vcpu_to_hv_vcpu(vcpu)->vp_index, msr, data);
+ ret = 0;
+ switch (msr) {
+ case HV_X64_MSR_SYNDBG_CONTROL:
+ syndbg->control.control = data;
+ syndbg_exit(vcpu, msr);
+ break;
+ case HV_X64_MSR_SYNDBG_STATUS:
+ syndbg->control.status = data;
+ break;
+ case HV_X64_MSR_SYNDBG_SEND_BUFFER:
+ syndbg->control.send_page = data;
+ break;
+ case HV_X64_MSR_SYNDBG_RECV_BUFFER:
+ syndbg->control.recv_page = data;
+ break;
+ case HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ syndbg->control.pending_page = data;
+ syndbg_exit(vcpu, msr);
+ break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ syndbg->options = data;
+ break;
+ default:
+ ret = 1;
+ break;
+ }
+
+ return ret;
+}
+
+static int syndbg_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+ struct kvm_hv_syndbg *syndbg = vcpu_to_hv_syndbg(vcpu);
+ int ret;
+
+ ret = 0;
+ switch (msr) {
+ case HV_X64_MSR_SYNDBG_CONTROL:
+ *pdata = syndbg->control.control;
+ break;
+ case HV_X64_MSR_SYNDBG_STATUS:
+ *pdata = syndbg->control.status;
+ break;
+ case HV_X64_MSR_SYNDBG_SEND_BUFFER:
+ *pdata = syndbg->control.send_page;
+ break;
+ case HV_X64_MSR_SYNDBG_RECV_BUFFER:
+ *pdata = syndbg->control.recv_page;
+ break;
+ case HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ *pdata = syndbg->control.pending_page;
+ break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ *pdata = syndbg->options;
+ break;
+ default:
+ ret = 1;
+ break;
+ }
+
+ trace_kvm_hv_syndbg_get_msr(vcpu->vcpu_id,
+ vcpu_to_hv_vcpu(vcpu)->vp_index, msr,
+ *pdata);
+ return ret;
+}
+
static int synic_get_msr(struct kvm_vcpu_hv_synic *synic, u32 msr, u64 *pdata,
bool host)
{
@@ -800,6 +901,8 @@ static bool kvm_hv_msr_partition_wide(u32 msr)
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
case HV_X64_MSR_TSC_EMULATION_CONTROL:
case HV_X64_MSR_TSC_EMULATION_STATUS:
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ case HV_X64_MSR_SYNDBG_CONTROL ... HV_X64_MSR_SYNDBG_PENDING_BUFFER:
r = true;
break;
}
@@ -1061,6 +1164,9 @@ static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
if (!host)
return 1;
break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ case HV_X64_MSR_SYNDBG_CONTROL ... HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ return syndbg_set_msr(vcpu, msr, data);
default:
vcpu_unimpl(vcpu, "Hyper-V unhandled wrmsr: 0x%x data 0x%llx\n",
msr, data);
@@ -1227,6 +1333,9 @@ static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
case HV_X64_MSR_TSC_EMULATION_STATUS:
data = hv->hv_tsc_emulation_status;
break;
+ case HV_X64_MSR_SYNDBG_OPTIONS:
+ case HV_X64_MSR_SYNDBG_CONTROL ... HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ return syndbg_get_msr(vcpu, msr, pdata);
default:
vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
return 1;
@@ -1797,6 +1906,9 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
{ .function = HYPERV_CPUID_ENLIGHTMENT_INFO },
{ .function = HYPERV_CPUID_IMPLEMENT_LIMITS },
{ .function = HYPERV_CPUID_NESTED_FEATURES },
+ { .function = HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS },
+ { .function = HYPERV_CPUID_SYNDBG_INTERFACE },
+ { .function = HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES },
};
int i, nent = ARRAY_SIZE(cpuid_entries);
@@ -1821,7 +1933,7 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
case HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS:
memcpy(signature, "Linux KVM Hv", 12);
- ent->eax = HYPERV_CPUID_NESTED_FEATURES;
+ ent->eax = HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES;
ent->ebx = signature[0];
ent->ecx = signature[1];
ent->edx = signature[2];
@@ -1856,9 +1968,12 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
ent->ebx |= HV_X64_POST_MESSAGES;
ent->ebx |= HV_X64_SIGNAL_EVENTS;
+ ent->ebx |= HV_X64_DEBUGGING;
ent->edx |= HV_FEATURE_FREQUENCY_MSRS_AVAILABLE;
ent->edx |= HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE;
+ ent->edx |= HV_X64_GUEST_DEBUGGING_AVAILABLE;
+ ent->edx |= HV_FEATURE_DEBUG_MSRS_AVAILABLE;
/*
* Direct Synthetic timers only make sense with in-kernel
@@ -1903,6 +2018,24 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
break;
+ case HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS:
+ memcpy(signature, "Linux KVM Hv", 12);
+
+ ent->eax = 0;
+ ent->ebx = signature[0];
+ ent->ecx = signature[1];
+ ent->edx = signature[2];
+ break;
+
+ case HYPERV_CPUID_SYNDBG_INTERFACE:
+ memcpy(signature, "VS#1\0\0\0\0\0\0\0\0", 12);
+ ent->eax = signature[0];
+ break;
+
+ case HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES:
+ ent->eax |= HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING;
+ break;
+
default:
break;
}
diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
index 56bc3416b62f..b8695dc5a3c0 100644
--- a/arch/x86/kvm/hyperv.h
+++ b/arch/x86/kvm/hyperv.h
@@ -68,6 +68,11 @@ static inline struct kvm_vcpu *synic_to_vcpu(struct kvm_vcpu_hv_synic *synic)
return hv_vcpu_to_vcpu(container_of(synic, struct kvm_vcpu_hv, synic));
}
+static inline struct kvm_hv_syndbg *vcpu_to_hv_syndbg(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->kvm->arch.hyperv.hv_syndbg;
+}
+
int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host);
int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host);
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index f194dd058470..bf6c3852868d 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -1515,6 +1515,57 @@ TRACE_EVENT(kvm_nested_vmenter_failed,
__print_symbolic(__entry->err, VMX_VMENTER_INSTRUCTION_ERRORS))
);
+/*
+ * Tracepoint for syndbg_set_msr.
+ */
+TRACE_EVENT(kvm_hv_syndbg_set_msr,
+ TP_PROTO(int vcpu_id, u32 vp_index, u32 msr, u64 data),
+ TP_ARGS(vcpu_id, vp_index, msr, data),
+
+ TP_STRUCT__entry(
+ __field(int, vcpu_id)
+ __field(u32, vp_index)
+ __field(u32, msr)
+ __field(u64, data)
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_id = vcpu_id;
+ __entry->vp_index = vp_index;
+ __entry->msr = msr;
+ __entry->data = data;
+ ),
+
+ TP_printk("vcpu_id %d vp_index %u msr 0x%x data 0x%llx",
+ __entry->vcpu_id, __entry->vp_index, __entry->msr,
+ __entry->data)
+);
+
+/*
+ * Tracepoint for syndbg_get_msr.
+ */
+TRACE_EVENT(kvm_hv_syndbg_get_msr,
+ TP_PROTO(int vcpu_id, u32 vp_index, u32 msr, u64 data),
+ TP_ARGS(vcpu_id, vp_index, msr, data),
+
+ TP_STRUCT__entry(
+ __field(int, vcpu_id)
+ __field(u32, vp_index)
+ __field(u32, msr)
+ __field(u64, data)
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_id = vcpu_id;
+ __entry->vp_index = vp_index;
+ __entry->msr = msr;
+ __entry->data = data;
+ ),
+
+ TP_printk("vcpu_id %d vp_index %u msr 0x%x data 0x%llx",
+ __entry->vcpu_id, __entry->vp_index, __entry->msr,
+ __entry->data)
+);
#endif /* _TRACE_KVM_H */
#undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5de200663f51..619c24bac79e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1214,6 +1214,10 @@ static const u32 emulated_msrs_all[] = {
HV_X64_MSR_VP_ASSIST_PAGE,
HV_X64_MSR_REENLIGHTENMENT_CONTROL, HV_X64_MSR_TSC_EMULATION_CONTROL,
HV_X64_MSR_TSC_EMULATION_STATUS,
+ HV_X64_MSR_SYNDBG_OPTIONS,
+ HV_X64_MSR_SYNDBG_CONTROL, HV_X64_MSR_SYNDBG_STATUS,
+ HV_X64_MSR_SYNDBG_SEND_BUFFER, HV_X64_MSR_SYNDBG_RECV_BUFFER,
+ HV_X64_MSR_SYNDBG_PENDING_BUFFER,
MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
MSR_KVM_PV_EOI_EN,
@@ -2906,6 +2910,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
*/
break;
case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
+ case HV_X64_MSR_SYNDBG_CONTROL ... HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ case HV_X64_MSR_SYNDBG_OPTIONS:
case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
case HV_X64_MSR_CRASH_CTL:
case HV_X64_MSR_STIMER0_CONFIG ... HV_X64_MSR_STIMER3_COUNT:
@@ -3151,6 +3157,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = 0x20000000;
break;
case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
+ case HV_X64_MSR_SYNDBG_CONTROL ... HV_X64_MSR_SYNDBG_PENDING_BUFFER:
+ case HV_X64_MSR_SYNDBG_OPTIONS:
case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
case HV_X64_MSR_CRASH_CTL:
case HV_X64_MSR_STIMER0_CONFIG ... HV_X64_MSR_STIMER3_COUNT:
@@ -3323,6 +3331,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_HYPERV_TLBFLUSH:
case KVM_CAP_HYPERV_SEND_IPI:
case KVM_CAP_HYPERV_CPUID:
+ case KVM_CAP_HYPERV_DEBUGGING:
case KVM_CAP_PCI_SEGMENT:
case KVM_CAP_DEBUGREGS:
case KVM_CAP_X86_ROBUST_SINGLESTEP:
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 7ee0ddc4c457..f20b81894f23 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -188,6 +188,7 @@ struct kvm_s390_cmma_log {
struct kvm_hyperv_exit {
#define KVM_EXIT_HYPERV_SYNIC 1
#define KVM_EXIT_HYPERV_HCALL 2
+#define KVM_EXIT_HYPERV_SYNDBG 3
__u32 type;
__u32 pad1;
union {
@@ -203,6 +204,15 @@ struct kvm_hyperv_exit {
__u64 result;
__u64 params[2];
} hcall;
+ struct {
+ __u32 msr;
+ __u32 pad2;
+ __u64 control;
+ __u64 status;
+ __u64 send_page;
+ __u64 recv_page;
+ __u64 pending_page;
+ } syndbg;
} u;
};
@@ -1012,6 +1022,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_NISV_TO_USER 177
#define KVM_CAP_ARM_INJECT_EXT_DABT 178
#define KVM_CAP_S390_VCPU_RESETS 179
+#define KVM_CAP_HYPERV_DEBUGGING 180
#ifdef KVM_CAP_IRQ_ROUTING
--
2.24.1
^ permalink raw reply related
* [PATCH v5 4/5] x86/kvm/hyper-v: enable hypercalls regardless of hypercall page
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
In-Reply-To: <20200313132034.132315-1-arilou@gmail.com>
Microsoft's kdvm.dll dbgtransport module does not respect the hypercall
page and simply identifies the CPU being used (AMD/Intel) and according
to it simply makes hypercalls with the relevant instruction
(vmmcall/vmcall respectively).
The relevant function in kdvm is KdHvConnectHypervisor which first checks
if the hypercall page has been enabled via HV_X64_MSR_HYPERCALL_ENABLE,
and in case it was not it simply sets the HV_X64_MSR_GUEST_OS_ID to
0x1000101010001 which means:
build_number = 0x0001
service_version = 0x01
minor_version = 0x01
major_version = 0x01
os_id = 0x00 (Undefined)
vendor_id = 1 (Microsoft)
os_type = 0 (A value of 0 indicates a proprietary, closed source OS)
and starts issuing the hypercall without setting the hypercall page.
To resolve this issue simply enable hypercalls also if the guest_os_id
is not 0.
Signed-off-by: Jon Doron <arilou@gmail.com>
---
arch/x86/kvm/hyperv.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index b6a97abe2bc9..917b10a637fc 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1639,7 +1639,10 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *current_vcpu, u64 ingpa, u64 outgpa,
bool kvm_hv_hypercall_enabled(struct kvm *kvm)
{
- return READ_ONCE(kvm->arch.hyperv.hv_hypercall) & HV_X64_MSR_HYPERCALL_ENABLE;
+ struct kvm_hv *hv = &kvm->arch.hyperv;
+
+ return READ_ONCE(hv->hv_hypercall) & HV_X64_MSR_HYPERCALL_ENABLE ||
+ READ_ONCE(hv->hv_guest_os_id) != 0;
}
static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
--
2.24.1
^ permalink raw reply related
* [PATCH v5 5/5] x86/kvm/hyper-v: Add support for synthetic debugger via hypercalls
From: Jon Doron @ 2020-03-13 13:20 UTC (permalink / raw)
To: kvm, linux-hyperv; +Cc: vkuznets, Jon Doron
In-Reply-To: <20200313132034.132315-1-arilou@gmail.com>
There is another mode for the synthetic debugger which uses hypercalls
to send/recv network data instead of the MSR interface.
This interface is much slower and less recommended since you might get
a lot of VMExits while KDVM polling for new packets to recv, rather
than simply checking the pending page to see if there is data avialble
and then request.
Signed-off-by: Jon Doron <arilou@gmail.com>
---
arch/x86/kvm/hyperv.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 917b10a637fc..4a77ff61658b 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1821,6 +1821,28 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
}
ret = kvm_hv_send_ipi(vcpu, ingpa, outgpa, true, false);
break;
+ case HVCALL_POST_DEBUG_DATA:
+ case HVCALL_RETRIEVE_DEBUG_DATA:
+ if (unlikely(fast)) {
+ ret = HV_STATUS_INVALID_PARAMETER;
+ break;
+ }
+ /* fallthrough */
+ case HVCALL_RESET_DEBUG_SESSION: {
+ struct kvm_hv_syndbg *syndbg = vcpu_to_hv_syndbg(vcpu);
+ if (!(syndbg->options & HV_X64_SYNDBG_OPTION_USE_HCALLS)) {
+ ret = HV_STATUS_OPERATION_DENIED;
+ break;
+ }
+ vcpu->run->exit_reason = KVM_EXIT_HYPERV;
+ vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL;
+ vcpu->run->hyperv.u.hcall.input = param;
+ vcpu->run->hyperv.u.hcall.params[0] = ingpa;
+ vcpu->run->hyperv.u.hcall.params[1] = outgpa;
+ vcpu->arch.complete_userspace_io =
+ kvm_hv_hypercall_complete_userspace;
+ return 0;
+ }
default:
ret = HV_STATUS_INVALID_HYPERCALL_CODE;
break;
--
2.24.1
^ permalink raw reply related
* RE: [PATCH v5 2/5] x86/hyper-v: Add synthetic debugger definitions
From: Michael Kelley @ 2020-03-13 20:45 UTC (permalink / raw)
To: Jon Doron, kvm@vger.kernel.org, linux-hyperv@vger.kernel.org; +Cc: vkuznets
In-Reply-To: <20200313132034.132315-3-arilou@gmail.com>
From: Jon Doron <arilou@gmail.com> Sent: Friday, March 13, 2020 6:21 AM
>
> Hyper-V synthetic debugger has two modes, one that uses MSRs and
> the other that use Hypercalls.
>
> Add all the required definitions to both types of synthetic debugger
> interface.
>
> Some of the required new CPUIDs and MSRs are not documented in the TLFS
> so they are in hyperv.h instead.
>
> Signed-off-by: Jon Doron <arilou@gmail.com>
> ---
> arch/x86/include/asm/hyperv-tlfs.h | 6 ++++++
> arch/x86/kvm/hyperv.h | 22 ++++++++++++++++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
> index 92abc1e42bfc..671ce2a39d4b 100644
> --- a/arch/x86/include/asm/hyperv-tlfs.h
> +++ b/arch/x86/include/asm/hyperv-tlfs.h
> @@ -131,6 +131,8 @@
> #define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE BIT(8)
> /* Crash MSR available */
> #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(10)
> +/* Support for debug MSRs available */
> +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE BIT(11)
> /* stimer Direct Mode is available */
> #define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(19)
>
> @@ -376,6 +378,9 @@ struct hv_tsc_emulation_status {
> #define HVCALL_SEND_IPI_EX 0x0015
> #define HVCALL_POST_MESSAGE 0x005c
> #define HVCALL_SIGNAL_EVENT 0x005d
> +#define HVCALL_POST_DEBUG_DATA 0x0069
> +#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
> +#define HVCALL_RESET_DEBUG_SESSION 0x006b
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
>
> @@ -419,6 +424,7 @@ enum HV_GENERIC_SET_FORMAT {
> #define HV_STATUS_INVALID_HYPERCALL_INPUT 3
> #define HV_STATUS_INVALID_ALIGNMENT 4
> #define HV_STATUS_INVALID_PARAMETER 5
> +#define HV_STATUS_OPERATION_DENIED 8
> #define HV_STATUS_INSUFFICIENT_MEMORY 11
> #define HV_STATUS_INVALID_PORT_ID 17
> #define HV_STATUS_INVALID_CONNECTION_ID 18
> diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
> index 757cb578101c..56bc3416b62f 100644
> --- a/arch/x86/kvm/hyperv.h
> +++ b/arch/x86/kvm/hyperv.h
> @@ -23,6 +23,28 @@
>
> #include <linux/kvm_host.h>
>
> +/* These defines are required by KDNet and they are not part of Hyper-V TLFS */
I'm looking for a bit more info in the comment so that it's clear that the
synthetic debugger functionality is not committed to be available going
forward. Perhaps something along the lines of:
/* The #defines related to the synthetic debugger are required by KDNet, but
* they are not documented in the Hyper-V TLFS because the synthetic debugger
* functionality has been deprecated and is subject to removal in future versions
* of Windows.
*/
But with that additional comment text,
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
> +#define HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080
> +#define HYPERV_CPUID_SYNDBG_INTERFACE 0x40000081
> +#define HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082
> +
> +/*
> + * Hyper-V synthetic debugger platform capabilities
> + * These are HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits.
> + */
> +#define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING BIT(1)
> +
> +/* Hyper-V Synthetic debug options MSR */
> +#define HV_X64_MSR_SYNDBG_CONTROL 0x400000F1
> +#define HV_X64_MSR_SYNDBG_STATUS 0x400000F2
> +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x400000F3
> +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x400000F4
> +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER 0x400000F5
> +#define HV_X64_MSR_SYNDBG_OPTIONS 0x400000FF
> +
> +/* Hyper-V HV_X64_MSR_SYNDBG_OPTIONS bits */
> +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2)
> +
> static inline struct kvm_vcpu_hv *vcpu_to_hv_vcpu(struct kvm_vcpu *vcpu)
> {
> return &vcpu->arch.hyperv;
> --
> 2.24.1
^ permalink raw reply
* RE: [PATCH v5 2/5] x86/hyper-v: Add synthetic debugger definitions
From: Michael Kelley @ 2020-03-14 14:14 UTC (permalink / raw)
To: Jon Doron; +Cc: kvm@vger.kernel.org, linux-hyperv@vger.kernel.org, vkuznets
In-Reply-To: <20200314044451.GA15879@jondnuc>
From: Jon Doron <arilou@gmail.com> Sent: Friday, March 13, 2020 9:45 PM
>
> On 13/03/2020, Michael Kelley wrote:
> >From: Jon Doron <arilou@gmail.com> Sent: Friday, March 13, 2020 6:21 AM
> >>
> >> Hyper-V synthetic debugger has two modes, one that uses MSRs and
> >> the other that use Hypercalls.
> >>
> >> Add all the required definitions to both types of synthetic debugger
> >> interface.
> >>
> >> Some of the required new CPUIDs and MSRs are not documented in the TLFS
> >> so they are in hyperv.h instead.
> >>
> >> Signed-off-by: Jon Doron <arilou@gmail.com>
> >> ---
> >> arch/x86/include/asm/hyperv-tlfs.h | 6 ++++++
> >> arch/x86/kvm/hyperv.h | 22 ++++++++++++++++++++++
> >> 2 files changed, 28 insertions(+)
> >>
> >> diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
> >> index 92abc1e42bfc..671ce2a39d4b 100644
> >> --- a/arch/x86/include/asm/hyperv-tlfs.h
> >> +++ b/arch/x86/include/asm/hyperv-tlfs.h
> >> @@ -131,6 +131,8 @@
> >> #define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE BIT(8)
> >> /* Crash MSR available */
> >> #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(10)
> >> +/* Support for debug MSRs available */
> >> +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE BIT(11)
> >> /* stimer Direct Mode is available */
> >> #define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(19)
> >>
> >> @@ -376,6 +378,9 @@ struct hv_tsc_emulation_status {
> >> #define HVCALL_SEND_IPI_EX 0x0015
> >> #define HVCALL_POST_MESSAGE 0x005c
> >> #define HVCALL_SIGNAL_EVENT 0x005d
> >> +#define HVCALL_POST_DEBUG_DATA 0x0069
> >> +#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
> >> +#define HVCALL_RESET_DEBUG_SESSION 0x006b
> >> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
> >> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
> >>
> >> @@ -419,6 +424,7 @@ enum HV_GENERIC_SET_FORMAT {
> >> #define HV_STATUS_INVALID_HYPERCALL_INPUT 3
> >> #define HV_STATUS_INVALID_ALIGNMENT 4
> >> #define HV_STATUS_INVALID_PARAMETER 5
> >> +#define HV_STATUS_OPERATION_DENIED 8
> >> #define HV_STATUS_INSUFFICIENT_MEMORY 11
> >> #define HV_STATUS_INVALID_PORT_ID 17
> >> #define HV_STATUS_INVALID_CONNECTION_ID 18
> >> diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
> >> index 757cb578101c..56bc3416b62f 100644
> >> --- a/arch/x86/kvm/hyperv.h
> >> +++ b/arch/x86/kvm/hyperv.h
> >> @@ -23,6 +23,28 @@
> >>
> >> #include <linux/kvm_host.h>
> >>
> >> +/* These defines are required by KDNet and they are not part of Hyper-V TLFS */
> >
> >I'm looking for a bit more info in the comment so that it's clear that the
> >synthetic debugger functionality is not committed to be available going
> >forward. Perhaps something along the lines of:
> >
> >/* The #defines related to the synthetic debugger are required by KDNet, but
> > * they are not documented in the Hyper-V TLFS because the synthetic debugger
> > * functionality has been deprecated and is subject to removal in future versions
> > * of Windows.
> > */
> >
> >But with that additional comment text,
> >
> >Reviewed-by: Michael Kelley <mikelley@microsoft.com>
> >
>
> Sure thing, but one quick question I have noticed that in the 6.0 TLFS
> the bit indicating the DEBUG_MSRS are available is still documented is
> that intentional or a juss a miss?
From the side conversation I had with the Hyper-V people, I think
this is just a miss. They took out the MSR definitions, but forgot to
take out the flag indicating the presence of the MSRs. As I think I
mentioned in an earlier email, there will be future updates to the
TLFS, and I've put this topic on my list of things to make sure get
cleaned up.
Michael
>
> Cheers,
> -- Jon.
>
> >> +#define HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080
> >> +#define HYPERV_CPUID_SYNDBG_INTERFACE 0x40000081
> >> +#define HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082
> >> +
> >> +/*
> >> + * Hyper-V synthetic debugger platform capabilities
> >> + * These are HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits.
> >> + */
> >> +#define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING BIT(1)
> >> +
> >> +/* Hyper-V Synthetic debug options MSR */
> >> +#define HV_X64_MSR_SYNDBG_CONTROL 0x400000F1
> >> +#define HV_X64_MSR_SYNDBG_STATUS 0x400000F2
> >> +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x400000F3
> >> +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x400000F4
> >> +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER 0x400000F5
> >> +#define HV_X64_MSR_SYNDBG_OPTIONS 0x400000FF
> >> +
> >> +/* Hyper-V HV_X64_MSR_SYNDBG_OPTIONS bits */
> >> +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2)
> >> +
> >> static inline struct kvm_vcpu_hv *vcpu_to_hv_vcpu(struct kvm_vcpu *vcpu)
> >> {
> >> return &vcpu->arch.hyperv;
> >> --
> >> 2.24.1
> >
^ permalink raw reply
* [PATCH v6 02/10] arm/arm64: smccc-1.1: Add vendor specific owner definition
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
In the SMCCC v1.1 spec, the Owning Entity Number in the Function
Identifier may have a value of 6 for a vendor specific hypervisor
service call. Add this #define.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
include/linux/arm-smccc.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 59494df..8229203 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -46,6 +46,7 @@
#define ARM_SMCCC_OWNER_OEM 3
#define ARM_SMCCC_OWNER_STANDARD 4
#define ARM_SMCCC_OWNER_STANDARD_HYP 5
+#define ARM_SMCCC_OWNER_VENDOR_HYP 6
#define ARM_SMCCC_OWNER_TRUSTED_APP 48
#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
#define ARM_SMCCC_OWNER_TRUSTED_OS 50
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 01/10] arm64: hyperv: Add core Hyper-V include files
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level
Functional Spec (TLFS). The TLFS is distinctly oriented to x86/x64,
and Hyper-V has not separated out the architecture-dependent parts into
x86/x64 vs. ARM64. So hyperv-tlfs.h includes information for ARM64
that is not yet formally published. The TLFS is available here:
docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
mshyperv.h defines Linux-specific structures and routines for
interacting with Hyper-V on ARM64, and #includes the architecture-
independent part of mshyperv.h in include/asm-generic.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
MAINTAINERS | 2 +
arch/arm64/include/asm/hyperv-tlfs.h | 413 +++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/mshyperv.h | 115 ++++++++++
3 files changed, 530 insertions(+)
create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
create mode 100644 arch/arm64/include/asm/mshyperv.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 58bb5c4..398cfdb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7809,6 +7809,8 @@ F: arch/x86/include/asm/trace/hyperv.h
F: arch/x86/include/asm/hyperv-tlfs.h
F: arch/x86/kernel/cpu/mshyperv.c
F: arch/x86/hyperv
+F: arch/arm64/include/asm/hyperv-tlfs.h
+F: arch/arm64/include/asm/mshyperv.h
F: drivers/clocksource/hyperv_timer.c
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h
new file mode 100644
index 0000000..5e6a087
--- /dev/null
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
@@ -0,0 +1,413 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * This file contains definitions from the Hyper-V Hypervisor Top-Level
+ * Functional Specification (TLFS):
+ * https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#ifndef _ASM_HYPERV_TLFS_H
+#define _ASM_HYPERV_TLFS_H
+
+#include <linux/types.h>
+
+/*
+ * All data structures defined in the TLFS that are shared between Hyper-V
+ * and a guest VM use Little Endian byte ordering. This matches the default
+ * byte ordering of Linux running on ARM64, so no special handling is required.
+ */
+
+
+/*
+ * While not explicitly listed in the TLFS, Hyper-V always runs with a page
+ * size of 4096. These definitions are used when communicating with Hyper-V
+ * using guest physical pages and guest physical page addresses, since the
+ * guest page size may not be 4096 on ARM64.
+ */
+#define HV_HYP_PAGE_SHIFT 12
+#define HV_HYP_PAGE_SIZE (1 << HV_HYP_PAGE_SHIFT)
+#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1))
+
+/*
+ * These Hyper-V registers provide information equivalent to the CPUID
+ * instruction on x86/x64.
+ */
+#define HV_REGISTER_HYPERVISOR_VERSION 0x00000100 /*CPUID 0x40000002 */
+#define HV_REGISTER_PRIVILEGES_AND_FEATURES 0x00000200 /*CPUID 0x40000003 */
+#define HV_REGISTER_FEATURES 0x00000201 /*CPUID 0x40000004 */
+#define HV_REGISTER_IMPLEMENTATION_LIMITS 0x00000202 /*CPUID 0x40000005 */
+#define HV_ARM64_REGISTER_INTERFACE_VERSION 0x00090006 /*CPUID 0x40000001 */
+
+/*
+ * Feature identification. HvRegisterPrivilegesAndFeaturesInfo returns a
+ * 128-bit value with flags indicating which features are available to the
+ * partition based upon the current partition privileges. The 128-bit
+ * value is broken up with different portions stored in different 32-bit
+ * fields in the ms_hyperv structure.
+ */
+
+/* Partition Reference Counter available*/
+#define HV_MSR_TIME_REF_COUNT_AVAILABLE BIT(1)
+
+/* Synthetic Timers available */
+#define HV_MSR_SYNTIMER_AVAILABLE BIT(3)
+
+/* Reference TSC available */
+#define HV_MSR_REFERENCE_TSC_AVAILABLE BIT(9)
+
+
+/*
+ * This group of flags is in the high order 64-bits of the returned
+ * 128-bit value. Note that this set of bit positions differs from what
+ * is used on x86/x64 architecture.
+ */
+
+/* Crash MSRs available */
+#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(8)
+
+/* STIMER direct mode is available */
+#define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(13)
+
+/*
+ * Implementation recommendations in register
+ * HvRegisterFeaturesInfo. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal performance.
+ */
+
+/*
+ * Recommend not using Auto EOI
+ */
+#define HV_DEPRECATING_AEOI_RECOMMENDED BIT(9)
+
+/*
+ * Synthetic register definitions equivalent to MSRs on x86/x64
+ */
+#define HV_REGISTER_CRASH_P0 0x00000210
+#define HV_REGISTER_CRASH_P1 0x00000211
+#define HV_REGISTER_CRASH_P2 0x00000212
+#define HV_REGISTER_CRASH_P3 0x00000213
+#define HV_REGISTER_CRASH_P4 0x00000214
+#define HV_REGISTER_CRASH_CTL 0x00000215
+
+#define HV_REGISTER_GUEST_OSID 0x00090002
+#define HV_REGISTER_VPINDEX 0x00090003
+#define HV_REGISTER_TIME_REFCOUNT 0x00090004
+#define HV_REGISTER_REFERENCE_TSC 0x00090017
+
+#define HV_REGISTER_SINT0 0x000A0000
+#define HV_REGISTER_SINT1 0x000A0001
+#define HV_REGISTER_SINT2 0x000A0002
+#define HV_REGISTER_SINT3 0x000A0003
+#define HV_REGISTER_SINT4 0x000A0004
+#define HV_REGISTER_SINT5 0x000A0005
+#define HV_REGISTER_SINT6 0x000A0006
+#define HV_REGISTER_SINT7 0x000A0007
+#define HV_REGISTER_SINT8 0x000A0008
+#define HV_REGISTER_SINT9 0x000A0009
+#define HV_REGISTER_SINT10 0x000A000A
+#define HV_REGISTER_SINT11 0x000A000B
+#define HV_REGISTER_SINT12 0x000A000C
+#define HV_REGISTER_SINT13 0x000A000D
+#define HV_REGISTER_SINT14 0x000A000E
+#define HV_REGISTER_SINT15 0x000A000F
+#define HV_REGISTER_SCONTROL 0x000A0010
+#define HV_REGISTER_SVERSION 0x000A0011
+#define HV_REGISTER_SIFP 0x000A0012
+#define HV_REGISTER_SIPP 0x000A0013
+#define HV_REGISTER_EOM 0x000A0014
+#define HV_REGISTER_SIRBP 0x000A0015
+
+#define HV_REGISTER_STIMER0_CONFIG 0x000B0000
+#define HV_REGISTER_STIMER0_COUNT 0x000B0001
+#define HV_REGISTER_STIMER1_CONFIG 0x000B0002
+#define HV_REGISTER_STIMER1_COUNT 0x000B0003
+#define HV_REGISTER_STIMER2_CONFIG 0x000B0004
+#define HV_REGISTER_STIMER2_COUNT 0x000B0005
+#define HV_REGISTER_STIMER3_CONFIG 0x000B0006
+#define HV_REGISTER_STIMER3_COUNT 0x000B0007
+
+/*
+ * Crash notification flags.
+ */
+#define HV_CRASH_CTL_CRASH_NOTIFY_MSG BIT_ULL(62)
+#define HV_CRASH_CTL_CRASH_NOTIFY BIT_ULL(63)
+
+/*
+ * The guest OS needs to register the guest ID with the hypervisor.
+ * The guest ID is a 64 bit entity and the structure of this ID is
+ * specified in the Hyper-V TLFS.
+ */
+#define HV_LINUX_VENDOR_ID 0x8100
+
+/* Declare the various hypercall operations. */
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003
+#define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008
+#define HVCALL_SEND_IPI 0x000b
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
+#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
+#define HVCALL_SEND_IPI_EX 0x0015
+#define HVCALL_GET_VP_REGISTERS 0x0050
+#define HVCALL_SET_VP_REGISTERS 0x0051
+#define HVCALL_POST_MESSAGE 0x005c
+#define HVCALL_SIGNAL_EVENT 0x005d
+#define HVCALL_RETARGET_INTERRUPT 0x007e
+#define HVCALL_START_VIRTUAL_PROCESSOR 0x0099
+
+/* Declare standard hypercall field values. */
+#define HV_PARTITION_ID_SELF ((u64)-1)
+#define HV_VP_INDEX_SELF ((u32)-2)
+
+#define HV_HYPERCALL_FAST_BIT BIT(16)
+#define HV_HYPERCALL_REP_COUNT_1 BIT_ULL(32)
+#define HV_HYPERCALL_RESULT_MASK GENMASK_ULL(15, 0)
+
+/* Define the hypercall status result */
+
+union hv_hypercall_status {
+ u64 as_uint64;
+ struct {
+ u16 status;
+ u16 reserved;
+ u16 reps_completed; /* Low 12 bits */
+ u16 reserved2;
+ };
+};
+
+/* hypercall status code */
+#define HV_STATUS_SUCCESS 0
+#define HV_STATUS_INVALID_HYPERCALL_CODE 2
+#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
+#define HV_STATUS_INVALID_ALIGNMENT 4
+#define HV_STATUS_INSUFFICIENT_MEMORY 11
+#define HV_STATUS_INVALID_CONNECTION_ID 18
+#define HV_STATUS_INSUFFICIENT_BUFFERS 19
+
+/* Define input and output layout for Get VP Register hypercall */
+struct hv_get_vp_register_input {
+ u64 partitionid;
+ u32 vpindex;
+ u8 inputvtl;
+ u8 padding[3];
+ u32 name0;
+ u32 name1;
+} __packed;
+
+struct hv_get_vp_register_output {
+ u64 registervaluelow;
+ u64 registervaluehigh;
+} __packed;
+
+#define HV_FLUSH_ALL_PROCESSORS BIT(0)
+#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1)
+#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
+#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
+
+enum HV_GENERIC_SET_FORMAT {
+ HV_GENERIC_SET_SPARSE_4K,
+ HV_GENERIC_SET_ALL,
+};
+
+/*
+ * The Hyper-V TimeRefCount register and the TSC
+ * page provide a guest VM clock with 100ns tick rate
+ */
+#define HV_CLOCK_HZ (NSEC_PER_SEC/100)
+
+/*
+ * The fields in this structure are set by Hyper-V and read
+ * by the Linux guest. They should be accessed with READ_ONCE()
+ * so the compiler doesn't optimize in a way that will cause
+ * problems. The union pads the size out to the page size
+ * used to communicate with Hyper-V.
+ */
+struct ms_hyperv_tsc_page {
+ union {
+ struct {
+ u32 tsc_sequence;
+ u32 reserved1;
+ u64 tsc_scale;
+ s64 tsc_offset;
+ } __packed;
+ u8 reserved2[HV_HYP_PAGE_SIZE];
+ };
+};
+
+/* Define the number of synthetic interrupt sources. */
+#define HV_SYNIC_SINT_COUNT (16)
+/* Define the expected SynIC version. */
+#define HV_SYNIC_VERSION_1 (0x1)
+
+#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
+#define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
+#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
+#define HV_SYNIC_SINT_MASKED (1ULL << 16)
+#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17)
+#define HV_SYNIC_SINT_VECTOR_MASK (0xFF)
+
+#define HV_SYNIC_STIMER_COUNT (4)
+
+/* Define synthetic interrupt controller message constants. */
+#define HV_MESSAGE_SIZE (256)
+#define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240)
+#define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30)
+
+/* Define hypervisor message types. */
+enum hv_message_type {
+ HVMSG_NONE = 0x00000000,
+
+ /* Memory access messages. */
+ HVMSG_UNMAPPED_GPA = 0x80000000,
+ HVMSG_GPA_INTERCEPT = 0x80000001,
+
+ /* Timer notification messages. */
+ HVMSG_TIMER_EXPIRED = 0x80000010,
+
+ /* Error messages. */
+ HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
+ HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021,
+ HVMSG_UNSUPPORTED_FEATURE = 0x80000022,
+
+ /* Trace buffer complete messages. */
+ HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040,
+};
+
+/* Define synthetic interrupt controller message flags. */
+union hv_message_flags {
+ __u8 asu8;
+ struct {
+ __u8 msg_pending:1;
+ __u8 reserved:7;
+ } __packed;
+};
+
+/* Define port identifier type. */
+union hv_port_id {
+ __u32 asu32;
+ struct {
+ __u32 id:24;
+ __u32 reserved:8;
+ } __packed u;
+};
+
+/* Define synthetic interrupt controller message header. */
+struct hv_message_header {
+ __u32 message_type;
+ __u8 payload_size;
+ union hv_message_flags message_flags;
+ __u8 reserved[2];
+ union {
+ __u64 sender;
+ union hv_port_id port;
+ };
+} __packed;
+
+/* Define synthetic interrupt controller message format. */
+struct hv_message {
+ struct hv_message_header header;
+ union {
+ __u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+ } u;
+} __packed;
+
+/* Define the synthetic interrupt message page layout. */
+struct hv_message_page {
+ struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
+} __packed;
+
+/* Define timer message payload structure. */
+struct hv_timer_message_payload {
+ __u32 timer_index;
+ __u32 reserved;
+ __u64 expiration_time; /* When the timer expired */
+ __u64 delivery_time; /* When the message was delivered */
+} __packed;
+
+#define HV_STIMER_ENABLE (1ULL << 0)
+#define HV_STIMER_PERIODIC (1ULL << 1)
+#define HV_STIMER_LAZY (1ULL << 2)
+#define HV_STIMER_AUTOENABLE (1ULL << 3)
+#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F)
+
+
+/* Define synthetic interrupt controller flag constants. */
+#define HV_EVENT_FLAGS_COUNT (256 * 8)
+#define HV_EVENT_FLAGS_LONG_COUNT (256 / sizeof(unsigned long))
+
+/*
+ * Timer configuration register.
+ */
+union hv_stimer_config {
+ u64 as_uint64;
+ struct {
+ u64 enable:1;
+ u64 periodic:1;
+ u64 lazy:1;
+ u64 auto_enable:1;
+ u64 apic_vector:8;
+ u64 direct_mode:1;
+ u64 reserved_z0:3;
+ u64 sintx:4;
+ u64 reserved_z1:44;
+ } __packed;
+};
+
+
+/* Define the synthetic interrupt controller event flags format. */
+union hv_synic_event_flags {
+ unsigned long flags[HV_EVENT_FLAGS_LONG_COUNT];
+};
+
+/* Define SynIC control register. */
+union hv_synic_scontrol {
+ u64 as_uint64;
+ struct {
+ u64 enable:1;
+ u64 reserved:63;
+ } __packed;
+};
+
+/* Define synthetic interrupt source. */
+union hv_synic_sint {
+ u64 as_uint64;
+ struct {
+ u64 vector:8;
+ u64 reserved1:8;
+ u64 masked:1;
+ u64 auto_eoi:1;
+ u64 reserved2:46;
+ } __packed;
+};
+
+/* Define the format of the SIMP register */
+union hv_synic_simp {
+ u64 as_uint64;
+ struct {
+ u64 simp_enabled:1;
+ u64 preserved:11;
+ u64 base_simp_gpa:52;
+ } __packed;
+};
+
+/* Define the format of the SIEFP register */
+union hv_synic_siefp {
+ u64 as_uint64;
+ struct {
+ u64 siefp_enabled:1;
+ u64 preserved:11;
+ u64 base_siefp_gpa:52;
+ } __packed;
+};
+
+struct hv_vpset {
+ u64 format;
+ u64 valid_bank_mask;
+ u64 bank_contents[];
+} __packed;
+
+
+#endif
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
new file mode 100644
index 0000000..60b3f68
--- /dev/null
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -0,0 +1,115 @@
+/* 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 <linux/arm-smccc.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_enable_vdso_clocksource()
+#define hv_set_clocksource_vdso(val) \
+ ((val).vdso_clock_mode = VDSO_CLOCKMODE_NONE)
+
+#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 */
+#define hv_get_raw_timer() arch_timer_read_counter()
+
+/* SMCCC hypercall parameters */
+#define HV_SMCCC_FUNC_NUMBER 1
+#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \
+ ARM_SMCCC_STD_CALL, \
+ ARM_SMCCC_SMC_64, \
+ ARM_SMCCC_OWNER_VENDOR_HYP, \
+ HV_SMCCC_FUNC_NUMBER)
+
+#include <asm-generic/mshyperv.h>
+
+#endif
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 03/10] arm64: hyperv: Add hypercall and register access functions
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add ARM64-specific code to make Hyper-V hypercalls and to
access virtual processor synthetic registers via hypercalls.
Hypercalls follow the SMC Calling Convention spec v1.1.
This code is architecture dependent and is mostly driven by
architecture independent code in the VMbus driver and the
Hyper-V timer clocksource driver.
This code is built only when CONFIG_HYPERV is enabled.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
MAINTAINERS | 1 +
arch/arm64/Kbuild | 1 +
arch/arm64/hyperv/Makefile | 2 +
arch/arm64/hyperv/hv_core.c | 167 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 171 insertions(+)
create mode 100644 arch/arm64/hyperv/Makefile
create mode 100644 arch/arm64/hyperv/hv_core.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 398cfdb..64ad2bf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7811,6 +7811,7 @@ F: arch/x86/kernel/cpu/mshyperv.c
F: arch/x86/hyperv
F: arch/arm64/include/asm/hyperv-tlfs.h
F: arch/arm64/include/asm/mshyperv.h
+F: arch/arm64/hyperv
F: drivers/clocksource/hyperv_timer.c
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
diff --git a/arch/arm64/Kbuild b/arch/arm64/Kbuild
index d646582..7a37608 100644
--- a/arch/arm64/Kbuild
+++ b/arch/arm64/Kbuild
@@ -3,4 +3,5 @@ obj-y += kernel/ mm/
obj-$(CONFIG_NET) += net/
obj-$(CONFIG_KVM) += kvm/
obj-$(CONFIG_XEN) += xen/
+obj-$(subst m,y,$(CONFIG_HYPERV)) += hyperv/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
new file mode 100644
index 0000000..1697d30
--- /dev/null
+++ b/arch/arm64/hyperv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y := hv_core.o
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
new file mode 100644
index 0000000..272c348
--- /dev/null
+++ b/arch/arm64/hyperv/hv_core.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Initialization of the interface with Microsoft's Hyper-V hypervisor,
+ * and various low level utility routines for interacting with Hyper-V.
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/hyperv.h>
+#include <linux/arm-smccc.h>
+#include <asm-generic/bug.h>
+#include <asm/hyperv-tlfs.h>
+#include <asm/mshyperv.h>
+
+
+/*
+ * hv_do_hypercall- Invoke the specified hypercall
+ */
+u64 hv_do_hypercall(u64 control, void *input, void *output)
+{
+ u64 input_address;
+ u64 output_address;
+ struct arm_smccc_res res;
+
+ input_address = input ? virt_to_phys(input) : 0;
+ output_address = output ? virt_to_phys(output) : 0;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control,
+ input_address, output_address, &res);
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_hypercall);
+
+/*
+ * hv_do_fast_hypercall8 -- Invoke the specified hypercall
+ * with arguments in registers instead of physical memory.
+ * Avoids the overhead of virt_to_phys for simple hypercalls.
+ */
+
+u64 hv_do_fast_hypercall8(u16 code, u64 input)
+{
+ u64 control;
+ struct arm_smccc_res res;
+
+ control = (u64)code | HV_HYPERCALL_FAST_BIT;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control, input, &res);
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
+
+
+/*
+ * Set a single VP register to a 64-bit value.
+ */
+void hv_set_vpreg(u32 msr, u64 value)
+{
+ union hv_hypercall_status status;
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_hvc(
+ HV_FUNC_ID,
+ HVCALL_SET_VP_REGISTERS | HV_HYPERCALL_FAST_BIT |
+ HV_HYPERCALL_REP_COUNT_1,
+ HV_PARTITION_ID_SELF,
+ HV_VP_INDEX_SELF,
+ msr,
+ 0,
+ value,
+ 0,
+ &res);
+ status.as_uint64 = res.a0;
+
+ /*
+ * Something is fundamentally broken in the hypervisor if
+ * setting a VP register fails. There's really no way to
+ * continue as a guest VM, so panic.
+ */
+ BUG_ON(status.status != HV_STATUS_SUCCESS);
+}
+EXPORT_SYMBOL_GPL(hv_set_vpreg);
+
+/*
+ * Get the value of a single VP register. One version
+ * returns just 64 bits and another returns the full 128 bits.
+ * The two versions are separate to avoid complicating the
+ * calling sequence for the more frequently used 64 bit version.
+ */
+
+/*
+ * Input and output memory allocation sizes are rounded up to a power
+ * of 2 so kmalloc() will guarantee alignment. In turn, the alignment
+ * ensures that the allocations don't cross a page boundary, which is
+ * required by the hypercall interface.
+ */
+#define INPUTSIZE (4 * sizeof(u64))
+#define OUTPUTSIZE (2 * sizeof(u64))
+
+static void __hv_get_vpreg_128(u32 msr, struct hv_get_vp_register_output *res)
+{
+ union hv_hypercall_status status;
+ struct hv_get_vp_register_input *input;
+
+ BUILD_BUG_ON(sizeof(*input) > INPUTSIZE);
+
+ input = kzalloc(INPUTSIZE, GFP_ATOMIC);
+
+ input->partitionid = HV_PARTITION_ID_SELF;
+ input->vpindex = HV_VP_INDEX_SELF;
+ input->inputvtl = 0;
+ input->name0 = msr;
+ input->name1 = 0;
+
+
+ status.as_uint64 = hv_do_hypercall(
+ HVCALL_GET_VP_REGISTERS | HV_HYPERCALL_REP_COUNT_1,
+ input, res);
+
+ /*
+ * Something is fundamentally broken in the hypervisor if
+ * getting a VP register fails. There's really no way to
+ * continue as a guest VM, so panic.
+ */
+ BUG_ON(status.status != HV_STATUS_SUCCESS);
+
+ kfree(input);
+}
+
+u64 hv_get_vpreg(u32 msr)
+{
+ struct hv_get_vp_register_output *output;
+ u64 result;
+
+ BUILD_BUG_ON(sizeof(*output) > OUTPUTSIZE);
+ output = kmalloc(OUTPUTSIZE, GFP_ATOMIC);
+
+ __hv_get_vpreg_128(msr, output);
+
+ result = output->registervaluelow;
+ kfree(output);
+ return result;
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg);
+
+void hv_get_vpreg_128(u32 msr, struct hv_get_vp_register_output *res)
+{
+ struct hv_get_vp_register_output *output;
+
+ BUILD_BUG_ON(sizeof(*output) > OUTPUTSIZE);
+ output = kmalloc(OUTPUTSIZE, GFP_ATOMIC);
+
+ __hv_get_vpreg_128(msr, output);
+
+ res->registervaluelow = output->registervaluelow;
+ res->registervaluehigh = output->registervaluehigh;
+ kfree(output);
+}
+EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 09/10] arm64: efi: Export screen_info
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
The Hyper-V frame buffer driver may be built as a module, and
it needs access to screen_info. So export screen_info.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/arm64/kernel/efi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index d0cf596..8ff557a 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -55,6 +55,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
/* we will fill this structure from the stub, so don't put it in .bss */
struct screen_info screen_info __section(.data);
+EXPORT_SYMBOL(screen_info);
int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 05/10] arm64: hyperv: Add interrupt handlers for VMbus and stimer
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add ARM64-specific code to set up and handle the interrupts
generated by Hyper-V for VMbus messages and for stimer expiration.
This code is architecture dependent and is mostly driven by
architecture independent code in the VMbus driver and the
Hyper-V timer clocksource driver.
This code is built only when CONFIG_HYPERV is enabled.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/arm64/hyperv/Makefile | 2 +-
arch/arm64/hyperv/mshyperv.c | 139 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/hyperv/mshyperv.c
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
index 1697d30..87c31c0 100644
--- a/arch/arm64/hyperv/Makefile
+++ b/arch/arm64/hyperv/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y := hv_core.o
+obj-y := hv_core.o mshyperv.o
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
new file mode 100644
index 0000000..ae6ece6
--- /dev/null
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Core routines for interacting with Microsoft's Hyper-V hypervisor,
+ * including setting up VMbus and STIMER interrupts, and handling
+ * crashes and kexecs. These interactions are through a set of
+ * static "handler" variables set by the architecture independent
+ * VMbus and STIMER drivers.
+ *
+ * Copyright (C) 2019, Microsoft, Inc.
+ *
+ * Author : Michael Kelley <mikelley@microsoft.com>
+ */
+
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/kexec.h>
+#include <linux/acpi.h>
+#include <linux/ptrace.h>
+#include <asm/hyperv-tlfs.h>
+#include <asm/mshyperv.h>
+
+static void (*vmbus_handler)(void);
+static void (*hv_stimer0_handler)(void);
+
+static int vmbus_irq;
+static long __percpu *vmbus_evt;
+static long __percpu *stimer0_evt;
+
+irqreturn_t hyperv_vector_handler(int irq, void *dev_id)
+{
+ vmbus_handler();
+ return IRQ_HANDLED;
+}
+
+/* Must be done just once */
+void hv_setup_vmbus_irq(void (*handler)(void))
+{
+ int result;
+
+ vmbus_handler = handler;
+ vmbus_irq = acpi_register_gsi(NULL, HYPERVISOR_CALLBACK_VECTOR,
+ ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH);
+ if (vmbus_irq <= 0) {
+ pr_err("Can't register Hyper-V VMBus GSI. Error %d",
+ vmbus_irq);
+ vmbus_irq = 0;
+ return;
+ }
+ vmbus_evt = alloc_percpu(long);
+ result = request_percpu_irq(vmbus_irq, hyperv_vector_handler,
+ "Hyper-V VMbus", vmbus_evt);
+ if (result) {
+ pr_err("Can't request Hyper-V VMBus IRQ %d. Error %d",
+ vmbus_irq, result);
+ free_percpu(vmbus_evt);
+ acpi_unregister_gsi(vmbus_irq);
+ vmbus_irq = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
+
+/* Must be done just once */
+void hv_remove_vmbus_irq(void)
+{
+ if (vmbus_irq) {
+ free_percpu_irq(vmbus_irq, vmbus_evt);
+ free_percpu(vmbus_evt);
+ acpi_unregister_gsi(vmbus_irq);
+ }
+}
+EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
+
+/* Must be done by each CPU */
+void hv_enable_vmbus_irq(void)
+{
+ enable_percpu_irq(vmbus_irq, 0);
+}
+EXPORT_SYMBOL_GPL(hv_enable_vmbus_irq);
+
+/* Must be done by each CPU */
+void hv_disable_vmbus_irq(void)
+{
+ disable_percpu_irq(vmbus_irq);
+}
+EXPORT_SYMBOL_GPL(hv_disable_vmbus_irq);
+
+/* Routines to do per-architecture handling of STIMER0 when in Direct Mode */
+
+static irqreturn_t hv_stimer0_vector_handler(int irq, void *dev_id)
+{
+ if (hv_stimer0_handler)
+ hv_stimer0_handler();
+ return IRQ_HANDLED;
+}
+
+int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
+{
+ int localirq;
+ int result;
+
+ localirq = acpi_register_gsi(NULL, HV_STIMER0_IRQNR,
+ ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH);
+ if (localirq <= 0) {
+ pr_err("Can't register Hyper-V stimer0 GSI. Error %d",
+ localirq);
+ *irq = 0;
+ return -1;
+ }
+ stimer0_evt = alloc_percpu(long);
+ result = request_percpu_irq(localirq, hv_stimer0_vector_handler,
+ "Hyper-V stimer0", stimer0_evt);
+ if (result) {
+ pr_err("Can't request Hyper-V stimer0 IRQ %d. Error %d",
+ localirq, result);
+ free_percpu(stimer0_evt);
+ acpi_unregister_gsi(localirq);
+ *irq = 0;
+ return -1;
+ }
+
+ hv_stimer0_handler = handler;
+ *vector = HV_STIMER0_IRQNR;
+ *irq = localirq;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq);
+
+void hv_remove_stimer0_irq(int irq)
+{
+ hv_stimer0_handler = NULL;
+ if (irq) {
+ free_percpu_irq(irq, stimer0_evt);
+ free_percpu(stimer0_evt);
+ acpi_unregister_gsi(irq);
+ }
+}
+EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 08/10] Drivers: hv: vmbus: Add hooks for per-CPU IRQ
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add hooks to enable/disable a per-CPU IRQ for VMbus. These hooks
are in the architecture independent setup and shutdown paths for
Hyper-V, and are needed by Linux guests on Hyper-V on ARM64. The
x86/x64 implementation is null because VMbus interrupts on x86/x64
don't use an IRQ.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/x86/include/asm/mshyperv.h | 4 ++++
drivers/hv/hv.c | 3 +++
2 files changed, 7 insertions(+)
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 1c42ecb..0e5db78 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -59,6 +59,10 @@ typedef int (*hyperv_fill_flush_list_func)(
#endif
void hyperv_vector_handler(struct pt_regs *regs);
+/* On x86/x64, there isn't a real IRQ to be enabled/disable */
+static inline void hv_enable_vmbus_irq(void) {}
+static inline void hv_disable_vmbus_irq(void) {}
+
/*
* Routines for stimer0 Direct Mode handling.
* On x86/x64, there are no percpu actions to take.
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 6098e0c..035d3df 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -180,6 +180,7 @@ void hv_synic_enable_regs(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
/* Setup the shared SINT. */
+ hv_enable_vmbus_irq();
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
@@ -241,6 +242,8 @@ void hv_synic_disable_regs(unsigned int cpu)
hv_get_synic_state(sctrl.as_uint64);
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
+
+ hv_disable_vmbus_irq();
}
int hv_synic_cleanup(unsigned int cpu)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 06/10] arm64: hyperv: Add kexec and panic handlers
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add functions to set up and remove kexec and panic
handlers, and to inform Hyper-V about a guest panic.
These functions are called from architecture independent
code in the VMbus driver.
This code is built only when CONFIG_HYPERV is enabled.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/arm64/hyperv/hv_core.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
arch/arm64/hyperv/mshyperv.c | 26 +++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 4aa6b8f..8d6de9f 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -199,3 +199,64 @@ void hv_get_vpreg_128(u32 msr, struct hv_get_vp_register_output *res)
kfree(output);
}
EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
+
+void hyperv_report_panic(struct pt_regs *regs, long err)
+{
+ static bool panic_reported;
+ u64 guest_id;
+
+ /*
+ * We prefer to report panic on 'die' chain as we have proper
+ * registers to report, but if we miss it (e.g. on BUG()) we need
+ * to report it on 'panic'.
+ */
+ if (panic_reported)
+ return;
+ panic_reported = true;
+
+ guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID);
+
+ /*
+ * Hyper-V provides the ability to store only 5 values.
+ * Pick the passed in error value, the guest_id, and the PC.
+ * The first two general registers are added arbitrarily.
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_P0, err);
+ hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id);
+ hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc);
+ hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->regs[0]);
+ hv_set_vpreg(HV_REGISTER_CRASH_P4, regs->regs[1]);
+
+ /*
+ * Let Hyper-V know there is crash data available
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic);
+
+/*
+ * hyperv_report_panic_msg - report panic message to Hyper-V
+ * @pa: physical address of the panic page containing the message
+ * @size: size of the message in the page
+ */
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
+{
+ /*
+ * P3 to contain the physical address of the panic page & P4 to
+ * contain the size of the panic data in that page. Rest of the
+ * registers are no-op when the NOTIFY_MSG flag is set.
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_P0, 0);
+ hv_set_vpreg(HV_REGISTER_CRASH_P1, 0);
+ hv_set_vpreg(HV_REGISTER_CRASH_P2, 0);
+ hv_set_vpreg(HV_REGISTER_CRASH_P3, pa);
+ hv_set_vpreg(HV_REGISTER_CRASH_P4, size);
+
+ /*
+ * Let Hyper-V know there is crash data available along with
+ * the panic message.
+ */
+ hv_set_vpreg(HV_REGISTER_CRASH_CTL,
+ (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index ae6ece6..c58940d 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -23,6 +23,8 @@
static void (*vmbus_handler)(void);
static void (*hv_stimer0_handler)(void);
+static void (*hv_kexec_handler)(void);
+static void (*hv_crash_handler)(struct pt_regs *regs);
static int vmbus_irq;
static long __percpu *vmbus_evt;
@@ -137,3 +139,27 @@ void hv_remove_stimer0_irq(int irq)
}
}
EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
+
+void hv_setup_kexec_handler(void (*handler)(void))
+{
+ hv_kexec_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
+
+void hv_remove_kexec_handler(void)
+{
+ hv_kexec_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
+
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
+{
+ hv_crash_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
+
+void hv_remove_crash_handler(void)
+{
+ hv_crash_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 07/10] arm64: hyperv: Initialize hypervisor on boot
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add ARM64-specific code to initialize the Hyper-V
hypervisor when booting as a guest VM. Provide functions
and data structures indicating hypervisor status that
are needed by VMbus driver.
This code is built only when CONFIG_HYPERV is enabled.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/arm64/hyperv/hv_core.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 8d6de9f..b496f59 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -13,14 +13,47 @@
#include <linux/types.h>
#include <linux/version.h>
#include <linux/export.h>
+#include <linux/vmalloc.h>
#include <linux/mm.h>
+#include <linux/acpi.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/hyperv.h>
#include <linux/arm-smccc.h>
#include <linux/string.h>
+#include <linux/cpuhotplug.h>
+#include <linux/psci.h>
+#include <linux/sched_clock.h>
#include <asm-generic/bug.h>
#include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h>
+#include <asm/sysreg.h>
+#include <clocksource/hyperv_timer.h>
+
+static bool hyperv_initialized;
+
+struct ms_hyperv_info ms_hyperv __ro_after_init;
+EXPORT_SYMBOL_GPL(ms_hyperv);
+
+u32 *hv_vp_index;
+EXPORT_SYMBOL_GPL(hv_vp_index);
+
+u32 hv_max_vp_index;
+EXPORT_SYMBOL_GPL(hv_max_vp_index);
+
+static int hv_cpu_init(unsigned int cpu)
+{
+ u64 msr_vp_index;
+
+ hv_get_vp_index(msr_vp_index);
+
+ hv_vp_index[smp_processor_id()] = msr_vp_index;
+
+ if (msr_vp_index > hv_max_vp_index)
+ hv_max_vp_index = msr_vp_index;
+
+ return 0;
+}
/*
@@ -57,6 +90,117 @@ void hv_free_hyperv_page(unsigned long addr)
/*
+ * This function is invoked via the ACPI clocksource probe mechanism. We
+ * don't actually use any values from the ACPI GTDT table, but we set up
+ * the Hyper-V synthetic clocksource and do other initialization for
+ * interacting with Hyper-V the first time. Using early_initcall to invoke
+ * this function is too late because interrupts are already enabled at that
+ * point, and hv_init_clocksource() must run before interrupts are enabled.
+ *
+ * 1. Setup the guest ID.
+ * 2. Get features and hints info from Hyper-V
+ * 3. Setup per-cpu VP indices.
+ * 4. Initialize the Hyper-V clocksource.
+ */
+
+static int __init hyperv_init(struct acpi_table_header *table)
+{
+ struct hv_get_vp_register_output result;
+ u32 a, b, c, d;
+ u64 guest_id;
+ int i, cpuhp;
+
+ /*
+ * If we're in a VM on Hyper-V, the ACPI hypervisor_id field will
+ * have the string "MsHyperV".
+ */
+ if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
+ return -EINVAL;
+
+ /* Setup the guest ID */
+ guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
+ hv_set_vpreg(HV_REGISTER_GUEST_OSID, guest_id);
+
+ /* Get the features and hints from Hyper-V */
+ hv_get_vpreg_128(HV_REGISTER_PRIVILEGES_AND_FEATURES, &result);
+ ms_hyperv.features = lower_32_bits(result.registervaluelow);
+ ms_hyperv.misc_features = lower_32_bits(result.registervaluehigh);
+
+ hv_get_vpreg_128(HV_REGISTER_FEATURES, &result);
+ ms_hyperv.hints = lower_32_bits(result.registervaluelow);
+
+ pr_info("Hyper-V: Features 0x%x, misc features 0x%x, hints 0x%x\n",
+ ms_hyperv.features, ms_hyperv.misc_features, ms_hyperv.hints);
+
+ /*
+ * Hyper-V on ARM64 doesn't support AutoEOI. Add the hint
+ * that tells architecture independent code not to use this
+ * feature.
+ */
+ ms_hyperv.hints |= HV_DEPRECATING_AEOI_RECOMMENDED;
+
+ /* Get information about the Hyper-V host version */
+ hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result);
+ a = lower_32_bits(result.registervaluelow);
+ b = upper_32_bits(result.registervaluelow);
+ c = lower_32_bits(result.registervaluehigh);
+ d = upper_32_bits(result.registervaluehigh);
+ pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n",
+ b >> 16, b & 0xFFFF, a, d & 0xFFFFFF, c, d >> 24);
+
+ /* Allocate and initialize percpu VP index array */
+ hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
+ GFP_KERNEL);
+ if (!hv_vp_index)
+ return -ENOMEM;
+
+ for (i = 0; i < num_possible_cpus(); i++)
+ hv_vp_index[i] = VP_INVAL;
+
+ cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "arm64/hyperv_init:online", hv_cpu_init, NULL);
+ if (cpuhp < 0)
+ goto free_vp_index;
+
+ hv_init_clocksource();
+ if (hv_stimer_alloc())
+ goto remove_cpuhp_state;
+
+ hyperv_initialized = true;
+ return 0;
+
+remove_cpuhp_state:
+ cpuhp_remove_state(cpuhp);
+free_vp_index:
+ kfree(hv_vp_index);
+ hv_vp_index = NULL;
+ return -EINVAL;
+}
+TIMER_ACPI_DECLARE(hyperv, ACPI_SIG_GTDT, hyperv_init);
+
+
+/*
+ * Called from hv_init_clocksource() to do ARM64
+ * specific initialization of the sched clock
+ */
+void __init hv_setup_sched_clock(void *sched_clock)
+{
+ sched_clock_register(sched_clock, 64, HV_CLOCK_HZ);
+}
+
+/*
+ * This routine is called before kexec/kdump, it does the required cleanup.
+ */
+void hyperv_cleanup(void)
+{
+ /* Reset our OS id */
+ hv_set_vpreg(HV_REGISTER_GUEST_OSID, 0);
+
+}
+EXPORT_SYMBOL_GPL(hyperv_cleanup);
+
+
+/*
* hv_do_hypercall- Invoke the specified hypercall
*/
u64 hv_do_hypercall(u64 control, void *input, void *output)
@@ -260,3 +404,15 @@ void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
(HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
}
EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
+
+bool hv_is_hyperv_initialized(void)
+{
+ return hyperv_initialized;
+}
+EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
+
+bool hv_is_hibernation_supported(void)
+{
+ return false;
+}
+EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 10/10] Drivers: hv: Enable Hyper-V code to be built on ARM64
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on
ARM64, causing the Hyper-V specific code to be built.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
drivers/hv/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 79e5356..1113e49 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
config HYPERV
tristate "Microsoft Hyper-V client drivers"
- depends on X86 && ACPI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+ depends on ACPI && \
+ ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
select PARAVIRT
select X86_HV_CALLBACK_VECTOR
help
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 04/10] arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-1-git-send-email-mikelley@microsoft.com>
Add ARM64-specific code to allocate memory with HV_HYP_PAGE_SIZE
size and alignment. These are for use when pages need to be shared
with Hyper-V. Separate functions are needed as the page size used
by Hyper-V may not be the same as the guest page size.
This code is built only when CONFIG_HYPERV is enabled.
Signed-off-by: Michael Kelley <mikelley@microsoft.com>
---
arch/arm64/hyperv/hv_core.c | 34 ++++++++++++++++++++++++++++++++++
include/asm-generic/mshyperv.h | 5 +++++
2 files changed, 39 insertions(+)
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 272c348..4aa6b8f 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -17,12 +17,46 @@
#include <linux/slab.h>
#include <linux/hyperv.h>
#include <linux/arm-smccc.h>
+#include <linux/string.h>
#include <asm-generic/bug.h>
#include <asm/hyperv-tlfs.h>
#include <asm/mshyperv.h>
/*
+ * Functions for allocating and freeing memory with size and
+ * alignment HV_HYP_PAGE_SIZE. These functions are needed because
+ * the guest page size may not be the same as the Hyper-V page
+ * size. We depend upon kmalloc() aligning power-of-two size
+ * allocations to the allocation size boundary, so that the
+ * allocated memory appears to Hyper-V as a page of the size
+ * it expects.
+ *
+ * These functions are used by arm64 specific code as well as
+ * arch independent Hyper-V drivers.
+ */
+
+void *hv_alloc_hyperv_page(void)
+{
+ BUILD_BUG_ON(PAGE_SIZE < HV_HYP_PAGE_SIZE);
+ return kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(hv_alloc_hyperv_page);
+
+void *hv_alloc_hyperv_zeroed_page(void)
+{
+ return kzalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page);
+
+void hv_free_hyperv_page(unsigned long addr)
+{
+ kfree((void *)addr);
+}
+EXPORT_SYMBOL_GPL(hv_free_hyperv_page);
+
+
+/*
* hv_do_hypercall- Invoke the specified hypercall
*/
u64 hv_do_hypercall(u64 control, void *input, void *output)
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index b3f1082..1a7c4c5 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -99,6 +99,11 @@ static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void);
+void *hv_alloc_hyperv_page(void);
+void *hv_alloc_hyperv_zeroed_page(void);
+void hv_free_hyperv_page(unsigned long addr);
+
+
#if IS_ENABLED(CONFIG_HYPERV)
/*
* Hypervisor's notion of virtual processor ID is different from
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 00/10] Subject: Enable Linux guests on Hyper-V on ARM64
From: Michael Kelley @ 2020-03-14 15:35 UTC (permalink / raw)
To: will, ardb, arnd, catalin.marinas, mark.rutland, maz,
linux-arm-kernel, gregkh, linux-kernel, linux-hyperv, linux-efi,
linux-arch, olaf, apw, vkuznets, jasowang, marcelo.cerri, kys
Cc: mikelley, sunilmut, boqun.feng
This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its interrupts and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.
The ten patches are organized as follows:
1) Add include files that define the Hyper-V interface as
described in the Hyper-V Top Level Functional Spec (TLFS), plus
additional definitions specific to Linux running on Hyper-V.
2) Add #define for vendor specific owner definition to linux/arm-smccc.h
3) thru 7) Add core Hyper-V support on ARM64, including hypercalls,
interrupt handlers, kexec & panic handlers, and core hypervisor
initialization.
8) Update the existing VMbus driver to generalize interrupt
management across x86/x64 and ARM64.
9) Export screen_info so it may be used by the Hyper-V frame buffer
driver built as a module. It's already exported for x86,
powerpc, and alpha architectures.
10) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.
Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress:
* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, but
allows guests with 16K/64K page size. However, the Linux drivers
for Hyper-V synthetic devices assume the guest page size is 4K.
This patch set lays the groundwork for larger guest page sizes,
but additional patches are coming to update these drivers.
* The Hyper-V vPCI driver at drivers/pci/host/pci-hyperv.c has
x86/x64-specific code and is not being built for ARM64. Fixing
this driver to enable vPCI devices on ARM64 will be done later.
In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC"). Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology. This will be
fixed when Hyper-V updates the usage in the TLFS.
This patch set is based on a 5.6-rc5 linux-next tree.
Changes in v6:
* Use SMCCC hypercall interface instead of direct invocation
of HVC instruction and the Hyper-V hypercall interface
[Marc Zyngier]
* Reimplemented functions to alloc/free Hyper-V size pages
using kmalloc/kfree since kmalloc now guarantees alignment of
power of 2 size allocations [Marc Zyngier]
* Export screen_info in arm64 architecture so it can be used
by the Hyper-V buffer driver built as a module
* Renamed source file arch/arm64/hyperv/hv_init.c to hv_core.c
to better reflect its content
* Fixed the bit position of certain feature flags presented by
Hyper-V to the guest. The bit positions on ARM64 don't match
the position on x86 like originally thought.
* Minor fixups to rebase to 5.6-rc5 linux-next
Changes in v5:
* Minor fixups to rebase to 5.4-rc1 linux-next
Changes in v4:
* Moved clock-related code into an architecture independent
Hyper-V clocksource driver that is already upstream. Clock
related code is removed from this patch set except for the
ARM64 specific interrupt handler. [Marc Zyngier]
* Separately upstreamed the split of mshyperv.h into arch independent
and arch dependent portions. The arch independent portion has been
removed from this patch set.
* Divided patch #2 of the series into multiple smaller patches
[Marc Zyngier]
* Changed a dozen or so smaller things based on feedback
[Marc Zyngier, Will Deacon]
* Added functions to alloc/free Hyper-V size pages for use by
drivers for Hyper-V synthetic devices when updated to not assume
guest page size and Hyper-v page size are the same
Changes in v3:
* Added initialization of hv_vp_index array like was recently
added on x86 branch [KY Srinivasan]
* Changed Hyper-V ARM64 register symbols to be all uppercase
instead of mixed case [KY Srinivasan]
* Separated mshyperv.h into two files, one architecture
independent and one architecture dependent. After this code
is upstream, will make changes to the x86 code to use the
architecture independent file and remove duplication. And
once we have a multi-architecture Hyper-V TLFS, will do a
separate patch to split hyperv-tlfs.h in the same way.
[KY Srinivasan]
* Minor tweaks to rebase to latest linux-next code
Changes in v2:
* Removed patch to implement slow_virt_to_phys() on ARM64.
Use of slow_virt_to_phys() in arch independent Hyper-V
drivers has been eliminated by commit 6ba34171bcbd
("Drivers: hv: vmbus: Remove use of slow_virt_to_phys()")
* Minor tweaks to rebase to latest linux-next code
Michael Kelley (10):
arm64: hyperv: Add core Hyper-V include files
arm/arm64: smccc-1.1: Add vendor specific owner definition
arm64: hyperv: Add hypercall and register access functions
arm64: hyperv: Add memory alloc/free functions for Hyper-V size pages
arm64: hyperv: Add interrupt handlers for VMbus and stimer
arm64: hyperv: Add kexec and panic handlers
arm64: hyperv: Initialize hypervisor on boot
Drivers: hv: vmbus: Add hooks for per-CPU IRQ
arm64: efi: Export screen_info
Drivers: hv: Enable Hyper-V code to be built on ARM64
MAINTAINERS | 3 +
arch/arm64/Kbuild | 1 +
arch/arm64/hyperv/Makefile | 2 +
arch/arm64/hyperv/hv_core.c | 418 +++++++++++++++++++++++++++++++++++
arch/arm64/hyperv/mshyperv.c | 165 ++++++++++++++
arch/arm64/include/asm/hyperv-tlfs.h | 413 ++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/mshyperv.h | 115 ++++++++++
arch/arm64/kernel/efi.c | 1 +
arch/x86/include/asm/mshyperv.h | 4 +
drivers/hv/Kconfig | 3 +-
drivers/hv/hv.c | 3 +
include/asm-generic/mshyperv.h | 5 +
include/linux/arm-smccc.h | 1 +
13 files changed, 1133 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/hyperv/Makefile
create mode 100644 arch/arm64/hyperv/hv_core.c
create mode 100644 arch/arm64/hyperv/mshyperv.c
create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
create mode 100644 arch/arm64/include/asm/mshyperv.h
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH v8 0/5] Add a unified parameter "nopvspin"
From: Paolo Bonzini @ 2020-03-14 11:14 UTC (permalink / raw)
To: Zhenzhong Duan, linux-kernel, tglx, x86, peterz
Cc: mingo, bp, rkrcmar, sean.j.christopherson, vkuznets, wanpengli,
jmattson, joro, boris.ostrovsky, jgross, will, linux-hyperv, kvm,
mikelley, kys, haiyangz, sthemmin, sashal
In-Reply-To: <1571829384-5309-1-git-send-email-zhenzhong.duan@oracle.com>
Peter/Thomas, can you apply this to tip or give your Acked-by?
Thanks,
Paolo
On 23/10/19 13:16, Zhenzhong Duan wrote:
> There are cases folks want to disable spinlock optimization for
> debug/test purpose. Xen and hyperv already have parameters "xen_nopvspin"
> and "hv_nopvspin" to support that, but kvm doesn't.
>
> The first patch adds that feature to KVM guest with "nopvspin".
>
> For compatibility reason original parameters "xen_nopvspin" and
> "hv_nopvspin" are retained and marked obsolete.
>
> v8:
> PATCH2: use 'kvm-guest' instead of 'kvm_guest' [Sean Christopherson]
> PATCH3: add a comment to explain missed 'return' [Sean Christopherson]
>
> v7:
> PATCH3: update comment and use goto, add RB [Vitaly Kuznetsov]
>
> v6:
> PATCH1: add Reviewed-by [Vitaly Kuznetsov]
> PATCH2: change 'pv' to 'PV', add Reviewed-by [Vitaly Kuznetsov]
> PATCH3: refactor 'if' branch in kvm_spinlock_init() [Vitaly Kuznetsov]
>
> v5:
> PATCH1: new patch to revert a currently unnecessory commit,
> code is simpler a bit after that change. [Boris Ostrovsky]
> PATCH3: fold 'if' statement,add comments on virt_spin_lock_key,
> reorder with PATCH2 to better reflect dependency
> PATCH4: fold 'if' statement, add Reviewed-by [Boris Ostrovsky]
> PATCH5: add Reviewed-by [Michael Kelley]
>
> v4:
> PATCH1: use variable name nopvspin instead of pvspin and
> defined it as __initdata, changed print message,
> updated patch description [Sean Christopherson]
> PATCH2: remove Suggested-by, use "kvm-guest:" prefix [Sean Christopherson]
> PATCH3: make variable nopvsin and xen_pvspin coexist
> remove Reviewed-by due to code change [Sean Christopherson]
> PATCH4: make variable nopvsin and hv_pvspin coexist [Sean Christopherson]
>
> v3:
> PATCH2: Fix indentation
>
> v2:
> PATCH1: pick the print code change into separate PATCH2,
> updated patch description [Vitaly Kuznetsov]
> PATCH2: new patch with print code change [Vitaly Kuznetsov]
> PATCH3: add Reviewed-by [Juergen Gross]
>
> Zhenzhong Duan (5):
> Revert "KVM: X86: Fix setup the virt_spin_lock_key before static key
> get initialized"
> x86/kvm: Change print code to use pr_*() format
> x86/kvm: Add "nopvspin" parameter to disable PV spinlocks
> xen: Mark "xen_nopvspin" parameter obsolete
> x86/hyperv: Mark "hv_nopvspin" parameter obsolete
>
> Documentation/admin-guide/kernel-parameters.txt | 14 ++++-
> arch/x86/hyperv/hv_spinlock.c | 4 ++
> arch/x86/include/asm/qspinlock.h | 1 +
> arch/x86/kernel/kvm.c | 79 ++++++++++++++++---------
> arch/x86/xen/spinlock.c | 4 +-
> kernel/locking/qspinlock.c | 7 +++
> 6 files changed, 76 insertions(+), 33 deletions(-)
>
^ permalink raw reply
* Re: [PATCH v5 2/5] x86/hyper-v: Add synthetic debugger definitions
From: Jon Doron @ 2020-03-14 4:44 UTC (permalink / raw)
To: Michael Kelley
Cc: kvm@vger.kernel.org, linux-hyperv@vger.kernel.org, vkuznets
In-Reply-To: <MW2PR2101MB10521050158699C7C96613F5D7FA0@MW2PR2101MB1052.namprd21.prod.outlook.com>
On 13/03/2020, Michael Kelley wrote:
>From: Jon Doron <arilou@gmail.com> Sent: Friday, March 13, 2020 6:21 AM
>>
>> Hyper-V synthetic debugger has two modes, one that uses MSRs and
>> the other that use Hypercalls.
>>
>> Add all the required definitions to both types of synthetic debugger
>> interface.
>>
>> Some of the required new CPUIDs and MSRs are not documented in the TLFS
>> so they are in hyperv.h instead.
>>
>> Signed-off-by: Jon Doron <arilou@gmail.com>
>> ---
>> arch/x86/include/asm/hyperv-tlfs.h | 6 ++++++
>> arch/x86/kvm/hyperv.h | 22 ++++++++++++++++++++++
>> 2 files changed, 28 insertions(+)
>>
>> diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
>> index 92abc1e42bfc..671ce2a39d4b 100644
>> --- a/arch/x86/include/asm/hyperv-tlfs.h
>> +++ b/arch/x86/include/asm/hyperv-tlfs.h
>> @@ -131,6 +131,8 @@
>> #define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE BIT(8)
>> /* Crash MSR available */
>> #define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(10)
>> +/* Support for debug MSRs available */
>> +#define HV_FEATURE_DEBUG_MSRS_AVAILABLE BIT(11)
>> /* stimer Direct Mode is available */
>> #define HV_STIMER_DIRECT_MODE_AVAILABLE BIT(19)
>>
>> @@ -376,6 +378,9 @@ struct hv_tsc_emulation_status {
>> #define HVCALL_SEND_IPI_EX 0x0015
>> #define HVCALL_POST_MESSAGE 0x005c
>> #define HVCALL_SIGNAL_EVENT 0x005d
>> +#define HVCALL_POST_DEBUG_DATA 0x0069
>> +#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
>> +#define HVCALL_RESET_DEBUG_SESSION 0x006b
>> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
>> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
>>
>> @@ -419,6 +424,7 @@ enum HV_GENERIC_SET_FORMAT {
>> #define HV_STATUS_INVALID_HYPERCALL_INPUT 3
>> #define HV_STATUS_INVALID_ALIGNMENT 4
>> #define HV_STATUS_INVALID_PARAMETER 5
>> +#define HV_STATUS_OPERATION_DENIED 8
>> #define HV_STATUS_INSUFFICIENT_MEMORY 11
>> #define HV_STATUS_INVALID_PORT_ID 17
>> #define HV_STATUS_INVALID_CONNECTION_ID 18
>> diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
>> index 757cb578101c..56bc3416b62f 100644
>> --- a/arch/x86/kvm/hyperv.h
>> +++ b/arch/x86/kvm/hyperv.h
>> @@ -23,6 +23,28 @@
>>
>> #include <linux/kvm_host.h>
>>
>> +/* These defines are required by KDNet and they are not part of Hyper-V TLFS */
>
>I'm looking for a bit more info in the comment so that it's clear that the
>synthetic debugger functionality is not committed to be available going
>forward. Perhaps something along the lines of:
>
>/* The #defines related to the synthetic debugger are required by KDNet, but
> * they are not documented in the Hyper-V TLFS because the synthetic debugger
> * functionality has been deprecated and is subject to removal in future versions
> * of Windows.
> */
>
>But with that additional comment text,
>
>Reviewed-by: Michael Kelley <mikelley@microsoft.com>
>
Sure thing, but one quick question I have noticed that in the 6.0 TLFS
the bit indicating the DEBUG_MSRS are available is still documented is
that intentional or a juss a miss?
Cheers,
-- Jon.
>> +#define HYPERV_CPUID_SYNDBG_VENDOR_AND_MAX_FUNCTIONS 0x40000080
>> +#define HYPERV_CPUID_SYNDBG_INTERFACE 0x40000081
>> +#define HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES 0x40000082
>> +
>> +/*
>> + * Hyper-V synthetic debugger platform capabilities
>> + * These are HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX bits.
>> + */
>> +#define HV_X64_SYNDBG_CAP_ALLOW_KERNEL_DEBUGGING BIT(1)
>> +
>> +/* Hyper-V Synthetic debug options MSR */
>> +#define HV_X64_MSR_SYNDBG_CONTROL 0x400000F1
>> +#define HV_X64_MSR_SYNDBG_STATUS 0x400000F2
>> +#define HV_X64_MSR_SYNDBG_SEND_BUFFER 0x400000F3
>> +#define HV_X64_MSR_SYNDBG_RECV_BUFFER 0x400000F4
>> +#define HV_X64_MSR_SYNDBG_PENDING_BUFFER 0x400000F5
>> +#define HV_X64_MSR_SYNDBG_OPTIONS 0x400000FF
>> +
>> +/* Hyper-V HV_X64_MSR_SYNDBG_OPTIONS bits */
>> +#define HV_X64_SYNDBG_OPTION_USE_HCALLS BIT(2)
>> +
>> static inline struct kvm_vcpu_hv *vcpu_to_hv_vcpu(struct kvm_vcpu *vcpu)
>> {
>> return &vcpu->arch.hyperv;
>> --
>> 2.24.1
>
^ permalink raw reply
* Re: [PATCH v6 01/10] arm64: hyperv: Add core Hyper-V include files
From: Marc Zyngier @ 2020-03-15 17:31 UTC (permalink / raw)
To: Michael Kelley
Cc: will, ardb, arnd, catalin.marinas, mark.rutland, linux-arm-kernel,
gregkh, linux-kernel, linux-hyperv, linux-efi, linux-arch, olaf,
apw, vkuznets, jasowang, marcelo.cerri, kys, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-2-git-send-email-mikelley@microsoft.com>
On Sat, 14 Mar 2020 15:35:10 +0000,
Hi Michael,
Michael Kelley <mikelley@microsoft.com> wrote:
>
> hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level
> Functional Spec (TLFS). The TLFS is distinctly oriented to x86/x64,
> and Hyper-V has not separated out the architecture-dependent parts into
> x86/x64 vs. ARM64. So hyperv-tlfs.h includes information for ARM64
> that is not yet formally published. The TLFS is available here:
>
> docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
>
> mshyperv.h defines Linux-specific structures and routines for
> interacting with Hyper-V on ARM64, and #includes the architecture-
> independent part of mshyperv.h in include/asm-generic.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> ---
> MAINTAINERS | 2 +
> arch/arm64/include/asm/hyperv-tlfs.h | 413 +++++++++++++++++++++++++++++++++++
> arch/arm64/include/asm/mshyperv.h | 115 ++++++++++
> 3 files changed, 530 insertions(+)
> create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
> create mode 100644 arch/arm64/include/asm/mshyperv.h
So this is a pretty large patch, mostly containing constants and other
data structures that don't necessarily make sense immediately (or at
least, I can't make sense of it without reading all the other 9
patches and going back to patch #1).
Could you please consider splitting this into more discreet bits that
get added as required by the supporting code?
So here's only a few sparse comments:
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 58bb5c4..398cfdb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7809,6 +7809,8 @@ F: arch/x86/include/asm/trace/hyperv.h
> F: arch/x86/include/asm/hyperv-tlfs.h
> F: arch/x86/kernel/cpu/mshyperv.c
> F: arch/x86/hyperv
> +F: arch/arm64/include/asm/hyperv-tlfs.h
> +F: arch/arm64/include/asm/mshyperv.h
> F: drivers/clocksource/hyperv_timer.c
> F: drivers/hid/hid-hyperv.c
> F: drivers/hv/
> diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h
> new file mode 100644
> index 0000000..5e6a087
> --- /dev/null
> +++ b/arch/arm64/include/asm/hyperv-tlfs.h
> @@ -0,0 +1,413 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/*
> + * This file contains definitions from the Hyper-V Hypervisor Top-Level
> + * Functional Specification (TLFS):
> + * https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
> + *
> + * Copyright (C) 2019, Microsoft, Inc.
> + *
> + * Author : Michael Kelley <mikelley@microsoft.com>
> + */
> +
> +#ifndef _ASM_HYPERV_TLFS_H
> +#define _ASM_HYPERV_TLFS_H
> +
> +#include <linux/types.h>
> +
> +/*
> + * All data structures defined in the TLFS that are shared between Hyper-V
> + * and a guest VM use Little Endian byte ordering. This matches the default
> + * byte ordering of Linux running on ARM64, so no special handling is required.
> + */
> +
> +
> +/*
> + * While not explicitly listed in the TLFS, Hyper-V always runs with a page
> + * size of 4096. These definitions are used when communicating with Hyper-V
> + * using guest physical pages and guest physical page addresses, since the
> + * guest page size may not be 4096 on ARM64.
> + */
> +#define HV_HYP_PAGE_SHIFT 12
> +#define HV_HYP_PAGE_SIZE (1 << HV_HYP_PAGE_SHIFT)
Probably worth writing this as 1UL to be on the safe side.
> +#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1))
> +
> +/*
> + * These Hyper-V registers provide information equivalent to the CPUID
> + * instruction on x86/x64.
> + */
> +#define HV_REGISTER_HYPERVISOR_VERSION 0x00000100 /*CPUID 0x40000002 */
> +#define HV_REGISTER_PRIVILEGES_AND_FEATURES 0x00000200 /*CPUID 0x40000003 */
> +#define HV_REGISTER_FEATURES 0x00000201 /*CPUID 0x40000004 */
> +#define HV_REGISTER_IMPLEMENTATION_LIMITS 0x00000202 /*CPUID 0x40000005 */
> +#define HV_ARM64_REGISTER_INTERFACE_VERSION 0x00090006 /*CPUID 0x40000001 */
> +
> +/*
> + * Feature identification. HvRegisterPrivilegesAndFeaturesInfo returns a
> + * 128-bit value with flags indicating which features are available to the
> + * partition based upon the current partition privileges. The 128-bit
> + * value is broken up with different portions stored in different 32-bit
> + * fields in the ms_hyperv structure.
> + */
> +
> +/* Partition Reference Counter available*/
> +#define HV_MSR_TIME_REF_COUNT_AVAILABLE BIT(1)
> +
> +/* Synthetic Timers available */
> +#define HV_MSR_SYNTIMER_AVAILABLE BIT(3)
> +
> +/* Reference TSC available */
> +#define HV_MSR_REFERENCE_TSC_AVAILABLE BIT(9)
> +
> +
> +/*
> + * This group of flags is in the high order 64-bits of the returned
> + * 128-bit value. Note that this set of bit positions differs from what
> + * is used on x86/x64 architecture.
> + */
> +
> +/* Crash MSRs available */
> +#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(8)
It is confusing that you don't have a single bit space for all these
flags. It'd probably help if you had a structure describing this
128bit value in multiple 32bit or 64bit words, and indicating which
field the bit position is relevant to.
[...]
> +/* Define the hypercall status result */
> +
> +union hv_hypercall_status {
> + u64 as_uint64;
nit: it'd be more consistent if as_uint64 was actually a uint64 type.
> + struct {
> + u16 status;
> + u16 reserved;
> + u16 reps_completed; /* Low 12 bits */
> + u16 reserved2;
> + };
> +};
> +
> +/* hypercall status code */
> +#define HV_STATUS_SUCCESS 0
> +#define HV_STATUS_INVALID_HYPERCALL_CODE 2
> +#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
> +#define HV_STATUS_INVALID_ALIGNMENT 4
> +#define HV_STATUS_INSUFFICIENT_MEMORY 11
> +#define HV_STATUS_INVALID_CONNECTION_ID 18
> +#define HV_STATUS_INSUFFICIENT_BUFFERS 19
> +
> +/* Define input and output layout for Get VP Register hypercall */
> +struct hv_get_vp_register_input {
> + u64 partitionid;
> + u32 vpindex;
> + u8 inputvtl;
> + u8 padding[3];
> + u32 name0;
> + u32 name1;
> +} __packed;
> +
> +struct hv_get_vp_register_output {
> + u64 registervaluelow;
> + u64 registervaluehigh;
> +} __packed;
> +
> +#define HV_FLUSH_ALL_PROCESSORS BIT(0)
> +#define HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES BIT(1)
> +#define HV_FLUSH_NON_GLOBAL_MAPPINGS_ONLY BIT(2)
I"m curious: Are these supposed to be PV'd TLB invalidation
operations?
> +#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
> +
> +enum HV_GENERIC_SET_FORMAT {
> + HV_GENERIC_SET_SPARSE_4K,
> + HV_GENERIC_SET_ALL,
> +};
> +
> +/*
> + * The Hyper-V TimeRefCount register and the TSC
> + * page provide a guest VM clock with 100ns tick rate
> + */
> +#define HV_CLOCK_HZ (NSEC_PER_SEC/100)
> +
> +/*
> + * The fields in this structure are set by Hyper-V and read
> + * by the Linux guest. They should be accessed with READ_ONCE()
> + * so the compiler doesn't optimize in a way that will cause
> + * problems. The union pads the size out to the page size
> + * used to communicate with Hyper-V.
> + */
> +struct ms_hyperv_tsc_page {
> + union {
> + struct {
> + u32 tsc_sequence;
> + u32 reserved1;
> + u64 tsc_scale;
> + s64 tsc_offset;
> + } __packed;
> + u8 reserved2[HV_HYP_PAGE_SIZE];
> + };
> +};
> +
> +/* Define the number of synthetic interrupt sources. */
> +#define HV_SYNIC_SINT_COUNT (16)
> +/* Define the expected SynIC version. */
> +#define HV_SYNIC_VERSION_1 (0x1)
> +
> +#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
> +#define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
> +#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
> +#define HV_SYNIC_SINT_MASKED (1ULL << 16)
> +#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17)
> +#define HV_SYNIC_SINT_VECTOR_MASK (0xFF)
Let's me guess: a PV interrupt controller? Do you really need this?
Specially as I don't see any PV irqchip driver in this submission...
[...]
> diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
> new file mode 100644
> index 0000000..60b3f68
> --- /dev/null
> +++ b/arch/arm64/include/asm/mshyperv.h
> @@ -0,0 +1,115 @@
> +/* 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 <linux/arm-smccc.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.
I'm not convinced it is OK. If you don't try to do the right thing
now, what is the incentive to do it later? Starting to hard code
things is akin to going back to the ARM board files of old. Been
there, managed to fix it, not going back to it again anytime soon.
> + * 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_enable_vdso_clocksource()
> +#define hv_set_clocksource_vdso(val) \
> + ((val).vdso_clock_mode = VDSO_CLOCKMODE_NONE)
> +
> +#if IS_ENABLED(CONFIG_HYPERV)
I don't think this guards anything useful.
> +#define hv_enable_stimer0_percpu_irq(irq) enable_percpu_irq(irq, 0)
> +#define hv_disable_stimer0_percpu_irq(irq) disable_percpu_irq(irq)
and this looks pretty premature.
> +#endif
> +
> +/* ARM64 specific code to read the hardware clock */
> +#define hv_get_raw_timer() arch_timer_read_counter()
> +
> +/* SMCCC hypercall parameters */
> +#define HV_SMCCC_FUNC_NUMBER 1
> +#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \
> + ARM_SMCCC_STD_CALL, \
> + ARM_SMCCC_SMC_64, \
> + ARM_SMCCC_OWNER_VENDOR_HYP, \
This is only defined in patch #2...
> + HV_SMCCC_FUNC_NUMBER)
> +
> +#include <asm-generic/mshyperv.h>
> +
> +#endif
Thanks,
M.
--
Jazz is not dead, it just smells funny.
^ permalink raw reply
* Re: [PATCH v6 06/10] arm64: hyperv: Add kexec and panic handlers
From: Marc Zyngier @ 2020-03-15 18:15 UTC (permalink / raw)
To: Michael Kelley
Cc: will, ardb, arnd, catalin.marinas, mark.rutland, linux-arm-kernel,
gregkh, linux-kernel, linux-hyperv, linux-efi, linux-arch, olaf,
apw, vkuznets, jasowang, marcelo.cerri, kys, sunilmut, boqun.feng
In-Reply-To: <1584200119-18594-7-git-send-email-mikelley@microsoft.com>
On Sat, 14 Mar 2020 15:35:15 +0000,
Michael Kelley <mikelley@microsoft.com> wrote:
>
> Add functions to set up and remove kexec and panic
> handlers, and to inform Hyper-V about a guest panic.
> These functions are called from architecture independent
> code in the VMbus driver.
>
> This code is built only when CONFIG_HYPERV is enabled.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
> ---
> arch/arm64/hyperv/hv_core.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
> arch/arm64/hyperv/mshyperv.c | 26 +++++++++++++++++++
> 2 files changed, 87 insertions(+)
>
> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
> index 4aa6b8f..8d6de9f 100644
> --- a/arch/arm64/hyperv/hv_core.c
> +++ b/arch/arm64/hyperv/hv_core.c
> @@ -199,3 +199,64 @@ void hv_get_vpreg_128(u32 msr, struct hv_get_vp_register_output *res)
> kfree(output);
> }
> EXPORT_SYMBOL_GPL(hv_get_vpreg_128);
> +
> +void hyperv_report_panic(struct pt_regs *regs, long err)
> +{
> + static bool panic_reported;
> + u64 guest_id;
> +
> + /*
> + * We prefer to report panic on 'die' chain as we have proper
> + * registers to report, but if we miss it (e.g. on BUG()) we need
> + * to report it on 'panic'.
> + */
> + if (panic_reported)
> + return;
> + panic_reported = true;
How does this work when multiple vcpus are crashing at once? Are you
guaranteed to be single-threaded at this point?
> +
> + guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID);
> +
> + /*
> + * Hyper-V provides the ability to store only 5 values.
> + * Pick the passed in error value, the guest_id, and the PC.
> + * The first two general registers are added arbitrarily.
> + */
> + hv_set_vpreg(HV_REGISTER_CRASH_P0, err);
> + hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id);
> + hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc);
> + hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->regs[0]);
> + hv_set_vpreg(HV_REGISTER_CRASH_P4, regs->regs[1]);
How about reporting useful information, a pointer to some data
structure describing the fault? As it is, the usefulness of this is
pretty dubious.
> +
> + /*
> + * Let Hyper-V know there is crash data available
> + */
> + hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
> +}
> +EXPORT_SYMBOL_GPL(hyperv_report_panic);
> +
> +/*
> + * hyperv_report_panic_msg - report panic message to Hyper-V
> + * @pa: physical address of the panic page containing the message
> + * @size: size of the message in the page
> + */
> +void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
> +{
> + /*
> + * P3 to contain the physical address of the panic page & P4 to
> + * contain the size of the panic data in that page. Rest of the
> + * registers are no-op when the NOTIFY_MSG flag is set.
> + */
> + hv_set_vpreg(HV_REGISTER_CRASH_P0, 0);
> + hv_set_vpreg(HV_REGISTER_CRASH_P1, 0);
> + hv_set_vpreg(HV_REGISTER_CRASH_P2, 0);
> + hv_set_vpreg(HV_REGISTER_CRASH_P3, pa);
> + hv_set_vpreg(HV_REGISTER_CRASH_P4, size);
> +
> + /*
> + * Let Hyper-V know there is crash data available along with
> + * the panic message.
> + */
> + hv_set_vpreg(HV_REGISTER_CRASH_CTL,
> + (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
> +}
> +EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
> index ae6ece6..c58940d 100644
> --- a/arch/arm64/hyperv/mshyperv.c
> +++ b/arch/arm64/hyperv/mshyperv.c
> @@ -23,6 +23,8 @@
>
> static void (*vmbus_handler)(void);
> static void (*hv_stimer0_handler)(void);
> +static void (*hv_kexec_handler)(void);
> +static void (*hv_crash_handler)(struct pt_regs *regs);
Why is this in the arch-specific code? Yes, it lives in the x86 arch
code too, but I don't see what prevents it from being moved to the
vmbus_drv.c code.
>
> static int vmbus_irq;
> static long __percpu *vmbus_evt;
> @@ -137,3 +139,27 @@ void hv_remove_stimer0_irq(int irq)
> }
> }
> EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
> +
> +void hv_setup_kexec_handler(void (*handler)(void))
> +{
> + hv_kexec_handler = handler;
> +}
> +EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
> +
> +void hv_remove_kexec_handler(void)
> +{
> + hv_kexec_handler = NULL;
> +}
> +EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
> +
> +void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
> +{
> + hv_crash_handler = handler;
> +}
> +EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
> +
> +void hv_remove_crash_handler(void)
> +{
> + hv_crash_handler = NULL;
> +}
> +EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
> --
> 1.8.3.1
>
>
Thanks,
M.
--
Jazz is not dead, it just smells funny.
^ permalink raw reply
* Re: [PATCH v6 09/10] arm64: efi: Export screen_info
From: Arnd Bergmann @ 2020-03-16 8:20 UTC (permalink / raw)
To: Michael Kelley
Cc: Will Deacon, Ard Biesheuvel, Catalin Marinas, Mark Rutland,
Marc Zyngier, Linux ARM, gregkh, linux-kernel@vger.kernel.org,
linux-hyperv, linux-efi, linux-arch, olaf, Andy Whitcroft,
Vitaly Kuznetsov, Jason Wang, marcelo.cerri, K. Y. Srinivasan,
sunilmut, Boqun Feng
In-Reply-To: <1584200119-18594-10-git-send-email-mikelley@microsoft.com>
On Sat, Mar 14, 2020 at 4:36 PM Michael Kelley <mikelley@microsoft.com> wrote:
>
> The Hyper-V frame buffer driver may be built as a module, and
> it needs access to screen_info. So export screen_info.
>
> Signed-off-by: Michael Kelley <mikelley@microsoft.com>
Is there any chance of using a more modern KMS based driver for the screen
than the old fbdev subsystem? I had hoped to one day completely remove
support for the old CONFIG_VIDEO_FBDEV and screen_info from modern
architectures.
Arnd
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox