2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <kern/assert.h>
30 #include <kern/hvg_hypercall.h>
31 #include <i386/cpuid.h>
36 hvg_live_coredump_enabled(void)
38 return cpuid_vmm_present() && (cpuid_vmm_get_applepv_features() & CPUID_LEAF_FEATURE_COREDUMP
) != 0;
42 * This routine issues an Apple hypercall that notifies the hypervisor to
43 * take a guest kernel coredump. If the vmcore argument is not NULL, the
44 * name tag of the vmcore file is copied into the caller's vmcore tag array.
45 * Otherwise the name tag is ignored.
49 hvg_hcall_trigger_dump(hvg_hcall_vmcore_file_t
*vmcore
,
50 const hvg_hcall_dump_option_t dump_option
)
52 hvg_hcall_return_t ret
;
53 hvg_hcall_output_regs_t output
;
54 const size_t reg_size
= sizeof(output
.rax
);
56 /* Does the hypervisor support feature: live kernel core dump? */
57 if (!hvg_live_coredump_enabled()) {
58 return HVG_HCALL_FEAT_DISABLED
;
61 /* Make sure that we don't overflow vmcore tag array with hypercall output */
62 if (vmcore
&& (reg_size
!= sizeof(uint64_t))) {
63 os_log_error(OS_LOG_DEFAULT
, "%s: invalid hcall register size, %zu bytes (expect %zu bytes)\n",
64 __func__
, reg_size
, sizeof(uint64_t));
65 return HVG_HCALL_INVALID_PARAMETER
;
68 switch (dump_option
) {
69 case HVG_HCALL_DUMP_OPTION_REGULAR
:
70 /* Only regular dump-guest-memory is supported for now */
73 return HVG_HCALL_INVALID_PARAMETER
;
76 /* Everything checks out, issue hypercall */
77 memset(&output
, 0, sizeof(hvg_hcall_output_regs_t
));
78 ret
= hvg_hypercall1(HVG_HCALL_TRIGGER_DUMP
,
82 if (ret
== HVG_HCALL_SUCCESS
) {
84 /* Caller requested vmcore tag to be returned */
85 memcpy(&vmcore
->tag
[0], &output
.rax
, reg_size
);
86 memcpy(&vmcore
->tag
[reg_size
], &output
.rdi
, reg_size
);
87 memcpy(&vmcore
->tag
[reg_size
* 2], &output
.rsi
, reg_size
);
88 memcpy(&vmcore
->tag
[reg_size
* 3], &output
.rdx
, reg_size
);
89 memcpy(&vmcore
->tag
[reg_size
* 4], &output
.rcx
, reg_size
);
90 memcpy(&vmcore
->tag
[reg_size
* 5], &output
.r8
, reg_size
);
91 memcpy(&vmcore
->tag
[reg_size
* 6], &output
.r9
, reg_size
);
92 vmcore
->tag
[reg_size
* 7] = '\0';