# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # uts/i86pc/i86hvm/Makefile # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # This makefile drives the production of the i86hvm platform modules. # # i86pc implementation architecture dependent # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../.. # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # Hammerhead: GNU Make target-specific syntax (was dmake :=) def: TARGET = def all: TARGET = all install: TARGET = install install_h: TARGET = install_h clean: TARGET = clean clobber: TARGET = clobber check: TARGET = check # # Default build targets. # .KEEP_STATE: .PARALLEL: $(HVM_KMODS) def all clean clobber: $(HVM_KMODS) install: install_implementations .WAIT \ $(HVM_KMODS) install_implementations: \ $(ROOT_HVM_DIR) \ $(ROOT_HVM_DRV_DIR) \ $(ROOT_HVM_MISC_DIR) \ $(USR_HVM_DIR) $(HVM_KMODS): FRC @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) install_h check: FRC # # Include common targets. # include $(UTSBASE)/$(PLATFORM)/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Define objects HVM_BOOTSTRAP_OBJS += hvm_bootstrap.o PV_CMDK_OBJS += cmdk.o PV_RTLS_OBJS += rtls.o PV_SD_OBJS += sd.o XDF_OBJS += xdf.o XNF_OBJS += xnf.o XPV_OBJS += xpv_support.o xvdi.o gnttab.o evtchn.o xenbus_comms.o \ xenbus_client.o xenbus_probe.o xenbus_xs.o XPVD_OBJS += xpvd.o # Include i86hvm header files INC_PATH += -I$(UTSBASE)/common/xen -I$(UTSBASE)/i86pc/i86hvm # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # Hammerhead: i86hvm modules install to unified /kernel/ (no platform split) ROOT_HVM_DIR = $(ROOT)/kernel ROOT_HVM_MOD_DIR = $(ROOT)/kernel ROOT_HVM_DRV_DIR_32 = $(ROOT_HVM_MOD_DIR)/drv ROOT_HVM_DRV_DIR_64 = $(ROOT_HVM_MOD_DIR)/drv ROOT_HVM_DRV_DIR = $(ROOT_HVM_DRV_DIR_$(CLASS)) ROOT_HVM_MISC_DIR_32 = $(ROOT_HVM_MOD_DIR)/misc ROOT_HVM_MISC_DIR_64 = $(ROOT_HVM_MOD_DIR)/misc ROOT_HVM_MISC_DIR = $(ROOT_HVM_MISC_DIR_$(CLASS)) USR_HVM_DIR = $(USR_PLAT_DIR)/i86hvm # # Define modules. # HVM_DRV_KMODS= cmdk rtls xdf xnf xpv xpvd HVM_MISC_KMODS= hvm_bootstrap HVM_KMODS= $(HVM_DRV_KMODS) $(HVM_MISC_KMODS) include $(UTSBASE)/i86pc/i86hvm/Makefile.files # # Include common rules. # include $(UTSBASE)/i86pc/Makefile.i86pc # # Indicate that we are building for the i86hvm semi-platform. # Also use Solaris specific code in xen public header files. # CPPFLAGS += -DXPV_HVM_DRIVER -D_SOLARIS ASFLAGS += -DXPV_HVM_DRIVER # needs work SMATCH=off # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # This Makefile defines the build rules for the directory # uts/i86pc/i86hvm. # # The following two-level ordering must be maintained in this file. # Lines are sorted first in order of decreasing specificity based on # the first directory component. That is, i86pc rules come before # intel rules come before common rules. # # Lines whose initial directory components are equal are sorted # alphabetically by the remaining components. # # Section 1a: C object build rules # $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/i86hvm/io/xpv/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/i86hvm/io/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) $(OBJS_DIR)/%.o: $(UTSBASE)/common/xen/io/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) $(OBJS_DIR)/%.o: $(UTSBASE)/common/xen/os/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Common targets for i86hvm platform-implementation specific modules. # .KEEP_STATE: # # Rules for implementation subdirectories. # $(ROOT_HVM_DIR): $(INS.dir) $(ROOT_HVM_MOD_DIR): $(ROOT_HVM_DIR) $(INS.dir) $(ROOT_HVM_DRV_DIR_32): $(ROOT_HVM_MOD_DIR) $(INS.dir) $(ROOT_HVM_DRV_DIR_64): $(ROOT_HVM_DRV_DIR_32) $(INS.dir) $(ROOT_HVM_MISC_DIR_32): $(ROOT_HVM_MOD_DIR) $(INS.dir) $(ROOT_HVM_MISC_DIR_64): $(ROOT_HVM_MISC_DIR_32) $(INS.dir) $(ROOT_HVM_MOD_DIR)/%: $(OBJS_DIR)/% $(ROOT_HVM_MOD_DIR) FRC $(INS.file) $(ROOT_HVM_DRV_DIR)/%: $(OBJS_DIR)/% $(ROOT_HVM_DRV_DIR) FRC $(INS.file) $(ROOT_HVM_MISC_DIR)/%: $(OBJS_DIR)/% $(ROOT_HVM_MISC_DIR) FRC $(INS.file) $(USR_HVM_DIR): $(INS.dir) # # Include common targets. # include $(UTSBASE)/$(PLATFORM)/i86hvm/Makefile.rules include $(UTSBASE)/$(PLATFORM)/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. UTSBASE= ../../.. MODULE= cmdk OBJECTS= $(PV_CMDK_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE= $(ROOT_HVM_DRV_DIR)/$(MODULE) include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm ALL_TARGET= $(BINARY) INSTALL_TARGET= $(BINARY) $(ROOTMODULE) .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) include $(UTSBASE)/i86pc/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # uts/i86pc/hvm_bootstrap/Makefile # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # i86pc architecture dependent # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../../.. # # Define the module and object file sets. # MODULE = hvm_bootstrap OBJECTS = $(HVM_BOOTSTRAP_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(ROOT_HVM_MISC_DIR)/$(MODULE) # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # # Define targets # ALL_TARGET = $(BINARY) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/i86hvm/Makefile.targ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Fake cmdk module. Prevents the real cmdk driver from loading in * a xen HVM domain so that xdf may operate instead. */ #include #include #include /*ARGSUSED*/ static int stubattach(dev_info_t *dip, ddi_attach_cmd_t cmd) { return (DDI_SUCCESS); } /*ARGSUSED*/ static int stubdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) { return (DDI_SUCCESS); } static struct dev_ops stub_ops = { DEVO_REV, 0, NULL, nulldev, nulldev, stubattach, stubdetach, nodev, NULL, NULL, NULL, ddi_quiesce_not_needed }; static struct modldrv modldrv = { &mod_driverops, "xVM cmdk stub", &stub_ops }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modldrv, NULL }; int _init(void) { return (mod_install(&modlinkage)); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } int _fini(void) { return (EBUSY); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include /* * The hvm_bootstrap misc module is installed in the i86hvm platform * directly so it will only be loaded in HVM emulated environment. */ /* * hvmboot_rootconf() exists to force attach all xdf disk driver nodes * before the pv cmdk disk driver comes along and tries to access any of * these nodes (which usually happens when mounting the root disk device * in an hvm environment). See the block comments at the top of pv_cmdk.c * for more information about why this is necessary. * * hvmboot_rootconf() also force attaches xnf network driver nodes so * that boot interface can be plumbed when booted via the network. */ int hvmboot_rootconf() { dev_info_t *xpvd_dip; major_t dev_major; dev_major = ddi_name_to_major("xdf"); if (dev_major == (major_t)-1) cmn_err(CE_PANIC, "unable to load xdf disk driver"); if (resolve_pathname("/xpvd", &xpvd_dip, NULL, NULL) != 0) cmn_err(CE_PANIC, "unable to configure /xpvd nexus"); (void) ndi_devi_config_driver(xpvd_dip, 0, dev_major); dev_major = ddi_name_to_major("xnf"); if (dev_major == (major_t)-1) cmn_err(CE_PANIC, "unable to load xnf network driver"); (void) ndi_devi_config_driver(xpvd_dip, 0, dev_major); ndi_rele_devi(xpvd_dip); return (0); } static struct modlmisc modlmisc = { &mod_miscops, "hvm_bootstrap misc module" }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modlmisc, NULL }; int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } int _init() { return (mod_install(&modlinkage)); } int _fini() { return (EBUSY); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Fake rtls module. Prevents the real rtls driver from loading in * a xen HVM domain so that xnf may operate instead. */ #include #include #include static struct dev_ops stub_ops = { DEVO_REV, 0, NULL, nulldev, nulldev, NULL, NULL, nodev, NULL, NULL, NULL, ddi_quiesce_not_needed }; static struct modldrv modldrv = { &mod_driverops, "xVM rtls stub", &stub_ops }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modldrv, NULL }; int _init(void) { return (mod_install(&modlinkage)); } int _info(struct modinfo *modinfop) { return (mod_info(&modlinkage, modinfop)); } int _fini(void) { return (EBUSY); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2014 by Delphix. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include extern dev_info_t *xpv_dip; static ddi_intr_handle_t *evtchn_ihp = NULL; static ddi_softint_handle_t evtchn_to_handle[NR_EVENT_CHANNELS]; kmutex_t ec_lock; static int evtchn_callback_irq = -1; static volatile ulong_t *pending_events; static volatile ulong_t *masked_events; /* log2(NBBY * sizeof (ulong)) */ #define EVTCHN_SHIFT 6 /* Atomically get and clear a ulong from memory. */ #define GET_AND_CLEAR(src, targ) { \ membar_enter(); \ do { \ targ = *src; \ } while (atomic_cas_ulong(src, targ, 0) != targ); \ } /* Get the first and last bits set in a bitmap */ #define GET_BOUNDS(bitmap, low, high) { \ int _i; \ low = high = -1; \ for (_i = 0; _i <= sizeof (ulong_t); _i++) \ if (bitmap & (1UL << _i)) { \ if (low == -1) \ low = _i; \ high = _i; \ } \ } void ec_bind_evtchn_to_handler(int evtchn, pri_t pri, ec_handler_fcn_t handler, void *arg1) { ddi_softint_handle_t hdl; if (evtchn < 0 || evtchn >= NR_EVENT_CHANNELS) { cmn_err(CE_WARN, "Binding invalid event channel: %d", evtchn); return; } (void) ddi_intr_add_softint(xpv_dip, &hdl, pri, handler, (caddr_t)arg1); mutex_enter(&ec_lock); ASSERT(evtchn_to_handle[evtchn] == NULL); evtchn_to_handle[evtchn] = hdl; mutex_exit(&ec_lock); /* Let the hypervisor know we're prepared to handle this event */ hypervisor_unmask_event(evtchn); } void ec_unbind_evtchn(int evtchn) { evtchn_close_t close; ddi_softint_handle_t hdl; if (evtchn < 0 || evtchn >= NR_EVENT_CHANNELS) { cmn_err(CE_WARN, "Unbinding invalid event channel: %d", evtchn); return; } /* * Let the hypervisor know we're no longer prepared to handle this * event */ hypervisor_mask_event(evtchn); /* Cleanup the event handler metadata */ mutex_enter(&ec_lock); hdl = evtchn_to_handle[evtchn]; evtchn_to_handle[evtchn] = NULL; mutex_exit(&ec_lock); close.port = evtchn; (void) HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); (void) ddi_intr_remove_softint(hdl); } void ec_notify_via_evtchn(unsigned int port) { evtchn_send_t send; if ((int)port == -1) return; send.port = port; (void) HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); } void hypervisor_unmask_event(unsigned int ev) { int index = ev >> EVTCHN_SHIFT; ulong_t bit = 1UL << (ev & ((1UL << EVTCHN_SHIFT) - 1)); volatile ulong_t *maskp; evtchn_unmask_t unmask; /* * index,bit contain the event number as an index into the * masked-events bitmask. Set it to 0. */ maskp = &masked_events[index]; atomic_and_ulong(maskp, ~bit); /* Let the hypervisor know the event has been unmasked */ unmask.port = ev; if (HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask) != 0) panic("xen_evtchn_unmask() failed"); } /* Set a bit in an evtchan mask word */ void hypervisor_mask_event(uint_t ev) { int index = ev >> EVTCHN_SHIFT; ulong_t bit = 1UL << (ev & ((1UL << EVTCHN_SHIFT) - 1)); volatile ulong_t *maskp; maskp = &masked_events[index]; atomic_or_ulong(maskp, bit); } void hypervisor_clear_event(uint_t ev) { int index = ev >> EVTCHN_SHIFT; ulong_t bit = 1UL << (ev & ((1UL << EVTCHN_SHIFT) - 1)); volatile ulong_t *maskp; maskp = &pending_events[index]; atomic_and_ulong(maskp, ~bit); } int xen_alloc_unbound_evtchn(int domid, int *evtchnp) { evtchn_alloc_unbound_t alloc; int err; alloc.dom = DOMID_SELF; alloc.remote_dom = (domid_t)domid; if ((err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &alloc)) == 0) { *evtchnp = alloc.port; /* ensure evtchn is masked till we're ready to use it */ (void) hypervisor_mask_event(*evtchnp); } else { err = xen_xlate_errcode(err); } return (err); } int xen_bind_interdomain(int domid, int remote_port, int *port) { evtchn_bind_interdomain_t bind; int err; bind.remote_dom = (domid_t)domid; bind.remote_port = remote_port; if ((err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &bind)) == 0) *port = bind.local_port; else err = xen_xlate_errcode(err); return (err); } /*ARGSUSED*/ uint_t evtchn_callback_fcn(caddr_t arg0, caddr_t arg1) { ulong_t pending_word; int i, j, port; volatile struct vcpu_info *vci; uint_t rv = DDI_INTR_UNCLAIMED; ddi_softint_handle_t hdl; int low, high; ulong_t sels; /* * Xen hard-codes all notifications to VCPU0, so we bind * ourselves via xpv.conf. Note that this also assumes that all * evtchns are bound to VCPU0, which is true by default. */ ASSERT(CPU->cpu_id == 0); vci = &HYPERVISOR_shared_info->vcpu_info[0]; again: DTRACE_PROBE2(evtchn__scan__start, int, vci->evtchn_upcall_pending, ulong_t, vci->evtchn_pending_sel); atomic_and_8(&vci->evtchn_upcall_pending, 0); /* * Find the upper and lower bounds in which we need to search for * pending events. */ GET_AND_CLEAR(&vci->evtchn_pending_sel, sels); /* sels == 1 is by far the most common case. Make it fast */ if (sels == 1) low = high = 0; else if (sels == 0) return (rv); else GET_BOUNDS(sels, low, high); /* Scan the port list, looking for words with bits set */ for (i = low; i <= high; i++) { ulong_t tmp; GET_AND_CLEAR(&pending_events[i], tmp); pending_word = tmp & ~(masked_events[i]); /* Scan the bits in the word, looking for pending events */ while (pending_word != 0) { j = lowbit(pending_word) - 1; port = (i << EVTCHN_SHIFT) + j; pending_word = pending_word & ~(1UL << j); /* * If there is a handler registered for this event, * schedule a softint of the appropriate priority * to execute it. */ if ((hdl = evtchn_to_handle[port]) != NULL) { (void) ddi_intr_trigger_softint(hdl, NULL); rv = DDI_INTR_CLAIMED; } } } DTRACE_PROBE2(evtchn__scan__end, int, vci->evtchn_upcall_pending, ulong_t, vci->evtchn_pending_sel); if ((volatile uint8_t)vci->evtchn_upcall_pending || ((volatile ulong_t)vci->evtchn_pending_sel)) goto again; return (rv); } static int set_hvm_callback(int irq) { struct xen_hvm_param xhp; xhp.domid = DOMID_SELF; xhp.index = HVM_PARAM_CALLBACK_IRQ; xhp.value = irq; return (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp)); } void ec_fini() { int i; for (i = 0; i < NR_EVENT_CHANNELS; i++) ec_unbind_evtchn(i); evtchn_callback_irq = -1; if (evtchn_ihp != NULL) { (void) ddi_intr_disable(*evtchn_ihp); (void) ddi_intr_remove_handler(*evtchn_ihp); (void) ddi_intr_free(*evtchn_ihp); kmem_free(evtchn_ihp, sizeof (ddi_intr_handle_t)); evtchn_ihp = NULL; } } int ec_init(void) { int i; int rv, actual; ddi_intr_handle_t *ihp; /* * Translate the variable-sized pending and masked event bitmasks * into constant-sized arrays of uint32_t's. */ pending_events = &HYPERVISOR_shared_info->evtchn_pending[0]; masked_events = &HYPERVISOR_shared_info->evtchn_mask[0]; /* * Clear our event handler structures and prevent the hypervisor * from triggering any events. */ mutex_init(&ec_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7)); for (i = 0; i < NR_EVENT_CHANNELS; i++) { evtchn_to_handle[i] = NULL; (void) hypervisor_mask_event(i); } /* * Allocate and initialize an interrupt handler to process the * hypervisor's "hey you have events pending!" interrupt. */ ihp = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP); rv = ddi_intr_alloc(xpv_dip, ihp, DDI_INTR_TYPE_FIXED, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL); if (rv < 0 || actual != 1) { cmn_err(CE_WARN, "Could not allocate evtchn interrupt: %d", rv); return (-1); } rv = ddi_intr_add_handler(*ihp, evtchn_callback_fcn, NULL, NULL); if (rv < 0) { (void) ddi_intr_free(*ihp); cmn_err(CE_WARN, "Could not attach evtchn handler"); return (-1); } evtchn_ihp = ihp; if (ddi_intr_enable(*ihp) != DDI_SUCCESS) { cmn_err(CE_WARN, "Could not enable evtchn interrupts\n"); return (-1); } /* Tell the hypervisor which interrupt we're waiting on. */ evtchn_callback_irq = ((ddi_intr_handle_impl_t *)*ihp)->ih_vector; if (set_hvm_callback(evtchn_callback_irq) != 0) { cmn_err(CE_WARN, "Couldn't register evtchn callback"); return (-1); } return (0); } void ec_resume(void) { int i; /* New event-channel space is not 'live' yet. */ for (i = 0; i < NR_EVENT_CHANNELS; i++) (void) hypervisor_mask_event(i); if (set_hvm_callback(evtchn_callback_irq) != 0) cmn_err(CE_WARN, "Couldn't register evtchn callback"); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # interrupt-priorities=9; # # Xen requires us to run this ISR on VCPU0, since that's where all HVM # event channels are bound to, and only the vcpu_info for VCPU0 gets # updated. This will bind us to VCPU0, as well as preventing any # attempt to offline the CPU. # xpv_intpt_bind_cpus=0; /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define XPV_MINOR 0 #define XPV_BUFSIZE 128 /* virtual addr for the store_mfn page */ caddr_t xb_addr; dev_info_t *xpv_dip; static dev_info_t *xpvd_dip; #ifdef DEBUG int xen_suspend_debug; #define SUSPEND_DEBUG if (xen_suspend_debug) xen_printf #else #define SUSPEND_DEBUG(...) #endif /* * Forward declarations */ static int xpv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); static int xpv_attach(dev_info_t *, ddi_attach_cmd_t); static int xpv_detach(dev_info_t *, ddi_detach_cmd_t); static int xpv_open(dev_t *, int, int, cred_t *); static int xpv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); static struct cb_ops xpv_cb_ops = { xpv_open, nulldev, /* close */ nodev, /* strategy */ nodev, /* print */ nodev, /* dump */ nodev, /* read */ nodev, /* write */ xpv_ioctl, /* ioctl */ nodev, /* devmap */ nodev, /* mmap */ nodev, /* segmap */ nochpoll, /* poll */ ddi_prop_op, NULL, D_MP, CB_REV, NULL, NULL }; static struct dev_ops xpv_dv_ops = { DEVO_REV, 0, xpv_getinfo, nulldev, /* identify */ nulldev, /* probe */ xpv_attach, xpv_detach, nodev, /* reset */ &xpv_cb_ops, NULL, /* struct bus_ops */ NULL, /* power */ ddi_quiesce_not_supported, /* devo_quiesce */ }; static struct modldrv modldrv = { &mod_driverops, "xpv driver", &xpv_dv_ops }; static struct modlinkage modl = { MODREV_1, { (void *)&modldrv, NULL /* null termination */ } }; static ddi_dma_attr_t xpv_dma_attr = { DMA_ATTR_V0, /* version of this structure */ 0, /* lowest usable address */ 0xffffffffffffffffULL, /* highest usable address */ 0x7fffffff, /* maximum DMAable byte count */ MMU_PAGESIZE, /* alignment in bytes */ 0x7ff, /* bitmap of burst sizes */ 1, /* minimum transfer */ 0xffffffffU, /* maximum transfer */ 0x7fffffffULL, /* maximum segment length */ 1, /* maximum number of segments */ 1, /* granularity */ 0, /* flags (reserved) */ }; static ddi_device_acc_attr_t xpv_accattr = { DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC }; #define MAX_ALLOCATIONS 10 static ddi_dma_handle_t xpv_dma_handle[MAX_ALLOCATIONS]; static ddi_acc_handle_t xpv_dma_acchandle[MAX_ALLOCATIONS]; static int xen_alloc_cnt = 0; void * xen_alloc_pages(pgcnt_t cnt) { size_t len; int a = xen_alloc_cnt++; caddr_t addr; ASSERT(xen_alloc_cnt < MAX_ALLOCATIONS); if (ddi_dma_alloc_handle(xpv_dip, &xpv_dma_attr, DDI_DMA_SLEEP, 0, &xpv_dma_handle[a]) != DDI_SUCCESS) return (NULL); if (ddi_dma_mem_alloc(xpv_dma_handle[a], MMU_PAGESIZE * cnt, &xpv_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, &addr, &len, &xpv_dma_acchandle[a]) != DDI_SUCCESS) { ddi_dma_free_handle(&xpv_dma_handle[a]); cmn_err(CE_WARN, "Couldn't allocate memory for xpv devices"); return (NULL); } return (addr); } /* * This function is invoked twice, first time with reprogram=0 to set up * the xpvd portion of the device tree. The second time it is ignored. */ static void xpv_enumerate(int reprogram) { dev_info_t *dip; if (reprogram != 0) return; ndi_devi_alloc_sleep(ddi_root_node(), "xpvd", (pnode_t)DEVI_SID_NODEID, &dip); (void) ndi_devi_bind_driver(dip, 0); /* * Too early to enumerate split device drivers in domU * since we need to create taskq thread during enumeration. * So, we only enumerate softdevs and console here. */ xendev_enum_all(dip, B_TRUE); } /* * Translate a hypervisor errcode to a Solaris error code. */ int xen_xlate_errcode(int error) { #define CASE(num) case X_##num: error = num; break switch (-error) { CASE(EPERM); CASE(ENOENT); CASE(ESRCH); CASE(EINTR); CASE(EIO); CASE(ENXIO); CASE(E2BIG); CASE(ENOMEM); CASE(EACCES); CASE(EFAULT); CASE(EBUSY); CASE(EEXIST); CASE(ENODEV); CASE(EISDIR); CASE(EINVAL); CASE(ENOSPC); CASE(ESPIPE); CASE(EROFS); CASE(ENOSYS); CASE(ENOTEMPTY); CASE(EISCONN); CASE(ENODATA); default: panic("xen_xlate_errcode: unknown error %d", error); } return (error); #undef CASE } /*PRINTFLIKE1*/ void xen_printf(const char *fmt, ...) { va_list adx; va_start(adx, fmt); printf(fmt, adx); va_end(adx); } /* * Stub functions to get the FE drivers to build, and to catch drivers that * misbehave in HVM domains. */ /*ARGSUSED*/ void xen_release_pfn(pfn_t pfn) { panic("xen_release_pfn() is not supported in HVM domains"); } /*ARGSUSED*/ void reassign_pfn(pfn_t pfn, mfn_t mfn) { panic("reassign_pfn() is not supported in HVM domains"); } /*ARGSUSED*/ long balloon_free_pages(uint_t page_cnt, mfn_t *mfns, caddr_t kva, pfn_t *pfns) { panic("balloon_free_pages() is not supported in HVM domains"); return (0); } /*ARGSUSED*/ void balloon_drv_added(int64_t delta) { panic("balloon_drv_added() is not supported in HVM domains"); } /* * Add a mapping for the machine page at the given virtual address. */ void kbm_map_ma(maddr_t ma, uintptr_t va, uint_t level) { ASSERT(level == 0); hat_devload(kas.a_hat, (caddr_t)va, MMU_PAGESIZE, mmu_btop(ma), PROT_READ | PROT_WRITE, HAT_LOAD); } /*ARGSUSED*/ int xen_map_gref(uint_t cmd, gnttab_map_grant_ref_t *mapop, uint_t count, boolean_t uvaddr) { long rc; ASSERT(cmd == GNTTABOP_map_grant_ref); rc = HYPERVISOR_grant_table_op(cmd, mapop, count); return (rc); } static struct xenbus_watch shutdown_watch; taskq_t *xen_shutdown_tq; #define SHUTDOWN_INVALID -1 #define SHUTDOWN_POWEROFF 0 #define SHUTDOWN_REBOOT 1 #define SHUTDOWN_SUSPEND 2 #define SHUTDOWN_HALT 3 #define SHUTDOWN_MAX 4 #define SHUTDOWN_TIMEOUT_SECS (60 * 5) int xen_suspend_devices(dev_info_t *dip) { int error; char buf[XPV_BUFSIZE]; SUSPEND_DEBUG("xen_suspend_devices\n"); for (; dip != NULL; dip = ddi_get_next_sibling(dip)) { if (xen_suspend_devices(ddi_get_child(dip))) return (ENXIO); if (ddi_get_driver(dip) == NULL) continue; SUSPEND_DEBUG("Suspending device %s\n", ddi_deviname(dip, buf)); ASSERT((DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED) == 0); if (!i_ddi_devi_attached(dip)) { error = DDI_FAILURE; } else { error = devi_detach(dip, DDI_SUSPEND); } if (error == DDI_SUCCESS) { DEVI(dip)->devi_cpr_flags |= DCF_CPR_SUSPENDED; } else { SUSPEND_DEBUG("WARNING: Unable to suspend device %s\n", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Unable to suspend device %s.", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Device is busy or does not " "support suspend/resume."); return (ENXIO); } } return (0); } int xen_resume_devices(dev_info_t *start, int resume_failed) { dev_info_t *dip, *next, *last = NULL; int did_suspend; int error = resume_failed; char buf[XPV_BUFSIZE]; SUSPEND_DEBUG("xen_resume_devices\n"); while (last != start) { dip = start; next = ddi_get_next_sibling(dip); while (next != last) { dip = next; next = ddi_get_next_sibling(dip); } /* * cpr is the only one that uses this field and the device * itself hasn't resumed yet, there is no need to use a * lock, even though kernel threads are active by now. */ did_suspend = DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED; if (did_suspend) DEVI(dip)->devi_cpr_flags &= ~DCF_CPR_SUSPENDED; /* * There may be background attaches happening on devices * that were not originally suspended by cpr, so resume * only devices that were suspended by cpr. Also, stop * resuming after the first resume failure, but traverse * the entire tree to clear the suspend flag. */ if (did_suspend && !error) { SUSPEND_DEBUG("Resuming device %s\n", ddi_deviname(dip, buf)); /* * If a device suspended by cpr gets detached during * the resume process (for example, due to hotplugging) * before cpr gets around to issuing it a DDI_RESUME, * we'll have problems. */ if (!i_ddi_devi_attached(dip)) { cmn_err(CE_WARN, "Skipping %s, device " "not ready for resume", ddi_deviname(dip, buf)); } else { if (devi_attach(dip, DDI_RESUME) != DDI_SUCCESS) { error = ENXIO; } } } if (error == ENXIO) { cmn_err(CE_WARN, "Unable to resume device %s", ddi_deviname(dip, buf)); } error = xen_resume_devices(ddi_get_child(dip), error); last = dip; } return (error); } /*ARGSUSED*/ static int check_xpvd(dev_info_t *dip, void *arg) { char *name; name = ddi_node_name(dip); if (name == NULL || strcmp(name, "xpvd")) { return (DDI_WALK_CONTINUE); } else { xpvd_dip = dip; return (DDI_WALK_TERMINATE); } } /* * Top level routine to direct suspend/resume of a domain. */ void xen_suspend_domain(void) { extern void rtcsync(void); extern void ec_resume(void); extern kmutex_t ec_lock; struct xen_add_to_physmap xatp; ulong_t flags; int err; cmn_err(CE_NOTE, "Domain suspending for save/migrate"); SUSPEND_DEBUG("xen_suspend_domain\n"); /* * We only want to suspend the PV devices, since the emulated devices * are suspended by saving the emulated device state. The PV devices * are all children of the xpvd nexus device. So we search the * device tree for the xpvd node to use as the root of the tree to * be suspended. */ if (xpvd_dip == NULL) ddi_walk_devs(ddi_root_node(), check_xpvd, NULL); /* * suspend interrupts and devices */ if (xpvd_dip != NULL) (void) xen_suspend_devices(ddi_get_child(xpvd_dip)); else cmn_err(CE_WARN, "No PV devices found to suspend"); SUSPEND_DEBUG("xenbus_suspend\n"); xenbus_suspend(); mutex_enter(&cpu_lock); /* * Suspend on vcpu 0 */ thread_affinity_set(curthread, 0); kpreempt_disable(); if (ncpus > 1) pause_cpus(NULL, NULL); /* * We can grab the ec_lock as it's a spinlock with a high SPL. Hence * any holder would have dropped it to get through pause_cpus(). */ mutex_enter(&ec_lock); /* * From here on in, we can't take locks. */ flags = intr_clear(); SUSPEND_DEBUG("HYPERVISOR_suspend\n"); /* * At this point we suspend and sometime later resume. * Note that this call may return with an indication of a cancelled * for now no matter ehat the return we do a full resume of all * suspended drivers, etc. */ (void) HYPERVISOR_shutdown(SHUTDOWN_suspend); /* * Point HYPERVISOR_shared_info to the proper place. */ xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; xatp.gpfn = xen_shared_info_frame; if ((err = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) != 0) panic("Could not set shared_info page. error: %d", err); SUSPEND_DEBUG("gnttab_resume\n"); gnttab_resume(); SUSPEND_DEBUG("ec_resume\n"); ec_resume(); intr_restore(flags); if (ncpus > 1) start_cpus(); mutex_exit(&ec_lock); mutex_exit(&cpu_lock); /* * Now we can take locks again. */ rtcsync(); SUSPEND_DEBUG("xenbus_resume\n"); xenbus_resume(); SUSPEND_DEBUG("xen_resume_devices\n"); if (xpvd_dip != NULL) (void) xen_resume_devices(ddi_get_child(xpvd_dip), 0); thread_affinity_clear(curthread); kpreempt_enable(); SUSPEND_DEBUG("finished xen_suspend_domain\n"); cmn_err(CE_NOTE, "domain restore/migrate completed"); } static void xen_dirty_shutdown(void *arg) { int cmd = (uintptr_t)arg; cmn_err(CE_WARN, "Externally requested shutdown failed or " "timed out.\nShutting down.\n"); switch (cmd) { case SHUTDOWN_HALT: case SHUTDOWN_POWEROFF: (void) kadmin(A_SHUTDOWN, AD_POWEROFF, NULL, kcred); break; case SHUTDOWN_REBOOT: (void) kadmin(A_REBOOT, AD_BOOT, NULL, kcred); break; } } static void xen_shutdown(void *arg) { int cmd = (uintptr_t)arg; proc_t *initpp; ASSERT(cmd > SHUTDOWN_INVALID && cmd < SHUTDOWN_MAX); if (cmd == SHUTDOWN_SUSPEND) { xen_suspend_domain(); return; } switch (cmd) { case SHUTDOWN_POWEROFF: force_shutdown_method = AD_POWEROFF; break; case SHUTDOWN_HALT: force_shutdown_method = AD_HALT; break; case SHUTDOWN_REBOOT: force_shutdown_method = AD_BOOT; break; } /* * If we're still booting and init(1) isn't set up yet, simply halt. */ mutex_enter(&pidlock); initpp = prfind(P_INITPID); mutex_exit(&pidlock); if (initpp == NULL) { extern void halt(char *); halt("Power off the System"); /* just in case */ } /* * else, graceful shutdown with inittab and all getting involved */ psignal(initpp, SIGPWR); (void) timeout(xen_dirty_shutdown, arg, SHUTDOWN_TIMEOUT_SECS * drv_usectohz(MICROSEC)); } /*ARGSUSED*/ static void xen_shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; xenbus_transaction_t xbt; int err, shutdown_code = SHUTDOWN_INVALID; unsigned int slen; again: err = xenbus_transaction_start(&xbt); if (err) return; if (xenbus_read(xbt, "control", "shutdown", (void *)&str, &slen)) { (void) xenbus_transaction_end(xbt, 1); return; } SUSPEND_DEBUG("%d: xen_shutdown_handler: \"%s\"\n", CPU->cpu_id, str); /* * If this is a watch fired from our write below, check out early to * avoid an infinite loop. */ if (strcmp(str, "") == 0) { (void) xenbus_transaction_end(xbt, 0); kmem_free(str, slen); return; } else if (strcmp(str, "poweroff") == 0) { shutdown_code = SHUTDOWN_POWEROFF; } else if (strcmp(str, "reboot") == 0) { shutdown_code = SHUTDOWN_REBOOT; } else if (strcmp(str, "suspend") == 0) { shutdown_code = SHUTDOWN_SUSPEND; } else if (strcmp(str, "halt") == 0) { shutdown_code = SHUTDOWN_HALT; } else { printf("Ignoring shutdown request: %s\n", str); } (void) xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == EAGAIN) { SUSPEND_DEBUG("%d: trying again\n", CPU->cpu_id); kmem_free(str, slen); goto again; } kmem_free(str, slen); if (shutdown_code != SHUTDOWN_INVALID) { (void) taskq_dispatch(xen_shutdown_tq, xen_shutdown, (void *)(intptr_t)shutdown_code, 0); } } static int xpv_drv_init(void) { if (xpv_feature(XPVF_HYPERCALLS) < 0 || xpv_feature(XPVF_SHARED_INFO) < 0) return (-1); /* Set up the grant tables. */ gnttab_init(); /* Set up event channel support */ if (ec_init() != 0) return (-1); /* Set up xenbus */ xb_addr = vmem_alloc(heap_arena, MMU_PAGESIZE, VM_SLEEP); xs_early_init(); xs_domu_init(); /* Set up for suspend/resume/migrate */ xen_shutdown_tq = taskq_create("shutdown_taskq", 1, maxclsyspri - 1, 1, 1, TASKQ_PREPOPULATE); shutdown_watch.node = "control/shutdown"; shutdown_watch.callback = xen_shutdown_handler; if (register_xenbus_watch(&shutdown_watch)) cmn_err(CE_WARN, "Failed to set shutdown watcher"); return (0); } static void xen_pv_fini() { ec_fini(); } /*ARGSUSED*/ static int xpv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) { if (getminor((dev_t)arg) != XPV_MINOR) return (DDI_FAILURE); switch (cmd) { case DDI_INFO_DEVT2DEVINFO: *result = xpv_dip; break; case DDI_INFO_DEVT2INSTANCE: *result = 0; break; default: return (DDI_FAILURE); } return (DDI_SUCCESS); } static int xpv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { if (cmd != DDI_ATTACH) return (DDI_FAILURE); if (ddi_create_minor_node(dip, ddi_get_name(dip), S_IFCHR, ddi_get_instance(dip), DDI_PSEUDO, 0) != DDI_SUCCESS) return (DDI_FAILURE); xpv_dip = dip; if (xpv_drv_init() != 0) return (DDI_FAILURE); ddi_report_dev(dip); /* * If the memscrubber attempts to scrub the pages we hand to Xen, * the domain will panic. */ memscrub_disable(); /* Report our version to dom0 */ (void) xenbus_printf(XBT_NULL, "guest/xpv", "version", "%d", HVMPV_XPV_VERS); return (DDI_SUCCESS); } /* * Attempts to reload the PV driver plumbing hang on Intel platforms, so * we don't want to unload the framework by accident. */ int xpv_allow_detach = 0; static int xpv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { if (cmd != DDI_DETACH || xpv_allow_detach == 0) return (DDI_FAILURE); if (xpv_dip != NULL) { xen_pv_fini(); ddi_remove_minor_node(dip, NULL); xpv_dip = NULL; } return (DDI_SUCCESS); } /*ARGSUSED1*/ static int xpv_open(dev_t *dev, int flag, int otyp, cred_t *cr) { return (getminor(*dev) == XPV_MINOR ? 0 : ENXIO); } /*ARGSUSED*/ static int xpv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p) { return (EINVAL); } int _init(void) { int err; if ((err = mod_install(&modl)) != 0) return (err); impl_bus_add_probe(xpv_enumerate); return (0); } int _fini(void) { int err; if ((err = mod_remove(&modl)) != 0) return (err); impl_bus_delete_probe(xpv_enumerate); return (0); } int _info(struct modinfo *modinfop) { return (mod_info(&modl, modinfop)); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # UTSBASE= ../../.. MODULE= rtls OBJECTS= $(PV_RTLS_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE= $(ROOT_HVM_DRV_DIR)/$(MODULE) include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm ALL_TARGET= $(BINARY) INSTALL_TARGET= $(BINARY) $(ROOTMODULE) .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) include $(UTSBASE)/i86pc/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # uts/i86pc/xdf/Makefile # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # i86pc architecture dependent # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../../.. # # Define the module and object file sets. # MODULE = xdf OBJECTS = $(XDF_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(ROOT_HVM_DRV_DIR)/$(MODULE) # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # # Define targets # ALL_TARGET = $(BINARY) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # Overrides CPPFLAGS += -DHVMPV_XDF_VERS=2 LDFLAGS += -Nmisc/cmlb -Ndrv/xpvd -Ndrv/xpv CERRWARN += -Wno-parentheses CERRWARN += -Wno-switch # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # uts/i86pc/xnf/Makefile # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # This makefile drives the production of the xve # network driver kernel module. # # i86pc architecture dependent # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../../.. # # Define the module and object file sets. # MODULE = xnf OBJECTS = $(XNF_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(ROOT_HVM_DRV_DIR)/$(MODULE) # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # # Define targets # ALL_TARGET = $(BINARY) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) # # Driver depends on MAC & IP # CPPFLAGS += -DHVMPV_XNF_VERS=1 LDFLAGS += -Nmisc/mac -Ndrv/ip -Ndrv/xpvd -Ndrv/xpv # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # uts/i86pc/xpv/Makefile # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # # This makefile drives the production of the xpv # driver, which provides the necessary infrastructure for # paravirtualized front-end drivers in HVM systems. # # i86pc implementation architecture dependent # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../../.. # # Define the module and object file sets. # MODULE = xpv OBJECTS = $(XPV_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(ROOT_HVM_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/i86pc/i86hvm/io/xpv # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # # Define targets # ALL_TARGET = $(BINARY) $(CONFMOD) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) CPPFLAGS += -DHVMPV_XPV_VERS=1 LDFLAGS += -N mach/pcplusmp # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/i86hvm/Makefile.targ # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # # # This makefile drives the production of the xpvd nexus driver # # i86pc implementation architecture dependent # # # Path to the base of the uts directory tree (usually /usr/src/uts). # UTSBASE = ../../.. # # Define the module and object file sets. # MODULE = xpvd OBJECTS = $(XPVD_OBJS:%=$(OBJS_DIR)/%) ROOTMODULE = $(ROOT_HVM_DRV_DIR)/$(MODULE) CONF_SRCDIR = $(UTSBASE)/common/xen/io # # Include common rules. # include $(UTSBASE)/i86pc/i86hvm/Makefile.i86hvm # # Define targets # ALL_TARGET = $(BINARY) $(CONFMOD) INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) CPPFLAGS += -DHVMPV_XPVD_VERS=1 LDFLAGS += -Ndrv/xpv CERRWARN += $(CNOWARN_UNINIT) # # Default build targets. # .KEEP_STATE: def: $(DEF_DEPS) all: $(ALL_DEPS) clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) install: $(INSTALL_DEPS) # # Include common targets. # include $(UTSBASE)/i86pc/i86hvm/Makefile.targ