hv.c revision eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4f
13e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/* 23e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 33e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Copyright (c) 2009, Microsoft Corporation. 43e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 53e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is free software; you can redistribute it and/or modify it 63e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * under the terms and conditions of the GNU General Public License, 73e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * version 2, as published by the Free Software Foundation. 83e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 93e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT 103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * more details. 133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * You should have received a copy of the GNU General Public License along with 153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA. 173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Authors: 193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Haiyang Zhang <haiyangz@microsoft.com> 203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Hank Janssen <hjanssen@microsoft.com> 213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen */ 233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 24a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/kernel.h> 25a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/mm.h> 26b7c947f04888b8bb2dc79832c10ede73c5b8dae2Bill Pemberton#include <linux/vmalloc.h> 274983b39a0687b00688478e6748b979a02934b234Greg Kroah-Hartman#include "osd.h" 2809d50ff8a233a39e8697e776b06cf5be2de48bb1Greg Kroah-Hartman#include "include/logging.h" 293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen#include "VmbusPrivate.h" 303e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 31454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Globals */ 323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 33454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* The one and only */ 34af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartmanstruct hv_context gHvContext = { 35af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartman .SynICInitialized = false, 36af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartman .HypercallPage = NULL, 37af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartman .SignalEventParam = NULL, 38af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartman .SignalEventBuffer = NULL, 393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}; 403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 423e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 443e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvQueryHypervisorPresence() 463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 473e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Query the cpuid for presense of windows hypervisor 493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 503e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssenstatic int 523e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenHvQueryHypervisorPresence ( 533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen void 543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ) 553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 563e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int eax; 573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int ebx; 583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int ecx; 593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int edx; 603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int op; 613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen eax = 0; 633e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ebx = 0; 643e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ecx = 0; 653e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen edx = 0; 663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen op = HvCpuIdFunctionVersionAndFeatures; 67f931a70c370cc826191a51a79500b34cd592b25bGreg Kroah-Hartman cpuid(op, &eax, &ebx, &ecx, &edx); 683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return (ecx & HV_PRESENT_BIT); 703e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 753e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvQueryHypervisorInfo() 773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 783e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Get version info of the windows hypervisor 803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssenstatic int 833e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenHvQueryHypervisorInfo ( 843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen void 853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ) 863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int eax; 883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int ebx; 893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int ecx; 903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int edx; 913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int maxLeaf; 923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen unsigned int op; 933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 94454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 95454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Its assumed that this is called after confirming that Viridian 96454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * is present. Query id and revision. 97454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 98454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton 993e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen eax = 0; 1013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ebx = 0; 1023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ecx = 0; 1033e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen edx = 0; 1043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen op = HvCpuIdFunctionHvVendorAndMaxFunction; 105f931a70c370cc826191a51a79500b34cd592b25bGreg Kroah-Hartman cpuid(op, &eax, &ebx, &ecx, &edx); 1063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_INFO(VMBUS, "Vendor ID: %c%c%c%c%c%c%c%c%c%c%c%c", 108454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton (ebx & 0xFF), 109454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ebx >> 8) & 0xFF), 110454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ebx >> 16) & 0xFF), 111454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ebx >> 24) & 0xFF), 112454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton (ecx & 0xFF), 113454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ecx >> 8) & 0xFF), 114454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ecx >> 16) & 0xFF), 115454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((ecx >> 24) & 0xFF), 116454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton (edx & 0xFF), 117454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((edx >> 8) & 0xFF), 118454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((edx >> 16) & 0xFF), 119454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((edx >> 24) & 0xFF)); 1203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen maxLeaf = eax; 1223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen eax = 0; 1233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ebx = 0; 1243e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ecx = 0; 1253e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen edx = 0; 1263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen op = HvCpuIdFunctionHvInterface; 127f931a70c370cc826191a51a79500b34cd592b25bGreg Kroah-Hartman cpuid(op, &eax, &ebx, &ecx, &edx); 1283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_INFO(VMBUS, "Interface ID: %c%c%c%c", 130454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton (eax & 0xFF), 131454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((eax >> 8) & 0xFF), 132454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((eax >> 16) & 0xFF), 133454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ((eax >> 24) & 0xFF)); 1343e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (maxLeaf >= HvCpuIdFunctionMsHvVersion) { 136454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton eax = 0; 137454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ebx = 0; 138454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ecx = 0; 139454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton edx = 0; 140454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton op = HvCpuIdFunctionMsHvVersion; 141f931a70c370cc826191a51a79500b34cd592b25bGreg Kroah-Hartman cpuid(op, &eax, &ebx, &ecx, &edx); 142454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton DPRINT_INFO(VMBUS, "OS Build:%d-%d.%d-%d-%d.%d", 143454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton eax, 144454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ebx >> 16, 145454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ebx & 0xFFFF, 146454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton ecx, 147454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton edx >> 24, 148454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton edx & 0xFFFFFF); 1493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1503e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return maxLeaf; 1513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 1523e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 1553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1563e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 1573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvDoHypercall() 1583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1593e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 1603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Invoke the specified hypercall 1613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 16359471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartmanstatic u64 1643e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenHvDoHypercall ( 16559471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 Control, 1663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen void* Input, 1673e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen void* Output 1683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ) 1693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 170530cf2070be30831a371b6c7181d15e5976b6fc7Greg Kroah-Hartman#ifdef CONFIG_X86_64 17159471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 hvStatus=0; 172fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman u64 inputAddress = (Input)? virt_to_phys(Input) : 0; 173fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman u64 outputAddress = (Output)? virt_to_phys(Output) : 0; 1743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen volatile void* hypercallPage = gHvContext.HypercallPage; 1753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "Hypercall <control %llx input phys %llx virt %p output phys %llx virt %p hypercall %p>", 1773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Control, 1783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen inputAddress, 1793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Input, 1803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen outputAddress, 1813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Output, 1823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen hypercallPage); 1833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen __asm__ __volatile__ ("mov %0, %%r8" : : "r" (outputAddress): "r8"); 1853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen __asm__ __volatile__ ("call *%3" : "=a"(hvStatus): "c" (Control), "d" (inputAddress), "m" (hypercallPage)); 1863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatus); 1883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return hvStatus; 1903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen#else 1923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1934d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 controlHi = Control >> 32; 1944d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 controlLo = Control & 0xFFFFFFFF; 1954d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 hvStatusHi = 1; 1964d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 hvStatusLo = 1; 197fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman u64 inputAddress = (Input) ? virt_to_phys(Input) : 0; 1984d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 inputAddressHi = inputAddress >> 32; 1994d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 inputAddressLo = inputAddress & 0xFFFFFFFF; 200fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman u64 outputAddress = (Output) ? virt_to_phys(Output) : 0; 2014d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 outputAddressHi = outputAddress >> 32; 2024d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 outputAddressLo = outputAddress & 0xFFFFFFFF; 2033e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen volatile void* hypercallPage = gHvContext.HypercallPage; 2043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "Hypercall <control %llx input %p output %p>", 2063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Control, 2073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Input, 2083e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Output); 2093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen __asm__ __volatile__ ("call *%8" : "=d"(hvStatusHi), "=a"(hvStatusLo) : "d" (controlHi), "a" (controlLo), "b" (inputAddressHi), "c" (inputAddressLo), "D"(outputAddressHi), "S"(outputAddressLo), "m" (hypercallPage)); 2113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 21359471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman DPRINT_DBG(VMBUS, "Hypercall <return %llx>", hvStatusLo | ((u64)hvStatusHi << 32)); 2143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 21559471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman return (hvStatusLo | ((u64)hvStatusHi << 32)); 216454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton#endif /* x86_64 */ 2173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 2183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 2203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2213e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 2223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvInit() 2233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2243e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 2253e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Main initialization routine. This routine must be called 2263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen before any other routines in here are called 2273e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 22998d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-Hartmanint HvInit (void) 2303e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 2313e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen int ret=0; 2323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen int maxLeaf; 233f80b3d51a6708b5f14a59c53b1343db59efdda1eGreg Kroah-Hartman union hv_x64_msr_hypercall_contents hypercallMsr; 234949cadaa054588db0c4a3a0cfc3ac93f08fda913Greg Kroah-Hartman void *virtAddr = NULL; 2353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ENTER(VMBUS); 2373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 23844f357f835d8a8223b922984eea01aaea29a5f0fBill Pemberton memset(gHvContext.synICEventPage, 0, sizeof(void *) * MAX_NUM_CPUS); 23944f357f835d8a8223b922984eea01aaea29a5f0fBill Pemberton memset(gHvContext.synICMessagePage, 0, sizeof(void *) * MAX_NUM_CPUS); 2403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!HvQueryHypervisorPresence()) 2423e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 2433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "No Windows hypervisor detected!!"); 2443e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 2453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_INFO(VMBUS, "Windows hypervisor detected! Retrieving more info..."); 2483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen maxLeaf = HvQueryHypervisorInfo(); 250454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* HvQueryHypervisorFeatures(maxLeaf); */ 2513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 252454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Determine if we are running on xenlinux (ie x2v shim) or native linux */ 253a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_GUEST_OS_ID, gHvContext.GuestId); 2543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == 0) 2553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 256454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Write our OS info */ 257a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID); 2583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.GuestId = HV_LINUX_GUEST_ID; 2603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 262454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* See if the hypercall page is already set */ 263a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64); 2643e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == HV_LINUX_GUEST_ID) 2653e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 266454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Allocate the hypercall page memory */ 267bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman /* virtAddr = osd_PageAlloc(1); */ 268bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman virtAddr = osd_VirtualAllocExec(PAGE_SIZE); 2693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2703e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!virtAddr) 2713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 2723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "unable to allocate hypercall page!!"); 2733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 2743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen hypercallMsr.Enable = 1; 277fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman /* hypercallMsr.GuestPhysicalAddress = virt_to_phys(virtAddr) >> PAGE_SHIFT; */ 278fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr); 279a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64); 2803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 281454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Confirm that hypercall page did get setup. */ 2823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen hypercallMsr.AsUINT64 = 0; 283a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64); 2843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!hypercallMsr.Enable) 2853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 2863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "unable to set hypercall page!!"); 2873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 2883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.HypercallPage = virtAddr; 2913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen else 2933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 2943e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!", gHvContext.GuestId); 2953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 2963e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2973e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2982701f686d7083d516c2f937031515b032d71f563Greg Kroah-Hartman DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx", 2992701f686d7083d516c2f937031515b032d71f563Greg Kroah-Hartman gHvContext.HypercallPage, 3002701f686d7083d516c2f937031515b032d71f563Greg Kroah-Hartman (u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT); 3013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 302454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the global signal event param for the signal event hypercall */ 303af248e1f1283792e95fd9842fe343f9260300c9dGreg Kroah-Hartman gHvContext.SignalEventBuffer = kmalloc(sizeof(struct hv_input_signal_event_buffer), GFP_KERNEL); 3043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!gHvContext.SignalEventBuffer) 3053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 3073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3083e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 309cba4decdd3dcd224b17631572456951aace0a27eGreg Kroah-Hartman gHvContext.SignalEventParam = (struct hv_input_signal_event *)(ALIGN_UP((unsigned long)gHvContext.SignalEventBuffer, HV_HYPERCALL_PARAM_ALIGN)); 3104d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman gHvContext.SignalEventParam->ConnectionId.Asu32 = 0; 3113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.SignalEventParam->ConnectionId.u.Id = VMBUS_EVENT_CONNECTION_ID; 3123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.SignalEventParam->FlagNumber = 0; 3133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.SignalEventParam->RsvdZ = 0; 3143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 315454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */ 3163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 3183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 3203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3213e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenCleanup: 3223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (virtAddr) 3233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3243e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (hypercallMsr.Enable) 3253e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen hypercallMsr.AsUINT64 = 0; 327a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64); 3283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 330b7c947f04888b8bb2dc79832c10ede73c5b8dae2Bill Pemberton vfree(virtAddr); 3313e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ret = -1; 3333e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 3343e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 3363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 3373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3383e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 3403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3413e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 3423e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvCleanup() 3433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3443e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 3453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Cleanup routine. This routine is called normally during driver unloading or exiting. 3463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 34898d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-Hartmanvoid HvCleanup (void) 3493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 350f80b3d51a6708b5f14a59c53b1343db59efdda1eGreg Kroah-Hartman union hv_x64_msr_hypercall_contents hypercallMsr; 3513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3523e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ENTER(VMBUS); 3533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.SignalEventBuffer) 3553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3568c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(gHvContext.SignalEventBuffer); 3573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.SignalEventBuffer = NULL; 3583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.SignalEventParam = NULL; 3593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == HV_LINUX_GUEST_ID) 3623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3633e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.HypercallPage) 3643e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 3653e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen hypercallMsr.AsUINT64 = 0; 366a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64); 367b7c947f04888b8bb2dc79832c10ede73c5b8dae2Bill Pemberton vfree(gHvContext.HypercallPage); 3683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen gHvContext.HypercallPage = NULL; 3693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3703e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 3713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 3733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 3753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 3783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3793e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 3803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvPostMessage() 3813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3823e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 3833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Post a message using the hypervisor message IPC. This 3843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen involves a hypercall. 3853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 38798d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-HartmanHV_STATUS HvPostMessage( 388eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_connection_id connectionId, 389eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman enum hv_message_type messageType, 3908282c400144a83f85f637a5251740d670e392e84Greg Kroah-Hartman void * payload, 39145635d9703d649645afa52b23896d02e38a73852Greg Kroah-Hartman size_t payloadSize 3923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ) 3933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 3943e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen struct alignedInput { 39559471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 alignment8; 396cba4decdd3dcd224b17631572456951aace0a27eGreg Kroah-Hartman struct hv_input_post_message msg; 3973e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen }; 3983e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 399cba4decdd3dcd224b17631572456951aace0a27eGreg Kroah-Hartman struct hv_input_post_message *alignedMsg; 4003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HV_STATUS status; 401c4b0bc94828a86cfb6a975b0e0d92dc1cd389565Greg Kroah-Hartman unsigned long addr; 4023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4033e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (payloadSize > HV_MESSAGE_PAYLOAD_BYTE_COUNT) 4043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 4053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return -1; 4063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 4073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4080a72f3cf9f53ae0f4f1c6e05bb081d99b5d72db2Greg Kroah-Hartman addr = (unsigned long)kmalloc(sizeof(struct alignedInput), GFP_ATOMIC); 4093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!addr) 4113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 4123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return -1; 4133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 4143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 415cba4decdd3dcd224b17631572456951aace0a27eGreg Kroah-Hartman alignedMsg = (struct hv_input_post_message *)(ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN)); 4163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen alignedMsg->ConnectionId = connectionId; 4183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen alignedMsg->MessageType = messageType; 4193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen alignedMsg->PayloadSize = payloadSize; 4203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen memcpy((void*)alignedMsg->Payload, payload, payloadSize); 4213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 422949cadaa054588db0c4a3a0cfc3ac93f08fda913Greg Kroah-Hartman status = HvDoHypercall(HvCallPostMessage, alignedMsg, NULL) & 0xFFFF; 4233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4248c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree((void*)addr); 4253e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return status; 4273e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 4283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4303e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 4313e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4323e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 4333e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvSignalEvent() 4343e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4353e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 4363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Signal an event on the specified connection using the hypervisor event IPC. This 4373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen involves a hypercall. 4383e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 44098d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-HartmanHV_STATUS HvSignalEvent(void) 4413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 4423e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HV_STATUS status; 4433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 444949cadaa054588db0c4a3a0cfc3ac93f08fda913Greg Kroah-Hartman status = HvDoHypercall(HvCallSignalEvent, gHvContext.SignalEventParam, NULL) & 0xFFFF; 4453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return status; 4473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 4483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4503e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 4513e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4523e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 4533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvSynicInit() 4543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4553e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 4563e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Initialize the Synthethic Interrupt Controller. If it is already initialized by 4573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen another entity (ie x2v shim), we need to retrieve the initialized message and event pages. 4583e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Otherwise, we create and initialize the message and event pages. 4593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 46198d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-Hartmanint HvSynicInit (u32 irqVector) 4623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 46359471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 version; 464eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_simp simp; 465eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_siefp siefp; 466eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_sint sharedSint; 467eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_scontrol sctrl; 46859471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 guestID; 4693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen int ret=0; 4703e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ENTER(VMBUS); 4723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!gHvContext.HypercallPage) 4743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 4753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 4763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 4773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 4783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 479454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check the version */ 480a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SVERSION, version); 4813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_INFO(VMBUS, "SynIC version: %llx", version); 4833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 484454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* TODO: Handle SMP */ 4853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID) 4863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 4873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since it is already set."); 4883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 489a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); 490a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); 4913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 4923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx", simp.AsUINT64, siefp.AsUINT64); 4933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 494454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Determine if we are running on xenlinux (ie x2v shim) or native linux */ 495a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); 4963e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (guestID == HV_LINUX_GUEST_ID) 4973e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 498fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman gHvContext.synICMessagePage[0] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); 499fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman gHvContext.synICEventPage[0] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); 5003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen else 5023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 5033e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "unknown guest id!!"); 5043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 5053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", gHvContext.synICMessagePage[0], gHvContext.synICEventPage[0]); 5073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5083e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen else 5093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 510bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman gHvContext.synICMessagePage[0] = osd_PageAlloc(1); 5113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.synICMessagePage[0] == NULL) 5123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 5133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!"); 5143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 5153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 517bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman gHvContext.synICEventPage[0] = osd_PageAlloc(1); 5183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.synICEventPage[0] == NULL) 5193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 5203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!"); 5213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen goto Cleanup; 5223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 524454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the Synic's message page */ 525a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); 5263e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen simp.SimpEnabled = 1; 527fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) >> PAGE_SHIFT; 5283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5293e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64); 5303e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 531a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); 5323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 533454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the Synic's event page */ 534a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); 5353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen siefp.SiefpEnabled = 1; 536fa56d361b07513cba87cc5c2b57f3f51248f89a8Greg Kroah-Hartman siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) >> PAGE_SHIFT; 5373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5383e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64); 5393e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 540a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); 5413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 542454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the interception SINT. */ 543a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman /* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */ 544454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* interceptionSint.AsUINT64); */ 545454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton 546454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the shared SINT. */ 547a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); 5483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen sharedSint.AsUINT64 = 0; 550454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton sharedSint.Vector = irqVector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ 551454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton sharedSint.Masked = false; 552454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton sharedSint.AutoEoi = true; 5533e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5543e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_DBG(VMBUS, "HV_X64_MSR_SINT1 msr set to: %llx", sharedSint.AsUINT64); 5553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 556a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); 5573e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 558454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Enable the global synic bit */ 559a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64); 5603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen sctrl.Enable = 1; 5613e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 562a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SCONTROL, sctrl.AsUINT64); 5633e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5640e727613ac6e1648d681a75d794862225c801d4bGreg Kroah-Hartman gHvContext.SynICInitialized = true; 5653e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 5673e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5683e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 5693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5703e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenCleanup: 5713e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen ret = -1; 5723e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == HV_LINUX_GUEST_ID) 5743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 5753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.synICEventPage[0]) 5763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 577bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_PageFree(gHvContext.synICEventPage[0],1); 5783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5803e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.synICMessagePage[0]) 5813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 582bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_PageFree(gHvContext.synICMessagePage[0], 1); 5833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 5853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5863e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 5873e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 5893e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5903e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 5913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/*++ 5933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5943e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenName: 5953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen HvSynicCleanup() 5963e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 5973e7ee4902fe6996048f03433dd111426db3cfa92Hank JanssenDescription: 5983e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen Cleanup routine for HvSynicInit(). 5993e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen--*/ 60198d9fac4f0dec8545ed94abe729a15865cff6686Greg Kroah-Hartmanvoid HvSynicCleanup(void) 6023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 603eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_sint sharedSint; 604eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_simp simp; 605eacb1b4d24c2a8b7c1d73bb72e04920980ec8a4fGreg Kroah-Hartman union hv_synic_siefp siefp; 6063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_ENTER(VMBUS); 6083e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6093e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (!gHvContext.SynICInitialized) 6103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 6113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 6123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return; 6133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 6143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 615a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); 6163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen sharedSint.Masked = 1; 6183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 619454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Disable the interrupt */ 620a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); 6213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 622454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 623454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Disable and free the resources only if we are running as 624454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * native linux since in xenlinux, we are sharing the 625454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * resources with the x2v shim 626454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 6273e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen if (gHvContext.GuestId == HV_LINUX_GUEST_ID) 6283e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen { 629a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); 6303e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen simp.SimpEnabled = 0; 6313e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen simp.BaseSimpGpa = 0; 6323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 633a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); 6343e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 635a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); 6363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen siefp.SiefpEnabled = 0; 6373e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen siefp.BaseSiefpGpa = 0; 6383e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 639a51ed7d65d62aa5ad8d364aa76af30328c26263fGreg Kroah-Hartman wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); 6403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 641bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_PageFree(gHvContext.synICMessagePage[0], 1); 642bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_PageFree(gHvContext.synICEventPage[0], 1); 6433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 6443e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen DPRINT_EXIT(VMBUS); 6463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 6473e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 6483e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 649454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* eof */ 650