hv_proc.c (5438B)
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/types.h> 3#include <linux/vmalloc.h> 4#include <linux/mm.h> 5#include <linux/clockchips.h> 6#include <linux/acpi.h> 7#include <linux/hyperv.h> 8#include <linux/slab.h> 9#include <linux/cpuhotplug.h> 10#include <linux/minmax.h> 11#include <asm/hypervisor.h> 12#include <asm/mshyperv.h> 13#include <asm/apic.h> 14 15#include <asm/trace/hyperv.h> 16 17/* 18 * See struct hv_deposit_memory. The first u64 is partition ID, the rest 19 * are GPAs. 20 */ 21#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) 22 23/* Deposits exact number of pages. Must be called with interrupts enabled. */ 24int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) 25{ 26 struct page **pages, *page; 27 int *counts; 28 int num_allocations; 29 int i, j, page_count; 30 int order; 31 u64 status; 32 int ret; 33 u64 base_pfn; 34 struct hv_deposit_memory *input_page; 35 unsigned long flags; 36 37 if (num_pages > HV_DEPOSIT_MAX) 38 return -E2BIG; 39 if (!num_pages) 40 return 0; 41 42 /* One buffer for page pointers and counts */ 43 page = alloc_page(GFP_KERNEL); 44 if (!page) 45 return -ENOMEM; 46 pages = page_address(page); 47 48 counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); 49 if (!counts) { 50 free_page((unsigned long)pages); 51 return -ENOMEM; 52 } 53 54 /* Allocate all the pages before disabling interrupts */ 55 i = 0; 56 57 while (num_pages) { 58 /* Find highest order we can actually allocate */ 59 order = 31 - __builtin_clz(num_pages); 60 61 while (1) { 62 pages[i] = alloc_pages_node(node, GFP_KERNEL, order); 63 if (pages[i]) 64 break; 65 if (!order) { 66 ret = -ENOMEM; 67 num_allocations = i; 68 goto err_free_allocations; 69 } 70 --order; 71 } 72 73 split_page(pages[i], order); 74 counts[i] = 1 << order; 75 num_pages -= counts[i]; 76 i++; 77 } 78 num_allocations = i; 79 80 local_irq_save(flags); 81 82 input_page = *this_cpu_ptr(hyperv_pcpu_input_arg); 83 84 input_page->partition_id = partition_id; 85 86 /* Populate gpa_page_list - these will fit on the input page */ 87 for (i = 0, page_count = 0; i < num_allocations; ++i) { 88 base_pfn = page_to_pfn(pages[i]); 89 for (j = 0; j < counts[i]; ++j, ++page_count) 90 input_page->gpa_page_list[page_count] = base_pfn + j; 91 } 92 status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, 93 page_count, 0, input_page, NULL); 94 local_irq_restore(flags); 95 if (!hv_result_success(status)) { 96 pr_err("Failed to deposit pages: %lld\n", status); 97 ret = hv_result(status); 98 goto err_free_allocations; 99 } 100 101 ret = 0; 102 goto free_buf; 103 104err_free_allocations: 105 for (i = 0; i < num_allocations; ++i) { 106 base_pfn = page_to_pfn(pages[i]); 107 for (j = 0; j < counts[i]; ++j) 108 __free_page(pfn_to_page(base_pfn + j)); 109 } 110 111free_buf: 112 free_page((unsigned long)pages); 113 kfree(counts); 114 return ret; 115} 116 117int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) 118{ 119 struct hv_add_logical_processor_in *input; 120 struct hv_add_logical_processor_out *output; 121 u64 status; 122 unsigned long flags; 123 int ret = HV_STATUS_SUCCESS; 124 int pxm = node_to_pxm(node); 125 126 /* 127 * When adding a logical processor, the hypervisor may return 128 * HV_STATUS_INSUFFICIENT_MEMORY. When that happens, we deposit more 129 * pages and retry. 130 */ 131 do { 132 local_irq_save(flags); 133 134 input = *this_cpu_ptr(hyperv_pcpu_input_arg); 135 /* We don't do anything with the output right now */ 136 output = *this_cpu_ptr(hyperv_pcpu_output_arg); 137 138 input->lp_index = lp_index; 139 input->apic_id = apic_id; 140 input->flags = 0; 141 input->proximity_domain_info.domain_id = pxm; 142 input->proximity_domain_info.flags.reserved = 0; 143 input->proximity_domain_info.flags.proximity_info_valid = 1; 144 input->proximity_domain_info.flags.proximity_preferred = 1; 145 status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, 146 input, output); 147 local_irq_restore(flags); 148 149 if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { 150 if (!hv_result_success(status)) { 151 pr_err("%s: cpu %u apic ID %u, %lld\n", __func__, 152 lp_index, apic_id, status); 153 ret = hv_result(status); 154 } 155 break; 156 } 157 ret = hv_call_deposit_pages(node, hv_current_partition_id, 1); 158 } while (!ret); 159 160 return ret; 161} 162 163int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) 164{ 165 struct hv_create_vp *input; 166 u64 status; 167 unsigned long irq_flags; 168 int ret = HV_STATUS_SUCCESS; 169 int pxm = node_to_pxm(node); 170 171 /* Root VPs don't seem to need pages deposited */ 172 if (partition_id != hv_current_partition_id) { 173 /* The value 90 is empirically determined. It may change. */ 174 ret = hv_call_deposit_pages(node, partition_id, 90); 175 if (ret) 176 return ret; 177 } 178 179 do { 180 local_irq_save(irq_flags); 181 182 input = *this_cpu_ptr(hyperv_pcpu_input_arg); 183 184 input->partition_id = partition_id; 185 input->vp_index = vp_index; 186 input->flags = flags; 187 input->subnode_type = HvSubnodeAny; 188 if (node != NUMA_NO_NODE) { 189 input->proximity_domain_info.domain_id = pxm; 190 input->proximity_domain_info.flags.reserved = 0; 191 input->proximity_domain_info.flags.proximity_info_valid = 1; 192 input->proximity_domain_info.flags.proximity_preferred = 1; 193 } else { 194 input->proximity_domain_info.as_uint64 = 0; 195 } 196 status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); 197 local_irq_restore(irq_flags); 198 199 if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { 200 if (!hv_result_success(status)) { 201 pr_err("%s: vcpu %u, lp %u, %lld\n", __func__, 202 vp_index, flags, status); 203 ret = hv_result(status); 204 } 205 break; 206 } 207 ret = hv_call_deposit_pages(node, partition_id, 1); 208 209 } while (!ret); 210 211 return ret; 212} 213