Index: sys/conf/files.amd64 =================================================================== --- sys/conf/files.amd64 (revision 335682) +++ sys/conf/files.amd64 (working copy) @@ -745,6 +745,7 @@ x86/x86/pvclock.c standard x86/x86/stack_machdep.c optional ddb | stack x86/x86/tsc.c standard +x86/x86/vmware_guestrpc.c optional vmware_guestrpc x86/x86/delay.c standard x86/xen/hvm.c optional xenhvm x86/xen/xen_intr.c optional xenhvm Index: sys/conf/files.i386 =================================================================== --- sys/conf/files.i386 (revision 335682) +++ sys/conf/files.i386 (working copy) @@ -623,6 +623,7 @@ x86/x86/nexus.c standard x86/x86/stack_machdep.c optional ddb | stack x86/x86/tsc.c standard +x86/x86/vmware_guestrpc.c optional vmware_guestrpc x86/x86/pvclock.c standard x86/x86/delay.c standard x86/xen/hvm.c optional xenhvm Index: sys/conf/options.amd64 =================================================================== --- sys/conf/options.amd64 (revision 335682) +++ sys/conf/options.amd64 (working copy) @@ -69,3 +69,6 @@ # EFI Runtime services support EFIRT opt_efirt.h + +# VMware support +VMWARE_GUESTRPC opt_global.h Index: sys/conf/options.i386 =================================================================== --- sys/conf/options.i386 (revision 335682) +++ sys/conf/options.i386 (working copy) @@ -120,3 +120,6 @@ # options for the Intel C600 SAS driver (isci) ISCI_LOGGING opt_isci.h + +# VMware support +VMWARE_GUESTRPC opt_global.h Index: sys/x86/include/vmware.h =================================================================== --- sys/x86/include/vmware.h (revision 335682) +++ sys/x86/include/vmware.h (working copy) @@ -33,6 +33,7 @@ #define VMW_HVPORT 0x5658 #define VMW_HVCMD_GETVERSION 10 +#define VMW_HVCMD_GUESTRPC 30 #define VMW_HVCMD_GETHZ 45 #define VMW_HVCMD_GETVCPU_INFO 68 @@ -40,13 +41,25 @@ #define VMW_VCPUINFO_VCPU_RESERVED (1 << 31) static __inline void -vmware_hvcall(u_int cmd, u_int *p) +vmware_hypercall(int chan, u_int cmd, u_int param, u_int *p) { __asm __volatile("inl %w3, %0" : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) - : "0" (VMW_HVMAGIC), "1" (UINT_MAX), "2" (cmd), "3" (VMW_HVPORT) + : "0" (VMW_HVMAGIC), "1" (param), "2" (cmd), + "3" (VMW_HVPORT | (chan << 16)) : "memory"); } +/* + * Retain the old API for backwards compatibility + * XXX deprecate after some time? + */ +static __inline void +vmware_hvcall(u_int cmd, u_int *p) +{ + + vmware_hypercall(0, cmd, UINT_MAX, p); +} + #endif /* !_X86_VMWARE_H_ */ Index: sys/x86/include/vmware_guestrpc.h =================================================================== --- sys/x86/include/vmware_guestrpc.h (nonexistent) +++ sys/x86/include/vmware_guestrpc.h (working copy) @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2015, Juniper Networks, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _X86_VMWARE_GUESTRPC_H_ +#define _X86_VMWARE_GUESTRPC_H_ + +struct sbuf; + +int vmware_guestrpc_cmd(struct sbuf *sbufp); +int vmware_guestrpc_set_guestinfo(const char *keyword, const char *val); +int vmware_guestrpc_get_guestinfo(const char *keyword, struct sbuf *sbufp); + +#endif /* _X86_VMWARE_GUESTRPC_H_ */ Property changes on: sys/x86/include/vmware_guestrpc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/x86/x86/vmware_guestrpc.c =================================================================== --- sys/x86/x86/vmware_guestrpc.c (nonexistent) +++ sys/x86/x86/vmware_guestrpc.c (working copy) @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 2013, 2015, 2018, Juniper Networks, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef VMWARE_GUESTRPC_DEBUG +#define VMW_GUESTRPC_DBGPRINT(fmt, ...) \ + do { \ + if (vmware_guestrpc_debug > 0) \ + printf(fmt, ##__VA_ARGS__); \ + } while (0) +#else +#define VMW_GUESTRPC_DBGPRINT(fmt, ...) +#endif + +/* GuestRPC Subcommands */ +#define VMW_HVGUESTRPC_OPEN 0x00 +#define VMW_HVGUESTRPC_SEND_LEN 0x01 +#define VMW_HVGUESTRPC_SEND_DATA 0x02 +#define VMW_HVGUESTRPC_RECV_LEN 0x03 +#define VMW_HVGUESTRPC_RECV_DATA 0x04 +#define VMW_HVGUESTRPC_FINISH_RECV 0x05 +#define VMW_HVGUESTRPC_CLOSE 0x06 +/* GuestRPC Parameters */ +#define VMW_HVGUESTRPC_OPEN_MAGIC 0x49435052 +/* GuestRPC Status */ +#define VMW_HVGUESTRPC_FAILURE 0x00000000 +#define VMW_HVGUESTRPC_OPEN_SUCCESS 0x00010000 +#define VMW_HVGUESTRPC_SEND_LEN_SUCCESS 0x00810000 +#define VMW_HVGUESTRPC_SEND_DATA_SUCCESS 0x00010000 +#define VMW_HVGUESTRPC_RECV_LEN_SUCCESS 0x00830000 +#define VMW_HVGUESTRPC_RECV_DATA_SUCCESS 0x00010000 +#define VMW_HVGUESTRPC_FINISH_RECV_SUCCESS 0x00010000 +#define VMW_HVGUESTRPC_CLOSE_SUCCESS 0x00010000 + +#define VMW_GUESTRPC_EBX(_p) ((_p)[1]) +#define VMW_GUESTRPC_EDXHI(_p) ((_p)[3] >> 16) +#define VMW_GUESTRPC_STATUS(_p) ((_p)[2]) + +#define VMW_GUESTRPC_MAX_PARAMS 4 + +#ifdef VMWARE_GUESTRPC_DEBUG +int vmware_guestrpc_debug; +SYSCTL_INT(_debug, OID_AUTO, vmware_guestrpc, CTLFLAG_RDTUN, + &vmware_guestrpc_debug, 0, "Debug VMware GUESTRPC hypercalls"); +#endif + +static __inline void +vmware_guestrpc(int chan, uint16_t subcmd, uint32_t param, u_int *p) +{ + + VMW_GUESTRPC_DBGPRINT("%s(%d, %#x, %#x, %p)\n", __func__, chan, subcmd, + param, p); + vmware_hypercall(chan, VMW_HVCMD_GUESTRPC | (subcmd << 16), param, p); + VMW_GUESTRPC_DBGPRINT("p[0] = %#x\np[1] = %#x\np[2] = %#x\n" + "p[3] = %#x\n", p[0], p[1], p[2], p[3]); +} + +static int +vmware_guestrpc_open(void) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(0, VMW_HVGUESTRPC_OPEN, VMW_HVGUESTRPC_OPEN_MAGIC, + p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_OPEN_SUCCESS) + return (-1); + + return (VMW_GUESTRPC_EDXHI(p)); +} + +static int +vmware_guestrpc_send_len(int channel, size_t len) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(channel, VMW_HVGUESTRPC_SEND_LEN, len, p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_SEND_LEN_SUCCESS) + return (-1); + + return (0); +} + +static int +vmware_guestrpc_send_data(int channel, uint32_t data) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(channel, VMW_HVGUESTRPC_SEND_DATA, data, p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_SEND_DATA_SUCCESS) + return (-1); + + return (0); +} + +static int +vmware_guestrpc_recv_len(int channel, size_t *lenp) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(channel, VMW_HVGUESTRPC_RECV_LEN, 0, p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_RECV_LEN_SUCCESS) + return (-1); + + *lenp = VMW_GUESTRPC_EBX(p); + return (VMW_GUESTRPC_EDXHI(p)); +} + +static int +vmware_guestrpc_recv_data(int channel, int id, uint32_t *datap) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(channel, VMW_HVGUESTRPC_RECV_DATA, id, p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_RECV_DATA_SUCCESS) + return (-1); + + *datap = VMW_GUESTRPC_EBX(p); + return (0); +} + +static int +vmware_guestrpc_close(int channel) +{ + u_int p[VMW_GUESTRPC_MAX_PARAMS]; + + vmware_guestrpc(channel, VMW_HVGUESTRPC_CLOSE, 0, p); + if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_CLOSE_SUCCESS) + return (-1); + + return (0); +} + +int +vmware_guestrpc_cmd(struct sbuf *sbufp) +{ + char *buf; + size_t cnt, len; + int chan, id, status; + uint32_t data; + + chan = vmware_guestrpc_open(); + if (chan == -1) + return (-1); + + buf = sbuf_data(sbufp); + len = sbuf_len(sbufp); + status = vmware_guestrpc_send_len(chan, len); + if (status == -1) + goto done; + + while (len > 0) { + data = 0; + cnt = min(sizeof(data), len); + memcpy(&data, buf, cnt); + status = vmware_guestrpc_send_data(chan, data); + if (status == -1) + goto done; + buf += cnt; + len -= cnt; + } + + id = vmware_guestrpc_recv_len(chan, &len); + if (id == -1) + goto done; + + sbuf_clear(sbufp); + while (len > 0) { + status = vmware_guestrpc_recv_data(chan, id, &data); + if (status == -1) + goto done; + sbuf_bcat(sbufp, &data, sizeof(data)); + len -= min(sizeof(data), len); + } + +done: + vmware_guestrpc_close(chan); + return (status); +} + +int +vmware_guestrpc_set_guestinfo(const char *keyword, const char *val) +{ + struct sbuf sb; + char *buf; + + VMW_GUESTRPC_DBGPRINT("%s: %s=%s\n", __func__, keyword, val); + + if (sbuf_new(&sb, NULL, 256, SBUF_AUTOEXTEND) == NULL) + return (-1); + sbuf_printf(&sb, "info-set guestinfo.fbsd.%s %s", keyword, val); + sbuf_trim(&sb); + sbuf_finish(&sb); + + if (vmware_guestrpc_cmd(&sb) == -1) + return (-1); + + sbuf_finish(&sb); + buf = sbuf_data(&sb); + + VMW_GUESTRPC_DBGPRINT("%s: result: %s\n", __func__, buf); + + /* + * VMware hypervisor returns: + * "1" on sucess + * "0" on failure + */ + return ((buf[0] == '0') ? -1 : 0); +} + +int +vmware_guestrpc_get_guestinfo(const char *keyword, struct sbuf *sbufp) +{ + struct sbuf sb; + char *buf; + ssize_t len; + + VMW_GUESTRPC_DBGPRINT("%s: %s\n", __func__, keyword); + + if (sbuf_new(&sb, NULL, 256, SBUF_AUTOEXTEND) == NULL) + return (-1); + sbuf_printf(&sb, "info-get guestinfo.fbsd.%s", keyword); + sbuf_trim(&sb); + sbuf_finish(&sb); + + if (vmware_guestrpc_cmd(&sb) == -1) + return (-1); + + sbuf_finish(&sb); + buf = sbuf_data(&sb); + len = sbuf_len(&sb); + if (len < 2) + return (-1); + + VMW_GUESTRPC_DBGPRINT("%s: result: %s\n", __func__, buf); + + /* + * VMware hypervisor returns: + * "1 " on success + * "0 No value found" on failure + */ + if (buf[0] == '0') + return (-1); + + sbuf_cat(sbufp, buf + 2); + return (0); +} + +static int +vmware_guestrpc_modload(struct module *module, int cmd, void *arg) +{ + int error; + + switch (cmd) { + case MOD_LOAD: + case MOD_UNLOAD: + error = 0; + break; + default: + error = EINVAL; + break; + } + return (error); +} + +static moduledata_t vmware_guestrpc_mod = { + "vmware_guestrpc", + &vmware_guestrpc_modload, + NULL +}; + +DECLARE_MODULE(vmware_guestrpc, vmware_guestrpc_mod, SI_SUB_HYPERVISOR, + SI_ORDER_MIDDLE); +MODULE_VERSION(vmware_guestrpc, 1); Property changes on: sys/x86/x86/vmware_guestrpc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property