hv.c revision 0a46618d58c90f93e8b8e9a18062d1691b70297e
1b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox/* 2b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Copyright (c) 2009, Microsoft Corporation. 3b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * 4b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * This program is free software; you can redistribute it and/or modify it 5b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * under the terms and conditions of the GNU General Public License, 6b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * version 2, as published by the Free Software Foundation. 7b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * 8b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * This program is distributed in the hope it will be useful, but WITHOUT 9b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * more details. 12b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * 13b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * You should have received a copy of the GNU General Public License along with 14b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Place - Suite 330, Boston, MA 02111-1307 USA. 16b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * 17b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Authors: 18b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Haiyang Zhang <haiyangz@microsoft.com> 19b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Hank Janssen <hjanssen@microsoft.com> 20b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * 218de055350fbaa96b6563892c195a60be583faa9cMatthew Wilcox */ 22b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 23fd63e9ceeeae58cfe877c2d49d41c1bf7532303cMatthew Wilcox 24b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include <linux/kernel.h> 25b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include <linux/mm.h> 26b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include <linux/slab.h> 275aff9382ddc8aac6eb0c70ffbb351652d71da69aMatthew Wilcox#include <linux/vmalloc.h> 28b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include "hv_api.h" 29b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include "logging.h" 30b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#include "vmbus_private.h" 31b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 321fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox/* The one and only */ 33b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcoxstruct hv_context hv_context = { 34b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox .synic_initialized = false, 35b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox .hypercall_page = NULL, 36b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox .signal_event_param = NULL, 37b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox .signal_event_buffer = NULL, 38be7b62754e097adc0cb16c25c9ee86ee20de62fbMatthew Wilcox}; 39c3bfe7176c035a0a2c70bc79180fb13a6c57142aMatthew Wilcox 40b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox/* 41b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * query_hypervisor_presence 42b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * - Query the cpuid for presense of windows hypervisor 435d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma */ 44797a796a13df6b84a4791e57306737059b5b2384Hitoshi Mitakestatic int query_hypervisor_presence(void) 45797a796a13df6b84a4791e57306737059b5b2384Hitoshi Mitake{ 46b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int eax; 47b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int ebx; 48b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int ecx; 49b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int edx; 50e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox unsigned int op; 51b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 52b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox eax = 0; 53b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ebx = 0; 54b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ecx = 0; 5558ffacb545f76fc2c65d1fbfa5acf5184a2a09e6Matthew Wilcox edx = 0; 5658ffacb545f76fc2c65d1fbfa5acf5184a2a09e6Matthew Wilcox op = HVCPUID_VERSION_FEATURES; 5758ffacb545f76fc2c65d1fbfa5acf5184a2a09e6Matthew Wilcox cpuid(op, &eax, &ebx, &ecx, &edx); 581fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox 591fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox return ecx & HV_PRESENT_BIT; 601fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox} 611fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox 62b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox/* 63b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * query_hypervisor_info - Get version info of the windows hypervisor 64b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox */ 65b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcoxstatic int query_hypervisor_info(void) 66b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox{ 67b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int eax; 68091b609258b8e01cc45b01a41ca5e496f674d989Matthew Wilcox unsigned int ebx; 69b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int ecx; 70b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int edx; 71b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int max_leaf; 72b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox unsigned int op; 73b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 74b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox /* 751fa6aeadf18aeebd7a217d7a3a933856448375b6Matthew Wilcox * Its assumed that this is called after confirming that Viridian 76b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * is present. Query id and revision. 77b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox */ 78b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox eax = 0; 79b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ebx = 0; 80b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ecx = 0; 81b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox edx = 0; 82b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox op = HVCPUID_VENDOR_MAXFUNCTION; 83e9539f47525ecee05c9f22c3565885f3e9492c52Matthew Wilcox cpuid(op, &eax, &ebx, &ecx, &edx); 84e9539f47525ecee05c9f22c3565885f3e9492c52Matthew Wilcox 85b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox/* DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c", 86b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox (ebx & 0xFF), 87b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ebx >> 8) & 0xFF), 88b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ebx >> 16) & 0xFF), 89b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ebx >> 24) & 0xFF), 90b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox (ecx & 0xFF), 91b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ecx >> 8) & 0xFF), 92b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ecx >> 16) & 0xFF), 93b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((ecx >> 24) & 0xFF), 94b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox (edx & 0xFF), 95b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((edx >> 8) & 0xFF), 96b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((edx >> 16) & 0xFF), 97b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ((edx >> 24) & 0xFF)); 98f8ebf8409abfdaeeb8c847381629a2a8b8e3d816Vishal Verma*/ 99b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox max_leaf = eax; 100b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox/* eax = 0; 101b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ebx = 0; 102b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ecx = 0; 1036ecec74520d8a357726e6c12f99080dbe7b347ddKeith Busch edx = 0; 104b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox op = HVCPUID_INTERFACE; 105b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox cpuid(op, &eax, &ebx, &ecx, &edx); 1065c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox 107c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c", 108c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox (eax & 0xFF), 109e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox ((eax >> 8) & 0xFF), 110c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox ((eax >> 16) & 0xFF), 111c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox ((eax >> 24) & 0xFF)); 112e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox*/ 113e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox 114e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox if (max_leaf >= HVCPUID_VERSION) { 115e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox eax = 0; 116e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox ebx = 0; 117e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox ecx = 0; 118e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox edx = 0; 119e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox op = HVCPUID_VERSION; 120b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox cpuid(op, &eax, &ebx, &ecx, &edx); 121714a7a22884b74862540bc84955274d86b2f6040Matthew Wilcox pr_info("Hyper-V Host OS Build:%d-%d.%d-%d-%d.%d\n", 122714a7a22884b74862540bc84955274d86b2f6040Matthew Wilcox eax, 123714a7a22884b74862540bc84955274d86b2f6040Matthew Wilcox ebx >> 16, 124c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox ebx & 0xFFFF, 125b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox ecx, 126b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox edx >> 24, 127b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox edx & 0xFFFFFF); 128b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox } 129b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox return max_leaf; 130b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox} 131184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox 132184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox/* 133184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox * do_hypercall- Invoke the specified hypercall 134b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox */ 135c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcoxstatic u64 do_hypercall(u64 control, void *input, void *output) 136c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox{ 137b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox#ifdef CONFIG_X86_64 138e6d15f79f997a98b3a69abbc462fc9041cc1a7b4Matthew Wilcox u64 hv_status = 0; 139e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox u64 input_address = (input) ? virt_to_phys(input) : 0; 140b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u64 output_address = (output) ? virt_to_phys(output) : 0; 141b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox volatile void *hypercall_page = hv_context.hypercall_page; 142b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 143b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); 144b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox __asm__ __volatile__("call *%3" : "=a" (hv_status) : 145b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox "c" (control), "d" (input_address), 146b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox "m" (hypercall_page)); 147b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 148c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox return hv_status; 149c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 150e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox#else 151b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 152b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 control_hi = control >> 32; 153b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 control_lo = control & 0xFFFFFFFF; 154b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 hv_status_hi = 1; 155c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox u32 hv_status_lo = 1; 156b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u64 input_address = (input) ? virt_to_phys(input) : 0; 157b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 input_address_hi = input_address >> 32; 158b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 input_address_lo = input_address & 0xFFFFFFFF; 159e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox u64 output_address = (output) ? virt_to_phys(output) : 0; 160b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 output_address_hi = output_address >> 32; 161b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u32 output_address_lo = output_address & 0xFFFFFFFF; 162b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox volatile void *hypercall_page = hv_context.hypercall_page; 163c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 164c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), 165d2d8703481f60d67f49e3177196cbe474b11377cMatthew Wilcox "=a"(hv_status_lo) : "d" (control_hi), 166d2d8703481f60d67f49e3177196cbe474b11377cMatthew Wilcox "a" (control_lo), "b" (input_address_hi), 167d2d8703481f60d67f49e3177196cbe474b11377cMatthew Wilcox "c" (input_address_lo), "D"(output_address_hi), 16800df5cb4eb927078850086f8becc3286a69ea12eMatthew Wilcox "S"(output_address_lo), "m" (hypercall_page)); 169be7b62754e097adc0cb16c25c9ee86ee20de62fbMatthew Wilcox 1705c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox return hv_status_lo | ((u64)hv_status_hi << 32); 171c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox#endif /* !x86_64 */ 172c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox} 173c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 174c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox/* 175c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox * hv_init - Main initialization routine. 176c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox * 177c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox * This routine must be called before any other routines in here are called 1785c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox */ 179c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcoxint hv_init(void) 180c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox{ 181c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox int ret = 0; 182c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox int max_leaf; 183c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox union hv_x64_msr_hypercall_contents hypercall_msr; 1845c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox void *virtaddr = NULL; 185c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 186c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); 187c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox memset(hv_context.synic_message_page, 0, 188c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox sizeof(void *) * MAX_NUM_CPUS); 189c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 1905c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox if (!query_hypervisor_presence()) 191c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox goto Cleanup; 192c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 193184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox max_leaf = query_hypervisor_info(); 194184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox /* HvQueryHypervisorFeatures(maxLeaf); */ 195184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox 196c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox /* 197c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox * We only support running on top of Hyper-V 198b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox */ 199c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); 200e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox 201b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox if (hv_context.guestid != 0) 202c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox goto Cleanup; 203c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 20448e3d39816416b3bf03dee3a796c0c04427c1a31Matthew Wilcox /* Write our OS info */ 205c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); 206859361a228258edf4821d9f5635825033eca78e8Keith Busch hv_context.guestid = HV_LINUX_GUEST_ID; 207859361a228258edf4821d9f5635825033eca78e8Keith Busch 208c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox /* See if the hypercall page is already set */ 209c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 210e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox 211b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox /* 212b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * Allocate the hypercall page memory 213c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox * virtaddr = osd_page_alloc(1); 214b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox */ 215b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); 216c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 217c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox if (!virtaddr) 2183c0cf138d7789feb3f335f6f1d24ad8fc8b3a23fMatthew Wilcox goto Cleanup; 219c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 220e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox hypercall_msr.enable = 1; 221c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 222c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox hypercall_msr.guest_physical_address = vmalloc_to_pfn(virtaddr); 223c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 224c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox 225e85248e516c550382ba33ca325c272a0ca397e44Matthew Wilcox /* Confirm that hypercall page did get setup. */ 226c2f5b65020869215814df03c3941dac9436f99fbMatthew Wilcox hypercall_msr.as_uint64 = 0; 2273c0cf138d7789feb3f335f6f1d24ad8fc8b3a23fMatthew Wilcox rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 2283c0cf138d7789feb3f335f6f1d24ad8fc8b3a23fMatthew Wilcox 2295d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma if (!hypercall_msr.enable) 230b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox goto Cleanup; 231040a93b52a9eee8177ebaf2ba0ee0f9f518d1bf8Matthew Wilcox 232b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.hypercall_page = virtaddr; 233b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 2345d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma /* Setup the global signal event param for the signal event hypercall */ 235b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_buffer = 2361b23484bd012c078de2ea939249e2fb2e85a0a6eMatthew Wilcox kmalloc(sizeof(struct hv_input_signal_event_buffer), 237b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox GFP_KERNEL); 238b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox if (!hv_context.signal_event_buffer) 239b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox goto Cleanup; 240714a7a22884b74862540bc84955274d86b2f6040Matthew Wilcox 241b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_param = 242b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox (struct hv_input_signal_event *) 243b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox (ALIGN((unsigned long) 244b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_buffer, 245b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox HV_HYPERCALL_PARAM_ALIGN)); 246b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_param->connectionid.asu32 = 0; 247b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_param->connectionid.u.id = 248b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox VMBUS_EVENT_CONNECTION_ID; 249b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_param->flag_number = 0; 250b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_param->rsvdz = 0; 251b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 252b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox return ret; 253b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 254b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew WilcoxCleanup: 2557547881d0951384f9833ec3a80fac8f3f16f3b98Matthew Wilcox if (virtaddr) { 256b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox if (hypercall_msr.enable) { 257b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hypercall_msr.as_uint64 = 0; 258b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 259b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox } 260b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 261b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox vfree(virtaddr); 262eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox } 263e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews ret = -1; 264eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox return ret; 265e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews} 266e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 267eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox/* 268eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * hv_cleanup - Cleanup routine. 269eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * 270eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * This routine is called normally during driver unloading or exiting. 271eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox */ 272eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcoxvoid hv_cleanup(void) 273eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox{ 274eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox union hv_x64_msr_hypercall_contents hypercall_msr; 275eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 276eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox kfree(hv_context.signal_event_buffer); 277b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox hv_context.signal_event_buffer = NULL; 278eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox hv_context.signal_event_param = NULL; 279eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 280b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox if (hv_context.hypercall_page) { 281eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox hypercall_msr.as_uint64 = 0; 282eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 283eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox vfree(hv_context.hypercall_page); 284eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox hv_context.hypercall_page = NULL; 285eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox } 286eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox} 287eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 288eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox/* 2892b1960341576bf51c01b12fefeb1cc53820923e7Keith Busch * hv_post_message - Post a message using the hypervisor message IPC. 2906198221fa0df0298513b35796f63f242ea97134eKeith Busch * 291eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * This involves a hypercall. 292eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox */ 293eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcoxu16 hv_post_message(union hv_connection_id connection_id, 294b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox enum hv_message_type message_type, 295b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox void *payload, size_t payload_size) 2965d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma{ 297b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox struct aligned_input { 298eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox u64 alignment8; 299eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox struct hv_input_post_message msg; 300eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox }; 301eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 302eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox struct hv_input_post_message *aligned_msg; 303eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox u16 status; 304eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox unsigned long addr; 305eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 306eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT) 307eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox return -1; 308eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 309eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC); 310eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox if (!addr) 311eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox return -1; 312b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 313b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox aligned_msg = (struct hv_input_post_message *) 3146198221fa0df0298513b35796f63f242ea97134eKeith Busch (ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN)); 3156198221fa0df0298513b35796f63f242ea97134eKeith Busch 3166198221fa0df0298513b35796f63f242ea97134eKeith Busch aligned_msg->connectionid = connection_id; 3176198221fa0df0298513b35796f63f242ea97134eKeith Busch aligned_msg->message_type = message_type; 3186198221fa0df0298513b35796f63f242ea97134eKeith Busch aligned_msg->payload_size = payload_size; 3196198221fa0df0298513b35796f63f242ea97134eKeith Busch memcpy((void *)aligned_msg->payload, payload, payload_size); 3206198221fa0df0298513b35796f63f242ea97134eKeith Busch 3216198221fa0df0298513b35796f63f242ea97134eKeith Busch status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL) 3226198221fa0df0298513b35796f63f242ea97134eKeith Busch & 0xFFFF; 3236198221fa0df0298513b35796f63f242ea97134eKeith Busch 3246198221fa0df0298513b35796f63f242ea97134eKeith Busch kfree((void *)addr); 3256198221fa0df0298513b35796f63f242ea97134eKeith Busch 3266198221fa0df0298513b35796f63f242ea97134eKeith Busch return status; 3276198221fa0df0298513b35796f63f242ea97134eKeith Busch} 3286198221fa0df0298513b35796f63f242ea97134eKeith Busch 3296198221fa0df0298513b35796f63f242ea97134eKeith Busch 3306198221fa0df0298513b35796f63f242ea97134eKeith Busch/* 3316198221fa0df0298513b35796f63f242ea97134eKeith Busch * hv_signal_event - 3326198221fa0df0298513b35796f63f242ea97134eKeith Busch * Signal an event on the specified connection using the hypervisor event IPC. 3336198221fa0df0298513b35796f63f242ea97134eKeith Busch * 3346198221fa0df0298513b35796f63f242ea97134eKeith Busch * This involves a hypercall. 3356198221fa0df0298513b35796f63f242ea97134eKeith Busch */ 3366198221fa0df0298513b35796f63f242ea97134eKeith Buschu16 hv_signal_event(void) 3376198221fa0df0298513b35796f63f242ea97134eKeith Busch{ 3385c1281a3bf5655ec1b90db495da3a2b77826ba88Matthew Wilcox u16 status; 339b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox 340b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox status = do_hypercall(HVCALL_SIGNAL_EVENT, 341eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox hv_context.signal_event_param, 342eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox NULL) & 0xFFFF; 343b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox return status; 344b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox} 3459e59d091b0eb04f223ed037348e3d9e36f30e72bKeith Busch 3462b1960341576bf51c01b12fefeb1cc53820923e7Keith Busch/* 347b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox * hv_synic_init - Initialize the Synthethic Interrupt Controller. 3489e59d091b0eb04f223ed037348e3d9e36f30e72bKeith Busch * 3499e59d091b0eb04f223ed037348e3d9e36f30e72bKeith Busch * If it is already initialized by another entity (ie x2v shim), we need to 350eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * retrieve the initialized message and event pages. Otherwise, we create and 351427e97080196548557b288517537ab7eb48c309fKeith Busch * initialize the message and event pages. 3521ad2f8932a72bf375361727949ced2cb4e8cfcefMatthew Wilcox */ 353427e97080196548557b288517537ab7eb48c309fKeith Buschvoid hv_synic_init(void *irqarg) 3541ad2f8932a72bf375361727949ced2cb4e8cfcefMatthew Wilcox{ 355b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox u64 version; 356b60503ba432b16fc84442a84e29a7aad2c0c363dMatthew Wilcox union hv_synic_simp simp; 357184d2944cb3b92a2e8e1733c59d1e531ad6e924aMatthew Wilcox union hv_synic_siefp siefp; 3585d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma union hv_synic_sint shared_sint; 3595d0f6131a79adfa1fb51309c5f81a2a4ef879dd4Vishal Verma union hv_synic_scontrol sctrl; 360ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 36199802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox u32 irq_vector = *((u32 *)(irqarg)); 362eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox int cpu = smp_processor_id(); 363eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 364ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox if (!hv_context.hypercall_page) 365ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox return; 366ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 367e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews /* Check the version */ 368eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox rdmsrl(HV_X64_MSR_SVERSION, version); 369e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 370eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox hv_context.synic_message_page[cpu] = 371ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox (void *)get_zeroed_page(GFP_ATOMIC); 372ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 373ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox if (hv_context.synic_message_page[cpu] == NULL) { 374ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox pr_err("Unable to allocate SYNIC message page\n"); 375eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox goto Cleanup; 376ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox } 377ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 378ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox hv_context.synic_event_page[cpu] = 379ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox (void *)get_zeroed_page(GFP_ATOMIC); 380ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 381ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox if (hv_context.synic_event_page[cpu] == NULL) { 382ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox pr_err("Unable to allocate SYNIC event page\n"); 383ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox goto Cleanup; 384ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox } 385ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 386ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox /* Setup the Synic's message page */ 387ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); 388eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox simp.simp_enabled = 1; 389e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu]) 390e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews >> PAGE_SHIFT; 391e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 39299802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); 39399802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox 394eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox /* Setup the Synic's event page */ 39599802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); 39699802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox siefp.siefp_enabled = 1; 397eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu]) 39899802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox >> PAGE_SHIFT; 39999802a7aee2b3dd720e382c52b892cc6a8122b11Matthew Wilcox 400b77954cbddff28d55a36fad3c16f4daebb0f01dfMatthew Wilcox wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); 401b77954cbddff28d55a36fad3c16f4daebb0f01dfMatthew Wilcox 402b77954cbddff28d55a36fad3c16f4daebb0f01dfMatthew Wilcox /* Setup the interception SINT. */ 403eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox /* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */ 404eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox /* interceptionSint.as_uint64); */ 405b77954cbddff28d55a36fad3c16f4daebb0f01dfMatthew Wilcox 406eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox /* Setup the shared SINT. */ 407eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); 408e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 409e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews shared_sint.as_uint64 = 0; 410e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ 4117523d834dd1573610078eb1ac0933f6490232f90Matthew Wilcox shared_sint.masked = false; 412e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews shared_sint.auto_eoi = true; 413b77954cbddff28d55a36fad3c16f4daebb0f01dfMatthew Wilcox 414eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); 415eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox 416eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox /* Enable the global synic bit */ 4177523d834dd1573610078eb1ac0933f6490232f90Matthew Wilcox rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); 4187523d834dd1573610078eb1ac0933f6490232f90Matthew Wilcox sctrl.enable = 1; 4197523d834dd1573610078eb1ac0933f6490232f90Matthew Wilcox 420e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); 421e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 422e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews hv_context.synic_initialized = true; 423e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews return; 424e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 425e025344c56e08b155f43ea09647969286c78377cShane Michael MatthewsCleanup: 426e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews if (hv_context.synic_event_page[cpu]) 427e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews free_page((unsigned long)hv_context.synic_event_page[cpu]); 428e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews 429e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews if (hv_context.synic_message_page[cpu]) 430e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews free_page((unsigned long)hv_context.synic_message_page[cpu]); 431e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews return; 432e025344c56e08b155f43ea09647969286c78377cShane Michael Matthews} 433ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox 434ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox/* 435eca18b2394a9387feeaf14cd884ddddd7a809d19Matthew Wilcox * hv_synic_cleanup - Cleanup routine for hv_synic_init(). 436ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcox */ 437ff22b54fda2078fc3cd1bcdcb7a5ce5d08fd6591Matthew Wilcoxvoid hv_synic_cleanup(void *arg) 438427e97080196548557b288517537ab7eb48c309fKeith Busch{ 439427e97080196548557b288517537ab7eb48c309fKeith Busch union hv_synic_sint shared_sint; 440427e97080196548557b288517537ab7eb48c309fKeith Busch union hv_synic_simp simp; 441427e97080196548557b288517537ab7eb48c309fKeith Busch union hv_synic_siefp siefp; 442427e97080196548557b288517537ab7eb48c309fKeith Busch int cpu = smp_processor_id(); 443427e97080196548557b288517537ab7eb48c309fKeith Busch 444427e97080196548557b288517537ab7eb48c309fKeith Busch if (!hv_context.synic_initialized) 445427e97080196548557b288517537ab7eb48c309fKeith Busch return; 446427e97080196548557b288517537ab7eb48c309fKeith Busch 447427e97080196548557b288517537ab7eb48c309fKeith Busch rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); 448427e97080196548557b288517537ab7eb48c309fKeith Busch 449427e97080196548557b288517537ab7eb48c309fKeith Busch shared_sint.masked = 1; 450427e97080196548557b288517537ab7eb48c309fKeith Busch 451427e97080196548557b288517537ab7eb48c309fKeith Busch /* Need to correctly cleanup in the case of SMP!!! */ 452427e97080196548557b288517537ab7eb48c309fKeith Busch /* Disable the interrupt */ 453427e97080196548557b288517537ab7eb48c309fKeith Busch wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); 4541b56749e541ad59068582f2a28297843e243b856Keith Busch 4551b56749e541ad59068582f2a28297843e243b856Keith Busch rdmsrl(HV_X64_MSR_SIMP, simp.as_uint64); 456427e97080196548557b288517537ab7eb48c309fKeith Busch simp.simp_enabled = 0; 457427e97080196548557b288517537ab7eb48c309fKeith Busch simp.base_simp_gpa = 0; 458427e97080196548557b288517537ab7eb48c309fKeith Busch 459427e97080196548557b288517537ab7eb48c309fKeith Busch wrmsrl(HV_X64_MSR_SIMP, simp.as_uint64); 460427e97080196548557b288517537ab7eb48c309fKeith Busch 461427e97080196548557b288517537ab7eb48c309fKeith Busch rdmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); 462427e97080196548557b288517537ab7eb48c309fKeith Busch siefp.siefp_enabled = 0; 463427e97080196548557b288517537ab7eb48c309fKeith Busch siefp.base_siefp_gpa = 0; 464427e97080196548557b288517537ab7eb48c309fKeith Busch 465427e97080196548557b288517537ab7eb48c309fKeith Busch wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); 466427e97080196548557b288517537ab7eb48c309fKeith Busch 467427e97080196548557b288517537ab7eb48c309fKeith Busch free_page((unsigned long)hv_context.synic_message_page[cpu]); 468427e97080196548557b288517537ab7eb48c309fKeith Busch free_page((unsigned long)hv_context.synic_event_page[cpu]); 469427e97080196548557b288517537ab7eb48c309fKeith Busch} 470427e97080196548557b288517537ab7eb48c309fKeith Busch