History

Merge tag 'hyperv-next-signed-20211102' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv updates from Wei Liu: - Initial patch set for Hyper-V isolation VM support (Tianyu Lan) - Fix a warning on preemption (Vitaly Kuznetsov) - A bunch of misc cleanup patches * tag 'hyperv-next-signed-20211102' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: x86/hyperv: Protect set_hv_tscchange_cb() against getting preempted Drivers: hv : vmbus: Adding NULL pointer check x86/hyperv: Remove duplicate include x86/hyperv: Remove duplicated include in hv_init Drivers: hv: vmbus: Remove unused code to check for subchannels Drivers: hv: vmbus: Initialize VMbus ring buffer for Isolation VM Drivers: hv: vmbus: Add SNP support for VMbus channel initiate message x86/hyperv: Add ghcb hvcall support for SNP VM x86/hyperv: Add Write/Read MSR registers via ghcb page Drivers: hv: vmbus: Mark vmbus ring buffer visible to host in Isolation VM x86/hyperv: Add new hvcall guest address host visibility support x86/hyperv: Initialize shared memory boundary in the Isolation VM. x86/hyperv: Initialize GHCB page in Isolation VM

Linus Torvalds committed 5 years ago

Commit 44261f82 parents 0aaa58e 285f68a21 files · +761 −172Browse files

Unified · Split

21 files
  1. arch/x86/hyperv/Makefile +1 −1
  2. arch/x86/hyperv/hv_init.c +61 −21
  3. arch/x86/hyperv/ivm.c +289 −0
  4. arch/x86/include/asm/hyperv-tlfs.h +17 −0
  5. arch/x86/include/asm/mshyperv.h +57 −13
  6. arch/x86/kernel/cpu/mshyperv.c +5 −0
  7. arch/x86/mm/pat/set_memory.c +18 −5
  8. drivers/hv/Kconfig +1 −0
  9. drivers/hv/channel.c +48 −24
  10. drivers/hv/channel_mgmt.c +0 −34
  11. drivers/hv/connection.c +94 −7
  12. drivers/hv/hv.c +65 −17
  13. drivers/hv/hv_common.c +12 −0
  14. drivers/hv/hyperv_vmbus.h +2 −0
  15. drivers/hv/ring_buffer.c +44 −13
  16. drivers/net/hyperv/hyperv_net.h +3 −2
  17. drivers/net/hyperv/netvsc.c +7 −8
  18. drivers/uio/uio_hv_generic.c +8 −10
  19. include/asm-generic/hyperv-tlfs.h +1 −0
  20. include/asm-generic/mshyperv.h +19 −1
  21. include/linux/hyperv.h +9 −16
arch/x86/hyperv/Makefile+1−1
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-y := hv_init.o mmu.o nested.o irqdomain.o2obj-y := hv_init.o mmu.o nested.o irqdomain.o ivm.o
3obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o3obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o
4 4
5ifdef CONFIG_X86_645ifdef CONFIG_X86_64
arch/x86/hyperv/hv_init.c+61−21
@@ -36,12 +36,42 @@ EXPORT_SYMBOL_GPL(hv_current_partition_id); · 35 unmodified lines
36void *hv_hypercall_pg;36void *hv_hypercall_pg;
37EXPORT_SYMBOL_GPL(hv_hypercall_pg);37EXPORT_SYMBOL_GPL(hv_hypercall_pg);
38 38
39union hv_ghcb __percpu **hv_ghcb_pg;
40
39/* Storage to save the hypercall page temporarily for hibernation */41/* Storage to save the hypercall page temporarily for hibernation */
40static void *hv_hypercall_pg_saved;42static void *hv_hypercall_pg_saved;
41 43
42struct hv_vp_assist_page **hv_vp_assist_page;44struct hv_vp_assist_page **hv_vp_assist_page;
43EXPORT_SYMBOL_GPL(hv_vp_assist_page);45EXPORT_SYMBOL_GPL(hv_vp_assist_page);
44 46
47static int hyperv_init_ghcb(void)
48{
49 u64 ghcb_gpa;
50 void *ghcb_va;
51 void **ghcb_base;
52
53 if (!hv_isolation_type_snp())
54 return 0;
55
56 if (!hv_ghcb_pg)
57 return -EINVAL;
58
59 /*
60 * GHCB page is allocated by paravisor. The address
61 * returned by MSR_AMD64_SEV_ES_GHCB is above shared
62 * memory boundary and map it here.
63 */
64 rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
65 ghcb_va = memremap(ghcb_gpa, HV_HYP_PAGE_SIZE, MEMREMAP_WB);
66 if (!ghcb_va)
67 return -ENOMEM;
68
69 ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
70 *ghcb_base = ghcb_va;
71
72 return 0;
73}
74
45static int hv_cpu_init(unsigned int cpu)75static int hv_cpu_init(unsigned int cpu)
46{76{
47 union hv_vp_assist_msr_contents msr = { 0 };77 union hv_vp_assist_msr_contents msr = { 0 };
@@ -85,7 +115,7 @@ static int hv_cpu_init(unsigned int cpu) · 37 unmodified lines
85 }115 }
86 }116 }
87 117
88 return 0;118 return hyperv_init_ghcb();
89}119}
90 120
91static void (*hv_reenlightenment_cb)(void);121static void (*hv_reenlightenment_cb)(void);
@@ -139,7 +169,6 @@ void set_hv_tscchange_cb(void (*cb)(void)) · 47 unmodified lines
139 struct hv_reenlightenment_control re_ctrl = {169 struct hv_reenlightenment_control re_ctrl = {
140 .vector = HYPERV_REENLIGHTENMENT_VECTOR,170 .vector = HYPERV_REENLIGHTENMENT_VECTOR,
141 .enabled = 1,171 .enabled = 1,
142 .target_vp = hv_vp_index[smp_processor_id()]
143 };172 };
144 struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};173 struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
145 174
@@ -153,8 +182,12 @@ void set_hv_tscchange_cb(void (*cb)(void)) · 7 unmodified lines
153 /* Make sure callback is registered before we write to MSRs */182 /* Make sure callback is registered before we write to MSRs */
154 wmb();183 wmb();
155 184
185 re_ctrl.target_vp = hv_vp_index[get_cpu()];
186
156 wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));187 wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
157 wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));188 wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));
189
190 put_cpu();
158}191}
159EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);192EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);
160 193
@@ -177,6 +210,14 @@ static int hv_cpu_die(unsigned int cpu) · 16 unmodified lines
177{210{
178 struct hv_reenlightenment_control re_ctrl;211 struct hv_reenlightenment_control re_ctrl;
179 unsigned int new_cpu;212 unsigned int new_cpu;
213 void **ghcb_va;
214
215 if (hv_ghcb_pg) {
216 ghcb_va = (void **)this_cpu_ptr(hv_ghcb_pg);
217 if (*ghcb_va)
218 memunmap(*ghcb_va);
219 *ghcb_va = NULL;
220 }
180 221
181 hv_common_cpu_die(cpu);222 hv_common_cpu_die(cpu);
182 223
@@ -366,10 +407,16 @@ void __init hyperv_init(void) · 183 unmodified lines
366 goto common_free;407 goto common_free;
367 }408 }
368 409
410 if (hv_isolation_type_snp()) {
411 hv_ghcb_pg = alloc_percpu(union hv_ghcb *);
412 if (!hv_ghcb_pg)
413 goto free_vp_assist_page;
414 }
415
369 cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",416 cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
370 hv_cpu_init, hv_cpu_die);417 hv_cpu_init, hv_cpu_die);
371 if (cpuhp < 0)418 if (cpuhp < 0)
372 goto free_vp_assist_page;419 goto free_ghcb_page;
373 420
374 /*421 /*
375 * Setup the hypercall page and enable hypercalls.422 * Setup the hypercall page and enable hypercalls.
@@ -379,14 +426,15 @@ void __init hyperv_init(void) · 3 unmodified lines
379 guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);426 guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
380 wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);427 wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
381 428
429 /* Hyper-V requires to write guest os id via ghcb in SNP IVM. */
430 hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);
431
382 hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START,432 hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START,
383 VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,433 VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,
384 VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,434 VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
385 __builtin_return_address(0));435 __builtin_return_address(0));
386 if (hv_hypercall_pg == NULL) {436 if (hv_hypercall_pg == NULL)
387 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);437 goto clean_guest_os_id;
388 goto remove_cpuhp_state;
389 }
390 438
391 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);439 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
392 hypercall_msr.enable = 1;440 hypercall_msr.enable = 1;
@@ -456,8 +504,12 @@ void __init hyperv_init(void) · 63 unmodified lines
456 hv_query_ext_cap(0);504 hv_query_ext_cap(0);
457 return;505 return;
458 506
459remove_cpuhp_state:507clean_guest_os_id:
508 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
509 hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
460 cpuhp_remove_state(cpuhp);510 cpuhp_remove_state(cpuhp);
511free_ghcb_page:
512 free_percpu(hv_ghcb_pg);
461free_vp_assist_page:513free_vp_assist_page:
462 kfree(hv_vp_assist_page);514 kfree(hv_vp_assist_page);
463 hv_vp_assist_page = NULL;515 hv_vp_assist_page = NULL;
@@ -476,6 +528,7 @@ void hyperv_cleanup(void) · 12 unmodified lines
476 528
477 /* Reset our OS id */529 /* Reset our OS id */
478 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);530 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
531 hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
479 532
480 /*533 /*
481 * Reset hypercall page reference before reset the page,534 * Reset hypercall page reference before reset the page,
@@ -546,16 +599,3 @@ bool hv_is_hyperv_initialized(void) · 64 unmodified lines
546 return hypercall_msr.enable;599 return hypercall_msr.enable;
547}600}
548EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);601EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
549
550enum hv_isolation_type hv_get_isolation_type(void)
551{
552 if (!(ms_hyperv.priv_high & HV_ISOLATION))
553 return HV_ISOLATION_TYPE_NONE;
554 return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
555}
556EXPORT_SYMBOL_GPL(hv_get_isolation_type);
557
558bool hv_is_isolation_supported(void)
559{
560 return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
561}
arch/x86/hyperv/ivm.c+289−0
@@ -0,0 +1,289 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Hyper-V Isolation VM interface with paravisor and hypervisor
4 *
5 * Author:
6 * Tianyu Lan <Tianyu.Lan@microsoft.com>
7 */
8
9#include <linux/bitfield.h>
10#include <linux/hyperv.h>
11#include <linux/types.h>
12#include <linux/slab.h>
13#include <asm/svm.h>
14#include <asm/sev.h>
15#include <asm/io.h>
16#include <asm/mshyperv.h>
17#include <asm/hypervisor.h>
18
19#ifdef CONFIG_AMD_MEM_ENCRYPT
20
21#define GHCB_USAGE_HYPERV_CALL 1
22
23union hv_ghcb {
24 struct ghcb ghcb;
25 struct {
26 u64 hypercalldata[509];
27 u64 outputgpa;
28 union {
29 union {
30 struct {
31 u32 callcode : 16;
32 u32 isfast : 1;
33 u32 reserved1 : 14;
34 u32 isnested : 1;
35 u32 countofelements : 12;
36 u32 reserved2 : 4;
37 u32 repstartindex : 12;
38 u32 reserved3 : 4;
39 };
40 u64 asuint64;
41 } hypercallinput;
42 union {
43 struct {
44 u16 callstatus;
45 u16 reserved1;
46 u32 elementsprocessed : 12;
47 u32 reserved2 : 20;
48 };
49 u64 asunit64;
50 } hypercalloutput;
51 };
52 u64 reserved2;
53 } hypercall;
54} __packed __aligned(HV_HYP_PAGE_SIZE);
55
56u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
57{
58 union hv_ghcb *hv_ghcb;
59 void **ghcb_base;
60 unsigned long flags;
61 u64 status;
62
63 if (!hv_ghcb_pg)
64 return -EFAULT;
65
66 WARN_ON(in_nmi());
67
68 local_irq_save(flags);
69 ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
70 hv_ghcb = (union hv_ghcb *)*ghcb_base;
71 if (!hv_ghcb) {
72 local_irq_restore(flags);
73 return -EFAULT;
74 }
75
76 hv_ghcb->ghcb.protocol_version = GHCB_PROTOCOL_MAX;
77 hv_ghcb->ghcb.ghcb_usage = GHCB_USAGE_HYPERV_CALL;
78
79 hv_ghcb->hypercall.outputgpa = (u64)output;
80 hv_ghcb->hypercall.hypercallinput.asuint64 = 0;
81 hv_ghcb->hypercall.hypercallinput.callcode = control;
82
83 if (input_size)
84 memcpy(hv_ghcb->hypercall.hypercalldata, input, input_size);
85
86 VMGEXIT();
87
88 hv_ghcb->ghcb.ghcb_usage = 0xffffffff;
89 memset(hv_ghcb->ghcb.save.valid_bitmap, 0,
90 sizeof(hv_ghcb->ghcb.save.valid_bitmap));
91
92 status = hv_ghcb->hypercall.hypercalloutput.callstatus;
93
94 local_irq_restore(flags);
95
96 return status;
97}
98
99void hv_ghcb_msr_write(u64 msr, u64 value)
100{
101 union hv_ghcb *hv_ghcb;
102 void **ghcb_base;
103 unsigned long flags;
104 struct es_em_ctxt ctxt;
105
106 if (!hv_ghcb_pg)
107 return;
108
109 WARN_ON(in_nmi());
110
111 local_irq_save(flags);
112 ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
113 hv_ghcb = (union hv_ghcb *)*ghcb_base;
114 if (!hv_ghcb) {
115 local_irq_restore(flags);
116 return;
117 }
118
119 ghcb_set_rcx(&hv_ghcb->ghcb, msr);
120 ghcb_set_rax(&hv_ghcb->ghcb, lower_32_bits(value));
121 ghcb_set_rdx(&hv_ghcb->ghcb, upper_32_bits(value));
122
123 if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, false, &ctxt,
124 SVM_EXIT_MSR, 1, 0))
125 pr_warn("Fail to write msr via ghcb %llx.\n", msr);
126
127 local_irq_restore(flags);
128}
129EXPORT_SYMBOL_GPL(hv_ghcb_msr_write);
130
131void hv_ghcb_msr_read(u64 msr, u64 *value)
132{
133 union hv_ghcb *hv_ghcb;
134 void **ghcb_base;
135 unsigned long flags;
136 struct es_em_ctxt ctxt;
137
138 /* Check size of union hv_ghcb here. */
139 BUILD_BUG_ON(sizeof(union hv_ghcb) != HV_HYP_PAGE_SIZE);
140
141 if (!hv_ghcb_pg)
142 return;
143
144 WARN_ON(in_nmi());
145
146 local_irq_save(flags);
147 ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
148 hv_ghcb = (union hv_ghcb *)*ghcb_base;
149 if (!hv_ghcb) {
150 local_irq_restore(flags);
151 return;
152 }
153
154 ghcb_set_rcx(&hv_ghcb->ghcb, msr);
155 if (sev_es_ghcb_hv_call(&hv_ghcb->ghcb, false, &ctxt,
156 SVM_EXIT_MSR, 0, 0))
157 pr_warn("Fail to read msr via ghcb %llx.\n", msr);
158 else
159 *value = (u64)lower_32_bits(hv_ghcb->ghcb.save.rax)
160 | ((u64)lower_32_bits(hv_ghcb->ghcb.save.rdx) << 32);
161 local_irq_restore(flags);
162}
163EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
164#endif
165
166enum hv_isolation_type hv_get_isolation_type(void)
167{
168 if (!(ms_hyperv.priv_high & HV_ISOLATION))
169 return HV_ISOLATION_TYPE_NONE;
170 return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
171}
172EXPORT_SYMBOL_GPL(hv_get_isolation_type);
173
174/*
175 * hv_is_isolation_supported - Check system runs in the Hyper-V
176 * isolation VM.
177 */
178bool hv_is_isolation_supported(void)
179{
180 if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
181 return false;
182
183 if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
184 return false;
185
186 return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
187}
188
189DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
190
191/*
192 * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
193 * isolation VM.
194 */
195bool hv_isolation_type_snp(void)
196{
197 return static_branch_unlikely(&isolation_type_snp);
198}
199
200/*
201 * hv_mark_gpa_visibility - Set pages visible to host via hvcall.
202 *
203 * In Isolation VM, all guest memory is encrypted from host and guest
204 * needs to set memory visible to host via hvcall before sharing memory
205 * with host.
206 */
207static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
208 enum hv_mem_host_visibility visibility)
209{
210 struct hv_gpa_range_for_visibility **input_pcpu, *input;
211 u16 pages_processed;
212 u64 hv_status;
213 unsigned long flags;
214
215 /* no-op if partition isolation is not enabled */
216 if (!hv_is_isolation_supported())
217 return 0;
218
219 if (count > HV_MAX_MODIFY_GPA_REP_COUNT) {
220 pr_err("Hyper-V: GPA count:%d exceeds supported:%lu\n", count,
221 HV_MAX_MODIFY_GPA_REP_COUNT);
222 return -EINVAL;
223 }
224
225 local_irq_save(flags);
226 input_pcpu = (struct hv_gpa_range_for_visibility **)
227 this_cpu_ptr(hyperv_pcpu_input_arg);
228 input = *input_pcpu;
229 if (unlikely(!input)) {
230 local_irq_restore(flags);
231 return -EINVAL;
232 }
233
234 input->partition_id = HV_PARTITION_ID_SELF;
235 input->host_visibility = visibility;
236 input->reserved0 = 0;
237 input->reserved1 = 0;
238 memcpy((void *)input->gpa_page_list, pfn, count * sizeof(*pfn));
239 hv_status = hv_do_rep_hypercall(
240 HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY, count,
241 0, input, &pages_processed);
242 local_irq_restore(flags);
243
244 if (hv_result_success(hv_status))
245 return 0;
246 else
247 return -EFAULT;
248}
249
250/*
251 * hv_set_mem_host_visibility - Set specified memory visible to host.
252 *
253 * In Isolation VM, all guest memory is encrypted from host and guest
254 * needs to set memory visible to host via hvcall before sharing memory
255 * with host. This function works as wrap of hv_mark_gpa_visibility()
256 * with memory base and size.
257 */
258int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visible)
259{
260 enum hv_mem_host_visibility visibility = visible ?
261 VMBUS_PAGE_VISIBLE_READ_WRITE : VMBUS_PAGE_NOT_VISIBLE;
262 u64 *pfn_array;
263 int ret = 0;
264 int i, pfn;
265
266 if (!hv_is_isolation_supported() || !hv_hypercall_pg)
267 return 0;
268
269 pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
270 if (!pfn_array)
271 return -ENOMEM;
272
273 for (i = 0, pfn = 0; i < pagecount; i++) {
274 pfn_array[pfn] = virt_to_hvpfn((void *)kbuffer + i * HV_HYP_PAGE_SIZE);
275 pfn++;
276
277 if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) {
278 ret = hv_mark_gpa_visibility(pfn, pfn_array,
279 visibility);
280 if (ret)
281 goto err_free_pfn_array;
282 pfn = 0;
283 }
284 }
285
286 err_free_pfn_array:
287 kfree(pfn_array);
288 return ret;
289}
arch/x86/include/asm/hyperv-tlfs.h+17−0
@@ -276,6 +276,23 @@ enum hv_isolation_type { · 275 unmodified lines
276#define HV_X64_MSR_TIME_REF_COUNT HV_REGISTER_TIME_REF_COUNT276#define HV_X64_MSR_TIME_REF_COUNT HV_REGISTER_TIME_REF_COUNT
277#define HV_X64_MSR_REFERENCE_TSC HV_REGISTER_REFERENCE_TSC277#define HV_X64_MSR_REFERENCE_TSC HV_REGISTER_REFERENCE_TSC
278 278
279/* Hyper-V memory host visibility */
280enum hv_mem_host_visibility {
281 VMBUS_PAGE_NOT_VISIBLE = 0,
282 VMBUS_PAGE_VISIBLE_READ_ONLY = 1,
283 VMBUS_PAGE_VISIBLE_READ_WRITE = 3
284};
285
286/* HvCallModifySparseGpaPageHostVisibility hypercall */
287#define HV_MAX_MODIFY_GPA_REP_COUNT ((PAGE_SIZE / sizeof(u64)) - 2)
288struct hv_gpa_range_for_visibility {
289 u64 partition_id;
290 u32 host_visibility:2;
291 u32 reserved0:30;
292 u32 reserved1;
293 u64 gpa_page_list[HV_MAX_MODIFY_GPA_REP_COUNT];
294} __packed;
295
279/*296/*
280 * Declare the MSR used to setup pages used to communicate with the hypervisor.297 * Declare the MSR used to setup pages used to communicate with the hypervisor.
281 */298 */
arch/x86/include/asm/mshyperv.h+57−13
@@ -11,23 +11,14 @@ · 10 unmodified lines
11#include <asm/paravirt.h>11#include <asm/paravirt.h>
12#include <asm/mshyperv.h>12#include <asm/mshyperv.h>
13 13
14union hv_ghcb;
15
16DECLARE_STATIC_KEY_FALSE(isolation_type_snp);
17
14typedef int (*hyperv_fill_flush_list_func)(18typedef int (*hyperv_fill_flush_list_func)(
15 struct hv_guest_mapping_flush_list *flush,19 struct hv_guest_mapping_flush_list *flush,
16 void *data);20 void *data);
17 21
18static inline void hv_set_register(unsigned int reg, u64 value)
19{
20 wrmsrl(reg, value);
21}
22
23static inline u64 hv_get_register(unsigned int reg)
24{
25 u64 value;
26
27 rdmsrl(reg, value);
28 return value;
29}
30
31#define hv_get_raw_timer() rdtsc_ordered()22#define hv_get_raw_timer() rdtsc_ordered()
32 23
33void hyperv_vector_handler(struct pt_regs *regs);24void hyperv_vector_handler(struct pt_regs *regs);
@@ -39,6 +30,8 @@ extern void *hv_hypercall_pg; · 5 unmodified lines
39 30
40extern u64 hv_current_partition_id;31extern u64 hv_current_partition_id;
41 32
33extern union hv_ghcb __percpu **hv_ghcb_pg;
34
42int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);35int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
43int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);36int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
44int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);37int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
@@ -188,6 +181,50 @@ struct irq_domain *hv_create_pci_msi_domain(void); · 143 unmodified lines
188int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,181int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
189 struct hv_interrupt_entry *entry);182 struct hv_interrupt_entry *entry);
190int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);183int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
184int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
185
186#ifdef CONFIG_AMD_MEM_ENCRYPT
187void hv_ghcb_msr_write(u64 msr, u64 value);
188void hv_ghcb_msr_read(u64 msr, u64 *value);
189#else
190static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
191static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
192#endif
193
194extern bool hv_isolation_type_snp(void);
195
196static inline bool hv_is_synic_reg(unsigned int reg)
197{
198 if ((reg >= HV_REGISTER_SCONTROL) &&
199 (reg <= HV_REGISTER_SINT15))
200 return true;
201 return false;
202}
203
204static inline u64 hv_get_register(unsigned int reg)
205{
206 u64 value;
207
208 if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
209 hv_ghcb_msr_read(reg, &value);
210 else
211 rdmsrl(reg, value);
212 return value;
213}
214
215static inline void hv_set_register(unsigned int reg, u64 value)
216{
217 if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
218 hv_ghcb_msr_write(reg, value);
219
220 /* Write proxy bit via wrmsl instruction */
221 if (reg >= HV_REGISTER_SINT0 &&
222 reg <= HV_REGISTER_SINT15)
223 wrmsrl(reg, value | 1 << 20);
224 } else {
225 wrmsrl(reg, value);
226 }
227}
191 228
192#else /* CONFIG_HYPERV */229#else /* CONFIG_HYPERV */
193static inline void hyperv_init(void) {}230static inline void hyperv_init(void) {}
@@ -205,6 +242,13 @@ static inline int hyperv_flush_guest_mapping_range(u64 as, · 11 unmodified lines
205{242{
206 return -1;243 return -1;
207}244}
245static inline void hv_set_register(unsigned int reg, u64 value) { }
246static inline u64 hv_get_register(unsigned int reg) { return 0; }
247static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
248 bool visible)
249{
250 return -1;
251}
208#endif /* CONFIG_HYPERV */252#endif /* CONFIG_HYPERV */
209 253
210 254
arch/x86/kernel/cpu/mshyperv.c+5−0
@@ -313,9 +313,14 @@ static void __init ms_hyperv_init_platform(void) · 312 unmodified lines
313 if (ms_hyperv.priv_high & HV_ISOLATION) {313 if (ms_hyperv.priv_high & HV_ISOLATION) {
314 ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);314 ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);
315 ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);315 ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);
316 ms_hyperv.shared_gpa_boundary =
317 BIT_ULL(ms_hyperv.shared_gpa_boundary_bits);
316 318
317 pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",319 pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",
318 ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);320 ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);
321
322 if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP)
323 static_branch_enable(&isolation_type_snp);
319 }324 }
320 325
321 if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {326 if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {
arch/x86/mm/pat/set_memory.c+18−5
@@ -30,6 +30,8 @@ · 29 unmodified lines
30#include <asm/proto.h>30#include <asm/proto.h>
31#include <asm/memtype.h>31#include <asm/memtype.h>
32#include <asm/set_memory.h>32#include <asm/set_memory.h>
33#include <asm/hyperv-tlfs.h>
34#include <asm/mshyperv.h>
33 35
34#include "../mm_internal.h"36#include "../mm_internal.h"
35 37
@@ -1981,15 +1983,15 @@ int set_memory_global(unsigned long addr, int numpages) · 1945 unmodified lines
1981 __pgprot(_PAGE_GLOBAL), 0);1983 __pgprot(_PAGE_GLOBAL), 0);
1982}1984}
1983 1985
1984static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)1986/*
1987 * __set_memory_enc_pgtable() is used for the hypervisors that get
1988 * informed about "encryption" status via page tables.
1989 */
1990static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
1985{1991{
1986 struct cpa_data cpa;1992 struct cpa_data cpa;
1987 int ret;1993 int ret;
1988 1994
1989 /* Nothing to do if memory encryption is not active */
1990 if (!cc_platform_has(CC_ATTR_MEM_ENCRYPT))
1991 return 0;
1992
1993 /* Should not be working on unaligned addresses */1995 /* Should not be working on unaligned addresses */
1994 if (WARN_ONCE(addr & ~PAGE_MASK, "misaligned address: %#lx\n", addr))1996 if (WARN_ONCE(addr & ~PAGE_MASK, "misaligned address: %#lx\n", addr))
1995 addr &= PAGE_MASK;1997 addr &= PAGE_MASK;
@@ -2024,6 +2026,17 @@ static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc) · 28 unmodified lines
2024 return ret;2026 return ret;
2025}2027}
2026 2028
2029static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
2030{
2031 if (hv_is_isolation_supported())
2032 return hv_set_mem_host_visibility(addr, numpages, !enc);
2033
2034 if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
2035 return __set_memory_enc_pgtable(addr, numpages, enc);
2036
2037 return 0;
2038}
2039
2027int set_memory_encrypted(unsigned long addr, int numpages)2040int set_memory_encrypted(unsigned long addr, int numpages)
2028{2041{
2029 return __set_memory_enc_dec(addr, numpages, true);2042 return __set_memory_enc_dec(addr, numpages, true);
drivers/hv/Kconfig+1−0
@@ -8,6 +8,7 @@ config HYPERV · 7 unmodified lines
8 || (ARM64 && !CPU_BIG_ENDIAN))8 || (ARM64 && !CPU_BIG_ENDIAN))
9 select PARAVIRT9 select PARAVIRT
10 select X86_HV_CALLBACK_VECTOR if X8610 select X86_HV_CALLBACK_VECTOR if X86
11 select VMAP_PFN
11 help12 help
12 Select this option to run Linux as a Hyper-V client operating13 Select this option to run Linux as a Hyper-V client operating
13 system.14 system.
drivers/hv/channel.c+48−24
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <linux/hyperv.h>17#include <linux/hyperv.h>
18#include <linux/uio.h>18#include <linux/uio.h>
19#include <linux/interrupt.h>19#include <linux/interrupt.h>
20#include <linux/set_memory.h>
20#include <asm/page.h>21#include <asm/page.h>
21#include <asm/mshyperv.h>22#include <asm/mshyperv.h>
22 23
@@ -456,7 +457,7 @@ nomem: · 433 unmodified lines
456static int __vmbus_establish_gpadl(struct vmbus_channel *channel,457static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
457 enum hv_gpadl_type type, void *kbuffer,458 enum hv_gpadl_type type, void *kbuffer,
458 u32 size, u32 send_offset,459 u32 size, u32 send_offset,
459 u32 *gpadl_handle)460 struct vmbus_gpadl *gpadl)
460{461{
461 struct vmbus_channel_gpadl_header *gpadlmsg;462 struct vmbus_channel_gpadl_header *gpadlmsg;
462 struct vmbus_channel_gpadl_body *gpadl_body;463 struct vmbus_channel_gpadl_body *gpadl_body;
@@ -474,6 +475,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, · 11 unmodified lines
474 if (ret)475 if (ret)
475 return ret;476 return ret;
476 477
478 ret = set_memory_decrypted((unsigned long)kbuffer,
479 PFN_UP(size));
480 if (ret) {
481 dev_warn(&channel->device_obj->device,
482 "Failed to set host visibility for new GPADL %d.\n",
483 ret);
484 return ret;
485 }
486
477 init_completion(&msginfo->waitevent);487 init_completion(&msginfo->waitevent);
478 msginfo->waiting_channel = channel;488 msginfo->waiting_channel = channel;
479 489
@@ -537,7 +547,10 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, · 57 unmodified lines
537 }547 }
538 548
539 /* At this point, we received the gpadl created msg */549 /* At this point, we received the gpadl created msg */
540 *gpadl_handle = gpadlmsg->gpadl;550 gpadl->gpadl_handle = gpadlmsg->gpadl;
551 gpadl->buffer = kbuffer;
552 gpadl->size = size;
553
541 554
542cleanup:555cleanup:
543 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);556 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
@@ -549,6 +562,11 @@ cleanup: · 5 unmodified lines
549 }562 }
550 563
551 kfree(msginfo);564 kfree(msginfo);
565
566 if (ret)
567 set_memory_encrypted((unsigned long)kbuffer,
568 PFN_UP(size));
569
552 return ret;570 return ret;
553}571}
554 572
@@ -561,10 +579,10 @@ cleanup: · 6 unmodified lines
561 * @gpadl_handle: some funky thing579 * @gpadl_handle: some funky thing
562 */580 */
563int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,581int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
564 u32 size, u32 *gpadl_handle)582 u32 size, struct vmbus_gpadl *gpadl)
565{583{
566 return __vmbus_establish_gpadl(channel, HV_GPADL_BUFFER, kbuffer, size,584 return __vmbus_establish_gpadl(channel, HV_GPADL_BUFFER, kbuffer, size,
567 0U, gpadl_handle);585 0U, gpadl);
568}586}
569EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);587EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
570 588
@@ -665,17 +683,8 @@ static int __vmbus_open(struct vmbus_channel *newchannel, · 94 unmodified lines
665 if (!newchannel->max_pkt_size)683 if (!newchannel->max_pkt_size)
666 newchannel->max_pkt_size = VMBUS_DEFAULT_MAX_PKT_SIZE;684 newchannel->max_pkt_size = VMBUS_DEFAULT_MAX_PKT_SIZE;
667 685
668 err = hv_ringbuffer_init(&newchannel->outbound, page, send_pages, 0);
669 if (err)
670 goto error_clean_ring;
671
672 err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages],
673 recv_pages, newchannel->max_pkt_size);
674 if (err)
675 goto error_clean_ring;
676
677 /* Establish the gpadl for the ring buffer */686 /* Establish the gpadl for the ring buffer */
678 newchannel->ringbuffer_gpadlhandle = 0;687 newchannel->ringbuffer_gpadlhandle.gpadl_handle = 0;
679 688
680 err = __vmbus_establish_gpadl(newchannel, HV_GPADL_RING,689 err = __vmbus_establish_gpadl(newchannel, HV_GPADL_RING,
681 page_address(newchannel->ringbuffer_page),690 page_address(newchannel->ringbuffer_page),
@@ -685,6 +694,16 @@ static int __vmbus_open(struct vmbus_channel *newchannel, · 3 unmodified lines
685 if (err)694 if (err)
686 goto error_clean_ring;695 goto error_clean_ring;
687 696
697 err = hv_ringbuffer_init(&newchannel->outbound,
698 page, send_pages, 0);
699 if (err)
700 goto error_free_gpadl;
701
702 err = hv_ringbuffer_init(&newchannel->inbound, &page[send_pages],
703 recv_pages, newchannel->max_pkt_size);
704 if (err)
705 goto error_free_gpadl;
706
688 /* Create and init the channel open message */707 /* Create and init the channel open message */
689 open_info = kzalloc(sizeof(*open_info) +708 open_info = kzalloc(sizeof(*open_info) +
690 sizeof(struct vmbus_channel_open_channel),709 sizeof(struct vmbus_channel_open_channel),
@@ -701,7 +720,8 @@ static int __vmbus_open(struct vmbus_channel *newchannel, · 10 unmodified lines
701 open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;720 open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
702 open_msg->openid = newchannel->offermsg.child_relid;721 open_msg->openid = newchannel->offermsg.child_relid;
703 open_msg->child_relid = newchannel->offermsg.child_relid;722 open_msg->child_relid = newchannel->offermsg.child_relid;
704 open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;723 open_msg->ringbuffer_gpadlhandle
724 = newchannel->ringbuffer_gpadlhandle.gpadl_handle;
705 /*725 /*
706 * The unit of ->downstream_ringbuffer_pageoffset is HV_HYP_PAGE and726 * The unit of ->downstream_ringbuffer_pageoffset is HV_HYP_PAGE and
707 * the unit of ->ringbuffer_send_offset (i.e. send_pages) is PAGE, so727 * the unit of ->ringbuffer_send_offset (i.e. send_pages) is PAGE, so
@@ -759,8 +779,7 @@ error_clean_msglist: · 51 unmodified lines
759error_free_info:779error_free_info:
760 kfree(open_info);780 kfree(open_info);
761error_free_gpadl:781error_free_gpadl:
762 vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);782 vmbus_teardown_gpadl(newchannel, &newchannel->ringbuffer_gpadlhandle);
763 newchannel->ringbuffer_gpadlhandle = 0;
764error_clean_ring:783error_clean_ring:
765 hv_ringbuffer_cleanup(&newchannel->outbound);784 hv_ringbuffer_cleanup(&newchannel->outbound);
766 hv_ringbuffer_cleanup(&newchannel->inbound);785 hv_ringbuffer_cleanup(&newchannel->inbound);
@@ -806,7 +825,7 @@ EXPORT_SYMBOL_GPL(vmbus_open); · 39 unmodified lines
806/*825/*
807 * vmbus_teardown_gpadl -Teardown the specified GPADL handle826 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
808 */827 */
809int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)828int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpadl)
810{829{
811 struct vmbus_channel_gpadl_teardown *msg;830 struct vmbus_channel_gpadl_teardown *msg;
812 struct vmbus_channel_msginfo *info;831 struct vmbus_channel_msginfo *info;
@@ -825,7 +844,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) · 12 unmodified lines
825 844
826 msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;845 msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
827 msg->child_relid = channel->offermsg.child_relid;846 msg->child_relid = channel->offermsg.child_relid;
828 msg->gpadl = gpadl_handle;847 msg->gpadl = gpadl->gpadl_handle;
829 848
830 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);849 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
831 list_add_tail(&info->msglistentry,850 list_add_tail(&info->msglistentry,
@@ -845,6 +864,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) · 13 unmodified lines
845 864
846 wait_for_completion(&info->waitevent);865 wait_for_completion(&info->waitevent);
847 866
867 gpadl->gpadl_handle = 0;
868
848post_msg_err:869post_msg_err:
849 /*870 /*
850 * If the channel has been rescinded;871 * If the channel has been rescinded;
@@ -859,6 +880,12 @@ post_msg_err: · 8 unmodified lines
859 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);880 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
860 881
861 kfree(info);882 kfree(info);
883
884 ret = set_memory_encrypted((unsigned long)gpadl->buffer,
885 PFN_UP(gpadl->size));
886 if (ret)
887 pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
888
862 return ret;889 return ret;
863}890}
864EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);891EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
@@ -933,9 +960,8 @@ static int vmbus_close_internal(struct vmbus_channel *channel) · 68 unmodified lines
933 }960 }
934 961
935 /* Tear down the gpadl for the channel's ring buffer */962 /* Tear down the gpadl for the channel's ring buffer */
936 else if (channel->ringbuffer_gpadlhandle) {963 else if (channel->ringbuffer_gpadlhandle.gpadl_handle) {
937 ret = vmbus_teardown_gpadl(channel,964 ret = vmbus_teardown_gpadl(channel, &channel->ringbuffer_gpadlhandle);
938 channel->ringbuffer_gpadlhandle);
939 if (ret) {965 if (ret) {
940 pr_err("Close failed: teardown gpadl return %d\n", ret);966 pr_err("Close failed: teardown gpadl return %d\n", ret);
941 /*967 /*
@@ -943,8 +969,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) · 1 unmodified line
943 * it is perhaps better to leak memory.969 * it is perhaps better to leak memory.
944 */970 */
945 }971 }
946
947 channel->ringbuffer_gpadlhandle = 0;
948 }972 }
949 973
950 if (!ret)974 if (!ret)
drivers/hv/channel_mgmt.c+0−34
@@ -1581,21 +1581,6 @@ cleanup: · 1580 unmodified lines
1581 return ret;1581 return ret;
1582}1582}
1583 1583
1584static void invoke_sc_cb(struct vmbus_channel *primary_channel)
1585{
1586 struct list_head *cur, *tmp;
1587 struct vmbus_channel *cur_channel;
1588
1589 if (primary_channel->sc_creation_callback == NULL)
1590 return;
1591
1592 list_for_each_safe(cur, tmp, &primary_channel->sc_list) {
1593 cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
1594
1595 primary_channel->sc_creation_callback(cur_channel);
1596 }
1597}
1598
1599void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,1584void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel,
1600 void (*sc_cr_cb)(struct vmbus_channel *new_sc))1585 void (*sc_cr_cb)(struct vmbus_channel *new_sc))
1601{1586{
@@ -1603,25 +1588,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, · 1 unmodified line
1603}1588}
1604EXPORT_SYMBOL_GPL(vmbus_set_sc_create_callback);1589EXPORT_SYMBOL_GPL(vmbus_set_sc_create_callback);
1605 1590
1606bool vmbus_are_subchannels_present(struct vmbus_channel *primary)
1607{
1608 bool ret;
1609
1610 ret = !list_empty(&primary->sc_list);
1611
1612 if (ret) {
1613 /*
1614 * Invoke the callback on sub-channel creation.
1615 * This will present a uniform interface to the
1616 * clients.
1617 */
1618 invoke_sc_cb(primary);
1619 }
1620
1621 return ret;
1622}
1623EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present);
1624
1625void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,1591void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
1626 void (*chn_rescind_cb)(struct vmbus_channel *))1592 void (*chn_rescind_cb)(struct vmbus_channel *))
1627{1593{
drivers/hv/connection.c+94−7
@@ -19,6 +19,8 @@ · 18 unmodified lines
19#include <linux/vmalloc.h>19#include <linux/vmalloc.h>
20#include <linux/hyperv.h>20#include <linux/hyperv.h>
21#include <linux/export.h>21#include <linux/export.h>
22#include <linux/io.h>
23#include <linux/set_memory.h>
22#include <asm/mshyperv.h>24#include <asm/mshyperv.h>
23 25
24#include "hyperv_vmbus.h"26#include "hyperv_vmbus.h"
@@ -102,8 +104,9 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version) · 77 unmodified lines
102 vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID;104 vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID;
103 }105 }
104 106
105 msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);107 msg->monitor_page1 = vmbus_connection.monitor_pages_pa[0];
106 msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);108 msg->monitor_page2 = vmbus_connection.monitor_pages_pa[1];
109
107 msg->target_vcpu = hv_cpu_number_to_vp_number(VMBUS_CONNECT_CPU);110 msg->target_vcpu = hv_cpu_number_to_vp_number(VMBUS_CONNECT_CPU);
108 111
109 /*112 /*
@@ -216,6 +219,65 @@ int vmbus_connect(void) · 106 unmodified lines
216 goto cleanup;219 goto cleanup;
217 }220 }
218 221
222 vmbus_connection.monitor_pages_original[0]
223 = vmbus_connection.monitor_pages[0];
224 vmbus_connection.monitor_pages_original[1]
225 = vmbus_connection.monitor_pages[1];
226 vmbus_connection.monitor_pages_pa[0]
227 = virt_to_phys(vmbus_connection.monitor_pages[0]);
228 vmbus_connection.monitor_pages_pa[1]
229 = virt_to_phys(vmbus_connection.monitor_pages[1]);
230
231 if (hv_is_isolation_supported()) {
232 ret = set_memory_decrypted((unsigned long)
233 vmbus_connection.monitor_pages[0],
234 1);
235 ret |= set_memory_decrypted((unsigned long)
236 vmbus_connection.monitor_pages[1],
237 1);
238 if (ret)
239 goto cleanup;
240
241 /*
242 * Isolation VM with AMD SNP needs to access monitor page via
243 * address space above shared gpa boundary.
244 */
245 if (hv_isolation_type_snp()) {
246 vmbus_connection.monitor_pages_pa[0] +=
247 ms_hyperv.shared_gpa_boundary;
248 vmbus_connection.monitor_pages_pa[1] +=
249 ms_hyperv.shared_gpa_boundary;
250
251 vmbus_connection.monitor_pages[0]
252 = memremap(vmbus_connection.monitor_pages_pa[0],
253 HV_HYP_PAGE_SIZE,
254 MEMREMAP_WB);
255 if (!vmbus_connection.monitor_pages[0]) {
256 ret = -ENOMEM;
257 goto cleanup;
258 }
259
260 vmbus_connection.monitor_pages[1]
261 = memremap(vmbus_connection.monitor_pages_pa[1],
262 HV_HYP_PAGE_SIZE,
263 MEMREMAP_WB);
264 if (!vmbus_connection.monitor_pages[1]) {
265 ret = -ENOMEM;
266 goto cleanup;
267 }
268 }
269
270 /*
271 * Set memory host visibility hvcall smears memory
272 * and so zero monitor pages here.
273 */
274 memset(vmbus_connection.monitor_pages[0], 0x00,
275 HV_HYP_PAGE_SIZE);
276 memset(vmbus_connection.monitor_pages[1], 0x00,
277 HV_HYP_PAGE_SIZE);
278
279 }
280
219 msginfo = kzalloc(sizeof(*msginfo) +281 msginfo = kzalloc(sizeof(*msginfo) +
220 sizeof(struct vmbus_channel_initiate_contact),282 sizeof(struct vmbus_channel_initiate_contact),
221 GFP_KERNEL);283 GFP_KERNEL);
@@ -303,10 +365,31 @@ void vmbus_disconnect(void) · 81 unmodified lines
303 vmbus_connection.int_page = NULL;365 vmbus_connection.int_page = NULL;
304 }366 }
305 367
306 hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]);368 if (hv_is_isolation_supported()) {
307 hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]);369 /*
308 vmbus_connection.monitor_pages[0] = NULL;370 * memunmap() checks input address is ioremap address or not
309 vmbus_connection.monitor_pages[1] = NULL;371 * inside. It doesn't unmap any thing in the non-SNP CVM and
372 * so not check CVM type here.
373 */
374 memunmap(vmbus_connection.monitor_pages[0]);
375 memunmap(vmbus_connection.monitor_pages[1]);
376
377 set_memory_encrypted((unsigned long)
378 vmbus_connection.monitor_pages_original[0],
379 1);
380 set_memory_encrypted((unsigned long)
381 vmbus_connection.monitor_pages_original[1],
382 1);
383 }
384
385 hv_free_hyperv_page((unsigned long)
386 vmbus_connection.monitor_pages_original[0]);
387 hv_free_hyperv_page((unsigned long)
388 vmbus_connection.monitor_pages_original[1]);
389 vmbus_connection.monitor_pages_original[0] =
390 vmbus_connection.monitor_pages[0] = NULL;
391 vmbus_connection.monitor_pages_original[1] =
392 vmbus_connection.monitor_pages[1] = NULL;
310}393}
311 394
312/*395/*
@@ -447,6 +530,10 @@ void vmbus_set_event(struct vmbus_channel *channel) · 134 unmodified lines
447 530
448 ++channel->sig_events;531 ++channel->sig_events;
449 532
450 hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);533 if (hv_isolation_type_snp())
534 hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event,
535 NULL, sizeof(channel->sig_event));
536 else
537 hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
451}538}
452EXPORT_SYMBOL_GPL(vmbus_set_event);539EXPORT_SYMBOL_GPL(vmbus_set_event);
drivers/hv/hv.c+65−17
@@ -8,6 +8,7 @@ · 7 unmodified lines
8 */8 */
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 10
11#include <linux/io.h>
11#include <linux/kernel.h>12#include <linux/kernel.h>
12#include <linux/mm.h>13#include <linux/mm.h>
13#include <linux/slab.h>14#include <linux/slab.h>
@@ -97,7 +98,13 @@ int hv_post_message(union hv_connection_id connection_id, · 83 unmodified lines
97 aligned_msg->payload_size = payload_size;98 aligned_msg->payload_size = payload_size;
98 memcpy((void *)aligned_msg->payload, payload, payload_size);99 memcpy((void *)aligned_msg->payload, payload, payload_size);
99 100
100 status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);101 if (hv_isolation_type_snp())
102 status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE,
103 (void *)aligned_msg, NULL,
104 sizeof(*aligned_msg));
105 else
106 status = hv_do_hypercall(HVCALL_POST_MESSAGE,
107 aligned_msg, NULL);
101 108
102 /* Preemption must remain disabled until after the hypercall109 /* Preemption must remain disabled until after the hypercall
103 * so some other thread can't get scheduled onto this cpu and110 * so some other thread can't get scheduled onto this cpu and
@@ -136,17 +143,24 @@ int hv_synic_alloc(void) · 32 unmodified lines
136 tasklet_init(&hv_cpu->msg_dpc,143 tasklet_init(&hv_cpu->msg_dpc,
137 vmbus_on_msg_dpc, (unsigned long) hv_cpu);144 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
138 145
139 hv_cpu->synic_message_page =146 /*
140 (void *)get_zeroed_page(GFP_ATOMIC);147 * Synic message and event pages are allocated by paravisor.
141 if (hv_cpu->synic_message_page == NULL) {148 * Skip these pages allocation here.
142 pr_err("Unable to allocate SYNIC message page\n");149 */
143 goto err;150 if (!hv_isolation_type_snp()) {
144 }151 hv_cpu->synic_message_page =
152 (void *)get_zeroed_page(GFP_ATOMIC);
153 if (hv_cpu->synic_message_page == NULL) {
154 pr_err("Unable to allocate SYNIC message page\n");
155 goto err;
156 }
145 157
146 hv_cpu->synic_event_page = (void *)get_zeroed_page(GFP_ATOMIC);158 hv_cpu->synic_event_page =
147 if (hv_cpu->synic_event_page == NULL) {159 (void *)get_zeroed_page(GFP_ATOMIC);
148 pr_err("Unable to allocate SYNIC event page\n");160 if (hv_cpu->synic_event_page == NULL) {
149 goto err;161 pr_err("Unable to allocate SYNIC event page\n");
162 goto err;
163 }
150 }164 }
151 165
152 hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC);166 hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -201,16 +215,35 @@ void hv_synic_enable_regs(unsigned int cpu) · 48 unmodified lines
201 /* Setup the Synic's message page */215 /* Setup the Synic's message page */
202 simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);216 simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
203 simp.simp_enabled = 1;217 simp.simp_enabled = 1;
204 simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)218
205 >> HV_HYP_PAGE_SHIFT;219 if (hv_isolation_type_snp()) {
220 hv_cpu->synic_message_page
221 = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
222 HV_HYP_PAGE_SIZE, MEMREMAP_WB);
223 if (!hv_cpu->synic_message_page)
224 pr_err("Fail to map syinc message page.\n");
225 } else {
226 simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)
227 >> HV_HYP_PAGE_SHIFT;
228 }
206 229
207 hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);230 hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
208 231
209 /* Setup the Synic's event page */232 /* Setup the Synic's event page */
210 siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);233 siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
211 siefp.siefp_enabled = 1;234 siefp.siefp_enabled = 1;
212 siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)235
213 >> HV_HYP_PAGE_SHIFT;236 if (hv_isolation_type_snp()) {
237 hv_cpu->synic_event_page =
238 memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
239 HV_HYP_PAGE_SIZE, MEMREMAP_WB);
240
241 if (!hv_cpu->synic_event_page)
242 pr_err("Fail to map syinc event page.\n");
243 } else {
244 siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)
245 >> HV_HYP_PAGE_SHIFT;
246 }
214 247
215 hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);248 hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
216 249
@@ -257,6 +290,8 @@ int hv_synic_init(unsigned int cpu) · 40 unmodified lines
257 */290 */
258void hv_synic_disable_regs(unsigned int cpu)291void hv_synic_disable_regs(unsigned int cpu)
259{292{
293 struct hv_per_cpu_context *hv_cpu
294 = per_cpu_ptr(hv_context.cpu_context, cpu);
260 union hv_synic_sint shared_sint;295 union hv_synic_sint shared_sint;
261 union hv_synic_simp simp;296 union hv_synic_simp simp;
262 union hv_synic_siefp siefp;297 union hv_synic_siefp siefp;
@@ -273,14 +308,27 @@ void hv_synic_disable_regs(unsigned int cpu) · 10 unmodified lines
273 shared_sint.as_uint64);308 shared_sint.as_uint64);
274 309
275 simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);310 simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
311 /*
312 * In Isolation VM, sim and sief pages are allocated by
313 * paravisor. These pages also will be used by kdump
314 * kernel. So just reset enable bit here and keep page
315 * addresses.
316 */
276 simp.simp_enabled = 0;317 simp.simp_enabled = 0;
277 simp.base_simp_gpa = 0;318 if (hv_isolation_type_snp())
319 memunmap(hv_cpu->synic_message_page);
320 else
321 simp.base_simp_gpa = 0;
278 322
279 hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);323 hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
280 324
281 siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);325 siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
282 siefp.siefp_enabled = 0;326 siefp.siefp_enabled = 0;
283 siefp.base_siefp_gpa = 0;327
328 if (hv_isolation_type_snp())
329 memunmap(hv_cpu->synic_event_page);
330 else
331 siefp.base_siefp_gpa = 0;
284 332
285 hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);333 hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
286 334
drivers/hv/hv_common.c+12−0
@@ -249,6 +249,12 @@ bool __weak hv_is_isolation_supported(void) · 248 unmodified lines
249}249}
250EXPORT_SYMBOL_GPL(hv_is_isolation_supported);250EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
251 251
252bool __weak hv_isolation_type_snp(void)
253{
254 return false;
255}
256EXPORT_SYMBOL_GPL(hv_isolation_type_snp);
257
252void __weak hv_setup_vmbus_handler(void (*handler)(void))258void __weak hv_setup_vmbus_handler(void (*handler)(void))
253{259{
254}260}
@@ -283,3 +289,9 @@ void __weak hyperv_cleanup(void) · 28 unmodified lines
283{289{
284}290}
285EXPORT_SYMBOL_GPL(hyperv_cleanup);291EXPORT_SYMBOL_GPL(hyperv_cleanup);
292
293u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
294{
295 return HV_STATUS_INVALID_PARAMETER;
296}
297EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);
drivers/hv/hyperv_vmbus.h+2−0
@@ -241,6 +241,8 @@ struct vmbus_connection { · 240 unmodified lines
241 * is child->parent notification241 * is child->parent notification
242 */242 */
243 struct hv_monitor_page *monitor_pages[2];243 struct hv_monitor_page *monitor_pages[2];
244 void *monitor_pages_original[2];
245 phys_addr_t monitor_pages_pa[2];
244 struct list_head chn_msg_list;246 struct list_head chn_msg_list;
245 spinlock_t channelmsg_lock;247 spinlock_t channelmsg_lock;
246 248
drivers/hv/ring_buffer.c+44−13
@@ -17,6 +17,8 @@ · 16 unmodified lines
17#include <linux/vmalloc.h>17#include <linux/vmalloc.h>
18#include <linux/slab.h>18#include <linux/slab.h>
19#include <linux/prefetch.h>19#include <linux/prefetch.h>
20#include <linux/io.h>
21#include <asm/mshyperv.h>
20 22
21#include "hyperv_vmbus.h"23#include "hyperv_vmbus.h"
22 24
@@ -183,8 +185,10 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *channel) · 160 unmodified lines
183int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,185int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
184 struct page *pages, u32 page_cnt, u32 max_pkt_size)186 struct page *pages, u32 page_cnt, u32 max_pkt_size)
185{187{
186 int i;
187 struct page **pages_wraparound;188 struct page **pages_wraparound;
189 unsigned long *pfns_wraparound;
190 u64 pfn;
191 int i;
188 192
189 BUILD_BUG_ON((sizeof(struct hv_ring_buffer) != PAGE_SIZE));193 BUILD_BUG_ON((sizeof(struct hv_ring_buffer) != PAGE_SIZE));
190 194
@@ -192,23 +196,50 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, · 1 unmodified line
192 * First page holds struct hv_ring_buffer, do wraparound mapping for196 * First page holds struct hv_ring_buffer, do wraparound mapping for
193 * the rest.197 * the rest.
194 */198 */
195 pages_wraparound = kcalloc(page_cnt * 2 - 1, sizeof(struct page *),199 if (hv_isolation_type_snp()) {
196 GFP_KERNEL);200 pfn = page_to_pfn(pages) +
197 if (!pages_wraparound)201 PFN_DOWN(ms_hyperv.shared_gpa_boundary);
198 return -ENOMEM;202
203 pfns_wraparound = kcalloc(page_cnt * 2 - 1,
204 sizeof(unsigned long), GFP_KERNEL);
205 if (!pfns_wraparound)
206 return -ENOMEM;
199 207
200 pages_wraparound[0] = pages;208 pfns_wraparound[0] = pfn;
201 for (i = 0; i < 2 * (page_cnt - 1); i++)209 for (i = 0; i < 2 * (page_cnt - 1); i++)
202 pages_wraparound[i + 1] = &pages[i % (page_cnt - 1) + 1];210 pfns_wraparound[i + 1] = pfn + i % (page_cnt - 1) + 1;
203 211
204 ring_info->ring_buffer = (struct hv_ring_buffer *)212 ring_info->ring_buffer = (struct hv_ring_buffer *)
205 vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP, PAGE_KERNEL);213 vmap_pfn(pfns_wraparound, page_cnt * 2 - 1,
214 PAGE_KERNEL);
215 kfree(pfns_wraparound);
206 216
207 kfree(pages_wraparound);217 if (!ring_info->ring_buffer)
218 return -ENOMEM;
208 219
220 /* Zero ring buffer after setting memory host visibility. */
221 memset(ring_info->ring_buffer, 0x00, PAGE_SIZE * page_cnt);
222 } else {
223 pages_wraparound = kcalloc(page_cnt * 2 - 1,
224 sizeof(struct page *),
225 GFP_KERNEL);
226 if (!pages_wraparound)
227 return -ENOMEM;
228
229 pages_wraparound[0] = pages;
230 for (i = 0; i < 2 * (page_cnt - 1); i++)
231 pages_wraparound[i + 1] =
232 &pages[i % (page_cnt - 1) + 1];
233
234 ring_info->ring_buffer = (struct hv_ring_buffer *)
235 vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP,
236 PAGE_KERNEL);
237
238 kfree(pages_wraparound);
239 if (!ring_info->ring_buffer)
240 return -ENOMEM;
241 }
209 242
210 if (!ring_info->ring_buffer)
211 return -ENOMEM;
212 243
213 ring_info->ring_buffer->read_index =244 ring_info->ring_buffer->read_index =
214 ring_info->ring_buffer->write_index = 0;245 ring_info->ring_buffer->write_index = 0;
drivers/net/hyperv/hyperv_net.h+3−2
@@ -1075,14 +1075,15 @@ struct netvsc_device { · 1074 unmodified lines
1075 /* Receive buffer allocated by us but manages by NetVSP */1075 /* Receive buffer allocated by us but manages by NetVSP */
1076 void *recv_buf;1076 void *recv_buf;
1077 u32 recv_buf_size; /* allocated bytes */1077 u32 recv_buf_size; /* allocated bytes */
1078 u32 recv_buf_gpadl_handle;1078 struct vmbus_gpadl recv_buf_gpadl_handle;
1079 u32 recv_section_cnt;1079 u32 recv_section_cnt;
1080 u32 recv_section_size;1080 u32 recv_section_size;
1081 u32 recv_completion_cnt;1081 u32 recv_completion_cnt;
1082 1082
1083 /* Send buffer allocated by us */1083 /* Send buffer allocated by us */
1084 void *send_buf;1084 void *send_buf;
1085 u32 send_buf_gpadl_handle;1085 u32 send_buf_size;
1086 struct vmbus_gpadl send_buf_gpadl_handle;
1086 u32 send_section_cnt;1087 u32 send_section_cnt;
1087 u32 send_section_size;1088 u32 send_section_size;
1088 unsigned long *send_section_map;1089 unsigned long *send_section_map;
drivers/net/hyperv/netvsc.c+7−8
@@ -278,9 +278,9 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device, · 277 unmodified lines
278{278{
279 int ret;279 int ret;
280 280
281 if (net_device->recv_buf_gpadl_handle) {281 if (net_device->recv_buf_gpadl_handle.gpadl_handle) {
282 ret = vmbus_teardown_gpadl(device->channel,282 ret = vmbus_teardown_gpadl(device->channel,
283 net_device->recv_buf_gpadl_handle);283 &net_device->recv_buf_gpadl_handle);
284 284
285 /* If we failed here, we might as well return and have a leak285 /* If we failed here, we might as well return and have a leak
286 * rather than continue and a bugchk286 * rather than continue and a bugchk
@@ -290,7 +290,6 @@ static void netvsc_teardown_recv_gpadl(struct hv_device *device, · 3 unmodified lines
290 "unable to teardown receive buffer's gpadl\n");290 "unable to teardown receive buffer's gpadl\n");
291 return;291 return;
292 }292 }
293 net_device->recv_buf_gpadl_handle = 0;
294 }293 }
295}294}
296 295
@@ -300,9 +299,9 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device, · 3 unmodified lines
300{299{
301 int ret;300 int ret;
302 301
303 if (net_device->send_buf_gpadl_handle) {302 if (net_device->send_buf_gpadl_handle.gpadl_handle) {
304 ret = vmbus_teardown_gpadl(device->channel,303 ret = vmbus_teardown_gpadl(device->channel,
305 net_device->send_buf_gpadl_handle);304 &net_device->send_buf_gpadl_handle);
306 305
307 /* If we failed here, we might as well return and have a leak306 /* If we failed here, we might as well return and have a leak
308 * rather than continue and a bugchk307 * rather than continue and a bugchk
@@ -312,7 +311,6 @@ static void netvsc_teardown_send_gpadl(struct hv_device *device, · 3 unmodified lines
312 "unable to teardown send buffer's gpadl\n");311 "unable to teardown send buffer's gpadl\n");
313 return;312 return;
314 }313 }
315 net_device->send_buf_gpadl_handle = 0;
316 }314 }
317}315}
318 316
@@ -380,7 +378,7 @@ static int netvsc_init_buf(struct hv_device *device, · 61 unmodified lines
380 memset(init_packet, 0, sizeof(struct nvsp_message));378 memset(init_packet, 0, sizeof(struct nvsp_message));
381 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;379 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
382 init_packet->msg.v1_msg.send_recv_buf.380 init_packet->msg.v1_msg.send_recv_buf.
383 gpadl_handle = net_device->recv_buf_gpadl_handle;381 gpadl_handle = net_device->recv_buf_gpadl_handle.gpadl_handle;
384 init_packet->msg.v1_msg.382 init_packet->msg.v1_msg.
385 send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;383 send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
386 384
@@ -463,6 +461,7 @@ static int netvsc_init_buf(struct hv_device *device, · 76 unmodified lines
463 ret = -ENOMEM;461 ret = -ENOMEM;
464 goto cleanup;462 goto cleanup;
465 }463 }
464 net_device->send_buf_size = buf_size;
466 465
467 /* Establish the gpadl handle for this buffer on this466 /* Establish the gpadl handle for this buffer on this
468 * channel. Note: This call uses the vmbus connection rather467 * channel. Note: This call uses the vmbus connection rather
@@ -482,7 +481,7 @@ static int netvsc_init_buf(struct hv_device *device, · 13 unmodified lines
482 memset(init_packet, 0, sizeof(struct nvsp_message));481 memset(init_packet, 0, sizeof(struct nvsp_message));
483 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;482 init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF;
484 init_packet->msg.v1_msg.send_send_buf.gpadl_handle =483 init_packet->msg.v1_msg.send_send_buf.gpadl_handle =
485 net_device->send_buf_gpadl_handle;484 net_device->send_buf_gpadl_handle.gpadl_handle;
486 init_packet->msg.v1_msg.send_send_buf.id = NETVSC_SEND_BUFFER_ID;485 init_packet->msg.v1_msg.send_send_buf.id = NETVSC_SEND_BUFFER_ID;
487 486
488 trace_nvsp_send(ndev, init_packet);487 trace_nvsp_send(ndev, init_packet);
drivers/uio/uio_hv_generic.c+8−10
@@ -58,11 +58,11 @@ struct hv_uio_private_data { · 57 unmodified lines
58 atomic_t refcnt;58 atomic_t refcnt;
59 59
60 void *recv_buf;60 void *recv_buf;
61 u32 recv_gpadl;61 struct vmbus_gpadl recv_gpadl;
62 char recv_name[32]; /* "recv_4294967295" */62 char recv_name[32]; /* "recv_4294967295" */
63 63
64 void *send_buf;64 void *send_buf;
65 u32 send_gpadl;65 struct vmbus_gpadl send_gpadl;
66 char send_name[32];66 char send_name[32];
67};67};
68 68
@@ -179,15 +179,13 @@ hv_uio_new_channel(struct vmbus_channel *new_sc) · 110 unmodified lines
179static void179static void
180hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)180hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
181{181{
182 if (pdata->send_gpadl) {182 if (pdata->send_gpadl.gpadl_handle) {
183 vmbus_teardown_gpadl(dev->channel, pdata->send_gpadl);183 vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
184 pdata->send_gpadl = 0;
185 vfree(pdata->send_buf);184 vfree(pdata->send_buf);
186 }185 }
187 186
188 if (pdata->recv_gpadl) {187 if (pdata->recv_gpadl.gpadl_handle) {
189 vmbus_teardown_gpadl(dev->channel, pdata->recv_gpadl);188 vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
190 pdata->recv_gpadl = 0;
191 vfree(pdata->recv_buf);189 vfree(pdata->recv_buf);
192 }190 }
193}191}
@@ -303,7 +301,7 @@ hv_uio_probe(struct hv_device *dev, · 109 unmodified lines
303 301
304 /* put Global Physical Address Label in name */302 /* put Global Physical Address Label in name */
305 snprintf(pdata->recv_name, sizeof(pdata->recv_name),303 snprintf(pdata->recv_name, sizeof(pdata->recv_name),
306 "recv:%u", pdata->recv_gpadl);304 "recv:%u", pdata->recv_gpadl.gpadl_handle);
307 pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;305 pdata->info.mem[RECV_BUF_MAP].name = pdata->recv_name;
308 pdata->info.mem[RECV_BUF_MAP].addr306 pdata->info.mem[RECV_BUF_MAP].addr
309 = (uintptr_t)pdata->recv_buf;307 = (uintptr_t)pdata->recv_buf;
@@ -324,7 +322,7 @@ hv_uio_probe(struct hv_device *dev, · 14 unmodified lines
324 }322 }
325 323
326 snprintf(pdata->send_name, sizeof(pdata->send_name),324 snprintf(pdata->send_name, sizeof(pdata->send_name),
327 "send:%u", pdata->send_gpadl);325 "send:%u", pdata->send_gpadl.gpadl_handle);
328 pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name;326 pdata->info.mem[SEND_BUF_MAP].name = pdata->send_name;
329 pdata->info.mem[SEND_BUF_MAP].addr327 pdata->info.mem[SEND_BUF_MAP].addr
330 = (uintptr_t)pdata->send_buf;328 = (uintptr_t)pdata->send_buf;
include/asm-generic/hyperv-tlfs.h+1−0
@@ -158,6 +158,7 @@ struct ms_hyperv_tsc_page { · 157 unmodified lines
158#define HVCALL_RETARGET_INTERRUPT 0x007e158#define HVCALL_RETARGET_INTERRUPT 0x007e
159#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af159#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
160#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0160#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
161#define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY 0x00db
161 162
162/* Extended hypercalls */163/* Extended hypercalls */
163#define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001164#define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001
include/asm-generic/mshyperv.h+19−1
@@ -35,7 +35,17 @@ struct ms_hyperv_info { · 34 unmodified lines
35 u32 max_vp_index;35 u32 max_vp_index;
36 u32 max_lp_index;36 u32 max_lp_index;
37 u32 isolation_config_a;37 u32 isolation_config_a;
38 u32 isolation_config_b;38 union {
39 u32 isolation_config_b;
40 struct {
41 u32 cvm_type : 4;
42 u32 reserved1 : 1;
43 u32 shared_gpa_boundary_active : 1;
44 u32 shared_gpa_boundary_bits : 6;
45 u32 reserved2 : 20;
46 };
47 };
48 u64 shared_gpa_boundary;
39};49};
40extern struct ms_hyperv_info ms_hyperv;50extern struct ms_hyperv_info ms_hyperv;
41 51
@@ -44,6 +54,7 @@ extern void __percpu **hyperv_pcpu_output_arg; · 2 unmodified lines
44 54
45extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);55extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
46extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);56extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
57extern bool hv_isolation_type_snp(void);
47 58
48/* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */59/* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */
49static inline int hv_result(u64 status)60static inline int hv_result(u64 status)
@@ -254,12 +265,19 @@ bool hv_is_hyperv_initialized(void); · 204 unmodified lines
254bool hv_is_hibernation_supported(void);265bool hv_is_hibernation_supported(void);
255enum hv_isolation_type hv_get_isolation_type(void);266enum hv_isolation_type hv_get_isolation_type(void);
256bool hv_is_isolation_supported(void);267bool hv_is_isolation_supported(void);
268bool hv_isolation_type_snp(void);
269u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
257void hyperv_cleanup(void);270void hyperv_cleanup(void);
258bool hv_query_ext_cap(u64 cap_query);271bool hv_query_ext_cap(u64 cap_query);
259#else /* CONFIG_HYPERV */272#else /* CONFIG_HYPERV */
260static inline bool hv_is_hyperv_initialized(void) { return false; }273static inline bool hv_is_hyperv_initialized(void) { return false; }
261static inline bool hv_is_hibernation_supported(void) { return false; }274static inline bool hv_is_hibernation_supported(void) { return false; }
262static inline void hyperv_cleanup(void) {}275static inline void hyperv_cleanup(void) {}
276static inline bool hv_is_isolation_supported(void) { return false; }
277static inline enum hv_isolation_type hv_get_isolation_type(void)
278{
279 return HV_ISOLATION_TYPE_NONE;
280}
263#endif /* CONFIG_HYPERV */281#endif /* CONFIG_HYPERV */
264 282
265#endif283#endif
include/linux/hyperv.h+9−16
@@ -803,6 +803,12 @@ struct vmbus_device { · 802 unmodified lines
803 803
804#define VMBUS_DEFAULT_MAX_PKT_SIZE 4096804#define VMBUS_DEFAULT_MAX_PKT_SIZE 4096
805 805
806struct vmbus_gpadl {
807 u32 gpadl_handle;
808 u32 size;
809 void *buffer;
810};
811
806struct vmbus_channel {812struct vmbus_channel {
807 struct list_head listentry;813 struct list_head listentry;
808 814
@@ -822,7 +828,7 @@ struct vmbus_channel { · 13 unmodified lines
822 bool rescind_ref; /* got rescind msg, got channel reference */828 bool rescind_ref; /* got rescind msg, got channel reference */
823 struct completion rescind_event;829 struct completion rescind_event;
824 830
825 u32 ringbuffer_gpadlhandle;831 struct vmbus_gpadl ringbuffer_gpadlhandle;
826 832
827 /* Allocated memory for ring buffer */833 /* Allocated memory for ring buffer */
828 struct page *ringbuffer_page;834 struct page *ringbuffer_page;
@@ -1100,19 +1106,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, · 271 unmodified lines
1100void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,1106void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
1101 void (*chn_rescind_cb)(struct vmbus_channel *));1107 void (*chn_rescind_cb)(struct vmbus_channel *));
1102 1108
1103/*
1104 * Check if sub-channels have already been offerred. This API will be useful
1105 * when the driver is unloaded after establishing sub-channels. In this case,
1106 * when the driver is re-loaded, the driver would have to check if the
1107 * subchannels have already been established before attempting to request
1108 * the creation of sub-channels.
1109 * This function returns TRUE to indicate that subchannels have already been
1110 * created.
1111 * This function should be invoked after setting the callback function for
1112 * sub-channel creation.
1113 */
1114bool vmbus_are_subchannels_present(struct vmbus_channel *primary);
1115
1116/* The format must be the same as struct vmdata_gpa_direct */1109/* The format must be the same as struct vmdata_gpa_direct */
1117struct vmbus_channel_packet_page_buffer {1110struct vmbus_channel_packet_page_buffer {
1118 u16 type;1111 u16 type;
@@ -1192,10 +1185,10 @@ extern int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, · 73 unmodified lines
1192extern int vmbus_establish_gpadl(struct vmbus_channel *channel,1185extern int vmbus_establish_gpadl(struct vmbus_channel *channel,
1193 void *kbuffer,1186 void *kbuffer,
1194 u32 size,1187 u32 size,
1195 u32 *gpadl_handle);1188 struct vmbus_gpadl *gpadl);
1196 1189
1197extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,1190extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
1198 u32 gpadl_handle);1191 struct vmbus_gpadl *gpadl);
1199 1192
1200void vmbus_reset_channel_cb(struct vmbus_channel *channel);1193void vmbus_reset_channel_cb(struct vmbus_channel *channel);
1201 1194