Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Hyper-V nested virtualization code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2018, Microsoft, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Author : Lan Tianyu <Tianyu.Lan@microsoft.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #define pr_fmt(fmt)  "Hyper-V: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <asm/hyperv-tlfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/mshyperv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/tlbflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/trace/hyperv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) int hyperv_flush_guest_mapping(u64 as)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct hv_guest_mapping_flush **flush_pcpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct hv_guest_mapping_flush *flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	u64 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	int ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	if (!hv_hypercall_pg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	flush_pcpu = (struct hv_guest_mapping_flush **)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 		this_cpu_ptr(hyperv_pcpu_input_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	flush = *flush_pcpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (unlikely(!flush)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	flush->address_space = as;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	flush->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 				 flush, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (!(status & HV_HYPERCALL_RESULT_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	trace_hyperv_nested_flush_guest_mapping(as, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) int hyperv_fill_flush_guest_mapping_list(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		struct hv_guest_mapping_flush_list *flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		u64 start_gfn, u64 pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	u64 cur = start_gfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	u64 additional_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	int gpa_n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		 * If flush requests exceed max flush count, go back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		 * flush tlbs without range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		if (gpa_n >= HV_MAX_FLUSH_REP_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		additional_pages = min_t(u64, pages, HV_MAX_FLUSH_PAGES) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		flush->gpa_list[gpa_n].page.additional_pages = additional_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		flush->gpa_list[gpa_n].page.largepage = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		flush->gpa_list[gpa_n].page.basepfn = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		pages -= additional_pages + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		cur += additional_pages + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		gpa_n++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	} while (pages > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	return gpa_n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) int hyperv_flush_guest_mapping_range(u64 as,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		hyperv_fill_flush_list_func fill_flush_list_func, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	struct hv_guest_mapping_flush_list **flush_pcpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	struct hv_guest_mapping_flush_list *flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	u64 status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	int ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	int gpa_n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (!hv_hypercall_pg || !fill_flush_list_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	flush_pcpu = (struct hv_guest_mapping_flush_list **)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		this_cpu_ptr(hyperv_pcpu_input_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	flush = *flush_pcpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (unlikely(!flush)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	flush->address_space = as;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	flush->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	gpa_n = fill_flush_list_func(flush, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (gpa_n < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		goto fault;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	status = hv_do_rep_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				     gpa_n, 0, flush, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (!(status & HV_HYPERCALL_RESULT_MASK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		ret = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fault:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	trace_hyperv_nested_flush_guest_mapping_range(as, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping_range);