From de993f1c63216ab277e3e932d54df8c3b892acf5 Mon Sep 17 00:00:00 2001 From: Josef 'Jeff' Sipek Date: Fri, 12 Jan 2018 18:29:46 -0500 Subject: [PATCH] remove xen support This commit removes most of the code to support xen dom0 and domU, however it makes no attempt at removing the tons of #ifdefs related to xen support in the remainder of the repo. --- FEATURES.txt | 1 + arch/x86/Sconfig | 4 +- arch/x86/kernel/platform/i86pc/os/mlsetup.c | 8 - arch/x86/kernel/platform/i86pc/os/xpv_platform.c | 255 -- arch/x86/kernel/platform/i86xpv/include/Makefile | 4 - .../kernel/platform/i86xpv/include/sys/Makefile | 11 - .../kernel/platform/i86xpv/include/sys/balloon.h | 57 - .../platform/i86xpv/include/sys/balloon_impl.h | 76 - .../kernel/platform/i86xpv/include/sys/cpr_impl.h | 59 - .../platform/i86xpv/include/sys/domcaps_impl.h | 54 - .../platform/i86xpv/include/sys/evtchn_impl.h | 199 -- .../platform/i86xpv/include/sys/machprivregs.h | 544 --- .../platform/i86xpv/include/sys/privcmd_impl.h | 61 - .../kernel/platform/i86xpv/include/sys/xen_mmu.h | 135 - .../kernel/platform/i86xpv/include/sys/xpv_impl.h | 47 - .../kernel/platform/i86xpv/include/sys/xpv_panic.h | 62 - .../kernel/platform/i86xpv/include/sys/xpv_user.h | 63 - .../x86/kernel/platform/i86xpv/include/vm/Makefile | 8 - .../x86/kernel/platform/i86xpv/include/vm/seg_mf.h | 64 - arch/x86/kernel/platform/i86xpv/mapfile-32 | 81 - arch/x86/kernel/platform/i86xpv/mapfile-64 | 78 - arch/x86/kernel/xen/os/hypercall.c | 433 --- exception_lists/packaging | 6 - usr/src/cmd/boot/filelist/i386/filelist.ramdisk | 2 - usr/src/cmd/devfsadm/i386/Makefile | 5 +- usr/src/cmd/devfsadm/i386/xen_link.c | 111 - usr/src/cmd/dtrace/test/tst/Makefile | 2 +- usr/src/cmd/dtrace/test/tst/i86xpv/Makefile | 29 - .../cmd/dtrace/test/tst/i86xpv/xdt/tst.basic.ksh | 77 - .../dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh | 64 - .../dtrace/test/tst/i86xpv/xdt/tst.memenable.ksh | 65 - .../dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh | 121 - .../dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh | 74 - usr/src/cmd/mdb/common/modules/genunix/memory.c | 26 - usr/src/cmd/mdb/i86xpv/Makefile | 28 - usr/src/cmd/mdb/i86xpv/Makefile.i86xpv | 47 - usr/src/cmd/mdb/i86xpv/modules/Makefile | 29 - usr/src/cmd/mdb/i86xpv/modules/unix/Makefile | 29 - usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile | 53 - usr/src/cmd/mdb/i86xpv/modules/xpv/Makefile | 29 - usr/src/cmd/mdb/i86xpv/modules/xpv/amd64/Makefile | 47 - usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c | 288 -- usr/src/cmd/mdb/i86xpv/modules/xpv_psm/Makefile | 29 - .../cmd/mdb/i86xpv/modules/xpv_psm/amd64/Makefile | 49 - usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c | 536 --- usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile | 29 - .../cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile | 49 - usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c | 496 --- usr/src/cmd/mdb/intel/amd64/genunix/Makefile | 1 - usr/src/cmd/mdb/intel/modules/Makefile | 2 +- usr/src/cmd/mdb/intel/modules/mdb_kb/Makefile | 29 - .../cmd/mdb/intel/modules/mdb_kb/amd64/Makefile | 46 - usr/src/cmd/mdb/intel/modules/mdb_kb/mdb_kb.c | 1607 --------- usr/src/pkg/Makefile | 3 - usr/src/pkg/manifests/developer-debug-mdb.mf | 23 - usr/src/pkg/manifests/driver-xvm-pv.mf | 65 +- usr/src/pkg/manifests/system-core-os.mf | 1 - usr/src/pkg/manifests/system-dtrace-tests.mf | 8 - usr/src/pkg/manifests/system-header.mf | 5 - .../system-kernel-dtrace-providers-xdt.mf | 52 +- usr/src/pkg/manifests/system-kernel-platform.mf | 85 - usr/src/uts/common/xen/dtrace/xdt.c | 2182 ------------ usr/src/uts/common/xen/dtrace/xdt.conf | 33 - usr/src/uts/common/xen/io/blk_common.c | 1021 ------ usr/src/uts/common/xen/io/blk_common.h | 70 - usr/src/uts/common/xen/io/blkif_impl.h | 96 - usr/src/uts/common/xen/io/evtchn_dev.c | 740 ---- usr/src/uts/common/xen/io/xdb.c | 1977 ----------- usr/src/uts/common/xen/io/xdb.h | 184 - usr/src/uts/common/xen/io/xdf.c | 3627 -------------------- usr/src/uts/common/xen/io/xdf.h | 332 -- usr/src/uts/common/xen/io/xenbus_client.c | 287 -- usr/src/uts/common/xen/io/xenbus_comms.c | 311 -- usr/src/uts/common/xen/io/xenbus_dev.c | 677 ---- usr/src/uts/common/xen/io/xenbus_probe.c | 185 - usr/src/uts/common/xen/io/xenbus_xs.c | 1139 ------ usr/src/uts/common/xen/io/xencons.c | 1656 --------- usr/src/uts/common/xen/io/xencons.conf | 27 - usr/src/uts/common/xen/io/xencons.h | 208 -- usr/src/uts/common/xen/io/xnb.c | 2075 ----------- usr/src/uts/common/xen/io/xnb.h | 216 -- usr/src/uts/common/xen/io/xnbe.c | 163 - usr/src/uts/common/xen/io/xnbo.c | 742 ---- usr/src/uts/common/xen/io/xnbu.c | 533 --- usr/src/uts/common/xen/io/xnf.c | 2759 --------------- usr/src/uts/common/xen/io/xnf.h | 183 - usr/src/uts/common/xen/io/xpv_autoconfig.c | 120 - usr/src/uts/common/xen/io/xpvd.c | 1007 ------ usr/src/uts/common/xen/io/xpvd.conf | 28 - usr/src/uts/common/xen/io/xpvtap.c | 1638 --------- usr/src/uts/common/xen/io/xpvtap.h | 185 - usr/src/uts/common/xen/os/gnttab.c | 681 ---- usr/src/uts/common/xen/os/xvdi.c | 2423 ------------- usr/src/uts/common/xen/public/COPYING | 38 - usr/src/uts/common/xen/public/README.DO_NOT_EDIT | 36 - usr/src/uts/common/xen/public/arch-x86/xen-mca.h | 422 --- .../uts/common/xen/public/arch-x86/xen-x86_32.h | 254 -- .../uts/common/xen/public/arch-x86/xen-x86_64.h | 286 -- usr/src/uts/common/xen/public/arch-x86/xen.h | 241 -- usr/src/uts/common/xen/public/callback.h | 121 - usr/src/uts/common/xen/public/domctl.h | 707 ---- usr/src/uts/common/xen/public/elfnote.h | 244 -- usr/src/uts/common/xen/public/event_channel.h | 264 -- usr/src/uts/common/xen/public/features.h | 83 - usr/src/uts/common/xen/public/grant_table.h | 438 --- usr/src/uts/common/xen/public/hvm/hvm_op.h | 131 - usr/src/uts/common/xen/public/hvm/params.h | 111 - usr/src/uts/common/xen/public/io/blkif.h | 148 - usr/src/uts/common/xen/public/io/console.h | 51 - usr/src/uts/common/xen/public/io/netif.h | 205 -- usr/src/uts/common/xen/public/io/protocols.h | 40 - usr/src/uts/common/xen/public/io/ring.h | 313 -- usr/src/uts/common/xen/public/io/xenbus.h | 80 - usr/src/uts/common/xen/public/io/xs_wire.h | 130 - usr/src/uts/common/xen/public/memory.h | 290 -- usr/src/uts/common/xen/public/nmi.h | 78 - usr/src/uts/common/xen/public/physdev.h | 259 -- usr/src/uts/common/xen/public/platform.h | 354 -- usr/src/uts/common/xen/public/sched.h | 121 - usr/src/uts/common/xen/public/sysctl.h | 490 --- usr/src/uts/common/xen/public/trace.h | 207 -- usr/src/uts/common/xen/public/vcpu.h | 213 -- usr/src/uts/common/xen/public/version.h | 91 - usr/src/uts/common/xen/public/xen-compat.h | 44 - usr/src/uts/common/xen/public/xen.h | 676 ---- usr/src/uts/common/xen/public/xsm/acm.h | 223 -- usr/src/uts/common/xen/public/xsm/acm_ops.h | 159 - usr/src/uts/common/xen/sys/README | 36 - usr/src/uts/common/xen/sys/evtchn.h | 101 - usr/src/uts/common/xen/sys/gnttab.h | 154 - usr/src/uts/common/xen/sys/privcmd.h | 87 - usr/src/uts/common/xen/sys/xenbus.h | 44 - usr/src/uts/common/xen/sys/xenbus_comms.h | 64 - usr/src/uts/common/xen/sys/xenbus_impl.h | 272 -- usr/src/uts/common/xen/sys/xendev.h | 303 -- usr/src/uts/i86pc/Makefile | 11 +- usr/src/uts/i86pc/Makefile.files | 4 - usr/src/uts/i86pc/Makefile.i86pc | 11 - usr/src/uts/i86pc/Makefile.rules | 4 - usr/src/uts/i86pc/i86hvm/Makefile | 79 - usr/src/uts/i86pc/i86hvm/Makefile.files | 50 - usr/src/uts/i86pc/i86hvm/Makefile.i86hvm | 59 - usr/src/uts/i86pc/i86hvm/Makefile.rules | 57 - usr/src/uts/i86pc/i86hvm/Makefile.targ | 68 - usr/src/uts/i86pc/i86hvm/hvm_bootstrap/Makefile | 75 - usr/src/uts/i86pc/i86hvm/hvm_cmdk/Makefile | 91 - usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile | 83 - usr/src/uts/i86pc/i86hvm/io/hvm_bootstrap.c | 95 - usr/src/uts/i86pc/i86hvm/io/pv_cmdk.c | 674 ---- usr/src/uts/i86pc/i86hvm/io/pv_rtls.c | 79 - usr/src/uts/i86pc/i86hvm/io/pv_sd.c | 187 - usr/src/uts/i86pc/i86hvm/io/xdf_shell.c | 1284 ------- usr/src/uts/i86pc/i86hvm/io/xdf_shell.h | 161 - usr/src/uts/i86pc/i86hvm/io/xpv/evtchn.c | 398 --- usr/src/uts/i86pc/i86hvm/io/xpv/xpv.conf | 33 - usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c | 816 ----- usr/src/uts/i86pc/i86hvm/pv_cmdk/Makefile | 81 - usr/src/uts/i86pc/i86hvm/pv_rtls/Makefile | 75 - usr/src/uts/i86pc/i86hvm/pv_sd/Makefile | 78 - usr/src/uts/i86pc/i86hvm/xdf/Makefile | 80 - usr/src/uts/i86pc/i86hvm/xnf/Makefile | 84 - usr/src/uts/i86pc/i86hvm/xpv/Makefile | 83 - usr/src/uts/i86pc/i86hvm/xpvd/Makefile | 81 - usr/src/uts/i86xpv/Makefile | 101 - usr/src/uts/i86xpv/Makefile.files | 257 -- usr/src/uts/i86xpv/Makefile.i86xpv | 290 -- usr/src/uts/i86xpv/Makefile.rules | 195 -- usr/src/uts/i86xpv/Makefile.targ | 42 - usr/src/uts/i86xpv/amd_opteron/Makefile | 95 - usr/src/uts/i86xpv/authenticamd/Makefile | 76 - usr/src/uts/i86xpv/balloon/Makefile | 75 - usr/src/uts/i86xpv/boot/boot_xconsole.c | 242 -- usr/src/uts/i86xpv/consconfig_dacf/Makefile | 74 - usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_mca_xpv.c | 305 -- usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_poll_xpv.c | 200 -- usr/src/uts/i86xpv/cpu/scripts/Makefile | 46 - usr/src/uts/i86xpv/domcaps/Makefile | 75 - usr/src/uts/i86xpv/evtchn/Makefile | 75 - usr/src/uts/i86xpv/genassym/Makefile | 98 - usr/src/uts/i86xpv/generic_cpu/Makefile | 74 - usr/src/uts/i86xpv/genuineintel/Makefile | 76 - usr/src/uts/i86xpv/gfx_private/Makefile | 85 - usr/src/uts/i86xpv/io/balloon_drv.c | 197 -- usr/src/uts/i86xpv/io/domcaps.c | 187 - usr/src/uts/i86xpv/io/privcmd.c | 411 --- usr/src/uts/i86xpv/io/privcmd_hcall.c | 1252 ------- usr/src/uts/i86xpv/io/psm/mp_platform_xpv.c | 2153 ------------ usr/src/uts/i86xpv/io/psm/xpv_intr.c | 363 -- usr/src/uts/i86xpv/io/psm/xpv_psm.c | 1705 --------- usr/src/uts/i86xpv/io/psm/xpv_uppc.c | 924 ----- usr/src/uts/i86xpv/io/xpvtod.c | 191 -- usr/src/uts/i86xpv/ioat/Makefile | 91 - usr/src/uts/i86xpv/isa/Makefile | 117 - usr/src/uts/i86xpv/ml/hyperevent.s | 235 -- usr/src/uts/i86xpv/ml/panic_asm.s | 372 -- usr/src/uts/i86xpv/ml/xenguest.s | 57 - usr/src/uts/i86xpv/npe/Makefile | 94 - usr/src/uts/i86xpv/os/balloon.c | 1061 ------ usr/src/uts/i86xpv/os/evtchn.c | 1605 --------- usr/src/uts/i86xpv/os/mach_kdi.c | 262 -- usr/src/uts/i86xpv/os/mp_xen.c | 1057 ------ usr/src/uts/i86xpv/os/xen_machdep.c | 1397 -------- usr/src/uts/i86xpv/os/xen_mmu.c | 453 --- usr/src/uts/i86xpv/os/xpv_panic.c | 1027 ------ usr/src/uts/i86xpv/os/xpv_timestamp.c | 172 - usr/src/uts/i86xpv/pci-ide/Makefile | 89 - usr/src/uts/i86xpv/pci/Makefile | 92 - usr/src/uts/i86xpv/pit_beep/Makefile | 72 - usr/src/uts/i86xpv/privcmd/Makefile | 78 - usr/src/uts/i86xpv/rootnex/Makefile | 87 - usr/src/uts/i86xpv/unix/Makefile | 188 - usr/src/uts/i86xpv/unix/dboot/Mapfile.dboot | 59 - usr/src/uts/i86xpv/vm/seg_mf.c | 753 ---- usr/src/uts/i86xpv/xdb/Makefile | 82 - usr/src/uts/i86xpv/xdf/Makefile | 80 - usr/src/uts/i86xpv/xdt/Makefile | 55 - usr/src/uts/i86xpv/xenbus/Makefile | 81 - usr/src/uts/i86xpv/xencons/Makefile | 82 - usr/src/uts/i86xpv/xnb/Makefile | 94 - usr/src/uts/i86xpv/xnbe/Makefile | 91 - usr/src/uts/i86xpv/xnbo/Makefile | 91 - usr/src/uts/i86xpv/xnbu/Makefile | 91 - usr/src/uts/i86xpv/xnf/Makefile | 88 - usr/src/uts/i86xpv/xpv_autoconfig/Makefile | 75 - usr/src/uts/i86xpv/xpv_psm/Makefile | 95 - usr/src/uts/i86xpv/xpv_uppc/Makefile | 89 - usr/src/uts/i86xpv/xpvd/Makefile | 77 - usr/src/uts/i86xpv/xpvtap/Makefile | 92 - usr/src/uts/i86xpv/xpvtod/Makefile | 75 - usr/src/uts/i86xpv/xsvc/Makefile | 88 - usr/src/uts/intel/Makefile | 2 +- 231 files changed, 17 insertions(+), 68239 deletions(-) delete mode 100644 arch/x86/kernel/platform/i86pc/os/xpv_platform.c delete mode 100644 arch/x86/kernel/platform/i86xpv/include/Makefile delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/Makefile delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/balloon.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/balloon_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/cpr_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/domcaps_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/evtchn_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/machprivregs.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/privcmd_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/xen_mmu.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/xpv_impl.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/xpv_panic.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/sys/xpv_user.h delete mode 100644 arch/x86/kernel/platform/i86xpv/include/vm/Makefile delete mode 100644 arch/x86/kernel/platform/i86xpv/include/vm/seg_mf.h delete mode 100644 arch/x86/kernel/platform/i86xpv/mapfile-32 delete mode 100644 arch/x86/kernel/platform/i86xpv/mapfile-64 delete mode 100644 arch/x86/kernel/xen/os/hypercall.c delete mode 100644 usr/src/cmd/devfsadm/i386/xen_link.c delete mode 100644 usr/src/cmd/dtrace/test/tst/i86xpv/Makefile delete mode 100755 usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.basic.ksh delete mode 100755 usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh delete mode 100755 usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.memenable.ksh delete mode 100755 usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh delete mode 100755 usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh delete mode 100644 usr/src/cmd/mdb/i86xpv/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/Makefile.i86xpv delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/unix/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv/amd64/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_psm/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_psm/amd64/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile delete mode 100644 usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c delete mode 100644 usr/src/cmd/mdb/intel/modules/mdb_kb/Makefile delete mode 100644 usr/src/cmd/mdb/intel/modules/mdb_kb/amd64/Makefile delete mode 100644 usr/src/cmd/mdb/intel/modules/mdb_kb/mdb_kb.c rewrite usr/src/pkg/manifests/driver-xvm-pv.mf (98%) rewrite usr/src/pkg/manifests/system-kernel-dtrace-providers-xdt.mf (96%) delete mode 100644 usr/src/uts/common/xen/dtrace/xdt.c delete mode 100644 usr/src/uts/common/xen/dtrace/xdt.conf delete mode 100644 usr/src/uts/common/xen/io/blk_common.c delete mode 100644 usr/src/uts/common/xen/io/blk_common.h delete mode 100644 usr/src/uts/common/xen/io/blkif_impl.h delete mode 100644 usr/src/uts/common/xen/io/evtchn_dev.c delete mode 100644 usr/src/uts/common/xen/io/xdb.c delete mode 100644 usr/src/uts/common/xen/io/xdb.h delete mode 100644 usr/src/uts/common/xen/io/xdf.c delete mode 100644 usr/src/uts/common/xen/io/xdf.h delete mode 100644 usr/src/uts/common/xen/io/xenbus_client.c delete mode 100644 usr/src/uts/common/xen/io/xenbus_comms.c delete mode 100644 usr/src/uts/common/xen/io/xenbus_dev.c delete mode 100644 usr/src/uts/common/xen/io/xenbus_probe.c delete mode 100644 usr/src/uts/common/xen/io/xenbus_xs.c delete mode 100644 usr/src/uts/common/xen/io/xencons.c delete mode 100644 usr/src/uts/common/xen/io/xencons.conf delete mode 100644 usr/src/uts/common/xen/io/xencons.h delete mode 100644 usr/src/uts/common/xen/io/xnb.c delete mode 100644 usr/src/uts/common/xen/io/xnb.h delete mode 100644 usr/src/uts/common/xen/io/xnbe.c delete mode 100644 usr/src/uts/common/xen/io/xnbo.c delete mode 100644 usr/src/uts/common/xen/io/xnbu.c delete mode 100644 usr/src/uts/common/xen/io/xnf.c delete mode 100644 usr/src/uts/common/xen/io/xnf.h delete mode 100644 usr/src/uts/common/xen/io/xpv_autoconfig.c delete mode 100644 usr/src/uts/common/xen/io/xpvd.c delete mode 100644 usr/src/uts/common/xen/io/xpvd.conf delete mode 100644 usr/src/uts/common/xen/io/xpvtap.c delete mode 100644 usr/src/uts/common/xen/io/xpvtap.h delete mode 100644 usr/src/uts/common/xen/os/gnttab.c delete mode 100644 usr/src/uts/common/xen/os/xvdi.c delete mode 100644 usr/src/uts/common/xen/public/COPYING delete mode 100644 usr/src/uts/common/xen/public/README.DO_NOT_EDIT delete mode 100644 usr/src/uts/common/xen/public/arch-x86/xen-mca.h delete mode 100644 usr/src/uts/common/xen/public/arch-x86/xen-x86_32.h delete mode 100644 usr/src/uts/common/xen/public/arch-x86/xen-x86_64.h delete mode 100644 usr/src/uts/common/xen/public/arch-x86/xen.h delete mode 100644 usr/src/uts/common/xen/public/callback.h delete mode 100644 usr/src/uts/common/xen/public/domctl.h delete mode 100644 usr/src/uts/common/xen/public/elfnote.h delete mode 100644 usr/src/uts/common/xen/public/event_channel.h delete mode 100644 usr/src/uts/common/xen/public/features.h delete mode 100644 usr/src/uts/common/xen/public/grant_table.h delete mode 100644 usr/src/uts/common/xen/public/hvm/hvm_op.h delete mode 100644 usr/src/uts/common/xen/public/hvm/params.h delete mode 100644 usr/src/uts/common/xen/public/io/blkif.h delete mode 100644 usr/src/uts/common/xen/public/io/console.h delete mode 100644 usr/src/uts/common/xen/public/io/netif.h delete mode 100644 usr/src/uts/common/xen/public/io/protocols.h delete mode 100644 usr/src/uts/common/xen/public/io/ring.h delete mode 100644 usr/src/uts/common/xen/public/io/xenbus.h delete mode 100644 usr/src/uts/common/xen/public/io/xs_wire.h delete mode 100644 usr/src/uts/common/xen/public/memory.h delete mode 100644 usr/src/uts/common/xen/public/nmi.h delete mode 100644 usr/src/uts/common/xen/public/physdev.h delete mode 100644 usr/src/uts/common/xen/public/platform.h delete mode 100644 usr/src/uts/common/xen/public/sched.h delete mode 100644 usr/src/uts/common/xen/public/sysctl.h delete mode 100644 usr/src/uts/common/xen/public/trace.h delete mode 100644 usr/src/uts/common/xen/public/vcpu.h delete mode 100644 usr/src/uts/common/xen/public/version.h delete mode 100644 usr/src/uts/common/xen/public/xen-compat.h delete mode 100644 usr/src/uts/common/xen/public/xen.h delete mode 100644 usr/src/uts/common/xen/public/xsm/acm.h delete mode 100644 usr/src/uts/common/xen/public/xsm/acm_ops.h delete mode 100644 usr/src/uts/common/xen/sys/README delete mode 100644 usr/src/uts/common/xen/sys/evtchn.h delete mode 100644 usr/src/uts/common/xen/sys/gnttab.h delete mode 100644 usr/src/uts/common/xen/sys/privcmd.h delete mode 100644 usr/src/uts/common/xen/sys/xenbus.h delete mode 100644 usr/src/uts/common/xen/sys/xenbus_comms.h delete mode 100644 usr/src/uts/common/xen/sys/xenbus_impl.h delete mode 100644 usr/src/uts/common/xen/sys/xendev.h delete mode 100644 usr/src/uts/i86pc/i86hvm/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/Makefile.files delete mode 100644 usr/src/uts/i86pc/i86hvm/Makefile.i86hvm delete mode 100644 usr/src/uts/i86pc/i86hvm/Makefile.rules delete mode 100644 usr/src/uts/i86pc/i86hvm/Makefile.targ delete mode 100644 usr/src/uts/i86pc/i86hvm/hvm_bootstrap/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/hvm_cmdk/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/io/hvm_bootstrap.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/pv_cmdk.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/pv_rtls.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/pv_sd.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/xdf_shell.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/xdf_shell.h delete mode 100644 usr/src/uts/i86pc/i86hvm/io/xpv/evtchn.c delete mode 100644 usr/src/uts/i86pc/i86hvm/io/xpv/xpv.conf delete mode 100644 usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c delete mode 100644 usr/src/uts/i86pc/i86hvm/pv_cmdk/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/pv_rtls/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/pv_sd/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/xdf/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/xnf/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/xpv/Makefile delete mode 100644 usr/src/uts/i86pc/i86hvm/xpvd/Makefile delete mode 100644 usr/src/uts/i86xpv/Makefile delete mode 100644 usr/src/uts/i86xpv/Makefile.files delete mode 100644 usr/src/uts/i86xpv/Makefile.i86xpv delete mode 100644 usr/src/uts/i86xpv/Makefile.rules delete mode 100644 usr/src/uts/i86xpv/Makefile.targ delete mode 100644 usr/src/uts/i86xpv/amd_opteron/Makefile delete mode 100644 usr/src/uts/i86xpv/authenticamd/Makefile delete mode 100644 usr/src/uts/i86xpv/balloon/Makefile delete mode 100644 usr/src/uts/i86xpv/boot/boot_xconsole.c delete mode 100644 usr/src/uts/i86xpv/consconfig_dacf/Makefile delete mode 100644 usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_mca_xpv.c delete mode 100644 usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_poll_xpv.c delete mode 100644 usr/src/uts/i86xpv/cpu/scripts/Makefile delete mode 100644 usr/src/uts/i86xpv/domcaps/Makefile delete mode 100644 usr/src/uts/i86xpv/evtchn/Makefile delete mode 100644 usr/src/uts/i86xpv/genassym/Makefile delete mode 100644 usr/src/uts/i86xpv/generic_cpu/Makefile delete mode 100644 usr/src/uts/i86xpv/genuineintel/Makefile delete mode 100644 usr/src/uts/i86xpv/gfx_private/Makefile delete mode 100644 usr/src/uts/i86xpv/io/balloon_drv.c delete mode 100644 usr/src/uts/i86xpv/io/domcaps.c delete mode 100644 usr/src/uts/i86xpv/io/privcmd.c delete mode 100644 usr/src/uts/i86xpv/io/privcmd_hcall.c delete mode 100644 usr/src/uts/i86xpv/io/psm/mp_platform_xpv.c delete mode 100644 usr/src/uts/i86xpv/io/psm/xpv_intr.c delete mode 100644 usr/src/uts/i86xpv/io/psm/xpv_psm.c delete mode 100644 usr/src/uts/i86xpv/io/psm/xpv_uppc.c delete mode 100644 usr/src/uts/i86xpv/io/xpvtod.c delete mode 100644 usr/src/uts/i86xpv/ioat/Makefile delete mode 100644 usr/src/uts/i86xpv/isa/Makefile delete mode 100644 usr/src/uts/i86xpv/ml/hyperevent.s delete mode 100644 usr/src/uts/i86xpv/ml/panic_asm.s delete mode 100644 usr/src/uts/i86xpv/ml/xenguest.s delete mode 100644 usr/src/uts/i86xpv/npe/Makefile delete mode 100644 usr/src/uts/i86xpv/os/balloon.c delete mode 100644 usr/src/uts/i86xpv/os/evtchn.c delete mode 100644 usr/src/uts/i86xpv/os/mach_kdi.c delete mode 100644 usr/src/uts/i86xpv/os/mp_xen.c delete mode 100644 usr/src/uts/i86xpv/os/xen_machdep.c delete mode 100644 usr/src/uts/i86xpv/os/xen_mmu.c delete mode 100644 usr/src/uts/i86xpv/os/xpv_panic.c delete mode 100644 usr/src/uts/i86xpv/os/xpv_timestamp.c delete mode 100644 usr/src/uts/i86xpv/pci-ide/Makefile delete mode 100644 usr/src/uts/i86xpv/pci/Makefile delete mode 100644 usr/src/uts/i86xpv/pit_beep/Makefile delete mode 100644 usr/src/uts/i86xpv/privcmd/Makefile delete mode 100644 usr/src/uts/i86xpv/rootnex/Makefile delete mode 100644 usr/src/uts/i86xpv/unix/Makefile delete mode 100644 usr/src/uts/i86xpv/unix/dboot/Mapfile.dboot delete mode 100644 usr/src/uts/i86xpv/vm/seg_mf.c delete mode 100644 usr/src/uts/i86xpv/xdb/Makefile delete mode 100644 usr/src/uts/i86xpv/xdf/Makefile delete mode 100644 usr/src/uts/i86xpv/xdt/Makefile delete mode 100644 usr/src/uts/i86xpv/xenbus/Makefile delete mode 100644 usr/src/uts/i86xpv/xencons/Makefile delete mode 100644 usr/src/uts/i86xpv/xnb/Makefile delete mode 100644 usr/src/uts/i86xpv/xnbe/Makefile delete mode 100644 usr/src/uts/i86xpv/xnbo/Makefile delete mode 100644 usr/src/uts/i86xpv/xnbu/Makefile delete mode 100644 usr/src/uts/i86xpv/xnf/Makefile delete mode 100644 usr/src/uts/i86xpv/xpv_autoconfig/Makefile delete mode 100644 usr/src/uts/i86xpv/xpv_psm/Makefile delete mode 100644 usr/src/uts/i86xpv/xpv_uppc/Makefile delete mode 100644 usr/src/uts/i86xpv/xpvd/Makefile delete mode 100644 usr/src/uts/i86xpv/xpvtap/Makefile delete mode 100644 usr/src/uts/i86xpv/xpvtod/Makefile delete mode 100644 usr/src/uts/i86xpv/xsvc/Makefile diff --git a/FEATURES.txt b/FEATURES.txt index 3c4e7c7657..d292dce678 100644 --- a/FEATURES.txt +++ b/FEATURES.txt @@ -11,6 +11,7 @@ changed. -------------- - 32-bit x86 kernel support (32-bit x86 applications are still supported) - sparc support + - xen domU and dom0 support - Trusted Solaris aka. Trusted Extensions - SVR4 pkg support & code - solaris10 zone brand diff --git a/arch/x86/Sconfig b/arch/x86/Sconfig index a593812c1e..6182a80d6b 100644 --- a/arch/x86/Sconfig +++ b/arch/x86/Sconfig @@ -18,9 +18,9 @@ ISA64 'amd64) - (select + (const PLATFORM - ('i86pc 'i86xpv)) + 'i86pc) (const ; Build 64-bit kernel modules diff --git a/arch/x86/kernel/platform/i86pc/os/mlsetup.c b/arch/x86/kernel/platform/i86pc/os/mlsetup.c index e0ad359d81..67d0dde169 100644 --- a/arch/x86/kernel/platform/i86pc/os/mlsetup.c +++ b/arch/x86/kernel/platform/i86pc/os/mlsetup.c @@ -63,11 +63,6 @@ #include #include #include -#ifdef __xpv -#include -#else -#include -#endif /* * some globals for patching the result of cpuid @@ -183,9 +178,6 @@ mlsetup(struct regs *rp) cpuid_pass1(cpu[0], x86_featureset); #if !defined(__xpv) - if ((get_hwenv() & HW_XEN_HVM) != 0) - xen_hvm_init(); - /* * Before we do anything with the TSCs, we need to work around * Intel erratum BT81. On some CPUs, warm reset does not diff --git a/arch/x86/kernel/platform/i86pc/os/xpv_platform.c b/arch/x86/kernel/platform/i86pc/os/xpv_platform.c deleted file mode 100644 index 14bdb1ab44..0000000000 --- a/arch/x86/kernel/platform/i86pc/os/xpv_platform.c +++ /dev/null @@ -1,255 +0,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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#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 - -static int xen_hvm_inited; - -/* - * This structure is ordinarily constructed by Xen. In the HVM world, we - * manually fill in the few fields the PV drivers need. - */ -static start_info_t __xen_info; -start_info_t *xen_info = NULL; - -static int xen_bits = -1; -static int xen_major = -1, xen_minor = -1; - -/* - * Feature bits; more bits will be added, like direct I/O, etc. - */ -#define XEN_HVM_HYPERCALLS 0x0001 -#define XEN_HVM_TLBFLUSH 0x0002 -static uint64_t xen_hvm_features; - -/* Metadata page shared between domain and Xen */ -shared_info_t *HYPERVISOR_shared_info = NULL; -pfn_t xen_shared_info_frame; - -/* Page containing code to issue hypercalls. */ -extern caddr_t hypercall_page; -extern caddr_t hypercall_shared_info_page; - -static int -hvm_get_param(int param_id, uint64_t *val) -{ - struct xen_hvm_param xhp; - - xhp.domid = DOMID_SELF; - xhp.index = param_id; - if ((HYPERVISOR_hvm_op(HVMOP_get_param, &xhp) < 0)) - return (-1); - *val = xhp.value; - return (0); -} - -void -xen_hvm_init(void) -{ - struct cpuid_regs cp; - uint32_t xen_signature[4], base; - char *xen_str; - struct xen_add_to_physmap xatp; - xen_capabilities_info_t caps; - pfn_t pfn; - uint64_t msrval, val; - - if (xen_hvm_inited != 0) - return; - - xen_hvm_inited = 1; - - /* - * Xen's pseudo-cpuid function returns a string representing - * the Xen signature in %ebx, %ecx, and %edx. - * Loop over the base values, since it may be different if - * the hypervisor has hyper-v emulation switched on. - * - * %eax contains the maximum supported cpuid function. - */ - for (base = 0x40000000; base < 0x40010000; base += 0x100) { - cp.cp_eax = base; - (void) __cpuid_insn(&cp); - xen_signature[0] = cp.cp_ebx; - xen_signature[1] = cp.cp_ecx; - xen_signature[2] = cp.cp_edx; - xen_signature[3] = 0; - xen_str = (char *)xen_signature; - if (strcmp("XenVMMXenVMM", xen_str) == 0 && - cp.cp_eax >= (base + 2)) - break; - } - if (base >= 0x40010000) - return; - - /* - * cpuid function at base + 1 returns the Xen version in %eax. The - * top 16 bits are the major version, the bottom 16 are the minor - * version. - */ - cp.cp_eax = base + 1; - (void) __cpuid_insn(&cp); - xen_major = cp.cp_eax >> 16; - xen_minor = cp.cp_eax & 0xffff; - - /* - * Below version 3.1 we can't do anything special as a HVM domain; - * the PV drivers don't work, many hypercalls are not available, - * etc. - */ - if (xen_major < 3 || (xen_major == 3 && xen_minor < 1)) - return; - - /* - * cpuid function at base + 2 returns information about the - * hypercall page. %eax nominally contains the number of pages - * with hypercall code, but according to the Xen guys, "I'll - * guarantee that remains one forever more, so you can just - * allocate a single page and get quite upset if you ever see CPUID - * return more than one page." %ebx contains an MSR we use to ask - * Xen to remap each page at a specific pfn. - */ - cp.cp_eax = base + 2; - (void) __cpuid_insn(&cp); - - /* - * Let Xen know where we want the hypercall page mapped. We - * already have a page allocated in the .text section to simplify - * the wrapper code. - */ - pfn = va_to_pfn(&hypercall_page); - msrval = mmu_ptob(pfn); - wrmsr(cp.cp_ebx, msrval); - - /* Fill in the xen_info data */ - xen_info = &__xen_info; - (void) sprintf(xen_info->magic, "xen-%d.%d", xen_major, xen_minor); - - if (hvm_get_param(HVM_PARAM_STORE_PFN, &val) < 0) - return; - /* - * The first hypercall worked, so mark hypercalls as working. - */ - xen_hvm_features |= XEN_HVM_HYPERCALLS; - - xen_info->store_mfn = (mfn_t)val; - if (hvm_get_param(HVM_PARAM_STORE_EVTCHN, &val) < 0) - return; - xen_info->store_evtchn = (mfn_t)val; - - /* Figure out whether the hypervisor is 32-bit or 64-bit. */ - if ((HYPERVISOR_xen_version(XENVER_capabilities, &caps) == 0)) { - ((char *)(caps))[sizeof (caps) - 1] = '\0'; - if (strstr(caps, "x86_64") != NULL) - xen_bits = 64; - else if (strstr(caps, "x86_32") != NULL) - xen_bits = 32; - } - - if (xen_bits < 0) - return; -#ifdef __amd64 - ASSERT(xen_bits == 64); -#endif - - /* - * Allocate space for the shared_info page and tell Xen where it - * is. - */ - xen_shared_info_frame = va_to_pfn(&hypercall_shared_info_page); - xatp.domid = DOMID_SELF; - xatp.idx = 0; - xatp.space = XENMAPSPACE_shared_info; - xatp.gpfn = xen_shared_info_frame; - if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) - return; - - HYPERVISOR_shared_info = (void *)&hypercall_shared_info_page; - - /* - * A working HVM tlb flush hypercall was introduced in Xen 3.3. - */ - if (xen_major > 3 || (xen_major == 3 && xen_minor >= 3)) - xen_hvm_features |= XEN_HVM_TLBFLUSH; -} - -/* - * Returns: - * -1 if a feature is not available - * 1 if a boolean feature is available - * > 0 if numeric feature is available - */ -int -xpv_feature(int which) -{ - switch (which) { - case XPVF_BITS: - return (xen_bits); - case XPVF_VERSION_MAJOR: - return (xen_major); - case XPVF_VERSION_MINOR: - return (xen_minor); - case XPVF_HYPERCALLS: - if (xen_hvm_features & XEN_HVM_HYPERCALLS) - return (1); - break; - case XPVF_SHARED_INFO: - if (HYPERVISOR_shared_info != NULL) - return (1); - break; - case XPVF_TLB_FLUSH: - if (xen_hvm_features & XEN_HVM_TLBFLUSH) - return (1); - break; - default: - break; - } - - return (-1); -} diff --git a/arch/x86/kernel/platform/i86xpv/include/Makefile b/arch/x86/kernel/platform/i86xpv/include/Makefile deleted file mode 100644 index d0e4b6ff93..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -SUBDIR = vm \ - sys - -.include diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/Makefile b/arch/x86/kernel/platform/i86xpv/include/sys/Makefile deleted file mode 100644 index 14692ed73a..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -INCDIR= /usr/platform/i86xpv/include/sys -INCS= balloon.h \ - machprivregs.h \ - xen_mmu.h \ - xpv_impl.h - -.include -.include -.include - -.include <${SRCTOP}/Makefile.cfgparam> diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/balloon.h b/arch/x86/kernel/platform/i86xpv/include/sys/balloon.h deleted file mode 100644 index 641147b539..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/balloon.h +++ /dev/null @@ -1,57 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_BALLOON_H -#define _SYS_BALLOON_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BALLOON_DEV_NAME "balloon" -#define BALLOON_PATHNAME "xen/" BALLOON_DEV_NAME - -#define BALLOON_DRIVER_NAME "balloon" - -#define BLN_IOCTL_BASE ('B' << 24) | ('A' << 16) - -/* - * To return the desired value. These defines are copied in balloon.py - * in the hypervisor gate, so woe befall anyone who changes these. - */ -#define BLN_IOCTL_CURRENT (BLN_IOCTL_BASE | 0x1) -#define BLN_IOCTL_TARGET (BLN_IOCTL_BASE | 0x2) -#define BLN_IOCTL_LOW (BLN_IOCTL_BASE | 0x3) -#define BLN_IOCTL_HIGH (BLN_IOCTL_BASE | 0x4) -#define BLN_IOCTL_LIMIT (BLN_IOCTL_BASE | 0x5) - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_BALLOON_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/balloon_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/balloon_impl.h deleted file mode 100644 index d708151e1e..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/balloon_impl.h +++ /dev/null @@ -1,76 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_BALLOON_IMPL_H -#define _SYS_BALLOON_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include /* to get typedef of mfn_t */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file contains interfaces for both the balloon kernel thread - * and the balloon driver. The balloon device is installed under /dev/xen, - * and can be used with the ioctl values in balloon.h to get the balloon - * memory status. - */ - -/* balloon thread declarations */ -void balloon_init(pgcnt_t); -size_t balloon_values(int); -void balloon_drv_added(int64_t); -void balloon_drv_subtracted(int64_t); -long balloon_alloc_pages(uint_t, mfn_t *); -long balloon_free_pages(uint_t, mfn_t *, caddr_t, pfn_t *); -long balloon_replace_pages(uint_t, page_t **, uint_t, uint_t, mfn_t *); - -/* balloon driver information */ -#define BALLOON_MINOR 0 - -/* - * Critical stats for the balloon thread. All values are in pages. - */ -typedef struct { - pgcnt_t bln_current_pages; /* current reservation */ - pgcnt_t bln_new_target; /* target value for reservation */ - pgcnt_t bln_max_pages; /* first pfn for which we don't have a page_t */ - pgcnt_t bln_low; /* lowest value of reservation since boot */ - pgcnt_t bln_high; /* highest value of reservation since boot */ - spgcnt_t bln_hv_pages; /* number of total pages given to hypervisor */ - spgcnt_t bln_hard_limit; /* domain's max-mem limit */ -} bln_stats_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_BALLOON_IMPL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/cpr_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/cpr_impl.h deleted file mode 100644 index a58d569795..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/cpr_impl.h +++ /dev/null @@ -1,59 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_CPR_IMPL_H -#define _SYS_CPR_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef _ASM - -#include -#include -#include - - -typedef uint64_t cpr_ptr; -typedef uint64_t cpr_ext; - -struct cpr_map_info { - cpr_ptr virt; - cpr_ext phys; - uint_t size; -}; - -#endif /* _ASM */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_CPR_IMPL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/domcaps_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/domcaps_impl.h deleted file mode 100644 index 937ad3cb70..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/domcaps_impl.h +++ /dev/null @@ -1,54 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_DOMCAPS_IMPL_H -#define _SYS_DOMCAPS_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * /dev names: - * /dev/xen/ - containing directory - * capabilities - domain properties - */ - -#define DOMCAPS_DRIVER_NAME "domcaps" - -#define DOMCAPS_MINOR 0 - -#define DOMCAPS_DEV_NAME "capabilities" -#define DOMCAPS_PATHNAME "xen/" DOMCAPS_DEV_NAME - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_DOMCAPS_IMPL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/evtchn_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/evtchn_impl.h deleted file mode 100644 index dc79cf9bfd..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/evtchn_impl.h +++ /dev/null @@ -1,199 +0,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. - */ -/* - * evtchn.h (renamed to evtchn_impl.h) - * - * Communication via Xen event channels. - * Also definitions for the device that demuxes notifications to userspace. - * - * Copyright (c) 2004-2005, K A Fraser - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _SYS_EVTCHN_H -#define _SYS_EVTCHN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* evtchn binding types */ -#define IRQT_UNBOUND 0 /* unassigned irq */ -#define IRQT_PIRQ 1 /* IRQ from phys hdw device */ -#define IRQT_VIRQ 2 /* Virtual IRQ from Xen */ -#define IRQT_IPI 3 /* Inter VCPU interrupt IRQ */ -#define IRQT_EVTCHN 4 /* Virtual device IRQ */ -#define IRQT_DEV_EVTCHN 5 /* Special evtchn device IRQ */ - -#define SET_EVTCHN_BIT(bit, arrayp) \ - ((arrayp)[bit >> EVTCHN_SHIFT] |= \ - (1ul << ((bit) & ((1ul << EVTCHN_SHIFT) - 1)))) -#define CLEAR_EVTCHN_BIT(bit, arrayp) \ - ((arrayp)[bit >> EVTCHN_SHIFT] &= \ - ~((1ul << ((bit) & ((1ul << EVTCHN_SHIFT) - 1))))) -#define TEST_EVTCHN_BIT(bit, arrayp) \ - ((arrayp)[bit >> EVTCHN_SHIFT] & \ - (1ul << ((bit) & ((1ul << EVTCHN_SHIFT) - 1)))) - -/* Xen will never allocate port zero for any purpose. */ -#define INVALID_EVTCHN 0 - -/* XXPV - should these defines be somewhere else? xenos.h perhaps? */ - -#define IPL_DEBUG 15 /* domain debug interrupt */ -#define IPL_CONS 9 -#define IPL_VIF 6 -#define IPL_VBD 5 -#define IPL_EVTCHN 1 - -#define PIRQ_BASE 0 /* base of pirq range */ -#define NR_PIRQS 256 /* Number of supported physical irqs */ -#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS) /* base of dynamic irq range */ -#define NR_DYNIRQS 256 /* Number of dynamic irqs */ -#define NR_IRQS (NR_PIRQS + NR_DYNIRQS) /* total irq count */ - -#define PIRQ_TO_IRQ(pirq) ((pirq) + PIRQ_BASE) -#define IRQ_TO_PIRQ(irq) ((irq) - PIRQ_BASE) - -#define DYNIRQ_TO_IRQ(dirq) ((dirq) + DYNIRQ_BASE) -#define IRQ_TO_DYNIRQ(irq) ((irq) - DYNIRQ_BASE) - -#if defined(_LP64) -#define EVTCHN_SHIFT 6 /* log2(NBBY * sizeof (ulong_t)) */ -#else -#define EVTCHN_SHIFT 5 /* log2(NBBY * sizeof (ulong_t)) */ -#endif - -#define INVALID_IRQ -1 - -extern int ec_dev_irq; -extern kmutex_t ec_lock; - -typedef struct mec_info { - ushort_t mi_evtchns[NCPU]; /* event channels for this IRQ */ - short mi_irq; /* the IRQ, or INVALID_IRQ */ - char mi_shared; /* one evtchn for all CPUs? */ -} mec_info_t; - -/* - * Careful: ii_ipl is /only/ set if there's a handler for this IRQ. - */ -typedef struct irq_info { - union { - ushort_t evtchn; /* event channel */ - ushort_t index; /* index to next table if mec */ - } ii_u; - uchar_t ii_type; /* IRQ type as above */ - union { - uchar_t ipl; /* IPL of IRQ, != 0 => has handler */ - uchar_t has_handler; /* alternate name for ipl */ - } ii_u2; -} irq_info_t; - -extern int ec_is_edge_pirq(int); -extern int ec_init(void); -extern void ec_init_debug_irq(void); -extern void ec_suspend(void); -extern void ec_resume(void); -extern void ec_wait_on_evtchn(int, int (*)(void *), void *); -extern void ec_wait_on_ipi(int, int (*)(void *), void *); - -extern void ec_setup_pirq(int, int, cpuset_t *); -extern void ec_set_irq_affinity(int, cpuset_t); -extern int ec_set_irq_priority(int, int); - -extern int ec_bind_ipi_to_irq(int, int); -extern void ec_bind_cpu_ipis(int); -extern int ec_bind_evtchn_to_irq(int); -extern int ec_bind_virq_to_irq(int, int); -extern void ec_unbind_irq(int irq); - -extern void ec_send_ipi(int, int); -extern void ec_try_ipi(int, int); -extern void ec_clear_irq(int); -extern void ec_unmask_irq(int); -extern void ec_try_unmask_irq(int); -extern int ec_block_irq(int); -extern void ec_unpend_irq(int); -extern int ec_irq_needs_rebind(int, int); -extern int ec_irq_rebindable(int); -extern int ec_pending_irq(unsigned int); -extern void ec_enable_irq(unsigned int); -extern void ec_disable_irq(unsigned int); - -extern int xen_bind_interdomain(int, int, int *); -extern int xen_bind_virq(unsigned int, processorid_t, int *); -extern int xen_alloc_unbound_evtchn(int, int *); -extern void ec_bind_vcpu(int, int); - -extern int ec_mask_evtchn(unsigned int); -extern void ec_unmask_evtchn(unsigned int); -extern void ec_clear_evtchn(unsigned int); - -extern void ec_notify_via_evtchn(unsigned int); - -/* - * /dev/xen/evtchn handling. - */ -extern void ec_irq_add_evtchn(int, int); -extern void ec_irq_rm_evtchn(int, int); -extern int ec_dev_alloc_irq(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_EVTCHN_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/machprivregs.h b/arch/x86/kernel/platform/i86xpv/include/sys/machprivregs.h deleted file mode 100644 index 64780f0c4e..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/machprivregs.h +++ /dev/null @@ -1,544 +0,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. - */ - -#ifndef _SYS_MACHPRIVREGS_H -#define _SYS_MACHPRIVREGS_H - -#include - -/* - * Platform dependent instruction sequences for manipulating - * privileged state - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * CLI and STI are quite complex to virtualize! - */ - -#if defined(__amd64) - -#define CURVCPU(r) \ - movq %gs:CPU_VCPU_INFO, r - -#define CURTHREAD(r) \ - movq %gs:CPU_THREAD, r - -#elif defined(__i386) - -#define CURVCPU(r) \ - movl %gs:CPU_VCPU_INFO, r - -#define CURTHREAD(r) \ - movl %gs:CPU_THREAD, r - -#endif /* __i386 */ - -#define XEN_TEST_EVENT_PENDING(r) \ - testb $0xff, VCPU_INFO_EVTCHN_UPCALL_PENDING(r) - -#define XEN_SET_UPCALL_MASK(r) \ - movb $1, VCPU_INFO_EVTCHN_UPCALL_MASK(r) - -#define XEN_GET_UPCALL_MASK(r, mask) \ - movb VCPU_INFO_EVTCHN_UPCALL_MASK(r), mask - -#define XEN_TEST_UPCALL_MASK(r) \ - testb $1, VCPU_INFO_EVTCHN_UPCALL_MASK(r) - -#define XEN_CLEAR_UPCALL_MASK(r) \ - ASSERT_UPCALL_MASK_IS_SET; \ - movb $0, VCPU_INFO_EVTCHN_UPCALL_MASK(r) - -#ifdef DEBUG - -/* - * Much logic depends on the upcall mask being set at - * various points in the code; use this macro to validate. - * - * Need to use CURVCPU(r) to establish the vcpu pointer. - */ -#if defined(__amd64) - -#define ASSERT_UPCALL_MASK_IS_SET \ - pushq %r11; \ - CURVCPU(%r11); \ - XEN_TEST_UPCALL_MASK(%r11); \ - jne 6f; \ - cmpl $0, stistipanic(%rip); \ - jle 6f; \ - movl $-1, stistipanic(%rip); \ - movq stistimsg(%rip), %rdi; \ - xorl %eax, %eax; \ - call panic; \ -6: pushq %rax; \ - pushq %rbx; \ - movl %gs:CPU_ID, %eax; \ - leaq .+0(%rip), %r11; \ - leaq laststi(%rip), %rbx; \ - movq %r11, (%rbx, %rax, 8); \ - popq %rbx; \ - popq %rax; \ - popq %r11 - -#define SAVE_CLI_LOCATION \ - pushq %rax; \ - pushq %rbx; \ - pushq %rcx; \ - movl %gs:CPU_ID, %eax; \ - leaq .+0(%rip), %rcx; \ - leaq lastcli, %rbx; \ - movq %rcx, (%rbx, %rax, 8); \ - popq %rcx; \ - popq %rbx; \ - popq %rax; \ - -#elif defined(__i386) - -#define ASSERT_UPCALL_MASK_IS_SET \ - pushl %ecx; \ - CURVCPU(%ecx); \ - XEN_TEST_UPCALL_MASK(%ecx); \ - jne 6f; \ - cmpl $0, stistipanic; \ - jle 6f; \ - movl $-1, stistipanic; \ - movl stistimsg, %ecx; \ - pushl %ecx; \ - call panic; \ -6: pushl %eax; \ - pushl %ebx; \ - movl %gs:CPU_ID, %eax; \ - leal .+0, %ecx; \ - leal laststi, %ebx; \ - movl %ecx, (%ebx, %eax, 4); \ - popl %ebx; \ - popl %eax; \ - popl %ecx - -#define SAVE_CLI_LOCATION \ - pushl %eax; \ - pushl %ebx; \ - pushl %ecx; \ - movl %gs:CPU_ID, %eax; \ - leal .+0, %ecx; \ - leal lastcli, %ebx; \ - movl %ecx, (%ebx, %eax, 4); \ - popl %ecx; \ - popl %ebx; \ - popl %eax; \ - -#endif /* __i386 */ - -#else /* DEBUG */ - -#define ASSERT_UPCALL_MASK_IS_SET /* empty */ -#define SAVE_CLI_LOCATION /* empty */ - -#endif /* DEBUG */ - -#define KPREEMPT_DISABLE(t) \ - addb $1, T_PREEMPT(t) - -#define KPREEMPT_ENABLE_NOKP(t) \ - subb $1, T_PREEMPT(t) - -#define CLI(r) \ - CURTHREAD(r); \ - KPREEMPT_DISABLE(r); \ - CURVCPU(r); \ - XEN_SET_UPCALL_MASK(r); \ - SAVE_CLI_LOCATION; \ - CURTHREAD(r); \ - KPREEMPT_ENABLE_NOKP(r) - -#define CLIRET(r, ret) \ - CURTHREAD(r); \ - KPREEMPT_DISABLE(r); \ - CURVCPU(r); \ - XEN_GET_UPCALL_MASK(r, ret); \ - XEN_SET_UPCALL_MASK(r); \ - SAVE_CLI_LOCATION; \ - CURTHREAD(r); \ - KPREEMPT_ENABLE_NOKP(r) - -/* - * We use the fact that HYPERVISOR_block will clear the upcall mask - * for us and then give us an upcall if there is a pending event - * to achieve getting a callback on this cpu without the danger of - * being preempted and migrating to another cpu between the upcall - * enable and the callback delivery. - */ -#if defined(__amd64) - -#define STI_CLOBBER /* clobbers %rax, %rdi, %r11 */ \ - CURVCPU(%r11); \ - ASSERT_UPCALL_MASK_IS_SET; \ - movw $0x100, %ax; /* assume mask set, pending clear */ \ - movw $0, %di; /* clear mask and pending */ \ - lock; \ - cmpxchgw %di, VCPU_INFO_EVTCHN_UPCALL_PENDING(%r11); \ - jz 7f; /* xchg worked, we're done */ \ - movl $__HYPERVISOR_sched_op, %eax; /* have pending upcall */ \ - movl $SCHEDOP_block, %edi; \ - pushq %rsi; /* hypercall clobbers C param regs plus r10 */ \ - pushq %rcx; \ - pushq %rdx; \ - pushq %r8; \ - pushq %r9; \ - pushq %r10; \ - TRAP_INSTR; /* clear upcall mask, force upcall */ \ - popq %r10; \ - popq %r9; \ - popq %r8; \ - popq %rdx; \ - popq %rcx; \ - popq %rsi; \ -7: - -#define STI \ - pushq %r11; \ - pushq %rdi; \ - pushq %rax; \ - STI_CLOBBER; /* clobbers %r11, %rax, %rdi */ \ - popq %rax; \ - popq %rdi; \ - popq %r11 - -#elif defined(__i386) - -#define STI_CLOBBER /* clobbers %eax, %ebx, %ecx */ \ - CURVCPU(%ecx); \ - ASSERT_UPCALL_MASK_IS_SET; \ - movw $0x100, %ax; /* assume mask set, pending clear */ \ - movw $0, %bx; /* clear mask and pending */ \ - lock; \ - cmpxchgw %bx, VCPU_INFO_EVTCHN_UPCALL_PENDING(%ecx); \ - jz 7f; /* xchg worked, we're done */ \ - movl $__HYPERVISOR_sched_op, %eax; /* have pending upcall */ \ - movl $SCHEDOP_block, %ebx; \ - TRAP_INSTR; /* clear upcall mask, force upcall */ \ -7: - -#define STI \ - pushl %eax; \ - pushl %ebx; \ - pushl %ecx; \ - STI_CLOBBER; /* clobbers %eax, %ebx, %ecx */ \ - popl %ecx; \ - popl %ebx; \ - popl %eax - -#endif /* __i386 */ - -/* - * Map the PS_IE bit to the hypervisor's event mask bit - * To -set- the event mask, we have to do a CLI - * To -clear- the event mask, we have to do a STI - * (with all the accompanying pre-emption and callbacks, ick) - * - * And vice versa. - */ - -#if defined(__amd64) - -#define IE_TO_EVENT_MASK(rtmp, rfl) \ - testq $PS_IE, rfl; \ - jnz 4f; \ - CLI(rtmp); \ - jmp 5f; \ -4: STI; \ -5: - -#define EVENT_MASK_TO_IE(rtmp, rfl) \ - andq $_BITNOT(PS_IE), rfl; \ - CURVCPU(rtmp); \ - XEN_TEST_UPCALL_MASK(rtmp); \ - jnz 1f; \ - orq $PS_IE, rfl; \ -1: - -#elif defined(__i386) - -#define IE_TO_EVENT_MASK(rtmp, rfl) \ - testl $PS_IE, rfl; \ - jnz 4f; \ - CLI(rtmp); \ - jmp 5f; \ -4: STI; \ -5: - -#define EVENT_MASK_TO_IE(rtmp, rfl) \ - andl $_BITNOT(PS_IE), rfl; \ - CURVCPU(rtmp); \ - XEN_TEST_UPCALL_MASK(rtmp); \ - jnz 1f; \ - orl $PS_IE, rfl; \ -1: - -#endif /* __i386 */ - -/* - * Used to re-enable interrupts in the body of exception handlers - */ - -#if defined(__amd64) - -#define ENABLE_INTR_FLAGS \ - pushq $F_ON; \ - popfq; \ - STI - -#elif defined(__i386) - -#define ENABLE_INTR_FLAGS \ - pushl $F_ON; \ - popfl; \ - STI - -#endif /* __i386 */ - -/* - * Virtualize IRET and SYSRET - */ - -#if defined(__amd64) - -#if defined(DEBUG) - -/* - * Die nastily with a #ud trap if we are about to switch to user - * mode in HYPERVISOR_IRET and RUPDATE_PENDING is set. - */ -#define __ASSERT_NO_RUPDATE_PENDING \ - pushq %r15; \ - cmpw $KCS_SEL, 0x10(%rsp); \ - je 1f; \ - movq %gs:CPU_THREAD, %r15; \ - movq T_LWP(%r15), %r15; \ - testb $0x1, PCB_RUPDATE(%r15); \ - je 1f; \ - ud2; \ -1: popq %r15 - -#else /* DEBUG */ - -#define __ASSERT_NO_RUPDATE_PENDING - -#endif /* DEBUG */ - -/* - * Switching from guest kernel to user mode. - * flag == VGCF_IN_SYSCALL => return via sysret - * flag == 0 => return via iretq - * - * See definition in public/arch-x86_64.h. Stack going in must be: - * rax, r11, rcx, flags, rip, cs, rflags, rsp, ss. - */ -#define HYPERVISOR_IRET(flag) \ - __ASSERT_NO_RUPDATE_PENDING; \ - pushq $flag; \ - pushq %rcx; \ - pushq %r11; \ - pushq %rax; \ - movl $__HYPERVISOR_iret, %eax; \ - syscall; \ - ud2 /* die nastily if we return! */ - -#define IRET HYPERVISOR_IRET(0) - -/* - * XXPV: Normally we would expect to use sysret to return from kernel to - * user mode when using the syscall instruction. The iret hypercall - * does support both iret and sysret semantics. For us to use sysret - * style would require that we use the hypervisor's private descriptors - * that obey syscall instruction's imposed segment selector ordering. - * With iret we can use whatever %cs value we choose. We should fix - * this to use sysret one day. - */ -#define SYSRETQ HYPERVISOR_IRET(0) -#define SYSRETL ud2 /* 32-bit syscall/sysret not supported */ -#define SWAPGS /* empty - handled in hypervisor */ - -#elif defined(__i386) - -/* - * Switching from guest kernel to user mode. - * See definition in public/arch-x86_32.h. Stack going in must be: - * eax, flags, eip, cs, eflags, esp, ss. - */ -#define HYPERVISOR_IRET \ - pushl %eax; \ - movl $__HYPERVISOR_iret, %eax; \ - int $0x82; \ - ud2 /* die nastily if we return! */ - -#define IRET HYPERVISOR_IRET -#define SYSRET ud2 /* 32-bit syscall/sysret not supported */ - -#endif /* __i386 */ - - -/* - * Xen 3.x wedges the current value of upcall_mask into unused byte of - * saved %cs on stack at the time of passing through a trap or interrupt - * gate. Since Xen also updates PS_IE in %[e,r]lags as well, we always - * mask off the saved upcall mask so the kernel and/or tools like debuggers - * will not be confused about bits set in reserved portions of %cs slot. - * - * See xen/include/public/arch-x86_[32,64].h:cpu_user_regs_t for details. - */ -#if defined(__amd64) - -#define CLEAN_CS movb $0, REGOFF_CS+4(%rsp) - -#elif defined(__i386) - -#define CLEAN_CS movb $0, REGOFF_CS+2(%esp) - -#endif /* __i386 */ - -/* - * All exceptions for amd64 have %r11 and %rcx on the stack. - * Just pop them back into their appropriate registers and - * let it get saved as is running native. - */ -#if defined(__amd64) - -#define XPV_TRAP_POP \ - popq %rcx; \ - popq %r11 - -#define XPV_TRAP_PUSH \ - pushq %r11; \ - pushq %rcx - -#endif /* __amd64 */ - - -/* - * Macros for saving the original segment registers and restoring them - * for fast traps. - */ -#if defined(__amd64) - -/* - * Smaller versions of INTR_PUSH and INTR_POP for fast traps. - * The following registers have been pushed onto the stack by - * hardware at this point: - * - * greg_t r_rip; - * greg_t r_cs; - * greg_t r_rfl; - * greg_t r_rsp; - * greg_t r_ss; - * - * This handler is executed both by 32-bit and 64-bit applications. - * 64-bit applications allow us to treat the set (%rdi, %rsi, %rdx, - * %rcx, %r8, %r9, %r10, %r11, %rax) as volatile across function calls. - * However, 32-bit applications only expect (%eax, %edx, %ecx) to be volatile - * across a function call -- in particular, %esi and %edi MUST be saved! - * - * We could do this differently by making a FAST_INTR_PUSH32 for 32-bit - * programs, and FAST_INTR_PUSH for 64-bit programs, but it doesn't seem - * particularly worth it. - * - */ -#define FAST_INTR_PUSH \ - INTGATE_INIT_KERNEL_FLAGS; \ - popq %rcx; \ - popq %r11; \ - subq $REGOFF_RIP, %rsp; \ - movq %rsi, REGOFF_RSI(%rsp); \ - movq %rdi, REGOFF_RDI(%rsp); \ - CLEAN_CS - -#define FAST_INTR_POP \ - movq REGOFF_RSI(%rsp), %rsi; \ - movq REGOFF_RDI(%rsp), %rdi; \ - addq $REGOFF_RIP, %rsp - -#define FAST_INTR_RETURN \ - ASSERT_UPCALL_MASK_IS_SET; \ - HYPERVISOR_IRET(0) - -#elif defined(__i386) - -#define FAST_INTR_PUSH \ - cld; \ - __SEGREGS_PUSH \ - __SEGREGS_LOAD_KERNEL \ - -#define FAST_INTR_POP \ - __SEGREGS_POP - -#define FAST_INTR_RETURN \ - IRET - -#endif /* __i386 */ - -/* - * Handling the CR0.TS bit for floating point handling. - * - * When the TS bit is *set*, attempts to touch the floating - * point hardware will result in a #nm trap. - */ -#if defined(__amd64) - -#define STTS(rtmp) \ - pushq %rdi; \ - movl $1, %edi; \ - call HYPERVISOR_fpu_taskswitch; \ - popq %rdi - -#define CLTS \ - pushq %rdi; \ - xorl %edi, %edi; \ - call HYPERVISOR_fpu_taskswitch; \ - popq %rdi - -#elif defined(__i386) - -#define STTS(r) \ - pushl $1; \ - call HYPERVISOR_fpu_taskswitch; \ - addl $4, %esp - -#define CLTS \ - pushl $0; \ - call HYPERVISOR_fpu_taskswitch; \ - addl $4, %esp - -#endif /* __i386 */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_MACHPRIVREGS_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/privcmd_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/privcmd_impl.h deleted file mode 100644 index 3970cd72af..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/privcmd_impl.h +++ /dev/null @@ -1,61 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_PRIVCMD_IMPL_H -#define _SYS_PRIVCMD_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * /dev names: - * /dev/xen/ - containing directory - * privcmd - privileged commands - */ - -#define PRIVCMD_DRIVER_NAME "privcmd" - -#define PRIVCMD_NODE "privcmd" -#define PRIVCMD_MINOR 0 - -#define PRIVCMD_DEV_NAME "privcmd" -#define PRIVCMD_PATHNAME "xen/" PRIVCMD_DEV_NAME - -#if defined(_KERNEL) - -extern int do_privcmd_hypercall(void *, int, cred_t *, int *); - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_PRIVCMD_IMPL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/xen_mmu.h b/arch/x86/kernel/platform/i86xpv/include/sys/xen_mmu.h deleted file mode 100644 index 4e61e3b109..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/xen_mmu.h +++ /dev/null @@ -1,135 +0,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. - */ - -#ifndef _SYS_XEN_MMU_H -#define _SYS_XEN_MMU_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Platform-dependent MMU routines and types for the hypervisor. - * - * WARNING: this header file is used by both dboot and i86pc, so don't go using - * normal kernel headers. - */ - -#if (defined(_BOOT) && defined(_BOOT_TARGET_amd64)) || \ - (!defined(_BOOT) && defined(__amd64)) -#define __target_amd64 -#endif - -typedef uint64_t maddr_t; -#define mfn_to_ma(mfn) ((maddr_t)(mfn) << MMU_PAGESHIFT) - -#ifdef __xpv - -#ifdef __target_amd64 - -#define IN_HYPERVISOR_VA(va) \ - ((va) >= HYPERVISOR_VIRT_START && (va) < HYPERVISOR_VIRT_END) - -#else /* __target_amd64 */ - -#define IN_HYPERVISOR_VA(va) ((va) >= xen_virt_start) - -/* - * Do this to help catch any uses. - */ -#undef HYPERVISOR_VIRT_START -#undef machine_to_phys_mapping - -#endif /* __target_amd64 */ - -#undef __target_amd64 - -paddr_t ma_to_pa(maddr_t); -maddr_t pa_to_ma(paddr_t); -#endif /* __xpv */ - -extern uintptr_t xen_virt_start; -extern pfn_t *mfn_to_pfn_mapping; - -#ifndef _BOOT - -/* - * On the hypervisor we need: - * - a way to map a machine address (ie, not pseudo-physical). - * - to relocate initial hypervisor data structures into kernel VA range. - * - a way to translate between physical addresses and machine addresses. - * - a way to change the machine address behind a physical address. - */ -typedef ulong_t mfn_t; -extern mfn_t *mfn_list; -extern mfn_t *mfn_list_pages; -extern mfn_t *mfn_list_pages_page; -extern ulong_t mfn_count; -extern mfn_t cached_max_mfn; - -/* - * locks for mfn_list[] and machine_to_phys_mapping[] when migration / suspend - * events happen - */ -extern void xen_block_migrate(void); -extern void xen_allow_migrate(void); -extern void xen_start_migrate(void); -extern void xen_end_migrate(void); - -/* - * Conversion between machine (hardware) addresses and pseudo-physical - * addresses. - */ -#ifdef __xpv -pfn_t mfn_to_pfn(mfn_t); -mfn_t pfn_to_mfn(pfn_t); -#endif - -struct page; - -void xen_relocate_start_info(void); - -/* - * interfaces to create/destroy pfn_t values for devices or foreign memory - * - * xen_assign_pfn() creates (or looks up) a local pfn value to use for things - * like a foreign domain memory mfn or a device mfn. - * - * xen_release_pfn() destroys the association between a pfn and foreign mfn. - */ -pfn_t xen_assign_pfn(mfn_t mfn); -void xen_release_pfn(pfn_t); -uint_t pfn_is_foreign(pfn_t); -void reassign_pfn(pfn_t pfn, mfn_t mfn); - -#define MFN_INVALID (-(mfn_t)1) - -#endif /* !_BOOT */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XEN_MMU_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_impl.h b/arch/x86/kernel/platform/i86xpv/include/sys/xpv_impl.h deleted file mode 100644 index 680bebdf0d..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_impl.h +++ /dev/null @@ -1,47 +0,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. - */ - -#ifndef _SYS_XPV_IMPL_H -#define _SYS_XPV_IMPL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(_ASM) -#include -#endif - -#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ - -#include -#include - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XPV_IMPL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_panic.h b/arch/x86/kernel/platform/i86xpv/include/sys/xpv_panic.h deleted file mode 100644 index 063e663536..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_panic.h +++ /dev/null @@ -1,62 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_XPV_PANIC_H -#define _SYS_XPV_PANIC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -extern void xpv_panic_sti(); -extern void xpv_panic_halt(); -extern void xpv_panic_getcrs(ulong_t *); -extern void xpv_panic_setcr3(ulong_t); -extern void xpv_panic_reload_cr3(); -extern ulong_t xpv_panic_resetgs(); -extern void xpv_panic_init(); -extern void xpv_panic_hdlr(); -extern void *xpv_traceback(void *); - -extern void xpv_div0trap(), xpv_dbgtrap(), xpv_nmiint(), xpv_brktrap(); -extern void xpv_ovflotrap(), xpv_boundstrap(), xpv_invoptrap(); -extern void xpv_ndptrap(), xpv_syserrtrap(), xpv_invaltrap(); -extern void xpv_invtsstrap(), xpv_segnptrap(), xpv_stktrap(); -extern void xpv_gptrap(), xpv_pftrap(), xpv_ndperr(); -extern void xpv_overrun(), xpv_resvtrap(); -extern void xpv_achktrap(), xpv_mcetrap(); -extern void xpv_xmtrap(), xpv_timer_trap(), xpv_surprise_intr(); - -extern int dump_xpv_addr(); -extern void dump_xpv_pfn(); -extern int dump_xpv_data(void *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XPV_PANIC_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_user.h b/arch/x86/kernel/platform/i86xpv/include/sys/xpv_user.h deleted file mode 100644 index 80c62c06f2..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/sys/xpv_user.h +++ /dev/null @@ -1,63 +0,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. - */ - -#ifndef _SYS_XPV_SYSCTL_H -#define _SYS_XPV_SYSCTL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This header file defines things needed for access to sysctl(), - * domctl(), and other API features that are only used by userspace - * upstream. On Solaris, due to privcmd and a couple of other uses, we - * need them in the kernel, so isolate their use to this file. - */ - -#define __XEN_TOOLS__ - -#include -#include -#include - - -#if !defined(__GNUC__) && defined(__i386__) -#define set_xen_guest_handle_u(hnd, val) do { (hnd).u.p = val; } while (0) -#define get_xen_guest_handle_u(val, hnd) do { val = (hnd).u.p; } while (0) -#else -#define set_xen_guest_handle_u(hnd, val) do { (hnd).p = val; } while (0) -#define get_xen_guest_handle_u(val, hnd) do { val = (hnd).p; } while (0) -#endif - -extern long HYPERVISOR_xsm_op(struct xen_acmctl *); -extern long HYPERVISOR_sysctl(xen_sysctl_t *); -extern long HYPERVISOR_domctl(xen_domctl_t *domctl); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XPV_SYSCTL_H */ diff --git a/arch/x86/kernel/platform/i86xpv/include/vm/Makefile b/arch/x86/kernel/platform/i86xpv/include/vm/Makefile deleted file mode 100644 index 6cb1d0b4fe..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/vm/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -INCDIR= /usr/platform/i86xpv/include/vm -INCS= seg_mf.h - -.include -.include -.include - -.include <${SRCTOP}/Makefile.cfgparam> diff --git a/arch/x86/kernel/platform/i86xpv/include/vm/seg_mf.h b/arch/x86/kernel/platform/i86xpv/include/vm/seg_mf.h deleted file mode 100644 index 316a1f51bd..0000000000 --- a/arch/x86/kernel/platform/i86xpv/include/vm/seg_mf.h +++ /dev/null @@ -1,64 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _VM_SEG_MF_H -#define _VM_SEG_MF_H - - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct segmf_crargs { - dev_t dev; - uchar_t prot; - uchar_t maxprot; -}; - -extern int segmf_create(struct seg *, void *); - -extern int segmf_add_mfns(struct seg *, caddr_t, mfn_t, pgcnt_t, domid_t); - -/* max grefs which can be passed into segmf_add_grefs */ -#define SEGMF_MAX_GREFS 0x10 - -/* segmf_add_grefs flags */ -#define SEGMF_GREF_WR 0x1 /* Map gref writable */ - -extern int segmf_add_grefs(struct seg *, caddr_t, uint_t, grant_ref_t *, - uint_t, domid_t); -extern int segmf_release_grefs(struct seg *, caddr_t, uint_t); -extern void segmf_add_gref_pte(struct seg *, caddr_t, uint64_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _VM_SEG_MF_H */ diff --git a/arch/x86/kernel/platform/i86xpv/mapfile-32 b/arch/x86/kernel/platform/i86xpv/mapfile-32 deleted file mode 100644 index e6e49e1bea..0000000000 --- a/arch/x86/kernel/platform/i86xpv/mapfile-32 +++ /dev/null @@ -1,81 +0,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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# - -$mapfile_version 2 - -# -# This is 1:1 mapped code to setup the kernel memory image. -# It needs to be after (in physical) the kernel bits, so that -# they have full 8 Meg of memory. -# -LOAD_SEGMENT dboot { - FLAGS = READ WRITE EXECUTE; - NOHDR; - PADDR = 0x40800000; - VADDR = 0x40800000; - ASSIGN_SECTION { - IS_NAME = .data; - FILE_BASENAME = dboot.o; - }; -}; - -# -# kernel text segment -# -LOAD_SEGMENT text { - FLAGS = READ EXECUTE; - NOHDR; - PADDR = 0x40000000; - VADDR = 0xf4c00000; - OS_ORDER = .text; - ASSIGN_SECTION { - TYPE = PROGBITS; - FLAGS = ALLOC !WRITE; - }; -}; - -# -# start the data segment on a new 4MB page boundary -# -LOAD_SEGMENT data { - FLAGS = READ WRITE EXECUTE; - PADDR = 0x40400000; - VADDR = 0xf5000000; - OS_ORDER = .data; - ASSIGN_SECTION { - TYPE = PROGBITS; - FLAGS = ALLOC WRITE; - }; - ASSIGN_SECTION { - TYPE = NOBITS; - FLAGS = ALLOC WRITE; - }; -}; - -NOTE_SEGMENT note { - ASSIGN_SECTION { - TYPE = NOTE; - }; -}; diff --git a/arch/x86/kernel/platform/i86xpv/mapfile-64 b/arch/x86/kernel/platform/i86xpv/mapfile-64 deleted file mode 100644 index d5b18bfcd6..0000000000 --- a/arch/x86/kernel/platform/i86xpv/mapfile-64 +++ /dev/null @@ -1,78 +0,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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# - -$mapfile_version 2 - -# -# This is 1:1 mapped code to setup the kernel memory image. -# It needs to be after (in physical) the kernel bits, so that -# they have full 8 Meg of memory. -# -LOAD_SEGMENT dboot { - FLAGS = READ WRITE EXECUTE; - NOHDR; - PADDR = 0x40800000; - VADDR = 0x40800000; - ASSIGN_SECTION { - IS_NAME = .data; - FILE_BASENAME = dboot.o; - }; -}; - -LOAD_SEGMENT text { - FLAGS = READ EXECUTE; - NOHDR; - PADDR = 0x40000000; - VADDR = 0xFFFFFFFFFB800000; - OS_ORDER = .text; - ASSIGN_SECTION { - TYPE = PROGBITS; - FLAGS = ALLOC !WRITE; - }; -}; - -# -# start the data segment on a new 4MB page boundary -# -LOAD_SEGMENT data { - FLAGS = READ WRITE EXECUTE; - PADDR = 0x40400000; - VADDR = 0xFFFFFFFFFBC00000; - OS_ORDER = .data; - ASSIGN_SECTION { - TYPE = PROGBITS; - FLAGS = ALLOC WRITE; - }; - ASSIGN_SECTION { - TYPE = NOBITS; - FLAGS = ALLOC WRITE; - }; -}; - -NOTE_SEGMENT note { - ASSIGN_SECTION { - TYPE = NOTE; - }; -}; diff --git a/arch/x86/kernel/xen/os/hypercall.c b/arch/x86/kernel/xen/os/hypercall.c deleted file mode 100644 index 308c7246db..0000000000 --- a/arch/x86/kernel/xen/os/hypercall.c +++ /dev/null @@ -1,433 +0,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. - */ - -/* - * Provides basic C wrappers around hypervisor invocation. - * - * i386: eax = vector: ebx, ecx, edx, esi, edi = args 1-5 - * eax = return value - * (argument registers may be clobbered on return) - * - * amd64:rax = vector: rdi, rsi, rdx, r10, r8, r9 = args 1-6 - * rax = return value - * (arguments registers not clobbered on return; rcx, r11 are) - */ - -#include -#ifndef __xpv -#include -#else -#include -#endif - -#include -#include -#include -#include - -long -HYPERVISOR_set_trap_table(trap_info_t *table) -{ - return (__hypercall1(__HYPERVISOR_set_trap_table, (ulong_t)table)); -} - -int -HYPERVISOR_mmu_update(mmu_update_t *req, int count, int *success_count, - domid_t domain_id) -{ - return (__hypercall4_int(__HYPERVISOR_mmu_update, - (ulong_t)req, (long)count, (ulong_t)success_count, - (ulong_t)domain_id)); -} - -long -HYPERVISOR_set_gdt(ulong_t *frame_list, int entries) -{ - return (__hypercall2( - __HYPERVISOR_set_gdt, (ulong_t)frame_list, (long)entries)); -} - -/* - * XXPV Seems like "sp" would be a better name for both amd64 and i386? - * For now stay consistent with xen project source. - */ -long -HYPERVISOR_stack_switch(ulong_t ss, ulong_t esp) -{ - return (__hypercall2(__HYPERVISOR_stack_switch, ss, esp)); -} - -#if defined(__amd64) - -long -HYPERVISOR_set_callbacks(ulong_t event_address, ulong_t failsafe_address, - ulong_t syscall_address) -{ - return (__hypercall3(__HYPERVISOR_set_callbacks, - event_address, failsafe_address, syscall_address)); -} - -#elif defined(__i386) - -long -HYPERVISOR_set_callbacks( - ulong_t event_selector, ulong_t event_address, - ulong_t failsafe_selector, ulong_t failsafe_address) -{ - return (__hypercall4(__HYPERVISOR_set_callbacks, - event_selector, event_address, - failsafe_selector, failsafe_address)); -} - -#endif /* __amd64 */ - -long -HYPERVISOR_fpu_taskswitch(int set) -{ - return (__hypercall1(__HYPERVISOR_fpu_taskswitch, (long)set)); -} - -/* *** __HYPERVISOR_sched_op_compat *** OBSOLETED */ - -long -HYPERVISOR_platform_op(xen_platform_op_t *platform_op) -{ - return (__hypercall1(__HYPERVISOR_platform_op, (ulong_t)platform_op)); -} - -/* *** __HYPERVISOR_set_debugreg *** NOT IMPLEMENTED */ - -/* *** __HYPERVISOR_get_debugreg *** NOT IMPLEMENTED */ - -long -HYPERVISOR_update_descriptor(maddr_t ma, uint64_t desc) -{ -#if defined(__amd64) - - return (__hypercall2(__HYPERVISOR_update_descriptor, ma, desc)); - -#elif defined(__i386) - - return (__hypercall4(__HYPERVISOR_update_descriptor, - (ulong_t)ma, (ulong_t)(ma >>32), - (ulong_t)desc, (ulong_t)(desc >> 32))); - -#endif -} - -long -HYPERVISOR_memory_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_memory_op, (long)cmd, - (ulong_t)arg)); -} - -long -HYPERVISOR_multicall(void *call_list, uint_t nr_calls) -{ - return (__hypercall2(__HYPERVISOR_multicall, - (ulong_t)call_list, (ulong_t)nr_calls)); -} - -int -HYPERVISOR_update_va_mapping(ulong_t va, uint64_t new_pte, ulong_t flags) -{ -#if !defined(_BOOT) - if (IN_XPV_PANIC()) - return (0); -#endif -#if defined(__amd64) - - return (__hypercall3_int(__HYPERVISOR_update_va_mapping, va, - new_pte, flags)); - -#elif defined(__i386) - - return (__hypercall4_int(__HYPERVISOR_update_va_mapping, va, - (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags)); - -#endif /* __i386 */ -} - -/* - * Note: this timeout must be the Xen system time not hrtime (see - * xpv_timestamp.c). - */ -long -HYPERVISOR_set_timer_op(uint64_t timeout) -{ -#if defined(__amd64) - - return (__hypercall1(__HYPERVISOR_set_timer_op, timeout)); - -#elif defined(__i386) - - uint32_t timeout_hi = (uint32_t)(timeout >> 32); - uint32_t timeout_lo = (uint32_t)timeout; - return (__hypercall2(__HYPERVISOR_set_timer_op, - (ulong_t)timeout_lo, (ulong_t)timeout_hi)); - -#endif /* __i386 */ -} - -/* *** __HYPERVISOR_event_channel_op_compat *** OBSOLETED */ - -long -HYPERVISOR_xen_version(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_xen_version, (long)cmd, - (ulong_t)arg)); -} - -long -HYPERVISOR_console_io(int cmd, int count, char *str) -{ - return (__hypercall3(__HYPERVISOR_console_io, (long)cmd, (long)count, - (ulong_t)str)); -} - -/* *** __HYPERVISOR_physdev_op_compat *** OBSOLETED */ - -/* - * **** - * NOTE: this hypercall should not be called directly for a - * GNTTABOP_map_grant_ref. Instead xen_map_gref() should be called. - * **** - */ -long -HYPERVISOR_grant_table_op(uint_t cmd, void *uop, uint_t count) -{ - int ret_val; - ret_val = __hypercall3(__HYPERVISOR_grant_table_op, - (long)cmd, (ulong_t)uop, (ulong_t)count); - return (ret_val); -} - -long -HYPERVISOR_vm_assist(uint_t cmd, uint_t type) -{ - return (__hypercall2(__HYPERVISOR_vm_assist, - (ulong_t)cmd, (ulong_t)type)); -} - -int -HYPERVISOR_update_va_mapping_otherdomain(ulong_t va, - uint64_t new_pte, ulong_t flags, domid_t domain_id) -{ -#if defined(__amd64) - - return (__hypercall4_int(__HYPERVISOR_update_va_mapping_otherdomain, - va, new_pte, flags, (ulong_t)domain_id)); - -#elif defined(__i386) - - return (__hypercall5_int(__HYPERVISOR_update_va_mapping_otherdomain, - va, (ulong_t)new_pte, (ulong_t)(new_pte >> 32), flags, - (ulong_t)domain_id)); - -#endif /* __i386 */ -} - -/* - * *** __HYPERVISOR_iret *** - * see HYPERVISOR_IRET() macro in i86xpv/sys/machprivregs.h - */ - -long -HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args) -{ - return (__hypercall3(__HYPERVISOR_vcpu_op, (long)cmd, (long)vcpuid, - (ulong_t)extra_args)); -} - -#if defined(__amd64) - -long -HYPERVISOR_set_segment_base(int reg, ulong_t value) -{ - return (__hypercall2(__HYPERVISOR_set_segment_base, (long)reg, value)); -} - -#endif /* __amd64 */ - -int -HYPERVISOR_mmuext_op(struct mmuext_op *req, int count, uint_t *success_count, - domid_t domain_id) -{ - return (__hypercall4_int(__HYPERVISOR_mmuext_op, - (ulong_t)req, (long)count, (ulong_t)success_count, - (ulong_t)domain_id)); -} - -long -HYPERVISOR_nmi_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_nmi_op, (long)cmd, (ulong_t)arg)); -} - -long -HYPERVISOR_sched_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_sched_op, - (ulong_t)cmd, (ulong_t)arg)); -} - -long -HYPERVISOR_callback_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_callback_op, - (ulong_t)cmd, (ulong_t)arg)); -} - -/* *** __HYPERVISOR_xenoprof_op *** NOT IMPLEMENTED */ - -long -HYPERVISOR_event_channel_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_event_channel_op, (long)cmd, - (ulong_t)arg)); -} - -long -HYPERVISOR_physdev_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_physdev_op, (long)cmd, - (ulong_t)arg)); -} - -long -HYPERVISOR_hvm_op(int cmd, void *arg) -{ - return (__hypercall2(__HYPERVISOR_hvm_op, (long)cmd, (ulong_t)arg)); -} - -#if defined(__xpv) -long -HYPERVISOR_xsm_op(struct xen_acmctl *arg) -{ - return (__hypercall1(__HYPERVISOR_xsm_op, (ulong_t)arg)); -} - -long -HYPERVISOR_sysctl(xen_sysctl_t *sysctl) -{ - return (__hypercall1(__HYPERVISOR_sysctl, (ulong_t)sysctl)); -} - -long -HYPERVISOR_domctl(xen_domctl_t *domctl) -{ - return (__hypercall1(__HYPERVISOR_domctl, (ulong_t)domctl)); -} -#endif /* __xpv */ - -/* *** __HYPERVISOR_kexec_op *** NOT IMPLEMENTED */ - -/* - * - * HYPERCALL HELPER ROUTINES - * These don't have there own unique hypercalls. - * - */ - -long -HYPERVISOR_yield(void) -{ - return (HYPERVISOR_sched_op(SCHEDOP_yield, NULL)); -} - -long -HYPERVISOR_block(void) -{ - return (HYPERVISOR_sched_op(SCHEDOP_block, NULL)); -} - -long -HYPERVISOR_shutdown(uint_t reason) -{ - struct sched_shutdown sched_shutdown; - - sched_shutdown.reason = reason; - - return (HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown)); -} - -/* - * Poll one or more event-channel ports, and return when pending. - * An optional timeout (in nanoseconds, absolute time since boot) may be - * specified. Note: this timeout must be the Xen system time not hrtime (see - * xpv_timestamp.c). - */ -long -HYPERVISOR_poll(evtchn_port_t *ports, uint_t nr_ports, uint64_t timeout) -{ - struct sched_poll sched_poll; - - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(sched_poll.ports, ports); - sched_poll.nr_ports = nr_ports; - sched_poll.timeout = timeout; - - return (HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll)); -} - -long -HYPERVISOR_suspend(ulong_t start_info_mfn) -{ - struct sched_shutdown sched_shutdown; - - sched_shutdown.reason = SHUTDOWN_suspend; - - return (__hypercall3(__HYPERVISOR_sched_op, SCHEDOP_shutdown, - (ulong_t)&sched_shutdown, start_info_mfn)); -} - -long -HYPERVISOR_mca(uint32_t cmd, xen_mc_t *xmcp) -{ - long rv; - - switch (cmd) { - case XEN_MC_fetch: - case XEN_MC_physcpuinfo: - case XEN_MC_msrinject: - case XEN_MC_mceinject: - break; - - case XEN_MC_notifydomain: - return (ENOTSUP); - - default: - return (EINVAL); - } - - xmcp->interface_version = XEN_MCA_INTERFACE_VERSION; - xmcp->cmd = cmd; - - rv = __hypercall1(__HYPERVISOR_mca, (ulong_t)xmcp); - - return (rv); -} diff --git a/exception_lists/packaging b/exception_lists/packaging index d2a0d5e53a..42fcdec4f6 100644 --- a/exception_lists/packaging +++ b/exception_lists/packaging @@ -442,12 +442,6 @@ usr/include/sys/extdirent.h usr/include/libvscan.h usr/include/sys/vscan.h # -# i86hvm is not a full platform. It is just a home for paravirtualized -# drivers. There is no usr/ component to this sub-platform, but the -# directory is created in the proto area to keep other tools happy. -# -usr/platform/i86hvm i386 -# # Private sdcard framework headers # usr/include/sys/sdcard diff --git a/usr/src/cmd/boot/filelist/i386/filelist.ramdisk b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk index 0633517b10..a158b5cb32 100644 --- a/usr/src/cmd/boot/filelist/i386/filelist.ramdisk +++ b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk @@ -17,8 +17,6 @@ etc/rtc_config etc/system etc/hostid kernel -platform/i86hvm/kernel platform/i86pc/kernel -platform/i86xpv/kernel platform/i86pc/ucode/GenuineIntel platform/i86pc/ucode/AuthenticAMD diff --git a/usr/src/cmd/devfsadm/i386/Makefile b/usr/src/cmd/devfsadm/i386/Makefile index a67c9f5677..4f1c48e55d 100644 --- a/usr/src/cmd/devfsadm/i386/Makefile +++ b/usr/src/cmd/devfsadm/i386/Makefile @@ -24,10 +24,7 @@ LINK_OBJS_i386 = \ drm_link_i386.o \ - misc_link_i386.o \ - xen_link.o - -xen_link.o xen_link.ln xen_link.po := CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include + misc_link_i386.o include ../Makefile.com diff --git a/usr/src/cmd/devfsadm/i386/xen_link.c b/usr/src/cmd/devfsadm/i386/xen_link.c deleted file mode 100644 index f133596ae6..0000000000 --- a/usr/src/cmd/devfsadm/i386/xen_link.c +++ /dev/null @@ -1,111 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Handle miscellaneous children of xendev - */ -static int devxen(di_minor_t, di_node_t); -static int xdt(di_minor_t minor, di_node_t node); - -static devfsadm_create_t xen_cbt[] = { - { "xendev", DDI_PSEUDO, "xenbus", - TYPE_EXACT | DRV_EXACT, ILEVEL_0, devxen, - }, - { "xendev", DDI_PSEUDO, PRIVCMD_DRIVER_NAME, - TYPE_EXACT | DRV_EXACT, ILEVEL_0, devxen, - }, - { "xendev", DDI_PSEUDO, "evtchn", - TYPE_EXACT | DRV_EXACT, ILEVEL_0, devxen, - }, - { "xendev", DDI_PSEUDO, DOMCAPS_DRIVER_NAME, - TYPE_EXACT | DRV_EXACT, ILEVEL_0, devxen, - }, - { "xendev", DDI_PSEUDO, BALLOON_DRIVER_NAME, - TYPE_EXACT | DRV_EXACT, ILEVEL_0, devxen, - }, - { "pseudo", DDI_PSEUDO, "xdt", - TYPE_EXACT | DRV_EXACT, ILEVEL_0, xdt - }, -}; - -DEVFSADM_CREATE_INIT_V0(xen_cbt); - -static devfsadm_remove_t xen_remove_cbt[] = { - { "xendev", "^" "xen/xenbus" "$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all - }, - { "xendev", "^" PRIVCMD_PATHNAME "$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all - }, - { "xendev", "^" "xen/evtchn" "$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all - }, - { "xendev", "^" DOMCAPS_PATHNAME "$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all - }, - { "xendev", "^" BALLOON_PATHNAME "$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all - }, -}; - -DEVFSADM_REMOVE_INIT_V0(xen_remove_cbt); - -/* - * /dev/xen/ -> /devices/xendev/: - */ -static int -devxen(di_minor_t minor, di_node_t node) -{ - char buf[256]; - - (void) snprintf(buf, sizeof (buf), "xen/%s", di_minor_name(minor)); - (void) devfsadm_mklink(buf, node, minor, 0); - - return (DEVFSADM_CONTINUE); -} - -static int -xdt(di_minor_t minor, di_node_t node) -{ - char *mname = di_minor_name(minor); - char path[MAXPATHLEN]; - - (void) snprintf(path, sizeof (path), "dtrace/provider/%s", mname); - (void) devfsadm_mklink(path, node, minor, 0); - - return (DEVFSADM_CONTINUE); -} diff --git a/usr/src/cmd/dtrace/test/tst/Makefile b/usr/src/cmd/dtrace/test/tst/Makefile index 27c9c69960..196d32c45d 100644 --- a/usr/src/cmd/dtrace/test/tst/Makefile +++ b/usr/src/cmd/dtrace/test/tst/Makefile @@ -27,7 +27,7 @@ include $(SRC)/Makefile.master -SUBDIRS= common $(MACH:i386=i386 i86xpv) +SUBDIRS= common $(MACH) include ../Makefile.subdirs dstyle := TARGET += dstyle diff --git a/usr/src/cmd/dtrace/test/tst/i86xpv/Makefile b/usr/src/cmd/dtrace/test/tst/i86xpv/Makefile deleted file mode 100644 index 68378bbe3f..0000000000 --- a/usr/src/cmd/dtrace/test/tst/i86xpv/Makefile +++ /dev/null @@ -1,29 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com diff --git a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.basic.ksh b/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.basic.ksh deleted file mode 100755 index 3a5ce6f0d0..0000000000 --- a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.basic.ksh +++ /dev/null @@ -1,77 +0,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. -# - -# -# ASSERTION: Make sure that we can map in and read the Xen trace buffers. -# - -if [ $# != 1 ]; then - echo expected one argument: '<'dtrace-path'>' - exit 2 -fi - -# -# Do not fail the test in a domU -# -if [ ! -c /dev/xen/privcmd ]; then - exit 0 -fi - -dtrace=$1 - -script() -{ - $dtrace -qs /dev/stdin <on++; - } - - xdt:sched::off-cpu - /arg0 == 0 && self->on/ - { - self->off++; - } - - xdt:sched::off-cpu - /self->on > 50 && self->off > 50/ - { - exit(0); - } - - profile:::tick-1sec - /n++ > 10/ - { - exit(1); - } -EOF -} - -script -status=$? - -exit $status diff --git a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh b/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh deleted file mode 100755 index 3719c20265..0000000000 --- a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.hvmenable.ksh +++ /dev/null @@ -1,64 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -# -# ASSERTION: HVM probes should enable successfully. -# - -if [ $# != 1 ]; then - echo expected one argument: '<'dtrace-path'>' - exit 2 -fi - -# -# Do not fail the test in a domU -# -if [ ! -c /dev/xen/privcmd ]; then - exit 0 -fi - -dtrace=$1 - -script() -{ - $dtrace -qs /dev/stdin <' - exit 2 -fi - -# -# Do not fail the test in a domU -# -if [ ! -c /dev/xen/privcmd ]; then - exit 0 -fi - -dtrace=$1 - -script() -{ - $dtrace -qs /dev/stdin <' - exit 2 -fi - -# -# do not fail test in a domU -# -if [ ! -c /dev/xen/privcmd ]; then - exit 0 -fi - -dtrace=$1 -outf=/tmp/sched.args.$$ - -script() -{ - $dtrace -c '/usr/bin/sleep 10' -o $outf -qs /dev/stdin < 1) { - for (pcpu = p[1]; pcpu <= p[2];\ - pcpu++) { - cpumap[domid, vcpu, - pcpu] = 1 - } - } else { - cpumap[domid, vcpu, - affinity[i]] = 1 - } - } - } - } - } - - /^$/ { next } - - /wake/ { - if (vcpumap[$1, $2]) { - next - } else { - print "error: " $0 - exit 1 - } - } - - { - if (cpumap[$1, $2, "any"] || cpumap[$1, $2, $3]) { - next - } else { - print "error: " $0 - exit 1 - } - } - ' $outf -} - -script -status=$? - -if [ $status == 0 ]; then - validate - status=$? -fi - -rm $outf -exit $status diff --git a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh b/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh deleted file mode 100755 index 54c3352ea5..0000000000 --- a/usr/src/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedenable.ksh +++ /dev/null @@ -1,74 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -# -# ASSERTION: Sched probes should enable successfully. -# - -if [ $# != 1 ]; then - echo expected one argument: '<'dtrace-path'>' - exit 2 -fi - -# -# do not fail test in a domU -# -if [ ! -c /dev/xen/privcmd ]; then - exit 0 -fi - -dtrace=$1 - -script() -{ - $dtrace -qs /dev/stdin < #include #include -#if defined(__i386) || defined(__amd64) -#include -#endif #include "avl.h" #include "memory.h" @@ -402,10 +399,6 @@ memstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) vn_htable_t ht; struct vnode *kvps; uintptr_t vn_size = 0; -#if defined(__i386) || defined(__amd64) - bln_stats_t bln_stats; - ssize_t bln_size; -#endif bzero(&stats, sizeof (memstat_t)); @@ -524,29 +517,10 @@ memstat(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) else freemem = 0; -#if defined(__i386) || defined(__amd64) - /* Are we running under Xen? If so, get balloon memory usage. */ - if ((bln_size = mdb_readvar(&bln_stats, "bln_stats")) != -1) { - if (freemem > bln_stats.bln_hv_pages) - freemem -= bln_stats.bln_hv_pages; - else - freemem = 0; - } -#endif - mdb_printf("Free (freelist) %16lu %16llu %3lu%%\n", freemem, (uint64_t)freemem * PAGESIZE / (1024 * 1024), MS_PCT_TOTAL(freemem)); -#if defined(__i386) || defined(__amd64) - if (bln_size != -1) { - mdb_printf("Balloon %16lu %16llu %3lu%%\n", - bln_stats.bln_hv_pages, - (uint64_t)bln_stats.bln_hv_pages * PAGESIZE / (1024 * 1024), - MS_PCT_TOTAL(bln_stats.bln_hv_pages)); - } -#endif - mdb_printf("\nTotal %16lu %16lu\n", physmem, (uint64_t)physmem * PAGESIZE / (1024 * 1024)); diff --git a/usr/src/cmd/mdb/i86xpv/Makefile b/usr/src/cmd/mdb/i86xpv/Makefile deleted file mode 100644 index ed18e0b728..0000000000 --- a/usr/src/cmd/mdb/i86xpv/Makefile +++ /dev/null @@ -1,28 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -SUBDIRS = modules -include ../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/Makefile.i86xpv b/usr/src/cmd/mdb/i86xpv/Makefile.i86xpv deleted file mode 100644 index 6ee27410f4..0000000000 --- a/usr/src/cmd/mdb/i86xpv/Makefile.i86xpv +++ /dev/null @@ -1,47 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -ROOTMOD = $(ROOT)/usr/platform/i86xpv/lib/mdb/$(MDBTGT)$(MACHMODDIR) -ROOTKMOD = $(ROOT)/platform/i86xpv/kernel/kmdb$(MACHMODDIR) - -$(ROOT)/usr/platform/i86xpv/lib/mdb: - $(INS.dir) - -$(ROOT)/usr/platform/i86xpv/lib/mdb/$(MDBTGT): $(ROOT)/usr/platform/i86xpv/lib/mdb - $(INS.dir) - -$(ROOT)/usr/platform/i86xpv/lib/mdb/$(MDBTGT)/amd64: \ - $(ROOT)/usr/platform/i86xpv/lib/mdb/$(MDBTGT) - $(INS.dir) - -$(ROOT)/platform/i86xpv/kernel: - $(INS.dir) - -$(ROOT)/platform/i86xpv/kernel/kmdb: $(ROOT)/platform/i86xpv/kernel - $(INS.dir) - -$(ROOT)/platform/i86xpv/kernel/kmdb/amd64: $(ROOT)/platform/i86xpv/kernel/kmdb - $(INS.dir) diff --git a/usr/src/cmd/mdb/i86xpv/modules/Makefile b/usr/src/cmd/mdb/i86xpv/modules/Makefile deleted file mode 100644 index 2df43b2ad4..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/Makefile +++ /dev/null @@ -1,29 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -SUBDIRS = unix xpv xpv_psm xpv_uppc -include ../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/modules/unix/Makefile b/usr/src/cmd/mdb/i86xpv/modules/unix/Makefile deleted file mode 100644 index 08500728e6..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/unix/Makefile +++ /dev/null @@ -1,29 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/Makefile.master -$(BUILD64)SUBDIRS += $(MACH64) -include ../../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile deleted file mode 100644 index f598fac566..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/unix/amd64/Makefile +++ /dev/null @@ -1,53 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. - -MODULE = unix.so -MDBTGT = kvm - -MODSRCS = unix.c i86mmu.c -MODASMSRCS = unix_sup.s - -include ../../../../../Makefile.cmd -include ../../../../../Makefile.cmd.64 -include ../../../../intel/Makefile.amd64 -include ../../../Makefile.i86xpv -include ../../../../Makefile.module - -MODSRCS_DIR = ../../../../i86pc/modules/unix/ - -CPPFLAGS += -DMP -D_MACHDEP -D__xpv -CPPFLAGS += -I../../../../common -CPPFLAGS += -I$(SRC)/uts/common -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/include -CPPFLAGS += -I$(SRC)/uts/intel - -CERRWARN += -Wno-char-subscripts -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-label -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-unused-function diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv/Makefile deleted file mode 100644 index 08500728e6..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv/Makefile +++ /dev/null @@ -1,29 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/Makefile.master -$(BUILD64)SUBDIRS += $(MACH64) -include ../../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv/amd64/Makefile deleted file mode 100644 index 6dfc3b67ed..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv/amd64/Makefile +++ /dev/null @@ -1,47 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -MODULE = xpv.so -MODULE_BUILD_TYPE = mdb -MDBTGT = kvm - -MODSRCS = xpv.c - -include ../../../../../Makefile.cmd -include ../../../../../Makefile.cmd.64 -include ../../../../intel/Makefile.amd64 -include ../../../Makefile.i86xpv -include ../../../../Makefile.module - -MODSRCS_DIR = ../../../../i86pc/modules/common - -CPPFLAGS += -DMP -D_MACHDEP -D__xpv -D_MDB -D__x86_64__ -CPPFLAGS += -I../../../../common -CPPFLAGS += -I../../../../i86pc/modules/common -CPPFLAGS += -I$(SRC)/uts/common -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c b/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c deleted file mode 100644 index ed623bf344..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c +++ /dev/null @@ -1,288 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 2012 by Delphix. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static mdb_ctf_id_t domain_type; - -/* - * Some constants found in the non-public sched.h header file - */ -#define MAX_EVTCHNS NR_EVENT_CHANNELS -#define EVTCHNS_PER_BUCKET 128 -#define NR_EVTCHN_BUCKETS (MAX_EVTCHNS / EVTCHNS_PER_BUCKET) - -/* - * "struct domain" is an internal Xen structure. Rather than trying to - * keep the mdb source in sync with Xen, we use CTF to extract the - * interesting bits from the binary, and stash them in the structure - * defined below. - */ -typedef struct mdb_xpv_domain { - short domain_id; - int tot_pages; - int max_pages; - int xenheap_pages; - ulong_t domain_flags; - char is_hvm; - struct vcpu *vcpu[MAX_VIRT_CPUS]; - struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; - struct domain *next_in_list; -} mdb_xpv_domain_t; - -static uintptr_t -get_dom0_addr() -{ - GElf_Sym sym; - uintptr_t addr; - - if ((mdb_lookup_by_obj(MDB_TGT_OBJ_EVERY, "dom0", &sym)) == 1) { - mdb_warn("can't find symbol 'dom0'"); - return (0); - } - - if (sym.st_size != sizeof (uintptr_t)) { - mdb_printf("Symbol 'dom0' found, but with the wrong size\n"); - return (0); - } - - if (mdb_vread(&addr, sym.st_size, sym.st_value) == -1) { - mdb_warn("can't read data for symbol 'dom0'"); - return (0); - } - - return (addr); -} - -typedef struct domain_walk { - uint_t dw_step; -} domain_walk_t; - -int -domain_walk_init(mdb_walk_state_t *wsp) -{ - domain_walk_t *dwp; - - if (wsp->walk_addr == (uintptr_t)NULL) - if ((wsp->walk_addr = get_dom0_addr()) == (uintptr_t)NULL) - return (WALK_ERR); - - dwp = mdb_alloc(sizeof (domain_walk_t), UM_SLEEP); - dwp->dw_step = FALSE; - wsp->walk_data = dwp; - return (WALK_NEXT); -} - -int -domain_walk_step(mdb_walk_state_t *wsp) -{ - domain_walk_t *dwp = (domain_walk_t *)wsp->walk_data; - mdb_xpv_domain_t dom; - int status; - - if (wsp->walk_addr == (uintptr_t)NULL) - return (WALK_DONE); - - status = wsp->walk_callback(wsp->walk_addr, (void *)wsp->walk_addr, - wsp->walk_cbdata); - - if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t", - wsp->walk_addr, 0) != 0) - return (WALK_ERR); - wsp->walk_addr = (uintptr_t)dom.next_in_list; - - dwp->dw_step = TRUE; - return (status); -} - -void -domain_walk_fini(mdb_walk_state_t *wsp) -{ - domain_walk_t *dwp = (domain_walk_t *)wsp->walk_data; - - mdb_free(dwp, sizeof (domain_walk_t)); -} - -typedef struct vcpu_walk { - uint_t vw_count; - uint_t vw_step; -} vcpu_walk_t; - -int -vcpu_walk_init(mdb_walk_state_t *wsp) -{ - vcpu_walk_t *vwp; - uintptr_t off; - - if (wsp->walk_addr == (uintptr_t)NULL) - if ((wsp->walk_addr = get_dom0_addr()) == (uintptr_t)NULL) - return (WALK_ERR); - - if (mdb_ctf_offsetof(domain_type, "vcpu", &off)) { - mdb_warn("can't find per-domain vcpu information"); - return (WALK_ERR); - } - - wsp->walk_addr = wsp->walk_addr + (off / NBBY); - vwp = mdb_alloc(sizeof (vcpu_walk_t), UM_SLEEP); - vwp->vw_step = FALSE; - vwp->vw_count = 0; - wsp->walk_data = vwp; - return (WALK_NEXT); -} - -int -vcpu_walk_step(mdb_walk_state_t *wsp) -{ - vcpu_walk_t *vwp = (vcpu_walk_t *)wsp->walk_data; - uintptr_t vcpu_ptr; - int status; - - if (vwp->vw_count++ >= MAX_VIRT_CPUS) - return (WALK_DONE); - if ((wsp->walk_addr == (uintptr_t)NULL) || - (mdb_vread(&vcpu_ptr, sizeof (uintptr_t), wsp->walk_addr) == -1) || - (vcpu_ptr == 0)) - return (WALK_DONE); - - status = wsp->walk_callback(vcpu_ptr, (void *)vcpu_ptr, - wsp->walk_cbdata); - - wsp->walk_addr = wsp->walk_addr + sizeof (uintptr_t); - vwp->vw_step = TRUE; - return (status); -} - -void -vcpu_walk_fini(mdb_walk_state_t *wsp) -{ - vcpu_walk_t *vwp = (vcpu_walk_t *)wsp->walk_data; - - mdb_free(vwp, sizeof (vcpu_walk_t)); -} - -int -domain(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - mdb_xpv_domain_t dom; - uintptr_t off, vcpu_addr, evtchn_addr; - - if (!mdb_ctf_type_valid(domain_type)) { - mdb_warn("Can't parse Xen domain info.\n"); - return (DCMD_ERR); - } - - if (!(flags & DCMD_ADDRSPEC)) { - if (mdb_walk_dcmd("domain", "domain", argc, argv) == -1) { - mdb_warn("can't walk domains"); - return (DCMD_ERR); - } - return (DCMD_OK); - } - - if (DCMD_HDRSPEC(flags)) - mdb_printf("%?s %3s %8s %8s %8s %3s %?s %?s\n", - "ADDR", "ID", "TPAGES", "MPAGES", "FLAGS", "HVM", - "VCPU", "EVTCHN"); - - if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t", addr, - 0) != 0) - return (DCMD_ERR); - - if (mdb_ctf_offsetof(domain_type, "vcpu", &off)) { - mdb_warn("can't find per-domain vcpu information"); - return (DCMD_ERR); - } - vcpu_addr = addr + (off / NBBY); - if (mdb_ctf_offsetof(domain_type, "evtchn", &off)) { - mdb_warn("can't find per-domain event channel information"); - return (DCMD_ERR); - } - evtchn_addr = addr + (off / NBBY); - mdb_printf("%?lx %3d %8x %8x %8x %3d %?lx %?lx\n", - addr, dom.domain_id, dom.tot_pages, dom.max_pages, dom.domain_flags, - dom.is_hvm, vcpu_addr, evtchn_addr); - - return (DCMD_OK); -} - -static const mdb_dcmd_t dcmds[] = { - { "domain", ":", "display Xen domain info", domain }, - { NULL } -}; - -static const mdb_walker_t walkers[] = { - { "domain", "walk list of Xen domains", - domain_walk_init, domain_walk_step, domain_walk_fini }, - { "vcpu", "walk a Xen domain's vcpus", - vcpu_walk_init, vcpu_walk_step, vcpu_walk_fini }, - { NULL } -}; - -static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; - -typedef struct mdb_xpv_panic_info { - int pi_version; -} mdb_xpv_panic_info_t; - -const mdb_modinfo_t * -_mdb_init(void) -{ - uintptr_t pip; - mdb_xpv_panic_info_t pi; - - if (mdb_readsym(&pip, sizeof (pip), "xpv_panic_info") == -1) { - mdb_warn("failed to read xpv panic_info pointer"); - return (NULL); - } - if (mdb_ctf_vread(&pi, "struct panic_info", "mdb_xpv_panic_info_t", - pip, 0) == -1) - return (NULL); - - if (pi.pi_version != PANIC_INFO_VERSION) { - mdb_warn("unrecognized hypervisor panic format"); - return (NULL); - } - - if (mdb_ctf_lookup_by_name("struct domain", &domain_type) != 0) { - mdb_warn("Can't parse Xen domain info: " - "'struct domain' not found.\n"); - mdb_ctf_type_invalidate(&domain_type); - } - - return (&modinfo); -} diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/Makefile deleted file mode 100644 index 08500728e6..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/Makefile +++ /dev/null @@ -1,29 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/Makefile.master -$(BUILD64)SUBDIRS += $(MACH64) -include ../../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/amd64/Makefile deleted file mode 100644 index 86c760f4a2..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/amd64/Makefile +++ /dev/null @@ -1,49 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. - -MODULE = xpv_psm.so -MDBTGT = kvm - -MODSRCS = xpv_psm.c intr_common.c - -include ../../../../../Makefile.cmd -include ../../../../../Makefile.cmd.64 -include ../../../../intel/Makefile.amd64 -include ../../../Makefile.i86xpv -include ../../../../Makefile.module - -MODSRCS_DIR = ../../../../i86pc/modules/common - -CPPFLAGS += -DMP -D_MACHDEP -D__xen -CPPFLAGS += -I../../../../common -CPPFLAGS += -I../../../../i86pc/modules/common -CPPFLAGS += -I$(SRC)/uts/common -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/include -CPPFLAGS += -I$(SRC)/uts/intel - -CERRWARN += -Wno-unused-function diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c deleted file mode 100644 index a54cbf0623..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c +++ /dev/null @@ -1,536 +0,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. - */ -/* - * Copyright (c) 2013 by Delphix. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include - -#include "intr_common.h" - -typedef struct mdb_shared_info { - unsigned long evtchn_pending[sizeof (unsigned long) * NBBY]; - unsigned long evtchn_mask[sizeof (unsigned long) * NBBY]; -} mdb_shared_info_t; - -static mdb_shared_info_t shared_info; -static int have_shared_info; -static uintptr_t evtchn_cpus_addr; -static struct av_head avec_tbl[NR_IRQS]; -static irq_info_t irq_tbl[NR_IRQS]; -static mec_info_t ipi_tbl[MAXIPL]; -static mec_info_t virq_tbl[NR_VIRQS]; -static short evtchn_tbl[NR_EVENT_CHANNELS]; -static apic_irq_t *apic_irq_tbl[APIC_MAX_VECTOR+1]; -static char level_tbl[APIC_MAX_VECTOR+1]; - -static int -update_tables(void) -{ - GElf_Sym sym; - uintptr_t shared_info_addr; - - if (mdb_readvar(&irq_tbl, "irq_info") == -1) { - mdb_warn("failed to read irq_info"); - return (0); - } - - if (mdb_readvar(&ipi_tbl, "ipi_info") == -1) { - mdb_warn("failed to read ipi_info"); - return (0); - } - - if (mdb_readvar(&avec_tbl, "autovect") == -1) { - mdb_warn("failed to read autovect"); - return (0); - } - - if (mdb_readvar(&irq_tbl, "irq_info") == -1) { - mdb_warn("failed to read irq_info"); - return (0); - } - - if (mdb_readvar(&ipi_tbl, "ipi_info") == -1) { - mdb_warn("failed to read ipi_info"); - return (0); - } - - if (mdb_readvar(&virq_tbl, "virq_info") == -1) { - mdb_warn("failed to read virq_info"); - return (0); - } - - if (mdb_readvar(&evtchn_tbl, "evtchn_to_irq") == -1) { - mdb_warn("failed to read evtchn_to_irq"); - return (0); - } - - if (mdb_readvar(&apic_irq_tbl, "apic_irq_table") == -1) { - mdb_warn("failed to read apic_irq_table"); - return (0); - } - - if (mdb_readvar(&level_tbl, "apic_level_intr") == -1) { - mdb_warn("failed to read apic_level_intr"); - return (0); - } - - if (mdb_lookup_by_name("evtchn_cpus", &sym) == -1) { - mdb_warn("failed to lookup evtchn_cpus"); - return (0); - } - - evtchn_cpus_addr = sym.st_value; - - if (mdb_readvar(&shared_info_addr, "HYPERVISOR_shared_info") == -1) { - mdb_warn("failed to read HYPERVISOR_shared_info"); - return (0); - } - - /* - * It's normal for this to fail with a domain dump. - */ - if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t", - shared_info_addr, MDB_CTF_VREAD_QUIET) != -1) - have_shared_info = 1; - - return (1); -} - -static const char * -virq_type(int irq) -{ - int i; - - for (i = 0; i < NR_VIRQS; i++) { - if (virq_tbl[i].mi_irq == irq) - break; - } - - switch (i) { - case VIRQ_TIMER: - return ("virq:timer"); - case VIRQ_DEBUG: - return ("virq:debug"); - case VIRQ_CONSOLE: - return ("virq:console"); - case VIRQ_DOM_EXC: - return ("virq:dom exc"); - case VIRQ_DEBUGGER: - return ("virq:debugger"); - case VIRQ_MCA: - return ("virq:mca"); - default: - break; - } - - return ("virq:?"); -} - -static const char * -irq_type(int irq, int extended) -{ - switch (irq_tbl[irq].ii_type) { - case IRQT_UNBOUND: - return ("unset"); - case IRQT_PIRQ: - return ("pirq"); - case IRQT_VIRQ: - if (extended) - return (virq_type(irq)); - return ("virq"); - case IRQT_IPI: - return ("ipi"); - case IRQT_EVTCHN: - return ("evtchn"); - case IRQT_DEV_EVTCHN: - return ("device"); - } - - return ("?"); -} - -/* - * We need a non-trivial IPL lookup as the CPU poke's IRQ doesn't have ii_ipl - * set -- see evtchn.h. - */ -static int -irq_ipl(int irq) -{ - int i; - - if (irq_tbl[irq].ii_u2.ipl != 0) - return (irq_tbl[irq].ii_u2.ipl); - - for (i = 0; i < MAXIPL; i++) { - if (ipi_tbl[i].mi_irq == irq) { - return (i); - } - } - - return (0); -} - -static void -print_cpu(irq_info_t *irqp, int evtchn) -{ - size_t cpuset_size = BT_BITOUL(NCPU) * sizeof (ulong_t); - int cpu; - - if (irqp != NULL) { - switch (irqp->ii_type) { - case IRQT_VIRQ: - case IRQT_IPI: - mdb_printf("all "); - return; - - case IRQT_DEV_EVTCHN: - mdb_printf("0 "); - return; - - default: - break; - } - } - - if (evtchn >= NR_EVENT_CHANNELS || evtchn == 0) { - mdb_printf("- "); - return; - } - - cpu = mdb_cpuset_find(evtchn_cpus_addr + - (cpuset_size * evtchn)); - - /* - * XXPV: we should verify this against the CPU's mask and show - * something if they don't match. - */ - mdb_printf("%-4d", cpu); -} - -static void -print_isr(int i) -{ - if (avec_tbl[i].avh_link != NULL) { - struct autovec avhp; - - (void) mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link); - - interrupt_print_isr((uintptr_t)avhp.av_vector, - (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip); - } else if (irq_ipl(i) == XC_CPUPOKE_PIL) { - mdb_printf("poke_cpu"); - } -} - -static int -evtchn_masked(int i) -{ - return (!!TEST_EVTCHN_BIT(i, &shared_info.evtchn_mask[0])); -} - -static int -evtchn_pending(int i) -{ - return (!!TEST_EVTCHN_BIT(i, &shared_info.evtchn_pending[0])); -} - -typedef struct mdb_xpv_psm_autovec { - dev_info_t *av_dip; -} mdb_xpv_psm_autovec_t; - -static void -print_bus(int irq) -{ - char parent[7]; - uintptr_t dip_addr; - struct dev_info dev_info; - mdb_xpv_psm_autovec_t avhp; - - if (mdb_ctf_vread(&avhp, "struct autovec", "mdb_xpv_psm_autovec_t", - (uintptr_t)avec_tbl[irq].avh_link, MDB_CTF_VREAD_QUIET) == -1) - goto fail; - - dip_addr = (uintptr_t)avhp.av_dip; - - if (dip_addr == (uintptr_t)NULL) - goto fail; - - /* - * Sigh. As a result of the perennial confusion of how you do opaque - * handles, dev_info_t has a funny old type, which means we can't use - * mdb_ctf_vread() here. - */ - - if (mdb_vread(&dev_info, sizeof (struct dev_info), dip_addr) == -1) - goto fail; - - dip_addr = (uintptr_t)dev_info.devi_parent; - - if (mdb_vread(&dev_info, sizeof (struct dev_info), dip_addr) == -1) - goto fail; - - if (mdb_readstr(parent, 7, (uintptr_t)dev_info.devi_node_name) == -1) - goto fail; - - mdb_printf("%-6s ", parent); - return; - -fail: - mdb_printf("- "); -} - -static void -ec_interrupt_dump(int i) -{ - irq_info_t *irqp = &irq_tbl[i]; - char evtchn[8]; - - if (irqp->ii_type == IRQT_UNBOUND) - return; - - if (option_flags & INTR_DISPLAY_INTRSTAT) { - print_cpu(irqp, irqp->ii_u.evtchn); - print_isr(i); - mdb_printf("\n"); - return; - } - - switch (irqp->ii_type) { - case IRQT_EVTCHN: - case IRQT_VIRQ: - if (irqp->ii_u.index == VIRQ_TIMER) { - strcpy(evtchn, "T"); - } else { - mdb_snprintf(evtchn, sizeof (evtchn), "%-7d", - irqp->ii_u.evtchn); - } - break; - case IRQT_IPI: - strcpy(evtchn, "I"); - break; - case IRQT_DEV_EVTCHN: - strcpy(evtchn, "D"); - break; - } - - /* IRQ */ - mdb_printf("%3d ", i); - /* Vector */ - mdb_printf("- "); - /* Evtchn */ - mdb_printf("%-7s", evtchn); - /* IPL */ - mdb_printf("%-4d", irq_ipl(i)); - /* Bus */ - print_bus(i); - /* Trigger */ - mdb_printf("%-4s", "Edg"); - /* Type */ - mdb_printf("%-7s", irq_type(i, 0)); - /* CPU */ - print_cpu(irqp, irqp->ii_u.evtchn); - /* Share */ - mdb_printf("- "); - /* APIC/INT# */ - mdb_printf("- "); - - print_isr(i); - - mdb_printf("\n"); -} - -/* ARGSUSED */ -static int -interrupts_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - int i; - - option_flags = 0; - if (mdb_getopts(argc, argv, - 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags, - 'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags, - NULL) != argc) - return (DCMD_USAGE); - - if (!update_tables()) - return (DCMD_ERR); - - if (option_flags & INTR_DISPLAY_INTRSTAT) { - mdb_printf("%CPU "); - } else { - mdb_printf("%IRQ Vect Evtchn IPL Bus Trg Type " - "CPU Share APIC/INT# "); - } - mdb_printf("%s %\n", option_flags & INTR_DISPLAY_DRVR_INST ? - "Driver Name(s)" : "ISR(s)"); - - for (i = 0; i < NR_IRQS; i++) { - if (irq_tbl[i].ii_type == IRQT_PIRQ) { - apic_irq_t airq; - - if (irq_tbl[i].ii_u.evtchn == 0) - continue; - - if (mdb_vread(&airq, sizeof (apic_irq_t), - (uintptr_t)apic_irq_tbl[i]) == -1) - continue; - - apic_interrupt_dump(&airq, &avec_tbl[i], i, - &irq_tbl[i].ii_u.evtchn, level_tbl[i]); - continue; - } - - ec_interrupt_dump(i); - } - - return (DCMD_OK); -} - -static void -evtchn_dump(int i) -{ - int irq = evtchn_tbl[i]; - - if (irq == INVALID_IRQ) { - mdb_printf("%-14s%-7d%-4s%-4s", "unassigned", i, "-", "-"); - print_cpu(NULL, i); - if (have_shared_info) { - mdb_printf("%-7d", evtchn_masked(i)); - mdb_printf("%-8d", evtchn_pending(i)); - } - mdb_printf("\n"); - return; - } - - /* Type */ - mdb_printf("%-14s", irq_type(irq, 1)); - /* Evtchn */ - mdb_printf("%-7d", i); - /* IRQ */ - mdb_printf("%-4d", irq); - /* IPL */ - mdb_printf("%-4d", irq_ipl(irq)); - /* CPU */ - print_cpu(NULL, i); - if (have_shared_info) { - /* Masked/Pending */ - mdb_printf("%-7d", evtchn_masked(i)); - mdb_printf("%-8d", evtchn_pending(i)); - } - /* ISR */ - print_isr(irq); - - mdb_printf("\n"); -} - -/* ARGSUSED */ -static int -evtchns_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - int i; - - option_flags = 0; - if (mdb_getopts(argc, argv, - 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags, - NULL) != argc) - return (DCMD_USAGE); - - if (!update_tables()) - return (DCMD_ERR); - - if (flags & DCMD_ADDRSPEC) { - /* - * Note: we allow the invalid evtchn 0, as it can help catch if - * we incorrectly try to configure it. - */ - if ((int)addr >= NR_EVENT_CHANNELS) { - mdb_warn("Invalid event channel %d.\n", (int)addr); - return (DCMD_ERR); - } - } - - mdb_printf("%Type Evtchn IRQ IPL CPU "); - if (have_shared_info) - mdb_printf("Masked Pending "); - - mdb_printf("%s %\n", option_flags & INTR_DISPLAY_DRVR_INST ? - "Driver Name(s)" : "ISR(s)"); - - if (flags & DCMD_ADDRSPEC) { - evtchn_dump((int)addr); - return (DCMD_OK); - } - - for (i = 0; i < NR_EVENT_CHANNELS; i++) { - if (evtchn_tbl[i] == INVALID_IRQ) - continue; - - evtchn_dump(i); - } - - return (DCMD_OK); -} - -static void -evtchns_help(void) -{ - mdb_printf("Print valid event channels\n" - "If %addr% is given, interpret it as an evtchn to print " - "details of.\n" - "By default, only interrupt service routine names are printed.\n\n" - "Switches:\n" - " -d instead of ISR, print \n"); -} - -static const mdb_dcmd_t dcmds[] = { - { "interrupts", "?[-di]", "print interrupts", interrupts_dump, - interrupt_help }, - { "evtchns", "?[-d]", "print event channels", evtchns_dump, - evtchns_help }, - { "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump, - soft_interrupt_help}, - { NULL } -}; - -static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL }; - -const mdb_modinfo_t * -_mdb_init(void) -{ - GElf_Sym sym; - - if (mdb_lookup_by_name("gld_intr", &sym) != -1) - if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) - gld_intr_addr = (uintptr_t)sym.st_value; - - return (&modinfo); -} diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile deleted file mode 100644 index d693f32aa1..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile +++ /dev/null @@ -1,29 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/Makefile.master -$(BUILD64)SUBDIRS += $(MACH64) -include ../../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile deleted file mode 100644 index 62e80b4c21..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile +++ /dev/null @@ -1,49 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. - -MODULE = xpv_uppc.so -MDBTGT = kvm - -MODSRCS = xpv_uppc.c intr_common.c - -include ../../../../../Makefile.cmd -include ../../../../../Makefile.cmd.64 -include ../../../../intel/Makefile.amd64 -include ../../../Makefile.i86xpv -include ../../../../Makefile.module - -MODSRCS_DIR = ../../../../i86pc/modules/common - -CPPFLAGS += -DMP -D_MACHDEP -D__xen -CPPFLAGS += -I../../../../common -CPPFLAGS += -I../../../../i86pc/modules/common -CPPFLAGS += -I$(SRC)/uts/common -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/include -CPPFLAGS += -I$(SRC)/uts/intel - -CERRWARN += -Wno-unused-function diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c deleted file mode 100644 index f5b4144285..0000000000 --- a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c +++ /dev/null @@ -1,496 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* - * Copyright (c) 2013 by Delphix. All rights reserved. - */ - -#include -#include -#include -#include - -#include "intr_common.h" - -typedef struct mdb_shared_info { - unsigned long evtchn_pending[sizeof (unsigned long) * NBBY]; - unsigned long evtchn_mask[sizeof (unsigned long) * NBBY]; -} mdb_shared_info_t; - -static mdb_shared_info_t shared_info; -static struct av_head avec_tbl[NR_IRQS]; -static uint16_t shared_tbl[MAX_ISA_IRQ + 1]; -static irq_info_t irq_tbl[NR_IRQS]; -static mec_info_t virq_tbl[NR_VIRQS]; -static short evtchn_tbl[NR_EVENT_CHANNELS]; - -static int -update_tables(void) -{ - uintptr_t shared_info_addr; - - if (mdb_readvar(&irq_tbl, "irq_info") == -1) { - mdb_warn("failed to read irq_info"); - return (0); - } - - if (mdb_readvar(&virq_tbl, "virq_info") == -1) { - mdb_warn("failed to read virq_info"); - return (0); - } - - if (mdb_readvar(&evtchn_tbl, "evtchn_to_irq") == -1) { - mdb_warn("failed to read evtchn_to_irq"); - return (0); - } - - if (mdb_readvar(&avec_tbl, "autovect") == -1) { - mdb_warn("failed to read autovect"); - return (0); - } - - if (mdb_readvar(&shared_tbl, "xen_uppc_irq_shared_table") == -1) { - mdb_warn("failed to read xen_uppc_irq_shared_table"); - return (0); - } - - if (mdb_readvar(&shared_info_addr, "HYPERVISOR_shared_info") == -1) { - mdb_warn("failed to read HYPERVISOR_shared_info"); - return (0); - } - - if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t", - shared_info_addr, 0) == -1) - return (0); - - return (1); -} - - -static char * -interrupt_print_bus(uintptr_t dip_addr) -{ - char bind_name[MAXPATHLEN + 1]; - struct dev_info dev_info; - - if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) { - mdb_warn("failed to read child dip"); - return ("-"); - } - - while (dev_info.devi_parent != 0) { - if (mdb_vread(&dev_info, sizeof (dev_info), - (uintptr_t)dev_info.devi_parent) == -1) - break; - - (void) mdb_readstr(bind_name, sizeof (bind_name), - (uintptr_t)dev_info.devi_binding_name); - if (strcmp(bind_name, "isa") == 0) - return ("ISA"); - else if (strcmp(bind_name, "pci") == 0 || - strcmp(bind_name, "npe") == 0) - return ("PCI"); - } - return ("-"); -} - -static const char * -virq_type(int irq) -{ - int i; - - for (i = 0; i < NR_VIRQS; i++) { - if (virq_tbl[i].mi_irq == irq) - break; - } - - switch (i) { - case VIRQ_TIMER: - return ("virq:timer"); - case VIRQ_DEBUG: - return ("virq:debug"); - case VIRQ_CONSOLE: - return ("virq:console"); - case VIRQ_DOM_EXC: - return ("virq:dom exc"); - case VIRQ_DEBUGGER: - return ("virq:debugger"); - default: - break; - } - - return ("virq:?"); -} - -static const char * -irq_type(int irq, int extended) -{ - switch (irq_tbl[irq].ii_type) { - case IRQT_UNBOUND: - return ("unset"); - case IRQT_PIRQ: - return ("pirq"); - case IRQT_VIRQ: - if (extended) - return (virq_type(irq)); - return ("virq"); - case IRQT_IPI: - return ("ipi"); - case IRQT_EVTCHN: - return ("evtchn"); - case IRQT_DEV_EVTCHN: - return ("device"); - } - - return ("?"); -} - -static void -print_isr(int i) -{ - struct autovec avhp; - - if (avec_tbl[i].avh_link == NULL) - return; - - (void) mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link); - - interrupt_print_isr((uintptr_t)avhp.av_vector, - (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip); - - while (avhp.av_link != NULL && - mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avhp.av_link) != -1) { - mdb_printf(", "); - interrupt_print_isr((uintptr_t)avhp.av_vector, - (uintptr_t)avhp.av_intarg1, (uintptr_t)avhp.av_dip); - } -} - -static int -evtchn_masked(int i) -{ - return (TEST_EVTCHN_BIT(i, &shared_info.evtchn_mask[0]) != 0); -} - -static int -evtchn_pending(int i) -{ - return (TEST_EVTCHN_BIT(i, &shared_info.evtchn_pending[0]) != 0); -} - -static void -pic_interrupt_dump(int i, struct autovec *avhp, int evtchn) -{ - if (option_flags & INTR_DISPLAY_INTRSTAT) { - mdb_printf("%-3d ", 0); - print_isr(i); - mdb_printf("\n"); - return; - } - - mdb_printf("%-3d 0x%2x %-6d %6d/%-2d %-3s %-6s %-5d ", - i, i + PIC_VECTBASE, evtchn, avec_tbl[i].avh_lo_pri, - avec_tbl[i].avh_hi_pri, avhp->av_dip ? - interrupt_print_bus((uintptr_t)avhp->av_dip) : "-", - irq_type(i, 0), shared_tbl[i]); - - print_isr(i); - - mdb_printf("\n"); -} - -static void -ec_interrupt_dump(int i) -{ - irq_info_t *irqp = &irq_tbl[i]; - struct autovec avhp; - char evtchn[8]; - - if (irqp->ii_type == IRQT_UNBOUND) - return; - - if (option_flags & INTR_DISPLAY_INTRSTAT) { - mdb_printf("%-3d ", 0); - print_isr(i); - mdb_printf("\n"); - return; - } - - - memset(&avhp, 0, sizeof (avhp)); - if (avec_tbl[i].avh_link != NULL) - (void) mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link); - - switch (irqp->ii_type) { - case IRQT_EVTCHN: - case IRQT_VIRQ: - if (irqp->ii_u.index == VIRQ_TIMER) { - strcpy(evtchn, "T"); - } else { - mdb_snprintf(evtchn, sizeof (evtchn), "%-7d", - irqp->ii_u.evtchn); - } - break; - case IRQT_IPI: - strcpy(evtchn, "I"); - break; - case IRQT_DEV_EVTCHN: - strcpy(evtchn, "D"); - break; - } - - /* IRQ */ - mdb_printf("%3d ", i); - /* Vector */ - mdb_printf("- "); - /* Evtchn */ - mdb_printf("%-7s", evtchn); - /* IPL */ - mdb_printf("%6d/%-2d ", irq_tbl[i].ii_u2.ipl, irq_tbl[i].ii_u2.ipl); - /* Bus */ - mdb_printf("%-3s ", avhp.av_dip - ? interrupt_print_bus((uintptr_t)avhp.av_dip) : "-"); - /* Type */ - mdb_printf("%-6s ", irq_type(i, 0)); - /* Share */ - mdb_printf("- "); - - print_isr(i); - - mdb_printf("\n"); -} - -/* - * uppc_interrupt_dump: - * Dump uppc(7d) interrupt information. - */ -/* ARGSUSED */ -int -xen_uppc_interrupt_dump(uintptr_t addr, uint_t flags, int argc, - const mdb_arg_t *argv) -{ - int i; - boolean_t found = B_FALSE; - struct autovec avhp; - - option_flags = 0; - if (mdb_getopts(argc, argv, - 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags, - 'i', MDB_OPT_SETBITS, INTR_DISPLAY_INTRSTAT, &option_flags, - NULL) != argc) - return (DCMD_USAGE); - - if (!update_tables()) - return (DCMD_ERR); - - /* - * By default, on all x86 systems ::interrupts from xen_uppc(7d) gets - * loaded first. For APIC systems the ::interrupts from xpv_psm(7d) - * ought to be executed. Confusion stems as both modules export the - * same dcmd. - */ - for (i = 0; i < MAX_ISA_IRQ + 1; i++) - if (shared_tbl[i]) { - found = B_TRUE; - break; - } - - if (found == B_FALSE) { - if (mdb_lookup_by_obj("xpv_psm", "apic_irq_table", - NULL) == 0) { - return (mdb_call_dcmd("xpv_psm`interrupts", - addr, flags, argc, argv)); - } - } - - /* Print the header first */ - if (option_flags & INTR_DISPLAY_INTRSTAT) - mdb_printf("%CPU "); - else - mdb_printf("%IRQ Vect Evtchn IPL(lo/hi) Bus Type Share "); - mdb_printf("%s %\n", option_flags & INTR_DISPLAY_DRVR_INST ? - "Driver Name(s)" : "ISR(s)"); - - for (i = 0; i < NR_IRQS; i++) { - if (irq_tbl[i].ii_type == IRQT_PIRQ) { - if (irq_tbl[i].ii_u.evtchn == 0) - continue; - - /* Read the entry, if invalid continue */ - if (mdb_vread(&avhp, sizeof (struct autovec), - (uintptr_t)avec_tbl[i].avh_link) == -1) - continue; - - pic_interrupt_dump(i, &avhp, irq_tbl[i].ii_u.evtchn); - continue; - } - - ec_interrupt_dump(i); - } - - return (DCMD_OK); -} - - -static void -evtchn_dump(int i) -{ - int irq = evtchn_tbl[i]; - - if (irq == INVALID_IRQ) { - mdb_printf("%-14s%-7d%-4s%-7s", "unassigned", i, "-", "-"); - mdb_printf("%-4d", 0); - mdb_printf("%-7d", evtchn_masked(i)); - mdb_printf("%-8d", evtchn_pending(i)); - mdb_printf("\n"); - return; - } - - /* Type */ - mdb_printf("%-14s", irq_type(irq, 1)); - /* Evtchn */ - mdb_printf("%-7d", i); - /* IRQ */ - mdb_printf("%-4d", irq); - /* IPL */ - mdb_printf("%6d/%-2d ", irq_tbl[irq].ii_u2.ipl, - irq_tbl[irq].ii_u2.ipl); - /* CPU */ - mdb_printf("%-4d", 0); - /* Masked/Pending */ - mdb_printf("%-7d", evtchn_masked(i)); - mdb_printf("%-8d", evtchn_pending(i)); - /* ISR */ - print_isr(irq); - - mdb_printf("\n"); -} - -/* ARGSUSED */ -static int -evtchns_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) -{ - int i; - boolean_t found = B_FALSE; - - option_flags = 0; - if (mdb_getopts(argc, argv, - 'd', MDB_OPT_SETBITS, INTR_DISPLAY_DRVR_INST, &option_flags, - NULL) != argc) - return (DCMD_USAGE); - - if (!update_tables()) - return (DCMD_ERR); - - /* - * By default, on all x86 systems ::evtchns from xen_uppc(7d) gets - * loaded first. For APIC systems the ::evtchns from xpv_psm(7d) - * ought to be executed. Confusion stems as both modules export the - * same dcmd. - */ - for (i = 0; i < MAX_ISA_IRQ + 1; i++) - if (shared_tbl[i]) { - found = B_TRUE; - break; - } - - if (found == B_FALSE) { - if (mdb_lookup_by_obj("xpv_psm", "apic_irq_table", - NULL) == 0) { - return (mdb_call_dcmd("xpv_psm`evtchns", - addr, flags, argc, argv)); - } - } - - if (flags & DCMD_ADDRSPEC) { - /* - * Note: we allow the invalid evtchn 0, as it can help catch if - * we incorrectly try to configure it. - */ - if ((int)addr >= NR_EVENT_CHANNELS) { - mdb_warn("Invalid event channel %d.\n", (int)addr); - return (DCMD_ERR); - } - } - - mdb_printf("%Type Evtchn IRQ IPL(lo/hi) CPU " - "Masked Pending "); - mdb_printf("%s %\n", option_flags & INTR_DISPLAY_DRVR_INST ? - "Driver Name(s)" : "ISR(s)"); - - if (flags & DCMD_ADDRSPEC) { - evtchn_dump((int)addr); - return (DCMD_OK); - } - - for (i = 0; i < NR_EVENT_CHANNELS; i++) { - if (evtchn_tbl[i] == INVALID_IRQ) - continue; - - evtchn_dump(i); - } - - return (DCMD_OK); -} - -static void -evtchns_help(void) -{ - mdb_printf("Print valid event channels\n" - "If %addr% is given, interpret it as an evtchn to print " - "details of.\n" - "By default, only interrupt service routine names are printed.\n\n" - "Switches:\n" - " -d instead of ISR, print \n"); -} - -/* - * MDB module linkage information: - */ -static const mdb_dcmd_t dcmds[] = { - { "interrupts", "?[-di]", "print interrupts", xen_uppc_interrupt_dump, - interrupt_help}, - { "evtchns", "?[-d]", "print event channels", evtchns_dump, - evtchns_help }, - { "softint", "?[-d]", "print soft interrupts", soft_interrupt_dump, - soft_interrupt_help}, - { NULL } -}; - -static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, NULL }; - -const mdb_modinfo_t * -_mdb_init(void) -{ - GElf_Sym sym; - - if (mdb_lookup_by_name("gld_intr", &sym) != -1) - if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) - gld_intr_addr = (uintptr_t)sym.st_value; - - return (&modinfo); -} diff --git a/usr/src/cmd/mdb/intel/amd64/genunix/Makefile b/usr/src/cmd/mdb/intel/amd64/genunix/Makefile index d615b54c1d..aa260a026a 100644 --- a/usr/src/cmd/mdb/intel/amd64/genunix/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/genunix/Makefile @@ -61,7 +61,6 @@ dmod/$(MODULE) := LDLIBS += -lm -lproc # kludge until we invent -DDONTINCLUDEMACHPARAM or something. # CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include # Needed to include c2/audit.h (from cred.h) CPPFLAGS += -I$(SRC)/uts/common diff --git a/usr/src/cmd/mdb/intel/modules/Makefile b/usr/src/cmd/mdb/intel/modules/Makefile index 96ccc108d6..ad6df04383 100644 --- a/usr/src/cmd/mdb/intel/modules/Makefile +++ b/usr/src/cmd/mdb/intel/modules/Makefile @@ -22,7 +22,7 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -SUBDIRS = mdb_kb \ +SUBDIRS = \ i40e \ generic_cpu \ amd_opteron \ diff --git a/usr/src/cmd/mdb/intel/modules/mdb_kb/Makefile b/usr/src/cmd/mdb/intel/modules/mdb_kb/Makefile deleted file mode 100644 index 08500728e6..0000000000 --- a/usr/src/cmd/mdb/intel/modules/mdb_kb/Makefile +++ /dev/null @@ -1,29 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -include $(SRC)/Makefile.master -$(BUILD64)SUBDIRS += $(MACH64) -include ../../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/intel/modules/mdb_kb/amd64/Makefile b/usr/src/cmd/mdb/intel/modules/mdb_kb/amd64/Makefile deleted file mode 100644 index 12a5945dae..0000000000 --- a/usr/src/cmd/mdb/intel/modules/mdb_kb/amd64/Makefile +++ /dev/null @@ -1,46 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -MODULE = mdb_kb.so -MDBTGT = kvm -MODULE_BUILD_TYPE = mdb - -MODSRCS = mdb_kb.c - -include ../../../../../Makefile.cmd -include ../../../../../Makefile.cmd.64 -include ../../../../intel/Makefile.amd64 -include ../../../../Makefile.module - -C99MODE= $(C99_ENABLE) - -CPPFLAGS += -DMP -D_MACHDEP -D_MDB -D__xpv -CPPFLAGS += -U_KERNEL -D_KMEMUSER -CPPFLAGS += -I../../../../common -CPPFLAGS += -I$(SRC)/uts/common -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -CPPFLAGS += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -CPPFLAGS += -I$(SRC)/uts/intel diff --git a/usr/src/cmd/mdb/intel/modules/mdb_kb/mdb_kb.c b/usr/src/cmd/mdb/intel/modules/mdb_kb/mdb_kb.c deleted file mode 100644 index 959db8dba9..0000000000 --- a/usr/src/cmd/mdb/intel/modules/mdb_kb/mdb_kb.c +++ /dev/null @@ -1,1607 +0,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. - */ - -/* - * KVM backend for hypervisor domain dumps. We don't use libkvm for - * such dumps, since they do not have a namelist file or the typical - * dump structures we expect to aid bootstrapping. Instead, we - * bootstrap based upon a debug_info structure at a known VA, using the - * guest's own page tables to resolve to physical addresses, and - * construct the namelist in a manner similar to ksyms_snapshot(). - * - * Note that there are two formats understood by this module: the older, - * ad hoc format, which we call 'core' within this file, and an - * ELF-based format, known as 'elf'. - * - * We only support the older format generated on Solaris dom0: before we - * fixed it, core dump files were broken whenever a PFN didn't map a - * real MFN (!). - */ - -#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 XKB_SHDR_NULL 0 -#define XKB_SHDR_SYMTAB 1 -#define XKB_SHDR_STRTAB 2 -#define XKB_SHDR_SHSTRTAB 3 -#define XKB_SHDR_NUM 4 - -#define XKB_WALK_LOCAL 0x1 -#define XKB_WALK_GLOBAL 0x2 -#define XKB_WALK_STR 0x4 -#define XKB_WALK_ALL (XKB_WALK_LOCAL | XKB_WALK_GLOBAL | XKB_WALK_STR) - -#if defined(__i386) -#define DEBUG_INFO 0xf4bff000 -#define DEBUG_INFO_HVM 0xfe7ff000 -#elif defined(__amd64) -#define DEBUG_INFO 0xfffffffffb7ff000 -#define DEBUG_INFO_HVM 0xfffffffffb7ff000 -#endif - -#define PAGE_SIZE 0x1000 -#define PAGE_SHIFT 12 -#define PAGE_OFFSET(a) ((a) & (PAGE_SIZE - 1)) -#define PAGE_MASK(a) ((a) & ~(PAGE_SIZE - 1)) -#define PAGE_ALIGNED(a) (((a) & (PAGE_SIZE -1)) == 0) -#define PT_PADDR_LGPG 0x000fffffffffe000ull -#define PT_PADDR 0x000ffffffffff000ull -#define PT_VALID 0x1 -#define PT_PAGESIZE 0x080 -#define PTE_IS_LGPG(p, l) ((l) > 0 && ((p) & PT_PAGESIZE)) - -#define XC_CORE_MAGIC 0xF00FEBED -#define XC_CORE_MAGIC_HVM 0xF00FEBEE - -#define VGCF_HVM_GUEST (1<<1) - -typedef struct xc_core_header { - unsigned int xch_magic; - unsigned int xch_nr_vcpus; - unsigned int xch_nr_pages; - unsigned int xch_ctxt_offset; - unsigned int xch_index_offset; - unsigned int xch_pages_offset; -} xc_core_header_t; - -struct xc_elf_header { - uint64_t xeh_magic; - uint64_t xeh_nr_vcpus; - uint64_t xeh_nr_pages; - uint64_t xeh_page_size; -}; - -struct xc_elf_version { - uint64_t xev_major; - uint64_t xev_minor; - xen_extraversion_t xev_extra; - xen_compile_info_t xev_compile_info; - xen_capabilities_info_t xev_capabilities; - xen_changeset_info_t xev_changeset; - xen_platform_parameters_t xev_platform_parameters; - uint64_t xev_pagesize; -}; - -/* - * Either an old-style (3.0.4) core format, or the ELF format. - */ -typedef enum { - XKB_FORMAT_UNKNOWN = 0, - XKB_FORMAT_CORE = 1, - XKB_FORMAT_ELF = 2 -} xkb_type_t; - -typedef struct mfn_map { - mfn_t mm_mfn; - char *mm_map; -} mfn_map_t; - -typedef struct mmu_info { - size_t mi_max; - size_t mi_shift[4]; - size_t mi_ptes; - size_t mi_ptesize; -} mmu_info_t; - -typedef struct xkb_core { - xc_core_header_t xc_hdr; - void *xc_p2m_buf; -} xkb_core_t; - -typedef struct xkb_elf { - mdb_gelf_file_t *xe_gelf; - size_t *xe_off; - struct xc_elf_header xe_hdr; - struct xc_elf_version xe_version; -} xkb_elf_t; - -typedef struct xkb { - char *xkb_path; - int xkb_fd; - int xkb_is_hvm; - - xkb_type_t xkb_type; - xkb_core_t xkb_core; - xkb_elf_t xkb_elf; - - size_t xkb_nr_vcpus; - size_t xkb_nr_pages; - size_t xkb_pages_off; - xen_pfn_t xkb_max_pfn; - mfn_t xkb_max_mfn; - int xkb_is_pae; - - mmu_info_t xkb_mmu; - debug_info_t xkb_info; - - void *xkb_vcpu_data; - size_t xkb_vcpu_data_sz; - struct vcpu_guest_context **xkb_vcpus; - - char *xkb_pages; - mfn_t *xkb_p2m; - xen_pfn_t *xkb_m2p; - mfn_map_t xkb_pt_map[4]; - mfn_map_t xkb_map; - - char *xkb_namelist; - size_t xkb_namesize; -} xkb_t; - -static const char xkb_shstrtab[] = "\0.symtab\0.strtab\0.shstrtab\0"; - -typedef struct xkb_namelist { - Ehdr kh_elf_hdr; - Phdr kh_text_phdr; - Phdr kh_data_phdr; - Shdr kh_shdr[XKB_SHDR_NUM]; - char shstrings[sizeof (xkb_shstrtab)]; -} xkb_namelist_t; - -static int xkb_build_ksyms(xkb_t *); -static offset_t xkb_mfn_to_offset(xkb_t *, mfn_t); -static mfn_t xkb_va_to_mfn(xkb_t *, uintptr_t, mfn_t); -static ssize_t xkb_read(xkb_t *, uintptr_t, void *, size_t); -static int xkb_read_word(xkb_t *, uintptr_t, uintptr_t *); -static char *xkb_map_mfn(xkb_t *, mfn_t, mfn_map_t *); -static int xkb_close(xkb_t *); - -/* - * Jump through the hoops we need to to correctly identify a core file - * of either the old or new format. - */ -int -xkb_identify(const char *file, int *longmode) -{ - xc_core_header_t header; - mdb_gelf_file_t *gf = NULL; - mdb_gelf_sect_t *sect = NULL; - mdb_io_t *io = NULL; - char *notes = NULL; - char *pos; - int ret = 0; - size_t sz; - int fd; - - if ((fd = open64(file, O_RDONLY)) == -1) - return (-1); - - if (pread64(fd, &header, sizeof (header), 0) != sizeof (header)) { - (void) close(fd); - return (0); - } - - (void) close(fd); - - if (header.xch_magic == XC_CORE_MAGIC) { - *longmode = 0; - - /* - * Indeed. - */ - sz = header.xch_index_offset - header.xch_ctxt_offset; -#ifdef _LP64 - if (sizeof (struct vcpu_guest_context) * - header.xch_nr_vcpus == sz) - *longmode = 1; -#else - if (sizeof (struct vcpu_guest_context) * - header.xch_nr_vcpus != sz) - *longmode = 1; -#endif /* _LP64 */ - - return (1); - } - - if ((io = mdb_fdio_create_path(NULL, file, O_RDONLY, 0)) == NULL) - return (-1); - - if ((gf = mdb_gelf_create(io, ET_NONE, GF_FILE)) == NULL) - goto out; - - if ((sect = mdb_gelf_sect_by_name(gf, ".note.Xen")) == NULL) - goto out; - - if ((notes = mdb_gelf_sect_load(gf, sect)) == NULL) - goto out; - - for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) { - struct xc_elf_version *vers; - /* LINTED - alignment */ - Elf64_Nhdr *nhdr = (Elf64_Nhdr *)pos; - char *desc; - char *name; - - name = pos + sizeof (*nhdr); - desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4); - - pos = desc + nhdr->n_descsz; - - if (nhdr->n_type != XEN_ELFNOTE_DUMPCORE_XEN_VERSION) - continue; - - /* - * The contents of this struct differ between 32 and 64 - * bit; however, not until past the 'xev_capabilities' - * member, so we can just about get away with this. - */ - - /* LINTED - alignment */ - vers = (struct xc_elf_version *)desc; - - if (strstr(vers->xev_capabilities, "x86_64")) { - /* - * 64-bit hypervisor, but it can still be - * a 32-bit domain core. 32-bit domain cores - * are also dumped in Elf64 format, but they - * have e_machine set to EM_386, not EM_AMD64. - */ - if (gf->gf_ehdr.e_machine == EM_386) - *longmode = 0; - else - *longmode = 1; - } else if (strstr(vers->xev_capabilities, "x86_32") || - strstr(vers->xev_capabilities, "x86_32p")) { - /* - * 32-bit hypervisor, can only be a 32-bit core. - */ - *longmode = 0; - } else { - mdb_warn("couldn't derive word size of dump; " - "assuming 64-bit"); - *longmode = 1; - } - } - - ret = 1; - -out: - if (gf != NULL) - mdb_gelf_destroy(gf); - else if (io != NULL) - mdb_io_destroy(io); - return (ret); -} - -static void * -xkb_fail(xkb_t *xkb, const char *msg, ...) -{ - va_list args; - - va_start(args, msg); - if (xkb != NULL) - (void) fprintf(stderr, "%s: ", xkb->xkb_path); - (void) vfprintf(stderr, msg, args); - (void) fprintf(stderr, "\n"); - va_end(args); - if (xkb != NULL) - (void) xkb_close(xkb); - - errno = ENOEXEC; - - return (NULL); -} - -static int -xkb_build_m2p(xkb_t *xkb) -{ - size_t i; - - for (i = 0; i <= xkb->xkb_max_pfn; i++) { - if (xkb->xkb_p2m[i] != MFN_INVALID && - xkb->xkb_p2m[i] > xkb->xkb_max_mfn) - xkb->xkb_max_mfn = xkb->xkb_p2m[i]; - } - - xkb->xkb_m2p = mdb_alloc((xkb->xkb_max_mfn + 1) * sizeof (xen_pfn_t), - UM_SLEEP); - - for (i = 0; i <= xkb->xkb_max_mfn; i++) - xkb->xkb_m2p[i] = PFN_INVALID; - - for (i = 0; i <= xkb->xkb_max_pfn; i++) { - if (xkb->xkb_p2m[i] != MFN_INVALID) - xkb->xkb_m2p[xkb->xkb_p2m[i]] = i; - } - - return (1); -} - -/* - * With FORMAT_CORE, we can use the table in the dump file directly. - * Just to make things fun, they've not page-aligned the p2m table. - */ -static int -xkb_map_p2m(xkb_t *xkb) -{ - offset_t off; - size_t size; - xkb_core_t *xc = &xkb->xkb_core; - size_t count = xkb->xkb_nr_pages; - size_t boff = xc->xc_hdr.xch_index_offset; - - size = (sizeof (mfn_t) * count) + (PAGE_SIZE * 2); - size = PAGE_MASK(size); - off = PAGE_MASK(boff); - - /* LINTED - alignment */ - xc->xc_p2m_buf = mmap(NULL, size, PROT_READ, - MAP_SHARED, xkb->xkb_fd, off); - - if (xc->xc_p2m_buf == (xen_pfn_t *)MAP_FAILED) { - (void) xkb_fail(xkb, "cannot map p2m table"); - return (0); - } - - /* LINTED - alignment */ - xkb->xkb_p2m = (mfn_t *)((char *)xc->xc_p2m_buf + - PAGE_OFFSET(boff)); - - return (1); -} - -/* - * With FORMAT_ELF, we have a set of pairs, which we convert - * into a linear array indexed by pfn for convenience. We also need to - * track the mapping between mfn and the offset in the file: a pfn with - * no mfn will not appear in the core file. - */ -static int -xkb_build_p2m(xkb_t *xkb) -{ - xkb_elf_t *xe = &xkb->xkb_elf; - mdb_gelf_sect_t *sect; - size_t size; - size_t i; - - struct elf_p2m { - uint64_t pfn; - uint64_t gmfn; - } *p2m; - - sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_p2m"); - - if (sect == NULL) { - (void) xkb_fail(xkb, "cannot find section .xen_p2m"); - return (0); - } - - if ((p2m = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) { - (void) xkb_fail(xkb, "couldn't read .xen_p2m"); - return (0); - } - - for (i = 0; i < xkb->xkb_nr_pages; i++) { - if (p2m[i].pfn > xkb->xkb_max_pfn) - xkb->xkb_max_pfn = p2m[i].pfn; - } - - size = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1); - xkb->xkb_p2m = mdb_alloc(size, UM_SLEEP); - size = sizeof (size_t) * (xkb->xkb_max_pfn + 1); - xe->xe_off = mdb_alloc(size, UM_SLEEP); - - for (i = 0; i <= xkb->xkb_max_pfn; i++) { - xkb->xkb_p2m[i] = PFN_INVALID; - xe->xe_off[i] = (size_t)-1; - } - - for (i = 0; i < xkb->xkb_nr_pages; i++) { - xkb->xkb_p2m[p2m[i].pfn] = p2m[i].gmfn; - xe->xe_off[p2m[i].pfn] = i; - } - - return (1); -} - -/* - * For HVM images, we don't have the corresponding MFN list; the table - * is just a mapping from page index in the dump to the corresponding - * PFN. To simplify the other code, we'll pretend that these PFNs are - * really MFNs as well, by populating xkb_p2m. - */ -static int -xkb_build_fake_p2m(xkb_t *xkb) -{ - xkb_elf_t *xe = &xkb->xkb_elf; - mdb_gelf_sect_t *sect; - size_t size; - size_t i; - - uint64_t *p2pfn; - - sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pfn"); - - if (sect == NULL) { - (void) xkb_fail(xkb, "cannot find section .xen_pfn"); - return (0); - } - - if ((p2pfn = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) { - (void) xkb_fail(xkb, "couldn't read .xen_pfn"); - return (0); - } - - for (i = 0; i < xkb->xkb_nr_pages; i++) { - if (p2pfn[i] != PFN_INVALID && p2pfn[i] > xkb->xkb_max_pfn) - xkb->xkb_max_pfn = p2pfn[i]; - } - - size = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1); - xkb->xkb_p2m = mdb_alloc(size, UM_SLEEP); - - size = sizeof (size_t) * (xkb->xkb_max_pfn + 1); - xe->xe_off = mdb_alloc(size, UM_SLEEP); - - for (i = 0; i <= xkb->xkb_max_pfn; i++) { - xkb->xkb_p2m[i] = PFN_INVALID; - xe->xe_off[i] = (size_t)-1; - } - - for (i = 0; i < xkb->xkb_nr_pages; i++) { - if (p2pfn[i] == PFN_INVALID) - continue; - xkb->xkb_p2m[p2pfn[i]] = p2pfn[i]; - xe->xe_off[p2pfn[i]] = i; - } - - return (1); -} - -/* - * Return the MFN of the top-level page table for the given as. - */ -static mfn_t -xkb_as_to_mfn(xkb_t *xkb, struct as *as) -{ - uintptr_t asp = (uintptr_t)as; - uintptr_t hatp; - uintptr_t htablep; - uintptr_t pfn; - - if (!xkb_read_word(xkb, asp + offsetof(struct as, a_hat), &hatp)) - return (MFN_INVALID); - if (!xkb_read_word(xkb, hatp + xkb->xkb_info.di_hat_htable_off, - &htablep)) - return (MFN_INVALID); - if (!xkb_read_word(xkb, htablep + xkb->xkb_info.di_ht_pfn_off, - &pfn)) - return (MFN_INVALID); - - if (pfn > xkb->xkb_max_pfn) - return (MFN_INVALID); - - return (xkb->xkb_p2m[pfn]); -} - -static mfn_t -xkb_cr3_to_pfn(xkb_t *xkb) -{ - uint64_t cr3 = xkb->xkb_vcpus[0]->ctrlreg[3]; - if (xkb->xkb_is_hvm) - return (cr3 >> PAGE_SHIFT); - return (xen_cr3_to_pfn(cr3)); -} - -static ssize_t -xkb_read_helper(xkb_t *xkb, struct as *as, int phys, uint64_t addr, - void *buf, size_t size) -{ - size_t left = size; - int windowed = (xkb->xkb_pages == NULL); - mfn_t tlmfn = xkb_cr3_to_pfn(xkb); - - if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID) - return (-1); - - while (left) { - uint64_t pos = addr + (size - left); - char *outpos = (char *)buf + (size - left); - size_t pageoff = PAGE_OFFSET(pos); - size_t sz = MIN(left, PAGE_SIZE - pageoff); - mfn_t mfn; - - if (!phys) { - mfn = xkb_va_to_mfn(xkb, pos, tlmfn); - if (mfn == MFN_INVALID) - return (-1); - } else { - xen_pfn_t pfn = pos >> PAGE_SHIFT; - if (pfn > xkb->xkb_max_pfn) - return (-1); - mfn = xkb->xkb_p2m[pfn]; - if (mfn == MFN_INVALID) - return (-1); - } - - /* - * If we're windowed then pread() is much faster. - */ - if (windowed) { - offset_t off = xkb_mfn_to_offset(xkb, mfn); - int ret; - - if (off == ~1ULL) - return (-1); - - off += pageoff; - - ret = pread64(xkb->xkb_fd, outpos, sz, off); - if (ret == -1) - return (-1); - if (ret != sz) - return ((size - left) + ret); - - left -= ret; - } else { - if (xkb_map_mfn(xkb, mfn, &xkb->xkb_map) == NULL) - return (-1); - - bcopy(xkb->xkb_map.mm_map + pageoff, outpos, sz); - - left -= sz; - } - } - - return (size); -} - -static ssize_t -xkb_pread(xkb_t *xkb, uint64_t addr, void *buf, size_t size) -{ - return (xkb_read_helper(xkb, NULL, 1, addr, buf, size)); -} - -static ssize_t -xkb_aread(xkb_t *xkb, uintptr_t addr, void *buf, size_t size, struct as *as) -{ - return (xkb_read_helper(xkb, as, 0, addr, buf, size)); -} - -static ssize_t -xkb_read(xkb_t *xkb, uintptr_t addr, void *buf, size_t size) -{ - return (xkb_aread(xkb, addr, buf, size, NULL)); -} - -static int -xkb_read_word(xkb_t *xkb, uintptr_t addr, uintptr_t *buf) -{ - if (xkb_read(xkb, addr, buf, sizeof (uintptr_t)) != - sizeof (uintptr_t)) - return (0); - return (1); -} - -static char * -xkb_readstr(xkb_t *xkb, uintptr_t addr) -{ - char *str = mdb_alloc(1024, UM_SLEEP); - size_t i; - - for (i = 0; i < 1024; i++) { - if (xkb_read(xkb, addr + i, &str[i], 1) != 1) { - mdb_free(str, 1024); - return (NULL); - } - - if (str[i] == '\0') - break; - } - - if (i == 1024) { - mdb_free(str, 1024); - return (NULL); - } - - return (str); -} - -static offset_t -xkb_pfn_to_off(xkb_t *xkb, xen_pfn_t pfn) -{ - if (pfn == PFN_INVALID || pfn > xkb->xkb_max_pfn) - return (-1ULL); - - if (xkb->xkb_type == XKB_FORMAT_CORE) - return (PAGE_SIZE * pfn); - - return (PAGE_SIZE * (xkb->xkb_elf.xe_off[pfn])); -} - -static offset_t -xkb_mfn_to_offset(xkb_t *xkb, mfn_t mfn) -{ - xen_pfn_t pfn; - - if (mfn > xkb->xkb_max_mfn) - return (-1ULL); - - pfn = xkb->xkb_m2p[mfn]; - - if (pfn == PFN_INVALID) - return (-1ULL); - - return (xkb->xkb_pages_off + xkb_pfn_to_off(xkb, pfn)); -} - -static char * -xkb_map_mfn(xkb_t *xkb, mfn_t mfn, mfn_map_t *mm) -{ - int windowed = (xkb->xkb_pages == NULL); - offset_t off; - - if (mm->mm_mfn == mfn) - return (mm->mm_map); - - mm->mm_mfn = mfn; - - if (windowed) { - if (mm->mm_map != (char *)MAP_FAILED) { - (void) munmap(mm->mm_map, PAGE_SIZE); - mm->mm_map = (void *)MAP_FAILED; - } - - if ((off = xkb_mfn_to_offset(xkb, mfn)) == (-1ULL)) - return (NULL); - - mm->mm_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, - xkb->xkb_fd, off); - - if (mm->mm_map == (char *)MAP_FAILED) - return (NULL); - } else { - xen_pfn_t pfn; - - mm->mm_map = NULL; - - if (mfn > xkb->xkb_max_mfn) - return (NULL); - - pfn = xkb->xkb_m2p[mfn]; - - if (pfn == PFN_INVALID) - return (NULL); - - mm->mm_map = xkb->xkb_pages + xkb_pfn_to_off(xkb, pfn); - } - - return (mm->mm_map); -} - -static uint64_t -xkb_get_pte(mmu_info_t *mmu, char *ptep) -{ - uint64_t pte = 0; - - if (mmu->mi_ptesize == 8) { - /* LINTED - alignment */ - pte = *((uint64_t *)ptep); - } else { - /* LINTED - alignment */ - pte = *((uint32_t *)ptep); - } - - return (pte); -} - -static mfn_t -xkb_pte_to_base_mfn(uint64_t pte, size_t level) -{ - if (PTE_IS_LGPG(pte, level)) { - pte &= PT_PADDR_LGPG; - } else { - pte &= PT_PADDR; - } - - return (pte >> PAGE_SHIFT); -} - -/* - * Resolve the given VA into an MFN, using the provided mfn as a top-level page - * table. - */ -static mfn_t -xkb_va_to_mfn(xkb_t *xkb, uintptr_t va, mfn_t mfn) -{ - mmu_info_t *mmu = &xkb->xkb_mmu; - uint64_t pte; - size_t level; - - for (level = mmu->mi_max; ; --level) { - size_t entry; - - if (xkb_map_mfn(xkb, mfn, &xkb->xkb_pt_map[level]) == NULL) - return (MFN_INVALID); - - entry = (va >> mmu->mi_shift[level]) & (mmu->mi_ptes - 1); - - pte = xkb_get_pte(mmu, (char *)xkb->xkb_pt_map[level].mm_map + - entry * mmu->mi_ptesize); - - if ((mfn = xkb_pte_to_base_mfn(pte, level)) == MFN_INVALID) - return (MFN_INVALID); - - if (level == 0) - break; - - /* - * Currently 'mfn' refers to the base MFN of the - * large-page mapping. Add on the 4K-sized index into - * the large-page mapping to get the right MFN within - * the mapping. - */ - if (PTE_IS_LGPG(pte, level)) { - mfn += (va & ((1 << mmu->mi_shift[level]) - 1)) >> - PAGE_SHIFT; - break; - } - } - - return (mfn); -} - -static int -xkb_read_module(xkb_t *xkb, uintptr_t modulep, struct module *module, - uintptr_t *sym_addr, uintptr_t *sym_count, uintptr_t *str_addr) -{ - if (xkb_read(xkb, modulep, module, sizeof (struct module)) != - sizeof (struct module)) - return (0); - - if (!xkb_read_word(xkb, (uintptr_t)module->symhdr + - offsetof(Shdr, sh_addr), sym_addr)) - return (0); - - if (!xkb_read_word(xkb, (uintptr_t)module->strhdr + - offsetof(Shdr, sh_addr), str_addr)) - return (0); - - if (!xkb_read_word(xkb, (uintptr_t)module->symhdr + - offsetof(Shdr, sh_size), sym_count)) - return (0); - *sym_count /= sizeof (Sym); - - return (1); -} - -static int -xkb_read_modsyms(xkb_t *xkb, char **buf, size_t *sizes, int types, - uintptr_t sym_addr, uintptr_t str_addr, uintptr_t sym_count) -{ - size_t i; - - for (i = 0; i < sym_count; i++) { - Sym sym; - char *name; - size_t sz; - int type = XKB_WALK_GLOBAL; - - if (xkb_read(xkb, sym_addr + i * sizeof (sym), &sym, - sizeof (sym)) != sizeof (sym)) - return (0); - - if (GELF_ST_BIND(sym.st_info) == STB_LOCAL) - type = XKB_WALK_LOCAL; - - name = xkb_readstr(xkb, str_addr + sym.st_name); - - sym.st_shndx = SHN_ABS; - sym.st_name = sizes[XKB_WALK_STR]; - - sizes[type] += sizeof (sym); - sz = strlen(name) + 1; - sizes[XKB_WALK_STR] += sz; - - if (buf != NULL) { - if (types & type) { - bcopy(&sym, *buf, sizeof (sym)); - *buf += sizeof (sym); - } - if (types & XKB_WALK_STR) { - bcopy(name, *buf, sz); - *buf += sz; - } - } - - mdb_free(name, 1024); - } - - return (1); -} - -static int -xkb_walk_syms(xkb_t *xkb, uintptr_t modhead, char **buf, - size_t *sizes, int types) -{ - uintptr_t modctl = modhead; - uintptr_t modulep; - struct module module; - uintptr_t sym_count; - uintptr_t sym_addr; - uintptr_t str_addr; - size_t max_iter = 500; - - bzero(sizes, sizeof (*sizes) * (XKB_WALK_STR + 1)); - - /* - * empty first symbol - */ - sizes[XKB_WALK_LOCAL] += sizeof (Sym); - sizes[XKB_WALK_STR] += 1; - - if (buf != NULL) { - if (types & XKB_WALK_LOCAL) { - Sym tmp; - bzero(&tmp, sizeof (tmp)); - bcopy(&tmp, *buf, sizeof (tmp)); - *buf += sizeof (tmp); - } - if (types & XKB_WALK_STR) { - **buf = '\0'; - (*buf)++; - } - } - - for (;;) { - if (!xkb_read_word(xkb, - modctl + offsetof(struct modctl, mod_mp), &modulep)) - return (0); - - if (modulep == (uintptr_t)NULL) - goto next; - - if (!xkb_read_module(xkb, modulep, &module, &sym_addr, - &sym_count, &str_addr)) - return (0); - - if ((module.flags & KOBJ_NOKSYMS)) - goto next; - - if (!xkb_read_modsyms(xkb, buf, sizes, types, sym_addr, - str_addr, sym_count)) - return (0); - -next: - if (!xkb_read_word(xkb, - modctl + offsetof(struct modctl, mod_next), &modctl)) - return (0); - - if (modctl == modhead) - break; - /* - * Try and prevent us looping forever if we have a broken list. - */ - if (--max_iter == 0) - break; - } - - return (1); -} - -/* - * Userspace equivalent of ksyms_snapshot(). Since we don't have a namelist - * file for hypervisor images, we fabricate one here using code similar - * to that of /dev/ksyms. - */ -static int -xkb_build_ksyms(xkb_t *xkb) -{ - debug_info_t *info = &xkb->xkb_info; - size_t sizes[XKB_WALK_STR + 1]; - xkb_namelist_t *hdr; - char *buf; - struct modctl modules; - uintptr_t module; - Shdr *shp; - - if (xkb_read(xkb, info->di_modules, &modules, - sizeof (struct modctl)) != sizeof (struct modctl)) - return (0); - - module = (uintptr_t)modules.mod_mp; - - if (!xkb_walk_syms(xkb, info->di_modules, NULL, sizes, - XKB_WALK_LOCAL | XKB_WALK_GLOBAL | XKB_WALK_STR)) - return (0); - - xkb->xkb_namesize = sizeof (xkb_namelist_t); - xkb->xkb_namesize += sizes[XKB_WALK_LOCAL]; - xkb->xkb_namesize += sizes[XKB_WALK_GLOBAL]; - xkb->xkb_namesize += sizes[XKB_WALK_STR]; - - if ((xkb->xkb_namelist = mdb_zalloc(xkb->xkb_namesize, UM_SLEEP)) - == NULL) - return (0); - - /* LINTED - alignment */ - hdr = (xkb_namelist_t *)xkb->xkb_namelist; - - if (xkb_read(xkb, module + offsetof(struct module, hdr), - &hdr->kh_elf_hdr, sizeof (Ehdr)) != sizeof (Ehdr)) - return (0); - - hdr->kh_elf_hdr.e_phoff = offsetof(xkb_namelist_t, kh_text_phdr); - hdr->kh_elf_hdr.e_shoff = offsetof(xkb_namelist_t, kh_shdr); - hdr->kh_elf_hdr.e_phnum = 2; - hdr->kh_elf_hdr.e_shnum = XKB_SHDR_NUM; - hdr->kh_elf_hdr.e_shstrndx = XKB_SHDR_SHSTRTAB; - - hdr->kh_text_phdr.p_type = PT_LOAD; - hdr->kh_text_phdr.p_vaddr = (Addr)info->di_s_text; - hdr->kh_text_phdr.p_memsz = (Word)(info->di_e_text - info->di_s_text); - hdr->kh_text_phdr.p_flags = PF_R | PF_X; - - hdr->kh_data_phdr.p_type = PT_LOAD; - hdr->kh_data_phdr.p_vaddr = (Addr)info->di_s_data; - hdr->kh_data_phdr.p_memsz = (Word)(info->di_e_data - info->di_s_data); - hdr->kh_data_phdr.p_flags = PF_R | PF_W | PF_X; - - shp = &hdr->kh_shdr[XKB_SHDR_SYMTAB]; - shp->sh_name = 1; /* xkb_shstrtab[1] = ".symtab" */ - shp->sh_type = SHT_SYMTAB; - shp->sh_offset = sizeof (xkb_namelist_t); - shp->sh_size = sizes[XKB_WALK_LOCAL] + sizes[XKB_WALK_GLOBAL]; - shp->sh_link = XKB_SHDR_STRTAB; - shp->sh_info = sizes[XKB_WALK_LOCAL] / sizeof (Sym); - shp->sh_addralign = sizeof (Addr); - shp->sh_entsize = sizeof (Sym); - shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset); - - - shp = &hdr->kh_shdr[XKB_SHDR_STRTAB]; - shp->sh_name = 9; /* xkb_shstrtab[9] = ".strtab" */ - shp->sh_type = SHT_STRTAB; - shp->sh_offset = sizeof (xkb_namelist_t) + - sizes[XKB_WALK_LOCAL] + sizes[XKB_WALK_GLOBAL]; - shp->sh_size = sizes[XKB_WALK_STR]; - shp->sh_addralign = 1; - shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset); - - - shp = &hdr->kh_shdr[XKB_SHDR_SHSTRTAB]; - shp->sh_name = 17; /* xkb_shstrtab[17] = ".shstrtab" */ - shp->sh_type = SHT_STRTAB; - shp->sh_offset = offsetof(xkb_namelist_t, shstrings); - shp->sh_size = sizeof (xkb_shstrtab); - shp->sh_addralign = 1; - shp->sh_addr = (Addr)(xkb->xkb_namelist + shp->sh_offset); - - bcopy(xkb_shstrtab, hdr->shstrings, sizeof (xkb_shstrtab)); - - buf = xkb->xkb_namelist + sizeof (xkb_namelist_t); - - if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes, - XKB_WALK_LOCAL)) - return (0); - if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes, - XKB_WALK_GLOBAL)) - return (0); - if (!xkb_walk_syms(xkb, info->di_modules, &buf, sizes, - XKB_WALK_STR)) - return (0); - - return (1); -} - -static xkb_t * -xkb_open_core(xkb_t *xkb) -{ - xkb_core_t *xc = &xkb->xkb_core; - size_t sz; - int i; - struct vcpu_guest_context *vcp; - - xkb->xkb_type = XKB_FORMAT_CORE; - - if ((xkb->xkb_fd = open64(xkb->xkb_path, O_RDONLY)) == -1) - return (xkb_fail(xkb, "cannot open %s", xkb->xkb_path)); - - if (pread64(xkb->xkb_fd, &xc->xc_hdr, sizeof (xc->xc_hdr), 0) != - sizeof (xc->xc_hdr)) - return (xkb_fail(xkb, "invalid dump file")); - - if (xc->xc_hdr.xch_magic == XC_CORE_MAGIC_HVM) - return (xkb_fail(xkb, "cannot process HVM images")); - - if (xc->xc_hdr.xch_magic != XC_CORE_MAGIC) { - return (xkb_fail(xkb, "invalid magic %d", - xc->xc_hdr.xch_magic)); - } - - /* - * With FORMAT_CORE, all pages are in the dump (non-existing - * ones are zeroed out). - */ - xkb->xkb_nr_pages = xc->xc_hdr.xch_nr_pages; - xkb->xkb_pages_off = xc->xc_hdr.xch_pages_offset; - xkb->xkb_max_pfn = xc->xc_hdr.xch_nr_pages - 1; - xkb->xkb_nr_vcpus = xc->xc_hdr.xch_nr_vcpus; - - sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context); - xkb->xkb_vcpu_data_sz = sz; - xkb->xkb_vcpu_data = mdb_alloc(sz, UM_SLEEP); - - if (pread64(xkb->xkb_fd, xkb->xkb_vcpu_data, sz, - xc->xc_hdr.xch_ctxt_offset) != sz) - return (xkb_fail(xkb, "cannot read VCPU contexts")); - - sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *); - xkb->xkb_vcpus = mdb_alloc(sz, UM_SLEEP); - - vcp = xkb->xkb_vcpu_data; - for (i = 0; i < xkb->xkb_nr_vcpus; i++) - xkb->xkb_vcpus[i] = &vcp[i]; - - /* - * Try to map all the data pages. If we can't, fall back to the - * window/pread() approach, which is significantly slower. - */ - xkb->xkb_pages = mmap(NULL, PAGE_SIZE * xkb->xkb_nr_pages, - PROT_READ, MAP_SHARED, xkb->xkb_fd, xc->xc_hdr.xch_pages_offset); - - if (xkb->xkb_pages == (char *)MAP_FAILED) - xkb->xkb_pages = NULL; - - /* - * We'd like to adapt for correctness' sake, but we have no way of - * detecting a PAE guest, since cr4 writes are disallowed. - */ - xkb->xkb_is_pae = 1; - - if (!xkb_map_p2m(xkb)) - return (NULL); - - return (xkb); -} - -static xkb_t * -xkb_open_elf(xkb_t *xkb) -{ - xkb_elf_t *xe = &xkb->xkb_elf; - mdb_gelf_sect_t *sect; - char *notes; - char *pos; - mdb_io_t *io; - size_t sz; - int i; - void *dp; - - if ((io = mdb_fdio_create_path(NULL, xkb->xkb_path, - O_RDONLY, 0)) == NULL) - return (xkb_fail(xkb, "failed to open")); - - xe->xe_gelf = mdb_gelf_create(io, ET_NONE, GF_FILE); - - if (xe->xe_gelf == NULL) { - mdb_io_destroy(io); - return (xkb); - } - - xkb->xkb_fd = mdb_fdio_fileno(io); - - sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".note.Xen"); - - if (sect == NULL) - return (xkb); - - if ((notes = mdb_gelf_sect_load(xe->xe_gelf, sect)) == NULL) - return (xkb); - - /* - * Now we know this is indeed a hypervisor core dump, even if - * it's corrupted. - */ - xkb->xkb_type = XKB_FORMAT_ELF; - - for (pos = notes; pos < notes + sect->gs_shdr.sh_size; ) { - /* LINTED - alignment */ - Elf64_Nhdr *nhdr = (Elf64_Nhdr *)pos; - uint64_t vers; - char *desc; - char *name; - - name = pos + sizeof (*nhdr); - desc = (char *)P2ROUNDUP((uintptr_t)name + nhdr->n_namesz, 4); - - pos = desc + nhdr->n_descsz; - - switch (nhdr->n_type) { - case XEN_ELFNOTE_DUMPCORE_NONE: - break; - - case XEN_ELFNOTE_DUMPCORE_HEADER: - if (nhdr->n_descsz != sizeof (struct xc_elf_header)) { - return (xkb_fail(xkb, "invalid ELF note " - "XEN_ELFNOTE_DUMPCORE_HEADER\n")); - } - - bcopy(desc, &xe->xe_hdr, - sizeof (struct xc_elf_header)); - break; - - case XEN_ELFNOTE_DUMPCORE_XEN_VERSION: - if (nhdr->n_descsz < sizeof (struct xc_elf_version)) { - return (xkb_fail(xkb, "invalid ELF note " - "XEN_ELFNOTE_DUMPCORE_XEN_VERSION\n")); - } - - bcopy(desc, &xe->xe_version, - sizeof (struct xc_elf_version)); - break; - - case XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION: - /* LINTED - alignment */ - vers = *((uint64_t *)desc); - if ((vers >> 32) != 0) { - return (xkb_fail(xkb, "unknown major " - "version %d (expected 0)\n", - (int)(vers >> 32))); - } - - if ((vers & 0xffffffff) != 1) { - mdb_warn("unexpected dump minor number " - "version %d (expected 1)\n", - (int)(vers & 0xffffffff)); - } - break; - - default: - mdb_warn("unknown ELF note %d(%s)\n", - nhdr->n_type, name); - break; - } - } - - xkb->xkb_is_hvm = xe->xe_hdr.xeh_magic == XC_CORE_MAGIC_HVM; - - if (xe->xe_hdr.xeh_magic != XC_CORE_MAGIC && - xe->xe_hdr.xeh_magic != XC_CORE_MAGIC_HVM) { - return (xkb_fail(xkb, "invalid magic %d", - xe->xe_hdr.xeh_magic)); - } - - xkb->xkb_nr_pages = xe->xe_hdr.xeh_nr_pages; - xkb->xkb_is_pae = (strstr(xe->xe_version.xev_capabilities, - "x86_32p") != NULL); - - sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_prstatus"); - - if (sect == NULL) - return (xkb_fail(xkb, "cannot find section .xen_prstatus")); - - if (sect->gs_shdr.sh_entsize < sizeof (vcpu_guest_context_t)) - return (xkb_fail(xkb, "invalid section .xen_prstatus")); - - xkb->xkb_nr_vcpus = sect->gs_shdr.sh_size / sect->gs_shdr.sh_entsize; - - xkb->xkb_vcpu_data = mdb_gelf_sect_load(xe->xe_gelf, sect); - if (xkb->xkb_vcpu_data == NULL) - return (xkb_fail(xkb, "cannot load section .xen_prstatus")); - xkb->xkb_vcpu_data_sz = sect->gs_shdr.sh_size; - - /* - * The vcpu_guest_context structures saved in the core file - * are actually unions of the 64-bit and 32-bit versions. - * Don't rely on the entry size to match the size of - * the structure, but set up an array of pointers. - */ - sz = xkb->xkb_nr_vcpus * sizeof (struct vcpu_guest_context *); - xkb->xkb_vcpus = mdb_alloc(sz, UM_SLEEP); - for (i = 0; i < xkb->xkb_nr_vcpus; i++) { - dp = ((char *)xkb->xkb_vcpu_data + - i * sect->gs_shdr.sh_entsize); - xkb->xkb_vcpus[i] = dp; - } - - sect = mdb_gelf_sect_by_name(xe->xe_gelf, ".xen_pages"); - - if (sect == NULL) - return (xkb_fail(xkb, "cannot find section .xen_pages")); - - if (!PAGE_ALIGNED(sect->gs_shdr.sh_offset)) - return (xkb_fail(xkb, ".xen_pages is not page aligned")); - - if (sect->gs_shdr.sh_entsize != PAGE_SIZE) - return (xkb_fail(xkb, "invalid section .xen_pages")); - - xkb->xkb_pages_off = sect->gs_shdr.sh_offset; - - /* - * Try to map all the data pages. If we can't, fall back to the - * window/pread() approach, which is significantly slower. - */ - xkb->xkb_pages = mmap(NULL, PAGE_SIZE * xkb->xkb_nr_pages, - PROT_READ, MAP_SHARED, xkb->xkb_fd, xkb->xkb_pages_off); - - if (xkb->xkb_pages == (char *)MAP_FAILED) - xkb->xkb_pages = NULL; - - if (xkb->xkb_is_hvm) { - if (!xkb_build_fake_p2m(xkb)) - return (NULL); - } else { - if (!xkb_build_p2m(xkb)) - return (NULL); - } - - return (xkb); -} - -static void -xkb_init_mmu(xkb_t *xkb) -{ -#if defined(__amd64) - xkb->xkb_mmu.mi_max = 3; - xkb->xkb_mmu.mi_shift[0] = 12; - xkb->xkb_mmu.mi_shift[1] = 21; - xkb->xkb_mmu.mi_shift[2] = 30; - xkb->xkb_mmu.mi_shift[3] = 39; - xkb->xkb_mmu.mi_ptes = 512; - xkb->xkb_mmu.mi_ptesize = 8; -#elif defined(__i386) - if (xkb->xkb_is_pae) { - xkb->xkb_mmu.mi_max = 2; - xkb->xkb_mmu.mi_shift[0] = 12; - xkb->xkb_mmu.mi_shift[1] = 21; - xkb->xkb_mmu.mi_shift[2] = 30; - xkb->xkb_mmu.mi_ptes = 512; - xkb->xkb_mmu.mi_ptesize = 8; - } else { - xkb->xkb_mmu.mi_max = 1; - xkb->xkb_mmu.mi_shift[0] = 12; - xkb->xkb_mmu.mi_shift[1] = 22; - xkb->xkb_mmu.mi_ptes = 1024; - xkb->xkb_mmu.mi_ptesize = 4; - } -#endif -} - -/*ARGSUSED*/ -xkb_t * -xkb_open(const char *namelist, const char *corefile, const char *swapfile, - int flag, const char *err) -{ - uintptr_t debug_info = DEBUG_INFO; - struct stat64 corestat; - xkb_t *xkb = NULL; - size_t i; - - if (stat64(corefile, &corestat) == -1) - return (xkb_fail(xkb, "cannot stat %s", corefile)); - - if (flag != O_RDONLY) - return (xkb_fail(xkb, "invalid open flags")); - - xkb = mdb_zalloc(sizeof (*xkb), UM_SLEEP); - - for (i = 0; i < 4; i++) { - xkb->xkb_pt_map[i].mm_mfn = MFN_INVALID; - xkb->xkb_pt_map[i].mm_map = (char *)MAP_FAILED; - } - - xkb->xkb_type = XKB_FORMAT_UNKNOWN; - xkb->xkb_map.mm_mfn = MFN_INVALID; - xkb->xkb_map.mm_map = (char *)MAP_FAILED; - xkb->xkb_core.xc_p2m_buf = (char *)MAP_FAILED; - xkb->xkb_fd = -1; - - xkb->xkb_path = strdup(corefile); - - if ((xkb = xkb_open_elf(xkb)) == NULL) - return (NULL); - - if (xkb->xkb_type == XKB_FORMAT_UNKNOWN) { - if (!xkb_open_core(xkb)) - return (NULL); - } - - xkb_init_mmu(xkb); - - if (!xkb_build_m2p(xkb)) - return (NULL); - - if (xkb->xkb_is_hvm) - debug_info = DEBUG_INFO_HVM; - - if (xkb_read(xkb, debug_info, &xkb->xkb_info, - sizeof (xkb->xkb_info)) != sizeof (xkb->xkb_info)) - return (xkb_fail(xkb, "cannot read debug_info")); - - if (xkb->xkb_info.di_magic != DEBUG_INFO_MAGIC) { - return (xkb_fail(xkb, "invalid debug info magic %d", - xkb->xkb_info.di_magic)); - } - - if (xkb->xkb_info.di_version != DEBUG_INFO_VERSION) { - return (xkb_fail(xkb, "unknown debug info version %d", - xkb->xkb_info.di_version)); - } - - if (!xkb_build_ksyms(xkb)) - return (xkb_fail(xkb, "cannot construct namelist")); - - return (xkb); -} - -int -xkb_close(xkb_t *xkb) -{ - size_t i, sz; - - if (xkb == NULL) - return (0); - - if (xkb->xkb_m2p != NULL) { - mdb_free(xkb->xkb_m2p, - (xkb->xkb_max_mfn + 1) * sizeof (xen_pfn_t)); - } - - if (xkb->xkb_pages != NULL) { - (void) munmap((void *)xkb->xkb_pages, - PAGE_SIZE * xkb->xkb_nr_pages); - } else { - for (i = 0; i < 4; i++) { - char *addr = xkb->xkb_pt_map[i].mm_map; - if (addr != (char *)MAP_FAILED) - (void) munmap((void *)addr, PAGE_SIZE); - } - if (xkb->xkb_map.mm_map != (char *)MAP_FAILED) { - (void) munmap((void *)xkb->xkb_map.mm_map, - PAGE_SIZE); - } - } - - if (xkb->xkb_namelist != NULL) - mdb_free(xkb->xkb_namelist, xkb->xkb_namesize); - - if (xkb->xkb_type == XKB_FORMAT_ELF) { - xkb_elf_t *xe = &xkb->xkb_elf; - - if (xe->xe_gelf != NULL) - mdb_gelf_destroy(xe->xe_gelf); - - sz = sizeof (xen_pfn_t) * (xkb->xkb_max_pfn + 1); - - if (xkb->xkb_p2m != NULL) - mdb_free(xkb->xkb_p2m, sz); - - sz = sizeof (size_t) * (xkb->xkb_max_pfn + 1); - - if (xe->xe_off != NULL) - mdb_free(xe->xe_off, sz); - - } else if (xkb->xkb_type == XKB_FORMAT_CORE) { - xkb_core_t *xc = &xkb->xkb_core; - - if (xkb->xkb_fd != -1) - (void) close(xkb->xkb_fd); - - sz = (xkb->xkb_nr_pages * sizeof (mfn_t)) + (PAGE_SIZE * 2); - sz = PAGE_MASK(sz); - - if (xc->xc_p2m_buf != (xen_pfn_t *)MAP_FAILED) - (void) munmap(xc->xc_p2m_buf, sz); - - if (xkb->xkb_vcpu_data != NULL) - mdb_free(xkb->xkb_vcpu_data, xkb->xkb_vcpu_data_sz); - } - - if (xkb->xkb_vcpus != NULL) { - sz = sizeof (struct vcpu_guest_context *) * - xkb->xkb_nr_vcpus; - mdb_free(xkb->xkb_vcpus, sz); - } - - free(xkb->xkb_path); - - mdb_free(xkb, sizeof (*xkb)); - return (0); -} - -/*ARGSUSED*/ -static mdb_io_t * -xkb_sym_io(xkb_t *xkb, const char *symfile) -{ - mdb_io_t *io = mdb_memio_create(xkb->xkb_namelist, xkb->xkb_namesize); - - if (io == NULL) - mdb_warn("failed to create namelist from %s", xkb->xkb_path); - - return (io); -} - -uint64_t -xkb_vtop(xkb_t *xkb, struct as *as, uintptr_t addr) -{ - mfn_t tlmfn = xkb_cr3_to_pfn(xkb); - mfn_t mfn; - - if (as != NULL && (tlmfn = xkb_as_to_mfn(xkb, as)) == MFN_INVALID) - return (-1ULL); - - mfn = xkb_va_to_mfn(xkb, addr, tlmfn); - - if (mfn == MFN_INVALID || mfn > xkb->xkb_max_mfn) - return (-1ULL); - - return (((uint64_t)xkb->xkb_m2p[mfn] << PAGE_SHIFT) - | PAGE_OFFSET(addr)); -} - -static int -xkb_getmregs(xkb_t *xkb, uint_t cpu, struct privmregs *mregs) -{ - struct vcpu_guest_context *vcpu; - struct cpu_user_regs *ur; - struct regs *regs; - - if (cpu >= xkb->xkb_nr_vcpus) { - errno = EINVAL; - return (-1); - } - - bzero(mregs, sizeof (*mregs)); - - vcpu = xkb->xkb_vcpus[cpu]; - ur = &vcpu->user_regs; - regs = &mregs->pm_gregs; - - regs->r_ss = ur->ss; - regs->r_cs = ur->cs; - regs->r_ds = ur->ds; - regs->r_es = ur->es; - regs->r_fs = ur->fs; - regs->r_gs = ur->gs; - regs->r_trapno = ur->entry_vector; - regs->r_err = ur->error_code; -#ifdef __amd64 - regs->r_savfp = ur->rbp; - regs->r_savpc = ur->rip; - regs->r_rdi = ur->rdi; - regs->r_rsi = ur->rsi; - regs->r_rdx = ur->rdx; - regs->r_rcx = ur->rcx; - regs->r_r8 = ur->r8; - regs->r_r9 = ur->r9; - regs->r_rax = ur->rax; - regs->r_rbx = ur->rbx; - regs->r_rbp = ur->rbp; - regs->r_r10 = ur->r10; - regs->r_r11 = ur->r11; - regs->r_r12 = ur->r12; - regs->r_r13 = ur->r13; - regs->r_r14 = ur->r14; - regs->r_r15 = ur->r15; - regs->r_rip = ur->rip; - regs->r_rfl = ur->rflags; - regs->r_rsp = ur->rsp; -#else - regs->r_savfp = ur->ebp; - regs->r_savpc = ur->eip; - regs->r_edi = ur->edi; - regs->r_esi = ur->esi; - regs->r_ebp = ur->ebp; - regs->r_esp = ur->esp; - regs->r_ebx = ur->ebx; - regs->r_edx = ur->edx; - regs->r_ecx = ur->ecx; - regs->r_eax = ur->eax; - regs->r_eip = ur->eip; - regs->r_efl = ur->eflags; - regs->r_uesp = 0; -#endif - - bcopy(&vcpu->ctrlreg, &mregs->pm_cr, 8 * sizeof (ulong_t)); - bcopy(&vcpu->debugreg, &mregs->pm_dr, 8 * sizeof (ulong_t)); - - mregs->pm_flags = PM_GREGS | PM_CRREGS | PM_DRREGS; - - return (0); -} - -static mdb_kb_ops_t xpv_kb_ops = { - .kb_open = (void *(*)())xkb_open, - .kb_close = (int (*)())xkb_close, - .kb_sym_io = (mdb_io_t *(*)())xkb_sym_io, - .kb_kread = (ssize_t (*)())xkb_read, - .kb_kwrite = (ssize_t (*)())mdb_tgt_notsup, - .kb_aread = (ssize_t (*)())xkb_aread, - .kb_awrite = (ssize_t (*)())mdb_tgt_notsup, - .kb_pread = (ssize_t (*)())xkb_pread, - .kb_pwrite = (ssize_t (*)())mdb_tgt_notsup, - .kb_vtop = (uint64_t (*)())xkb_vtop, - .kb_getmregs = (int (*)())xkb_getmregs -}; - -mdb_kb_ops_t * -mdb_kb_ops(void) -{ - return (&xpv_kb_ops); -} - -static const mdb_dcmd_t dcmds[] = { NULL, }; -static const mdb_walker_t walkers[] = { NULL, }; -static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; - -const mdb_modinfo_t * -_mdb_init(void) -{ - return (&modinfo); -} - -void -_mdb_fini(void) -{ -} diff --git a/usr/src/pkg/Makefile b/usr/src/pkg/Makefile index 80f8ed0456..19d17465ed 100644 --- a/usr/src/pkg/Makefile +++ b/usr/src/pkg/Makefile @@ -177,7 +177,6 @@ PM_INC= transforms manifests PKGMOG_DEFINES= \ i386_ONLY=$(POUND_SIGN) \ i86pc_ONLY=$(POUND_SIGN) \ - i86xpv_ONLY=$(POUND_SIGN) \ $(PKGMACH)_ONLY= \ $(CONFIG_PLATFORM)_ONLY= \ CONFIG_PLATFORM=$(CONFIG_PLATFORM) \ @@ -198,9 +197,7 @@ PKGMOG_DEFINES= \ HUMAN_VERSION=$(VERSION) PKGDEP_TOKENS_i386= \ - 'PLATFORM=i86hvm' \ 'PLATFORM=i86pc' \ - 'PLATFORM=i86xpv' \ 'ISALIST=amd64' \ 'ISALIST=i386' PKGDEP_TOKENS= $(PKGDEP_TOKENS_$(PKGMACH)) diff --git a/usr/src/pkg/manifests/developer-debug-mdb.mf b/usr/src/pkg/manifests/developer-debug-mdb.mf index b8f251b72f..0d1b16113a 100644 --- a/usr/src/pkg/manifests/developer-debug-mdb.mf +++ b/usr/src/pkg/manifests/developer-debug-mdb.mf @@ -102,12 +102,6 @@ $(i386_ONLY)file path=platform/$(CONFIG_PLATFORM)/kernel/kmdb/$(ARCH64)/unix \ group=sys mode=0555 $(i386_ONLY)file path=platform/$(CONFIG_PLATFORM)/kernel/kmdb/$(ARCH64)/uppc \ group=sys mode=0555 -$(i86xpv_ONLY)file \ - path=platform/$(CONFIG_PLATFORM)/kernel/kmdb/$(ARCH64)/xpv_psm group=sys \ - mode=0555 -$(i86xpv_ONLY)file \ - path=platform/$(CONFIG_PLATFORM)/kernel/kmdb/$(ARCH64)/xpv_uppc group=sys \ - mode=0555 file path=usr/bin/$(ARCH32)/mdb mode=0555 file path=usr/bin/$(ARCH64)/mdb mode=0555 file path=usr/include/sys/mdb_modapi.h mode=0644 @@ -128,7 +122,6 @@ file path=usr/lib/mdb/kvm/$(ARCH64)/krtld.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/lofs.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/logindmux.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/mac.so group=sys mode=0555 -$(i386_ONLY)file path=usr/lib/mdb/kvm/$(ARCH64)/mdb_kb.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/mdb_ks.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/mm.so group=sys mode=0555 file path=usr/lib/mdb/kvm/$(ARCH64)/mpt_sas.so group=sys mode=0555 @@ -184,22 +177,6 @@ $(i386_ONLY)file path=usr/platform/i86pc/lib/mdb/kvm/$(ARCH64)/unix.so \ group=sys mode=0555 $(i386_ONLY)file path=usr/platform/i86pc/lib/mdb/kvm/$(ARCH64)/uppc.so \ group=sys mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/$(ARCH64)/unix.so \ - group=sys mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/$(ARCH64)/xpv.so \ - group=sys mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/$(ARCH64)/xpv_psm.so \ - group=sys mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/$(ARCH64)/xpv_uppc.so \ - group=sys mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/unix.so group=sys \ - mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/xpv.so group=sys \ - mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/xpv_psm.so group=sys \ - mode=0555 -$(i86xpv_ONLY)file path=usr/platform/i86xpv/lib/mdb/kvm/xpv_uppc.so group=sys \ - mode=0555 file path=usr/share/man/man1/adb.1 file path=usr/share/man/man1/kmdb.1 file path=usr/share/man/man1/mdb.1 diff --git a/usr/src/pkg/manifests/driver-xvm-pv.mf b/usr/src/pkg/manifests/driver-xvm-pv.mf dissimilarity index 98% index 90616fc36d..cb9dbe4cf2 100644 --- a/usr/src/pkg/manifests/driver-xvm-pv.mf +++ b/usr/src/pkg/manifests/driver-xvm-pv.mf @@ -1,62 +1,3 @@ -# -# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# The default for payload-bearing actions in this package is to appear in the -# global zone only. See the include file for greater detail, as well as -# information about overriding the defaults. -# - -set name=pkg.fmri value=pkg:/driver/xvm/pv@$(PKGVERS) -set name=pkg.description value="xVM Paravirtualized Drivers" -set name=pkg.summary value="xVM Paravirtualized Drivers" -set name=info.classification \ - value=org.opensolaris.category.2008:System/Virtualization -set name=variant.arch value=i386 -dir path=platform group=sys -dir path=platform/$(ARCH32)hvm group=sys -dir path=platform/$(ARCH32)hvm/kernel group=sys -dir path=platform/$(ARCH32)hvm/kernel/drv group=sys -dir path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64) group=sys -dir path=platform/$(ARCH32)hvm/kernel/misc group=sys -dir path=platform/$(ARCH32)hvm/kernel/misc/$(ARCH64) group=sys -driver name=xpv alias=pci5853,1.1 -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/cmdk group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/rtls group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/sd group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/xdf group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/xnf group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/xpv group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/$(ARCH64)/xpvd group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/xpv.conf group=sys -file path=platform/$(ARCH32)hvm/kernel/drv/xpvd.conf group=sys -file path=platform/$(ARCH32)hvm/kernel/misc/$(ARCH64)/hvm_bootstrap group=sys \ - mode=0755 -file path=platform/$(ARCH32)hvm/kernel/misc/$(ARCH64)/hvm_cmdk group=sys \ - mode=0755 -file path=platform/$(ARCH32)hvm/kernel/misc/$(ARCH64)/hvm_sd group=sys \ - mode=0755 -license cr_Sun license=cr_Sun -license lic_CDDL license=lic_CDDL +set name=pkg.fmri value=pkg:/driver/xvm/pv@$(PKGVERS) +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true diff --git a/usr/src/pkg/manifests/system-core-os.mf b/usr/src/pkg/manifests/system-core-os.mf index ac90c03184..ab8c5e7537 100644 --- a/usr/src/pkg/manifests/system-core-os.mf +++ b/usr/src/pkg/manifests/system-core-os.mf @@ -796,7 +796,6 @@ file path=usr/lib/devfsadm/linkmod/SUNW_sgen_link.so group=sys file path=usr/lib/devfsadm/linkmod/SUNW_smp_link.so group=sys file path=usr/lib/devfsadm/linkmod/SUNW_tape_link.so group=sys file path=usr/lib/devfsadm/linkmod/SUNW_usb_link.so group=sys -$(i386_ONLY)file path=usr/lib/devfsadm/linkmod/SUNW_xen_link.so group=sys file path=usr/lib/diffh mode=0555 file path=usr/lib/fs/bootfs/mount mode=0555 file path=usr/lib/fs/ctfs/mount mode=0555 diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf index 6c68110e6d..78d266ddea 100644 --- a/usr/src/pkg/manifests/system-dtrace-tests.mf +++ b/usr/src/pkg/manifests/system-dtrace-tests.mf @@ -123,8 +123,6 @@ dir path=opt/SUNWdtrt/tst/common/usdt dir path=opt/SUNWdtrt/tst/common/ustack dir path=opt/SUNWdtrt/tst/common/vars dir path=opt/SUNWdtrt/tst/common/version -$(i386_ONLY)dir path=opt/SUNWdtrt/tst/i86xpv -$(i386_ONLY)dir path=opt/SUNWdtrt/tst/i86xpv/xdt file path=opt/SUNWdtrt/README mode=0444 file path=opt/SUNWdtrt/bin/$(ARCH32)/chkargs mode=0555 file path=opt/SUNWdtrt/bin/$(ARCH64)/chkargs mode=0555 @@ -2074,11 +2072,5 @@ file path=opt/SUNWdtrt/tst/common/vars/tst.ucaller.ksh.out mode=0444 file path=opt/SUNWdtrt/tst/common/vars/tst.uid.d mode=0444 file path=opt/SUNWdtrt/tst/common/vars/tst.walltimestamp.d mode=0444 file path=opt/SUNWdtrt/tst/common/version/tst.1.0.d mode=0444 -$(i386_ONLY)file path=opt/SUNWdtrt/tst/i86xpv/xdt/tst.basic.ksh mode=0444 -$(i386_ONLY)file path=opt/SUNWdtrt/tst/i86xpv/xdt/tst.hvmenable.ksh mode=0444 -$(i386_ONLY)file path=opt/SUNWdtrt/tst/i86xpv/xdt/tst.memenable.ksh mode=0444 -$(i386_ONLY)file path=opt/SUNWdtrt/tst/i86xpv/xdt/tst.schedargs.ksh mode=0444 -$(i386_ONLY)file path=opt/SUNWdtrt/tst/i86xpv/xdt/tst.schedenable.ksh \ - mode=0444 license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf index 69b616d972..f8e31f3297 100644 --- a/usr/src/pkg/manifests/system-header.mf +++ b/usr/src/pkg/manifests/system-header.mf @@ -1444,11 +1444,6 @@ $(i386_ONLY)file path=usr/platform/i86pc/include/vm/hat_pte.h $(i386_ONLY)file path=usr/platform/i86pc/include/vm/hment.h $(i386_ONLY)file path=usr/platform/i86pc/include/vm/htable.h $(i386_ONLY)file path=usr/platform/i86pc/include/vm/kboot_mmu.h -$(i86xpv_ONLY)file path=usr/platform/i86xpv/include/sys/balloon.h -$(i86xpv_ONLY)file path=usr/platform/i86xpv/include/sys/machprivregs.h -$(i86xpv_ONLY)file path=usr/platform/i86xpv/include/sys/xen_mmu.h -$(i86xpv_ONLY)file path=usr/platform/i86xpv/include/sys/xpv_impl.h -$(i86xpv_ONLY)file path=usr/platform/i86xpv/include/vm/seg_mf.h file path=usr/share/man/man3head/acct.h.3head file path=usr/share/man/man3head/aio.h.3head file path=usr/share/man/man3head/ar.h.3head diff --git a/usr/src/pkg/manifests/system-kernel-dtrace-providers-xdt.mf b/usr/src/pkg/manifests/system-kernel-dtrace-providers-xdt.mf dissimilarity index 96% index d0cdf3551f..274b873477 100644 --- a/usr/src/pkg/manifests/system-kernel-dtrace-providers-xdt.mf +++ b/usr/src/pkg/manifests/system-kernel-dtrace-providers-xdt.mf @@ -1,49 +1,3 @@ -# -# 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 (c) 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# The default for payload-bearing actions in this package is to appear in the -# global zone only. See the include file for greater detail, as well as -# information about overriding the defaults. -# - -set name=pkg.fmri value=pkg:/system/kernel/dtrace/providers/xdt@$(PKGVERS) -set name=pkg.description \ - value="DTrace provider for tracing events in the xVM hypervisor" -set name=pkg.summary value="xVM Hypervisor Dynamic Tracing (DTrace) Provider" -set name=info.classification \ - value=org.opensolaris.category.2008:Development/System -set name=variant.arch value=i386 -dir path=platform group=sys -$(i86xpv_ONLY)dir path=platform/i86xpv group=sys -$(i86xpv_ONLY)dir path=platform/i86xpv/kernel group=sys -$(i86xpv_ONLY)dir path=platform/i86xpv/kernel/drv group=sys -$(i86xpv_ONLY)dir path=platform/i86xpv/kernel/drv/$(ARCH64) group=sys -$(i86xpv_ONLY)driver name=xdt -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xdt group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xdt group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xdt.conf group=sys -license cr_Sun license=cr_Sun -license lic_CDDL license=lic_CDDL +set name=pkg.fmri value=pkg:/system/kernel/dtrace/providers/xdt@$(PKGVERS) +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true diff --git a/usr/src/pkg/manifests/system-kernel-platform.mf b/usr/src/pkg/manifests/system-kernel-platform.mf index 3664a84a62..555ff32a57 100644 --- a/usr/src/pkg/manifests/system-kernel-platform.mf +++ b/usr/src/pkg/manifests/system-kernel-platform.mf @@ -57,9 +57,6 @@ $(i386_ONLY)dir path=platform/$(CONFIG_PLATFORM)/kernel/mach/$(ARCH64) \ $(i386_ONLY)dir path=platform/$(CONFIG_PLATFORM)/kernel/misc group=sys $(i386_ONLY)dir path=platform/$(CONFIG_PLATFORM)/kernel/misc/$(ARCH64) \ group=sys -$(i86xpv_ONLY)dir path=platform/$(CONFIG_PLATFORM)/kernel/tod group=sys -$(i86xpv_ONLY)dir path=platform/$(CONFIG_PLATFORM)/kernel/tod/$(ARCH64) \ - group=sys $(i386_ONLY)dir path=platform/$(CONFIG_PLATFORM)/ucode group=sys dir path=usr/share/man/man4 $(i386_ONLY)driver name=acpinex alias=acpivirtnex @@ -88,8 +85,6 @@ $(i386_ONLY)driver name=xnbo \ alias=xnb,SUNW_mac $(i386_ONLY)driver name=xnbu alias=xnb,netfront $(i386_ONLY)driver name=xnf -$(i86xpv_ONLY)driver name=xpvd -$(i86xpv_ONLY)driver name=xpvtap perms="* 0666 root sys" $(i386_ONLY)file path=platform/$(CONFIG_PLATFORM)/kernel/$(ARCH64)/unix \ group=sys mode=0755 $(i386_ONLY)file path=platform/i86pc/kernel/cpu/$(ARCH64)/cpu.generic \ @@ -132,86 +127,6 @@ $(i386_ONLY)file path=platform/i86pc/ucode/amd-ucode.bin group=sys mode=0444 \ preserve=true reboot-needed=true $(i386_ONLY)file path=platform/i86pc/ucode/intel-ucode.txt group=sys mode=0444 \ preserve=true reboot-needed=true -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/cpu/$(ARCH64)/cpu.generic \ - group=sys mode=0755 -$(i86xpv_ONLY)file \ - path=platform/i86xpv/kernel/cpu/$(ARCH64)/cpu_ms.AuthenticAMD group=sys \ - mode=0755 -$(i86xpv_ONLY)file \ - path=platform/i86xpv/kernel/cpu/$(ARCH64)/cpu_ms.AuthenticAMD.15 \ - group=sys mode=0755 -$(i86xpv_ONLY)file \ - path=platform/i86xpv/kernel/cpu/$(ARCH64)/cpu_ms.GenuineIntel group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/cpu/cpu.generic group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/cpu/cpu_ms.AuthenticAMD \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/cpu/cpu_ms.AuthenticAMD.15 \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/cpu/cpu_ms.GenuineIntel \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/dacf/$(ARCH64)/consconfig_dacf \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/dacf/consconfig_dacf group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/balloon group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/domcaps group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/evtchn group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/isa group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/npe group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/pci group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/pit_beep \ - group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/privcmd group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/rootnex group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xdb group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xdf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xenbus group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xencons group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xnbe group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xnbo group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xnbu group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xnf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xpvd group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/$(ARCH64)/xpvtap group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/balloon group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/domcaps group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/evtchn group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/isa group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/npe group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/pci group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/pit_beep group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/pit_beep.conf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/privcmd group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/rootnex group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xdf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xenbus group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xencons group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xencons.conf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xnf group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/drv/xpvd group=sys -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/mach/$(ARCH64)/xpv_psm \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/mach/$(ARCH64)/xpv_uppc \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/mach/xpv_psm group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/mach/xpv_uppc group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/misc/$(ARCH64)/gfx_private \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/misc/$(ARCH64)/xnb group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/misc/$(ARCH64)/xpv_autoconfig \ - group=sys mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/misc/gfx_private group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/misc/xpv_autoconfig group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/tod/$(ARCH64)/xpvtod group=sys \ - mode=0755 -$(i86xpv_ONLY)file path=platform/i86xpv/kernel/tod/xpvtod group=sys mode=0755 $(i386_ONLY)file path=usr/share/man/man4/sysbus.4 $(i386_ONLY)file path=usr/share/man/man7d/npe.7d license cr_Sun license=cr_Sun diff --git a/usr/src/uts/common/xen/dtrace/xdt.c b/usr/src/uts/common/xen/dtrace/xdt.c deleted file mode 100644 index 2162eacd39..0000000000 --- a/usr/src/uts/common/xen/dtrace/xdt.c +++ /dev/null @@ -1,2182 +0,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. - */ - -/* - * Xen event provider for DTrace - * - * NOTE: This provider is PRIVATE. It is intended as a short-term solution and - * may disappear or be re-implemented at anytime. - * - * This provider isn't suitable as a general-purpose solution for a number of - * reasons. First and foremost, we rely on the Xen tracing mechanism and don't - * have any way to gather data other than that collected by the Xen trace - * buffers. Further, it does not fit into the DTrace model (see "Interacting - * with DTrace" below.) - * - * - * Tracing in Xen - * -------------- - * - * Xen implements a tracing facility for generating and collecting execution - * event traces from the hypervisor. When tracing is enabled, compiled in - * probes record events in contiguous per-CPU trace buffers. - * - * +---------+ - * +------+ | | - * | CPUn |----> | BUFFERn | - * +------+ | | - * +---------+- tbuf.va + (tbuf.size * n) - * : : - * +---------+ - * +------+ | | - * | CPU1 |----> | BUFFER1 | - * +------+ | | - * +---------+- tbuf.va + tbuf.size - * +------+ | | - * | CPU0 |----> | BUFFER0 | - * +------+ | | - * +---------+- tbuf.va - * - * Each CPU buffer consists of a metadata header followed by the trace records. - * The metadata consists of a producer/consumer pair of pointers into the buffer - * that point to the next record to be written and the next record to be read - * respectively. - * - * A trace record can be in one of two forms, depending on if the TSC is - * included. The record header indicates whether or not the TSC field is - * present. - * - * 1. Trace record without TSC: - * +------------------------------------------------------------+ - * | HEADER(uint32_t) | DATA FIELDS | - * +------------------------------------------------------------+ - * - * 2. Trace record with TSC: - * +--------------------------------------------------------------------------+ - * | HEADER(uint32_t) | TSC(uint64_t) | DATA FIELDS | - * +--------------------------------------------------------------------------+ - * - * Where, - * - * HEADER bit field: - * +--------------------------------------------------------------------------+ - * | C | NDATA | EVENT | - * +--------------------------------------------------------------------------+ - * 31 30 28 27 0 - * - * EVENT: Event ID. - * NDATA: Number of populated data fields. - * C: TSC included. - * - * DATA FIELDS: - * +--------------------------------------------------------------------------+ - * | D1(uint32_t) | D2(uint32_t) | D3(uint32_t) | . . . | D7(uint32_t) | - * +--------------------------------------------------------------------------+ - * - * - * Interacting with DTrace - * ----------------------- - * - * Every xdt_poll_nsec nano-seconds we poll the trace buffers for data and feed - * each entry into dtrace_probe() with the corresponding probe ID for the event. - * As a result of this periodic collection implementation probe firings are - * asynchronous. This is the only sensible way to implement this form of - * provider, but because of its asynchronous nature asking things like - * "current CPU" and, more importantly, arbitrary questions about the context - * surrounding the probe firing are not meaningful. So, consumers should not - * attempt to infer anything beyond what is supplied via the probe arguments. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define XDT_POLL_DEFAULT 100000000 /* default poll interval (ns) */ -#define XDT_POLL_MIN 10000000 /* min poll interval (ns) */ -#define XDT_TBUF_RETRY 50 /* tbuf disable retry count */ - -/* - * The domid must match IDLE_DOMAIN_ID in xen.hg/xen/include/xen/sched.h - * in the xVM gate. - */ -#define IS_IDLE_DOM(domid) (domid == 0x7FFFU) - -/* Macros to extract the domid and cpuid from a HVM trace data field */ -#define HVM_DOMID(d) (d >> 16) -#define HVM_VCPUID(d) (d & 0xFFFF) - -/* Flags for shadow page table events */ -#define SH_GUEST_32 0x000 -#define SH_GUEST_PAE 0x100 -#define SH_GUEST_64 0x200 - -#define XDT_PROBE5(event, arg0, arg1, arg2, arg3, arg4) { \ - dtrace_id_t id = xdt_probemap[event]; \ - if (id) \ - dtrace_probe(id, arg0, arg1, arg2, arg3, arg4); \ -} \ - -#define XDT_PROBE4(event, arg0, arg1, arg2, arg3) \ - XDT_PROBE5(event, arg0, arg1, arg2, arg3, 0) - -#define XDT_PROBE3(event, arg0, arg1, arg2) \ - XDT_PROBE5(event, arg0, arg1, arg2, 0, 0) - -#define XDT_PROBE2(event, arg0, arg1) \ - XDT_PROBE5(event, arg0, arg1, 0, 0, 0) - -#define XDT_PROBE1(event, arg0) \ - XDT_PROBE5(event, arg0, 0, 0, 0, 0) - -#define XDT_PROBE0(event) \ - XDT_PROBE5(event, 0, 0, 0, 0, 0) - -/* Probe classes */ -#define XDT_SCHED 0 -#define XDT_MEM 1 -#define XDT_HVM 2 -#define XDT_GEN 3 -#define XDT_PV 4 -#define XDT_SHADOW 5 -#define XDT_PM 6 -#define XDT_NCLASSES 7 - -/* Probe events */ -#define XDT_EVT_INVALID (-(int)1) -#define XDT_SCHED_OFF_CPU 0 -#define XDT_SCHED_ON_CPU 1 -#define XDT_SCHED_IDLE_OFF_CPU 2 -#define XDT_SCHED_IDLE_ON_CPU 3 -#define XDT_SCHED_BLOCK 4 -#define XDT_SCHED_SLEEP 5 -#define XDT_SCHED_WAKE 6 -#define XDT_SCHED_YIELD 7 -#define XDT_SCHED_SHUTDOWN_POWEROFF 8 -#define XDT_SCHED_SHUTDOWN_REBOOT 9 -#define XDT_SCHED_SHUTDOWN_SUSPEND 10 -#define XDT_SCHED_SHUTDOWN_CRASH 11 -#define XDT_MEM_PAGE_GRANT_MAP 12 -#define XDT_MEM_PAGE_GRANT_UNMAP 13 -#define XDT_MEM_PAGE_GRANT_TRANSFER 14 -#define XDT_HVM_VMENTRY 15 -#define XDT_HVM_VMEXIT 16 -#define XDT_TRC_LOST_RECORDS 17 -#define XDT_SCHED_ADD_VCPU 18 -#define XDT_SCHED_REM_VCPU 19 /* unused */ -#define XDT_SCHED_CTL 20 /* unused */ -#define XDT_SCHED_ADJDOM 21 -#define XDT_SCHED_S_TIMER_FN 22 /* unused */ -#define XDT_SCHED_T_TIMER_FN 23 /* unused */ -#define XDT_SCHED_DOM_TIMER_FN 24 /* unused */ -#define XDT_PV_HYPERCALL 25 -#define XDT_PV_TRAP 26 -#define XDT_PV_PAGE_FAULT 27 -#define XDT_PV_FORCED_INVALID_OP 28 -#define XDT_PV_EMULATE_PRIVOP 29 -#define XDT_PV_EMULATE_4GB 30 /* unused (32-bit HV only ) */ -#define XDT_PV_MATH_STATE_RESTORE 31 -#define XDT_PV_PAGING_FIXUP 32 -#define XDT_PV_DT_MAPPING_FAULT 33 -#define XDT_PV_PTWR_EMULATION 34 -#define XDT_HVM_PF_XEN 35 -#define XDT_HVM_PF_INJECT 36 -#define XDT_HVM_EXC_INJECT 37 -#define XDT_HVM_VIRQ_INJECT 38 -#define XDT_HVM_VIRQ_REINJECT 39 -#define XDT_HVM_IO_READ 40 /* unused */ -#define XDT_HVM_IO_WRITE 41 /* unused */ -#define XDT_HVM_CR_READ 42 -#define XDT_HVM_CR_WRITE 43 -#define XDT_HVM_DR_READ 44 /* unused */ -#define XDT_HVM_DR_WRITE 45 /* unused */ -#define XDT_HVM_MSR_READ 46 -#define XDT_HVM_MSR_WRITE 47 -#define XDT_HVM_CPUID 48 -#define XDT_HVM_INTR 49 -#define XDT_HVM_INTR_WINDOW 50 -#define XDT_HVM_NMI 51 -#define XDT_HVM_SMI 52 -#define XDT_HVM_VMMCALL 53 -#define XDT_HVM_HLT 54 -#define XDT_HVM_INVLPG 55 -#define XDT_HVM_MCE 56 -#define XDT_HVM_IOPORT_READ 57 -#define XDT_HVM_IOPORT_WRITE 58 -#define XDT_HVM_CLTS 59 -#define XDT_HVM_LMSW 60 -#define XDT_HVM_IOMEM_READ 61 -#define XDT_HVM_IOMEM_WRITE 62 -#define XDT_SHADOW_NOT_SHADOW 63 -#define XDT_SHADOW_FAST_PROPAGATE 64 -#define XDT_SHADOW_FAST_MMIO 65 -#define XDT_SHADOW_FALSE_FAST_PATH 66 -#define XDT_SHADOW_MMIO 67 -#define XDT_SHADOW_FIXUP 68 -#define XDT_SHADOW_DOMF_DYING 69 -#define XDT_SHADOW_EMULATE 70 -#define XDT_SHADOW_EMULATE_UNSHADOW_USER 71 -#define XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ 72 -#define XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED 73 -#define XDT_SHADOW_WRMAP_BF 74 -#define XDT_SHADOW_PREALLOC_UNPIN 75 -#define XDT_SHADOW_RESYNC_FULL 76 -#define XDT_SHADOW_RESYNC_ONLY 77 -#define XDT_PM_FREQ_CHANGE 78 -#define XDT_PM_IDLE_ENTRY 79 -#define XDT_PM_IDLE_EXIT 80 -#define XDT_SCHED_RUNSTATE_CHANGE 81 -#define XDT_SCHED_CONTINUE_RUNNING 82 -#define XDT_NEVENTS 83 - -typedef struct { - const char *pr_mod; /* probe module */ - const char *pr_name; /* probe name */ - int evt_id; /* event id */ - uint_t class; /* probe class */ -} xdt_probe_t; - -typedef struct { - uint32_t trc_mask; /* trace mask */ - uint32_t cnt; /* num enabled probes in class */ -} xdt_classinfo_t; - -typedef struct { - ulong_t prev_domid; /* previous dom executed */ - ulong_t prev_vcpuid; /* previous vcpu executed */ - ulong_t prev_ctime; /* time spent on cpu */ - ulong_t next_domid; /* next dom to be scheduled */ - ulong_t next_vcpuid; /* next vcpu to be scheduled */ - ulong_t next_wtime; /* time spent waiting to get on cpu */ - ulong_t next_ts; /* allocated time slice */ - ulong_t cur_domid; /* current dom */ - ulong_t cur_vcpuid; /* current vcpuid */ - int curinfo_valid; /* info is valid */ -} xdt_schedinfo_t; - -static struct { - uint_t cnt; /* total num of trace buffers */ - size_t size; /* size of each cpu buffer */ - mfn_t start_mfn; /* starting mfn of buffers */ - caddr_t va; /* va buffers are mapped into */ - - /* per-cpu buffers */ - struct t_buf **meta; /* buffer metadata */ - struct t_rec **data; /* buffer data records */ - - /* statistics */ - uint64_t stat_dropped_recs; /* records dropped */ - uint64_t stat_spurious_cpu; /* recs with garbage cpuids */ - uint64_t stat_spurious_switch; /* inconsistent vcpu switches */ - uint64_t stat_unknown_shutdown; /* unknown shutdown code */ - uint64_t stat_unknown_recs; /* unknown records */ -} tbuf; - -static size_t tbuf_data_size; - -static char *xdt_stats[] = { - "dropped_recs", -}; - -/* - * Tunable variables - * - * The following may be tuned by adding a line to /etc/system that - * includes both the name of the module ("xdt") and the name of the variable. - * For example: - * set xdt:xdt_tbuf_pages = 40 - */ -uint_t xdt_tbuf_pages = 20; /* pages to alloc per-cpu buf */ - -/* - * The following may be tuned by adding a line to - * /platform/i86xpv/kernel/drv/xdt.conf. - * For example: - * xdt_poll_nsec = 200000000; - */ -static hrtime_t xdt_poll_nsec; /* trace buffer poll interval */ - -/* - * Another tunable variable: the maximum number of records to process - * in one scan. If it is 0 (e.g. not set in /etc/system), it will - * be set to ncpu * (bufsize / max_rec_size). - * - * Having an upper limit avoids a situation where the scan would loop - * endlessly in case the hypervisor adds records quicker than we - * can process them. It's better to drop records than to loop, obviously. - */ -uint_t xdt_max_recs = 0; - -/* - * Internal variables - */ -static dev_info_t *xdt_devi; -static dtrace_provider_id_t xdt_id; -static uint_t xdt_ncpus; /* total number of phys CPUs */ -static uint32_t cur_trace_mask; /* current trace mask */ -static xdt_schedinfo_t *xdt_cpu_schedinfo; /* per-cpu sched info */ -dtrace_id_t xdt_probemap[XDT_NEVENTS]; /* map of enabled probes */ -dtrace_id_t xdt_prid[XDT_NEVENTS]; /* IDs of registered events */ -static cyclic_id_t xdt_cyclic = CYCLIC_NONE; -static kstat_t *xdt_kstats; -static xdt_classinfo_t xdt_classinfo[XDT_NCLASSES]; - -/* - * These provide context when probes fire. They can be accessed - * from xdt dtrace probe (as `xdt_curdom, etc). It's ok for these - * to be global, and not per-cpu, as probes are run strictly in sequence - * as the trace buffers are - */ -uint_t xdt_curdom, xdt_curvcpu, xdt_curpcpu; -uint64_t xdt_timestamp; - -static xdt_probe_t xdt_probe[] = { - /* Sched probes */ - { "sched", "off-cpu", XDT_SCHED_OFF_CPU, XDT_SCHED }, - { "sched", "on-cpu", XDT_SCHED_ON_CPU, XDT_SCHED }, - { "sched", "idle-off-cpu", XDT_SCHED_IDLE_OFF_CPU, XDT_SCHED }, - { "sched", "idle-on-cpu", XDT_SCHED_IDLE_ON_CPU, XDT_SCHED }, - { "sched", "block", XDT_SCHED_BLOCK, XDT_SCHED }, - { "sched", "sleep", XDT_SCHED_SLEEP, XDT_SCHED }, - { "sched", "wake", XDT_SCHED_WAKE, XDT_SCHED }, - { "sched", "yield", XDT_SCHED_YIELD, XDT_SCHED }, - { "sched", "shutdown-poweroff", XDT_SCHED_SHUTDOWN_POWEROFF, - XDT_SCHED }, - { "sched", "shutdown-reboot", XDT_SCHED_SHUTDOWN_REBOOT, XDT_SCHED }, - { "sched", "shutdown-suspend", XDT_SCHED_SHUTDOWN_SUSPEND, XDT_SCHED }, - { "sched", "shutdown-crash", XDT_SCHED_SHUTDOWN_CRASH, XDT_SCHED }, - { "sched", "add", XDT_SCHED_ADD_VCPU, XDT_SCHED }, - { "sched", "runstate-change", XDT_SCHED_RUNSTATE_CHANGE, XDT_SCHED }, - { "sched", "continue-running", XDT_SCHED_CONTINUE_RUNNING, XDT_SCHED }, - - /* Memory probes */ - { "mem", "page-grant-map", XDT_MEM_PAGE_GRANT_MAP, XDT_MEM }, - { "mem", "page-grant-unmap", XDT_MEM_PAGE_GRANT_UNMAP, XDT_MEM }, - { "mem", "page-grant-transfer", XDT_MEM_PAGE_GRANT_TRANSFER, XDT_MEM }, - - {"pv", "hypercall", XDT_PV_HYPERCALL, XDT_PV }, - {"pv", "trap", XDT_PV_TRAP, XDT_PV }, - {"pv", "page-fault", XDT_PV_PAGE_FAULT, XDT_PV }, - {"pv", "forced-invalid-op", XDT_PV_FORCED_INVALID_OP, XDT_PV }, - {"pv", "emulate-priv-op", XDT_PV_EMULATE_PRIVOP, XDT_PV }, - {"pv", "math-state-restore", XDT_PV_MATH_STATE_RESTORE, XDT_PV }, - {"pv", "paging-fixup", XDT_PV_PAGING_FIXUP, XDT_PV }, - {"pv", "dt-mapping-fault", XDT_PV_DT_MAPPING_FAULT, XDT_PV }, - {"pv", "pte-write-emul", XDT_PV_PTWR_EMULATION, XDT_PV }, - - /* HVM probes */ - { "hvm", "vmentry", XDT_HVM_VMENTRY, XDT_HVM }, - { "hvm", "vmexit", XDT_HVM_VMEXIT, XDT_HVM }, - { "hvm", "pagefault-xen", XDT_HVM_PF_XEN, XDT_HVM }, - { "hvm", "pagefault-inject", XDT_HVM_PF_INJECT, XDT_HVM }, - { "hvm", "exception-inject", XDT_HVM_EXC_INJECT, XDT_HVM }, - { "hvm", "virq-inject", XDT_HVM_VIRQ_INJECT, XDT_HVM }, - { "hvm", "cr-read", XDT_HVM_CR_READ, XDT_HVM }, - { "hvm", "cr-write", XDT_HVM_CR_WRITE, XDT_HVM }, - { "hvm", "msr-read", XDT_HVM_MSR_READ, XDT_HVM }, - { "hvm", "msr-write", XDT_HVM_MSR_WRITE, XDT_HVM }, - { "hvm", "cpuid", XDT_HVM_CPUID, XDT_HVM }, - { "hvm", "intr", XDT_HVM_INTR, XDT_HVM }, - { "hvm", "intr-window", XDT_HVM_INTR_WINDOW, XDT_HVM }, - { "hvm", "nmi", XDT_HVM_NMI, XDT_HVM }, - { "hvm", "smi", XDT_HVM_SMI, XDT_HVM }, - { "hvm", "vmmcall", XDT_HVM_VMMCALL, XDT_HVM }, - { "hvm", "hlt", XDT_HVM_HLT, XDT_HVM }, - { "hvm", "invlpg", XDT_HVM_INVLPG, XDT_HVM }, - { "hvm", "mce", XDT_HVM_MCE, XDT_HVM }, - { "hvm", "pio-read", XDT_HVM_IOPORT_READ, XDT_HVM }, - { "hvm", "pio-write", XDT_HVM_IOPORT_WRITE, XDT_HVM }, - { "hvm", "mmio-read", XDT_HVM_IOMEM_READ, XDT_HVM }, - { "hvm", "mmio-write", XDT_HVM_IOMEM_WRITE, XDT_HVM }, - { "hvm", "clts", XDT_HVM_CLTS, XDT_HVM }, - { "hvm", "lmsw", XDT_HVM_LMSW, XDT_HVM }, - - { "shadow", "fault-not-shadow", XDT_SHADOW_NOT_SHADOW, XDT_SHADOW }, - { "shadow", "fast-propagate", XDT_SHADOW_FAST_PROPAGATE, XDT_SHADOW }, - { "shadow", "fast-mmio", XDT_SHADOW_FAST_MMIO, XDT_SHADOW }, - { "shadow", "false-fast-path", XDT_SHADOW_FALSE_FAST_PATH, - XDT_SHADOW }, - { "shadow", "mmio", XDT_SHADOW_MMIO, XDT_SHADOW }, - { "shadow", "fixup", XDT_SHADOW_FIXUP, XDT_SHADOW }, - { "shadow", "domf-dying", XDT_SHADOW_DOMF_DYING, XDT_SHADOW }, - { "shadow", "emulate", XDT_SHADOW_EMULATE, XDT_SHADOW }, - { "shadow", "emulate-unshadow-user", XDT_SHADOW_EMULATE_UNSHADOW_USER, - XDT_SHADOW }, - { "shadow", "emulate-unshadow-evtinj", - XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, XDT_SHADOW }, - { "shadow", "emulate-unshadow-unhandled", - XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, XDT_SHADOW }, - { "shadow", "wrmap-bf", XDT_SHADOW_WRMAP_BF, XDT_SHADOW }, - { "shadow", "prealloc-unpin", XDT_SHADOW_PREALLOC_UNPIN, XDT_SHADOW }, - { "shadow", "resync-full", XDT_SHADOW_RESYNC_FULL, XDT_SHADOW }, - { "shadow", "resync-only", XDT_SHADOW_RESYNC_ONLY, XDT_SHADOW }, - - { "pm", "freq-change", XDT_PM_FREQ_CHANGE, XDT_PM }, - { "pm", "idle-entry", XDT_PM_IDLE_ENTRY, XDT_PM }, - { "pm", "idle-exit", XDT_PM_IDLE_EXIT, XDT_PM }, - - /* Trace buffer related probes */ - { "trace", "records-lost", XDT_TRC_LOST_RECORDS, XDT_GEN }, - - { NULL } -}; - -static inline uint32_t -xdt_nr_active_probes() -{ - int i; - uint32_t tot = 0; - - for (i = 0; i < XDT_NCLASSES; i++) - tot += xdt_classinfo[i].cnt; - - return (tot); -} - -static void -xdt_init_trace_masks(void) -{ - xdt_classinfo[XDT_SCHED].trc_mask = TRC_SCHED; - xdt_classinfo[XDT_MEM].trc_mask = TRC_MEM; - xdt_classinfo[XDT_HVM].trc_mask = TRC_HVM; - xdt_classinfo[XDT_GEN].trc_mask = TRC_GEN; - xdt_classinfo[XDT_PV].trc_mask = TRC_PV; - xdt_classinfo[XDT_SHADOW].trc_mask = TRC_SHADOW; - xdt_classinfo[XDT_PM].trc_mask = TRC_PM; -} - -static int -xdt_kstat_update(kstat_t *ksp, int flag) -{ - kstat_named_t *knp; - - if (flag != KSTAT_READ) - return (EACCES); - - knp = ksp->ks_data; - - /* - * Assignment order should match that of the names in - * xdt_stats. - */ - (knp++)->value.ui64 = tbuf.stat_dropped_recs; - - return (0); -} - -static void -xdt_kstat_init(void) -{ - int nstats = sizeof (xdt_stats) / sizeof (xdt_stats[0]); - char **cp = xdt_stats; - kstat_named_t *knp; - - if ((xdt_kstats = kstat_create("xdt", 0, "trace_statistics", "misc", - KSTAT_TYPE_NAMED, nstats, 0)) == NULL) - return; - - xdt_kstats->ks_update = xdt_kstat_update; - - knp = xdt_kstats->ks_data; - while (nstats > 0) { - kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); - knp++; - cp++; - nstats--; - } - - kstat_install(xdt_kstats); -} - -static int -xdt_sysctl_tbuf(xen_sysctl_tbuf_op_t *tbuf_op) -{ - xen_sysctl_t op; - int xerr; - - op.cmd = XEN_SYSCTL_tbuf_op; - op.interface_version = XEN_SYSCTL_INTERFACE_VERSION; - op.u.tbuf_op = *tbuf_op; - - if ((xerr = HYPERVISOR_sysctl(&op)) != 0) - return (xen_xlate_errcode(xerr)); - - *tbuf_op = op.u.tbuf_op; - return (0); -} - -static int -xdt_map_trace_buffers(mfn_t mfn, caddr_t va, size_t len) -{ - x86pte_t pte; - caddr_t const sva = va; - caddr_t const eva = va + len; - int xerr; - - ASSERT(mfn != MFN_INVALID); - ASSERT(va != NULL); - ASSERT(IS_PAGEALIGNED(len)); - - for (; va < eva; va += MMU_PAGESIZE) { - /* - * Ask the HAT to load a throwaway mapping to page zero, then - * overwrite it with the hypervisor mapping. It gets removed - * later via hat_unload(). - */ - hat_devload(kas.a_hat, va, MMU_PAGESIZE, (pfn_t)0, - PROT_READ | HAT_UNORDERED_OK, - HAT_LOAD_NOCONSIST | HAT_LOAD); - - pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER - | PT_FOREIGN | PT_WRITABLE; - - xerr = HYPERVISOR_update_va_mapping_otherdomain((ulong_t)va, - pte, UVMF_INVLPG | UVMF_LOCAL, DOMID_XEN); - - if (xerr != 0) { - /* unmap pages loaded so far */ - size_t ulen = (uintptr_t)(va + MMU_PAGESIZE) - - (uintptr_t)sva; - hat_unload(kas.a_hat, sva, ulen, HAT_UNLOAD_UNMAP); - return (xen_xlate_errcode(xerr)); - } - - mfn++; - } - - return (0); -} - -static int -xdt_attach_trace_buffers(void) -{ - xen_sysctl_tbuf_op_t tbuf_op; - size_t len; - int err; - uint_t i; - - /* - * Xen does not support trace buffer re-sizing. If the buffers - * have already been allocated we just use them as is. - */ - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_get_info; - if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0) - return (err); - - if (tbuf_op.size == 0) { - /* set trace buffer size */ - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_set_size; - tbuf_op.size = xdt_tbuf_pages; - (void) xdt_sysctl_tbuf(&tbuf_op); - - /* get trace buffer info */ - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_get_info; - if ((err = xdt_sysctl_tbuf(&tbuf_op)) != 0) - return (err); - - if (tbuf_op.size == 0) { - cmn_err(CE_NOTE, "Couldn't allocate trace buffers."); - return (ENOBUFS); - } - } - - tbuf.size = tbuf_op.size; - tbuf.start_mfn = (mfn_t)tbuf_op.buffer_mfn; - tbuf.cnt = xdt_ncpus; - - ASSERT(tbuf.start_mfn != MFN_INVALID); - ASSERT(tbuf.cnt > 0); - - len = tbuf.size * tbuf.cnt; - tbuf.va = vmem_alloc(heap_arena, len, VM_SLEEP); - - if ((err = xdt_map_trace_buffers(tbuf.start_mfn, tbuf.va, len)) != 0) { - vmem_free(heap_arena, tbuf.va, len); - tbuf.va = NULL; - return (err); - } - - tbuf.meta = (struct t_buf **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.meta), - KM_SLEEP); - tbuf.data = (struct t_rec **)kmem_alloc(tbuf.cnt * sizeof (*tbuf.data), - KM_SLEEP); - - for (i = 0; i < tbuf.cnt; i++) { - void *cpu_buf = (void *)(tbuf.va + (tbuf.size * i)); - tbuf.meta[i] = cpu_buf; - tbuf.data[i] = (struct t_rec *)((uintptr_t)cpu_buf + - sizeof (struct t_buf)); - - /* throw away stale trace records */ - tbuf.meta[i]->cons = tbuf.meta[i]->prod; - } - - tbuf_data_size = tbuf.size - sizeof (struct t_buf); - if (xdt_max_recs == 0) - xdt_max_recs = (xdt_ncpus * tbuf_data_size) - / sizeof (struct t_rec); - - return (0); -} - -static void -xdt_detach_trace_buffers(void) -{ - size_t len = tbuf.size * tbuf.cnt; - - ASSERT(tbuf.va != NULL); - - hat_unload(kas.a_hat, tbuf.va, len, - HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK); - vmem_free(heap_arena, tbuf.va, len); - kmem_free(tbuf.meta, tbuf.cnt * sizeof (*tbuf.meta)); - kmem_free(tbuf.data, tbuf.cnt * sizeof (*tbuf.data)); -} - -static void -xdt_update_sched_context(uint_t cpuid, uint_t dom, uint_t vcpu) -{ - xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid]; - - sp->cur_domid = dom; - sp->cur_vcpuid = vcpu; - sp->curinfo_valid = 1; -} - -static void -xdt_update_domain_context(uint_t dom, uint_t vcpu) -{ - xdt_curdom = dom; - xdt_curvcpu = vcpu; -} - -static size_t -xdt_process_rec(uint_t cpuid, struct t_rec *rec) -{ - xdt_schedinfo_t *sp = &xdt_cpu_schedinfo[cpuid]; - uint_t dom, vcpu; - int eid; - uint32_t *data; - uint64_t tsc, addr64, rip64, val64, pte64; - size_t rec_size; - - ASSERT(rec != NULL); - ASSERT(xdt_ncpus == xpv_nr_phys_cpus()); - - if (cpuid >= xdt_ncpus) { - tbuf.stat_spurious_cpu++; - goto done; - } - - /* - * If our current state isn't valid, and if this is not - * an event that will update our state, skip it. - */ - - if (!sp->curinfo_valid && - rec->event != TRC_SCHED_SWITCH && - rec->event != TRC_LOST_RECORDS) - goto done; - - if (rec->cycles_included) { - data = rec->u.cycles.extra_u32; - tsc = (((uint64_t)rec->u.cycles.cycles_hi) << 32) - | rec->u.cycles.cycles_lo; - } else { - data = rec->u.nocycles.extra_u32; - tsc = 0; - } - - xdt_timestamp = tsc; - - switch (rec->event) { - /* - * Sched probes - */ - case TRC_SCHED_SWITCH_INFPREV: - /* - * Info on vCPU being de-scheduled - * - * data[0] = prev domid - * data[1] = time spent on pcpu - */ - sp->prev_domid = data[0]; - sp->prev_ctime = data[1]; - break; - - case TRC_SCHED_SWITCH_INFNEXT: - /* - * Info on next vCPU to be scheduled - * - * data[0] = next domid - * data[1] = time spent waiting to get on cpu - * data[2] = time slice - */ - sp->next_domid = data[0]; - sp->next_wtime = data[1]; - sp->next_ts = data[2]; - break; - - case TRC_SCHED_SWITCH: - /* - * vCPU switch - * - * data[0] = prev domid - * data[1] = prev vcpuid - * data[2] = next domid - * data[3] = next vcpuid - */ - - /* - * Provide valid context for this probe if there - * wasn't one. - */ - if (!sp->curinfo_valid) - xdt_update_domain_context(data[0], data[1]); - - xdt_update_sched_context(cpuid, data[0], data[1]); - - if (data[0] != sp->prev_domid && - data[2] != sp->next_domid) { - /* prev and next info don't match doms being sched'd */ - tbuf.stat_spurious_switch++; - goto switchdone; - } - - sp->prev_vcpuid = data[1]; - sp->next_vcpuid = data[3]; - - XDT_PROBE3(IS_IDLE_DOM(sp->prev_domid)? - XDT_SCHED_IDLE_OFF_CPU:XDT_SCHED_OFF_CPU, - sp->prev_domid, sp->prev_vcpuid, sp->prev_ctime); - - XDT_PROBE4(IS_IDLE_DOM(sp->next_domid)? - XDT_SCHED_IDLE_ON_CPU:XDT_SCHED_ON_CPU, - sp->next_domid, sp->next_vcpuid, sp->next_wtime, - sp->next_ts); -switchdone: - xdt_update_sched_context(cpuid, data[2], data[3]); - xdt_update_domain_context(data[2], data[3]); - - break; - - case TRC_SCHED_BLOCK: - /* - * vCPU blocked - * - * data[0] = domid - * data[1] = vcpuid - */ - XDT_PROBE2(XDT_SCHED_BLOCK, data[0], data[1]); - break; - - case TRC_SCHED_SLEEP: - /* - * Put vCPU to sleep - * - * data[0] = domid - * data[1] = vcpuid - */ - XDT_PROBE2(XDT_SCHED_SLEEP, data[0], data[1]); - break; - - case TRC_SCHED_WAKE: - /* - * Wake up vCPU - * - * data[0] = domid - * data[1] = vcpuid - */ - XDT_PROBE2(XDT_SCHED_WAKE, data[0], data[1]); - break; - - case TRC_SCHED_YIELD: - /* - * vCPU yielded - * - * data[0] = domid - * data[1] = vcpuid - */ - XDT_PROBE2(XDT_SCHED_YIELD, data[0], data[1]); - break; - - case TRC_SCHED_SHUTDOWN: - /* - * Guest shutting down - * - * data[0] = domid - * data[1] = initiating vcpu - * data[2] = shutdown code - */ - switch (data[2]) { - case SHUTDOWN_poweroff: - eid = XDT_SCHED_SHUTDOWN_POWEROFF; - break; - case SHUTDOWN_reboot: - eid = XDT_SCHED_SHUTDOWN_REBOOT; - break; - case SHUTDOWN_suspend: - eid = XDT_SCHED_SHUTDOWN_SUSPEND; - break; - case SHUTDOWN_crash: - eid = XDT_SCHED_SHUTDOWN_CRASH; - break; - default: - tbuf.stat_unknown_shutdown++; - goto done; - } - - XDT_PROBE2(eid, data[0], data[1]); - break; - - case TRC_SCHED_DOM_REM: - case TRC_SCHED_CTL: - case TRC_SCHED_S_TIMER_FN: - case TRC_SCHED_T_TIMER_FN: - case TRC_SCHED_DOM_TIMER_FN: - /* unused */ - break; - case TRC_SCHED_DOM_ADD: - /* - * Add vcpu to a guest. - * - * data[0] = domid - * data[1] = vcpu - */ - XDT_PROBE2(XDT_SCHED_ADD_VCPU, data[0], data[1]); - break; - case TRC_SCHED_ADJDOM: - /* - * Scheduling parameters for a guest - * were modified. - * - * data[0] = domid; - */ - XDT_PROBE1(XDT_SCHED_ADJDOM, data[1]); - break; - case TRC_SCHED_RUNSTATE_CHANGE: - /* - * Runstate change for a VCPU. - * - * data[0] = (domain << 16) | vcpu; - * data[1] = oldstate; - * data[2] = newstate; - */ - XDT_PROBE4(XDT_SCHED_RUNSTATE_CHANGE, data[0] >> 16, - data[0] & 0xffff, data[1], data[2]); - break; - case TRC_SCHED_CONTINUE_RUNNING: - /* - * VCPU is back on a physical CPU that it previously - * was also running this VCPU. - * - * data[0] = (domain << 16) | vcpu; - */ - XDT_PROBE2(XDT_SCHED_CONTINUE_RUNNING, data[0] >> 16, - data[0] & 0xffff); - break; - /* - * Mem probes - */ - case TRC_MEM_PAGE_GRANT_MAP: - /* - * Guest mapped page grant - * - * data[0] = target domid - */ - XDT_PROBE1(XDT_MEM_PAGE_GRANT_MAP, data[0]); - break; - - case TRC_MEM_PAGE_GRANT_UNMAP: - /* - * Guest unmapped page grant - * - * data[0] = target domid - */ - XDT_PROBE1(XDT_MEM_PAGE_GRANT_UNMAP, data[0]); - break; - - case TRC_MEM_PAGE_GRANT_TRANSFER: - /* - * Page grant is being transferred - * - * data[0] = target domid - */ - XDT_PROBE1(XDT_MEM_PAGE_GRANT_TRANSFER, data[0]); - break; - - /* - * Probes for PV domains. - */ - case TRC_PV_HYPERCALL: - /* - * Hypercall from a 32-bit PV domain. - * - * data[0] = eip - * data[1] = eax - */ - XDT_PROBE2(XDT_PV_HYPERCALL, data[0], data[1]); - break; - case TRC_PV_HYPERCALL | TRC_64_FLAG: - /* - * Hypercall from a 64-bit PV domain. - * - * data[0] = rip(0:31) - * data[1] = rip(32:63) - * data[2] = eax; - */ - rip64 = (((uint64_t)data[1]) << 32) | data[0]; - XDT_PROBE2(XDT_PV_HYPERCALL, rip64, data[2]); - break; - case TRC_PV_TRAP: - /* - * Trap in a 32-bit PV domain. - * - * data[0] = eip - * data[1] = trapnr | (error_code_valid << 15) - * | (error_code << 16); - */ - XDT_PROBE4(XDT_PV_TRAP, data[0], data[1] & 0x7fff, - (data[1] >> 15) & 1, data[1] >> 16); - break; - case TRC_PV_TRAP | TRC_64_FLAG: - /* - * Trap in a 64-bit PV domain. - * - * data[0] = rip(0:31) - * data[1] = rip(32:63) - * data[2] = trapnr | (error_code_valid << 15) - * | (error_code << 16); - */ - rip64 = (((uint64_t)data[1]) << 32) | data[2]; - XDT_PROBE4(XDT_PV_TRAP, rip64, data[2] & 0x7fff, - (data[2] >> 15) & 1, data[2] >> 16); - break; - case TRC_PV_PAGE_FAULT: - /* - * Page fault in a 32-bit PV domain. - * - * data[0] = eip - * data[1] = vaddr - * data[2] = error code - */ - XDT_PROBE3(XDT_PV_PAGE_FAULT, data[0], data[1], data[2]); - break; - case TRC_PV_PAGE_FAULT | TRC_64_FLAG: - /* - * Page fault in a 32-bit PV domain. - * - * data[0] = rip(0:31) - * data[1] = rip(31:63) - * data[2] = vaddr(0:31) - * data[3] = vaddr(31:63) - * data[4] = error code - */ - rip64 = (((uint64_t)data[1]) << 32) | data[0]; - addr64 = (((uint64_t)data[3]) << 32) | data[2]; - XDT_PROBE3(XDT_PV_PAGE_FAULT, rip64, addr64, data[4]); - break; - case TRC_PV_FORCED_INVALID_OP: - /* - * Hypervisor emulated a forced invalid op (ud2) - * in a 32-bit PV domain. - * - * data[1] = eip - */ - XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, data[1]); - break; - case TRC_PV_FORCED_INVALID_OP | TRC_64_FLAG: - /* - * Hypervisor emulated a forced invalid op (ud2) - * in a 64-bit PV domain. - * - * data[1] = rip(0:31) - * data[2] = rip(31:63) - * - */ - rip64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE1(XDT_PV_FORCED_INVALID_OP, rip64); - break; - case TRC_PV_EMULATE_PRIVOP: - /* - * Hypervisor emulated a privileged operation - * in a 32-bit PV domain. - * - * data[0] = eip - */ - XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, data[0]); - break; - case TRC_PV_EMULATE_PRIVOP | TRC_64_FLAG: - /* - * Hypervisor emulated a privileged operation - * in a 64-bit PV domain. - * - * data[0] = rip(0:31) - * data[1] = rip(31:63) - */ - rip64 = (((uint64_t)data[1]) << 32) | data[0]; - XDT_PROBE1(XDT_PV_EMULATE_PRIVOP, rip64); - break; - case TRC_PV_EMULATE_4GB: - /* unused, 32-bit hypervisor only */ - break; - case TRC_PV_MATH_STATE_RESTORE: - /* - * Hypervisor restores math state after FP DNA trap. - * - * No arguments. - */ - XDT_PROBE0(XDT_PV_MATH_STATE_RESTORE); - break; - case TRC_PV_PAGING_FIXUP: - /* - * Hypervisor fixed up a page fault (e.g. it was - * a side-effect of hypervisor guest page table - * bookkeeping, and not propagated to the guest). - * - * data[0] = eip - * data[1] = vaddr - */ - XDT_PROBE2(XDT_PV_PAGING_FIXUP, data[0], data[2]); - break; - case TRC_PV_PAGING_FIXUP | TRC_64_FLAG: - /* - * Hypervisor fixed up a page fault (e.g. it was - * a side-effect of hypervisor guest page table - * bookkeeping, and not propagated to the guest). - * - * data[0] = eip(0:31) - * data[1] = eip(31:63) - * data[2] = vaddr(0:31) - * data[3] = vaddr(31:63) - */ - rip64 = (((uint64_t)data[1]) << 32) | data[0]; - addr64 = (((uint64_t)data[3]) << 32) | data[2]; - XDT_PROBE2(XDT_PV_PAGING_FIXUP, rip64, addr64); - break; - case TRC_PV_GDT_LDT_MAPPING_FAULT: - /* - * Descriptor table mapping fault in a 32-bit PV domain. - * data[0] = eip - * data[1] = offset - */ - XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, data[0], data[1]); - break; - case TRC_PV_GDT_LDT_MAPPING_FAULT | TRC_64_FLAG: - /* - * Descriptor table mapping fault in a 64-bit PV domain. - * - * data[0] = eip(0:31) - * data[1] = eip(31:63) - * data[2] = offset(0:31) - * data[3] = offset(31:63) - */ - rip64 = (((uint64_t)data[1]) << 32) | data[0]; - val64 = (((uint64_t)data[3]) << 32) | data[2]; - XDT_PROBE2(XDT_PV_DT_MAPPING_FAULT, rip64, val64); - break; - case TRC_PV_PTWR_EMULATION: - case TRC_PV_PTWR_EMULATION_PAE | TRC_64_FLAG: - /* - * Should only happen on 32-bit hypervisor; unused. - */ - break; - case TRC_PV_PTWR_EMULATION_PAE: - /* - * PTE write emulation for a 32-bit PV domain. - * - * data[0] = pte - * data[1] = addr - * data[2] = eip - */ - XDT_PROBE3(XDT_PV_PTWR_EMULATION, data[0], data[1], data[2]); - break; - case TRC_PV_PTWR_EMULATION | TRC_64_FLAG: - /* - * PTE write emulation for a 64-bit PV domain. - * - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = addr(0:31) - * data[3] = addr(32:63) - * data[4] = rip(0:31) - * data[5] = rip(32:63) - */ - pte64 = (((uint64_t)data[1]) << 32) | data[0]; - addr64 = (((uint64_t)data[3]) << 32) | data[2]; - rip64 = (((uint64_t)data[5]) << 32) | data[4]; - XDT_PROBE3(XDT_PV_PTWR_EMULATION, pte64, addr64, rip64); - break; - - /* - * HVM probes - */ - case TRC_HVM_VMENTRY: - /* - * Return to guest via vmx_launch/vmrun - * - */ - XDT_PROBE0(XDT_HVM_VMENTRY); - break; - - case TRC_HVM_VMEXIT: - /* - * Entry into VMEXIT handler from 32-bit HVM domain - * - * data[0] = cpu vendor specific exit code - * data[1] = guest eip - */ - XDT_PROBE2(XDT_HVM_VMEXIT, data[0], data[1]); - break; - case TRC_HVM_VMEXIT64: - /* - * Entry into VMEXIT handler from 64-bit HVM domain - * - * data[0] = cpu vendor specific exit code - * data[1] = guest rip(0:31) - * data[2] = guest rip(32:64) - */ - rip64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_VMEXIT, data[0], rip64); - break; - - case TRC_HVM_PF_XEN64: - /* - * Pagefault in a guest that is a Xen (e.g. shadow) - * artifact, and is not injected back into the guest. - * - * data[0] = error code - * data[1] = guest VA(0:31) - * data[2] = guest VA(32:64) - */ - addr64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_PF_XEN, data[0], addr64); - break; - - case TRC_HVM_PF_XEN: - /* - * Same as above, but for a 32-bit HVM domain. - * - * data[0] = error code - * data[1] = guest VA - */ - XDT_PROBE2(XDT_HVM_PF_XEN, data[0], data[1]); - break; - - case TRC_HVM_PF_INJECT: - /* - * 32-bit Xen only. - */ - break; - case TRC_HVM_PF_INJECT64: - /* - * Pagefault injected back into a guest (e.g. the shadow - * code found no mapping). - * - * data[0] = error code - * data[1] = guest VA(0:31) - * data[2] = guest VA(32:64) - */ - addr64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_PF_INJECT, data[0], addr64); - break; - - case TRC_HVM_INJ_EXC: - /* - * Exception injected into an HVM guest. - * - * data[0] = trap - * data[1] = error code - */ - XDT_PROBE2(XDT_HVM_EXC_INJECT, data[0], data[1]); - break; - case TRC_HVM_INJ_VIRQ: - /* - * Interrupt inject into an HVM guest. - * - * data[0] = vector - */ - XDT_PROBE1(XDT_HVM_VIRQ_INJECT, data[0]); - break; - case TRC_HVM_REINJ_VIRQ: - case TRC_HVM_IO_READ: - case TRC_HVM_IO_WRITE: - /* unused */ - break; - case TRC_HVM_CR_READ64: - /* - * Control register read. Intel VMX only. - * - * data[0] = control register # - * data[1] = value(0:31) - * data[2] = value(32:63) - */ - val64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64); - break; - case TRC_HVM_CR_READ: - /* - * unused (32-bit Xen only) - */ - break; - case TRC_HVM_CR_WRITE64: - /* - * Control register write. Intel VMX only. - * - * data[0] = control register # - * data[1] = value(0:31) - * data[2] = value(32:63) - */ - val64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_CR_READ, data[0], val64); - break; - case TRC_HVM_CR_WRITE: - /* - * unused (32-bit Xen only) - */ - break; - case TRC_HVM_DR_READ: - /* - * unused. - * - * data[0] = (domid<<16 + vcpuid) - */ - break; - case TRC_HVM_DR_WRITE: - /* - * Debug register write. Not too useful; no values, - * so we ignore this. - * - * data[0] = (domid<<16 + vcpuid) - */ - break; - case TRC_HVM_MSR_READ: - /* - * MSR read. - * - * data[0] = MSR - * data[1] = value(0:31) - * data[2] = value(32:63) - */ - val64 = (((uint64_t)data[3]) << 32) | data[2]; - XDT_PROBE2(XDT_HVM_MSR_READ, data[0], val64); - break; - case TRC_HVM_MSR_WRITE: - /* - * MSR write. - * - * data[0] = MSR; - * data[1] = value(0:31) - * data[2] = value(32:63) - */ - val64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_MSR_WRITE, data[0], val64); - break; - case TRC_HVM_CPUID: - /* - * CPUID insn. - * - * data[0] = %eax (input) - * data[1] = %eax - * data[2] = %ebx - * data[3] = %ecx - * data[4] = %edx - */ - XDT_PROBE5(XDT_HVM_CPUID, data[0], data[1], data[2], data[3], - data[4]); - break; - case TRC_HVM_INTR: - /* - * VMEXIT because of an interrupt. - */ - XDT_PROBE0(XDT_HVM_INTR); - break; - case TRC_HVM_INTR_WINDOW: - /* - * VMEXIT because of an interrupt window (an interrupt - * can't be delivered immediately to a HVM guest and must - * be delayed). - * - * data[0] = vector - * data[1] = source - * data[2] = info - */ - XDT_PROBE3(XDT_HVM_INTR_WINDOW, data[0], data[1], data[2]); - break; - case TRC_HVM_NMI: - /* - * VMEXIT because of an NMI. - */ - XDT_PROBE0(XDT_HVM_NMI); - break; - case TRC_HVM_SMI: - /* - * VMEXIT because of an SMI - */ - XDT_PROBE0(XDT_HVM_SMI); - break; - case TRC_HVM_VMMCALL: - /* - * VMMCALL insn. - * - * data[0] = %eax - */ - XDT_PROBE1(XDT_HVM_VMMCALL, data[0]); - break; - case TRC_HVM_HLT: - /* - * HLT insn. - * - * data[0] = 1 if VCPU runnable, 0 if not - */ - XDT_PROBE1(XDT_HVM_HLT, data[0]); - break; - case TRC_HVM_INVLPG64: - /* - * - * data[0] = INVLPGA ? 1 : 0 - * data[1] = vaddr(0:31) - * data[2] = vaddr(32:63) - */ - addr64 = (((uint64_t)data[2]) << 32) | data[1]; - XDT_PROBE2(XDT_HVM_INVLPG, data[0], addr64); - break; - case TRC_HVM_INVLPG: - /* - * unused (32-bit Xen only) - * - * data[0] = (domid<<16 + vcpuid) - */ - break; - case TRC_HVM_MCE: - /* - * #MCE VMEXIT - * - */ - XDT_PROBE0(XDT_HVM_MCE); - break; - case TRC_HVM_IOPORT_READ: - case TRC_HVM_IOPORT_WRITE: - case TRC_HVM_IOMEM_READ: - case TRC_HVM_IOMEM_WRITE: - /* - * data[0] = addr(0:31) - * data[1] = addr(32:63) - * data[2] = count - * data[3] = size - */ - switch (rec->event) { - case TRC_HVM_IOPORT_READ: - eid = XDT_HVM_IOPORT_READ; - break; - case TRC_HVM_IOPORT_WRITE: - eid = XDT_HVM_IOPORT_WRITE; - break; - case TRC_HVM_IOMEM_READ: - eid = XDT_HVM_IOMEM_READ; - break; - case TRC_HVM_IOMEM_WRITE: - eid = XDT_HVM_IOMEM_WRITE; - break; - } - addr64 = (((uint64_t)data[1]) << 32) | data[0]; - XDT_PROBE3(eid, addr64, data[2], data[3]); - break; - case TRC_HVM_CLTS: - /* - * CLTS insn (Intel VMX only) - */ - XDT_PROBE0(XDT_HVM_CLTS); - break; - case TRC_HVM_LMSW64: - /* - * LMSW insn. - * - * data[0] = value(0:31) - * data[1] = value(32:63) - */ - val64 = (((uint64_t)data[1]) << 32) | data[0]; - XDT_PROBE1(XDT_HVM_LMSW, val64); - break; - case TRC_HVM_LMSW: - /* - * unused (32-bit Xen only) - */ - break; - - /* - * Shadow page table probes (mainly used for HVM domains - * without hardware paging support). - */ - case TRC_SHADOW_NOT_SHADOW | SH_GUEST_32: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = va - * data[3] = flags - */ - pte64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, data[2], data[3]); - break; - case TRC_SHADOW_NOT_SHADOW | SH_GUEST_PAE: - case TRC_SHADOW_NOT_SHADOW | SH_GUEST_64: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = va(0:31) - * data[3] = va(32:63) - * data[4] = flags - */ - addr64 = ((uint64_t)data[2] << 32) | data[3]; - pte64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE3(XDT_SHADOW_NOT_SHADOW, pte64, addr64, data[4]); - break; - case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_32: - /* - * data[0] = va - */ - XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, data[0]); - break; - case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_PAE: - case TRC_SHADOW_FAST_PROPAGATE | SH_GUEST_64: - /* - * data[0] = va(0:31) - * data[1] = va(32:63) - */ - addr64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_FAST_PROPAGATE, addr64); - break; - case TRC_SHADOW_FAST_MMIO | SH_GUEST_32: - /* - * data[0] = va - */ - XDT_PROBE1(XDT_SHADOW_FAST_MMIO, data[0]); - break; - case TRC_SHADOW_FAST_MMIO | SH_GUEST_PAE: - case TRC_SHADOW_FAST_MMIO | SH_GUEST_64: - /* - * data[0] = va(0:31) - * data[1] = va(32:63) - */ - addr64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_FAST_MMIO, addr64); - break; - case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_32: - /* - * data[0] = va - */ - XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, data[0]); - break; - case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_PAE: - case TRC_SHADOW_FALSE_FAST_PATH | SH_GUEST_64: - /* - * data[0] = va(0:31) - * data[1] = va(32:63) - */ - addr64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_FALSE_FAST_PATH, addr64); - break; - case TRC_SHADOW_MMIO | SH_GUEST_32: - /* - * data[0] = va - */ - XDT_PROBE1(XDT_SHADOW_MMIO, data[0]); - break; - case TRC_SHADOW_MMIO | SH_GUEST_PAE: - case TRC_SHADOW_MMIO | SH_GUEST_64: - /* - * data[0] = va(0:31) - * data[1] = va(32:63) - */ - addr64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_MMIO, addr64); - break; - case TRC_SHADOW_FIXUP | SH_GUEST_32: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = va - * data[3] = flags - */ - pte64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, data[2], data[3]); - break; - case TRC_SHADOW_FIXUP | SH_GUEST_64: - case TRC_SHADOW_FIXUP | SH_GUEST_PAE: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = va(0:31) - * data[3] = va(32:63) - * data[4] = flags - */ - addr64 = ((uint64_t)data[2] << 32) | data[3]; - pte64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE3(XDT_SHADOW_FIXUP, pte64, addr64, data[4]); - break; - case TRC_SHADOW_DOMF_DYING | SH_GUEST_32: - /* - * data[0] = va - */ - XDT_PROBE1(XDT_SHADOW_DOMF_DYING, data[0]); - break; - case TRC_SHADOW_DOMF_DYING | SH_GUEST_PAE: - case TRC_SHADOW_DOMF_DYING | SH_GUEST_64: - /* - * data[0] = va(0:31) - * data[1] = va(32:63) - */ - addr64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_DOMF_DYING, addr64); - break; - case TRC_SHADOW_EMULATE | SH_GUEST_32: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = val(0:31) - * data[3] = val(32:63) - * data[4] = addr - * data[5] = flags - */ - pte64 = ((uint64_t)data[1] << 32) | data[0]; - val64 = ((uint64_t)data[3] << 32) | data[2]; - XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4], - data[5] & 0x7fffffff, data[5] >> 29); - break; - case TRC_SHADOW_EMULATE | SH_GUEST_PAE: - case TRC_SHADOW_EMULATE | SH_GUEST_64: - /* - * data[0] = pte(0:31) - * data[1] = pte(32:63) - * data[2] = val(0:31) - * data[3] = val(32:63) - * data[4] = addr(0:31) - * data[5] = addr(32:63) - * data[6] = flags - */ - pte64 = ((uint64_t)data[1] << 32) | data[0]; - val64 = ((uint64_t)data[3] << 32) | data[2]; - addr64 = ((uint64_t)data[5] << 32) | data[4]; - XDT_PROBE5(XDT_SHADOW_EMULATE, pte64, val64, data[4], - data[6] & 0x7fffffff, data[6] >> 29); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_32: - /* - * data[0] = gfn - * data[1] = vaddr - */ - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, data[0], data[1]); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_PAE: - case TRC_SHADOW_EMULATE_UNSHADOW_USER | SH_GUEST_64: - /* - * data[0] = gfn(0:31) - * data[1] = gfn(32:63) - * data[2] = vaddr(0:31) - * data[3] = vaddr(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - addr64 = ((uint64_t)data[3] << 32) | data[2]; - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_USER, val64, addr64); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_32: - /* - * data[0] = gfn - * data[1] = vaddr - */ - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, data[0], - data[1]); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_PAE: - case TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ | SH_GUEST_64: - /* - * data[0] = gfn(0:31) - * data[1] = gfn(32:63) - * data[2] = vaddr(0:31) - * data[3] = vaddr(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - addr64 = ((uint64_t)data[3] << 32) | data[2]; - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_EVTINJ, val64, addr64); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_32: - /* - * data[0] = gfn - * data[1] = vaddr - */ - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, data[0], - data[1]); - break; - case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_PAE: - case TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED | SH_GUEST_64: - /* - * data[0] = gfn(0:31) - * data[1] = gfn(32:63) - * data[2] = vaddr(0:31) - * data[3] = vaddr(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - addr64 = ((uint64_t)data[3] << 32) | data[2]; - XDT_PROBE2(XDT_SHADOW_EMULATE_UNSHADOW_UNHANDLED, val64, - addr64); - break; - case TRC_SHADOW_WRMAP_BF: - /* - * data[0] = gfn(0:31) - * data[1] = gfn(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_WRMAP_BF, val64); - break; - case TRC_SHADOW_PREALLOC_UNPIN: - /* - * data[0] = gfn(0:31) - * data[1] = gfn(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_PREALLOC_UNPIN, val64); - break; - case TRC_SHADOW_RESYNC_FULL: - /* - * data[0] = gmfn(0:31) - * data[1] = gmfn(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_RESYNC_FULL, val64); - break; - case TRC_SHADOW_RESYNC_ONLY: - /* - * data[0] = gmfn(0:31) - * data[1] = gmfn(32:63) - */ - val64 = ((uint64_t)data[1] << 32) | data[0]; - XDT_PROBE1(XDT_SHADOW_RESYNC_ONLY, val64); - break; - - /* - * Power management probes. - */ - case TRC_PM_FREQ_CHANGE: - /* - * data[0] = old freq - * data[1] = new freq - */ - XDT_PROBE2(XDT_PM_FREQ_CHANGE, data[0], data[1]); - break; - case TRC_PM_IDLE_ENTRY: - /* - * data[0] = C-state - * data[1] = time - */ - XDT_PROBE2(XDT_PM_IDLE_ENTRY, data[0], data[1]); - break; - case TRC_PM_IDLE_EXIT: - /* - * data[0] = C-state - * data[1] = time - */ - XDT_PROBE2(XDT_PM_IDLE_EXIT, data[0], data[1]); - break; - case TRC_LOST_RECORDS: - vcpu = data[1] >> 16; - dom = data[1] & 0xffff; - xdt_update_sched_context(cpuid, dom, vcpu); - xdt_update_domain_context(dom, vcpu); - XDT_PROBE1(XDT_TRC_LOST_RECORDS, cpuid); - tbuf.stat_dropped_recs++; - break; - - default: - tbuf.stat_unknown_recs++; - break; - } - -done: - rec_size = 4 + (rec->cycles_included ? 8 : 0) + (rec->extra_u32 * 4); - return (rec_size); -} - -/* - * Scan all CPU buffers for the record with the lowest timestamp so - * that the probes will fire in order. - */ -static int -xdt_get_first_rec(uint_t *cpuidp, struct t_rec **recp, uint32_t *consp) -{ - uint_t cpuid; - uint32_t prod, cons, offset; - struct t_rec *rec; - uint64_t minstamp = ~0ULL, stamp; - uintptr_t data; - - for (cpuid = 0; cpuid < tbuf.cnt; cpuid++) { - cons = tbuf.meta[cpuid]->cons; - prod = tbuf.meta[cpuid]->prod; - membar_consumer(); - if (prod == cons) - continue; - - offset = cons % tbuf_data_size; - data = (uintptr_t)tbuf.data[cpuid] + offset; - rec = (struct t_rec *)data; - ASSERT((caddr_t)rec < tbuf.va + (tbuf.size * (cpuid + 1))); - - /* - * All records that we know about have time cycles included. - * If this record doesn't have them, assume it's a type - * that we don't handle. Use a 0 time value, which will make - * it get handled first (it will be thrown away). - */ - if (rec->cycles_included) - stamp = (((uint64_t)rec->u.cycles.cycles_hi) << 32) - | rec->u.cycles.cycles_lo; - else - stamp = 0; - - if (stamp < minstamp) { - minstamp = stamp; - *cpuidp = cpuid; - *recp = rec; - *consp = cons; - } - } - - if (minstamp != ~0ULL) - return (1); - - return (0); -} - -/*ARGSUSED*/ -static void -xdt_tbuf_scan(void *arg) -{ - uint32_t bytes_done, cons; - struct t_rec *rec; - xdt_schedinfo_t *sp; - uint_t nrecs, cpuid; - - for (nrecs = 0; - nrecs < xdt_max_recs && xdt_get_first_rec(&cpuid, &rec, &cons) > 0; - nrecs++) { - xdt_curpcpu = cpuid; - sp = &xdt_cpu_schedinfo[cpuid]; - if (sp->curinfo_valid) - xdt_update_domain_context(sp->cur_domid, - sp->cur_vcpuid); - - bytes_done = xdt_process_rec(cpuid, rec); - cons += bytes_done; - /* - * cons and prod are incremented modulo (2 * tbuf_data_size). - * See . - */ - if (cons >= 2 * tbuf_data_size) - cons -= 2 * tbuf_data_size; - membar_exit(); - tbuf.meta[cpuid]->cons = cons; - } -} - -static void -xdt_cyclic_enable(void) -{ - cyc_handler_t hdlr; - cyc_time_t when; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - hdlr.cyh_func = xdt_tbuf_scan; - hdlr.cyh_arg = NULL; - hdlr.cyh_level = CY_LOW_LEVEL; - - when.cyt_interval = xdt_poll_nsec; - when.cyt_when = dtrace_gethrtime() + when.cyt_interval; - - xdt_cyclic = cyclic_add(&hdlr, &when); -} - -static void -xdt_probe_create(xdt_probe_t *p) -{ - ASSERT(p != NULL && p->pr_mod != NULL); - - if (dtrace_probe_lookup(xdt_id, p->pr_mod, NULL, p->pr_name) != 0) - return; - - xdt_prid[p->evt_id] = dtrace_probe_create(xdt_id, p->pr_mod, NULL, - p->pr_name, dtrace_mach_aframes(), p); -} - -/*ARGSUSED*/ -static void -xdt_provide(void *arg, const dtrace_probedesc_t *desc) -{ - const char *mod, *name; - int i; - - if (desc == NULL) { - for (i = 0; xdt_probe[i].pr_mod != NULL; i++) { - xdt_probe_create(&xdt_probe[i]); - } - } else { - mod = desc->dtpd_mod; - name = desc->dtpd_name; - for (i = 0; xdt_probe[i].pr_mod != NULL; i++) { - int l1 = strlen(xdt_probe[i].pr_name); - int l2 = strlen(xdt_probe[i].pr_mod); - if (strncmp(name, xdt_probe[i].pr_name, l1) == 0 && - strncmp(mod, xdt_probe[i].pr_mod, l2) == 0) - break; - } - - if (xdt_probe[i].pr_mod == NULL) - return; - xdt_probe_create(&xdt_probe[i]); - } - -} - -/*ARGSUSED*/ -static void -xdt_destroy(void *arg, dtrace_id_t id, void *parg) -{ - xdt_probe_t *p = parg; - xdt_prid[p->evt_id] = 0; -} - -static void -xdt_set_trace_mask(uint32_t mask) -{ - xen_sysctl_tbuf_op_t tbuf_op; - - /* Always need to trace scheduling, for context */ - if (mask != 0) - mask |= TRC_SCHED; - tbuf_op.evt_mask = mask; - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_set_evt_mask; - (void) xdt_sysctl_tbuf(&tbuf_op); -} - -/*ARGSUSED*/ -static int -xdt_enable(void *arg, dtrace_id_t id, void *parg) -{ - xdt_probe_t *p = parg; - xen_sysctl_tbuf_op_t tbuf_op; - - ASSERT(MUTEX_HELD(&cpu_lock)); - ASSERT(xdt_prid[p->evt_id] != 0); - - xdt_probemap[p->evt_id] = xdt_prid[p->evt_id]; - xdt_classinfo[p->class].cnt++; - - if (xdt_classinfo[p->class].cnt == 1) { - /* set the trace mask for this class */ - cur_trace_mask |= xdt_classinfo[p->class].trc_mask; - xdt_set_trace_mask(cur_trace_mask); - } - - if (xdt_cyclic == CYCLIC_NONE) { - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_enable; - if (xdt_sysctl_tbuf(&tbuf_op) != 0) { - cmn_err(CE_NOTE, "Couldn't enable hypervisor tracing."); - return (-1); - } - - xdt_cyclic_enable(); - } - return (0); -} - -/*ARGSUSED*/ -static void -xdt_disable(void *arg, dtrace_id_t id, void *parg) -{ - xdt_probe_t *p = parg; - xen_sysctl_tbuf_op_t tbuf_op; - int i, err; - - ASSERT(MUTEX_HELD(&cpu_lock)); - ASSERT(xdt_probemap[p->evt_id] != 0); - ASSERT(xdt_probemap[p->evt_id] == xdt_prid[p->evt_id]); - ASSERT(xdt_classinfo[p->class].cnt > 0); - - /* - * We could be here in the slight window between the cyclic firing and - * a call to dtrace_probe() occurring. We need to be careful if we tear - * down any shared state. - */ - - xdt_probemap[p->evt_id] = 0; - xdt_classinfo[p->class].cnt--; - - if (xdt_nr_active_probes() == 0) { - cur_trace_mask = 0; - - if (xdt_cyclic == CYCLIC_NONE) - return; - - for (i = 0; i < xdt_ncpus; i++) - xdt_cpu_schedinfo[i].curinfo_valid = 0; - - /* - * We will try to disable the trace buffers. If we fail for some - * reason we will try again, up to a count of XDT_TBUF_RETRY. - * If we still aren't successful we try to set the trace mask - * to 0 in order to prevent trace records from being written. - */ - tbuf_op.cmd = XEN_SYSCTL_TBUFOP_disable; - i = 0; - do { - err = xdt_sysctl_tbuf(&tbuf_op); - } while ((err != 0) && (++i < XDT_TBUF_RETRY)); - - if (err != 0) { - cmn_err(CE_NOTE, - "Couldn't disable hypervisor tracing."); - xdt_set_trace_mask(0); - } else { - cyclic_remove(xdt_cyclic); - xdt_cyclic = CYCLIC_NONE; - /* - * We don't bother making the hypercall to set - * the trace mask, since it will be reset when - * tracing is re-enabled. - */ - } - } else if (xdt_classinfo[p->class].cnt == 0) { - cur_trace_mask ^= xdt_classinfo[p->class].trc_mask; - /* other probes are enabled, so add the sub-class mask back */ - cur_trace_mask |= 0xF000; - xdt_set_trace_mask(cur_trace_mask); - } -} - -static dtrace_pattr_t xdt_attr = { -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_PLATFORM }, -}; - -static dtrace_pops_t xdt_pops = { - xdt_provide, /* dtps_provide() */ - NULL, /* dtps_provide_module() */ - xdt_enable, /* dtps_enable() */ - xdt_disable, /* dtps_disable() */ - NULL, /* dtps_suspend() */ - NULL, /* dtps_resume() */ - NULL, /* dtps_getargdesc() */ - NULL, /* dtps_getargval() */ - NULL, /* dtps_usermode() */ - xdt_destroy /* dtps_destroy() */ -}; - -static int -xdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - int val; - - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_ATTACH: - break; - - case DDI_RESUME: - /* - * We might support proper suspend/resume in the future, so, - * return DDI_FAILURE for now. - */ - return (DDI_FAILURE); - - default: - return (DDI_FAILURE); - } - - xdt_ncpus = xpv_nr_phys_cpus(); - ASSERT(xdt_ncpus > 0); - - if (ddi_create_minor_node(devi, "xdt", S_IFCHR, 0, DDI_PSEUDO, 0) == - DDI_FAILURE || xdt_attach_trace_buffers() != 0 || - dtrace_register("xdt", &xdt_attr, DTRACE_PRIV_KERNEL, NULL, - &xdt_pops, NULL, &xdt_id) != 0) { - if (tbuf.va != NULL) - xdt_detach_trace_buffers(); - ddi_remove_minor_node(devi, NULL); - return (DDI_FAILURE); - } - - val = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, - "xdt_poll_nsec", XDT_POLL_DEFAULT); - xdt_poll_nsec = MAX(val, XDT_POLL_MIN); - - xdt_cpu_schedinfo = (xdt_schedinfo_t *)kmem_zalloc(xdt_ncpus * - sizeof (xdt_schedinfo_t), KM_SLEEP); - xdt_init_trace_masks(); - xdt_kstat_init(); - - xdt_devi = devi; - ddi_report_dev(devi); - return (DDI_SUCCESS); -} - -static int -xdt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - switch (cmd) { - case DDI_DETACH: - break; - - case DDI_SUSPEND: - /* - * We might support proper suspend/resume in the future. So - * return DDI_FAILURE for now. - */ - return (DDI_FAILURE); - - default: - return (DDI_FAILURE); - } - - if (dtrace_unregister(xdt_id) != 0) - return (DDI_FAILURE); - - xdt_detach_trace_buffers(); - kmem_free(xdt_cpu_schedinfo, xdt_ncpus * sizeof (xdt_schedinfo_t)); - if (xdt_cyclic != CYCLIC_NONE) - cyclic_remove(xdt_cyclic); - if (xdt_kstats != NULL) - kstat_delete(xdt_kstats); - xdt_devi = NULL; - ddi_remove_minor_node(devi, NULL); - - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static int -xdt_info(dev_info_t *devi, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - int error; - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = xdt_devi; - error = DDI_SUCCESS; - break; - case DDI_INFO_DEVT2INSTANCE: - *result = NULL; - error = DDI_SUCCESS; - break; - default: - error = DDI_FAILURE; - } - return (error); -} - -static struct cb_ops xdt_cb_ops = { - nulldev, /* open(9E) */ - nodev, /* close(9E) */ - nodev, /* strategy(9E) */ - nodev, /* print(9E) */ - nodev, /* dump(9E) */ - nodev, /* read(9E) */ - nodev, /* write(9E) */ - nodev, /* ioctl(9E) */ - nodev, /* devmap(9E) */ - nodev, /* mmap(9E) */ - nodev, /* segmap(9E) */ - nochpoll, /* chpoll(9E) */ - ddi_prop_op, /* prop_op(9E) */ - NULL, /* streamtab(9S) */ - D_MP | D_64BIT | D_NEW /* cb_flag */ -}; - -static struct dev_ops xdt_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - xdt_info, /* getinfo(9E) */ - nulldev, /* identify(9E) */ - nulldev, /* probe(9E) */ - xdt_attach, /* attach(9E) */ - xdt_detach, /* detach(9E) */ - nulldev, /* devo_reset */ - &xdt_cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* power(9E) */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - - -static struct modldrv modldrv = { - &mod_driverops, - "Hypervisor event tracing", - &xdt_ops -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/xen/dtrace/xdt.conf b/usr/src/uts/common/xen/dtrace/xdt.conf deleted file mode 100644 index bd1ec82c91..0000000000 --- a/usr/src/uts/common/xen/dtrace/xdt.conf +++ /dev/null @@ -1,33 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -# -# Tunable Properties -# xdt_poll_nsec: interval in nano-seconds to poll trace buffers -# -name="xdt" parent="pseudo" instance=0; diff --git a/usr/src/uts/common/xen/io/blk_common.c b/usr/src/uts/common/xen/io/blk_common.c deleted file mode 100644 index b352345024..0000000000 --- a/usr/src/uts/common/xen/io/blk_common.c +++ /dev/null @@ -1,1021 +0,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 "blk_common.h" - - -/* blk interface status */ -enum blk_if_state { - /* - * initial state - */ - BLK_IF_UNKNOWN = 0, - /* - * frontend xenbus state changed to XenbusStateConnected, - * we finally connect - */ - BLK_IF_CONNECTED, - /* - * frontend xenbus state changed to XenbusStateClosed, - * interface disconnected - */ - BLK_IF_DISCONNECTED -}; - -/* backend device status */ -enum blk_be_state { - /* initial state */ - BLK_BE_UNKNOWN = 0, - /* backend device is ready (hotplug script finishes successfully) */ - BLK_BE_READY -}; - -/* frontend status */ -enum blk_fe_state { - /* initial state */ - BLK_FE_UNKNOWN = 0, - /* - * frontend's xenbus state has changed to - * XenbusStateInitialised, is ready for connecting - */ - BLK_FE_READY -}; - -typedef struct blk_ring_state_s { - kmutex_t rs_mutex; - boolean_t rs_sleeping_on_ring; - boolean_t rs_ring_up; - kcondvar_t rs_cv; -} blk_ring_state_t; - -/* Disk Statistics */ -static char *blk_stats[] = { - "rd_reqs", - "wr_reqs", - "br_reqs", - "fl_reqs", - "oo_reqs" -}; - -typedef struct blk_stats_s { - uint64_t bs_req_reads; - uint64_t bs_req_writes; - uint64_t bs_req_barriers; - uint64_t bs_req_flushes; -} blk_stats_t; - -struct blk_ring_s { - kmutex_t ri_mutex; - dev_info_t *ri_dip; - - kstat_t *ri_kstats; - blk_stats_t ri_stats; - - blk_intr_t ri_intr; - caddr_t ri_intr_arg; - blk_ring_cb_t ri_ringup; - caddr_t ri_ringup_arg; - blk_ring_cb_t ri_ringdown; - caddr_t ri_ringdown_arg; - - /* blk interface, backend, and frontend status */ - enum blk_if_state ri_if_status; - enum blk_be_state ri_be_status; - enum blk_fe_state ri_fe_status; - - domid_t ri_fe; - - enum blkif_protocol ri_protocol; - size_t ri_nentry; - size_t ri_entrysize; - - xendev_ring_t *ri_ring; - blk_ring_state_t ri_state; -}; - - -static void blk_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, - void *arg, void *impl_data); -static void blk_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, - void *arg, void *impl_data); -static int blk_check_state_transition(blk_ring_t ring, XenbusState oestate); -static int blk_start_connect(blk_ring_t ring); -static void blk_start_disconnect(blk_ring_t ring); -static void blk_ring_close(blk_ring_t ring); -static int blk_bindto_frontend(blk_ring_t ring); -static void blk_unbindfrom_frontend(blk_ring_t ring); -static uint_t blk_intr(caddr_t arg); - -static int blk_kstat_init(blk_ring_t ring); -static void blk_kstat_fini(blk_ring_t ring); -static int blk_kstat_update(kstat_t *ksp, int flag); - -static void blk_ring_request_32(blkif_request_t *dst, - blkif_x86_32_request_t *src); -static void blk_ring_request_64(blkif_request_t *dst, - blkif_x86_64_request_t *src); - -static void blk_ring_response_32(blkif_x86_32_response_t *dst, - blkif_response_t *src); -static void blk_ring_response_64(blkif_x86_64_response_t *dst, - blkif_response_t *src); - - -/* - * blk_ring_init() - */ -int -blk_ring_init(blk_ringinit_args_t *args, blk_ring_t *ringp) -{ - blk_ring_t ring; - int e; - - - ring = kmem_zalloc(sizeof (struct blk_ring_s), KM_SLEEP); - mutex_init(&ring->ri_mutex, NULL, MUTEX_DRIVER, NULL); - ring->ri_dip = args->ar_dip; - ring->ri_intr = args->ar_intr; - ring->ri_intr_arg = args->ar_intr_arg; - ring->ri_ringup = args->ar_ringup; - ring->ri_ringup_arg = args->ar_ringup_arg; - ring->ri_ringdown = args->ar_ringdown; - ring->ri_ringdown_arg = args->ar_ringdown_arg; - - ring->ri_if_status = BLK_IF_UNKNOWN; - ring->ri_be_status = BLK_BE_UNKNOWN; - ring->ri_fe_status = BLK_FE_UNKNOWN; - ring->ri_state.rs_sleeping_on_ring = B_FALSE; - ring->ri_state.rs_ring_up = B_FALSE; - - mutex_init(&ring->ri_state.rs_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&ring->ri_state.rs_cv, NULL, CV_DRIVER, NULL); - - e = blk_kstat_init(ring); - if (e != DDI_SUCCESS) { - goto ringinitfail_kstat; - } - - /* Watch frontend and hotplug state change */ - if (xvdi_add_event_handler(ring->ri_dip, XS_OE_STATE, - blk_oe_state_change, ring) != DDI_SUCCESS) { - goto ringinitfail_oestate; - } - if (xvdi_add_event_handler(ring->ri_dip, XS_HP_STATE, - blk_hp_state_change, ring) != DDI_SUCCESS) { - goto ringinitfail_hpstate; - } - - /* - * Kick-off hotplug script - */ - if (xvdi_post_event(ring->ri_dip, XEN_HP_ADD) != DDI_SUCCESS) { - cmn_err(CE_WARN, "blk@%s: failed to start hotplug script", - ddi_get_name_addr(ring->ri_dip)); - goto ringinitfail_postevent; - } - - /* - * start waiting for hotplug event and otherend state event - * mainly for debugging, frontend will not take any op seeing this - */ - (void) xvdi_switch_state(ring->ri_dip, XBT_NULL, XenbusStateInitWait); - - *ringp = ring; - return (DDI_SUCCESS); - -ringinitfail_postevent: - xvdi_remove_event_handler(ring->ri_dip, XS_HP_STATE); -ringinitfail_hpstate: - xvdi_remove_event_handler(ring->ri_dip, XS_OE_STATE); -ringinitfail_oestate: - blk_kstat_fini(ring); -ringinitfail_kstat: - cv_destroy(&ring->ri_state.rs_cv); - mutex_destroy(&ring->ri_state.rs_mutex); - mutex_destroy(&ring->ri_mutex); - kmem_free(ring, sizeof (struct blk_ring_s)); - return (DDI_FAILURE); -} - - -/* - * blk_ring_fini() - */ -void -blk_ring_fini(blk_ring_t *ringp) -{ - blk_ring_t ring; - - - ring = *ringp; - - mutex_enter(&ring->ri_mutex); - if (ring->ri_if_status != BLK_IF_DISCONNECTED) { - blk_ring_close(ring); - } - mutex_exit(&ring->ri_mutex); - - xvdi_remove_event_handler(ring->ri_dip, NULL); - blk_kstat_fini(ring); - cv_destroy(&ring->ri_state.rs_cv); - mutex_destroy(&ring->ri_state.rs_mutex); - mutex_destroy(&ring->ri_mutex); - kmem_free(ring, sizeof (struct blk_ring_s)); - - *ringp = NULL; -} - - -/* - * blk_kstat_init() - */ -static int -blk_kstat_init(blk_ring_t ring) -{ - int nstat = sizeof (blk_stats) / sizeof (blk_stats[0]); - char **cp = blk_stats; - kstat_named_t *knp; - - ring->ri_kstats = kstat_create(ddi_get_name(ring->ri_dip), - ddi_get_instance(ring->ri_dip), "req_statistics", "block", - KSTAT_TYPE_NAMED, nstat, 0); - if (ring->ri_kstats == NULL) { - return (DDI_FAILURE); - } - - ring->ri_kstats->ks_private = ring; - ring->ri_kstats->ks_update = blk_kstat_update; - - knp = ring->ri_kstats->ks_data; - while (nstat > 0) { - kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); - knp++; - cp++; - nstat--; - } - - kstat_install(ring->ri_kstats); - - return (DDI_SUCCESS); -} - - -/* - * blk_kstat_fini() - */ -static void -blk_kstat_fini(blk_ring_t ring) -{ - kstat_delete(ring->ri_kstats); -} - - -/* - * blk_kstat_update() - */ -static int -blk_kstat_update(kstat_t *ksp, int flag) -{ - kstat_named_t *knp; - blk_stats_t *stats; - blk_ring_t ring; - - - if (flag != KSTAT_READ) { - return (EACCES); - } - - ring = ksp->ks_private; - stats = &ring->ri_stats; - knp = ksp->ks_data; - - /* - * Assignment order should match that of the names in - * blk_stats. - */ - (knp++)->value.ui64 = stats->bs_req_reads; - (knp++)->value.ui64 = stats->bs_req_writes; - (knp++)->value.ui64 = stats->bs_req_barriers; - (knp++)->value.ui64 = stats->bs_req_flushes; - (knp++)->value.ui64 = 0; /* oo_req */ - - return (0); -} - - -/* - * blk_oe_state_change() - */ -/*ARGSUSED*/ -static void -blk_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, - void *impl_data) -{ - XenbusState new_state; - blk_ring_t ring; - - - ring = (blk_ring_t)arg; - new_state = *(XenbusState *)impl_data; - - mutex_enter(&ring->ri_mutex); - - if (blk_check_state_transition(ring, new_state) == DDI_FAILURE) { - mutex_exit(&ring->ri_mutex); - return; - } - - switch (new_state) { - case XenbusStateInitialised: - ASSERT(ring->ri_if_status == BLK_IF_UNKNOWN); - - /* frontend is ready for connecting */ - ring->ri_fe_status = BLK_FE_READY; - - if (ring->ri_be_status == BLK_BE_READY) { - mutex_exit(&ring->ri_mutex); - if (blk_start_connect(ring) != DDI_SUCCESS) - (void) blk_start_disconnect(ring); - mutex_enter(&ring->ri_mutex); - } - break; - case XenbusStateClosing: - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing); - break; - case XenbusStateClosed: - /* clean up */ - (void) xvdi_post_event(ring->ri_dip, XEN_HP_REMOVE); - if (ring->ri_ringdown != NULL) { - (*(ring->ri_ringdown))(ring->ri_ringdown_arg); - } - blk_ring_close(ring); - - /* reset state in case of reconnect */ - ring->ri_if_status = BLK_IF_UNKNOWN; - ring->ri_be_status = BLK_BE_UNKNOWN; - ring->ri_fe_status = BLK_FE_UNKNOWN; - ring->ri_state.rs_sleeping_on_ring = B_FALSE; - ring->ri_state.rs_ring_up = B_FALSE; - - break; - default: - ASSERT(0); - } - - mutex_exit(&ring->ri_mutex); -} - - -/* - * blk_hp_state_change() - */ -/*ARGSUSED*/ -static void -blk_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, - void *impl_data) -{ - xendev_hotplug_state_t hpstate; - blk_ring_t ring; - - - ring = (blk_ring_t)arg; - hpstate = *(xendev_hotplug_state_t *)impl_data; - - mutex_enter(&ring->ri_mutex); - if (hpstate == Connected) { - /* Hotplug script has completed successfully */ - if (ring->ri_be_status == BLK_BE_UNKNOWN) { - ring->ri_be_status = BLK_BE_READY; - if (ring->ri_fe_status == BLK_FE_READY) { - mutex_exit(&ring->ri_mutex); - /* try to connect to frontend */ - if (blk_start_connect(ring) != DDI_SUCCESS) - (void) blk_start_disconnect(ring); - mutex_enter(&ring->ri_mutex); - } - } - } - mutex_exit(&ring->ri_mutex); -} - - -/* - * blk_check_state_transition() - * check the XenbusState change to see if the change is a valid transition - * or not. The new state is written by frontend domain, or by running - * xenstore-write to change it manually in dom0. - */ -static int -blk_check_state_transition(blk_ring_t ring, XenbusState oestate) -{ - switch (ring->ri_if_status) { - case BLK_IF_UNKNOWN: - if (ring->ri_fe_status == BLK_FE_UNKNOWN) { - if ((oestate == XenbusStateUnknown) || - (oestate == XenbusStateConnected)) - goto statechkfail_bug; - else if ((oestate == XenbusStateInitialising) || - (oestate == XenbusStateInitWait)) - goto statechkfail_nop; - } else { - if ((oestate == XenbusStateUnknown) || - (oestate == XenbusStateInitialising) || - (oestate == XenbusStateInitWait) || - (oestate == XenbusStateConnected)) - goto statechkfail_bug; - else if (oestate == XenbusStateInitialised) - goto statechkfail_nop; - } - break; - - case BLK_IF_CONNECTED: - if ((oestate == XenbusStateUnknown) || - (oestate == XenbusStateInitialising) || - (oestate == XenbusStateInitWait) || - (oestate == XenbusStateInitialised)) - goto statechkfail_bug; - else if (oestate == XenbusStateConnected) - goto statechkfail_nop; - break; - - case BLK_IF_DISCONNECTED: - default: - goto statechkfail_bug; - } - - return (DDI_SUCCESS); - -statechkfail_bug: - cmn_err(CE_NOTE, "blk@%s: unexpected otherend " - "state change to %d!, when status is %d", - ddi_get_name_addr(ring->ri_dip), oestate, - ring->ri_if_status); - -statechkfail_nop: - return (DDI_FAILURE); -} - - -/* - * blk_start_connect() - * Kick-off connect process - * If ri_fe_status == BLK_FE_READY and ri_be_status == BLK_BE_READY - * the ri_if_status will be changed to BLK_IF_CONNECTED on success, - * otherwise, ri_if_status will not be changed - */ -static int -blk_start_connect(blk_ring_t ring) -{ - xenbus_transaction_t xbt; - dev_info_t *dip; - char *barrier; - char *xsnode; - uint_t len; - int e; - - - dip = ring->ri_dip; - - /* - * Start connect to frontend only when backend device are ready - * and frontend has moved to XenbusStateInitialised, which means - * ready to connect - */ - ASSERT(ring->ri_fe_status == BLK_FE_READY); - ASSERT(ring->ri_be_status == BLK_BE_READY); - - xsnode = xvdi_get_xsname(dip); - if (xsnode == NULL) { - goto startconnectfail_get_xsname; - } - - ring->ri_fe = xvdi_get_oeid(dip); - if (ring->ri_fe == (domid_t)-1) { - goto startconnectfail_get_oeid; - } - - e = xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialised); - if (e > 0) { - goto startconnectfail_switch_init; - } - - e = blk_bindto_frontend(ring); - if (e != DDI_SUCCESS) { - goto startconnectfail_bindto_frontend; - } - ring->ri_if_status = BLK_IF_CONNECTED; - - e = ddi_add_intr(dip, 0, NULL, NULL, blk_intr, (caddr_t)ring); - if (e != DDI_SUCCESS) { - goto startconnectfail_add_intr; - } - -trans_retry: - e = xenbus_transaction_start(&xbt); - if (e != 0) { - xvdi_fatal_error(dip, e, "transaction start"); - goto startconnectfail_transaction_start; - } - - /* xentop requires the instance in xenstore */ - e = xenbus_printf(xbt, xsnode, "instance", "%d", - ddi_get_instance(ring->ri_dip)); - if (e != 0) { - cmn_err(CE_WARN, "xdb@%s: failed to write 'instance'", - ddi_get_name_addr(dip)); - xvdi_fatal_error(dip, e, "writing 'instance'"); - (void) xenbus_transaction_end(xbt, 1); - goto startconnectfail_xenbus_printf; - } - - /* If feature-barrier isn't present in xenstore, add it */ - e = xenbus_read(xbt, xsnode, "feature-barrier", (void **)&barrier, - &len); - if (e != 0) { - e = xenbus_printf(xbt, xsnode, "feature-barrier", "%d", 1); - if (e != 0) { - cmn_err(CE_WARN, "xdb@%s: failed to write " - "'feature-barrier'", ddi_get_name_addr(dip)); - xvdi_fatal_error(dip, e, "writing 'feature-barrier'"); - (void) xenbus_transaction_end(xbt, 1); - goto startconnectfail_xenbus_printf; - } - } else { - kmem_free(barrier, len); - } - - e = xvdi_switch_state(dip, xbt, XenbusStateConnected); - if (e > 0) { - xvdi_fatal_error(dip, e, "writing 'state'"); - (void) xenbus_transaction_end(xbt, 1); - goto startconnectfail_switch_connected; - } - - e = xenbus_transaction_end(xbt, 0); - if (e != 0) { - if (e == EAGAIN) { - /* transaction is ended, don't need to abort it */ - goto trans_retry; - } - xvdi_fatal_error(dip, e, "completing transaction"); - goto startconnectfail_transaction_end; - } - - mutex_enter(&ring->ri_state.rs_mutex); - ring->ri_state.rs_ring_up = B_TRUE; - if (ring->ri_state.rs_sleeping_on_ring) { - ring->ri_state.rs_sleeping_on_ring = B_FALSE; - cv_signal(&ring->ri_state.rs_cv); - } - mutex_exit(&ring->ri_state.rs_mutex); - - if (ring->ri_ringup != NULL) { - (*(ring->ri_ringup))(ring->ri_ringup_arg); - } - - return (DDI_SUCCESS); - - -startconnectfail_transaction_end: -startconnectfail_switch_connected: -startconnectfail_xenbus_printf: -startconnectfail_transaction_start: - ddi_remove_intr(dip, 0, NULL); -startconnectfail_add_intr: - blk_unbindfrom_frontend(ring); - ring->ri_fe = (domid_t)-1; -startconnectfail_bindto_frontend: - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed); -startconnectfail_switch_init: -startconnectfail_get_oeid: -startconnectfail_get_xsname: - return (DDI_FAILURE); -} - - -/* - * blk_start_disconnect() - * Kick-off disconnect process. ri_if_status will not be changed - */ -static void -blk_start_disconnect(blk_ring_t ring) -{ - /* Kick-off disconnect process */ - (void) xvdi_switch_state(ring->ri_dip, XBT_NULL, XenbusStateClosing); -} - - -/* - * blk_ring_close() - * Disconnect from frontend and close backend device - * ifstatus will be changed to BLK_DISCONNECTED - * Xenbus state will be changed to XenbusStateClosed - */ -static void -blk_ring_close(blk_ring_t ring) -{ - dev_info_t *dip; - - - /* mutex protect ri_if_status only here */ - ASSERT(MUTEX_HELD(&ring->ri_mutex)); - - dip = ring->ri_dip; - - if (ring->ri_if_status != BLK_IF_CONNECTED) { - return; - } - - ring->ri_if_status = BLK_IF_DISCONNECTED; - mutex_exit(&ring->ri_mutex); - - /* stop accepting I/O request from frontend */ - ddi_remove_intr(dip, 0, NULL); - - blk_unbindfrom_frontend(ring); - ring->ri_fe = (domid_t)-1; - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed); - mutex_enter(&ring->ri_mutex); -} - - -/* - * blk_bindto_frontend() - */ -static int -blk_bindto_frontend(blk_ring_t ring) -{ - evtchn_port_t evtchn; - char protocol[64]; - grant_ref_t gref; - dev_info_t *dip; - char *oename; - int e; - - - dip = ring->ri_dip; - protocol[0] = 0x0; - - /* - * Gather info from frontend - */ - oename = xvdi_get_oename(dip); - if (oename == NULL) { - return (DDI_FAILURE); - } - - e = xenbus_gather(XBT_NULL, oename, "ring-ref", "%lu", &gref, - "event-channel", "%u", &evtchn, NULL); - if (e != 0) { - xvdi_fatal_error(dip, e, - "Getting ring-ref and evtchn from frontend"); - return (DDI_FAILURE); - } - - e = xenbus_gather(XBT_NULL, oename, "protocol", "%63s", - protocol, NULL); - if (e != 0) { - (void) strcpy(protocol, "unspecified, assuming native"); - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE) == 0) { - ring->ri_protocol = BLKIF_PROTOCOL_NATIVE; - ring->ri_nentry = BLKIF_RING_SIZE; - ring->ri_entrysize = sizeof (union blkif_sring_entry); - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { - ring->ri_protocol = BLKIF_PROTOCOL_X86_32; - ring->ri_nentry = BLKIF_X86_32_RING_SIZE; - ring->ri_entrysize = sizeof (union blkif_x86_32_sring_entry); - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { - ring->ri_protocol = BLKIF_PROTOCOL_X86_64; - ring->ri_nentry = BLKIF_X86_64_RING_SIZE; - ring->ri_entrysize = sizeof (union blkif_x86_64_sring_entry); - } else { - xvdi_fatal_error(dip, e, "unknown fe protocol"); - return (DDI_FAILURE); - } - - /* - * map and init ring - */ - e = xvdi_map_ring(dip, ring->ri_nentry, ring->ri_entrysize, gref, - &ring->ri_ring); - if (e != DDI_SUCCESS) { - return (DDI_FAILURE); - } - - /* - * bind event channel - */ - e = xvdi_bind_evtchn(dip, evtchn); - if (e != DDI_SUCCESS) { - xvdi_unmap_ring(ring->ri_ring); - return (DDI_FAILURE); - } - - - return (DDI_SUCCESS); -} - - -/* - * blk_unbindfrom_frontend() - */ -static void -blk_unbindfrom_frontend(blk_ring_t ring) -{ - xvdi_free_evtchn(ring->ri_dip); - xvdi_unmap_ring(ring->ri_ring); -} - - -/* - * blk_intr() - */ -static uint_t -blk_intr(caddr_t arg) -{ - blk_ring_t ring; - - ring = (blk_ring_t)arg; - if (ring->ri_if_status != BLK_IF_CONNECTED) { - return (DDI_INTR_CLAIMED); - } - - (void) (*ring->ri_intr)(ring->ri_intr_arg); - return (DDI_INTR_CLAIMED); -} - - -/* - * blk_ring_request_get() - */ -boolean_t -blk_ring_request_get(blk_ring_t ring, blkif_request_t *req) -{ - blkif_request_t *src; - blk_stats_t *stats; - - - mutex_enter(&ring->ri_mutex); - - if (ring->ri_if_status != BLK_IF_CONNECTED) { - mutex_exit(&ring->ri_mutex); - return (B_FALSE); - } - - src = xvdi_ring_get_request(ring->ri_ring); - if (src == NULL) { - mutex_exit(&ring->ri_mutex); - return (B_FALSE); - } - - switch (ring->ri_protocol) { - case BLKIF_PROTOCOL_NATIVE: - bcopy(src, req, sizeof (*req)); - break; - case BLKIF_PROTOCOL_X86_32: - blk_ring_request_32(req, (blkif_x86_32_request_t *)src); - break; - case BLKIF_PROTOCOL_X86_64: - blk_ring_request_64(req, (blkif_x86_64_request_t *)src); - break; - default: - cmn_err(CE_WARN, "blkif@%s: unrecognised protocol: %d", - ddi_get_name_addr(ring->ri_dip), - ring->ri_protocol); - } - mutex_exit(&ring->ri_mutex); - - stats = &ring->ri_stats; - switch (req->operation) { - case BLKIF_OP_READ: - stats->bs_req_reads++; - break; - case BLKIF_OP_WRITE: - stats->bs_req_writes++; - break; - case BLKIF_OP_WRITE_BARRIER: - stats->bs_req_barriers++; - break; - case BLKIF_OP_FLUSH_DISKCACHE: - stats->bs_req_flushes++; - break; - } - - return (B_TRUE); -} - - -/* - * blk_ring_request_requeue() - * if a request is requeued, caller will have to poll for request - * later. - */ -void -blk_ring_request_requeue(blk_ring_t ring) -{ - mutex_enter(&ring->ri_mutex); - - if (ring->ri_if_status != BLK_IF_CONNECTED) { - mutex_exit(&ring->ri_mutex); - return; - } - - ring->ri_ring->xr_sring.br.req_cons--; - - mutex_exit(&ring->ri_mutex); -} - - -/* - * blk_ring_response_put() - */ -void -blk_ring_response_put(blk_ring_t ring, blkif_response_t *src) -{ - blkif_response_t *rsp; - int e; - - - mutex_enter(&ring->ri_mutex); - - if (ring->ri_if_status != BLK_IF_CONNECTED) { - mutex_exit(&ring->ri_mutex); - return; - } - - rsp = xvdi_ring_get_response(ring->ri_ring); - ASSERT(rsp); - - switch (ring->ri_protocol) { - case BLKIF_PROTOCOL_NATIVE: - bcopy(src, rsp, sizeof (*rsp)); - break; - case BLKIF_PROTOCOL_X86_32: - blk_ring_response_32((blkif_x86_32_response_t *)rsp, src); - break; - case BLKIF_PROTOCOL_X86_64: - blk_ring_response_64((blkif_x86_64_response_t *)rsp, src); - break; - default: - cmn_err(CE_WARN, "blk@%s: unrecognised protocol: %d", - ddi_get_name_addr(ring->ri_dip), - ring->ri_protocol); - } - - e = xvdi_ring_push_response(ring->ri_ring); - if (e != 0) { - xvdi_notify_oe(ring->ri_dip); - } - - mutex_exit(&ring->ri_mutex); -} - - -/* - * blk_ring_request_32() - */ -static void -blk_ring_request_32(blkif_request_t *dst, blkif_x86_32_request_t *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->sector_number = src->sector_number; - if (n > src->nr_segments) - n = src->nr_segments; - for (i = 0; i < n; i++) - dst->seg[i] = src->seg[i]; -} - - -/* - * blk_ring_request_64() - */ -static void -blk_ring_request_64(blkif_request_t *dst, blkif_x86_64_request_t *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->sector_number = src->sector_number; - if (n > src->nr_segments) - n = src->nr_segments; - for (i = 0; i < n; i++) - dst->seg[i] = src->seg[i]; -} - - -/* - * blk_ring_response_32() - */ -static void -blk_ring_response_32(blkif_x86_32_response_t *dst, blkif_response_t *src) -{ - dst->id = src->id; - dst->operation = src->operation; - dst->status = src->status; -} - - -/* - * blk_ring_response_64() - */ -static void -blk_ring_response_64(blkif_x86_64_response_t *dst, blkif_response_t *src) -{ - dst->id = src->id; - dst->operation = src->operation; - dst->status = src->status; -} - - -/* - * blk_ring_request_dump() - */ -void -blk_ring_request_dump(blkif_request_t *req) -{ - int i; - - /* - * Exploit the public interface definitions for BLKIF_OP_READ - * etc.. - */ - char *op_name[] = { "read", "write", "barrier", "flush" }; - - cmn_err(CE_NOTE, " op=%s", op_name[req->operation]); - cmn_err(CE_NOTE, " num of segments=%d", req->nr_segments); - cmn_err(CE_NOTE, " handle=%d", req->handle); - cmn_err(CE_NOTE, " id=0x%llx", (unsigned long long)req->id); - cmn_err(CE_NOTE, " start sector=%llu", - (unsigned long long)req->sector_number); - for (i = 0; i < req->nr_segments; i++) { - cmn_err(CE_NOTE, " gref=%d, first sec=%d," - "last sec=%d", req->seg[i].gref, req->seg[i].first_sect, - req->seg[i].last_sect); - } -} - - -/* - * blk_ring_response_dump() - */ -void -blk_ring_response_dump(blkif_response_t *resp) -{ - /* - * Exploit the public interface definitions for BLKIF_OP_READ - * etc.. - */ - char *op_name[] = { "read", "write", "barrier", "flush" }; - - cmn_err(CE_NOTE, " op=%d:%s", resp->operation, - op_name[resp->operation]); - cmn_err(CE_NOTE, " op=%d", resp->operation); - cmn_err(CE_NOTE, " status=%d", resp->status); -} diff --git a/usr/src/uts/common/xen/io/blk_common.h b/usr/src/uts/common/xen/io/blk_common.h deleted file mode 100644 index 8b22ec1826..0000000000 --- a/usr/src/uts/common/xen/io/blk_common.h +++ /dev/null @@ -1,70 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_BLK_COMMON_H -#define _SYS_BLK_COMMON_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - - -typedef uint_t (*blk_intr_t)(caddr_t arg); -typedef void (*blk_ring_cb_t)(caddr_t arg); - -typedef struct blk_ringinit_args_s { - dev_info_t *ar_dip; - - /* callbacks */ - blk_intr_t ar_intr; - caddr_t ar_intr_arg; - blk_ring_cb_t ar_ringup; - caddr_t ar_ringup_arg; - blk_ring_cb_t ar_ringdown; - caddr_t ar_ringdown_arg; -} blk_ringinit_args_t; - -typedef struct blk_ring_s *blk_ring_t; - -int blk_ring_init(blk_ringinit_args_t *args, blk_ring_t *ring); -void blk_ring_fini(blk_ring_t *ring); - -boolean_t blk_ring_request_get(blk_ring_t ring, blkif_request_t *req); -void blk_ring_request_requeue(blk_ring_t ring); -void blk_ring_request_dump(blkif_request_t *req); - -void blk_ring_response_put(blk_ring_t ring, blkif_response_t *resp); -void blk_ring_response_dump(blkif_response_t *req); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_BLK_COMMON_H */ diff --git a/usr/src/uts/common/xen/io/blkif_impl.h b/usr/src/uts/common/xen/io/blkif_impl.h deleted file mode 100644 index 060688309e..0000000000 --- a/usr/src/uts/common/xen/io/blkif_impl.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#ifndef __XEN_BLKIF_H__ -#define __XEN_BLKIF_H__ - -#include -#include -#include - -/* Not a real protocol. Used to generate ring structs which contain - * the elements common to all protocols only. This way we get a - * compiler-checkable way to use common struct elements, so we can - * avoid using switch(protocol) in a number of places. */ - -/* i386 protocol version */ - -#pragma pack(4) - -struct blkif_x86_32_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ - blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; -struct blkif_x86_32_response { - uint64_t id; /* copied from request */ - uint8_t operation; /* copied from request */ - int16_t status; /* BLKIF_RSP_??? */ -}; -typedef struct blkif_x86_32_request blkif_x86_32_request_t; -typedef struct blkif_x86_32_response blkif_x86_32_response_t; - -#pragma pack() - -/* x86_64 protocol version */ -struct blkif_x86_64_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ -#if defined(__GNUC__) - uint64_t __attribute__((__aligned__(8))) id; -#else - uint8_t pad[4]; - uint64_t id; -#endif - blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; -struct blkif_x86_64_response { -#if defined(__GNUC__) - uint64_t __attribute__((__aligned__(8))) id; -#else - uint64_t id; -#endif - uint8_t operation; /* copied from request */ - int16_t status; /* BLKIF_RSP_??? */ -}; -typedef struct blkif_x86_64_request blkif_x86_64_request_t; -typedef struct blkif_x86_64_response blkif_x86_64_response_t; - -DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response); -DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response); - -enum blkif_protocol { - BLKIF_PROTOCOL_NATIVE = 1, - BLKIF_PROTOCOL_X86_32 = 2, - BLKIF_PROTOCOL_X86_64 = 3, -}; - -#define BLKIF_RING_SIZE \ - __RING_SIZE((blkif_sring_t *)NULL, PAGESIZE) -#define BLKIF_X86_32_RING_SIZE \ - __RING_SIZE((blkif_x86_32_sring_t *)NULL, PAGESIZE) -#define BLKIF_X86_64_RING_SIZE \ - __RING_SIZE((blkif_x86_64_sring_t *)NULL, PAGESIZE) - -#endif /* __XEN_BLKIF_H__ */ diff --git a/usr/src/uts/common/xen/io/evtchn_dev.c b/usr/src/uts/common/xen/io/evtchn_dev.c deleted file mode 100644 index 3fec61b229..0000000000 --- a/usr/src/uts/common/xen/io/evtchn_dev.c +++ /dev/null @@ -1,740 +0,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. - */ - - -/* - * evtchn.c - * - * Driver for receiving and demuxing event-channel signals. - * - * Copyright (c) 2004-2005, K A Fraser - * Multi-process extensions Copyright (c) 2004, Steven Smith - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Some handy macros */ -#define EVTCHNDRV_MINOR2INST(minor) ((int)(minor)) -#define EVTCHNDRV_DEFAULT_NCLONES 256 -#define EVTCHNDRV_INST2SOFTS(inst) \ - (ddi_get_soft_state(evtchndrv_statep, (inst))) - -/* Soft state data structure for evtchn driver */ -struct evtsoftdata { - dev_info_t *dip; - /* Notification ring, accessed via /dev/xen/evtchn. */ -#define EVTCHN_RING_SIZE (PAGESIZE / sizeof (evtchn_port_t)) -#define EVTCHN_RING_MASK(_i) ((_i) & (EVTCHN_RING_SIZE - 1)) - evtchn_port_t *ring; - unsigned int ring_cons, ring_prod, ring_overflow; - - kcondvar_t evtchn_wait; /* Processes wait on this when ring is empty. */ - kmutex_t evtchn_lock; - struct pollhead evtchn_pollhead; - - pid_t pid; /* last pid to bind to this event channel. */ - processorid_t cpu; /* cpu thread/evtchn is bound to */ -}; - -static void *evtchndrv_statep; -int evtchndrv_nclones = EVTCHNDRV_DEFAULT_NCLONES; -static int *evtchndrv_clone_tab; -static dev_info_t *evtchndrv_dip; -static kmutex_t evtchndrv_clone_tab_mutex; - -static int evtchndrv_detach(dev_info_t *, ddi_detach_cmd_t); - -/* Who's bound to each port? */ -static struct evtsoftdata *port_user[NR_EVENT_CHANNELS]; -static kmutex_t port_user_lock; - -void -evtchn_device_upcall() -{ - struct evtsoftdata *ep; - int port; - - /* - * This is quite gross, we had to leave the evtchn that led to this - * invocation in a per-cpu mailbox, retrieve it now. - * We do this because the interface doesn't offer us a way to pass - * a dynamic argument up through the generic interrupt service layer. - * The mailbox is safe since we either run with interrupts disabled or - * non-preemptable till we reach here. - */ - port = CPU->cpu_m.mcpu_ec_mbox; - ASSERT(port != 0); - CPU->cpu_m.mcpu_ec_mbox = 0; - ec_clear_evtchn(port); - mutex_enter(&port_user_lock); - - if ((ep = port_user[port]) != NULL) { - mutex_enter(&ep->evtchn_lock); - if ((ep->ring_prod - ep->ring_cons) < EVTCHN_RING_SIZE) { - ep->ring[EVTCHN_RING_MASK(ep->ring_prod)] = port; - /* - * Wake up reader when ring goes non-empty - */ - if (ep->ring_cons == ep->ring_prod++) { - cv_signal(&ep->evtchn_wait); - mutex_exit(&ep->evtchn_lock); - pollwakeup(&ep->evtchn_pollhead, - POLLIN | POLLRDNORM); - goto done; - } - } else { - ep->ring_overflow = 1; - } - mutex_exit(&ep->evtchn_lock); - } - -done: - mutex_exit(&port_user_lock); -} - -/* ARGSUSED */ -static int -evtchndrv_read(dev_t dev, struct uio *uio, cred_t *cr) -{ - int rc = 0; - ssize_t count; - unsigned int c, p, bytes1 = 0, bytes2 = 0; - struct evtsoftdata *ep; - minor_t minor = getminor(dev); - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - - /* Whole number of ports. */ - count = uio->uio_resid; - count &= ~(sizeof (evtchn_port_t) - 1); - - if (count == 0) - return (0); - - if (count > PAGESIZE) - count = PAGESIZE; - - mutex_enter(&ep->evtchn_lock); - for (;;) { - if (ep->ring_overflow) { - rc = EFBIG; - goto done; - } - - if ((c = ep->ring_cons) != (p = ep->ring_prod)) - break; - - if (uio->uio_fmode & O_NONBLOCK) { - rc = EAGAIN; - goto done; - } - - if (cv_wait_sig(&ep->evtchn_wait, &ep->evtchn_lock) == 0) { - rc = EINTR; - goto done; - } - } - - /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ - if (((c ^ p) & EVTCHN_RING_SIZE) != 0) { - bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * - sizeof (evtchn_port_t); - bytes2 = EVTCHN_RING_MASK(p) * sizeof (evtchn_port_t); - } else { - bytes1 = (p - c) * sizeof (evtchn_port_t); - bytes2 = 0; - } - - /* Truncate chunks according to caller's maximum byte count. */ - if (bytes1 > count) { - bytes1 = count; - bytes2 = 0; - } else if ((bytes1 + bytes2) > count) { - bytes2 = count - bytes1; - } - - if (uiomove(&ep->ring[EVTCHN_RING_MASK(c)], bytes1, UIO_READ, uio) || - ((bytes2 != 0) && uiomove(&ep->ring[0], bytes2, UIO_READ, uio))) { - rc = EFAULT; - goto done; - } - - ep->ring_cons += (bytes1 + bytes2) / sizeof (evtchn_port_t); -done: - mutex_exit(&ep->evtchn_lock); - return (rc); -} - -/* ARGSUSED */ -static int -evtchndrv_write(dev_t dev, struct uio *uio, cred_t *cr) -{ - int rc, i; - ssize_t count; - evtchn_port_t *kbuf; - struct evtsoftdata *ep; - ulong_t flags; - minor_t minor = getminor(dev); - evtchn_port_t sbuf[32]; - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - - - /* Whole number of ports. */ - count = uio->uio_resid; - count &= ~(sizeof (evtchn_port_t) - 1); - - if (count == 0) - return (0); - - if (count > PAGESIZE) - count = PAGESIZE; - - if (count <= sizeof (sbuf)) - kbuf = sbuf; - else - kbuf = kmem_alloc(PAGESIZE, KM_SLEEP); - if ((rc = uiomove(kbuf, count, UIO_WRITE, uio)) != 0) - goto out; - - mutex_enter(&port_user_lock); - for (i = 0; i < (count / sizeof (evtchn_port_t)); i++) - if ((kbuf[i] < NR_EVENT_CHANNELS) && - (port_user[kbuf[i]] == ep)) { - flags = intr_clear(); - ec_unmask_evtchn(kbuf[i]); - intr_restore(flags); - } - mutex_exit(&port_user_lock); - -out: - if (kbuf != sbuf) - kmem_free(kbuf, PAGESIZE); - return (rc); -} - -static void -evtchn_bind_to_user(struct evtsoftdata *u, int port) -{ - ulong_t flags; - - /* - * save away the PID of the last process to bind to this event channel. - * Useful for debugging. - */ - u->pid = ddi_get_pid(); - - mutex_enter(&port_user_lock); - ASSERT(port_user[port] == NULL); - port_user[port] = u; - ec_irq_add_evtchn(ec_dev_irq, port); - flags = intr_clear(); - ec_unmask_evtchn(port); - intr_restore(flags); - mutex_exit(&port_user_lock); -} - -static void -evtchndrv_close_evtchn(int port) -{ - struct evtsoftdata *ep; - - ASSERT(MUTEX_HELD(&port_user_lock)); - ep = port_user[port]; - ASSERT(ep != NULL); - (void) ec_mask_evtchn(port); - /* - * It is possible the event is in transit to us. - * If it is already in the ring buffer, then a client may - * get a spurious event notification on the next read of - * of the evtchn device. Clients will need to be able to - * handle getting a spurious event notification. - */ - port_user[port] = NULL; - /* - * The event is masked and should stay so, clean it up. - */ - ec_irq_rm_evtchn(ec_dev_irq, port); -} - -/* ARGSUSED */ -static int -evtchndrv_ioctl(dev_t dev, int cmd, intptr_t data, int flag, cred_t *cr, - int *rvalp) -{ - int err = 0; - struct evtsoftdata *ep; - minor_t minor = getminor(dev); - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - - *rvalp = 0; - - switch (cmd) { - case IOCTL_EVTCHN_BIND_VIRQ: { - struct ioctl_evtchn_bind_virq bind; - - if (copyin((void *)data, &bind, sizeof (bind))) { - err = EFAULT; - break; - } - - if ((err = xen_bind_virq(bind.virq, 0, rvalp)) != 0) - break; - - evtchn_bind_to_user(ep, *rvalp); - break; - } - - case IOCTL_EVTCHN_BIND_INTERDOMAIN: { - struct ioctl_evtchn_bind_interdomain bind; - - if (copyin((void *)data, &bind, sizeof (bind))) { - err = EFAULT; - break; - } - - if ((err = xen_bind_interdomain(bind.remote_domain, - bind.remote_port, rvalp)) != 0) - break; - - ec_bind_vcpu(*rvalp, 0); - evtchn_bind_to_user(ep, *rvalp); - break; - } - - case IOCTL_EVTCHN_BIND_UNBOUND_PORT: { - struct ioctl_evtchn_bind_unbound_port bind; - - if (copyin((void *)data, &bind, sizeof (bind))) { - err = EFAULT; - break; - } - - if ((err = xen_alloc_unbound_evtchn(bind.remote_domain, - rvalp)) != 0) - break; - - evtchn_bind_to_user(ep, *rvalp); - break; - } - - case IOCTL_EVTCHN_UNBIND: { - struct ioctl_evtchn_unbind unbind; - - if (copyin((void *)data, &unbind, sizeof (unbind))) { - err = EFAULT; - break; - } - - if (unbind.port >= NR_EVENT_CHANNELS) { - err = EFAULT; - break; - } - - mutex_enter(&port_user_lock); - - if (port_user[unbind.port] != ep) { - mutex_exit(&port_user_lock); - err = ENOTCONN; - break; - } - - evtchndrv_close_evtchn(unbind.port); - mutex_exit(&port_user_lock); - break; - } - - case IOCTL_EVTCHN_NOTIFY: { - struct ioctl_evtchn_notify notify; - - if (copyin((void *)data, ¬ify, sizeof (notify))) { - err = EFAULT; - break; - } - - if (notify.port >= NR_EVENT_CHANNELS) { - err = EINVAL; - } else if (port_user[notify.port] != ep) { - err = ENOTCONN; - } else { - ec_notify_via_evtchn(notify.port); - } - break; - } - - default: - err = ENOSYS; - } - - return (err); -} - -static int -evtchndrv_poll(dev_t dev, short ev, int anyyet, short *revp, pollhead_t **phpp) -{ - struct evtsoftdata *ep; - minor_t minor = getminor(dev); - short mask = 0; - - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - *phpp = NULL; - - if (ev & POLLOUT) - mask |= POLLOUT; - if (ep->ring_overflow) - mask |= POLLERR; - if (ev & (POLLIN | POLLRDNORM)) { - mutex_enter(&ep->evtchn_lock); - if (ep->ring_cons != ep->ring_prod) - mask |= (POLLIN | POLLRDNORM) & ev; - else - if (mask == 0 && !anyyet) - *phpp = &ep->evtchn_pollhead; - mutex_exit(&ep->evtchn_lock); - } - *revp = mask; - return (0); -} - - -/* ARGSUSED */ -static int -evtchndrv_open(dev_t *devp, int flag, int otyp, cred_t *credp) -{ - struct evtsoftdata *ep; - minor_t minor = getminor(*devp); - - if (otyp == OTYP_BLK) - return (ENXIO); - - /* - * only allow open on minor = 0 - the clone device - */ - if (minor != 0) - return (ENXIO); - - /* - * find a free slot and grab it - */ - mutex_enter(&evtchndrv_clone_tab_mutex); - for (minor = 1; minor < evtchndrv_nclones; minor++) { - if (evtchndrv_clone_tab[minor] == 0) { - evtchndrv_clone_tab[minor] = 1; - break; - } - } - mutex_exit(&evtchndrv_clone_tab_mutex); - if (minor == evtchndrv_nclones) - return (EAGAIN); - - /* Allocate softstate structure */ - if (ddi_soft_state_zalloc(evtchndrv_statep, - EVTCHNDRV_MINOR2INST(minor)) != DDI_SUCCESS) { - mutex_enter(&evtchndrv_clone_tab_mutex); - evtchndrv_clone_tab[minor] = 0; - mutex_exit(&evtchndrv_clone_tab_mutex); - return (EAGAIN); - } - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - - /* ... and init it */ - ep->dip = evtchndrv_dip; - - cv_init(&ep->evtchn_wait, NULL, CV_DEFAULT, NULL); - mutex_init(&ep->evtchn_lock, NULL, MUTEX_DEFAULT, NULL); - - ep->ring = kmem_alloc(PAGESIZE, KM_SLEEP); - - /* clone driver */ - *devp = makedevice(getmajor(*devp), minor); - - return (0); -} - -/* ARGSUSED */ -static int -evtchndrv_close(dev_t dev, int flag, int otyp, struct cred *credp) -{ - struct evtsoftdata *ep; - minor_t minor = getminor(dev); - int i; - - ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor)); - if (ep == NULL) - return (ENXIO); - - mutex_enter(&port_user_lock); - - - for (i = 0; i < NR_EVENT_CHANNELS; i++) { - if (port_user[i] != ep) - continue; - - evtchndrv_close_evtchn(i); - } - - mutex_exit(&port_user_lock); - - kmem_free(ep->ring, PAGESIZE); - ddi_soft_state_free(evtchndrv_statep, EVTCHNDRV_MINOR2INST(minor)); - - /* - * free clone tab slot - */ - mutex_enter(&evtchndrv_clone_tab_mutex); - evtchndrv_clone_tab[minor] = 0; - mutex_exit(&evtchndrv_clone_tab_mutex); - - return (0); -} - -/* ARGSUSED */ -static int -evtchndrv_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) -{ - dev_t dev = (dev_t)arg; - minor_t minor = getminor(dev); - int retval; - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - if (minor != 0 || evtchndrv_dip == NULL) { - *result = NULL; - retval = DDI_FAILURE; - } else { - *result = (void *)evtchndrv_dip; - retval = DDI_SUCCESS; - } - break; - case DDI_INFO_DEVT2INSTANCE: - *result = NULL; - retval = DDI_SUCCESS; - break; - default: - retval = DDI_FAILURE; - } - return (retval); -} - - -static int -evtchndrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int error; - int unit = ddi_get_instance(dip); - - - switch (cmd) { - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - cmn_err(CE_WARN, "evtchn_attach: unknown cmd 0x%x\n", cmd); - return (DDI_FAILURE); - } - - /* DDI_ATTACH */ - - /* - * only one instance - but we clone using the open routine - */ - if (ddi_get_instance(dip) > 0) - return (DDI_FAILURE); - - mutex_init(&evtchndrv_clone_tab_mutex, NULL, MUTEX_DRIVER, - NULL); - - error = ddi_create_minor_node(dip, "evtchn", S_IFCHR, unit, - DDI_PSEUDO, 0); - if (error != DDI_SUCCESS) - goto fail; - - /* - * save dip for getinfo - */ - evtchndrv_dip = dip; - ddi_report_dev(dip); - - mutex_init(&port_user_lock, NULL, MUTEX_DRIVER, NULL); - (void) memset(port_user, 0, sizeof (port_user)); - - ec_dev_irq = ec_dev_alloc_irq(); - (void) add_avintr(NULL, IPL_EVTCHN, (avfunc)evtchn_device_upcall, - "evtchn_driver", ec_dev_irq, NULL, NULL, NULL, dip); - - return (DDI_SUCCESS); - -fail: - (void) evtchndrv_detach(dip, DDI_DETACH); - return (error); -} - -/*ARGSUSED*/ -static int -evtchndrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - /* - * Don't allow detach for now. - */ - return (DDI_FAILURE); -} - -/* Solaris driver framework */ - -static struct cb_ops evtchndrv_cb_ops = { - evtchndrv_open, /* cb_open */ - evtchndrv_close, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - evtchndrv_read, /* cb_read */ - evtchndrv_write, /* cb_write */ - evtchndrv_ioctl, /* cb_ioctl */ - nodev, /* cb_devmap */ - nodev, /* cb_mmap */ - nodev, /* cb_segmap */ - evtchndrv_poll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - 0, /* cb_stream */ - D_NEW | D_MP | D_64BIT /* cb_flag */ -}; - -static struct dev_ops evtchndrv_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - evtchndrv_info, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - evtchndrv_attach, /* devo_attach */ - evtchndrv_detach, /* devo_detach */ - nodev, /* devo_reset */ - &evtchndrv_cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "Evtchn driver", /* Name of the module. */ - &evtchndrv_dev_ops /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - int err; - - err = ddi_soft_state_init(&evtchndrv_statep, - sizeof (struct evtsoftdata), 1); - if (err) - return (err); - - err = mod_install(&modlinkage); - if (err) - ddi_soft_state_fini(&evtchndrv_statep); - else - evtchndrv_clone_tab = kmem_zalloc( - sizeof (int) * evtchndrv_nclones, KM_SLEEP); - return (err); -} - -int -_fini(void) -{ - int e; - - e = mod_remove(&modlinkage); - if (e) - return (e); - - ddi_soft_state_fini(&evtchndrv_statep); - - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/xen/io/xdb.c b/usr/src/uts/common/xen/io/xdb.c deleted file mode 100644 index 4a4ef5ae1f..0000000000 --- a/usr/src/uts/common/xen/io/xdb.c +++ /dev/null @@ -1,1977 +0,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. - */ - -/* - * Note: This is the backend part of the split PV disk driver. This driver - * is not a nexus driver, nor is it a leaf driver(block/char/stream driver). - * Currently, it does not create any minor node. So, although, it runs in - * backend domain, it will not be used directly from within dom0. - * It simply gets block I/O requests issued by frontend from a shared page - * (blkif ring buffer - defined by Xen) between backend and frontend domain, - * generates a buf, and push it down to underlying disk target driver via - * ldi interface. When buf is done, this driver will generate a response - * and put it into ring buffer to inform frontend of the status of the I/O - * request issued by it. When a new virtual device entry is added in xenstore, - * there will be an watch event sent from Xen to xvdi framework, who will, - * in turn, create the devinfo node and try to attach this driver - * (see xvdi_create_dev). When frontend peer changes its state to - * XenbusStateClose, an event will also be sent from Xen to xvdi framework, - * who will detach and remove this devinfo node (see i_xvdi_oestate_handler). - * I/O requests get from ring buffer and event coming from xenstore cannot be - * trusted. We verify them in xdb_get_buf() and xdb_check_state_transition(). - * - * Virtual device configuration is read/written from/to the database via - * xenbus_* interfaces. Driver also use xvdi_* to interact with hypervisor. - * There is an on-going effort to make xvdi_* cover all xenbus_*. - */ - -#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 - -static xdb_t *xdb_statep; -static int xdb_debug = 0; - -static void xdb_close(dev_info_t *); -static int xdb_push_response(xdb_t *, uint64_t, uint8_t, uint16_t); -static int xdb_get_request(xdb_t *, blkif_request_t *); -static void blkif_get_x86_32_req(blkif_request_t *, blkif_x86_32_request_t *); -static void blkif_get_x86_64_req(blkif_request_t *, blkif_x86_64_request_t *); -static int xdb_biodone(buf_t *); - - -#ifdef DEBUG -/* - * debug aid functions - */ - -static void -logva(xdb_t *vdp, uint64_t va) -{ - uint64_t *page_addrs; - int i; - - page_addrs = vdp->page_addrs; - for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { - if (page_addrs[i] == va) - debug_enter("VA remapping found!"); - } - - for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { - if (page_addrs[i] == 0) { - page_addrs[i] = va; - break; - } - } - ASSERT(i < XDB_MAX_IO_PAGES(vdp)); -} - -static void -unlogva(xdb_t *vdp, uint64_t va) -{ - uint64_t *page_addrs; - int i; - - page_addrs = vdp->page_addrs; - for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { - if (page_addrs[i] == va) { - page_addrs[i] = 0; - break; - } - } - ASSERT(i < XDB_MAX_IO_PAGES(vdp)); -} - -static void -xdb_dump_request_oe(blkif_request_t *req) -{ - int i; - - /* - * Exploit the public interface definitions for BLKIF_OP_READ - * etc.. - */ - char *op_name[] = { "read", "write", "barrier", "flush" }; - - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "op=%s", op_name[req->operation])); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "num of segments=%d", - req->nr_segments)); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "handle=%d", req->handle)); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "id=%llu", - (unsigned long long)req->id)); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "start sector=%llu", - (unsigned long long)req->sector_number)); - for (i = 0; i < req->nr_segments; i++) { - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "gref=%d, first sec=%d," - "last sec=%d", req->seg[i].gref, req->seg[i].first_sect, - req->seg[i].last_sect)); - } -} -#endif /* DEBUG */ - -/* - * Statistics. - */ -static char *xdb_stats[] = { - "rd_reqs", - "wr_reqs", - "br_reqs", - "fl_reqs", - "oo_reqs" -}; - -static int -xdb_kstat_update(kstat_t *ksp, int flag) -{ - xdb_t *vdp; - kstat_named_t *knp; - - if (flag != KSTAT_READ) - return (EACCES); - - vdp = ksp->ks_private; - knp = ksp->ks_data; - - /* - * Assignment order should match that of the names in - * xdb_stats. - */ - (knp++)->value.ui64 = vdp->xs_stat_req_reads; - (knp++)->value.ui64 = vdp->xs_stat_req_writes; - (knp++)->value.ui64 = vdp->xs_stat_req_barriers; - (knp++)->value.ui64 = vdp->xs_stat_req_flushes; - (knp++)->value.ui64 = 0; /* oo_req */ - - return (0); -} - -static boolean_t -xdb_kstat_init(xdb_t *vdp) -{ - int nstat = sizeof (xdb_stats) / sizeof (xdb_stats[0]); - char **cp = xdb_stats; - kstat_named_t *knp; - - if ((vdp->xs_kstats = kstat_create("xdb", - ddi_get_instance(vdp->xs_dip), - "req_statistics", "block", KSTAT_TYPE_NAMED, - nstat, 0)) == NULL) - return (B_FALSE); - - vdp->xs_kstats->ks_private = vdp; - vdp->xs_kstats->ks_update = xdb_kstat_update; - - knp = vdp->xs_kstats->ks_data; - while (nstat > 0) { - kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); - knp++; - cp++; - nstat--; - } - - kstat_install(vdp->xs_kstats); - - return (B_TRUE); -} - -static char * -i_pathname(dev_info_t *dip) -{ - char *path, *rv; - - path = kmem_alloc(MAXPATHLEN, KM_SLEEP); - (void) ddi_pathname(dip, path); - rv = strdup(path); - kmem_free(path, MAXPATHLEN); - - return (rv); -} - -static buf_t * -xdb_get_buf(xdb_t *vdp, blkif_request_t *req, xdb_request_t *xreq) -{ - buf_t *bp; - uint8_t segs, curseg; - int sectors; - int i, err; - gnttab_map_grant_ref_t mapops[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - ddi_acc_handle_t acchdl; - - acchdl = vdp->xs_ring_hdl; - bp = XDB_XREQ2BP(xreq); - curseg = xreq->xr_curseg; - /* init a new xdb request */ - if (req != NULL) { - ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); - boolean_t pagemapok = B_TRUE; - uint8_t op = ddi_get8(acchdl, &req->operation); - - xreq->xr_vdp = vdp; - xreq->xr_op = op; - xreq->xr_id = ddi_get64(acchdl, &req->id); - segs = xreq->xr_buf_pages = ddi_get8(acchdl, &req->nr_segments); - if (segs == 0) { - if (op != BLKIF_OP_FLUSH_DISKCACHE) - cmn_err(CE_WARN, "!non-BLKIF_OP_FLUSH_DISKCACHE" - " is seen from domain %d with zero " - "length data buffer!", vdp->xs_peer); - bioinit(bp); - bp->b_bcount = 0; - bp->b_lblkno = 0; - bp->b_un.b_addr = NULL; - return (bp); - } else if (op == BLKIF_OP_FLUSH_DISKCACHE) { - cmn_err(CE_WARN, "!BLKIF_OP_FLUSH_DISKCACHE" - " is seen from domain %d with non-zero " - "length data buffer!", vdp->xs_peer); - } - - /* - * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST - * according to the definition of blk interface by Xen - * we do sanity check here - */ - if (segs > BLKIF_MAX_SEGMENTS_PER_REQUEST) - segs = xreq->xr_buf_pages = - BLKIF_MAX_SEGMENTS_PER_REQUEST; - - for (i = 0; i < segs; i++) { - uint8_t fs, ls; - - mapops[i].host_addr = - (uint64_t)(uintptr_t)XDB_IOPAGE_VA( - vdp->xs_iopage_va, xreq->xr_idx, i); - mapops[i].dom = vdp->xs_peer; - mapops[i].ref = ddi_get32(acchdl, &req->seg[i].gref); - mapops[i].flags = GNTMAP_host_map; - if (op != BLKIF_OP_READ) - mapops[i].flags |= GNTMAP_readonly; - - fs = ddi_get8(acchdl, &req->seg[i].first_sect); - ls = ddi_get8(acchdl, &req->seg[i].last_sect); - - /* - * first_sect should be no bigger than last_sect and - * both of them should be no bigger than - * XB_LAST_SECTOR_IN_SEG according to definition - * of blk interface by Xen, so sanity check again - */ - if (fs > XB_LAST_SECTOR_IN_SEG) - fs = XB_LAST_SECTOR_IN_SEG; - if (ls > XB_LAST_SECTOR_IN_SEG) - ls = XB_LAST_SECTOR_IN_SEG; - if (fs > ls) - fs = ls; - - xreq->xr_segs[i].fs = fs; - xreq->xr_segs[i].ls = ls; - } - - /* map in io pages */ - err = xen_map_gref(GNTTABOP_map_grant_ref, mapops, i, B_FALSE); - if (err != 0) - return (NULL); - for (i = 0; i < segs; i++) { - /* - * Although HYPERVISOR_grant_table_op() returned no - * error, mapping of each single page can fail. So, - * we have to do the check here and handle the error - * if needed - */ - if (mapops[i].status != GNTST_okay) { - int j; - for (j = 0; j < i; j++) { -#ifdef DEBUG - unlogva(vdp, mapops[j].host_addr); -#endif - xen_release_pfn( - xreq->xr_plist[j].p_pagenum); - } - pagemapok = B_FALSE; - break; - } - /* record page mapping handle for unmapping later */ - xreq->xr_page_hdls[i] = mapops[i].handle; -#ifdef DEBUG - logva(vdp, mapops[i].host_addr); -#endif - /* - * Pass the MFNs down using the shadow list (xr_pplist) - * - * This is pretty ugly since we have implict knowledge - * of how the rootnex binds buffers. - * The GNTTABOP_map_grant_ref op makes us do some ugly - * stuff since we're not allowed to touch these PTEs - * from the VM. - * - * Obviously, these aren't real page_t's. The rootnex - * only needs p_pagenum. - * Also, don't use btop() here or 32 bit PAE breaks. - */ - xreq->xr_pplist[i] = &xreq->xr_plist[i]; - xreq->xr_plist[i].p_pagenum = - xen_assign_pfn(mapops[i].dev_bus_addr >> PAGESHIFT); - } - - /* - * not all pages mapped in successfully, unmap those mapped-in - * page and return failure - */ - if (!pagemapok) { - gnttab_unmap_grant_ref_t unmapop; - - for (i = 0; i < segs; i++) { - if (mapops[i].status != GNTST_okay) - continue; - unmapop.host_addr = - (uint64_t)(uintptr_t)XDB_IOPAGE_VA( - vdp->xs_iopage_va, xreq->xr_idx, i); - unmapop.dev_bus_addr = (uintptr_t)NULL; - unmapop.handle = mapops[i].handle; - (void) HYPERVISOR_grant_table_op( - GNTTABOP_unmap_grant_ref, &unmapop, 1); - } - - return (NULL); - } - bioinit(bp); - bp->b_lblkno = ddi_get64(acchdl, &req->sector_number); - bp->b_flags = B_BUSY | B_SHADOW | B_PHYS; - bp->b_flags |= (ddi_get8(acchdl, &req->operation) == - BLKIF_OP_READ) ? B_READ : (B_WRITE | B_ASYNC); - } else { - uint64_t blkst; - int isread; - - /* reuse this buf */ - blkst = bp->b_lblkno + bp->b_bcount / DEV_BSIZE; - isread = bp->b_flags & B_READ; - bioreset(bp); - bp->b_lblkno = blkst; - bp->b_flags = B_BUSY | B_SHADOW | B_PHYS; - bp->b_flags |= isread ? B_READ : (B_WRITE | B_ASYNC); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "reuse buf, xreq is %d!!", - xreq->xr_idx)); - } - - /* form a buf */ - bp->b_un.b_addr = XDB_IOPAGE_VA(vdp->xs_iopage_va, xreq->xr_idx, - curseg) + xreq->xr_segs[curseg].fs * DEV_BSIZE; - bp->b_shadow = &xreq->xr_pplist[curseg]; - bp->b_iodone = xdb_biodone; - sectors = 0; - - /* - * Run through the segments. There are XB_NUM_SECTORS_PER_SEG sectors - * per segment. On some OSes (e.g. Linux), there may be empty gaps - * between segments. (i.e. the first segment may end on sector 6 and - * the second segment start on sector 4). - * - * if a segments first sector is not set to 0, and this is not the - * first segment in our buf, end this buf now. - * - * if a segments last sector is not set to XB_LAST_SECTOR_IN_SEG, and - * this is not the last segment in the request, add this segment into - * the buf, then end this buf (updating the pointer to point to the - * next segment next time around). - */ - for (i = curseg; i < xreq->xr_buf_pages; i++) { - if ((xreq->xr_segs[i].fs != 0) && (i != curseg)) { - break; - } - sectors += (xreq->xr_segs[i].ls - xreq->xr_segs[i].fs + 1); - if ((xreq->xr_segs[i].ls != XB_LAST_SECTOR_IN_SEG) && - (i != (xreq->xr_buf_pages - 1))) { - i++; - break; - } - } - xreq->xr_curseg = i; - bp->b_bcount = sectors * DEV_BSIZE; - bp->b_bufsize = bp->b_bcount; - - return (bp); -} - -static xdb_request_t * -xdb_get_req(xdb_t *vdp) -{ - xdb_request_t *req; - int idx; - - ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); - ASSERT(vdp->xs_free_req != -1); - req = &vdp->xs_req[vdp->xs_free_req]; - vdp->xs_free_req = req->xr_next; - idx = req->xr_idx; - bzero(req, sizeof (xdb_request_t)); - req->xr_idx = idx; - return (req); -} - -static void -xdb_free_req(xdb_request_t *req) -{ - xdb_t *vdp = req->xr_vdp; - - ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); - req->xr_next = vdp->xs_free_req; - vdp->xs_free_req = req->xr_idx; -} - -static void -xdb_response(xdb_t *vdp, blkif_request_t *req, boolean_t ok) -{ - ddi_acc_handle_t acchdl = vdp->xs_ring_hdl; - - if (xdb_push_response(vdp, ddi_get64(acchdl, &req->id), - ddi_get8(acchdl, &req->operation), ok)) - xvdi_notify_oe(vdp->xs_dip); -} - -static void -xdb_init_ioreqs(xdb_t *vdp) -{ - int i; - - ASSERT(vdp->xs_nentry); - - if (vdp->xs_req == NULL) - vdp->xs_req = kmem_alloc(vdp->xs_nentry * - sizeof (xdb_request_t), KM_SLEEP); -#ifdef DEBUG - if (vdp->page_addrs == NULL) - vdp->page_addrs = kmem_zalloc(XDB_MAX_IO_PAGES(vdp) * - sizeof (uint64_t), KM_SLEEP); -#endif - for (i = 0; i < vdp->xs_nentry; i++) { - vdp->xs_req[i].xr_idx = i; - vdp->xs_req[i].xr_next = i + 1; - } - vdp->xs_req[vdp->xs_nentry - 1].xr_next = -1; - vdp->xs_free_req = 0; - - /* alloc va in host dom for io page mapping */ - vdp->xs_iopage_va = vmem_xalloc(heap_arena, - XDB_MAX_IO_PAGES(vdp) * PAGESIZE, PAGESIZE, 0, 0, 0, 0, - VM_SLEEP); - for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) - hat_prepare_mapping(kas.a_hat, - vdp->xs_iopage_va + i * PAGESIZE, NULL); -} - -static void -xdb_uninit_ioreqs(xdb_t *vdp) -{ - int i; - - for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) - hat_release_mapping(kas.a_hat, - vdp->xs_iopage_va + i * PAGESIZE); - vmem_xfree(heap_arena, vdp->xs_iopage_va, - XDB_MAX_IO_PAGES(vdp) * PAGESIZE); - if (vdp->xs_req != NULL) { - kmem_free(vdp->xs_req, vdp->xs_nentry * sizeof (xdb_request_t)); - vdp->xs_req = NULL; - } -#ifdef DEBUG - if (vdp->page_addrs != NULL) { - kmem_free(vdp->page_addrs, XDB_MAX_IO_PAGES(vdp) * - sizeof (uint64_t)); - vdp->page_addrs = NULL; - } -#endif -} - -static uint_t -xdb_intr(caddr_t arg) -{ - xdb_t *vdp = (xdb_t *)arg; - dev_info_t *dip = vdp->xs_dip; - blkif_request_t req, *reqp = &req; - xdb_request_t *xreq; - buf_t *bp; - uint8_t op; - int ret = DDI_INTR_UNCLAIMED; - - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - "xdb@%s: I/O request received from dom %d", - ddi_get_name_addr(dip), vdp->xs_peer)); - - mutex_enter(&vdp->xs_iomutex); - - /* shouldn't touch ring buffer if not in connected state */ - if (!vdp->xs_if_connected) { - mutex_exit(&vdp->xs_iomutex); - return (DDI_INTR_UNCLAIMED); - } - ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised); - - /* - * We'll loop till there is no more request in the ring - * We won't stuck in this loop for ever since the size of ring buffer - * is limited, and frontend will stop pushing requests into it when - * the ring buffer is full - */ - - /* req_event will be increased in xvdi_ring_get_request() */ - while (xdb_get_request(vdp, reqp)) { - ret = DDI_INTR_CLAIMED; - - op = ddi_get8(vdp->xs_ring_hdl, &reqp->operation); - if (op == BLKIF_OP_READ || - op == BLKIF_OP_WRITE || - op == BLKIF_OP_WRITE_BARRIER || - op == BLKIF_OP_FLUSH_DISKCACHE) { -#ifdef DEBUG - xdb_dump_request_oe(reqp); -#endif - xreq = xdb_get_req(vdp); - ASSERT(xreq); - switch (op) { - case BLKIF_OP_READ: - vdp->xs_stat_req_reads++; - break; - case BLKIF_OP_WRITE_BARRIER: - vdp->xs_stat_req_barriers++; - /* FALLTHRU */ - case BLKIF_OP_WRITE: - vdp->xs_stat_req_writes++; - break; - case BLKIF_OP_FLUSH_DISKCACHE: - vdp->xs_stat_req_flushes++; - break; - } - - xreq->xr_curseg = 0; /* start from first segment */ - bp = xdb_get_buf(vdp, reqp, xreq); - if (bp == NULL) { - /* failed to form a buf */ - xdb_free_req(xreq); - xdb_response(vdp, reqp, B_FALSE); - continue; - } - bp->av_forw = NULL; - - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - " buf %p, blkno %lld, size %lu, addr %p", - (void *)bp, (longlong_t)bp->b_blkno, - (ulong_t)bp->b_bcount, (void *)bp->b_un.b_addr)); - - /* send bp to underlying blk driver */ - if (vdp->xs_f_iobuf == NULL) { - vdp->xs_f_iobuf = vdp->xs_l_iobuf = bp; - } else { - vdp->xs_l_iobuf->av_forw = bp; - vdp->xs_l_iobuf = bp; - } - } else { - xdb_response(vdp, reqp, B_FALSE); - XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: " - "Unsupported cmd received from dom %d", - ddi_get_name_addr(dip), vdp->xs_peer)); - } - } - /* notify our taskq to push buf to underlying blk driver */ - if (ret == DDI_INTR_CLAIMED) - cv_broadcast(&vdp->xs_iocv); - - mutex_exit(&vdp->xs_iomutex); - - return (ret); -} - -static int -xdb_biodone(buf_t *bp) -{ - int i, err, bioerr; - uint8_t segs; - gnttab_unmap_grant_ref_t unmapops[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - xdb_request_t *xreq = XDB_BP2XREQ(bp); - xdb_t *vdp = xreq->xr_vdp; - buf_t *nbp; - - bioerr = geterror(bp); - if (bioerr) - XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: I/O error %d", - ddi_get_name_addr(vdp->xs_dip), bioerr)); - - /* check if we are done w/ this I/O request */ - if ((bioerr == 0) && (xreq->xr_curseg < xreq->xr_buf_pages)) { - nbp = xdb_get_buf(vdp, NULL, xreq); - if (nbp) { - err = ldi_strategy(vdp->xs_ldi_hdl, nbp); - if (err == 0) { - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - "sent buf to backend ok")); - return (DDI_SUCCESS); - } - bioerr = EIO; - XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: " - "sent buf to backend dev failed, err=%d", - ddi_get_name_addr(vdp->xs_dip), err)); - } else { - bioerr = EIO; - } - } - - /* unmap io pages */ - segs = xreq->xr_buf_pages; - /* - * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST - * according to the definition of blk interface by Xen - */ - ASSERT(segs <= BLKIF_MAX_SEGMENTS_PER_REQUEST); - for (i = 0; i < segs; i++) { - unmapops[i].host_addr = (uint64_t)(uintptr_t)XDB_IOPAGE_VA( - vdp->xs_iopage_va, xreq->xr_idx, i); -#ifdef DEBUG - mutex_enter(&vdp->xs_iomutex); - unlogva(vdp, unmapops[i].host_addr); - mutex_exit(&vdp->xs_iomutex); -#endif - unmapops[i].dev_bus_addr = (uintptr_t)NULL; - unmapops[i].handle = xreq->xr_page_hdls[i]; - } - err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - unmapops, segs); - ASSERT(!err); - - /* - * If we have reached a barrier write or a cache flush , then we must - * flush all our I/Os. - */ - if (xreq->xr_op == BLKIF_OP_WRITE_BARRIER || - xreq->xr_op == BLKIF_OP_FLUSH_DISKCACHE) { - /* - * XXX At this point the write did succeed, so I don't - * believe we should report an error because the flush - * failed. However, this is a debatable point, so - * maybe we need to think more carefully about this. - * For now, just cast to void. - */ - (void) ldi_ioctl(vdp->xs_ldi_hdl, - DKIOCFLUSHWRITECACHE, (intptr_t)NULL, FKIOCTL, kcred, NULL); - } - - mutex_enter(&vdp->xs_iomutex); - - /* send response back to frontend */ - if (vdp->xs_if_connected) { - ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised); - if (xdb_push_response(vdp, xreq->xr_id, xreq->xr_op, bioerr)) - xvdi_notify_oe(vdp->xs_dip); - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - "sent resp back to frontend, id=%llu", - (unsigned long long)xreq->xr_id)); - } - /* free io resources */ - biofini(bp); - xdb_free_req(xreq); - - vdp->xs_ionum--; - if (!vdp->xs_if_connected && (vdp->xs_ionum == 0)) { - /* we're closing, someone is waiting for I/O clean-up */ - cv_signal(&vdp->xs_ionumcv); - } - - mutex_exit(&vdp->xs_iomutex); - - return (DDI_SUCCESS); -} - -static int -xdb_bindto_frontend(xdb_t *vdp) -{ - int err; - char *oename; - grant_ref_t gref; - evtchn_port_t evtchn; - dev_info_t *dip = vdp->xs_dip; - char protocol[64] = ""; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - /* - * Switch to the XenbusStateInitialised state. This let's the - * frontend know that we're about to negotiate a connection. - */ - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialised); - - /* - * Gather info from frontend - */ - oename = xvdi_get_oename(dip); - if (oename == NULL) - return (DDI_FAILURE); - - err = xenbus_gather(XBT_NULL, oename, - XBP_RING_REF, "%lu", &gref, - XBP_EVENT_CHAN, "%u", &evtchn, - NULL); - if (err != 0) { - xvdi_dev_error(dip, err, - "Getting ring-ref and evtchn from frontend"); - return (DDI_FAILURE); - } - - vdp->xs_blk_protocol = BLKIF_PROTOCOL_NATIVE; - vdp->xs_nentry = BLKIF_RING_SIZE; - vdp->xs_entrysize = sizeof (union blkif_sring_entry); - - err = xenbus_gather(XBT_NULL, oename, - XBP_PROTOCOL, "%63s", protocol, NULL); - if (err) - (void) strcpy(protocol, "unspecified, assuming native"); - else { - /* - * We must check for NATIVE first, so that the fast path - * is taken for copying data from the guest to the host. - */ - if (strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE) != 0) { - if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { - vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_32; - vdp->xs_nentry = BLKIF_X86_32_RING_SIZE; - vdp->xs_entrysize = - sizeof (union blkif_x86_32_sring_entry); - } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == - 0) { - vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_64; - vdp->xs_nentry = BLKIF_X86_64_RING_SIZE; - vdp->xs_entrysize = - sizeof (union blkif_x86_64_sring_entry); - } else { - xvdi_fatal_error(dip, err, "unknown protocol"); - return (DDI_FAILURE); - } - } - } -#ifdef DEBUG - cmn_err(CE_NOTE, "!xdb@%s: blkif protocol '%s' ", - ddi_get_name_addr(dip), protocol); -#endif - - /* - * Map and init ring. The ring parameters must match those which - * have been allocated in the front end. - */ - if (xvdi_map_ring(dip, vdp->xs_nentry, vdp->xs_entrysize, - gref, &vdp->xs_ring) != DDI_SUCCESS) - return (DDI_FAILURE); - - /* - * This will be removed after we use shadow I/O ring request since - * we don't need to access the ring itself directly, thus the access - * handle is not needed - */ - vdp->xs_ring_hdl = vdp->xs_ring->xr_acc_hdl; - - /* bind event channel */ - err = xvdi_bind_evtchn(dip, evtchn); - if (err != DDI_SUCCESS) { - xvdi_unmap_ring(vdp->xs_ring); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static void -xdb_unbindfrom_frontend(xdb_t *vdp) -{ - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - xvdi_free_evtchn(vdp->xs_dip); - xvdi_unmap_ring(vdp->xs_ring); -} - -/* - * xdb_params_change() initiates a allows change to the underlying device/file - * that the backend is accessing. It does this by disconnecting from the - * frontend, closing the old device, clearing a bunch of xenbus parameters, - * and switching back to the XenbusStateInitialising state. The frontend - * should notice this transition to the XenbusStateInitialising state and - * should attempt to reconnect to us (the backend). - */ -static void -xdb_params_change(xdb_t *vdp, char *params, boolean_t update_xs) -{ - xenbus_transaction_t xbt; - dev_info_t *dip = vdp->xs_dip; - char *xsname; - int err; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - ASSERT(vdp->xs_params_path != NULL); - - if ((xsname = xvdi_get_xsname(dip)) == NULL) - return; - if (strcmp(vdp->xs_params_path, params) == 0) - return; - - /* - * Close the device we're currently accessing and update the - * path which points to our backend device/file. - */ - xdb_close(dip); - vdp->xs_fe_initialised = B_FALSE; - -trans_retry: - if ((err = xenbus_transaction_start(&xbt)) != 0) { - xvdi_dev_error(dip, err, "params change transaction init"); - goto errout; - } - - /* - * Delete all the xenbus properties that are connection dependant - * and go back to the initializing state so that the frontend - * driver can re-negotiate a connection. - */ - if (((err = xenbus_rm(xbt, xsname, XBP_FB)) != 0) || - ((err = xenbus_rm(xbt, xsname, XBP_INFO)) != 0) || - ((err = xenbus_rm(xbt, xsname, "sector-size")) != 0) || - ((err = xenbus_rm(xbt, xsname, XBP_SECTORS)) != 0) || - ((err = xenbus_rm(xbt, xsname, "instance")) != 0) || - ((err = xenbus_rm(xbt, xsname, "node")) != 0) || - (update_xs && ((err = xenbus_printf(xbt, xsname, - "params", "%s", params)) != 0)) || - ((err = xvdi_switch_state(dip, - xbt, XenbusStateInitialising) > 0))) { - (void) xenbus_transaction_end(xbt, 1); - xvdi_dev_error(dip, err, "params change transaction setup"); - goto errout; - } - - if ((err = xenbus_transaction_end(xbt, 0)) != 0) { - if (err == EAGAIN) { - /* transaction is ended, don't need to abort it */ - goto trans_retry; - } - xvdi_dev_error(dip, err, "params change transaction commit"); - goto errout; - } - - /* Change the device that we plan to access */ - strfree(vdp->xs_params_path); - vdp->xs_params_path = strdup(params); - return; - -errout: - (void) xvdi_switch_state(dip, xbt, XenbusStateInitialising); -} - -/* - * xdb_watch_params_cb() - This callback is invoked whenever there - * is an update to the following xenbus parameter: - * /local/domain/0/backend/vbd///params - * - * This normally happens during xm block-configure operations, which - * are used to change CD device images for HVM domUs. - */ -/*ARGSUSED*/ -static void -xdb_watch_params_cb(dev_info_t *dip, const char *path, void *arg) -{ - xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); - char *xsname, *oename, *str, *str2; - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((oename = xvdi_get_oename(dip)) == NULL)) { - return; - } - - mutex_enter(&vdp->xs_cbmutex); - - if (xenbus_read_str(xsname, "params", &str) != 0) { - mutex_exit(&vdp->xs_cbmutex); - return; - } - - if (strcmp(vdp->xs_params_path, str) == 0) { - /* Nothing todo */ - mutex_exit(&vdp->xs_cbmutex); - strfree(str); - return; - } - - /* - * If the frontend isn't a cd device, doesn't support media - * requests, or has locked the media, then we can't change - * the params value. restore the current value. - */ - str2 = NULL; - if (!XDB_IS_FE_CD(vdp) || - (xenbus_read_str(oename, XBP_MEDIA_REQ, &str2) != 0) || - (strcmp(str2, XBV_MEDIA_REQ_LOCK) == 0)) { - if (str2 != NULL) - strfree(str2); - strfree(str); - - str = i_pathname(dip); - cmn_err(CE_NOTE, - "!%s: media locked, ignoring params update", str); - strfree(str); - - mutex_exit(&vdp->xs_cbmutex); - return; - } - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, - "block-configure params request: \"%s\"", str)); - - xdb_params_change(vdp, str, B_FALSE); - mutex_exit(&vdp->xs_cbmutex); - strfree(str); -} - -/* - * xdb_watch_media_req_cb() - This callback is invoked whenever there - * is an update to the following xenbus parameter: - * /local/domain//device/vbd//media-req - * - * Media requests are only supported on CD devices and are issued by - * the frontend. Currently the only supported media request operaions - * are "lock" and "eject". A "lock" prevents the backend from changing - * the backing device/file (via xm block-configure). An "eject" requests - * tells the backend device that it should disconnect from the frontend - * and closing the backing device/file that is currently in use. - */ -/*ARGSUSED*/ -static void -xdb_watch_media_req_cb(dev_info_t *dip, const char *path, void *arg) -{ - xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); - char *oename, *str; - - mutex_enter(&vdp->xs_cbmutex); - - if ((oename = xvdi_get_oename(dip)) == NULL) { - mutex_exit(&vdp->xs_cbmutex); - return; - } - - if (xenbus_read_str(oename, XBP_MEDIA_REQ, &str) != 0) { - mutex_exit(&vdp->xs_cbmutex); - return; - } - - if (!XDB_IS_FE_CD(vdp)) { - xvdi_dev_error(dip, EINVAL, - "media-req only supported for cdrom devices"); - mutex_exit(&vdp->xs_cbmutex); - return; - } - - if (strcmp(str, XBV_MEDIA_REQ_EJECT) != 0) { - mutex_exit(&vdp->xs_cbmutex); - strfree(str); - return; - } - strfree(str); - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "media eject request")); - - xdb_params_change(vdp, "", B_TRUE); - (void) xenbus_printf(XBT_NULL, oename, - XBP_MEDIA_REQ, "%s", XBV_MEDIA_REQ_NONE); - mutex_exit(&vdp->xs_cbmutex); -} - -/* - * If we're dealing with a cdrom device, let the frontend know that - * we support media requests via XBP_MEDIA_REQ_SUP, and setup a watch - * to handle those frontend media request changes, which modify the - * following xenstore parameter: - * /local/domain//device/vbd//media-req - */ -static boolean_t -xdb_media_req_init(xdb_t *vdp) -{ - dev_info_t *dip = vdp->xs_dip; - char *xsname, *oename; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((oename = xvdi_get_oename(dip)) == NULL)) - return (B_FALSE); - - if (!XDB_IS_FE_CD(vdp)) - return (B_TRUE); - - if (xenbus_printf(XBT_NULL, xsname, XBP_MEDIA_REQ_SUP, "%d", 1) != 0) - return (B_FALSE); - - if (xvdi_add_xb_watch_handler(dip, oename, - XBP_MEDIA_REQ, xdb_watch_media_req_cb, NULL) != DDI_SUCCESS) { - xvdi_dev_error(dip, EAGAIN, - "Failed to register watch for cdrom media requests"); - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * Get our params value. Also, if we're using "params" then setup a - * watch to handle xm block-configure operations which modify the - * following xenstore parameter: - * /local/domain/0/backend/vbd///params - */ -static boolean_t -xdb_params_init(xdb_t *vdp) -{ - dev_info_t *dip = vdp->xs_dip; - char *str, *xsname; - int err; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - ASSERT(vdp->xs_params_path == NULL); - - if ((xsname = xvdi_get_xsname(dip)) == NULL) - return (B_FALSE); - - err = xenbus_read_str(xsname, "params", &str); - if (err != 0) { - return (B_FALSE); - } - vdp->xs_params_path = str; - - if (xvdi_add_xb_watch_handler(dip, xsname, "params", - xdb_watch_params_cb, NULL) != DDI_SUCCESS) { - strfree(vdp->xs_params_path); - vdp->xs_params_path = NULL; - return (B_FALSE); - } - - return (B_TRUE); -} - -#define LOFI_CTRL_NODE "/dev/lofictl" -#define LOFI_DEV_NODE "/devices/pseudo/lofi@0:" -#define LOFI_MODE (FREAD | FWRITE | FEXCL) - -static int -xdb_setup_node(xdb_t *vdp, char *path) -{ - dev_info_t *dip = vdp->xs_dip; - char *xsname, *str; - ldi_handle_t ldi_hdl; - struct lofi_ioctl *li; - int minor, err; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if ((xsname = xvdi_get_xsname(dip)) == NULL) - return (DDI_FAILURE); - - if ((err = xenbus_read_str(xsname, "type", &str)) != 0) { - xvdi_dev_error(dip, err, "Getting type from backend device"); - return (DDI_FAILURE); - } - if (strcmp(str, "file") == 0) - vdp->xs_type |= XDB_DEV_BE_LOFI; - strfree(str); - - if (!XDB_IS_BE_LOFI(vdp)) { - (void) strlcpy(path, vdp->xs_params_path, MAXPATHLEN); - ASSERT(vdp->xs_lofi_path == NULL); - return (DDI_SUCCESS); - } - - do { - err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred, - &ldi_hdl, vdp->xs_ldi_li); - } while (err == EBUSY); - if (err != 0) { - return (DDI_FAILURE); - } - - li = kmem_zalloc(sizeof (*li), KM_SLEEP); - (void) strlcpy(li->li_filename, vdp->xs_params_path, - sizeof (li->li_filename)); - err = ldi_ioctl(ldi_hdl, LOFI_MAP_FILE, (intptr_t)li, - LOFI_MODE | FKIOCTL, kcred, &minor); - (void) ldi_close(ldi_hdl, LOFI_MODE, kcred); - kmem_free(li, sizeof (*li)); - - if (err != 0) { - cmn_err(CE_WARN, "xdb@%s: Failed to create lofi dev for %s", - ddi_get_name_addr(dip), vdp->xs_params_path); - return (DDI_FAILURE); - } - - /* - * return '/devices/...' instead of '/dev/lofi/...' since the - * former is available immediately after calling ldi_ioctl - */ - (void) snprintf(path, MAXPATHLEN, LOFI_DEV_NODE "%d", minor); - (void) xenbus_printf(XBT_NULL, xsname, "node", "%s", path); - - ASSERT(vdp->xs_lofi_path == NULL); - vdp->xs_lofi_path = strdup(path); - - return (DDI_SUCCESS); -} - -static void -xdb_teardown_node(xdb_t *vdp) -{ - dev_info_t *dip = vdp->xs_dip; - ldi_handle_t ldi_hdl; - struct lofi_ioctl *li; - int err; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if (!XDB_IS_BE_LOFI(vdp)) - return; - - vdp->xs_type &= ~XDB_DEV_BE_LOFI; - ASSERT(vdp->xs_lofi_path != NULL); - - li = kmem_zalloc(sizeof (*li), KM_SLEEP); - (void) strlcpy(li->li_filename, vdp->xs_params_path, - sizeof (li->li_filename)); - - do { - err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred, - &ldi_hdl, vdp->xs_ldi_li); - } while (err == EBUSY); - - if (err != 0) { - kmem_free(li, sizeof (*li)); - return; - } - - if (ldi_ioctl(ldi_hdl, LOFI_UNMAP_FILE, (intptr_t)li, - LOFI_MODE | FKIOCTL, kcred, NULL) != 0) { - cmn_err(CE_WARN, "xdb@%s: Failed to delete lofi dev for %s", - ddi_get_name_addr(dip), li->li_filename); - } - - (void) ldi_close(ldi_hdl, LOFI_MODE, kcred); - kmem_free(li, sizeof (*li)); - - strfree(vdp->xs_lofi_path); - vdp->xs_lofi_path = NULL; -} - -static int -xdb_open_device(xdb_t *vdp) -{ - dev_info_t *dip = vdp->xs_dip; - uint64_t devsize; - int blksize; - char *nodepath; - char *xsname; - char *str; - int err; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if (strlen(vdp->xs_params_path) == 0) { - /* - * it's possible to have no backing device when dealing - * with a pv cdrom drive that has no virtual cd associated - * with it. - */ - ASSERT(XDB_IS_FE_CD(vdp)); - ASSERT(vdp->xs_sectors == 0); - ASSERT(vdp->xs_ldi_li == NULL); - ASSERT(vdp->xs_ldi_hdl == NULL); - return (DDI_SUCCESS); - } - - /* - * after the hotplug scripts have "connected" the device, check to see - * if we're using a dynamic device. If so, replace the params path - * with the dynamic one. - */ - xsname = xvdi_get_xsname(dip); - err = xenbus_read_str(xsname, "dynamic-device-path", &str); - if (err == 0) { - strfree(vdp->xs_params_path); - vdp->xs_params_path = str; - } - - if (ldi_ident_from_dip(dip, &vdp->xs_ldi_li) != 0) - return (DDI_FAILURE); - - nodepath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); - - /* try to open backend device */ - if (xdb_setup_node(vdp, nodepath) != DDI_SUCCESS) { - xvdi_dev_error(dip, ENXIO, - "Getting device path of backend device"); - ldi_ident_release(vdp->xs_ldi_li); - kmem_free(nodepath, MAXPATHLEN); - return (DDI_FAILURE); - } - - if (ldi_open_by_name(nodepath, - FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), - kcred, &vdp->xs_ldi_hdl, vdp->xs_ldi_li) != 0) { - xdb_teardown_node(vdp); - ldi_ident_release(vdp->xs_ldi_li); - cmn_err(CE_WARN, "xdb@%s: Failed to open: %s", - ddi_get_name_addr(dip), nodepath); - kmem_free(nodepath, MAXPATHLEN); - return (DDI_FAILURE); - } - - if (ldi_get_size(vdp->xs_ldi_hdl, &devsize) != DDI_SUCCESS) { - (void) ldi_close(vdp->xs_ldi_hdl, - FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred); - xdb_teardown_node(vdp); - ldi_ident_release(vdp->xs_ldi_li); - kmem_free(nodepath, MAXPATHLEN); - return (DDI_FAILURE); - } - - blksize = ldi_prop_get_int64(vdp->xs_ldi_hdl, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - "blksize", DEV_BSIZE); - if (blksize == DEV_BSIZE) - blksize = ldi_prop_get_int(vdp->xs_ldi_hdl, - LDI_DEV_T_ANY | DDI_PROP_DONTPASS | - DDI_PROP_NOTPROM, "device-blksize", DEV_BSIZE); - - vdp->xs_sec_size = blksize; - vdp->xs_sectors = devsize / blksize; - - /* check if the underlying device is a CD/DVD disc */ - if (ldi_prop_get_int(vdp->xs_ldi_hdl, LDI_DEV_T_ANY | DDI_PROP_DONTPASS, - INQUIRY_DEVICE_TYPE, DTYPE_DIRECT) == DTYPE_RODIRECT) - vdp->xs_type |= XDB_DEV_BE_CD; - - /* check if the underlying device is a removable disk */ - if (ldi_prop_exists(vdp->xs_ldi_hdl, - LDI_DEV_T_ANY | DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - "removable-media")) - vdp->xs_type |= XDB_DEV_BE_RMB; - - kmem_free(nodepath, MAXPATHLEN); - return (DDI_SUCCESS); -} - -static void -xdb_close_device(xdb_t *vdp) -{ - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if (strlen(vdp->xs_params_path) == 0) { - ASSERT(XDB_IS_FE_CD(vdp)); - ASSERT(vdp->xs_sectors == 0); - ASSERT(vdp->xs_ldi_li == NULL); - ASSERT(vdp->xs_ldi_hdl == NULL); - return; - } - - (void) ldi_close(vdp->xs_ldi_hdl, - FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred); - xdb_teardown_node(vdp); - ldi_ident_release(vdp->xs_ldi_li); - vdp->xs_type &= ~(XDB_DEV_BE_CD | XDB_DEV_BE_RMB); - vdp->xs_sectors = 0; - vdp->xs_ldi_li = NULL; - vdp->xs_ldi_hdl = NULL; -} - -/* - * Kick-off connect process - * If xs_fe_initialised == B_TRUE and xs_hp_connected == B_TRUE - * the xs_if_connected will be changed to B_TRUE on success, - */ -static void -xdb_start_connect(xdb_t *vdp) -{ - xenbus_transaction_t xbt; - dev_info_t *dip = vdp->xs_dip; - boolean_t fb_exists; - int err, instance = ddi_get_instance(dip); - uint64_t sectors; - uint_t dinfo, ssize; - char *xsname; - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((vdp->xs_peer = xvdi_get_oeid(dip)) == (domid_t)-1)) - return; - - mutex_enter(&vdp->xs_iomutex); - /* - * if the hotplug scripts haven't run or if the frontend is not - * initialized, then we can't try to connect. - */ - if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) { - ASSERT(!vdp->xs_if_connected); - mutex_exit(&vdp->xs_iomutex); - return; - } - - /* If we're already connected then there's nothing todo */ - if (vdp->xs_if_connected) { - mutex_exit(&vdp->xs_iomutex); - return; - } - mutex_exit(&vdp->xs_iomutex); - - /* - * Start connect to frontend only when backend device are ready - * and frontend has moved to XenbusStateInitialised, which means - * ready to connect. - */ - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, - "xdb@%s: starting connection process", ddi_get_name_addr(dip))); - - if (xdb_open_device(vdp) != DDI_SUCCESS) - return; - - if (xdb_bindto_frontend(vdp) != DDI_SUCCESS) { - xdb_close_device(vdp); - return; - } - - /* init i/o requests */ - xdb_init_ioreqs(vdp); - - if (ddi_add_intr(dip, 0, NULL, NULL, xdb_intr, (caddr_t)vdp) - != DDI_SUCCESS) { - xdb_uninit_ioreqs(vdp); - xdb_unbindfrom_frontend(vdp); - xdb_close_device(vdp); - return; - } - - dinfo = 0; - if (XDB_IS_RO(vdp)) - dinfo |= VDISK_READONLY; - if (XDB_IS_BE_RMB(vdp)) - dinfo |= VDISK_REMOVABLE; - if (XDB_IS_BE_CD(vdp)) - dinfo |= VDISK_CDROM; - if (XDB_IS_FE_CD(vdp)) - dinfo |= VDISK_REMOVABLE | VDISK_CDROM; - - /* - * we can recieve intr any time from now on - * mark that we're ready to take intr - */ - mutex_enter(&vdp->xs_iomutex); - ASSERT(vdp->xs_fe_initialised); - vdp->xs_if_connected = B_TRUE; - mutex_exit(&vdp->xs_iomutex); - -trans_retry: - /* write into xenstore the info needed by frontend */ - if ((err = xenbus_transaction_start(&xbt)) != 0) { - xvdi_dev_error(dip, err, "connect transaction init"); - goto errout; - } - - /* If feature-barrier isn't present in xenstore, add it. */ - fb_exists = xenbus_exists(xsname, XBP_FB); - - ssize = (vdp->xs_sec_size == 0) ? DEV_BSIZE : vdp->xs_sec_size; - sectors = vdp->xs_sectors; - if (((!fb_exists && - (err = xenbus_printf(xbt, xsname, XBP_FB, "%d", 1)))) || - (err = xenbus_printf(xbt, xsname, XBP_INFO, "%u", dinfo)) || - (err = xenbus_printf(xbt, xsname, XBP_SECTOR_SIZE, "%u", ssize)) || - (err = xenbus_printf(xbt, xsname, - XBP_SECTORS, "%"PRIu64, sectors)) || - (err = xenbus_printf(xbt, xsname, "instance", "%d", instance)) || - ((err = xvdi_switch_state(dip, xbt, XenbusStateConnected)) > 0)) { - (void) xenbus_transaction_end(xbt, 1); - xvdi_dev_error(dip, err, "connect transaction setup"); - goto errout; - } - - if ((err = xenbus_transaction_end(xbt, 0)) != 0) { - if (err == EAGAIN) { - /* transaction is ended, don't need to abort it */ - goto trans_retry; - } - xvdi_dev_error(dip, err, "connect transaction commit"); - goto errout; - } - - return; - -errout: - xdb_close(dip); -} - -/* - * Disconnect from frontend and close backend device - */ -static void -xdb_close(dev_info_t *dip) -{ - xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); - - ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); - mutex_enter(&vdp->xs_iomutex); - - /* - * if the hotplug scripts haven't run or if the frontend is not - * initialized, then we can't be connected, so there's no - * connection to close. - */ - if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) { - ASSERT(!vdp->xs_if_connected); - mutex_exit(&vdp->xs_iomutex); - return; - } - - /* if we're not connected, there's nothing to do */ - if (!vdp->xs_if_connected) { - cv_broadcast(&vdp->xs_iocv); - mutex_exit(&vdp->xs_iomutex); - return; - } - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "closing while connected")); - - vdp->xs_if_connected = B_FALSE; - cv_broadcast(&vdp->xs_iocv); - - mutex_exit(&vdp->xs_iomutex); - - /* stop accepting I/O request from frontend */ - ddi_remove_intr(dip, 0, NULL); - - /* clear all on-going I/Os, if any */ - mutex_enter(&vdp->xs_iomutex); - while (vdp->xs_ionum > 0) - cv_wait(&vdp->xs_ionumcv, &vdp->xs_iomutex); - mutex_exit(&vdp->xs_iomutex); - - /* clean up resources and close this interface */ - xdb_uninit_ioreqs(vdp); - xdb_unbindfrom_frontend(vdp); - xdb_close_device(vdp); - vdp->xs_peer = (domid_t)-1; -} - -static void -xdb_send_buf(void *arg) -{ - xdb_t *vdp = (xdb_t *)arg; - buf_t *bp; - int err; - - mutex_enter(&vdp->xs_iomutex); - while (vdp->xs_send_buf) { - if ((bp = vdp->xs_f_iobuf) == NULL) { - /* wait for some io to send */ - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - "send buf waiting for io")); - cv_wait(&vdp->xs_iocv, &vdp->xs_iomutex); - continue; - } - - vdp->xs_f_iobuf = bp->av_forw; - bp->av_forw = NULL; - vdp->xs_ionum++; - - mutex_exit(&vdp->xs_iomutex); - if (bp->b_bcount == 0) { - /* no I/O needs to be done */ - (void) xdb_biodone(bp); - mutex_enter(&vdp->xs_iomutex); - continue; - } - - err = EIO; - if (vdp->xs_ldi_hdl != NULL) - err = ldi_strategy(vdp->xs_ldi_hdl, bp); - if (err != 0) { - bp->b_flags |= B_ERROR; - (void) xdb_biodone(bp); - XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, - "xdb@%s: sent buf to backend devfailed, err=%d", - ddi_get_name_addr(vdp->xs_dip), err)); - } else { - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, - "sent buf to backend ok")); - } - mutex_enter(&vdp->xs_iomutex); - } - XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "send buf finishing")); - mutex_exit(&vdp->xs_iomutex); -} - -/*ARGSUSED*/ -static void -xdb_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, - void *impl_data) -{ - xendev_hotplug_state_t state = *(xendev_hotplug_state_t *)impl_data; - xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: " - "hotplug status change to %d!", ddi_get_name_addr(dip), state)); - - if (state != Connected) - return; - - mutex_enter(&vdp->xs_cbmutex); - - /* If hotplug script have already run, there's nothing todo */ - if (vdp->xs_hp_connected) { - mutex_exit(&vdp->xs_cbmutex); - return; - } - - vdp->xs_hp_connected = B_TRUE; - xdb_start_connect(vdp); - mutex_exit(&vdp->xs_cbmutex); -} - -/*ARGSUSED*/ -static void -xdb_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, - void *impl_data) -{ - XenbusState new_state = *(XenbusState *)impl_data; - xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: " - "otherend state change to %d!", ddi_get_name_addr(dip), new_state)); - - mutex_enter(&vdp->xs_cbmutex); - - /* - * Now it'd really be nice if there was a well defined state - * transition model for xen frontend drivers, but unfortunatly - * there isn't. So we're stuck with assuming that all state - * transitions are possible, and we'll just have to deal with - * them regardless of what state we're in. - */ - switch (new_state) { - case XenbusStateUnknown: - case XenbusStateInitialising: - case XenbusStateInitWait: - /* tear down our connection to the frontend */ - xdb_close(dip); - vdp->xs_fe_initialised = B_FALSE; - break; - - case XenbusStateInitialised: - /* - * If we were conected, then we need to drop the connection - * and re-negotiate it. - */ - xdb_close(dip); - vdp->xs_fe_initialised = B_TRUE; - xdb_start_connect(vdp); - break; - - case XenbusStateConnected: - /* nothing todo here other than congratulate the frontend */ - break; - - case XenbusStateClosing: - /* monkey see monkey do */ - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing); - break; - - case XenbusStateClosed: - /* tear down our connection to the frontend */ - xdb_close(dip); - vdp->xs_fe_initialised = B_FALSE; - (void) xvdi_switch_state(dip, XBT_NULL, new_state); - break; - } - - mutex_exit(&vdp->xs_cbmutex); -} - -static int -xdb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - ddi_iblock_cookie_t ibc; - xdb_t *vdp; - int instance = ddi_get_instance(dip); - char *xsname, *oename; - char *str; - - switch (cmd) { - case DDI_RESUME: - return (DDI_FAILURE); - case DDI_ATTACH: - break; - default: - return (DDI_FAILURE); - } - /* DDI_ATTACH */ - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((oename = xvdi_get_oename(dip)) == NULL)) - return (DDI_FAILURE); - - /* - * Disable auto-detach. This is necessary so that we don't get - * detached while we're disconnected from the front end. - */ - (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1); - - if (ddi_get_iblock_cookie(dip, 0, &ibc) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (ddi_soft_state_zalloc(xdb_statep, instance) != DDI_SUCCESS) - return (DDI_FAILURE); - - vdp = ddi_get_soft_state(xdb_statep, instance); - vdp->xs_dip = dip; - mutex_init(&vdp->xs_iomutex, NULL, MUTEX_DRIVER, (void *)ibc); - mutex_init(&vdp->xs_cbmutex, NULL, MUTEX_DRIVER, (void *)ibc); - cv_init(&vdp->xs_iocv, NULL, CV_DRIVER, NULL); - cv_init(&vdp->xs_ionumcv, NULL, CV_DRIVER, NULL); - ddi_set_driver_private(dip, vdp); - - if (!xdb_kstat_init(vdp)) - goto errout1; - - /* Check if the frontend device is supposed to be a cdrom */ - if (xenbus_read_str(oename, XBP_DEV_TYPE, &str) != 0) - return (DDI_FAILURE); - if (strcmp(str, XBV_DEV_TYPE_CD) == 0) - vdp->xs_type |= XDB_DEV_FE_CD; - strfree(str); - - /* Check if the frontend device is supposed to be read only */ - if (xenbus_read_str(xsname, "mode", &str) != 0) - return (DDI_FAILURE); - if ((strcmp(str, "r") == 0) || (strcmp(str, "ro") == 0)) - vdp->xs_type |= XDB_DEV_RO; - strfree(str); - - mutex_enter(&vdp->xs_cbmutex); - if (!xdb_media_req_init(vdp) || !xdb_params_init(vdp)) { - xvdi_remove_xb_watch_handlers(dip); - mutex_exit(&vdp->xs_cbmutex); - goto errout2; - } - mutex_exit(&vdp->xs_cbmutex); - - vdp->xs_send_buf = B_TRUE; - vdp->xs_iotaskq = ddi_taskq_create(dip, "xdb_iotask", 1, - TASKQ_DEFAULTPRI, 0); - (void) ddi_taskq_dispatch(vdp->xs_iotaskq, xdb_send_buf, vdp, - DDI_SLEEP); - - /* Watch frontend and hotplug state change */ - if ((xvdi_add_event_handler(dip, XS_OE_STATE, xdb_oe_state_change, - NULL) != DDI_SUCCESS) || - (xvdi_add_event_handler(dip, XS_HP_STATE, xdb_hp_state_change, - NULL) != DDI_SUCCESS)) - goto errout3; - - /* - * Kick-off hotplug script - */ - if (xvdi_post_event(dip, XEN_HP_ADD) != DDI_SUCCESS) { - cmn_err(CE_WARN, "xdb@%s: failed to start hotplug script", - ddi_get_name_addr(dip)); - goto errout3; - } - - /* - * start waiting for hotplug event and otherend state event - * mainly for debugging, frontend will not take any op seeing this - */ - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitWait); - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: attached!", - ddi_get_name_addr(dip))); - return (DDI_SUCCESS); - -errout3: - ASSERT(vdp->xs_hp_connected && vdp->xs_if_connected); - - xvdi_remove_event_handler(dip, NULL); - - /* Disconnect from the backend */ - mutex_enter(&vdp->xs_cbmutex); - mutex_enter(&vdp->xs_iomutex); - vdp->xs_send_buf = B_FALSE; - cv_broadcast(&vdp->xs_iocv); - mutex_exit(&vdp->xs_iomutex); - mutex_exit(&vdp->xs_cbmutex); - - /* wait for all io to dtrain and destroy io taskq */ - ddi_taskq_destroy(vdp->xs_iotaskq); - - /* tear down block-configure watch */ - mutex_enter(&vdp->xs_cbmutex); - xvdi_remove_xb_watch_handlers(dip); - mutex_exit(&vdp->xs_cbmutex); - -errout2: - /* remove kstats */ - kstat_delete(vdp->xs_kstats); - -errout1: - /* free up driver state */ - ddi_set_driver_private(dip, NULL); - cv_destroy(&vdp->xs_iocv); - cv_destroy(&vdp->xs_ionumcv); - mutex_destroy(&vdp->xs_cbmutex); - mutex_destroy(&vdp->xs_iomutex); - ddi_soft_state_free(xdb_statep, instance); - - return (DDI_FAILURE); -} - -/*ARGSUSED*/ -static int -xdb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - xdb_t *vdp = XDB_INST2SOFTS(instance); - - switch (cmd) { - case DDI_SUSPEND: - return (DDI_FAILURE); - case DDI_DETACH: - break; - default: - return (DDI_FAILURE); - } - - /* DDI_DETACH handling */ - - /* refuse to detach if we're still in use by the frontend */ - mutex_enter(&vdp->xs_iomutex); - if (vdp->xs_if_connected) { - mutex_exit(&vdp->xs_iomutex); - return (DDI_FAILURE); - } - vdp->xs_send_buf = B_FALSE; - cv_broadcast(&vdp->xs_iocv); - mutex_exit(&vdp->xs_iomutex); - - xvdi_remove_event_handler(dip, NULL); - (void) xvdi_post_event(dip, XEN_HP_REMOVE); - - ddi_taskq_destroy(vdp->xs_iotaskq); - - mutex_enter(&vdp->xs_cbmutex); - xvdi_remove_xb_watch_handlers(dip); - mutex_exit(&vdp->xs_cbmutex); - - cv_destroy(&vdp->xs_iocv); - cv_destroy(&vdp->xs_ionumcv); - mutex_destroy(&vdp->xs_cbmutex); - mutex_destroy(&vdp->xs_iomutex); - kstat_delete(vdp->xs_kstats); - ddi_set_driver_private(dip, NULL); - ddi_soft_state_free(xdb_statep, instance); - - XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: detached!", - ddi_get_name_addr(dip))); - return (DDI_SUCCESS); -} - -static struct dev_ops xdb_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - ddi_getinfo_1to1, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xdb_attach, /* devo_attach */ - xdb_detach, /* devo_detach */ - nodev, /* devo_reset */ - NULL, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -/* - * Module linkage information for the kernel. - */ -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. */ - "vbd backend driver", /* Name of the module */ - &xdb_dev_ops /* driver ops */ -}; - -static struct modlinkage xdb_modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - int rv; - - if ((rv = ddi_soft_state_init((void **)&xdb_statep, - sizeof (xdb_t), 0)) == 0) - if ((rv = mod_install(&xdb_modlinkage)) != 0) - ddi_soft_state_fini((void **)&xdb_statep); - return (rv); -} - -int -_fini(void) -{ - int rv; - - if ((rv = mod_remove(&xdb_modlinkage)) != 0) - return (rv); - ddi_soft_state_fini((void **)&xdb_statep); - return (rv); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&xdb_modlinkage, modinfop)); -} - -static int -xdb_get_request(xdb_t *vdp, blkif_request_t *req) -{ - void *src = xvdi_ring_get_request(vdp->xs_ring); - - if (src == NULL) - return (0); - - switch (vdp->xs_blk_protocol) { - case BLKIF_PROTOCOL_NATIVE: - (void) memcpy(req, src, sizeof (*req)); - break; - case BLKIF_PROTOCOL_X86_32: - blkif_get_x86_32_req(req, src); - break; - case BLKIF_PROTOCOL_X86_64: - blkif_get_x86_64_req(req, src); - break; - default: - cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d", - ddi_get_name_addr(vdp->xs_dip), - vdp->xs_blk_protocol); - } - return (1); -} - -static int -xdb_push_response(xdb_t *vdp, uint64_t id, uint8_t op, uint16_t status) -{ - ddi_acc_handle_t acchdl = vdp->xs_ring_hdl; - blkif_response_t *rsp = xvdi_ring_get_response(vdp->xs_ring); - blkif_x86_32_response_t *rsp_32 = (blkif_x86_32_response_t *)rsp; - blkif_x86_64_response_t *rsp_64 = (blkif_x86_64_response_t *)rsp; - - ASSERT(rsp); - - switch (vdp->xs_blk_protocol) { - case BLKIF_PROTOCOL_NATIVE: - ddi_put64(acchdl, &rsp->id, id); - ddi_put8(acchdl, &rsp->operation, op); - ddi_put16(acchdl, (uint16_t *)&rsp->status, - status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); - break; - case BLKIF_PROTOCOL_X86_32: - ddi_put64(acchdl, &rsp_32->id, id); - ddi_put8(acchdl, &rsp_32->operation, op); - ddi_put16(acchdl, (uint16_t *)&rsp_32->status, - status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); - break; - case BLKIF_PROTOCOL_X86_64: - ddi_put64(acchdl, &rsp_64->id, id); - ddi_put8(acchdl, &rsp_64->operation, op); - ddi_put16(acchdl, (uint16_t *)&rsp_64->status, - status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); - break; - default: - cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d", - ddi_get_name_addr(vdp->xs_dip), - vdp->xs_blk_protocol); - } - - return (xvdi_ring_push_response(vdp->xs_ring)); -} - -static void -blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->sector_number = src->sector_number; - if (n > src->nr_segments) - n = src->nr_segments; - for (i = 0; i < n; i++) - dst->seg[i] = src->seg[i]; -} - -static void -blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->sector_number = src->sector_number; - if (n > src->nr_segments) - n = src->nr_segments; - for (i = 0; i < n; i++) - dst->seg[i] = src->seg[i]; -} diff --git a/usr/src/uts/common/xen/io/xdb.h b/usr/src/uts/common/xen/io/xdb.h deleted file mode 100644 index 2173ca6ad9..0000000000 --- a/usr/src/uts/common/xen/io/xdb.h +++ /dev/null @@ -1,184 +0,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. - */ - - -#ifndef _SYS_XDB_H -#define _SYS_XDB_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define XDB_DBG_ALL 0xf -#define XDB_DBG_IO 0x1 -#define XDB_DBG_INFO 0x2 -#define XDB_DBPRINT(lvl, fmt) { if (xdb_debug & lvl) cmn_err fmt; } - -/* - * Info of the exported blk device - */ -#define XDB_DEV_RO (1 << 0) /* backend and frontend are read-only */ -#define XDB_DEV_BE_LOFI (1 << 1) /* backend device is a lofi device */ -#define XDB_DEV_BE_RMB (1 << 2) /* backend device is removable */ -#define XDB_DEV_BE_CD (1 << 3) /* backend device is cdrom */ -#define XDB_DEV_FE_CD (1 << 4) /* frontend device is cdrom */ - -#define XDB_IS_RO(vdp) ((vdp)->xs_type & XDB_DEV_RO) -#define XDB_IS_BE_LOFI(vdp) ((vdp)->xs_type & XDB_DEV_BE_LOFI) -#define XDB_IS_BE_RMB(vdp) ((vdp)->xs_type & XDB_DEV_BE_RMB) -#define XDB_IS_BE_CD(vdp) ((vdp)->xs_type & XDB_DEV_BE_CD) -#define XDB_IS_FE_CD(vdp) ((vdp)->xs_type & XDB_DEV_FE_CD) - -/* - * Other handy macrosx - */ -#define XDB_MINOR2INST(m) (int)(m) -#define XDB_INST2MINOR(i) (minor_t)(i) -#define XDB_INST2SOFTS(instance) \ - ((xdb_t *)ddi_get_soft_state(xdb_statep, (instance))) -#define XDB_MAX_IO_PAGES(v) ((v)->xs_nentry * BLKIF_MAX_SEGMENTS_PER_REQUEST) -/* get kva of a mapped-in page coresponding to (xreq-index, seg) pair */ -#define XDB_IOPAGE_VA(_pagebase, _xreqidx, _seg) \ - ((_pagebase) + ((_xreqidx) \ - * BLKIF_MAX_SEGMENTS_PER_REQUEST \ - + (_seg)) * PAGESIZE) -#define XDB_XREQ2BP(xreq) (&(xreq)->xr_buf) -#define XDB_BP2XREQ(bp) \ - ((xdb_request_t *)((char *)(bp) - offsetof(xdb_request_t, xr_buf))) - -/* describe one blkif segment */ -typedef struct xdb_seg { - uint8_t fs; /* start sector # within this page (segment) */ - uint8_t ls; /* end sector # within this page (segment) */ -} xdb_seg_t; - -typedef struct xdb xdb_t; - -/* one blkif_request_t matches one xdb_request_t */ -typedef struct xdb_request { - /* buf associated with this I/O request */ - buf_t xr_buf; - /* softstate instance associated with this I/O request */ - xdb_t *xr_vdp; - /* the next segment we're going to process */ - int xr_curseg; - /* index of this xdb_request_t in vdp->xs_req */ - int xr_idx; - /* next index for a statical linked list */ - int xr_next; - /* 'id' copied from blkif_request_t */ - uint64_t xr_id; - /* 'operation' copied from blkif_request_t */ - uint8_t xr_op; - /* how many pages(segments) in this I/O request */ - uint8_t xr_buf_pages; - /* all segments of this I/O request */ - xdb_seg_t xr_segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - /* all grant table handles used in this I/O request */ - grant_handle_t xr_page_hdls[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - struct page xr_plist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - struct page *xr_pplist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -} xdb_request_t; - -/* Soft state data structure for each backend vbd */ -struct xdb { - /* devinfo node pointer of this xdb */ - dev_info_t *xs_dip; - /* coresponding frontend domain id */ - domid_t xs_peer; - /* read-only, removable, cdrom? */ - uint32_t xs_type; - /* # of total sectors */ - uint64_t xs_sectors; - /* sector size if existed */ - uint_t xs_sec_size; - /* blkif I/O request ring buffer */ - xendev_ring_t *xs_ring; - /* handle to access the ring buffer */ - ddi_acc_handle_t xs_ring_hdl; - ldi_ident_t xs_ldi_li; - ldi_handle_t xs_ldi_hdl; - /* base kva for mapped-in I/O page from frontend domain */ - caddr_t xs_iopage_va; - /* mutex lock for I/O related code path */ - kmutex_t xs_iomutex; - /* - * mutex lock for event handling related code path - * need to be grabbed before xs_iomutex - */ - kmutex_t xs_cbmutex; - /* # of on-going I/O buf in backend domain */ - uint_t xs_ionum; - /* task thread for pushing buf to underlying target driver */ - ddi_taskq_t *xs_iotaskq; - /* cv used in I/O code path, protected by xs_iomutex */ - kcondvar_t xs_iocv; - kcondvar_t xs_ionumcv; - /* - * head and tail of linked list for I/O bufs need to be pushed to - * underlying target driver - */ - buf_t *xs_f_iobuf; - buf_t *xs_l_iobuf; - /* head of free list of xdb_request_t */ - int xs_free_req; - /* pre-allocated xdb_request_t pool */ - xdb_request_t *xs_req; - kstat_t *xs_kstats; - uint64_t xs_stat_req_reads; - uint64_t xs_stat_req_writes; - uint64_t xs_stat_req_barriers; - uint64_t xs_stat_req_flushes; - enum blkif_protocol xs_blk_protocol; - size_t xs_nentry; - size_t xs_entrysize; - - /* Protected by xs_cbmutex */ - boolean_t xs_hp_connected; /* hot plug scripts have run */ - boolean_t xs_fe_initialised; /* frontend is initialized */ - char *xs_lofi_path; - char *xs_params_path; - struct xenbus_watch *xs_watch_params; - struct xenbus_watch *xs_watch_media_req; - ddi_taskq_t *xs_watch_taskq; - int xs_watch_taskq_count; - - /* Protected by xs_cbmutex and xs_iomutex */ - boolean_t xs_if_connected; /* connected to frontend */ - - /* Protected by xs_iomutex */ - boolean_t xs_send_buf; - -#ifdef DEBUG - uint64_t *page_addrs; /* for debug aid */ -#endif /* DEBUG */ -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XDB_H */ diff --git a/usr/src/uts/common/xen/io/xdf.c b/usr/src/uts/common/xen/io/xdf.c deleted file mode 100644 index 8a6291720d..0000000000 --- a/usr/src/uts/common/xen/io/xdf.c +++ /dev/null @@ -1,3627 +0,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. - */ - -/* - * xdf.c - Xen Virtual Block Device Driver - * TODO: - * - support alternate block size (currently only DEV_BSIZE supported) - * - revalidate geometry for removable devices - * - * This driver export solaris disk device nodes, accepts IO requests from - * those nodes, and services those requests by talking to a backend device - * in another domain. - * - * Communication with the backend device is done via a ringbuffer (which is - * managed via xvdi interfaces) and dma memory (which is managed via ddi - * interfaces). - * - * Communication with the backend device is dependant upon establishing a - * connection to the backend device. This connection process involves - * reading device configuration information from xenbus and publishing - * some frontend runtime configuration parameters via the xenbus (for - * consumption by the backend). Once we've published runtime configuration - * information via the xenbus, the backend device can enter the connected - * state and we'll enter the XD_CONNECTED state. But before we can allow - * random IO to begin, we need to do IO to the backend device to determine - * the device label and if flush operations are supported. Once this is - * done we enter the XD_READY state and can process any IO operations. - * - * We recieve notifications of xenbus state changes for the backend device - * (aka, the "other end") via the xdf_oe_change() callback. This callback - * is single threaded, meaning that we can't recieve new notification of - * other end state changes while we're processing an outstanding - * notification of an other end state change. There for we can't do any - * blocking operations from the xdf_oe_change() callback. This is why we - * have a seperate taskq (xdf_ready_tq) which exists to do the necessary - * IO to get us from the XD_CONNECTED to the XD_READY state. All IO - * generated by the xdf_ready_tq thread (xdf_ready_tq_thread) will go - * throught xdf_lb_rdwr(), which is a synchronous IO interface. IOs - * generated by the xdf_ready_tq_thread thread have priority over all - * other IO requests. - * - * We also communicate with the backend device via the xenbus "media-req" - * (XBP_MEDIA_REQ) property. For more information on this see the - * comments in blkif.h. - */ - -#include - -#include -#include -#include -#include -#include -#include -#ifdef XPV_HVM_DRIVER -#include -#include -#else /* !XPV_HVM_DRIVER */ -#include -#endif /* !XPV_HVM_DRIVER */ -#include -#include -#include -#include -#include -#include - -/* - * DEBUG_EVAL can be used to include debug only statements without - * having to use '#ifdef DEBUG' statements - */ -#ifdef DEBUG -#define DEBUG_EVAL(x) (x) -#else /* !DEBUG */ -#define DEBUG_EVAL(x) -#endif /* !DEBUG */ - -#define XDF_DRAIN_MSEC_DELAY (50*1000) /* 00.05 sec */ -#define XDF_DRAIN_RETRY_COUNT 200 /* 10.00 sec */ - -#define INVALID_DOMID ((domid_t)-1) -#define FLUSH_DISKCACHE 0x1 -#define WRITE_BARRIER 0x2 -#define DEFAULT_FLUSH_BLOCK 156 /* block to write to cause a cache flush */ -#define USE_WRITE_BARRIER(vdp) \ - ((vdp)->xdf_feature_barrier && !(vdp)->xdf_flush_supported) -#define USE_FLUSH_DISKCACHE(vdp) \ - ((vdp)->xdf_feature_barrier && (vdp)->xdf_flush_supported) -#define IS_WRITE_BARRIER(vdp, bp) \ - (!IS_READ(bp) && USE_WRITE_BARRIER(vdp) && \ - ((bp)->b_un.b_addr == (vdp)->xdf_cache_flush_block)) -#define IS_FLUSH_DISKCACHE(bp) \ - (!IS_READ(bp) && USE_FLUSH_DISKCACHE(vdp) && ((bp)->b_bcount == 0)) - -#define VREQ_DONE(vreq) \ - (((vreq)->v_status == VREQ_DMAWIN_DONE) && \ - (((vreq)->v_flush_diskcache == FLUSH_DISKCACHE) || \ - (((vreq)->v_dmaw + 1) == (vreq)->v_ndmaws))) - -#define BP_VREQ(bp) ((v_req_t *)((bp)->av_back)) -#define BP_VREQ_SET(bp, vreq) (((bp)->av_back = (buf_t *)(vreq))) - -extern int do_polled_io; - -/* run-time tunables that we don't want the compiler to optimize away */ -volatile int xdf_debug = 0; -volatile boolean_t xdf_barrier_flush_disable = B_FALSE; - -/* per module globals */ -major_t xdf_major; -static void *xdf_ssp; -static kmem_cache_t *xdf_vreq_cache; -static kmem_cache_t *xdf_gs_cache; -static int xdf_maxphys = XB_MAXPHYS; -static diskaddr_t xdf_flush_block = DEFAULT_FLUSH_BLOCK; -static int xdf_fbrewrites; /* flush block re-write count */ - -/* misc public functions (used by xdf_shell.c) */ -int xdf_lb_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t, void *); -int xdf_lb_getinfo(dev_info_t *, int, void *, void *); - -/* misc private functions */ -static void xdf_io_start(xdf_t *); - -/* callbacks from commmon label */ -static cmlb_tg_ops_t xdf_lb_ops = { - TG_DK_OPS_VERSION_1, - xdf_lb_rdwr, - xdf_lb_getinfo -}; - -/* - * I/O buffer DMA attributes - * Make sure: one DMA window contains BLKIF_MAX_SEGMENTS_PER_REQUEST at most - */ -static ddi_dma_attr_t xb_dma_attr = { - DMA_ATTR_V0, - (uint64_t)0, /* lowest address */ - (uint64_t)0xffffffffffffffff, /* highest usable address */ - (uint64_t)0xffffff, /* DMA counter limit max */ - (uint64_t)XB_BSIZE, /* alignment in bytes */ - XB_BSIZE - 1, /* bitmap of burst sizes */ - XB_BSIZE, /* min transfer */ - (uint64_t)XB_MAX_XFER, /* maximum transfer */ - (uint64_t)PAGEOFFSET, /* 1 page segment length */ - BLKIF_MAX_SEGMENTS_PER_REQUEST, /* maximum number of segments */ - XB_BSIZE, /* granularity */ - 0, /* flags (reserved) */ -}; - -static ddi_device_acc_attr_t xc_acc_attr = { - DDI_DEVICE_ATTR_V0, - DDI_NEVERSWAP_ACC, - DDI_STRICTORDER_ACC -}; - -static void -xdf_timeout_handler(void *arg) -{ - xdf_t *vdp = arg; - - mutex_enter(&vdp->xdf_dev_lk); - vdp->xdf_timeout_id = 0; - mutex_exit(&vdp->xdf_dev_lk); - - /* new timeout thread could be re-scheduled */ - xdf_io_start(vdp); -} - -/* - * callback func when DMA/GTE resources is available - * - * Note: we only register one callback function to grant table subsystem - * since we only have one 'struct gnttab_free_callback' in xdf_t. - */ -static int -xdf_dmacallback(caddr_t arg) -{ - xdf_t *vdp = (xdf_t *)arg; - ASSERT(vdp != NULL); - - DPRINTF(DMA_DBG, ("xdf@%s: DMA callback started\n", - vdp->xdf_addr)); - - ddi_trigger_softintr(vdp->xdf_softintr_id); - return (DDI_DMA_CALLBACK_DONE); -} - -static ge_slot_t * -gs_get(xdf_t *vdp, int isread) -{ - grant_ref_t gh; - ge_slot_t *gs; - - /* try to alloc GTEs needed in this slot, first */ - if (gnttab_alloc_grant_references( - BLKIF_MAX_SEGMENTS_PER_REQUEST, &gh) == -1) { - if (vdp->xdf_gnt_callback.next == NULL) { - SETDMACBON(vdp); - gnttab_request_free_callback( - &vdp->xdf_gnt_callback, - (void (*)(void *))xdf_dmacallback, - (void *)vdp, - BLKIF_MAX_SEGMENTS_PER_REQUEST); - } - return (NULL); - } - - gs = kmem_cache_alloc(xdf_gs_cache, KM_NOSLEEP); - if (gs == NULL) { - gnttab_free_grant_references(gh); - if (vdp->xdf_timeout_id == 0) - /* restart I/O after one second */ - vdp->xdf_timeout_id = - timeout(xdf_timeout_handler, vdp, hz); - return (NULL); - } - - /* init gs_slot */ - gs->gs_oeid = vdp->xdf_peer; - gs->gs_isread = isread; - gs->gs_ghead = gh; - gs->gs_ngrefs = 0; - - return (gs); -} - -static void -gs_free(ge_slot_t *gs) -{ - int i; - - /* release all grant table entry resources used in this slot */ - for (i = 0; i < gs->gs_ngrefs; i++) - gnttab_end_foreign_access(gs->gs_ge[i], !gs->gs_isread, 0); - gnttab_free_grant_references(gs->gs_ghead); - list_remove(&gs->gs_vreq->v_gs, gs); - kmem_cache_free(xdf_gs_cache, gs); -} - -static grant_ref_t -gs_grant(ge_slot_t *gs, mfn_t mfn) -{ - grant_ref_t gr = gnttab_claim_grant_reference(&gs->gs_ghead); - - ASSERT(gr != -1); - ASSERT(gs->gs_ngrefs < BLKIF_MAX_SEGMENTS_PER_REQUEST); - gs->gs_ge[gs->gs_ngrefs++] = gr; - gnttab_grant_foreign_access_ref(gr, gs->gs_oeid, mfn, !gs->gs_isread); - - return (gr); -} - -/* - * Alloc a vreq for this bp - * bp->av_back contains the pointer to the vreq upon return - */ -static v_req_t * -vreq_get(xdf_t *vdp, buf_t *bp) -{ - v_req_t *vreq = NULL; - - ASSERT(BP_VREQ(bp) == NULL); - - vreq = kmem_cache_alloc(xdf_vreq_cache, KM_NOSLEEP); - if (vreq == NULL) { - if (vdp->xdf_timeout_id == 0) - /* restart I/O after one second */ - vdp->xdf_timeout_id = - timeout(xdf_timeout_handler, vdp, hz); - return (NULL); - } - bzero(vreq, sizeof (v_req_t)); - list_create(&vreq->v_gs, sizeof (ge_slot_t), - offsetof(ge_slot_t, gs_vreq_link)); - vreq->v_buf = bp; - vreq->v_status = VREQ_INIT; - vreq->v_runq = B_FALSE; - BP_VREQ_SET(bp, vreq); - /* init of other fields in vreq is up to the caller */ - - list_insert_head(&vdp->xdf_vreq_act, (void *)vreq); - - return (vreq); -} - -static void -vreq_free(xdf_t *vdp, v_req_t *vreq) -{ - buf_t *bp = vreq->v_buf; - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(BP_VREQ(bp) == vreq); - - list_remove(&vdp->xdf_vreq_act, vreq); - - if (vreq->v_flush_diskcache == FLUSH_DISKCACHE) - goto done; - - switch (vreq->v_status) { - case VREQ_DMAWIN_DONE: - case VREQ_GS_ALLOCED: - case VREQ_DMABUF_BOUND: - (void) ddi_dma_unbind_handle(vreq->v_dmahdl); - /*FALLTHRU*/ - case VREQ_DMAMEM_ALLOCED: - if (!ALIGNED_XFER(bp)) { - ASSERT(vreq->v_abuf != NULL); - if (!IS_ERROR(bp) && IS_READ(bp)) - bcopy(vreq->v_abuf, bp->b_un.b_addr, - bp->b_bcount); - ddi_dma_mem_free(&vreq->v_align); - } - /*FALLTHRU*/ - case VREQ_MEMDMAHDL_ALLOCED: - if (!ALIGNED_XFER(bp)) - ddi_dma_free_handle(&vreq->v_memdmahdl); - /*FALLTHRU*/ - case VREQ_DMAHDL_ALLOCED: - ddi_dma_free_handle(&vreq->v_dmahdl); - break; - default: - break; - } -done: - ASSERT(!vreq->v_runq); - list_destroy(&vreq->v_gs); - kmem_cache_free(xdf_vreq_cache, vreq); -} - -/* - * Snarf new data if our flush block was re-written - */ -static void -check_fbwrite(xdf_t *vdp, buf_t *bp, daddr_t blkno) -{ - int nblks; - boolean_t mapin; - - if (IS_WRITE_BARRIER(vdp, bp)) - return; /* write was a flush write */ - - mapin = B_FALSE; - nblks = bp->b_bcount >> DEV_BSHIFT; - if (xdf_flush_block >= blkno && xdf_flush_block < (blkno + nblks)) { - xdf_fbrewrites++; - if (bp->b_flags & (B_PAGEIO | B_PHYS)) { - mapin = B_TRUE; - bp_mapin(bp); - } - bcopy(bp->b_un.b_addr + - ((xdf_flush_block - blkno) << DEV_BSHIFT), - vdp->xdf_cache_flush_block, DEV_BSIZE); - if (mapin) - bp_mapout(bp); - } -} - -/* - * Initalize the DMA and grant table resources for the buf - */ -static int -vreq_setup(xdf_t *vdp, v_req_t *vreq) -{ - int rc; - ddi_dma_attr_t dmaattr; - uint_t ndcs, ndws; - ddi_dma_handle_t dh; - ddi_dma_handle_t mdh; - ddi_dma_cookie_t dc; - ddi_acc_handle_t abh; - caddr_t aba; - ge_slot_t *gs; - size_t bufsz; - off_t off; - size_t sz; - buf_t *bp = vreq->v_buf; - int dma_flags = (IS_READ(bp) ? DDI_DMA_READ : DDI_DMA_WRITE) | - DDI_DMA_STREAMING | DDI_DMA_PARTIAL; - - switch (vreq->v_status) { - case VREQ_INIT: - if (IS_FLUSH_DISKCACHE(bp)) { - if ((gs = gs_get(vdp, IS_READ(bp))) == NULL) { - DPRINTF(DMA_DBG, ("xdf@%s: " - "get ge_slotfailed\n", vdp->xdf_addr)); - return (DDI_FAILURE); - } - vreq->v_blkno = 0; - vreq->v_nslots = 1; - vreq->v_flush_diskcache = FLUSH_DISKCACHE; - vreq->v_status = VREQ_GS_ALLOCED; - gs->gs_vreq = vreq; - list_insert_head(&vreq->v_gs, gs); - return (DDI_SUCCESS); - } - - if (IS_WRITE_BARRIER(vdp, bp)) - vreq->v_flush_diskcache = WRITE_BARRIER; - vreq->v_blkno = bp->b_blkno + - (diskaddr_t)(uintptr_t)bp->b_private; - /* See if we wrote new data to our flush block */ - if (!IS_READ(bp) && USE_WRITE_BARRIER(vdp)) - check_fbwrite(vdp, bp, vreq->v_blkno); - vreq->v_status = VREQ_INIT_DONE; - /*FALLTHRU*/ - - case VREQ_INIT_DONE: - /* - * alloc DMA handle - */ - rc = ddi_dma_alloc_handle(vdp->xdf_dip, &xb_dma_attr, - xdf_dmacallback, (caddr_t)vdp, &dh); - if (rc != DDI_SUCCESS) { - SETDMACBON(vdp); - DPRINTF(DMA_DBG, ("xdf@%s: DMA handle alloc failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - - vreq->v_dmahdl = dh; - vreq->v_status = VREQ_DMAHDL_ALLOCED; - /*FALLTHRU*/ - - case VREQ_DMAHDL_ALLOCED: - /* - * alloc dma handle for 512-byte aligned buf - */ - if (!ALIGNED_XFER(bp)) { - /* - * XXPV: we need to temporarily enlarge the seg - * boundary and s/g length to work round CR6381968 - */ - dmaattr = xb_dma_attr; - dmaattr.dma_attr_seg = (uint64_t)-1; - dmaattr.dma_attr_sgllen = INT_MAX; - rc = ddi_dma_alloc_handle(vdp->xdf_dip, &dmaattr, - xdf_dmacallback, (caddr_t)vdp, &mdh); - if (rc != DDI_SUCCESS) { - SETDMACBON(vdp); - DPRINTF(DMA_DBG, ("xdf@%s: " - "unaligned buf DMAhandle alloc failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - vreq->v_memdmahdl = mdh; - vreq->v_status = VREQ_MEMDMAHDL_ALLOCED; - } - /*FALLTHRU*/ - - case VREQ_MEMDMAHDL_ALLOCED: - /* - * alloc 512-byte aligned buf - */ - if (!ALIGNED_XFER(bp)) { - if (bp->b_flags & (B_PAGEIO | B_PHYS)) - bp_mapin(bp); - rc = ddi_dma_mem_alloc(vreq->v_memdmahdl, - roundup(bp->b_bcount, XB_BSIZE), &xc_acc_attr, - DDI_DMA_STREAMING, xdf_dmacallback, (caddr_t)vdp, - &aba, &bufsz, &abh); - if (rc != DDI_SUCCESS) { - SETDMACBON(vdp); - DPRINTF(DMA_DBG, ("xdf@%s: " - "DMA mem allocation failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - - vreq->v_abuf = aba; - vreq->v_align = abh; - vreq->v_status = VREQ_DMAMEM_ALLOCED; - - ASSERT(bufsz >= bp->b_bcount); - if (!IS_READ(bp)) - bcopy(bp->b_un.b_addr, vreq->v_abuf, - bp->b_bcount); - } - /*FALLTHRU*/ - - case VREQ_DMAMEM_ALLOCED: - /* - * dma bind - */ - if (ALIGNED_XFER(bp)) { - rc = ddi_dma_buf_bind_handle(vreq->v_dmahdl, bp, - dma_flags, xdf_dmacallback, (caddr_t)vdp, - &dc, &ndcs); - } else { - rc = ddi_dma_addr_bind_handle(vreq->v_dmahdl, - NULL, vreq->v_abuf, bp->b_bcount, dma_flags, - xdf_dmacallback, (caddr_t)vdp, &dc, &ndcs); - } - if (rc == DDI_DMA_MAPPED || rc == DDI_DMA_PARTIAL_MAP) { - /* get num of dma windows */ - if (rc == DDI_DMA_PARTIAL_MAP) { - rc = ddi_dma_numwin(vreq->v_dmahdl, &ndws); - ASSERT(rc == DDI_SUCCESS); - } else { - ndws = 1; - } - } else { - SETDMACBON(vdp); - DPRINTF(DMA_DBG, ("xdf@%s: DMA bind failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - - vreq->v_dmac = dc; - vreq->v_dmaw = 0; - vreq->v_ndmacs = ndcs; - vreq->v_ndmaws = ndws; - vreq->v_nslots = ndws; - vreq->v_status = VREQ_DMABUF_BOUND; - /*FALLTHRU*/ - - case VREQ_DMABUF_BOUND: - /* - * get ge_slot, callback is set upon failure from gs_get(), - * if not set previously - */ - if ((gs = gs_get(vdp, IS_READ(bp))) == NULL) { - DPRINTF(DMA_DBG, ("xdf@%s: get ge_slot failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - - vreq->v_status = VREQ_GS_ALLOCED; - gs->gs_vreq = vreq; - list_insert_head(&vreq->v_gs, gs); - break; - - case VREQ_GS_ALLOCED: - /* nothing need to be done */ - break; - - case VREQ_DMAWIN_DONE: - /* - * move to the next dma window - */ - ASSERT((vreq->v_dmaw + 1) < vreq->v_ndmaws); - - /* get a ge_slot for this DMA window */ - if ((gs = gs_get(vdp, IS_READ(bp))) == NULL) { - DPRINTF(DMA_DBG, ("xdf@%s: get ge_slot failed\n", - vdp->xdf_addr)); - return (DDI_FAILURE); - } - - vreq->v_dmaw++; - VERIFY(ddi_dma_getwin(vreq->v_dmahdl, vreq->v_dmaw, &off, &sz, - &vreq->v_dmac, &vreq->v_ndmacs) == DDI_SUCCESS); - vreq->v_status = VREQ_GS_ALLOCED; - gs->gs_vreq = vreq; - list_insert_head(&vreq->v_gs, gs); - break; - - default: - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static int -xdf_cmlb_attach(xdf_t *vdp) -{ - dev_info_t *dip = vdp->xdf_dip; - - return (cmlb_attach(dip, &xdf_lb_ops, - XD_IS_CD(vdp) ? DTYPE_RODIRECT : DTYPE_DIRECT, - XD_IS_RM(vdp), - B_TRUE, - XD_IS_CD(vdp) ? DDI_NT_CD_XVMD : DDI_NT_BLOCK_XVMD, -#if defined(XPV_HVM_DRIVER) - (XD_IS_CD(vdp) ? 0 : CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT), -#else /* !XPV_HVM_DRIVER */ - XD_IS_CD(vdp) ? 0 : CMLB_FAKE_LABEL_ONE_PARTITION, -#endif /* !XPV_HVM_DRIVER */ - vdp->xdf_vd_lbl, NULL)); -} - -static void -xdf_io_err(buf_t *bp, int err, size_t resid) -{ - bioerror(bp, err); - if (resid == 0) - bp->b_resid = bp->b_bcount; - biodone(bp); -} - -static void -xdf_kstat_enter(xdf_t *vdp, buf_t *bp) -{ - v_req_t *vreq = BP_VREQ(bp); - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if (vdp->xdf_xdev_iostat == NULL) - return; - if ((vreq != NULL) && vreq->v_runq) { - kstat_runq_enter(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); - } else { - kstat_waitq_enter(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); - } -} - -static void -xdf_kstat_exit(xdf_t *vdp, buf_t *bp) -{ - v_req_t *vreq = BP_VREQ(bp); - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if (vdp->xdf_xdev_iostat == NULL) - return; - - if ((vreq != NULL) && vreq->v_runq) { - kstat_runq_exit(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); - } else { - kstat_waitq_exit(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); - } - - if (bp->b_flags & B_READ) { - KSTAT_IO_PTR(vdp->xdf_xdev_iostat)->reads++; - KSTAT_IO_PTR(vdp->xdf_xdev_iostat)->nread += bp->b_bcount; - } else if (bp->b_flags & B_WRITE) { - KSTAT_IO_PTR(vdp->xdf_xdev_iostat)->writes++; - KSTAT_IO_PTR(vdp->xdf_xdev_iostat)->nwritten += bp->b_bcount; - } -} - -static void -xdf_kstat_waitq_to_runq(xdf_t *vdp, buf_t *bp) -{ - v_req_t *vreq = BP_VREQ(bp); - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(!vreq->v_runq); - - vreq->v_runq = B_TRUE; - if (vdp->xdf_xdev_iostat == NULL) - return; - kstat_waitq_to_runq(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); -} - -static void -xdf_kstat_runq_to_waitq(xdf_t *vdp, buf_t *bp) -{ - v_req_t *vreq = BP_VREQ(bp); - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(vreq->v_runq); - - vreq->v_runq = B_FALSE; - if (vdp->xdf_xdev_iostat == NULL) - return; - kstat_runq_back_to_waitq(KSTAT_IO_PTR(vdp->xdf_xdev_iostat)); -} - -int -xdf_kstat_create(dev_info_t *dip, char *ks_module, int instance) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - kstat_t *kstat; - buf_t *bp; - - if ((kstat = kstat_create( - ks_module, instance, NULL, "disk", - KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT)) == NULL) - return (-1); - - /* See comment about locking in xdf_kstat_delete(). */ - mutex_enter(&vdp->xdf_iostat_lk); - mutex_enter(&vdp->xdf_dev_lk); - - /* only one kstat can exist at a time */ - if (vdp->xdf_xdev_iostat != NULL) { - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_iostat_lk); - kstat_delete(kstat); - return (-1); - } - - vdp->xdf_xdev_iostat = kstat; - vdp->xdf_xdev_iostat->ks_lock = &vdp->xdf_dev_lk; - kstat_install(vdp->xdf_xdev_iostat); - - /* - * Now that we've created a kstat, we need to update the waitq and - * runq counts for the kstat to reflect our current state. - * - * For a buf_t structure to be on the runq, it must have a ring - * buffer slot associated with it. To get a ring buffer slot the - * buf must first have a v_req_t and a ge_slot_t associated with it. - * Then when it is granted a ring buffer slot, v_runq will be set to - * true. - * - * For a buf_t structure to be on the waitq, it must not be on the - * runq. So to find all the buf_t's that should be on waitq, we - * walk the active buf list and add any buf_t's which aren't on the - * runq to the waitq. - */ - bp = vdp->xdf_f_act; - while (bp != NULL) { - xdf_kstat_enter(vdp, bp); - bp = bp->av_forw; - } - if (vdp->xdf_ready_tq_bp != NULL) - xdf_kstat_enter(vdp, vdp->xdf_ready_tq_bp); - - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_iostat_lk); - return (0); -} - -void -xdf_kstat_delete(dev_info_t *dip) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - kstat_t *kstat; - buf_t *bp; - - /* - * The locking order here is xdf_iostat_lk and then xdf_dev_lk. - * xdf_dev_lk is used to protect the xdf_xdev_iostat pointer - * and the contents of the our kstat. xdf_iostat_lk is used - * to protect the allocation and freeing of the actual kstat. - * xdf_dev_lk can't be used for this purpose because kstat - * readers use it to access the contents of the kstat and - * hence it can't be held when calling kstat_delete(). - */ - mutex_enter(&vdp->xdf_iostat_lk); - mutex_enter(&vdp->xdf_dev_lk); - - if (vdp->xdf_xdev_iostat == NULL) { - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_iostat_lk); - return; - } - - /* - * We're about to destroy the kstat structures, so it isn't really - * necessary to update the runq and waitq counts. But, since this - * isn't a hot code path we can afford to be a little pedantic and - * go ahead and decrement the runq and waitq kstat counters to zero - * before free'ing them. This helps us ensure that we've gotten all - * our accounting correct. - * - * For an explanation of how we determine which buffers go on the - * runq vs which go on the waitq, see the comments in - * xdf_kstat_create(). - */ - bp = vdp->xdf_f_act; - while (bp != NULL) { - xdf_kstat_exit(vdp, bp); - bp = bp->av_forw; - } - if (vdp->xdf_ready_tq_bp != NULL) - xdf_kstat_exit(vdp, vdp->xdf_ready_tq_bp); - - kstat = vdp->xdf_xdev_iostat; - vdp->xdf_xdev_iostat = NULL; - mutex_exit(&vdp->xdf_dev_lk); - kstat_delete(kstat); - mutex_exit(&vdp->xdf_iostat_lk); -} - -/* - * Add an IO requests onto the active queue. - * - * We have to detect IOs generated by xdf_ready_tq_thread. These IOs - * are used to establish a connection to the backend, so they recieve - * priority over all other IOs. Since xdf_ready_tq_thread only does - * synchronous IO, there can only be one xdf_ready_tq_thread request at any - * given time and we record the buf associated with that request in - * xdf_ready_tq_bp. - */ -static void -xdf_bp_push(xdf_t *vdp, buf_t *bp) -{ - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(bp->av_forw == NULL); - - xdf_kstat_enter(vdp, bp); - - if (curthread == vdp->xdf_ready_tq_thread) { - /* new IO requests from the ready thread */ - ASSERT(vdp->xdf_ready_tq_bp == NULL); - vdp->xdf_ready_tq_bp = bp; - return; - } - - /* this is normal IO request */ - ASSERT(bp != vdp->xdf_ready_tq_bp); - - if (vdp->xdf_f_act == NULL) { - /* this is only only IO on the active queue */ - ASSERT(vdp->xdf_l_act == NULL); - ASSERT(vdp->xdf_i_act == NULL); - vdp->xdf_f_act = vdp->xdf_l_act = vdp->xdf_i_act = bp; - return; - } - - /* add this IO to the tail of the active queue */ - vdp->xdf_l_act->av_forw = bp; - vdp->xdf_l_act = bp; - if (vdp->xdf_i_act == NULL) - vdp->xdf_i_act = bp; -} - -static void -xdf_bp_pop(xdf_t *vdp, buf_t *bp) -{ - buf_t *bp_iter; - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(VREQ_DONE(BP_VREQ(bp))); - - if (vdp->xdf_ready_tq_bp == bp) { - /* we're done with a ready thread IO request */ - ASSERT(bp->av_forw == NULL); - vdp->xdf_ready_tq_bp = NULL; - return; - } - - /* we're done with a normal IO request */ - ASSERT((bp->av_forw != NULL) || (bp == vdp->xdf_l_act)); - ASSERT((bp->av_forw == NULL) || (bp != vdp->xdf_l_act)); - ASSERT(VREQ_DONE(BP_VREQ(vdp->xdf_f_act))); - ASSERT(vdp->xdf_f_act != vdp->xdf_i_act); - - if (bp == vdp->xdf_f_act) { - /* This IO was at the head of our active queue. */ - vdp->xdf_f_act = bp->av_forw; - if (bp == vdp->xdf_l_act) - vdp->xdf_l_act = NULL; - } else { - /* There IO finished before some other pending IOs. */ - bp_iter = vdp->xdf_f_act; - while (bp != bp_iter->av_forw) { - bp_iter = bp_iter->av_forw; - ASSERT(VREQ_DONE(BP_VREQ(bp_iter))); - ASSERT(bp_iter != vdp->xdf_i_act); - } - bp_iter->av_forw = bp->av_forw; - if (bp == vdp->xdf_l_act) - vdp->xdf_l_act = bp_iter; - } - bp->av_forw = NULL; -} - -static buf_t * -xdf_bp_next(xdf_t *vdp) -{ - v_req_t *vreq; - buf_t *bp; - - if (vdp->xdf_state == XD_CONNECTED) { - /* - * If we're in the XD_CONNECTED state, we only service IOs - * from the xdf_ready_tq_thread thread. - */ - if ((bp = vdp->xdf_ready_tq_bp) == NULL) - return (NULL); - if (((vreq = BP_VREQ(bp)) == NULL) || (!VREQ_DONE(vreq))) - return (bp); - return (NULL); - } - - /* if we're not in the XD_CONNECTED or XD_READY state we can't do IO */ - if (vdp->xdf_state != XD_READY) - return (NULL); - - ASSERT(vdp->xdf_ready_tq_bp == NULL); - for (;;) { - if ((bp = vdp->xdf_i_act) == NULL) - return (NULL); - if (((vreq = BP_VREQ(bp)) == NULL) || (!VREQ_DONE(vreq))) - return (bp); - - /* advance the active buf index pointer */ - vdp->xdf_i_act = bp->av_forw; - } -} - -static void -xdf_io_fini(xdf_t *vdp, uint64_t id, int bioerr) -{ - ge_slot_t *gs = (ge_slot_t *)(uintptr_t)id; - v_req_t *vreq = gs->gs_vreq; - buf_t *bp = vreq->v_buf; - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(BP_VREQ(bp) == vreq); - - gs_free(gs); - - if (bioerr != 0) - bioerror(bp, bioerr); - ASSERT(vreq->v_nslots > 0); - if (--vreq->v_nslots > 0) - return; - - /* remove this IO from our active queue */ - xdf_bp_pop(vdp, bp); - - ASSERT(vreq->v_runq); - xdf_kstat_exit(vdp, bp); - vreq->v_runq = B_FALSE; - vreq_free(vdp, vreq); - - if (IS_ERROR(bp)) { - xdf_io_err(bp, geterror(bp), 0); - } else if (bp->b_resid != 0) { - /* Partial transfers are an error */ - xdf_io_err(bp, EIO, bp->b_resid); - } else { - biodone(bp); - } -} - -/* - * xdf interrupt handler - */ -static uint_t -xdf_intr_locked(xdf_t *vdp) -{ - xendev_ring_t *xbr; - blkif_response_t *resp; - int bioerr; - uint64_t id; - uint8_t op; - uint16_t status; - ddi_acc_handle_t acchdl; - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if ((xbr = vdp->xdf_xb_ring) == NULL) - return (DDI_INTR_UNCLAIMED); - - acchdl = vdp->xdf_xb_ring_hdl; - - /* - * complete all requests which have a response - */ - while (resp = xvdi_ring_get_response(xbr)) { - id = ddi_get64(acchdl, &resp->id); - op = ddi_get8(acchdl, &resp->operation); - status = ddi_get16(acchdl, (uint16_t *)&resp->status); - DPRINTF(INTR_DBG, ("resp: op %d id %"PRIu64" status %d\n", - op, id, status)); - - if (status != BLKIF_RSP_OKAY) { - DPRINTF(IO_DBG, ("xdf@%s: I/O error while %s", - vdp->xdf_addr, - (op == BLKIF_OP_READ) ? "reading" : "writing")); - bioerr = EIO; - } else { - bioerr = 0; - } - - xdf_io_fini(vdp, id, bioerr); - } - return (DDI_INTR_CLAIMED); -} - -/* - * xdf_intr runs at PIL 5, so no one else can grab xdf_dev_lk and - * block at a lower pil. - */ -static uint_t -xdf_intr(caddr_t arg) -{ - xdf_t *vdp = (xdf_t *)arg; - int rv; - - mutex_enter(&vdp->xdf_dev_lk); - rv = xdf_intr_locked(vdp); - mutex_exit(&vdp->xdf_dev_lk); - - if (!do_polled_io) - xdf_io_start(vdp); - - return (rv); -} - -static void -xdf_ring_push(xdf_t *vdp) -{ - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if (vdp->xdf_xb_ring == NULL) - return; - - if (xvdi_ring_push_request(vdp->xdf_xb_ring)) { - DPRINTF(IO_DBG, ( - "xdf@%s: xdf_ring_push: sent request(s) to backend\n", - vdp->xdf_addr)); - } - - if (xvdi_get_evtchn(vdp->xdf_dip) != INVALID_EVTCHN) - xvdi_notify_oe(vdp->xdf_dip); -} - -static int -xdf_ring_drain_locked(xdf_t *vdp) -{ - int pollc, rv = 0; - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf_ring_drain: start\n"); - - for (pollc = 0; pollc < XDF_DRAIN_RETRY_COUNT; pollc++) { - if (vdp->xdf_xb_ring == NULL) - goto out; - - if (xvdi_ring_has_unconsumed_responses(vdp->xdf_xb_ring)) - (void) xdf_intr_locked(vdp); - if (!xvdi_ring_has_incomp_request(vdp->xdf_xb_ring)) - goto out; - xdf_ring_push(vdp); - - /* file-backed devices can be slow */ - mutex_exit(&vdp->xdf_dev_lk); -#ifdef XPV_HVM_DRIVER - (void) HYPERVISOR_yield(); -#endif /* XPV_HVM_DRIVER */ - delay(drv_usectohz(XDF_DRAIN_MSEC_DELAY)); - mutex_enter(&vdp->xdf_dev_lk); - } - cmn_err(CE_WARN, "xdf@%s: xdf_ring_drain: timeout", vdp->xdf_addr); - -out: - if (vdp->xdf_xb_ring != NULL) { - if (xvdi_ring_has_incomp_request(vdp->xdf_xb_ring) || - xvdi_ring_has_unconsumed_responses(vdp->xdf_xb_ring)) - rv = EIO; - } - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_ring_drain: end, err=%d\n", - vdp->xdf_addr, rv); - return (rv); -} - -static int -xdf_ring_drain(xdf_t *vdp) -{ - int rv; - mutex_enter(&vdp->xdf_dev_lk); - rv = xdf_ring_drain_locked(vdp); - mutex_exit(&vdp->xdf_dev_lk); - return (rv); -} - -/* - * Destroy all v_req_t, grant table entries, and our ring buffer. - */ -static void -xdf_ring_destroy(xdf_t *vdp) -{ - v_req_t *vreq; - buf_t *bp; - ge_slot_t *gs; - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if ((vdp->xdf_state != XD_INIT) && - (vdp->xdf_state != XD_CONNECTED) && - (vdp->xdf_state != XD_READY)) { - ASSERT(vdp->xdf_xb_ring == NULL); - ASSERT(vdp->xdf_xb_ring_hdl == NULL); - ASSERT(vdp->xdf_peer == INVALID_DOMID); - ASSERT(vdp->xdf_evtchn == INVALID_EVTCHN); - ASSERT(list_is_empty(&vdp->xdf_vreq_act)); - return; - } - - /* - * We don't want to recieve async notifications from the backend - * when it finishes processing ring entries. - */ -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(vdp->xdf_evtchn); -#else /* !XPV_HVM_DRIVER */ - (void) ddi_remove_intr(vdp->xdf_dip, 0, NULL); -#endif /* !XPV_HVM_DRIVER */ - - /* - * Drain any requests in the ring. We need to do this before we - * can free grant table entries, because if active ring entries - * point to grants, then the backend could be trying to access - * those grants. - */ - (void) xdf_ring_drain_locked(vdp); - - /* We're done talking to the backend so free up our event channel */ - xvdi_free_evtchn(vdp->xdf_dip); - vdp->xdf_evtchn = INVALID_EVTCHN; - - while ((vreq = list_head(&vdp->xdf_vreq_act)) != NULL) { - bp = vreq->v_buf; - ASSERT(BP_VREQ(bp) == vreq); - - /* Free up any grant table entries associaed with this IO */ - while ((gs = list_head(&vreq->v_gs)) != NULL) - gs_free(gs); - - /* If this IO was on the runq, move it back to the waitq. */ - if (vreq->v_runq) - xdf_kstat_runq_to_waitq(vdp, bp); - - /* - * Reset any buf IO state since we're going to re-issue the - * IO when we reconnect. - */ - vreq_free(vdp, vreq); - BP_VREQ_SET(bp, NULL); - bioerror(bp, 0); - } - - /* reset the active queue index pointer */ - vdp->xdf_i_act = vdp->xdf_f_act; - - /* Destroy the ring */ - xvdi_free_ring(vdp->xdf_xb_ring); - vdp->xdf_xb_ring = NULL; - vdp->xdf_xb_ring_hdl = NULL; - vdp->xdf_peer = INVALID_DOMID; -} - -void -xdfmin(struct buf *bp) -{ - if (bp->b_bcount > xdf_maxphys) - bp->b_bcount = xdf_maxphys; -} - -/* - * Check if we have a pending "eject" media request. - */ -static int -xdf_eject_pending(xdf_t *vdp) -{ - dev_info_t *dip = vdp->xdf_dip; - char *xsname, *str; - - if (!vdp->xdf_media_req_supported) - return (B_FALSE); - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - (xenbus_read_str(xsname, XBP_MEDIA_REQ, &str) != 0)) - return (B_FALSE); - - if (strcmp(str, XBV_MEDIA_REQ_EJECT) != 0) { - strfree(str); - return (B_FALSE); - } - strfree(str); - return (B_TRUE); -} - -/* - * Generate a media request. - */ -static int -xdf_media_req(xdf_t *vdp, char *req, boolean_t media_required) -{ - dev_info_t *dip = vdp->xdf_dip; - char *xsname; - - /* - * we can't be holding xdf_dev_lk because xenbus_printf() can - * block while waiting for a PIL 1 interrupt message. this - * would cause a deadlock with xdf_intr() which needs to grab - * xdf_dev_lk as well and runs at PIL 5. - */ - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_NOT_HELD(&vdp->xdf_dev_lk)); - - if ((xsname = xvdi_get_xsname(dip)) == NULL) - return (ENXIO); - - /* Check if we support media requests */ - if (!XD_IS_CD(vdp) || !vdp->xdf_media_req_supported) - return (ENOTTY); - - /* If an eject is pending then don't allow any new requests */ - if (xdf_eject_pending(vdp)) - return (ENXIO); - - /* Make sure that there is media present */ - if (media_required && (vdp->xdf_xdev_nblocks == 0)) - return (ENXIO); - - /* We only allow operations when the device is ready and connected */ - if (vdp->xdf_state != XD_READY) - return (EIO); - - if (xenbus_printf(XBT_NULL, xsname, XBP_MEDIA_REQ, "%s", req) != 0) - return (EIO); - - return (0); -} - -/* - * populate a single blkif_request_t w/ a buf - */ -static void -xdf_process_rreq(xdf_t *vdp, struct buf *bp, blkif_request_t *rreq) -{ - grant_ref_t gr; - uint8_t fsect, lsect; - size_t bcnt; - paddr_t dma_addr; - off_t blk_off; - dev_info_t *dip = vdp->xdf_dip; - blkif_vdev_t vdev = xvdi_get_vdevnum(dip); - v_req_t *vreq = BP_VREQ(bp); - uint64_t blkno = vreq->v_blkno; - uint_t ndmacs = vreq->v_ndmacs; - ddi_acc_handle_t acchdl = vdp->xdf_xb_ring_hdl; - int seg = 0; - int isread = IS_READ(bp); - ge_slot_t *gs = list_head(&vreq->v_gs); - - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - ASSERT(vreq->v_status == VREQ_GS_ALLOCED); - - if (isread) - ddi_put8(acchdl, &rreq->operation, BLKIF_OP_READ); - else { - switch (vreq->v_flush_diskcache) { - case FLUSH_DISKCACHE: - ddi_put8(acchdl, &rreq->operation, - BLKIF_OP_FLUSH_DISKCACHE); - ddi_put16(acchdl, &rreq->handle, vdev); - ddi_put64(acchdl, &rreq->id, - (uint64_t)(uintptr_t)(gs)); - ddi_put8(acchdl, &rreq->nr_segments, 0); - vreq->v_status = VREQ_DMAWIN_DONE; - return; - case WRITE_BARRIER: - ddi_put8(acchdl, &rreq->operation, - BLKIF_OP_WRITE_BARRIER); - break; - default: - if (!vdp->xdf_wce) - ddi_put8(acchdl, &rreq->operation, - BLKIF_OP_WRITE_BARRIER); - else - ddi_put8(acchdl, &rreq->operation, - BLKIF_OP_WRITE); - break; - } - } - - ddi_put16(acchdl, &rreq->handle, vdev); - ddi_put64(acchdl, &rreq->sector_number, blkno); - ddi_put64(acchdl, &rreq->id, (uint64_t)(uintptr_t)(gs)); - - /* - * loop until all segments are populated or no more dma cookie in buf - */ - for (;;) { - /* - * Each segment of a blkif request can transfer up to - * one 4K page of data. - */ - bcnt = vreq->v_dmac.dmac_size; - dma_addr = vreq->v_dmac.dmac_laddress; - blk_off = (uint_t)((paddr_t)XB_SEGOFFSET & dma_addr); - fsect = blk_off >> XB_BSHIFT; - lsect = fsect + (bcnt >> XB_BSHIFT) - 1; - - ASSERT(bcnt <= PAGESIZE); - ASSERT((bcnt % XB_BSIZE) == 0); - ASSERT((blk_off & XB_BMASK) == 0); - ASSERT(fsect < XB_MAX_SEGLEN / XB_BSIZE && - lsect < XB_MAX_SEGLEN / XB_BSIZE); - - gr = gs_grant(gs, PATOMA(dma_addr) >> PAGESHIFT); - ddi_put32(acchdl, &rreq->seg[seg].gref, gr); - ddi_put8(acchdl, &rreq->seg[seg].first_sect, fsect); - ddi_put8(acchdl, &rreq->seg[seg].last_sect, lsect); - - DPRINTF(IO_DBG, ( - "xdf@%s: seg%d: dmacS %lu blk_off %ld\n", - vdp->xdf_addr, seg, vreq->v_dmac.dmac_size, blk_off)); - DPRINTF(IO_DBG, ( - "xdf@%s: seg%d: fs %d ls %d gr %d dma 0x%"PRIx64"\n", - vdp->xdf_addr, seg, fsect, lsect, gr, dma_addr)); - - blkno += (bcnt >> XB_BSHIFT); - seg++; - ASSERT(seg <= BLKIF_MAX_SEGMENTS_PER_REQUEST); - if (--ndmacs) { - ddi_dma_nextcookie(vreq->v_dmahdl, &vreq->v_dmac); - continue; - } - - vreq->v_status = VREQ_DMAWIN_DONE; - vreq->v_blkno = blkno; - break; - } - ddi_put8(acchdl, &rreq->nr_segments, seg); - DPRINTF(IO_DBG, ( - "xdf@%s: xdf_process_rreq: request id=%"PRIx64" ready\n", - vdp->xdf_addr, rreq->id)); -} - -static void -xdf_io_start(xdf_t *vdp) -{ - struct buf *bp; - v_req_t *vreq; - blkif_request_t *rreq; - boolean_t rreqready = B_FALSE; - - mutex_enter(&vdp->xdf_dev_lk); - - /* - * Populate the ring request(s). Loop until there is no buf to - * transfer or no free slot available in I/O ring. - */ - for (;;) { - /* don't start any new IO if we're suspending */ - if (vdp->xdf_suspending) - break; - if ((bp = xdf_bp_next(vdp)) == NULL) - break; - - /* if the buf doesn't already have a vreq, allocate one */ - if (((vreq = BP_VREQ(bp)) == NULL) && - ((vreq = vreq_get(vdp, bp)) == NULL)) - break; - - /* alloc DMA/GTE resources */ - if (vreq_setup(vdp, vreq) != DDI_SUCCESS) - break; - - /* get next blkif_request in the ring */ - if ((rreq = xvdi_ring_get_request(vdp->xdf_xb_ring)) == NULL) - break; - bzero(rreq, sizeof (blkif_request_t)); - rreqready = B_TRUE; - - /* populate blkif_request with this buf */ - xdf_process_rreq(vdp, bp, rreq); - - /* - * This buffer/vreq pair is has been allocated a ring buffer - * resources, so if it isn't already in our runq, add it. - */ - if (!vreq->v_runq) - xdf_kstat_waitq_to_runq(vdp, bp); - } - - /* Send the request(s) to the backend */ - if (rreqready) - xdf_ring_push(vdp); - - mutex_exit(&vdp->xdf_dev_lk); -} - - -/* check if partition is open, -1 - check all partitions on the disk */ -static boolean_t -xdf_isopen(xdf_t *vdp, int partition) -{ - int i; - ulong_t parbit; - boolean_t rval = B_FALSE; - - ASSERT((partition == -1) || - ((partition >= 0) || (partition < XDF_PEXT))); - - if (partition == -1) - parbit = (ulong_t)-1; - else - parbit = 1 << partition; - - for (i = 0; i < OTYPCNT; i++) { - if (vdp->xdf_vd_open[i] & parbit) - rval = B_TRUE; - } - - return (rval); -} - -/* - * The connection should never be closed as long as someone is holding - * us open, there is pending IO, or someone is waiting waiting for a - * connection. - */ -static boolean_t -xdf_busy(xdf_t *vdp) -{ - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if ((vdp->xdf_xb_ring != NULL) && - xvdi_ring_has_unconsumed_responses(vdp->xdf_xb_ring)) { - ASSERT(vdp->xdf_state != XD_CLOSED); - return (B_TRUE); - } - - if (!list_is_empty(&vdp->xdf_vreq_act) || (vdp->xdf_f_act != NULL)) { - ASSERT(vdp->xdf_state != XD_CLOSED); - return (B_TRUE); - } - - if (xdf_isopen(vdp, -1)) { - ASSERT(vdp->xdf_state != XD_CLOSED); - return (B_TRUE); - } - - if (vdp->xdf_connect_req > 0) { - ASSERT(vdp->xdf_state != XD_CLOSED); - return (B_TRUE); - } - - return (B_FALSE); -} - -static void -xdf_set_state(xdf_t *vdp, xdf_state_t new_state) -{ - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - DPRINTF(DDI_DBG, ("xdf@%s: state change %d -> %d\n", - vdp->xdf_addr, vdp->xdf_state, new_state)); - vdp->xdf_state = new_state; - cv_broadcast(&vdp->xdf_dev_cv); -} - -static void -xdf_disconnect(xdf_t *vdp, xdf_state_t new_state, boolean_t quiet) -{ - dev_info_t *dip = vdp->xdf_dip; - boolean_t busy; - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_NOT_HELD(&vdp->xdf_dev_lk)); - ASSERT((new_state == XD_UNKNOWN) || (new_state == XD_CLOSED)); - - /* Check if we're already there. */ - if (vdp->xdf_state == new_state) - return; - - mutex_enter(&vdp->xdf_dev_lk); - busy = xdf_busy(vdp); - - /* If we're already closed then there's nothing todo. */ - if (vdp->xdf_state == XD_CLOSED) { - ASSERT(!busy); - xdf_set_state(vdp, new_state); - mutex_exit(&vdp->xdf_dev_lk); - return; - } - -#ifdef DEBUG - /* UhOh. Warn the user that something bad has happened. */ - if (!quiet && busy && (vdp->xdf_state == XD_READY) && - (vdp->xdf_xdev_nblocks != 0)) { - cmn_err(CE_WARN, "xdf@%s: disconnected while in use", - vdp->xdf_addr); - } -#endif /* DEBUG */ - - xdf_ring_destroy(vdp); - - /* If we're busy then we can only go into the unknown state */ - xdf_set_state(vdp, (busy) ? XD_UNKNOWN : new_state); - mutex_exit(&vdp->xdf_dev_lk); - - /* if we're closed now, let the other end know */ - if (vdp->xdf_state == XD_CLOSED) - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed); -} - - -/* - * Kick-off connect process - * Status should be XD_UNKNOWN or XD_CLOSED - * On success, status will be changed to XD_INIT - * On error, it will be changed to XD_UNKNOWN - */ -static int -xdf_setstate_init(xdf_t *vdp) -{ - dev_info_t *dip = vdp->xdf_dip; - xenbus_transaction_t xbt; - grant_ref_t gref; - char *xsname, *str; - int rv; - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_NOT_HELD(&vdp->xdf_dev_lk)); - ASSERT((vdp->xdf_state == XD_UNKNOWN) || - (vdp->xdf_state == XD_CLOSED)); - - DPRINTF(DDI_DBG, - ("xdf@%s: starting connection process\n", vdp->xdf_addr)); - - /* - * If an eject is pending then don't allow a new connection. - * (Only the backend can clear media request eject request.) - */ - if (xdf_eject_pending(vdp)) - return (DDI_FAILURE); - - if ((xsname = xvdi_get_xsname(dip)) == NULL) - goto errout; - - if ((vdp->xdf_peer = xvdi_get_oeid(dip)) == INVALID_DOMID) - goto errout; - - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialising); - - /* - * Sanity check for the existance of the xenbus device-type property. - * This property might not exist if we our xenbus device nodes was - * force destroyed while we were still connected to the backend. - */ - if (xenbus_read_str(xsname, XBP_DEV_TYPE, &str) != 0) - goto errout; - strfree(str); - - if (xvdi_alloc_evtchn(dip) != DDI_SUCCESS) - goto errout; - - vdp->xdf_evtchn = xvdi_get_evtchn(dip); -#ifdef XPV_HVM_DRIVER - ec_bind_evtchn_to_handler(vdp->xdf_evtchn, IPL_VBD, xdf_intr, vdp); -#else /* !XPV_HVM_DRIVER */ - if (ddi_add_intr(dip, 0, NULL, NULL, xdf_intr, (caddr_t)vdp) != - DDI_SUCCESS) { - cmn_err(CE_WARN, "xdf@%s: xdf_setstate_init: " - "failed to add intr handler", vdp->xdf_addr); - goto errout1; - } -#endif /* !XPV_HVM_DRIVER */ - - if (xvdi_alloc_ring(dip, BLKIF_RING_SIZE, - sizeof (union blkif_sring_entry), &gref, &vdp->xdf_xb_ring) != - DDI_SUCCESS) { - cmn_err(CE_WARN, "xdf@%s: failed to alloc comm ring", - vdp->xdf_addr); - goto errout2; - } - vdp->xdf_xb_ring_hdl = vdp->xdf_xb_ring->xr_acc_hdl; /* ugly!! */ - - /* - * Write into xenstore the info needed by backend - */ -trans_retry: - if (xenbus_transaction_start(&xbt)) { - cmn_err(CE_WARN, "xdf@%s: failed to start transaction", - vdp->xdf_addr); - xvdi_fatal_error(dip, EIO, "connect transaction init"); - goto fail_trans; - } - - /* - * XBP_PROTOCOL is written by the domain builder in the case of PV - * domains. However, it is not written for HVM domains, so let's - * write it here. - */ - if (((rv = xenbus_printf(xbt, xsname, - XBP_MEDIA_REQ, "%s", XBV_MEDIA_REQ_NONE)) != 0) || - ((rv = xenbus_printf(xbt, xsname, - XBP_RING_REF, "%u", gref)) != 0) || - ((rv = xenbus_printf(xbt, xsname, - XBP_EVENT_CHAN, "%u", vdp->xdf_evtchn)) != 0) || - ((rv = xenbus_printf(xbt, xsname, - XBP_PROTOCOL, "%s", XEN_IO_PROTO_ABI_NATIVE)) != 0) || - ((rv = xvdi_switch_state(dip, xbt, XenbusStateInitialised)) > 0)) { - (void) xenbus_transaction_end(xbt, 1); - xvdi_fatal_error(dip, rv, "connect transaction setup"); - goto fail_trans; - } - - /* kick-off connect process */ - if (rv = xenbus_transaction_end(xbt, 0)) { - if (rv == EAGAIN) - goto trans_retry; - xvdi_fatal_error(dip, rv, "connect transaction commit"); - goto fail_trans; - } - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - mutex_enter(&vdp->xdf_dev_lk); - xdf_set_state(vdp, XD_INIT); - mutex_exit(&vdp->xdf_dev_lk); - - return (DDI_SUCCESS); - -fail_trans: - xvdi_free_ring(vdp->xdf_xb_ring); -errout2: -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(vdp->xdf_evtchn); -#else /* !XPV_HVM_DRIVER */ - (void) ddi_remove_intr(vdp->xdf_dip, 0, NULL); -#endif /* !XPV_HVM_DRIVER */ -errout1: - xvdi_free_evtchn(dip); - vdp->xdf_evtchn = INVALID_EVTCHN; -errout: - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - cmn_err(CE_WARN, "xdf@%s: failed to start connection to backend", - vdp->xdf_addr); - return (DDI_FAILURE); -} - -int -xdf_get_flush_block(xdf_t *vdp) -{ - /* - * Get a DEV_BSIZE aligned bufer - */ - vdp->xdf_flush_mem = kmem_alloc(vdp->xdf_xdev_secsize * 2, KM_SLEEP); - vdp->xdf_cache_flush_block = - (char *)P2ROUNDUP((uintptr_t)(vdp->xdf_flush_mem), - (int)vdp->xdf_xdev_secsize); - - if (xdf_lb_rdwr(vdp->xdf_dip, TG_READ, vdp->xdf_cache_flush_block, - xdf_flush_block, vdp->xdf_xdev_secsize, NULL) != 0) - return (DDI_FAILURE); - return (DDI_SUCCESS); -} - -static void -xdf_setstate_ready(void *arg) -{ - xdf_t *vdp = (xdf_t *)arg; - - vdp->xdf_ready_tq_thread = curthread; - - /* - * We've created all the minor nodes via cmlb_attach() using default - * value in xdf_attach() to make it possible to block in xdf_open(), - * in case there's anyone (say, booting thread) ever trying to open - * it before connected to backend. We will refresh all those minor - * nodes w/ latest info we've got now when we are almost connected. - */ - mutex_enter(&vdp->xdf_dev_lk); - if (vdp->xdf_cmbl_reattach) { - vdp->xdf_cmbl_reattach = B_FALSE; - - mutex_exit(&vdp->xdf_dev_lk); - if (xdf_cmlb_attach(vdp) != 0) { - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - return; - } - mutex_enter(&vdp->xdf_dev_lk); - } - - /* If we're not still trying to get to the ready state, then bail. */ - if (vdp->xdf_state != XD_CONNECTED) { - mutex_exit(&vdp->xdf_dev_lk); - return; - } - mutex_exit(&vdp->xdf_dev_lk); - - /* - * If backend has feature-barrier, see if it supports disk - * cache flush op. - */ - vdp->xdf_flush_supported = B_FALSE; - if (vdp->xdf_feature_barrier) { - /* - * Pretend we already know flush is supported so probe - * will attempt the correct op. - */ - vdp->xdf_flush_supported = B_TRUE; - if (xdf_lb_rdwr(vdp->xdf_dip, TG_WRITE, NULL, 0, 0, 0) == 0) { - vdp->xdf_flush_supported = B_TRUE; - } else { - vdp->xdf_flush_supported = B_FALSE; - /* - * If the other end does not support the cache flush op - * then we must use a barrier-write to force disk - * cache flushing. Barrier writes require that a data - * block actually be written. - * Cache a block to barrier-write when we are - * asked to perform a flush. - * XXX - would it be better to just copy 1 block - * (512 bytes) from whatever write we did last - * and rewrite that block? - */ - if (xdf_get_flush_block(vdp) != DDI_SUCCESS) { - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - return; - } - } - } - - mutex_enter(&vdp->xdf_cb_lk); - mutex_enter(&vdp->xdf_dev_lk); - if (vdp->xdf_state == XD_CONNECTED) - xdf_set_state(vdp, XD_READY); - mutex_exit(&vdp->xdf_dev_lk); - - /* Restart any currently queued up io */ - xdf_io_start(vdp); - - mutex_exit(&vdp->xdf_cb_lk); -} - -/* - * synthetic geometry - */ -#define XDF_NSECTS 256 -#define XDF_NHEADS 16 - -static void -xdf_synthetic_pgeom(dev_info_t *dip, cmlb_geom_t *geomp) -{ - xdf_t *vdp; - uint_t ncyl; - - vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip)); - - ncyl = vdp->xdf_xdev_nblocks / (XDF_NHEADS * XDF_NSECTS); - - bzero(geomp, sizeof (*geomp)); - geomp->g_ncyl = ncyl == 0 ? 1 : ncyl; - geomp->g_acyl = 0; - geomp->g_nhead = XDF_NHEADS; - geomp->g_nsect = XDF_NSECTS; - geomp->g_secsize = vdp->xdf_xdev_secsize; - geomp->g_capacity = vdp->xdf_xdev_nblocks; - geomp->g_intrlv = 0; - geomp->g_rpm = 7200; -} - -/* - * Finish other initialization after we've connected to backend - * Status should be XD_INIT before calling this routine - * On success, status should be changed to XD_CONNECTED. - * On error, status should stay XD_INIT - */ -static int -xdf_setstate_connected(xdf_t *vdp) -{ - dev_info_t *dip = vdp->xdf_dip; - cmlb_geom_t pgeom; - diskaddr_t nblocks = 0; - uint_t secsize = 0; - char *oename, *xsname, *str; - uint_t dinfo; - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_NOT_HELD(&vdp->xdf_dev_lk)); - ASSERT(vdp->xdf_state == XD_INIT); - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((oename = xvdi_get_oename(dip)) == NULL)) - return (DDI_FAILURE); - - /* Make sure the other end is XenbusStateConnected */ - if (xenbus_read_driver_state(oename) != XenbusStateConnected) - return (DDI_FAILURE); - - /* Determine if feature barrier is supported by backend */ - if (!(vdp->xdf_feature_barrier = xenbus_exists(oename, XBP_FB))) - cmn_err(CE_NOTE, "!xdf@%s: feature-barrier not supported", - vdp->xdf_addr); - - /* - * Probe backend. Read the device size into xdf_xdev_nblocks - * and set the VDISK_READONLY, VDISK_CDROM, and VDISK_REMOVABLE - * flags in xdf_dinfo. If the emulated device type is "cdrom", - * we always set VDISK_CDROM, regardless of if it's present in - * the xenbus info parameter. - */ - if (xenbus_gather(XBT_NULL, oename, - XBP_SECTORS, "%"SCNu64, &nblocks, - XBP_SECTOR_SIZE, "%u", &secsize, - XBP_INFO, "%u", &dinfo, - NULL) != 0) { - cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " - "cannot read backend info", vdp->xdf_addr); - return (DDI_FAILURE); - } - if (xenbus_read_str(xsname, XBP_DEV_TYPE, &str) != 0) { - cmn_err(CE_WARN, "xdf@%s: cannot read device-type", - vdp->xdf_addr); - return (DDI_FAILURE); - } - if (strcmp(str, XBV_DEV_TYPE_CD) == 0) - dinfo |= VDISK_CDROM; - strfree(str); - - if (secsize == 0 || !(ISP2(secsize / DEV_BSIZE))) - secsize = DEV_BSIZE; - vdp->xdf_xdev_nblocks = nblocks; - vdp->xdf_xdev_secsize = secsize; -#ifdef _ILP32 - if (vdp->xdf_xdev_nblocks > DK_MAX_BLOCKS) { - cmn_err(CE_WARN, "xdf@%s: xdf_setstate_connected: " - "backend disk device too large with %llu blocks for" - " 32-bit kernel", vdp->xdf_addr, vdp->xdf_xdev_nblocks); - xvdi_fatal_error(dip, EFBIG, "reading backend info"); - return (DDI_FAILURE); - } -#endif - - /* - * If the physical geometry for a fixed disk has been explicity - * set then make sure that the specified physical geometry isn't - * larger than the device we connected to. - */ - if (vdp->xdf_pgeom_fixed && - (vdp->xdf_pgeom.g_capacity > vdp->xdf_xdev_nblocks)) { - cmn_err(CE_WARN, - "xdf@%s: connect failed, fixed geometry too large", - vdp->xdf_addr); - return (DDI_FAILURE); - } - - vdp->xdf_media_req_supported = xenbus_exists(oename, XBP_MEDIA_REQ_SUP); - - /* mark vbd is ready for I/O */ - mutex_enter(&vdp->xdf_dev_lk); - xdf_set_state(vdp, XD_CONNECTED); - - /* check if the cmlb label should be updated */ - xdf_synthetic_pgeom(dip, &pgeom); - if ((vdp->xdf_dinfo != dinfo) || - (!vdp->xdf_pgeom_fixed && - (memcmp(&vdp->xdf_pgeom, &pgeom, sizeof (pgeom)) != 0))) { - vdp->xdf_cmbl_reattach = B_TRUE; - - vdp->xdf_dinfo = dinfo; - if (!vdp->xdf_pgeom_fixed) - vdp->xdf_pgeom = pgeom; - } - - if (XD_IS_CD(vdp) || XD_IS_RM(vdp)) { - if (vdp->xdf_xdev_nblocks == 0) { - vdp->xdf_mstate = DKIO_EJECTED; - cv_broadcast(&vdp->xdf_mstate_cv); - } else { - vdp->xdf_mstate = DKIO_INSERTED; - cv_broadcast(&vdp->xdf_mstate_cv); - } - } else { - if (vdp->xdf_mstate != DKIO_NONE) { - vdp->xdf_mstate = DKIO_NONE; - cv_broadcast(&vdp->xdf_mstate_cv); - } - } - - mutex_exit(&vdp->xdf_dev_lk); - - cmn_err(CE_CONT, "?xdf@%s: %"PRIu64" blocks", vdp->xdf_addr, - (uint64_t)vdp->xdf_xdev_nblocks); - - /* Restart any currently queued up io */ - xdf_io_start(vdp); - - /* - * To get to the ready state we have to do IO to the backend device, - * but we can't initiate IO from the other end change callback thread - * (which is the current context we're executing in.) This is because - * if the other end disconnects while we're doing IO from the callback - * thread, then we can't recieve that disconnect event and we hang - * waiting for an IO that can never complete. - */ - (void) ddi_taskq_dispatch(vdp->xdf_ready_tq, xdf_setstate_ready, vdp, - DDI_SLEEP); - - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateConnected); - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static void -xdf_oe_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, void *impl_data) -{ - XenbusState new_state = *(XenbusState *)impl_data; - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - - DPRINTF(DDI_DBG, ("xdf@%s: otherend state change to %d!\n", - vdp->xdf_addr, new_state)); - - mutex_enter(&vdp->xdf_cb_lk); - - /* We assume that this callback is single threaded */ - ASSERT(vdp->xdf_oe_change_thread == NULL); - DEBUG_EVAL(vdp->xdf_oe_change_thread = curthread); - - /* ignore any backend state changes if we're suspending/suspended */ - if (vdp->xdf_suspending || (vdp->xdf_state == XD_SUSPEND)) { - DEBUG_EVAL(vdp->xdf_oe_change_thread = NULL); - mutex_exit(&vdp->xdf_cb_lk); - return; - } - - switch (new_state) { - case XenbusStateUnknown: - case XenbusStateInitialising: - case XenbusStateInitWait: - case XenbusStateInitialised: - if (vdp->xdf_state == XD_INIT) - break; - - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - if (xdf_setstate_init(vdp) != DDI_SUCCESS) - break; - ASSERT(vdp->xdf_state == XD_INIT); - break; - - case XenbusStateConnected: - if ((vdp->xdf_state == XD_CONNECTED) || - (vdp->xdf_state == XD_READY)) - break; - - if (vdp->xdf_state != XD_INIT) { - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - if (xdf_setstate_init(vdp) != DDI_SUCCESS) - break; - ASSERT(vdp->xdf_state == XD_INIT); - } - - if (xdf_setstate_connected(vdp) != DDI_SUCCESS) { - xdf_disconnect(vdp, XD_UNKNOWN, B_FALSE); - break; - } - ASSERT(vdp->xdf_state == XD_CONNECTED); - break; - - case XenbusStateClosing: - if (xdf_isopen(vdp, -1)) { - cmn_err(CE_NOTE, - "xdf@%s: hot-unplug failed, still in use", - vdp->xdf_addr); - break; - } - /*FALLTHROUGH*/ - case XenbusStateClosed: - xdf_disconnect(vdp, XD_CLOSED, B_FALSE); - break; - } - - /* notify anybody waiting for oe state change */ - cv_broadcast(&vdp->xdf_dev_cv); - DEBUG_EVAL(vdp->xdf_oe_change_thread = NULL); - mutex_exit(&vdp->xdf_cb_lk); -} - -static int -xdf_connect_locked(xdf_t *vdp, boolean_t wait) -{ - int rv, timeouts = 0, reset = 20; - - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - /* we can't connect once we're in the closed state */ - if (vdp->xdf_state == XD_CLOSED) - return (XD_CLOSED); - - vdp->xdf_connect_req++; - while (vdp->xdf_state != XD_READY) { - mutex_exit(&vdp->xdf_dev_lk); - - /* only one thread at a time can be the connection thread */ - if (vdp->xdf_connect_thread == NULL) - vdp->xdf_connect_thread = curthread; - - if (vdp->xdf_connect_thread == curthread) { - if ((timeouts > 0) && ((timeouts % reset) == 0)) { - /* - * If we haven't establised a connection - * within the reset time, then disconnect - * so we can try again, and double the reset - * time. The reset time starts at 2 sec. - */ - (void) xdf_disconnect(vdp, XD_UNKNOWN, B_TRUE); - reset *= 2; - } - if (vdp->xdf_state == XD_UNKNOWN) - (void) xdf_setstate_init(vdp); - if (vdp->xdf_state == XD_INIT) - (void) xdf_setstate_connected(vdp); - } - - mutex_enter(&vdp->xdf_dev_lk); - if (!wait || (vdp->xdf_state == XD_READY)) - goto out; - - mutex_exit((&vdp->xdf_cb_lk)); - if (vdp->xdf_connect_thread != curthread) { - rv = cv_wait_sig(&vdp->xdf_dev_cv, &vdp->xdf_dev_lk); - } else { - /* delay for 0.1 sec */ - rv = cv_reltimedwait_sig(&vdp->xdf_dev_cv, - &vdp->xdf_dev_lk, drv_usectohz(100*1000), - TR_CLOCK_TICK); - if (rv == -1) - timeouts++; - } - mutex_exit((&vdp->xdf_dev_lk)); - mutex_enter((&vdp->xdf_cb_lk)); - mutex_enter((&vdp->xdf_dev_lk)); - if (rv == 0) - goto out; - } - -out: - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(MUTEX_HELD(&vdp->xdf_dev_lk)); - - if (vdp->xdf_connect_thread == curthread) { - /* - * wake up someone else so they can become the connection - * thread. - */ - cv_signal(&vdp->xdf_dev_cv); - vdp->xdf_connect_thread = NULL; - } - - /* Try to lock the media */ - mutex_exit((&vdp->xdf_dev_lk)); - (void) xdf_media_req(vdp, XBV_MEDIA_REQ_LOCK, B_TRUE); - mutex_enter((&vdp->xdf_dev_lk)); - - vdp->xdf_connect_req--; - return (vdp->xdf_state); -} - -static uint_t -xdf_iorestart(caddr_t arg) -{ - xdf_t *vdp = (xdf_t *)arg; - - ASSERT(vdp != NULL); - - mutex_enter(&vdp->xdf_dev_lk); - ASSERT(ISDMACBON(vdp)); - SETDMACBOFF(vdp); - mutex_exit(&vdp->xdf_dev_lk); - - xdf_io_start(vdp); - - return (DDI_INTR_CLAIMED); -} - -#if defined(XPV_HVM_DRIVER) - -typedef struct xdf_hvm_entry { - list_node_t xdf_he_list; - char *xdf_he_path; - dev_info_t *xdf_he_dip; -} xdf_hvm_entry_t; - -static list_t xdf_hvm_list; -static kmutex_t xdf_hvm_list_lock; - -static xdf_hvm_entry_t * -i_xdf_hvm_find(const char *path, dev_info_t *dip) -{ - xdf_hvm_entry_t *i; - - ASSERT((path != NULL) || (dip != NULL)); - ASSERT(MUTEX_HELD(&xdf_hvm_list_lock)); - - i = list_head(&xdf_hvm_list); - while (i != NULL) { - if ((path != NULL) && strcmp(i->xdf_he_path, path) != 0) { - i = list_next(&xdf_hvm_list, i); - continue; - } - if ((dip != NULL) && (i->xdf_he_dip != dip)) { - i = list_next(&xdf_hvm_list, i); - continue; - } - break; - } - return (i); -} - -dev_info_t * -xdf_hvm_hold(const char *path) -{ - xdf_hvm_entry_t *i; - dev_info_t *dip; - - mutex_enter(&xdf_hvm_list_lock); - i = i_xdf_hvm_find(path, NULL); - if (i == NULL) { - mutex_exit(&xdf_hvm_list_lock); - return (B_FALSE); - } - ndi_hold_devi(dip = i->xdf_he_dip); - mutex_exit(&xdf_hvm_list_lock); - return (dip); -} - -static void -xdf_hvm_add(dev_info_t *dip) -{ - xdf_hvm_entry_t *i; - char *path; - - /* figure out the path for the dip */ - path = kmem_zalloc(MAXPATHLEN, KM_SLEEP); - (void) ddi_pathname(dip, path); - - i = kmem_alloc(sizeof (*i), KM_SLEEP); - i->xdf_he_dip = dip; - i->xdf_he_path = i_ddi_strdup(path, KM_SLEEP); - - mutex_enter(&xdf_hvm_list_lock); - ASSERT(i_xdf_hvm_find(path, NULL) == NULL); - ASSERT(i_xdf_hvm_find(NULL, dip) == NULL); - list_insert_head(&xdf_hvm_list, i); - mutex_exit(&xdf_hvm_list_lock); - - kmem_free(path, MAXPATHLEN); -} - -static void -xdf_hvm_rm(dev_info_t *dip) -{ - xdf_hvm_entry_t *i; - - mutex_enter(&xdf_hvm_list_lock); - VERIFY((i = i_xdf_hvm_find(NULL, dip)) != NULL); - list_remove(&xdf_hvm_list, i); - mutex_exit(&xdf_hvm_list_lock); - - kmem_free(i->xdf_he_path, strlen(i->xdf_he_path) + 1); - kmem_free(i, sizeof (*i)); -} - -static void -xdf_hvm_init(void) -{ - list_create(&xdf_hvm_list, sizeof (xdf_hvm_entry_t), - offsetof(xdf_hvm_entry_t, xdf_he_list)); - mutex_init(&xdf_hvm_list_lock, NULL, MUTEX_DEFAULT, NULL); -} - -static void -xdf_hvm_fini(void) -{ - ASSERT(list_head(&xdf_hvm_list) == NULL); - list_destroy(&xdf_hvm_list); - mutex_destroy(&xdf_hvm_list_lock); -} - -boolean_t -xdf_hvm_connect(dev_info_t *dip) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - char *oename, *str; - int rv; - - mutex_enter(&vdp->xdf_cb_lk); - - /* - * Before try to establish a connection we need to wait for the - * backend hotplug scripts to have run. Once they are run the - * "/hotplug-status" property will be set to "connected". - */ - for (;;) { - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - - /* - * Get the xenbus path to the backend device. Note that - * we can't cache this path (and we look it up on each pass - * through this loop) because it could change during - * suspend, resume, and migration operations. - */ - if ((oename = xvdi_get_oename(dip)) == NULL) { - mutex_exit(&vdp->xdf_cb_lk); - return (B_FALSE); - } - - str = NULL; - if ((xenbus_read_str(oename, XBP_HP_STATUS, &str) == 0) && - (strcmp(str, XBV_HP_STATUS_CONN) == 0)) - break; - - if (str != NULL) - strfree(str); - - /* wait for an update to "/hotplug-status" */ - if (cv_wait_sig(&vdp->xdf_hp_status_cv, &vdp->xdf_cb_lk) == 0) { - /* we got interrupted by a signal */ - mutex_exit(&vdp->xdf_cb_lk); - return (B_FALSE); - } - } - - /* Good news. The backend hotplug scripts have been run. */ - ASSERT(MUTEX_HELD(&vdp->xdf_cb_lk)); - ASSERT(strcmp(str, XBV_HP_STATUS_CONN) == 0); - strfree(str); - - /* - * If we're emulating a cd device and if the backend doesn't support - * media request opreations, then we're not going to bother trying - * to establish a connection for a couple reasons. First off, media - * requests support is required to support operations like eject and - * media locking. Second, other backend platforms like Linux don't - * support hvm pv cdrom access. They don't even have a backend pv - * driver for cdrom device nodes, so we don't want to block forever - * waiting for a connection to a backend driver that doesn't exist. - */ - if (XD_IS_CD(vdp) && !xenbus_exists(oename, XBP_MEDIA_REQ_SUP)) { - mutex_exit(&vdp->xdf_cb_lk); - return (B_FALSE); - } - - mutex_enter(&vdp->xdf_dev_lk); - rv = xdf_connect_locked(vdp, B_TRUE); - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_cb_lk); - - return ((rv == XD_READY) ? B_TRUE : B_FALSE); -} - -int -xdf_hvm_setpgeom(dev_info_t *dip, cmlb_geom_t *geomp) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - - /* sanity check the requested physical geometry */ - mutex_enter(&vdp->xdf_dev_lk); - if ((geomp->g_secsize != XB_BSIZE) || - (geomp->g_capacity == 0)) { - mutex_exit(&vdp->xdf_dev_lk); - return (EINVAL); - } - - /* - * If we've already connected to the backend device then make sure - * we're not defining a physical geometry larger than our backend - * device. - */ - if ((vdp->xdf_xdev_nblocks != 0) && - (geomp->g_capacity > vdp->xdf_xdev_nblocks)) { - mutex_exit(&vdp->xdf_dev_lk); - return (EINVAL); - } - - bzero(&vdp->xdf_pgeom, sizeof (vdp->xdf_pgeom)); - vdp->xdf_pgeom.g_ncyl = geomp->g_ncyl; - vdp->xdf_pgeom.g_acyl = geomp->g_acyl; - vdp->xdf_pgeom.g_nhead = geomp->g_nhead; - vdp->xdf_pgeom.g_nsect = geomp->g_nsect; - vdp->xdf_pgeom.g_secsize = geomp->g_secsize; - vdp->xdf_pgeom.g_capacity = geomp->g_capacity; - vdp->xdf_pgeom.g_intrlv = geomp->g_intrlv; - vdp->xdf_pgeom.g_rpm = geomp->g_rpm; - - vdp->xdf_pgeom_fixed = B_TRUE; - mutex_exit(&vdp->xdf_dev_lk); - - /* force a re-validation */ - cmlb_invalidate(vdp->xdf_vd_lbl, NULL); - - return (0); -} - -boolean_t -xdf_is_cd(dev_info_t *dip) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - boolean_t rv; - - mutex_enter(&vdp->xdf_cb_lk); - rv = XD_IS_CD(vdp); - mutex_exit(&vdp->xdf_cb_lk); - return (rv); -} - -boolean_t -xdf_is_rm(dev_info_t *dip) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - boolean_t rv; - - mutex_enter(&vdp->xdf_cb_lk); - rv = XD_IS_RM(vdp); - mutex_exit(&vdp->xdf_cb_lk); - return (rv); -} - -boolean_t -xdf_media_req_supported(dev_info_t *dip) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - boolean_t rv; - - mutex_enter(&vdp->xdf_cb_lk); - rv = vdp->xdf_media_req_supported; - mutex_exit(&vdp->xdf_cb_lk); - return (rv); -} - -#endif /* XPV_HVM_DRIVER */ - -static int -xdf_lb_getcap(dev_info_t *dip, diskaddr_t *capp) -{ - xdf_t *vdp; - vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip)); - - if (vdp == NULL) - return (ENXIO); - - mutex_enter(&vdp->xdf_dev_lk); - *capp = vdp->xdf_pgeom.g_capacity; - DPRINTF(LBL_DBG, ("xdf@%s:capacity %llu\n", vdp->xdf_addr, *capp)); - mutex_exit(&vdp->xdf_dev_lk); - return (0); -} - -static int -xdf_lb_getpgeom(dev_info_t *dip, cmlb_geom_t *geomp) -{ - xdf_t *vdp; - - if ((vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip))) == NULL) - return (ENXIO); - *geomp = vdp->xdf_pgeom; - return (0); -} - -/* - * No real HBA, no geometry available from it - */ -/*ARGSUSED*/ -static int -xdf_lb_getvgeom(dev_info_t *dip, cmlb_geom_t *geomp) -{ - return (EINVAL); -} - -static int -xdf_lb_getattribute(dev_info_t *dip, tg_attribute_t *tgattributep) -{ - xdf_t *vdp; - - if (!(vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip)))) - return (ENXIO); - - if (XD_IS_RO(vdp)) - tgattributep->media_is_writable = 0; - else - tgattributep->media_is_writable = 1; - tgattributep->media_is_rotational = 0; - return (0); -} - -/* ARGSUSED3 */ -int -xdf_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) -{ - int instance; - xdf_t *vdp; - - instance = ddi_get_instance(dip); - - if ((vdp = ddi_get_soft_state(xdf_ssp, instance)) == NULL) - return (ENXIO); - - switch (cmd) { - case TG_GETPHYGEOM: - return (xdf_lb_getpgeom(dip, (cmlb_geom_t *)arg)); - case TG_GETVIRTGEOM: - return (xdf_lb_getvgeom(dip, (cmlb_geom_t *)arg)); - case TG_GETCAPACITY: - return (xdf_lb_getcap(dip, (diskaddr_t *)arg)); - case TG_GETBLOCKSIZE: - mutex_enter(&vdp->xdf_cb_lk); - *(uint32_t *)arg = vdp->xdf_xdev_secsize; - mutex_exit(&vdp->xdf_cb_lk); - return (0); - case TG_GETATTR: - return (xdf_lb_getattribute(dip, (tg_attribute_t *)arg)); - default: - return (ENOTTY); - } -} - -/* ARGSUSED5 */ -int -xdf_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufp, - diskaddr_t start, size_t reqlen, void *tg_cookie) -{ - xdf_t *vdp; - struct buf *bp; - int err = 0; - - vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip)); - - /* We don't allow IO from the oe_change callback thread */ - ASSERT(curthread != vdp->xdf_oe_change_thread); - - if ((start + ((reqlen / (vdp->xdf_xdev_secsize / DEV_BSIZE)) - >> DEV_BSHIFT)) > vdp->xdf_pgeom.g_capacity) - return (EINVAL); - - bp = getrbuf(KM_SLEEP); - if (cmd == TG_READ) - bp->b_flags = B_BUSY | B_READ; - else - bp->b_flags = B_BUSY | B_WRITE; - - bp->b_un.b_addr = bufp; - bp->b_bcount = reqlen; - bp->b_blkno = start * (vdp->xdf_xdev_secsize / DEV_BSIZE); - bp->b_edev = DDI_DEV_T_NONE; /* don't have dev_t */ - - mutex_enter(&vdp->xdf_dev_lk); - xdf_bp_push(vdp, bp); - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_start(vdp); - if (curthread == vdp->xdf_ready_tq_thread) - (void) xdf_ring_drain(vdp); - err = biowait(bp); - ASSERT(bp->b_flags & B_DONE); - freerbuf(bp); - return (err); -} - -/* - * Lock the current media. Set the media state to "lock". - * (Media locks are only respected by the backend driver.) - */ -static int -xdf_ioctl_mlock(xdf_t *vdp) -{ - int rv; - mutex_enter(&vdp->xdf_cb_lk); - rv = xdf_media_req(vdp, XBV_MEDIA_REQ_LOCK, B_TRUE); - mutex_exit(&vdp->xdf_cb_lk); - return (rv); -} - -/* - * Release a media lock. Set the media state to "none". - */ -static int -xdf_ioctl_munlock(xdf_t *vdp) -{ - int rv; - mutex_enter(&vdp->xdf_cb_lk); - rv = xdf_media_req(vdp, XBV_MEDIA_REQ_NONE, B_TRUE); - mutex_exit(&vdp->xdf_cb_lk); - return (rv); -} - -/* - * Eject the current media. Ignores any media locks. (Media locks - * are only for benifit of the the backend.) - */ -static int -xdf_ioctl_eject(xdf_t *vdp) -{ - int rv; - - mutex_enter(&vdp->xdf_cb_lk); - if ((rv = xdf_media_req(vdp, XBV_MEDIA_REQ_EJECT, B_FALSE)) != 0) { - mutex_exit(&vdp->xdf_cb_lk); - return (rv); - } - - /* - * We've set the media requests xenbus parameter to eject, so now - * disconnect from the backend, wait for the backend to clear - * the media requets xenbus paramter, and then we can reconnect - * to the backend. - */ - (void) xdf_disconnect(vdp, XD_UNKNOWN, B_TRUE); - mutex_enter(&vdp->xdf_dev_lk); - if (xdf_connect_locked(vdp, B_TRUE) != XD_READY) { - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_cb_lk); - return (EIO); - } - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_cb_lk); - return (0); -} - -/* - * Watch for media state changes. This can be an insertion of a device - * (triggered by a 'xm block-configure' request in another domain) or - * the ejection of a device (triggered by a local "eject" operation). - * For a full description of the DKIOCSTATE ioctl behavior see dkio(7I). - */ -static int -xdf_dkstate(xdf_t *vdp, enum dkio_state mstate) -{ - enum dkio_state prev_state; - - mutex_enter(&vdp->xdf_cb_lk); - prev_state = vdp->xdf_mstate; - - if (vdp->xdf_mstate == mstate) { - while (vdp->xdf_mstate == prev_state) { - if (cv_wait_sig(&vdp->xdf_mstate_cv, - &vdp->xdf_cb_lk) == 0) { - mutex_exit(&vdp->xdf_cb_lk); - return (EINTR); - } - } - } - - if ((prev_state != DKIO_INSERTED) && - (vdp->xdf_mstate == DKIO_INSERTED)) { - (void) xdf_media_req(vdp, XBV_MEDIA_REQ_LOCK, B_TRUE); - mutex_exit(&vdp->xdf_cb_lk); - return (0); - } - - mutex_exit(&vdp->xdf_cb_lk); - return (0); -} - -/*ARGSUSED*/ -static int -xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, - int *rvalp) -{ - minor_t minor = getminor(dev); - int part = XDF_PART(minor); - xdf_t *vdp; - int rv; - - if (((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) || - (!xdf_isopen(vdp, part))) - return (ENXIO); - - DPRINTF(IOCTL_DBG, ("xdf@%s:ioctl: cmd %d (0x%x)\n", - vdp->xdf_addr, cmd, cmd)); - - switch (cmd) { - default: - return (ENOTTY); - case DKIOCG_PHYGEOM: - case DKIOCG_VIRTGEOM: - case DKIOCGGEOM: - case DKIOCSGEOM: - case DKIOCGAPART: - case DKIOCSAPART: - case DKIOCGVTOC: - case DKIOCSVTOC: - case DKIOCPARTINFO: - case DKIOCGEXTVTOC: - case DKIOCSEXTVTOC: - case DKIOCEXTPARTINFO: - case DKIOCGMBOOT: - case DKIOCSMBOOT: - case DKIOCGETEFI: - case DKIOCSETEFI: - case DKIOCSETEXTPART: - case DKIOCPARTITION: - return (cmlb_ioctl(vdp->xdf_vd_lbl, dev, cmd, arg, mode, credp, - rvalp, NULL)); - case FDEJECT: - case DKIOCEJECT: - case CDROMEJECT: - return (xdf_ioctl_eject(vdp)); - case DKIOCLOCK: - return (xdf_ioctl_mlock(vdp)); - case DKIOCUNLOCK: - return (xdf_ioctl_munlock(vdp)); - case CDROMREADOFFSET: { - int offset = 0; - if (!XD_IS_CD(vdp)) - return (ENOTTY); - if (ddi_copyout(&offset, (void *)arg, sizeof (int), mode)) - return (EFAULT); - return (0); - } - case DKIOCGMEDIAINFO: { - struct dk_minfo media_info; - - media_info.dki_lbsize = vdp->xdf_xdev_secsize; - media_info.dki_capacity = vdp->xdf_pgeom.g_capacity; - if (XD_IS_CD(vdp)) - media_info.dki_media_type = DK_CDROM; - else - media_info.dki_media_type = DK_FIXED_DISK; - - if (ddi_copyout(&media_info, (void *)arg, - sizeof (struct dk_minfo), mode)) - return (EFAULT); - return (0); - } - case DKIOCINFO: { - struct dk_cinfo info; - - /* controller information */ - if (XD_IS_CD(vdp)) - info.dki_ctype = DKC_CDROM; - else - info.dki_ctype = DKC_VBD; - - info.dki_cnum = 0; - (void) strncpy((char *)(&info.dki_cname), "xdf", 8); - - /* unit information */ - info.dki_unit = ddi_get_instance(vdp->xdf_dip); - (void) strncpy((char *)(&info.dki_dname), "xdf", 8); - info.dki_flags = DKI_FMTVOL; - info.dki_partition = part; - info.dki_maxtransfer = maxphys / DEV_BSIZE; - info.dki_addr = 0; - info.dki_space = 0; - info.dki_prio = 0; - info.dki_vec = 0; - - if (ddi_copyout(&info, (void *)arg, sizeof (info), mode)) - return (EFAULT); - return (0); - } - case DKIOCSTATE: { - enum dkio_state mstate; - - if (ddi_copyin((void *)arg, &mstate, - sizeof (mstate), mode) != 0) - return (EFAULT); - if ((rv = xdf_dkstate(vdp, mstate)) != 0) - return (rv); - mstate = vdp->xdf_mstate; - if (ddi_copyout(&mstate, (void *)arg, - sizeof (mstate), mode) != 0) - return (EFAULT); - return (0); - } - case DKIOCREMOVABLE: { - int i = XD_IS_RM(vdp) ? 1 : 0; - if (ddi_copyout(&i, (caddr_t)arg, sizeof (i), mode)) - return (EFAULT); - return (0); - } - case DKIOCGETWCE: { - int i = XD_IS_RM(vdp) ? 1 : 0; - if (ddi_copyout(&i, (void *)arg, sizeof (i), mode)) - return (EFAULT); - return (0); - } - case DKIOCSETWCE: { - int i; - if (ddi_copyin((void *)arg, &i, sizeof (i), mode)) - return (EFAULT); - vdp->xdf_wce = (i != 0); - return (0); - } - case DKIOCFLUSHWRITECACHE: { - struct dk_callback *dkc = (struct dk_callback *)arg; - - if (vdp->xdf_flush_supported) { - rv = xdf_lb_rdwr(vdp->xdf_dip, TG_WRITE, - NULL, 0, 0, (void *)dev); - } else if (vdp->xdf_feature_barrier && - !xdf_barrier_flush_disable) { - rv = xdf_lb_rdwr(vdp->xdf_dip, TG_WRITE, - vdp->xdf_cache_flush_block, xdf_flush_block, - vdp->xdf_xdev_secsize, (void *)dev); - } else { - return (ENOTTY); - } - if ((mode & FKIOCTL) && (dkc != NULL) && - (dkc->dkc_callback != NULL)) { - (*dkc->dkc_callback)(dkc->dkc_cookie, rv); - /* need to return 0 after calling callback */ - rv = 0; - } - return (rv); - } - } - /*NOTREACHED*/ -} - -static int -xdf_strategy(struct buf *bp) -{ - xdf_t *vdp; - minor_t minor; - diskaddr_t p_blkct, p_blkst; - daddr_t blkno; - ulong_t nblks; - int part; - - minor = getminor(bp->b_edev); - part = XDF_PART(minor); - vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor)); - - mutex_enter(&vdp->xdf_dev_lk); - if (!xdf_isopen(vdp, part)) { - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_err(bp, ENXIO, 0); - return (0); - } - - /* We don't allow IO from the oe_change callback thread */ - ASSERT(curthread != vdp->xdf_oe_change_thread); - - /* Check for writes to a read only device */ - if (!IS_READ(bp) && XD_IS_RO(vdp)) { - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_err(bp, EROFS, 0); - return (0); - } - - /* Check if this I/O is accessing a partition or the entire disk */ - if ((long)bp->b_private == XB_SLICE_NONE) { - /* This I/O is using an absolute offset */ - p_blkct = vdp->xdf_xdev_nblocks; - p_blkst = 0; - } else { - /* This I/O is using a partition relative offset */ - mutex_exit(&vdp->xdf_dev_lk); - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkct, - &p_blkst, NULL, NULL, NULL)) { - xdf_io_err(bp, ENXIO, 0); - return (0); - } - mutex_enter(&vdp->xdf_dev_lk); - } - - /* - * Adjust the real blkno and bcount according to the underline - * physical sector size. - */ - blkno = bp->b_blkno / (vdp->xdf_xdev_secsize / XB_BSIZE); - - /* check for a starting block beyond the disk or partition limit */ - if (blkno > p_blkct) { - DPRINTF(IO_DBG, ("xdf@%s: block %lld exceeds VBD size %"PRIu64, - vdp->xdf_addr, (longlong_t)blkno, (uint64_t)p_blkct)); - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_err(bp, EINVAL, 0); - return (0); - } - - /* Legacy: don't set error flag at this case */ - if (blkno == p_blkct) { - mutex_exit(&vdp->xdf_dev_lk); - bp->b_resid = bp->b_bcount; - biodone(bp); - return (0); - } - - /* sanitize the input buf */ - bioerror(bp, 0); - bp->b_resid = 0; - bp->av_back = bp->av_forw = NULL; - - /* Adjust for partial transfer, this will result in an error later */ - if (vdp->xdf_xdev_secsize != 0 && - vdp->xdf_xdev_secsize != XB_BSIZE) { - nblks = bp->b_bcount / vdp->xdf_xdev_secsize; - } else { - nblks = bp->b_bcount >> XB_BSHIFT; - } - - if ((blkno + nblks) > p_blkct) { - if (vdp->xdf_xdev_secsize != 0 && - vdp->xdf_xdev_secsize != XB_BSIZE) { - bp->b_resid = - ((blkno + nblks) - p_blkct) * - vdp->xdf_xdev_secsize; - } else { - bp->b_resid = - ((blkno + nblks) - p_blkct) << - XB_BSHIFT; - } - bp->b_bcount -= bp->b_resid; - } - - DPRINTF(IO_DBG, ("xdf@%s: strategy blk %lld len %lu\n", - vdp->xdf_addr, (longlong_t)blkno, (ulong_t)bp->b_bcount)); - - /* Fix up the buf struct */ - bp->b_flags |= B_BUSY; - bp->b_private = (void *)(uintptr_t)p_blkst; - - xdf_bp_push(vdp, bp); - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_start(vdp); - if (do_polled_io) - (void) xdf_ring_drain(vdp); - return (0); -} - -/*ARGSUSED*/ -static int -xdf_read(dev_t dev, struct uio *uiop, cred_t *credp) -{ - xdf_t *vdp; - minor_t minor; - diskaddr_t p_blkcnt; - int part; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - DPRINTF(IO_DBG, ("xdf@%s: read offset 0x%"PRIx64"\n", - vdp->xdf_addr, (int64_t)uiop->uio_offset)); - - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) - return (ENXIO); - - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkcnt, - NULL, NULL, NULL, NULL)) - return (ENXIO); - - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) - return (ENOSPC); - - if (U_INVAL(uiop)) - return (EINVAL); - - return (physio(xdf_strategy, NULL, dev, B_READ, xdfmin, uiop)); -} - -/*ARGSUSED*/ -static int -xdf_write(dev_t dev, struct uio *uiop, cred_t *credp) -{ - xdf_t *vdp; - minor_t minor; - diskaddr_t p_blkcnt; - int part; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - DPRINTF(IO_DBG, ("xdf@%s: write offset 0x%"PRIx64"\n", - vdp->xdf_addr, (int64_t)uiop->uio_offset)); - - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) - return (ENXIO); - - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkcnt, - NULL, NULL, NULL, NULL)) - return (ENXIO); - - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) - return (ENOSPC); - - if (U_INVAL(uiop)) - return (EINVAL); - - return (physio(xdf_strategy, NULL, dev, B_WRITE, xdfmin, uiop)); -} - -/*ARGSUSED*/ -static int -xdf_aread(dev_t dev, struct aio_req *aiop, cred_t *credp) -{ - xdf_t *vdp; - minor_t minor; - struct uio *uiop = aiop->aio_uio; - diskaddr_t p_blkcnt; - int part; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) - return (ENXIO); - - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkcnt, - NULL, NULL, NULL, NULL)) - return (ENXIO); - - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) - return (ENOSPC); - - if (U_INVAL(uiop)) - return (EINVAL); - - return (aphysio(xdf_strategy, anocancel, dev, B_READ, xdfmin, aiop)); -} - -/*ARGSUSED*/ -static int -xdf_awrite(dev_t dev, struct aio_req *aiop, cred_t *credp) -{ - xdf_t *vdp; - minor_t minor; - struct uio *uiop = aiop->aio_uio; - diskaddr_t p_blkcnt; - int part; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) - return (ENXIO); - - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkcnt, - NULL, NULL, NULL, NULL)) - return (ENXIO); - - if (uiop->uio_loffset >= XB_DTOB(p_blkcnt, vdp)) - return (ENOSPC); - - if (U_INVAL(uiop)) - return (EINVAL); - - return (aphysio(xdf_strategy, anocancel, dev, B_WRITE, xdfmin, aiop)); -} - -static int -xdf_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) -{ - struct buf dumpbuf, *dbp = &dumpbuf; - xdf_t *vdp; - minor_t minor; - int err = 0; - int part; - diskaddr_t p_blkcnt, p_blkst; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - DPRINTF(IO_DBG, ("xdf@%s: dump addr (0x%p) blk (%ld) nblks (%d)\n", - vdp->xdf_addr, (void *)addr, blkno, nblk)); - - /* We don't allow IO from the oe_change callback thread */ - ASSERT(curthread != vdp->xdf_oe_change_thread); - - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) - return (ENXIO); - - if (cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkcnt, &p_blkst, - NULL, NULL, NULL)) - return (ENXIO); - - if ((blkno + nblk) > - (p_blkcnt * (vdp->xdf_xdev_secsize / XB_BSIZE))) { - cmn_err(CE_WARN, "xdf@%s: block %ld exceeds VBD size %"PRIu64, - vdp->xdf_addr, (daddr_t)((blkno + nblk) / - (vdp->xdf_xdev_secsize / XB_BSIZE)), (uint64_t)p_blkcnt); - return (EINVAL); - } - - bioinit(dbp); - dbp->b_flags = B_BUSY; - dbp->b_un.b_addr = addr; - dbp->b_bcount = nblk << DEV_BSHIFT; - dbp->b_blkno = blkno; - dbp->b_edev = dev; - dbp->b_private = (void *)(uintptr_t)p_blkst; - - mutex_enter(&vdp->xdf_dev_lk); - xdf_bp_push(vdp, dbp); - mutex_exit(&vdp->xdf_dev_lk); - xdf_io_start(vdp); - err = xdf_ring_drain(vdp); - biofini(dbp); - return (err); -} - -/*ARGSUSED*/ -static int -xdf_close(dev_t dev, int flag, int otyp, struct cred *credp) -{ - minor_t minor; - xdf_t *vdp; - int part; - ulong_t parbit; - - minor = getminor(dev); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - mutex_enter(&vdp->xdf_dev_lk); - part = XDF_PART(minor); - if (!xdf_isopen(vdp, part)) { - mutex_exit(&vdp->xdf_dev_lk); - return (ENXIO); - } - parbit = 1 << part; - - ASSERT((vdp->xdf_vd_open[otyp] & parbit) != 0); - if (otyp == OTYP_LYR) { - ASSERT(vdp->xdf_vd_lyropen[part] > 0); - if (--vdp->xdf_vd_lyropen[part] == 0) - vdp->xdf_vd_open[otyp] &= ~parbit; - } else { - vdp->xdf_vd_open[otyp] &= ~parbit; - } - vdp->xdf_vd_exclopen &= ~parbit; - - mutex_exit(&vdp->xdf_dev_lk); - return (0); -} - -static int -xdf_open(dev_t *devp, int flag, int otyp, cred_t *credp) -{ - minor_t minor; - xdf_t *vdp; - int part; - ulong_t parbit; - diskaddr_t p_blkct = 0; - boolean_t firstopen; - boolean_t nodelay; - - minor = getminor(*devp); - if ((vdp = ddi_get_soft_state(xdf_ssp, XDF_INST(minor))) == NULL) - return (ENXIO); - - nodelay = (flag & (FNDELAY | FNONBLOCK)); - - DPRINTF(DDI_DBG, ("xdf@%s: opening\n", vdp->xdf_addr)); - - /* do cv_wait until connected or failed */ - mutex_enter(&vdp->xdf_cb_lk); - mutex_enter(&vdp->xdf_dev_lk); - if (!nodelay && (xdf_connect_locked(vdp, B_TRUE) != XD_READY)) { - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_cb_lk); - return (ENXIO); - } - mutex_exit(&vdp->xdf_cb_lk); - - if ((flag & FWRITE) && XD_IS_RO(vdp)) { - mutex_exit(&vdp->xdf_dev_lk); - return (EROFS); - } - - part = XDF_PART(minor); - parbit = 1 << part; - if ((vdp->xdf_vd_exclopen & parbit) || - ((flag & FEXCL) && xdf_isopen(vdp, part))) { - mutex_exit(&vdp->xdf_dev_lk); - return (EBUSY); - } - - /* are we the first one to open this node? */ - firstopen = !xdf_isopen(vdp, -1); - - if (otyp == OTYP_LYR) - vdp->xdf_vd_lyropen[part]++; - - vdp->xdf_vd_open[otyp] |= parbit; - - if (flag & FEXCL) - vdp->xdf_vd_exclopen |= parbit; - - mutex_exit(&vdp->xdf_dev_lk); - - /* force a re-validation */ - if (firstopen) - cmlb_invalidate(vdp->xdf_vd_lbl, NULL); - - /* If this is a non-blocking open then we're done */ - if (nodelay) - return (0); - - /* - * This is a blocking open, so we require: - * - that the disk have a valid label on it - * - that the size of the partition that we're opening is non-zero - */ - if ((cmlb_partinfo(vdp->xdf_vd_lbl, part, &p_blkct, - NULL, NULL, NULL, NULL) != 0) || (p_blkct == 0)) { - (void) xdf_close(*devp, flag, otyp, credp); - return (ENXIO); - } - - return (0); -} - -/*ARGSUSED*/ -static void -xdf_watch_hp_status_cb(dev_info_t *dip, const char *path, void *arg) -{ - xdf_t *vdp = (xdf_t *)ddi_get_driver_private(dip); - cv_broadcast(&vdp->xdf_hp_status_cv); -} - -static int -xdf_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int flags, - char *name, caddr_t valuep, int *lengthp) -{ - xdf_t *vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip)); - - /* - * Sanity check that if a dev_t or dip were specified that they - * correspond to this device driver. On debug kernels we'll - * panic and on non-debug kernels we'll return failure. - */ - ASSERT(ddi_driver_major(dip) == xdf_major); - ASSERT((dev == DDI_DEV_T_ANY) || (getmajor(dev) == xdf_major)); - if ((ddi_driver_major(dip) != xdf_major) || - ((dev != DDI_DEV_T_ANY) && (getmajor(dev) != xdf_major))) - return (DDI_PROP_NOT_FOUND); - - if (vdp == NULL) - return (ddi_prop_op(dev, dip, prop_op, flags, - name, valuep, lengthp)); - - return (cmlb_prop_op(vdp->xdf_vd_lbl, - dev, dip, prop_op, flags, name, valuep, lengthp, - XDF_PART(getminor(dev)), NULL)); -} - -/*ARGSUSED*/ -static int -xdf_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **rp) -{ - int instance = XDF_INST(getminor((dev_t)arg)); - xdf_t *vbdp; - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - if ((vbdp = ddi_get_soft_state(xdf_ssp, instance)) == NULL) { - *rp = NULL; - return (DDI_FAILURE); - } - *rp = vbdp->xdf_dip; - return (DDI_SUCCESS); - - case DDI_INFO_DEVT2INSTANCE: - *rp = (void *)(uintptr_t)instance; - return (DDI_SUCCESS); - - default: - return (DDI_FAILURE); - } -} - -/*ARGSUSED*/ -static int -xdf_resume(dev_info_t *dip) -{ - xdf_t *vdp; - char *oename; - - if ((vdp = ddi_get_soft_state(xdf_ssp, ddi_get_instance(dip))) == NULL) - goto err; - - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_resume\n", vdp->xdf_addr); - - mutex_enter(&vdp->xdf_cb_lk); - - if (xvdi_resume(dip) != DDI_SUCCESS) { - mutex_exit(&vdp->xdf_cb_lk); - goto err; - } - - if (((oename = xvdi_get_oename(dip)) == NULL) || - (xvdi_add_xb_watch_handler(dip, oename, XBP_HP_STATUS, - xdf_watch_hp_status_cb, NULL) != DDI_SUCCESS)) { - mutex_exit(&vdp->xdf_cb_lk); - goto err; - } - - mutex_enter(&vdp->xdf_dev_lk); - ASSERT(vdp->xdf_state != XD_READY); - xdf_set_state(vdp, XD_UNKNOWN); - mutex_exit(&vdp->xdf_dev_lk); - - if (xdf_setstate_init(vdp) != DDI_SUCCESS) { - mutex_exit(&vdp->xdf_cb_lk); - goto err; - } - - mutex_exit(&vdp->xdf_cb_lk); - - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_resume: done\n", vdp->xdf_addr); - return (DDI_SUCCESS); -err: - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_resume: fail\n", vdp->xdf_addr); - return (DDI_FAILURE); -} - -static int -xdf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int n, instance = ddi_get_instance(dip); - ddi_iblock_cookie_t ibc, softibc; - boolean_t dev_iscd = B_FALSE; - xdf_t *vdp; - char *oename, *xsname, *str; - - if ((n = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_NOTPROM, - "xdf_debug", 0)) != 0) - xdf_debug = n; - - switch (cmd) { - case DDI_RESUME: - return (xdf_resume(dip)); - case DDI_ATTACH: - break; - default: - return (DDI_FAILURE); - } - /* DDI_ATTACH */ - - if (((xsname = xvdi_get_xsname(dip)) == NULL) || - ((oename = xvdi_get_oename(dip)) == NULL)) - return (DDI_FAILURE); - - /* - * Disable auto-detach. This is necessary so that we don't get - * detached while we're disconnected from the back end. - */ - if ((ddi_prop_update_int(DDI_DEV_T_NONE, dip, - DDI_NO_AUTODETACH, 1) != DDI_PROP_SUCCESS)) - return (DDI_FAILURE); - - /* driver handles kernel-issued IOCTLs */ - if (ddi_prop_create(DDI_DEV_T_NONE, dip, - DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - - if (ddi_get_iblock_cookie(dip, 0, &ibc) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (ddi_get_soft_iblock_cookie(dip, - DDI_SOFTINT_LOW, &softibc) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (xenbus_read_str(xsname, XBP_DEV_TYPE, &str) != 0) { - cmn_err(CE_WARN, "xdf@%s: cannot read device-type", - ddi_get_name_addr(dip)); - return (DDI_FAILURE); - } - if (strcmp(str, XBV_DEV_TYPE_CD) == 0) - dev_iscd = B_TRUE; - strfree(str); - - if (ddi_soft_state_zalloc(xdf_ssp, instance) != DDI_SUCCESS) - return (DDI_FAILURE); - - DPRINTF(DDI_DBG, ("xdf@%s: attaching\n", ddi_get_name_addr(dip))); - vdp = ddi_get_soft_state(xdf_ssp, instance); - ddi_set_driver_private(dip, vdp); - vdp->xdf_dip = dip; - vdp->xdf_addr = ddi_get_name_addr(dip); - vdp->xdf_suspending = B_FALSE; - vdp->xdf_media_req_supported = B_FALSE; - vdp->xdf_peer = INVALID_DOMID; - vdp->xdf_evtchn = INVALID_EVTCHN; - list_create(&vdp->xdf_vreq_act, sizeof (v_req_t), - offsetof(v_req_t, v_link)); - cv_init(&vdp->xdf_dev_cv, NULL, CV_DEFAULT, NULL); - cv_init(&vdp->xdf_hp_status_cv, NULL, CV_DEFAULT, NULL); - cv_init(&vdp->xdf_mstate_cv, NULL, CV_DEFAULT, NULL); - mutex_init(&vdp->xdf_dev_lk, NULL, MUTEX_DRIVER, (void *)ibc); - mutex_init(&vdp->xdf_cb_lk, NULL, MUTEX_DRIVER, (void *)ibc); - mutex_init(&vdp->xdf_iostat_lk, NULL, MUTEX_DRIVER, (void *)ibc); - vdp->xdf_cmbl_reattach = B_TRUE; - if (dev_iscd) { - vdp->xdf_dinfo |= VDISK_CDROM; - vdp->xdf_mstate = DKIO_EJECTED; - } else { - vdp->xdf_mstate = DKIO_NONE; - } - - if ((vdp->xdf_ready_tq = ddi_taskq_create(dip, "xdf_ready_tq", - 1, TASKQ_DEFAULTPRI, 0)) == NULL) - goto errout0; - - if (xvdi_add_xb_watch_handler(dip, oename, XBP_HP_STATUS, - xdf_watch_hp_status_cb, NULL) != DDI_SUCCESS) - goto errout0; - - if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &vdp->xdf_softintr_id, - &softibc, NULL, xdf_iorestart, (caddr_t)vdp) != DDI_SUCCESS) { - cmn_err(CE_WARN, "xdf@%s: failed to add softintr", - ddi_get_name_addr(dip)); - goto errout0; - } - - /* - * Initialize the physical geometry stucture. Note that currently - * we don't know the size of the backend device so the number - * of blocks on the device will be initialized to zero. Once - * we connect to the backend device we'll update the physical - * geometry to reflect the real size of the device. - */ - xdf_synthetic_pgeom(dip, &vdp->xdf_pgeom); - vdp->xdf_pgeom_fixed = B_FALSE; - - /* - * create default device minor nodes: non-removable disk - * we will adjust minor nodes after we are connected w/ backend - */ - cmlb_alloc_handle(&vdp->xdf_vd_lbl); - if (xdf_cmlb_attach(vdp) != 0) { - cmn_err(CE_WARN, - "xdf@%s: attach failed, cmlb attach failed", - ddi_get_name_addr(dip)); - goto errout0; - } - - /* - * We ship with cache-enabled disks - */ - vdp->xdf_wce = B_TRUE; - - mutex_enter(&vdp->xdf_cb_lk); - /* Watch backend XenbusState change */ - if (xvdi_add_event_handler(dip, - XS_OE_STATE, xdf_oe_change, NULL) != DDI_SUCCESS) { - mutex_exit(&vdp->xdf_cb_lk); - goto errout0; - } - - if (xdf_setstate_init(vdp) != DDI_SUCCESS) { - cmn_err(CE_WARN, "xdf@%s: start connection failed", - ddi_get_name_addr(dip)); - mutex_exit(&vdp->xdf_cb_lk); - goto errout1; - } - mutex_exit(&vdp->xdf_cb_lk); - -#if defined(XPV_HVM_DRIVER) - - xdf_hvm_add(dip); - - /* Report our version to dom0. */ - if (xenbus_printf(XBT_NULL, "guest/xdf", "version", "%d", - HVMPV_XDF_VERS)) - cmn_err(CE_WARN, "xdf: couldn't write version\n"); - -#endif /* XPV_HVM_DRIVER */ - - /* create kstat for iostat(1M) */ - if (xdf_kstat_create(dip, "xdf", instance) != 0) { - cmn_err(CE_WARN, "xdf@%s: failed to create kstat", - ddi_get_name_addr(dip)); - goto errout1; - } - - - ddi_report_dev(dip); - DPRINTF(DDI_DBG, ("xdf@%s: attached\n", vdp->xdf_addr)); - return (DDI_SUCCESS); - -errout1: - (void) xvdi_switch_state(vdp->xdf_dip, XBT_NULL, XenbusStateClosed); - xvdi_remove_event_handler(dip, XS_OE_STATE); -errout0: - if (vdp->xdf_vd_lbl != NULL) { - cmlb_detach(vdp->xdf_vd_lbl, NULL); - cmlb_free_handle(&vdp->xdf_vd_lbl); - vdp->xdf_vd_lbl = NULL; - } - if (vdp->xdf_softintr_id != NULL) - ddi_remove_softintr(vdp->xdf_softintr_id); - xvdi_remove_xb_watch_handlers(dip); - if (vdp->xdf_ready_tq != NULL) - ddi_taskq_destroy(vdp->xdf_ready_tq); - mutex_destroy(&vdp->xdf_cb_lk); - mutex_destroy(&vdp->xdf_dev_lk); - cv_destroy(&vdp->xdf_dev_cv); - cv_destroy(&vdp->xdf_hp_status_cv); - ddi_soft_state_free(xdf_ssp, instance); - ddi_set_driver_private(dip, NULL); - ddi_prop_remove_all(dip); - cmn_err(CE_WARN, "xdf@%s: attach failed", ddi_get_name_addr(dip)); - return (DDI_FAILURE); -} - -static int -xdf_suspend(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - xdf_t *vdp; - - if ((vdp = ddi_get_soft_state(xdf_ssp, instance)) == NULL) - return (DDI_FAILURE); - - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_suspend\n", vdp->xdf_addr); - - xvdi_suspend(dip); - - mutex_enter(&vdp->xdf_cb_lk); - mutex_enter(&vdp->xdf_dev_lk); - - vdp->xdf_suspending = B_TRUE; - xdf_ring_destroy(vdp); - xdf_set_state(vdp, XD_SUSPEND); - vdp->xdf_suspending = B_FALSE; - - mutex_exit(&vdp->xdf_dev_lk); - mutex_exit(&vdp->xdf_cb_lk); - - if (xdf_debug & SUSRES_DBG) - xen_printf("xdf@%s: xdf_suspend: done\n", vdp->xdf_addr); - - return (DDI_SUCCESS); -} - -static int -xdf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - xdf_t *vdp; - int instance; - - switch (cmd) { - - case DDI_PM_SUSPEND: - break; - - case DDI_SUSPEND: - return (xdf_suspend(dip)); - - case DDI_DETACH: - break; - - default: - return (DDI_FAILURE); - } - - instance = ddi_get_instance(dip); - DPRINTF(DDI_DBG, ("xdf@%s: detaching\n", ddi_get_name_addr(dip))); - vdp = ddi_get_soft_state(xdf_ssp, instance); - - if (vdp == NULL) - return (DDI_FAILURE); - - mutex_enter(&vdp->xdf_cb_lk); - xdf_disconnect(vdp, XD_CLOSED, B_FALSE); - if (vdp->xdf_state != XD_CLOSED) { - mutex_exit(&vdp->xdf_cb_lk); - return (DDI_FAILURE); - } - mutex_exit(&vdp->xdf_cb_lk); - - ASSERT(!ISDMACBON(vdp)); - -#if defined(XPV_HVM_DRIVER) - xdf_hvm_rm(dip); -#endif /* XPV_HVM_DRIVER */ - - if (vdp->xdf_timeout_id != 0) - (void) untimeout(vdp->xdf_timeout_id); - - xvdi_remove_event_handler(dip, XS_OE_STATE); - ddi_taskq_destroy(vdp->xdf_ready_tq); - - cmlb_detach(vdp->xdf_vd_lbl, NULL); - cmlb_free_handle(&vdp->xdf_vd_lbl); - - /* we'll support backend running in domU later */ -#ifdef DOMU_BACKEND - (void) xvdi_post_event(dip, XEN_HP_REMOVE); -#endif - - list_destroy(&vdp->xdf_vreq_act); - ddi_prop_remove_all(dip); - xdf_kstat_delete(dip); - ddi_remove_softintr(vdp->xdf_softintr_id); - xvdi_remove_xb_watch_handlers(dip); - ddi_set_driver_private(dip, NULL); - cv_destroy(&vdp->xdf_dev_cv); - mutex_destroy(&vdp->xdf_cb_lk); - mutex_destroy(&vdp->xdf_dev_lk); - if (vdp->xdf_cache_flush_block != NULL) - kmem_free(vdp->xdf_flush_mem, 2 * vdp->xdf_xdev_secsize); - ddi_soft_state_free(xdf_ssp, instance); - return (DDI_SUCCESS); -} - -/* - * Driver linkage structures. - */ -static struct cb_ops xdf_cbops = { - xdf_open, - xdf_close, - xdf_strategy, - nodev, - xdf_dump, - xdf_read, - xdf_write, - xdf_ioctl, - nodev, - nodev, - nodev, - nochpoll, - xdf_prop_op, - NULL, - D_MP | D_NEW | D_64BIT, - CB_REV, - xdf_aread, - xdf_awrite -}; - -struct dev_ops xdf_devops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - xdf_getinfo, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xdf_attach, /* devo_attach */ - xdf_detach, /* devo_detach */ - nodev, /* devo_reset */ - &xdf_cbops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -/* - * Module linkage structures. - */ -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "virtual block driver", /* short description */ - &xdf_devops /* driver specific ops */ -}; - -static struct modlinkage xdf_modlinkage = { - MODREV_1, (void *)&modldrv, NULL -}; - -/* - * standard module entry points - */ -int -_init(void) -{ - int rc; - - xdf_major = ddi_name_to_major("xdf"); - if (xdf_major == (major_t)-1) - return (EINVAL); - - if ((rc = ddi_soft_state_init(&xdf_ssp, sizeof (xdf_t), 0)) != 0) - return (rc); - - xdf_vreq_cache = kmem_cache_create("xdf_vreq_cache", - sizeof (v_req_t), 0, NULL, NULL, NULL, NULL, NULL, 0); - xdf_gs_cache = kmem_cache_create("xdf_gs_cache", - sizeof (ge_slot_t), 0, NULL, NULL, NULL, NULL, NULL, 0); - -#if defined(XPV_HVM_DRIVER) - xdf_hvm_init(); -#endif /* XPV_HVM_DRIVER */ - - if ((rc = mod_install(&xdf_modlinkage)) != 0) { -#if defined(XPV_HVM_DRIVER) - xdf_hvm_fini(); -#endif /* XPV_HVM_DRIVER */ - kmem_cache_destroy(xdf_vreq_cache); - kmem_cache_destroy(xdf_gs_cache); - ddi_soft_state_fini(&xdf_ssp); - return (rc); - } - - return (rc); -} - -int -_fini(void) -{ - int err; - if ((err = mod_remove(&xdf_modlinkage)) != 0) - return (err); - -#if defined(XPV_HVM_DRIVER) - xdf_hvm_fini(); -#endif /* XPV_HVM_DRIVER */ - - kmem_cache_destroy(xdf_vreq_cache); - kmem_cache_destroy(xdf_gs_cache); - ddi_soft_state_fini(&xdf_ssp); - - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&xdf_modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/xen/io/xdf.h b/usr/src/uts/common/xen/io/xdf.h deleted file mode 100644 index 173a2fdc19..0000000000 --- a/usr/src/uts/common/xen/io/xdf.h +++ /dev/null @@ -1,332 +0,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. - */ - - -#ifndef _SYS_XDF_H -#define _SYS_XDF_H - -#include -#include -#include -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * VBDs have standard 512 byte blocks - * A single blkif_request can transfer up to 11 pages of data, 1 page/segment - */ -#define XB_BSIZE DEV_BSIZE -#define XB_BMASK (XB_BSIZE - 1) -#define XB_BSHIFT 9 -#define XB_DTOB(bn, vdp) ((bn) * (vdp)->xdf_xdev_secsize) - -#define XB_MAX_SEGLEN (8 * XB_BSIZE) -#define XB_SEGOFFSET (XB_MAX_SEGLEN - 1) -#define XB_MAX_XFER (XB_MAX_SEGLEN * BLKIF_MAX_SEGMENTS_PER_REQUEST) -#define XB_MAXPHYS (XB_MAX_XFER * BLKIF_RING_SIZE) - -/* Number of sectors per segement */ -#define XB_NUM_SECTORS_PER_SEG (PAGESIZE / XB_BSIZE) -/* sectors are number 0 through XB_NUM_SECTORS_PER_SEG - 1 */ -#define XB_LAST_SECTOR_IN_SEG (XB_NUM_SECTORS_PER_SEG - 1) - - -/* - * Slice for absolute disk transaction. - * - * Hack Alert. XB_SLICE_NONE is a magic value that can be written into the - * b_private field of buf structures passed to xdf_strategy(). When present - * it indicates that the I/O is using an absolute offset. (ie, the I/O is - * not bound to any one partition.) This magic value is currently used by - * the pv_cmdk driver. This hack is shamelessly stolen from the sun4v vdc - * driver, another virtual disk device driver. (Although in the case of - * vdc the hack is less egregious since it is self contained within the - * vdc driver, where as here it is used as an interface between the pv_cmdk - * driver and the xdf driver.) - */ -#define XB_SLICE_NONE 0xFF - -/* - * blkif status - */ -typedef enum xdf_state { - /* - * initial state - */ - XD_UNKNOWN = 0, - /* - * ring and evtchn alloced, xenbus state changed to - * XenbusStateInitialised, wait for backend to connect - */ - XD_INIT = 1, - /* - * backend and frontend xenbus state has changed to - * XenbusStateConnected. IO is now allowed, but we are not still - * fully initialized. - */ - XD_CONNECTED = 2, - /* - * We're fully initialized and allowing regular IO. - */ - XD_READY = 3, - /* - * vbd interface close request received from backend, no more I/O - * requestis allowed to be put into ring buffer, while interrupt handler - * is allowed to run to finish any outstanding I/O request, disconnect - * process is kicked off by changing xenbus state to XenbusStateClosed - */ - XD_CLOSING = 4, - /* - * disconnection process finished, both backend and frontend's - * xenbus state has been changed to XenbusStateClosed, can be detached - */ - XD_CLOSED = 5, - /* - * We're either being suspended or resuming from a suspend. If we're - * in the process of suspending, we block all new IO, but but allow - * existing IO to drain. - */ - XD_SUSPEND = 6 -} xdf_state_t; - -/* - * 16 partitions + fdisk - */ -#define XDF_PSHIFT 6 -#define XDF_PMASK ((1 << XDF_PSHIFT) - 1) -#define XDF_PEXT (1 << XDF_PSHIFT) -#define XDF_MINOR(i, m) (((i) << XDF_PSHIFT) | (m)) -#define XDF_INST(m) ((m) >> XDF_PSHIFT) -#define XDF_PART(m) ((m) & XDF_PMASK) - -/* - * one blkif_request_t will have one corresponding ge_slot_t - * where we save those grant table refs used in this blkif_request_t - * - * the id of this ge_slot_t will also be put into 'id' field in - * each blkif_request_t when sent out to the ring buffer. - */ -typedef struct ge_slot { - list_node_t gs_vreq_link; - struct v_req *gs_vreq; - domid_t gs_oeid; - int gs_isread; - grant_ref_t gs_ghead; - int gs_ngrefs; - grant_ref_t gs_ge[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -} ge_slot_t; - -/* - * vbd I/O request - * - * An instance of this structure is bound to each buf passed to - * the driver's strategy by setting the pointer into bp->av_back. - * The id of this vreq will also be put into 'id' field in each - * blkif_request_t when sent out to the ring buffer for one DMA - * window of this buf. - * - * Vreq mainly contains DMA information for this buf. In one vreq/buf, - * there could be more than one DMA window, each of which will be - * mapped to one blkif_request_t/ge_slot_t. Ge_slot_t contains all grant - * table entry information for this buf. The ge_slot_t for current DMA - * window is pointed to by v_gs in vreq. - * - * So, grant table entries will only be alloc'ed when the DMA window is - * about to be transferred via blkif_request_t to the ring buffer. And - * they will be freed right after the blkif_response_t is seen. By this - * means, we can make use of grant table entries more efficiently. - */ -typedef struct v_req { - list_node_t v_link; - list_t v_gs; - int v_status; - buf_t *v_buf; - uint_t v_ndmacs; - uint_t v_dmaw; - uint_t v_ndmaws; - uint_t v_nslots; - uint64_t v_blkno; - ddi_dma_handle_t v_memdmahdl; - ddi_acc_handle_t v_align; - ddi_dma_handle_t v_dmahdl; - ddi_dma_cookie_t v_dmac; - caddr_t v_abuf; - uint8_t v_flush_diskcache; - boolean_t v_runq; -} v_req_t; - -/* - * Status set and checked in vreq->v_status by vreq_setup() - * - * These flags will help us to continue the vreq setup work from last failure - * point, instead of starting from scratch after each failure. - */ -#define VREQ_INIT 0x0 -#define VREQ_INIT_DONE 0x1 -#define VREQ_DMAHDL_ALLOCED 0x2 -#define VREQ_MEMDMAHDL_ALLOCED 0x3 -#define VREQ_DMAMEM_ALLOCED 0x4 -#define VREQ_DMABUF_BOUND 0x5 -#define VREQ_GS_ALLOCED 0x6 -#define VREQ_DMAWIN_DONE 0x7 - -/* - * virtual block device per-instance softstate - */ -typedef struct xdf { - dev_info_t *xdf_dip; - char *xdf_addr; - ddi_iblock_cookie_t xdf_ibc; /* mutex iblock cookie */ - domid_t xdf_peer; /* otherend's dom ID */ - xendev_ring_t *xdf_xb_ring; /* I/O ring buffer */ - ddi_acc_handle_t xdf_xb_ring_hdl; /* access handler for ring buffer */ - list_t xdf_vreq_act; /* active vreq list */ - buf_t *xdf_f_act; /* active buf list head */ - buf_t *xdf_l_act; /* active buf list tail */ - buf_t *xdf_i_act; /* active buf list index */ - xdf_state_t xdf_state; /* status of this virtual disk */ - boolean_t xdf_suspending; - ulong_t xdf_vd_open[OTYPCNT]; - ulong_t xdf_vd_lyropen[XDF_PEXT]; - ulong_t xdf_connect_req; - kthread_t *xdf_connect_thread; - ulong_t xdf_vd_exclopen; - kmutex_t xdf_iostat_lk; /* muxes lock for the iostat ptr */ - kmutex_t xdf_dev_lk; /* mutex lock for I/O path */ - kmutex_t xdf_cb_lk; /* mutex lock for event handling path */ - kcondvar_t xdf_dev_cv; /* cv used in I/O path */ - uint_t xdf_dinfo; /* disk info from backend xenstore */ - diskaddr_t xdf_xdev_nblocks; /* total size in block */ - uint_t xdf_xdev_secsize; /* disk blksize from backend */ - cmlb_geom_t xdf_pgeom; - boolean_t xdf_pgeom_set; - boolean_t xdf_pgeom_fixed; - kstat_t *xdf_xdev_iostat; - cmlb_handle_t xdf_vd_lbl; - ddi_softintr_t xdf_softintr_id; - timeout_id_t xdf_timeout_id; - struct gnttab_free_callback xdf_gnt_callback; - boolean_t xdf_feature_barrier; - boolean_t xdf_flush_supported; - boolean_t xdf_media_req_supported; - boolean_t xdf_wce; - boolean_t xdf_cmbl_reattach; - char *xdf_flush_mem; - char *xdf_cache_flush_block; - int xdf_evtchn; - enum dkio_state xdf_mstate; - kcondvar_t xdf_mstate_cv; - kcondvar_t xdf_hp_status_cv; - struct buf *xdf_ready_bp; - ddi_taskq_t *xdf_ready_tq; - kthread_t *xdf_ready_tq_thread; - struct buf *xdf_ready_tq_bp; -#ifdef DEBUG - int xdf_dmacallback_num; - kthread_t *xdf_oe_change_thread; -#endif -} xdf_t; - -/* - * VBD I/O requests must be aligned on a 512-byte boundary and specify - * a transfer size which is a mutiple of 512-bytes - */ -#define ALIGNED_XFER(bp) \ - ((((uintptr_t)((bp)->b_un.b_addr) & XB_BMASK) == 0) && \ - (((bp)->b_bcount & XB_BMASK) == 0)) - -#define U_INVAL(u) (((u)->uio_loffset & (offset_t)(XB_BMASK)) || \ - ((u)->uio_iov->iov_len & (offset_t)(XB_BMASK))) - -/* wrap pa_to_ma() for xdf to run in dom0 */ -#define PATOMA(addr) (DOMAIN_IS_INITDOMAIN(xen_info) ? addr : pa_to_ma(addr)) - -#define XD_IS_RO(vbd) (((vbd)->xdf_dinfo & VDISK_READONLY) != 0) -#define XD_IS_CD(vbd) (((vbd)->xdf_dinfo & VDISK_CDROM) != 0) -#define XD_IS_RM(vbd) (((vbd)->xdf_dinfo & VDISK_REMOVABLE) != 0) -#define IS_READ(bp) (((bp)->b_flags & B_READ) != 0) -#define IS_ERROR(bp) (((bp)->b_flags & B_ERROR) != 0) - -#define XDF_UPDATE_IO_STAT(vdp, bp) \ - { \ - kstat_io_t *kip = KSTAT_IO_PTR((vdp)->xdf_xdev_iostat); \ - size_t n_done = (bp)->b_bcount - (bp)->b_resid; \ - if ((bp)->b_flags & B_READ) { \ - kip->reads++; \ - kip->nread += n_done; \ - } else { \ - kip->writes++; \ - kip->nwritten += n_done; \ - } \ - } - -#ifdef DEBUG -#define DPRINTF(flag, args) {if (xdf_debug & (flag)) prom_printf args; } -#define SETDMACBON(vbd) {(vbd)->xdf_dmacallback_num++; } -#define SETDMACBOFF(vbd) {(vbd)->xdf_dmacallback_num--; } -#define ISDMACBON(vbd) ((vbd)->xdf_dmacallback_num > 0) -#else -#define DPRINTF(flag, args) -#define SETDMACBON(vbd) -#define SETDMACBOFF(vbd) -#define ISDMACBON(vbd) -#endif /* DEBUG */ - -#define DDI_DBG 0x1 -#define DMA_DBG 0x2 -#define INTR_DBG 0x8 -#define IO_DBG 0x10 -#define IOCTL_DBG 0x20 -#define SUSRES_DBG 0x40 -#define LBL_DBG 0x80 - -#if defined(XPV_HVM_DRIVER) -extern int xdf_lb_getinfo(dev_info_t *, int, void *, void *); -extern int xdf_lb_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t, - void *); -extern void xdfmin(struct buf *bp); -extern dev_info_t *xdf_hvm_hold(const char *); -extern boolean_t xdf_hvm_connect(dev_info_t *); -extern int xdf_hvm_setpgeom(dev_info_t *, cmlb_geom_t *); -extern int xdf_kstat_create(dev_info_t *, char *, int); -extern void xdf_kstat_delete(dev_info_t *); -extern boolean_t xdf_is_cd(dev_info_t *); -extern boolean_t xdf_is_rm(dev_info_t *); -extern boolean_t xdf_media_req_supported(dev_info_t *); -#endif /* XPV_HVM_DRIVER */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XDF_H */ diff --git a/usr/src/uts/common/xen/io/xenbus_client.c b/usr/src/uts/common/xen/io/xenbus_client.c deleted file mode 100644 index 9a6fcb6365..0000000000 --- a/usr/src/uts/common/xen/io/xenbus_client.c +++ /dev/null @@ -1,287 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Client-facing interface for the Xenbus driver. In other words, the - * interface between the Xenbus and the device-specific code, be it the - * frontend or the backend of that driver. - * - * Copyright (C) 2005 XenSource Ltd - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifdef XPV_HVM_DRIVER -#include -#include -#else -#include -#include -#include -#endif -#include -#include -#include - - -int -xenbus_watch_path(struct xenbus_device *dev, const char *path, - struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)) -{ - int err; - - watch->node = path; - watch->callback = callback; - - err = register_xenbus_watch(watch); - - if (err) { - watch->node = NULL; - watch->callback = NULL; - xenbus_dev_fatal(dev, err, "adding watch on %s", path); - } - - return (err); -} - - -int -xenbus_watch_path2(struct xenbus_device *dev, const char *path, - const char *path2, struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)) -{ - int err; - char *state; - - state = kmem_alloc(strlen(path) + 1 + strlen(path2) + 1, KM_SLEEP); - (void) strcpy(state, path); - (void) strcat(state, "/"); - (void) strcat(state, path2); - - err = xenbus_watch_path(dev, state, watch, callback); - if (err) - kmem_free(state, strlen(state) + 1); - return (err); -} - -/* - * Returns 0 on success, -1 if no change was made, or an errno on failure. We - * check whether the state is currently set to the given value, and if not, - * then the state is set. We don't want to unconditionally write the given - * state, because we don't want to fire watches unnecessarily. Furthermore, if - * the node has gone, we don't write to it, as the device will be tearing down, - * and we don't want to resurrect that directory. - * - * XXPV: not clear that this is still safe if two threads are racing to update - * the state? - */ -int -xenbus_switch_state(struct xenbus_device *dev, xenbus_transaction_t xbt, - XenbusState state) -{ - int current_state; - int err; - - err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); - - /* XXPV: is this really the right thing to do? */ - if (err == ENOENT) - return (0); - if (err) - return (err); - - err = -1; - - if ((XenbusState)current_state != state) { - err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); - if (err) - xenbus_dev_fatal(dev, err, "writing new state"); - } - - return (err); -} - - -/* - * Return the path to the error node for the given device, or NULL on failure. - * If the value returned is non-NULL, then it is the caller's to kmem_free. - */ -static char * -error_path(struct xenbus_device *dev) -{ - char *path_buffer; - - path_buffer = kmem_alloc(strlen("error/") + strlen(dev->nodename) + - 1, KM_SLEEP); - - (void) strcpy(path_buffer, "error/"); - (void) strcpy(path_buffer + strlen("error/"), dev->nodename); - - return (path_buffer); -} - -static void -common_dev_error(struct xenbus_device *dev, int err, const char *fmt, - va_list ap) -{ - int ret; - unsigned int len; - char *printf_buffer = NULL, *path_buffer = NULL; - -#define PRINTF_BUFFER_SIZE 4096 - printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP); - - (void) snprintf(printf_buffer, PRINTF_BUFFER_SIZE, "%d ", err); - len = strlen(printf_buffer); - ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); - - ASSERT(len + ret <= PRINTF_BUFFER_SIZE-1); - dev->has_error = 1; - - path_buffer = error_path(dev); - - if (path_buffer == NULL) { - printf("xenbus: failed to write error node for %s (%s)\n", - dev->nodename, printf_buffer); - goto fail; - } - - if (xenbus_write(0, path_buffer, "error", printf_buffer) != 0) { - printf("xenbus: failed to write error node for %s (%s)\n", - dev->nodename, printf_buffer); - goto fail; - } - -fail: - if (printf_buffer) - kmem_free(printf_buffer, PRINTF_BUFFER_SIZE); - if (path_buffer) - kmem_free(path_buffer, strlen(path_buffer) + 1); -} - - -void -xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - common_dev_error(dev, err, fmt, ap); - va_end(ap); -} - - -void -xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - common_dev_error(dev, err, fmt, ap); - va_end(ap); - - (void) xenbus_switch_state(dev, XBT_NULL, XenbusStateClosing); -} - -/* Clear any error. */ -void -xenbus_dev_ok(struct xenbus_device *dev) -{ - if (dev->has_error) { - if (xenbus_rm(0, dev->nodename, "error") != 0) - printf("xenbus: failed to clear error node for %s\n", - dev->nodename); - else - dev->has_error = 0; - } -} - -int -xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) -{ - int err = gnttab_grant_foreign_access(dev->otherend_id, ring_mfn, 0); - if (err < 0) - xenbus_dev_fatal(dev, err, "granting access to ring page"); - return (err); -} - - -int -xenbus_alloc_evtchn(struct xenbus_device *dev, int *port) -{ - int err; - - err = xen_alloc_unbound_evtchn(dev->otherend_id, port); - if (err) - xenbus_dev_fatal(dev, err, "allocating event channel"); - return (err); -} - - -XenbusState -xenbus_read_driver_state(const char *path) -{ - XenbusState result; - - int err = xenbus_gather(XBT_NULL, path, "state", "%d", &result, NULL); - if (err) - result = XenbusStateClosed; - - return (result); -} - - -/* - * Local variables: - * c-file-style: "solaris" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/usr/src/uts/common/xen/io/xenbus_comms.c b/usr/src/uts/common/xen/io/xenbus_comms.c deleted file mode 100644 index b250feaa1d..0000000000 --- a/usr/src/uts/common/xen/io/xenbus_comms.c +++ /dev/null @@ -1,311 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * - * xenbus_comms.c - * - * Low level code to talks to Xen Store: ringbuffer and event channel. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include -#ifdef XPV_HVM_DRIVER -#include -#include -#include -#else -#include -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef XPV_HVM_DRIVER -static int xenbus_irq; -#endif -static ddi_umem_cookie_t xb_cookie; /* cookie for xenbus comm page */ -extern caddr_t xb_addr; /* va of xenbus comm page */ - -static kcondvar_t xb_wait_cv; -static kmutex_t xb_wait_lock; - -#define xs_domain_interface(ra) ((struct xenstore_domain_interface *)(ra)) - -/*ARGSUSED*/ -static uint_t -xenbus_intr(void *unused) -{ - mutex_enter(&xb_wait_lock); - cv_broadcast(&xb_wait_cv); - mutex_exit(&xb_wait_lock); - return (DDI_INTR_CLAIMED); -} - -static int -check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) -{ - return ((prod - cons) <= XENSTORE_RING_SIZE); -} - -static void * -get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod, - char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); - if ((XENSTORE_RING_SIZE - (prod - cons)) < *len) - *len = XENSTORE_RING_SIZE - (prod - cons); - return ((void *)(buf + MASK_XENSTORE_IDX(prod))); -} - -static const void * -get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod, - const char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); - if ((prod - cons) < *len) - *len = prod - cons; - return ((void *)(buf + MASK_XENSTORE_IDX(cons))); -} - - -int -xb_write(const void *data, unsigned len) -{ - volatile struct xenstore_domain_interface *intf = - xs_domain_interface(xb_addr); - XENSTORE_RING_IDX cons, prod; - extern int do_polled_io; - - while (len != 0) { - void *dst; - unsigned int avail; - - mutex_enter(&xb_wait_lock); - while ((intf->req_prod - intf->req_cons) == - XENSTORE_RING_SIZE) { - if (interrupts_unleashed && !do_polled_io) { - if (cv_wait_sig(&xb_wait_cv, - &xb_wait_lock) == 0) { - mutex_exit(&xb_wait_lock); - return (EINTR); - } - } else { /* polled mode needed for early probes */ - (void) HYPERVISOR_yield(); - } - } - mutex_exit(&xb_wait_lock); - /* Read indexes, then verify. */ - cons = intf->req_cons; - prod = intf->req_prod; - membar_enter(); - if (!check_indexes(cons, prod)) - return (EIO); - - dst = get_output_chunk(cons, prod, (char *)intf->req, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - - (void) memcpy(dst, data, avail); - data = (void *)((uintptr_t)data + avail); - len -= avail; - - /* Other side must not see new header until data is there. */ - membar_producer(); - intf->req_prod += avail; - - /* This implies mb() before other side sees interrupt. */ - ec_notify_via_evtchn(xen_info->store_evtchn); - } - - return (0); -} - -int -xb_read(void *data, unsigned len) -{ - volatile struct xenstore_domain_interface *intf = - xs_domain_interface(xb_addr); - XENSTORE_RING_IDX cons, prod; - extern int do_polled_io; - - while (len != 0) { - unsigned int avail; - const char *src; - - mutex_enter(&xb_wait_lock); - while (intf->rsp_cons == intf->rsp_prod) { - if (interrupts_unleashed && !do_polled_io) { - if (cv_wait_sig(&xb_wait_cv, - &xb_wait_lock) == 0) { - mutex_exit(&xb_wait_lock); - return (EINTR); - } - } else { /* polled mode needed for early probes */ - (void) HYPERVISOR_yield(); - } - } - mutex_exit(&xb_wait_lock); - /* Read indexes, then verify. */ - cons = intf->rsp_cons; - prod = intf->rsp_prod; - membar_enter(); - if (!check_indexes(cons, prod)) - return (EIO); - - src = get_input_chunk(cons, prod, (char *)intf->rsp, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - - /* We must read header before we read data. */ - membar_consumer(); - - (void) memcpy(data, src, avail); - data = (void *)((uintptr_t)data + avail); - len -= avail; - - /* Other side must not see free space until we've copied out */ - membar_enter(); - intf->rsp_cons += avail; - - /* Implies mb(): they will see new header. */ - ec_notify_via_evtchn(xen_info->store_evtchn); - } - - return (0); -} - -void -xb_suspend(void) -{ -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(xen_info->store_evtchn); -#else - rem_avintr(NULL, IPL_XENBUS, (avfunc)xenbus_intr, xenbus_irq); -#endif -} - -void -xb_setup_intr(void) -{ -#ifdef XPV_HVM_DRIVER - ec_bind_evtchn_to_handler(xen_info->store_evtchn, IPL_XENBUS, - xenbus_intr, NULL); -#else - xenbus_irq = ec_bind_evtchn_to_irq(xen_info->store_evtchn); - if (xenbus_irq < 0) { - cmn_err(CE_WARN, "Couldn't bind xenbus event channel"); - return; - } - if (!add_avintr(NULL, IPL_XENBUS, (avfunc)xenbus_intr, "xenbus", - xenbus_irq, NULL, NULL, NULL, NULL)) - cmn_err(CE_WARN, "XENBUS add intr failed\n"); -#endif -} - -/* - * Set up our xenstore page and event channel. Domain 0 needs to allocate a - * page and event channel; other domains use what we are told. - */ -void -xb_init(void) -{ - int err; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - - if (xb_addr != NULL) - return; - - xb_addr = ddi_umem_alloc(PAGESIZE, DDI_UMEM_SLEEP, - &xb_cookie); - xen_info->store_mfn = pfn_to_mfn(hat_getpfnum(kas.a_hat, - xb_addr)); - - err = xen_alloc_unbound_evtchn(0, - (int *)&xen_info->store_evtchn); - ASSERT(err == 0); - } else { - /* - * This is harmless on first boot, but needed for resume and - * migrate. We use kbm_map_ma() as a shortcut instead of - * directly using HYPERVISOR_update_va_mapping(). - */ - ASSERT(xb_addr != NULL); - kbm_map_ma(mfn_to_ma(xen_info->store_mfn), - (uintptr_t)xb_addr, 0); - } - - ASSERT(xen_info->store_evtchn); -} - -void * -xb_xenstore_cookie(void) -{ - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - return (xb_cookie); -} diff --git a/usr/src/uts/common/xen/io/xenbus_dev.c b/usr/src/uts/common/xen/io/xenbus_dev.c deleted file mode 100644 index 1103f7066c..0000000000 --- a/usr/src/uts/common/xen/io/xenbus_dev.c +++ /dev/null @@ -1,677 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * xenbus_dev.c - * - * Driver giving user-space access to the kernel's xenbus connection - * to xenstore. - * - * Copyright (c) 2005, Christian Limpach - * Copyright (c) 2005, Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef XPV_HVM_DRIVER -#include -#include -#include -#endif -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define XENBUSDRV_DBPRINT(fmt) { if (xenbusdrv_debug) cmn_err fmt; } -#else -#define XENBUSDRV_DBPRINT(fmt) -#endif /* ifdef DEBUG */ - -/* Some handy macros */ -#define XENBUSDRV_MASK_READ_IDX(idx) ((idx) & (PAGESIZE - 1)) -#define XENBUSDRV_MINOR2INST(minor) ((int)(minor)) -#define XENBUSDRV_NCLONES 256 -#define XENBUSDRV_INST2SOFTS(instance) \ - ((xenbus_dev_t *)ddi_get_soft_state(xenbusdrv_statep, (instance))) - -static int xenbusdrv_debug = 0; -static int xenbusdrv_clone_tab[XENBUSDRV_NCLONES]; -static dev_info_t *xenbusdrv_dip; -static kmutex_t xenbusdrv_clone_tab_mutex; - -struct xenbus_dev_transaction { - list_t list; - xenbus_transaction_t handle; -}; - -/* Soft state data structure for xenbus driver */ -struct xenbus_dev_data { - dev_info_t *dip; - - /* In-progress transaction. */ - list_t transactions; - - /* Partial request. */ - unsigned int len; - union { - struct xsd_sockmsg msg; - char buffer[MMU_PAGESIZE]; - } u; - - /* Response queue. */ - char read_buffer[MMU_PAGESIZE]; - unsigned int read_cons, read_prod; - kcondvar_t read_cv; - kmutex_t read_mutex; - int xenstore_inst; -}; -typedef struct xenbus_dev_data xenbus_dev_t; -static void *xenbusdrv_statep; - -static int xenbusdrv_info(dev_info_t *, ddi_info_cmd_t, void *, void **); -static int xenbusdrv_attach(dev_info_t *, ddi_attach_cmd_t); -static int xenbusdrv_detach(dev_info_t *, ddi_detach_cmd_t); -static int xenbusdrv_open(dev_t *, int, int, cred_t *); -static int xenbusdrv_close(dev_t, int, int, cred_t *); -static int xenbusdrv_read(dev_t, struct uio *, cred_t *); -static int xenbusdrv_write(dev_t, struct uio *, cred_t *); -static int xenbusdrv_devmap(dev_t, devmap_cookie_t, offset_t, size_t, size_t *, - uint_t); -static int xenbusdrv_segmap(dev_t, off_t, ddi_as_handle_t, caddr_t *, off_t, - uint_t, uint_t, uint_t, cred_t *); -static int xenbusdrv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); -static int xenbusdrv_queue_reply(xenbus_dev_t *, const struct xsd_sockmsg *, - const char *); - -/* Solaris driver framework */ - -static struct cb_ops xenbusdrv_cb_ops = { - xenbusdrv_open, /* cb_open */ - xenbusdrv_close, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - xenbusdrv_read, /* cb_read */ - xenbusdrv_write, /* cb_write */ - xenbusdrv_ioctl, /* cb_ioctl */ - xenbusdrv_devmap, /* cb_devmap */ - NULL, /* cb_mmap */ - xenbusdrv_segmap, /* cb_segmap */ - nochpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - 0, /* cb_stream */ - D_DEVMAP | D_NEW | D_MP, /* cb_flag */ - CB_REV -}; - -static struct dev_ops xenbusdrv_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - xenbusdrv_info, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xenbusdrv_attach, /* devo_attach */ - xenbusdrv_detach, /* devo_detach */ - nodev, /* devo_reset */ - &xenbusdrv_cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "virtual bus driver", /* Name of the module. */ - &xenbusdrv_dev_ops /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -int -_init(void) -{ - int e; - - e = ddi_soft_state_init(&xenbusdrv_statep, sizeof (xenbus_dev_t), 1); - if (e) - return (e); - - e = mod_install(&modlinkage); - if (e) - ddi_soft_state_fini(&xenbusdrv_statep); - - return (e); -} - -int -_fini(void) -{ - int e; - - e = mod_remove(&modlinkage); - if (e) - return (e); - - ddi_soft_state_fini(&xenbusdrv_statep); - - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* ARGSUSED */ -static int -xenbusdrv_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) -{ - dev_t dev = (dev_t)arg; - minor_t minor = getminor(dev); - int retval; - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - if (minor != 0 || xenbusdrv_dip == NULL) { - *result = NULL; - retval = DDI_FAILURE; - } else { - *result = (void *)xenbusdrv_dip; - retval = DDI_SUCCESS; - } - break; - case DDI_INFO_DEVT2INSTANCE: - *result = NULL; - retval = DDI_SUCCESS; - break; - default: - retval = DDI_FAILURE; - } - return (retval); -} - -static int -xenbusdrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int error; - int unit = ddi_get_instance(dip); - - - switch (cmd) { - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - cmn_err(CE_WARN, "xenbus_attach: unknown cmd 0x%x\n", cmd); - return (DDI_FAILURE); - } - - /* DDI_ATTACH */ - - /* - * only one instance - but we clone using the open routine - */ - if (ddi_get_instance(dip) > 0) - return (DDI_FAILURE); - - mutex_init(&xenbusdrv_clone_tab_mutex, NULL, MUTEX_DRIVER, - NULL); - - error = ddi_create_minor_node(dip, "xenbus", S_IFCHR, unit, - DDI_PSEUDO, 0); - if (error != DDI_SUCCESS) - goto fail; - - /* - * save dip for getinfo - */ - xenbusdrv_dip = dip; - ddi_report_dev(dip); - -#ifndef XPV_HVM_DRIVER - if (DOMAIN_IS_INITDOMAIN(xen_info)) - xs_dom0_init(); -#endif - - return (DDI_SUCCESS); - -fail: - (void) xenbusdrv_detach(dip, DDI_DETACH); - return (error); -} - -static int -xenbusdrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - /* - * again, only one instance - */ - if (ddi_get_instance(dip) > 0) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_DETACH: - ddi_remove_minor_node(dip, NULL); - mutex_destroy(&xenbusdrv_clone_tab_mutex); - xenbusdrv_dip = NULL; - return (DDI_SUCCESS); - case DDI_SUSPEND: - return (DDI_SUCCESS); - default: - cmn_err(CE_WARN, "xenbus_detach: unknown cmd 0x%x\n", cmd); - return (DDI_FAILURE); - } -} - -/* ARGSUSED */ -static int -xenbusdrv_open(dev_t *devp, int flag, int otyp, cred_t *cr) -{ - xenbus_dev_t *xbs; - minor_t minor = getminor(*devp); - - if (otyp == OTYP_BLK) - return (ENXIO); - - /* - * only allow open on minor = 0 - the clone device - */ - if (minor != 0) - return (ENXIO); - - /* - * find a free slot and grab it - */ - mutex_enter(&xenbusdrv_clone_tab_mutex); - for (minor = 1; minor < XENBUSDRV_NCLONES; minor++) { - if (xenbusdrv_clone_tab[minor] == 0) { - xenbusdrv_clone_tab[minor] = 1; - break; - } - } - mutex_exit(&xenbusdrv_clone_tab_mutex); - if (minor == XENBUSDRV_NCLONES) - return (EAGAIN); - - /* Allocate softstate structure */ - if (ddi_soft_state_zalloc(xenbusdrv_statep, - XENBUSDRV_MINOR2INST(minor)) != DDI_SUCCESS) { - mutex_enter(&xenbusdrv_clone_tab_mutex); - xenbusdrv_clone_tab[minor] = 0; - mutex_exit(&xenbusdrv_clone_tab_mutex); - return (EAGAIN); - } - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor)); - - /* ... and init it */ - xbs->dip = xenbusdrv_dip; - mutex_init(&xbs->read_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&xbs->read_cv, NULL, CV_DEFAULT, NULL); - list_create(&xbs->transactions, sizeof (struct xenbus_dev_transaction), - offsetof(struct xenbus_dev_transaction, list)); - - /* clone driver */ - *devp = makedevice(getmajor(*devp), minor); - XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv open succeeded, minor=%d", - minor)); - - return (0); -} - -/* ARGSUSED */ -static int -xenbusdrv_close(dev_t dev, int flag, int otyp, struct cred *cr) -{ - xenbus_dev_t *xbs; - minor_t minor = getminor(dev); - struct xenbus_dev_transaction *trans; - - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(minor)); - if (xbs == NULL) - return (ENXIO); - -#ifdef notyet - /* - * XXPV - would like to be able to notify xenstore down here, but - * as the daemon is currently written, it doesn't leave the device - * open after initial setup, so we have no way of knowing if it has - * gone away. - */ - if (xbs->xenstore_inst) - xs_notify_xenstore_down(); -#endif - /* free pending transaction */ - while (trans = (struct xenbus_dev_transaction *) - list_head(&xbs->transactions)) { - (void) xenbus_transaction_end(trans->handle, 1); - list_remove(&xbs->transactions, (void *)trans); - kmem_free(trans, sizeof (*trans)); - } - - mutex_destroy(&xbs->read_mutex); - cv_destroy(&xbs->read_cv); - ddi_soft_state_free(xenbusdrv_statep, XENBUSDRV_MINOR2INST(minor)); - - /* - * free clone tab slot - */ - mutex_enter(&xenbusdrv_clone_tab_mutex); - xenbusdrv_clone_tab[minor] = 0; - mutex_exit(&xenbusdrv_clone_tab_mutex); - - XENBUSDRV_DBPRINT((CE_NOTE, "Xenbus drv close succeeded, minor=%d", - minor)); - - return (0); -} - -/* ARGSUSED */ -static int -xenbusdrv_read(dev_t dev, struct uio *uiop, cred_t *cr) -{ - xenbus_dev_t *xbs; - size_t len; - int res, ret; - int idx; - - XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_read called")); - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); - - mutex_enter(&xbs->read_mutex); - - /* check if we have something to read */ - while (xbs->read_prod == xbs->read_cons) { - if (cv_wait_sig(&xbs->read_cv, &xbs->read_mutex) == 0) { - mutex_exit(&xbs->read_mutex); - return (EINTR); - } - } - - idx = XENBUSDRV_MASK_READ_IDX(xbs->read_cons); - res = uiop->uio_resid; - - len = xbs->read_prod - xbs->read_cons; - - if (len > (sizeof (xbs->read_buffer) - idx)) - len = sizeof (xbs->read_buffer) - idx; - if (len > res) - len = res; - - ret = uiomove(xbs->read_buffer + idx, len, UIO_READ, uiop); - xbs->read_cons += res - uiop->uio_resid; - mutex_exit(&xbs->read_mutex); - - return (ret); -} - -/* - * prepare data for xenbusdrv_read() - */ -static int -xenbusdrv_queue_reply(xenbus_dev_t *xbs, const struct xsd_sockmsg *msg, - const char *reply) -{ - int i; - int remaining; - - XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply called")); - - mutex_enter(&xbs->read_mutex); - - remaining = sizeof (xbs->read_buffer) - - (xbs->read_prod - xbs->read_cons); - - if (sizeof (*msg) + msg->len > remaining) { - mutex_exit(&xbs->read_mutex); - return (EOVERFLOW); - } - - for (i = 0; i < sizeof (*msg); i++, xbs->read_prod++) { - xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] = - ((char *)msg)[i]; - } - - for (i = 0; i < msg->len; i++, xbs->read_prod++) { - xbs->read_buffer[XENBUSDRV_MASK_READ_IDX(xbs->read_prod)] = - reply[i]; - } - - cv_broadcast(&xbs->read_cv); - - mutex_exit(&xbs->read_mutex); - - XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_queue_reply exited")); - - return (0); -} - -/* ARGSUSED */ -static int -xenbusdrv_write(dev_t dev, struct uio *uiop, cred_t *cr) -{ - xenbus_dev_t *xbs; - struct xenbus_dev_transaction *trans; - void *reply; - size_t len; - int rc = 0; - - XENBUSDRV_DBPRINT((CE_NOTE, "xenbusdrv_write called")); - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); - len = uiop->uio_resid; - - if ((len + xbs->len) > sizeof (xbs->u.buffer)) { - XENBUSDRV_DBPRINT((CE_WARN, "Request is too big")); - rc = EINVAL; - goto out; - } - - if (uiomove(xbs->u.buffer + xbs->len, len, UIO_WRITE, uiop) != 0) { - XENBUSDRV_DBPRINT((CE_WARN, "Uiomove failed")); - rc = EFAULT; - goto out; - } - - xbs->len += len; - - if (xbs->len < (sizeof (xbs->u.msg)) || - xbs->len < (sizeof (xbs->u.msg) + xbs->u.msg.len)) { - XENBUSDRV_DBPRINT((CE_NOTE, "Partial request")); - return (0); - } - - switch (xbs->u.msg.type) { - case XS_TRANSACTION_START: - case XS_TRANSACTION_END: - case XS_DIRECTORY: - case XS_READ: - case XS_GET_PERMS: - case XS_RELEASE: - case XS_GET_DOMAIN_PATH: - case XS_WRITE: - case XS_MKDIR: - case XS_RM: - case XS_SET_PERMS: - /* send the request to xenstore and get feedback */ - rc = xenbus_dev_request_and_reply(&xbs->u.msg, &reply); - if (rc) { - XENBUSDRV_DBPRINT((CE_WARN, - "xenbus_dev_request_and_reply failed")); - goto out; - } - - /* handle transaction start/end */ - if (xbs->u.msg.type == XS_TRANSACTION_START) { - trans = kmem_alloc(sizeof (*trans), KM_SLEEP); - (void) ddi_strtoul((char *)reply, NULL, 0, - (unsigned long *)&trans->handle); - list_insert_tail(&xbs->transactions, (void *)trans); - } else if (xbs->u.msg.type == XS_TRANSACTION_END) { - /* try to find out the ending transaction */ - for (trans = (struct xenbus_dev_transaction *) - list_head(&xbs->transactions); trans; - trans = (struct xenbus_dev_transaction *) - list_next(&xbs->transactions, (void *)trans)) - if (trans->handle == - (xenbus_transaction_t) - xbs->u.msg.tx_id) - break; - ASSERT(trans); - /* free it, if we find it */ - list_remove(&xbs->transactions, (void *)trans); - kmem_free(trans, sizeof (*trans)); - } - - /* prepare data for xenbusdrv_read() to get */ - rc = xenbusdrv_queue_reply(xbs, &xbs->u.msg, reply); - - kmem_free(reply, xbs->u.msg.len + 1); - break; - default: - rc = EINVAL; - } - -out: - xbs->len = 0; - return (rc); -} - -/*ARGSUSED*/ -static int -xenbusdrv_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, - size_t *maplen, uint_t model) -{ - xenbus_dev_t *xbs; - int err; - - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); - - if (off != 0 || len != PAGESIZE) - return (-1); - - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return (-1); - - err = devmap_umem_setup(dhp, xbs->dip, NULL, xb_xenstore_cookie(), - 0, PAGESIZE, PROT_READ | PROT_WRITE | PROT_USER, 0, NULL); - - if (err) - return (err); - - *maplen = PAGESIZE; - - return (0); -} - -static int -xenbusdrv_segmap(dev_t dev, off_t off, ddi_as_handle_t as, caddr_t *addrp, - off_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr) -{ - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - return (ddi_devmap_segmap(dev, off, as, addrp, len, prot, - maxprot, flags, cr)); -} - -/*ARGSUSED*/ -static int -xenbusdrv_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, - int *rvalp) -{ - xenbus_dev_t *xbs; - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - xbs = XENBUSDRV_INST2SOFTS(XENBUSDRV_MINOR2INST(getminor(dev))); - switch (cmd) { - case IOCTL_XENBUS_XENSTORE_EVTCHN: - *rvalp = xen_info->store_evtchn; - break; - case IOCTL_XENBUS_NOTIFY_UP: - xs_notify_xenstore_up(); - xbs->xenstore_inst = 1; - break; - default: - return (EINVAL); - } - - return (0); -} diff --git a/usr/src/uts/common/xen/io/xenbus_probe.c b/usr/src/uts/common/xen/io/xenbus_probe.c deleted file mode 100644 index 050f11ad1c..0000000000 --- a/usr/src/uts/common/xen/io/xenbus_probe.c +++ /dev/null @@ -1,185 +0,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. - */ - -/* - * Talks to Xen Store to figure out what devices we have. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * Copyright (C) 2005 Mike Wray, Hewlett-Packard - * Copyright (C) 2005 XenSource Ltd - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifdef XPV_HVM_DRIVER -#include -#endif -#include -#include -#include -#include - -static int -read_otherend_details(struct xenbus_device *xendev, - char *id_node, char *path_node) -{ - int err = xenbus_gather(XBT_NULL, xendev->nodename, - id_node, "%i", &xendev->otherend_id, path_node, NULL, - &xendev->otherend, NULL); - if (err) { - xenbus_dev_fatal(xendev, err, - "reading other end details from %s", xendev->nodename); - return (err); - } - if (strlen(xendev->otherend) == 0 || - !xenbus_exists_dir(xendev->otherend, "")) { - xenbus_dev_fatal(xendev, X_ENOENT, "missing other end from %s", - xendev->nodename); - kmem_free((void *)xendev->otherend, - strlen(xendev->otherend) + 1); - xendev->otherend = NULL; - return (X_ENOENT); - } - - return (0); -} - - -static int -read_backend_details(struct xenbus_device *xendev) -{ - return (read_otherend_details(xendev, "backend-id", "backend")); -} - - -static int -read_frontend_details(struct xenbus_device *xendev) -{ - return (read_otherend_details(xendev, "frontend-id", "frontend")); -} - - -static void -free_otherend_details(struct xenbus_device *dev) -{ - if (dev->otherend != NULL) { - kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); - dev->otherend = NULL; - } -} - - -static void -free_otherend_watch(struct xenbus_device *dev) -{ - if (dev->otherend_watch.node) { - unregister_xenbus_watch(&dev->otherend_watch); - kmem_free((void *)dev->otherend_watch.node, - strlen(dev->otherend_watch.node) + 1); - dev->otherend_watch.node = NULL; - } -} - - -/*ARGSUSED2*/ -static void -otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) -{ - struct xenbus_device *dev = watch->dev; - XenbusState state; - - /* - * Protect us against watches firing on old details when the otherend - * details change, say immediately after a resume. - */ - if (!dev->otherend || - strncmp(dev->otherend, vec[XS_WATCH_PATH], strlen(dev->otherend))) { -#if 0 - printf("Ignoring watch at %s", vec[XS_WATCH_PATH]); -#endif - return; - } - - state = xenbus_read_driver_state(dev->otherend); - -#if 0 - printf("state is %d, %s, %s", - state, dev->otherend_watch.node, vec[XS_WATCH_PATH]); -#endif - if (dev->otherend_changed) - dev->otherend_changed(dev, state); -} - - -int -talk_to_otherend(struct xenbus_device *dev) -{ - int err; - - free_otherend_watch(dev); - free_otherend_details(dev); - - if (dev->frontend) - err = read_backend_details(dev); - else - err = read_frontend_details(dev); - if (err) - return (err); - - dev->otherend_watch.dev = dev; - return (xenbus_watch_path2(dev, dev->otherend, "state", - &dev->otherend_watch, otherend_changed)); -} - - -/* - * Local variables: - * c-file-style: "solaris" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/usr/src/uts/common/xen/io/xenbus_xs.c b/usr/src/uts/common/xen/io/xenbus_xs.c deleted file mode 100644 index 3d6b46cb24..0000000000 --- a/usr/src/uts/common/xen/io/xenbus_xs.c +++ /dev/null @@ -1,1139 +0,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. - */ - -/* - * - * xenbus_xs.c - * - * This is the kernel equivalent of the "xs" library. We don't need everything - * and we use xenbus_comms for communication. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * NOTE: To future maintainers of the Solaris version of this file: - * I found the Linux version of this code to be very disgusting in - * overloading pointers and error codes into void * return values. - * The main difference you will find is that all such usage is changed - * to pass pointers to void* to be filled in with return values and - * the functions return error codes. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define _XSD_ERRORS_DEFINED -#ifdef XPV_HVM_DRIVER -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#define streq(a, b) (strcmp((a), (b)) == 0) - -#define list_empty(list) (list_head(list) == NULL) - -struct xs_stored_msg { - list_node_t list; - - struct xsd_sockmsg hdr; - - union { - /* Queued replies. */ - struct { - char *body; - } reply; - - /* Queued watch events. */ - struct { - struct xenbus_watch *handle; - char **vec; - unsigned int vec_size; - } watch; - } un; -}; - -static struct xs_handle { - /* A list of replies. Currently only one will ever be outstanding. */ - list_t reply_list; - kmutex_t reply_lock; - kcondvar_t reply_cv; - - /* One request at a time. */ - kmutex_t request_mutex; - - /* Protect transactions against save/restore. */ - krwlock_t suspend_lock; -} xs_state; - -static int last_req_id; - -/* - * List of clients wanting a xenstore up notification, and a lock to protect it - */ -static boolean_t xenstore_up; -static list_t notify_list; -static kmutex_t notify_list_lock; -static taskq_t *xenbus_taskq; - -/* List of registered watches, and a lock to protect it. */ -static list_t watches; -static kmutex_t watches_lock; - -/* List of pending watch callback events, and a lock to protect it. */ -static list_t watch_events; -static kmutex_t watch_events_lock; - -/* - * Details of the xenwatch callback kernel thread. The thread waits on the - * watch_events_cv for work to do (queued on watch_events list). When it - * wakes up it acquires the xenwatch_mutex before reading the list and - * carrying out work. - */ -static kmutex_t xenwatch_mutex; -static kcondvar_t watch_events_cv; - -static int process_msg(void); - -static int -get_error(const char *errorstring) -{ - unsigned int i; - - for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { - if (i == (sizeof (xsd_errors) / sizeof (xsd_errors[0])) - 1) { - cmn_err(CE_WARN, - "XENBUS xen store gave: unknown error %s", - errorstring); - return (EINVAL); - } - } - return (xsd_errors[i].errnum); -} - -/* - * Read a synchronous reply from xenstore. Since we can return early before - * reading a relevant reply, we discard any messages not matching the request - * ID. Caller must free returned message on success. - */ -static int -read_reply(struct xsd_sockmsg *req_hdr, struct xs_stored_msg **reply) -{ - extern int do_polled_io; - - mutex_enter(&xs_state.reply_lock); - - for (;;) { - while (list_empty(&xs_state.reply_list)) { - if (interrupts_unleashed && !do_polled_io) { - if (cv_wait_sig(&xs_state.reply_cv, - &xs_state.reply_lock) == 0) { - mutex_exit(&xs_state.reply_lock); - *reply = NULL; - return (EINTR); - } - } else { /* polled mode needed for early probes */ - mutex_exit(&xs_state.reply_lock); - (void) HYPERVISOR_yield(); - (void) process_msg(); - mutex_enter(&xs_state.reply_lock); - } - } - - *reply = list_head(&xs_state.reply_list); - list_remove(&xs_state.reply_list, *reply); - - if ((*reply)->hdr.req_id == req_hdr->req_id) - break; - } - - mutex_exit(&xs_state.reply_lock); - return (0); -} - -/* Emergency write. */ -void -xenbus_debug_write(const char *str, unsigned int count) -{ - struct xsd_sockmsg msg = { 0 }; - - msg.type = XS_DEBUG; - msg.len = sizeof ("print") + count + 1; - - mutex_enter(&xs_state.request_mutex); - (void) xb_write(&msg, sizeof (msg)); - (void) xb_write("print", sizeof ("print")); - (void) xb_write(str, count); - (void) xb_write("", 1); - mutex_exit(&xs_state.request_mutex); -} - -/* - * This is pretty unpleasant. First off, there's the horrible logic around - * suspend_lock and transactions. Also, we can be interrupted either before we - * write a message, or before we receive a reply. A client that wants to - * survive this can't know which case happened. Luckily all clients don't care - * about signals currently, and the alternative (a hard wait on a userspace - * daemon) isn't exactly preferable. Caller must free 'reply' on success. - */ -int -xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **reply) -{ - struct xsd_sockmsg req_msg = *msg; - struct xs_stored_msg *reply_msg = NULL; - int err; - - if (req_msg.type == XS_TRANSACTION_START) - rw_enter(&xs_state.suspend_lock, RW_READER); - - mutex_enter(&xs_state.request_mutex); - - msg->req_id = last_req_id++; - - err = xb_write(msg, sizeof (*msg) + msg->len); - if (err) { - if (req_msg.type == XS_TRANSACTION_START) - rw_exit(&xs_state.suspend_lock); - msg->type = XS_ERROR; - *reply = NULL; - goto out; - } - - err = read_reply(msg, &reply_msg); - - if (err) { - if (msg->type == XS_TRANSACTION_START) - rw_exit(&xs_state.suspend_lock); - *reply = NULL; - goto out; - } - - *reply = reply_msg->un.reply.body; - *msg = reply_msg->hdr; - - if (reply_msg->hdr.type == XS_TRANSACTION_END) - rw_exit(&xs_state.suspend_lock); - -out: - if (reply_msg != NULL) - kmem_free(reply_msg, sizeof (*reply_msg)); - - mutex_exit(&xs_state.request_mutex); - return (err); -} - -/* - * Send message to xs, return errcode, rval filled in with pointer - * to kmem_alloc'ed reply. - */ -static int -xs_talkv(xenbus_transaction_t t, - enum xsd_sockmsg_type type, - const iovec_t *iovec, - unsigned int num_vecs, - void **rval, - unsigned int *len) -{ - struct xsd_sockmsg msg; - struct xs_stored_msg *reply_msg; - char *reply; - unsigned int i; - int err; - - msg.tx_id = (uint32_t)(unsigned long)t; - msg.type = type; - msg.len = 0; - for (i = 0; i < num_vecs; i++) - msg.len += iovec[i].iov_len; - - mutex_enter(&xs_state.request_mutex); - - msg.req_id = last_req_id++; - - err = xb_write(&msg, sizeof (msg)); - if (err) { - mutex_exit(&xs_state.request_mutex); - return (err); - } - - for (i = 0; i < num_vecs; i++) { - err = xb_write(iovec[i].iov_base, iovec[i].iov_len); - if (err) { - mutex_exit(&xs_state.request_mutex); - return (err); - } - } - - err = read_reply(&msg, &reply_msg); - - mutex_exit(&xs_state.request_mutex); - - if (err) - return (err); - - reply = reply_msg->un.reply.body; - - if (reply_msg->hdr.type == XS_ERROR) { - err = get_error(reply); - kmem_free(reply, reply_msg->hdr.len + 1); - goto out; - } - - if (len != NULL) - *len = reply_msg->hdr.len + 1; - - ASSERT(reply_msg->hdr.type == type); - - if (rval != NULL) - *rval = reply; - else - kmem_free(reply, reply_msg->hdr.len + 1); - -out: - kmem_free(reply_msg, sizeof (*reply_msg)); - return (err); -} - -/* Simplified version of xs_talkv: single message. */ -static int -xs_single(xenbus_transaction_t t, - enum xsd_sockmsg_type type, - const char *string, void **ret, - unsigned int *len) -{ - iovec_t iovec; - - iovec.iov_base = (char *)string; - iovec.iov_len = strlen(string) + 1; - return (xs_talkv(t, type, &iovec, 1, ret, len)); -} - -static unsigned int -count_strings(const char *strings, unsigned int len) -{ - unsigned int num; - const char *p; - - for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) - num++; - - return (num); -} - -/* Return the path to dir with /name appended. Buffer must be kmem_free()'ed */ -static char * -join(const char *dir, const char *name) -{ - char *buffer; - size_t slashlen; - - slashlen = streq(name, "") ? 0 : 1; - buffer = kmem_alloc(strlen(dir) + slashlen + strlen(name) + 1, - KM_SLEEP); - - (void) strcpy(buffer, dir); - if (slashlen != 0) { - (void) strcat(buffer, "/"); - (void) strcat(buffer, name); - } - return (buffer); -} - -static char ** -split(char *strings, unsigned int len, unsigned int *num) -{ - char *p, **ret; - - /* Count the strings. */ - if ((*num = count_strings(strings, len - 1)) == 0) - return (NULL); - - /* Transfer to one big alloc for easy freeing. */ - ret = kmem_alloc(*num * sizeof (char *) + (len - 1), KM_SLEEP); - (void) memcpy(&ret[*num], strings, len - 1); - kmem_free(strings, len); - - strings = (char *)&ret[*num]; - for (p = strings, *num = 0; p < strings + (len - 1); - p += strlen(p) + 1) { - ret[(*num)++] = p; - } - - return (ret); -} - -char ** -xenbus_directory(xenbus_transaction_t t, - const char *dir, const char *node, unsigned int *num) -{ - char *strings, *path; - unsigned int len; - int err; - - path = join(dir, node); - err = xs_single(t, XS_DIRECTORY, path, (void **)&strings, &len); - kmem_free(path, strlen(path) + 1); - if (err != 0 || strings == NULL) { - /* sigh, we lose error code info here */ - *num = 0; - return (NULL); - } - - return (split(strings, len, num)); -} - -/* Check if a path exists. */ -boolean_t -xenbus_exists(const char *dir, const char *node) -{ - void *p; - uint_t n; - - if (xenbus_read(XBT_NULL, dir, node, &p, &n) != 0) - return (B_FALSE); - kmem_free(p, n); - return (B_TRUE); -} - -/* Check if a directory path exists. */ -boolean_t -xenbus_exists_dir(const char *dir, const char *node) -{ - char **d; - unsigned int dir_n; - int i, len; - - d = xenbus_directory(XBT_NULL, dir, node, &dir_n); - if (d == NULL) - return (B_FALSE); - for (i = 0, len = 0; i < dir_n; i++) - len += strlen(d[i]) + 1 + sizeof (char *); - kmem_free(d, len); - return (B_TRUE); -} - -/* - * Get the value of a single file. - * Returns a kmem_alloced value in retp: call kmem_free() on it after use. - * len indicates length in bytes. - */ -int -xenbus_read(xenbus_transaction_t t, - const char *dir, const char *node, void **retp, unsigned int *len) -{ - char *path; - int err; - - path = join(dir, node); - err = xs_single(t, XS_READ, path, retp, len); - kmem_free(path, strlen(path) + 1); - return (err); -} - -int -xenbus_read_str(const char *dir, const char *node, char **retp) -{ - uint_t n; - int err; - char *str; - - /* - * Since we access the xenbus value immediatly we can't be - * part of a transaction. - */ - if ((err = xenbus_read(XBT_NULL, dir, node, (void **)&str, &n)) != 0) - return (err); - ASSERT((str != NULL) && (n > 0)); - - /* - * Why bother with this? Because xenbus is truly annoying in the - * fact that when it returns a string, it doesn't guarantee that - * the memory that holds the string is of size strlen() + 1. - * This forces callers to keep track of the size of the memory - * containing the string. Ugh. We'll work around this by - * re-allocate strings to always be of size strlen() + 1. - */ - *retp = strdup(str); - kmem_free(str, n); - return (0); -} - -/* - * Write the value of a single file. - * Returns err on failure. - */ -int -xenbus_write(xenbus_transaction_t t, - const char *dir, const char *node, const char *string) -{ - char *path; - iovec_t iovec[2]; - int ret; - - path = join(dir, node); - - iovec[0].iov_base = (void *)path; - iovec[0].iov_len = strlen(path) + 1; - iovec[1].iov_base = (void *)string; - iovec[1].iov_len = strlen(string); - - ret = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL); - kmem_free(path, iovec[0].iov_len); - return (ret); -} - -/* Create a new directory. */ -int -xenbus_mkdir(xenbus_transaction_t t, const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - ret = xs_single(t, XS_MKDIR, path, NULL, NULL); - kmem_free(path, strlen(path) + 1); - return (ret); -} - -/* Destroy a file or directory (directories must be empty). */ -int -xenbus_rm(xenbus_transaction_t t, const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - ret = xs_single(t, XS_RM, path, NULL, NULL); - kmem_free(path, strlen(path) + 1); - return (ret); -} - -/* - * Start a transaction: changes by others will not be seen during this - * transaction, and changes will not be visible to others until end. - */ -int -xenbus_transaction_start(xenbus_transaction_t *t) -{ - void *id_str; - unsigned long id; - int err; - unsigned int len; - - rw_enter(&xs_state.suspend_lock, RW_READER); - - err = xs_single(XBT_NULL, XS_TRANSACTION_START, "", &id_str, &len); - if (err) { - rw_exit(&xs_state.suspend_lock); - return (err); - } - - (void) ddi_strtoul((char *)id_str, NULL, 0, &id); - *t = (xenbus_transaction_t)id; - kmem_free(id_str, len); - - return (0); -} - -/* - * End a transaction. - * If abandon is true, transaction is discarded instead of committed. - */ -int -xenbus_transaction_end(xenbus_transaction_t t, int abort) -{ - char abortstr[2]; - int err; - - if (abort) - (void) strcpy(abortstr, "F"); - else - (void) strcpy(abortstr, "T"); - - err = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL); - - rw_exit(&xs_state.suspend_lock); - - return (err); -} - -/* - * Single read and scanf: returns errno or 0. This can only handle a single - * conversion specifier. - */ -/* SCANFLIKE4 */ -int -xenbus_scanf(xenbus_transaction_t t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; - char *val; - unsigned int len; - - ret = xenbus_read(t, dir, node, (void **)&val, &len); - if (ret) - return (ret); - - va_start(ap, fmt); - if (vsscanf(val, fmt, ap) != 1) - ret = ERANGE; - va_end(ap); - kmem_free(val, len); - return (ret); -} - -/* Single printf and write: returns errno or 0. */ -/* PRINTFLIKE4 */ -int -xenbus_printf(xenbus_transaction_t t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; -#define PRINTF_BUFFER_SIZE 4096 - char *printf_buffer; - - printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP); - - va_start(ap, fmt); - ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); - va_end(ap); - - ASSERT(ret <= PRINTF_BUFFER_SIZE-1); - ret = xenbus_write(t, dir, node, printf_buffer); - - kmem_free(printf_buffer, PRINTF_BUFFER_SIZE); - - return (ret); -} - - -/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int -xenbus_gather(xenbus_transaction_t t, const char *dir, ...) -{ - va_list ap; - const char *name; - int ret = 0; - unsigned int len; - - va_start(ap, dir); - while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - char *p; - - ret = xenbus_read(t, dir, name, (void **)&p, &len); - if (ret) - break; - if (fmt) { - ASSERT(result != NULL); - if (sscanf(p, fmt, result) != 1) - ret = EINVAL; - kmem_free(p, len); - } else - *(char **)result = p; - } - va_end(ap); - return (ret); -} - -static int -xs_watch(const char *path, const char *token) -{ - iovec_t iov[2]; - - iov[0].iov_base = (void *)path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = (void *)token; - iov[1].iov_len = strlen(token) + 1; - - return (xs_talkv(XBT_NULL, XS_WATCH, iov, 2, NULL, NULL)); -} - -static int -xs_unwatch(const char *path, const char *token) -{ - iovec_t iov[2]; - - iov[0].iov_base = (char *)path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = (char *)token; - iov[1].iov_len = strlen(token) + 1; - - return (xs_talkv(XBT_NULL, XS_UNWATCH, iov, 2, NULL, NULL)); -} - -static struct xenbus_watch * -find_watch(const char *token) -{ - struct xenbus_watch *i, *cmp; - - (void) ddi_strtoul(token, NULL, 16, (unsigned long *)&cmp); - - for (i = list_head(&watches); i != NULL; i = list_next(&watches, i)) - if (i == cmp) - break; - - return (i); -} - -/* Register a xenstore state notify callback */ -int -xs_register_xenbus_callback(void (*callback)(int)) -{ - struct xenbus_notify *xbn, *xnp; - - xbn = kmem_alloc(sizeof (struct xenbus_notify), KM_SLEEP); - xbn->notify_func = callback; - mutex_enter(¬ify_list_lock); - /* - * Make sure not already on the list - */ - xnp = list_head(¬ify_list); - for (; xnp != NULL; xnp = list_next(¬ify_list, xnp)) { - if (xnp->notify_func == callback) { - kmem_free(xbn, sizeof (struct xenbus_notify)); - mutex_exit(¬ify_list_lock); - return (EEXIST); - } - } - xnp = xbn; - list_insert_tail(¬ify_list, xbn); -done: - if (xenstore_up) - xnp->notify_func(XENSTORE_UP); - mutex_exit(¬ify_list_lock); - return (0); -} - -/* - * Notify clients of xenstore state - */ -static void -do_notify_callbacks(void *arg) -{ - struct xenbus_notify *xnp; - - mutex_enter(¬ify_list_lock); - xnp = list_head(¬ify_list); - for (; xnp != NULL; xnp = list_next(¬ify_list, xnp)) { - xnp->notify_func((int)((uintptr_t)arg)); - } - mutex_exit(¬ify_list_lock); -} - -void -xs_notify_xenstore_up(void) -{ - xenstore_up = B_TRUE; - (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks, - (void *)XENSTORE_UP, 0); -} - -void -xs_notify_xenstore_down(void) -{ - xenstore_up = B_FALSE; - (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks, - (void *)XENSTORE_DOWN, 0); -} - -/* Register callback to watch this node. */ -int -register_xenbus_watch(struct xenbus_watch *watch) -{ - /* Pointer in ascii is the token. */ - char token[sizeof (watch) * 2 + 1]; - int err; - - ASSERT(xenstore_up); - (void) snprintf(token, sizeof (token), "%lX", (long)watch); - - rw_enter(&xs_state.suspend_lock, RW_READER); - - mutex_enter(&watches_lock); - /* - * May be re-registering a watch if xenstore daemon was restarted - */ - if (find_watch(token) == NULL) - list_insert_tail(&watches, watch); - mutex_exit(&watches_lock); - - DTRACE_XPV3(xenbus__register__watch, const char *, watch->node, - uintptr_t, watch->callback, struct xenbus_watch *, watch); - - err = xs_watch(watch->node, token); - - /* Ignore errors due to multiple registration. */ - if ((err != 0) && (err != EEXIST)) { - mutex_enter(&watches_lock); - list_remove(&watches, watch); - mutex_exit(&watches_lock); - } - - rw_exit(&xs_state.suspend_lock); - - return (err); -} - -static void -free_stored_msg(struct xs_stored_msg *msg) -{ - int i, len = 0; - - for (i = 0; i < msg->un.watch.vec_size; i++) - len += strlen(msg->un.watch.vec[i]) + 1 + sizeof (char *); - kmem_free(msg->un.watch.vec, len); - kmem_free(msg, sizeof (*msg)); -} - -void -unregister_xenbus_watch(struct xenbus_watch *watch) -{ - struct xs_stored_msg *msg; - char token[sizeof (watch) * 2 + 1]; - int err; - - (void) snprintf(token, sizeof (token), "%lX", (long)watch); - - rw_enter(&xs_state.suspend_lock, RW_READER); - - mutex_enter(&watches_lock); - ASSERT(find_watch(token)); - list_remove(&watches, watch); - mutex_exit(&watches_lock); - - DTRACE_XPV3(xenbus__unregister__watch, const char *, watch->node, - uintptr_t, watch->callback, struct xenbus_watch *, watch); - - err = xs_unwatch(watch->node, token); - if (err) - cmn_err(CE_WARN, "XENBUS Failed to release watch %s: %d", - watch->node, err); - - rw_exit(&xs_state.suspend_lock); - - /* Cancel pending watch events. */ - mutex_enter(&watch_events_lock); - msg = list_head(&watch_events); - - while (msg != NULL) { - struct xs_stored_msg *tmp = list_next(&watch_events, msg); - if (msg->un.watch.handle == watch) { - list_remove(&watch_events, msg); - free_stored_msg(msg); - } - msg = tmp; - } - - mutex_exit(&watch_events_lock); - - /* Flush any currently-executing callback, unless we are it. :-) */ - if (mutex_owner(&xenwatch_mutex) != curthread) { - mutex_enter(&xenwatch_mutex); - mutex_exit(&xenwatch_mutex); - } -} - -void -xenbus_suspend(void) -{ - rw_enter(&xs_state.suspend_lock, RW_WRITER); - mutex_enter(&xs_state.request_mutex); - - xb_suspend(); -} - -void -xenbus_resume(void) -{ - struct xenbus_watch *watch; - char token[sizeof (watch) * 2 + 1]; - - mutex_exit(&xs_state.request_mutex); - - xb_init(); - xb_setup_intr(); - - /* No need for watches_lock: the suspend_lock is sufficient. */ - for (watch = list_head(&watches); watch != NULL; - watch = list_next(&watches, watch)) { - (void) snprintf(token, sizeof (token), "%lX", (long)watch); - (void) xs_watch(watch->node, token); - } - - rw_exit(&xs_state.suspend_lock); -} - -static void -xenwatch_thread(void) -{ - struct xs_stored_msg *msg; - struct xenbus_watch *watch; - - for (;;) { - mutex_enter(&watch_events_lock); - while (list_empty(&watch_events)) - cv_wait(&watch_events_cv, &watch_events_lock); - msg = list_head(&watch_events); - ASSERT(msg != NULL); - list_remove(&watch_events, msg); - watch = msg->un.watch.handle; - mutex_exit(&watch_events_lock); - - mutex_enter(&xenwatch_mutex); - - DTRACE_XPV4(xenbus__fire__watch, - const char *, watch->node, - uintptr_t, watch->callback, - struct xenbus_watch *, watch, - const char *, msg->un.watch.vec[XS_WATCH_PATH]); - - watch->callback(watch, (const char **)msg->un.watch.vec, - msg->un.watch.vec_size); - - free_stored_msg(msg); - mutex_exit(&xenwatch_mutex); - } -} - -static int -process_msg(void) -{ - struct xs_stored_msg *msg; - char *body; - int err, mlen; - - msg = kmem_alloc(sizeof (*msg), KM_SLEEP); - - err = xb_read(&msg->hdr, sizeof (msg->hdr)); - if (err) { - kmem_free(msg, sizeof (*msg)); - return (err); - } - - mlen = msg->hdr.len + 1; - body = kmem_alloc(mlen, KM_SLEEP); - - err = xb_read(body, msg->hdr.len); - if (err) { - kmem_free(body, mlen); - kmem_free(msg, sizeof (*msg)); - return (err); - } - - body[mlen - 1] = '\0'; - - if (msg->hdr.type == XS_WATCH_EVENT) { - const char *token; - msg->un.watch.vec = split(body, msg->hdr.len + 1, - &msg->un.watch.vec_size); - if (msg->un.watch.vec == NULL) { - kmem_free(msg, sizeof (*msg)); - return (EIO); - } - - mutex_enter(&watches_lock); - token = msg->un.watch.vec[XS_WATCH_TOKEN]; - if ((msg->un.watch.handle = find_watch(token)) != NULL) { - mutex_enter(&watch_events_lock); - - DTRACE_XPV4(xenbus__enqueue__watch, - const char *, msg->un.watch.handle->node, - uintptr_t, msg->un.watch.handle->callback, - struct xenbus_watch *, msg->un.watch.handle, - const char *, msg->un.watch.vec[XS_WATCH_PATH]); - - list_insert_tail(&watch_events, msg); - cv_broadcast(&watch_events_cv); - mutex_exit(&watch_events_lock); - } else { - free_stored_msg(msg); - } - mutex_exit(&watches_lock); - } else { - msg->un.reply.body = body; - mutex_enter(&xs_state.reply_lock); - list_insert_tail(&xs_state.reply_list, msg); - mutex_exit(&xs_state.reply_lock); - cv_signal(&xs_state.reply_cv); - } - - return (0); -} - -static void -xenbus_thread(void) -{ - int err; - - /* - * We have to wait for interrupts to be ready, so we don't clash - * with the polled-IO code in read_reply(). - */ - while (!interrupts_unleashed) - delay(10); - - for (;;) { - err = process_msg(); - if (err) - cmn_err(CE_WARN, "XENBUS error %d while reading " - "message", err); - } -} - -/* - * When setting up xenbus, dom0 and domU have to take different paths, which - * makes this code a little confusing. For dom0: - * - * xs_early_init - mutex init only - * xs_dom0_init - called on xenbus dev attach: set up our xenstore page and - * event channel; start xenbus threads for responding to interrupts. - * - * And for domU: - * - * xs_early_init - mutex init; set up our xenstore page and event channel - * xs_domu_init - installation of IRQ handler; start xenbus threads. - * - * We need an early init on domU so we can use xenbus in polled mode to - * discover devices, VCPUs etc. - * - * On resume, we use xb_init() and xb_setup_intr() to restore xenbus to a - * working state. - */ - -void -xs_early_init(void) -{ - list_create(&xs_state.reply_list, sizeof (struct xs_stored_msg), - offsetof(struct xs_stored_msg, list)); - list_create(&watch_events, sizeof (struct xs_stored_msg), - offsetof(struct xs_stored_msg, list)); - list_create(&watches, sizeof (struct xenbus_watch), - offsetof(struct xenbus_watch, list)); - list_create(¬ify_list, sizeof (struct xenbus_notify), - offsetof(struct xenbus_notify, list)); - mutex_init(&xs_state.reply_lock, NULL, MUTEX_DEFAULT, NULL); - mutex_init(&xs_state.request_mutex, NULL, MUTEX_DEFAULT, NULL); - mutex_init(¬ify_list_lock, NULL, MUTEX_DEFAULT, NULL); - rw_init(&xs_state.suspend_lock, NULL, RW_DEFAULT, NULL); - cv_init(&xs_state.reply_cv, NULL, CV_DEFAULT, NULL); - - if (DOMAIN_IS_INITDOMAIN(xen_info)) - return; - - xb_init(); - xenstore_up = B_TRUE; -} - -static void -xs_thread_init(void) -{ - (void) thread_create(NULL, 0, xenwatch_thread, NULL, 0, &p0, - TS_RUN, minclsyspri); - (void) thread_create(NULL, 0, xenbus_thread, NULL, 0, &p0, - TS_RUN, minclsyspri); - xenbus_taskq = taskq_create("xenbus_taskq", 1, - maxclsyspri - 1, 1, 1, TASKQ_PREPOPULATE); - ASSERT(xenbus_taskq != NULL); -} - -void -xs_domu_init(void) -{ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - return; - - /* - * Add interrupt handler for xenbus now, must wait till after - * psm module is loaded. All use of xenbus is in polled mode - * until xs_init is called since it is what kicks off the xs - * server threads. - */ - xs_thread_init(); - xb_setup_intr(); -} - - -void -xs_dom0_init(void) -{ - static boolean_t initialized = B_FALSE; - - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - /* - * The xenbus driver might be re-attaching. - */ - if (initialized) - return; - - xb_init(); - xs_thread_init(); - xb_setup_intr(); - - initialized = B_TRUE; -} diff --git a/usr/src/uts/common/xen/io/xencons.c b/usr/src/uts/common/xen/io/xencons.c deleted file mode 100644 index c2e7b7f08d..0000000000 --- a/usr/src/uts/common/xen/io/xencons.c +++ /dev/null @@ -1,1656 +0,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 (c) 1990, 1991 UNIX System Laboratories, Inc. */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ -/* All Rights Reserved */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -/* - * - * Copyright (c) 2004 Christian Limpach. - * 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. - * 3. This section intentionally left blank. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - */ -/* - * Section 3 of the above license was updated in response to bug 6379571. - */ - -/* - * Hypervisor virtual console driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef DEBUG -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xencons.h" - -#include -#include -#include -#include - -#ifdef DEBUG -#define XENCONS_DEBUG_INIT 0x0001 /* msgs during driver initialization. */ -#define XENCONS_DEBUG_INPUT 0x0002 /* characters received during int. */ -#define XENCONS_DEBUG_EOT 0x0004 /* msgs when wait for xmit to finish. */ -#define XENCONS_DEBUG_CLOSE 0x0008 /* msgs when driver open/close called */ -#define XENCONS_DEBUG_PROCS 0x0020 /* each proc name as it is entered. */ -#define XENCONS_DEBUG_OUT 0x0100 /* msgs about output events. */ -#define XENCONS_DEBUG_BUSY 0x0200 /* msgs when xmit is enabled/disabled */ -#define XENCONS_DEBUG_MODEM 0x0400 /* msgs about modem status & control. */ -#define XENCONS_DEBUG_MODM2 0x0800 /* msgs about modem status & control. */ -#define XENCONS_DEBUG_IOCTL 0x1000 /* Output msgs about ioctl messages. */ -#define XENCONS_DEBUG_CHIP 0x2000 /* msgs about chip identification. */ -#define XENCONS_DEBUG_SFLOW 0x4000 /* msgs when S/W flowcontrol active */ -#define XENCONS_DEBUG(x) (debug & (x)) -static int debug = 0; -#else -#define XENCONS_DEBUG(x) B_FALSE -#endif - -#define XENCONS_WBUFSIZE 4096 - -static boolean_t abort_charseq_recognize(uchar_t); - -/* The async interrupt entry points */ -static void xcasync_ioctl(struct asyncline *, queue_t *, mblk_t *); -static void xcasync_reioctl(void *); -static void xcasync_start(struct asyncline *); -static void xenconsputchar(cons_polledio_arg_t, uchar_t); -static int xenconsgetchar(cons_polledio_arg_t); -static boolean_t xenconsischar(cons_polledio_arg_t); - -static uint_t xenconsintr(caddr_t); -static uint_t xenconsintr_priv(caddr_t); -/*PRINTFLIKE2*/ -static void xenconserror(int, const char *, ...) __KPRINTFLIKE(2); -static void xencons_soft_state_free(struct xencons *); -static boolean_t -xcasync_flowcontrol_sw_input(struct xencons *, async_flowc_action, int); -static void -xcasync_flowcontrol_sw_output(struct xencons *, async_flowc_action); - -void *xencons_soft_state; -char *xencons_wbuf; -struct xencons *xencons_console; - -static void -xenconssetup_avintr(struct xencons *xcp, int attach) -{ - /* - * On xen, CPU 0 always exists and can't be taken offline, - * so binding this thread to it should always succeed. - */ - mutex_enter(&cpu_lock); - thread_affinity_set(curthread, 0); - mutex_exit(&cpu_lock); - - if (attach) { - /* Setup our interrupt binding. */ - (void) add_avintr(NULL, IPL_CONS, (avfunc)xenconsintr_priv, - "xencons", xcp->console_irq, (caddr_t)xcp, NULL, NULL, - xcp->dip); - } else { - /* - * Cleanup interrupt configuration. Note that the framework - * _should_ ensure that when rem_avintr() returns the interrupt - * service routine is not currently executing and that it won't - * be invoked again. - */ - (void) rem_avintr(NULL, IPL_CONS, (avfunc)xenconsintr_priv, - xcp->console_irq); - } - - /* Notify our caller that we're done. */ - mutex_enter(&xcp->excl); - cv_signal(&xcp->excl_cv); - mutex_exit(&xcp->excl); - - /* Clear our binding to CPU 0 */ - thread_affinity_clear(curthread); - -} - -static void -xenconssetup_add_avintr(struct xencons *xcp) -{ - xenconssetup_avintr(xcp, B_TRUE); -} - -static void -xenconssetup_rem_avintr(struct xencons *xcp) -{ - xenconssetup_avintr(xcp, B_FALSE); -} - -static int -xenconsdetach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - int instance; - struct xencons *xcp; - - if (cmd != DDI_DETACH && cmd != DDI_SUSPEND) - return (DDI_FAILURE); - - if (cmd == DDI_SUSPEND) { - ddi_remove_intr(devi, 0, NULL); - return (DDI_SUCCESS); - } - - /* - * We should never try to detach the console driver on a domU - * because it should always be held open - */ - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return (DDI_FAILURE); - - instance = ddi_get_instance(devi); /* find out which unit */ - - xcp = ddi_get_soft_state(xencons_soft_state, instance); - if (xcp == NULL) - return (DDI_FAILURE); - - /* - * Cleanup our interrupt bindings. For more info on why we - * do this in a seperate thread, see the comments for when we - * setup the interrupt bindings. - */ - xencons_console = NULL; - mutex_enter(&xcp->excl); - (void) taskq_dispatch(system_taskq, - (void (*)(void *))xenconssetup_rem_avintr, xcp, TQ_SLEEP); - cv_wait(&xcp->excl_cv, &xcp->excl); - mutex_exit(&xcp->excl); - - /* remove all minor device node(s) for this device */ - ddi_remove_minor_node(devi, NULL); - - /* free up state */ - xencons_soft_state_free(xcp); - kmem_free(xencons_wbuf, XENCONS_WBUFSIZE); - - DEBUGNOTE1(XENCONS_DEBUG_INIT, "xencons%d: shutdown complete", - instance); - return (DDI_SUCCESS); -} - -static void -xenconssetup(struct xencons *xcp) -{ - xcp->ifp = (volatile struct xencons_interface *)HYPERVISOR_console_page; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - xencons_wbuf = kmem_alloc(XENCONS_WBUFSIZE, KM_SLEEP); - - /* - * Activate the xen console virq. Note that xen requires - * that VIRQs be bound to CPU 0 when first created. - */ - xcp->console_irq = ec_bind_virq_to_irq(VIRQ_CONSOLE, 0); - - /* - * Ok. This is kinda ugly. We want to register an - * interrupt handler for the xen console virq, but - * virq's are xen sepcific and currently the DDI doesn't - * support binding to them. So instead we need to use - * add_avintr(). So to make things more complicated, - * we already had to bind the xen console VIRQ to CPU 0, - * and add_avintr() needs to be invoked on the same CPU - * where the VIRQ is bound, in this case on CPU 0. We - * could just temporarily bind ourselves to CPU 0, but - * we don't want to do that since this attach thread - * could have been invoked in a user thread context, - * in which case this thread could already have some - * pre-existing cpu binding. So to avoid changing our - * cpu binding we're going to use a taskq thread that - * will bind to CPU 0 and register our interrupts - * handler for us. - */ - mutex_enter(&xcp->excl); - (void) taskq_dispatch(system_taskq, - (void (*)(void *))xenconssetup_add_avintr, xcp, TQ_SLEEP); - cv_wait(&xcp->excl_cv, &xcp->excl); - mutex_exit(&xcp->excl); - } else { - (void) xvdi_alloc_evtchn(xcp->dip); - xcp->evtchn = xvdi_get_evtchn(xcp->dip); - (void) ddi_add_intr(xcp->dip, 0, NULL, NULL, xenconsintr, - (caddr_t)xcp); - } -} - -static int -xenconsattach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - int instance = ddi_get_instance(devi); - struct xencons *xcp; - int ret; - - /* There can be only one. */ - if (instance != 0) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_RESUME: - xcp = xencons_console; - xenconssetup(xcp); - return (DDI_SUCCESS); - case DDI_ATTACH: - break; - default: - return (DDI_FAILURE); - } - - ret = ddi_soft_state_zalloc(xencons_soft_state, instance); - if (ret != DDI_SUCCESS) - return (DDI_FAILURE); - xcp = ddi_get_soft_state(xencons_soft_state, instance); - ASSERT(xcp != NULL); /* can't fail - we only just allocated it */ - - /* - * Set up the other components of the xencons structure for this port. - */ - xcp->unit = instance; - xcp->dip = devi; - - /* Fill in the polled I/O structure. */ - xcp->polledio.cons_polledio_version = CONSPOLLEDIO_V0; - xcp->polledio.cons_polledio_argument = (cons_polledio_arg_t)xcp; - xcp->polledio.cons_polledio_putchar = xenconsputchar; - xcp->polledio.cons_polledio_getchar = xenconsgetchar; - xcp->polledio.cons_polledio_ischar = xenconsischar; - xcp->polledio.cons_polledio_enter = NULL; - xcp->polledio.cons_polledio_exit = NULL; - - /* - * Initializes the asyncline structure which has TTY protocol-private - * data before enabling interrupts. - */ - xcp->priv = kmem_zalloc(sizeof (struct asyncline), KM_SLEEP); - xcp->priv->async_common = xcp; - cv_init(&xcp->priv->async_flags_cv, NULL, CV_DRIVER, NULL); - - /* Initialize mutexes before accessing the interface. */ - mutex_init(&xcp->excl, NULL, MUTEX_DRIVER, NULL); - cv_init(&xcp->excl_cv, NULL, CV_DEFAULT, NULL); - - /* create minor device node for this device */ - ret = ddi_create_minor_node(devi, "xencons", S_IFCHR, instance, - DDI_NT_SERIAL, 0); - if (ret != DDI_SUCCESS) { - ddi_remove_minor_node(devi, NULL); - xencons_soft_state_free(xcp); - return (DDI_FAILURE); - } - - ddi_report_dev(devi); - xencons_console = xcp; - xenconssetup(xcp); - DEBUGCONT1(XENCONS_DEBUG_INIT, "xencons%dattach: done\n", instance); - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static int -xenconsinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, - void **result) -{ - dev_t dev = (dev_t)arg; - int instance, error; - struct xencons *xcp; - - instance = getminor(dev); - xcp = ddi_get_soft_state(xencons_soft_state, instance); - if (xcp == NULL) - return (DDI_FAILURE); - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (xcp->dip == NULL) - error = DDI_FAILURE; - else { - *result = (void *) xcp->dip; - error = DDI_SUCCESS; - } - break; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)(intptr_t)instance; - error = DDI_SUCCESS; - break; - default: - error = DDI_FAILURE; - } - return (error); -} - -/* xencons_soft_state_free - local wrapper for ddi_soft_state_free(9F) */ - -static void -xencons_soft_state_free(struct xencons *xcp) -{ - mutex_destroy(&xcp->excl); - cv_destroy(&xcp->excl_cv); - kmem_free(xcp->priv, sizeof (struct asyncline)); - ddi_soft_state_free(xencons_soft_state, xcp->unit); -} - -/*ARGSUSED*/ -static int -xenconsopen(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr) -{ - struct xencons *xcp; - struct asyncline *async; - int unit; - - unit = getminor(*dev); - DEBUGCONT1(XENCONS_DEBUG_CLOSE, "xencons%dopen\n", unit); - xcp = ddi_get_soft_state(xencons_soft_state, unit); - if (xcp == NULL) - return (ENXIO); /* unit not configured */ - async = xcp->priv; - mutex_enter(&xcp->excl); - -again: - - if ((async->async_flags & ASYNC_ISOPEN) == 0) { - async->async_ttycommon.t_iflag = 0; - async->async_ttycommon.t_iocpending = NULL; - async->async_ttycommon.t_size.ws_row = 0; - async->async_ttycommon.t_size.ws_col = 0; - async->async_ttycommon.t_size.ws_xpixel = 0; - async->async_ttycommon.t_size.ws_ypixel = 0; - async->async_dev = *dev; - async->async_wbufcid = 0; - - async->async_startc = CSTART; - async->async_stopc = CSTOP; - } else if ((async->async_ttycommon.t_flags & TS_XCLUDE) && - secpolicy_excl_open(cr) != 0) { - mutex_exit(&xcp->excl); - return (EBUSY); - } - - async->async_ttycommon.t_flags |= TS_SOFTCAR; - - async->async_ttycommon.t_readq = rq; - async->async_ttycommon.t_writeq = WR(rq); - rq->q_ptr = WR(rq)->q_ptr = (caddr_t)async; - mutex_exit(&xcp->excl); - /* - * Caution here -- qprocson sets the pointers that are used by canput - * called by xencons_rxint. ASYNC_ISOPEN must *not* be set until those - * pointers are valid. - */ - qprocson(rq); - async->async_flags |= ASYNC_ISOPEN; - DEBUGCONT1(XENCONS_DEBUG_INIT, "asy%dopen: done\n", unit); - return (0); -} - - -/* - * Close routine. - */ -/*ARGSUSED*/ -static int -xenconsclose(queue_t *q, int flag, cred_t *credp) -{ - struct asyncline *async; - struct xencons *xcp; -#ifdef DEBUG - int instance; -#endif - - async = (struct asyncline *)q->q_ptr; - ASSERT(async != NULL); - xcp = async->async_common; -#ifdef DEBUG - instance = xcp->unit; - DEBUGCONT1(XENCONS_DEBUG_CLOSE, "xencons%dclose\n", instance); -#endif - - mutex_enter(&xcp->excl); - async->async_flags |= ASYNC_CLOSING; - - async->async_ocnt = 0; - if (async->async_xmitblk != NULL) - freeb(async->async_xmitblk); - async->async_xmitblk = NULL; - -out: - ttycommon_close(&async->async_ttycommon); - - /* - * Cancel outstanding "bufcall" request. - */ - if (async->async_wbufcid != 0) { - unbufcall(async->async_wbufcid); - async->async_wbufcid = 0; - } - - /* Note that qprocsoff can't be done until after interrupts are off */ - qprocsoff(q); - q->q_ptr = WR(q)->q_ptr = NULL; - async->async_ttycommon.t_readq = NULL; - async->async_ttycommon.t_writeq = NULL; - - /* - * Clear out device state, except persistant device property flags. - */ - async->async_flags = 0; - cv_broadcast(&async->async_flags_cv); - mutex_exit(&xcp->excl); - - DEBUGCONT1(XENCONS_DEBUG_CLOSE, "xencons%dclose: done\n", instance); - return (0); -} - -#define INBUF_IX(ix, ifp) (DOMAIN_IS_INITDOMAIN(xen_info) ? \ - (ix) : MASK_XENCONS_IDX((ix), (ifp)->in)) - -/* - * Handle a xen console rx interrupt. - */ -/*ARGSUSED*/ -static void -xencons_rxint(struct xencons *xcp) -{ - struct asyncline *async; - short cc; - mblk_t *bp; - queue_t *q; - uchar_t c, buf[16]; - uchar_t *cp; - tty_common_t *tp; - int instance; - volatile struct xencons_interface *ifp; - XENCONS_RING_IDX cons, prod; - - DEBUGCONT0(XENCONS_DEBUG_PROCS, "xencons_rxint\n"); - -loop: - mutex_enter(&xcp->excl); - - /* sanity check if we should bail */ - if (xencons_console == NULL) { - mutex_exit(&xcp->excl); - goto out; - } - - async = xcp->priv; - instance = xcp->unit; - ifp = xcp->ifp; - tp = &async->async_ttycommon; - q = tp->t_readq; - - if (async->async_flags & ASYNC_OUT_FLW_RESUME) { - xcasync_start(async); - async->async_flags &= ~ASYNC_OUT_FLW_RESUME; - } - - /* - * If data is available, send it up the stream if there's - * somebody listening. - */ - if (!(async->async_flags & ASYNC_ISOPEN)) { - mutex_exit(&xcp->excl); - goto out; - } - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - cc = HYPERVISOR_console_io(CONSOLEIO_read, 16, (char *)buf); - cp = buf; - cons = 0; - } else { - cons = ifp->in_cons; - prod = ifp->in_prod; - - cc = prod - cons; - cp = (uchar_t *)ifp->in; - } - if (cc <= 0) { - mutex_exit(&xcp->excl); - goto out; - } - - /* - * Check for character break sequence. - * - * Note that normally asy drivers only check for a character sequence - * if abort_enable == KIOCABORTALTERNATE and otherwise use a break - * sensed on the line to do an abort_sequence_enter. Since the - * hypervisor does not use a real chip for the console we default to - * using the alternate sequence. - */ - if ((abort_enable == KIOCABORTENABLE) && (xcp->flags & ASY_CONSOLE)) { - XENCONS_RING_IDX i; - - for (i = 0; i < cc; i++) { - c = cp[INBUF_IX(cons + i, ifp)]; - if (abort_charseq_recognize(c)) { - /* - * Eat abort seg, it's not a valid debugger - * command. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - membar_producer(); - ifp->in_cons = cons + i; - } else { - cons += i; - } - abort_sequence_enter(NULL); - /* - * Back from debugger, resume normal processing - */ - mutex_exit(&xcp->excl); - goto loop; - } - } - } - - if (!canput(q)) { - if (!(async->async_inflow_source & IN_FLOW_STREAMS)) { - (void) xcasync_flowcontrol_sw_input(xcp, FLOW_STOP, - IN_FLOW_STREAMS); - } - mutex_exit(&xcp->excl); - goto out; - } - if (async->async_inflow_source & IN_FLOW_STREAMS) { - (void) xcasync_flowcontrol_sw_input(xcp, FLOW_START, - IN_FLOW_STREAMS); - } - DEBUGCONT2(XENCONS_DEBUG_INPUT, - "xencons%d_rxint: %d char(s) in queue.\n", instance, cc); - if (!(bp = allocb(cc, BPRI_MED))) { - mutex_exit(&xcp->excl); - ttycommon_qfull(&async->async_ttycommon, q); - goto out; - } - do { - c = cp[INBUF_IX(cons++, ifp)]; - /* - * We handle XON/XOFF char if IXON is set, - * but if received char is _POSIX_VDISABLE, - * we left it to the up level module. - */ - if (tp->t_iflag & IXON) { - if ((c == async->async_stopc) && - (c != _POSIX_VDISABLE)) { - xcasync_flowcontrol_sw_output(xcp, FLOW_STOP); - continue; - } else if ((c == async->async_startc) && - (c != _POSIX_VDISABLE)) { - xcasync_flowcontrol_sw_output(xcp, FLOW_START); - continue; - } - if ((tp->t_iflag & IXANY) && - (async->async_flags & ASYNC_SW_OUT_FLW)) { - xcasync_flowcontrol_sw_output(xcp, FLOW_START); - } - } - *bp->b_wptr++ = c; - } while (--cc); - membar_producer(); - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - ifp->in_cons = cons; - mutex_exit(&xcp->excl); - if (bp->b_wptr > bp->b_rptr) { - if (!canput(q)) { - xenconserror(CE_NOTE, "xencons%d: local queue full", - instance); - freemsg(bp); - } else - (void) putq(q, bp); - } else - freemsg(bp); - if (DOMAIN_IS_INITDOMAIN(xen_info)) - goto loop; -out: - DEBUGCONT1(XENCONS_DEBUG_PROCS, "xencons%d_rxint: done\n", instance); - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - ec_notify_via_evtchn(xcp->evtchn); -} - - -/* - * Handle a xen console tx interrupt. - */ -/*ARGSUSED*/ -static void -xencons_txint(struct xencons *xcp) -{ - struct asyncline *async; - - DEBUGCONT0(XENCONS_DEBUG_PROCS, "xencons_txint\n"); - - /* - * prevent recursive entry - */ - if (mutex_owner(&xcp->excl) == curthread) { - goto out; - } - - mutex_enter(&xcp->excl); - if (xencons_console == NULL) { - mutex_exit(&xcp->excl); - goto out; - } - - /* make sure the device is open */ - async = xcp->priv; - if ((async->async_flags & ASYNC_ISOPEN) != 0) - xcasync_start(async); - - mutex_exit(&xcp->excl); -out: - DEBUGCONT0(XENCONS_DEBUG_PROCS, "xencons_txint: done\n"); -} - - -/* - * Get an event when input ring becomes not empty or output ring becomes not - * full. - */ -static uint_t -xenconsintr(caddr_t arg) -{ - struct xencons *xcp = (struct xencons *)arg; - volatile struct xencons_interface *ifp = xcp->ifp; - - if (ifp->in_prod != ifp->in_cons) - xencons_rxint(xcp); - if (ifp->out_prod - ifp->out_cons < sizeof (ifp->out)) - xencons_txint(xcp); - return (DDI_INTR_CLAIMED); -} - -/* - * Console interrupt routine for priviliged domains - */ -static uint_t -xenconsintr_priv(caddr_t arg) -{ - struct xencons *xcp = (struct xencons *)arg; - - xencons_rxint(xcp); - xencons_txint(xcp); - return (DDI_INTR_CLAIMED); -} - -/* - * Start output on a line, unless it's busy, frozen, or otherwise. - */ -/*ARGSUSED*/ -static void -xcasync_start(struct asyncline *async) -{ - struct xencons *xcp = async->async_common; - int cc; - queue_t *q; - mblk_t *bp; - int len, space, blen; - mblk_t *nbp; - -#ifdef DEBUG - int instance = xcp->unit; - - DEBUGCONT1(XENCONS_DEBUG_PROCS, "async%d_nstart\n", instance); -#endif - ASSERT(mutex_owned(&xcp->excl)); - - /* - * Check only pended sw input flow control. - */ -domore: - (void) xcasync_flowcontrol_sw_input(xcp, FLOW_CHECK, IN_FLOW_NULL); - - if ((q = async->async_ttycommon.t_writeq) == NULL) { - return; /* not attached to a stream */ - } - - for (;;) { - if ((bp = getq(q)) == NULL) - return; /* no data to transmit */ - - /* - * We have a message block to work on. - * Check whether it's a break, a delay, or an ioctl (the latter - * occurs if the ioctl in question was waiting for the output - * to drain). If it's one of those, process it immediately. - */ - switch (bp->b_datap->db_type) { - - case M_IOCTL: - /* - * This ioctl was waiting for the output ahead of - * it to drain; obviously, it has. Do it, and - * then grab the next message after it. - */ - mutex_exit(&xcp->excl); - xcasync_ioctl(async, q, bp); - mutex_enter(&xcp->excl); - continue; - } - - while (bp != NULL && (cc = bp->b_wptr - bp->b_rptr) == 0) { - nbp = bp->b_cont; - freeb(bp); - bp = nbp; - } - if (bp != NULL) - break; - } - - /* - * We have data to transmit. If output is stopped, put - * it back and try again later. - */ - if (async->async_flags & (ASYNC_SW_OUT_FLW | ASYNC_STOPPED)) { - (void) putbq(q, bp); - return; - } - - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - len = 0; - space = XENCONS_WBUFSIZE; - while (bp != NULL && space) { - blen = bp->b_wptr - bp->b_rptr; - cc = min(blen, space); - bcopy(bp->b_rptr, &xencons_wbuf[len], cc); - bp->b_rptr += cc; - if (cc == blen) { - nbp = bp->b_cont; - freeb(bp); - bp = nbp; - } - space -= cc; - len += cc; - } - mutex_exit(&xcp->excl); - (void) HYPERVISOR_console_io(CONSOLEIO_write, len, - xencons_wbuf); - mutex_enter(&xcp->excl); - if (bp != NULL) - (void) putbq(q, bp); /* not done with this msg yet */ - /* - * There are no completion interrupts when using the - * HYPERVISOR_console_io call to write console data - * so we loop here till we have sent all the data to the - * hypervisor. - */ - goto domore; - } else { - volatile struct xencons_interface *ifp = xcp->ifp; - XENCONS_RING_IDX cons, prod; - - cons = ifp->out_cons; - prod = ifp->out_prod; - membar_enter(); - while (bp != NULL && ((prod - cons) < sizeof (ifp->out))) { - ifp->out[MASK_XENCONS_IDX(prod++, ifp->out)] = - *bp->b_rptr++; - if (bp->b_rptr == bp->b_wptr) { - nbp = bp->b_cont; - freeb(bp); - bp = nbp; - } - } - membar_producer(); - ifp->out_prod = prod; - ec_notify_via_evtchn(xcp->evtchn); - if (bp != NULL) - (void) putbq(q, bp); /* not done with this msg yet */ - } -} - - -/* - * Process an "ioctl" message sent down to us. - * Note that we don't need to get any locks until we are ready to access - * the hardware. Nothing we access until then is going to be altered - * outside of the STREAMS framework, so we should be safe. - */ -static void -xcasync_ioctl(struct asyncline *async, queue_t *wq, mblk_t *mp) -{ - struct xencons *xcp = async->async_common; - tty_common_t *tp = &async->async_ttycommon; - struct iocblk *iocp; - unsigned datasize; - int error = 0; - -#ifdef DEBUG - int instance = xcp->unit; - - DEBUGCONT1(XENCONS_DEBUG_PROCS, "async%d_ioctl\n", instance); -#endif - - if (tp->t_iocpending != NULL) { - /* - * We were holding an "ioctl" response pending the - * availability of an "mblk" to hold data to be passed up; - * another "ioctl" came through, which means that "ioctl" - * must have timed out or been aborted. - */ - freemsg(async->async_ttycommon.t_iocpending); - async->async_ttycommon.t_iocpending = NULL; - } - - iocp = (struct iocblk *)mp->b_rptr; - - /* - * For TIOCMGET and the PPS ioctls, do NOT call ttycommon_ioctl() - * because this function frees up the message block (mp->b_cont) that - * contains the user location where we pass back the results. - * - * Similarly, CONSOPENPOLLEDIO needs ioc_count, which ttycommon_ioctl - * zaps. We know that ttycommon_ioctl doesn't know any CONS* - * ioctls, so keep the others safe too. - */ - DEBUGCONT2(XENCONS_DEBUG_IOCTL, "async%d_ioctl: %s\n", - instance, - iocp->ioc_cmd == TIOCMGET ? "TIOCMGET" : - iocp->ioc_cmd == TIOCMSET ? "TIOCMSET" : - iocp->ioc_cmd == TIOCMBIS ? "TIOCMBIS" : - iocp->ioc_cmd == TIOCMBIC ? "TIOCMBIC" : "other"); - - switch (iocp->ioc_cmd) { - case TIOCMGET: - case TIOCGPPS: - case TIOCSPPS: - case TIOCGPPSEV: - case CONSOPENPOLLEDIO: - case CONSCLOSEPOLLEDIO: - case CONSSETABORTENABLE: - case CONSGETABORTENABLE: - error = -1; /* Do Nothing */ - break; - default: - - /* - * The only way in which "ttycommon_ioctl" can fail is if the - * "ioctl" requires a response containing data to be returned - * to the user, and no mblk could be allocated for the data. - * No such "ioctl" alters our state. Thus, we always go ahead - * and do any state-changes the "ioctl" calls for. If we - * couldn't allocate the data, "ttycommon_ioctl" has stashed - * the "ioctl" away safely, so we just call "bufcall" to - * request that we be called back when we stand a better - * chance of allocating the data. - */ - if ((datasize = ttycommon_ioctl(tp, wq, mp, &error)) != 0) { - if (async->async_wbufcid) - unbufcall(async->async_wbufcid); - async->async_wbufcid = bufcall(datasize, BPRI_HI, - (void (*)(void *)) xcasync_reioctl, - (void *)(intptr_t)async->async_common->unit); - return; - } - } - - mutex_enter(&xcp->excl); - - if (error == 0) { - /* - * "ttycommon_ioctl" did most of the work; we just use the - * data it set up. - */ - switch (iocp->ioc_cmd) { - - case TCSETS: - case TCSETSF: - case TCSETSW: - case TCSETA: - case TCSETAW: - case TCSETAF: - break; - } - } else if (error < 0) { - /* - * "ttycommon_ioctl" didn't do anything; we process it here. - */ - error = 0; - switch (iocp->ioc_cmd) { - - case TCSBRK: - error = miocpullup(mp, sizeof (int)); - break; - - case TIOCSBRK: - mioc2ack(mp, NULL, 0, 0); - break; - - case TIOCCBRK: - mioc2ack(mp, NULL, 0, 0); - break; - - case CONSOPENPOLLEDIO: - error = miocpullup(mp, sizeof (cons_polledio_arg_t)); - if (error != 0) - break; - - *(cons_polledio_arg_t *)mp->b_cont->b_rptr = - (cons_polledio_arg_t)&xcp->polledio; - - mp->b_datap->db_type = M_IOCACK; - break; - - case CONSCLOSEPOLLEDIO: - mp->b_datap->db_type = M_IOCACK; - iocp->ioc_error = 0; - iocp->ioc_rval = 0; - break; - - case CONSSETABORTENABLE: - error = secpolicy_console(iocp->ioc_cr); - if (error != 0) - break; - - if (iocp->ioc_count != TRANSPARENT) { - error = EINVAL; - break; - } - - if (*(intptr_t *)mp->b_cont->b_rptr) - xcp->flags |= ASY_CONSOLE; - else - xcp->flags &= ~ASY_CONSOLE; - - mp->b_datap->db_type = M_IOCACK; - iocp->ioc_error = 0; - iocp->ioc_rval = 0; - break; - - case CONSGETABORTENABLE: - /*CONSTANTCONDITION*/ - ASSERT(sizeof (boolean_t) <= sizeof (boolean_t *)); - /* - * Store the return value right in the payload - * we were passed. Crude. - */ - mcopyout(mp, NULL, sizeof (boolean_t), NULL, NULL); - *(boolean_t *)mp->b_cont->b_rptr = - (xcp->flags & ASY_CONSOLE) != 0; - break; - - default: - /* - * If we don't understand it, it's an error. NAK it. - */ - error = EINVAL; - break; - } - } - if (error != 0) { - iocp->ioc_error = error; - mp->b_datap->db_type = M_IOCNAK; - } - mutex_exit(&xcp->excl); - qreply(wq, mp); - DEBUGCONT1(XENCONS_DEBUG_PROCS, "async%d_ioctl: done\n", instance); -} - -static int -xenconsrsrv(queue_t *q) -{ - mblk_t *bp; - - while (canputnext(q) && (bp = getq(q))) - putnext(q, bp); - return (0); -} - -/* - * Put procedure for write queue. - * Respond to M_STOP, M_START, M_IOCTL, and M_FLUSH messages here; - * set the flow control character for M_STOPI and M_STARTI messages; - * queue up M_BREAK, M_DELAY, and M_DATA messages for processing - * by the start routine, and then call the start routine; discard - * everything else. Note that this driver does not incorporate any - * mechanism to negotiate to handle the canonicalization process. - * It expects that these functions are handled in upper module(s), - * as we do in ldterm. - */ -static int -xenconswput(queue_t *q, mblk_t *mp) -{ - struct asyncline *async; - struct xencons *xcp; - - async = (struct asyncline *)q->q_ptr; - xcp = async->async_common; - - switch (mp->b_datap->db_type) { - - case M_STOP: - mutex_enter(&xcp->excl); - async->async_flags |= ASYNC_STOPPED; - mutex_exit(&xcp->excl); - freemsg(mp); - break; - - case M_START: - mutex_enter(&xcp->excl); - if (async->async_flags & ASYNC_STOPPED) { - async->async_flags &= ~ASYNC_STOPPED; - xcasync_start(async); - } - mutex_exit(&xcp->excl); - freemsg(mp); - break; - - case M_IOCTL: - switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) { - - case TCSETSW: - case TCSETSF: - case TCSETAW: - case TCSETAF: - /* - * The changes do not take effect until all - * output queued before them is drained. - * Put this message on the queue, so that - * "xcasync_start" will see it when it's done - * with the output before it. Poke the - * start routine, just in case. - */ - (void) putq(q, mp); - mutex_enter(&xcp->excl); - xcasync_start(async); - mutex_exit(&xcp->excl); - break; - - default: - /* - * Do it now. - */ - xcasync_ioctl(async, q, mp); - break; - } - break; - - case M_FLUSH: - if (*mp->b_rptr & FLUSHW) { - mutex_enter(&xcp->excl); - /* - * Flush our write queue. - */ - flushq(q, FLUSHDATA); /* XXX doesn't flush M_DELAY */ - if (async->async_xmitblk != NULL) { - freeb(async->async_xmitblk); - async->async_xmitblk = NULL; - } - mutex_exit(&xcp->excl); - *mp->b_rptr &= ~FLUSHW; /* it has been flushed */ - } - if (*mp->b_rptr & FLUSHR) { - flushq(RD(q), FLUSHDATA); - qreply(q, mp); /* give the read queues a crack at it */ - } else { - freemsg(mp); - } - - /* - * We must make sure we process messages that survive the - * write-side flush. - */ - mutex_enter(&xcp->excl); - xcasync_start(async); - mutex_exit(&xcp->excl); - break; - - case M_BREAK: - case M_DELAY: - case M_DATA: - /* - * Queue the message up to be transmitted, - * and poke the start routine. - */ - (void) putq(q, mp); - mutex_enter(&xcp->excl); - xcasync_start(async); - mutex_exit(&xcp->excl); - break; - - case M_STOPI: - mutex_enter(&xcp->excl); - mutex_enter(&xcp->excl); - if (!(async->async_inflow_source & IN_FLOW_USER)) { - (void) xcasync_flowcontrol_sw_input(xcp, FLOW_STOP, - IN_FLOW_USER); - } - mutex_exit(&xcp->excl); - mutex_exit(&xcp->excl); - freemsg(mp); - break; - - case M_STARTI: - mutex_enter(&xcp->excl); - mutex_enter(&xcp->excl); - if (async->async_inflow_source & IN_FLOW_USER) { - (void) xcasync_flowcontrol_sw_input(xcp, FLOW_START, - IN_FLOW_USER); - } - mutex_exit(&xcp->excl); - mutex_exit(&xcp->excl); - freemsg(mp); - break; - - case M_CTL: - if (MBLKL(mp) >= sizeof (struct iocblk) && - ((struct iocblk *)mp->b_rptr)->ioc_cmd == MC_POSIXQUERY) { - ((struct iocblk *)mp->b_rptr)->ioc_cmd = MC_HAS_POSIX; - qreply(q, mp); - } else { - freemsg(mp); - } - break; - - default: - freemsg(mp); - break; - } - return (0); -} - -/* - * Retry an "ioctl", now that "bufcall" claims we may be able to allocate - * the buffer we need. - */ -static void -xcasync_reioctl(void *unit) -{ - int instance = (uintptr_t)unit; - struct asyncline *async; - struct xencons *xcp; - queue_t *q; - mblk_t *mp; - - xcp = ddi_get_soft_state(xencons_soft_state, instance); - ASSERT(xcp != NULL); - async = xcp->priv; - - /* - * The bufcall is no longer pending. - */ - mutex_enter(&xcp->excl); - async->async_wbufcid = 0; - if ((q = async->async_ttycommon.t_writeq) == NULL) { - mutex_exit(&xcp->excl); - return; - } - if ((mp = async->async_ttycommon.t_iocpending) != NULL) { - /* not pending any more */ - async->async_ttycommon.t_iocpending = NULL; - mutex_exit(&xcp->excl); - xcasync_ioctl(async, q, mp); - } else - mutex_exit(&xcp->excl); -} - - -/* - * debugger/console support routines. - */ - -/* - * put a character out - * Do not use interrupts. If char is LF, put out CR, LF. - */ -/*ARGSUSED*/ -static void -xenconsputchar(cons_polledio_arg_t arg, uchar_t c) -{ - struct xencons *xcp = xencons_console; - volatile struct xencons_interface *ifp = xcp->ifp; - XENCONS_RING_IDX prod; - - if (c == '\n') - xenconsputchar(arg, '\r'); - - /* - * domain 0 can use the console I/O... - */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - char buffer[1]; - - buffer[0] = c; - (void) HYPERVISOR_console_io(CONSOLEIO_write, 1, buffer); - return; - } - - /* - * domU has to go through dom0 virtual console. - */ - while (ifp->out_prod - ifp->out_cons == sizeof (ifp->out)) - (void) HYPERVISOR_yield(); - - prod = ifp->out_prod; - ifp->out[MASK_XENCONS_IDX(prod++, ifp->out)] = c; - membar_producer(); - ifp->out_prod = prod; - ec_notify_via_evtchn(xcp->evtchn); -} - -/* - * See if there's a character available. If no character is - * available, return 0. Run in polled mode, no interrupts. - */ -static boolean_t -xenconsischar(cons_polledio_arg_t arg) -{ - struct xencons *xcp = (struct xencons *)arg; - volatile struct xencons_interface *ifp = xcp->ifp; - - if (xcp->polldix < xcp->polllen) - return (B_TRUE); - /* - * domain 0 can use the console I/O... - */ - xcp->polldix = 0; - xcp->polllen = 0; - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - xcp->polllen = HYPERVISOR_console_io(CONSOLEIO_read, 1, - (char *)xcp->pollbuf); - return (xcp->polllen != 0); - } - - /* - * domU has to go through virtual console device. - */ - if (ifp->in_prod != ifp->in_cons) { - XENCONS_RING_IDX cons; - - cons = ifp->in_cons; - membar_enter(); - xcp->pollbuf[0] = ifp->in[MASK_XENCONS_IDX(cons++, ifp->in)]; - membar_producer(); - ifp->in_cons = cons; - xcp->polllen = 1; - } - return (xcp->polllen != 0); -} - -/* - * Get a character. Run in polled mode, no interrupts. - */ -static int -xenconsgetchar(cons_polledio_arg_t arg) -{ - struct xencons *xcp = (struct xencons *)arg; - - ec_wait_on_evtchn(xcp->evtchn, (int (*)(void *))xenconsischar, arg); - - return (xcp->pollbuf[xcp->polldix++]); -} - -static void -xenconserror(int level, const char *fmt, ...) -{ - va_list adx; - static time_t last; - static const char *lastfmt; - time_t now; - - /* - * Don't print the same error message too often. - * Print the message only if we have not printed the - * message within the last second. - * Note: that fmt cannot be a pointer to a string - * stored on the stack. The fmt pointer - * must be in the data segment otherwise lastfmt would point - * to non-sense. - */ - now = gethrestime_sec(); - if (last == now && lastfmt == fmt) - return; - - last = now; - lastfmt = fmt; - - va_start(adx, fmt); - vcmn_err(level, fmt, adx); - va_end(adx); -} - - -/* - * Check for abort character sequence - */ -static boolean_t -abort_charseq_recognize(uchar_t ch) -{ - static int state = 0; -#define CNTRL(c) ((c)&037) - static char sequence[] = { '\r', '~', CNTRL('b') }; - - if (ch == sequence[state]) { - if (++state >= sizeof (sequence)) { - state = 0; - return (B_TRUE); - } - } else { - state = (ch == sequence[0]) ? 1 : 0; - } - return (B_FALSE); -} - -/* - * Flow control functions - */ - -/* - * Software output flow control - * This function can be executed sucessfully at any situation. - * It does not handle HW, and just change the SW output flow control flag. - * INPUT VALUE of onoff: - * FLOW_START means to clear SW output flow control flag, - * also set ASYNC_OUT_FLW_RESUME. - * FLOW_STOP means to set SW output flow control flag, - * also clear ASYNC_OUT_FLW_RESUME. - */ -static void -xcasync_flowcontrol_sw_output(struct xencons *xcp, async_flowc_action onoff) -{ - struct asyncline *async = xcp->priv; - int instance = xcp->unit; - - ASSERT(mutex_owned(&xcp->excl)); - - if (!(async->async_ttycommon.t_iflag & IXON)) - return; - - switch (onoff) { - case FLOW_STOP: - async->async_flags |= ASYNC_SW_OUT_FLW; - async->async_flags &= ~ASYNC_OUT_FLW_RESUME; - DEBUGCONT1(XENCONS_DEBUG_SFLOW, - "xencons%d: output sflow stop\n", instance); - break; - case FLOW_START: - async->async_flags &= ~ASYNC_SW_OUT_FLW; - async->async_flags |= ASYNC_OUT_FLW_RESUME; - DEBUGCONT1(XENCONS_DEBUG_SFLOW, - "xencons%d: output sflow start\n", instance); - break; - default: - break; - } -} - -/* - * Software input flow control - * This function can execute software input flow control - * INPUT VALUE of onoff: - * FLOW_START means to send out a XON char - * and clear SW input flow control flag. - * FLOW_STOP means to send out a XOFF char - * and set SW input flow control flag. - * FLOW_CHECK means to check whether there is pending XON/XOFF - * if it is true, send it out. - * INPUT VALUE of type: - * IN_FLOW_STREAMS means flow control is due to STREAMS - * IN_FLOW_USER means flow control is due to user's commands - * RETURN VALUE: B_FALSE means no flow control char is sent - * B_TRUE means one flow control char is sent - */ -static boolean_t -xcasync_flowcontrol_sw_input(struct xencons *xcp, async_flowc_action onoff, - int type) -{ - struct asyncline *async = xcp->priv; - int instance = xcp->unit; - int rval = B_FALSE; - - ASSERT(mutex_owned(&xcp->excl)); - - if (!(async->async_ttycommon.t_iflag & IXOFF)) - return (rval); - - /* - * If we get this far, then we know IXOFF is set. - */ - switch (onoff) { - case FLOW_STOP: - async->async_inflow_source |= type; - - /* - * We'll send an XOFF character for each of up to - * three different input flow control attempts to stop input. - * If we already send out one XOFF, but FLOW_STOP comes again, - * it seems that input flow control becomes more serious, - * then send XOFF again. - */ - if (async->async_inflow_source & (IN_FLOW_STREAMS | - IN_FLOW_USER)) - async->async_flags |= ASYNC_SW_IN_FLOW | - ASYNC_SW_IN_NEEDED; - DEBUGCONT2(XENCONS_DEBUG_SFLOW, "xencons%d: input sflow stop, " - "type = %x\n", instance, async->async_inflow_source); - break; - case FLOW_START: - async->async_inflow_source &= ~type; - if (async->async_inflow_source == 0) { - async->async_flags = (async->async_flags & - ~ASYNC_SW_IN_FLOW) | ASYNC_SW_IN_NEEDED; - DEBUGCONT1(XENCONS_DEBUG_SFLOW, "xencons%d: " - "input sflow start\n", instance); - } - break; - default: - break; - } - - if (async->async_flags & ASYNC_SW_IN_NEEDED) { - /* - * If we get this far, then we know we need to send out - * XON or XOFF char. - */ - char c; - - rval = B_TRUE; - c = (async->async_flags & ASYNC_SW_IN_FLOW) ? - async->async_stopc : async->async_startc; - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - (void) HYPERVISOR_console_io(CONSOLEIO_write, 1, &c); - async->async_flags &= ~ASYNC_SW_IN_NEEDED; - return (rval); - } else { - xenconsputchar(NULL, c); - } - } - return (rval); -} - -struct module_info xencons_info = { - 0, - "xencons", - 0, - INFPSZ, - 4096, - 128 -}; - -static struct qinit xencons_rint = { - putq, - xenconsrsrv, - xenconsopen, - xenconsclose, - NULL, - &xencons_info, - NULL -}; - -static struct qinit xencons_wint = { - xenconswput, - NULL, - NULL, - NULL, - NULL, - &xencons_info, - NULL -}; - -struct streamtab xencons_str_info = { - &xencons_rint, - &xencons_wint, - NULL, - NULL -}; - -static struct cb_ops cb_xencons_ops = { - nodev, /* cb_open */ - nodev, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - nodev, /* cb_read */ - nodev, /* cb_write */ - nodev, /* cb_ioctl */ - nodev, /* cb_devmap */ - nodev, /* cb_mmap */ - nodev, /* cb_segmap */ - nochpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - &xencons_str_info, /* cb_stream */ - D_MP /* cb_flag */ -}; - -struct dev_ops xencons_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - xenconsinfo, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xenconsattach, /* devo_attach */ - xenconsdetach, /* devo_detach */ - nodev, /* devo_reset */ - &cb_xencons_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "virtual console driver", - &xencons_ops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&modldrv, - NULL -}; - -int -_init(void) -{ - int rv; - - if ((rv = ddi_soft_state_init(&xencons_soft_state, - sizeof (struct xencons), 1)) != 0) - return (rv); - if ((rv = mod_install(&modlinkage)) != 0) { - ddi_soft_state_fini(&xencons_soft_state); - return (rv); - } - DEBUGCONT2(XENCONS_DEBUG_INIT, "%s, debug = %x\n", - modldrv.drv_linkinfo, debug); - return (0); -} - -int -_fini(void) -{ - int rv; - - if ((rv = mod_remove(&modlinkage)) != 0) - return (rv); - - ddi_soft_state_fini(&xencons_soft_state); - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/xen/io/xencons.conf b/usr/src/uts/common/xen/io/xencons.conf deleted file mode 100644 index 6e2eb55376..0000000000 --- a/usr/src/uts/common/xen/io/xencons.conf +++ /dev/null @@ -1,27 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -#pragma ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/uts/common/xen/io/xencons.h b/usr/src/uts/common/xen/io/xencons.h deleted file mode 100644 index 356931d9a8..0000000000 --- a/usr/src/uts/common/xen/io/xencons.h +++ /dev/null @@ -1,208 +0,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 (c) 1990, 1991 UNIX System Laboratories, Inc. */ -/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ -/* All Rights Reserved */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_XENCONS_H -#define _SYS_XENCONS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - - -/* - * Xencons tracing macros. These are a similar to some macros in sys/vtrace.h. - * - * XXX - Needs review: would it be better to use the macros in sys/vtrace.h ? - */ -#ifdef DEBUG -#define DEBUGWARN0(fac, format) \ - if (debug & (fac)) \ - cmn_err(CE_WARN, format) -#define DEBUGNOTE0(fac, format) \ - if (debug & (fac)) \ - cmn_err(CE_NOTE, format) -#define DEBUGNOTE1(fac, format, arg1) \ - if (debug & (fac)) \ - cmn_err(CE_NOTE, format, arg1) -#define DEBUGNOTE2(fac, format, arg1, arg2) \ - if (debug & (fac)) \ - cmn_err(CE_NOTE, format, arg1, arg2) -#define DEBUGNOTE3(fac, format, arg1, arg2, arg3) \ - if (debug & (fac)) \ - cmn_err(CE_NOTE, format, arg1, arg2, arg3) -#define DEBUGCONT0(fac, format) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format) -#define DEBUGCONT1(fac, format, arg1) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format, arg1) -#define DEBUGCONT2(fac, format, arg1, arg2) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format, arg1, arg2) -#define DEBUGCONT3(fac, format, arg1, arg2, arg3) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format, arg1, arg2, arg3) -#define DEBUGCONT4(fac, format, arg1, arg2, arg3, arg4) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format, arg1, arg2, arg3, arg4) -#define DEBUGCONT10(fac, format, \ - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) \ - if (debug & (fac)) \ - cmn_err(CE_CONT, format, \ - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) -#else -#define DEBUGWARN0(fac, format) -#define DEBUGNOTE0(fac, format) -#define DEBUGNOTE1(fac, format, arg1) -#define DEBUGNOTE2(fac, format, arg1, arg2) -#define DEBUGNOTE3(fac, format, arg1, arg2, arg3) -#define DEBUGCONT0(fac, format) -#define DEBUGCONT1(fac, format, arg1) -#define DEBUGCONT2(fac, format, arg1, arg2) -#define DEBUGCONT3(fac, format, arg1, arg2, arg3) -#define DEBUGCONT4(fac, format, arg1, arg2, arg3, arg4) -#define DEBUGCONT10(fac, format, \ - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) -#endif - -/* enum value for sw and hw flow control action */ -typedef enum { - FLOW_CHECK, - FLOW_STOP, - FLOW_START -} async_flowc_action; - -#define async_stopc async_ttycommon.t_stopc -#define async_startc async_ttycommon.t_startc - -/* - * Console instance data. - * Each of the fields in this structure is required to be protected by a - * mutex lock at the highest priority at which it can be altered. - */ - -struct xencons { - int flags; /* random flags */ - struct asyncline *priv; /* protocol private data -- asyncline */ - dev_info_t *dip; /* dev_info */ - int unit; /* which port */ - kmutex_t excl; /* adaptive mutex */ - kcondvar_t excl_cv; /* condition variable */ - struct cons_polledio polledio; /* polled I/O functions */ - unsigned char pollbuf[60]; /* polled I/O data */ - int polldix; /* polled data buffer index */ - int polllen; /* polled data buffer length */ - volatile struct xencons_interface *ifp; /* console ring buffers */ - int console_irq; /* dom0 console interrupt */ - int evtchn; /* console event channel */ -}; - -/* - * Asychronous protocol private data structure for ASY. - * Each of the fields in the structure is required to be protected by - * the lower priority lock except the fields that are set only at - * base level but cleared (with out lock) at interrupt level. - */ - -struct asyncline { - int async_flags; /* random flags */ - kcondvar_t async_flags_cv; /* condition variable for flags */ - dev_t async_dev; /* device major/minor numbers */ - mblk_t *async_xmitblk; /* transmit: active msg block */ - struct xencons *async_common; /* device common data */ - tty_common_t async_ttycommon; /* tty driver common data */ - bufcall_id_t async_wbufcid; /* id for pending write-side bufcall */ - timeout_id_t async_polltid; /* softint poll timeout id */ - timeout_id_t async_dtrtid; /* delaying DTR turn on */ - timeout_id_t async_utbrktid; /* hold minimum untimed break time id */ - - /* - * The following fields are protected by the excl_hi lock. - * Some, such as async_flowc, are set only at the base level and - * cleared (without the lock) only by the interrupt level. - */ - uchar_t *async_optr; /* output pointer */ - int async_ocnt; /* output count */ - ushort_t async_rput; /* producing pointer for input */ - ushort_t async_rget; /* consuming pointer for input */ - int async_inflow_source; /* input flow control type */ - - union { - struct { - uchar_t _hw; /* overrun (hw) */ - uchar_t _sw; /* overrun (sw) */ - } _a; - ushort_t uover_overrun; - } async_uover; -#define async_overrun async_uover._a.uover_overrun -#define async_hw_overrun async_uover._a._hw -#define async_sw_overrun async_uover._a._sw - short async_ext; /* modem status change count */ - short async_work; /* work to do flag */ -}; - -/* definitions for async_flags field */ -#define ASYNC_EXCL_OPEN 0x10000000 /* exclusive open */ -#define ASYNC_WOPEN 0x00000001 /* waiting for open to complete */ -#define ASYNC_ISOPEN 0x00000002 /* open is complete */ -#define ASYNC_STOPPED 0x00000010 /* output is stopped */ -#define ASYNC_PROGRESS 0x00001000 /* made progress on output effort */ -#define ASYNC_CLOSING 0x00002000 /* processing close on stream */ -#define ASYNC_SW_IN_FLOW 0x00020000 /* sw input flow control in effect */ -#define ASYNC_SW_OUT_FLW 0x00040000 /* sw output flow control in effect */ -#define ASYNC_SW_IN_NEEDED 0x00080000 /* sw input flow control char is */ - /* needed to be sent */ -#define ASYNC_OUT_FLW_RESUME 0x00100000 /* output need to be resumed */ - /* because of transition of flow */ - /* control from stop to start */ - - -/* definitions for asy_flags field */ -#define ASY_CONSOLE 0x00000080 - -/* definitions for async_inflow_source field in struct asyncline */ -#define IN_FLOW_NULL 0x00000000 -#define IN_FLOW_STREAMS 0x00000002 -#define IN_FLOW_USER 0x00000004 - -#define XENCONS_BURST 128 /* burst size for console writes */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XENCONS_H */ diff --git a/usr/src/uts/common/xen/io/xnb.c b/usr/src/uts/common/xen/io/xnb.c deleted file mode 100644 index 761597653b..0000000000 --- a/usr/src/uts/common/xen/io/xnb.c +++ /dev/null @@ -1,2075 +0,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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifdef DEBUG -#define XNB_DEBUG 1 -#endif /* DEBUG */ - -#include "xnb.h" - -#include -#include -#include -#include -#include -#include /* For mac_fix_cksum(). */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The terms "transmit" and "receive" are used in alignment with domU, - * which means that packets originating from the peer domU are "transmitted" - * to other parts of the system and packets are "received" from them. - */ - -/* - * Should we allow guests to manipulate multicast group membership? - */ -static boolean_t xnb_multicast_control = B_TRUE; - -static boolean_t xnb_connect_rings(dev_info_t *); -static void xnb_disconnect_rings(dev_info_t *); -static void xnb_oe_state_change(dev_info_t *, ddi_eventcookie_t, - void *, void *); -static void xnb_hp_state_change(dev_info_t *, ddi_eventcookie_t, - void *, void *); - -static int xnb_txbuf_constructor(void *, void *, int); -static void xnb_txbuf_destructor(void *, void *); -static void xnb_tx_notify_peer(xnb_t *, boolean_t); -static void xnb_tx_mark_complete(xnb_t *, RING_IDX, int16_t); - -mblk_t *xnb_to_peer(xnb_t *, mblk_t *); -mblk_t *xnb_copy_to_peer(xnb_t *, mblk_t *); - -static void setup_gop(xnb_t *, gnttab_copy_t *, uchar_t *, - size_t, size_t, size_t, grant_ref_t); -#pragma inline(setup_gop) -static boolean_t is_foreign(void *); -#pragma inline(is_foreign) - -#define INVALID_GRANT_HANDLE ((grant_handle_t)-1) -#define INVALID_GRANT_REF ((grant_ref_t)-1) - -static kmutex_t xnb_alloc_page_lock; - -/* - * On a 32 bit PAE system physical and machine addresses are larger - * than 32 bits. ddi_btop() on such systems take an unsigned long - * argument, and so addresses above 4G are truncated before ddi_btop() - * gets to see them. To avoid this, code the shift operation here. - */ -#define xnb_btop(addr) ((addr) >> PAGESHIFT) - -/* DMA attributes for transmit and receive data */ -static ddi_dma_attr_t buf_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 */ - 0xffffffffffffffffULL, /* maximum segment length */ - 1, /* maximum number of segments */ - 1, /* granularity */ - 0, /* flags (reserved) */ -}; - -/* DMA access attributes for data: NOT to be byte swapped. */ -static ddi_device_acc_attr_t data_accattr = { - DDI_DEVICE_ATTR_V0, - DDI_NEVERSWAP_ACC, - DDI_STRICTORDER_ACC -}; - -/* - * Statistics. - */ -static const char * const aux_statistics[] = { - "rx_cksum_deferred", - "tx_cksum_no_need", - "rx_rsp_notok", - "tx_notify_deferred", - "tx_notify_sent", - "rx_notify_deferred", - "rx_notify_sent", - "tx_too_early", - "rx_too_early", - "rx_allocb_failed", - "tx_allocb_failed", - "rx_foreign_page", - "mac_full", - "spurious_intr", - "allocation_success", - "allocation_failure", - "small_allocation_success", - "small_allocation_failure", - "other_allocation_failure", - "rx_pageboundary_crossed", - "rx_cpoparea_grown", - "csum_hardware", - "csum_software", - "tx_overflow_page", - "tx_unexpected_flags", -}; - -static int -xnb_ks_aux_update(kstat_t *ksp, int flag) -{ - xnb_t *xnbp; - kstat_named_t *knp; - - if (flag != KSTAT_READ) - return (EACCES); - - xnbp = ksp->ks_private; - knp = ksp->ks_data; - - /* - * Assignment order should match that of the names in - * aux_statistics. - */ - (knp++)->value.ui64 = xnbp->xnb_stat_rx_cksum_deferred; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_cksum_no_need; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_rsp_notok; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_notify_deferred; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_notify_sent; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_notify_deferred; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_notify_sent; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_too_early; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_too_early; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_allocb_failed; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_allocb_failed; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_foreign_page; - (knp++)->value.ui64 = xnbp->xnb_stat_mac_full; - (knp++)->value.ui64 = xnbp->xnb_stat_spurious_intr; - (knp++)->value.ui64 = xnbp->xnb_stat_allocation_success; - (knp++)->value.ui64 = xnbp->xnb_stat_allocation_failure; - (knp++)->value.ui64 = xnbp->xnb_stat_small_allocation_success; - (knp++)->value.ui64 = xnbp->xnb_stat_small_allocation_failure; - (knp++)->value.ui64 = xnbp->xnb_stat_other_allocation_failure; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_pagebndry_crossed; - (knp++)->value.ui64 = xnbp->xnb_stat_rx_cpoparea_grown; - (knp++)->value.ui64 = xnbp->xnb_stat_csum_hardware; - (knp++)->value.ui64 = xnbp->xnb_stat_csum_software; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_overflow_page; - (knp++)->value.ui64 = xnbp->xnb_stat_tx_unexpected_flags; - - return (0); -} - -static boolean_t -xnb_ks_init(xnb_t *xnbp) -{ - int nstat = sizeof (aux_statistics) / - sizeof (aux_statistics[0]); - const char * const *cp = aux_statistics; - kstat_named_t *knp; - - /* - * Create and initialise kstats. - */ - xnbp->xnb_kstat_aux = kstat_create(ddi_driver_name(xnbp->xnb_devinfo), - ddi_get_instance(xnbp->xnb_devinfo), "aux_statistics", "net", - KSTAT_TYPE_NAMED, nstat, 0); - if (xnbp->xnb_kstat_aux == NULL) - return (B_FALSE); - - xnbp->xnb_kstat_aux->ks_private = xnbp; - xnbp->xnb_kstat_aux->ks_update = xnb_ks_aux_update; - - knp = xnbp->xnb_kstat_aux->ks_data; - while (nstat > 0) { - kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); - - knp++; - cp++; - nstat--; - } - - kstat_install(xnbp->xnb_kstat_aux); - - return (B_TRUE); -} - -static void -xnb_ks_free(xnb_t *xnbp) -{ - kstat_delete(xnbp->xnb_kstat_aux); -} - -/* - * Calculate and insert the transport checksum for an arbitrary packet. - */ -static mblk_t * -xnb_software_csum(xnb_t *xnbp, mblk_t *mp) -{ - _NOTE(ARGUNUSED(xnbp)); - - /* - * XXPV dme: shouldn't rely on mac_fix_cksum(), not least - * because it doesn't cover all of the interesting cases :-( - */ - mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM); - - return (mac_fix_cksum(mp)); -} - -mblk_t * -xnb_process_cksum_flags(xnb_t *xnbp, mblk_t *mp, uint32_t capab) -{ - struct ether_header *ehp; - uint16_t sap; - uint32_t offset; - ipha_t *ipha; - - ASSERT(mp->b_next == NULL); - - /* - * Check that the packet is contained in a single mblk. In - * the "from peer" path this is true today, but may change - * when scatter gather support is added. In the "to peer" - * path we cannot be sure, but in most cases it will be true - * (in the xnbo case the packet has come from a MAC device - * which is unlikely to split packets). - */ - if (mp->b_cont != NULL) - goto software; - - /* - * If the MAC has no hardware capability don't do any further - * checking. - */ - if (capab == 0) - goto software; - - ASSERT(MBLKL(mp) >= sizeof (struct ether_header)); - ehp = (struct ether_header *)mp->b_rptr; - - if (ntohs(ehp->ether_type) == VLAN_TPID) { - struct ether_vlan_header *evhp; - - ASSERT(MBLKL(mp) >= sizeof (struct ether_vlan_header)); - evhp = (struct ether_vlan_header *)mp->b_rptr; - sap = ntohs(evhp->ether_type); - offset = sizeof (struct ether_vlan_header); - } else { - sap = ntohs(ehp->ether_type); - offset = sizeof (struct ether_header); - } - - /* - * We only attempt to do IPv4 packets in hardware. - */ - if (sap != ETHERTYPE_IP) - goto software; - - /* - * We know that this is an IPv4 packet. - */ - ipha = (ipha_t *)(mp->b_rptr + offset); - - switch (ipha->ipha_protocol) { - case IPPROTO_TCP: - case IPPROTO_UDP: { - uint32_t start, length, stuff, cksum; - uint16_t *stuffp; - - /* - * This is a TCP/IPv4 or UDP/IPv4 packet, for which we - * can use full IPv4 and partial checksum offload. - */ - if ((capab & (HCKSUM_INET_FULL_V4|HCKSUM_INET_PARTIAL)) == 0) - break; - - start = IP_SIMPLE_HDR_LENGTH; - length = ntohs(ipha->ipha_length); - if (ipha->ipha_protocol == IPPROTO_TCP) { - stuff = start + TCP_CHECKSUM_OFFSET; - cksum = IP_TCP_CSUM_COMP; - } else { - stuff = start + UDP_CHECKSUM_OFFSET; - cksum = IP_UDP_CSUM_COMP; - } - stuffp = (uint16_t *)(mp->b_rptr + offset + stuff); - - if (capab & HCKSUM_INET_FULL_V4) { - /* - * Some devices require that the checksum - * field of the packet is zero for full - * offload. - */ - *stuffp = 0; - - mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM); - - xnbp->xnb_stat_csum_hardware++; - - return (mp); - } - - if (capab & HCKSUM_INET_PARTIAL) { - if (*stuffp == 0) { - ipaddr_t src, dst; - - /* - * Older Solaris guests don't insert - * the pseudo-header checksum, so we - * calculate it here. - */ - src = ipha->ipha_src; - dst = ipha->ipha_dst; - - cksum += (dst >> 16) + (dst & 0xFFFF); - cksum += (src >> 16) + (src & 0xFFFF); - cksum += length - IP_SIMPLE_HDR_LENGTH; - - cksum = (cksum >> 16) + (cksum & 0xFFFF); - cksum = (cksum >> 16) + (cksum & 0xFFFF); - - ASSERT(cksum <= 0xFFFF); - - *stuffp = (uint16_t)(cksum ? cksum : ~cksum); - } - - mac_hcksum_set(mp, start, stuff, length, 0, - HCK_PARTIALCKSUM); - - xnbp->xnb_stat_csum_hardware++; - - return (mp); - } - - /* NOTREACHED */ - break; - } - - default: - /* Use software. */ - break; - } - -software: - /* - * We are not able to use any offload so do the whole thing in - * software. - */ - xnbp->xnb_stat_csum_software++; - - return (xnb_software_csum(xnbp, mp)); -} - -int -xnb_attach(dev_info_t *dip, xnb_flavour_t *flavour, void *flavour_data) -{ - xnb_t *xnbp; - char *xsname; - char cachename[32]; - - xnbp = kmem_zalloc(sizeof (*xnbp), KM_SLEEP); - - xnbp->xnb_flavour = flavour; - xnbp->xnb_flavour_data = flavour_data; - xnbp->xnb_devinfo = dip; - xnbp->xnb_evtchn = INVALID_EVTCHN; - xnbp->xnb_irq = B_FALSE; - xnbp->xnb_tx_ring_handle = INVALID_GRANT_HANDLE; - xnbp->xnb_rx_ring_handle = INVALID_GRANT_HANDLE; - xnbp->xnb_connected = B_FALSE; - xnbp->xnb_hotplugged = B_FALSE; - xnbp->xnb_detachable = B_FALSE; - xnbp->xnb_peer = xvdi_get_oeid(dip); - xnbp->xnb_be_status = XNB_STATE_INIT; - xnbp->xnb_fe_status = XNB_STATE_INIT; - - xnbp->xnb_tx_buf_count = 0; - - xnbp->xnb_rx_hv_copy = B_FALSE; - xnbp->xnb_multicast_control = B_FALSE; - - xnbp->xnb_rx_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP); - ASSERT(xnbp->xnb_rx_va != NULL); - - if (ddi_get_iblock_cookie(dip, 0, &xnbp->xnb_icookie) - != DDI_SUCCESS) - goto failure; - - /* Allocated on demand, when/if we enter xnb_copy_to_peer(). */ - xnbp->xnb_rx_cpop = NULL; - xnbp->xnb_rx_cpop_count = 0; - - mutex_init(&xnbp->xnb_tx_lock, NULL, MUTEX_DRIVER, - xnbp->xnb_icookie); - mutex_init(&xnbp->xnb_rx_lock, NULL, MUTEX_DRIVER, - xnbp->xnb_icookie); - mutex_init(&xnbp->xnb_state_lock, NULL, MUTEX_DRIVER, - xnbp->xnb_icookie); - - /* Set driver private pointer now. */ - ddi_set_driver_private(dip, xnbp); - - (void) sprintf(cachename, "xnb_tx_buf_cache_%d", ddi_get_instance(dip)); - xnbp->xnb_tx_buf_cache = kmem_cache_create(cachename, - sizeof (xnb_txbuf_t), 0, - xnb_txbuf_constructor, xnb_txbuf_destructor, - NULL, xnbp, NULL, 0); - if (xnbp->xnb_tx_buf_cache == NULL) - goto failure_0; - - if (!xnb_ks_init(xnbp)) - goto failure_1; - - /* - * Receive notification of changes in the state of the - * driver in the guest domain. - */ - if (xvdi_add_event_handler(dip, XS_OE_STATE, xnb_oe_state_change, - NULL) != DDI_SUCCESS) - goto failure_2; - - /* - * Receive notification of hotplug events. - */ - if (xvdi_add_event_handler(dip, XS_HP_STATE, xnb_hp_state_change, - NULL) != DDI_SUCCESS) - goto failure_2; - - xsname = xvdi_get_xsname(dip); - - if (xenbus_printf(XBT_NULL, xsname, - "feature-multicast-control", "%d", - xnb_multicast_control ? 1 : 0) != 0) - goto failure_3; - - if (xenbus_printf(XBT_NULL, xsname, - "feature-rx-copy", "%d", 1) != 0) - goto failure_3; - /* - * Linux domUs seem to depend on "feature-rx-flip" being 0 - * in addition to "feature-rx-copy" being 1. It seems strange - * to use four possible states to describe a binary decision, - * but we might as well play nice. - */ - if (xenbus_printf(XBT_NULL, xsname, - "feature-rx-flip", "%d", 0) != 0) - goto failure_3; - - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitWait); - (void) xvdi_post_event(dip, XEN_HP_ADD); - - return (DDI_SUCCESS); - -failure_3: - xvdi_remove_event_handler(dip, NULL); - -failure_2: - xnb_ks_free(xnbp); - -failure_1: - kmem_cache_destroy(xnbp->xnb_tx_buf_cache); - -failure_0: - mutex_destroy(&xnbp->xnb_state_lock); - mutex_destroy(&xnbp->xnb_rx_lock); - mutex_destroy(&xnbp->xnb_tx_lock); - -failure: - vmem_free(heap_arena, xnbp->xnb_rx_va, PAGESIZE); - kmem_free(xnbp, sizeof (*xnbp)); - return (DDI_FAILURE); -} - -void -xnb_detach(dev_info_t *dip) -{ - xnb_t *xnbp = ddi_get_driver_private(dip); - - ASSERT(xnbp != NULL); - ASSERT(!xnbp->xnb_connected); - ASSERT(xnbp->xnb_tx_buf_count == 0); - - xnb_disconnect_rings(dip); - - xvdi_remove_event_handler(dip, NULL); - - xnb_ks_free(xnbp); - - kmem_cache_destroy(xnbp->xnb_tx_buf_cache); - - ddi_set_driver_private(dip, NULL); - - mutex_destroy(&xnbp->xnb_state_lock); - mutex_destroy(&xnbp->xnb_rx_lock); - mutex_destroy(&xnbp->xnb_tx_lock); - - if (xnbp->xnb_rx_cpop_count > 0) - kmem_free(xnbp->xnb_rx_cpop, sizeof (xnbp->xnb_rx_cpop[0]) - * xnbp->xnb_rx_cpop_count); - - ASSERT(xnbp->xnb_rx_va != NULL); - vmem_free(heap_arena, xnbp->xnb_rx_va, PAGESIZE); - - kmem_free(xnbp, sizeof (*xnbp)); -} - -/* - * Allocate a page from the hypervisor to be flipped to the peer. - * - * Try to get pages in batches to reduce the overhead of calls into - * the balloon driver. - */ -static mfn_t -xnb_alloc_page(xnb_t *xnbp) -{ -#define WARNING_RATE_LIMIT 100 -#define BATCH_SIZE 256 - static mfn_t mfns[BATCH_SIZE]; /* common across all instances */ - static int nth = BATCH_SIZE; - mfn_t mfn; - - mutex_enter(&xnb_alloc_page_lock); - if (nth == BATCH_SIZE) { - if (balloon_alloc_pages(BATCH_SIZE, mfns) != BATCH_SIZE) { - xnbp->xnb_stat_allocation_failure++; - mutex_exit(&xnb_alloc_page_lock); - - /* - * Try for a single page in low memory situations. - */ - if (balloon_alloc_pages(1, &mfn) != 1) { - if ((xnbp->xnb_stat_small_allocation_failure++ - % WARNING_RATE_LIMIT) == 0) - cmn_err(CE_WARN, "xnb_alloc_page: " - "Cannot allocate memory to " - "transfer packets to peer."); - return (0); - } else { - xnbp->xnb_stat_small_allocation_success++; - return (mfn); - } - } - - nth = 0; - xnbp->xnb_stat_allocation_success++; - } - - mfn = mfns[nth++]; - mutex_exit(&xnb_alloc_page_lock); - - ASSERT(mfn != 0); - - return (mfn); -#undef BATCH_SIZE -#undef WARNING_RATE_LIMIT -} - -/* - * Free a page back to the hypervisor. - * - * This happens only in the error path, so batching is not worth the - * complication. - */ -static void -xnb_free_page(xnb_t *xnbp, mfn_t mfn) -{ - _NOTE(ARGUNUSED(xnbp)); - int r; - pfn_t pfn; - - pfn = xen_assign_pfn(mfn); - pfnzero(pfn, 0, PAGESIZE); - xen_release_pfn(pfn); - - if ((r = balloon_free_pages(1, &mfn, NULL, NULL)) != 1) { - cmn_err(CE_WARN, "free_page: cannot decrease memory " - "reservation (%d): page kept but unusable (mfn = 0x%lx).", - r, mfn); - } -} - -/* - * Similar to RING_HAS_UNCONSUMED_REQUESTS(&xnbp->rx_ring) but using - * local variables. Used in both xnb_to_peer() and xnb_copy_to_peer(). - */ -#define XNB_RING_HAS_UNCONSUMED_REQUESTS(_r) \ - ((((_r)->sring->req_prod - loop) < \ - (RING_SIZE(_r) - (loop - prod))) ? \ - ((_r)->sring->req_prod - loop) : \ - (RING_SIZE(_r) - (loop - prod))) - -/* - * Pass packets to the peer using page flipping. - */ -mblk_t * -xnb_to_peer(xnb_t *xnbp, mblk_t *mp) -{ - mblk_t *free = mp, *prev = NULL; - size_t len; - gnttab_transfer_t *gop; - boolean_t notify; - RING_IDX loop, prod, end; - - /* - * For each packet the sequence of operations is: - * - * 1. get a new page from the hypervisor. - * 2. get a request slot from the ring. - * 3. copy the data into the new page. - * 4. transfer the page to the peer. - * 5. update the request slot. - * 6. kick the peer. - * 7. free mp. - * - * In order to reduce the number of hypercalls, we prepare - * several packets for the peer and perform a single hypercall - * to transfer them. - */ - - mutex_enter(&xnbp->xnb_rx_lock); - - /* - * If we are not connected to the peer or have not yet - * finished hotplug it is too early to pass packets to the - * peer. - */ - if (!(xnbp->xnb_connected && xnbp->xnb_hotplugged)) { - mutex_exit(&xnbp->xnb_rx_lock); - DTRACE_PROBE(flip_rx_too_early); - xnbp->xnb_stat_rx_too_early++; - return (mp); - } - - loop = xnbp->xnb_rx_ring.req_cons; - prod = xnbp->xnb_rx_ring.rsp_prod_pvt; - gop = xnbp->xnb_rx_top; - - while ((mp != NULL) && - XNB_RING_HAS_UNCONSUMED_REQUESTS(&xnbp->xnb_rx_ring)) { - - mfn_t mfn; - pfn_t pfn; - netif_rx_request_t *rxreq; - netif_rx_response_t *rxresp; - char *valoop; - mblk_t *ml; - uint16_t cksum_flags; - - /* 1 */ - if ((mfn = xnb_alloc_page(xnbp)) == 0) { - xnbp->xnb_stat_rx_defer++; - break; - } - - /* 2 */ - rxreq = RING_GET_REQUEST(&xnbp->xnb_rx_ring, loop); - -#ifdef XNB_DEBUG - if (!(rxreq->id < NET_RX_RING_SIZE)) - cmn_err(CE_PANIC, "xnb_to_peer: " - "id %d out of range in request 0x%p", - rxreq->id, (void *)rxreq); -#endif /* XNB_DEBUG */ - - /* Assign a pfn and map the new page at the allocated va. */ - pfn = xen_assign_pfn(mfn); - hat_devload(kas.a_hat, xnbp->xnb_rx_va, PAGESIZE, - pfn, PROT_READ | PROT_WRITE, HAT_LOAD); - - /* 3 */ - len = 0; - valoop = xnbp->xnb_rx_va; - for (ml = mp; ml != NULL; ml = ml->b_cont) { - size_t chunk = ml->b_wptr - ml->b_rptr; - - bcopy(ml->b_rptr, valoop, chunk); - valoop += chunk; - len += chunk; - } - - ASSERT(len < PAGESIZE); - - /* Release the pfn. */ - hat_unload(kas.a_hat, xnbp->xnb_rx_va, PAGESIZE, - HAT_UNLOAD_UNMAP); - xen_release_pfn(pfn); - - /* 4 */ - gop->mfn = mfn; - gop->domid = xnbp->xnb_peer; - gop->ref = rxreq->gref; - - /* 5.1 */ - rxresp = RING_GET_RESPONSE(&xnbp->xnb_rx_ring, prod); - rxresp->offset = 0; - rxresp->flags = 0; - - cksum_flags = xnbp->xnb_flavour->xf_cksum_to_peer(xnbp, mp); - if (cksum_flags != 0) - xnbp->xnb_stat_rx_cksum_deferred++; - rxresp->flags |= cksum_flags; - - rxresp->id = RING_GET_REQUEST(&xnbp->xnb_rx_ring, prod)->id; - rxresp->status = len; - - loop++; - prod++; - gop++; - prev = mp; - mp = mp->b_next; - } - - /* - * Did we actually do anything? - */ - if (loop == xnbp->xnb_rx_ring.req_cons) { - mutex_exit(&xnbp->xnb_rx_lock); - return (mp); - } - - end = loop; - - /* - * Unlink the end of the 'done' list from the remainder. - */ - ASSERT(prev != NULL); - prev->b_next = NULL; - - if (HYPERVISOR_grant_table_op(GNTTABOP_transfer, xnbp->xnb_rx_top, - loop - xnbp->xnb_rx_ring.req_cons) != 0) { - cmn_err(CE_WARN, "xnb_to_peer: transfer operation failed"); - } - - loop = xnbp->xnb_rx_ring.req_cons; - prod = xnbp->xnb_rx_ring.rsp_prod_pvt; - gop = xnbp->xnb_rx_top; - - while (loop < end) { - int16_t status = NETIF_RSP_OKAY; - - if (gop->status != 0) { - status = NETIF_RSP_ERROR; - - /* - * If the status is anything other than - * GNTST_bad_page then we don't own the page - * any more, so don't try to give it back. - */ - if (gop->status != GNTST_bad_page) - gop->mfn = 0; - } else { - /* The page is no longer ours. */ - gop->mfn = 0; - } - - if (gop->mfn != 0) - /* - * Give back the page, as we won't be using - * it. - */ - xnb_free_page(xnbp, gop->mfn); - else - /* - * We gave away a page, update our accounting - * now. - */ - balloon_drv_subtracted(1); - - /* 5.2 */ - if (status != NETIF_RSP_OKAY) { - RING_GET_RESPONSE(&xnbp->xnb_rx_ring, prod)->status = - status; - } else { - xnbp->xnb_stat_ipackets++; - xnbp->xnb_stat_rbytes += len; - } - - loop++; - prod++; - gop++; - } - - xnbp->xnb_rx_ring.req_cons = loop; - xnbp->xnb_rx_ring.rsp_prod_pvt = prod; - - /* 6 */ - /* LINTED: constant in conditional context */ - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xnbp->xnb_rx_ring, notify); - if (notify) { - ec_notify_via_evtchn(xnbp->xnb_evtchn); - xnbp->xnb_stat_rx_notify_sent++; - } else { - xnbp->xnb_stat_rx_notify_deferred++; - } - - if (mp != NULL) - xnbp->xnb_stat_rx_defer++; - - mutex_exit(&xnbp->xnb_rx_lock); - - /* Free mblk_t's that we consumed. */ - freemsgchain(free); - - return (mp); -} - -/* Helper functions for xnb_copy_to_peer(). */ - -/* - * Grow the array of copy operation descriptors. - */ -static boolean_t -grow_cpop_area(xnb_t *xnbp) -{ - size_t count; - gnttab_copy_t *new; - - ASSERT(MUTEX_HELD(&xnbp->xnb_rx_lock)); - - count = xnbp->xnb_rx_cpop_count + CPOP_DEFCNT; - - if ((new = kmem_alloc(sizeof (new[0]) * count, KM_NOSLEEP)) == NULL) { - xnbp->xnb_stat_other_allocation_failure++; - return (B_FALSE); - } - - bcopy(xnbp->xnb_rx_cpop, new, - sizeof (xnbp->xnb_rx_cpop[0]) * xnbp->xnb_rx_cpop_count); - - kmem_free(xnbp->xnb_rx_cpop, - sizeof (xnbp->xnb_rx_cpop[0]) * xnbp->xnb_rx_cpop_count); - - xnbp->xnb_rx_cpop = new; - xnbp->xnb_rx_cpop_count = count; - - xnbp->xnb_stat_rx_cpoparea_grown++; - - return (B_TRUE); -} - -/* - * Check whether an address is on a page that's foreign to this domain. - */ -static boolean_t -is_foreign(void *addr) -{ - pfn_t pfn = hat_getpfnum(kas.a_hat, addr); - - return ((pfn & PFN_IS_FOREIGN_MFN) == PFN_IS_FOREIGN_MFN); -} - -/* - * Insert a newly allocated mblk into a chain, replacing the old one. - */ -static mblk_t * -replace_msg(mblk_t *mp, size_t len, mblk_t *mp_prev, mblk_t *ml_prev) -{ - uint32_t start, stuff, end, value, flags; - mblk_t *new_mp; - - new_mp = copyb(mp); - if (new_mp == NULL) { - cmn_err(CE_PANIC, "replace_msg: cannot alloc new message" - "for %p, len %lu", (void *) mp, len); - } - - mac_hcksum_get(mp, &start, &stuff, &end, &value, &flags); - mac_hcksum_set(new_mp, start, stuff, end, value, flags); - - new_mp->b_next = mp->b_next; - new_mp->b_prev = mp->b_prev; - new_mp->b_cont = mp->b_cont; - - /* Make sure we only overwrite pointers to the mblk being replaced. */ - if (mp_prev != NULL && mp_prev->b_next == mp) - mp_prev->b_next = new_mp; - - if (ml_prev != NULL && ml_prev->b_cont == mp) - ml_prev->b_cont = new_mp; - - mp->b_next = mp->b_prev = mp->b_cont = NULL; - freemsg(mp); - - return (new_mp); -} - -/* - * Set all the fields in a gnttab_copy_t. - */ -static void -setup_gop(xnb_t *xnbp, gnttab_copy_t *gp, uchar_t *rptr, - size_t s_off, size_t d_off, size_t len, grant_ref_t d_ref) -{ - ASSERT(xnbp != NULL && gp != NULL); - - gp->source.offset = s_off; - gp->source.u.gmfn = pfn_to_mfn(hat_getpfnum(kas.a_hat, (caddr_t)rptr)); - gp->source.domid = DOMID_SELF; - - gp->len = (uint16_t)len; - gp->flags = GNTCOPY_dest_gref; - gp->status = 0; - - gp->dest.u.ref = d_ref; - gp->dest.offset = d_off; - gp->dest.domid = xnbp->xnb_peer; -} - -/* - * Pass packets to the peer using hypervisor copy operations. - */ -mblk_t * -xnb_copy_to_peer(xnb_t *xnbp, mblk_t *mp) -{ - mblk_t *free = mp, *mp_prev = NULL, *saved_mp = mp; - mblk_t *ml, *ml_prev; - boolean_t notify; - RING_IDX loop, prod; - int i; - - /* - * If the peer does not pre-post buffers for received packets, - * use page flipping to pass packets to it. - */ - if (!xnbp->xnb_rx_hv_copy) - return (xnb_to_peer(xnbp, mp)); - - /* - * For each packet the sequence of operations is: - * - * 1. get a request slot from the ring. - * 2. set up data for hypercall (see NOTE below) - * 3. have the hypervisore copy the data - * 4. update the request slot. - * 5. kick the peer. - * - * NOTE ad 2. - * In order to reduce the number of hypercalls, we prepare - * several mblks (mp->b_cont != NULL) for the peer and - * perform a single hypercall to transfer them. We also have - * to set up a seperate copy operation for every page. - * - * If we have more than one packet (mp->b_next != NULL), we do - * this whole dance repeatedly. - */ - - mutex_enter(&xnbp->xnb_rx_lock); - - if (!(xnbp->xnb_connected && xnbp->xnb_hotplugged)) { - mutex_exit(&xnbp->xnb_rx_lock); - DTRACE_PROBE(copy_rx_too_early); - xnbp->xnb_stat_rx_too_early++; - return (mp); - } - - loop = xnbp->xnb_rx_ring.req_cons; - prod = xnbp->xnb_rx_ring.rsp_prod_pvt; - - while ((mp != NULL) && - XNB_RING_HAS_UNCONSUMED_REQUESTS(&xnbp->xnb_rx_ring)) { - netif_rx_request_t *rxreq; - size_t d_offset, len; - int item_count; - gnttab_copy_t *gop_cp; - netif_rx_response_t *rxresp; - uint16_t cksum_flags; - int16_t status = NETIF_RSP_OKAY; - - /* 1 */ - rxreq = RING_GET_REQUEST(&xnbp->xnb_rx_ring, loop); - -#ifdef XNB_DEBUG - if (!(rxreq->id < NET_RX_RING_SIZE)) - cmn_err(CE_PANIC, "xnb_copy_to_peer: " - "id %d out of range in request 0x%p", - rxreq->id, (void *)rxreq); -#endif /* XNB_DEBUG */ - - /* 2 */ - d_offset = 0; - len = 0; - item_count = 0; - - gop_cp = xnbp->xnb_rx_cpop; - - /* - * We walk the b_cont pointers and set up a - * gnttab_copy_t for each sub-page chunk in each data - * block. - */ - /* 2a */ - for (ml = mp, ml_prev = NULL; ml != NULL; ml = ml->b_cont) { - size_t chunk = ml->b_wptr - ml->b_rptr; - uchar_t *r_tmp, *rpt_align; - size_t r_offset; - - /* - * The hypervisor will not allow us to - * reference a foreign page (e.g. one - * belonging to another domain) by mfn in the - * copy operation. If the data in this mblk is - * on such a page we must copy the data into a - * local page before initiating the hypervisor - * copy operation. - */ - if (is_foreign(ml->b_rptr) || is_foreign(ml->b_wptr)) { - mblk_t *ml_new = replace_msg(ml, chunk, - mp_prev, ml_prev); - - /* We can still use old ml, but not *ml! */ - if (free == ml) - free = ml_new; - if (mp == ml) - mp = ml_new; - ml = ml_new; - - xnbp->xnb_stat_rx_foreign_page++; - } - - rpt_align = (uchar_t *)ALIGN2PAGE(ml->b_rptr); - r_offset = (uint16_t)(ml->b_rptr - rpt_align); - r_tmp = ml->b_rptr; - - if (d_offset + chunk > PAGESIZE) - cmn_err(CE_PANIC, "xnb_copy_to_peer: mp %p " - "(svd: %p), ml %p,rpt_alg. %p, d_offset " - "(%lu) + chunk (%lu) > PAGESIZE %d!", - (void *)mp, (void *)saved_mp, (void *)ml, - (void *)rpt_align, - d_offset, chunk, (int)PAGESIZE); - - while (chunk > 0) { - size_t part_len; - - if (item_count == xnbp->xnb_rx_cpop_count) { - if (!grow_cpop_area(xnbp)) - goto failure; - gop_cp = &xnbp->xnb_rx_cpop[item_count]; - } - /* - * If our mblk crosses a page boundary, we need - * to do a seperate copy for each page. - */ - if (r_offset + chunk > PAGESIZE) { - part_len = PAGESIZE - r_offset; - - DTRACE_PROBE3(mblk_page_crossed, - (mblk_t *), ml, int, chunk, int, - (int)r_offset); - - xnbp->xnb_stat_rx_pagebndry_crossed++; - } else { - part_len = chunk; - } - - setup_gop(xnbp, gop_cp, r_tmp, r_offset, - d_offset, part_len, rxreq->gref); - - chunk -= part_len; - - len += part_len; - d_offset += part_len; - r_tmp += part_len; - /* - * The 2nd, 3rd ... last copies will always - * start at r_tmp, therefore r_offset is 0. - */ - r_offset = 0; - gop_cp++; - item_count++; - } - ml_prev = ml; - - DTRACE_PROBE4(mblk_loop_end, (mblk_t *), ml, int, - chunk, int, len, int, item_count); - } - /* 3 */ - if (HYPERVISOR_grant_table_op(GNTTABOP_copy, xnbp->xnb_rx_cpop, - item_count) != 0) { - cmn_err(CE_WARN, "xnb_copy_to_peer: copy op. failed"); - DTRACE_PROBE(HV_granttableopfailed); - } - - /* 4 */ - rxresp = RING_GET_RESPONSE(&xnbp->xnb_rx_ring, prod); - rxresp->offset = 0; - - rxresp->flags = 0; - - DTRACE_PROBE4(got_RX_rsp, int, (int)rxresp->id, int, - (int)rxresp->offset, int, (int)rxresp->flags, int, - (int)rxresp->status); - - cksum_flags = xnbp->xnb_flavour->xf_cksum_to_peer(xnbp, mp); - if (cksum_flags != 0) - xnbp->xnb_stat_rx_cksum_deferred++; - rxresp->flags |= cksum_flags; - - rxresp->id = RING_GET_REQUEST(&xnbp->xnb_rx_ring, prod)->id; - rxresp->status = len; - - DTRACE_PROBE4(RX_rsp_set, int, (int)rxresp->id, int, - (int)rxresp->offset, int, (int)rxresp->flags, int, - (int)rxresp->status); - - for (i = 0; i < item_count; i++) { - if (xnbp->xnb_rx_cpop[i].status != 0) { - DTRACE_PROBE2(cpop_status_nonnull, int, - (int)xnbp->xnb_rx_cpop[i].status, - int, i); - status = NETIF_RSP_ERROR; - } - } - - /* 5.2 */ - if (status != NETIF_RSP_OKAY) { - RING_GET_RESPONSE(&xnbp->xnb_rx_ring, prod)->status = - status; - xnbp->xnb_stat_rx_rsp_notok++; - } else { - xnbp->xnb_stat_ipackets++; - xnbp->xnb_stat_rbytes += len; - } - - loop++; - prod++; - mp_prev = mp; - mp = mp->b_next; - } -failure: - /* - * Did we actually do anything? - */ - if (loop == xnbp->xnb_rx_ring.req_cons) { - mutex_exit(&xnbp->xnb_rx_lock); - return (mp); - } - - /* - * Unlink the end of the 'done' list from the remainder. - */ - ASSERT(mp_prev != NULL); - mp_prev->b_next = NULL; - - xnbp->xnb_rx_ring.req_cons = loop; - xnbp->xnb_rx_ring.rsp_prod_pvt = prod; - - /* 6 */ - /* LINTED: constant in conditional context */ - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xnbp->xnb_rx_ring, notify); - if (notify) { - ec_notify_via_evtchn(xnbp->xnb_evtchn); - xnbp->xnb_stat_rx_notify_sent++; - } else { - xnbp->xnb_stat_rx_notify_deferred++; - } - - if (mp != NULL) - xnbp->xnb_stat_rx_defer++; - - mutex_exit(&xnbp->xnb_rx_lock); - - /* Free mblk_t structs we have consumed. */ - freemsgchain(free); - - return (mp); -} - - -static void -xnb_tx_notify_peer(xnb_t *xnbp, boolean_t force) -{ - boolean_t notify; - - ASSERT(MUTEX_HELD(&xnbp->xnb_tx_lock)); - - /* LINTED: constant in conditional context */ - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xnbp->xnb_tx_ring, notify); - if (notify || force) { - ec_notify_via_evtchn(xnbp->xnb_evtchn); - xnbp->xnb_stat_tx_notify_sent++; - } else { - xnbp->xnb_stat_tx_notify_deferred++; - } -} - -static void -xnb_tx_mark_complete(xnb_t *xnbp, RING_IDX id, int16_t status) -{ - RING_IDX i; - netif_tx_response_t *txresp; - - ASSERT(MUTEX_HELD(&xnbp->xnb_tx_lock)); - - i = xnbp->xnb_tx_ring.rsp_prod_pvt; - - txresp = RING_GET_RESPONSE(&xnbp->xnb_tx_ring, i); - txresp->id = id; - txresp->status = status; - - xnbp->xnb_tx_ring.rsp_prod_pvt = i + 1; - - /* - * Note that we don't push the change to the peer here - that - * is the callers responsibility. - */ -} - -static void -xnb_txbuf_recycle(xnb_txbuf_t *txp) -{ - xnb_t *xnbp = txp->xt_xnbp; - - kmem_cache_free(xnbp->xnb_tx_buf_cache, txp); - - xnbp->xnb_tx_buf_outstanding--; -} - -static int -xnb_txbuf_constructor(void *buf, void *arg, int kmflag) -{ - _NOTE(ARGUNUSED(kmflag)); - xnb_txbuf_t *txp = buf; - xnb_t *xnbp = arg; - size_t len; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - - txp->xt_free_rtn.free_func = xnb_txbuf_recycle; - txp->xt_free_rtn.free_arg = (caddr_t)txp; - txp->xt_xnbp = xnbp; - txp->xt_next = NULL; - - if (ddi_dma_alloc_handle(xnbp->xnb_devinfo, &buf_dma_attr, - 0, 0, &txp->xt_dma_handle) != DDI_SUCCESS) - goto failure; - - if (ddi_dma_mem_alloc(txp->xt_dma_handle, PAGESIZE, &data_accattr, - DDI_DMA_STREAMING, 0, 0, &txp->xt_buf, &len, - &txp->xt_acc_handle) != DDI_SUCCESS) - goto failure_1; - - if (ddi_dma_addr_bind_handle(txp->xt_dma_handle, NULL, txp->xt_buf, - len, DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0, - &dma_cookie, &ncookies) - != DDI_DMA_MAPPED) - goto failure_2; - ASSERT(ncookies == 1); - - txp->xt_mfn = xnb_btop(dma_cookie.dmac_laddress); - txp->xt_buflen = dma_cookie.dmac_size; - - DTRACE_PROBE(txbuf_allocated); - - atomic_inc_32(&xnbp->xnb_tx_buf_count); - xnbp->xnb_tx_buf_outstanding++; - - return (0); - -failure_2: - ddi_dma_mem_free(&txp->xt_acc_handle); - -failure_1: - ddi_dma_free_handle(&txp->xt_dma_handle); - -failure: - - return (-1); -} - -static void -xnb_txbuf_destructor(void *buf, void *arg) -{ - xnb_txbuf_t *txp = buf; - xnb_t *xnbp = arg; - - (void) ddi_dma_unbind_handle(txp->xt_dma_handle); - ddi_dma_mem_free(&txp->xt_acc_handle); - ddi_dma_free_handle(&txp->xt_dma_handle); - - atomic_dec_32(&xnbp->xnb_tx_buf_count); -} - -/* - * Take packets from the peer and deliver them onward. - */ -static mblk_t * -xnb_from_peer(xnb_t *xnbp) -{ - RING_IDX start, end, loop; - gnttab_copy_t *cop; - xnb_txbuf_t **txpp; - netif_tx_request_t *txreq; - boolean_t work_to_do, need_notify = B_FALSE; - mblk_t *head, *tail; - int n_data_req, i; - - ASSERT(MUTEX_HELD(&xnbp->xnb_tx_lock)); - - head = tail = NULL; -around: - - /* LINTED: constant in conditional context */ - RING_FINAL_CHECK_FOR_REQUESTS(&xnbp->xnb_tx_ring, work_to_do); - if (!work_to_do) { -finished: - xnb_tx_notify_peer(xnbp, need_notify); - - return (head); - } - - start = xnbp->xnb_tx_ring.req_cons; - end = xnbp->xnb_tx_ring.sring->req_prod; - - if ((end - start) > NET_TX_RING_SIZE) { - /* - * This usually indicates that the frontend driver is - * misbehaving, as it's not possible to have more than - * NET_TX_RING_SIZE ring elements in play at any one - * time. - * - * We reset the ring pointers to the state declared by - * the frontend and try to carry on. - */ - cmn_err(CE_WARN, "xnb_from_peer: domain %d tried to give us %u " - "items in the ring, resetting and trying to recover.", - xnbp->xnb_peer, (end - start)); - - /* LINTED: constant in conditional context */ - BACK_RING_ATTACH(&xnbp->xnb_tx_ring, - (netif_tx_sring_t *)xnbp->xnb_tx_ring_addr, PAGESIZE); - - goto around; - } - - loop = start; - cop = xnbp->xnb_tx_cop; - txpp = xnbp->xnb_tx_bufp; - n_data_req = 0; - - while (loop < end) { - static const uint16_t acceptable_flags = - NETTXF_csum_blank | - NETTXF_data_validated | - NETTXF_extra_info; - uint16_t unexpected_flags; - - txreq = RING_GET_REQUEST(&xnbp->xnb_tx_ring, loop); - - unexpected_flags = txreq->flags & ~acceptable_flags; - if (unexpected_flags != 0) { - /* - * The peer used flag bits that we do not - * recognize. - */ - cmn_err(CE_WARN, "xnb_from_peer: " - "unexpected flag bits (0x%x) from peer " - "in transmit request", - unexpected_flags); - xnbp->xnb_stat_tx_unexpected_flags++; - - /* Mark this entry as failed. */ - xnb_tx_mark_complete(xnbp, txreq->id, NETIF_RSP_ERROR); - need_notify = B_TRUE; - - } else if (txreq->flags & NETTXF_extra_info) { - struct netif_extra_info *erp; - boolean_t status; - - loop++; /* Consume another slot in the ring. */ - ASSERT(loop <= end); - - erp = (struct netif_extra_info *) - RING_GET_REQUEST(&xnbp->xnb_tx_ring, loop); - - switch (erp->type) { - case XEN_NETIF_EXTRA_TYPE_MCAST_ADD: - ASSERT(xnbp->xnb_multicast_control); - status = xnbp->xnb_flavour->xf_mcast_add(xnbp, - &erp->u.mcast.addr); - break; - case XEN_NETIF_EXTRA_TYPE_MCAST_DEL: - ASSERT(xnbp->xnb_multicast_control); - status = xnbp->xnb_flavour->xf_mcast_del(xnbp, - &erp->u.mcast.addr); - break; - default: - status = B_FALSE; - cmn_err(CE_WARN, "xnb_from_peer: " - "unknown extra type %d", erp->type); - break; - } - - xnb_tx_mark_complete(xnbp, txreq->id, - status ? NETIF_RSP_OKAY : NETIF_RSP_ERROR); - need_notify = B_TRUE; - - } else if ((txreq->offset > PAGESIZE) || - (txreq->offset + txreq->size > PAGESIZE)) { - /* - * Peer attempted to refer to data beyond the - * end of the granted page. - */ - cmn_err(CE_WARN, "xnb_from_peer: " - "attempt to refer beyond the end of granted " - "page in txreq (offset %d, size %d).", - txreq->offset, txreq->size); - xnbp->xnb_stat_tx_overflow_page++; - - /* Mark this entry as failed. */ - xnb_tx_mark_complete(xnbp, txreq->id, NETIF_RSP_ERROR); - need_notify = B_TRUE; - - } else { - xnb_txbuf_t *txp; - - txp = kmem_cache_alloc(xnbp->xnb_tx_buf_cache, - KM_NOSLEEP); - if (txp == NULL) - break; - - txp->xt_mblk = desballoc((unsigned char *)txp->xt_buf, - txp->xt_buflen, 0, &txp->xt_free_rtn); - if (txp->xt_mblk == NULL) { - kmem_cache_free(xnbp->xnb_tx_buf_cache, txp); - break; - } - - txp->xt_idx = loop; - txp->xt_id = txreq->id; - - cop->source.u.ref = txreq->gref; - cop->source.domid = xnbp->xnb_peer; - cop->source.offset = txreq->offset; - - cop->dest.u.gmfn = txp->xt_mfn; - cop->dest.domid = DOMID_SELF; - cop->dest.offset = 0; - - cop->len = txreq->size; - cop->flags = GNTCOPY_source_gref; - cop->status = 0; - - *txpp = txp; - - txpp++; - cop++; - n_data_req++; - - ASSERT(n_data_req <= NET_TX_RING_SIZE); - } - - loop++; - } - - xnbp->xnb_tx_ring.req_cons = loop; - - if (n_data_req == 0) - goto around; - - if (HYPERVISOR_grant_table_op(GNTTABOP_copy, - xnbp->xnb_tx_cop, n_data_req) != 0) { - - cmn_err(CE_WARN, "xnb_from_peer: copy operation failed"); - - txpp = xnbp->xnb_tx_bufp; - i = n_data_req; - while (i > 0) { - kmem_cache_free(xnbp->xnb_tx_buf_cache, *txpp); - txpp++; - i--; - } - - goto finished; - } - - txpp = xnbp->xnb_tx_bufp; - cop = xnbp->xnb_tx_cop; - i = n_data_req; - - while (i > 0) { - xnb_txbuf_t *txp = *txpp; - - txreq = RING_GET_REQUEST(&xnbp->xnb_tx_ring, txp->xt_idx); - - if (cop->status != 0) { -#ifdef XNB_DEBUG - cmn_err(CE_WARN, "xnb_from_peer: " - "txpp 0x%p failed (%d)", - (void *)*txpp, cop->status); -#endif /* XNB_DEBUG */ - xnb_tx_mark_complete(xnbp, txp->xt_id, NETIF_RSP_ERROR); - freemsg(txp->xt_mblk); - } else { - mblk_t *mp; - - mp = txp->xt_mblk; - mp->b_rptr = mp->b_wptr = (unsigned char *)txp->xt_buf; - mp->b_wptr += txreq->size; - mp->b_next = NULL; - - /* - * If there are checksum flags, process them - * appropriately. - */ - if ((txreq->flags & - (NETTXF_csum_blank | NETTXF_data_validated)) - != 0) { - mp = xnbp->xnb_flavour->xf_cksum_from_peer(xnbp, - mp, txreq->flags); - xnbp->xnb_stat_tx_cksum_no_need++; - - txp->xt_mblk = mp; - } - - if (head == NULL) { - ASSERT(tail == NULL); - head = mp; - } else { - ASSERT(tail != NULL); - tail->b_next = mp; - } - tail = mp; - - xnbp->xnb_stat_opackets++; - xnbp->xnb_stat_obytes += txreq->size; - - xnb_tx_mark_complete(xnbp, txp->xt_id, NETIF_RSP_OKAY); - } - - txpp++; - cop++; - i--; - } - - goto around; - /* NOTREACHED */ -} - -static uint_t -xnb_intr(caddr_t arg) -{ - xnb_t *xnbp = (xnb_t *)arg; - mblk_t *mp; - - xnbp->xnb_stat_intr++; - - mutex_enter(&xnbp->xnb_tx_lock); - - ASSERT(xnbp->xnb_connected); - - mp = xnb_from_peer(xnbp); - - mutex_exit(&xnbp->xnb_tx_lock); - - if (!xnbp->xnb_hotplugged) { - xnbp->xnb_stat_tx_too_early++; - goto fail; - } - if (mp == NULL) { - xnbp->xnb_stat_spurious_intr++; - goto fail; - } - - xnbp->xnb_flavour->xf_from_peer(xnbp, mp); - - return (DDI_INTR_CLAIMED); - -fail: - freemsgchain(mp); - return (DDI_INTR_CLAIMED); -} - -/* - * Read our configuration from xenstore. - */ -boolean_t -xnb_read_xs_config(xnb_t *xnbp) -{ - char *xsname; - char mac[ETHERADDRL * 3]; - - xsname = xvdi_get_xsname(xnbp->xnb_devinfo); - - if (xenbus_scanf(XBT_NULL, xsname, - "mac", "%s", mac) != 0) { - cmn_err(CE_WARN, "xnb_attach: " - "cannot read mac address from %s", - xsname); - return (B_FALSE); - } - - if (ether_aton(mac, xnbp->xnb_mac_addr) != ETHERADDRL) { - cmn_err(CE_WARN, - "xnb_attach: cannot parse mac address %s", - mac); - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * Read the configuration of the peer from xenstore. - */ -boolean_t -xnb_read_oe_config(xnb_t *xnbp) -{ - char *oename; - int i; - - oename = xvdi_get_oename(xnbp->xnb_devinfo); - - if (xenbus_gather(XBT_NULL, oename, - "event-channel", "%u", &xnbp->xnb_fe_evtchn, - "tx-ring-ref", "%lu", &xnbp->xnb_tx_ring_ref, - "rx-ring-ref", "%lu", &xnbp->xnb_rx_ring_ref, - NULL) != 0) { - cmn_err(CE_WARN, "xnb_read_oe_config: " - "cannot read other-end details from %s", - oename); - return (B_FALSE); - } - - /* - * Check whether our peer requests receive side hypervisor - * copy. - */ - if (xenbus_scanf(XBT_NULL, oename, - "request-rx-copy", "%d", &i) != 0) - i = 0; - if (i != 0) - xnbp->xnb_rx_hv_copy = B_TRUE; - - /* - * Check whether our peer requests multicast_control. - */ - if (xenbus_scanf(XBT_NULL, oename, - "request-multicast-control", "%d", &i) != 0) - i = 0; - if (i != 0) - xnbp->xnb_multicast_control = B_TRUE; - - /* - * The Linux backend driver here checks to see if the peer has - * set 'feature-no-csum-offload'. This is used to indicate - * that the guest cannot handle receiving packets without a - * valid checksum. We don't check here, because packets passed - * to the peer _always_ have a valid checksum. - * - * There are three cases: - * - * - the NIC is dedicated: packets from the wire should always - * have a valid checksum. If the hardware validates the - * checksum then the relevant bit will be set in the packet - * attributes and we will inform the peer. It can choose to - * ignore the hardware verification. - * - * - the NIC is shared (VNIC) and a packet originates from the - * wire: this is the same as the case above - the packets - * will have a valid checksum. - * - * - the NIC is shared (VNIC) and a packet originates from the - * host: the MAC layer ensures that all such packets have a - * valid checksum by calculating one if the stack did not. - */ - - return (B_TRUE); -} - -void -xnb_start_connect(xnb_t *xnbp) -{ - dev_info_t *dip = xnbp->xnb_devinfo; - - if (!xnb_connect_rings(dip)) { - cmn_err(CE_WARN, "xnb_start_connect: " - "cannot connect rings"); - goto failed; - } - - if (!xnbp->xnb_flavour->xf_start_connect(xnbp)) { - cmn_err(CE_WARN, "xnb_start_connect: " - "flavour failed to connect"); - goto failed; - } - - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateConnected); - return; - -failed: - xnbp->xnb_flavour->xf_peer_disconnected(xnbp); - xnb_disconnect_rings(dip); - (void) xvdi_switch_state(dip, XBT_NULL, - XenbusStateClosed); - (void) xvdi_post_event(dip, XEN_HP_REMOVE); -} - -static boolean_t -xnb_connect_rings(dev_info_t *dip) -{ - xnb_t *xnbp = ddi_get_driver_private(dip); - struct gnttab_map_grant_ref map_op; - - /* - * Cannot attempt to connect the rings if already connected. - */ - ASSERT(!xnbp->xnb_connected); - - /* - * 1. allocate a vaddr for the tx page, one for the rx page. - * 2. call GNTTABOP_map_grant_ref to map the relevant pages - * into the allocated vaddr (one for tx, one for rx). - * 3. call EVTCHNOP_bind_interdomain to have the event channel - * bound to this domain. - * 4. associate the event channel with an interrupt. - * 5. enable the interrupt. - */ - - /* 1.tx */ - xnbp->xnb_tx_ring_addr = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE, - 0, 0, 0, 0, VM_SLEEP); - ASSERT(xnbp->xnb_tx_ring_addr != NULL); - - /* 2.tx */ - map_op.host_addr = (uint64_t)((long)xnbp->xnb_tx_ring_addr); - map_op.flags = GNTMAP_host_map; - map_op.ref = xnbp->xnb_tx_ring_ref; - map_op.dom = xnbp->xnb_peer; - hat_prepare_mapping(kas.a_hat, xnbp->xnb_tx_ring_addr, NULL); - if (xen_map_gref(GNTTABOP_map_grant_ref, &map_op, 1, B_FALSE) != 0 || - map_op.status != 0) { - cmn_err(CE_WARN, "xnb_connect_rings: cannot map tx-ring page."); - goto fail; - } - xnbp->xnb_tx_ring_handle = map_op.handle; - - /* LINTED: constant in conditional context */ - BACK_RING_INIT(&xnbp->xnb_tx_ring, - (netif_tx_sring_t *)xnbp->xnb_tx_ring_addr, PAGESIZE); - - /* 1.rx */ - xnbp->xnb_rx_ring_addr = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE, - 0, 0, 0, 0, VM_SLEEP); - ASSERT(xnbp->xnb_rx_ring_addr != NULL); - - /* 2.rx */ - map_op.host_addr = (uint64_t)((long)xnbp->xnb_rx_ring_addr); - map_op.flags = GNTMAP_host_map; - map_op.ref = xnbp->xnb_rx_ring_ref; - map_op.dom = xnbp->xnb_peer; - hat_prepare_mapping(kas.a_hat, xnbp->xnb_rx_ring_addr, NULL); - if (xen_map_gref(GNTTABOP_map_grant_ref, &map_op, 1, B_FALSE) != 0 || - map_op.status != 0) { - cmn_err(CE_WARN, "xnb_connect_rings: cannot map rx-ring page."); - goto fail; - } - xnbp->xnb_rx_ring_handle = map_op.handle; - - /* LINTED: constant in conditional context */ - BACK_RING_INIT(&xnbp->xnb_rx_ring, - (netif_rx_sring_t *)xnbp->xnb_rx_ring_addr, PAGESIZE); - - /* 3 */ - if (xvdi_bind_evtchn(dip, xnbp->xnb_fe_evtchn) != DDI_SUCCESS) { - cmn_err(CE_WARN, "xnb_connect_rings: " - "cannot bind event channel %d", xnbp->xnb_evtchn); - xnbp->xnb_evtchn = INVALID_EVTCHN; - goto fail; - } - xnbp->xnb_evtchn = xvdi_get_evtchn(dip); - - /* - * It would be good to set the state to XenbusStateConnected - * here as well, but then what if ddi_add_intr() failed? - * Changing the state in the store will be noticed by the peer - * and cannot be "taken back". - */ - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - xnbp->xnb_connected = B_TRUE; - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - /* 4, 5 */ - if (ddi_add_intr(dip, 0, NULL, NULL, xnb_intr, (caddr_t)xnbp) - != DDI_SUCCESS) { - cmn_err(CE_WARN, "xnb_connect_rings: cannot add interrupt"); - goto fail; - } - xnbp->xnb_irq = B_TRUE; - - return (B_TRUE); - -fail: - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - xnbp->xnb_connected = B_FALSE; - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - return (B_FALSE); -} - -static void -xnb_disconnect_rings(dev_info_t *dip) -{ - xnb_t *xnbp = ddi_get_driver_private(dip); - - if (xnbp->xnb_irq) { - ddi_remove_intr(dip, 0, NULL); - xnbp->xnb_irq = B_FALSE; - } - - if (xnbp->xnb_evtchn != INVALID_EVTCHN) { - xvdi_free_evtchn(dip); - xnbp->xnb_evtchn = INVALID_EVTCHN; - } - - if (xnbp->xnb_rx_ring_handle != INVALID_GRANT_HANDLE) { - struct gnttab_unmap_grant_ref unmap_op; - - unmap_op.host_addr = (uint64_t)(uintptr_t) - xnbp->xnb_rx_ring_addr; - unmap_op.dev_bus_addr = 0; - unmap_op.handle = xnbp->xnb_rx_ring_handle; - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, 1) != 0) - cmn_err(CE_WARN, "xnb_disconnect_rings: " - "cannot unmap rx-ring page (%d)", - unmap_op.status); - - xnbp->xnb_rx_ring_handle = INVALID_GRANT_HANDLE; - } - - if (xnbp->xnb_rx_ring_addr != NULL) { - hat_release_mapping(kas.a_hat, xnbp->xnb_rx_ring_addr); - vmem_free(heap_arena, xnbp->xnb_rx_ring_addr, PAGESIZE); - xnbp->xnb_rx_ring_addr = NULL; - } - - if (xnbp->xnb_tx_ring_handle != INVALID_GRANT_HANDLE) { - struct gnttab_unmap_grant_ref unmap_op; - - unmap_op.host_addr = (uint64_t)(uintptr_t) - xnbp->xnb_tx_ring_addr; - unmap_op.dev_bus_addr = 0; - unmap_op.handle = xnbp->xnb_tx_ring_handle; - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - &unmap_op, 1) != 0) - cmn_err(CE_WARN, "xnb_disconnect_rings: " - "cannot unmap tx-ring page (%d)", - unmap_op.status); - - xnbp->xnb_tx_ring_handle = INVALID_GRANT_HANDLE; - } - - if (xnbp->xnb_tx_ring_addr != NULL) { - hat_release_mapping(kas.a_hat, xnbp->xnb_tx_ring_addr); - vmem_free(heap_arena, xnbp->xnb_tx_ring_addr, PAGESIZE); - xnbp->xnb_tx_ring_addr = NULL; - } -} - -static void -xnb_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, - void *arg, void *impl_data) -{ - _NOTE(ARGUNUSED(id, arg)); - xnb_t *xnbp = ddi_get_driver_private(dip); - XenbusState new_state = *(XenbusState *)impl_data; - - ASSERT(xnbp != NULL); - - switch (new_state) { - case XenbusStateConnected: - /* spurious state change */ - if (xnbp->xnb_connected) - return; - - if (!xnb_read_oe_config(xnbp) || - !xnbp->xnb_flavour->xf_peer_connected(xnbp)) { - cmn_err(CE_WARN, "xnb_oe_state_change: " - "read otherend config error"); - (void) xvdi_switch_state(dip, XBT_NULL, - XenbusStateClosed); - (void) xvdi_post_event(dip, XEN_HP_REMOVE); - - break; - } - - - mutex_enter(&xnbp->xnb_state_lock); - xnbp->xnb_fe_status = XNB_STATE_READY; - if (xnbp->xnb_be_status == XNB_STATE_READY) - xnb_start_connect(xnbp); - mutex_exit(&xnbp->xnb_state_lock); - - /* - * Now that we've attempted to connect it's reasonable - * to allow an attempt to detach. - */ - xnbp->xnb_detachable = B_TRUE; - - break; - - case XenbusStateClosing: - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing); - - break; - - case XenbusStateClosed: - xnbp->xnb_flavour->xf_peer_disconnected(xnbp); - - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - xnb_disconnect_rings(dip); - xnbp->xnb_connected = B_FALSE; - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosed); - (void) xvdi_post_event(dip, XEN_HP_REMOVE); - /* - * In all likelyhood this is already set (in the above - * case), but if the peer never attempted to connect - * and the domain is destroyed we get here without - * having been through the case above, so we set it to - * be sure. - */ - xnbp->xnb_detachable = B_TRUE; - - break; - - default: - break; - } -} - -static void -xnb_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, - void *arg, void *impl_data) -{ - _NOTE(ARGUNUSED(id, arg)); - xnb_t *xnbp = ddi_get_driver_private(dip); - xendev_hotplug_state_t state = *(xendev_hotplug_state_t *)impl_data; - - ASSERT(xnbp != NULL); - - switch (state) { - case Connected: - /* spurious hotplug event */ - if (xnbp->xnb_hotplugged) - break; - - if (!xnb_read_xs_config(xnbp)) - break; - - if (!xnbp->xnb_flavour->xf_hotplug_connected(xnbp)) - break; - - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - xnbp->xnb_hotplugged = B_TRUE; - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - mutex_enter(&xnbp->xnb_state_lock); - xnbp->xnb_be_status = XNB_STATE_READY; - if (xnbp->xnb_fe_status == XNB_STATE_READY) - xnb_start_connect(xnbp); - mutex_exit(&xnbp->xnb_state_lock); - - break; - - default: - break; - } -} - -static struct modldrv modldrv = { - &mod_miscops, "xnb", -}; - -static struct modlinkage modlinkage = { - MODREV_1, &modldrv, NULL -}; - -int -_init(void) -{ - int i; - - mutex_init(&xnb_alloc_page_lock, NULL, MUTEX_DRIVER, NULL); - - i = mod_install(&modlinkage); - if (i != DDI_SUCCESS) - mutex_destroy(&xnb_alloc_page_lock); - - return (i); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -int -_fini(void) -{ - int i; - - i = mod_remove(&modlinkage); - if (i == DDI_SUCCESS) - mutex_destroy(&xnb_alloc_page_lock); - - return (i); -} diff --git a/usr/src/uts/common/xen/io/xnb.h b/usr/src/uts/common/xen/io/xnb.h deleted file mode 100644 index f9704b78af..0000000000 --- a/usr/src/uts/common/xen/io/xnb.h +++ /dev/null @@ -1,216 +0,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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - * xnb.h - definitions for Xen dom0 network driver - */ - -#ifndef _SYS_XNB_H -#define _SYS_XNB_H - -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NET_TX_RING_SIZE __CONST_RING_SIZE(netif_tx, PAGESIZE) -#define NET_RX_RING_SIZE __CONST_RING_SIZE(netif_rx, PAGESIZE) - -#define XNBMAXPKT 1500 /* MTU size */ - -/* DEBUG flags */ -#define XNBDDI 0x01 -#define XNBTRACE 0x02 -#define XNBSEND 0x04 -#define XNBRECV 0x08 -#define XNBINTR 0x10 -#define XNBRING 0x20 -#define XNBCKSUM 0x40 - -#define XNB_STATE_INIT 0x01 -#define XNB_STATE_READY 0x02 - -typedef struct xnb xnb_t; - -/* - * The xnb module provides core inter-domain network protocol functionality. - * It is connected to the rest of Solaris in two ways: - * - as a GLDv3 driver (with xnbu), - * - as a GLDv3 consumer (with xnbo). - * - * The different modes of operation are termed "flavours" and each - * instance of an xnb based driver operates in one and only one mode. - * The common xnb driver exports a set of functions to these drivers - * (declarations at the foot of this file) and calls back into the - * drivers via the xnb_flavour_t structure. - */ -typedef struct xnb_flavour { - void (*xf_from_peer)(xnb_t *, mblk_t *); - boolean_t (*xf_peer_connected)(xnb_t *); - void (*xf_peer_disconnected)(xnb_t *); - boolean_t (*xf_hotplug_connected)(xnb_t *); - boolean_t (*xf_start_connect)(xnb_t *); - mblk_t *(*xf_cksum_from_peer)(xnb_t *, mblk_t *, uint16_t); - uint16_t (*xf_cksum_to_peer)(xnb_t *, mblk_t *); - boolean_t (*xf_mcast_add)(xnb_t *, ether_addr_t *); - boolean_t (*xf_mcast_del)(xnb_t *, ether_addr_t *); -} xnb_flavour_t; - -typedef struct xnb_txbuf { - frtn_t xt_free_rtn; - xnb_t *xt_xnbp; - struct xnb_txbuf *xt_next; - RING_IDX xt_id; - RING_IDX xt_idx; - uint16_t xt_status; - - ddi_dma_handle_t xt_dma_handle; - ddi_acc_handle_t xt_acc_handle; - caddr_t xt_buf; - size_t xt_buflen; - mfn_t xt_mfn; - - mblk_t *xt_mblk; - - unsigned int xt_flags; - -#define XNB_TXBUF_INUSE 0x01 - -} xnb_txbuf_t; - -/* Per network-interface-controller driver private structure */ -struct xnb { - /* most interesting stuff first to assist debugging */ - dev_info_t *xnb_devinfo; /* System per-device info. */ - - xnb_flavour_t *xnb_flavour; - void *xnb_flavour_data; - - boolean_t xnb_irq; - unsigned char xnb_mac_addr[ETHERADDRL]; - - uint64_t xnb_stat_ipackets; - uint64_t xnb_stat_opackets; - uint64_t xnb_stat_rbytes; - uint64_t xnb_stat_obytes; - - uint64_t xnb_stat_intr; - uint64_t xnb_stat_rx_defer; - - uint64_t xnb_stat_rx_cksum_deferred; - uint64_t xnb_stat_tx_cksum_no_need; - - uint64_t xnb_stat_rx_rsp_notok; - - uint64_t xnb_stat_tx_notify_sent; - uint64_t xnb_stat_tx_notify_deferred; - - uint64_t xnb_stat_rx_notify_sent; - uint64_t xnb_stat_rx_notify_deferred; - - uint64_t xnb_stat_tx_too_early; - uint64_t xnb_stat_rx_too_early; - uint64_t xnb_stat_rx_allocb_failed; - uint64_t xnb_stat_tx_allocb_failed; - uint64_t xnb_stat_rx_foreign_page; - uint64_t xnb_stat_tx_overflow_page; - uint64_t xnb_stat_tx_unexpected_flags; - uint64_t xnb_stat_mac_full; - uint64_t xnb_stat_spurious_intr; - uint64_t xnb_stat_allocation_success; - uint64_t xnb_stat_allocation_failure; - uint64_t xnb_stat_small_allocation_success; - uint64_t xnb_stat_small_allocation_failure; - uint64_t xnb_stat_other_allocation_failure; - - uint64_t xnb_stat_rx_pagebndry_crossed; - uint64_t xnb_stat_rx_cpoparea_grown; - - uint64_t xnb_stat_csum_hardware; - uint64_t xnb_stat_csum_software; - - kstat_t *xnb_kstat_aux; - - ddi_iblock_cookie_t xnb_icookie; - - kmutex_t xnb_rx_lock; - kmutex_t xnb_tx_lock; - kmutex_t xnb_state_lock; - - int xnb_be_status; - int xnb_fe_status; - - kmem_cache_t *xnb_tx_buf_cache; - uint32_t xnb_tx_buf_count; - int xnb_tx_buf_outstanding; - - netif_rx_back_ring_t xnb_rx_ring; /* rx interface struct ptr */ - void *xnb_rx_ring_addr; - grant_ref_t xnb_rx_ring_ref; - grant_handle_t xnb_rx_ring_handle; - - netif_tx_back_ring_t xnb_tx_ring; /* tx interface struct ptr */ - void *xnb_tx_ring_addr; - grant_ref_t xnb_tx_ring_ref; - grant_handle_t xnb_tx_ring_handle; - - boolean_t xnb_connected; - boolean_t xnb_hotplugged; - boolean_t xnb_detachable; - int xnb_evtchn; /* channel to front end */ - evtchn_port_t xnb_fe_evtchn; - domid_t xnb_peer; - - xnb_txbuf_t *xnb_tx_bufp[NET_TX_RING_SIZE]; - gnttab_copy_t xnb_tx_cop[NET_TX_RING_SIZE]; - - caddr_t xnb_rx_va; - gnttab_transfer_t xnb_rx_top[NET_RX_RING_SIZE]; - - boolean_t xnb_rx_hv_copy; - boolean_t xnb_multicast_control; - boolean_t xnb_no_csum_offload; - - gnttab_copy_t *xnb_rx_cpop; -#define CPOP_DEFCNT 8 - size_t xnb_rx_cpop_count; /* in elements */ -}; - -extern int xnb_attach(dev_info_t *, xnb_flavour_t *, void *); -extern void xnb_detach(dev_info_t *); -extern mblk_t *xnb_copy_to_peer(xnb_t *, mblk_t *); -extern mblk_t *xnb_process_cksum_flags(xnb_t *, mblk_t *, uint32_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XNB_H */ diff --git a/usr/src/uts/common/xen/io/xnbe.c b/usr/src/uts/common/xen/io/xnbe.c deleted file mode 100644 index f584d5b982..0000000000 --- a/usr/src/uts/common/xen/io/xnbe.c +++ /dev/null @@ -1,163 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -/* - * Xen network backend - ioemu version. - * - * HVM guest domains use an emulated network device (typically the - * rtl8139) to access the physical network via IO emulation running in - * a backend domain (generally domain 0). - * - * The IO emulation code sends and receives packets using DLPI, usually - * through a virtual NIC (vnic). - * - * The creation of the relevant vnic to correspond to the network interface - * in the guest domain requires the use of 'hotplug' scripts in the backend - * domain. This driver ensures that the hotplug scripts are run when - * such guest domains are created. - * - * It is used as a result of the 'compatible' property associated with - * IO emulated devices. See /etc/driver_aliases and common/xen/os/xvdi.c. - */ - -#ifdef DEBUG -#define XNBE_DEBUG 1 -#endif /* DEBUG */ - -#include -#include -#include -#include -#include -#ifdef XNBE_DEBUG -#include -#endif /* XNBE_DEBUG */ - -#ifdef XNBE_DEBUG -int xnbe_debug = 0; -#endif /* XNBE_DEBUG */ - -static int -xnbe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ -#ifdef XNBE_DEBUG - if (xnbe_debug > 0) - cmn_err(CE_NOTE, "xnbe_attach: dip 0x%p, cmd %d", - (void *)dip, cmd); -#endif /* XNBE_DEBUG */ - - switch (cmd) { - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - (void) xvdi_post_event(dip, XEN_HP_ADD); - - return (DDI_SUCCESS); -} - -static int -xnbe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ -#ifdef XNBE_DEBUG - if (xnbe_debug > 0) - cmn_err(CE_NOTE, "detach: dip 0x%p, cmd %d", - (void *)dip, cmd); -#endif /* XNBE_DEBUG */ - - switch (cmd) { - case DDI_DETACH: - return (DDI_SUCCESS); - case DDI_SUSPEND: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } -} - -static struct cb_ops cb_ops = { - nulldev, /* open */ - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* cb_prop_op */ - 0, /* streamtab */ - D_NEW | D_MP | D_64BIT /* Driver compatibility flag */ -}; - -static struct dev_ops ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - nulldev, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xnbe_attach, /* devo_attach */ - xnbe_detach, /* devo_detach */ - nodev, /* devo_reset */ - &cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, "xnbe driver", &ops, -}; - -static struct modlinkage modlinkage = { - MODREV_1, &modldrv, NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} diff --git a/usr/src/uts/common/xen/io/xnbo.c b/usr/src/uts/common/xen/io/xnbo.c deleted file mode 100644 index 55234a4c7f..0000000000 --- a/usr/src/uts/common/xen/io/xnbo.c +++ /dev/null @@ -1,742 +0,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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Xen network backend - mac client edition. - * - * A driver that sits above an existing GLDv3/Nemo MAC driver and - * relays packets to/from that driver from/to a guest domain. - */ - -#ifdef DEBUG -#define XNBO_DEBUG 1 -#endif /* DEBUG */ - -#include "xnb.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef XNBO_DEBUG -boolean_t xnbo_cksum_offload_to_peer = B_TRUE; -boolean_t xnbo_cksum_offload_from_peer = B_TRUE; -#endif /* XNBO_DEBUG */ - -/* Track multicast addresses. */ -typedef struct xmca { - struct xmca *next; - ether_addr_t addr; -} xmca_t; - -/* State about this device instance. */ -typedef struct xnbo { - mac_handle_t o_mh; - mac_client_handle_t o_mch; - mac_unicast_handle_t o_mah; - mac_promisc_handle_t o_mphp; - boolean_t o_running; - boolean_t o_promiscuous; - uint32_t o_hcksum_capab; - xmca_t *o_mca; - char o_link_name[LIFNAMSIZ]; - boolean_t o_need_rx_filter; - boolean_t o_need_setphysaddr; - boolean_t o_multicast_control; -} xnbo_t; - -static void xnbo_close_mac(xnb_t *); -static void i_xnbo_close_mac(xnb_t *, boolean_t); - -/* - * Packets from the peer come here. We pass them to the mac device. - */ -static void -xnbo_to_mac(xnb_t *xnbp, mblk_t *mp) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - - ASSERT(mp != NULL); - - if (!xnbop->o_running) { - xnbp->xnb_stat_tx_too_early++; - goto fail; - } - - if (mac_tx(xnbop->o_mch, mp, 0, - MAC_DROP_ON_NO_DESC, NULL) != 0) { - xnbp->xnb_stat_mac_full++; - } - - return; - -fail: - freemsgchain(mp); -} - -/* - * Process the checksum flags `flags' provided by the peer for the - * packet `mp'. - */ -static mblk_t * -xnbo_cksum_from_peer(xnb_t *xnbp, mblk_t *mp, uint16_t flags) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - - ASSERT(mp->b_next == NULL); - - if ((flags & NETTXF_csum_blank) != 0) { - uint32_t capab = xnbop->o_hcksum_capab; - -#ifdef XNBO_DEBUG - if (!xnbo_cksum_offload_from_peer) - capab = 0; -#endif /* XNBO_DEBUG */ - - /* - * The checksum in the packet is blank. Determine - * whether we can do hardware offload and, if so, - * update the flags on the mblk according. If not, - * calculate and insert the checksum using software. - */ - mp = xnb_process_cksum_flags(xnbp, mp, capab); - } - - return (mp); -} - -/* - * Calculate the checksum flags to be relayed to the peer for the - * packet `mp'. - */ -static uint16_t -xnbo_cksum_to_peer(xnb_t *xnbp, mblk_t *mp) -{ - _NOTE(ARGUNUSED(xnbp)); - uint16_t r = 0; - uint32_t pflags, csum; - -#ifdef XNBO_DEBUG - if (!xnbo_cksum_offload_to_peer) - return (0); -#endif /* XNBO_DEBUG */ - - /* - * We might also check for HCK_PARTIALCKSUM here and, - * providing that the partial checksum covers the TCP/UDP - * payload, return NETRXF_data_validated. - * - * It seems that it's probably not worthwhile, as even MAC - * devices which advertise HCKSUM_INET_PARTIAL in their - * capabilities tend to use HCK_FULLCKSUM on the receive side - * - they are actually saying that in the output path the - * caller must use HCK_PARTIALCKSUM. - * - * Then again, if a NIC supports HCK_PARTIALCKSUM in its' - * output path, the host IP stack will use it. If such packets - * are destined for the peer (i.e. looped around) we would - * gain some advantage. - */ - - mac_hcksum_get(mp, NULL, NULL, NULL, &csum, &pflags); - - /* - * If the MAC driver has asserted that the checksum is - * good, let the peer know. - */ - if (((pflags & HCK_FULLCKSUM) != 0) && - (((pflags & HCK_FULLCKSUM_OK) != 0) || - (csum == 0xffff))) - r |= NETRXF_data_validated; - - return (r); -} - -/* - * Packets from the mac device come here. We pass them to the peer. - */ -/*ARGSUSED*/ -static void -xnbo_from_mac(void *arg, mac_resource_handle_t mrh, mblk_t *mp, - boolean_t loopback) -{ - xnb_t *xnbp = arg; - - mp = xnb_copy_to_peer(xnbp, mp); - - if (mp != NULL) - freemsgchain(mp); -} - -/* - * Packets from the mac device come here. We pass them to the peer if - * the destination mac address matches or it's a multicast/broadcast - * address. - */ -static void -xnbo_from_mac_filter(void *arg, mac_resource_handle_t mrh, mblk_t *mp, - boolean_t loopback) -{ - _NOTE(ARGUNUSED(loopback)); - xnb_t *xnbp = arg; - xnbo_t *xnbop = xnbp->xnb_flavour_data; - mblk_t *next, *keep, *keep_head, *free, *free_head; - - keep = keep_head = free = free_head = NULL; - -#define ADD(list, bp) \ - if (list != NULL) \ - list->b_next = bp; \ - else \ - list##_head = bp; \ - list = bp; - - for (; mp != NULL; mp = next) { - mac_header_info_t hdr_info; - - next = mp->b_next; - mp->b_next = NULL; - - if (mac_header_info(xnbop->o_mh, mp, &hdr_info) != 0) { - ADD(free, mp); - continue; - } - - if ((hdr_info.mhi_dsttype == MAC_ADDRTYPE_BROADCAST) || - (hdr_info.mhi_dsttype == MAC_ADDRTYPE_MULTICAST)) { - ADD(keep, mp); - continue; - } - - if (bcmp(hdr_info.mhi_daddr, xnbp->xnb_mac_addr, - sizeof (xnbp->xnb_mac_addr)) == 0) { - ADD(keep, mp); - continue; - } - - ADD(free, mp); - } -#undef ADD - - if (keep_head != NULL) - xnbo_from_mac(xnbp, mrh, keep_head, B_FALSE); - - if (free_head != NULL) - freemsgchain(free_head); -} - -static boolean_t -xnbo_open_mac(xnb_t *xnbp, char *mac) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - int err; - const mac_info_t *mi; - void (*rx_fn)(void *, mac_resource_handle_t, mblk_t *, boolean_t); - struct ether_addr ea; - uint_t max_sdu; - mac_diag_t diag; - - if ((err = mac_open_by_linkname(mac, &xnbop->o_mh)) != 0) { - cmn_err(CE_WARN, "xnbo_open_mac: " - "cannot open mac for link %s (%d)", mac, err); - return (B_FALSE); - } - ASSERT(xnbop->o_mh != NULL); - - mi = mac_info(xnbop->o_mh); - ASSERT(mi != NULL); - - if (mi->mi_media != DL_ETHER) { - cmn_err(CE_WARN, "xnbo_open_mac: " - "device is not DL_ETHER (%d)", mi->mi_media); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - if (mi->mi_media != mi->mi_nativemedia) { - cmn_err(CE_WARN, "xnbo_open_mac: " - "device media and native media mismatch (%d != %d)", - mi->mi_media, mi->mi_nativemedia); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - - mac_sdu_get(xnbop->o_mh, NULL, &max_sdu); - if (max_sdu > XNBMAXPKT) { - cmn_err(CE_WARN, "xnbo_open_mac: mac device SDU too big (%d)", - max_sdu); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - - /* - * MAC_OPEN_FLAGS_MULTI_PRIMARY is relevant when we are migrating a - * guest on the localhost itself. In this case we would have the MAC - * client open for the guest being migrated *and* also for the - * migrated guest (i.e. the former will be active till the migration - * is complete when the latter will be activated). This flag states - * that it is OK for mac_unicast_add to add the primary MAC unicast - * address multiple times. - */ - if (mac_client_open(xnbop->o_mh, &xnbop->o_mch, NULL, - MAC_OPEN_FLAGS_USE_DATALINK_NAME | - MAC_OPEN_FLAGS_MULTI_PRIMARY) != 0) { - cmn_err(CE_WARN, "xnbo_open_mac: " - "error (%d) opening mac client", err); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - - if (xnbop->o_need_rx_filter) - rx_fn = xnbo_from_mac_filter; - else - rx_fn = xnbo_from_mac; - - err = mac_unicast_add_set_rx(xnbop->o_mch, NULL, MAC_UNICAST_PRIMARY, - &xnbop->o_mah, 0, &diag, xnbop->o_multicast_control ? rx_fn : NULL, - xnbp); - if (err != 0) { - cmn_err(CE_WARN, "xnbo_open_mac: failed to get the primary " - "MAC address of %s: %d", mac, err); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - if (!xnbop->o_multicast_control) { - err = mac_promisc_add(xnbop->o_mch, MAC_CLIENT_PROMISC_ALL, - rx_fn, xnbp, &xnbop->o_mphp, MAC_PROMISC_FLAGS_NO_TX_LOOP | - MAC_PROMISC_FLAGS_VLAN_TAG_STRIP); - if (err != 0) { - cmn_err(CE_WARN, "xnbo_open_mac: " - "cannot enable promiscuous mode of %s: %d", - mac, err); - i_xnbo_close_mac(xnbp, B_TRUE); - return (B_FALSE); - } - xnbop->o_promiscuous = B_TRUE; - } - - if (xnbop->o_need_setphysaddr) { - err = mac_unicast_primary_set(xnbop->o_mh, xnbp->xnb_mac_addr); - /* Warn, but continue on. */ - if (err != 0) { - bcopy(xnbp->xnb_mac_addr, ea.ether_addr_octet, - ETHERADDRL); - cmn_err(CE_WARN, "xnbo_open_mac: " - "cannot set MAC address of %s to " - "%s: %d", mac, ether_sprintf(&ea), err); - } - } - - if (!mac_capab_get(xnbop->o_mh, MAC_CAPAB_HCKSUM, - &xnbop->o_hcksum_capab)) - xnbop->o_hcksum_capab = 0; - - xnbop->o_running = B_TRUE; - - return (B_TRUE); -} - -static void -xnbo_close_mac(xnb_t *xnbp) -{ - i_xnbo_close_mac(xnbp, B_FALSE); -} - -static void -i_xnbo_close_mac(xnb_t *xnbp, boolean_t locked) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - xmca_t *loop; - - ASSERT(!locked || MUTEX_HELD(&xnbp->xnb_state_lock)); - - if (xnbop->o_mh == NULL) - return; - - if (xnbop->o_running) - xnbop->o_running = B_FALSE; - - if (!locked) - mutex_enter(&xnbp->xnb_state_lock); - loop = xnbop->o_mca; - xnbop->o_mca = NULL; - if (!locked) - mutex_exit(&xnbp->xnb_state_lock); - - while (loop != NULL) { - xmca_t *next = loop->next; - - DTRACE_PROBE3(mcast_remove, - (char *), "close", - (void *), xnbp, - (etheraddr_t *), loop->addr); - (void) mac_multicast_remove(xnbop->o_mch, loop->addr); - kmem_free(loop, sizeof (*loop)); - loop = next; - } - - if (xnbop->o_promiscuous) { - if (xnbop->o_mphp != NULL) { - mac_promisc_remove(xnbop->o_mphp); - xnbop->o_mphp = NULL; - } - xnbop->o_promiscuous = B_FALSE; - } else { - if (xnbop->o_mch != NULL) - mac_rx_clear(xnbop->o_mch); - } - - if (xnbop->o_mah != NULL) { - (void) mac_unicast_remove(xnbop->o_mch, xnbop->o_mah); - xnbop->o_mah = NULL; - } - - if (xnbop->o_mch != NULL) { - mac_client_close(xnbop->o_mch, 0); - xnbop->o_mch = NULL; - } - - mac_close(xnbop->o_mh); - xnbop->o_mh = NULL; -} - -/* - * Hotplug has completed and we are connected to the peer. We have all - * the information we need to exchange traffic, so open the MAC device - * and configure it appropriately. - */ -static boolean_t -xnbo_start_connect(xnb_t *xnbp) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - - return (xnbo_open_mac(xnbp, xnbop->o_link_name)); -} - -/* - * The guest has successfully synchronize with this instance. We read - * the configuration of the guest from xenstore to check whether the - * guest requests multicast control. If not (the default) we make a - * note that the MAC device needs to be used in promiscious mode. - */ -static boolean_t -xnbo_peer_connected(xnb_t *xnbp) -{ - char *oename; - int request; - xnbo_t *xnbop = xnbp->xnb_flavour_data; - - oename = xvdi_get_oename(xnbp->xnb_devinfo); - - if (xenbus_scanf(XBT_NULL, oename, - "request-multicast-control", "%d", &request) != 0) - request = 0; - xnbop->o_multicast_control = (request > 0); - - return (B_TRUE); -} - -/* - * The guest domain has closed down the inter-domain connection. We - * close the underlying MAC device. - */ -static void -xnbo_peer_disconnected(xnb_t *xnbp) -{ - xnbo_close_mac(xnbp); -} - -/* - * The hotplug script has completed. We read information from xenstore - * about our configuration, most notably the name of the MAC device we - * should use. - */ -static boolean_t -xnbo_hotplug_connected(xnb_t *xnbp) -{ - char *xsname; - xnbo_t *xnbop = xnbp->xnb_flavour_data; - int need; - - xsname = xvdi_get_xsname(xnbp->xnb_devinfo); - - if (xenbus_scanf(XBT_NULL, xsname, - "nic", "%s", xnbop->o_link_name) != 0) { - cmn_err(CE_WARN, "xnbo_connect: " - "cannot read nic name from %s", xsname); - return (B_FALSE); - } - - if (xenbus_scanf(XBT_NULL, xsname, - "SUNW-need-rx-filter", "%d", &need) != 0) - need = 0; - xnbop->o_need_rx_filter = (need > 0); - - if (xenbus_scanf(XBT_NULL, xsname, - "SUNW-need-set-physaddr", "%d", &need) != 0) - need = 0; - xnbop->o_need_setphysaddr = (need > 0); - - return (B_TRUE); -} - -/* - * Find the multicast address `addr', return B_TRUE if it is one that - * we receive. If `remove', remove it from the set received. - */ -static boolean_t -xnbo_mcast_find(xnb_t *xnbp, ether_addr_t *addr, boolean_t remove) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - xmca_t *prev, *del, *this; - - ASSERT(MUTEX_HELD(&xnbp->xnb_state_lock)); - ASSERT(xnbop->o_promiscuous == B_FALSE); - - prev = del = NULL; - - this = xnbop->o_mca; - - while (this != NULL) { - if (bcmp(&this->addr, addr, sizeof (this->addr)) == 0) { - del = this; - if (remove) { - if (prev == NULL) - xnbop->o_mca = this->next; - else - prev->next = this->next; - } - break; - } - - prev = this; - this = this->next; - } - - if (del == NULL) - return (B_FALSE); - - if (remove) { - DTRACE_PROBE3(mcast_remove, - (char *), "remove", - (void *), xnbp, - (etheraddr_t *), del->addr); - mac_multicast_remove(xnbop->o_mch, del->addr); - kmem_free(del, sizeof (*del)); - } - - return (B_TRUE); -} - -/* - * Add the multicast address `addr' to the set received. - */ -static boolean_t -xnbo_mcast_add(xnb_t *xnbp, ether_addr_t *addr) -{ - xnbo_t *xnbop = xnbp->xnb_flavour_data; - boolean_t r = B_FALSE; - - ASSERT(xnbop->o_promiscuous == B_FALSE); - - mutex_enter(&xnbp->xnb_state_lock); - - if (xnbo_mcast_find(xnbp, addr, B_FALSE)) { - r = B_TRUE; - } else if (mac_multicast_add(xnbop->o_mch, - (const uint8_t *)addr) == 0) { - xmca_t *mca; - - DTRACE_PROBE3(mcast_add, - (char *), "add", - (void *), xnbp, - (etheraddr_t *), addr); - - mca = kmem_alloc(sizeof (*mca), KM_SLEEP); - bcopy(addr, &mca->addr, sizeof (mca->addr)); - - mca->next = xnbop->o_mca; - xnbop->o_mca = mca; - - r = B_TRUE; - } - - mutex_exit(&xnbp->xnb_state_lock); - - return (r); -} - -/* - * Remove the multicast address `addr' from the set received. - */ -static boolean_t -xnbo_mcast_del(xnb_t *xnbp, ether_addr_t *addr) -{ - boolean_t r; - - mutex_enter(&xnbp->xnb_state_lock); - r = xnbo_mcast_find(xnbp, addr, B_TRUE); - mutex_exit(&xnbp->xnb_state_lock); - - return (r); -} - -static int -xnbo_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - static xnb_flavour_t flavour = { - xnbo_to_mac, xnbo_peer_connected, xnbo_peer_disconnected, - xnbo_hotplug_connected, xnbo_start_connect, - xnbo_cksum_from_peer, xnbo_cksum_to_peer, - xnbo_mcast_add, xnbo_mcast_del, - }; - xnbo_t *xnbop; - - switch (cmd) { - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - xnbop = kmem_zalloc(sizeof (*xnbop), KM_SLEEP); - - if (xnb_attach(dip, &flavour, xnbop) != DDI_SUCCESS) { - kmem_free(xnbop, sizeof (*xnbop)); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static int -xnbo_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - xnb_t *xnbp = ddi_get_driver_private(dip); - xnbo_t *xnbop = xnbp->xnb_flavour_data; - - switch (cmd) { - case DDI_DETACH: - break; - case DDI_SUSPEND: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - if (!xnbp->xnb_detachable || xnbp->xnb_connected || - (xnbp->xnb_tx_buf_count > 0)) { - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - return (DDI_FAILURE); - } - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - xnbo_close_mac(xnbp); - kmem_free(xnbop, sizeof (*xnbop)); - - xnb_detach(dip); - - return (DDI_SUCCESS); -} - -static struct cb_ops cb_ops = { - nulldev, /* open */ - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* cb_prop_op */ - 0, /* streamtab */ - D_NEW | D_MP | D_64BIT /* Driver compatibility flag */ -}; - -static struct dev_ops ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - nulldev, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xnbo_attach, /* devo_attach */ - xnbo_detach, /* devo_detach */ - nodev, /* devo_reset */ - &cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL, /* devo_power */ - ddi_quiesce_not_needed, /* devo_quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, "xnbo driver", &ops, -}; - -static struct modlinkage modlinkage = { - MODREV_1, &modldrv, NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} diff --git a/usr/src/uts/common/xen/io/xnbu.c b/usr/src/uts/common/xen/io/xnbu.c deleted file mode 100644 index c41a584e8b..0000000000 --- a/usr/src/uts/common/xen/io/xnbu.c +++ /dev/null @@ -1,533 +0,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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Xen inter-domain backend - GLDv3 driver edition. - * - * A traditional GLDv3 driver used to communicate with a guest - * domain. This driver is typically plumbed underneath the IP stack - * or a software ethernet bridge. - */ - -#include "xnb.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Required driver entry points for GLDv3 */ -static int xnbu_m_start(void *); -static void xnbu_m_stop(void *); -static int xnbu_m_set_mac_addr(void *, const uint8_t *); -static int xnbu_m_set_multicast(void *, boolean_t, const uint8_t *); -static int xnbu_m_set_promiscuous(void *, boolean_t); -static int xnbu_m_stat(void *, uint_t, uint64_t *); -static boolean_t xnbu_m_getcapab(void *, mac_capab_t, void *); -static mblk_t *xnbu_m_send(void *, mblk_t *); - -typedef struct xnbu { - mac_handle_t u_mh; - boolean_t u_need_sched; -} xnbu_t; - -static mac_callbacks_t xnbu_callbacks = { - MC_GETCAPAB, - xnbu_m_stat, - xnbu_m_start, - xnbu_m_stop, - xnbu_m_set_promiscuous, - xnbu_m_set_multicast, - xnbu_m_set_mac_addr, - xnbu_m_send, - NULL, - NULL, - xnbu_m_getcapab -}; - -static void -xnbu_to_host(xnb_t *xnbp, mblk_t *mp) -{ - xnbu_t *xnbup = xnbp->xnb_flavour_data; - boolean_t sched = B_FALSE; - - ASSERT(mp != NULL); - - mac_rx(xnbup->u_mh, NULL, mp); - - mutex_enter(&xnbp->xnb_rx_lock); - - /* - * If a transmit attempt failed because we ran out of ring - * space and there is now some space, re-enable the transmit - * path. - */ - if (xnbup->u_need_sched && - RING_HAS_UNCONSUMED_REQUESTS(&xnbp->xnb_rx_ring)) { - sched = B_TRUE; - xnbup->u_need_sched = B_FALSE; - } - - mutex_exit(&xnbp->xnb_rx_lock); - - if (sched) - mac_tx_update(xnbup->u_mh); -} - -static mblk_t * -xnbu_cksum_from_peer(xnb_t *xnbp, mblk_t *mp, uint16_t flags) -{ - /* - * Take a conservative approach - if the checksum is blank - * then we fill it in. - * - * If the consumer of the packet is IP then we might actually - * only need fill it in if the data is not validated, but how - * do we know who might end up with the packet? - */ - - if ((flags & NETTXF_csum_blank) != 0) { - /* - * The checksum is blank. We must fill it in here. - */ - mp = xnb_process_cksum_flags(xnbp, mp, 0); - - /* - * Because we calculated the checksum ourselves we - * know that it must be good, so we assert this. - */ - flags |= NETTXF_data_validated; - } - - if ((flags & NETTXF_data_validated) != 0) { - /* - * The checksum is asserted valid. - */ - mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM_OK); - } - - return (mp); -} - -static uint16_t -xnbu_cksum_to_peer(xnb_t *xnbp, mblk_t *mp) -{ - _NOTE(ARGUNUSED(xnbp)); - uint16_t r = 0; - uint32_t pflags; - - mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &pflags); - - /* - * If the protocol stack has requested checksum - * offload, inform the peer that we have not - * calculated the checksum. - */ - if ((pflags & HCK_FULLCKSUM) != 0) - r |= NETRXF_csum_blank; - - return (r); -} - -static boolean_t -xnbu_start_connect(xnb_t *xnbp) -{ - xnbu_t *xnbup = xnbp->xnb_flavour_data; - - mac_link_update(xnbup->u_mh, LINK_STATE_UP); - /* - * We are able to send packets now - bring them on. - */ - mac_tx_update(xnbup->u_mh); - - return (B_TRUE); -} - -static boolean_t -xnbu_peer_connected(xnb_t *xnbp) -{ - _NOTE(ARGUNUSED(xnbp)); - - return (B_TRUE); -} - -static void -xnbu_peer_disconnected(xnb_t *xnbp) -{ - xnbu_t *xnbup = xnbp->xnb_flavour_data; - - mac_link_update(xnbup->u_mh, LINK_STATE_DOWN); -} - -/*ARGSUSED*/ -static boolean_t -xnbu_hotplug_connected(xnb_t *xnbp) -{ - return (B_TRUE); -} - -static mblk_t * -xnbu_m_send(void *arg, mblk_t *mp) -{ - xnb_t *xnbp = arg; - xnbu_t *xnbup = xnbp->xnb_flavour_data; - boolean_t sched = B_FALSE; - - mp = xnb_copy_to_peer(arg, mp); - - mutex_enter(&xnbp->xnb_rx_lock); - /* - * If we consumed all of the mblk_t's offered, perhaps we need - * to indicate that we can accept more. Otherwise we are full - * and need to wait for space. - */ - if (mp == NULL) { - sched = xnbup->u_need_sched; - xnbup->u_need_sched = B_FALSE; - } else { - xnbup->u_need_sched = B_TRUE; - } - mutex_exit(&xnbp->xnb_rx_lock); - - /* - * If a previous transmit attempt failed because the ring - * was full, try again now. - */ - if (sched) - mac_tx_update(xnbup->u_mh); - - return (mp); -} - -/* - * xnbu_m_set_mac_addr() -- set the physical network address on the board - */ -/* ARGSUSED */ -static int -xnbu_m_set_mac_addr(void *arg, const uint8_t *macaddr) -{ - xnb_t *xnbp = arg; - xnbu_t *xnbup = xnbp->xnb_flavour_data; - - bcopy(macaddr, xnbp->xnb_mac_addr, ETHERADDRL); - mac_unicst_update(xnbup->u_mh, xnbp->xnb_mac_addr); - - return (0); -} - -/* - * xnbu_m_set_multicast() -- set (enable) or disable a multicast address - */ -/*ARGSUSED*/ -static int -xnbu_m_set_multicast(void *arg, boolean_t add, const uint8_t *mca) -{ - /* - * We always accept all packets from the peer, so nothing to - * do for enable or disable. - */ - return (0); -} - - -/* - * xnbu_m_set_promiscuous() -- set or reset promiscuous mode on the board - */ -/* ARGSUSED */ -static int -xnbu_m_set_promiscuous(void *arg, boolean_t on) -{ - /* - * We always accept all packets from the peer, so nothing to - * do for enable or disable. - */ - return (0); -} - -/* - * xnbu_m_start() -- start the board receiving and enable interrupts. - */ -/*ARGSUSED*/ -static int -xnbu_m_start(void *arg) -{ - return (0); -} - -/* - * xnbu_m_stop() - disable hardware - */ -/*ARGSUSED*/ -static void -xnbu_m_stop(void *arg) -{ -} - -static int -xnbu_m_stat(void *arg, uint_t stat, uint64_t *val) -{ - xnb_t *xnbp = arg; - - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - -#define map_stat(q, r) \ - case (MAC_STAT_##q): \ - *val = xnbp->xnb_stat_##r; \ - break - - switch (stat) { - - map_stat(IPACKETS, opackets); - map_stat(OPACKETS, ipackets); - map_stat(RBYTES, obytes); - map_stat(OBYTES, rbytes); - - default: - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - return (ENOTSUP); - } - -#undef map_stat - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - return (0); -} - -static boolean_t -xnbu_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) -{ - _NOTE(ARGUNUSED(arg)); - - switch (cap) { - case MAC_CAPAB_HCKSUM: { - uint32_t *capab = cap_data; - - *capab = HCKSUM_INET_PARTIAL; - break; - } - default: - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * All packets are passed to the peer, so adding and removing - * multicast addresses is meaningless. - */ -static boolean_t -xnbu_mcast_add(xnb_t *xnbp, ether_addr_t *addr) -{ - _NOTE(ARGUNUSED(xnbp, addr)); - - return (B_TRUE); -} - -static boolean_t -xnbu_mcast_del(xnb_t *xnbp, ether_addr_t *addr) -{ - _NOTE(ARGUNUSED(xnbp, addr)); - - return (B_TRUE); -} - -static int -xnbu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - static xnb_flavour_t flavour = { - xnbu_to_host, xnbu_peer_connected, xnbu_peer_disconnected, - xnbu_hotplug_connected, xnbu_start_connect, - xnbu_cksum_from_peer, xnbu_cksum_to_peer, - xnbu_mcast_add, xnbu_mcast_del, - }; - xnbu_t *xnbup; - xnb_t *xnbp; - mac_register_t *mr; - int err; - - switch (cmd) { - case DDI_ATTACH: - break; - case DDI_RESUME: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - xnbup = kmem_zalloc(sizeof (*xnbup), KM_SLEEP); - - if ((mr = mac_alloc(MAC_VERSION)) == NULL) { - kmem_free(xnbup, sizeof (*xnbup)); - return (DDI_FAILURE); - } - - if (xnb_attach(dip, &flavour, xnbup) != DDI_SUCCESS) { - mac_free(mr); - kmem_free(xnbup, sizeof (*xnbup)); - return (DDI_FAILURE); - } - - xnbp = ddi_get_driver_private(dip); - ASSERT(xnbp != NULL); - - mr->m_dip = dip; - mr->m_driver = xnbp; - - /* - * Initialize pointers to device specific functions which will be - * used by the generic layer. - */ - mr->m_type_ident = MAC_PLUGIN_IDENT_ETHER; - mr->m_src_addr = xnbp->xnb_mac_addr; - mr->m_callbacks = &xnbu_callbacks; - mr->m_min_sdu = 0; - mr->m_max_sdu = XNBMAXPKT; - /* - * xnbu is a virtual device, and it is not associated with any - * physical device. Its margin size is determined by the maximum - * packet size it can handle, which is PAGESIZE. - */ - mr->m_margin = PAGESIZE - XNBMAXPKT - sizeof (struct ether_header); - - (void) memset(xnbp->xnb_mac_addr, 0xff, ETHERADDRL); - xnbp->xnb_mac_addr[0] &= 0xfe; - xnbup->u_need_sched = B_FALSE; - - /* - * Register ourselves with the GLDv3 interface. - */ - err = mac_register(mr, &xnbup->u_mh); - mac_free(mr); - if (err != 0) { - xnb_detach(dip); - kmem_free(xnbup, sizeof (*xnbup)); - return (DDI_FAILURE); - } - - mac_link_update(xnbup->u_mh, LINK_STATE_DOWN); - - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -int -xnbu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - xnb_t *xnbp = ddi_get_driver_private(dip); - xnbu_t *xnbup = xnbp->xnb_flavour_data; - - switch (cmd) { - case DDI_DETACH: - break; - case DDI_SUSPEND: - return (DDI_SUCCESS); - default: - return (DDI_FAILURE); - } - - ASSERT(xnbp != NULL); - ASSERT(xnbup != NULL); - - mutex_enter(&xnbp->xnb_tx_lock); - mutex_enter(&xnbp->xnb_rx_lock); - - if (!xnbp->xnb_detachable || xnbp->xnb_connected || - (xnbp->xnb_tx_buf_count > 0)) { - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - return (DDI_FAILURE); - } - - mutex_exit(&xnbp->xnb_rx_lock); - mutex_exit(&xnbp->xnb_tx_lock); - - /* - * Attempt to unregister the mac. - */ - if ((xnbup->u_mh != NULL) && (mac_unregister(xnbup->u_mh) != 0)) - return (DDI_FAILURE); - kmem_free(xnbup, sizeof (*xnbup)); - - xnb_detach(dip); - - return (DDI_SUCCESS); -} - -DDI_DEFINE_STREAM_OPS(ops, nulldev, nulldev, xnbu_attach, xnbu_detach, - nodev, NULL, D_MP, NULL, ddi_quiesce_not_supported); - -static struct modldrv modldrv = { - &mod_driverops, "xnbu driver", &ops -}; - -static struct modlinkage modlinkage = { - MODREV_1, &modldrv, NULL -}; - -int -_init(void) -{ - int i; - - mac_init_ops(&ops, "xnbu"); - - i = mod_install(&modlinkage); - if (i != DDI_SUCCESS) - mac_fini_ops(&ops); - - return (i); -} - -int -_fini(void) -{ - int i; - - i = mod_remove(&modlinkage); - if (i == DDI_SUCCESS) - mac_fini_ops(&ops); - - return (i); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/xen/io/xnf.c b/usr/src/uts/common/xen/io/xnf.c deleted file mode 100644 index 2f895a33d7..0000000000 --- a/usr/src/uts/common/xen/io/xnf.c +++ /dev/null @@ -1,2759 +0,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 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * - * Copyright (c) 2004 Christian Limpach. - * 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. - * 3. This section intentionally left blank. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - */ -/* - * Section 3 of the above license was updated in response to bug 6379571. - */ - -/* - * xnf.c - GLDv3 network driver for domU. - */ - -/* - * This driver uses four per-instance locks: - * - * xnf_gref_lock: - * - * Protects access to the grant reference list stored in - * xnf_gref_head. Grant references should be acquired and released - * using gref_get() and gref_put() respectively. - * - * xnf_schedlock: - * - * Protects: - * xnf_need_sched - used to record that a previous transmit attempt - * failed (and consequently it will be necessary to call - * mac_tx_update() when transmit resources are available). - * xnf_pending_multicast - the number of multicast requests that - * have been submitted to the backend for which we have not - * processed responses. - * - * xnf_txlock: - * - * Protects the transmit ring (xnf_tx_ring) and associated - * structures (notably xnf_tx_pkt_id and xnf_tx_pkt_id_head). - * - * xnf_rxlock: - * - * Protects the receive ring (xnf_rx_ring) and associated - * structures (notably xnf_rx_pkt_info). - * - * If driver-global state that affects both the transmit and receive - * rings is manipulated, both xnf_txlock and xnf_rxlock should be - * held, in that order. - * - * xnf_schedlock is acquired both whilst holding xnf_txlock and - * without. It should always be acquired after xnf_txlock if both are - * held. - * - * Notes: - * - atomic_add_64() is used to manipulate counters where we require - * accuracy. For counters intended only for observation by humans, - * post increment/decrement are used instead. - */ - -#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 -#ifdef XPV_HVM_DRIVER -#include -#include -#else -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include - -#include - -#if defined(DEBUG) || defined(__lint) -#define XNF_DEBUG -#endif - -#ifdef XNF_DEBUG -int xnf_debug = 0; -xnf_t *xnf_debug_instance = NULL; -#endif - -/* - * On a 32 bit PAE system physical and machine addresses are larger - * than 32 bits. ddi_btop() on such systems take an unsigned long - * argument, and so addresses above 4G are truncated before ddi_btop() - * gets to see them. To avoid this, code the shift operation here. - */ -#define xnf_btop(addr) ((addr) >> PAGESHIFT) - -unsigned int xnf_max_tx_frags = 1; - -/* - * Should we use the multicast control feature if the backend provides - * it? - */ -boolean_t xnf_multicast_control = B_TRUE; - -/* - * Received packets below this size are copied to a new streams buffer - * rather than being desballoc'ed. - * - * This value is chosen to accommodate traffic where there are a large - * number of small packets. For data showing a typical distribution, - * see: - * - * Sinha07a: - * Rishi Sinha, Christos Papadopoulos, and John - * Heidemann. Internet Packet Size Distributions: Some - * Observations. Technical Report ISI-TR-2007-643, - * USC/Information Sciences Institute, May, 2007. Orignally - * released October 2005 as web page - * http://netweb.usc.edu/~sinha/pkt-sizes/. - * . - */ -size_t xnf_rx_copy_limit = 64; - -#define INVALID_GRANT_HANDLE ((grant_handle_t)-1) -#define INVALID_GRANT_REF ((grant_ref_t)-1) -#define INVALID_TX_ID ((uint16_t)-1) - -#define TX_ID_TO_TXID(p, id) (&((p)->xnf_tx_pkt_id[(id)])) -#define TX_ID_VALID(i) (((i) != INVALID_TX_ID) && ((i) < NET_TX_RING_SIZE)) - -/* Required system entry points */ -static int xnf_attach(dev_info_t *, ddi_attach_cmd_t); -static int xnf_detach(dev_info_t *, ddi_detach_cmd_t); - -/* Required driver entry points for Nemo */ -static int xnf_start(void *); -static void xnf_stop(void *); -static int xnf_set_mac_addr(void *, const uint8_t *); -static int xnf_set_multicast(void *, boolean_t, const uint8_t *); -static int xnf_set_promiscuous(void *, boolean_t); -static mblk_t *xnf_send(void *, mblk_t *); -static uint_t xnf_intr(caddr_t); -static int xnf_stat(void *, uint_t, uint64_t *); -static boolean_t xnf_getcapab(void *, mac_capab_t, void *); - -/* Driver private functions */ -static int xnf_alloc_dma_resources(xnf_t *); -static void xnf_release_dma_resources(xnf_t *); -static void xnf_release_mblks(xnf_t *); - -static int xnf_buf_constructor(void *, void *, int); -static void xnf_buf_destructor(void *, void *); -static xnf_buf_t *xnf_buf_get(xnf_t *, int, boolean_t); -#pragma inline(xnf_buf_get) -static void xnf_buf_put(xnf_t *, xnf_buf_t *, boolean_t); -#pragma inline(xnf_buf_put) -static void xnf_buf_refresh(xnf_buf_t *); -#pragma inline(xnf_buf_refresh) -static void xnf_buf_recycle(xnf_buf_t *); - -static int xnf_tx_buf_constructor(void *, void *, int); -static void xnf_tx_buf_destructor(void *, void *); - -static grant_ref_t gref_get(xnf_t *); -#pragma inline(gref_get) -static void gref_put(xnf_t *, grant_ref_t); -#pragma inline(gref_put) - -static xnf_txid_t *txid_get(xnf_t *); -#pragma inline(txid_get) -static void txid_put(xnf_t *, xnf_txid_t *); -#pragma inline(txid_put) - -void xnf_send_driver_status(int, int); -static void xnf_rxbuf_hang(xnf_t *, xnf_buf_t *); -static int xnf_tx_clean_ring(xnf_t *); -static void oe_state_change(dev_info_t *, ddi_eventcookie_t, - void *, void *); -static boolean_t xnf_kstat_init(xnf_t *); -static void xnf_rx_collect(xnf_t *); - -static mac_callbacks_t xnf_callbacks = { - MC_GETCAPAB, - xnf_stat, - xnf_start, - xnf_stop, - xnf_set_promiscuous, - xnf_set_multicast, - xnf_set_mac_addr, - xnf_send, - NULL, - NULL, - xnf_getcapab -}; - -/* DMA attributes for network ring buffer */ -static ddi_dma_attr_t ringbuf_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 */ - 0xffffffffffffffffULL, /* maximum segment length */ - 1, /* maximum number of segments */ - 1, /* granularity */ - 0, /* flags (reserved) */ -}; - -/* DMA attributes for transmit and receive data */ -static ddi_dma_attr_t buf_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 */ - 0xffffffffffffffffULL, /* maximum segment length */ - 1, /* maximum number of segments */ - 1, /* granularity */ - 0, /* flags (reserved) */ -}; - -/* DMA access attributes for registers and descriptors */ -static ddi_device_acc_attr_t accattr = { - DDI_DEVICE_ATTR_V0, - DDI_STRUCTURE_LE_ACC, /* This is a little-endian device */ - DDI_STRICTORDER_ACC -}; - -/* DMA access attributes for data: NOT to be byte swapped. */ -static ddi_device_acc_attr_t data_accattr = { - DDI_DEVICE_ATTR_V0, - DDI_NEVERSWAP_ACC, - DDI_STRICTORDER_ACC -}; - -DDI_DEFINE_STREAM_OPS(xnf_dev_ops, nulldev, nulldev, xnf_attach, xnf_detach, - nodev, NULL, D_MP, NULL, ddi_quiesce_not_supported); - -static struct modldrv xnf_modldrv = { - &mod_driverops, - "Virtual Ethernet driver", - &xnf_dev_ops -}; - -static struct modlinkage modlinkage = { - MODREV_1, &xnf_modldrv, NULL -}; - -int -_init(void) -{ - int r; - - mac_init_ops(&xnf_dev_ops, "xnf"); - r = mod_install(&modlinkage); - if (r != DDI_SUCCESS) - mac_fini_ops(&xnf_dev_ops); - - return (r); -} - -int -_fini(void) -{ - return (EBUSY); /* XXPV should be removable */ -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* - * Acquire a grant reference. - */ -static grant_ref_t -gref_get(xnf_t *xnfp) -{ - grant_ref_t gref; - - mutex_enter(&xnfp->xnf_gref_lock); - - do { - gref = gnttab_claim_grant_reference(&xnfp->xnf_gref_head); - - } while ((gref == INVALID_GRANT_REF) && - (gnttab_alloc_grant_references(16, &xnfp->xnf_gref_head) == 0)); - - mutex_exit(&xnfp->xnf_gref_lock); - - if (gref == INVALID_GRANT_REF) { - xnfp->xnf_stat_gref_failure++; - } else { - atomic_inc_64(&xnfp->xnf_stat_gref_outstanding); - if (xnfp->xnf_stat_gref_outstanding > xnfp->xnf_stat_gref_peak) - xnfp->xnf_stat_gref_peak = - xnfp->xnf_stat_gref_outstanding; - } - - return (gref); -} - -/* - * Release a grant reference. - */ -static void -gref_put(xnf_t *xnfp, grant_ref_t gref) -{ - ASSERT(gref != INVALID_GRANT_REF); - - mutex_enter(&xnfp->xnf_gref_lock); - gnttab_release_grant_reference(&xnfp->xnf_gref_head, gref); - mutex_exit(&xnfp->xnf_gref_lock); - - atomic_dec_64(&xnfp->xnf_stat_gref_outstanding); -} - -/* - * Acquire a transmit id. - */ -static xnf_txid_t * -txid_get(xnf_t *xnfp) -{ - xnf_txid_t *tidp; - - ASSERT(MUTEX_HELD(&xnfp->xnf_txlock)); - - if (xnfp->xnf_tx_pkt_id_head == INVALID_TX_ID) - return (NULL); - - ASSERT(TX_ID_VALID(xnfp->xnf_tx_pkt_id_head)); - - tidp = TX_ID_TO_TXID(xnfp, xnfp->xnf_tx_pkt_id_head); - xnfp->xnf_tx_pkt_id_head = tidp->next; - tidp->next = INVALID_TX_ID; - - ASSERT(tidp->txbuf == NULL); - - return (tidp); -} - -/* - * Release a transmit id. - */ -static void -txid_put(xnf_t *xnfp, xnf_txid_t *tidp) -{ - ASSERT(MUTEX_HELD(&xnfp->xnf_txlock)); - ASSERT(TX_ID_VALID(tidp->id)); - ASSERT(tidp->next == INVALID_TX_ID); - - tidp->txbuf = NULL; - tidp->next = xnfp->xnf_tx_pkt_id_head; - xnfp->xnf_tx_pkt_id_head = tidp->id; -} - -/* - * Get `wanted' slots in the transmit ring, waiting for at least that - * number if `wait' is B_TRUE. Force the ring to be cleaned by setting - * `wanted' to zero. - * - * Return the number of slots available. - */ -static int -tx_slots_get(xnf_t *xnfp, int wanted, boolean_t wait) -{ - int slotsfree; - boolean_t forced_clean = (wanted == 0); - - ASSERT(MUTEX_HELD(&xnfp->xnf_txlock)); - - /* LINTED: constant in conditional context */ - while (B_TRUE) { - slotsfree = RING_FREE_REQUESTS(&xnfp->xnf_tx_ring); - - if ((slotsfree < wanted) || forced_clean) - slotsfree = xnf_tx_clean_ring(xnfp); - - /* - * If there are more than we need free, tell other - * people to come looking again. We hold txlock, so we - * are able to take our slots before anyone else runs. - */ - if (slotsfree > wanted) - cv_broadcast(&xnfp->xnf_cv_tx_slots); - - if (slotsfree >= wanted) - break; - - if (!wait) - break; - - cv_wait(&xnfp->xnf_cv_tx_slots, &xnfp->xnf_txlock); - } - - ASSERT(slotsfree <= RING_SIZE(&(xnfp->xnf_tx_ring))); - - return (slotsfree); -} - -static int -xnf_setup_rings(xnf_t *xnfp) -{ - domid_t oeid; - struct xenbus_device *xsd; - RING_IDX i; - int err; - xnf_txid_t *tidp; - xnf_buf_t **bdescp; - - oeid = xvdi_get_oeid(xnfp->xnf_devinfo); - xsd = xvdi_get_xsd(xnfp->xnf_devinfo); - - if (xnfp->xnf_tx_ring_ref != INVALID_GRANT_REF) - gnttab_end_foreign_access(xnfp->xnf_tx_ring_ref, 0, 0); - - err = gnttab_grant_foreign_access(oeid, - xnf_btop(pa_to_ma(xnfp->xnf_tx_ring_phys_addr)), 0); - if (err <= 0) { - err = -err; - xenbus_dev_error(xsd, err, "granting access to tx ring page"); - goto out; - } - xnfp->xnf_tx_ring_ref = (grant_ref_t)err; - - if (xnfp->xnf_rx_ring_ref != INVALID_GRANT_REF) - gnttab_end_foreign_access(xnfp->xnf_rx_ring_ref, 0, 0); - - err = gnttab_grant_foreign_access(oeid, - xnf_btop(pa_to_ma(xnfp->xnf_rx_ring_phys_addr)), 0); - if (err <= 0) { - err = -err; - xenbus_dev_error(xsd, err, "granting access to rx ring page"); - goto out; - } - xnfp->xnf_rx_ring_ref = (grant_ref_t)err; - - mutex_enter(&xnfp->xnf_txlock); - - /* - * Setup/cleanup the TX ring. Note that this can lose packets - * after a resume, but we expect to stagger on. - */ - xnfp->xnf_tx_pkt_id_head = INVALID_TX_ID; /* I.e. emtpy list. */ - for (i = 0, tidp = &xnfp->xnf_tx_pkt_id[0]; - i < NET_TX_RING_SIZE; - i++, tidp++) { - xnf_txbuf_t *txp; - - tidp->id = i; - - txp = tidp->txbuf; - if (txp == NULL) { - tidp->next = INVALID_TX_ID; /* Appease txid_put(). */ - txid_put(xnfp, tidp); - continue; - } - - ASSERT(txp->tx_txreq.gref != INVALID_GRANT_REF); - ASSERT(txp->tx_mp != NULL); - - switch (txp->tx_type) { - case TX_DATA: - VERIFY(gnttab_query_foreign_access(txp->tx_txreq.gref) - == 0); - - if (txp->tx_bdesc == NULL) { - (void) gnttab_end_foreign_access_ref( - txp->tx_txreq.gref, 1); - gref_put(xnfp, txp->tx_txreq.gref); - (void) ddi_dma_unbind_handle( - txp->tx_dma_handle); - } else { - xnf_buf_put(xnfp, txp->tx_bdesc, B_TRUE); - } - - freemsg(txp->tx_mp); - txid_put(xnfp, tidp); - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - - break; - - case TX_MCAST_REQ: - txp->tx_type = TX_MCAST_RSP; - txp->tx_status = NETIF_RSP_DROPPED; - cv_broadcast(&xnfp->xnf_cv_multicast); - - /* - * The request consumed two slots in the ring, - * yet only a single xnf_txid_t is used. Step - * over the empty slot. - */ - i++; - ASSERT(i < NET_TX_RING_SIZE); - - break; - - case TX_MCAST_RSP: - break; - } - } - - /* LINTED: constant in conditional context */ - SHARED_RING_INIT(xnfp->xnf_tx_ring.sring); - /* LINTED: constant in conditional context */ - FRONT_RING_INIT(&xnfp->xnf_tx_ring, - xnfp->xnf_tx_ring.sring, PAGESIZE); - - mutex_exit(&xnfp->xnf_txlock); - - mutex_enter(&xnfp->xnf_rxlock); - - /* - * Clean out any buffers currently posted to the receive ring - * before we reset it. - */ - for (i = 0, bdescp = &xnfp->xnf_rx_pkt_info[0]; - i < NET_RX_RING_SIZE; - i++, bdescp++) { - if (*bdescp != NULL) { - xnf_buf_put(xnfp, *bdescp, B_FALSE); - *bdescp = NULL; - } - } - - /* LINTED: constant in conditional context */ - SHARED_RING_INIT(xnfp->xnf_rx_ring.sring); - /* LINTED: constant in conditional context */ - FRONT_RING_INIT(&xnfp->xnf_rx_ring, - xnfp->xnf_rx_ring.sring, PAGESIZE); - - /* - * Fill the ring with buffers. - */ - for (i = 0; i < NET_RX_RING_SIZE; i++) { - xnf_buf_t *bdesc; - - bdesc = xnf_buf_get(xnfp, KM_SLEEP, B_FALSE); - VERIFY(bdesc != NULL); - xnf_rxbuf_hang(xnfp, bdesc); - } - - /* LINTED: constant in conditional context */ - RING_PUSH_REQUESTS(&xnfp->xnf_rx_ring); - - mutex_exit(&xnfp->xnf_rxlock); - - return (0); - -out: - if (xnfp->xnf_tx_ring_ref != INVALID_GRANT_REF) - gnttab_end_foreign_access(xnfp->xnf_tx_ring_ref, 0, 0); - xnfp->xnf_tx_ring_ref = INVALID_GRANT_REF; - - if (xnfp->xnf_rx_ring_ref != INVALID_GRANT_REF) - gnttab_end_foreign_access(xnfp->xnf_rx_ring_ref, 0, 0); - xnfp->xnf_rx_ring_ref = INVALID_GRANT_REF; - - return (err); -} - -/* - * Connect driver to back end, called to set up communication with - * back end driver both initially and on resume after restore/migrate. - */ -void -xnf_be_connect(xnf_t *xnfp) -{ - const char *message; - xenbus_transaction_t xbt; - struct xenbus_device *xsd; - char *xsname; - int err; - - ASSERT(!xnfp->xnf_connected); - - xsd = xvdi_get_xsd(xnfp->xnf_devinfo); - xsname = xvdi_get_xsname(xnfp->xnf_devinfo); - - err = xnf_setup_rings(xnfp); - if (err != 0) { - cmn_err(CE_WARN, "failed to set up tx/rx rings"); - xenbus_dev_error(xsd, err, "setting up ring"); - return; - } - -again: - err = xenbus_transaction_start(&xbt); - if (err != 0) { - xenbus_dev_error(xsd, EIO, "starting transaction"); - return; - } - - err = xenbus_printf(xbt, xsname, "tx-ring-ref", "%u", - xnfp->xnf_tx_ring_ref); - if (err != 0) { - message = "writing tx ring-ref"; - goto abort_transaction; - } - - err = xenbus_printf(xbt, xsname, "rx-ring-ref", "%u", - xnfp->xnf_rx_ring_ref); - if (err != 0) { - message = "writing rx ring-ref"; - goto abort_transaction; - } - - err = xenbus_printf(xbt, xsname, "event-channel", "%u", - xnfp->xnf_evtchn); - if (err != 0) { - message = "writing event-channel"; - goto abort_transaction; - } - - err = xenbus_printf(xbt, xsname, "feature-rx-notify", "%d", 1); - if (err != 0) { - message = "writing feature-rx-notify"; - goto abort_transaction; - } - - err = xenbus_printf(xbt, xsname, "request-rx-copy", "%d", 1); - if (err != 0) { - message = "writing request-rx-copy"; - goto abort_transaction; - } - - if (xnfp->xnf_be_mcast_control) { - err = xenbus_printf(xbt, xsname, "request-multicast-control", - "%d", 1); - if (err != 0) { - message = "writing request-multicast-control"; - goto abort_transaction; - } - } - - err = xvdi_switch_state(xnfp->xnf_devinfo, xbt, XenbusStateConnected); - if (err != 0) { - message = "switching state to XenbusStateConnected"; - goto abort_transaction; - } - - err = xenbus_transaction_end(xbt, 0); - if (err != 0) { - if (err == EAGAIN) - goto again; - xenbus_dev_error(xsd, err, "completing transaction"); - } - - return; - -abort_transaction: - (void) xenbus_transaction_end(xbt, 1); - xenbus_dev_error(xsd, err, "%s", message); -} - -/* - * Read configuration information from xenstore. - */ -void -xnf_read_config(xnf_t *xnfp) -{ - int err, be_cap; - char mac[ETHERADDRL * 3]; - char *oename = xvdi_get_oename(xnfp->xnf_devinfo); - - err = xenbus_scanf(XBT_NULL, oename, "mac", - "%s", (char *)&mac[0]); - if (err != 0) { - /* - * bad: we're supposed to be set up with a proper mac - * addr. at this point - */ - cmn_err(CE_WARN, "%s%d: no mac address", - ddi_driver_name(xnfp->xnf_devinfo), - ddi_get_instance(xnfp->xnf_devinfo)); - return; - } - if (ether_aton(mac, xnfp->xnf_mac_addr) != ETHERADDRL) { - err = ENOENT; - xenbus_dev_error(xvdi_get_xsd(xnfp->xnf_devinfo), ENOENT, - "parsing %s/mac", xvdi_get_xsname(xnfp->xnf_devinfo)); - return; - } - - err = xenbus_scanf(XBT_NULL, oename, - "feature-rx-copy", "%d", &be_cap); - /* - * If we fail to read the store we assume that the key is - * absent, implying an older domain at the far end. Older - * domains cannot do HV copy. - */ - if (err != 0) - be_cap = 0; - xnfp->xnf_be_rx_copy = (be_cap != 0); - - err = xenbus_scanf(XBT_NULL, oename, - "feature-multicast-control", "%d", &be_cap); - /* - * If we fail to read the store we assume that the key is - * absent, implying an older domain at the far end. Older - * domains do not support multicast control. - */ - if (err != 0) - be_cap = 0; - xnfp->xnf_be_mcast_control = (be_cap != 0) && xnf_multicast_control; -} - -/* - * attach(9E) -- Attach a device to the system - */ -static int -xnf_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) -{ - mac_register_t *macp; - xnf_t *xnfp; - int err; - char cachename[32]; - -#ifdef XNF_DEBUG - if (xnf_debug & XNF_DEBUG_DDI) - printf("xnf%d: attach(0x%p)\n", ddi_get_instance(devinfo), - (void *)devinfo); -#endif - - switch (cmd) { - case DDI_RESUME: - xnfp = ddi_get_driver_private(devinfo); - xnfp->xnf_gen++; - - (void) xvdi_resume(devinfo); - (void) xvdi_alloc_evtchn(devinfo); - xnfp->xnf_evtchn = xvdi_get_evtchn(devinfo); -#ifdef XPV_HVM_DRIVER - ec_bind_evtchn_to_handler(xnfp->xnf_evtchn, IPL_VIF, xnf_intr, - xnfp); -#else - (void) ddi_add_intr(devinfo, 0, NULL, NULL, xnf_intr, - (caddr_t)xnfp); -#endif - return (DDI_SUCCESS); - - case DDI_ATTACH: - break; - - default: - return (DDI_FAILURE); - } - - /* - * Allocate gld_mac_info_t and xnf_instance structures - */ - macp = mac_alloc(MAC_VERSION); - if (macp == NULL) - return (DDI_FAILURE); - xnfp = kmem_zalloc(sizeof (*xnfp), KM_SLEEP); - - macp->m_dip = devinfo; - macp->m_driver = xnfp; - xnfp->xnf_devinfo = devinfo; - - macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; - macp->m_src_addr = xnfp->xnf_mac_addr; - macp->m_callbacks = &xnf_callbacks; - macp->m_min_sdu = 0; - macp->m_max_sdu = XNF_MAXPKT; - - xnfp->xnf_running = B_FALSE; - xnfp->xnf_connected = B_FALSE; - xnfp->xnf_be_rx_copy = B_FALSE; - xnfp->xnf_be_mcast_control = B_FALSE; - xnfp->xnf_need_sched = B_FALSE; - - xnfp->xnf_rx_head = NULL; - xnfp->xnf_rx_tail = NULL; - xnfp->xnf_rx_new_buffers_posted = B_FALSE; - -#ifdef XPV_HVM_DRIVER - /* - * Report our version to dom0. - */ - if (xenbus_printf(XBT_NULL, "guest/xnf", "version", "%d", - HVMPV_XNF_VERS)) - cmn_err(CE_WARN, "xnf: couldn't write version\n"); -#endif - - /* - * Get the iblock cookie with which to initialize the mutexes. - */ - if (ddi_get_iblock_cookie(devinfo, 0, &xnfp->xnf_icookie) - != DDI_SUCCESS) - goto failure; - - mutex_init(&xnfp->xnf_txlock, - NULL, MUTEX_DRIVER, xnfp->xnf_icookie); - mutex_init(&xnfp->xnf_rxlock, - NULL, MUTEX_DRIVER, xnfp->xnf_icookie); - mutex_init(&xnfp->xnf_schedlock, - NULL, MUTEX_DRIVER, xnfp->xnf_icookie); - mutex_init(&xnfp->xnf_gref_lock, - NULL, MUTEX_DRIVER, xnfp->xnf_icookie); - - cv_init(&xnfp->xnf_cv_state, NULL, CV_DEFAULT, NULL); - cv_init(&xnfp->xnf_cv_multicast, NULL, CV_DEFAULT, NULL); - cv_init(&xnfp->xnf_cv_tx_slots, NULL, CV_DEFAULT, NULL); - - (void) sprintf(cachename, "xnf_buf_cache_%d", - ddi_get_instance(devinfo)); - xnfp->xnf_buf_cache = kmem_cache_create(cachename, - sizeof (xnf_buf_t), 0, - xnf_buf_constructor, xnf_buf_destructor, - NULL, xnfp, NULL, 0); - if (xnfp->xnf_buf_cache == NULL) - goto failure_0; - - (void) sprintf(cachename, "xnf_tx_buf_cache_%d", - ddi_get_instance(devinfo)); - xnfp->xnf_tx_buf_cache = kmem_cache_create(cachename, - sizeof (xnf_txbuf_t), 0, - xnf_tx_buf_constructor, xnf_tx_buf_destructor, - NULL, xnfp, NULL, 0); - if (xnfp->xnf_tx_buf_cache == NULL) - goto failure_1; - - xnfp->xnf_gref_head = INVALID_GRANT_REF; - - if (xnf_alloc_dma_resources(xnfp) == DDI_FAILURE) { - cmn_err(CE_WARN, "xnf%d: failed to allocate and initialize " - "driver data structures", - ddi_get_instance(xnfp->xnf_devinfo)); - goto failure_2; - } - - xnfp->xnf_rx_ring.sring->rsp_event = - xnfp->xnf_tx_ring.sring->rsp_event = 1; - - xnfp->xnf_tx_ring_ref = INVALID_GRANT_REF; - xnfp->xnf_rx_ring_ref = INVALID_GRANT_REF; - - /* set driver private pointer now */ - ddi_set_driver_private(devinfo, xnfp); - - if (!xnf_kstat_init(xnfp)) - goto failure_3; - - /* - * Allocate an event channel, add the interrupt handler and - * bind it to the event channel. - */ - (void) xvdi_alloc_evtchn(devinfo); - xnfp->xnf_evtchn = xvdi_get_evtchn(devinfo); -#ifdef XPV_HVM_DRIVER - ec_bind_evtchn_to_handler(xnfp->xnf_evtchn, IPL_VIF, xnf_intr, xnfp); -#else - (void) ddi_add_intr(devinfo, 0, NULL, NULL, xnf_intr, (caddr_t)xnfp); -#endif - - err = mac_register(macp, &xnfp->xnf_mh); - mac_free(macp); - macp = NULL; - if (err != 0) - goto failure_4; - - if (xvdi_add_event_handler(devinfo, XS_OE_STATE, oe_state_change, NULL) - != DDI_SUCCESS) - goto failure_5; - -#ifdef XPV_HVM_DRIVER - /* - * In the HVM case, this driver essentially replaces a driver for - * a 'real' PCI NIC. Without the "model" property set to - * "Ethernet controller", like the PCI code does, netbooting does - * not work correctly, as strplumb_get_netdev_path() will not find - * this interface. - */ - (void) ndi_prop_update_string(DDI_DEV_T_NONE, devinfo, "model", - "Ethernet controller"); -#endif - -#ifdef XNF_DEBUG - if (xnf_debug_instance == NULL) - xnf_debug_instance = xnfp; -#endif - - return (DDI_SUCCESS); - -failure_5: - (void) mac_unregister(xnfp->xnf_mh); - -failure_4: -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(xnfp->xnf_evtchn); - xvdi_free_evtchn(devinfo); -#else - ddi_remove_intr(devinfo, 0, xnfp->xnf_icookie); -#endif - xnfp->xnf_evtchn = INVALID_EVTCHN; - kstat_delete(xnfp->xnf_kstat_aux); - -failure_3: - xnf_release_dma_resources(xnfp); - -failure_2: - kmem_cache_destroy(xnfp->xnf_tx_buf_cache); - -failure_1: - kmem_cache_destroy(xnfp->xnf_buf_cache); - -failure_0: - cv_destroy(&xnfp->xnf_cv_tx_slots); - cv_destroy(&xnfp->xnf_cv_multicast); - cv_destroy(&xnfp->xnf_cv_state); - - mutex_destroy(&xnfp->xnf_gref_lock); - mutex_destroy(&xnfp->xnf_schedlock); - mutex_destroy(&xnfp->xnf_rxlock); - mutex_destroy(&xnfp->xnf_txlock); - -failure: - kmem_free(xnfp, sizeof (*xnfp)); - if (macp != NULL) - mac_free(macp); - - return (DDI_FAILURE); -} - -/* detach(9E) -- Detach a device from the system */ -static int -xnf_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) -{ - xnf_t *xnfp; /* Our private device info */ - -#ifdef XNF_DEBUG - if (xnf_debug & XNF_DEBUG_DDI) - printf("xnf_detach(0x%p)\n", (void *)devinfo); -#endif - - xnfp = ddi_get_driver_private(devinfo); - - switch (cmd) { - case DDI_SUSPEND: -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(xnfp->xnf_evtchn); - xvdi_free_evtchn(devinfo); -#else - ddi_remove_intr(devinfo, 0, xnfp->xnf_icookie); -#endif - - xvdi_suspend(devinfo); - - mutex_enter(&xnfp->xnf_rxlock); - mutex_enter(&xnfp->xnf_txlock); - - xnfp->xnf_evtchn = INVALID_EVTCHN; - xnfp->xnf_connected = B_FALSE; - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); - - /* claim link to be down after disconnect */ - mac_link_update(xnfp->xnf_mh, LINK_STATE_DOWN); - return (DDI_SUCCESS); - - case DDI_DETACH: - break; - - default: - return (DDI_FAILURE); - } - - if (xnfp->xnf_connected) - return (DDI_FAILURE); - - /* - * Cannot detach if we have xnf_buf_t outstanding. - */ - if (xnfp->xnf_stat_buf_allocated > 0) - return (DDI_FAILURE); - - if (mac_unregister(xnfp->xnf_mh) != 0) - return (DDI_FAILURE); - - kstat_delete(xnfp->xnf_kstat_aux); - - /* Stop the receiver */ - xnf_stop(xnfp); - - xvdi_remove_event_handler(devinfo, XS_OE_STATE); - - /* Remove the interrupt */ -#ifdef XPV_HVM_DRIVER - ec_unbind_evtchn(xnfp->xnf_evtchn); - xvdi_free_evtchn(devinfo); -#else - ddi_remove_intr(devinfo, 0, xnfp->xnf_icookie); -#endif - - /* Release any pending xmit mblks */ - xnf_release_mblks(xnfp); - - /* Release all DMA resources */ - xnf_release_dma_resources(xnfp); - - cv_destroy(&xnfp->xnf_cv_tx_slots); - cv_destroy(&xnfp->xnf_cv_multicast); - cv_destroy(&xnfp->xnf_cv_state); - - kmem_cache_destroy(xnfp->xnf_tx_buf_cache); - kmem_cache_destroy(xnfp->xnf_buf_cache); - - mutex_destroy(&xnfp->xnf_gref_lock); - mutex_destroy(&xnfp->xnf_schedlock); - mutex_destroy(&xnfp->xnf_rxlock); - mutex_destroy(&xnfp->xnf_txlock); - - kmem_free(xnfp, sizeof (*xnfp)); - - return (DDI_SUCCESS); -} - -/* - * xnf_set_mac_addr() -- set the physical network address on the board. - */ -static int -xnf_set_mac_addr(void *arg, const uint8_t *macaddr) -{ - _NOTE(ARGUNUSED(arg, macaddr)); - - /* - * We can't set our macaddr. - */ - return (ENOTSUP); -} - -/* - * xnf_set_multicast() -- set (enable) or disable a multicast address. - * - * Program the hardware to enable/disable the multicast address - * in "mca". Enable if "add" is true, disable if false. - */ -static int -xnf_set_multicast(void *arg, boolean_t add, const uint8_t *mca) -{ - xnf_t *xnfp = arg; - xnf_txbuf_t *txp; - int n_slots; - RING_IDX slot; - xnf_txid_t *tidp; - netif_tx_request_t *txrp; - struct netif_extra_info *erp; - boolean_t notify, result; - - /* - * If the backend does not support multicast control then we - * must assume that the right packets will just arrive. - */ - if (!xnfp->xnf_be_mcast_control) - return (0); - - txp = kmem_cache_alloc(xnfp->xnf_tx_buf_cache, KM_SLEEP); - - mutex_enter(&xnfp->xnf_txlock); - - /* - * If we're not yet connected then claim success. This is - * acceptable because we refresh the entire set of multicast - * addresses when we get connected. - * - * We can't wait around here because the MAC layer expects - * this to be a non-blocking operation - waiting ends up - * causing a deadlock during resume. - */ - if (!xnfp->xnf_connected) { - mutex_exit(&xnfp->xnf_txlock); - return (0); - } - - /* - * 1. Acquire two slots in the ring. - * 2. Fill in the slots. - * 3. Request notification when the operation is done. - * 4. Kick the peer. - * 5. Wait for the response via xnf_tx_clean_ring(). - */ - - n_slots = tx_slots_get(xnfp, 2, B_TRUE); - ASSERT(n_slots >= 2); - - slot = xnfp->xnf_tx_ring.req_prod_pvt; - tidp = txid_get(xnfp); - VERIFY(tidp != NULL); - - txp->tx_type = TX_MCAST_REQ; - txp->tx_slot = slot; - - txrp = RING_GET_REQUEST(&xnfp->xnf_tx_ring, slot); - erp = (struct netif_extra_info *) - RING_GET_REQUEST(&xnfp->xnf_tx_ring, slot + 1); - - txrp->gref = 0; - txrp->size = 0; - txrp->offset = 0; - /* Set tx_txreq.id to appease xnf_tx_clean_ring(). */ - txrp->id = txp->tx_txreq.id = tidp->id; - txrp->flags = NETTXF_extra_info; - - erp->type = add ? XEN_NETIF_EXTRA_TYPE_MCAST_ADD : - XEN_NETIF_EXTRA_TYPE_MCAST_DEL; - bcopy((void *)mca, &erp->u.mcast.addr, ETHERADDRL); - - tidp->txbuf = txp; - - xnfp->xnf_tx_ring.req_prod_pvt = slot + 2; - - mutex_enter(&xnfp->xnf_schedlock); - xnfp->xnf_pending_multicast++; - mutex_exit(&xnfp->xnf_schedlock); - - /* LINTED: constant in conditional context */ - RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xnfp->xnf_tx_ring, - notify); - if (notify) - ec_notify_via_evtchn(xnfp->xnf_evtchn); - - while (txp->tx_type == TX_MCAST_REQ) - cv_wait(&xnfp->xnf_cv_multicast, - &xnfp->xnf_txlock); - - ASSERT(txp->tx_type == TX_MCAST_RSP); - - mutex_enter(&xnfp->xnf_schedlock); - xnfp->xnf_pending_multicast--; - mutex_exit(&xnfp->xnf_schedlock); - - result = (txp->tx_status == NETIF_RSP_OKAY); - - txid_put(xnfp, tidp); - - mutex_exit(&xnfp->xnf_txlock); - - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - - return (result ? 0 : 1); -} - -/* - * xnf_set_promiscuous() -- set or reset promiscuous mode on the board - * - * Program the hardware to enable/disable promiscuous mode. - */ -static int -xnf_set_promiscuous(void *arg, boolean_t on) -{ - _NOTE(ARGUNUSED(arg, on)); - - /* - * We can't really do this, but we pretend that we can in - * order that snoop will work. - */ - return (0); -} - -/* - * Clean buffers that we have responses for from the transmit ring. - */ -static int -xnf_tx_clean_ring(xnf_t *xnfp) -{ - boolean_t work_to_do; - - ASSERT(MUTEX_HELD(&xnfp->xnf_txlock)); - -loop: - while (RING_HAS_UNCONSUMED_RESPONSES(&xnfp->xnf_tx_ring)) { - RING_IDX cons, prod, i; - - cons = xnfp->xnf_tx_ring.rsp_cons; - prod = xnfp->xnf_tx_ring.sring->rsp_prod; - membar_consumer(); - /* - * Clean tx requests from ring that we have responses - * for. - */ - DTRACE_PROBE2(xnf_tx_clean_range, int, cons, int, prod); - for (i = cons; i != prod; i++) { - netif_tx_response_t *trp; - xnf_txid_t *tidp; - xnf_txbuf_t *txp; - - trp = RING_GET_RESPONSE(&xnfp->xnf_tx_ring, i); - ASSERT(TX_ID_VALID(trp->id)); - - tidp = TX_ID_TO_TXID(xnfp, trp->id); - ASSERT(tidp->id == trp->id); - ASSERT(tidp->next == INVALID_TX_ID); - - txp = tidp->txbuf; - ASSERT(txp != NULL); - ASSERT(txp->tx_txreq.id == trp->id); - - switch (txp->tx_type) { - case TX_DATA: - if (gnttab_query_foreign_access( - txp->tx_txreq.gref) != 0) - cmn_err(CE_PANIC, - "tx grant %d still in use by " - "backend domain", - txp->tx_txreq.gref); - - if (txp->tx_bdesc == NULL) { - (void) gnttab_end_foreign_access_ref( - txp->tx_txreq.gref, 1); - gref_put(xnfp, txp->tx_txreq.gref); - (void) ddi_dma_unbind_handle( - txp->tx_dma_handle); - } else { - xnf_buf_put(xnfp, txp->tx_bdesc, - B_TRUE); - } - - freemsg(txp->tx_mp); - txid_put(xnfp, tidp); - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - - break; - - case TX_MCAST_REQ: - txp->tx_type = TX_MCAST_RSP; - txp->tx_status = trp->status; - cv_broadcast(&xnfp->xnf_cv_multicast); - - break; - - case TX_MCAST_RSP: - break; - - default: - cmn_err(CE_PANIC, "xnf_tx_clean_ring: " - "invalid xnf_txbuf_t type: %d", - txp->tx_type); - break; - } - } - /* - * Record the last response we dealt with so that we - * know where to start next time around. - */ - xnfp->xnf_tx_ring.rsp_cons = prod; - membar_enter(); - } - - /* LINTED: constant in conditional context */ - RING_FINAL_CHECK_FOR_RESPONSES(&xnfp->xnf_tx_ring, work_to_do); - if (work_to_do) - goto loop; - - return (RING_FREE_REQUESTS(&xnfp->xnf_tx_ring)); -} - -/* - * Allocate and fill in a look-aside buffer for the packet `mp'. Used - * to ensure that the packet is physically contiguous and contained - * within a single page. - */ -static xnf_buf_t * -xnf_tx_pullup(xnf_t *xnfp, mblk_t *mp) -{ - xnf_buf_t *bd; - caddr_t bp; - - bd = xnf_buf_get(xnfp, KM_SLEEP, B_TRUE); - if (bd == NULL) - return (NULL); - - bp = bd->buf; - while (mp != NULL) { - size_t len = MBLKL(mp); - - bcopy(mp->b_rptr, bp, len); - bp += len; - - mp = mp->b_cont; - } - - ASSERT((bp - bd->buf) <= PAGESIZE); - - xnfp->xnf_stat_tx_pullup++; - - return (bd); -} - -/* - * Insert the pseudo-header checksum into the packet `buf'. - */ -void -xnf_pseudo_cksum(caddr_t buf, int length) -{ - struct ether_header *ehp; - uint16_t sap, len, *stuff; - uint32_t cksum; - size_t offset; - ipha_t *ipha; - ipaddr_t src, dst; - - ASSERT(length >= sizeof (*ehp)); - ehp = (struct ether_header *)buf; - - if (ntohs(ehp->ether_type) == VLAN_TPID) { - struct ether_vlan_header *evhp; - - ASSERT(length >= sizeof (*evhp)); - evhp = (struct ether_vlan_header *)buf; - sap = ntohs(evhp->ether_type); - offset = sizeof (*evhp); - } else { - sap = ntohs(ehp->ether_type); - offset = sizeof (*ehp); - } - - ASSERT(sap == ETHERTYPE_IP); - - /* Packet should have been pulled up by the caller. */ - if ((offset + sizeof (ipha_t)) > length) { - cmn_err(CE_WARN, "xnf_pseudo_cksum: no room for checksum"); - return; - } - - ipha = (ipha_t *)(buf + offset); - - ASSERT(IPH_HDR_LENGTH(ipha) == IP_SIMPLE_HDR_LENGTH); - - len = ntohs(ipha->ipha_length) - IP_SIMPLE_HDR_LENGTH; - - switch (ipha->ipha_protocol) { - case IPPROTO_TCP: - stuff = IPH_TCPH_CHECKSUMP(ipha, IP_SIMPLE_HDR_LENGTH); - cksum = IP_TCP_CSUM_COMP; - break; - case IPPROTO_UDP: - stuff = IPH_UDPH_CHECKSUMP(ipha, IP_SIMPLE_HDR_LENGTH); - cksum = IP_UDP_CSUM_COMP; - break; - default: - cmn_err(CE_WARN, "xnf_pseudo_cksum: unexpected protocol %d", - ipha->ipha_protocol); - return; - } - - src = ipha->ipha_src; - dst = ipha->ipha_dst; - - cksum += (dst >> 16) + (dst & 0xFFFF); - cksum += (src >> 16) + (src & 0xFFFF); - cksum += htons(len); - - cksum = (cksum >> 16) + (cksum & 0xFFFF); - cksum = (cksum >> 16) + (cksum & 0xFFFF); - - ASSERT(cksum <= 0xFFFF); - - *stuff = (uint16_t)(cksum ? cksum : ~cksum); -} - -/* - * Push a list of prepared packets (`txp') into the transmit ring. - */ -static xnf_txbuf_t * -tx_push_packets(xnf_t *xnfp, xnf_txbuf_t *txp) -{ - int slots_free; - RING_IDX slot; - boolean_t notify; - - mutex_enter(&xnfp->xnf_txlock); - - ASSERT(xnfp->xnf_running); - - /* - * Wait until we are connected to the backend. - */ - while (!xnfp->xnf_connected) - cv_wait(&xnfp->xnf_cv_state, &xnfp->xnf_txlock); - - slots_free = tx_slots_get(xnfp, 1, B_FALSE); - DTRACE_PROBE1(xnf_send_slotsfree, int, slots_free); - - slot = xnfp->xnf_tx_ring.req_prod_pvt; - - while ((txp != NULL) && (slots_free > 0)) { - xnf_txid_t *tidp; - netif_tx_request_t *txrp; - - tidp = txid_get(xnfp); - VERIFY(tidp != NULL); - - txrp = RING_GET_REQUEST(&xnfp->xnf_tx_ring, slot); - - txp->tx_slot = slot; - txp->tx_txreq.id = tidp->id; - *txrp = txp->tx_txreq; - - tidp->txbuf = txp; - - xnfp->xnf_stat_opackets++; - xnfp->xnf_stat_obytes += txp->tx_txreq.size; - - txp = txp->tx_next; - slots_free--; - slot++; - - } - - xnfp->xnf_tx_ring.req_prod_pvt = slot; - - /* - * Tell the peer that we sent something, if it cares. - */ - /* LINTED: constant in conditional context */ - RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xnfp->xnf_tx_ring, - notify); - if (notify) - ec_notify_via_evtchn(xnfp->xnf_evtchn); - - mutex_exit(&xnfp->xnf_txlock); - - return (txp); -} - -/* - * Send the chain of packets `mp'. Called by the MAC framework. - */ -static mblk_t * -xnf_send(void *arg, mblk_t *mp) -{ - xnf_t *xnfp = arg; - domid_t oeid; - xnf_txbuf_t *head, *tail; - mblk_t *ml; - int prepared; - - oeid = xvdi_get_oeid(xnfp->xnf_devinfo); - - /* - * Prepare packets for transmission. - */ - head = tail = NULL; - prepared = 0; - while (mp != NULL) { - xnf_txbuf_t *txp; - int n_chunks, length; - boolean_t page_oops; - uint32_t pflags; - - for (ml = mp, n_chunks = length = 0, page_oops = B_FALSE; - ml != NULL; - ml = ml->b_cont, n_chunks++) { - - /* - * Test if this buffer includes a page - * boundary. The test assumes that the range - * b_rptr...b_wptr can include only a single - * boundary. - */ - if (xnf_btop((size_t)ml->b_rptr) != - xnf_btop((size_t)ml->b_wptr)) { - xnfp->xnf_stat_tx_pagebndry++; - page_oops = B_TRUE; - } - - length += MBLKL(ml); - } - DTRACE_PROBE1(xnf_send_b_cont, int, n_chunks); - - /* - * Make sure packet isn't too large. - */ - if (length > XNF_FRAMESIZE) { - cmn_err(CE_WARN, - "xnf%d: oversized packet (%d bytes) dropped", - ddi_get_instance(xnfp->xnf_devinfo), length); - freemsg(mp); - continue; - } - - txp = kmem_cache_alloc(xnfp->xnf_tx_buf_cache, KM_SLEEP); - - txp->tx_type = TX_DATA; - - if ((n_chunks > xnf_max_tx_frags) || page_oops) { - /* - * Loan a side buffer rather than the mblk - * itself. - */ - txp->tx_bdesc = xnf_tx_pullup(xnfp, mp); - if (txp->tx_bdesc == NULL) { - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - break; - } - - txp->tx_bufp = txp->tx_bdesc->buf; - txp->tx_mfn = txp->tx_bdesc->buf_mfn; - txp->tx_txreq.gref = txp->tx_bdesc->grant_ref; - - } else { - int rc; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - - rc = ddi_dma_addr_bind_handle(txp->tx_dma_handle, - NULL, (char *)mp->b_rptr, length, - DDI_DMA_WRITE | DDI_DMA_STREAMING, - DDI_DMA_DONTWAIT, 0, &dma_cookie, - &ncookies); - if (rc != DDI_DMA_MAPPED) { - ASSERT(rc != DDI_DMA_INUSE); - ASSERT(rc != DDI_DMA_PARTIAL_MAP); - -#ifdef XNF_DEBUG - if (rc != DDI_DMA_NORESOURCES) - cmn_err(CE_WARN, - "xnf%d: bind_handle failed (%x)", - ddi_get_instance(xnfp->xnf_devinfo), - rc); -#endif - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - break; - } - ASSERT(ncookies == 1); - - txp->tx_bdesc = NULL; - txp->tx_bufp = (caddr_t)mp->b_rptr; - txp->tx_mfn = - xnf_btop(pa_to_ma(dma_cookie.dmac_laddress)); - txp->tx_txreq.gref = gref_get(xnfp); - if (txp->tx_txreq.gref == INVALID_GRANT_REF) { - (void) ddi_dma_unbind_handle( - txp->tx_dma_handle); - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - break; - } - gnttab_grant_foreign_access_ref(txp->tx_txreq.gref, - oeid, txp->tx_mfn, 1); - } - - txp->tx_next = NULL; - txp->tx_mp = mp; - txp->tx_txreq.size = length; - txp->tx_txreq.offset = (uintptr_t)txp->tx_bufp & PAGEOFFSET; - txp->tx_txreq.flags = 0; - mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &pflags); - if (pflags != 0) { - /* - * If the local protocol stack requests checksum - * offload we set the 'checksum blank' flag, - * indicating to the peer that we need the checksum - * calculated for us. - * - * We _don't_ set the validated flag, because we haven't - * validated that the data and the checksum match. - */ - xnf_pseudo_cksum(txp->tx_bufp, length); - txp->tx_txreq.flags |= NETTXF_csum_blank; - - xnfp->xnf_stat_tx_cksum_deferred++; - } - - if (head == NULL) { - ASSERT(tail == NULL); - - head = txp; - } else { - ASSERT(tail != NULL); - - tail->tx_next = txp; - } - tail = txp; - - mp = mp->b_next; - prepared++; - - /* - * There is no point in preparing more than - * NET_TX_RING_SIZE, as we won't be able to push them - * into the ring in one go and would hence have to - * un-prepare the extra. - */ - if (prepared == NET_TX_RING_SIZE) - break; - } - - DTRACE_PROBE1(xnf_send_prepared, int, prepared); - - if (mp != NULL) { -#ifdef XNF_DEBUG - int notprepared = 0; - mblk_t *l = mp; - - while (l != NULL) { - notprepared++; - l = l->b_next; - } - - DTRACE_PROBE1(xnf_send_notprepared, int, notprepared); -#else /* !XNF_DEBUG */ - DTRACE_PROBE1(xnf_send_notprepared, int, -1); -#endif /* XNF_DEBUG */ - } - - /* - * Push the packets we have prepared into the ring. They may - * not all go. - */ - if (head != NULL) - head = tx_push_packets(xnfp, head); - - /* - * If some packets that we prepared were not sent, unprepare - * them and add them back to the head of those we didn't - * prepare. - */ - { - xnf_txbuf_t *loop; - mblk_t *mp_head, *mp_tail; - int unprepared = 0; - - mp_head = mp_tail = NULL; - loop = head; - - while (loop != NULL) { - xnf_txbuf_t *next = loop->tx_next; - - if (loop->tx_bdesc == NULL) { - (void) gnttab_end_foreign_access_ref( - loop->tx_txreq.gref, 1); - gref_put(xnfp, loop->tx_txreq.gref); - (void) ddi_dma_unbind_handle( - loop->tx_dma_handle); - } else { - xnf_buf_put(xnfp, loop->tx_bdesc, B_TRUE); - } - - ASSERT(loop->tx_mp != NULL); - if (mp_head == NULL) - mp_head = loop->tx_mp; - mp_tail = loop->tx_mp; - - kmem_cache_free(xnfp->xnf_tx_buf_cache, loop); - loop = next; - unprepared++; - } - - if (mp_tail == NULL) { - ASSERT(mp_head == NULL); - } else { - ASSERT(mp_head != NULL); - - mp_tail->b_next = mp; - mp = mp_head; - } - - DTRACE_PROBE1(xnf_send_unprepared, int, unprepared); - } - - /* - * If any mblks are left then we have deferred for some reason - * and need to ask for a re-schedule later. This is typically - * due to the ring filling. - */ - if (mp != NULL) { - mutex_enter(&xnfp->xnf_schedlock); - xnfp->xnf_need_sched = B_TRUE; - mutex_exit(&xnfp->xnf_schedlock); - - xnfp->xnf_stat_tx_defer++; - } - - return (mp); -} - -/* - * Notification of RX packets. Currently no TX-complete interrupt is - * used, as we clean the TX ring lazily. - */ -static uint_t -xnf_intr(caddr_t arg) -{ - xnf_t *xnfp = (xnf_t *)arg; - mblk_t *mp; - boolean_t need_sched, clean_ring; - - mutex_enter(&xnfp->xnf_rxlock); - - /* - * Interrupts before we are connected are spurious. - */ - if (!xnfp->xnf_connected) { - mutex_exit(&xnfp->xnf_rxlock); - xnfp->xnf_stat_unclaimed_interrupts++; - return (DDI_INTR_UNCLAIMED); - } - - /* - * Receive side processing. - */ - do { - /* - * Collect buffers from the ring. - */ - xnf_rx_collect(xnfp); - - /* - * Interrupt me when the next receive buffer is consumed. - */ - xnfp->xnf_rx_ring.sring->rsp_event = - xnfp->xnf_rx_ring.rsp_cons + 1; - xen_mb(); - - } while (RING_HAS_UNCONSUMED_RESPONSES(&xnfp->xnf_rx_ring)); - - if (xnfp->xnf_rx_new_buffers_posted) { - boolean_t notify; - - /* - * Indicate to the peer that we have re-filled the - * receive ring, if it cares. - */ - /* LINTED: constant in conditional context */ - RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xnfp->xnf_rx_ring, notify); - if (notify) - ec_notify_via_evtchn(xnfp->xnf_evtchn); - xnfp->xnf_rx_new_buffers_posted = B_FALSE; - } - - mp = xnfp->xnf_rx_head; - xnfp->xnf_rx_head = xnfp->xnf_rx_tail = NULL; - - xnfp->xnf_stat_interrupts++; - mutex_exit(&xnfp->xnf_rxlock); - - if (mp != NULL) - mac_rx(xnfp->xnf_mh, NULL, mp); - - /* - * Transmit side processing. - * - * If a previous transmit attempt failed or we have pending - * multicast requests, clean the ring. - * - * If we previously stalled transmission and cleaning produces - * some free slots, tell upstream to attempt sending again. - * - * The odd style is to avoid acquiring xnf_txlock unless we - * will actually look inside the tx machinery. - */ - mutex_enter(&xnfp->xnf_schedlock); - need_sched = xnfp->xnf_need_sched; - clean_ring = need_sched || (xnfp->xnf_pending_multicast > 0); - mutex_exit(&xnfp->xnf_schedlock); - - if (clean_ring) { - int free_slots; - - mutex_enter(&xnfp->xnf_txlock); - free_slots = tx_slots_get(xnfp, 0, B_FALSE); - - if (need_sched && (free_slots > 0)) { - mutex_enter(&xnfp->xnf_schedlock); - xnfp->xnf_need_sched = B_FALSE; - mutex_exit(&xnfp->xnf_schedlock); - - mac_tx_update(xnfp->xnf_mh); - } - mutex_exit(&xnfp->xnf_txlock); - } - - return (DDI_INTR_CLAIMED); -} - -/* - * xnf_start() -- start the board receiving and enable interrupts. - */ -static int -xnf_start(void *arg) -{ - xnf_t *xnfp = arg; - -#ifdef XNF_DEBUG - if (xnf_debug & XNF_DEBUG_TRACE) - printf("xnf%d start(0x%p)\n", - ddi_get_instance(xnfp->xnf_devinfo), (void *)xnfp); -#endif - - mutex_enter(&xnfp->xnf_rxlock); - mutex_enter(&xnfp->xnf_txlock); - - /* Accept packets from above. */ - xnfp->xnf_running = B_TRUE; - - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); - - return (0); -} - -/* xnf_stop() - disable hardware */ -static void -xnf_stop(void *arg) -{ - xnf_t *xnfp = arg; - -#ifdef XNF_DEBUG - if (xnf_debug & XNF_DEBUG_TRACE) - printf("xnf%d stop(0x%p)\n", - ddi_get_instance(xnfp->xnf_devinfo), (void *)xnfp); -#endif - - mutex_enter(&xnfp->xnf_rxlock); - mutex_enter(&xnfp->xnf_txlock); - - xnfp->xnf_running = B_FALSE; - - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); -} - -/* - * Hang buffer `bdesc' on the RX ring. - */ -static void -xnf_rxbuf_hang(xnf_t *xnfp, xnf_buf_t *bdesc) -{ - netif_rx_request_t *reqp; - RING_IDX hang_ix; - - ASSERT(MUTEX_HELD(&xnfp->xnf_rxlock)); - - reqp = RING_GET_REQUEST(&xnfp->xnf_rx_ring, - xnfp->xnf_rx_ring.req_prod_pvt); - hang_ix = (RING_IDX) (reqp - RING_GET_REQUEST(&xnfp->xnf_rx_ring, 0)); - ASSERT(xnfp->xnf_rx_pkt_info[hang_ix] == NULL); - - reqp->id = bdesc->id = hang_ix; - reqp->gref = bdesc->grant_ref; - - xnfp->xnf_rx_pkt_info[hang_ix] = bdesc; - xnfp->xnf_rx_ring.req_prod_pvt++; - - xnfp->xnf_rx_new_buffers_posted = B_TRUE; -} - -/* - * Collect packets from the RX ring, storing them in `xnfp' for later - * use. - */ -static void -xnf_rx_collect(xnf_t *xnfp) -{ - mblk_t *head, *tail; - - ASSERT(MUTEX_HELD(&xnfp->xnf_rxlock)); - - /* - * Loop over unconsumed responses: - * 1. get a response - * 2. take corresponding buffer off recv. ring - * 3. indicate this by setting slot to NULL - * 4. create a new message and - * 5. copy data in, adjust ptr - */ - - head = tail = NULL; - - while (RING_HAS_UNCONSUMED_RESPONSES(&xnfp->xnf_rx_ring)) { - netif_rx_response_t *rxpkt; - xnf_buf_t *bdesc; - ssize_t len; - size_t off; - mblk_t *mp = NULL; - boolean_t hwcsum = B_FALSE; - grant_ref_t ref; - - /* 1. */ - rxpkt = RING_GET_RESPONSE(&xnfp->xnf_rx_ring, - xnfp->xnf_rx_ring.rsp_cons); - - DTRACE_PROBE4(xnf_rx_got_rsp, int, (int)rxpkt->id, - int, (int)rxpkt->offset, - int, (int)rxpkt->flags, - int, (int)rxpkt->status); - - /* - * 2. - */ - bdesc = xnfp->xnf_rx_pkt_info[rxpkt->id]; - - /* - * 3. - */ - xnfp->xnf_rx_pkt_info[rxpkt->id] = NULL; - ASSERT(bdesc->id == rxpkt->id); - - ref = bdesc->grant_ref; - off = rxpkt->offset; - len = rxpkt->status; - - if (!xnfp->xnf_running) { - DTRACE_PROBE4(xnf_rx_not_running, - int, rxpkt->status, - char *, bdesc->buf, int, rxpkt->offset, - char *, ((char *)bdesc->buf) + rxpkt->offset); - - xnfp->xnf_stat_drop++; - - } else if (len <= 0) { - DTRACE_PROBE4(xnf_rx_pkt_status_negative, - int, rxpkt->status, - char *, bdesc->buf, int, rxpkt->offset, - char *, ((char *)bdesc->buf) + rxpkt->offset); - - xnfp->xnf_stat_errrx++; - - switch (len) { - case 0: - xnfp->xnf_stat_runt++; - break; - case NETIF_RSP_ERROR: - xnfp->xnf_stat_mac_rcv_error++; - break; - case NETIF_RSP_DROPPED: - xnfp->xnf_stat_norxbuf++; - break; - } - - } else if (bdesc->grant_ref == INVALID_GRANT_REF) { - cmn_err(CE_WARN, "Bad rx grant reference %d " - "from domain %d", ref, - xvdi_get_oeid(xnfp->xnf_devinfo)); - - } else if ((off + len) > PAGESIZE) { - cmn_err(CE_WARN, "Rx packet overflows page " - "(offset %ld, length %ld) from domain %d", - off, len, xvdi_get_oeid(xnfp->xnf_devinfo)); - } else { - xnf_buf_t *nbuf = NULL; - - DTRACE_PROBE4(xnf_rx_packet, int, len, - char *, bdesc->buf, int, off, - char *, ((char *)bdesc->buf) + off); - - ASSERT(off + len <= PAGEOFFSET); - - if (rxpkt->flags & NETRXF_data_validated) - hwcsum = B_TRUE; - - /* - * If the packet is below a pre-determined - * size we will copy data out rather than - * replace it. - */ - if (len > xnf_rx_copy_limit) - nbuf = xnf_buf_get(xnfp, KM_NOSLEEP, B_FALSE); - - /* - * If we have a replacement buffer, attempt to - * wrap the existing one with an mblk_t in - * order that the upper layers of the stack - * might use it directly. - */ - if (nbuf != NULL) { - mp = desballoc((unsigned char *)bdesc->buf, - bdesc->len, 0, &bdesc->free_rtn); - if (mp == NULL) { - xnfp->xnf_stat_rx_desballoc_fail++; - xnfp->xnf_stat_norxbuf++; - - xnf_buf_put(xnfp, nbuf, B_FALSE); - nbuf = NULL; - } else { - mp->b_rptr = mp->b_rptr + off; - mp->b_wptr = mp->b_rptr + len; - - /* - * Release the grant reference - * associated with this buffer - * - they are scarce and the - * upper layers of the stack - * don't need it. - */ - (void) gnttab_end_foreign_access_ref( - bdesc->grant_ref, 0); - gref_put(xnfp, bdesc->grant_ref); - bdesc->grant_ref = INVALID_GRANT_REF; - - bdesc = nbuf; - } - } - - if (nbuf == NULL) { - /* - * No replacement buffer allocated - - * attempt to copy the data out and - * re-hang the existing buffer. - */ - - /* 4. */ - mp = allocb(len, BPRI_MED); - if (mp == NULL) { - xnfp->xnf_stat_rx_allocb_fail++; - xnfp->xnf_stat_norxbuf++; - } else { - /* 5. */ - bcopy(bdesc->buf + off, mp->b_wptr, - len); - mp->b_wptr += len; - } - } - } - - /* Re-hang the buffer. */ - xnf_rxbuf_hang(xnfp, bdesc); - - if (mp != NULL) { - if (hwcsum) { - /* - * If the peer says that the data has - * been validated then we declare that - * the full checksum has been - * verified. - * - * We don't look at the "checksum - * blank" flag, and hence could have a - * packet here that we are asserting - * is good with a blank checksum. - */ - mac_hcksum_set(mp, 0, 0, 0, 0, - HCK_FULLCKSUM_OK); - xnfp->xnf_stat_rx_cksum_no_need++; - } - if (head == NULL) { - ASSERT(tail == NULL); - - head = mp; - } else { - ASSERT(tail != NULL); - - tail->b_next = mp; - } - tail = mp; - - ASSERT(mp->b_next == NULL); - - xnfp->xnf_stat_ipackets++; - xnfp->xnf_stat_rbytes += len; - } - - xnfp->xnf_rx_ring.rsp_cons++; - } - - /* - * Store the mblks we have collected. - */ - if (head != NULL) { - ASSERT(tail != NULL); - - if (xnfp->xnf_rx_head == NULL) { - ASSERT(xnfp->xnf_rx_tail == NULL); - - xnfp->xnf_rx_head = head; - } else { - ASSERT(xnfp->xnf_rx_tail != NULL); - - xnfp->xnf_rx_tail->b_next = head; - } - xnfp->xnf_rx_tail = tail; - } -} - -/* - * xnf_alloc_dma_resources() -- initialize the drivers structures - */ -static int -xnf_alloc_dma_resources(xnf_t *xnfp) -{ - dev_info_t *devinfo = xnfp->xnf_devinfo; - size_t len; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - int rc; - caddr_t rptr; - - /* - * The code below allocates all the DMA data structures that - * need to be released when the driver is detached. - * - * Allocate page for the transmit descriptor ring. - */ - if (ddi_dma_alloc_handle(devinfo, &ringbuf_dma_attr, - DDI_DMA_SLEEP, 0, &xnfp->xnf_tx_ring_dma_handle) != DDI_SUCCESS) - goto alloc_error; - - if (ddi_dma_mem_alloc(xnfp->xnf_tx_ring_dma_handle, - PAGESIZE, &accattr, DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, 0, &rptr, &len, - &xnfp->xnf_tx_ring_dma_acchandle) != DDI_SUCCESS) { - ddi_dma_free_handle(&xnfp->xnf_tx_ring_dma_handle); - xnfp->xnf_tx_ring_dma_handle = NULL; - goto alloc_error; - } - - if ((rc = ddi_dma_addr_bind_handle(xnfp->xnf_tx_ring_dma_handle, NULL, - rptr, PAGESIZE, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies)) != DDI_DMA_MAPPED) { - ddi_dma_mem_free(&xnfp->xnf_tx_ring_dma_acchandle); - ddi_dma_free_handle(&xnfp->xnf_tx_ring_dma_handle); - xnfp->xnf_tx_ring_dma_handle = NULL; - xnfp->xnf_tx_ring_dma_acchandle = NULL; - if (rc == DDI_DMA_NORESOURCES) - goto alloc_error; - else - goto error; - } - - ASSERT(ncookies == 1); - bzero(rptr, PAGESIZE); - /* LINTED: constant in conditional context */ - SHARED_RING_INIT((netif_tx_sring_t *)rptr); - /* LINTED: constant in conditional context */ - FRONT_RING_INIT(&xnfp->xnf_tx_ring, (netif_tx_sring_t *)rptr, PAGESIZE); - xnfp->xnf_tx_ring_phys_addr = dma_cookie.dmac_laddress; - - /* - * Allocate page for the receive descriptor ring. - */ - if (ddi_dma_alloc_handle(devinfo, &ringbuf_dma_attr, - DDI_DMA_SLEEP, 0, &xnfp->xnf_rx_ring_dma_handle) != DDI_SUCCESS) - goto alloc_error; - - if (ddi_dma_mem_alloc(xnfp->xnf_rx_ring_dma_handle, - PAGESIZE, &accattr, DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, 0, &rptr, &len, - &xnfp->xnf_rx_ring_dma_acchandle) != DDI_SUCCESS) { - ddi_dma_free_handle(&xnfp->xnf_rx_ring_dma_handle); - xnfp->xnf_rx_ring_dma_handle = NULL; - goto alloc_error; - } - - if ((rc = ddi_dma_addr_bind_handle(xnfp->xnf_rx_ring_dma_handle, NULL, - rptr, PAGESIZE, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies)) != DDI_DMA_MAPPED) { - ddi_dma_mem_free(&xnfp->xnf_rx_ring_dma_acchandle); - ddi_dma_free_handle(&xnfp->xnf_rx_ring_dma_handle); - xnfp->xnf_rx_ring_dma_handle = NULL; - xnfp->xnf_rx_ring_dma_acchandle = NULL; - if (rc == DDI_DMA_NORESOURCES) - goto alloc_error; - else - goto error; - } - - ASSERT(ncookies == 1); - bzero(rptr, PAGESIZE); - /* LINTED: constant in conditional context */ - SHARED_RING_INIT((netif_rx_sring_t *)rptr); - /* LINTED: constant in conditional context */ - FRONT_RING_INIT(&xnfp->xnf_rx_ring, (netif_rx_sring_t *)rptr, PAGESIZE); - xnfp->xnf_rx_ring_phys_addr = dma_cookie.dmac_laddress; - - return (DDI_SUCCESS); - -alloc_error: - cmn_err(CE_WARN, "xnf%d: could not allocate enough DMA memory", - ddi_get_instance(xnfp->xnf_devinfo)); -error: - xnf_release_dma_resources(xnfp); - return (DDI_FAILURE); -} - -/* - * Release all DMA resources in the opposite order from acquisition - */ -static void -xnf_release_dma_resources(xnf_t *xnfp) -{ - int i; - - /* - * Free receive buffers which are currently associated with - * descriptors. - */ - mutex_enter(&xnfp->xnf_rxlock); - for (i = 0; i < NET_RX_RING_SIZE; i++) { - xnf_buf_t *bp; - - if ((bp = xnfp->xnf_rx_pkt_info[i]) == NULL) - continue; - xnfp->xnf_rx_pkt_info[i] = NULL; - xnf_buf_put(xnfp, bp, B_FALSE); - } - mutex_exit(&xnfp->xnf_rxlock); - - /* Free the receive ring buffer. */ - if (xnfp->xnf_rx_ring_dma_acchandle != NULL) { - (void) ddi_dma_unbind_handle(xnfp->xnf_rx_ring_dma_handle); - ddi_dma_mem_free(&xnfp->xnf_rx_ring_dma_acchandle); - ddi_dma_free_handle(&xnfp->xnf_rx_ring_dma_handle); - xnfp->xnf_rx_ring_dma_acchandle = NULL; - } - /* Free the transmit ring buffer. */ - if (xnfp->xnf_tx_ring_dma_acchandle != NULL) { - (void) ddi_dma_unbind_handle(xnfp->xnf_tx_ring_dma_handle); - ddi_dma_mem_free(&xnfp->xnf_tx_ring_dma_acchandle); - ddi_dma_free_handle(&xnfp->xnf_tx_ring_dma_handle); - xnfp->xnf_tx_ring_dma_acchandle = NULL; - } - -} - -/* - * Release any packets and associated structures used by the TX ring. - */ -static void -xnf_release_mblks(xnf_t *xnfp) -{ - RING_IDX i; - xnf_txid_t *tidp; - - for (i = 0, tidp = &xnfp->xnf_tx_pkt_id[0]; - i < NET_TX_RING_SIZE; - i++, tidp++) { - xnf_txbuf_t *txp = tidp->txbuf; - - if (txp != NULL) { - ASSERT(txp->tx_mp != NULL); - freemsg(txp->tx_mp); - - txid_put(xnfp, tidp); - kmem_cache_free(xnfp->xnf_tx_buf_cache, txp); - } - } -} - -static int -xnf_buf_constructor(void *buf, void *arg, int kmflag) -{ - int (*ddiflags)(caddr_t) = DDI_DMA_SLEEP; - xnf_buf_t *bdesc = buf; - xnf_t *xnfp = arg; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - size_t len; - - if (kmflag & KM_NOSLEEP) - ddiflags = DDI_DMA_DONTWAIT; - - /* Allocate a DMA access handle for the buffer. */ - if (ddi_dma_alloc_handle(xnfp->xnf_devinfo, &buf_dma_attr, - ddiflags, 0, &bdesc->dma_handle) != DDI_SUCCESS) - goto failure; - - /* Allocate DMA-able memory for buffer. */ - if (ddi_dma_mem_alloc(bdesc->dma_handle, - PAGESIZE, &data_accattr, DDI_DMA_STREAMING, ddiflags, 0, - &bdesc->buf, &len, &bdesc->acc_handle) != DDI_SUCCESS) - goto failure_1; - - /* Bind to virtual address of buffer to get physical address. */ - if (ddi_dma_addr_bind_handle(bdesc->dma_handle, NULL, - bdesc->buf, len, DDI_DMA_RDWR | DDI_DMA_STREAMING, - ddiflags, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) - goto failure_2; - ASSERT(ncookies == 1); - - bdesc->free_rtn.free_func = xnf_buf_recycle; - bdesc->free_rtn.free_arg = (caddr_t)bdesc; - bdesc->xnfp = xnfp; - bdesc->buf_phys = dma_cookie.dmac_laddress; - bdesc->buf_mfn = pfn_to_mfn(xnf_btop(bdesc->buf_phys)); - bdesc->len = dma_cookie.dmac_size; - bdesc->grant_ref = INVALID_GRANT_REF; - bdesc->gen = xnfp->xnf_gen; - - atomic_inc_64(&xnfp->xnf_stat_buf_allocated); - - return (0); - -failure_2: - ddi_dma_mem_free(&bdesc->acc_handle); - -failure_1: - ddi_dma_free_handle(&bdesc->dma_handle); - -failure: - - ASSERT(kmflag & KM_NOSLEEP); /* Cannot fail for KM_SLEEP. */ - return (-1); -} - -static void -xnf_buf_destructor(void *buf, void *arg) -{ - xnf_buf_t *bdesc = buf; - xnf_t *xnfp = arg; - - (void) ddi_dma_unbind_handle(bdesc->dma_handle); - ddi_dma_mem_free(&bdesc->acc_handle); - ddi_dma_free_handle(&bdesc->dma_handle); - - atomic_dec_64(&xnfp->xnf_stat_buf_allocated); -} - -static xnf_buf_t * -xnf_buf_get(xnf_t *xnfp, int flags, boolean_t readonly) -{ - grant_ref_t gref; - xnf_buf_t *bufp; - - /* - * Usually grant references are more scarce than memory, so we - * attempt to acquire a grant reference first. - */ - gref = gref_get(xnfp); - if (gref == INVALID_GRANT_REF) - return (NULL); - - bufp = kmem_cache_alloc(xnfp->xnf_buf_cache, flags); - if (bufp == NULL) { - gref_put(xnfp, gref); - return (NULL); - } - - ASSERT(bufp->grant_ref == INVALID_GRANT_REF); - - bufp->grant_ref = gref; - - if (bufp->gen != xnfp->xnf_gen) - xnf_buf_refresh(bufp); - - gnttab_grant_foreign_access_ref(bufp->grant_ref, - xvdi_get_oeid(bufp->xnfp->xnf_devinfo), - bufp->buf_mfn, readonly ? 1 : 0); - - atomic_inc_64(&xnfp->xnf_stat_buf_outstanding); - - return (bufp); -} - -static void -xnf_buf_put(xnf_t *xnfp, xnf_buf_t *bufp, boolean_t readonly) -{ - if (bufp->grant_ref != INVALID_GRANT_REF) { - (void) gnttab_end_foreign_access_ref( - bufp->grant_ref, readonly ? 1 : 0); - gref_put(xnfp, bufp->grant_ref); - bufp->grant_ref = INVALID_GRANT_REF; - } - - kmem_cache_free(xnfp->xnf_buf_cache, bufp); - - atomic_dec_64(&xnfp->xnf_stat_buf_outstanding); -} - -/* - * Refresh any cached data about a buffer after resume. - */ -static void -xnf_buf_refresh(xnf_buf_t *bdesc) -{ - bdesc->buf_mfn = pfn_to_mfn(xnf_btop(bdesc->buf_phys)); - bdesc->gen = bdesc->xnfp->xnf_gen; -} - -/* - * Streams `freeb' routine for `xnf_buf_t' when used as transmit - * look-aside buffers. - */ -static void -xnf_buf_recycle(xnf_buf_t *bdesc) -{ - xnf_t *xnfp = bdesc->xnfp; - - xnf_buf_put(xnfp, bdesc, B_TRUE); -} - -static int -xnf_tx_buf_constructor(void *buf, void *arg, int kmflag) -{ - int (*ddiflags)(caddr_t) = DDI_DMA_SLEEP; - xnf_txbuf_t *txp = buf; - xnf_t *xnfp = arg; - - if (kmflag & KM_NOSLEEP) - ddiflags = DDI_DMA_DONTWAIT; - - if (ddi_dma_alloc_handle(xnfp->xnf_devinfo, &buf_dma_attr, - ddiflags, 0, &txp->tx_dma_handle) != DDI_SUCCESS) { - ASSERT(kmflag & KM_NOSLEEP); /* Cannot fail for KM_SLEEP. */ - return (-1); - } - - return (0); -} - -static void -xnf_tx_buf_destructor(void *buf, void *arg) -{ - _NOTE(ARGUNUSED(arg)); - xnf_txbuf_t *txp = buf; - - ddi_dma_free_handle(&txp->tx_dma_handle); -} - -/* - * Statistics. - */ -static char *xnf_aux_statistics[] = { - "tx_cksum_deferred", - "rx_cksum_no_need", - "interrupts", - "unclaimed_interrupts", - "tx_pullup", - "tx_pagebndry", - "tx_attempt", - "buf_allocated", - "buf_outstanding", - "gref_outstanding", - "gref_failure", - "gref_peak", - "rx_allocb_fail", - "rx_desballoc_fail", -}; - -static int -xnf_kstat_aux_update(kstat_t *ksp, int flag) -{ - xnf_t *xnfp; - kstat_named_t *knp; - - if (flag != KSTAT_READ) - return (EACCES); - - xnfp = ksp->ks_private; - knp = ksp->ks_data; - - /* - * Assignment order must match that of the names in - * xnf_aux_statistics. - */ - (knp++)->value.ui64 = xnfp->xnf_stat_tx_cksum_deferred; - (knp++)->value.ui64 = xnfp->xnf_stat_rx_cksum_no_need; - - (knp++)->value.ui64 = xnfp->xnf_stat_interrupts; - (knp++)->value.ui64 = xnfp->xnf_stat_unclaimed_interrupts; - (knp++)->value.ui64 = xnfp->xnf_stat_tx_pullup; - (knp++)->value.ui64 = xnfp->xnf_stat_tx_pagebndry; - (knp++)->value.ui64 = xnfp->xnf_stat_tx_attempt; - - (knp++)->value.ui64 = xnfp->xnf_stat_buf_allocated; - (knp++)->value.ui64 = xnfp->xnf_stat_buf_outstanding; - (knp++)->value.ui64 = xnfp->xnf_stat_gref_outstanding; - (knp++)->value.ui64 = xnfp->xnf_stat_gref_failure; - (knp++)->value.ui64 = xnfp->xnf_stat_gref_peak; - (knp++)->value.ui64 = xnfp->xnf_stat_rx_allocb_fail; - (knp++)->value.ui64 = xnfp->xnf_stat_rx_desballoc_fail; - - return (0); -} - -static boolean_t -xnf_kstat_init(xnf_t *xnfp) -{ - int nstat = sizeof (xnf_aux_statistics) / - sizeof (xnf_aux_statistics[0]); - char **cp = xnf_aux_statistics; - kstat_named_t *knp; - - /* - * Create and initialise kstats. - */ - if ((xnfp->xnf_kstat_aux = kstat_create("xnf", - ddi_get_instance(xnfp->xnf_devinfo), - "aux_statistics", "net", KSTAT_TYPE_NAMED, - nstat, 0)) == NULL) - return (B_FALSE); - - xnfp->xnf_kstat_aux->ks_private = xnfp; - xnfp->xnf_kstat_aux->ks_update = xnf_kstat_aux_update; - - knp = xnfp->xnf_kstat_aux->ks_data; - while (nstat > 0) { - kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); - - knp++; - cp++; - nstat--; - } - - kstat_install(xnfp->xnf_kstat_aux); - - return (B_TRUE); -} - -static int -xnf_stat(void *arg, uint_t stat, uint64_t *val) -{ - xnf_t *xnfp = arg; - - mutex_enter(&xnfp->xnf_rxlock); - mutex_enter(&xnfp->xnf_txlock); - -#define mac_stat(q, r) \ - case (MAC_STAT_##q): \ - *val = xnfp->xnf_stat_##r; \ - break - -#define ether_stat(q, r) \ - case (ETHER_STAT_##q): \ - *val = xnfp->xnf_stat_##r; \ - break - - switch (stat) { - - mac_stat(IPACKETS, ipackets); - mac_stat(OPACKETS, opackets); - mac_stat(RBYTES, rbytes); - mac_stat(OBYTES, obytes); - mac_stat(NORCVBUF, norxbuf); - mac_stat(IERRORS, errrx); - mac_stat(NOXMTBUF, tx_defer); - - ether_stat(MACRCV_ERRORS, mac_rcv_error); - ether_stat(TOOSHORT_ERRORS, runt); - - /* always claim to be in full duplex mode */ - case ETHER_STAT_LINK_DUPLEX: - *val = LINK_DUPLEX_FULL; - break; - - /* always claim to be at 1Gb/s link speed */ - case MAC_STAT_IFSPEED: - *val = 1000000000ull; - break; - - default: - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); - - return (ENOTSUP); - } - -#undef mac_stat -#undef ether_stat - - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); - - return (0); -} - -static boolean_t -xnf_getcapab(void *arg, mac_capab_t cap, void *cap_data) -{ - _NOTE(ARGUNUSED(arg)); - - switch (cap) { - case MAC_CAPAB_HCKSUM: { - uint32_t *capab = cap_data; - - /* - * Whilst the flag used to communicate with the IO - * domain is called "NETTXF_csum_blank", the checksum - * in the packet must contain the pseudo-header - * checksum and not zero. - * - * To help out the IO domain, we might use - * HCKSUM_INET_PARTIAL. Unfortunately our stack will - * then use checksum offload for IPv6 packets, which - * the IO domain can't handle. - * - * As a result, we declare outselves capable of - * HCKSUM_INET_FULL_V4. This means that we receive - * IPv4 packets from the stack with a blank checksum - * field and must insert the pseudo-header checksum - * before passing the packet to the IO domain. - */ - *capab = HCKSUM_INET_FULL_V4; - break; - } - default: - return (B_FALSE); - } - - return (B_TRUE); -} - -/* - * The state of the peer has changed - react accordingly. - */ -static void -oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, - void *arg, void *impl_data) -{ - _NOTE(ARGUNUSED(id, arg)); - xnf_t *xnfp = ddi_get_driver_private(dip); - XenbusState new_state = *(XenbusState *)impl_data; - - ASSERT(xnfp != NULL); - - switch (new_state) { - case XenbusStateUnknown: - case XenbusStateInitialising: - case XenbusStateInitialised: - case XenbusStateClosing: - case XenbusStateClosed: - case XenbusStateReconfiguring: - case XenbusStateReconfigured: - break; - - case XenbusStateInitWait: - xnf_read_config(xnfp); - - if (!xnfp->xnf_be_rx_copy) { - cmn_err(CE_WARN, - "The xnf driver requires a dom0 that " - "supports 'feature-rx-copy'."); - (void) xvdi_switch_state(xnfp->xnf_devinfo, - XBT_NULL, XenbusStateClosed); - break; - } - - /* - * Connect to the backend. - */ - xnf_be_connect(xnfp); - - /* - * Our MAC address as discovered by xnf_read_config(). - */ - mac_unicst_update(xnfp->xnf_mh, xnfp->xnf_mac_addr); - - break; - - case XenbusStateConnected: - mutex_enter(&xnfp->xnf_rxlock); - mutex_enter(&xnfp->xnf_txlock); - - xnfp->xnf_connected = B_TRUE; - /* - * Wake up any threads waiting to send data to - * backend. - */ - cv_broadcast(&xnfp->xnf_cv_state); - - mutex_exit(&xnfp->xnf_txlock); - mutex_exit(&xnfp->xnf_rxlock); - - /* - * Kick the peer in case it missed any transmits - * request in the TX ring. - */ - ec_notify_via_evtchn(xnfp->xnf_evtchn); - - /* - * There may already be completed receive requests in - * the ring sent by backend after it gets connected - * but before we see its state change here, so we call - * xnf_intr() to handle them, if any. - */ - (void) xnf_intr((caddr_t)xnfp); - - /* - * Mark the link up now that we are connected. - */ - mac_link_update(xnfp->xnf_mh, LINK_STATE_UP); - - /* - * Tell the backend about the multicast addresses in - * which we are interested. - */ - mac_multicast_refresh(xnfp->xnf_mh, NULL, xnfp, B_TRUE); - - break; - - default: - break; - } -} diff --git a/usr/src/uts/common/xen/io/xnf.h b/usr/src/uts/common/xen/io/xnf.h deleted file mode 100644 index 0c8eb2e373..0000000000 --- a/usr/src/uts/common/xen/io/xnf.h +++ /dev/null @@ -1,183 +0,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. - */ - -#ifndef _SYS_XNF_H -#define _SYS_XNF_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define NET_TX_RING_SIZE __CONST_RING_SIZE(netif_tx, PAGESIZE) -#define NET_RX_RING_SIZE __CONST_RING_SIZE(netif_rx, PAGESIZE) - -#define XNF_MAXPKT 1500 /* MTU size */ -#define XNF_FRAMESIZE 1514 /* frame size including MAC header */ - -/* DEBUG flags */ -#define XNF_DEBUG_DDI 0x01 -#define XNF_DEBUG_TRACE 0x02 - -/* - * Information about each receive buffer and any transmit look-aside - * buffers. - */ -typedef struct xnf_buf { - frtn_t free_rtn; - struct xnf *xnfp; - ddi_dma_handle_t dma_handle; - caddr_t buf; /* DMA-able data buffer */ - paddr_t buf_phys; - mfn_t buf_mfn; - size_t len; - struct xnf_buf *next; /* For linking into free list */ - ddi_acc_handle_t acc_handle; - grant_ref_t grant_ref; /* grant table reference */ - uint16_t id; /* buffer id */ - unsigned int gen; -} xnf_buf_t; - -/* - * Information about each transmit buffer. - */ -typedef struct xnf_txbuf { - struct xnf_txbuf *tx_next; - mblk_t *tx_mp; /* mblk associated with packet */ - netif_tx_request_t tx_txreq; - caddr_t tx_bufp; - ddi_dma_handle_t tx_dma_handle; - mfn_t tx_mfn; - xnf_buf_t *tx_bdesc; /* Look-aside buffer, if used. */ - unsigned char tx_type; - int16_t tx_status; - RING_IDX tx_slot; - -#define TX_DATA 1 -#define TX_MCAST_REQ 2 -#define TX_MCAST_RSP 3 -} xnf_txbuf_t; - -/* - * Information about each outstanding transmit operation. - */ -typedef struct xnf_txid { - uint16_t id; /* Id of this transmit buffer. */ - uint16_t next; /* Freelist of ids. */ - xnf_txbuf_t *txbuf; /* Buffer details. */ -} xnf_txid_t; - -/* - * Per-instance data. - */ -typedef struct xnf { - /* most interesting stuff first to assist debugging */ - dev_info_t *xnf_devinfo; - mac_handle_t xnf_mh; - unsigned char xnf_mac_addr[ETHERADDRL]; - - unsigned int xnf_gen; /* Increments on resume. */ - - boolean_t xnf_connected; - boolean_t xnf_running; - - boolean_t xnf_be_rx_copy; - boolean_t xnf_be_mcast_control; - - uint64_t xnf_stat_interrupts; - uint64_t xnf_stat_unclaimed_interrupts; - uint64_t xnf_stat_norxbuf; - uint64_t xnf_stat_drop; - uint64_t xnf_stat_errrx; - - uint64_t xnf_stat_tx_attempt; - uint64_t xnf_stat_tx_pullup; - uint64_t xnf_stat_tx_pagebndry; - uint64_t xnf_stat_tx_defer; - uint64_t xnf_stat_mac_rcv_error; - uint64_t xnf_stat_runt; - - uint64_t xnf_stat_ipackets; - uint64_t xnf_stat_opackets; - uint64_t xnf_stat_rbytes; - uint64_t xnf_stat_obytes; - - uint64_t xnf_stat_tx_cksum_deferred; - uint64_t xnf_stat_rx_cksum_no_need; - - uint64_t xnf_stat_buf_allocated; - uint64_t xnf_stat_buf_outstanding; - uint64_t xnf_stat_gref_outstanding; - uint64_t xnf_stat_gref_failure; - uint64_t xnf_stat_gref_peak; - uint64_t xnf_stat_rx_allocb_fail; - uint64_t xnf_stat_rx_desballoc_fail; - - kstat_t *xnf_kstat_aux; - - ddi_iblock_cookie_t xnf_icookie; - - netif_tx_front_ring_t xnf_tx_ring; - ddi_dma_handle_t xnf_tx_ring_dma_handle; - ddi_acc_handle_t xnf_tx_ring_dma_acchandle; - paddr_t xnf_tx_ring_phys_addr; - grant_ref_t xnf_tx_ring_ref; - - xnf_txid_t xnf_tx_pkt_id[NET_TX_RING_SIZE]; - uint16_t xnf_tx_pkt_id_head; - kmutex_t xnf_txlock; - kmutex_t xnf_schedlock; - boolean_t xnf_need_sched; - kcondvar_t xnf_cv_tx_slots; - kmem_cache_t *xnf_tx_buf_cache; - - netif_rx_front_ring_t xnf_rx_ring; - ddi_dma_handle_t xnf_rx_ring_dma_handle; - ddi_acc_handle_t xnf_rx_ring_dma_acchandle; - paddr_t xnf_rx_ring_phys_addr; - grant_ref_t xnf_rx_ring_ref; - - xnf_buf_t *xnf_rx_pkt_info[NET_RX_RING_SIZE]; - kmutex_t xnf_rxlock; - mblk_t *xnf_rx_head; - mblk_t *xnf_rx_tail; - boolean_t xnf_rx_new_buffers_posted; - kmem_cache_t *xnf_buf_cache; - - uint16_t xnf_evtchn; - - kmutex_t xnf_gref_lock; - grant_ref_t xnf_gref_head; - - kcondvar_t xnf_cv_state; - kcondvar_t xnf_cv_multicast; - uint_t xnf_pending_multicast; -} xnf_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XNF_H */ diff --git a/usr/src/uts/common/xen/io/xpv_autoconfig.c b/usr/src/uts/common/xen/io/xpv_autoconfig.c deleted file mode 100644 index a1a0556df6..0000000000 --- a/usr/src/uts/common/xen/io/xpv_autoconfig.c +++ /dev/null @@ -1,120 +0,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 2008 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 - -extern int xen_boot_debug; - -/* - * Internal structures and functions - */ -int xendev_nounload = 0; -void xendev_enumerate(int); - -/* - * Interface routines - */ - -static struct modlmisc modlmisc = { - &mod_miscops, "virtual device probe" -}; - -static struct modlinkage modlinkage = { - MODREV_1, (void *)&modlmisc, NULL -}; - -int -_init(void) -{ - int err; - - if ((err = mod_install(&modlinkage)) != 0) - return (err); - - impl_bus_add_probe(xendev_enumerate); - return (0); -} - -int -_fini(void) -{ - int err; - - if (xendev_nounload) - return (EBUSY); - - if ((err = mod_remove(&modlinkage)) != 0) - return (err); - - impl_bus_delete_probe(xendev_enumerate); - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - - -/* - * This functions is invoked twice, first time with reprogram=0 to - * set up the xpvd portion of the device tree. The second time is - * ignored. - */ -void -xendev_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); -} diff --git a/usr/src/uts/common/xen/io/xpvd.c b/usr/src/uts/common/xen/io/xpvd.c deleted file mode 100644 index 7bbd1085a0..0000000000 --- a/usr/src/uts/common/xen/io/xpvd.c +++ /dev/null @@ -1,1007 +0,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. - */ -/* - * Copyright 2012 Garrett D'Amore . All rights reserved. - */ - -/* - * Host to hypervisor virtual devices nexus driver - * - * TODO: - * - Add watchpoints on vbd/vif and enumerate/offline on watch callback - * - Add DR IOCTLs - * - Filter/restrict property lookups into xenstore - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XPV_HVM_DRIVER -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#include -#endif -#include -#include - -/* - * DDI dev_ops entrypoints - */ -static int xpvd_info(dev_info_t *, ddi_info_cmd_t, void *, void **); -static int xpvd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); -static int xpvd_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); - - -/* - * NDI bus_ops entrypoints - */ -static int xpvd_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, - void *); -static int xpvd_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, - ddi_intr_handle_impl_t *, void *); -static int xpvd_prop_op(dev_t, dev_info_t *, dev_info_t *, ddi_prop_op_t, - int, char *, caddr_t, int *); -static int xpvd_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, - void *, dev_info_t **); -static int xpvd_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t, - void *); -static int xpvd_get_eventcookie(dev_info_t *, dev_info_t *, - char *, ddi_eventcookie_t *); -static int xpvd_add_eventcall(dev_info_t *, dev_info_t *, - ddi_eventcookie_t, void (*)(dev_info_t *, - ddi_eventcookie_t, void *, void *), - void *, ddi_callback_id_t *); -static int xpvd_remove_eventcall(dev_info_t *, ddi_callback_id_t); -static int xpvd_post_event(dev_info_t *, dev_info_t *, - ddi_eventcookie_t, void *); - -/* - * misc functions - */ -static int xpvd_enable_intr(dev_info_t *, ddi_intr_handle_impl_t *, int); -static void xpvd_disable_intr(dev_info_t *, ddi_intr_handle_impl_t *, int); -static int xpvd_removechild(dev_info_t *); -static int xpvd_initchild(dev_info_t *); -static int xpvd_name_child(dev_info_t *, char *, int); -static boolean_t i_xpvd_parse_devname(char *, xendev_devclass_t *, - domid_t *, int *); - - -/* Extern declarations */ -extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, - psm_intr_op_t, int *); - -struct bus_ops xpvd_bus_ops = { - BUSO_REV, - i_ddi_bus_map, - NULL, - NULL, - NULL, - i_ddi_map_fault, - NULL, - ddi_dma_allochdl, - ddi_dma_freehdl, - ddi_dma_bindhdl, - ddi_dma_unbindhdl, - ddi_dma_flush, - ddi_dma_win, - ddi_dma_mctl, - xpvd_ctlops, - xpvd_prop_op, - xpvd_get_eventcookie, - xpvd_add_eventcall, - xpvd_remove_eventcall, - xpvd_post_event, - 0, /* (*bus_intr_ctl)(); */ - xpvd_bus_config, - xpvd_bus_unconfig, - NULL, /* (*bus_fm_init)(); */ - NULL, /* (*bus_fm_fini)(); */ - NULL, /* (*bus_fm_access_enter)(); */ - NULL, /* (*bus_fm_access_exit)(); */ - NULL, /* (*bus_power)(); */ - xpvd_intr_ops /* (*bus_intr_op)(); */ -}; - -struct dev_ops xpvd_ops = { - DEVO_REV, /* devo_rev */ - 0, /* refcnt */ - xpvd_info, /* info */ - nulldev, /* identify */ - nulldev, /* probe */ - xpvd_attach, /* attach */ - xpvd_detach, /* detach */ - nulldev, /* reset */ - NULL, /* driver operations */ - &xpvd_bus_ops, /* bus operations */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - - -dev_info_t *xpvd_dip; - -#define CF_DBG 0x1 -#define ALL_DBG 0xff - -static ndi_event_definition_t xpvd_ndi_event_defs[] = { - { 0, XS_OE_STATE, EPL_KERNEL, NDI_EVENT_POST_TO_TGT }, - { 1, XS_HP_STATE, EPL_KERNEL, NDI_EVENT_POST_TO_TGT }, -}; - -#define XENDEV_N_NDI_EVENTS \ - (sizeof (xpvd_ndi_event_defs) / sizeof (xpvd_ndi_event_defs[0])) - -static ndi_event_set_t xpvd_ndi_events = { - NDI_EVENTS_REV1, XENDEV_N_NDI_EVENTS, xpvd_ndi_event_defs -}; - -static ndi_event_hdl_t xpvd_ndi_event_handle; - -/* - * Hypervisor interrupt capabilities - */ -#define XENDEV_INTR_CAPABILITIES \ - (DDI_INTR_FLAG_EDGE | DDI_INTR_FLAG_MASKABLE | DDI_INTR_FLAG_PENDING) - -/* - * Module linkage information for the kernel. - */ - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module */ - "virtual device nexus driver", - &xpvd_ops, /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&modldrv, - NULL -}; - -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -/* ARGSUSED */ -static int -xpvd_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) -{ - switch (cmd) { - default: - return (DDI_FAILURE); - - case DDI_INFO_DEVT2INSTANCE: - *result = NULL; - return (DDI_SUCCESS); - - case DDI_INFO_DEVT2DEVINFO: - *result = (void *)xpvd_dip; - return (DDI_SUCCESS); - } -} - -/*ARGSUSED*/ -static int -xpvd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - extern void xvdi_watch_devices(int); -#ifdef XPV_HVM_DRIVER - extern dev_info_t *xpv_dip; - - if (xpv_dip == NULL) { - if (ddi_hold_installed_driver(ddi_name_to_major("xpv")) == - NULL) { - cmn_err(CE_WARN, "Couldn't initialize xpv framework"); - return (DDI_FAILURE); - } - } -#endif /* XPV_HVM_DRIVER */ - - if (ndi_event_alloc_hdl(devi, 0, &xpvd_ndi_event_handle, - NDI_SLEEP) != NDI_SUCCESS) { - xpvd_dip = NULL; - return (DDI_FAILURE); - } - if (ndi_event_bind_set(xpvd_ndi_event_handle, &xpvd_ndi_events, - NDI_SLEEP) != NDI_SUCCESS) { - (void) ndi_event_free_hdl(xpvd_ndi_event_handle); - xpvd_dip = NULL; - return (DDI_FAILURE); - } - -#ifdef XPV_HVM_DRIVER - (void) ddi_prop_update_int(DDI_DEV_T_NONE, devi, DDI_NO_AUTODETACH, 1); - - /* - * Report our version to dom0. - */ - if (xenbus_printf(XBT_NULL, "guest/xpvd", "version", "%d", - HVMPV_XPVD_VERS)) - cmn_err(CE_WARN, "xpvd: couldn't write version\n"); -#endif /* XPV_HVM_DRIVER */ - - /* watch both frontend and backend for new devices */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - (void) xs_register_xenbus_callback(xvdi_watch_devices); - else - xvdi_watch_devices(XENSTORE_UP); - - xpvd_dip = devi; - ddi_report_dev(devi); - - return (DDI_SUCCESS); -} - -/*ARGSUSED*/ -static int -xpvd_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - return (DDI_FAILURE); -} - -/* - * xpvd_prop_op() - * - * Query xenstore for the value of properties if DDI_PROP_NOTPROM - * is not set. Xenstore property values are represented as ascii strings. - */ -static int -xpvd_prop_op(dev_t dev, dev_info_t *dip, dev_info_t *ch_dip, - ddi_prop_op_t prop_op, int mod_flags, char *name, caddr_t valuep, - int *lengthp) -{ - caddr_t buff; - struct xendev_ppd *pdp; - void *prop_str; - size_t prop_len; - unsigned int len; - int rv; - - pdp = (struct xendev_ppd *)ddi_get_parent_data(ch_dip); - - if ((pdp == NULL) || !(mod_flags & (DDI_PROP_CANSLEEP)) || - (mod_flags & DDI_PROP_NOTPROM) || (pdp->xd_xsdev.nodename == NULL)) - goto toss_off; - /* - * First try reading the property off the the frontend. if that - * fails, try and read it from the backend node. If that - * also fails, pass the request on the DDI framework - */ - prop_str = NULL; - if ((xenbus_read(XBT_NULL, pdp->xd_xsdev.nodename, name, &prop_str, - &len) == 0) && (prop_str != NULL) && (strlen(prop_str) != 0)) - goto got_xs_prop; - - prop_str = NULL; - if ((pdp->xd_xsdev.otherend != NULL) && - (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, name, &prop_str, - &len) == 0) && (prop_str != NULL) && (strlen(prop_str) != 0)) - goto got_xs_prop; - -toss_off: - return (ddi_bus_prop_op(dev, dip, ch_dip, prop_op, - mod_flags | DDI_PROP_NOTPROM, name, valuep, lengthp)); - -got_xs_prop: - prop_len = strlen(prop_str) + 1; - rv = DDI_PROP_SUCCESS; - - switch (prop_op) { - case PROP_LEN: - *lengthp = prop_len; - break; - - case PROP_LEN_AND_VAL_ALLOC: - buff = kmem_alloc((size_t)prop_len, KM_SLEEP); - *(caddr_t *)valuep = (caddr_t)buff; - break; - case PROP_LEN_AND_VAL_BUF: - buff = (caddr_t)valuep; - if (*lengthp < prop_len) - rv = DDI_PROP_BUF_TOO_SMALL; - break; - default: - rv = DDI_PROP_INVAL_ARG; - break; - } - - if ((rv == DDI_PROP_SUCCESS) && (prop_len > 0)) { - bcopy(prop_str, buff, prop_len); - *lengthp = prop_len; - } - kmem_free(prop_str, len); - return (rv); -} - - -/* - * return address of the device's interrupt spec structure. - */ -/*ARGSUSED*/ -struct intrspec * -xpvd_get_ispec(dev_info_t *rdip, uint_t inumber) -{ - struct xendev_ppd *pdp; - - ASSERT(inumber == 0); - - if ((pdp = ddi_get_parent_data(rdip)) == NULL) - return (NULL); - - return (&pdp->xd_ispec); -} - -/* - * return (and determine) the interrupt priority of the device. - */ -/*ARGSUSED*/ -static int -xpvd_get_priority(dev_info_t *dip, int inum, int *pri) -{ - struct xendev_ppd *pdp; - struct intrspec *ispec; - int *intpriorities; - uint_t num_intpriorities; - - DDI_INTR_NEXDBG((CE_CONT, "xpvd_get_priority: dip = 0x%p\n", - (void *)dip)); - - ASSERT(inum == 0); - - if ((pdp = ddi_get_parent_data(dip)) == NULL) - return (DDI_FAILURE); - - ispec = &pdp->xd_ispec; - - /* - * Set the default priority based on the device class. The - * "interrupt-priorities" property can be used to override - * the default. - */ - if (ispec->intrspec_pri == 0) { - ispec->intrspec_pri = xendev_devclass_ipl(pdp->xd_devclass); - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, - "interrupt-priorities", &intpriorities, - &num_intpriorities) == DDI_PROP_SUCCESS) { - ispec->intrspec_pri = intpriorities[0]; - ddi_prop_free(intpriorities); - } - } - *pri = ispec->intrspec_pri; - return (DDI_SUCCESS); -} - - -/* - * xpvd_intr_ops: bus_intr_op() function for interrupt support - */ -/* ARGSUSED */ -static int -xpvd_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, - ddi_intr_handle_impl_t *hdlp, void *result) -{ - int priority = 0; - struct intrspec *ispec; - struct xendev_ppd *pdp; - - DDI_INTR_NEXDBG((CE_CONT, - "xpvd_intr_ops: pdip 0x%p, rdip 0x%p, op %x handle 0x%p\n", - (void *)pdip, (void *)rdip, intr_op, (void *)hdlp)); - - /* Process the request */ - switch (intr_op) { - case DDI_INTROP_SUPPORTED_TYPES: - /* Fixed supported by default */ - *(int *)result = DDI_INTR_TYPE_FIXED; - break; - - case DDI_INTROP_NINTRS: - *(int *)result = 1; - break; - - case DDI_INTROP_ALLOC: - /* - * FIXED interrupts: just return available interrupts - */ - if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) { - /* - * event channels are edge-triggered, maskable, - * and support int pending. - */ - hdlp->ih_cap |= XENDEV_INTR_CAPABILITIES; - *(int *)result = 1; /* DDI_INTR_TYPE_FIXED */ - } else { - return (DDI_FAILURE); - } - break; - - case DDI_INTROP_FREE: - ispec = xpvd_get_ispec(rdip, (int)hdlp->ih_inum); - if (ispec == NULL) - return (DDI_FAILURE); - ispec->intrspec_pri = 0; /* mark as un-initialized */ - break; - - case DDI_INTROP_GETPRI: - if (xpvd_get_priority(rdip, hdlp->ih_inum, &priority) != - DDI_SUCCESS) - return (DDI_FAILURE); - DDI_INTR_NEXDBG((CE_CONT, "xpvd_intr_ops: priority = 0x%x\n", - priority)); - *(int *)result = priority; - break; - - case DDI_INTROP_SETPRI: - /* Validate the interrupt priority passed */ - if (*(int *)result > LOCK_LEVEL) - return (DDI_FAILURE); - - /* Ensure that PSM is all initialized */ - if (psm_intr_ops == NULL) - return (DDI_FAILURE); - - /* Change the priority */ - if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_PRI, result) == - PSM_FAILURE) - return (DDI_FAILURE); - - ispec = xpvd_get_ispec(rdip, (int)hdlp->ih_inum); - if (ispec == NULL) - return (DDI_FAILURE); - ispec->intrspec_pri = *(int *)result; - break; - - case DDI_INTROP_ADDISR: - /* update ispec */ - ispec = xpvd_get_ispec(rdip, (int)hdlp->ih_inum); - if (ispec == NULL) - return (DDI_FAILURE); - ispec->intrspec_func = hdlp->ih_cb_func; - - break; - - case DDI_INTROP_REMISR: - ispec = xpvd_get_ispec(rdip, (int)hdlp->ih_inum); - pdp = (struct xendev_ppd *)ddi_get_parent_data(rdip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_evtchn != INVALID_EVTCHN); - - if (ispec) { - ispec->intrspec_vec = 0; - ispec->intrspec_func = (uint_t (*)()) 0; - } - pdp->xd_evtchn = INVALID_EVTCHN; - break; - - case DDI_INTROP_GETCAP: - if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) { - /* - * event channels are edge-triggered, maskable, - * and support int pending. - */ - *(int *)result = XENDEV_INTR_CAPABILITIES; - } else { - *(int *)result = 0; - return (DDI_FAILURE); - } - DDI_INTR_NEXDBG((CE_CONT, "xpvd: GETCAP returned = %x\n", - *(int *)result)); - break; - case DDI_INTROP_SETCAP: - DDI_INTR_NEXDBG((CE_CONT, "xpvd_intr_ops: SETCAP cap=0x%x\n", - *(int *)result)); - if (psm_intr_ops == NULL) - return (DDI_FAILURE); - - if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) { - DDI_INTR_NEXDBG((CE_CONT, "GETCAP: psm_intr_ops" - " returned failure\n")); - return (DDI_FAILURE); - } - break; - - case DDI_INTROP_ENABLE: - if (psm_intr_ops == NULL) - return (DDI_FAILURE); - - if (xpvd_enable_intr(rdip, hdlp, (int)hdlp->ih_inum) != - DDI_SUCCESS) - return (DDI_FAILURE); - - DDI_INTR_NEXDBG((CE_CONT, "xpvd_intr_ops: ENABLE vec=0x%x\n", - hdlp->ih_vector)); - break; - - case DDI_INTROP_DISABLE: - if (psm_intr_ops == NULL) - return (DDI_FAILURE); - xpvd_disable_intr(rdip, hdlp, hdlp->ih_inum); - DDI_INTR_NEXDBG((CE_CONT, "xpvd_intr_ops: DISABLE vec = %x\n", - hdlp->ih_vector)); - break; - - case DDI_INTROP_BLOCKENABLE: - case DDI_INTROP_BLOCKDISABLE: - return (DDI_FAILURE); - - case DDI_INTROP_SETMASK: - case DDI_INTROP_CLRMASK: -#ifdef XPV_HVM_DRIVER - return (DDI_ENOTSUP); -#else - /* - * Handle this here - */ - if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) - return (DDI_FAILURE); - if (intr_op == DDI_INTROP_SETMASK) { - ec_disable_irq(hdlp->ih_vector); - } else { - ec_enable_irq(hdlp->ih_vector); - } - break; -#endif - case DDI_INTROP_GETPENDING: -#ifdef XPV_HVM_DRIVER - return (DDI_ENOTSUP); -#else - if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) - return (DDI_FAILURE); - *(int *)result = ec_pending_irq(hdlp->ih_vector); - DDI_INTR_NEXDBG((CE_CONT, "xpvd: GETPENDING returned = %x\n", - *(int *)result)); - break; -#endif - - case DDI_INTROP_NAVAIL: - *(int *)result = 1; - DDI_INTR_NEXDBG((CE_CONT, "xpvd: NAVAIL returned = %x\n", - *(int *)result)); - break; - - default: - return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result)); - } - - return (DDI_SUCCESS); -} - - -static int -xpvd_enable_intr(dev_info_t *rdip, ddi_intr_handle_impl_t *hdlp, int inum) -{ - int vector; - ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private; - - DDI_INTR_NEXDBG((CE_CONT, "xpvd_enable_intr: hdlp %p inum %x\n", - (void *)hdlp, inum)); - - ihdl_plat_datap->ip_ispecp = xpvd_get_ispec(rdip, inum); - if (ihdl_plat_datap->ip_ispecp == NULL) - return (DDI_FAILURE); - - /* translate the interrupt if needed */ - (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector); - DDI_INTR_NEXDBG((CE_CONT, "xpvd_enable_intr: priority=%x vector=%x\n", - hdlp->ih_pri, vector)); - - /* Add the interrupt handler */ - if (!add_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, - DEVI(rdip)->devi_name, vector, hdlp->ih_cb_arg1, - hdlp->ih_cb_arg2, NULL, rdip)) - return (DDI_FAILURE); - - /* Note this really is an irq. */ - hdlp->ih_vector = (ushort_t)vector; - - return (DDI_SUCCESS); -} - - -static void -xpvd_disable_intr(dev_info_t *rdip, ddi_intr_handle_impl_t *hdlp, int inum) -{ - int vector; - ihdl_plat_t *ihdl_plat_datap = (ihdl_plat_t *)hdlp->ih_private; - - DDI_INTR_NEXDBG((CE_CONT, "xpvd_disable_intr: \n")); - ihdl_plat_datap->ip_ispecp = xpvd_get_ispec(rdip, inum); - if (ihdl_plat_datap->ip_ispecp == NULL) - return; - - /* translate the interrupt if needed */ - (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, &vector); - - /* Disable the interrupt handler */ - rem_avintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, vector); - ihdl_plat_datap->ip_ispecp = NULL; -} - -/*ARGSUSED*/ -static int -xpvd_ctlops(dev_info_t *dip, dev_info_t *rdip, - ddi_ctl_enum_t ctlop, void *arg, void *result) -{ - switch (ctlop) { - case DDI_CTLOPS_REPORTDEV: - if (rdip == (dev_info_t *)0) - return (DDI_FAILURE); - cmn_err(CE_CONT, "?%s@%s, %s%d\n", ddi_node_name(rdip), - ddi_get_name_addr(rdip), ddi_driver_name(rdip), - ddi_get_instance(rdip)); - return (DDI_SUCCESS); - - case DDI_CTLOPS_INITCHILD: - return (xpvd_initchild((dev_info_t *)arg)); - - case DDI_CTLOPS_UNINITCHILD: - return (xpvd_removechild((dev_info_t *)arg)); - - case DDI_CTLOPS_SIDDEV: - return (DDI_SUCCESS); - - case DDI_CTLOPS_REGSIZE: - case DDI_CTLOPS_NREGS: - return (DDI_FAILURE); - - case DDI_CTLOPS_POWER: { - return (ddi_ctlops(dip, rdip, ctlop, arg, result)); - } - - default: - return (ddi_ctlops(dip, rdip, ctlop, arg, result)); - } - - /* NOTREACHED */ - -} - -/* - * Assign the address portion of the node name - */ -static int -xpvd_name_child(dev_info_t *child, char *addr, int addrlen) -{ - int *domain, *vdev; - uint_t ndomain, nvdev; - char *prop_str; - - /* - * i_xpvd_parse_devname() knows the formats used by this - * routine. If this code changes, so must that. - */ - - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, - "domain", &domain, &ndomain) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - ASSERT(ndomain == 1); - - /* - * Use "domain" and "vdev" properties (backend drivers). - */ - if (*domain != DOMID_SELF) { - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, - DDI_PROP_DONTPASS, "vdev", &vdev, &nvdev) - != DDI_PROP_SUCCESS) { - ddi_prop_free(domain); - return (DDI_FAILURE); - } - ASSERT(nvdev == 1); - - (void) snprintf(addr, addrlen, "%d,%d", domain[0], vdev[0]); - ddi_prop_free(vdev); - ddi_prop_free(domain); - return (DDI_SUCCESS); - } - ddi_prop_free(domain); - - /* - * Use "unit-address" property (frontend/softdev drivers). - */ - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, - "unit-address", &prop_str) != DDI_PROP_SUCCESS) - return (DDI_FAILURE); - (void) strlcpy(addr, prop_str, addrlen); - ddi_prop_free(prop_str); - return (DDI_SUCCESS); -} - -static int -xpvd_initchild(dev_info_t *child) -{ - char addr[80]; - - /* - * Pseudo nodes indicate a prototype node with per-instance - * properties to be merged into the real h/w device node. - */ - if (ndi_dev_is_persistent_node(child) == 0) { - ddi_set_parent_data(child, NULL); - - /* - * Try to merge the properties from this prototype - * node into real h/w nodes. - */ - if (ndi_merge_node(child, xpvd_name_child) == DDI_SUCCESS) { - /* - * Merged ok - return failure to remove the node. - */ - ddi_set_name_addr(child, NULL); - return (DDI_FAILURE); - } - - /* - * The child was not merged into a h/w node, - * but there's not much we can do with it other - * than return failure to cause the node to be removed. - */ - cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", - ddi_get_name(child), ddi_get_name_addr(child), - ddi_get_name(child)); - ddi_set_name_addr(child, NULL); - return (DDI_NOT_WELL_FORMED); - } - - if (xvdi_init_dev(child) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (xpvd_name_child(child, addr, sizeof (addr)) != DDI_SUCCESS) { - xvdi_uninit_dev(child); - return (DDI_FAILURE); - } - ddi_set_name_addr(child, addr); - - return (DDI_SUCCESS); -} - -static int -xpvd_removechild(dev_info_t *dip) -{ - xvdi_uninit_dev(dip); - - ddi_set_name_addr(dip, NULL); - - /* - * Strip the node to properly convert it back to prototype - * form. - */ - ddi_remove_minor_node(dip, NULL); - - return (DDI_SUCCESS); -} - -static int -xpvd_bus_unconfig(dev_info_t *parent, uint_t flag, ddi_bus_config_op_t op, - void *device_name) -{ - return (ndi_busop_bus_unconfig(parent, flag, op, device_name)); -} - -/* - * Given the name of a child of xpvd, determine the device class, - * domain and vdevnum to which it refers. - */ -static boolean_t -i_xpvd_parse_devname(char *name, xendev_devclass_t *devclassp, - domid_t *domp, int *vdevp) -{ - int len = strlen(name) + 1; - char *device_name = i_ddi_strdup(name, KM_SLEEP); - char *cname = NULL, *caddr = NULL; - boolean_t ret; - - i_ddi_parse_name(device_name, &cname, &caddr, NULL); - - if ((cname == NULL) || (strlen(cname) == 0) || - (caddr == NULL) || (strlen(caddr) == 0)) { - ret = B_FALSE; - goto done; - } - - *devclassp = xendev_nodename_to_devclass(cname); - if (*devclassp < 0) { - ret = B_FALSE; - goto done; - } - - /* - * Parsing the address component requires knowledge of how - * xpvd_name_child() works. If that code changes, so must - * this. - */ - - /* Backend format is ",". */ - if (sscanf(caddr, "%hu,%d", domp, vdevp) == 2) { - ret = B_TRUE; - goto done; - } - - /* Frontend format is "". */ - *domp = DOMID_SELF; - if (sscanf(caddr, "%d", vdevp) == 1) - ret = B_TRUE; -done: - kmem_free(device_name, len); - return (ret); -} - -/* - * xpvd_bus_config() - * - * BUS_CONFIG_ONE: - * Enumerate the exact instance of a driver. - * - * BUS_CONFIG_ALL: - * Enumerate all the instances of all the possible children (seen before - * and never seen before). - * - * BUS_CONFIG_DRIVER: - * Enumerate all the instances of a particular driver. - */ -static int -xpvd_bus_config(dev_info_t *parent, uint_t flag, ddi_bus_config_op_t op, - void *arg, dev_info_t **childp) -{ - int circ; - char *cname = NULL; - - ndi_devi_enter(parent, &circ); - - switch (op) { - case BUS_CONFIG_ONE: { - xendev_devclass_t devclass; - domid_t dom; - int vdev; - - if (!i_xpvd_parse_devname(arg, &devclass, &dom, &vdev)) { - ndi_devi_exit(parent, circ); - return (NDI_FAILURE); - } - - *childp = xvdi_find_dev(parent, devclass, dom, vdev); - if (*childp == NULL) - *childp = xvdi_create_dev(parent, devclass, dom, vdev); - - ndi_devi_exit(parent, circ); - - if (*childp == NULL) - return (NDI_FAILURE); - else - return (ndi_busop_bus_config(parent, flag, - op, arg, childp, 0)); - } - - case BUS_CONFIG_DRIVER: { - xendev_devclass_t devclass = XEN_INVAL; - - cname = ddi_major_to_name((major_t)(uintptr_t)arg); - if (cname != NULL) - devclass = xendev_nodename_to_devclass(cname); - - if (devclass == XEN_INVAL) { - ndi_devi_exit(parent, circ); - return (NDI_FAILURE); - } else { - xendev_enum_class(parent, devclass); - ndi_devi_exit(parent, circ); - return (ndi_busop_bus_config(parent, flag, op, - arg, childp, 0)); - } - /* NOTREACHED */ - } - - case BUS_CONFIG_ALL: - xendev_enum_all(parent, B_FALSE); - ndi_devi_exit(parent, circ); - - return (ndi_busop_bus_config(parent, flag, op, - arg, childp, 0)); - - default: - ndi_devi_exit(parent, circ); - return (NDI_FAILURE); - } -} - -/*ARGSUSED*/ -static int -xpvd_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, - char *eventname, ddi_eventcookie_t *cookie) -{ - return (ndi_event_retrieve_cookie(xpvd_ndi_event_handle, - rdip, eventname, cookie, NDI_EVENT_NOPASS)); -} - -/*ARGSUSED*/ -static int -xpvd_add_eventcall(dev_info_t *dip, dev_info_t *rdip, - ddi_eventcookie_t cookie, void (*callback)(dev_info_t *dip, - ddi_eventcookie_t cookie, void *arg, void *bus_impldata), - void *arg, ddi_callback_id_t *cb_id) -{ - return (ndi_event_add_callback(xpvd_ndi_event_handle, - rdip, cookie, callback, arg, NDI_SLEEP, cb_id)); -} - -/*ARGSUSED*/ -static int -xpvd_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) -{ - return (ndi_event_remove_callback(xpvd_ndi_event_handle, - cb_id)); -} - -/*ARGSUSED*/ -static int -xpvd_post_event(dev_info_t *dip, dev_info_t *rdip, - ddi_eventcookie_t cookie, void *bus_impldata) -{ - return (ndi_event_run_callbacks(xpvd_ndi_event_handle, rdip, - cookie, bus_impldata)); -} diff --git a/usr/src/uts/common/xen/io/xpvd.conf b/usr/src/uts/common/xen/io/xpvd.conf deleted file mode 100644 index 55262457f9..0000000000 --- a/usr/src/uts/common/xen/io/xpvd.conf +++ /dev/null @@ -1,28 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# ident "%Z%%M% %I% %E% SMI" - -name="xpvd" class="root"; diff --git a/usr/src/uts/common/xen/io/xpvtap.c b/usr/src/uts/common/xen/io/xpvtap.c deleted file mode 100644 index 57290aa9d5..0000000000 --- a/usr/src/uts/common/xen/io/xpvtap.c +++ /dev/null @@ -1,1638 +0,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 - - -static int xpvtap_open(dev_t *devp, int flag, int otyp, cred_t *cred); -static int xpvtap_close(dev_t devp, int flag, int otyp, cred_t *cred); -static int xpvtap_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, - cred_t *cred, int *rval); -static int xpvtap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, - size_t len, size_t *maplen, uint_t model); -static int xpvtap_segmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp, - off_t len, unsigned int prot, unsigned int maxprot, unsigned int flags, - cred_t *cred_p); -static int xpvtap_chpoll(dev_t dev, short events, int anyyet, short *reventsp, - struct pollhead **phpp); - -static struct cb_ops xpvtap_cb_ops = { - xpvtap_open, /* cb_open */ - xpvtap_close, /* cb_close */ - nodev, /* cb_strategy */ - nodev, /* cb_print */ - nodev, /* cb_dump */ - nodev, /* cb_read */ - nodev, /* cb_write */ - xpvtap_ioctl, /* cb_ioctl */ - xpvtap_devmap, /* cb_devmap */ - nodev, /* cb_mmap */ - xpvtap_segmap, /* cb_segmap */ - xpvtap_chpoll, /* cb_chpoll */ - ddi_prop_op, /* cb_prop_op */ - NULL, /* cb_stream */ - D_NEW | D_MP | D_64BIT | D_DEVMAP, /* cb_flag */ - CB_REV -}; - -static int xpvtap_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, - void **result); -static int xpvtap_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); -static int xpvtap_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); - -static struct dev_ops xpvtap_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* devo_refcnt */ - xpvtap_getinfo, /* devo_getinfo */ - nulldev, /* devo_identify */ - nulldev, /* devo_probe */ - xpvtap_attach, /* devo_attach */ - xpvtap_detach, /* devo_detach */ - nodev, /* devo_reset */ - &xpvtap_cb_ops, /* devo_cb_ops */ - NULL, /* devo_bus_ops */ - NULL /* power */ -}; - - -static struct modldrv xpvtap_modldrv = { - &mod_driverops, /* Type of module. This one is a driver */ - "xpvtap driver", /* Name of the module. */ - &xpvtap_dev_ops, /* driver ops */ -}; - -static struct modlinkage xpvtap_modlinkage = { - MODREV_1, - (void *) &xpvtap_modldrv, - NULL -}; - - -void *xpvtap_statep; - - -static xpvtap_state_t *xpvtap_drv_init(int instance); -static void xpvtap_drv_fini(xpvtap_state_t *state); -static uint_t xpvtap_intr(caddr_t arg); - -typedef void (*xpvtap_rs_cleanup_t)(xpvtap_state_t *state, uint_t rs); -static void xpvtap_rs_init(uint_t min_val, uint_t max_val, - xpvtap_rs_hdl_t *handle); -static void xpvtap_rs_fini(xpvtap_rs_hdl_t *handle); -static int xpvtap_rs_alloc(xpvtap_rs_hdl_t handle, uint_t *rs); -static void xpvtap_rs_free(xpvtap_rs_hdl_t handle, uint_t rs); -static void xpvtap_rs_flush(xpvtap_rs_hdl_t handle, - xpvtap_rs_cleanup_t callback, void *arg); - -static int xpvtap_segmf_register(xpvtap_state_t *state); -static void xpvtap_segmf_unregister(struct as *as, void *arg, uint_t event); - -static int xpvtap_user_init(xpvtap_state_t *state); -static void xpvtap_user_fini(xpvtap_state_t *state); -static int xpvtap_user_ring_init(xpvtap_state_t *state); -static void xpvtap_user_ring_fini(xpvtap_state_t *state); -static int xpvtap_user_thread_init(xpvtap_state_t *state); -static void xpvtap_user_thread_fini(xpvtap_state_t *state); -static void xpvtap_user_thread_start(caddr_t arg); -static void xpvtap_user_thread_stop(xpvtap_state_t *state); -static void xpvtap_user_thread(void *arg); - -static void xpvtap_user_app_stop(caddr_t arg); - -static int xpvtap_user_request_map(xpvtap_state_t *state, blkif_request_t *req, - uint_t *uid); -static int xpvtap_user_request_push(xpvtap_state_t *state, - blkif_request_t *req, uint_t uid); -static int xpvtap_user_response_get(xpvtap_state_t *state, - blkif_response_t *resp, uint_t *uid); -static void xpvtap_user_request_unmap(xpvtap_state_t *state, uint_t uid); - - -/* - * _init() - */ -int -_init(void) -{ - int e; - - e = ddi_soft_state_init(&xpvtap_statep, sizeof (xpvtap_state_t), 1); - if (e != 0) { - return (e); - } - - e = mod_install(&xpvtap_modlinkage); - if (e != 0) { - ddi_soft_state_fini(&xpvtap_statep); - return (e); - } - - return (0); -} - - -/* - * _info() - */ -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&xpvtap_modlinkage, modinfop)); -} - - -/* - * _fini() - */ -int -_fini(void) -{ - int e; - - e = mod_remove(&xpvtap_modlinkage); - if (e != 0) { - return (e); - } - - ddi_soft_state_fini(&xpvtap_statep); - - return (0); -} - - -/* - * xpvtap_attach() - */ -static int -xpvtap_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - blk_ringinit_args_t args; - xpvtap_state_t *state; - int instance; - int e; - - - switch (cmd) { - case DDI_ATTACH: - break; - - case DDI_RESUME: - return (DDI_SUCCESS); - - default: - return (DDI_FAILURE); - } - - /* initialize our state info */ - instance = ddi_get_instance(dip); - state = xpvtap_drv_init(instance); - if (state == NULL) { - return (DDI_FAILURE); - } - state->bt_dip = dip; - - /* Initialize the guest ring */ - args.ar_dip = state->bt_dip; - args.ar_intr = xpvtap_intr; - args.ar_intr_arg = (caddr_t)state; - args.ar_ringup = xpvtap_user_thread_start; - args.ar_ringup_arg = (caddr_t)state; - args.ar_ringdown = xpvtap_user_app_stop; - args.ar_ringdown_arg = (caddr_t)state; - e = blk_ring_init(&args, &state->bt_guest_ring); - if (e != DDI_SUCCESS) { - goto attachfail_ringinit; - } - - /* create the minor node (for ioctl/mmap) */ - e = ddi_create_minor_node(dip, "xpvtap", S_IFCHR, instance, - DDI_PSEUDO, 0); - if (e != DDI_SUCCESS) { - goto attachfail_minor_node; - } - - /* Report that driver was loaded */ - ddi_report_dev(dip); - - return (DDI_SUCCESS); - -attachfail_minor_node: - blk_ring_fini(&state->bt_guest_ring); -attachfail_ringinit: - xpvtap_drv_fini(state); - return (DDI_FAILURE); -} - - -/* - * xpvtap_detach() - */ -static int -xpvtap_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - xpvtap_state_t *state; - int instance; - - - instance = ddi_get_instance(dip); - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (DDI_FAILURE); - } - - switch (cmd) { - case DDI_DETACH: - break; - - case DDI_SUSPEND: - default: - return (DDI_FAILURE); - } - - xpvtap_user_thread_stop(state); - blk_ring_fini(&state->bt_guest_ring); - xpvtap_drv_fini(state); - ddi_remove_minor_node(dip, NULL); - - return (DDI_SUCCESS); -} - - -/* - * xpvtap_getinfo() - */ -/*ARGSUSED*/ -static int -xpvtap_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) -{ - xpvtap_state_t *state; - int instance; - dev_t dev; - int e; - - - dev = (dev_t)arg; - instance = getminor(dev); - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (DDI_FAILURE); - } - *result = (void *)state->bt_dip; - e = DDI_SUCCESS; - break; - - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)(uintptr_t)instance; - e = DDI_SUCCESS; - break; - - default: - e = DDI_FAILURE; - break; - } - - return (e); -} - - -/* - * xpvtap_open() - */ -/*ARGSUSED*/ -static int -xpvtap_open(dev_t *devp, int flag, int otyp, cred_t *cred) -{ - xpvtap_state_t *state; - int instance; - - - if (secpolicy_xvm_control(cred)) { - return (EPERM); - } - - instance = getminor(*devp); - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (ENXIO); - } - - /* we should only be opened once */ - mutex_enter(&state->bt_open.bo_mutex); - if (state->bt_open.bo_opened) { - mutex_exit(&state->bt_open.bo_mutex); - return (EBUSY); - } - state->bt_open.bo_opened = B_TRUE; - mutex_exit(&state->bt_open.bo_mutex); - - /* - * save the apps address space. need it for mapping/unmapping grefs - * since will be doing it in a separate kernel thread. - */ - state->bt_map.um_as = curproc->p_as; - - return (0); -} - - -/* - * xpvtap_close() - */ -/*ARGSUSED*/ -static int -xpvtap_close(dev_t devp, int flag, int otyp, cred_t *cred) -{ - xpvtap_state_t *state; - int instance; - - - instance = getminor(devp); - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (ENXIO); - } - - /* - * wake thread so it can cleanup and wait for it to exit so we can - * be sure it's not in the middle of processing a request/response. - */ - mutex_enter(&state->bt_thread.ut_mutex); - state->bt_thread.ut_wake = B_TRUE; - state->bt_thread.ut_exit = B_TRUE; - cv_signal(&state->bt_thread.ut_wake_cv); - if (!state->bt_thread.ut_exit_done) { - cv_wait(&state->bt_thread.ut_exit_done_cv, - &state->bt_thread.ut_mutex); - } - ASSERT(state->bt_thread.ut_exit_done); - mutex_exit(&state->bt_thread.ut_mutex); - - state->bt_map.um_as = NULL; - state->bt_map.um_guest_pages = NULL; - - /* - * when the ring is brought down, a userland hotplug script is run - * which tries to bring the userland app down. We'll wait for a bit - * for the user app to exit. Notify the thread waiting that the app - * has closed the driver. - */ - mutex_enter(&state->bt_open.bo_mutex); - ASSERT(state->bt_open.bo_opened); - state->bt_open.bo_opened = B_FALSE; - cv_signal(&state->bt_open.bo_exit_cv); - mutex_exit(&state->bt_open.bo_mutex); - - return (0); -} - - -/* - * xpvtap_ioctl() - */ -/*ARGSUSED*/ -static int -xpvtap_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, - int *rval) -{ - xpvtap_state_t *state; - int instance; - - - if (secpolicy_xvm_control(cred)) { - return (EPERM); - } - - instance = getminor(dev); - if (instance == -1) { - return (EBADF); - } - - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (EBADF); - } - - switch (cmd) { - case XPVTAP_IOCTL_RESP_PUSH: - /* - * wake thread, thread handles guest requests and user app - * responses. - */ - mutex_enter(&state->bt_thread.ut_mutex); - state->bt_thread.ut_wake = B_TRUE; - cv_signal(&state->bt_thread.ut_wake_cv); - mutex_exit(&state->bt_thread.ut_mutex); - break; - - default: - cmn_err(CE_WARN, "ioctl(%d) not supported\n", cmd); - return (ENXIO); - } - - return (0); -} - - -/* - * xpvtap_segmap() - */ -/*ARGSUSED*/ -static int -xpvtap_segmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp, - off_t len, unsigned int prot, unsigned int maxprot, unsigned int flags, - cred_t *cred_p) -{ - struct segmf_crargs a; - xpvtap_state_t *state; - int instance; - int e; - - - if (secpolicy_xvm_control(cred_p)) { - return (EPERM); - } - - instance = getminor(dev); - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (EBADF); - } - - /* the user app should be doing a MAP_SHARED mapping */ - if ((flags & MAP_TYPE) != MAP_SHARED) { - return (EINVAL); - } - - /* - * if this is the user ring (offset = 0), devmap it (which ends up in - * xpvtap_devmap). devmap will alloc and map the ring into the - * app's VA space. - */ - if (off == 0) { - e = devmap_setup(dev, (offset_t)off, asp, addrp, (size_t)len, - prot, maxprot, flags, cred_p); - return (e); - } - - /* this should be the mmap for the gref pages (offset = PAGESIZE) */ - if (off != PAGESIZE) { - return (EINVAL); - } - - /* make sure we get the size we're expecting */ - if (len != XPVTAP_GREF_BUFSIZE) { - return (EINVAL); - } - - /* - * reserve user app VA space for the gref pages and use segmf to - * manage the backing store for the physical memory. segmf will - * map in/out the grefs and fault them in/out. - */ - ASSERT(asp == state->bt_map.um_as); - as_rangelock(asp); - if ((flags & MAP_FIXED) == 0) { - map_addr(addrp, len, 0, 0, flags); - if (*addrp == NULL) { - as_rangeunlock(asp); - return (ENOMEM); - } - } else { - /* User specified address */ - (void) as_unmap(asp, *addrp, len); - } - a.dev = dev; - a.prot = (uchar_t)prot; - a.maxprot = (uchar_t)maxprot; - e = as_map(asp, *addrp, len, segmf_create, &a); - if (e != 0) { - as_rangeunlock(asp); - return (e); - } - as_rangeunlock(asp); - - /* - * Stash user base address, and compute address where the request - * array will end up. - */ - state->bt_map.um_guest_pages = (caddr_t)*addrp; - state->bt_map.um_guest_size = (size_t)len; - - /* register an as callback so we can cleanup when the app goes away */ - e = as_add_callback(asp, xpvtap_segmf_unregister, state, - AS_UNMAP_EVENT, *addrp, len, KM_SLEEP); - if (e != 0) { - (void) as_unmap(asp, *addrp, len); - return (EINVAL); - } - - /* wake thread to see if there are requests already queued up */ - mutex_enter(&state->bt_thread.ut_mutex); - state->bt_thread.ut_wake = B_TRUE; - cv_signal(&state->bt_thread.ut_wake_cv); - mutex_exit(&state->bt_thread.ut_mutex); - - return (0); -} - - -/* - * xpvtap_devmap() - */ -/*ARGSUSED*/ -static int -xpvtap_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len, - size_t *maplen, uint_t model) -{ - xpvtap_user_ring_t *usring; - xpvtap_state_t *state; - int instance; - int e; - - - instance = getminor(dev); - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (EBADF); - } - - /* we should only get here if the offset was == 0 */ - if (off != 0) { - return (EINVAL); - } - - /* we should only be mapping in one page */ - if (len != PAGESIZE) { - return (EINVAL); - } - - /* - * we already allocated the user ring during driver attach, all we - * need to do is map it into the user app's VA. - */ - usring = &state->bt_user_ring; - e = devmap_umem_setup(dhp, state->bt_dip, NULL, usring->ur_cookie, 0, - PAGESIZE, PROT_ALL, DEVMAP_DEFAULTS, NULL); - if (e < 0) { - return (e); - } - - /* return the size to compete the devmap */ - *maplen = PAGESIZE; - - return (0); -} - - -/* - * xpvtap_chpoll() - */ -static int -xpvtap_chpoll(dev_t dev, short events, int anyyet, short *reventsp, - struct pollhead **phpp) -{ - xpvtap_user_ring_t *usring; - xpvtap_state_t *state; - int instance; - - - instance = getminor(dev); - if (instance == -1) { - return (EBADF); - } - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - return (EBADF); - } - - if (((events & (POLLIN | POLLRDNORM)) == 0) && !anyyet) { - *reventsp = 0; - return (EINVAL); - } - - /* - * if we pushed requests on the user ring since the last poll, wakeup - * the user app - */ - usring = &state->bt_user_ring; - if (usring->ur_prod_polled != usring->ur_ring.req_prod_pvt) { - - /* - * XXX - is this faster here or xpvtap_user_request_push?? - * prelim data says here. Because less membars or because - * user thread will spin in poll requests before getting to - * responses? - */ - RING_PUSH_REQUESTS(&usring->ur_ring); - - usring->ur_prod_polled = usring->ur_ring.sring->req_prod; - *reventsp = POLLIN | POLLRDNORM; - - /* no new requests */ - } else { - *reventsp = 0; - if (!anyyet) { - *phpp = &state->bt_pollhead; - } - } - - return (0); -} - - -/* - * xpvtap_drv_init() - */ -static xpvtap_state_t * -xpvtap_drv_init(int instance) -{ - xpvtap_state_t *state; - int e; - - - e = ddi_soft_state_zalloc(xpvtap_statep, instance); - if (e != DDI_SUCCESS) { - return (NULL); - } - state = ddi_get_soft_state(xpvtap_statep, instance); - if (state == NULL) { - goto drvinitfail_get_soft_state; - } - - state->bt_instance = instance; - mutex_init(&state->bt_open.bo_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&state->bt_open.bo_exit_cv, NULL, CV_DRIVER, NULL); - state->bt_open.bo_opened = B_FALSE; - state->bt_map.um_registered = B_FALSE; - - /* initialize user ring, thread, mapping state */ - e = xpvtap_user_init(state); - if (e != DDI_SUCCESS) { - goto drvinitfail_userinit; - } - - return (state); - -drvinitfail_userinit: - cv_destroy(&state->bt_open.bo_exit_cv); - mutex_destroy(&state->bt_open.bo_mutex); -drvinitfail_get_soft_state: - (void) ddi_soft_state_free(xpvtap_statep, instance); - return (NULL); -} - - -/* - * xpvtap_drv_fini() - */ -static void -xpvtap_drv_fini(xpvtap_state_t *state) -{ - xpvtap_user_fini(state); - cv_destroy(&state->bt_open.bo_exit_cv); - mutex_destroy(&state->bt_open.bo_mutex); - (void) ddi_soft_state_free(xpvtap_statep, state->bt_instance); -} - - -/* - * xpvtap_intr() - * this routine will be called when we have a request on the guest ring. - */ -static uint_t -xpvtap_intr(caddr_t arg) -{ - xpvtap_state_t *state; - - - state = (xpvtap_state_t *)arg; - - /* wake thread, thread handles guest requests and user app responses */ - mutex_enter(&state->bt_thread.ut_mutex); - state->bt_thread.ut_wake = B_TRUE; - cv_signal(&state->bt_thread.ut_wake_cv); - mutex_exit(&state->bt_thread.ut_mutex); - - return (DDI_INTR_CLAIMED); -} - - -/* - * xpvtap_segmf_register() - */ -static int -xpvtap_segmf_register(xpvtap_state_t *state) -{ - struct seg *seg; - uint64_t pte_ma; - struct as *as; - caddr_t uaddr; - uint_t pgcnt; - int i; - - - as = state->bt_map.um_as; - pgcnt = btopr(state->bt_map.um_guest_size); - uaddr = state->bt_map.um_guest_pages; - - if (pgcnt == 0) { - return (DDI_FAILURE); - } - - AS_LOCK_ENTER(as, RW_READER); - - seg = as_findseg(as, state->bt_map.um_guest_pages, 0); - if ((seg == NULL) || ((uaddr + state->bt_map.um_guest_size) > - (seg->s_base + seg->s_size))) { - AS_LOCK_EXIT(as); - return (DDI_FAILURE); - } - - /* - * lock down the htables so the HAT can't steal them. Register the - * PTE MA's for each gref page with seg_mf so we can do user space - * gref mappings. - */ - for (i = 0; i < pgcnt; i++) { - hat_prepare_mapping(as->a_hat, uaddr, &pte_ma); - hat_devload(as->a_hat, uaddr, PAGESIZE, (pfn_t)0, - PROT_READ | PROT_WRITE | PROT_USER | HAT_UNORDERED_OK, - HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK); - hat_release_mapping(as->a_hat, uaddr); - segmf_add_gref_pte(seg, uaddr, pte_ma); - uaddr += PAGESIZE; - } - - state->bt_map.um_registered = B_TRUE; - - AS_LOCK_EXIT(as); - - return (DDI_SUCCESS); -} - - -/* - * xpvtap_segmf_unregister() - * as_callback routine - */ -/*ARGSUSED*/ -static void -xpvtap_segmf_unregister(struct as *as, void *arg, uint_t event) -{ - xpvtap_state_t *state; - caddr_t uaddr; - uint_t pgcnt; - int i; - - - state = (xpvtap_state_t *)arg; - if (!state->bt_map.um_registered) { - /* remove the callback (which is this routine) */ - (void) as_delete_callback(as, arg); - return; - } - - pgcnt = btopr(state->bt_map.um_guest_size); - uaddr = state->bt_map.um_guest_pages; - - /* unmap any outstanding req's grefs */ - xpvtap_rs_flush(state->bt_map.um_rs, xpvtap_user_request_unmap, state); - - /* Unlock the gref pages */ - for (i = 0; i < pgcnt; i++) { - AS_LOCK_ENTER(as, RW_WRITER); - hat_prepare_mapping(as->a_hat, uaddr, NULL); - hat_unload(as->a_hat, uaddr, PAGESIZE, HAT_UNLOAD_UNLOCK); - hat_release_mapping(as->a_hat, uaddr); - AS_LOCK_EXIT(as); - uaddr += PAGESIZE; - } - - /* remove the callback (which is this routine) */ - (void) as_delete_callback(as, arg); - - state->bt_map.um_registered = B_FALSE; -} - - -/* - * xpvtap_user_init() - */ -static int -xpvtap_user_init(xpvtap_state_t *state) -{ - xpvtap_user_map_t *map; - int e; - - - map = &state->bt_map; - - /* Setup the ring between the driver and user app */ - e = xpvtap_user_ring_init(state); - if (e != DDI_SUCCESS) { - return (DDI_FAILURE); - } - - /* - * the user ring can handle BLKIF_RING_SIZE outstanding requests. This - * is the same number of requests as the guest ring. Initialize the - * state we use to track request IDs to the user app. These IDs will - * also identify which group of gref pages correspond with the - * request. - */ - xpvtap_rs_init(0, (BLKIF_RING_SIZE - 1), &map->um_rs); - - /* - * allocate the space to store a copy of each outstanding requests. We - * will need to reference the ID and the number of segments when we - * get the response from the user app. - */ - map->um_outstanding_reqs = kmem_zalloc( - sizeof (*map->um_outstanding_reqs) * BLKIF_RING_SIZE, - KM_SLEEP); - - /* - * initialize the thread we use to process guest requests and user - * responses. - */ - e = xpvtap_user_thread_init(state); - if (e != DDI_SUCCESS) { - goto userinitfail_user_thread_init; - } - - return (DDI_SUCCESS); - -userinitfail_user_thread_init: - xpvtap_rs_fini(&map->um_rs); - kmem_free(map->um_outstanding_reqs, - sizeof (*map->um_outstanding_reqs) * BLKIF_RING_SIZE); - xpvtap_user_ring_fini(state); - return (DDI_FAILURE); -} - - -/* - * xpvtap_user_ring_init() - */ -static int -xpvtap_user_ring_init(xpvtap_state_t *state) -{ - xpvtap_user_ring_t *usring; - - - usring = &state->bt_user_ring; - - /* alocate and initialize the page for the shared user ring */ - usring->ur_sring = (blkif_sring_t *)ddi_umem_alloc(PAGESIZE, - DDI_UMEM_SLEEP, &usring->ur_cookie); - SHARED_RING_INIT(usring->ur_sring); - FRONT_RING_INIT(&usring->ur_ring, usring->ur_sring, PAGESIZE); - usring->ur_prod_polled = 0; - - return (DDI_SUCCESS); -} - - -/* - * xpvtap_user_thread_init() - */ -static int -xpvtap_user_thread_init(xpvtap_state_t *state) -{ - xpvtap_user_thread_t *thread; - char taskqname[32]; - - - thread = &state->bt_thread; - - mutex_init(&thread->ut_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&thread->ut_wake_cv, NULL, CV_DRIVER, NULL); - cv_init(&thread->ut_exit_done_cv, NULL, CV_DRIVER, NULL); - thread->ut_wake = B_FALSE; - thread->ut_exit = B_FALSE; - thread->ut_exit_done = B_TRUE; - - /* create but don't start the user thread */ - (void) sprintf(taskqname, "xvptap_%d", state->bt_instance); - thread->ut_taskq = ddi_taskq_create(state->bt_dip, taskqname, 1, - TASKQ_DEFAULTPRI, 0); - if (thread->ut_taskq == NULL) { - goto userinitthrfail_taskq_create; - } - - return (DDI_SUCCESS); - -userinitthrfail_taskq_dispatch: - ddi_taskq_destroy(thread->ut_taskq); -userinitthrfail_taskq_create: - cv_destroy(&thread->ut_exit_done_cv); - cv_destroy(&thread->ut_wake_cv); - mutex_destroy(&thread->ut_mutex); - - return (DDI_FAILURE); -} - - -/* - * xpvtap_user_thread_start() - */ -static void -xpvtap_user_thread_start(caddr_t arg) -{ - xpvtap_user_thread_t *thread; - xpvtap_state_t *state; - int e; - - - state = (xpvtap_state_t *)arg; - thread = &state->bt_thread; - - /* start the user thread */ - thread->ut_exit_done = B_FALSE; - e = ddi_taskq_dispatch(thread->ut_taskq, xpvtap_user_thread, state, - DDI_SLEEP); - if (e != DDI_SUCCESS) { - thread->ut_exit_done = B_TRUE; - cmn_err(CE_WARN, "Unable to start user thread\n"); - } -} - - -/* - * xpvtap_user_thread_stop() - */ -static void -xpvtap_user_thread_stop(xpvtap_state_t *state) -{ - /* wake thread so it can exit */ - mutex_enter(&state->bt_thread.ut_mutex); - state->bt_thread.ut_wake = B_TRUE; - state->bt_thread.ut_exit = B_TRUE; - cv_signal(&state->bt_thread.ut_wake_cv); - if (!state->bt_thread.ut_exit_done) { - cv_wait(&state->bt_thread.ut_exit_done_cv, - &state->bt_thread.ut_mutex); - } - mutex_exit(&state->bt_thread.ut_mutex); - ASSERT(state->bt_thread.ut_exit_done); -} - - -/* - * xpvtap_user_fini() - */ -static void -xpvtap_user_fini(xpvtap_state_t *state) -{ - xpvtap_user_map_t *map; - - - map = &state->bt_map; - - xpvtap_user_thread_fini(state); - xpvtap_rs_fini(&map->um_rs); - kmem_free(map->um_outstanding_reqs, - sizeof (*map->um_outstanding_reqs) * BLKIF_RING_SIZE); - xpvtap_user_ring_fini(state); -} - - -/* - * xpvtap_user_ring_fini() - */ -static void -xpvtap_user_ring_fini(xpvtap_state_t *state) -{ - ddi_umem_free(state->bt_user_ring.ur_cookie); -} - - -/* - * xpvtap_user_thread_fini() - */ -static void -xpvtap_user_thread_fini(xpvtap_state_t *state) -{ - ddi_taskq_destroy(state->bt_thread.ut_taskq); - cv_destroy(&state->bt_thread.ut_exit_done_cv); - cv_destroy(&state->bt_thread.ut_wake_cv); - mutex_destroy(&state->bt_thread.ut_mutex); -} - - -/* - * xpvtap_user_thread() - */ -static void -xpvtap_user_thread(void *arg) -{ - xpvtap_user_thread_t *thread; - blkif_response_t resp; - xpvtap_state_t *state; - blkif_request_t req; - boolean_t b; - uint_t uid; - int e; - - - state = (xpvtap_state_t *)arg; - thread = &state->bt_thread; - -xpvtap_thread_start: - /* See if we are supposed to exit */ - mutex_enter(&thread->ut_mutex); - if (thread->ut_exit) { - thread->ut_exit_done = B_TRUE; - cv_signal(&state->bt_thread.ut_exit_done_cv); - mutex_exit(&thread->ut_mutex); - return; - } - - /* - * if we aren't supposed to be awake, wait until someone wakes us. - * when we wake up, check for a kill or someone telling us to exit. - */ - if (!thread->ut_wake) { - e = cv_wait_sig(&thread->ut_wake_cv, &thread->ut_mutex); - if ((e == 0) || (thread->ut_exit)) { - thread->ut_exit = B_TRUE; - mutex_exit(&thread->ut_mutex); - goto xpvtap_thread_start; - } - } - - /* if someone didn't wake us, go back to the start of the thread */ - if (!thread->ut_wake) { - mutex_exit(&thread->ut_mutex); - goto xpvtap_thread_start; - } - - /* we are awake */ - thread->ut_wake = B_FALSE; - mutex_exit(&thread->ut_mutex); - - /* process requests from the guest */ - do { - /* - * check for requests from the guest. if we don't have any, - * break out of the loop. - */ - e = blk_ring_request_get(state->bt_guest_ring, &req); - if (e == B_FALSE) { - break; - } - - /* we got a request, map the grefs into the user app's VA */ - e = xpvtap_user_request_map(state, &req, &uid); - if (e != DDI_SUCCESS) { - /* - * If we couldn't map the request (e.g. user app hasn't - * opened the device yet), requeue it and try again - * later - */ - blk_ring_request_requeue(state->bt_guest_ring); - break; - } - - /* push the request to the user app */ - e = xpvtap_user_request_push(state, &req, uid); - if (e != DDI_SUCCESS) { - resp.id = req.id; - resp.operation = req.operation; - resp.status = BLKIF_RSP_ERROR; - blk_ring_response_put(state->bt_guest_ring, &resp); - } - } while (!thread->ut_exit); - - /* process reponses from the user app */ - do { - /* - * check for responses from the user app. if we don't have any, - * break out of the loop. - */ - b = xpvtap_user_response_get(state, &resp, &uid); - if (b != B_TRUE) { - break; - } - - /* - * if we got a response, unmap the grefs from the matching - * request. - */ - xpvtap_user_request_unmap(state, uid); - - /* push the response to the guest */ - blk_ring_response_put(state->bt_guest_ring, &resp); - } while (!thread->ut_exit); - - goto xpvtap_thread_start; -} - - -/* - * xpvtap_user_request_map() - */ -static int -xpvtap_user_request_map(xpvtap_state_t *state, blkif_request_t *req, - uint_t *uid) -{ - grant_ref_t gref[BLKIF_MAX_SEGMENTS_PER_REQUEST]; - struct seg *seg; - struct as *as; - domid_t domid; - caddr_t uaddr; - uint_t flags; - int i; - int e; - - - domid = xvdi_get_oeid(state->bt_dip); - - as = state->bt_map.um_as; - if ((as == NULL) || (state->bt_map.um_guest_pages == NULL)) { - return (DDI_FAILURE); - } - - /* has to happen after segmap returns */ - if (!state->bt_map.um_registered) { - /* register the pte's with segmf */ - e = xpvtap_segmf_register(state); - if (e != DDI_SUCCESS) { - return (DDI_FAILURE); - } - } - - /* alloc an ID for the user ring */ - e = xpvtap_rs_alloc(state->bt_map.um_rs, uid); - if (e != DDI_SUCCESS) { - return (DDI_FAILURE); - } - - /* if we don't have any segments to map, we're done */ - if ((req->operation == BLKIF_OP_WRITE_BARRIER) || - (req->operation == BLKIF_OP_FLUSH_DISKCACHE) || - (req->nr_segments == 0)) { - return (DDI_SUCCESS); - } - - /* get the apps gref address */ - uaddr = XPVTAP_GREF_REQADDR(state->bt_map.um_guest_pages, *uid); - - AS_LOCK_ENTER(as, RW_READER); - seg = as_findseg(as, state->bt_map.um_guest_pages, 0); - if ((seg == NULL) || ((uaddr + mmu_ptob(req->nr_segments)) > - (seg->s_base + seg->s_size))) { - AS_LOCK_EXIT(as); - return (DDI_FAILURE); - } - - /* if we are reading from disk, we are writing into memory */ - flags = 0; - if (req->operation == BLKIF_OP_READ) { - flags |= SEGMF_GREF_WR; - } - - /* Load the grefs into seg_mf */ - for (i = 0; i < req->nr_segments; i++) { - gref[i] = req->seg[i].gref; - } - (void) segmf_add_grefs(seg, uaddr, flags, gref, req->nr_segments, - domid); - - AS_LOCK_EXIT(as); - - return (DDI_SUCCESS); -} - - -/* - * xpvtap_user_request_push() - */ -static int -xpvtap_user_request_push(xpvtap_state_t *state, blkif_request_t *req, - uint_t uid) -{ - blkif_request_t *outstanding_req; - blkif_front_ring_t *uring; - blkif_request_t *target; - xpvtap_user_map_t *map; - - - uring = &state->bt_user_ring.ur_ring; - map = &state->bt_map; - - target = RING_GET_REQUEST(uring, uring->req_prod_pvt); - - /* - * Save request from the frontend. used for ID mapping and unmap - * on response/cleanup - */ - outstanding_req = &map->um_outstanding_reqs[uid]; - bcopy(req, outstanding_req, sizeof (*outstanding_req)); - - /* put the request on the user ring */ - bcopy(req, target, sizeof (*req)); - target->id = (uint64_t)uid; - uring->req_prod_pvt++; - - pollwakeup(&state->bt_pollhead, POLLIN | POLLRDNORM); - - return (DDI_SUCCESS); -} - - -static void -xpvtap_user_request_unmap(xpvtap_state_t *state, uint_t uid) -{ - blkif_request_t *req; - struct seg *seg; - struct as *as; - caddr_t uaddr; - int e; - - - as = state->bt_map.um_as; - if (as == NULL) { - return; - } - - /* get a copy of the original request */ - req = &state->bt_map.um_outstanding_reqs[uid]; - - /* unmap the grefs for this request */ - if ((req->operation != BLKIF_OP_WRITE_BARRIER) && - (req->operation != BLKIF_OP_FLUSH_DISKCACHE) && - (req->nr_segments != 0)) { - uaddr = XPVTAP_GREF_REQADDR(state->bt_map.um_guest_pages, uid); - AS_LOCK_ENTER(as, RW_READER); - seg = as_findseg(as, state->bt_map.um_guest_pages, 0); - if ((seg == NULL) || ((uaddr + mmu_ptob(req->nr_segments)) > - (seg->s_base + seg->s_size))) { - AS_LOCK_EXIT(as); - xpvtap_rs_free(state->bt_map.um_rs, uid); - return; - } - - e = segmf_release_grefs(seg, uaddr, req->nr_segments); - if (e != 0) { - cmn_err(CE_WARN, "unable to release grefs"); - } - - AS_LOCK_EXIT(as); - } - - /* free up the user ring id */ - xpvtap_rs_free(state->bt_map.um_rs, uid); -} - - -static int -xpvtap_user_response_get(xpvtap_state_t *state, blkif_response_t *resp, - uint_t *uid) -{ - blkif_front_ring_t *uring; - blkif_response_t *target; - - - uring = &state->bt_user_ring.ur_ring; - - if (!RING_HAS_UNCONSUMED_RESPONSES(uring)) { - return (B_FALSE); - } - - target = NULL; - target = RING_GET_RESPONSE(uring, uring->rsp_cons); - if (target == NULL) { - return (B_FALSE); - } - - /* copy out the user app response */ - bcopy(target, resp, sizeof (*resp)); - uring->rsp_cons++; - - /* restore the quests id from the original request */ - *uid = (uint_t)resp->id; - resp->id = state->bt_map.um_outstanding_reqs[*uid].id; - - return (B_TRUE); -} - - -/* - * xpvtap_user_app_stop() - */ -static void xpvtap_user_app_stop(caddr_t arg) -{ - xpvtap_state_t *state; - clock_t rc; - - state = (xpvtap_state_t *)arg; - - /* - * Give the app 10 secs to exit. If it doesn't exit, it's not a serious - * problem, we just won't auto-detach the driver. - */ - mutex_enter(&state->bt_open.bo_mutex); - if (state->bt_open.bo_opened) { - rc = cv_reltimedwait(&state->bt_open.bo_exit_cv, - &state->bt_open.bo_mutex, drv_usectohz(10000000), - TR_CLOCK_TICK); - if (rc <= 0) { - cmn_err(CE_NOTE, "!user process still has driver open, " - "deferring detach\n"); - } - } - mutex_exit(&state->bt_open.bo_mutex); -} - - -/* - * xpvtap_rs_init() - * Initialize the resource structure. init() returns a handle to be used - * for the rest of the resource functions. This code is written assuming - * that min_val will be close to 0. Therefore, we will allocate the free - * buffer only taking max_val into account. - */ -static void -xpvtap_rs_init(uint_t min_val, uint_t max_val, xpvtap_rs_hdl_t *handle) -{ - xpvtap_rs_t *rstruct; - uint_t array_size; - uint_t index; - - - ASSERT(handle != NULL); - ASSERT(min_val < max_val); - - /* alloc space for resource structure */ - rstruct = kmem_alloc(sizeof (xpvtap_rs_t), KM_SLEEP); - - /* - * Test to see if the max value is 64-bit aligned. If so, we don't need - * to allocate an extra 64-bit word. alloc space for free buffer - * (8 bytes per uint64_t). - */ - if ((max_val & 0x3F) == 0) { - rstruct->rs_free_size = (max_val >> 6) * 8; - } else { - rstruct->rs_free_size = ((max_val >> 6) + 1) * 8; - } - rstruct->rs_free = kmem_alloc(rstruct->rs_free_size, KM_SLEEP); - - /* Initialize resource structure */ - rstruct->rs_min = min_val; - rstruct->rs_last = min_val; - rstruct->rs_max = max_val; - mutex_init(&rstruct->rs_mutex, NULL, MUTEX_DRIVER, NULL); - rstruct->rs_flushing = B_FALSE; - - /* Mark all resources as free */ - array_size = rstruct->rs_free_size >> 3; - for (index = 0; index < array_size; index++) { - rstruct->rs_free[index] = (uint64_t)0xFFFFFFFFFFFFFFFF; - } - - /* setup handle which is returned from this function */ - *handle = rstruct; -} - - -/* - * xpvtap_rs_fini() - * Frees up the space allocated in init(). Notice that a pointer to the - * handle is used for the parameter. fini() will set the handle to NULL - * before returning. - */ -static void -xpvtap_rs_fini(xpvtap_rs_hdl_t *handle) -{ - xpvtap_rs_t *rstruct; - - - ASSERT(handle != NULL); - - rstruct = (xpvtap_rs_t *)*handle; - - mutex_destroy(&rstruct->rs_mutex); - kmem_free(rstruct->rs_free, rstruct->rs_free_size); - kmem_free(rstruct, sizeof (xpvtap_rs_t)); - - /* set handle to null. This helps catch bugs. */ - *handle = NULL; -} - - -/* - * xpvtap_rs_alloc() - * alloc a resource. If alloc fails, we are out of resources. - */ -static int -xpvtap_rs_alloc(xpvtap_rs_hdl_t handle, uint_t *resource) -{ - xpvtap_rs_t *rstruct; - uint_t array_idx; - uint64_t free; - uint_t index; - uint_t last; - uint_t min; - uint_t max; - - - ASSERT(handle != NULL); - ASSERT(resource != NULL); - - rstruct = (xpvtap_rs_t *)handle; - - mutex_enter(&rstruct->rs_mutex); - min = rstruct->rs_min; - max = rstruct->rs_max; - - /* - * Find a free resource. This will return out of the loop once it finds - * a free resource. There are a total of 'max'-'min'+1 resources. - * Performs a round robin allocation. - */ - for (index = min; index <= max; index++) { - - array_idx = rstruct->rs_last >> 6; - free = rstruct->rs_free[array_idx]; - last = rstruct->rs_last & 0x3F; - - /* if the next resource to check is free */ - if ((free & ((uint64_t)1 << last)) != 0) { - /* we are using this resource */ - *resource = rstruct->rs_last; - - /* take it out of the free list */ - rstruct->rs_free[array_idx] &= ~((uint64_t)1 << last); - - /* - * increment the last count so we start checking the - * next resource on the next alloc(). Note the rollover - * at 'max'+1. - */ - rstruct->rs_last++; - if (rstruct->rs_last > max) { - rstruct->rs_last = rstruct->rs_min; - } - - /* unlock the resource structure */ - mutex_exit(&rstruct->rs_mutex); - - return (DDI_SUCCESS); - } - - /* - * This resource is not free, lets go to the next one. Note the - * rollover at 'max'. - */ - rstruct->rs_last++; - if (rstruct->rs_last > max) { - rstruct->rs_last = rstruct->rs_min; - } - } - - mutex_exit(&rstruct->rs_mutex); - - return (DDI_FAILURE); -} - - -/* - * xpvtap_rs_free() - * Free the previously alloc'd resource. Once a resource has been free'd, - * it can be used again when alloc is called. - */ -static void -xpvtap_rs_free(xpvtap_rs_hdl_t handle, uint_t resource) -{ - xpvtap_rs_t *rstruct; - uint_t array_idx; - uint_t offset; - - - ASSERT(handle != NULL); - - rstruct = (xpvtap_rs_t *)handle; - ASSERT(resource >= rstruct->rs_min); - ASSERT(resource <= rstruct->rs_max); - - if (!rstruct->rs_flushing) { - mutex_enter(&rstruct->rs_mutex); - } - - /* Put the resource back in the free list */ - array_idx = resource >> 6; - offset = resource & 0x3F; - rstruct->rs_free[array_idx] |= ((uint64_t)1 << offset); - - if (!rstruct->rs_flushing) { - mutex_exit(&rstruct->rs_mutex); - } -} - - -/* - * xpvtap_rs_flush() - */ -static void -xpvtap_rs_flush(xpvtap_rs_hdl_t handle, xpvtap_rs_cleanup_t callback, - void *arg) -{ - xpvtap_rs_t *rstruct; - uint_t array_idx; - uint64_t free; - uint_t index; - uint_t last; - uint_t min; - uint_t max; - - - ASSERT(handle != NULL); - - rstruct = (xpvtap_rs_t *)handle; - - mutex_enter(&rstruct->rs_mutex); - min = rstruct->rs_min; - max = rstruct->rs_max; - - rstruct->rs_flushing = B_TRUE; - - /* - * for all resources not free, call the callback routine to clean it - * up. - */ - for (index = min; index <= max; index++) { - - array_idx = rstruct->rs_last >> 6; - free = rstruct->rs_free[array_idx]; - last = rstruct->rs_last & 0x3F; - - /* if the next resource to check is not free */ - if ((free & ((uint64_t)1 << last)) == 0) { - /* call the callback to cleanup */ - (*callback)(arg, rstruct->rs_last); - - /* put it back in the free list */ - rstruct->rs_free[array_idx] |= ((uint64_t)1 << last); - } - - /* go to the next one. Note the rollover at 'max' */ - rstruct->rs_last++; - if (rstruct->rs_last > max) { - rstruct->rs_last = rstruct->rs_min; - } - } - - mutex_exit(&rstruct->rs_mutex); -} diff --git a/usr/src/uts/common/xen/io/xpvtap.h b/usr/src/uts/common/xen/io/xpvtap.h deleted file mode 100644 index a024944313..0000000000 --- a/usr/src/uts/common/xen/io/xpvtap.h +++ /dev/null @@ -1,185 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_XPVTAP_H -#define _SYS_XPVTAP_H - - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Notification from user app that it has pushed responses */ -#define XPVTAP_IOCTL_RESP_PUSH 1 - -/* Number of bytes the user app should mmap for the gref pages */ -#define XPVTAP_GREF_BUFSIZE \ - (BLKIF_RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGESIZE) - - -#ifdef _KERNEL - -#include - - -#define XPVTAP_GREF_REQADDR(base, id) (caddr_t) \ - ((uintptr_t)base + (id * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGESIZE)) - -/* structure used to keep track of resources */ -typedef struct xpvtap_rs_s { - /* - * Bounds of resource allocation. We will start allocating at rs_min - * and rollover at rs_max+1 (rs_max is included). e.g. for rs_min=0 - * and rs_max=7, we will have 8 total resources which can be alloced. - */ - uint_t rs_min; - uint_t rs_max; - - /* - * rs_free points to an array of 64-bit values used to track resource - * allocation. rs_free_size is the free buffer size in bytes. - */ - uint64_t *rs_free; - uint_t rs_free_size; - - /* - * last tracks the last alloc'd resource. This allows us to do a round - * robin allocation. - */ - uint_t rs_last; - - /* - * set when flushing all allocated resources. We'll know the lock - * is held. - */ - boolean_t rs_flushing; - - kmutex_t rs_mutex; -} xpvtap_rs_t; -typedef struct xpvtap_rs_s *xpvtap_rs_hdl_t; - -/* track if user app has the device open, and sleep waiting for close */ -typedef struct xpvtap_open_s { - kmutex_t bo_mutex; - boolean_t bo_opened; - kcondvar_t bo_exit_cv; -} xpvtap_open_t; - -/* - * ring between driver and user app. requests are forwared from the - * guest to the user app on this ring. reponses from the user app come in - * on this ring are then are forwarded to the guest. - */ -typedef struct xpvtap_user_ring_s { - /* ring state */ - blkif_front_ring_t ur_ring; - - /* - * pointer to allocated memory for the ring which is shared between - * the driver and the app. - */ - blkif_sring_t *ur_sring; - - /* umem cookie for free'ing up the umem */ - ddi_umem_cookie_t ur_cookie; - - RING_IDX ur_prod_polled; -} xpvtap_user_ring_t; - -/* - * track the requests that come in from the guest. we need to track the - * requests for two reasons. first, we need to know how many grefs we need - * to unmap when the app sends the response. second, since we use the ID in - * the request to index into um_guest_pages (tells the app where the segments - * are mapped), we need to have a mapping between the the ID we sent in the - * request to the app and the ID we got from the guest request. The response - * to the guest needs to have the later. - */ -typedef struct xpvtap_user_map_s { - /* address space of the user app. grab this in open */ - struct as *um_as; - - /* state to track request IDs we can send to the user app */ - xpvtap_rs_hdl_t um_rs; - - /* - * base user app VA of the mapped grefs. this VA space is large enough - * to map the max pages per request * max outstanding requests. - */ - caddr_t um_guest_pages; - size_t um_guest_size; - - /* - * have we locked down the gref buffer's ptes and registered - * them with segmf. This needs to happen after the user app - * has mmaped the gref buf. - */ - boolean_t um_registered; - - /* - * array of outstanding requests to the user app. Index into this - * array using the ID in the user app request. - */ - blkif_request_t *um_outstanding_reqs; -} xpvtap_user_map_t; - -/* thread start, wake, exit state */ -typedef struct xpvtap_user_thread_s { - kmutex_t ut_mutex; - kcondvar_t ut_wake_cv; - volatile boolean_t ut_wake; - volatile boolean_t ut_exit; - kcondvar_t ut_exit_done_cv; - volatile boolean_t ut_exit_done; - ddi_taskq_t *ut_taskq; -} xpvtap_user_thread_t; - -/* driver state */ -typedef struct xpvtap_state_s { - dev_info_t *bt_dip; - int bt_instance; - - /* ring between the guest and xpvtap */ - blk_ring_t bt_guest_ring; - - /* ring between xpvtap and the user app */ - xpvtap_user_ring_t bt_user_ring; - - xpvtap_user_map_t bt_map; - xpvtap_user_thread_t bt_thread; - struct pollhead bt_pollhead; - xpvtap_open_t bt_open; -} xpvtap_state_t; - -#endif /* _KERNEL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XPVTAP_H */ diff --git a/usr/src/uts/common/xen/os/gnttab.c b/usr/src/uts/common/xen/os/gnttab.c deleted file mode 100644 index ff3cebfc94..0000000000 --- a/usr/src/uts/common/xen/os/gnttab.c +++ /dev/null @@ -1,681 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * gnttab.c - * - * Granting foreign access to our memory reservation. - * - * Copyright (c) 2005-2006, Christopher Clark - * Copyright (c) 2004-2005, K A Fraser - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#ifdef XPV_HVM_DRIVER -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef XPV_HVM_DRIVER -#include -#include -#include -#endif -#include -#include -#include -#include - -/* Globals */ - -static grant_ref_t **gnttab_list; -static uint_t nr_grant_frames; -static int gnttab_free_count; -static grant_ref_t gnttab_free_head; -static kmutex_t gnttab_list_lock; -static grant_entry_t *shared; -static struct gnttab_free_callback *gnttab_free_callback_list; - -/* Macros */ - -#define GT_PGADDR(i) ((uintptr_t)shared + ((i) << MMU_PAGESHIFT)) -#define VALID_GRANT_REF(r) ((r) < (nr_grant_frames * GREFS_PER_GRANT_FRAME)) -#define RPP (PAGESIZE / sizeof (grant_ref_t)) -#define GNTTAB_ENTRY(entry) (gnttab_list[(entry) / RPP][(entry) % RPP]) -#define CMPXCHG(t, c, n) atomic_cas_16((t), (c), (n)) -/* External tools reserve first few grant table entries. */ -#define NR_RESERVED_ENTRIES 8 -#define GNTTAB_LIST_END 0xffffffff -#define GREFS_PER_GRANT_FRAME (PAGESIZE / sizeof (grant_entry_t)) - -/* Implementation */ - -static uint_t -max_nr_grant_frames(void) -{ - struct gnttab_query_size query; - int rc; - - query.dom = DOMID_SELF; - - rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1); - if ((rc < 0) || (query.status != GNTST_okay)) - return (4); /* Legacy max supported number of frames */ - - ASSERT(query.max_nr_frames); - return (query.max_nr_frames); -} - -static void -do_free_callbacks(void) -{ - struct gnttab_free_callback *callback, *next; - - callback = gnttab_free_callback_list; - gnttab_free_callback_list = NULL; - - while (callback != NULL) { - next = callback->next; - if (gnttab_free_count >= callback->count) { - callback->next = NULL; - callback->fn(callback->arg); - } else { - callback->next = gnttab_free_callback_list; - gnttab_free_callback_list = callback; - } - callback = next; - } -} - -static void -check_free_callbacks(void) -{ - if (gnttab_free_callback_list) - do_free_callbacks(); -} - -static int -grow_gnttab_list(uint_t more_frames) -{ - uint_t new_nr_grant_frames, extra_entries, i; - uint_t nr_glist_frames, new_nr_glist_frames; - - ASSERT(MUTEX_HELD(&gnttab_list_lock)); - - new_nr_grant_frames = nr_grant_frames + more_frames; - extra_entries = more_frames * GREFS_PER_GRANT_FRAME; - - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) - / RPP; - new_nr_glist_frames = (new_nr_grant_frames * GREFS_PER_GRANT_FRAME - + RPP - 1) / RPP; - for (i = nr_glist_frames; i < new_nr_glist_frames; i++) - gnttab_list[i] = kmem_alloc(PAGESIZE, KM_SLEEP); - - for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; - i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) - GNTTAB_ENTRY(i) = i + 1; - - GNTTAB_ENTRY(i) = gnttab_free_head; - gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; - gnttab_free_count += extra_entries; - - nr_grant_frames = new_nr_grant_frames; - - check_free_callbacks(); - - return (0); -} - -static int -gnttab_expand(uint_t req_entries) -{ - uint_t cur, extra; - - ASSERT(MUTEX_HELD(&gnttab_list_lock)); - - cur = nr_grant_frames; - extra = ((req_entries + (GREFS_PER_GRANT_FRAME - 1)) / - GREFS_PER_GRANT_FRAME); - if (cur + extra > max_nr_grant_frames()) - return (-1); - - return (grow_gnttab_list(extra)); -} - -static int -get_free_entries(int count) -{ - int ref, rc; - grant_ref_t head; - - mutex_enter(&gnttab_list_lock); - if (gnttab_free_count < count && - ((rc = gnttab_expand(count - gnttab_free_count)) < 0)) { - mutex_exit(&gnttab_list_lock); - return (rc); - } - ref = head = gnttab_free_head; - gnttab_free_count -= count; - while (count-- > 1) - head = GNTTAB_ENTRY(head); - gnttab_free_head = GNTTAB_ENTRY(head); - GNTTAB_ENTRY(head) = GNTTAB_LIST_END; - mutex_exit(&gnttab_list_lock); - return (ref); -} - -static void -put_free_entry(grant_ref_t ref) -{ - ASSERT(VALID_GRANT_REF(ref)); - - mutex_enter(&gnttab_list_lock); - GNTTAB_ENTRY(ref) = gnttab_free_head; - gnttab_free_head = ref; - gnttab_free_count++; - check_free_callbacks(); - mutex_exit(&gnttab_list_lock); -} - -/* - * Public grant-issuing interface functions - */ - -int -gnttab_grant_foreign_access(domid_t domid, gnttab_frame_t frame, int readonly) -{ - int ref; - - if ((ref = get_free_entries(1)) == -1) - return (-1); - - ASSERT(VALID_GRANT_REF(ref)); - - shared[ref].frame = frame; - shared[ref].domid = domid; - membar_producer(); - shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); - - return (ref); -} - -void -gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, - gnttab_frame_t frame, int readonly) -{ - ASSERT(VALID_GRANT_REF(ref)); - - shared[ref].frame = frame; - shared[ref].domid = domid; - membar_producer(); - shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); -} - - -int -gnttab_query_foreign_access(grant_ref_t ref) -{ - uint16_t nflags; - - ASSERT(VALID_GRANT_REF(ref)); - - nflags = shared[ref].flags; - - return (nflags & (GTF_reading|GTF_writing)); -} - -/* ARGSUSED */ -int -gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly) -{ - uint16_t flags, nflags; - - ASSERT(VALID_GRANT_REF(ref)); - - nflags = shared[ref].flags; - do { - if ((flags = nflags) & (GTF_reading|GTF_writing)) { - cmn_err(CE_WARN, "g.e. still in use!"); - return (0); - } - } while ((nflags = CMPXCHG(&shared[ref].flags, flags, 0)) != flags); - - return (1); -} - -void -gnttab_end_foreign_access(grant_ref_t ref, int readonly, gnttab_frame_t page) -{ - ASSERT(VALID_GRANT_REF(ref)); - - if (gnttab_end_foreign_access_ref(ref, readonly)) { - put_free_entry(ref); - /* - * XXPV - we don't support freeing a page here - */ - if (page != 0) { - cmn_err(CE_WARN, - "gnttab_end_foreign_access_ref: using unsupported free_page interface"); - /* free_page(page); */ - } - } else { - /* - * XXX This needs to be fixed so that the ref and page are - * placed on a list to be freed up later. - */ - cmn_err(CE_WARN, "leaking g.e. and page still in use!"); - } -} - -int -gnttab_grant_foreign_transfer(domid_t domid, pfn_t pfn) -{ - int ref; - - if ((ref = get_free_entries(1)) == -1) - return (-1); - - ASSERT(VALID_GRANT_REF(ref)); - - gnttab_grant_foreign_transfer_ref(ref, domid, pfn); - - return (ref); -} - -void -gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid, pfn_t pfn) -{ - ASSERT(VALID_GRANT_REF(ref)); - - shared[ref].frame = pfn; - shared[ref].domid = domid; - membar_producer(); - shared[ref].flags = GTF_accept_transfer; -} - -gnttab_frame_t -gnttab_end_foreign_transfer_ref(grant_ref_t ref) -{ - gnttab_frame_t frame; - uint16_t flags; - - ASSERT(VALID_GRANT_REF(ref)); - - /* - * If a transfer is not even yet started, try to reclaim the grant - * reference and return failure (== 0). - */ - while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { - if (CMPXCHG(&shared[ref].flags, flags, 0) == flags) - return (0); - (void) HYPERVISOR_yield(); - } - - /* If a transfer is in progress then wait until it is completed. */ - while (!(flags & GTF_transfer_completed)) { - flags = shared[ref].flags; - (void) HYPERVISOR_yield(); - } - - /* Read the frame number /after/ reading completion status. */ - membar_consumer(); - frame = shared[ref].frame; - ASSERT(frame != 0); - - return (frame); -} - -gnttab_frame_t -gnttab_end_foreign_transfer(grant_ref_t ref) -{ - gnttab_frame_t frame; - - ASSERT(VALID_GRANT_REF(ref)); - - frame = gnttab_end_foreign_transfer_ref(ref); - put_free_entry(ref); - return (frame); -} - -void -gnttab_free_grant_reference(grant_ref_t ref) -{ - ASSERT(VALID_GRANT_REF(ref)); - - put_free_entry(ref); -} - -void -gnttab_free_grant_references(grant_ref_t head) -{ - grant_ref_t ref; - int count = 1; - - if (head == GNTTAB_LIST_END) - return; - mutex_enter(&gnttab_list_lock); - ref = head; - while (GNTTAB_ENTRY(ref) != GNTTAB_LIST_END) { - ref = GNTTAB_ENTRY(ref); - count++; - } - GNTTAB_ENTRY(ref) = gnttab_free_head; - gnttab_free_head = head; - gnttab_free_count += count; - check_free_callbacks(); - mutex_exit(&gnttab_list_lock); -} - -int -gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head) -{ - int h = get_free_entries(count); - - if (h == -1) - return (-1); - - *head = h; - - return (0); -} - -int -gnttab_empty_grant_references(const grant_ref_t *private_head) -{ - return (*private_head == GNTTAB_LIST_END); -} - -int -gnttab_claim_grant_reference(grant_ref_t *private_head) -{ - grant_ref_t g = *private_head; - - if (g == GNTTAB_LIST_END) - return (-1); - *private_head = GNTTAB_ENTRY(g); - return (g); -} - -void -gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t release) -{ - ASSERT(VALID_GRANT_REF(release)); - - GNTTAB_ENTRY(release) = *private_head; - *private_head = release; -} - -void -gnttab_request_free_callback(struct gnttab_free_callback *callback, - void (*fn)(void *), void *arg, uint16_t count) -{ - mutex_enter(&gnttab_list_lock); - if (callback->next) - goto out; - callback->fn = fn; - callback->arg = arg; - callback->count = count; - callback->next = gnttab_free_callback_list; - gnttab_free_callback_list = callback; - check_free_callbacks(); -out: - mutex_exit(&gnttab_list_lock); -} - -void -gnttab_cancel_free_callback(struct gnttab_free_callback *callback) -{ - struct gnttab_free_callback **pcb; - - mutex_enter(&gnttab_list_lock); - for (pcb = &gnttab_free_callback_list; *pcb; pcb = &(*pcb)->next) { - if (*pcb == callback) { - *pcb = callback->next; - break; - } - } - mutex_exit(&gnttab_list_lock); -} - -static gnttab_frame_t * -gnttab_setup(gnttab_setup_table_t *pset) -{ - gnttab_frame_t *frames; - - frames = kmem_alloc(pset->nr_frames * sizeof (gnttab_frame_t), - KM_SLEEP); - - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(pset->frame_list, frames); - -#ifndef XPV_HVM_DRIVER - /* - * Take pset->nr_frames pages of grant table space from - * the hypervisor and map it - */ - if ((HYPERVISOR_grant_table_op(GNTTABOP_setup_table, pset, 1) != 0) || - (pset->status != 0)) { - cmn_err(CE_PANIC, "Grant Table setup failed"); - } -#endif - - return (frames); -} - -#ifdef XPV_HVM_DRIVER -static void -gnttab_map(void) -{ - struct xen_add_to_physmap xatp; - caddr_t va; - pfn_t pfn; - int i; - - va = (caddr_t)shared; - for (i = 0; i < max_nr_grant_frames(); i++) { - if ((pfn = hat_getpfnum(kas.a_hat, va)) == PFN_INVALID) - cmn_err(CE_PANIC, "gnttab_map: Invalid pfn"); - - xatp.domid = DOMID_SELF; - xatp.idx = i; - xatp.space = XENMAPSPACE_grant_table; - xatp.gpfn = pfn; - hat_unload(kas.a_hat, va, MMU_PAGESIZE, HAT_UNLOAD); - /* - * This call replaces the existing machine page backing - * the given gpfn with the page from the allocated grant - * table at index idx. The existing machine page is - * returned to the free list. - */ - if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp) != 0) - panic("Couldn't map grant table"); - hat_devload(kas.a_hat, va, MMU_PAGESIZE, pfn, - PROT_READ | PROT_WRITE | HAT_STORECACHING_OK, - HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); - va += MMU_PAGESIZE; - } -} -#endif /* XPV_HVM_DRIVER */ - -void -gnttab_init(void) -{ - gnttab_setup_table_t set; - int i; - uint_t nr_init_grefs, max_nr_glist_frames, nr_glist_frames; - gnttab_frame_t *frames; - - /* - * gnttab_init() should only be invoked once. - */ - mutex_enter(&gnttab_list_lock); - ASSERT(nr_grant_frames == 0); - nr_grant_frames = 1; - mutex_exit(&gnttab_list_lock); - - max_nr_glist_frames = (max_nr_grant_frames() * - GREFS_PER_GRANT_FRAME / RPP); - - set.dom = DOMID_SELF; - set.nr_frames = max_nr_grant_frames(); - frames = gnttab_setup(&set); - -#ifdef XPV_HVM_DRIVER - shared = (grant_entry_t *)xen_alloc_pages(set.nr_frames); - - gnttab_map(); -#else /* XPV_HVM_DRIVER */ - shared = vmem_xalloc(heap_arena, set.nr_frames * MMU_PAGESIZE, - MMU_PAGESIZE, 0, 0, 0, 0, VM_SLEEP); - for (i = 0; i < set.nr_frames; i++) { - hat_devload(kas.a_hat, (caddr_t)GT_PGADDR(i), PAGESIZE, - xen_assign_pfn(frames[i]), - PROT_READ | PROT_WRITE | HAT_STORECACHING_OK, - HAT_LOAD_LOCK); - } -#endif - - gnttab_list = kmem_alloc(max_nr_glist_frames * sizeof (grant_ref_t *), - KM_SLEEP); - - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) - / RPP; - for (i = 0; i < nr_glist_frames; i++) { - gnttab_list[i] = kmem_alloc(PAGESIZE, KM_SLEEP); - } - - kmem_free(frames, set.nr_frames * sizeof (gnttab_frame_t)); - - nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; - - for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) - GNTTAB_ENTRY(i) = i + 1; - - GNTTAB_ENTRY(nr_init_grefs - 1) = GNTTAB_LIST_END; - gnttab_free_count = nr_init_grefs - NR_RESERVED_ENTRIES; - gnttab_free_head = NR_RESERVED_ENTRIES; -} - -void -gnttab_resume(void) -{ - gnttab_setup_table_t set; - int i; - gnttab_frame_t *frames; - uint_t available_frames = max_nr_grant_frames(); - - if (available_frames < nr_grant_frames) { - cmn_err(CE_PANIC, "Hypervisor does not have enough grant " - "frames: required(%u), available(%u)", nr_grant_frames, - available_frames); - } - -#ifdef XPV_HVM_DRIVER - gnttab_map(); -#endif /* XPV_HVM_DRIVER */ - - set.dom = DOMID_SELF; - set.nr_frames = available_frames; - frames = gnttab_setup(&set); - - for (i = 0; i < available_frames; i++) { - (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), - FRAME_TO_MA(frames[i]) | PT_VALID | PT_WRITABLE, - UVMF_INVLPG | UVMF_ALL); - } - kmem_free(frames, set.nr_frames * sizeof (gnttab_frame_t)); -} - -void -gnttab_suspend(void) -{ - int i; - - /* - * clear grant table mappings before suspending - */ - for (i = 0; i < max_nr_grant_frames(); i++) { - (void) HYPERVISOR_update_va_mapping(GT_PGADDR(i), - 0, UVMF_INVLPG); - } -} - -/* - * Local variables: - * c-file-style: "solaris" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/usr/src/uts/common/xen/os/xvdi.c b/usr/src/uts/common/xen/os/xvdi.c deleted file mode 100644 index 28014eee0f..0000000000 --- a/usr/src/uts/common/xen/os/xvdi.c +++ /dev/null @@ -1,2423 +0,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. - */ - -/* - * Copyright (c) 2014 by Delphix. All rights reserved. - */ - -/* - * Xen virtual device driver interfaces - */ - -/* - * todo: - * + name space clean up: - * xvdi_* - public xen interfaces, for use by all leaf drivers - * xd_* - public xen data structures - * i_xvdi_* - implementation private functions - * xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops - * + add mdb dcmds to dump ring status - * + implement xvdi_xxx to wrap xenbus_xxx read/write function - * + convert (xendev_ring_t *) into xvdi_ring_handle_t - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef XPV_HVM_DRIVER -#include -#include -#include -#include -#include -#include -#include -#include -#else /* XPV_HVM_DRIVER */ -#include -#include -#include -#include -#endif /* XPV_HVM_DRIVER */ -#include -#include -#include -#include -#include -#include - - -#define isdigit(ch) ((ch) >= '0' && (ch) <= '9') -#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ - ((ch) >= 'A' && (ch) <= 'F')) - -static void xvdi_ring_init_sring(xendev_ring_t *); -static void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t); -#ifndef XPV_HVM_DRIVER -static void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t); -#endif -static void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *); - -static int i_xvdi_add_watches(dev_info_t *); -static void i_xvdi_rem_watches(dev_info_t *); - -static int i_xvdi_add_watch_oestate(dev_info_t *); -static void i_xvdi_rem_watch_oestate(dev_info_t *); -static void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState); -static void i_xvdi_oestate_handler(void *); - -static int i_xvdi_add_watch_hpstate(dev_info_t *); -static void i_xvdi_rem_watch_hpstate(dev_info_t *); -static void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **, - unsigned int); -static void i_xvdi_hpstate_handler(void *); - -static int i_xvdi_add_watch_bepath(dev_info_t *); -static void i_xvdi_rem_watch_bepath(dev_info_t *); -static void i_xvdi_bepath_cb(struct xenbus_watch *, const char **, - unsigned in); - -static void xendev_offline_device(void *); - -static void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **, - unsigned int); -static void i_xvdi_probe_path_handler(void *); - -typedef struct oestate_evt { - dev_info_t *dip; - XenbusState state; -} i_oestate_evt_t; - -typedef struct xd_cfg { - xendev_devclass_t devclass; - char *xsdev; - char *xs_path_fe; - char *xs_path_be; - char *node_fe; - char *node_be; - char *device_type; - int xd_ipl; - int flags; -} i_xd_cfg_t; - -#define XD_DOM_ZERO 0x01 /* dom0 only. */ -#define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */ -#define XD_DOM_IO 0x04 /* IO domains. */ - -#define XD_DOM_ALL (XD_DOM_ZERO | XD_DOM_GUEST) - -static i_xd_cfg_t xdci[] = { -#ifndef XPV_HVM_DRIVER - { XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL, - "console", IPL_CONS, XD_DOM_ALL, }, -#endif - - { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb", - "network", IPL_VIF, XD_DOM_ALL, }, - - { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb", - "block", IPL_VBD, XD_DOM_ALL, }, - - { XEN_BLKTAP, "tap", NULL, "backend/tap", NULL, "xpvtap", - "block", IPL_VBD, XD_DOM_ALL, }, - -#ifndef XPV_HVM_DRIVER - { XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL, - NULL, 0, XD_DOM_ALL, }, - - { XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL, - NULL, 0, XD_DOM_ALL, }, - - { XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL, - NULL, 0, XD_DOM_ALL, }, -#endif - - { XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL, - NULL, 0, XD_DOM_ZERO, }, - - { XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL, - NULL, 0, XD_DOM_ZERO, }, -}; -#define NXDC (sizeof (xdci) / sizeof (xdci[0])) - -static void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *); -static void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *); -static void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *); - -/* - * Xen device channel device access and DMA attributes - */ -static ddi_device_acc_attr_t xendev_dc_accattr = { - DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC -}; - -static ddi_dma_attr_t xendev_dc_dmaattr = { - 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 */ - 0xffffffffffffffffULL, /* maximum segment length */ - 1, /* maximum number of segments */ - 1, /* granularity */ - 0, /* flags (reserved) */ -}; - -static dev_info_t *xendev_dip = NULL; - -#define XVDI_DBG_STATE 0x01 -#define XVDI_DBG_PROBE 0x02 - -#ifdef DEBUG -int i_xvdi_debug = 0; - -#define XVDI_DPRINTF(flag, format, ...) \ -{ \ - if (i_xvdi_debug & (flag)) \ - prom_printf((format), __VA_ARGS__); \ -} -#else -#define XVDI_DPRINTF(flag, format, ...) -#endif /* DEBUG */ - -static i_xd_cfg_t * -i_xvdi_devclass2cfg(xendev_devclass_t devclass) -{ - i_xd_cfg_t *xdcp; - int i; - - for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) - if (xdcp->devclass == devclass) - return (xdcp); - - return (NULL); -} - -int -xvdi_init_dev(dev_info_t *dip) -{ - xendev_devclass_t devcls; - int vdevnum; - domid_t domid; - struct xendev_ppd *pdp; - i_xd_cfg_t *xdcp; - boolean_t backend; - char xsnamebuf[TYPICALMAXPATHLEN]; - char *xsname; - void *prop_str; - unsigned int prop_len; - char unitaddr[8]; - - devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "devclass", XEN_INVAL); - vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "vdev", VDEV_NOXS); - domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "domain", DOMID_SELF); - - backend = (domid != DOMID_SELF); - xdcp = i_xvdi_devclass2cfg(devcls); - if (xdcp->device_type != NULL) - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, - "device_type", xdcp->device_type); - - pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP); - pdp->xd_domain = domid; - pdp->xd_vdevnum = vdevnum; - pdp->xd_devclass = devcls; - pdp->xd_evtchn = INVALID_EVTCHN; - list_create(&pdp->xd_xb_watches, sizeof (xd_xb_watches_t), - offsetof(xd_xb_watches_t, xxw_list)); - mutex_init(&pdp->xd_evt_lk, NULL, MUTEX_DRIVER, NULL); - mutex_init(&pdp->xd_ndi_lk, NULL, MUTEX_DRIVER, NULL); - ddi_set_parent_data(dip, pdp); - - /* - * devices that do not need to interact with xenstore - */ - if (vdevnum == VDEV_NOXS) { - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, - "unit-address", "0"); - if (devcls == XEN_CONSOLE) - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, - "pm-hardware-state", "needs-suspend-resume"); - return (DDI_SUCCESS); - } - - /* - * PV devices that need to probe xenstore - */ - - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, - "pm-hardware-state", "needs-suspend-resume"); - - xsname = xsnamebuf; - if (!backend) - (void) snprintf(xsnamebuf, sizeof (xsnamebuf), - "%s/%d", xdcp->xs_path_fe, vdevnum); - else - (void) snprintf(xsnamebuf, sizeof (xsnamebuf), - "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum); - if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) { - /* Don't try to init a dev that may be closing */ - mutex_destroy(&pdp->xd_ndi_lk); - mutex_destroy(&pdp->xd_evt_lk); - kmem_free(pdp, sizeof (*pdp)); - ddi_set_parent_data(dip, NULL); - return (DDI_FAILURE); - } - - pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP); - pdp->xd_xsdev.devicetype = xdcp->xsdev; - pdp->xd_xsdev.frontend = (backend ? 0 : 1); - pdp->xd_xsdev.data = dip; - pdp->xd_xsdev.otherend_id = (backend ? domid : -1); - if (i_xvdi_add_watches(dip) != DDI_SUCCESS) { - cmn_err(CE_WARN, "xvdi_init_dev: " - "cannot add watches for %s", xsname); - xvdi_uninit_dev(dip); - return (DDI_FAILURE); - } - - if (backend) - return (DDI_SUCCESS); - - /* - * The unit-address for frontend devices is the name of the - * of the xenstore node containing the device configuration - * and is contained in the 'vdev' property. - * VIF devices are named using an incrementing integer. - * VBD devices are either named using the 16-bit dev_t value - * for linux 'hd' and 'xvd' devices, or a simple integer value - * in the range 0..767. 768 is the base value of the linux - * dev_t namespace, the dev_t value for 'hda'. - */ - (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum); - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address", - unitaddr); - - switch (devcls) { - case XEN_VNET: - if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str, - &prop_len) != 0) - break; - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac", - prop_str); - kmem_free(prop_str, prop_len); - break; - case XEN_VBLK: - /* - * cache a copy of the otherend name - * for ease of observeability - */ - if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, "dev", - &prop_str, &prop_len) != 0) - break; - (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, - "dev-address", prop_str); - kmem_free(prop_str, prop_len); - break; - default: - break; - } - - return (DDI_SUCCESS); -} - -void -xvdi_uninit_dev(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - if (pdp != NULL) { - /* Remove any registered callbacks. */ - xvdi_remove_event_handler(dip, NULL); - - /* Remove any registered watches. */ - i_xvdi_rem_watches(dip); - - /* tell other end to close */ - if (pdp->xd_xsdev.otherend_id != (domid_t)-1) - (void) xvdi_switch_state(dip, XBT_NULL, - XenbusStateClosed); - - if (pdp->xd_xsdev.nodename != NULL) - kmem_free((char *)(pdp->xd_xsdev.nodename), - strlen(pdp->xd_xsdev.nodename) + 1); - - ddi_set_parent_data(dip, NULL); - - mutex_destroy(&pdp->xd_ndi_lk); - mutex_destroy(&pdp->xd_evt_lk); - kmem_free(pdp, sizeof (*pdp)); - } -} - -/* - * Bind the event channel for this device instance. - * Currently we only support one evtchn per device instance. - */ -int -xvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn) -{ - struct xendev_ppd *pdp; - domid_t oeid; - int r; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); - - mutex_enter(&pdp->xd_evt_lk); - if (pdp->xd_devclass == XEN_CONSOLE) { - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - pdp->xd_evtchn = xen_info->console.domU.evtchn; - } else { - pdp->xd_evtchn = INVALID_EVTCHN; - mutex_exit(&pdp->xd_evt_lk); - return (DDI_SUCCESS); - } - } else { - oeid = pdp->xd_xsdev.otherend_id; - if (oeid == (domid_t)-1) { - mutex_exit(&pdp->xd_evt_lk); - return (DDI_FAILURE); - } - - if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) { - xvdi_dev_error(dip, r, "bind event channel"); - mutex_exit(&pdp->xd_evt_lk); - return (DDI_FAILURE); - } - } -#ifndef XPV_HVM_DRIVER - pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); -#endif - mutex_exit(&pdp->xd_evt_lk); - - return (DDI_SUCCESS); -} - -/* - * Allocate an event channel for this device instance. - * Currently we only support one evtchn per device instance. - */ -int -xvdi_alloc_evtchn(dev_info_t *dip) -{ - struct xendev_ppd *pdp; - domid_t oeid; - int rv; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); - - mutex_enter(&pdp->xd_evt_lk); - if (pdp->xd_devclass == XEN_CONSOLE) { - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - pdp->xd_evtchn = xen_info->console.domU.evtchn; - } else { - pdp->xd_evtchn = INVALID_EVTCHN; - mutex_exit(&pdp->xd_evt_lk); - return (DDI_SUCCESS); - } - } else { - oeid = pdp->xd_xsdev.otherend_id; - if (oeid == (domid_t)-1) { - mutex_exit(&pdp->xd_evt_lk); - return (DDI_FAILURE); - } - - if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) { - xvdi_dev_error(dip, rv, "bind event channel"); - mutex_exit(&pdp->xd_evt_lk); - return (DDI_FAILURE); - } - } -#ifndef XPV_HVM_DRIVER - pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); -#endif - mutex_exit(&pdp->xd_evt_lk); - - return (DDI_SUCCESS); -} - -/* - * Unbind the event channel for this device instance. - * Currently we only support one evtchn per device instance. - */ -void -xvdi_free_evtchn(dev_info_t *dip) -{ - struct xendev_ppd *pdp; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - - mutex_enter(&pdp->xd_evt_lk); - if (pdp->xd_evtchn != INVALID_EVTCHN) { -#ifndef XPV_HVM_DRIVER - ec_unbind_irq(pdp->xd_ispec.intrspec_vec); - pdp->xd_ispec.intrspec_vec = 0; -#endif - pdp->xd_evtchn = INVALID_EVTCHN; - } - mutex_exit(&pdp->xd_evt_lk); -} - -#ifndef XPV_HVM_DRIVER -/* - * Map an inter-domain communication ring for a virtual device. - * This is used by backend drivers. - */ -int -xvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize, - grant_ref_t gref, xendev_ring_t **ringpp) -{ - domid_t oeid; - gnttab_map_grant_ref_t mapop; - gnttab_unmap_grant_ref_t unmapop; - caddr_t ringva; - ddi_acc_hdl_t *ap; - ddi_acc_impl_t *iap; - xendev_ring_t *ring; - int err; - char errstr[] = "mapping in ring buffer"; - - ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); - oeid = xvdi_get_oeid(dip); - - /* alloc va in backend dom for ring buffer */ - ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE, - 0, 0, 0, 0, VM_SLEEP); - - /* map in ring page */ - hat_prepare_mapping(kas.a_hat, ringva, NULL); - mapop.host_addr = (uint64_t)(uintptr_t)ringva; - mapop.flags = GNTMAP_host_map; - mapop.ref = gref; - mapop.dom = oeid; - err = xen_map_gref(GNTTABOP_map_grant_ref, &mapop, 1, B_FALSE); - if (err) { - xvdi_fatal_error(dip, err, errstr); - goto errout1; - } - - if (mapop.status != 0) { - xvdi_fatal_error(dip, err, errstr); - goto errout2; - } - ring->xr_vaddr = ringva; - ring->xr_grant_hdl = mapop.handle; - ring->xr_gref = gref; - - /* - * init an acc handle and associate it w/ this ring - * this is only for backend drivers. we get the memory by calling - * vmem_xalloc(), instead of calling any ddi function, so we have - * to init an acc handle by ourselves - */ - ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL); - ap = impl_acc_hdl_get(ring->xr_acc_hdl); - ap->ah_vers = VERS_ACCHDL; - ap->ah_dip = dip; - ap->ah_xfermodes = DDI_DMA_CONSISTENT; - ap->ah_acc = xendev_dc_accattr; - iap = (ddi_acc_impl_t *)ap->ah_platform_private; - iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; - impl_acc_hdl_init(ap); - ap->ah_offset = 0; - ap->ah_len = (off_t)PAGESIZE; - ap->ah_addr = ring->xr_vaddr; - - /* init backend ring */ - xvdi_ring_init_back_ring(ring, nentry, entrysize); - - *ringpp = ring; - - return (DDI_SUCCESS); - -errout2: - /* unmap ring page */ - unmapop.host_addr = (uint64_t)(uintptr_t)ringva; - unmapop.handle = ring->xr_grant_hdl; - unmapop.dev_bus_addr = (uintptr_t)NULL; - (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); - hat_release_mapping(kas.a_hat, ringva); -errout1: - vmem_xfree(heap_arena, ringva, PAGESIZE); - kmem_free(ring, sizeof (xendev_ring_t)); - return (DDI_FAILURE); -} - -/* - * Unmap a ring for a virtual device. - * This is used by backend drivers. - */ -void -xvdi_unmap_ring(xendev_ring_t *ring) -{ - gnttab_unmap_grant_ref_t unmapop; - - ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); - - impl_acc_hdl_free(ring->xr_acc_hdl); - unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr; - unmapop.handle = ring->xr_grant_hdl; - unmapop.dev_bus_addr = (uintptr_t)NULL; - (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); - hat_release_mapping(kas.a_hat, ring->xr_vaddr); - vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE); - kmem_free(ring, sizeof (xendev_ring_t)); -} -#endif /* XPV_HVM_DRIVER */ - -/* - * Re-initialise an inter-domain communications ring for the backend domain. - * ring will be re-initialized after re-grant succeed - * ring will be freed if fails to re-grant access to backend domain - * so, don't keep useful data in the ring - * used only in frontend driver - */ -static void -xvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp) -{ - paddr_t rpaddr; - maddr_t rmaddr; - - ASSERT((ringp != NULL) && (ringp->xr_paddr != 0)); - rpaddr = ringp->xr_paddr; - - rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr); - gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip), - rmaddr >> PAGESHIFT, 0); - *gref = ringp->xr_gref; - - /* init frontend ring */ - xvdi_ring_init_sring(ringp); - xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents, - ringp->xr_entry_size); -} - -/* - * allocate Xen inter-domain communications ring for Xen virtual devices - * used only in frontend driver - * if *ringpp is not NULL, we'll simply re-init it - */ -int -xvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize, - grant_ref_t *gref, xendev_ring_t **ringpp) -{ - size_t len; - xendev_ring_t *ring; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - grant_ref_t ring_gref; - domid_t oeid; - maddr_t rmaddr; - - if (*ringpp) { - xvdi_reinit_ring(dip, gref, *ringpp); - return (DDI_SUCCESS); - } - - *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); - oeid = xvdi_get_oeid(dip); - - /* - * Allocate page for this ring buffer - */ - if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP, - 0, &ring->xr_dma_hdl) != DDI_SUCCESS) - goto err; - - if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE, - &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, - &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) { - ddi_dma_free_handle(&ring->xr_dma_hdl); - goto err; - } - - if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL, - ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) { - ddi_dma_mem_free(&ring->xr_acc_hdl); - ring->xr_vaddr = NULL; - ddi_dma_free_handle(&ring->xr_dma_hdl); - goto err; - } - ASSERT(ncookies == 1); - ring->xr_paddr = dma_cookie.dmac_laddress; - rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr : - pa_to_ma(ring->xr_paddr); - - if ((ring_gref = gnttab_grant_foreign_access(oeid, - rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) { - (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); - ddi_dma_mem_free(&ring->xr_acc_hdl); - ring->xr_vaddr = NULL; - ddi_dma_free_handle(&ring->xr_dma_hdl); - goto err; - } - *gref = ring->xr_gref = ring_gref; - - /* init frontend ring */ - xvdi_ring_init_sring(ring); - xvdi_ring_init_front_ring(ring, nentry, entrysize); - - return (DDI_SUCCESS); - -err: - kmem_free(ring, sizeof (xendev_ring_t)); - return (DDI_FAILURE); -} - -/* - * Release ring buffers allocated for Xen devices - * used for frontend driver - */ -void -xvdi_free_ring(xendev_ring_t *ring) -{ - ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); - - (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0); - (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); - ddi_dma_mem_free(&ring->xr_acc_hdl); - ddi_dma_free_handle(&ring->xr_dma_hdl); - kmem_free(ring, sizeof (xendev_ring_t)); -} - -dev_info_t * -xvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass, - domid_t dom, int vdev) -{ - dev_info_t *dip; - boolean_t backend; - i_xd_cfg_t *xdcp; - char xsnamebuf[TYPICALMAXPATHLEN]; - char *type, *node = NULL, *xsname = NULL; - unsigned int tlen; - int ret; - - ASSERT(DEVI_BUSY_OWNED(parent)); - - backend = (dom != DOMID_SELF); - xdcp = i_xvdi_devclass2cfg(devclass); - ASSERT(xdcp != NULL); - - if (vdev != VDEV_NOXS) { - if (!backend) { - (void) snprintf(xsnamebuf, sizeof (xsnamebuf), - "%s/%d", xdcp->xs_path_fe, vdev); - xsname = xsnamebuf; - node = xdcp->node_fe; - } else { - (void) snprintf(xsnamebuf, sizeof (xsnamebuf), - "%s/%d/%d", xdcp->xs_path_be, dom, vdev); - xsname = xsnamebuf; - node = xdcp->node_be; - } - } else { - node = xdcp->node_fe; - } - - /* Must have a driver to use. */ - if (node == NULL) - return (NULL); - - /* - * We need to check the state of this device before we go - * further, otherwise we'll end up with a dead loop if - * anything goes wrong. - */ - if ((xsname != NULL) && - (xenbus_read_driver_state(xsname) >= XenbusStateClosing)) - return (NULL); - - ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip); - - /* - * Driver binding uses the compatible property _before_ the - * node name, so we set the node name to the 'model' of the - * device (i.e. 'xnb' or 'xdb') and, if 'type' is present, - * encode both the model and the type in a compatible property - * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac'). This allows a - * driver binding based on the pair _before_ a - * binding based on the node name. - */ - if ((xsname != NULL) && - (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen) - == 0)) { - size_t clen; - char *c[1]; - - clen = strlen(node) + strlen(type) + 2; - c[0] = kmem_alloc(clen, KM_SLEEP); - (void) snprintf(c[0], clen, "%s,%s", node, type); - - (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, - dip, "compatible", (char **)c, 1); - - kmem_free(c[0], clen); - kmem_free(type, tlen); - } - - (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass); - (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom); - (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev); - - if (i_ddi_devi_attached(parent)) - ret = ndi_devi_online(dip, 0); - else - ret = ndi_devi_bind_driver(dip, 0); - if (ret != NDI_SUCCESS) - (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); - - return (dip); -} - -/* - * xendev_enum_class() - */ -void -xendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass) -{ - boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); - boolean_t domU = !dom0; - i_xd_cfg_t *xdcp; - - xdcp = i_xvdi_devclass2cfg(devclass); - ASSERT(xdcp != NULL); - - if (dom0 && !(xdcp->flags & XD_DOM_ZERO)) - return; - - if (domU && !(xdcp->flags & XD_DOM_GUEST)) - return; - - if (xdcp->xsdev == NULL) { - int circ; - - /* - * Don't need to probe this kind of device from the - * store, just create one if it doesn't exist. - */ - - ndi_devi_enter(parent, &circ); - if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS) - == NULL) - (void) xvdi_create_dev(parent, devclass, - DOMID_SELF, VDEV_NOXS); - ndi_devi_exit(parent, circ); - } else { - /* - * Probe this kind of device from the store, both - * frontend and backend. - */ - if (xdcp->node_fe != NULL) { - i_xvdi_enum_fe(parent, xdcp); - } - if (xdcp->node_be != NULL) { - i_xvdi_enum_be(parent, xdcp); - } - } -} - -/* - * xendev_enum_all() - */ -void -xendev_enum_all(dev_info_t *parent, boolean_t store_unavailable) -{ - int i; - i_xd_cfg_t *xdcp; - boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); - - for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { - /* - * Dom0 relies on watchpoints to create non-soft - * devices - don't attempt to iterate over the store. - */ - if (dom0 && (xdcp->xsdev != NULL)) - continue; - - /* - * If the store is not yet available, don't attempt to - * iterate. - */ - if (store_unavailable && (xdcp->xsdev != NULL)) - continue; - - xendev_enum_class(parent, xdcp->devclass); - } -} - -xendev_devclass_t -xendev_nodename_to_devclass(char *nodename) -{ - int i; - i_xd_cfg_t *xdcp; - - /* - * This relies on the convention that variants of a base - * driver share the same prefix and that there are no drivers - * which share a common prefix with the name of any other base - * drivers. - * - * So for a base driver 'xnb' (which is the name listed in - * xdci) the variants all begin with the string 'xnb' (in fact - * they are 'xnbe', 'xnbo' and 'xnbu') and there are no other - * base drivers which have the prefix 'xnb'. - */ - ASSERT(nodename != NULL); - for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { - if (((xdcp->node_fe != NULL) && - (strncmp(nodename, xdcp->node_fe, - strlen(xdcp->node_fe)) == 0)) || - ((xdcp->node_be != NULL) && - (strncmp(nodename, xdcp->node_be, - strlen(xdcp->node_be)) == 0))) - - return (xdcp->devclass); - } - return (XEN_INVAL); -} - -int -xendev_devclass_ipl(xendev_devclass_t devclass) -{ - i_xd_cfg_t *xdcp; - - xdcp = i_xvdi_devclass2cfg(devclass); - ASSERT(xdcp != NULL); - - return (xdcp->xd_ipl); -} - -/* - * Determine if a devinfo instance exists of a particular device - * class, domain and xenstore virtual device number. - */ -dev_info_t * -xvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass, - domid_t dom, int vdev) -{ - dev_info_t *dip; - - ASSERT(DEVI_BUSY_OWNED(parent)); - - switch (devclass) { - case XEN_CONSOLE: - case XEN_XENBUS: - case XEN_DOMCAPS: - case XEN_BALLOON: - case XEN_EVTCHN: - case XEN_PRIVCMD: - /* Console and soft devices have no vdev. */ - vdev = VDEV_NOXS; - break; - default: - break; - } - - for (dip = ddi_get_child(parent); dip != NULL; - dip = ddi_get_next_sibling(dip)) { - int *vdevnump, *domidp, *devclsp, vdevnum; - uint_t ndomid, nvdevnum, ndevcls; - xendev_devclass_t devcls; - domid_t domid; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - if (pdp == NULL) { - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "domain", &domidp, &ndomid) != - DDI_PROP_SUCCESS) - continue; - ASSERT(ndomid == 1); - domid = (domid_t)*domidp; - ddi_prop_free(domidp); - - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "vdev", &vdevnump, &nvdevnum) != - DDI_PROP_SUCCESS) - continue; - ASSERT(nvdevnum == 1); - vdevnum = *vdevnump; - ddi_prop_free(vdevnump); - - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "devclass", &devclsp, - &ndevcls) != DDI_PROP_SUCCESS) - continue; - ASSERT(ndevcls == 1); - devcls = (xendev_devclass_t)*devclsp; - ddi_prop_free(devclsp); - } else { - domid = pdp->xd_domain; - vdevnum = pdp->xd_vdevnum; - devcls = pdp->xd_devclass; - } - - if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass)) - return (dip); - } - return (NULL); -} - -int -xvdi_get_evtchn(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - return (pdp->xd_evtchn); -} - -int -xvdi_get_vdevnum(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - return (pdp->xd_vdevnum); -} - -char * -xvdi_get_xsname(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - return ((char *)(pdp->xd_xsdev.nodename)); -} - -char * -xvdi_get_oename(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - if (pdp->xd_devclass == XEN_CONSOLE) - return (NULL); - return ((char *)(pdp->xd_xsdev.otherend)); -} - -struct xenbus_device * -xvdi_get_xsd(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - return (&pdp->xd_xsdev); -} - -domid_t -xvdi_get_oeid(dev_info_t *xdip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(xdip); - - ASSERT(pdp != NULL); - if (pdp->xd_devclass == XEN_CONSOLE) - return ((domid_t)-1); - return ((domid_t)(pdp->xd_xsdev.otherend_id)); -} - -void -xvdi_dev_error(dev_info_t *dip, int errno, char *errstr) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - xenbus_dev_error(&pdp->xd_xsdev, errno, errstr); -} - -void -xvdi_fatal_error(dev_info_t *dip, int errno, char *errstr) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - xenbus_dev_fatal(&pdp->xd_xsdev, errno, errstr); -} - -static void -i_xvdi_oestate_handler(void *arg) -{ - i_oestate_evt_t *evt = (i_oestate_evt_t *)arg; - dev_info_t *dip = evt->dip; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - XenbusState oestate = pdp->xd_xsdev.otherend_state; - XenbusState curr_oestate = evt->state; - ddi_eventcookie_t evc; - - /* evt is alloc'ed in i_xvdi_oestate_cb */ - kmem_free(evt, sizeof (i_oestate_evt_t)); - - /* - * If the oestate we're handling is not the latest one, - * it does not make any sense to continue handling it. - */ - if (curr_oestate != oestate) - return; - - mutex_enter(&pdp->xd_ndi_lk); - - if (pdp->xd_oe_ehid != NULL) { - /* send notification to driver */ - if (ddi_get_eventcookie(dip, XS_OE_STATE, - &evc) == DDI_SUCCESS) { - mutex_exit(&pdp->xd_ndi_lk); - (void) ndi_post_event(dip, dip, evc, &oestate); - mutex_enter(&pdp->xd_ndi_lk); - } - } else { - /* - * take default action, if driver hasn't registered its - * event handler yet - */ - if (oestate == XenbusStateClosing) { - (void) xvdi_switch_state(dip, XBT_NULL, - XenbusStateClosed); - } else if (oestate == XenbusStateClosed) { - (void) xvdi_switch_state(dip, XBT_NULL, - XenbusStateClosed); - (void) xvdi_post_event(dip, XEN_HP_REMOVE); - } - } - - mutex_exit(&pdp->xd_ndi_lk); - - /* - * We'll try to remove the devinfo node of this device if the - * other end has closed. - */ - if (oestate == XenbusStateClosed) - (void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq, - xendev_offline_device, dip, DDI_SLEEP); -} - -static void -i_xvdi_hpstate_handler(void *arg) -{ - dev_info_t *dip = (dev_info_t *)arg; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - ddi_eventcookie_t evc; - char *hp_status; - unsigned int hpl; - - mutex_enter(&pdp->xd_ndi_lk); - if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) && - (xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "", - (void *)&hp_status, &hpl) == 0)) { - - xendev_hotplug_state_t new_state = Unrecognized; - - if (strcmp(hp_status, "connected") == 0) - new_state = Connected; - - mutex_exit(&pdp->xd_ndi_lk); - - (void) ndi_post_event(dip, dip, evc, &new_state); - kmem_free(hp_status, hpl); - return; - } - mutex_exit(&pdp->xd_ndi_lk); -} - -void -xvdi_notify_oe(dev_info_t *dip) -{ - struct xendev_ppd *pdp; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp->xd_evtchn != INVALID_EVTCHN); - ec_notify_via_evtchn(pdp->xd_evtchn); -} - -static void -i_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len) -{ - dev_info_t *dip = (dev_info_t *)w->dev; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - char *be = NULL; - unsigned int bel; - - ASSERT(len > XS_WATCH_PATH); - ASSERT(vec[XS_WATCH_PATH] != NULL); - - /* - * If the backend is not the same as that we already stored, - * re-set our watch for its' state. - */ - if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel) - == 0) && (strcmp(be, pdp->xd_xsdev.otherend) != 0)) - (void) i_xvdi_add_watch_oestate(dip); - - if (be != NULL) { - ASSERT(bel > 0); - kmem_free(be, bel); - } -} - -static void -i_xvdi_xb_watch_free(xd_xb_watches_t *xxwp) -{ - ASSERT(xxwp->xxw_ref == 0); - strfree((char *)xxwp->xxw_watch.node); - kmem_free(xxwp, sizeof (*xxwp)); -} - -static void -i_xvdi_xb_watch_release(xd_xb_watches_t *xxwp) -{ - ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk)); - ASSERT(xxwp->xxw_ref > 0); - if (--xxwp->xxw_ref == 0) - i_xvdi_xb_watch_free(xxwp); -} - -static void -i_xvdi_xb_watch_hold(xd_xb_watches_t *xxwp) -{ - ASSERT(MUTEX_HELD(&xxwp->xxw_xppd->xd_ndi_lk)); - ASSERT(xxwp->xxw_ref > 0); - xxwp->xxw_ref++; -} - -static void -i_xvdi_xb_watch_cb_tq(void *arg) -{ - xd_xb_watches_t *xxwp = (xd_xb_watches_t *)arg; - dev_info_t *dip = (dev_info_t *)xxwp->xxw_watch.dev; - struct xendev_ppd *pdp = xxwp->xxw_xppd; - - xxwp->xxw_cb(dip, xxwp->xxw_watch.node, xxwp->xxw_arg); - - mutex_enter(&pdp->xd_ndi_lk); - i_xvdi_xb_watch_release(xxwp); - mutex_exit(&pdp->xd_ndi_lk); -} - -static void -i_xvdi_xb_watch_cb(struct xenbus_watch *w, const char **vec, unsigned int len) -{ - dev_info_t *dip = (dev_info_t *)w->dev; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - xd_xb_watches_t *xxwp; - - ASSERT(len > XS_WATCH_PATH); - ASSERT(vec[XS_WATCH_PATH] != NULL); - - mutex_enter(&pdp->xd_ndi_lk); - for (xxwp = list_head(&pdp->xd_xb_watches); xxwp != NULL; - xxwp = list_next(&pdp->xd_xb_watches, xxwp)) { - if (w == &xxwp->xxw_watch) - break; - } - - if (xxwp == NULL) { - mutex_exit(&pdp->xd_ndi_lk); - return; - } - - i_xvdi_xb_watch_hold(xxwp); - (void) ddi_taskq_dispatch(pdp->xd_xb_watch_taskq, - i_xvdi_xb_watch_cb_tq, xxwp, DDI_SLEEP); - mutex_exit(&pdp->xd_ndi_lk); -} - -/* - * Any watches registered with xvdi_add_xb_watch_handler() get torn down during - * a suspend operation. So if a frontend driver want's to use these interfaces, - * that driver is responsible for re-registering any watches it had before - * the suspend operation. - */ -int -xvdi_add_xb_watch_handler(dev_info_t *dip, const char *dir, const char *node, - xvdi_xb_watch_cb_t cb, void *arg) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - xd_xb_watches_t *xxw_new, *xxwp; - char *path; - int n; - - ASSERT((dip != NULL) && (dir != NULL) && (node != NULL)); - ASSERT(cb != NULL); - - n = strlen(dir) + 1 + strlen(node) + 1; - path = kmem_zalloc(n, KM_SLEEP); - (void) strlcat(path, dir, n); - (void) strlcat(path, "/", n); - (void) strlcat(path, node, n); - ASSERT((strlen(path) + 1) == n); - - xxw_new = kmem_zalloc(sizeof (*xxw_new), KM_SLEEP); - xxw_new->xxw_ref = 1; - xxw_new->xxw_watch.node = path; - xxw_new->xxw_watch.callback = i_xvdi_xb_watch_cb; - xxw_new->xxw_watch.dev = (struct xenbus_device *)dip; - xxw_new->xxw_xppd = pdp; - xxw_new->xxw_cb = cb; - xxw_new->xxw_arg = arg; - - mutex_enter(&pdp->xd_ndi_lk); - - /* - * If this is the first watch we're setting up, create a taskq - * to dispatch watch events and initialize the watch list. - */ - if (pdp->xd_xb_watch_taskq == NULL) { - char tq_name[TASKQ_NAMELEN]; - - ASSERT(list_is_empty(&pdp->xd_xb_watches)); - - (void) snprintf(tq_name, sizeof (tq_name), - "%s_xb_watch_tq", ddi_get_name(dip)); - - if ((pdp->xd_xb_watch_taskq = ddi_taskq_create(dip, tq_name, - 1, TASKQ_DEFAULTPRI, 0)) == NULL) { - i_xvdi_xb_watch_release(xxw_new); - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - } - - /* Don't allow duplicate watches to be registered */ - for (xxwp = list_head(&pdp->xd_xb_watches); xxwp != NULL; - xxwp = list_next(&pdp->xd_xb_watches, xxwp)) { - - ASSERT(strcmp(xxwp->xxw_watch.node, path) != 0); - if (strcmp(xxwp->xxw_watch.node, path) != 0) - continue; - i_xvdi_xb_watch_release(xxw_new); - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - if (register_xenbus_watch(&xxw_new->xxw_watch) != 0) { - if (list_is_empty(&pdp->xd_xb_watches)) { - ddi_taskq_destroy(pdp->xd_xb_watch_taskq); - pdp->xd_xb_watch_taskq = NULL; - } - i_xvdi_xb_watch_release(xxw_new); - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - list_insert_head(&pdp->xd_xb_watches, xxw_new); - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_SUCCESS); -} - -/* - * Tear down all xenbus watches registered by the specified dip. - */ -void -xvdi_remove_xb_watch_handlers(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - xd_xb_watches_t *xxwp; - ddi_taskq_t *tq; - - mutex_enter(&pdp->xd_ndi_lk); - - while ((xxwp = list_remove_head(&pdp->xd_xb_watches)) != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - unregister_xenbus_watch(&xxwp->xxw_watch); - mutex_enter(&pdp->xd_ndi_lk); - i_xvdi_xb_watch_release(xxwp); - } - ASSERT(list_is_empty(&pdp->xd_xb_watches)); - - /* - * We can't hold xd_ndi_lk while we destroy the xd_xb_watch_taskq. - * This is because if there are currently any executing taskq threads, - * we will block until they are finished, and to finish they need - * to aquire xd_ndi_lk in i_xvdi_xb_watch_cb_tq() so they can release - * their reference on their corresponding xxwp structure. - */ - tq = pdp->xd_xb_watch_taskq; - pdp->xd_xb_watch_taskq = NULL; - mutex_exit(&pdp->xd_ndi_lk); - if (tq != NULL) - ddi_taskq_destroy(tq); -} - -static int -i_xvdi_add_watch_oestate(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_xsdev.nodename != NULL); - ASSERT(mutex_owned(&pdp->xd_ndi_lk)); - - /* - * Create taskq for delivering other end state change event to - * this device later. - * - * Set nthreads to 1 to make sure that events can be delivered - * in order. - * - * Note: It is _not_ guaranteed that driver can see every - * xenstore change under the path that it is watching. If two - * changes happen consecutively in a very short amount of - * time, it is likely that the driver will see only the last - * one. - */ - if (pdp->xd_oe_taskq == NULL) - if ((pdp->xd_oe_taskq = ddi_taskq_create(dip, - "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) - return (DDI_FAILURE); - - /* - * Watch for changes to the XenbusState of otherend. - */ - pdp->xd_xsdev.otherend_state = XenbusStateUnknown; - pdp->xd_xsdev.otherend_changed = i_xvdi_oestate_cb; - - if (talk_to_otherend(&pdp->xd_xsdev) != 0) { - i_xvdi_rem_watch_oestate(dip); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static void -i_xvdi_rem_watch_oestate(dev_info_t *dip) -{ - struct xendev_ppd *pdp; - struct xenbus_device *dev; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - ASSERT(mutex_owned(&pdp->xd_ndi_lk)); - - dev = &pdp->xd_xsdev; - - /* Unwatch for changes to XenbusState of otherend */ - if (dev->otherend_watch.node != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - unregister_xenbus_watch(&dev->otherend_watch); - mutex_enter(&pdp->xd_ndi_lk); - } - - /* make sure no event handler is running */ - if (pdp->xd_oe_taskq != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - ddi_taskq_destroy(pdp->xd_oe_taskq); - mutex_enter(&pdp->xd_ndi_lk); - pdp->xd_oe_taskq = NULL; - } - - /* clean up */ - dev->otherend_state = XenbusStateUnknown; - dev->otherend_id = (domid_t)-1; - if (dev->otherend_watch.node != NULL) - kmem_free((void *)dev->otherend_watch.node, - strlen(dev->otherend_watch.node) + 1); - dev->otherend_watch.node = NULL; - if (dev->otherend != NULL) - kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); - dev->otherend = NULL; -} - -static int -i_xvdi_add_watch_hpstate(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_xsdev.frontend == 0); - ASSERT(mutex_owned(&pdp->xd_ndi_lk)); - - /* - * Create taskq for delivering hotplug status change event to - * this device later. - * - * Set nthreads to 1 to make sure that events can be delivered - * in order. - * - * Note: It is _not_ guaranteed that driver can see every - * hotplug status change under the path that it is - * watching. If two changes happen consecutively in a very - * short amount of time, it is likely that the driver only - * sees the last one. - */ - if (pdp->xd_hp_taskq == NULL) - if ((pdp->xd_hp_taskq = ddi_taskq_create(dip, - "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) - return (DDI_FAILURE); - - if (pdp->xd_hp_watch.node == NULL) { - size_t len; - char *path; - - ASSERT(pdp->xd_xsdev.nodename != NULL); - - len = strlen(pdp->xd_xsdev.nodename) + - strlen("/hotplug-status") + 1; - path = kmem_alloc(len, KM_SLEEP); - (void) snprintf(path, len, "%s/hotplug-status", - pdp->xd_xsdev.nodename); - - pdp->xd_hp_watch.node = path; - pdp->xd_hp_watch.callback = i_xvdi_hpstate_cb; - pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */ - if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) { - i_xvdi_rem_watch_hpstate(dip); - return (DDI_FAILURE); - } - } - - return (DDI_SUCCESS); -} - -static void -i_xvdi_rem_watch_hpstate(dev_info_t *dip) -{ - struct xendev_ppd *pdp; - pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_xsdev.frontend == 0); - ASSERT(mutex_owned(&pdp->xd_ndi_lk)); - - /* Unwatch for changes to "hotplug-status" node for backend device. */ - if (pdp->xd_hp_watch.node != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - unregister_xenbus_watch(&pdp->xd_hp_watch); - mutex_enter(&pdp->xd_ndi_lk); - } - - /* Make sure no event handler is running. */ - if (pdp->xd_hp_taskq != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - ddi_taskq_destroy(pdp->xd_hp_taskq); - mutex_enter(&pdp->xd_ndi_lk); - pdp->xd_hp_taskq = NULL; - } - - /* Clean up. */ - if (pdp->xd_hp_watch.node != NULL) { - kmem_free((void *)pdp->xd_hp_watch.node, - strlen(pdp->xd_hp_watch.node) + 1); - pdp->xd_hp_watch.node = NULL; - } -} - -static int -i_xvdi_add_watches(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - - mutex_enter(&pdp->xd_ndi_lk); - - if (i_xvdi_add_watch_oestate(dip) != DDI_SUCCESS) { - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - if (pdp->xd_xsdev.frontend == 1) { - /* - * Frontend devices must watch for the backend path - * changing. - */ - if (i_xvdi_add_watch_bepath(dip) != DDI_SUCCESS) - goto unwatch_and_fail; - } else { - /* - * Backend devices must watch for hotplug events. - */ - if (i_xvdi_add_watch_hpstate(dip) != DDI_SUCCESS) - goto unwatch_and_fail; - } - - mutex_exit(&pdp->xd_ndi_lk); - - return (DDI_SUCCESS); - -unwatch_and_fail: - i_xvdi_rem_watch_oestate(dip); - mutex_exit(&pdp->xd_ndi_lk); - - return (DDI_FAILURE); -} - -static void -i_xvdi_rem_watches(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - - mutex_enter(&pdp->xd_ndi_lk); - - i_xvdi_rem_watch_oestate(dip); - - if (pdp->xd_xsdev.frontend == 1) - i_xvdi_rem_watch_bepath(dip); - else - i_xvdi_rem_watch_hpstate(dip); - - mutex_exit(&pdp->xd_ndi_lk); - - xvdi_remove_xb_watch_handlers(dip); -} - -static int -i_xvdi_add_watch_bepath(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_xsdev.frontend == 1); - - /* - * Frontend devices need to watch for the backend path changing. - */ - if (pdp->xd_bepath_watch.node == NULL) { - size_t len; - char *path; - - ASSERT(pdp->xd_xsdev.nodename != NULL); - - len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1; - path = kmem_alloc(len, KM_SLEEP); - (void) snprintf(path, len, "%s/backend", - pdp->xd_xsdev.nodename); - - pdp->xd_bepath_watch.node = path; - pdp->xd_bepath_watch.callback = i_xvdi_bepath_cb; - pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip; - if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) { - kmem_free(path, len); - pdp->xd_bepath_watch.node = NULL; - return (DDI_FAILURE); - } - } - - return (DDI_SUCCESS); -} - -static void -i_xvdi_rem_watch_bepath(dev_info_t *dip) -{ - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - - ASSERT(pdp != NULL); - ASSERT(pdp->xd_xsdev.frontend == 1); - ASSERT(mutex_owned(&pdp->xd_ndi_lk)); - - if (pdp->xd_bepath_watch.node != NULL) { - mutex_exit(&pdp->xd_ndi_lk); - unregister_xenbus_watch(&pdp->xd_bepath_watch); - mutex_enter(&pdp->xd_ndi_lk); - - kmem_free((void *)(pdp->xd_bepath_watch.node), - strlen(pdp->xd_bepath_watch.node) + 1); - pdp->xd_bepath_watch.node = NULL; - } -} - -int -xvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt, - XenbusState newState) -{ - int rv; - struct xendev_ppd *pdp; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - - XVDI_DPRINTF(XVDI_DBG_STATE, - "xvdi_switch_state: %s@%s's xenbus state moves to %d\n", - ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip), - ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip), - newState); - - rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState); - if (rv > 0) - cmn_err(CE_WARN, "xvdi_switch_state: change state failed"); - - return (rv); -} - -/* - * Notify hotplug script running in userland - */ -int -xvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc) -{ - struct xendev_ppd *pdp; - nvlist_t *attr_list = NULL; - i_xd_cfg_t *xdcp; - sysevent_id_t eid; - int err; - char devname[256]; /* XXPV dme: ? */ - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - - xdcp = i_xvdi_devclass2cfg(pdp->xd_devclass); - ASSERT(xdcp != NULL); - - (void) snprintf(devname, sizeof (devname) - 1, "%s%d", - ddi_driver_name(dip), ddi_get_instance(dip)); - - err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP); - if (err != DDI_SUCCESS) - goto failure; - - err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain); - if (err != DDI_SUCCESS) - goto failure; - err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum); - if (err != DDI_SUCCESS) - goto failure; - err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev); - if (err != DDI_SUCCESS) - goto failure; - err = nvlist_add_string(attr_list, "device", devname); - if (err != DDI_SUCCESS) - goto failure; - err = nvlist_add_string(attr_list, "fob", - ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend")); - if (err != DDI_SUCCESS) - goto failure; - - switch (hpc) { - case XEN_HP_ADD: - err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", - "add", attr_list, &eid, DDI_NOSLEEP); - break; - case XEN_HP_REMOVE: - err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", - "remove", attr_list, &eid, DDI_NOSLEEP); - break; - default: - err = DDI_FAILURE; - goto failure; - } - -failure: - nvlist_free(attr_list); - - return (err); -} - -/* ARGSUSED */ -static void -i_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec, - unsigned int len) -{ - char *path; - - if (xendev_dip == NULL) - xendev_dip = ddi_find_devinfo("xpvd", -1, 0); - - path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP); - - (void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq, - i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP); -} - -static void -i_xvdi_watch_device(char *path) -{ - struct xenbus_watch *w; - - ASSERT(path != NULL); - - w = kmem_zalloc(sizeof (*w), KM_SLEEP); - w->node = path; - w->callback = &i_xvdi_probe_path_cb; - w->dev = NULL; - - if (register_xenbus_watch(w) != 0) { - cmn_err(CE_WARN, "i_xvdi_watch_device: " - "cannot set watch on %s", path); - kmem_free(w, sizeof (*w)); - return; - } -} - -void -xvdi_watch_devices(int newstate) -{ - int devclass; - - /* - * Watch for devices being created in the store. - */ - if (newstate == XENSTORE_DOWN) - return; - for (devclass = 0; devclass < NXDC; devclass++) { - if (xdci[devclass].xs_path_fe != NULL) - i_xvdi_watch_device(xdci[devclass].xs_path_fe); - if (xdci[devclass].xs_path_be != NULL) - i_xvdi_watch_device(xdci[devclass].xs_path_be); - } -} - -/* - * Iterate over the store looking for backend devices to create. - */ -static void -i_xvdi_enum_be(dev_info_t *parent, i_xd_cfg_t *xdcp) -{ - char **domains; - unsigned int ndomains; - int ldomains, i; - - if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "", - &ndomains)) == NULL) - return; - - for (i = 0, ldomains = 0; i < ndomains; i++) { - ldomains += strlen(domains[i]) + 1 + sizeof (char *); - - i_xvdi_enum_worker(parent, xdcp, domains[i]); - } - kmem_free(domains, ldomains); -} - -/* - * Iterate over the store looking for frontend devices to create. - */ -static void -i_xvdi_enum_fe(dev_info_t *parent, i_xd_cfg_t *xdcp) -{ - i_xvdi_enum_worker(parent, xdcp, NULL); -} - -static void -i_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp, - char *domain) -{ - char *path, *domain_path, *ep; - char **devices; - unsigned int ndevices; - int ldevices, j, circ; - domid_t dom; - long tmplong; - - if (domain == NULL) { - dom = DOMID_SELF; - path = xdcp->xs_path_fe; - domain_path = ""; - } else { - (void) ddi_strtol(domain, &ep, 0, &tmplong); - dom = tmplong; - path = xdcp->xs_path_be; - domain_path = domain; - } - - if ((devices = xenbus_directory(XBT_NULL, path, domain_path, - &ndevices)) == NULL) - return; - - for (j = 0, ldevices = 0; j < ndevices; j++) { - int vdev; - - ldevices += strlen(devices[j]) + 1 + sizeof (char *); - (void) ddi_strtol(devices[j], &ep, 0, &tmplong); - vdev = tmplong; - - ndi_devi_enter(parent, &circ); - - if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) - (void) xvdi_create_dev(parent, xdcp->devclass, - dom, vdev); - - ndi_devi_exit(parent, circ); - } - kmem_free(devices, ldevices); -} - -/* - * Leaf drivers should call this in their detach() routine during suspend. - */ -void -xvdi_suspend(dev_info_t *dip) -{ - i_xvdi_rem_watches(dip); -} - -/* - * Leaf drivers should call this in their attach() routine during resume. - */ -int -xvdi_resume(dev_info_t *dip) -{ - return (i_xvdi_add_watches(dip)); -} - -/* - * Add event handler for the leaf driver - * to handle event triggered by the change in xenstore - */ -int -xvdi_add_event_handler(dev_info_t *dip, char *name, - void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *), - void *arg) -{ - ddi_eventcookie_t ecv; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - ddi_callback_id_t *cbid; - boolean_t call_handler; - i_oestate_evt_t *evt = NULL; - XenbusState oestate; - - ASSERT(pdp != NULL); - - mutex_enter(&pdp->xd_ndi_lk); - - if (strcmp(name, XS_OE_STATE) == 0) { - ASSERT(pdp->xd_xsdev.otherend != NULL); - - cbid = &pdp->xd_oe_ehid; - } else if (strcmp(name, XS_HP_STATE) == 0) { - if (pdp->xd_xsdev.frontend == 1) { - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - ASSERT(pdp->xd_hp_watch.node != NULL); - - cbid = &pdp->xd_hp_ehid; - } else { - /* Unsupported watch. */ - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - /* - * No event handler provided, take default action to handle - * event. - */ - if (evthandler == NULL) { - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_SUCCESS); - } - - ASSERT(*cbid == NULL); - - if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) { - cmn_err(CE_WARN, "failed to find %s cookie for %s@%s", - name, ddi_get_name(dip), ddi_get_name_addr(dip)); - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - if (ddi_add_event_handler(dip, ecv, evthandler, arg, cbid) - != DDI_SUCCESS) { - cmn_err(CE_WARN, "failed to add %s event handler for %s@%s", - name, ddi_get_name(dip), ddi_get_name_addr(dip)); - *cbid = NULL; - mutex_exit(&pdp->xd_ndi_lk); - return (DDI_FAILURE); - } - - /* - * if we're adding an oe state callback, and the ring has already - * transitioned out of Unknown, call the handler after we release - * the mutex. - */ - call_handler = B_FALSE; - if ((strcmp(name, XS_OE_STATE) == 0) && - (pdp->xd_xsdev.otherend_state != XenbusStateUnknown)) { - oestate = pdp->xd_xsdev.otherend_state; - call_handler = B_TRUE; - } - - mutex_exit(&pdp->xd_ndi_lk); - - if (call_handler) { - evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP); - evt->dip = dip; - evt->state = oestate; - (void) ddi_taskq_dispatch(pdp->xd_oe_taskq, - i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP); - } - - return (DDI_SUCCESS); -} - -/* - * Remove event handler for the leaf driver and unwatch xenstore - * so, driver will not be notified when xenstore entry changed later - */ -void -xvdi_remove_event_handler(dev_info_t *dip, char *name) -{ - struct xendev_ppd *pdp; - boolean_t rem_oe = B_FALSE, rem_hp = B_FALSE; - ddi_callback_id_t oeid = NULL, hpid = NULL; - - pdp = ddi_get_parent_data(dip); - ASSERT(pdp != NULL); - - if (name == NULL) { - rem_oe = B_TRUE; - rem_hp = B_TRUE; - } else if (strcmp(name, XS_OE_STATE) == 0) { - rem_oe = B_TRUE; - } else if (strcmp(name, XS_HP_STATE) == 0) { - rem_hp = B_TRUE; - } else { - cmn_err(CE_WARN, "event %s not supported, cannot remove", name); - return; - } - - mutex_enter(&pdp->xd_ndi_lk); - - if (rem_oe && (pdp->xd_oe_ehid != NULL)) { - oeid = pdp->xd_oe_ehid; - pdp->xd_oe_ehid = NULL; - } - - if (rem_hp && (pdp->xd_hp_ehid != NULL)) { - hpid = pdp->xd_hp_ehid; - pdp->xd_hp_ehid = NULL; - } - - mutex_exit(&pdp->xd_ndi_lk); - - if (oeid != NULL) - (void) ddi_remove_event_handler(oeid); - if (hpid != NULL) - (void) ddi_remove_event_handler(hpid); -} - - -/* - * common ring interfaces - */ - -#define FRONT_RING(_ringp) (&(_ringp)->xr_sring.fr) -#define BACK_RING(_ringp) (&(_ringp)->xr_sring.br) -#define GET_RING_SIZE(_ringp) RING_SIZE(FRONT_RING(ringp)) -#define GET_RING_ENTRY_FE(_ringp, _idx) \ - (FRONT_RING(_ringp)->sring->ring + \ - (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) -#define GET_RING_ENTRY_BE(_ringp, _idx) \ - (BACK_RING(_ringp)->sring->ring + \ - (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) - -unsigned int -xvdi_ring_avail_slots(xendev_ring_t *ringp) -{ - comif_ring_fe_t *frp; - comif_ring_be_t *brp; - - if (ringp->xr_frontend) { - frp = FRONT_RING(ringp); - return (GET_RING_SIZE(ringp) - - (frp->req_prod_pvt - frp->rsp_cons)); - } else { - brp = BACK_RING(ringp); - return (GET_RING_SIZE(ringp) - - (brp->rsp_prod_pvt - brp->req_cons)); - } -} - -int -xvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp) -{ - comif_ring_be_t *brp; - - ASSERT(!ringp->xr_frontend); - brp = BACK_RING(ringp); - return ((brp->req_cons != - ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) && - ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp))); -} - -int -xvdi_ring_has_incomp_request(xendev_ring_t *ringp) -{ - comif_ring_fe_t *frp; - - ASSERT(ringp->xr_frontend); - frp = FRONT_RING(ringp); - return (frp->req_prod_pvt != - ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); -} - -int -xvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp) -{ - comif_ring_fe_t *frp; - - ASSERT(ringp->xr_frontend); - frp = FRONT_RING(ringp); - return (frp->rsp_cons != - ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); -} - -/* NOTE: req_event will be increased as needed */ -void * -xvdi_ring_get_request(xendev_ring_t *ringp) -{ - comif_ring_fe_t *frp; - comif_ring_be_t *brp; - - if (ringp->xr_frontend) { - /* for frontend ring */ - frp = FRONT_RING(ringp); - if (!RING_FULL(frp)) - return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++)); - else - return (NULL); - } else { - /* for backend ring */ - brp = BACK_RING(ringp); - /* RING_FINAL_CHECK_FOR_REQUESTS() */ - if (xvdi_ring_has_unconsumed_requests(ringp)) - return (GET_RING_ENTRY_BE(ringp, brp->req_cons++)); - else { - ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event, - brp->req_cons + 1); - membar_enter(); - if (xvdi_ring_has_unconsumed_requests(ringp)) - return (GET_RING_ENTRY_BE(ringp, - brp->req_cons++)); - else - return (NULL); - } - } -} - -int -xvdi_ring_push_request(xendev_ring_t *ringp) -{ - RING_IDX old, new, reqevt; - comif_ring_fe_t *frp; - - /* only frontend should be able to push request */ - ASSERT(ringp->xr_frontend); - - /* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */ - frp = FRONT_RING(ringp); - old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod); - new = frp->req_prod_pvt; - ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new); - membar_enter(); - reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event); - return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old)); -} - -/* NOTE: rsp_event will be increased as needed */ -void * -xvdi_ring_get_response(xendev_ring_t *ringp) -{ - comif_ring_fe_t *frp; - comif_ring_be_t *brp; - - if (!ringp->xr_frontend) { - /* for backend ring */ - brp = BACK_RING(ringp); - return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++)); - } else { - /* for frontend ring */ - frp = FRONT_RING(ringp); - /* RING_FINAL_CHECK_FOR_RESPONSES() */ - if (xvdi_ring_has_unconsumed_responses(ringp)) - return (GET_RING_ENTRY_FE(ringp, frp->rsp_cons++)); - else { - ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event, - frp->rsp_cons + 1); - membar_enter(); - if (xvdi_ring_has_unconsumed_responses(ringp)) - return (GET_RING_ENTRY_FE(ringp, - frp->rsp_cons++)); - else - return (NULL); - } - } -} - -int -xvdi_ring_push_response(xendev_ring_t *ringp) -{ - RING_IDX old, new, rspevt; - comif_ring_be_t *brp; - - /* only backend should be able to push response */ - ASSERT(!ringp->xr_frontend); - - /* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */ - brp = BACK_RING(ringp); - old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod); - new = brp->rsp_prod_pvt; - ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new); - membar_enter(); - rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event); - return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old)); -} - -static void -xvdi_ring_init_sring(xendev_ring_t *ringp) -{ - ddi_acc_handle_t acchdl; - comif_sring_t *xsrp; - int i; - - xsrp = (comif_sring_t *)ringp->xr_vaddr; - acchdl = ringp->xr_acc_hdl; - - /* shared ring initialization */ - ddi_put32(acchdl, &xsrp->req_prod, 0); - ddi_put32(acchdl, &xsrp->rsp_prod, 0); - ddi_put32(acchdl, &xsrp->req_event, 1); - ddi_put32(acchdl, &xsrp->rsp_event, 1); - for (i = 0; i < sizeof (xsrp->pad); i++) - ddi_put8(acchdl, xsrp->pad + i, 0); -} - -static void -xvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) -{ - comif_ring_fe_t *xfrp; - - xfrp = &ringp->xr_sring.fr; - xfrp->req_prod_pvt = 0; - xfrp->rsp_cons = 0; - xfrp->nr_ents = nentry; - xfrp->sring = (comif_sring_t *)ringp->xr_vaddr; - - ringp->xr_frontend = 1; - ringp->xr_entry_size = entrysize; -} - -#ifndef XPV_HVM_DRIVER -static void -xvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) -{ - comif_ring_be_t *xbrp; - - xbrp = &ringp->xr_sring.br; - xbrp->rsp_prod_pvt = 0; - xbrp->req_cons = 0; - xbrp->nr_ents = nentry; - xbrp->sring = (comif_sring_t *)ringp->xr_vaddr; - - ringp->xr_frontend = 0; - ringp->xr_entry_size = entrysize; -} -#endif /* XPV_HVM_DRIVER */ - -static void -xendev_offline_device(void *arg) -{ - dev_info_t *dip = (dev_info_t *)arg; - char devname[MAXNAMELEN] = {0}; - - /* - * This is currently the only chance to delete a devinfo node, which - * is _not_ always successful. - */ - (void) ddi_deviname(dip, devname); - (void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE); - (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); -} - -static void -i_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate) -{ - dev_info_t *dip = (dev_info_t *)dev->data; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - i_oestate_evt_t *evt = NULL; - boolean_t call_handler; - - XVDI_DPRINTF(XVDI_DBG_STATE, - "i_xvdi_oestate_cb: %s@%s sees oestate change to %d\n", - ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip), - ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip), - oestate); - - /* only call the handler if our state has changed */ - call_handler = B_FALSE; - mutex_enter(&pdp->xd_ndi_lk); - if (dev->otherend_state != oestate) { - dev->otherend_state = oestate; - call_handler = B_TRUE; - } - mutex_exit(&pdp->xd_ndi_lk); - - if (call_handler) { - /* - * Try to deliver the oestate change event to the dip - */ - evt = kmem_alloc(sizeof (i_oestate_evt_t), KM_SLEEP); - evt->dip = dip; - evt->state = oestate; - (void) ddi_taskq_dispatch(pdp->xd_oe_taskq, - i_xvdi_oestate_handler, (void *)evt, DDI_SLEEP); - } -} - -/*ARGSUSED*/ -static void -i_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec, - unsigned int len) -{ - dev_info_t *dip = (dev_info_t *)w->dev; - struct xendev_ppd *pdp = ddi_get_parent_data(dip); - -#ifdef DEBUG - char *hp_status = NULL; - unsigned int hpl = 0; - - (void) xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "", - (void *)&hp_status, &hpl); - XVDI_DPRINTF(XVDI_DBG_STATE, - "i_xvdi_hpstate_cb: %s@%s sees hpstate change to %s\n", - ddi_binding_name(dip) == NULL ? "null" : ddi_binding_name(dip), - ddi_get_name_addr(dip) == NULL ? "null" : ddi_get_name_addr(dip), - hp_status == NULL ? "null" : hp_status); - if (hp_status != NULL) - kmem_free(hp_status, hpl); -#endif /* DEBUG */ - - (void) ddi_taskq_dispatch(pdp->xd_hp_taskq, - i_xvdi_hpstate_handler, (void *)dip, DDI_SLEEP); -} - -static void -i_xvdi_probe_path_handler(void *arg) -{ - dev_info_t *parent; - char *path = arg, *p = NULL; - int i, vdev, circ; - i_xd_cfg_t *xdcp; - boolean_t frontend; - domid_t dom; - - for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) { - - if ((xdcp->xs_path_fe != NULL) && - (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe)) - == 0)) { - - frontend = B_TRUE; - p = path + strlen(xdcp->xs_path_fe); - break; - } - - if ((xdcp->xs_path_be != NULL) && - (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be)) - == 0)) { - - frontend = B_FALSE; - p = path + strlen(xdcp->xs_path_be); - break; - } - - } - - if (p == NULL) { - cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " - "unexpected path prefix in %s", path); - goto done; - } - - if (frontend) { - dom = DOMID_SELF; - if (sscanf(p, "/%d/", &vdev) != 1) { - XVDI_DPRINTF(XVDI_DBG_PROBE, - "i_xvdi_probe_path_handler: " - "cannot parse frontend path %s", - path); - goto done; - } - } else { - if (sscanf(p, "/%hu/%d/", &dom, &vdev) != 2) { - XVDI_DPRINTF(XVDI_DBG_PROBE, - "i_xvdi_probe_path_handler: " - "cannot parse backend path %s", - path); - goto done; - } - } - - /* - * This is an oxymoron, so indicates a bogus configuration we - * must check for. - */ - if (vdev == VDEV_NOXS) { - cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " - "invalid path %s", path); - goto done; - } - - parent = xendev_dip; - ASSERT(parent != NULL); - - ndi_devi_enter(parent, &circ); - - if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) { - XVDI_DPRINTF(XVDI_DBG_PROBE, - "i_xvdi_probe_path_handler: create for %s", path); - (void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev); - } else { - XVDI_DPRINTF(XVDI_DBG_PROBE, - "i_xvdi_probe_path_handler: %s already exists", path); - } - - ndi_devi_exit(parent, circ); - -done: - kmem_free(path, strlen(path) + 1); -} diff --git a/usr/src/uts/common/xen/public/COPYING b/usr/src/uts/common/xen/public/COPYING deleted file mode 100644 index ffc6d6166f..0000000000 --- a/usr/src/uts/common/xen/public/COPYING +++ /dev/null @@ -1,38 +0,0 @@ -XEN NOTICE -========== - -This copyright applies to all files within this subdirectory and its -subdirectories: - include/public/*.h - include/public/hvm/*.h - include/public/io/*.h - -The intention is that these files can be freely copied into the source -tree of an operating system when porting that OS to run on Xen. Doing -so does *not* cause the OS to become subject to the terms of the GPL. - -All other files in the Xen source distribution are covered by version -2 of the GNU General Public License except where explicitly stated -otherwise within individual source files. - - -- Keir Fraser (on behalf of the Xen team) - -===================================================================== - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/usr/src/uts/common/xen/public/README.DO_NOT_EDIT b/usr/src/uts/common/xen/public/README.DO_NOT_EDIT deleted file mode 100644 index cce02258a1..0000000000 --- a/usr/src/uts/common/xen/public/README.DO_NOT_EDIT +++ /dev/null @@ -1,36 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)prototype.Makefile 1.15 06/02/08 SMI" -# -#pragma ident "%Z%%M% %I% %E% SMI" -# - -These files should not be edited in ON. They are copies from a specific -build of the xen consolidation which can be found in: - xen.hg/xen/include/public - -Any changes to these files should be done in the xen consolidation. - diff --git a/usr/src/uts/common/xen/public/arch-x86/xen-mca.h b/usr/src/uts/common/xen/public/arch-x86/xen-mca.h deleted file mode 100644 index 13fc5b1866..0000000000 --- a/usr/src/uts/common/xen/public/arch-x86/xen-mca.h +++ /dev/null @@ -1,422 +0,0 @@ -/****************************************************************************** - * arch-x86/mca.h - * - * Contributed by Advanced Micro Devices, Inc. - * Author: Christoph Egger - * - * Guest OS machine check interface to x86 Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* Full MCA functionality has the following Usecases from the guest side: - * - * Must have's: - * 1. Dom0 and DomU register machine check trap callback handlers - * (already done via "set_trap_table" hypercall) - * 2. Dom0 registers machine check event callback handler - * (doable via EVTCHNOP_bind_virq) - * 3. Dom0 and DomU fetches machine check data - * 4. Dom0 wants Xen to notify a DomU - * 5. Dom0 gets DomU ID from physical address - * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy") - * - * Nice to have's: - * 7. Dom0 wants Xen to deactivate a physical CPU - * This is better done as separate task, physical CPU hotplugging, - * and hypercall(s) should be sysctl's - * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to - * move a DomU (or Dom0 itself) away from a malicious page - * producing correctable errors. - * 9. offlining physical page: - * Xen free's and never re-uses a certain physical page. - * 10. Testfacility: Allow Dom0 to write values into machine check MSR's - * and tell Xen to trigger a machine check - */ - -#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__ -#define __XEN_PUBLIC_ARCH_X86_MCA_H__ - -/* Hypercall */ -#define __HYPERVISOR_mca __HYPERVISOR_arch_0 - -/* - * The xen-unstable repo has interface version 0x03000001; out interface - * is incompatible with that and any future minor revisions, so we - * choose a different version number range that is numerically less - * than that used in xen-unstable. - */ -#define XEN_MCA_INTERFACE_VERSION 0x01ecc003 - -/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */ -#define XEN_MC_NONURGENT 0x0001 -/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */ -#define XEN_MC_URGENT 0x0002 -/* IN: Dom0 acknowledges previosly-fetched telemetry */ -#define XEN_MC_ACK 0x0004 - -/* OUT: All is ok */ -#define XEN_MC_OK 0x0 -/* OUT: Domain could not fetch data. */ -#define XEN_MC_FETCHFAILED 0x1 -/* OUT: There was no machine check data to fetch. */ -#define XEN_MC_NODATA 0x2 -/* OUT: Between notification time and this hypercall an other - * (most likely) correctable error happened. The fetched data, - * does not match the original machine check data. */ -#define XEN_MC_NOMATCH 0x4 - -/* OUT: DomU did not register MC NMI handler. Try something else. */ -#define XEN_MC_CANNOTHANDLE 0x8 -/* OUT: Notifying DomU failed. Retry later or try something else. */ -#define XEN_MC_NOTDELIVERED 0x10 -/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */ - - -#ifndef __ASSEMBLY__ - -#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */ - -/* - * Machine Check Architecure: - * structs are read-only and used to report all kinds of - * correctable and uncorrectable errors detected by the HW. - * Dom0 and DomU: register a handler to get notified. - * Dom0 only: Correctable errors are reported via VIRQ_MCA - * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers - */ -#define MC_TYPE_GLOBAL 0 -#define MC_TYPE_BANK 1 -#define MC_TYPE_EXTENDED 2 -#define MC_TYPE_RECOVERY 3 - -struct mcinfo_common { - uint16_t type; /* structure type */ - uint16_t size; /* size of this struct in bytes */ -}; - - -#define MC_FLAG_CORRECTABLE (1 << 0) -#define MC_FLAG_UNCORRECTABLE (1 << 1) -#define MC_FLAG_RECOVERABLE (1 << 2) -#define MC_FLAG_POLLED (1 << 3) -#define MC_FLAG_RESET (1 << 4) -#define MC_FLAG_CMCI (1 << 5) -#define MC_FLAG_MCE (1 << 6) -/* contains global x86 mc information */ -struct mcinfo_global { - struct mcinfo_common common; - - /* running domain at the time in error (most likely the impacted one) */ - uint16_t mc_domid; - uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */ - uint32_t mc_socketid; /* physical socket of the physical core */ - uint16_t mc_coreid; /* physical impacted core */ - uint16_t mc_core_threadid; /* core thread of physical core */ - uint32_t mc_apicid; - uint32_t mc_flags; - uint64_t mc_gstatus; /* global status */ -}; - -/* contains bank local x86 mc information */ -struct mcinfo_bank { - struct mcinfo_common common; - - uint16_t mc_bank; /* bank nr */ - uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0 - * and if mc_addr is valid. Never valid on DomU. */ - uint64_t mc_status; /* bank status */ - uint64_t mc_addr; /* bank address, only valid - * if addr bit is set in mc_status */ - uint64_t mc_misc; - uint64_t mc_ctrl2; - uint64_t mc_tsc; -}; - - -struct mcinfo_msr { - uint64_t reg; /* MSR */ - uint64_t value; /* MSR value */ -}; - -/* contains mc information from other - * or additional mc MSRs */ -struct mcinfo_extended { - struct mcinfo_common common; - - /* You can fill up to five registers. - * If you need more, then use this structure - * multiple times. */ - - uint32_t mc_msrs; /* Number of msr with valid values. */ - /* - * Currently Intel extended MSR (32/64) include all gp registers - * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be - * useful at present. So expand this array to 16/32 to leave room. - */ - struct mcinfo_msr mc_msr[sizeof(void *) * 4]; -}; - -/* Recovery Action flags. Giving recovery result information to DOM0 */ - -/* Xen takes successful recovery action, the error is recovered */ -#define REC_ACTION_RECOVERED (0x1 << 0) -/* No action is performed by XEN */ -#define REC_ACTION_NONE (0x1 << 1) -/* It's possible DOM0 might take action ownership in some case */ -#define REC_ACTION_NEED_RESET (0x1 << 2) - -/* Different Recovery Action types, if the action is performed successfully, - * REC_ACTION_RECOVERED flag will be returned. - */ - -/* Page Offline Action */ -#define MC_ACTION_PAGE_OFFLINE (0x1 << 0) -/* CPU offline Action */ -#define MC_ACTION_CPU_OFFLINE (0x1 << 1) -/* L3 cache disable Action */ -#define MC_ACTION_CACHE_SHRINK (0x1 << 2) - -/* Below interface used between XEN/DOM0 for passing XEN's recovery action - * information to DOM0. - * usage Senario: After offlining broken page, XEN might pass its page offline - * recovery action result to DOM0. DOM0 will save the information in - * non-volatile memory for further proactive actions, such as offlining the - * easy broken page earlier when doing next reboot. -*/ -struct page_offline_action -{ - /* Params for passing the offlined page number to DOM0 */ - uint64_t mfn; - uint64_t status; -}; - -struct cpu_offline_action -{ - /* Params for passing the identity of the offlined CPU to DOM0 */ - uint32_t mc_socketid; - uint16_t mc_coreid; - uint16_t mc_core_threadid; -}; - -#define MAX_UNION_SIZE 16 -struct mcinfo_recovery -{ - struct mcinfo_common common; - uint16_t mc_bank; /* bank nr */ - uint8_t action_flags; - uint8_t action_types; - union { - struct page_offline_action page_retire; - struct cpu_offline_action cpu_offline; - uint8_t pad[MAX_UNION_SIZE]; - } action_info; -}; - - -#define MCINFO_HYPERCALLSIZE 1024 -#define MCINFO_MAXSIZE 768 - -struct mc_info { - /* Number of mcinfo_* entries in mi_data */ - uint32_t mi_nentries; - uint32_t _pad0; - uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8]; -}; -typedef struct mc_info mc_info_t; -DEFINE_XEN_GUEST_HANDLE(mc_info_t); - -#define __MC_MSR_ARRAYSIZE 8 -#define __MC_NMSRS 1 -#define MC_NCAPS 7 /* 7 CPU feature flag words */ -#define MC_CAPS_STD_EDX 0 /* cpuid level 0x00000001 (%edx) */ -#define MC_CAPS_AMD_EDX 1 /* cpuid level 0x80000001 (%edx) */ -#define MC_CAPS_TM 2 /* cpuid level 0x80860001 (TransMeta) */ -#define MC_CAPS_LINUX 3 /* Linux-defined */ -#define MC_CAPS_STD_ECX 4 /* cpuid level 0x00000001 (%ecx) */ -#define MC_CAPS_VIA 5 /* cpuid level 0xc0000001 */ -#define MC_CAPS_AMD_ECX 6 /* cpuid level 0x80000001 (%ecx) */ - -struct mcinfo_logical_cpu { - uint32_t mc_cpunr; - uint32_t mc_chipid; - uint16_t mc_coreid; - uint16_t mc_threadid; - uint32_t mc_apicid; - uint32_t mc_clusterid; - uint32_t mc_ncores; - uint32_t mc_ncores_active; - uint32_t mc_nthreads; - int32_t mc_cpuid_level; - uint32_t mc_family; - uint32_t mc_vendor; - uint32_t mc_model; - uint32_t mc_step; - char mc_vendorid[16]; - char mc_brandid[64]; - uint32_t mc_cpu_caps[MC_NCAPS]; - uint32_t mc_cache_size; - uint32_t mc_cache_alignment; - int32_t mc_nmsrvals; - struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE]; -}; -typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t; -DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t); - - -/* - * OS's should use these instead of writing their own lookup function - * each with its own bugs and drawbacks. - * We use macros instead of static inline functions to allow guests - * to include this header in assembly files (*.S). - */ -/* Prototype: - * uint32_t x86_mcinfo_nentries(struct mc_info *mi); - */ -#define x86_mcinfo_nentries(_mi) \ - (_mi)->mi_nentries -/* Prototype: - * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi); - */ -#define x86_mcinfo_first(_mi) \ - ((struct mcinfo_common *)(_mi)->mi_data) -/* Prototype: - * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic); - */ -#define x86_mcinfo_next(_mic) \ - ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size)) - -/* Prototype: - * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type); - */ -#define x86_mcinfo_lookup(_ret, _mi, _type) \ - do { \ - uint32_t found, i; \ - struct mcinfo_common *_mic; \ - \ - found = 0; \ - (_ret) = NULL; \ - if (_mi == NULL) break; \ - _mic = x86_mcinfo_first(_mi); \ - for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \ - if (_mic->type == (_type)) { \ - found = 1; \ - break; \ - } \ - _mic = x86_mcinfo_next(_mic); \ - } \ - (_ret) = found ? _mic : NULL; \ - } while (0) - - -/* Usecase 1 - * Register machine check trap callback handler - * (already done via "set_trap_table" hypercall) - */ - -/* Usecase 2 - * Dom0 registers machine check event callback handler - * done by EVTCHNOP_bind_virq - */ - -/* Usecase 3 - * Fetch machine check data from hypervisor. - * Note, this hypercall is special, because both Dom0 and DomU must use this. - */ -#define XEN_MC_fetch 1 -struct xen_mc_fetch { - /* IN/OUT variables. */ - uint32_t flags; /* IN: XEN_MC_NONURGENT, XEN_MC_URGENT, - XEN_MC_ACK if ack'ing an earlier fetch */ - /* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED, - XEN_MC_NODATA, XEN_MC_NOMATCH */ - uint32_t _pad0; - uint64_t fetch_id; /* OUT: id for ack, IN: id we are ack'ing */ - - /* OUT variables. */ - XEN_GUEST_HANDLE(mc_info_t) data; -}; -typedef struct xen_mc_fetch xen_mc_fetch_t; -DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t); - - -/* Usecase 4 - * This tells the hypervisor to notify a DomU about the machine check error - */ -#define XEN_MC_notifydomain 2 -struct xen_mc_notifydomain { - /* IN variables. */ - uint16_t mc_domid; /* The unprivileged domain to notify. */ - uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify. - * Usually echo'd value from the fetch hypercall. */ - - /* IN/OUT variables. */ - uint32_t flags; - -/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */ -/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */ -}; -typedef struct xen_mc_notifydomain xen_mc_notifydomain_t; -DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t); - -#define XEN_MC_physcpuinfo 3 -struct xen_mc_physcpuinfo { - /* IN/OUT */ - uint32_t ncpus; - uint32_t _pad0; - /* OUT */ - XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info; -}; - -#define XEN_MC_msrinject 4 -#define MC_MSRINJ_MAXMSRS 8 -struct xen_mc_msrinject { - /* IN */ - uint32_t mcinj_cpunr; /* target processor id */ - uint32_t mcinj_flags; /* see MC_MSRINJ_F_* below */ - uint32_t mcinj_count; /* 0 .. count-1 in array are valid */ - uint32_t _pad0; - struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS]; -}; - -/* Flags for mcinj_flags above; bits 16-31 are reserved */ -#define MC_MSRINJ_F_INTERPOSE 0x1 - -#define XEN_MC_mceinject 5 -struct xen_mc_mceinject { - unsigned int mceinj_cpunr; /* target processor id */ -}; - -struct xen_mc { - uint32_t cmd; - uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */ - union { - struct xen_mc_fetch mc_fetch; - struct xen_mc_notifydomain mc_notifydomain; - struct xen_mc_physcpuinfo mc_physcpuinfo; - struct xen_mc_msrinject mc_msrinject; - struct xen_mc_mceinject mc_mceinject; - } u; -}; -typedef struct xen_mc xen_mc_t; -DEFINE_XEN_GUEST_HANDLE(xen_mc_t); - -#endif /* __ASSEMBLY__ */ - -#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */ diff --git a/usr/src/uts/common/xen/public/arch-x86/xen-x86_32.h b/usr/src/uts/common/xen/public/arch-x86/xen-x86_32.h deleted file mode 100644 index 72eadef5ac..0000000000 --- a/usr/src/uts/common/xen/public/arch-x86/xen-x86_32.h +++ /dev/null @@ -1,254 +0,0 @@ -/****************************************************************************** - * xen-x86_32.h - * - * Guest OS interface to x86 32-bit Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2004-2007, K A Fraser - */ - -#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ -#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ - -/* - * Hypercall interface: - * Input: %ebx, %ecx, %edx, %esi, %edi (arguments 1-5) - * Output: %eax - * Access is via hypercall page (set up by guest loader or via a Xen MSR): - * call hypercall_page + hypercall-number * 32 - * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx) - */ - -/* - * Direct hypercall interface: - * As above, except the entry sequence to the hypervisor is: - * mov $hypercall-number*32,%eax ; int $0x82 - */ -#if !defined(_ASM) -#define TRAP_INSTR "int $0x82" -#else -#define TRAP_INSTR int $0x82 -#endif - -/* - * These flat segments are in the Xen-private section of every GDT. Since these - * are also present in the initial GDT, many OSes will be able to avoid - * installing their own GDT. - */ -#define FLAT_RING1_CS 0xe019 /* GDT index 259 */ -#define FLAT_RING1_DS 0xe021 /* GDT index 260 */ -#define FLAT_RING1_SS 0xe021 /* GDT index 260 */ -#define FLAT_RING3_CS 0xe02b /* GDT index 261 */ -#define FLAT_RING3_DS 0xe033 /* GDT index 262 */ -#define FLAT_RING3_SS 0xe033 /* GDT index 262 */ - -#define FLAT_KERNEL_CS FLAT_RING1_CS -#define FLAT_KERNEL_DS FLAT_RING1_DS -#define FLAT_KERNEL_SS FLAT_RING1_SS -#define FLAT_USER_CS FLAT_RING3_CS -#define FLAT_USER_DS FLAT_RING3_DS -#define FLAT_USER_SS FLAT_RING3_SS - -#define __HYPERVISOR_VIRT_START_PAE 0xF5800000 -#define __MACH2PHYS_VIRT_START_PAE 0xF5800000 -#define __MACH2PHYS_VIRT_END_PAE 0xF6800000 -#define HYPERVISOR_VIRT_START_PAE \ - mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE) -#define MACH2PHYS_VIRT_START_PAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE) -#define MACH2PHYS_VIRT_END_PAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE) - -/* Non-PAE bounds are obsolete. */ -#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000 -#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000 -#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000 -#define HYPERVISOR_VIRT_START_NONPAE \ - mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE) -#define MACH2PHYS_VIRT_START_NONPAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE) -#define MACH2PHYS_VIRT_END_NONPAE \ - mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE) - -#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE -#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE -#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE - -#ifndef HYPERVISOR_VIRT_START -#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) -#endif - -#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) -#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) -#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2) -#ifndef machine_to_phys_mapping -#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START) -#endif - -/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */ -#if defined(__XEN__) || defined(__XEN_TOOLS__) -#undef ___DEFINE_XEN_GUEST_HANDLE - -#ifdef __GNUC__ - -#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ - typedef struct { type *p; } \ - __guest_handle_ ## name; \ - typedef struct { union { type *p; uint64_aligned_t q; }; } \ - __guest_handle_64_ ## name - -#else /* __GNUC__ */ - -/* - * Workaround for 6671857. - */ -#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ - typedef struct { type *p; } \ - __guest_handle_ ## name; \ - typedef struct { union { type *p; uint64_aligned_t q; } u; }\ - __guest_handle_64_ ## name - -#endif /* __GNUC__ */ - -#undef set_xen_guest_handle -#define set_xen_guest_handle(hnd, val) \ - do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \ - (hnd).p = val; \ - } while ( 0 ) -#define uint64_aligned_t uint64_t __attribute__((aligned(8))) -#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name -#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name) -#endif - -#ifndef __ASSEMBLY__ - -struct cpu_user_regs { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint16_t error_code; /* private */ - uint16_t entry_vector; /* private */ - uint32_t eip; - uint16_t cs; - uint8_t saved_upcall_mask; - uint8_t _pad0; - uint32_t eflags; /* eflags.IF == !saved_upcall_mask */ - uint32_t esp; - uint16_t ss, _pad1; - uint16_t es, _pad2; - uint16_t ds, _pad3; - uint16_t fs, _pad4; - uint16_t gs, _pad5; -}; -typedef struct cpu_user_regs cpu_user_regs_t; -DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); - -/* - * Page-directory addresses above 4GB do not fit into architectural %cr3. - * When accessing %cr3, or equivalent field in vcpu_guest_context, guests - * must use the following accessor macros to pack/unpack valid MFNs. - */ -#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) -#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) - -struct arch_vcpu_info { - unsigned long cr2; - unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */ -}; -typedef struct arch_vcpu_info arch_vcpu_info_t; - -struct xen_callback { - unsigned long cs; - unsigned long eip; -}; -typedef struct xen_callback xen_callback_t; - -/* - * Structure used to capture the register state at panic time. This struct - * is built to mimic a similar structure in Solaris. If there is interest - * in making this panic implementation an official part of Xen, this should - * be made more platform-neutral. - */ -struct panic_regs { - unsigned long pad1; - unsigned long pad2; - - unsigned long gs; - unsigned long fs; - unsigned long es; - unsigned long ds; - unsigned long edi; - unsigned long esi; - unsigned long ebp; - unsigned long esp; - unsigned long ebx; - unsigned long edx; - unsigned long ecx; - unsigned long eax; - unsigned long pad3; - unsigned long pad4; - unsigned long eip; - unsigned long cs; - unsigned long efl; - unsigned long pad5; - unsigned long ss; -}; - -#endif /* !__ASSEMBLY__ */ - -/* Offsets of each field in the xen_panic_regs structure. */ -#define PANIC_REG_PAD1 0 -#define PANIC_REG_PAD2 4 -#define PANIC_REG_GS 8 -#define PANIC_REG_FS 12 -#define PANIC_REG_ES 16 -#define PANIC_REG_DS 20 -#define PANIC_REG_EDI 24 -#define PANIC_REG_ESI 28 -#define PANIC_REG_EBP 32 -#define PANIC_REG_ESP 36 -#define PANIC_REG_EBX 40 -#define PANIC_REG_EDX 44 -#define PANIC_REG_ECX 48 -#define PANIC_REG_EAX 52 -#define PANIC_REG_PAD3 56 -#define PANIC_REG_PAD4 60 -#define PANIC_REG_EIP 64 -#define PANIC_REG_CS 68 -#define PANIC_REG_EFL 72 -#define PANIC_REG_PAD5 76 -#define PANIC_REG_SS 80 -#define PANIC_REG_STRUCT_SIZE 84 - -#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/arch-x86/xen-x86_64.h b/usr/src/uts/common/xen/public/arch-x86/xen-x86_64.h deleted file mode 100644 index 3bf5833f91..0000000000 --- a/usr/src/uts/common/xen/public/arch-x86/xen-x86_64.h +++ /dev/null @@ -1,286 +0,0 @@ -/****************************************************************************** - * xen-x86_64.h - * - * Guest OS interface to x86 64-bit Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2004-2006, K A Fraser - */ - -#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ -#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ - -/* - * Hypercall interface: - * Input: %rdi, %rsi, %rdx, %r10, %r8 (arguments 1-5) - * Output: %rax - * Access is via hypercall page (set up by guest loader or via a Xen MSR): - * call hypercall_page + hypercall-number * 32 - * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi) - */ - -/* - * Direct hypercall interface: - * As above, except the entry sequence to the hypervisor is: - * mov $hypercall-number*32,%eax ; syscall - * Clobbered: %rcx, %r11, argument registers (as above) - */ -#if !defined(_ASM) -#define TRAP_INSTR "syscall" -#else -#define TRAP_INSTR syscall -#endif - -/* - * 64-bit segment selectors - * These flat segments are in the Xen-private section of every GDT. Since these - * are also present in the initial GDT, many OSes will be able to avoid - * installing their own GDT. - */ - -#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */ -#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */ -#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */ -#define FLAT_RING3_DS64 0x0000 /* NULL selector */ -#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */ -#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */ - -#define FLAT_KERNEL_DS64 FLAT_RING3_DS64 -#define FLAT_KERNEL_DS32 FLAT_RING3_DS32 -#define FLAT_KERNEL_DS FLAT_KERNEL_DS64 -#define FLAT_KERNEL_CS64 FLAT_RING3_CS64 -#define FLAT_KERNEL_CS32 FLAT_RING3_CS32 -#define FLAT_KERNEL_CS FLAT_KERNEL_CS64 -#define FLAT_KERNEL_SS64 FLAT_RING3_SS64 -#define FLAT_KERNEL_SS32 FLAT_RING3_SS32 -#define FLAT_KERNEL_SS FLAT_KERNEL_SS64 - -#define FLAT_USER_DS64 FLAT_RING3_DS64 -#define FLAT_USER_DS32 FLAT_RING3_DS32 -#define FLAT_USER_DS FLAT_USER_DS64 -#define FLAT_USER_CS64 FLAT_RING3_CS64 -#define FLAT_USER_CS32 FLAT_RING3_CS32 -#define FLAT_USER_CS FLAT_USER_CS64 -#define FLAT_USER_SS64 FLAT_RING3_SS64 -#define FLAT_USER_SS32 FLAT_RING3_SS32 -#define FLAT_USER_SS FLAT_USER_SS64 - -#define __HYPERVISOR_VIRT_START 0xFFFF800000000000 -#define __HYPERVISOR_VIRT_END 0xFFFF880000000000 -#define __MACH2PHYS_VIRT_START 0xFFFF800000000000 -#define __MACH2PHYS_VIRT_END 0xFFFF804000000000 - -#ifndef HYPERVISOR_VIRT_START -#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) -#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END) -#endif - -#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) -#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) -#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3) -#ifndef machine_to_phys_mapping -#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) -#endif - -/* - * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base) - * @which == SEGBASE_* ; @base == 64-bit base address - * Returns 0 on success. - */ -#define SEGBASE_FS 0 -#define SEGBASE_GS_USER 1 -#define SEGBASE_GS_KERNEL 2 -#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */ - -/* - * int HYPERVISOR_iret(void) - * All arguments are on the kernel stack, in the following format. - * Never returns if successful. Current kernel context is lost. - * The saved CS is mapped as follows: - * RING0 -> RING3 kernel mode. - * RING1 -> RING3 kernel mode. - * RING2 -> RING3 kernel mode. - * RING3 -> RING3 user mode. - * However RING0 indicates that the guest kernel should return to iteself - * directly with - * orb $3,1*8(%rsp) - * iretq - * If flags contains VGCF_in_syscall: - * Restore RAX, RIP, RFLAGS, RSP. - * Discard R11, RCX, CS, SS. - * Otherwise: - * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP. - * All other registers are saved on hypercall entry and restored to user. - */ -/* Guest exited in SYSCALL context? Return to guest with SYSRET? */ -#define _VGCF_in_syscall 8 -#define VGCF_in_syscall (1<<_VGCF_in_syscall) -#define VGCF_IN_SYSCALL VGCF_in_syscall - -#ifndef __ASSEMBLY__ - -struct iret_context { - /* Top of stack (%rsp at point of hypercall). */ - uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; - /* Bottom of iret stack frame. */ -}; - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */ -#define __DECL_REG(name) union { \ - uint64_t r ## name, e ## name; \ - uint32_t _e ## name; \ -} -#else -/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */ -#define __DECL_REG(name) uint64_t r ## name -#endif - -struct cpu_user_regs { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - __DECL_REG(bp); - __DECL_REG(bx); - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - __DECL_REG(ax); - __DECL_REG(cx); - __DECL_REG(dx); - __DECL_REG(si); - __DECL_REG(di); - uint32_t error_code; /* private */ - uint32_t entry_vector; /* private */ - __DECL_REG(ip); - uint16_t cs, _pad0[1]; - uint8_t saved_upcall_mask; - uint8_t _pad1[3]; - __DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */ - __DECL_REG(sp); - uint16_t ss, _pad2[3]; - uint16_t es, _pad3[3]; - uint16_t ds, _pad4[3]; - uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */ - uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */ -}; -typedef struct cpu_user_regs cpu_user_regs_t; -DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); - -#undef __DECL_REG - -#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12) -#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12) - -struct arch_vcpu_info { - unsigned long cr2; - unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ -}; -typedef struct arch_vcpu_info arch_vcpu_info_t; - -typedef unsigned long xen_callback_t; - -/* - * Structure used to capture the register state at panic time. This struct - * is built to mimic a similar structure in Solaris. If there is interest - * in making this panic implementation an official part of Xen, this should - * be made more platform-neutral. - */ -struct panic_regs { - unsigned long pad1; - unsigned long pad2; - unsigned long rdi; - unsigned long rsi; - unsigned long rdx; - unsigned long rcx; - unsigned long r8; - unsigned long r9; - unsigned long rax; - unsigned long rbx; - unsigned long rbp; - unsigned long r10; - unsigned long r11; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; - unsigned long pad3; - unsigned long pad4; - unsigned long ds; - unsigned long es; - unsigned long fs; - unsigned long gs; - unsigned long pad5; - unsigned long pad6; - unsigned long rip; - unsigned long cs; - unsigned long rfl; - unsigned long rsp; - unsigned long ss; -}; - -#endif /* !__ASSEMBLY__ */ - -/* Offsets of each field in the xen_panic_regs structure. */ -#define PANIC_REG_PAD1 0 -#define PANIC_REG_PAD2 8 -#define PANIC_REG_RDI 16 -#define PANIC_REG_RSI 24 -#define PANIC_REG_RDX 32 -#define PANIC_REG_RCX 40 -#define PANIC_REG_R8 48 -#define PANIC_REG_R9 56 -#define PANIC_REG_RAX 64 -#define PANIC_REG_RBX 72 -#define PANIC_REG_RBP 80 -#define PANIC_REG_R10 88 -#define PANIC_REG_R11 96 -#define PANIC_REG_R12 104 -#define PANIC_REG_R13 112 -#define PANIC_REG_R14 120 -#define PANIC_REG_R15 128 -#define PANIC_REG_PAD3 136 -#define PANIC_REG_PAD4 144 -#define PANIC_REG_DS 152 -#define PANIC_REG_ES 160 -#define PANIC_REG_FS 168 -#define PANIC_REG_GS 176 -#define PANIC_REG_PAD5 184 -#define PANIC_REG_PAD6 192 -#define PANIC_REG_RIP 200 -#define PANIC_REG_CS 208 -#define PANIC_REG_RFL 216 -#define PANIC_REG_RSP 224 -#define PANIC_REG_SS 232 -#define PANIC_REG_STRUCT_SIZE 240 - -#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/arch-x86/xen.h b/usr/src/uts/common/xen/public/arch-x86/xen.h deleted file mode 100644 index d416387160..0000000000 --- a/usr/src/uts/common/xen/public/arch-x86/xen.h +++ /dev/null @@ -1,241 +0,0 @@ -/****************************************************************************** - * arch-x86/xen.h - * - * Guest OS interface to x86 Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2004-2006, K A Fraser - */ - -#include "../xen.h" - -#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__ -#define __XEN_PUBLIC_ARCH_X86_XEN_H__ - -/* Structural guest handles introduced in 0x00030201. */ -#if __XEN_INTERFACE_VERSION__ >= 0x00030201 -#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ - typedef struct { type *p; } __guest_handle_ ## name -#else -#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ - typedef type * __guest_handle_ ## name -#endif - -#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ - ___DEFINE_XEN_GUEST_HANDLE(name, type); \ - ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type) -#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) -#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name -#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name) -#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) -#ifdef __XEN_TOOLS__ -#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) -#endif - -#if defined(__i386__) -#include "xen-x86_32.h" -#elif defined(__x86_64__) -#include "xen-x86_64.h" -#endif - -#ifndef __ASSEMBLY__ -typedef unsigned long xen_pfn_t; -#define PRI_xen_pfn "lx" -#endif - -/* - * SEGMENT DESCRIPTOR TABLES - */ -/* - * A number of GDT entries are reserved by Xen. These are not situated at the - * start of the GDT because some stupid OSes export hard-coded selector values - * in their ABI. These hard-coded values are always near the start of the GDT, - * so Xen places itself out of the way, at the far end of the GDT. - */ -#define FIRST_RESERVED_GDT_PAGE 14 -#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096) -#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8) - -/* Maximum number of virtual CPUs in multi-processor guests. */ -#define MAX_VIRT_CPUS 32 - -#ifndef __ASSEMBLY__ - -typedef unsigned long xen_ulong_t; - -/* - * Send an array of these to HYPERVISOR_set_trap_table(). - * The privilege level specifies which modes may enter a trap via a software - * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate - * privilege levels as follows: - * Level == 0: Noone may enter - * Level == 1: Kernel may enter - * Level == 2: Kernel may enter - * Level == 3: Everyone may enter - */ -#define TI_GET_DPL(_ti) ((_ti)->flags & 3) -#define TI_GET_IF(_ti) ((_ti)->flags & 4) -#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) -#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) -struct trap_info { - uint8_t vector; /* exception vector */ - uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */ - uint16_t cs; /* code selector */ - unsigned long address; /* code offset */ -}; -typedef struct trap_info trap_info_t; -DEFINE_XEN_GUEST_HANDLE(trap_info_t); - -typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ - -/* - * The following is all CPU context. Note that the fpu_ctxt block is filled - * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used. - */ -struct vcpu_guest_context { - /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */ - struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */ -#define VGCF_I387_VALID (1<<0) -#define VGCF_IN_KERNEL (1<<2) -#define _VGCF_i387_valid 0 -#define VGCF_i387_valid (1<<_VGCF_i387_valid) -#define _VGCF_in_kernel 2 -#define VGCF_in_kernel (1<<_VGCF_in_kernel) -#define _VGCF_failsafe_disables_events 3 -#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) -#define _VGCF_syscall_disables_events 4 -#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events) -#define _VGCF_online 5 -#define VGCF_online (1<<_VGCF_online) - unsigned long flags; /* VGCF_* flags */ - struct cpu_user_regs user_regs; /* User-level CPU registers */ - struct trap_info trap_ctxt[256]; /* Virtual IDT */ - unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */ - unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */ - unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */ - /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */ - unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */ - unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */ -#ifdef __i386__ - unsigned long event_callback_cs; /* CS:EIP of event callback */ - unsigned long event_callback_eip; - unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */ - unsigned long failsafe_callback_eip; -#else - unsigned long event_callback_eip; - unsigned long failsafe_callback_eip; -#ifdef __XEN__ - union { - unsigned long syscall_callback_eip; - struct { - unsigned int event_callback_cs; /* compat CS of event cb */ - unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */ - }; - }; -#else - unsigned long syscall_callback_eip; -#endif -#endif - unsigned long vm_assist; /* VMASST_TYPE_* bitmap */ -#ifdef __x86_64__ - /* Segment base addresses. */ - uint64_t fs_base; - uint64_t gs_base_kernel; - uint64_t gs_base_user; -#endif -}; -typedef struct vcpu_guest_context vcpu_guest_context_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); - -struct arch_shared_info { - unsigned long max_pfn; /* max pfn that appears in table */ - /* Frame containing list of mfns containing list of mfns containing p2m. */ - xen_pfn_t pfn_to_mfn_frame_list_list; - unsigned long nmi_reason; - uint64_t pad[32]; -}; -typedef struct arch_shared_info arch_shared_info_t; - -#define MCA_PANICDATA_MAGIC 0x5044 /* "PD" */ -#define MCA_PANICDATA_VERS 1 - -typedef struct xpv_mca_panic_data { - uint16_t mpd_magic; - uint16_t mpd_version; - int mpd_fwdptr_offset; - int mpd_revptr_offset; - int mpd_dataptr_offset; - void *mpd_urgent_processing; - void *mpd_urgent_dangling; - void *mpd_urgent_committed; - void *mpd_nonurgent_processing; - void *mpd_nonurgent_dangling; - void *mpd_nonurgent_committed; -} xpv_mca_panic_data_t; - -typedef struct panic_regs panic_regs_t; -struct panic_info { - int pi_version; /* panic_info format version */ - panic_regs_t *pi_regs; /* register state */ - void *pi_apic; /* local APIC address */ - char *pi_panicstr; /* panic message */ - void *pi_ram_start; /* Start of all-RAM mapping region */ - void *pi_ram_end; /* End of all-RAM mapping region */ - void *pi_xen_start; /* Start of Xen's text/heap */ - void *pi_xen_end; /* End of Xen's text/heap */ - void *pi_stktop; /* Top of current Xen stack */ - struct domain *pi_domain; /* Panicking domain */ - struct vcpu *pi_vcpu; /* Panicking vcpu */ - int pi_dom0cpu; /* cpu number - if a dom0 panic */ - xpv_mca_panic_data_t pi_mca; /* Machine check error telemetry */ -}; - -struct panic_frame { - unsigned long pf_fp; - unsigned long pf_pc; -}; - -#define PANIC_INFO_VERSION 3 - -#endif /* !__ASSEMBLY__ */ - -/* - * Prefix forces emulation of some non-trapping instructions. - * Currently only CPUID. - */ -#ifdef __ASSEMBLY__ -#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ; -#define XEN_CPUID XEN_EMULATE_PREFIX cpuid -#else -#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; " -#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" -#endif - -#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/callback.h b/usr/src/uts/common/xen/public/callback.h deleted file mode 100644 index f4962f66d8..0000000000 --- a/usr/src/uts/common/xen/public/callback.h +++ /dev/null @@ -1,121 +0,0 @@ -/****************************************************************************** - * callback.h - * - * Register guest OS callbacks with Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2006, Ian Campbell - */ - -#ifndef __XEN_PUBLIC_CALLBACK_H__ -#define __XEN_PUBLIC_CALLBACK_H__ - -#include "xen.h" - -/* - * Prototype for this hypercall is: - * long callback_op(int cmd, void *extra_args) - * @cmd == CALLBACKOP_??? (callback operation). - * @extra_args == Operation-specific extra arguments (NULL if none). - */ - -/* ia64, x86: Callback for event delivery. */ -#define CALLBACKTYPE_event 0 - -/* x86: Failsafe callback when guest state cannot be restored by Xen. */ -#define CALLBACKTYPE_failsafe 1 - -/* x86/64 hypervisor: Syscall by 64-bit guest app ('64-on-64-on-64'). */ -#define CALLBACKTYPE_syscall 2 - -/* - * x86/32 hypervisor: Only available on x86/32 when supervisor_mode_kernel - * feature is enabled. Do not use this callback type in new code. - */ -#define CALLBACKTYPE_sysenter_deprecated 3 - -/* x86: Callback for NMI delivery. */ -#define CALLBACKTYPE_nmi 4 - -/* - * x86: sysenter is only available as follows: - * - 32-bit hypervisor: with the supervisor_mode_kernel feature enabled - * - 64-bit hypervisor: 32-bit guest applications on Intel CPUs - * ('32-on-32-on-64', '32-on-64-on-64') - * [nb. also 64-bit guest applications on Intel CPUs - * ('64-on-64-on-64'), but syscall is preferred] - */ -#define CALLBACKTYPE_sysenter 5 - -/* - * x86/64 hypervisor: Syscall by 32-bit guest app on AMD CPUs - * ('32-on-32-on-64', '32-on-64-on-64') - */ -#define CALLBACKTYPE_syscall32 7 - -/* - * Disable event deliver during callback? This flag is ignored for event and - * NMI callbacks: event delivery is unconditionally disabled. - */ -#define _CALLBACKF_mask_events 0 -#define CALLBACKF_mask_events (1U << _CALLBACKF_mask_events) - -/* - * Register a callback. - */ -#define CALLBACKOP_register 0 -struct callback_register { - uint16_t type; - uint16_t flags; - xen_callback_t address; -}; -typedef struct callback_register callback_register_t; -DEFINE_XEN_GUEST_HANDLE(callback_register_t); - -/* - * Unregister a callback. - * - * Not all callbacks can be unregistered. -EINVAL will be returned if - * you attempt to unregister such a callback. - */ -#define CALLBACKOP_unregister 1 -struct callback_unregister { - uint16_t type; - uint16_t _unused; -}; -typedef struct callback_unregister callback_unregister_t; -DEFINE_XEN_GUEST_HANDLE(callback_unregister_t); - -#if __XEN_INTERFACE_VERSION__ < 0x00030207 -#undef CALLBACKTYPE_sysenter -#define CALLBACKTYPE_sysenter CALLBACKTYPE_sysenter_deprecated -#endif - -#endif /* __XEN_PUBLIC_CALLBACK_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/domctl.h b/usr/src/uts/common/xen/public/domctl.h deleted file mode 100644 index 7520134a4d..0000000000 --- a/usr/src/uts/common/xen/public/domctl.h +++ /dev/null @@ -1,707 +0,0 @@ -/****************************************************************************** - * domctl.h - * - * Domain management operations. For use by node control stack. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2002-2003, B Dragovic - * Copyright (c) 2002-2006, K Fraser - */ - -#ifndef __XEN_PUBLIC_DOMCTL_H__ -#define __XEN_PUBLIC_DOMCTL_H__ - -#if !defined(__XEN__) && !defined(__XEN_TOOLS__) -#error "domctl operations are intended for use by node control tools only" -#endif - -#include "xen.h" - -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000005 - -struct xenctl_cpumap { - XEN_GUEST_HANDLE_64(uint8) bitmap; - uint32_t nr_cpus; -}; - -/* - * NB. xen_domctl.domain is an IN/OUT parameter for this operation. - * If it is specified as zero, an id is auto-allocated and returned. - */ -#define XEN_DOMCTL_createdomain 1 -struct xen_domctl_createdomain { - /* IN parameters */ - uint32_t ssidref; - xen_domain_handle_t handle; - /* Is this an HVM guest (as opposed to a PV guest)? */ -#define _XEN_DOMCTL_CDF_hvm_guest 0 -#define XEN_DOMCTL_CDF_hvm_guest (1U<<_XEN_DOMCTL_CDF_hvm_guest) - /* Use hardware-assisted paging if available? */ -#define _XEN_DOMCTL_CDF_hap 1 -#define XEN_DOMCTL_CDF_hap (1U<<_XEN_DOMCTL_CDF_hap) - /* Should domain memory integrity be verifed by tboot during Sx? */ -#define _XEN_DOMCTL_CDF_s3_integrity 2 -#define XEN_DOMCTL_CDF_s3_integrity (1U<<_XEN_DOMCTL_CDF_s3_integrity) - uint32_t flags; -}; -typedef struct xen_domctl_createdomain xen_domctl_createdomain_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t); - -#define XEN_DOMCTL_destroydomain 2 -#define XEN_DOMCTL_pausedomain 3 -#define XEN_DOMCTL_unpausedomain 4 -#define XEN_DOMCTL_resumedomain 27 - -#define XEN_DOMCTL_getdomaininfo 5 -struct xen_domctl_getdomaininfo { - /* OUT variables. */ - domid_t domain; /* Also echoed in domctl.domain */ - /* Domain is scheduled to die. */ -#define _XEN_DOMINF_dying 0 -#define XEN_DOMINF_dying (1U<<_XEN_DOMINF_dying) - /* Domain is an HVM guest (as opposed to a PV guest). */ -#define _XEN_DOMINF_hvm_guest 1 -#define XEN_DOMINF_hvm_guest (1U<<_XEN_DOMINF_hvm_guest) - /* The guest OS has shut down. */ -#define _XEN_DOMINF_shutdown 2 -#define XEN_DOMINF_shutdown (1U<<_XEN_DOMINF_shutdown) - /* Currently paused by control software. */ -#define _XEN_DOMINF_paused 3 -#define XEN_DOMINF_paused (1U<<_XEN_DOMINF_paused) - /* Currently blocked pending an event. */ -#define _XEN_DOMINF_blocked 4 -#define XEN_DOMINF_blocked (1U<<_XEN_DOMINF_blocked) - /* Domain is currently running. */ -#define _XEN_DOMINF_running 5 -#define XEN_DOMINF_running (1U<<_XEN_DOMINF_running) - /* Being debugged. */ -#define _XEN_DOMINF_debugged 6 -#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged) - /* XEN_DOMINF_shutdown guest-supplied code. */ -#define XEN_DOMINF_shutdownmask 255 -#define XEN_DOMINF_shutdownshift 16 - uint32_t flags; /* XEN_DOMINF_* */ - uint64_aligned_t tot_pages; - uint64_aligned_t max_pages; - uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */ - uint64_aligned_t cpu_time; - uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ - uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ - uint32_t ssidref; - xen_domain_handle_t handle; -}; -typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); - - -#define XEN_DOMCTL_getmemlist 6 -struct xen_domctl_getmemlist { - /* IN variables. */ - /* Max entries to write to output buffer. */ - uint64_aligned_t max_pfns; - /* Start index in guest's page list. */ - uint64_aligned_t start_pfn; - XEN_GUEST_HANDLE_64(uint64) buffer; - /* OUT variables. */ - uint64_aligned_t num_pfns; -}; -typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t); - - -#define XEN_DOMCTL_getpageframeinfo 7 - -#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28 -#define XEN_DOMCTL_PFINFO_NOTAB (0x0U<<28) -#define XEN_DOMCTL_PFINFO_L1TAB (0x1U<<28) -#define XEN_DOMCTL_PFINFO_L2TAB (0x2U<<28) -#define XEN_DOMCTL_PFINFO_L3TAB (0x3U<<28) -#define XEN_DOMCTL_PFINFO_L4TAB (0x4U<<28) -#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28) -#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31) -#define XEN_DOMCTL_PFINFO_XTAB (0xfU<<28) /* invalid page */ -#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28) - -struct xen_domctl_getpageframeinfo { - /* IN variables. */ - uint64_aligned_t gmfn; /* GMFN to query */ - /* OUT variables. */ - /* Is the page PINNED to a type? */ - uint32_t type; /* see above type defs */ -}; -typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t); - - -#define XEN_DOMCTL_getpageframeinfo2 8 -struct xen_domctl_getpageframeinfo2 { - /* IN variables. */ - uint64_aligned_t num; - /* IN/OUT variables. */ - XEN_GUEST_HANDLE_64(uint32) array; -}; -typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t); - - -/* - * Control shadow pagetables operation - */ -#define XEN_DOMCTL_shadow_op 10 - -/* Disable shadow mode. */ -#define XEN_DOMCTL_SHADOW_OP_OFF 0 - -/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */ -#define XEN_DOMCTL_SHADOW_OP_ENABLE 32 - -/* Log-dirty bitmap operations. */ - /* Return the bitmap and clean internal copy for next round. */ -#define XEN_DOMCTL_SHADOW_OP_CLEAN 11 - /* Return the bitmap but do not modify internal copy. */ -#define XEN_DOMCTL_SHADOW_OP_PEEK 12 - -/* Memory allocation accessors. */ -#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 -#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 - -/* Legacy enable operations. */ - /* Equiv. to ENABLE with no mode flags. */ -#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 - /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */ -#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 - /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */ -#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 - -/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */ - /* - * Shadow pagetables are refcounted: guest does not use explicit mmu - * operations nor write-protect its pagetables. - */ -#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) - /* - * Log pages in a bitmap as they are dirtied. - * Used for live relocation to determine which pages must be re-sent. - */ -#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) - /* - * Automatically translate GPFNs into MFNs. - */ -#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) - /* - * Xen does not steal virtual address space from the guest. - * Requires HVM support. - */ -#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) - -struct xen_domctl_shadow_op_stats { - uint32_t fault_count; - uint32_t dirty_count; -}; -typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t); - -struct xen_domctl_shadow_op { - /* IN variables. */ - uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */ - - /* OP_ENABLE */ - uint32_t mode; /* XEN_DOMCTL_SHADOW_ENABLE_* */ - - /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */ - uint32_t mb; /* Shadow memory allocation in MB */ - - /* OP_PEEK / OP_CLEAN */ - XEN_GUEST_HANDLE_64(uint8) dirty_bitmap; - uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */ - struct xen_domctl_shadow_op_stats stats; -}; -typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t); - - -#define XEN_DOMCTL_max_mem 11 -struct xen_domctl_max_mem { - /* IN variables. */ - uint64_aligned_t max_memkb; -}; -typedef struct xen_domctl_max_mem xen_domctl_max_mem_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t); - - -#define XEN_DOMCTL_setvcpucontext 12 -#define XEN_DOMCTL_getvcpucontext 13 -struct xen_domctl_vcpucontext { - uint32_t vcpu; /* IN */ - XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */ -}; -typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t); - - -#define XEN_DOMCTL_getvcpuinfo 14 -struct xen_domctl_getvcpuinfo { - /* IN variables. */ - uint32_t vcpu; - /* OUT variables. */ - uint8_t online; /* currently online (not hotplugged)? */ - uint8_t blocked; /* blocked waiting for an event? */ - uint8_t running; /* currently scheduled on its CPU? */ - uint64_aligned_t cpu_time; /* total cpu time consumed (ns) */ - uint32_t cpu; /* current mapping */ -}; -typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t); - - -/* Get/set which physical cpus a vcpu can execute on. */ -#define XEN_DOMCTL_setvcpuaffinity 9 -#define XEN_DOMCTL_getvcpuaffinity 25 -struct xen_domctl_vcpuaffinity { - uint32_t vcpu; /* IN */ - struct xenctl_cpumap cpumap; /* IN/OUT */ -}; -typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t); - - -#define XEN_DOMCTL_max_vcpus 15 -struct xen_domctl_max_vcpus { - uint32_t max; /* maximum number of vcpus */ -}; -typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t); - - -#define XEN_DOMCTL_scheduler_op 16 -/* Scheduler types. */ -#define XEN_SCHEDULER_SEDF 4 -#define XEN_SCHEDULER_CREDIT 5 -/* Set or get info? */ -#define XEN_DOMCTL_SCHEDOP_putinfo 0 -#define XEN_DOMCTL_SCHEDOP_getinfo 1 -struct xen_domctl_scheduler_op { - uint32_t sched_id; /* XEN_SCHEDULER_* */ - uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */ - union { - struct xen_domctl_sched_sedf { - uint64_aligned_t period; - uint64_aligned_t slice; - uint64_aligned_t latency; - uint32_t extratime; - uint32_t weight; - } sedf; - struct xen_domctl_sched_credit { - uint16_t weight; - uint16_t cap; - } credit; - } u; -}; -typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t); - - -#define XEN_DOMCTL_setdomainhandle 17 -struct xen_domctl_setdomainhandle { - xen_domain_handle_t handle; -}; -typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t); - - -#define XEN_DOMCTL_setdebugging 18 -struct xen_domctl_setdebugging { - uint8_t enable; -}; -typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t); - - -#define XEN_DOMCTL_irq_permission 19 -struct xen_domctl_irq_permission { - uint8_t pirq; - uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ -}; -typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t); - - -#define XEN_DOMCTL_iomem_permission 20 -struct xen_domctl_iomem_permission { - uint64_aligned_t first_mfn;/* first page (physical page number) in range */ - uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ - uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ -}; -typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t); - - -#define XEN_DOMCTL_ioport_permission 21 -struct xen_domctl_ioport_permission { - uint32_t first_port; /* first port int range */ - uint32_t nr_ports; /* size of port range */ - uint8_t allow_access; /* allow or deny access to range? */ -}; -typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t); - - -#define XEN_DOMCTL_hypercall_init 22 -struct xen_domctl_hypercall_init { - uint64_aligned_t gmfn; /* GMFN to be initialised */ -}; -typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t); - - -#define XEN_DOMCTL_arch_setup 23 -#define _XEN_DOMAINSETUP_hvm_guest 0 -#define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest) -#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */ -#define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query) -#define _XEN_DOMAINSETUP_sioemu_guest 2 -#define XEN_DOMAINSETUP_sioemu_guest (1UL<<_XEN_DOMAINSETUP_sioemu_guest) -typedef struct xen_domctl_arch_setup { - uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */ -#ifdef __ia64__ - uint64_aligned_t bp; /* mpaddr of boot param area */ - uint64_aligned_t maxmem; /* Highest memory address for MDT. */ - uint64_aligned_t xsi_va; /* Xen shared_info area virtual address. */ - uint32_t hypercall_imm; /* Break imm for Xen hypercalls. */ - int8_t vhpt_size_log2; /* Log2 of VHPT size. */ -#endif -} xen_domctl_arch_setup_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t); - - -#define XEN_DOMCTL_settimeoffset 24 -struct xen_domctl_settimeoffset { - int32_t time_offset_seconds; /* applied to domain wallclock time */ -}; -typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); - - -#define XEN_DOMCTL_gethvmcontext 33 -#define XEN_DOMCTL_sethvmcontext 34 -typedef struct xen_domctl_hvmcontext { - uint32_t size; /* IN/OUT: size of buffer / bytes filled */ - XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call - * gethvmcontext with NULL - * buffer to get size req'd */ -} xen_domctl_hvmcontext_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t); - - -#define XEN_DOMCTL_set_address_size 35 -#define XEN_DOMCTL_get_address_size 36 -typedef struct xen_domctl_address_size { - uint32_t size; -} xen_domctl_address_size_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t); - - -#define XEN_DOMCTL_real_mode_area 26 -struct xen_domctl_real_mode_area { - uint32_t log; /* log2 of Real Mode Area size */ -}; -typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t); - - -#define XEN_DOMCTL_sendtrigger 28 -#define XEN_DOMCTL_SENDTRIGGER_NMI 0 -#define XEN_DOMCTL_SENDTRIGGER_RESET 1 -#define XEN_DOMCTL_SENDTRIGGER_INIT 2 -#define XEN_DOMCTL_SENDTRIGGER_POWER 3 -struct xen_domctl_sendtrigger { - uint32_t trigger; /* IN */ - uint32_t vcpu; /* IN */ -}; -typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t); - - -/* Assign PCI device to HVM guest. Sets up IOMMU structures. */ -#define XEN_DOMCTL_assign_device 37 -#define XEN_DOMCTL_test_assign_device 45 -#define XEN_DOMCTL_deassign_device 47 -struct xen_domctl_assign_device { - uint32_t machine_bdf; /* machine PCI ID of assigned device */ -}; -typedef struct xen_domctl_assign_device xen_domctl_assign_device_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t); - -/* Retrieve sibling devices infomation of machine_bdf */ -#define XEN_DOMCTL_get_device_group 50 -struct xen_domctl_get_device_group { - uint32_t machine_bdf; /* IN */ - uint32_t max_sdevs; /* IN */ - uint32_t num_sdevs; /* OUT */ - XEN_GUEST_HANDLE_64(uint32) sdev_array; /* OUT */ -}; -typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t); - -/* Pass-through interrupts: bind real irq -> hvm devfn. */ -#define XEN_DOMCTL_bind_pt_irq 38 -#define XEN_DOMCTL_unbind_pt_irq 48 -typedef enum pt_irq_type_e { - PT_IRQ_TYPE_PCI, - PT_IRQ_TYPE_ISA, - PT_IRQ_TYPE_MSI, - PT_IRQ_TYPE_MSI_TRANSLATE, -} pt_irq_type_t; -struct xen_domctl_bind_pt_irq { - uint32_t machine_irq; - pt_irq_type_t irq_type; - uint32_t hvm_domid; - - union { - struct { - uint8_t isa_irq; - } isa; - struct { - uint8_t bus; - uint8_t device; - uint8_t intx; - } pci; - struct { - uint8_t gvec; - uint32_t gflags; - uint64_aligned_t gtable; - } msi; - } u; -}; -typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t); - - -/* Bind machine I/O address range -> HVM address range. */ -#define XEN_DOMCTL_memory_mapping 39 -#define DPCI_ADD_MAPPING 1 -#define DPCI_REMOVE_MAPPING 0 -struct xen_domctl_memory_mapping { - uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */ - uint64_aligned_t first_mfn; /* first page (machine page) in range */ - uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ - uint32_t add_mapping; /* add or remove mapping */ - uint32_t padding; /* padding for 64-bit aligned structure */ -}; -typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t); - - -/* Bind machine I/O port range -> HVM I/O port range. */ -#define XEN_DOMCTL_ioport_mapping 40 -struct xen_domctl_ioport_mapping { - uint32_t first_gport; /* first guest IO port*/ - uint32_t first_mport; /* first machine IO port */ - uint32_t nr_ports; /* size of port range */ - uint32_t add_mapping; /* add or remove mapping */ -}; -typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t); - - -/* - * Pin caching type of RAM space for x86 HVM domU. - */ -#define XEN_DOMCTL_pin_mem_cacheattr 41 -/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */ -#define XEN_DOMCTL_MEM_CACHEATTR_UC 0 -#define XEN_DOMCTL_MEM_CACHEATTR_WC 1 -#define XEN_DOMCTL_MEM_CACHEATTR_WT 4 -#define XEN_DOMCTL_MEM_CACHEATTR_WP 5 -#define XEN_DOMCTL_MEM_CACHEATTR_WB 6 -#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7 -struct xen_domctl_pin_mem_cacheattr { - uint64_aligned_t start, end; - unsigned int type; /* XEN_DOMCTL_MEM_CACHEATTR_* */ -}; -typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t); - - -#define XEN_DOMCTL_set_ext_vcpucontext 42 -#define XEN_DOMCTL_get_ext_vcpucontext 43 -struct xen_domctl_ext_vcpucontext { - /* IN: VCPU that this call applies to. */ - uint32_t vcpu; - /* - * SET: Size of struct (IN) - * GET: Size of struct (OUT) - */ - uint32_t size; -#if defined(__i386__) || defined(__x86_64__) - /* SYSCALL from 32-bit mode and SYSENTER callback information. */ - /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */ - uint64_aligned_t syscall32_callback_eip; - uint64_aligned_t sysenter_callback_eip; - uint16_t syscall32_callback_cs; - uint16_t sysenter_callback_cs; - uint8_t syscall32_disables_events; - uint8_t sysenter_disables_events; -#endif -}; -typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t); - -/* - * Set optimizaton features for a domain - */ -#define XEN_DOMCTL_set_opt_feature 44 -struct xen_domctl_set_opt_feature { -#if defined(__ia64__) - struct xen_ia64_opt_feature optf; -#else - /* Make struct non-empty: do not depend on this field name! */ - uint64_t dummy; -#endif -}; -typedef struct xen_domctl_set_opt_feature xen_domctl_set_opt_feature_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_opt_feature_t); - -/* - * Set the target domain for a domain - */ -#define XEN_DOMCTL_set_target 46 -struct xen_domctl_set_target { - domid_t target; -}; -typedef struct xen_domctl_set_target xen_domctl_set_target_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t); - -#if defined(__i386__) || defined(__x86_64__) -# define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF -# define XEN_DOMCTL_set_cpuid 49 -struct xen_domctl_cpuid { - unsigned int input[2]; - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; -}; -typedef struct xen_domctl_cpuid xen_domctl_cpuid_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t); -#endif - -#define XEN_DOMCTL_subscribe 29 -struct xen_domctl_subscribe { - uint32_t port; /* IN */ -}; -typedef struct xen_domctl_subscribe xen_domctl_subscribe_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t); - -/* - * Define the maximum machine address size which should be allocated - * to a guest. - */ -#define XEN_DOMCTL_set_machine_address_size 51 -#define XEN_DOMCTL_get_machine_address_size 52 - -/* - * Do not inject spurious page faults into this domain. - */ -#define XEN_DOMCTL_suppress_spurious_page_faults 53 - -#define XEN_DOMCTL_debug_op 54 -#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0 -#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1 -struct xen_domctl_debug_op { - uint32_t op; /* IN */ - uint32_t vcpu; /* IN */ -}; -typedef struct xen_domctl_debug_op xen_domctl_debug_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t); - -/* - * Request a particular record from the HVM context - */ -#define XEN_DOMCTL_gethvmcontext_partial 55 -typedef struct xen_domctl_hvmcontext_partial { - uint32_t type; /* IN: Type of record required */ - uint32_t instance; /* IN: Instance of that type */ - XEN_GUEST_HANDLE_64(uint8) buffer; /* OUT: buffer to write record into */ -} xen_domctl_hvmcontext_partial_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t); - - -struct xen_domctl { - uint32_t cmd; - uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ - domid_t domain; - union { - struct xen_domctl_createdomain createdomain; - struct xen_domctl_getdomaininfo getdomaininfo; - struct xen_domctl_getmemlist getmemlist; - struct xen_domctl_getpageframeinfo getpageframeinfo; - struct xen_domctl_getpageframeinfo2 getpageframeinfo2; - struct xen_domctl_vcpuaffinity vcpuaffinity; - struct xen_domctl_shadow_op shadow_op; - struct xen_domctl_max_mem max_mem; - struct xen_domctl_vcpucontext vcpucontext; - struct xen_domctl_getvcpuinfo getvcpuinfo; - struct xen_domctl_max_vcpus max_vcpus; - struct xen_domctl_scheduler_op scheduler_op; - struct xen_domctl_setdomainhandle setdomainhandle; - struct xen_domctl_setdebugging setdebugging; - struct xen_domctl_irq_permission irq_permission; - struct xen_domctl_iomem_permission iomem_permission; - struct xen_domctl_ioport_permission ioport_permission; - struct xen_domctl_hypercall_init hypercall_init; - struct xen_domctl_arch_setup arch_setup; - struct xen_domctl_settimeoffset settimeoffset; - struct xen_domctl_real_mode_area real_mode_area; - struct xen_domctl_hvmcontext hvmcontext; - struct xen_domctl_hvmcontext_partial hvmcontext_partial; - struct xen_domctl_address_size address_size; - struct xen_domctl_sendtrigger sendtrigger; - struct xen_domctl_get_device_group get_device_group; - struct xen_domctl_assign_device assign_device; - struct xen_domctl_bind_pt_irq bind_pt_irq; - struct xen_domctl_memory_mapping memory_mapping; - struct xen_domctl_ioport_mapping ioport_mapping; - struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr; - struct xen_domctl_ext_vcpucontext ext_vcpucontext; - struct xen_domctl_set_opt_feature set_opt_feature; - struct xen_domctl_set_target set_target; - struct xen_domctl_subscribe subscribe; - struct xen_domctl_debug_op debug_op; -#if defined(__i386__) || defined(__x86_64__) - struct xen_domctl_cpuid cpuid; -#endif - uint8_t pad[128]; - } u; -}; -typedef struct xen_domctl xen_domctl_t; -DEFINE_XEN_GUEST_HANDLE(xen_domctl_t); - -#endif /* __XEN_PUBLIC_DOMCTL_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/elfnote.h b/usr/src/uts/common/xen/public/elfnote.h deleted file mode 100644 index 3888cc0c83..0000000000 --- a/usr/src/uts/common/xen/public/elfnote.h +++ /dev/null @@ -1,244 +0,0 @@ -/****************************************************************************** - * elfnote.h - * - * Definitions used for the Xen ELF notes. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2006, Ian Campbell, XenSource Ltd. - */ - -#ifndef __XEN_PUBLIC_ELFNOTE_H__ -#define __XEN_PUBLIC_ELFNOTE_H__ - -/* - * The notes should live in a PT_NOTE segment and have "Xen" in the - * name field. - * - * Numeric types are either 4 or 8 bytes depending on the content of - * the desc field. - * - * LEGACY indicated the fields in the legacy __xen_guest string which - * this a note type replaces. - */ - -/* - * NAME=VALUE pair (string). - */ -#define XEN_ELFNOTE_INFO 0 - -/* - * The virtual address of the entry point (numeric). - * - * LEGACY: VIRT_ENTRY - */ -#define XEN_ELFNOTE_ENTRY 1 - -/* The virtual address of the hypercall transfer page (numeric). - * - * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page - * number not a virtual address) - */ -#define XEN_ELFNOTE_HYPERCALL_PAGE 2 - -/* The virtual address where the kernel image should be mapped (numeric). - * - * Defaults to 0. - * - * LEGACY: VIRT_BASE - */ -#define XEN_ELFNOTE_VIRT_BASE 3 - -/* - * The offset of the ELF paddr field from the acutal required - * psuedo-physical address (numeric). - * - * This is used to maintain backwards compatibility with older kernels - * which wrote __PAGE_OFFSET into that field. This field defaults to 0 - * if not present. - * - * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE) - */ -#define XEN_ELFNOTE_PADDR_OFFSET 4 - -/* - * The version of Xen that we work with (string). - * - * LEGACY: XEN_VER - */ -#define XEN_ELFNOTE_XEN_VERSION 5 - -/* - * The name of the guest operating system (string). - * - * LEGACY: GUEST_OS - */ -#define XEN_ELFNOTE_GUEST_OS 6 - -/* - * The version of the guest operating system (string). - * - * LEGACY: GUEST_VER - */ -#define XEN_ELFNOTE_GUEST_VERSION 7 - -/* - * The loader type (string). - * - * LEGACY: LOADER - */ -#define XEN_ELFNOTE_LOADER 8 - -/* - * The kernel supports PAE (x86/32 only, string = "yes", "no" or - * "bimodal"). - * - * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting - * may be given as "yes,bimodal" which will cause older Xen to treat - * this kernel as PAE. - * - * LEGACY: PAE (n.b. The legacy interface included a provision to - * indicate 'extended-cr3' support allowing L3 page tables to be - * placed above 4G. It is assumed that any kernel new enough to use - * these ELF notes will include this and therefore "yes" here is - * equivalent to "yes[entended-cr3]" in the __xen_guest interface. - */ -#define XEN_ELFNOTE_PAE_MODE 9 - -/* - * The features supported/required by this kernel (string). - * - * The string must consist of a list of feature names (as given in - * features.h, without the "XENFEAT_" prefix) separated by '|' - * characters. If a feature is required for the kernel to function - * then the feature name must be preceded by a '!' character. - * - * LEGACY: FEATURES - */ -#define XEN_ELFNOTE_FEATURES 10 - -/* - * The kernel requires the symbol table to be loaded (string = "yes" or "no") - * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence - * of this string as a boolean flag rather than requiring "yes" or - * "no". - */ -#define XEN_ELFNOTE_BSD_SYMTAB 11 - -/* - * The lowest address the hypervisor hole can begin at (numeric). - * - * This must not be set higher than HYPERVISOR_VIRT_START. Its presence - * also indicates to the hypervisor that the kernel can deal with the - * hole starting at a higher address. - */ -#define XEN_ELFNOTE_HV_START_LOW 12 - -/* - * List of maddr_t-sized mask/value pairs describing how to recognize - * (non-present) L1 page table entries carrying valid MFNs (numeric). - */ -#define XEN_ELFNOTE_L1_MFN_VALID 13 - -/* - * Whether or not the guest supports cooperative suspend cancellation. - */ -#define XEN_ELFNOTE_SUSPEND_CANCEL 14 - -/* - * The (non-default) location the initial phys-to-machine map should be - * placed at by the hypervisor (Dom0) or the tools (DomU). - * The kernel must be prepared for this mapping to be established using - * large pages, despite such otherwise not being available to guests. - * The kernel must also be able to handle the page table pages used for - * this mapping not being accessible through the initial mapping. - * (Only x86-64 supports this at present.) - */ -#define XEN_ELFNOTE_INIT_P2M 15 - -/* - * The number of the highest elfnote defined. - */ -#define XEN_ELFNOTE_MAX XEN_ELFNOTE_INIT_P2M - -/* - * System information exported through crash notes. - * - * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO - * note in case of a system crash. This note will contain various - * information about the system, see xen/include/xen/elfcore.h. - */ -#define XEN_ELFNOTE_CRASH_INFO 0x1000001 - -/* - * System registers exported through crash notes. - * - * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS - * note per cpu in case of a system crash. This note is architecture - * specific and will contain registers not saved in the "CORE" note. - * See xen/include/xen/elfcore.h for more information. - */ -#define XEN_ELFNOTE_CRASH_REGS 0x1000002 - - -/* - * xen dump-core none note. - * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_NONE - * in its dump file to indicate that the file is xen dump-core - * file. This note doesn't have any other information. - * See tools/libxc/xc_core.h for more information. - */ -#define XEN_ELFNOTE_DUMPCORE_NONE 0x2000000 - -/* - * xen dump-core header note. - * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_HEADER - * in its dump file. - * See tools/libxc/xc_core.h for more information. - */ -#define XEN_ELFNOTE_DUMPCORE_HEADER 0x2000001 - -/* - * xen dump-core xen version note. - * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_XEN_VERSION - * in its dump file. It contains the xen version obtained via the - * XENVER hypercall. - * See tools/libxc/xc_core.h for more information. - */ -#define XEN_ELFNOTE_DUMPCORE_XEN_VERSION 0x2000002 - -/* - * xen dump-core format version note. - * xm dump-core code will create one XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION - * in its dump file. It contains a format version identifier. - * See tools/libxc/xc_core.h for more information. - */ -#define XEN_ELFNOTE_DUMPCORE_FORMAT_VERSION 0x2000003 - -#endif /* __XEN_PUBLIC_ELFNOTE_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/event_channel.h b/usr/src/uts/common/xen/public/event_channel.h deleted file mode 100644 index d35cce53e4..0000000000 --- a/usr/src/uts/common/xen/public/event_channel.h +++ /dev/null @@ -1,264 +0,0 @@ -/****************************************************************************** - * event_channel.h - * - * Event channels between domains. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2003-2004, K A Fraser. - */ - -#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__ -#define __XEN_PUBLIC_EVENT_CHANNEL_H__ - -/* - * Prototype for this hypercall is: - * int event_channel_op(int cmd, void *args) - * @cmd == EVTCHNOP_??? (event-channel operation). - * @args == Operation-specific extra arguments (NULL if none). - */ - -typedef uint32_t evtchn_port_t; -DEFINE_XEN_GUEST_HANDLE(evtchn_port_t); - -/* - * EVTCHNOP_alloc_unbound: Allocate a port in domain and mark as - * accepting interdomain bindings from domain . A fresh port - * is allocated in and returned as . - * NOTES: - * 1. If the caller is unprivileged then must be DOMID_SELF. - * 2. may be DOMID_SELF, allowing loopback connections. - */ -#define EVTCHNOP_alloc_unbound 6 -struct evtchn_alloc_unbound { - /* IN parameters */ - domid_t dom, remote_dom; - /* OUT parameters */ - evtchn_port_t port; -}; -typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t; - -/* - * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between - * the calling domain and . must identify - * a port that is unbound and marked as accepting bindings from the calling - * domain. A fresh port is allocated in the calling domain and returned as - * . - * NOTES: - * 2. may be DOMID_SELF, allowing loopback connections. - */ -#define EVTCHNOP_bind_interdomain 0 -struct evtchn_bind_interdomain { - /* IN parameters. */ - domid_t remote_dom; - evtchn_port_t remote_port; - /* OUT parameters. */ - evtchn_port_t local_port; -}; -typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t; - -/* - * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ on specified - * vcpu. - * NOTES: - * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list - * in xen.h for the classification of each VIRQ. - * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be - * re-bound via EVTCHNOP_bind_vcpu. - * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu. - * The allocated event channel is bound to the specified vcpu and the - * binding cannot be changed. - */ -#define EVTCHNOP_bind_virq 1 -struct evtchn_bind_virq { - /* IN parameters. */ - uint32_t virq; - uint32_t vcpu; - /* OUT parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_bind_virq evtchn_bind_virq_t; - -/* - * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ . - * NOTES: - * 1. A physical IRQ may be bound to at most one event channel per domain. - * 2. Only a sufficiently-privileged domain may bind to a physical IRQ. - */ -#define EVTCHNOP_bind_pirq 2 -struct evtchn_bind_pirq { - /* IN parameters. */ - uint32_t pirq; -#define BIND_PIRQ__WILL_SHARE 1 - uint32_t flags; /* BIND_PIRQ__* */ - /* OUT parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_bind_pirq evtchn_bind_pirq_t; - -/* - * EVTCHNOP_bind_ipi: Bind a local event channel to receive events. - * NOTES: - * 1. The allocated event channel is bound to the specified vcpu. The binding - * may not be changed. - */ -#define EVTCHNOP_bind_ipi 7 -struct evtchn_bind_ipi { - uint32_t vcpu; - /* OUT parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_bind_ipi evtchn_bind_ipi_t; - -/* - * EVTCHNOP_close: Close a local event channel . If the channel is - * interdomain then the remote end is placed in the unbound state - * (EVTCHNSTAT_unbound), awaiting a new connection. - */ -#define EVTCHNOP_close 3 -struct evtchn_close { - /* IN parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_close evtchn_close_t; - -/* - * EVTCHNOP_send: Send an event to the remote end of the channel whose local - * endpoint is . - */ -#define EVTCHNOP_send 4 -struct evtchn_send { - /* IN parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_send evtchn_send_t; - -/* - * EVTCHNOP_status: Get the current status of the communication channel which - * has an endpoint at . - * NOTES: - * 1. may be specified as DOMID_SELF. - * 2. Only a sufficiently-privileged domain may obtain the status of an event - * channel for which is not DOMID_SELF. - */ -#define EVTCHNOP_status 5 -struct evtchn_status { - /* IN parameters */ - domid_t dom; - evtchn_port_t port; - /* OUT parameters */ -#define EVTCHNSTAT_closed 0 /* Channel is not in use. */ -#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/ -#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */ -#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */ -#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */ -#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */ - uint32_t status; - uint32_t vcpu; /* VCPU to which this channel is bound. */ - union { - struct { - domid_t dom; - } unbound; /* EVTCHNSTAT_unbound */ - struct { - domid_t dom; - evtchn_port_t port; - } interdomain; /* EVTCHNSTAT_interdomain */ - uint32_t pirq; /* EVTCHNSTAT_pirq */ - uint32_t virq; /* EVTCHNSTAT_virq */ - } u; -}; -typedef struct evtchn_status evtchn_status_t; - -/* - * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an - * event is pending. - * NOTES: - * 1. IPI-bound channels always notify the vcpu specified at bind time. - * This binding cannot be changed. - * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time. - * This binding cannot be changed. - * 3. All other channels notify vcpu0 by default. This default is set when - * the channel is allocated (a port that is freed and subsequently reused - * has its binding reset to vcpu0). - */ -#define EVTCHNOP_bind_vcpu 8 -struct evtchn_bind_vcpu { - /* IN parameters. */ - evtchn_port_t port; - uint32_t vcpu; -}; -typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t; - -/* - * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver - * a notification to the appropriate VCPU if an event is pending. - */ -#define EVTCHNOP_unmask 9 -struct evtchn_unmask { - /* IN parameters. */ - evtchn_port_t port; -}; -typedef struct evtchn_unmask evtchn_unmask_t; - -/* - * EVTCHNOP_reset: Close all event channels associated with specified domain. - * NOTES: - * 1. may be specified as DOMID_SELF. - * 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF. - */ -#define EVTCHNOP_reset 10 -struct evtchn_reset { - /* IN parameters. */ - domid_t dom; -}; -typedef struct evtchn_reset evtchn_reset_t; - -/* - * Argument to event_channel_op_compat() hypercall. Superceded by new - * event_channel_op() hypercall since 0x00030202. - */ -struct evtchn_op { - uint32_t cmd; /* EVTCHNOP_* */ - union { - struct evtchn_alloc_unbound alloc_unbound; - struct evtchn_bind_interdomain bind_interdomain; - struct evtchn_bind_virq bind_virq; - struct evtchn_bind_pirq bind_pirq; - struct evtchn_bind_ipi bind_ipi; - struct evtchn_close close; - struct evtchn_send send; - struct evtchn_status status; - struct evtchn_bind_vcpu bind_vcpu; - struct evtchn_unmask unmask; - } u; -}; -typedef struct evtchn_op evtchn_op_t; -DEFINE_XEN_GUEST_HANDLE(evtchn_op_t); - -#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/features.h b/usr/src/uts/common/xen/public/features.h deleted file mode 100644 index 879131cda1..0000000000 --- a/usr/src/uts/common/xen/public/features.h +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** - * features.h - * - * Feature flags, reported by XENVER_get_features. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2006, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_FEATURES_H__ -#define __XEN_PUBLIC_FEATURES_H__ - -/* - * If set, the guest does not need to write-protect its pagetables, and can - * update them via direct writes. - */ -#define XENFEAT_writable_page_tables 0 - -/* - * If set, the guest does not need to write-protect its segment descriptor - * tables, and can update them via direct writes. - */ -#define XENFEAT_writable_descriptor_tables 1 - -/* - * If set, translation between the guest's 'pseudo-physical' address space - * and the host's machine address space are handled by the hypervisor. In this - * mode the guest does not need to perform phys-to/from-machine translations - * when performing page table operations. - */ -#define XENFEAT_auto_translated_physmap 2 - -/* If set, the guest is running in supervisor mode (e.g., x86 ring 0). */ -#define XENFEAT_supervisor_mode_kernel 3 - -/* - * If set, the guest does not need to allocate x86 PAE page directories - * below 4GB. This flag is usually implied by auto_translated_physmap. - */ -#define XENFEAT_pae_pgdir_above_4gb 4 - -/* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */ -#define XENFEAT_mmu_pt_update_preserve_ad 5 - -/* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */ -#define XENFEAT_highmem_assist 6 - -/* - * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel - * available pte bits. - */ -#define XENFEAT_gnttab_map_avail_bits 7 - -#define XENFEAT_NR_SUBMAPS 1 - -#endif /* __XEN_PUBLIC_FEATURES_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/grant_table.h b/usr/src/uts/common/xen/public/grant_table.h deleted file mode 100644 index ad116e71e1..0000000000 --- a/usr/src/uts/common/xen/public/grant_table.h +++ /dev/null @@ -1,438 +0,0 @@ -/****************************************************************************** - * grant_table.h - * - * Interface for granting foreign access to page frames, and receiving - * page-ownership transfers. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2004, K A Fraser - */ - -#ifndef __XEN_PUBLIC_GRANT_TABLE_H__ -#define __XEN_PUBLIC_GRANT_TABLE_H__ - - -/*********************************** - * GRANT TABLE REPRESENTATION - */ - -/* Some rough guidelines on accessing and updating grant-table entries - * in a concurrency-safe manner. For more information, Linux contains a - * reference implementation for guest OSes (arch/xen/kernel/grant_table.c). - * - * NB. WMB is a no-op on current-generation x86 processors. However, a - * compiler barrier will still be required. - * - * Introducing a valid entry into the grant table: - * 1. Write ent->domid. - * 2. Write ent->frame: - * GTF_permit_access: Frame to which access is permitted. - * GTF_accept_transfer: Pseudo-phys frame slot being filled by new - * frame, or zero if none. - * 3. Write memory barrier (WMB). - * 4. Write ent->flags, inc. valid type. - * - * Invalidating an unused GTF_permit_access entry: - * 1. flags = ent->flags. - * 2. Observe that !(flags & (GTF_reading|GTF_writing)). - * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0). - * NB. No need for WMB as reuse of entry is control-dependent on success of - * step 3, and all architectures guarantee ordering of ctrl-dep writes. - * - * Invalidating an in-use GTF_permit_access entry: - * This cannot be done directly. Request assistance from the domain controller - * which can set a timeout on the use of a grant entry and take necessary - * action. (NB. This is not yet implemented!). - * - * Invalidating an unused GTF_accept_transfer entry: - * 1. flags = ent->flags. - * 2. Observe that !(flags & GTF_transfer_committed). [*] - * 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0). - * NB. No need for WMB as reuse of entry is control-dependent on success of - * step 3, and all architectures guarantee ordering of ctrl-dep writes. - * [*] If GTF_transfer_committed is set then the grant entry is 'committed'. - * The guest must /not/ modify the grant entry until the address of the - * transferred frame is written. It is safe for the guest to spin waiting - * for this to occur (detect by observing GTF_transfer_completed in - * ent->flags). - * - * Invalidating a committed GTF_accept_transfer entry: - * 1. Wait for (ent->flags & GTF_transfer_completed). - * - * Changing a GTF_permit_access from writable to read-only: - * Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing. - * - * Changing a GTF_permit_access from read-only to writable: - * Use SMP-safe bit-setting instruction. - */ - -/* - * A grant table comprises a packed array of grant entries in one or more - * page frames shared between Xen and a guest. - * [XEN]: This field is written by Xen and read by the sharing guest. - * [GST]: This field is written by the guest and read by Xen. - */ -struct grant_entry { - /* GTF_xxx: various type and flag information. [XEN,GST] */ - uint16_t flags; - /* The domain being granted foreign privileges. [GST] */ - domid_t domid; - /* - * GTF_permit_access: Frame that @domid is allowed to map and access. [GST] - * GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN] - */ - uint32_t frame; -}; -typedef struct grant_entry grant_entry_t; - -/* - * Type of grant entry. - * GTF_invalid: This grant entry grants no privileges. - * GTF_permit_access: Allow @domid to map/access @frame. - * GTF_accept_transfer: Allow @domid to transfer ownership of one page frame - * to this guest. Xen writes the page number to @frame. - */ -#define GTF_invalid (0U<<0) -#define GTF_permit_access (1U<<0) -#define GTF_accept_transfer (2U<<0) -#define GTF_type_mask (3U<<0) - -/* - * Subflags for GTF_permit_access. - * GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST] - * GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN] - * GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN] - * GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST] - */ -#define _GTF_readonly (2) -#define GTF_readonly (1U<<_GTF_readonly) -#define _GTF_reading (3) -#define GTF_reading (1U<<_GTF_reading) -#define _GTF_writing (4) -#define GTF_writing (1U<<_GTF_writing) -#define _GTF_PWT (5) -#define GTF_PWT (1U<<_GTF_PWT) -#define _GTF_PCD (6) -#define GTF_PCD (1U<<_GTF_PCD) -#define _GTF_PAT (7) -#define GTF_PAT (1U<<_GTF_PAT) - -/* - * Subflags for GTF_accept_transfer: - * GTF_transfer_committed: Xen sets this flag to indicate that it is committed - * to transferring ownership of a page frame. When a guest sees this flag - * it must /not/ modify the grant entry until GTF_transfer_completed is - * set by Xen. - * GTF_transfer_completed: It is safe for the guest to spin-wait on this flag - * after reading GTF_transfer_committed. Xen will always write the frame - * address, followed by ORing this flag, in a timely manner. - */ -#define _GTF_transfer_committed (2) -#define GTF_transfer_committed (1U<<_GTF_transfer_committed) -#define _GTF_transfer_completed (3) -#define GTF_transfer_completed (1U<<_GTF_transfer_completed) - - -/*********************************** - * GRANT TABLE QUERIES AND USES - */ - -/* - * Reference to a grant entry in a specified domain's grant table. - */ -typedef uint32_t grant_ref_t; - -/* - * Handle to track a mapping created via a grant reference. - */ -typedef uint32_t grant_handle_t; - -/* - * GNTTABOP_map_grant_ref: Map the grant entry (,) for access - * by devices and/or host CPUs. If successful, is a tracking number - * that must be presented later to destroy the mapping(s). On error, - * is a negative status code. - * NOTES: - * 1. If GNTMAP_device_map is specified then is the address - * via which I/O devices may access the granted frame. - * 2. If GNTMAP_host_map is specified then a mapping will be added at - * either a host virtual address in the current address space, or at - * a PTE at the specified machine address. The type of mapping to - * perform is selected through the GNTMAP_contains_pte flag, and the - * address is specified in . - * 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a - * host mapping is destroyed by other means then it is *NOT* guaranteed - * to be accounted to the correct grant reference! - */ -#define GNTTABOP_map_grant_ref 0 -struct gnttab_map_grant_ref { - /* IN parameters. */ - uint64_t host_addr; - uint32_t flags; /* GNTMAP_* */ - grant_ref_t ref; - domid_t dom; - /* OUT parameters. */ - int16_t status; /* GNTST_* */ - grant_handle_t handle; - uint64_t dev_bus_addr; -}; -typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t); - -/* - * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings - * tracked by . If or is zero, that - * field is ignored. If non-zero, they must refer to a device/host mapping - * that is tracked by - * NOTES: - * 1. The call may fail in an undefined manner if either mapping is not - * tracked by . - * 3. After executing a batch of unmaps, it is guaranteed that no stale - * mappings will remain in the device or host TLBs. - */ -#define GNTTABOP_unmap_grant_ref 1 -struct gnttab_unmap_grant_ref { - /* IN parameters. */ - uint64_t host_addr; - uint64_t dev_bus_addr; - grant_handle_t handle; - /* OUT parameters. */ - int16_t status; /* GNTST_* */ -}; -typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t); - -/* - * GNTTABOP_setup_table: Set up a grant table for comprising at least - * pages. The frame addresses are written to the . - * Only addresses are written, even if the table is larger. - * NOTES: - * 1. may be specified as DOMID_SELF. - * 2. Only a sufficiently-privileged domain may specify != DOMID_SELF. - * 3. Xen may not support more than a single grant-table page per domain. - */ -#define GNTTABOP_setup_table 2 -struct gnttab_setup_table { - /* IN parameters. */ - domid_t dom; - uint32_t nr_frames; - /* OUT parameters. */ - int16_t status; /* GNTST_* */ - XEN_GUEST_HANDLE(ulong) frame_list; -}; -typedef struct gnttab_setup_table gnttab_setup_table_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t); - -/* - * GNTTABOP_dump_table: Dump the contents of the grant table to the - * xen console. Debugging use only. - */ -#define GNTTABOP_dump_table 3 -struct gnttab_dump_table { - /* IN parameters. */ - domid_t dom; - /* OUT parameters. */ - int16_t status; /* GNTST_* */ -}; -typedef struct gnttab_dump_table gnttab_dump_table_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t); - -/* - * GNTTABOP_transfer_grant_ref: Transfer to a foreign domain. The - * foreign domain has previously registered its interest in the transfer via - * . - * - * Note that, even if the transfer fails, the specified page no longer belongs - * to the calling domain *unless* the error is GNTST_bad_page. - */ -#define GNTTABOP_transfer 4 -struct gnttab_transfer { - /* IN parameters. */ - xen_pfn_t mfn; - domid_t domid; - grant_ref_t ref; - /* OUT parameters. */ - int16_t status; -}; -typedef struct gnttab_transfer gnttab_transfer_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t); - - -/* - * GNTTABOP_copy: Hypervisor based copy - * source and destinations can be eithers MFNs or, for foreign domains, - * grant references. the foreign domain has to grant read/write access - * in its grant table. - * - * The flags specify what type source and destinations are (either MFN - * or grant reference). - * - * Note that this can also be used to copy data between two domains - * via a third party if the source and destination domains had previously - * grant appropriate access to their pages to the third party. - * - * source_offset specifies an offset in the source frame, dest_offset - * the offset in the target frame and len specifies the number of - * bytes to be copied. - */ - -#define _GNTCOPY_source_gref (0) -#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref) -#define _GNTCOPY_dest_gref (1) -#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref) - -#define GNTTABOP_copy 5 -typedef struct gnttab_copy { - /* IN parameters. */ - struct { - union { - grant_ref_t ref; - xen_pfn_t gmfn; - } u; - domid_t domid; - uint16_t offset; - } source, dest; - uint16_t len; - uint16_t flags; /* GNTCOPY_* */ - /* OUT parameters. */ - int16_t status; -} gnttab_copy_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t); - -/* - * GNTTABOP_query_size: Query the current and maximum sizes of the shared - * grant table. - * NOTES: - * 1. may be specified as DOMID_SELF. - * 2. Only a sufficiently-privileged domain may specify != DOMID_SELF. - */ -#define GNTTABOP_query_size 6 -struct gnttab_query_size { - /* IN parameters. */ - domid_t dom; - /* OUT parameters. */ - uint32_t nr_frames; - uint32_t max_nr_frames; - int16_t status; /* GNTST_* */ -}; -typedef struct gnttab_query_size gnttab_query_size_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t); - -/* - * GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings - * tracked by but atomically replace the page table entry with one - * pointing to the machine address under . will be - * redirected to the null entry. - * NOTES: - * 1. The call may fail in an undefined manner if either mapping is not - * tracked by . - * 2. After executing a batch of unmaps, it is guaranteed that no stale - * mappings will remain in the device or host TLBs. - */ -#define GNTTABOP_unmap_and_replace 7 -struct gnttab_unmap_and_replace { - /* IN parameters. */ - uint64_t host_addr; - uint64_t new_addr; - grant_handle_t handle; - /* OUT parameters. */ - int16_t status; /* GNTST_* */ -}; -typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t; -DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t); - - -/* - * Bitfield values for gnttab_map_grant_ref.flags. - */ - /* Map the grant entry for access by I/O devices. */ -#define _GNTMAP_device_map (0) -#define GNTMAP_device_map (1<<_GNTMAP_device_map) - /* Map the grant entry for access by host CPUs. */ -#define _GNTMAP_host_map (1) -#define GNTMAP_host_map (1<<_GNTMAP_host_map) - /* Accesses to the granted frame will be restricted to read-only access. */ -#define _GNTMAP_readonly (2) -#define GNTMAP_readonly (1<<_GNTMAP_readonly) - /* - * GNTMAP_host_map subflag: - * 0 => The host mapping is usable only by the guest OS. - * 1 => The host mapping is usable by guest OS + current application. - */ -#define _GNTMAP_application_map (3) -#define GNTMAP_application_map (1<<_GNTMAP_application_map) - - /* - * GNTMAP_contains_pte subflag: - * 0 => This map request contains a host virtual address. - * 1 => This map request contains the machine addess of the PTE to update. - */ -#define _GNTMAP_contains_pte (4) -#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte) - -/* - * Bits to be placed in guest kernel available PTE bits (architecture - * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set). - */ -#define _GNTMAP_guest_avail0 (16) -#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0) - -/* - * Values for error status returns. All errors are -ve. - */ -#define GNTST_okay (0) /* Normal return. */ -#define GNTST_general_error (-1) /* General undefined error. */ -#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */ -#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */ -#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */ -#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */ -#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/ -#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */ -#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */ -#define GNTST_bad_page (-9) /* Specified page was invalid for op. */ -#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */ -#define GNTST_address_too_big (-11) /* transfer page address too large. */ - -#define GNTTABOP_error_msgs { \ - "okay", \ - "undefined error", \ - "unrecognised domain id", \ - "invalid grant reference", \ - "invalid mapping handle", \ - "invalid virtual address", \ - "invalid device address", \ - "no spare translation slot in the I/O MMU", \ - "permission denied", \ - "bad page", \ - "copy arguments cross page boundary", \ - "page address size too large" \ -} - -#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/hvm/hvm_op.h b/usr/src/uts/common/xen/public/hvm/hvm_op.h deleted file mode 100644 index f0ada2d758..0000000000 --- a/usr/src/uts/common/xen/public/hvm/hvm_op.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__ -#define __XEN_PUBLIC_HVM_HVM_OP_H__ - -/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */ -#define HVMOP_set_param 0 -#define HVMOP_get_param 1 -struct xen_hvm_param { - domid_t domid; /* IN */ - uint32_t index; /* IN */ - uint64_t value; /* IN/OUT */ -}; -typedef struct xen_hvm_param xen_hvm_param_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t); - -/* Set the logical level of one of a domain's PCI INTx wires. */ -#define HVMOP_set_pci_intx_level 2 -struct xen_hvm_set_pci_intx_level { - /* Domain to be updated. */ - domid_t domid; - /* PCI INTx identification in PCI topology (domain:bus:device:intx). */ - uint8_t domain, bus, device, intx; - /* Assertion level (0 = unasserted, 1 = asserted). */ - uint8_t level; -}; -typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t); - -/* Set the logical level of one of a domain's ISA IRQ wires. */ -#define HVMOP_set_isa_irq_level 3 -struct xen_hvm_set_isa_irq_level { - /* Domain to be updated. */ - domid_t domid; - /* ISA device identification, by ISA IRQ (0-15). */ - uint8_t isa_irq; - /* Assertion level (0 = unasserted, 1 = asserted). */ - uint8_t level; -}; -typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t); - -#define HVMOP_set_pci_link_route 4 -struct xen_hvm_set_pci_link_route { - /* Domain to be updated. */ - domid_t domid; - /* PCI link identifier (0-3). */ - uint8_t link; - /* ISA IRQ (1-15), or 0 (disable link). */ - uint8_t isa_irq; -}; -typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t); - -/* Flushes all VCPU TLBs: @arg must be NULL. */ -#define HVMOP_flush_tlbs 5 - -/* Following tools-only interfaces may change in future. */ -#if defined(__XEN__) || defined(__XEN_TOOLS__) - -/* Track dirty VRAM. */ -#define HVMOP_track_dirty_vram 6 -struct xen_hvm_track_dirty_vram { - /* Domain to be tracked. */ - domid_t domid; - /* First pfn to track. */ - uint64_aligned_t first_pfn; - /* Number of pages to track. */ - uint64_aligned_t nr; - /* OUT variable. */ - /* Dirty bitmap buffer. */ - XEN_GUEST_HANDLE_64(uint8) dirty_bitmap; -}; -typedef struct xen_hvm_track_dirty_vram xen_hvm_track_dirty_vram_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t); - -/* Notify that some pages got modified by the Device Model. */ -#define HVMOP_modified_memory 7 -struct xen_hvm_modified_memory { - /* Domain to be updated. */ - domid_t domid; - /* First pfn. */ - uint64_aligned_t first_pfn; - /* Number of pages. */ - uint64_aligned_t nr; -}; -typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t); - -#define HVMOP_set_mem_type 8 -typedef enum { - HVMMEM_ram_rw, /* Normal read/write guest RAM */ - HVMMEM_ram_ro, /* Read-only; writes are discarded */ - HVMMEM_mmio_dm, /* Reads and write go to the device model */ -} hvmmem_type_t; -/* Notify that a region of memory is to be treated in a specific way. */ -struct xen_hvm_set_mem_type { - /* Domain to be updated. */ - domid_t domid; - /* Memory type */ - hvmmem_type_t hvmmem_type; - /* First pfn. */ - uint64_aligned_t first_pfn; - /* Number of pages. */ - uint64_aligned_t nr; -}; -typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t); - - -#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ - -#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ diff --git a/usr/src/uts/common/xen/public/hvm/params.h b/usr/src/uts/common/xen/public/hvm/params.h deleted file mode 100644 index 15d828fe14..0000000000 --- a/usr/src/uts/common/xen/public/hvm/params.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __XEN_PUBLIC_HVM_PARAMS_H__ -#define __XEN_PUBLIC_HVM_PARAMS_H__ - -#include "hvm_op.h" - -/* - * Parameter space for HVMOP_{set,get}_param. - */ - -/* - * How should CPU0 event-channel notifications be delivered? - * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt). - * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows: - * Domain = val[47:32], Bus = val[31:16], - * DevFn = val[15: 8], IntX = val[ 1: 0] - * If val == 0 then CPU0 event-channel notifications are not delivered. - */ -#define HVM_PARAM_CALLBACK_IRQ 0 - -/* - * These are not used by Xen. They are here for convenience of HVM-guest - * xenbus implementations. - */ -#define HVM_PARAM_STORE_PFN 1 -#define HVM_PARAM_STORE_EVTCHN 2 - -#define HVM_PARAM_PAE_ENABLED 4 - -#define HVM_PARAM_IOREQ_PFN 5 - -#define HVM_PARAM_BUFIOREQ_PFN 6 - -#ifdef __ia64__ - -#define HVM_PARAM_NVRAM_FD 7 -#define HVM_PARAM_VHPT_SIZE 8 -#define HVM_PARAM_BUFPIOREQ_PFN 9 - -#elif defined(__i386__) || defined(__x86_64__) - -/* Expose Viridian interfaces to this HVM guest? */ -#define HVM_PARAM_VIRIDIAN 9 - -#endif - -/* - * Set mode for virtual timers (currently x86 only): - * delay_for_missed_ticks (default): - * Do not advance a vcpu's time beyond the correct delivery time for - * interrupts that have been missed due to preemption. Deliver missed - * interrupts when the vcpu is rescheduled and advance the vcpu's virtual - * time stepwise for each one. - * no_delay_for_missed_ticks: - * As above, missed interrupts are delivered, but guest time always tracks - * wallclock (i.e., real) time while doing so. - * no_missed_ticks_pending: - * No missed interrupts are held pending. Instead, to ensure ticks are - * delivered at some non-zero rate, if we detect missed ticks then the - * internal tick alarm is not disabled if the VCPU is preempted during the - * next tick period. - * one_missed_tick_pending: - * Missed interrupts are collapsed together and delivered as one 'late tick'. - * Guest time always tracks wallclock (i.e., real) time. - */ -#define HVM_PARAM_TIMER_MODE 10 -#define HVMPTM_delay_for_missed_ticks 0 -#define HVMPTM_no_delay_for_missed_ticks 1 -#define HVMPTM_no_missed_ticks_pending 2 -#define HVMPTM_one_missed_tick_pending 3 - -/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */ -#define HVM_PARAM_HPET_ENABLED 11 - -/* Identity-map page directory used by Intel EPT when CR0.PG=0. */ -#define HVM_PARAM_IDENT_PT 12 - -/* Device Model domain, defaults to 0. */ -#define HVM_PARAM_DM_DOMAIN 13 - -/* ACPI S state: currently support S0 and S3 on x86. */ -#define HVM_PARAM_ACPI_S_STATE 14 - -/* TSS used on Intel when CR0.PE=0. */ -#define HVM_PARAM_VM86_TSS 15 - -/* Boolean: Enable aligning all periodic vpts to reduce interrupts */ -#define HVM_PARAM_VPT_ALIGN 16 - -#define HVM_NR_PARAMS 17 - -#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ diff --git a/usr/src/uts/common/xen/public/io/blkif.h b/usr/src/uts/common/xen/public/io/blkif.h deleted file mode 100644 index 3e0c5abae3..0000000000 --- a/usr/src/uts/common/xen/public/io/blkif.h +++ /dev/null @@ -1,148 +0,0 @@ -/****************************************************************************** - * blkif.h - * - * Unified block-device I/O interface for Xen guest OSes. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2003-2004, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_IO_BLKIF_H__ -#define __XEN_PUBLIC_IO_BLKIF_H__ - -#include "ring.h" -#include "../grant_table.h" - -/* - * Front->back notifications: When enqueuing a new request, sending a - * notification can be made conditional on req_event (i.e., the generic - * hold-off mechanism provided by the ring macros). Backends must set - * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()). - * - * Back->front notifications: When enqueuing a new response, sending a - * notification can be made conditional on rsp_event (i.e., the generic - * hold-off mechanism provided by the ring macros). Frontends must set - * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()). - */ - -#ifndef blkif_vdev_t -#define blkif_vdev_t uint16_t -#endif -#define blkif_sector_t uint64_t - -/* - * REQUEST CODES. - */ -#define BLKIF_OP_READ 0 -#define BLKIF_OP_WRITE 1 -/* - * Recognised only if "feature-barrier" is present in backend xenbus info. - * The "feature-barrier" node contains a boolean indicating whether barrier - * requests are likely to succeed or fail. Either way, a barrier request - * may fail at any time with BLKIF_RSP_EOPNOTSUPP if it is unsupported by - * the underlying block-device hardware. The boolean simply indicates whether - * or not it is worthwhile for the frontend to attempt barrier requests. - * If a backend does not recognise BLKIF_OP_WRITE_BARRIER, it should *not* - * create the "feature-barrier" node! - */ -#define BLKIF_OP_WRITE_BARRIER 2 -/* - * Recognised if "feature-flush-cache" is present in backend xenbus - * info. A flush will ask the underlying storage hardware to flush its - * non-volatile caches as appropriate. The "feature-flush-cache" node - * contains a boolean indicating whether flush requests are likely to - * succeed or fail. Either way, a flush request may fail at any time - * with BLKIF_RSP_EOPNOTSUPP if it is unsupported by the underlying - * block-device hardware. The boolean simply indicates whether or not it - * is worthwhile for the frontend to attempt flushes. If a backend does - * not recognise BLKIF_OP_WRITE_FLUSH_CACHE, it should *not* create the - * "feature-flush-cache" node! - */ -#define BLKIF_OP_FLUSH_DISKCACHE 3 - -/* - * Maximum scatter/gather segments per request. - * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE. - * NB. This could be 12 if the ring indexes weren't stored in the same page. - */ -#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 - -/* - * NB. first_sect and last_sect in blkif_request_segment, as well as - * sector_number in blkif_request, are always expressed in 512-byte units. - * However they must be properly aligned to the real sector size of the - * physical disk, which is reported in the "sector-size" node in the backend - * xenbus info. Also the xenbus "sectors" node is expressed in 512-byte units. - */ -struct blkif_request_segment { - grant_ref_t gref; /* reference to I/O buffer frame */ - /* @first_sect: first sector in frame to transfer (inclusive). */ - /* @last_sect: last sector in frame to transfer (inclusive). */ - uint8_t first_sect, last_sect; -}; - -struct blkif_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ - blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; -typedef struct blkif_request blkif_request_t; - -struct blkif_response { - uint64_t id; /* copied from request */ - uint8_t operation; /* copied from request */ - int16_t status; /* BLKIF_RSP_??? */ -}; -typedef struct blkif_response blkif_response_t; - -/* - * STATUS RETURN CODES. - */ - /* Operation not supported (only happens on barrier writes). */ -#define BLKIF_RSP_EOPNOTSUPP -2 - /* Operation failed for some unspecified reason (-EIO). */ -#define BLKIF_RSP_ERROR -1 - /* Operation completed successfully. */ -#define BLKIF_RSP_OKAY 0 - -/* - * Generate blkif ring structures and types. - */ - -DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); - -#define VDISK_CDROM 0x1 -#define VDISK_REMOVABLE 0x2 -#define VDISK_READONLY 0x4 - -#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/io/console.h b/usr/src/uts/common/xen/public/io/console.h deleted file mode 100644 index 4b8c01a447..0000000000 --- a/usr/src/uts/common/xen/public/io/console.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * console.h - * - * Console I/O interface for Xen guest OSes. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_IO_CONSOLE_H__ -#define __XEN_PUBLIC_IO_CONSOLE_H__ - -typedef uint32_t XENCONS_RING_IDX; - -#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1)) - -struct xencons_interface { - char in[1024]; - char out[2048]; - XENCONS_RING_IDX in_cons, in_prod; - XENCONS_RING_IDX out_cons, out_prod; -}; - -#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/io/netif.h b/usr/src/uts/common/xen/public/io/netif.h deleted file mode 100644 index fbb5c27231..0000000000 --- a/usr/src/uts/common/xen/public/io/netif.h +++ /dev/null @@ -1,205 +0,0 @@ -/****************************************************************************** - * netif.h - * - * Unified network-device I/O interface for Xen guest OSes. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2003-2004, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_IO_NETIF_H__ -#define __XEN_PUBLIC_IO_NETIF_H__ - -#include "ring.h" -#include "../grant_table.h" - -/* - * Notifications after enqueuing any type of message should be conditional on - * the appropriate req_event or rsp_event field in the shared ring. - * If the client sends notification for rx requests then it should specify - * feature 'feature-rx-notify' via xenbus. Otherwise the backend will assume - * that it cannot safely queue packets (as it may not be kicked to send them). - */ - -/* - * This is the 'wire' format for packets: - * Request 1: netif_tx_request -- NETTXF_* (any flags) - * [Request 2: netif_tx_extra] (only if request 1 has NETTXF_extra_info) - * [Request 3: netif_tx_extra] (only if request 2 has XEN_NETIF_EXTRA_MORE) - * Request 4: netif_tx_request -- NETTXF_more_data - * Request 5: netif_tx_request -- NETTXF_more_data - * ... - * Request N: netif_tx_request -- 0 - */ - -/* Protocol checksum field is blank in the packet (hardware offload)? */ -#define _NETTXF_csum_blank (0) -#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank) - -/* Packet data has been validated against protocol checksum. */ -#define _NETTXF_data_validated (1) -#define NETTXF_data_validated (1U<<_NETTXF_data_validated) - -/* Packet continues in the next request descriptor. */ -#define _NETTXF_more_data (2) -#define NETTXF_more_data (1U<<_NETTXF_more_data) - -/* Packet to be followed by extra descriptor(s). */ -#define _NETTXF_extra_info (3) -#define NETTXF_extra_info (1U<<_NETTXF_extra_info) - -struct netif_tx_request { - grant_ref_t gref; /* Reference to buffer page */ - uint16_t offset; /* Offset within buffer page */ - uint16_t flags; /* NETTXF_* */ - uint16_t id; /* Echoed in response message. */ - uint16_t size; /* Packet size in bytes. */ -}; -typedef struct netif_tx_request netif_tx_request_t; - -/* Types of netif_extra_info descriptors. */ -#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */ -#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */ -#define XEN_NETIF_EXTRA_TYPE_MCAST_ADD (2) /* u.mcast */ -#define XEN_NETIF_EXTRA_TYPE_MCAST_DEL (3) /* u.mcast */ -#define XEN_NETIF_EXTRA_TYPE_MAX (4) - -/* netif_extra_info flags. */ -#define _XEN_NETIF_EXTRA_FLAG_MORE (0) -#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) - -/* GSO types - only TCPv4 currently supported. */ -#define XEN_NETIF_GSO_TYPE_TCPV4 (1) - -/* - * This structure needs to fit within both netif_tx_request and - * netif_rx_response for compatibility. - */ -struct netif_extra_info { - uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */ - uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */ - - union { - /* - * XEN_NETIF_EXTRA_TYPE_GSO: - */ - struct { - /* - * Maximum payload size of each segment. For example, for TCP this - * is just the path MSS. - */ - uint16_t size; - - /* - * GSO type. This determines the protocol of the packet and any - * extra features required to segment the packet properly. - */ - uint8_t type; /* XEN_NETIF_GSO_TYPE_* */ - - /* Future expansion. */ - uint8_t pad; - - /* - * GSO features. This specifies any extra GSO features required - * to process this packet, such as ECN support for TCPv4. - */ - uint16_t features; /* XEN_NETIF_GSO_FEAT_* */ - } gso; - - /* - * XEN_NETIF_EXTRA_TYPE_MCAST_{ADD,DEL}: - * Backend advertises availability via 'feature-multicast-control' - * xenbus node containing value '1'. - * Frontend requests this feature by advertising - * 'request-multicast-control' xenbus node containing value '1'. - * If multicast control is requested then multicast flooding is - * disabled and the frontend must explicitly register its interest - * in multicast groups using dummy transmit requests containing - * MCAST_{ADD,DEL} extra-info fragments. - */ - struct { - uint8_t addr[6]; /* Address to add/remove. */ - } mcast; - - uint16_t pad[3]; - } u; -}; -typedef struct netif_extra_info netif_extra_info_t; - -struct netif_tx_response { - uint16_t id; - int16_t status; /* NETIF_RSP_* */ -}; -typedef struct netif_tx_response netif_tx_response_t; - -struct netif_rx_request { - uint16_t id; /* Echoed in response message. */ - grant_ref_t gref; /* Reference to incoming granted frame */ -}; -typedef struct netif_rx_request netif_rx_request_t; - -/* Packet data has been validated against protocol checksum. */ -#define _NETRXF_data_validated (0) -#define NETRXF_data_validated (1U<<_NETRXF_data_validated) - -/* Protocol checksum field is blank in the packet (hardware offload)? */ -#define _NETRXF_csum_blank (1) -#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank) - -/* Packet continues in the next request descriptor. */ -#define _NETRXF_more_data (2) -#define NETRXF_more_data (1U<<_NETRXF_more_data) - -/* Packet to be followed by extra descriptor(s). */ -#define _NETRXF_extra_info (3) -#define NETRXF_extra_info (1U<<_NETRXF_extra_info) - -struct netif_rx_response { - uint16_t id; - uint16_t offset; /* Offset in page of start of received packet */ - uint16_t flags; /* NETRXF_* */ - int16_t status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */ -}; -typedef struct netif_rx_response netif_rx_response_t; - -/* - * Generate netif ring structures and types. - */ - -DEFINE_RING_TYPES(netif_tx, struct netif_tx_request, struct netif_tx_response); -DEFINE_RING_TYPES(netif_rx, struct netif_rx_request, struct netif_rx_response); - -#define NETIF_RSP_DROPPED -2 -#define NETIF_RSP_ERROR -1 -#define NETIF_RSP_OKAY 0 -/* No response: used for auxiliary requests (e.g., netif_tx_extra). */ -#define NETIF_RSP_NULL 1 - -#endif - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/io/protocols.h b/usr/src/uts/common/xen/public/io/protocols.h deleted file mode 100644 index 77bd1bdd28..0000000000 --- a/usr/src/uts/common/xen/public/io/protocols.h +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * protocols.h - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __XEN_PROTOCOLS_H__ -#define __XEN_PROTOCOLS_H__ - -#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi" -#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi" -#define XEN_IO_PROTO_ABI_IA64 "ia64-abi" - -#if defined(__i386__) -# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32 -#elif defined(__x86_64__) -# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64 -#elif defined(__ia64__) -# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64 -#else -# error arch fixup needed here -#endif - -#endif diff --git a/usr/src/uts/common/xen/public/io/ring.h b/usr/src/uts/common/xen/public/io/ring.h deleted file mode 100644 index 3184e9169d..0000000000 --- a/usr/src/uts/common/xen/public/io/ring.h +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************** - * ring.h - * - * Shared producer-consumer ring macros. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Tim Deegan and Andrew Warfield November 2004. - */ - -#ifndef __XEN_PUBLIC_IO_RING_H__ -#define __XEN_PUBLIC_IO_RING_H__ - -#include "../xen-compat.h" - -#if __XEN_INTERFACE_VERSION__ < 0x00030208 -#define xen_mb() mb() -#define xen_rmb() rmb() -#define xen_wmb() wmb() -#endif - -typedef unsigned int RING_IDX; - -/* Round a 32-bit unsigned constant down to the nearest power of two. */ -#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1)) -#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x)) -#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x)) -#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x)) -#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x)) - -/* - * Calculate size of a shared ring, given the total available space for the - * ring and indexes (_sz), and the name tag of the request/response structure. - * A ring contains as many entries as will fit, rounded down to the nearest - * power of two (so we can mask with (size-1) to loop around). - */ -#define __CONST_RING_SIZE(_s, _sz) \ - (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \ - sizeof(((struct _s##_sring *)0)->ring[0]))) -/* - * The same for passing in an actual pointer instead of a name tag. - */ -#define __RING_SIZE(_s, _sz) \ - (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0]))) - -/* - * Macros to make the correct C datatypes for a new kind of ring. - * - * To make a new ring datatype, you need to have two message structures, - * let's say request_t, and response_t already defined. - * - * In a header where you want the ring datatype declared, you then do: - * - * DEFINE_RING_TYPES(mytag, request_t, response_t); - * - * These expand out to give you a set of types, as you can see below. - * The most important of these are: - * - * mytag_sring_t - The shared ring. - * mytag_front_ring_t - The 'front' half of the ring. - * mytag_back_ring_t - The 'back' half of the ring. - * - * To initialize a ring in your code you need to know the location and size - * of the shared memory area (PAGE_SIZE, for instance). To initialise - * the front half: - * - * mytag_front_ring_t front_ring; - * SHARED_RING_INIT((mytag_sring_t *)shared_page); - * FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE); - * - * Initializing the back follows similarly (note that only the front - * initializes the shared ring): - * - * mytag_back_ring_t back_ring; - * BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE); - */ - -#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \ - \ -/* Shared ring entry */ \ -union __name##_sring_entry { \ - __req_t req; \ - __rsp_t rsp; \ -}; \ - \ -/* Shared ring page */ \ -struct __name##_sring { \ - RING_IDX req_prod, req_event; \ - RING_IDX rsp_prod, rsp_event; \ - uint8_t pad[48]; \ - union __name##_sring_entry ring[1]; /* variable-length */ \ -}; \ - \ -/* "Front" end's private variables */ \ -struct __name##_front_ring { \ - RING_IDX req_prod_pvt; \ - RING_IDX rsp_cons; \ - unsigned int nr_ents; \ - struct __name##_sring *sring; \ -}; \ - \ -/* "Back" end's private variables */ \ -struct __name##_back_ring { \ - RING_IDX rsp_prod_pvt; \ - RING_IDX req_cons; \ - unsigned int nr_ents; \ - struct __name##_sring *sring; \ -}; \ - \ -/* Syntactic sugar */ \ -typedef struct __name##_sring __name##_sring_t; \ -typedef struct __name##_front_ring __name##_front_ring_t; \ -typedef struct __name##_back_ring __name##_back_ring_t - -/* - * Macros for manipulating rings. - * - * FRONT_RING_whatever works on the "front end" of a ring: here - * requests are pushed on to the ring and responses taken off it. - * - * BACK_RING_whatever works on the "back end" of a ring: here - * requests are taken off the ring and responses put on. - * - * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL. - * This is OK in 1-for-1 request-response situations where the - * requestor (front end) never has more than RING_SIZE()-1 - * outstanding requests. - */ - -/* Initialising empty rings */ -#define SHARED_RING_INIT(_s) do { \ - (_s)->req_prod = (_s)->rsp_prod = 0; \ - (_s)->req_event = (_s)->rsp_event = 1; \ - (void)memset((_s)->pad, 0, sizeof((_s)->pad)); \ -} while(0) - -#define FRONT_RING_INIT(_r, _s, __size) do { \ - (_r)->req_prod_pvt = 0; \ - (_r)->rsp_cons = 0; \ - (_r)->nr_ents = __RING_SIZE(_s, __size); \ - (_r)->sring = (_s); \ -} while (0) - -#define BACK_RING_INIT(_r, _s, __size) do { \ - (_r)->rsp_prod_pvt = 0; \ - (_r)->req_cons = 0; \ - (_r)->nr_ents = __RING_SIZE(_s, __size); \ - (_r)->sring = (_s); \ -} while (0) - -/* Initialize to existing shared indexes -- for recovery */ -#define FRONT_RING_ATTACH(_r, _s, __size) do { \ - (_r)->sring = (_s); \ - (_r)->req_prod_pvt = (_s)->req_prod; \ - (_r)->rsp_cons = (_s)->rsp_prod; \ - (_r)->nr_ents = __RING_SIZE(_s, __size); \ -} while (0) - -#define BACK_RING_ATTACH(_r, _s, __size) do { \ - (_r)->sring = (_s); \ - (_r)->rsp_prod_pvt = (_s)->rsp_prod; \ - (_r)->req_cons = (_s)->req_prod; \ - (_r)->nr_ents = __RING_SIZE(_s, __size); \ -} while (0) - -/* How big is this ring? */ -#define RING_SIZE(_r) \ - ((_r)->nr_ents) - -/* Number of free requests (for use on front side only). */ -#define RING_FREE_REQUESTS(_r) \ - (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons)) - -/* Test if there is an empty slot available on the front ring. - * (This is only meaningful from the front. ) - */ -#define RING_FULL(_r) \ - (RING_FREE_REQUESTS(_r) == 0) - -/* Test if there are outstanding messages to be processed on a ring. */ -#define RING_HAS_UNCONSUMED_RESPONSES(_r) \ - ((_r)->sring->rsp_prod - (_r)->rsp_cons) - -#ifdef __GNUC__ -#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \ - unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \ - unsigned int rsp = RING_SIZE(_r) - \ - ((_r)->req_cons - (_r)->rsp_prod_pvt); \ - req < rsp ? req : rsp; \ -}) -#else -/* Same as above, but without the nice GCC ({ ... }) syntax. */ -#define RING_HAS_UNCONSUMED_REQUESTS(_r) \ - ((((_r)->sring->req_prod - (_r)->req_cons) < \ - (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \ - ((_r)->sring->req_prod - (_r)->req_cons) : \ - (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) -#endif - -/* Direct access to individual ring elements, by index. */ -#define RING_GET_REQUEST(_r, _idx) \ - (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req)) - -#define RING_GET_RESPONSE(_r, _idx) \ - (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp)) - -/* Loop termination condition: Would the specified index overflow the ring? */ -#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \ - (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r)) - -#define RING_PUSH_REQUESTS(_r) do { \ - xen_wmb(); /* back sees requests /before/ updated producer index */ \ - (_r)->sring->req_prod = (_r)->req_prod_pvt; \ -} while (0) - -#define RING_PUSH_RESPONSES(_r) do { \ - xen_wmb(); /* front sees resps /before/ updated producer index */ \ - (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \ -} while (0) - -/* - * Notification hold-off (req_event and rsp_event): - * - * When queueing requests or responses on a shared ring, it may not always be - * necessary to notify the remote end. For example, if requests are in flight - * in a backend, the front may be able to queue further requests without - * notifying the back (if the back checks for new requests when it queues - * responses). - * - * When enqueuing requests or responses: - * - * Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument - * is a boolean return value. True indicates that the receiver requires an - * asynchronous notification. - * - * After dequeuing requests or responses (before sleeping the connection): - * - * Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES(). - * The second argument is a boolean return value. True indicates that there - * are pending messages on the ring (i.e., the connection should not be put - * to sleep). - * - * These macros will set the req_event/rsp_event field to trigger a - * notification on the very next message that is enqueued. If you want to - * create batches of work (i.e., only receive a notification after several - * messages have been enqueued) then you will need to create a customised - * version of the FINAL_CHECK macro in your own code, which sets the event - * field appropriately. - */ - -#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \ - RING_IDX __old = (_r)->sring->req_prod; \ - RING_IDX __new = (_r)->req_prod_pvt; \ - xen_wmb(); /* back sees requests /before/ updated producer index */ \ - (_r)->sring->req_prod = __new; \ - xen_mb(); /* back sees new requests /before/ we check req_event */ \ - (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \ - (RING_IDX)(__new - __old)); \ -} while (0) - -#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \ - RING_IDX __old = (_r)->sring->rsp_prod; \ - RING_IDX __new = (_r)->rsp_prod_pvt; \ - xen_wmb(); /* front sees resps /before/ updated producer index */ \ - (_r)->sring->rsp_prod = __new; \ - xen_mb(); /* front sees new resps /before/ we check rsp_event */ \ - (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \ - (RING_IDX)(__new - __old)); \ -} while (0) - -#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \ - (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ - if (_work_to_do) break; \ - (_r)->sring->req_event = (_r)->req_cons + 1; \ - xen_mb(); \ - (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ -} while (0) - -#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \ - (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ - if (_work_to_do) break; \ - (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \ - xen_mb(); \ - (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ -} while (0) - -#endif /* __XEN_PUBLIC_IO_RING_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/io/xenbus.h b/usr/src/uts/common/xen/public/io/xenbus.h deleted file mode 100644 index 4a053df2a8..0000000000 --- a/usr/src/uts/common/xen/public/io/xenbus.h +++ /dev/null @@ -1,80 +0,0 @@ -/***************************************************************************** - * xenbus.h - * - * Xenbus protocol details. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (C) 2005 XenSource Ltd. - */ - -#ifndef _XEN_PUBLIC_IO_XENBUS_H -#define _XEN_PUBLIC_IO_XENBUS_H - -/* - * The state of either end of the Xenbus, i.e. the current communication - * status of initialisation across the bus. States here imply nothing about - * the state of the connection between the driver and the kernel's device - * layers. - */ -enum xenbus_state { - XenbusStateUnknown = 0, - - XenbusStateInitialising = 1, - - /* - * InitWait: Finished early initialisation but waiting for information - * from the peer or hotplug scripts. - */ - XenbusStateInitWait = 2, - - /* - * Initialised: Waiting for a connection from the peer. - */ - XenbusStateInitialised = 3, - - XenbusStateConnected = 4, - - /* - * Closing: The device is being closed due to an error or an unplug event. - */ - XenbusStateClosing = 5, - - XenbusStateClosed = 6, - - /* - * Reconfiguring: The device is being reconfigured. - */ - XenbusStateReconfiguring = 7, - - XenbusStateReconfigured = 8 -}; -typedef enum xenbus_state XenbusState; - -#endif /* _XEN_PUBLIC_IO_XENBUS_H */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/io/xs_wire.h b/usr/src/uts/common/xen/public/io/xs_wire.h deleted file mode 100644 index f6a49ab6bf..0000000000 --- a/usr/src/uts/common/xen/public/io/xs_wire.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Details of the "wire" protocol between Xen Store Daemon and client - * library or guest kernel. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (C) 2005 Rusty Russell IBM Corporation - */ - -#ifndef _XS_WIRE_H -#define _XS_WIRE_H - -enum xsd_sockmsg_type -{ - XS_DEBUG, - XS_DIRECTORY, - XS_READ, - XS_GET_PERMS, - XS_WATCH, - XS_UNWATCH, - XS_TRANSACTION_START, - XS_TRANSACTION_END, - XS_INTRODUCE, - XS_RELEASE, - XS_GET_DOMAIN_PATH, - XS_WRITE, - XS_MKDIR, - XS_RM, - XS_SET_PERMS, - XS_WATCH_EVENT, - XS_ERROR, - XS_IS_DOMAIN_INTRODUCED, - XS_RESUME, - XS_SET_TARGET -}; - -#define XS_WRITE_NONE "NONE" -#define XS_WRITE_CREATE "CREATE" -#define XS_WRITE_CREATE_EXCL "CREATE|EXCL" - -/* We hand errors as strings, for portability. */ -struct xsd_errors -{ - int errnum; - const char *errstring; -}; -#define XSD_ERROR(x) { x, #x } -/* LINTED: static unused */ -static struct xsd_errors xsd_errors[] -#if defined(__GNUC__) -__attribute__((unused)) -#endif - = { - XSD_ERROR(EINVAL), - XSD_ERROR(EACCES), - XSD_ERROR(EEXIST), - XSD_ERROR(EISDIR), - XSD_ERROR(ENOENT), - XSD_ERROR(ENOMEM), - XSD_ERROR(ENOSPC), - XSD_ERROR(EIO), - XSD_ERROR(ENOTEMPTY), - XSD_ERROR(ENOSYS), - XSD_ERROR(EROFS), - XSD_ERROR(EBUSY), - XSD_ERROR(EAGAIN), - XSD_ERROR(EISCONN) -}; - -struct xsd_sockmsg -{ - uint32_t type; /* XS_??? */ - uint32_t req_id;/* Request identifier, echoed in daemon's response. */ - uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */ - uint32_t len; /* Length of data following this. */ - - /* Generally followed by nul-terminated string(s). */ -}; - -enum xs_watch_type -{ - XS_WATCH_PATH = 0, - XS_WATCH_TOKEN -}; - -/* Inter-domain shared memory communications. */ -#define XENSTORE_RING_SIZE 1024 -typedef uint32_t XENSTORE_RING_IDX; -#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1)) -struct xenstore_domain_interface { - char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */ - char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */ - XENSTORE_RING_IDX req_cons, req_prod; - XENSTORE_RING_IDX rsp_cons, rsp_prod; -}; - -/* Violating this is very bad. See docs/misc/xenstore.txt. */ -#define XENSTORE_PAYLOAD_MAX 4096 - -/* Violating these just gets you an error back */ -#define XENSTORE_ABS_PATH_MAX 3072 -#define XENSTORE_REL_PATH_MAX 2048 - -#endif /* _XS_WIRE_H */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/memory.h b/usr/src/uts/common/xen/public/memory.h deleted file mode 100644 index ba4051e95f..0000000000 --- a/usr/src/uts/common/xen/public/memory.h +++ /dev/null @@ -1,290 +0,0 @@ -/****************************************************************************** - * memory.h - * - * Memory reservation and information. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_MEMORY_H__ -#define __XEN_PUBLIC_MEMORY_H__ - -/* - * Increase or decrease the specified domain's memory reservation. Returns the - * number of extents successfully allocated or freed. - * arg == addr of struct xen_memory_reservation. - */ -#define XENMEM_increase_reservation 0 -#define XENMEM_decrease_reservation 1 -#define XENMEM_populate_physmap 6 - -#if __XEN_INTERFACE_VERSION__ >= 0x00030209 -/* - * Maximum # bits addressable by the user of the allocated region (e.g., I/O - * devices often have a 32-bit limitation even in 64-bit systems). If zero - * then the user has no addressing restriction. This field is not used by - * XENMEM_decrease_reservation. - */ -#define XENMEMF_address_bits(x) (x) -#define XENMEMF_get_address_bits(x) ((x) & 0xffu) -/* NUMA node to allocate from. */ -#define XENMEMF_node(x) (((x) + 1) << 8) -#define XENMEMF_get_node(x) ((((x) >> 8) - 1) & 0xffu) -/* Flag to populate physmap with populate-on-demand entries */ -#define XENMEMF_populate_on_demand (1<<16) -#endif - -struct xen_memory_reservation { - - /* - * XENMEM_increase_reservation: - * OUT: MFN (*not* GMFN) bases of extents that were allocated - * XENMEM_decrease_reservation: - * IN: GMFN bases of extents to free - * XENMEM_populate_physmap: - * IN: GPFN bases of extents to populate with memory - * OUT: GMFN bases of extents that were allocated - * (NB. This command also updates the mach_to_phys translation table) - */ - XEN_GUEST_HANDLE(xen_pfn_t) extent_start; - - /* Number of extents, and size/alignment of each (2^extent_order pages). */ - xen_ulong_t nr_extents; - unsigned int extent_order; - -#if __XEN_INTERFACE_VERSION__ >= 0x00030209 - /* XENMEMF flags. */ - unsigned int mem_flags; -#else - unsigned int address_bits; -#endif - - /* - * Domain whose reservation is being changed. - * Unprivileged domains can specify only DOMID_SELF. - */ - domid_t domid; -}; -typedef struct xen_memory_reservation xen_memory_reservation_t; -DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t); - -/* - * An atomic exchange of memory pages. If return code is zero then - * @out.extent_list provides GMFNs of the newly-allocated memory. - * Returns zero on complete success, otherwise a negative error code. - * On complete success then always @nr_exchanged == @in.nr_extents. - * On partial success @nr_exchanged indicates how much work was done. - */ -#define XENMEM_exchange 11 -struct xen_memory_exchange { - /* - * [IN] Details of memory extents to be exchanged (GMFN bases). - * Note that @in.address_bits is ignored and unused. - */ - struct xen_memory_reservation in; - - /* - * [IN/OUT] Details of new memory extents. - * We require that: - * 1. @in.domid == @out.domid - * 2. @in.nr_extents << @in.extent_order == - * @out.nr_extents << @out.extent_order - * 3. @in.extent_start and @out.extent_start lists must not overlap - * 4. @out.extent_start lists GPFN bases to be populated - * 5. @out.extent_start is overwritten with allocated GMFN bases - */ - struct xen_memory_reservation out; - - /* - * [OUT] Number of input extents that were successfully exchanged: - * 1. The first @nr_exchanged input extents were successfully - * deallocated. - * 2. The corresponding first entries in the output extent list correctly - * indicate the GMFNs that were successfully exchanged. - * 3. All other input and output extents are untouched. - * 4. If not all input exents are exchanged then the return code of this - * command will be non-zero. - * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER! - */ - xen_ulong_t nr_exchanged; -}; -typedef struct xen_memory_exchange xen_memory_exchange_t; -DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); - -/* - * Returns the maximum machine frame number of mapped RAM in this system. - * This command always succeeds (it never returns an error code). - * arg == NULL. - */ -#define XENMEM_maximum_ram_page 2 - -/* - * Returns the current or maximum memory reservation, in pages, of the - * specified domain (may be DOMID_SELF). Returns -ve errcode on failure. - * arg == addr of domid_t. - */ -#define XENMEM_current_reservation 3 -#define XENMEM_maximum_reservation 4 - -/* - * Returns the maximum GPFN in use by the guest, or -ve errcode on failure. - */ -#define XENMEM_maximum_gpfn 14 - -/* - * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys - * mapping table. Architectures which do not have a m2p table do not implement - * this command. - * arg == addr of xen_machphys_mfn_list_t. - */ -#define XENMEM_machphys_mfn_list 5 -struct xen_machphys_mfn_list { - /* - * Size of the 'extent_start' array. Fewer entries will be filled if the - * machphys table is smaller than max_extents * 2MB. - */ - unsigned int max_extents; - - /* - * Pointer to buffer to fill with list of extent starts. If there are - * any large discontiguities in the machine address space, 2MB gaps in - * the machphys table will be represented by an MFN base of zero. - */ - XEN_GUEST_HANDLE(xen_pfn_t) extent_start; - - /* - * Number of extents written to the above array. This will be smaller - * than 'max_extents' if the machphys table is smaller than max_e * 2MB. - */ - unsigned int nr_extents; -}; -typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t; -DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t); - -/* - * Returns the location in virtual address space of the machine_to_phys - * mapping table. Architectures which do not have a m2p table, or which do not - * map it by default into guest address space, do not implement this command. - * arg == addr of xen_machphys_mapping_t. - */ -#define XENMEM_machphys_mapping 12 -struct xen_machphys_mapping { - xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */ - xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */ -}; -typedef struct xen_machphys_mapping xen_machphys_mapping_t; -DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t); - -/* - * Sets the GPFN at which a particular page appears in the specified guest's - * pseudophysical address space. - * arg == addr of xen_add_to_physmap_t. - */ -#define XENMEM_add_to_physmap 7 -struct xen_add_to_physmap { - /* Which domain to change the mapping for. */ - domid_t domid; - - /* Source mapping space. */ -#define XENMAPSPACE_shared_info 0 /* shared info page */ -#define XENMAPSPACE_grant_table 1 /* grant table page */ -#define XENMAPSPACE_gmfn 2 /* GMFN */ - unsigned int space; - - /* Index into source mapping space. */ - xen_ulong_t idx; - - /* GPFN where the source mapping page should appear. */ - xen_pfn_t gpfn; -}; -typedef struct xen_add_to_physmap xen_add_to_physmap_t; -DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t); - -/*** REMOVED ***/ -/*#define XENMEM_translate_gpfn_list 8*/ - -/* - * Returns the pseudo-physical memory map as it was when the domain - * was started (specified by XENMEM_set_memory_map). - * arg == addr of xen_memory_map_t. - */ -#define XENMEM_memory_map 9 -struct xen_memory_map { - /* - * On call the number of entries which can be stored in buffer. On - * return the number of entries which have been stored in - * buffer. - */ - unsigned int nr_entries; - - /* - * Entries in the buffer are in the same format as returned by the - * BIOS INT 0x15 EAX=0xE820 call. - */ - XEN_GUEST_HANDLE(void) buffer; -}; -typedef struct xen_memory_map xen_memory_map_t; -DEFINE_XEN_GUEST_HANDLE(xen_memory_map_t); - -/* - * Returns the real physical memory map. Passes the same structure as - * XENMEM_memory_map. - * arg == addr of xen_memory_map_t. - */ -#define XENMEM_machine_memory_map 10 - -/* - * Set the pseudo-physical memory map of a domain, as returned by - * XENMEM_memory_map. - * arg == addr of xen_foreign_memory_map_t. - */ -#define XENMEM_set_memory_map 13 -struct xen_foreign_memory_map { - domid_t domid; - struct xen_memory_map map; -}; -typedef struct xen_foreign_memory_map xen_foreign_memory_map_t; -DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t); - -#define XENMEM_set_pod_target 16 -#define XENMEM_get_pod_target 17 -struct xen_pod_target { - /* IN */ - uint64_t target_pages; - /* OUT */ - uint64_t tot_pages; - uint64_t pod_cache_pages; - uint64_t pod_entries; - /* IN */ - domid_t domid; -}; -typedef struct xen_pod_target xen_pod_target_t; -#endif /* __XEN_PUBLIC_MEMORY_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/nmi.h b/usr/src/uts/common/xen/public/nmi.h deleted file mode 100644 index b2b84018a3..0000000000 --- a/usr/src/uts/common/xen/public/nmi.h +++ /dev/null @@ -1,78 +0,0 @@ -/****************************************************************************** - * nmi.h - * - * NMI callback registration and reason codes. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_NMI_H__ -#define __XEN_PUBLIC_NMI_H__ - -/* - * NMI reason codes: - * Currently these are x86-specific, stored in arch_shared_info.nmi_reason. - */ - /* I/O-check error reported via ISA port 0x61, bit 6. */ -#define _XEN_NMIREASON_io_error 0 -#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error) - /* Parity error reported via ISA port 0x61, bit 7. */ -#define _XEN_NMIREASON_parity_error 1 -#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error) - /* Unknown hardware-generated NMI. */ -#define _XEN_NMIREASON_unknown 2 -#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown) - -/* - * long nmi_op(unsigned int cmd, void *arg) - * NB. All ops return zero on success, else a negative error code. - */ - -/* - * Register NMI callback for this (calling) VCPU. Currently this only makes - * sense for domain 0, vcpu 0. All other callers will be returned EINVAL. - * arg == pointer to xennmi_callback structure. - */ -#define XENNMI_register_callback 0 -struct xennmi_callback { - unsigned long handler_address; - unsigned long pad; -}; -typedef struct xennmi_callback xennmi_callback_t; -DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t); - -/* - * Deregister NMI callback for this (calling) VCPU. - * arg == NULL. - */ -#define XENNMI_unregister_callback 1 - -#endif /* __XEN_PUBLIC_NMI_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/physdev.h b/usr/src/uts/common/xen/public/physdev.h deleted file mode 100644 index cb7e4d469b..0000000000 --- a/usr/src/uts/common/xen/public/physdev.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __XEN_PUBLIC_PHYSDEV_H__ -#define __XEN_PUBLIC_PHYSDEV_H__ - -/* - * Prototype for this hypercall is: - * int physdev_op(int cmd, void *args) - * @cmd == PHYSDEVOP_??? (physdev operation). - * @args == Operation-specific extra arguments (NULL if none). - */ - -/* - * Notify end-of-interrupt (EOI) for the specified IRQ. - * @arg == pointer to physdev_eoi structure. - */ -#define PHYSDEVOP_eoi 12 -struct physdev_eoi { - /* IN */ - uint32_t irq; -}; -typedef struct physdev_eoi physdev_eoi_t; -DEFINE_XEN_GUEST_HANDLE(physdev_eoi_t); - -/* - * Register a shared page for the hypervisor to indicate whether the guest - * must issue PHYSDEVOP_eoi. The semantics of PHYSDEVOP_eoi change slightly - * once the guest used this function in that the associated event channel - * will automatically get unmasked. The page registered is used as a bit - * array indexed by Xen's PIRQ value. - */ -#define PHYSDEVOP_pirq_eoi_gmfn 17 -struct physdev_pirq_eoi_gmfn { - /* IN */ - xen_pfn_t gmfn; -}; -typedef struct physdev_pirq_eoi_gmfn physdev_pirq_eoi_gmfn_t; -DEFINE_XEN_GUEST_HANDLE(physdev_pirq_eoi_gmfn_t); - -/* - * Query the status of an IRQ line. - * @arg == pointer to physdev_irq_status_query structure. - */ -#define PHYSDEVOP_irq_status_query 5 -struct physdev_irq_status_query { - /* IN */ - uint32_t irq; - /* OUT */ - uint32_t flags; /* XENIRQSTAT_* */ -}; -typedef struct physdev_irq_status_query physdev_irq_status_query_t; -DEFINE_XEN_GUEST_HANDLE(physdev_irq_status_query_t); - -/* Need to call PHYSDEVOP_eoi when the IRQ has been serviced? */ -#define _XENIRQSTAT_needs_eoi (0) -#define XENIRQSTAT_needs_eoi (1U<<_XENIRQSTAT_needs_eoi) - -/* IRQ shared by multiple guests? */ -#define _XENIRQSTAT_shared (1) -#define XENIRQSTAT_shared (1U<<_XENIRQSTAT_shared) - -/* - * Set the current VCPU's I/O privilege level. - * @arg == pointer to physdev_set_iopl structure. - */ -#define PHYSDEVOP_set_iopl 6 -struct physdev_set_iopl { - /* IN */ - uint32_t iopl; -}; -typedef struct physdev_set_iopl physdev_set_iopl_t; -DEFINE_XEN_GUEST_HANDLE(physdev_set_iopl_t); - -/* - * Set the current VCPU's I/O-port permissions bitmap. - * @arg == pointer to physdev_set_iobitmap structure. - */ -#define PHYSDEVOP_set_iobitmap 7 -struct physdev_set_iobitmap { - /* IN */ -#if __XEN_INTERFACE_VERSION__ >= 0x00030205 - XEN_GUEST_HANDLE(uint8) bitmap; -#else - uint8_t *bitmap; -#endif - uint32_t nr_ports; -}; -typedef struct physdev_set_iobitmap physdev_set_iobitmap_t; -DEFINE_XEN_GUEST_HANDLE(physdev_set_iobitmap_t); - -/* - * Read or write an IO-APIC register. - * @arg == pointer to physdev_apic structure. - */ -#define PHYSDEVOP_apic_read 8 -#define PHYSDEVOP_apic_write 9 -struct physdev_apic { - /* IN */ - unsigned long apic_physbase; - uint32_t reg; - /* IN or OUT */ - uint32_t value; -}; -typedef struct physdev_apic physdev_apic_t; -DEFINE_XEN_GUEST_HANDLE(physdev_apic_t); - -/* - * Allocate or free a physical upcall vector for the specified IRQ line. - * @arg == pointer to physdev_irq structure. - */ -#define PHYSDEVOP_alloc_irq_vector 10 -#define PHYSDEVOP_free_irq_vector 11 -struct physdev_irq { - /* IN */ - uint32_t irq; - /* IN or OUT */ - uint32_t vector; -}; -typedef struct physdev_irq physdev_irq_t; -DEFINE_XEN_GUEST_HANDLE(physdev_irq_t); - -#define MAP_PIRQ_TYPE_MSI 0x0 -#define MAP_PIRQ_TYPE_GSI 0x1 -#define MAP_PIRQ_TYPE_UNKNOWN 0x2 - -#define PHYSDEVOP_map_pirq 13 -struct physdev_map_pirq { - domid_t domid; - /* IN */ - int type; - /* IN */ - int index; - /* IN or OUT */ - int pirq; - /* IN */ - int bus; - /* IN */ - int devfn; - /* IN */ - int entry_nr; - /* IN */ - uint64_t table_base; -}; -typedef struct physdev_map_pirq physdev_map_pirq_t; -DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t); - -#define PHYSDEVOP_unmap_pirq 14 -struct physdev_unmap_pirq { - domid_t domid; - /* IN */ - int pirq; -}; - -typedef struct physdev_unmap_pirq physdev_unmap_pirq_t; -DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t); - -#define PHYSDEVOP_manage_pci_add 15 -#define PHYSDEVOP_manage_pci_remove 16 -struct physdev_manage_pci { - /* IN */ - uint8_t bus; - uint8_t devfn; -}; - -typedef struct physdev_manage_pci physdev_manage_pci_t; -DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_t); - -#define PHYSDEVOP_restore_msi 19 -struct physdev_restore_msi { - /* IN */ - uint8_t bus; - uint8_t devfn; -}; -typedef struct physdev_restore_msi physdev_restore_msi_t; -DEFINE_XEN_GUEST_HANDLE(physdev_restore_msi_t); - -#define PHYSDEVOP_manage_pci_add_ext 20 -struct physdev_manage_pci_ext { - /* IN */ - uint8_t bus; - uint8_t devfn; - unsigned is_extfn; - unsigned is_virtfn; - struct { - uint8_t bus; - uint8_t devfn; - } physfn; -}; - -typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t; -DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t); - -/* - * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() - * hypercall since 0x00030202. - */ -struct physdev_op { - uint32_t cmd; - union { - struct physdev_irq_status_query irq_status_query; - struct physdev_set_iopl set_iopl; - struct physdev_set_iobitmap set_iobitmap; - struct physdev_apic apic_op; - struct physdev_irq irq_op; - } u; -}; -typedef struct physdev_op physdev_op_t; -DEFINE_XEN_GUEST_HANDLE(physdev_op_t); - -/* - * Notify that some PIRQ-bound event channels have been unmasked. - * ** This command is obsolete since interface version 0x00030202 and is ** - * ** unsupported by newer versions of Xen. ** - */ -#define PHYSDEVOP_IRQ_UNMASK_NOTIFY 4 - -/* - * These all-capitals physdev operation names are superceded by the new names - * (defined above) since interface version 0x00030202. - */ -#define PHYSDEVOP_IRQ_STATUS_QUERY PHYSDEVOP_irq_status_query -#define PHYSDEVOP_SET_IOPL PHYSDEVOP_set_iopl -#define PHYSDEVOP_SET_IOBITMAP PHYSDEVOP_set_iobitmap -#define PHYSDEVOP_APIC_READ PHYSDEVOP_apic_read -#define PHYSDEVOP_APIC_WRITE PHYSDEVOP_apic_write -#define PHYSDEVOP_ASSIGN_VECTOR PHYSDEVOP_alloc_irq_vector -#define PHYSDEVOP_FREE_VECTOR PHYSDEVOP_free_irq_vector -#define PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY XENIRQSTAT_needs_eoi -#define PHYSDEVOP_IRQ_SHARED XENIRQSTAT_shared - -#endif /* __XEN_PUBLIC_PHYSDEV_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/platform.h b/usr/src/uts/common/xen/public/platform.h deleted file mode 100644 index e618210ea5..0000000000 --- a/usr/src/uts/common/xen/public/platform.h +++ /dev/null @@ -1,354 +0,0 @@ -/****************************************************************************** - * platform.h - * - * Hardware platform operations. Intended for use by domain-0 kernel. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2002-2006, K Fraser - */ - -#ifndef __XEN_PUBLIC_PLATFORM_H__ -#define __XEN_PUBLIC_PLATFORM_H__ - -#include "xen.h" - -#define XENPF_INTERFACE_VERSION 0x03000001 - -/* - * Set clock such that it would read after 00:00:00 UTC, - * 1 January, 1970 if the current system time was . - */ -#define XENPF_settime 17 -struct xenpf_settime { - /* IN variables. */ - uint32_t secs; - uint32_t nsecs; - uint64_t system_time; -}; -typedef struct xenpf_settime xenpf_settime_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t); - -/* - * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type. - * On x86, @type is an architecture-defined MTRR memory type. - * On success, returns the MTRR that was used (@reg) and a handle that can - * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting. - * (x86-specific). - */ -#define XENPF_add_memtype 31 -struct xenpf_add_memtype { - /* IN variables. */ - xen_pfn_t mfn; - uint64_t nr_mfns; - uint32_t type; - /* OUT variables. */ - uint32_t handle; - uint32_t reg; -}; -typedef struct xenpf_add_memtype xenpf_add_memtype_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t); - -/* - * Tear down an existing memory-range type. If @handle is remembered then it - * should be passed in to accurately tear down the correct setting (in case - * of overlapping memory regions with differing types). If it is not known - * then @handle should be set to zero. In all cases @reg must be set. - * (x86-specific). - */ -#define XENPF_del_memtype 32 -struct xenpf_del_memtype { - /* IN variables. */ - uint32_t handle; - uint32_t reg; -}; -typedef struct xenpf_del_memtype xenpf_del_memtype_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t); - -/* Read current type of an MTRR (x86-specific). */ -#define XENPF_read_memtype 33 -struct xenpf_read_memtype { - /* IN variables. */ - uint32_t reg; - /* OUT variables. */ - xen_pfn_t mfn; - uint64_t nr_mfns; - uint32_t type; -}; -typedef struct xenpf_read_memtype xenpf_read_memtype_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t); - -#define XENPF_microcode_update 35 -struct xenpf_microcode_update { - /* IN variables. */ - XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */ - uint32_t length; /* Length of microcode data. */ -}; -typedef struct xenpf_microcode_update xenpf_microcode_update_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t); - -#define XENPF_platform_quirk 39 -#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */ -#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */ -#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */ -struct xenpf_platform_quirk { - /* IN variables. */ - uint32_t quirk_id; -}; -typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); - -#define XENPF_firmware_info 50 -#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ -#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ -#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ -struct xenpf_firmware_info { - /* IN variables. */ - uint32_t type; - uint32_t index; - /* OUT variables. */ - union { - struct { - /* Int13, Fn48: Check Extensions Present. */ - uint8_t device; /* %dl: bios device number */ - uint8_t version; /* %ah: major version */ - uint16_t interface_support; /* %cx: support bitmap */ - /* Int13, Fn08: Legacy Get Device Parameters. */ - uint16_t legacy_max_cylinder; /* %cl[7:6]:%ch: max cyl # */ - uint8_t legacy_max_head; /* %dh: max head # */ - uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector # */ - /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */ - /* NB. First uint16_t of buffer must be set to buffer size. */ - XEN_GUEST_HANDLE(void) edd_params; - } disk_info; /* XEN_FW_DISK_INFO */ - struct { - uint8_t device; /* bios device number */ - uint32_t mbr_signature; /* offset 0x1b8 in mbr */ - } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */ - struct { - /* Int10, AX=4F15: Get EDID info. */ - uint8_t capabilities; - uint8_t edid_transfer_time; - /* must refer to 128-byte buffer */ - XEN_GUEST_HANDLE(uint8) edid; - } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ - } u; -}; -typedef struct xenpf_firmware_info xenpf_firmware_info_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t); - -#define XENPF_enter_acpi_sleep 51 -struct xenpf_enter_acpi_sleep { - /* IN variables */ - uint16_t pm1a_cnt_val; /* PM1a control value. */ - uint16_t pm1b_cnt_val; /* PM1b control value. */ - uint32_t sleep_state; /* Which state to enter (Sn). */ - uint32_t flags; /* Must be zero. */ -}; -typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t); - -#define XENPF_change_freq 52 -struct xenpf_change_freq { - /* IN variables */ - uint32_t flags; /* Must be zero. */ - uint32_t cpu; /* Physical cpu. */ - uint64_t freq; /* New frequency (Hz). */ -}; -typedef struct xenpf_change_freq xenpf_change_freq_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t); - -/* - * Get idle times (nanoseconds since boot) for physical CPUs specified in the - * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is - * indexed by CPU number; only entries with the corresponding @cpumap_bitmap - * bit set are written to. On return, @cpumap_bitmap is modified so that any - * non-existent CPUs are cleared. Such CPUs have their @idletime array entry - * cleared. - */ -#define XENPF_getidletime 53 -struct xenpf_getidletime { - /* IN/OUT variables */ - /* IN: CPUs to interrogate; OUT: subset of IN which are present */ - XEN_GUEST_HANDLE(uint8) cpumap_bitmap; - /* IN variables */ - /* Size of cpumap bitmap. */ - uint32_t cpumap_nr_cpus; - /* Must be indexable for every cpu in cpumap_bitmap. */ - XEN_GUEST_HANDLE(uint64) idletime; - /* OUT variables */ - /* System time when the idletime snapshots were taken. */ - uint64_t now; -}; -typedef struct xenpf_getidletime xenpf_getidletime_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t); - -#define XENPF_set_processor_pminfo 54 - -/* ability bits */ -#define XEN_PROCESSOR_PM_CX 1 -#define XEN_PROCESSOR_PM_PX 2 -#define XEN_PROCESSOR_PM_TX 4 - -/* cmd type */ -#define XEN_PM_CX 0 -#define XEN_PM_PX 1 -#define XEN_PM_TX 2 - -/* Px sub info type */ -#define XEN_PX_PCT 1 -#define XEN_PX_PSS 2 -#define XEN_PX_PPC 4 -#define XEN_PX_PSD 8 - -struct xen_power_register { - uint32_t space_id; - uint32_t bit_width; - uint32_t bit_offset; - uint32_t access_size; - uint64_t address; -}; - -struct xen_processor_csd { - uint32_t domain; /* domain number of one dependent group */ - uint32_t coord_type; /* coordination type */ - uint32_t num; /* number of processors in same domain */ -}; -typedef struct xen_processor_csd xen_processor_csd_t; -DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t); - -struct xen_processor_cx { - struct xen_power_register reg; /* GAS for Cx trigger register */ - uint8_t type; /* cstate value, c0: 0, c1: 1, ... */ - uint32_t latency; /* worst latency (ms) to enter/exit this cstate */ - uint32_t power; /* average power consumption(mW) */ - uint32_t dpcnt; /* number of dependency entries */ - XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */ -}; -typedef struct xen_processor_cx xen_processor_cx_t; -DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t); - -struct xen_processor_flags { - uint32_t bm_control:1; - uint32_t bm_check:1; - uint32_t has_cst:1; - uint32_t power_setup_done:1; - uint32_t bm_rld_set:1; -}; - -struct xen_processor_power { - uint32_t count; /* number of C state entries in array below */ - struct xen_processor_flags flags; /* global flags of this processor */ - XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */ -}; - -struct xen_pct_register { - uint8_t descriptor; - uint16_t length; - uint8_t space_id; - uint8_t bit_width; - uint8_t bit_offset; - uint8_t reserved; - uint64_t address; -}; - -struct xen_processor_px { - uint64_t core_frequency; /* megahertz */ - uint64_t power; /* milliWatts */ - uint64_t transition_latency; /* microseconds */ - uint64_t bus_master_latency; /* microseconds */ - uint64_t control; /* control value */ - uint64_t status; /* success indicator */ -}; -typedef struct xen_processor_px xen_processor_px_t; -DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t); - -struct xen_psd_package { - uint64_t num_entries; - uint64_t revision; - uint64_t domain; - uint64_t coord_type; - uint64_t num_processors; -}; - -struct xen_processor_performance { - uint32_t flags; /* flag for Px sub info type */ - uint32_t platform_limit; /* Platform limitation on freq usage */ - struct xen_pct_register control_register; - struct xen_pct_register status_register; - uint32_t state_count; /* total available performance states */ - XEN_GUEST_HANDLE(xen_processor_px_t) states; - struct xen_psd_package domain_info; - uint32_t shared_type; /* coordination type of this processor */ -}; -typedef struct xen_processor_performance xen_processor_performance_t; -DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t); - -struct xenpf_set_processor_pminfo { - /* IN variables */ - uint32_t id; /* ACPI CPU ID */ - uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */ - union { - struct xen_processor_power power;/* Cx: _CST/_CSD */ - struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */ - } u; -}; -typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t); - -#define XENPF_panic_init 40 -struct xenpf_panic_init { - unsigned long panic_addr; -}; -typedef struct xenpf_panic_init xenpf_panic_init_t; -DEFINE_XEN_GUEST_HANDLE(xenpf_panic_init_t); - -struct xen_platform_op { - uint32_t cmd; - uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ - union { - struct xenpf_settime settime; - struct xenpf_add_memtype add_memtype; - struct xenpf_del_memtype del_memtype; - struct xenpf_read_memtype read_memtype; - struct xenpf_microcode_update microcode; - struct xenpf_platform_quirk platform_quirk; - struct xenpf_firmware_info firmware_info; - struct xenpf_enter_acpi_sleep enter_acpi_sleep; - struct xenpf_change_freq change_freq; - struct xenpf_getidletime getidletime; - struct xenpf_set_processor_pminfo set_pminfo; - struct xenpf_panic_init panic_init; - uint8_t pad[128]; - } u; -}; -typedef struct xen_platform_op xen_platform_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t); - -#endif /* __XEN_PUBLIC_PLATFORM_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/sched.h b/usr/src/uts/common/xen/public/sched.h deleted file mode 100644 index 2227a95be6..0000000000 --- a/usr/src/uts/common/xen/public/sched.h +++ /dev/null @@ -1,121 +0,0 @@ -/****************************************************************************** - * sched.h - * - * Scheduler state interactions - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_SCHED_H__ -#define __XEN_PUBLIC_SCHED_H__ - -#include "event_channel.h" - -/* - * The prototype for this hypercall is: - * long sched_op(int cmd, void *arg) - * @cmd == SCHEDOP_??? (scheduler operation). - * @arg == Operation-specific extra argument(s), as described below. - * - * Versions of Xen prior to 3.0.2 provided only the following legacy version - * of this hypercall, supporting only the commands yield, block and shutdown: - * long sched_op(int cmd, unsigned long arg) - * @cmd == SCHEDOP_??? (scheduler operation). - * @arg == 0 (SCHEDOP_yield and SCHEDOP_block) - * == SHUTDOWN_* code (SCHEDOP_shutdown) - * This legacy version is available to new guests as sched_op_compat(). - */ - -/* - * Voluntarily yield the CPU. - * @arg == NULL. - */ -#define SCHEDOP_yield 0 - -/* - * Block execution of this VCPU until an event is received for processing. - * If called with event upcalls masked, this operation will atomically - * reenable event delivery and check for pending events before blocking the - * VCPU. This avoids a "wakeup waiting" race. - * @arg == NULL. - */ -#define SCHEDOP_block 1 - -/* - * Halt execution of this domain (all VCPUs) and notify the system controller. - * @arg == pointer to sched_shutdown structure. - */ -#define SCHEDOP_shutdown 2 -struct sched_shutdown { - unsigned int reason; /* SHUTDOWN_* */ -}; -typedef struct sched_shutdown sched_shutdown_t; -DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t); - -/* - * Poll a set of event-channel ports. Return when one or more are pending. An - * optional timeout may be specified. - * @arg == pointer to sched_poll structure. - */ -#define SCHEDOP_poll 3 -struct sched_poll { - XEN_GUEST_HANDLE(evtchn_port_t) ports; - unsigned int nr_ports; - uint64_t timeout; -}; -typedef struct sched_poll sched_poll_t; -DEFINE_XEN_GUEST_HANDLE(sched_poll_t); - -/* - * Declare a shutdown for another domain. The main use of this function is - * in interpreting shutdown requests and reasons for fully-virtualized - * domains. A para-virtualized domain may use SCHEDOP_shutdown directly. - * @arg == pointer to sched_remote_shutdown structure. - */ -#define SCHEDOP_remote_shutdown 4 -struct sched_remote_shutdown { - domid_t domain_id; /* Remote domain ID */ - unsigned int reason; /* SHUTDOWN_xxx reason */ -}; -typedef struct sched_remote_shutdown sched_remote_shutdown_t; -DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t); - -/* - * Reason codes for SCHEDOP_shutdown. These may be interpreted by control - * software to determine the appropriate action. For the most part, Xen does - * not care about the shutdown code. - */ -#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */ -#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */ -#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */ -#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */ - -#endif /* __XEN_PUBLIC_SCHED_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/sysctl.h b/usr/src/uts/common/xen/public/sysctl.h deleted file mode 100644 index 33586ed4eb..0000000000 --- a/usr/src/uts/common/xen/public/sysctl.h +++ /dev/null @@ -1,490 +0,0 @@ -/****************************************************************************** - * sysctl.h - * - * System management operations. For use by node control stack. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2002-2006, K Fraser - */ - -#ifndef __XEN_PUBLIC_SYSCTL_H__ -#define __XEN_PUBLIC_SYSCTL_H__ - -#if !defined(__XEN__) && !defined(__XEN_TOOLS__) -#error "sysctl operations are intended for use by node control tools only" -#endif - -#include "xen.h" -#include "domctl.h" - -#define XEN_SYSCTL_INTERFACE_VERSION 0x00000006 - -/* - * Read console content from Xen buffer ring. - */ -#define XEN_SYSCTL_readconsole 1 -struct xen_sysctl_readconsole { - /* IN: Non-zero -> clear after reading. */ - uint8_t clear; - /* IN: Non-zero -> start index specified by @index field. */ - uint8_t incremental; - uint8_t pad0, pad1; - /* - * IN: Start index for consuming from ring buffer (if @incremental); - * OUT: End index after consuming from ring buffer. - */ - uint32_t index; - /* IN: Virtual address to write console data. */ - XEN_GUEST_HANDLE_64(char) buffer; - /* IN: Size of buffer; OUT: Bytes written to buffer. */ - uint32_t count; -}; -typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t); - -/* Get trace buffers machine base address */ -#define XEN_SYSCTL_tbuf_op 2 -struct xen_sysctl_tbuf_op { - /* IN variables */ -#define XEN_SYSCTL_TBUFOP_get_info 0 -#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1 -#define XEN_SYSCTL_TBUFOP_set_evt_mask 2 -#define XEN_SYSCTL_TBUFOP_set_size 3 -#define XEN_SYSCTL_TBUFOP_enable 4 -#define XEN_SYSCTL_TBUFOP_disable 5 - uint32_t cmd; - /* IN/OUT variables */ - struct xenctl_cpumap cpu_mask; - uint32_t evt_mask; - /* OUT variables */ - uint64_aligned_t buffer_mfn; - uint32_t size; -}; -typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t); - -/* - * Get physical information about the host machine - */ -#define XEN_SYSCTL_physinfo 3 - /* (x86) The platform supports HVM guests. */ -#define _XEN_SYSCTL_PHYSCAP_hvm 0 -#define XEN_SYSCTL_PHYSCAP_hvm (1u<<_XEN_SYSCTL_PHYSCAP_hvm) - /* (x86) The platform supports HVM-guest direct access to I/O devices. */ -#define _XEN_SYSCTL_PHYSCAP_hvm_directio 1 -#define XEN_SYSCTL_PHYSCAP_hvm_directio (1u<<_XEN_SYSCTL_PHYSCAP_hvm_directio) -struct xen_sysctl_physinfo { - uint32_t threads_per_core; - uint32_t cores_per_socket; - uint32_t nr_cpus; - uint32_t nr_nodes; - uint32_t cpu_khz; - uint64_aligned_t total_pages; - uint64_aligned_t free_pages; - uint64_aligned_t scrub_pages; - uint32_t hw_cap[8]; - - /* - * IN: maximum addressable entry in the caller-provided cpu_to_node array. - * OUT: largest cpu identifier in the system. - * If OUT is greater than IN then the cpu_to_node array is truncated! - */ - uint32_t max_cpu_id; - /* - * If not NULL, this array is filled with node identifier for each cpu. - * If a cpu has no node information (e.g., cpu not present) then the - * sentinel value ~0u is written. - * The size of this array is specified by the caller in @max_cpu_id. - * If the actual @max_cpu_id is smaller than the array then the trailing - * elements of the array will not be written by the sysctl. - */ - XEN_GUEST_HANDLE_64(uint32) cpu_to_node; - - /* XEN_SYSCTL_PHYSCAP_??? */ - uint32_t capabilities; -}; -typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t); - -/* - * Get the ID of the current scheduler. - */ -#define XEN_SYSCTL_sched_id 4 -struct xen_sysctl_sched_id { - /* OUT variable */ - uint32_t sched_id; -}; -typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t); - -/* Interface for controlling Xen software performance counters. */ -#define XEN_SYSCTL_perfc_op 5 -/* Sub-operations: */ -#define XEN_SYSCTL_PERFCOP_reset 1 /* Reset all counters to zero. */ -#define XEN_SYSCTL_PERFCOP_query 2 /* Get perfctr information. */ -struct xen_sysctl_perfc_desc { - char name[80]; /* name of perf counter */ - uint32_t nr_vals; /* number of values for this counter */ -}; -typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t); -typedef uint32_t xen_sysctl_perfc_val_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t); - -struct xen_sysctl_perfc_op { - /* IN variables. */ - uint32_t cmd; /* XEN_SYSCTL_PERFCOP_??? */ - /* OUT variables. */ - uint32_t nr_counters; /* number of counters description */ - uint32_t nr_vals; /* number of values */ - /* counter information (or NULL) */ - XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc; - /* counter values (or NULL) */ - XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val; -}; -typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t); - -#define XEN_SYSCTL_getdomaininfolist 6 -struct xen_sysctl_getdomaininfolist { - /* IN variables. */ - domid_t first_domain; - uint32_t max_domains; - XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer; - /* OUT variables. */ - uint32_t num_domains; -}; -typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); - -/* Inject debug keys into Xen. */ -#define XEN_SYSCTL_debug_keys 7 -struct xen_sysctl_debug_keys { - /* IN variables. */ - XEN_GUEST_HANDLE_64(char) keys; - uint32_t nr_keys; -}; -typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t); - -/* Get physical CPU information. */ -#define XEN_SYSCTL_getcpuinfo 8 -struct xen_sysctl_cpuinfo { - uint64_aligned_t idletime; -}; -typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t); -struct xen_sysctl_getcpuinfo { - /* IN variables. */ - uint32_t max_cpus; - XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info; - /* OUT variables. */ - uint32_t nr_cpus; -}; -typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); - -#define XEN_SYSCTL_availheap 9 -struct xen_sysctl_availheap { - /* IN variables. */ - uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */ - uint32_t max_bitwidth; /* Largest address width (zero if don't care). */ - int32_t node; /* NUMA node of interest (-1 for all nodes). */ - /* OUT variables. */ - uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */ -}; -typedef struct xen_sysctl_availheap xen_sysctl_availheap_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t); - -#define XEN_SYSCTL_get_pmstat 10 -struct pm_px_val { - uint64_aligned_t freq; /* Px core frequency */ - uint64_aligned_t residency; /* Px residency time */ - uint64_aligned_t count; /* Px transition count */ -}; -typedef struct pm_px_val pm_px_val_t; -DEFINE_XEN_GUEST_HANDLE(pm_px_val_t); - -struct pm_px_stat { - uint8_t total; /* total Px states */ - uint8_t usable; /* usable Px states */ - uint8_t last; /* last Px state */ - uint8_t cur; /* current Px state */ - XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */ - XEN_GUEST_HANDLE_64(pm_px_val_t) pt; -}; -typedef struct pm_px_stat pm_px_stat_t; -DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t); - -struct pm_cx_stat { - uint32_t nr; /* entry nr in triggers & residencies, including C0 */ - uint32_t last; /* last Cx state */ - uint64_aligned_t idle_time; /* idle time from boot */ - XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */ - XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */ -}; - -struct xen_sysctl_get_pmstat { -#define PMSTAT_CATEGORY_MASK 0xf0 -#define PMSTAT_PX 0x10 -#define PMSTAT_CX 0x20 -#define PMSTAT_get_max_px (PMSTAT_PX | 0x1) -#define PMSTAT_get_pxstat (PMSTAT_PX | 0x2) -#define PMSTAT_reset_pxstat (PMSTAT_PX | 0x3) -#define PMSTAT_get_max_cx (PMSTAT_CX | 0x1) -#define PMSTAT_get_cxstat (PMSTAT_CX | 0x2) -#define PMSTAT_reset_cxstat (PMSTAT_CX | 0x3) - uint32_t type; - uint32_t cpuid; - union { - struct pm_px_stat getpx; - struct pm_cx_stat getcx; - /* other struct for tx, etc */ - } u; -}; -typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t); - -/* - * Status codes. Must be greater than 0 to avoid confusing - * sysctl callers that see 0 as a plain successful return. - */ -#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1 -#define XEN_CPU_HOTPLUG_STATUS_ONLINE 2 -#define XEN_CPU_HOTPLUG_STATUS_NEW 3 - -#define XEN_SYSCTL_cpu_hotplug 11 -struct xen_sysctl_cpu_hotplug { - /* IN variables */ - uint32_t cpu; /* Physical cpu. */ -#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE 0 -#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1 -#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2 - uint32_t op; /* hotplug opcode */ -}; -typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t); - -/* - * Get/set xen power management, include - * 1. cpufreq governors and related parameters - */ -#define XEN_SYSCTL_pm_op 12 -struct xen_userspace { - uint32_t scaling_setspeed; -}; -typedef struct xen_userspace xen_userspace_t; - -struct xen_ondemand { - uint32_t sampling_rate_max; - uint32_t sampling_rate_min; - - uint32_t sampling_rate; - uint32_t up_threshold; -}; -typedef struct xen_ondemand xen_ondemand_t; - -/* - * cpufreq para name of this structure named - * same as sysfs file name of native linux - */ -#define CPUFREQ_NAME_LEN 16 -struct xen_get_cpufreq_para { - /* IN/OUT variable */ - uint32_t cpu_num; - uint32_t freq_num; - uint32_t gov_num; - - /* for all governors */ - /* OUT variable */ - XEN_GUEST_HANDLE_64(uint32) affected_cpus; - XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies; - XEN_GUEST_HANDLE_64(char) scaling_available_governors; - char scaling_driver[CPUFREQ_NAME_LEN]; - - uint32_t cpuinfo_cur_freq; - uint32_t cpuinfo_max_freq; - uint32_t cpuinfo_min_freq; - uint32_t scaling_cur_freq; - - char scaling_governor[CPUFREQ_NAME_LEN]; - uint32_t scaling_max_freq; - uint32_t scaling_min_freq; - - /* for specific governor */ - union { - struct xen_userspace userspace; - struct xen_ondemand ondemand; - } u; -}; - -struct xen_set_cpufreq_gov { - char scaling_governor[CPUFREQ_NAME_LEN]; -}; - -struct xen_set_cpufreq_para { - #define SCALING_MAX_FREQ 1 - #define SCALING_MIN_FREQ 2 - #define SCALING_SETSPEED 3 - #define SAMPLING_RATE 4 - #define UP_THRESHOLD 5 - - uint32_t ctrl_type; - uint32_t ctrl_value; -}; - -/* Get physical CPU topology information. */ -#define INVALID_TOPOLOGY_ID (~0U) -struct xen_get_cputopo { - /* IN: maximum addressable entry in - * the caller-provided cpu_to_core/socket. - */ - uint32_t max_cpus; - XEN_GUEST_HANDLE_64(uint32) cpu_to_core; - XEN_GUEST_HANDLE_64(uint32) cpu_to_socket; - - /* OUT: number of cpus returned - * If OUT is greater than IN then the cpu_to_core/socket is truncated! - */ - uint32_t nr_cpus; -}; - -struct xen_sysctl_pm_op { - #define PM_PARA_CATEGORY_MASK 0xf0 - #define CPUFREQ_PARA 0x10 - - /* cpufreq command type */ - #define GET_CPUFREQ_PARA (CPUFREQ_PARA | 0x01) - #define SET_CPUFREQ_GOV (CPUFREQ_PARA | 0x02) - #define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03) - #define GET_CPUFREQ_AVGFREQ (CPUFREQ_PARA | 0x04) - - /* get CPU topology */ - #define XEN_SYSCTL_pm_op_get_cputopo 0x20 - - /* set/reset scheduler power saving option */ - #define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21 - - /* cpuidle max_cstate access command */ - #define XEN_SYSCTL_pm_op_get_max_cstate 0x22 - #define XEN_SYSCTL_pm_op_set_max_cstate 0x23 - - /* set scheduler migration cost value */ - #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay 0x24 - #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay 0x25 - - uint32_t cmd; - uint32_t cpuid; - union { - struct xen_get_cpufreq_para get_para; - struct xen_set_cpufreq_gov set_gov; - struct xen_set_cpufreq_para set_para; - uint64_t get_avgfreq; - struct xen_get_cputopo get_topo; - uint32_t set_sched_opt_smt; - uint32_t get_max_cstate; - uint32_t set_max_cstate; - uint32_t get_vcpu_migration_delay; - uint32_t set_vcpu_migration_delay; - } u; -}; - -#define XEN_SYSCTL_page_offline_op 14 -struct xen_sysctl_page_offline_op { - /* IN: range of page to be offlined */ -#define sysctl_page_offline 1 -#define sysctl_page_online 2 -#define sysctl_query_page_offline 3 - uint32_t cmd; - uint32_t start; - uint32_t end; - /* OUT: result of page offline request */ - /* - * bit 0~15: result flags - * bit 16~31: owner - */ - XEN_GUEST_HANDLE(uint32) status; -}; - -#define PG_OFFLINE_STATUS_MASK (0xFFUL) - -/* The result is invalid, i.e. HV does not handle it */ -#define PG_OFFLINE_INVALID (0x1UL << 0) - -#define PG_OFFLINE_OFFLINED (0x1UL << 1) -#define PG_OFFLINE_PENDING (0x1UL << 2) -#define PG_OFFLINE_FAILED (0x1UL << 3) - -#define PG_ONLINE_FAILED PG_OFFLINE_FAILED -#define PG_ONLINE_ONLINED PG_OFFLINE_OFFLINED - -#define PG_OFFLINE_STATUS_OFFLINED (0x1UL << 1) -#define PG_OFFLINE_STATUS_ONLINE (0x1UL << 2) -#define PG_OFFLINE_STATUS_OFFLINE_PENDING (0x1UL << 3) -#define PG_OFFLINE_STATUS_BROKEN (0x1UL << 4) - -#define PG_OFFLINE_MISC_MASK (0xFFUL << 4) - -/* only valid when PG_OFFLINE_FAILED */ -#define PG_OFFLINE_XENPAGE (0x1UL << 8) -#define PG_OFFLINE_DOM0PAGE (0x1UL << 9) -#define PG_OFFLINE_ANONYMOUS (0x1UL << 10) -#define PG_OFFLINE_NOT_CONV_RAM (0x1UL << 11) -#define PG_OFFLINE_OWNED (0x1UL << 12) - -#define PG_OFFLINE_BROKEN (0x1UL << 13) -#define PG_ONLINE_BROKEN PG_OFFLINE_BROKEN - -#define PG_OFFLINE_OWNER_SHIFT 16 - -struct xen_sysctl { - uint32_t cmd; - uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ - union { - struct xen_sysctl_readconsole readconsole; - struct xen_sysctl_tbuf_op tbuf_op; - struct xen_sysctl_physinfo physinfo; - struct xen_sysctl_sched_id sched_id; - struct xen_sysctl_perfc_op perfc_op; - struct xen_sysctl_getdomaininfolist getdomaininfolist; - struct xen_sysctl_debug_keys debug_keys; - struct xen_sysctl_getcpuinfo getcpuinfo; - struct xen_sysctl_availheap availheap; - struct xen_sysctl_get_pmstat get_pmstat; - struct xen_sysctl_cpu_hotplug cpu_hotplug; - struct xen_sysctl_pm_op pm_op; - struct xen_sysctl_page_offline_op page_offline; - uint8_t pad[128]; - } u; -}; -typedef struct xen_sysctl xen_sysctl_t; -DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t); - -#endif /* __XEN_PUBLIC_SYSCTL_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/trace.h b/usr/src/uts/common/xen/public/trace.h deleted file mode 100644 index 76088e346d..0000000000 --- a/usr/src/uts/common/xen/public/trace.h +++ /dev/null @@ -1,207 +0,0 @@ -/****************************************************************************** - * include/public/trace.h - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Mark Williamson, (C) 2004 Intel Research Cambridge - * Copyright (C) 2005 Bin Ren - */ - -#ifndef __XEN_PUBLIC_TRACE_H__ -#define __XEN_PUBLIC_TRACE_H__ - -#define TRACE_EXTRA_MAX 7 -#define TRACE_EXTRA_SHIFT 28 - -/* Trace classes */ -#define TRC_CLS_SHIFT 16 -#define TRC_GEN 0x0001f000 /* General trace */ -#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */ -#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ -#define TRC_HVM 0x0008f000 /* Xen HVM trace */ -#define TRC_MEM 0x0010f000 /* Xen memory trace */ -#define TRC_PV 0x0020f000 /* Xen PV traces */ -#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */ -#define TRC_PM 0x0080f000 /* Xen power management trace */ -#define TRC_ALL 0x0ffff000 -#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) -#define TRC_HD_CYCLE_FLAG (1UL<<31) -#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) ) -#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX) - -/* Trace subclasses */ -#define TRC_SUBCLS_SHIFT 12 - -/* trace subclasses for SVM */ -#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */ -#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */ - -#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */ -#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */ - -/* Trace events per class */ -#define TRC_LOST_RECORDS (TRC_GEN + 1) -#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2) -#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3) - -#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1) -#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2) -#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1) -#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2) -#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3) -#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4) -#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5) -#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6) -#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7) -#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8) -#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9) -#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10) -#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11) -#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12) -#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13) -#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14) -#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15) - -#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1) -#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2) -#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3) - -#define TRC_PV_HYPERCALL (TRC_PV + 1) -#define TRC_PV_TRAP (TRC_PV + 3) -#define TRC_PV_PAGE_FAULT (TRC_PV + 4) -#define TRC_PV_FORCED_INVALID_OP (TRC_PV + 5) -#define TRC_PV_EMULATE_PRIVOP (TRC_PV + 6) -#define TRC_PV_EMULATE_4GB (TRC_PV + 7) -#define TRC_PV_MATH_STATE_RESTORE (TRC_PV + 8) -#define TRC_PV_PAGING_FIXUP (TRC_PV + 9) -#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV + 10) -#define TRC_PV_PTWR_EMULATION (TRC_PV + 11) -#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV + 12) - /* Indicates that addresses in trace record are 64 bits */ -#define TRC_64_FLAG (0x100) - -#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1) -#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2) -#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3) -#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4) -#define TRC_SHADOW_MMIO (TRC_SHADOW + 5) -#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6) -#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7) -#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8) -#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + 9) -#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + 10) -#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11) -#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12) -#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13) -#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14) -#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15) - -/* trace events per subclass */ -#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01) -#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02) -#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02) -#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01) -#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01) -#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02) -#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02) -#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03) -#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04) -#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05) -#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06) -#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07) -#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08) -#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08) -#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09) -#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09) -#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A) -#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B) -#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C) -#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D) -#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E) -#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F) -#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10) -#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11) -#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12) -#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13) -#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14) -#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14) -#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15) -#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16) -#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17) -#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18) -#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19) -#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19) -#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20) -#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216) -#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217) - -/* trace subclasses for power management */ -#define TRC_PM_FREQ 0x00801000 /* xen cpu freq events */ -#define TRC_PM_IDLE 0x00802000 /* xen cpu idle events */ - -/* trace events for per class */ -#define TRC_PM_FREQ_CHANGE (TRC_PM_FREQ + 0x01) -#define TRC_PM_IDLE_ENTRY (TRC_PM_IDLE + 0x01) -#define TRC_PM_IDLE_EXIT (TRC_PM_IDLE + 0x02) - -/* This structure represents a single trace buffer record. */ -struct t_rec { - uint32_t event:28; - uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */ - uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */ - union { - struct { - uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */ - uint32_t extra_u32[7]; /* event data items */ - } cycles; - struct { - uint32_t extra_u32[7]; /* event data items */ - } nocycles; - } u; -}; - -/* - * This structure contains the metadata for a single trace buffer. The head - * field, indexes into an array of struct t_rec's. - */ -struct t_buf { - /* Assume the data buffer size is X. X is generally not a power of 2. - * CONS and PROD are incremented modulo (2*X): - * 0 <= cons < 2*X - * 0 <= prod < 2*X - * This is done because addition modulo X breaks at 2^32 when X is not a - * power of 2: - * (((2^32 - 1) % X) + 1) % X != (2^32) % X - */ - uint32_t cons; /* Offset of next item to be consumed by control tools. */ - uint32_t prod; /* Offset of next item to be produced by Xen. */ - /* Records follow immediately after the meta-data header. */ -}; - -#endif /* __XEN_PUBLIC_TRACE_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/vcpu.h b/usr/src/uts/common/xen/public/vcpu.h deleted file mode 100644 index ab6549370e..0000000000 --- a/usr/src/uts/common/xen/public/vcpu.h +++ /dev/null @@ -1,213 +0,0 @@ -/****************************************************************************** - * vcpu.h - * - * VCPU initialisation, query, and hotplug. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_VCPU_H__ -#define __XEN_PUBLIC_VCPU_H__ - -/* - * Prototype for this hypercall is: - * int vcpu_op(int cmd, int vcpuid, void *extra_args) - * @cmd == VCPUOP_??? (VCPU operation). - * @vcpuid == VCPU to operate on. - * @extra_args == Operation-specific extra arguments (NULL if none). - */ - -/* - * Initialise a VCPU. Each VCPU can be initialised only once. A - * newly-initialised VCPU will not run until it is brought up by VCPUOP_up. - * - * @extra_arg == pointer to vcpu_guest_context structure containing initial - * state for the VCPU. - */ -#define VCPUOP_initialise 0 - -/* - * Bring up a VCPU. This makes the VCPU runnable. This operation will fail - * if the VCPU has not been initialised (VCPUOP_initialise). - */ -#define VCPUOP_up 1 - -/* - * Bring down a VCPU (i.e., make it non-runnable). - * There are a few caveats that callers should observe: - * 1. This operation may return, and VCPU_is_up may return false, before the - * VCPU stops running (i.e., the command is asynchronous). It is a good - * idea to ensure that the VCPU has entered a non-critical loop before - * bringing it down. Alternatively, this operation is guaranteed - * synchronous if invoked by the VCPU itself. - * 2. After a VCPU is initialised, there is currently no way to drop all its - * references to domain memory. Even a VCPU that is down still holds - * memory references via its pagetable base pointer and GDT. It is good - * practise to move a VCPU onto an 'idle' or default page table, LDT and - * GDT before bringing it down. - */ -#define VCPUOP_down 2 - -/* Returns 1 if the given VCPU is up. */ -#define VCPUOP_is_up 3 - -/* - * Return information about the state and running time of a VCPU. - * @extra_arg == pointer to vcpu_runstate_info structure. - */ -#define VCPUOP_get_runstate_info 4 -struct vcpu_runstate_info { - /* VCPU's current state (RUNSTATE_*). */ - int state; - /* When was current state entered (system time, ns)? */ - uint64_t state_entry_time; - /* - * Time spent in each RUNSTATE_* (ns). The sum of these times is - * guaranteed not to drift from system time. - */ - uint64_t time[4]; -}; -typedef struct vcpu_runstate_info vcpu_runstate_info_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_t); - -/* VCPU is currently running on a physical CPU. */ -#define RUNSTATE_running 0 - -/* VCPU is runnable, but not currently scheduled on any physical CPU. */ -#define RUNSTATE_runnable 1 - -/* VCPU is blocked (a.k.a. idle). It is therefore not runnable. */ -#define RUNSTATE_blocked 2 - -/* - * VCPU is not runnable, but it is not blocked. - * This is a 'catch all' state for things like hotplug and pauses by the - * system administrator (or for critical sections in the hypervisor). - * RUNSTATE_blocked dominates this state (it is the preferred state). - */ -#define RUNSTATE_offline 3 - -/* - * Register a shared memory area from which the guest may obtain its own - * runstate information without needing to execute a hypercall. - * Notes: - * 1. The registered address may be virtual or physical or guest handle, - * depending on the platform. Virtual address or guest handle should be - * registered on x86 systems. - * 2. Only one shared area may be registered per VCPU. The shared area is - * updated by the hypervisor each time the VCPU is scheduled. Thus - * runstate.state will always be RUNSTATE_running and - * runstate.state_entry_time will indicate the system time at which the - * VCPU was last scheduled to run. - * @extra_arg == pointer to vcpu_register_runstate_memory_area structure. - */ -#define VCPUOP_register_runstate_memory_area 5 -struct vcpu_register_runstate_memory_area { - union { - XEN_GUEST_HANDLE(vcpu_runstate_info_t) h; - struct vcpu_runstate_info *v; - uint64_t p; - } addr; -}; -typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t); - -/* - * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer - * which can be set via these commands. Periods smaller than one millisecond - * may not be supported. - */ -#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */ -#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */ -struct vcpu_set_periodic_timer { - uint64_t period_ns; -}; -typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t); - -/* - * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot - * timer which can be set via these commands. - */ -#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */ -#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */ -struct vcpu_set_singleshot_timer { - uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */ - uint32_t flags; /* VCPU_SSHOTTMR_??? */ -}; -typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t); - -/* Flags to VCPUOP_set_singleshot_timer. */ - /* Require the timeout to be in the future (return -ETIME if it's passed). */ -#define _VCPU_SSHOTTMR_future (0) -#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future) - -/* - * Register a memory location in the guest address space for the - * vcpu_info structure. This allows the guest to place the vcpu_info - * structure in a convenient place, such as in a per-cpu data area. - * The pointer need not be page aligned, but the structure must not - * cross a page boundary. - * - * This may be called only once per vcpu. - */ -#define VCPUOP_register_vcpu_info 10 /* arg == vcpu_register_vcpu_info_t */ -struct vcpu_register_vcpu_info { - uint64_t mfn; /* mfn of page to place vcpu_info */ - uint32_t offset; /* offset within page */ - uint32_t rsvd; /* unused */ -}; -typedef struct vcpu_register_vcpu_info vcpu_register_vcpu_info_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_register_vcpu_info_t); - -/* Send an NMI to the specified VCPU. @extra_arg == NULL. */ -#define VCPUOP_send_nmi 11 - -/* - * Get the physical ID information for a pinned vcpu's underlying physical - * processor. The physical ID informmation is architecture-specific. - * On x86: id[31:0]=apic_id, id[63:32]=acpi_id, and all values 0xff and - * greater are reserved. - * This command returns -EINVAL if it is not a valid operation for this VCPU. - */ -#define VCPUOP_get_physid 12 /* arg == vcpu_get_physid_t */ -struct vcpu_get_physid { - uint64_t phys_id; -}; -typedef struct vcpu_get_physid vcpu_get_physid_t; -DEFINE_XEN_GUEST_HANDLE(vcpu_get_physid_t); -#define xen_vcpu_physid_to_x86_apicid(physid) \ - ((((uint32_t)(physid)) >= 0xff) ? 0xff : ((uint8_t)(physid))) -#define xen_vcpu_physid_to_x86_acpiid(physid) \ - ((((uint32_t)((physid)>>32)) >= 0xff) ? 0xff : ((uint8_t)((physid)>>32))) - -#endif /* __XEN_PUBLIC_VCPU_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/version.h b/usr/src/uts/common/xen/public/version.h deleted file mode 100644 index 944ca620b0..0000000000 --- a/usr/src/uts/common/xen/public/version.h +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - * version.h - * - * Xen version, type, and compile information. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2005, Nguyen Anh Quynh - * Copyright (c) 2005, Keir Fraser - */ - -#ifndef __XEN_PUBLIC_VERSION_H__ -#define __XEN_PUBLIC_VERSION_H__ - -/* NB. All ops return zero on success, except XENVER_{version,pagesize} */ - -/* arg == NULL; returns major:minor (16:16). */ -#define XENVER_version 0 - -/* arg == xen_extraversion_t. */ -#define XENVER_extraversion 1 -typedef char xen_extraversion_t[16]; -#define XEN_EXTRAVERSION_LEN (sizeof(xen_extraversion_t)) - -/* arg == xen_compile_info_t. */ -#define XENVER_compile_info 2 -struct xen_compile_info { - char compiler[64]; - char compile_by[16]; - char compile_domain[32]; - char compile_date[32]; -}; -typedef struct xen_compile_info xen_compile_info_t; - -#define XENVER_capabilities 3 -typedef char xen_capabilities_info_t[1024]; -#define XEN_CAPABILITIES_INFO_LEN (sizeof(xen_capabilities_info_t)) - -#define XENVER_changeset 4 -typedef char xen_changeset_info_t[64]; -#define XEN_CHANGESET_INFO_LEN (sizeof(xen_changeset_info_t)) - -#define XENVER_platform_parameters 5 -struct xen_platform_parameters { - unsigned long virt_start; -}; -typedef struct xen_platform_parameters xen_platform_parameters_t; - -#define XENVER_get_features 6 -struct xen_feature_info { - unsigned int submap_idx; /* IN: which 32-bit submap to return */ - uint32_t submap; /* OUT: 32-bit submap */ -}; -typedef struct xen_feature_info xen_feature_info_t; - -/* Declares the features reported by XENVER_get_features. */ -#include "features.h" - -/* arg == NULL; returns host memory page size. */ -#define XENVER_pagesize 7 - -/* arg == xen_domain_handle_t. */ -#define XENVER_guest_handle 8 - -#endif /* __XEN_PUBLIC_VERSION_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/xen-compat.h b/usr/src/uts/common/xen/public/xen-compat.h deleted file mode 100644 index 329be076cd..0000000000 --- a/usr/src/uts/common/xen/public/xen-compat.h +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * xen-compat.h - * - * Guest OS interface to Xen. Compatibility layer. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2006, Christian Limpach - */ - -#ifndef __XEN_PUBLIC_XEN_COMPAT_H__ -#define __XEN_PUBLIC_XEN_COMPAT_H__ - -#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030209 - -#if defined(__XEN__) || defined(__XEN_TOOLS__) -/* Xen is built with matching headers and implements the latest interface. */ -#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ -#elif !defined(__XEN_INTERFACE_VERSION__) -/* Guests which do not specify a version get the legacy interface. */ -#define __XEN_INTERFACE_VERSION__ 0x00000000 -#endif - -#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__ -#error "These header files do not support the requested interface version." -#endif - -#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */ diff --git a/usr/src/uts/common/xen/public/xen.h b/usr/src/uts/common/xen/public/xen.h deleted file mode 100644 index b557a7decd..0000000000 --- a/usr/src/uts/common/xen/public/xen.h +++ /dev/null @@ -1,676 +0,0 @@ -/****************************************************************************** - * xen.h - * - * Guest OS interface to Xen. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright (c) 2004, K A Fraser - */ - -#ifndef __XEN_PUBLIC_XEN_H__ -#define __XEN_PUBLIC_XEN_H__ - -#include "xen-compat.h" - -#if defined(__i386) && !defined(__i386__) -#define __i386__ /* foo */ -#endif - -#if defined(__amd64) && !defined(__x86_64__) -#define __x86_64__ -#endif - -#if defined(_ASM) && !defined(__ASSEMBLY__) -#define __ASSEMBLY__ -#endif - -#if defined(__i386__) || defined(__x86_64__) -#include "arch-x86/xen.h" -#elif defined(__ia64__) -#include "arch-ia64.h" -#else -#error "Unsupported architecture" -#endif - -#ifndef __ASSEMBLY__ -/* Guest handles for primitive C types. */ -DEFINE_XEN_GUEST_HANDLE(char); -__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); -DEFINE_XEN_GUEST_HANDLE(int); -__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int); -DEFINE_XEN_GUEST_HANDLE(long); -__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long); -DEFINE_XEN_GUEST_HANDLE(void); - -DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); -#endif - -/* - * HYPERCALLS - */ - -#define __HYPERVISOR_set_trap_table 0 -#define __HYPERVISOR_mmu_update 1 -#define __HYPERVISOR_set_gdt 2 -#define __HYPERVISOR_stack_switch 3 -#define __HYPERVISOR_set_callbacks 4 -#define __HYPERVISOR_fpu_taskswitch 5 -#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */ -#define __HYPERVISOR_platform_op 7 -#define __HYPERVISOR_set_debugreg 8 -#define __HYPERVISOR_get_debugreg 9 -#define __HYPERVISOR_update_descriptor 10 -#define __HYPERVISOR_memory_op 12 -#define __HYPERVISOR_multicall 13 -#define __HYPERVISOR_update_va_mapping 14 -#define __HYPERVISOR_set_timer_op 15 -#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */ -#define __HYPERVISOR_xen_version 17 -#define __HYPERVISOR_console_io 18 -#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */ -#define __HYPERVISOR_grant_table_op 20 -#define __HYPERVISOR_vm_assist 21 -#define __HYPERVISOR_update_va_mapping_otherdomain 22 -#define __HYPERVISOR_iret 23 /* x86 only */ -#define __HYPERVISOR_vcpu_op 24 -#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ -#define __HYPERVISOR_mmuext_op 26 -#define __HYPERVISOR_xsm_op 27 -#define __HYPERVISOR_nmi_op 28 -#define __HYPERVISOR_sched_op 29 -#define __HYPERVISOR_callback_op 30 -#define __HYPERVISOR_xenoprof_op 31 -#define __HYPERVISOR_event_channel_op 32 -#define __HYPERVISOR_physdev_op 33 -#define __HYPERVISOR_hvm_op 34 -#define __HYPERVISOR_sysctl 35 -#define __HYPERVISOR_domctl 36 -#define __HYPERVISOR_kexec_op 37 - -/* Architecture-specific hypercall definitions. */ -#define __HYPERVISOR_arch_0 48 -#define __HYPERVISOR_arch_1 49 -#define __HYPERVISOR_arch_2 50 -#define __HYPERVISOR_arch_3 51 -#define __HYPERVISOR_arch_4 52 -#define __HYPERVISOR_arch_5 53 -#define __HYPERVISOR_arch_6 54 -#define __HYPERVISOR_arch_7 55 - -/* - * HYPERCALL COMPATIBILITY. - */ - -/* New sched_op hypercall introduced in 0x00030101. */ -#if __XEN_INTERFACE_VERSION__ < 0x00030101 -#undef __HYPERVISOR_sched_op -#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat -#endif - -/* New event-channel and physdev hypercalls introduced in 0x00030202. */ -#if __XEN_INTERFACE_VERSION__ < 0x00030202 -#undef __HYPERVISOR_event_channel_op -#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat -#undef __HYPERVISOR_physdev_op -#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat -#endif - -/* New platform_op hypercall introduced in 0x00030204. */ -#if __XEN_INTERFACE_VERSION__ < 0x00030204 -#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op -#endif - -/* - * VIRTUAL INTERRUPTS - * - * Virtual interrupts that a guest OS may receive from Xen. - * - * In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a - * global VIRQ. The former can be bound once per VCPU and cannot be re-bound. - * The latter can be allocated only once per guest: they must initially be - * allocated to VCPU0 but can subsequently be re-bound. - */ -#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */ -#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */ -#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */ -#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */ -#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */ -#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */ -#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */ -#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */ - -/* Architecture-specific VIRQ definitions. */ -#define VIRQ_ARCH_0 16 -#define VIRQ_ARCH_1 17 -#define VIRQ_ARCH_2 18 -#define VIRQ_ARCH_3 19 -#define VIRQ_ARCH_4 20 -#define VIRQ_ARCH_5 21 -#define VIRQ_ARCH_6 22 -#define VIRQ_ARCH_7 23 - -#define NR_VIRQS 24 - -/* - * MMU-UPDATE REQUESTS - * - * HYPERVISOR_mmu_update() accepts a list of (ptr, val) pairs. - * A foreigndom (FD) can be specified (or DOMID_SELF for none). - * Where the FD has some effect, it is described below. - * ptr[1:0] specifies the appropriate MMU_* command. - * - * ptr[1:0] == MMU_NORMAL_PT_UPDATE: - * Updates an entry in a page table. If updating an L1 table, and the new - * table entry is valid/present, the mapped frame must belong to the FD, if - * an FD has been specified. If attempting to map an I/O page then the - * caller assumes the privilege of the FD. - * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller. - * FD == DOMID_XEN: Map restricted areas of Xen's heap space. - * ptr[:2] -- Machine address of the page-table entry to modify. - * val -- Value to write. - * - * ptr[1:0] == MMU_MACHPHYS_UPDATE: - * Updates an entry in the machine->pseudo-physical mapping table. - * ptr[:2] -- Machine address within the frame whose mapping to modify. - * The frame must belong to the FD, if one is specified. - * val -- Value to write into the mapping entry. - * - * ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD: - * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed - * with those in @val. - */ -#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ -#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */ -#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */ - -/* - * MMU EXTENDED OPERATIONS - * - * HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures. - * A foreigndom (FD) can be specified (or DOMID_SELF for none). - * Where the FD has some effect, it is described below. - * - * cmd: MMUEXT_(UN)PIN_*_TABLE - * mfn: Machine frame number to be (un)pinned as a p.t. page. - * The frame must belong to the FD, if one is specified. - * - * cmd: MMUEXT_NEW_BASEPTR - * mfn: Machine frame number of new page-table base to install in MMU. - * - * cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only] - * mfn: Machine frame number of new page-table base to install in MMU - * when in user space. - * - * cmd: MMUEXT_TLB_FLUSH_LOCAL - * No additional arguments. Flushes local TLB. - * - * cmd: MMUEXT_INVLPG_LOCAL - * linear_addr: Linear address to be flushed from the local TLB. - * - * cmd: MMUEXT_TLB_FLUSH_MULTI - * vcpumask: Pointer to bitmap of VCPUs to be flushed. - * - * cmd: MMUEXT_INVLPG_MULTI - * linear_addr: Linear address to be flushed. - * vcpumask: Pointer to bitmap of VCPUs to be flushed. - * - * cmd: MMUEXT_TLB_FLUSH_ALL - * No additional arguments. Flushes all VCPUs' TLBs. - * - * cmd: MMUEXT_INVLPG_ALL - * linear_addr: Linear address to be flushed from all VCPUs' TLBs. - * - * cmd: MMUEXT_FLUSH_CACHE - * No additional arguments. Writes back and flushes cache contents. - * - * cmd: MMUEXT_SET_LDT - * linear_addr: Linear address of LDT base (NB. must be page-aligned). - * nr_ents: Number of entries in LDT. - * - * cmd: MMUEXT_CLEAR_PAGE - * mfn: Machine frame number to be cleared. - * - * cmd: MMUEXT_COPY_PAGE - * mfn: Machine frame number of the destination page. - * src_mfn: Machine frame number of the source page. - */ -#define MMUEXT_PIN_L1_TABLE 0 -#define MMUEXT_PIN_L2_TABLE 1 -#define MMUEXT_PIN_L3_TABLE 2 -#define MMUEXT_PIN_L4_TABLE 3 -#define MMUEXT_UNPIN_TABLE 4 -#define MMUEXT_NEW_BASEPTR 5 -#define MMUEXT_TLB_FLUSH_LOCAL 6 -#define MMUEXT_INVLPG_LOCAL 7 -#define MMUEXT_TLB_FLUSH_MULTI 8 -#define MMUEXT_INVLPG_MULTI 9 -#define MMUEXT_TLB_FLUSH_ALL 10 -#define MMUEXT_INVLPG_ALL 11 -#define MMUEXT_FLUSH_CACHE 12 -#define MMUEXT_SET_LDT 13 -#define MMUEXT_NEW_USER_BASEPTR 15 -#define MMUEXT_CLEAR_PAGE 16 -#define MMUEXT_COPY_PAGE 17 - -#ifndef __ASSEMBLY__ -struct mmuext_op { - unsigned int cmd; - union { - /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR - * CLEAR_PAGE, COPY_PAGE */ - xen_pfn_t mfn; - /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ - unsigned long linear_addr; - } arg1; - union { - /* SET_LDT */ - unsigned int nr_ents; - /* TLB_FLUSH_MULTI, INVLPG_MULTI */ -#if __XEN_INTERFACE_VERSION__ >= 0x00030205 - XEN_GUEST_HANDLE(const_void) vcpumask; -#else - const void *vcpumask; -#endif - /* COPY_PAGE */ - xen_pfn_t src_mfn; - } arg2; -}; -typedef struct mmuext_op mmuext_op_t; -DEFINE_XEN_GUEST_HANDLE(mmuext_op_t); -#endif - -/* These are passed as 'flags' to update_va_mapping. They can be ORed. */ -/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */ -/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */ -#define UVMF_NONE (0UL<<0) /* No flushing at all. */ -#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */ -#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */ -#define UVMF_FLUSHTYPE_MASK (3UL<<0) -#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */ -#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */ -#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */ - -/* - * Commands to HYPERVISOR_console_io(). - */ -#define CONSOLEIO_write 0 -#define CONSOLEIO_read 1 -#define CONSOLEIO_get_device 32 - -/* - * Commands to HYPERVISOR_vm_assist(). - */ -#define VMASST_CMD_enable 0 -#define VMASST_CMD_disable 1 - -/* x86/32 guests: simulate full 4GB segment limits. */ -#define VMASST_TYPE_4gb_segments 0 - -/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */ -#define VMASST_TYPE_4gb_segments_notify 1 - -/* - * x86 guests: support writes to bottom-level PTEs. - * NB1. Page-directory entries cannot be written. - * NB2. Guest must continue to remove all writable mappings of PTEs. - */ -#define VMASST_TYPE_writable_pagetables 2 - -/* x86/PAE guests: support PDPTs above 4GB. */ -#define VMASST_TYPE_pae_extended_cr3 3 - -#define MAX_VMASST_TYPE 3 - -#ifndef __ASSEMBLY__ - -typedef uint16_t domid_t; - -/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */ -#define DOMID_FIRST_RESERVED (0x7FF0U) - -/* DOMID_SELF is used in certain contexts to refer to oneself. */ -#define DOMID_SELF (0x7FF0U) - -/* - * DOMID_IO is used to restrict page-table updates to mapping I/O memory. - * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO - * is useful to ensure that no mappings to the OS's own heap are accidentally - * installed. (e.g., in Linux this could cause havoc as reference counts - * aren't adjusted on the I/O-mapping code path). - * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can - * be specified by any calling domain. - */ -#define DOMID_IO (0x7FF1U) - -/* - * DOMID_XEN is used to allow privileged domains to map restricted parts of - * Xen's heap space (e.g., the machine_to_phys table). - * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if - * the caller is privileged. - */ -#define DOMID_XEN (0x7FF2U) - -/* DOMID_INVALID is used to identity invalid domid */ -#define DOMID_INVALID (0x7FFFU) - -/* - * Send an array of these to HYPERVISOR_mmu_update(). - * NB. The fields are natural pointer/address size for this architecture. - */ -struct mmu_update { - uint64_t ptr; /* Machine address of PTE. */ - uint64_t val; /* New contents of PTE. */ -}; -typedef struct mmu_update mmu_update_t; -DEFINE_XEN_GUEST_HANDLE(mmu_update_t); - -/* - * Send an array of these to HYPERVISOR_multicall(). - * NB. The fields are natural register size for this architecture. - */ -struct multicall_entry { - unsigned long op, result; - unsigned long args[6]; -}; -typedef struct multicall_entry multicall_entry_t; -DEFINE_XEN_GUEST_HANDLE(multicall_entry_t); - -/* - * Event channel endpoints per domain: - * 1024 if a long is 32 bits; 4096 if a long is 64 bits. - */ -#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64) - -struct vcpu_time_info { - /* - * Updates to the following values are preceded and followed by an - * increment of 'version'. The guest can therefore detect updates by - * looking for changes to 'version'. If the least-significant bit of - * the version number is set then an update is in progress and the guest - * must wait to read a consistent set of values. - * The correct way to interact with the version number is similar to - * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry. - */ - uint32_t version; - uint32_t pad0; - uint64_t tsc_timestamp; /* TSC at last update of time vals. */ - uint64_t system_time; /* Time, in nanosecs, since boot. */ - /* - * Current system time: - * system_time + - * ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32) - * CPU frequency (Hz): - * ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift - */ - uint32_t tsc_to_system_mul; - int8_t tsc_shift; - int8_t pad1[3]; -}; /* 32 bytes */ -typedef struct vcpu_time_info vcpu_time_info_t; - -struct vcpu_info { - /* - * 'evtchn_upcall_pending' is written non-zero by Xen to indicate - * a pending notification for a particular VCPU. It is then cleared - * by the guest OS /before/ checking for pending work, thus avoiding - * a set-and-check race. Note that the mask is only accessed by Xen - * on the CPU that is currently hosting the VCPU. This means that the - * pending and mask flags can be updated by the guest without special - * synchronisation (i.e., no need for the x86 LOCK prefix). - * This may seem suboptimal because if the pending flag is set by - * a different CPU then an IPI may be scheduled even when the mask - * is set. However, note: - * 1. The task of 'interrupt holdoff' is covered by the per-event- - * channel mask bits. A 'noisy' event that is continually being - * triggered can be masked at source at this very precise - * granularity. - * 2. The main purpose of the per-VCPU mask is therefore to restrict - * reentrant execution: whether for concurrency control, or to - * prevent unbounded stack usage. Whatever the purpose, we expect - * that the mask will be asserted only for short periods at a time, - * and so the likelihood of a 'spurious' IPI is suitably small. - * The mask is read before making an event upcall to the guest: a - * non-zero mask therefore guarantees that the VCPU will not receive - * an upcall activation. The mask is cleared when the VCPU requests - * to block: this avoids wakeup-waiting races. - */ - uint8_t evtchn_upcall_pending; - uint8_t evtchn_upcall_mask; - unsigned long evtchn_pending_sel; - struct arch_vcpu_info arch; - struct vcpu_time_info time; -}; /* 64 bytes (x86) */ -#ifndef __XEN__ -typedef struct vcpu_info vcpu_info_t; -#endif - -/* - * Xen/kernel shared data -- pointer provided in start_info. - * - * This structure is defined to be both smaller than a page, and the - * only data on the shared page, but may vary in actual size even within - * compatible Xen versions; guests should not rely on the size - * of this structure remaining constant. - */ -struct shared_info { - struct vcpu_info vcpu_info[MAX_VIRT_CPUS]; - - /* - * A domain can create "event channels" on which it can send and receive - * asynchronous event notifications. There are three classes of event that - * are delivered by this mechanism: - * 1. Bi-directional inter- and intra-domain connections. Domains must - * arrange out-of-band to set up a connection (usually by allocating - * an unbound 'listener' port and avertising that via a storage service - * such as xenstore). - * 2. Physical interrupts. A domain with suitable hardware-access - * privileges can bind an event-channel port to a physical interrupt - * source. - * 3. Virtual interrupts ('events'). A domain can bind an event-channel - * port to a virtual interrupt source, such as the virtual-timer - * device or the emergency console. - * - * Event channels are addressed by a "port index". Each channel is - * associated with two bits of information: - * 1. PENDING -- notifies the domain that there is a pending notification - * to be processed. This bit is cleared by the guest. - * 2. MASK -- if this bit is clear then a 0->1 transition of PENDING - * will cause an asynchronous upcall to be scheduled. This bit is only - * updated by the guest. It is read-only within Xen. If a channel - * becomes pending while the channel is masked then the 'edge' is lost - * (i.e., when the channel is unmasked, the guest must manually handle - * pending notifications as no upcall will be scheduled by Xen). - * - * To expedite scanning of pending notifications, any 0->1 pending - * transition on an unmasked channel causes a corresponding bit in a - * per-vcpu selector word to be set. Each bit in the selector covers a - * 'C long' in the PENDING bitfield array. - */ - unsigned long evtchn_pending[sizeof(unsigned long) * 8]; - unsigned long evtchn_mask[sizeof(unsigned long) * 8]; - - /* - * Wallclock time: updated only by control software. Guests should base - * their gettimeofday() syscall on this wallclock-base value. - */ - uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */ - uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */ - uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */ - - struct arch_shared_info arch; - -}; -#ifndef __XEN__ -typedef struct shared_info shared_info_t; -#endif - -/* - * Start-of-day memory layout: - * 1. The domain is started within contiguous virtual-memory region. - * 2. The contiguous region ends on an aligned 4MB boundary. - * 3. This the order of bootstrap elements in the initial virtual region: - * a. relocated kernel image - * b. initial ram disk [mod_start, mod_len] - * c. list of allocated page frames [mfn_list, nr_pages] - * (unless relocated due to XEN_ELFNOTE_INIT_P2M) - * d. start_info_t structure [register ESI (x86)] - * e. bootstrap page tables [pt_base, CR3 (x86)] - * f. bootstrap stack [register ESP (x86)] - * 4. Bootstrap elements are packed together, but each is 4kB-aligned. - * 5. The initial ram disk may be omitted. - * 6. The list of page frames forms a contiguous 'pseudo-physical' memory - * layout for the domain. In particular, the bootstrap virtual-memory - * region is a 1:1 mapping to the first section of the pseudo-physical map. - * 7. All bootstrap elements are mapped read-writable for the guest OS. The - * only exception is the bootstrap page table, which is mapped read-only. - * 8. There is guaranteed to be at least 512kB padding after the final - * bootstrap element. If necessary, the bootstrap virtual region is - * extended by an extra 4MB to ensure this. - */ - -#define MAX_GUEST_CMDLINE 1024 -struct start_info { - /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */ - char magic[32]; /* "xen--". */ - unsigned long nr_pages; /* Total pages allocated to this domain. */ - unsigned long shared_info; /* MACHINE address of shared info struct. */ - uint32_t flags; /* SIF_xxx flags. */ - xen_pfn_t store_mfn; /* MACHINE page number of shared page. */ - uint32_t store_evtchn; /* Event channel for store communication. */ - union { - struct { - xen_pfn_t mfn; /* MACHINE page number of console page. */ - uint32_t evtchn; /* Event channel for console page. */ - } domU; - struct { - uint32_t info_off; /* Offset of console_info struct. */ - uint32_t info_size; /* Size of console_info struct from start.*/ - } dom0; - } console; - /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */ - unsigned long pt_base; /* VIRTUAL address of page directory. */ - unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */ - unsigned long mfn_list; /* VIRTUAL address of page-frame list. */ - unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */ - unsigned long mod_len; /* Size (bytes) of pre-loaded module. */ - int8_t cmd_line[MAX_GUEST_CMDLINE]; - /* The pfn range here covers both page table and p->m table frames. */ - unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */ - unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */ -}; -typedef struct start_info start_info_t; - -/* New console union for dom0 introduced in 0x00030203. */ -#if __XEN_INTERFACE_VERSION__ < 0x00030203 -#define console_mfn console.domU.mfn -#define console_evtchn console.domU.evtchn -#endif - -/* These flags are passed in the 'flags' field of start_info_t. */ -#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */ -#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */ -#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */ - -#define XEN_CONSOLE_INVALID -1 -#define XEN_CONSOLE_COM1 0 -#define XEN_CONSOLE_COM2 1 -#define XEN_CONSOLE_VGA 2 - -typedef struct dom0_vga_console_info { - uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */ -#define XEN_VGATYPE_TEXT_MODE_3 0x03 -#define XEN_VGATYPE_VESA_LFB 0x23 - - union { - struct { - /* Font height, in pixels. */ - uint16_t font_height; - /* Cursor location (column, row). */ - uint16_t cursor_x, cursor_y; - /* Number of rows and columns (dimensions in characters). */ - uint16_t rows, columns; - } text_mode_3; - - struct { - /* Width and height, in pixels. */ - uint16_t width, height; - /* Bytes per scan line. */ - uint16_t bytes_per_line; - /* Bits per pixel. */ - uint16_t bits_per_pixel; - /* LFB physical address, and size (in units of 64kB). */ - uint32_t lfb_base; - uint32_t lfb_size; - /* RGB mask offsets and sizes, as defined by VBE 1.2+ */ - uint8_t red_pos, red_size; - uint8_t green_pos, green_size; - uint8_t blue_pos, blue_size; - uint8_t rsvd_pos, rsvd_size; -#if __XEN_INTERFACE_VERSION__ >= 0x00030206 - /* VESA capabilities (offset 0xa, VESA command 0x4f00). */ - uint32_t gbl_caps; - /* Mode attributes (offset 0x0, VESA command 0x4f01). */ - uint16_t mode_attrs; -#endif - } vesa_lfb; - } u; -} dom0_vga_console_info_t; -#define xen_vga_console_info dom0_vga_console_info -#define xen_vga_console_info_t dom0_vga_console_info_t - -typedef uint8_t xen_domain_handle_t[16]; - -/* Turn a plain number into a C unsigned long constant. */ -#define __mk_unsigned_long(x) x ## UL -#define mk_unsigned_long(x) __mk_unsigned_long(x) - -__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t); -__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t); -__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t); -__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t); - -#else /* __ASSEMBLY__ */ - -/* In assembly code we cannot use C numeric constant suffixes. */ -#define mk_unsigned_long(x) x - -#endif /* !__ASSEMBLY__ */ - -/* Default definitions for macros used by domctl/sysctl. */ -#if defined(__XEN__) || defined(__XEN_TOOLS__) -#ifndef uint64_aligned_t -#define uint64_aligned_t uint64_t -#endif -#ifndef XEN_GUEST_HANDLE_64 -#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name) -#endif -#endif - -#endif /* __XEN_PUBLIC_XEN_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/xsm/acm.h b/usr/src/uts/common/xen/public/xsm/acm.h deleted file mode 100644 index b6ac8d5130..0000000000 --- a/usr/src/uts/common/xen/public/xsm/acm.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * acm.h: Xen access control module interface defintions - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Reiner Sailer - * Copyright (c) 2005, International Business Machines Corporation. - */ - -#ifndef _XEN_PUBLIC_ACM_H -#define _XEN_PUBLIC_ACM_H - -#include "../xen.h" - -/* default ssid reference value if not supplied */ -#define ACM_DEFAULT_SSID 0x0 -#define ACM_DEFAULT_LOCAL_SSID 0x0 - -/* Internal ACM ERROR types */ -#define ACM_OK 0 -#define ACM_UNDEF -1 -#define ACM_INIT_SSID_ERROR -2 -#define ACM_INIT_SOID_ERROR -3 -#define ACM_ERROR -4 - -/* External ACCESS DECISIONS */ -#define ACM_ACCESS_PERMITTED 0 -#define ACM_ACCESS_DENIED -111 -#define ACM_NULL_POINTER_ERROR -200 - -/* - Error codes reported in when trying to test for a new policy - These error codes are reported in an array of tuples where - each error code is followed by a parameter describing the error - more closely, such as a domain id. -*/ -#define ACM_EVTCHN_SHARING_VIOLATION 0x100 -#define ACM_GNTTAB_SHARING_VIOLATION 0x101 -#define ACM_DOMAIN_LOOKUP 0x102 -#define ACM_CHWALL_CONFLICT 0x103 -#define ACM_SSIDREF_IN_USE 0x104 - - -/* primary policy in lower 4 bits */ -#define ACM_NULL_POLICY 0 -#define ACM_CHINESE_WALL_POLICY 1 -#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2 -#define ACM_POLICY_UNDEFINED 15 - -/* combinations have secondary policy component in higher 4bit */ -#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \ - ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY) - -/* policy: */ -#define ACM_POLICY_NAME(X) \ - ((X) == (ACM_NULL_POLICY)) ? "NULL" : \ - ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL" : \ - ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT" : \ - ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT" : \ - "UNDEFINED" - -/* the following policy versions must be increased - * whenever the interpretation of the related - * policy's data structure changes - */ -#define ACM_POLICY_VERSION 4 -#define ACM_CHWALL_VERSION 1 -#define ACM_STE_VERSION 1 - -/* defines a ssid reference used by xen */ -typedef uint32_t ssidref_t; - -/* hooks that are known to domains */ -#define ACMHOOK_none 0 -#define ACMHOOK_sharing 1 -#define ACMHOOK_authorization 2 -#define ACMHOOK_conflictset 3 - -/* -------security policy relevant type definitions-------- */ - -/* type identifier; compares to "equal" or "not equal" */ -typedef uint16_t domaintype_t; - -/* CHINESE WALL POLICY DATA STRUCTURES - * - * current accumulated conflict type set: - * When a domain is started and has a type that is in - * a conflict set, the conflicting types are incremented in - * the aggregate set. When a domain is destroyed, the - * conflicting types to its type are decremented. - * If a domain has multiple types, this procedure works over - * all those types. - * - * conflict_aggregate_set[i] holds the number of - * running domains that have a conflict with type i. - * - * running_types[i] holds the number of running domains - * that include type i in their ssidref-referenced type set - * - * conflict_sets[i][j] is "0" if type j has no conflict - * with type i and is "1" otherwise. - */ -/* high-16 = version, low-16 = check magic */ -#define ACM_MAGIC 0x0001debc - -/* size of the SHA1 hash identifying the XML policy from which the - binary policy was created */ -#define ACM_SHA1_HASH_SIZE 20 - -/* each offset in bytes from start of the struct they - * are part of */ - -/* V3 of the policy buffer aded a version structure */ -struct acm_policy_version -{ - uint32_t major; - uint32_t minor; -}; - - -/* each buffer consists of all policy information for - * the respective policy given in the policy code - * - * acm_policy_buffer, acm_chwall_policy_buffer, - * and acm_ste_policy_buffer need to stay 32-bit aligned - * because we create binary policies also with external - * tools that assume packed representations (e.g. the java tool) - */ -struct acm_policy_buffer { - uint32_t magic; - uint32_t policy_version; /* ACM_POLICY_VERSION */ - uint32_t len; - uint32_t policy_reference_offset; - uint32_t primary_policy_code; - uint32_t primary_buffer_offset; - uint32_t secondary_policy_code; - uint32_t secondary_buffer_offset; - struct acm_policy_version xml_pol_version; /* add in V3 */ - uint8_t xml_policy_hash[ACM_SHA1_HASH_SIZE]; /* added in V4 */ -}; - - -struct acm_policy_reference_buffer { - uint32_t len; -}; - -struct acm_chwall_policy_buffer { - uint32_t policy_version; /* ACM_CHWALL_VERSION */ - uint32_t policy_code; - uint32_t chwall_max_types; - uint32_t chwall_max_ssidrefs; - uint32_t chwall_max_conflictsets; - uint32_t chwall_ssid_offset; - uint32_t chwall_conflict_sets_offset; - uint32_t chwall_running_types_offset; - uint32_t chwall_conflict_aggregate_offset; -}; - -struct acm_ste_policy_buffer { - uint32_t policy_version; /* ACM_STE_VERSION */ - uint32_t policy_code; - uint32_t ste_max_types; - uint32_t ste_max_ssidrefs; - uint32_t ste_ssid_offset; -}; - -struct acm_stats_buffer { - uint32_t magic; - uint32_t len; - uint32_t primary_policy_code; - uint32_t primary_stats_offset; - uint32_t secondary_policy_code; - uint32_t secondary_stats_offset; -}; - -struct acm_ste_stats_buffer { - uint32_t ec_eval_count; - uint32_t gt_eval_count; - uint32_t ec_denied_count; - uint32_t gt_denied_count; - uint32_t ec_cachehit_count; - uint32_t gt_cachehit_count; -}; - -struct acm_ssid_buffer { - uint32_t len; - ssidref_t ssidref; - uint32_t policy_reference_offset; - uint32_t primary_policy_code; - uint32_t primary_max_types; - uint32_t primary_types_offset; - uint32_t secondary_policy_code; - uint32_t secondary_max_types; - uint32_t secondary_types_offset; -}; - -#endif - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/public/xsm/acm_ops.h b/usr/src/uts/common/xen/public/xsm/acm_ops.h deleted file mode 100644 index 1fef7a0f8b..0000000000 --- a/usr/src/uts/common/xen/public/xsm/acm_ops.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * acm_ops.h: Xen access control module hypervisor commands - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Reiner Sailer - * Copyright (c) 2005,2006 International Business Machines Corporation. - */ - -#ifndef __XEN_PUBLIC_ACM_OPS_H__ -#define __XEN_PUBLIC_ACM_OPS_H__ - -#include "../xen.h" -#include "acm.h" - -/* - * Make sure you increment the interface version whenever you modify this file! - * This makes sure that old versions of acm tools will stop working in a - * well-defined way (rather than crashing the machine, for instance). - */ -#define ACM_INTERFACE_VERSION 0xAAAA000A - -/************************************************************************/ - -/* - * Prototype for this hypercall is: - * int acm_op(int cmd, void *args) - * @cmd == ACMOP_??? (access control module operation). - * @args == Operation-specific extra arguments (NULL if none). - */ - - -#define ACMOP_setpolicy 1 -struct acm_setpolicy { - /* IN */ - XEN_GUEST_HANDLE_64(void) pushcache; - uint32_t pushcache_size; -}; - - -#define ACMOP_getpolicy 2 -struct acm_getpolicy { - /* IN */ - XEN_GUEST_HANDLE_64(void) pullcache; - uint32_t pullcache_size; -}; - - -#define ACMOP_dumpstats 3 -struct acm_dumpstats { - /* IN */ - XEN_GUEST_HANDLE_64(void) pullcache; - uint32_t pullcache_size; -}; - - -#define ACMOP_getssid 4 -#define ACM_GETBY_ssidref 1 -#define ACM_GETBY_domainid 2 -struct acm_getssid { - /* IN */ - uint32_t get_ssid_by; /* ACM_GETBY_* */ - union { - domaintype_t domainid; - ssidref_t ssidref; - } id; - XEN_GUEST_HANDLE_64(void) ssidbuf; - uint32_t ssidbuf_size; -}; - -#define ACMOP_getdecision 5 -struct acm_getdecision { - /* IN */ - uint32_t get_decision_by1; /* ACM_GETBY_* */ - uint32_t get_decision_by2; /* ACM_GETBY_* */ - union { - domaintype_t domainid; - ssidref_t ssidref; - } id1; - union { - domaintype_t domainid; - ssidref_t ssidref; - } id2; - uint32_t hook; - /* OUT */ - uint32_t acm_decision; -}; - - -#define ACMOP_chgpolicy 6 -struct acm_change_policy { - /* IN */ - XEN_GUEST_HANDLE_64(void) policy_pushcache; - uint32_t policy_pushcache_size; - XEN_GUEST_HANDLE_64(void) del_array; - uint32_t delarray_size; - XEN_GUEST_HANDLE_64(void) chg_array; - uint32_t chgarray_size; - /* OUT */ - /* array with error code */ - XEN_GUEST_HANDLE_64(void) err_array; - uint32_t errarray_size; -}; - -#define ACMOP_relabeldoms 7 -struct acm_relabel_doms { - /* IN */ - XEN_GUEST_HANDLE_64(void) relabel_map; - uint32_t relabel_map_size; - /* OUT */ - XEN_GUEST_HANDLE_64(void) err_array; - uint32_t errarray_size; -}; - -/* future interface to Xen */ -struct xen_acmctl { - uint32_t cmd; - uint32_t interface_version; - union { - struct acm_setpolicy setpolicy; - struct acm_getpolicy getpolicy; - struct acm_dumpstats dumpstats; - struct acm_getssid getssid; - struct acm_getdecision getdecision; - struct acm_change_policy change_policy; - struct acm_relabel_doms relabel_doms; - } u; -}; - -typedef struct xen_acmctl xen_acmctl_t; -DEFINE_XEN_GUEST_HANDLE(xen_acmctl_t); - -#endif /* __XEN_PUBLIC_ACM_OPS_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/usr/src/uts/common/xen/sys/README b/usr/src/uts/common/xen/sys/README deleted file mode 100644 index 03aacc1943..0000000000 --- a/usr/src/uts/common/xen/sys/README +++ /dev/null @@ -1,36 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)prototype.Makefile 1.15 06/02/08 SMI" -# -#pragma ident "%Z%%M% %I% %E% SMI" -# - -evtchn.h, privcmd.h, and xenbus.h should not be edited in ON. They are -copies from a specific build of the xen consolidation which can be found in: - xen.hg/tools/libxc/xen/solaris - -Any changes to these files should be done in the xen consolidation. - diff --git a/usr/src/uts/common/xen/sys/evtchn.h b/usr/src/uts/common/xen/sys/evtchn.h deleted file mode 100644 index b564aba874..0000000000 --- a/usr/src/uts/common/xen/sys/evtchn.h +++ /dev/null @@ -1,101 +0,0 @@ -/****************************************************************************** - * evtchn.h - * - * Interface to /dev/xen/evtchn. - * - * Copyright (c) 2003-2005, K A Fraser - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _XEN_SYS_EVTCHN_H -#define _XEN_SYS_EVTCHN_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#define _IOC_NONE 0 -#define _IOC(flag, letter, inum, size) ((letter) << 8 | (inum)) - -/* - * Bind a fresh port to VIRQ @virq. - * Return allocated port. - */ -#define IOCTL_EVTCHN_BIND_VIRQ \ - _IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq)) -struct ioctl_evtchn_bind_virq { - unsigned int virq; -}; - -/* - * Bind a fresh port to remote <@remote_domain, @remote_port>. - * Return allocated port. - */ -#define IOCTL_EVTCHN_BIND_INTERDOMAIN \ - _IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain)) -struct ioctl_evtchn_bind_interdomain { - unsigned int remote_domain, remote_port; -}; - -/* - * Allocate a fresh port for binding to @remote_domain. - * Return allocated port. - */ -#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \ - _IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port)) -struct ioctl_evtchn_bind_unbound_port { - unsigned int remote_domain; -}; - -/* - * Unbind previously allocated @port. - */ -#define IOCTL_EVTCHN_UNBIND \ - _IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind)) -struct ioctl_evtchn_unbind { - unsigned int port; -}; - -/* - * Notify the given @port. - */ -#define IOCTL_EVTCHN_NOTIFY \ - _IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify)) -struct ioctl_evtchn_notify { - unsigned int port; -}; - -#endif /* _XEN_SYS_EVTCHN_H */ - -/* - * Local variables: - * c-file-style: "solaris" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/usr/src/uts/common/xen/sys/gnttab.h b/usr/src/uts/common/xen/sys/gnttab.h deleted file mode 100644 index eee9c27fbe..0000000000 --- a/usr/src/uts/common/xen/sys/gnttab.h +++ /dev/null @@ -1,154 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_GNTTAB_H -#define _SYS_GNTTAB_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * gnttab.h - * - * Two sets of functionality: - * 1. Granting foreign access to our memory reservation. - * 2. Accessing others' memory reservations via grant references. - * (i.e., mechanisms for both sender and recipient of grant references) - * - * Copyright (c) 2004-2005, K A Fraser - * Copyright (c) 2005, Christopher Clark - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct gnttab_free_callback { - struct gnttab_free_callback *next; - void (*fn)(void *); - void *arg; - uint16_t count; -}; - -/* - * For i86xpv the "frames" in grant table terminology are really MFNs. - */ -typedef mfn_t gnttab_frame_t; -#define FRAME_TO_MA(f) ((maddr_t)(f) << PAGESHIFT) - -int gnttab_grant_foreign_access(domid_t, gnttab_frame_t, int readonly); - -/* - * End access through the given grant reference, iff the grant entry is no - * longer in use. Return 1 if the grant entry was freed, 0 if it is still in - * use. - */ -int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly); - -/* - * Eventually end access through the given grant reference, and once that - * access has been ended, free the given page too. Access will be ended - * immediately iff the grant entry is not in use, otherwise it will happen - * some time later. page may be 0, in which case no freeing will occur. - */ -void gnttab_end_foreign_access(grant_ref_t ref, int readonly, - gnttab_frame_t page); - -int gnttab_grant_foreign_transfer(domid_t domid, pfn_t pfn); - -gnttab_frame_t gnttab_end_foreign_transfer_ref(grant_ref_t ref); -gnttab_frame_t gnttab_end_foreign_transfer(grant_ref_t ref); - -int gnttab_query_foreign_access(grant_ref_t ref); - -/* - * operations on reserved batches of grant references - */ -int gnttab_alloc_grant_references(uint16_t count, grant_ref_t *pprivate_head); - -void gnttab_free_grant_reference(grant_ref_t ref); - -void gnttab_free_grant_references(grant_ref_t head); - -int gnttab_empty_grant_references(const grant_ref_t *pprivate_head); - -int gnttab_claim_grant_reference(grant_ref_t *pprivate_head); - -void gnttab_release_grant_reference(grant_ref_t *private_head, - grant_ref_t release); - -void gnttab_request_free_callback(struct gnttab_free_callback *callback, - void (*fn)(void *), void *arg, uint16_t count); - -void gnttab_cancel_free_callback(struct gnttab_free_callback *callback); - -void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid, - gnttab_frame_t frame, int readonly); - -void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid, - pfn_t pfn); - -#define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr)) - -/* - * framework - */ -void gnttab_init(void); -void gnttab_suspend(void); -void gnttab_resume(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_GNTTAB_H */ diff --git a/usr/src/uts/common/xen/sys/privcmd.h b/usr/src/uts/common/xen/sys/privcmd.h deleted file mode 100644 index 9d72d31b6b..0000000000 --- a/usr/src/uts/common/xen/sys/privcmd.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2003-2005, K A Fraser - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _XEN_SYS_PRIVCMD_H -#define _XEN_SYS_PRIVCMD_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * WARNING: - * These numbers and structure are built into the ON privcmd - * driver, as well as the low-level tools and libraries in - * the Xen consolidation. - */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * ioctl numbers and corresponding data structures - */ - -#define __PRIVCMD_IOC (('p'<<24)|('r'<<16)|('v'<<8)) - -#define IOCTL_PRIVCMD_HYPERCALL (__PRIVCMD_IOC|0) -#define IOCTL_PRIVCMD_MMAP (__PRIVCMD_IOC|1) -#define IOCTL_PRIVCMD_MMAPBATCH (__PRIVCMD_IOC|2) - -typedef struct __privcmd_hypercall { - unsigned long op; - unsigned long arg[5]; -} privcmd_hypercall_t; - -typedef struct __privcmd_mmap_entry { - unsigned long va; - unsigned long mfn; - unsigned long npages; -} privcmd_mmap_entry_t; - -typedef struct __privcmd_mmap { - int num; - domid_t dom; /* target domain */ - privcmd_mmap_entry_t *entry; -} privcmd_mmap_t; - -typedef struct __privcmd_mmapbatch { - int num; /* number of pages to populate */ - domid_t dom; /* target domain */ - unsigned long addr; /* virtual address */ - unsigned long *arr; /* array of mfns - top nibble set on err */ -} privcmd_mmapbatch_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _XEN_SYS_PRIVCMD_H */ diff --git a/usr/src/uts/common/xen/sys/xenbus.h b/usr/src/uts/common/xen/sys/xenbus.h deleted file mode 100644 index edc7798c2d..0000000000 --- a/usr/src/uts/common/xen/sys/xenbus.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _XEN_SYS_XENBUS_H -#define _XEN_SYS_XENBUS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Return the xenstore event channel. - */ -#define IOCTL_XENBUS_XENSTORE_EVTCHN ('X' << 8) - -/* - * Notify the kernel that the xenstore is up and running - */ -#define IOCTL_XENBUS_NOTIFY_UP ('U' << 8) - -#endif /* _XEN_SYS_XENBUS_H */ diff --git a/usr/src/uts/common/xen/sys/xenbus_comms.h b/usr/src/uts/common/xen/sys/xenbus_comms.h deleted file mode 100644 index 7a008333fd..0000000000 --- a/usr/src/uts/common/xen/sys/xenbus_comms.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Private include for xenbus communications. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_XENBUS_COMMS_H -#define _SYS_XENBUS_COMMS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* xenbus interface interrupt */ -#define IPL_XENBUS 0x01 - -void xs_early_init(void); -void xs_domu_init(void); -void xs_dom0_init(void); -void xb_suspend(void); -void xb_init(void); -void xb_setup_intr(void); - -/* Low level routines. */ -int xb_write(const void *data, unsigned len); -int xb_read(void *data, unsigned len); - -ddi_umem_cookie_t xb_xenstore_cookie(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XENBUS_COMMS_H */ diff --git a/usr/src/uts/common/xen/sys/xenbus_impl.h b/usr/src/uts/common/xen/sys/xenbus_impl.h deleted file mode 100644 index 049086ae41..0000000000 --- a/usr/src/uts/common/xen/sys/xenbus_impl.h +++ /dev/null @@ -1,272 +0,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. - */ - -/* - * - * xenbus.h (renamed to xenbus_impl.h) - * - * Talks to Xen Store to figure out what devices we have. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _SYS_XENBUS_H -#define _SYS_XENBUS_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define XBT_NULL 0 - -typedef uint32_t xenbus_transaction_t; - -/* Register callback to watch this node. */ -struct xenbus_watch; -typedef void (*xenbus_watch_cb_t)(struct xenbus_watch *, - const char **vec, unsigned int len); -struct xenbus_watch { - list_node_t list; - const char *node; /* path being watched */ - xenbus_watch_cb_t callback; - struct xenbus_device *dev; -}; - -/* - * Call this function when xenstore is available, i.e. the daemon is - * connected to the xenbus device. - */ -struct xenbus_notify { - list_node_t list; - void (*notify_func) (int); -}; - -/* A xenbus device. */ -struct xenbus_device { - const char *devicetype; - const char *nodename; - const char *otherend; - int otherend_id; - int otherend_state; - struct xenbus_watch otherend_watch; - int has_error; - int frontend; - void (*otherend_changed)(struct xenbus_device *, XenbusState); - void *data; -}; - -typedef void (*xvdi_xb_watch_cb_t)(dev_info_t *dip, const char *path, - void *arg); - -typedef struct xd_xb_watches { - list_node_t xxw_list; - int xxw_ref; - struct xenbus_watch xxw_watch; - struct xendev_ppd *xxw_xppd; - xvdi_xb_watch_cb_t xxw_cb; - void *xxw_arg; -} xd_xb_watches_t; - -extern char **xenbus_directory(xenbus_transaction_t t, const char *dir, - const char *node, unsigned int *num); -extern int xenbus_read(xenbus_transaction_t t, const char *dir, - const char *node, void **rstr, unsigned int *len); -extern int xenbus_read_str(const char *dir, const char *node, char **rstr); -extern int xenbus_write(xenbus_transaction_t t, const char *dir, - const char *node, const char *string); -extern int xenbus_mkdir(xenbus_transaction_t t, const char *dir, - const char *node); -extern boolean_t xenbus_exists(const char *dir, const char *node); -extern boolean_t xenbus_exists_dir(const char *dir, const char *node); -extern int xenbus_rm(xenbus_transaction_t t, const char *dir, - const char *node); -extern int xenbus_transaction_start(xenbus_transaction_t *t); -extern int xenbus_transaction_end(xenbus_transaction_t t, int abort); - -/* Single read and scanf: returns errno or num scanned if > 0. */ -extern int xenbus_scanf(xenbus_transaction_t t, const char *dir, - const char *node, const char *fmt, ...); - -/* Single printf and write: returns errno or 0. */ -extern int xenbus_printf(xenbus_transaction_t t, const char *dir, - const char *node, const char *fmt, ...); - -/* - * Generic read function: NULL-terminated triples of name, - * sprintf-style type string, and pointer. Returns 0 or errno. - */ -extern int xenbus_gather(xenbus_transaction_t t, const char *dir, ...); - -extern int register_xenbus_watch(struct xenbus_watch *watch); -extern void unregister_xenbus_watch(struct xenbus_watch *watch); -extern void reregister_xenbus_watches(void); - -/* Called from xen core code. */ -extern void xenbus_suspend(void); -extern void xenbus_resume(void); - -#define XENBUS_EXIST_ERR(err) ((err) == ENOENT || (err) == ERANGE) - -/* - * Register a watch on the given path, using the given xenbus_watch structure - * for storage, and the given callback function as the callback. Return 0 on - * success, or errno on error. On success, the given path will be saved as - * watch->node, and remains the caller's to free. On error, watch->node will - * be NULL, the device will switch to XenbusStateClosing, and the error will - * be saved in the store. - */ -extern int xenbus_watch_path(struct xenbus_device *dev, const char *path, - struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)); - - -/* - * Register a watch on the given path/path2, using the given xenbus_watch - * structure for storage, and the given callback function as the callback. - * Return 0 on success, or errno on error. On success, the watched path - * (path/path2) will be saved as watch->node, and becomes the caller's to - * kfree(). On error, watch->node will be NULL, so the caller has nothing to - * free, the device will switch to XenbusStateClosing, and the error will be - * saved in the store. - */ -extern int xenbus_watch_path2(struct xenbus_device *dev, const char *path, - const char *path2, struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)); - - -/* - * Advertise in the store a change of the given driver to the given new_state. - * Perform the change inside the given transaction xbt. xbt may be NULL, in - * which case this is performed inside its own transaction. Return 0 on - * success, or errno on error. On error, the device will switch to - * XenbusStateClosing, and the error will be saved in the store. - */ -extern int xenbus_switch_state(struct xenbus_device *dev, - xenbus_transaction_t xbt, - XenbusState new_state); - - -/* - * Grant access to the given ring_mfn to the peer of the given device. Return - * 0 on success, or errno on error. On error, the device will switch to - * XenbusStateClosing, and the error will be saved in the store. - */ -extern int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn); - - -/* - * Allocate an event channel for the given xenbus_device, assigning the newly - * created local port to *port. Return 0 on success, or errno on error. On - * error, the device will switch to XenbusStateClosing, and the error will be - * saved in the store. - */ -extern int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); - - -/* - * Return the state of the driver rooted at the given store path, or - * XenbusStateClosed if no state can be read. - */ -extern XenbusState xenbus_read_driver_state(const char *path); - - -/* - * Report the given negative errno into the store, along with the given - * formatted message. - */ -extern void xenbus_dev_error(struct xenbus_device *dev, int err, - const char *fmt, ...); - - -/* - * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by - * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly - * closedown of this driver and its peer. - */ -extern void xenbus_dev_fatal(struct xenbus_device *dev, - int err, const char *fmt, ...); - -/* Clear any error. */ -extern void xenbus_dev_ok(struct xenbus_device *dev); - -/* - * Set up watches on other end of split device. - */ -extern int talk_to_otherend(struct xenbus_device *dev); - -#define XENSTORE_DOWN 0 /* xenstore is down */ -#define XENSTORE_UP 1 /* xenstore is up */ - -/* - * Register a notify callback function. - */ -extern int xs_register_xenbus_callback(void (*callback)(int)); - -/* - * Notify clients that xenstore is up - */ -extern void xs_notify_xenstore_up(void); - -/* - * Notify clients that xenstore is down - */ -extern void xs_notify_xenstore_down(void); - -struct xsd_sockmsg; - -extern int xenbus_dev_request_and_reply(struct xsd_sockmsg *, void **); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XENBUS_H */ diff --git a/usr/src/uts/common/xen/sys/xendev.h b/usr/src/uts/common/xen/sys/xendev.h deleted file mode 100644 index 4bc1f5fb8f..0000000000 --- a/usr/src/uts/common/xen/sys/xendev.h +++ /dev/null @@ -1,303 +0,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. - */ - -#ifndef _SYS_XENDEV_H -#define _SYS_XENDEV_H - - -#include -#include -#ifndef __xpv -#include -#include -#include -#endif -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Xenbus property interfaces, initialized by framework - */ -#define XBP_HP_STATUS "hotplug-status" /* backend prop: str */ -#define XBV_HP_STATUS_CONN "connected" /* backend prop val */ -#define XBP_DEV_TYPE "device-type" /* backend prop: str */ -#define XBV_DEV_TYPE_CD "cdrom" /* backend prop val */ - -/* - * Xenbus property interfaces, initialized by backend disk driver - */ -#define XBP_SECTOR_SIZE "sector-size" /* backend prop: uint */ -#define XBP_SECTORS "sectors" /* backend prop: uint64 */ -#define XBP_INFO "info" /* backend prop: uint */ -#define XBP_FB "feature-barrier" /* backend prop: boolean int */ - -/* - * Xenbus property interfaces, initialized by frontend disk driver - */ -#define XBP_RING_REF "ring-ref" /* frontend prop: long */ -#define XBP_EVENT_CHAN "event-channel" /* frontend prop: long */ -#define XBP_PROTOCOL "protocol" /* frontend prop: string */ - -/* - * Xenbus CDROM property interfaces, used by backend and frontend - * - * XBP_MEDIA_REQ_SUP - * - Backend xenbus property located at: - * backend/vbd///media-req-sup - * - Set by the backend, consumed by the frontend. - * - Cosumed by the frontend. - * - A boolean integer property indicating backend support - * for the XBP_MEDIA_REQ property. - * - * XBP_MEDIA_REQ - * - Frontend xenbus property located at: - * /local/domain//device/vbd//media-req - * - Set and consumed by both the frontend and backend. - * - Possible values: - * XBV_MEDIA_REQ_NONE, XBV_MEDIA_REQ_LOCK, and XBV_MEDIA_REQ_EJECT - * - Only applies to CDROM devices. - * - * XBV_MEDIA_REQ_NONE - * - XBP_MEDIA_REQ property valud - * - Set and consumed by both the frontend and backend. - * - Indicates that there are no currently outstanding media requet - * operations. - * - * XBV_MEDIA_REQ_LOCK - * - XBP_MEDIA_REQ property valud - * - Set by the frontend, consumed by the backend. - * - Indicates to the backend that the currenct media is locked - * and changes to the media (via xm block-configure for example) - * should not be allowed. - * - * XBV_MEDIA_REQ_EJECT - * - XBP_MEDIA_REQ property valud - * - Set by the frontend, consumed by the backend. - * - Indicates to the backend that the currenct media should be ejected. - * This means that the backend should close it's connection to - * the frontend device, close it's current backing store device/file, - * and then set the media-req property to XBV_MEDIA_REQ_NONE. (to - * indicate that the eject operation is complete.) - */ -#define XBP_MEDIA_REQ_SUP "media-req-sup" /* backend prop: boolean int */ -#define XBP_MEDIA_REQ "media-req" /* frontend prop: str */ -#define XBV_MEDIA_REQ_NONE "none" /* frontend prop val */ -#define XBV_MEDIA_REQ_LOCK "lock" /* frontend prop val */ -#define XBV_MEDIA_REQ_EJECT "eject" /* frontend prop val */ - -/* - * Xen device class codes - */ -typedef enum { - XEN_INVAL = -1, - XEN_CONSOLE = 0, - XEN_VNET, - XEN_VBLK, - XEN_XENBUS, - XEN_DOMCAPS, - XEN_BALLOON, - XEN_EVTCHN, - XEN_PRIVCMD, - XEN_BLKTAP, - XEN_LASTCLASS -} xendev_devclass_t; - -/* - * Hotplug request sent to userland event handler. - */ -typedef enum { - XEN_HP_ADD, - XEN_HP_REMOVE -} xendev_hotplug_cmd_t; - -/* - * Hotplug status. - * - * In fact, the Xen tools can write any arbitrary string into the - * hotplug-status node. We represent the known values here - anything - * else will be 'Unrecognized'. - */ -typedef enum { - Unrecognized, - Connected -} xendev_hotplug_state_t; - -struct xendev_ppd { - kmutex_t xd_evt_lk; - int xd_evtchn; - struct intrspec xd_ispec; - - xendev_devclass_t xd_devclass; - domid_t xd_domain; - int xd_vdevnum; - - kmutex_t xd_ndi_lk; - struct xenbus_device xd_xsdev; - struct xenbus_watch xd_hp_watch; - struct xenbus_watch xd_bepath_watch; - ddi_callback_id_t xd_oe_ehid; - ddi_callback_id_t xd_hp_ehid; - ddi_taskq_t *xd_oe_taskq; - ddi_taskq_t *xd_hp_taskq; - ddi_taskq_t *xd_xb_watch_taskq; - list_t xd_xb_watches; -}; - -#define XS_OE_STATE "SUNW,xendev:otherend_state" -#define XS_HP_STATE "SUNW,xendev:hotplug_state" - -/* - * A device with xd_vdevnum == VDEV_NOXS does not participate in - * xenstore. - */ -#define VDEV_NOXS (-1) - -void xendev_enum_class(dev_info_t *, xendev_devclass_t); -void xendev_enum_all(dev_info_t *, boolean_t); -xendev_devclass_t xendev_nodename_to_devclass(char *); -int xendev_devclass_ipl(xendev_devclass_t); -struct intrspec *xendev_get_ispec(dev_info_t *, uint_t); -void xvdi_suspend(dev_info_t *); -int xvdi_resume(dev_info_t *); -int xvdi_alloc_evtchn(dev_info_t *); -int xvdi_bind_evtchn(dev_info_t *, evtchn_port_t); -void xvdi_free_evtchn(dev_info_t *); -int xvdi_add_event_handler(dev_info_t *, char *, - void (*)(dev_info_t *, ddi_eventcookie_t, void *, void *), - void *arg); -void xvdi_remove_event_handler(dev_info_t *, char *); -int xvdi_get_evtchn(dev_info_t *); -int xvdi_get_vdevnum(dev_info_t *); -char *xvdi_get_xsname(dev_info_t *); -char *xvdi_get_oename(dev_info_t *); -domid_t xvdi_get_oeid(dev_info_t *); -void xvdi_dev_error(dev_info_t *, int, char *); -void xvdi_fatal_error(dev_info_t *, int, char *); -void xvdi_notify_oe(dev_info_t *); -int xvdi_post_event(dev_info_t *, xendev_hotplug_cmd_t); -struct xenbus_device *xvdi_get_xsd(dev_info_t *); -int xvdi_switch_state(dev_info_t *, xenbus_transaction_t, XenbusState); -dev_info_t *xvdi_create_dev(dev_info_t *, xendev_devclass_t, - domid_t, int); -int xvdi_init_dev(dev_info_t *); -void xvdi_uninit_dev(dev_info_t *); -dev_info_t *xvdi_find_dev(dev_info_t *, xendev_devclass_t, domid_t, int); - -extern int xvdi_add_xb_watch_handler(dev_info_t *, const char *, - const char *, xvdi_xb_watch_cb_t cb, void *); -extern void xvdi_remove_xb_watch_handlers(dev_info_t *); - -/* - * common ring interfaces - */ - -/* - * we need the pad between ring index - * and the real ring containing requests/responses, - * so that we can map comif_sring_t structure to - * any xxxif_sring_t structure defined via macros in ring.h - */ -#define SRINGPAD 48 - -typedef struct comif_sring { - RING_IDX req_prod, req_event; - RING_IDX rsp_prod, rsp_event; - uint8_t pad[SRINGPAD]; - /* - * variable length - * stores real request/response entries - * entry size is fixed per ring - */ - char ring[1]; -} comif_sring_t; - -typedef struct comif_ring_fe { - /* - * keep the member names as defined in ring.h - * in order to make use of the pre-defined macros - */ - RING_IDX req_prod_pvt; - RING_IDX rsp_cons; - unsigned int nr_ents; - comif_sring_t *sring; -} comif_ring_fe_t; - -typedef struct comif_ring_be { - /* - * keep the member names as defined in ring.h - * in order to make use of the pre-defined macros - */ - RING_IDX rsp_prod_pvt; - RING_IDX req_cons; - unsigned int nr_ents; - comif_sring_t *sring; -} comif_ring_be_t; - -typedef union comif_ring { - comif_ring_fe_t fr; - comif_ring_be_t br; -} comif_ring_t; - -typedef struct xendev_req { - unsigned long next; - void *req; -} xendev_req_t; - -typedef struct xendev_ring { - ddi_dma_handle_t xr_dma_hdl; - ddi_acc_handle_t xr_acc_hdl; - grant_handle_t xr_grant_hdl; - caddr_t xr_vaddr; - paddr_t xr_paddr; - grant_ref_t xr_gref; - int xr_entry_size; - int xr_frontend; - comif_ring_t xr_sring; -} xendev_ring_t; - -int xvdi_alloc_ring(dev_info_t *, size_t, size_t, grant_ref_t *, - xendev_ring_t **); -void xvdi_free_ring(xendev_ring_t *); -int xvdi_map_ring(dev_info_t *, size_t, size_t, grant_ref_t, - xendev_ring_t **); -void xvdi_unmap_ring(xendev_ring_t *); -uint_t xvdi_ring_avail_slots(xendev_ring_t *); -int xvdi_ring_has_unconsumed_requests(xendev_ring_t *); -int xvdi_ring_has_incomp_request(xendev_ring_t *); -int xvdi_ring_has_unconsumed_responses(xendev_ring_t *); -void* xvdi_ring_get_request(xendev_ring_t *); -int xvdi_ring_push_request(xendev_ring_t *); -void* xvdi_ring_get_response(xendev_ring_t *); -int xvdi_ring_push_response(xendev_ring_t *); - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_XENDEV_H */ diff --git a/usr/src/uts/i86pc/Makefile b/usr/src/uts/i86pc/Makefile index 2bc6d6bcd4..8eea2f0a8b 100644 --- a/usr/src/uts/i86pc/Makefile +++ b/usr/src/uts/i86pc/Makefile @@ -50,13 +50,13 @@ INITIAL_TARGETS = \ cpu/scripts def all clean clobber: setup genassym unix .WAIT \ - $(KMODS) $(XMODS) $(IMPLEMENTATIONS) + $(KMODS) $(XMODS) install: install_platforms setup genassym unix .WAIT \ - $(KMODS) $(XMODS) $(IMPLEMENTATIONS) + $(KMODS) $(XMODS) # list the modules under i86pc. -modlist: unix $(KMODS) $(XMODS) $(IMPLEMENTATIONS) +modlist: unix $(KMODS) $(XMODS) # list the modules for Install -k i86pc. modlist.karch: modlist modlist.intel @@ -70,9 +70,6 @@ genassym unix $(KMODS): FRC setup: FRC @cd cpu/scripts; pwd; $(MAKE) $(TARGET) -$(IMPLEMENTATIONS): FRC - @cd $@; pwd; THISIMPL=$@ $(MAKE) $(NO_STATE) $(TARGET) - $(XMODS): FRC @if [ -f $@/Makefile ]; then \ cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET); \ @@ -80,7 +77,7 @@ $(XMODS): FRC true; \ fi -install_h check: $(IMPLEMENTATIONS) FRC +install_h check: FRC # # Definitions for the /platform directory aliases. diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files index 5b02e42f66..e4a6f7eec1 100644 --- a/usr/src/uts/i86pc/Makefile.files +++ b/usr/src/uts/i86pc/Makefile.files @@ -68,7 +68,6 @@ CORE_OBJS += \ hold_page.o \ hrtimers.o \ htable.o \ - hypercall.o \ hypersubr.o \ i86_mmu.o \ ibft.o \ @@ -119,7 +118,6 @@ CORE_OBJS += \ trap.o \ turbo.o \ vm_machdep.o \ - xpv_platform.o \ x_call.o # @@ -242,9 +240,7 @@ AMD_IOMMU_OBJS += amd_iommu.o amd_iommu_impl.o amd_iommu_acpi.o \ ALL_DEFS += -Di86pc INC_PATH += -I$(SRCTOP)/include INC_PATH += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -INC_PATH += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include INC_PATH += -I$(UTSBASE)/i86pc -I$(SRC)/common -INC_PATH += -I$(UTSBASE)/i86xpv -I$(UTSBASE)/common/xen # # Since the assym files are derived, the dependencies must be explicit for diff --git a/usr/src/uts/i86pc/Makefile.i86pc b/usr/src/uts/i86pc/Makefile.i86pc index 6a3d84a51e..eb328779a7 100644 --- a/usr/src/uts/i86pc/Makefile.i86pc +++ b/usr/src/uts/i86pc/Makefile.i86pc @@ -41,17 +41,6 @@ PLATFORM = i86pc UNAME_M = $(PLATFORM) # -# Definitions for the platform-specific /platform directories. -# -# IMPLEMENTATIONS is used to designate i86pc machines which have -# platform specific modules. All code specific to a given implementation -# resides in the appropriately named subdirectory. This requires -# these platforms to have their own Makefiles to define ROOT_PLAT_DIRS, -# USR_PLAT_DIRS, etc. -# -IMPLEMENTATIONS = i86hvm - -# # Everybody needs to know how to build modstubs.o and to locate unix.o # UNIX_DIR = $(UTSBASE)/$(PLATFORM)/unix diff --git a/usr/src/uts/i86pc/Makefile.rules b/usr/src/uts/i86pc/Makefile.rules index 560e650462..e123fd9516 100644 --- a/usr/src/uts/i86pc/Makefile.rules +++ b/usr/src/uts/i86pc/Makefile.rules @@ -218,10 +218,6 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/xsvc/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(SRCTOP)/arch/x86/kernel/xen/os/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - $(OBJS_DIR)/%.o: $(SRCTOP)/arch/x86/kernel/platform/i86pc/dboot/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) diff --git a/usr/src/uts/i86pc/i86hvm/Makefile b/usr/src/uts/i86pc/i86hvm/Makefile deleted file mode 100644 index 2733222d49..0000000000 --- a/usr/src/uts/i86pc/i86hvm/Makefile +++ /dev/null @@ -1,79 +0,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 -# -# -# uts/i86pc/i86hvm/Makefile -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# 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 - -def := TARGET= def -all := TARGET= all -install := TARGET= install -install_h := TARGET= install_h -clean := TARGET= clean -clobber := TARGET= clobber -modlist := TARGET= modlist -modlist := NO_STATE= -K $$MODSTATE$$$$ -check := TARGET= check - -# -# Default build targets. -# -.KEEP_STATE: - -.PARALLEL: $(HVM_KMODS) - -def all clean clobber modlist: $(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 diff --git a/usr/src/uts/i86pc/i86hvm/Makefile.files b/usr/src/uts/i86pc/i86hvm/Makefile.files deleted file mode 100644 index 704d10226e..0000000000 --- a/usr/src/uts/i86pc/i86hvm/Makefile.files +++ /dev/null @@ -1,50 +0,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. -# -# This Makefile defines file modules in the directory uts/i86pc/i86hvm -# and its children. These are the source files which are i86pc/i86hvm -# "implementation architecture" dependent. -# - -# -# Define objects -# -HVM_BOOTSTRAP_OBJS += hvm_bootstrap.o -HVM_CMDK_OBJS += cmdk.o -HVM_SD_OBJS += sd.o sd_xbuf.o -PV_CMDK_OBJS += pv_cmdk.o xdf_shell.o -PV_RTLS_OBJS += pv_rtls.o -PV_SD_OBJS += pv_sd.o xdf_shell.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 -# -I$(UTSBASE)/../common -INC_PATH += -I$(UTSBASE)/common/xen -I$(UTSBASE)/i86pc/i86hvm diff --git a/usr/src/uts/i86pc/i86hvm/Makefile.i86hvm b/usr/src/uts/i86pc/i86hvm/Makefile.i86hvm deleted file mode 100644 index 9e875530d6..0000000000 --- a/usr/src/uts/i86pc/i86hvm/Makefile.i86hvm +++ /dev/null @@ -1,59 +0,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 -# -# -# uts/i86pc/Makefile.hvm -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile provides support for building PV drivers that run -# in an HVM environment. -# - -ROOT_HVM_DIR = $(ROOT_PLAT_DIR)/i86hvm -ROOT_HVM_MOD_DIR = $(ROOT_HVM_DIR)/kernel -ROOT_HVM_DRV_DIR_32 = $(ROOT_HVM_MOD_DIR)/drv -ROOT_HVM_DRV_DIR_64 = $(ROOT_HVM_MOD_DIR)/drv/$(MACH64) -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/$(MACH64) -ROOT_HVM_MISC_DIR = $(ROOT_HVM_MISC_DIR_$(CLASS)) -USR_HVM_DIR = $(USR_PLAT_DIR)/i86hvm - -# -# Define modules. -# -HVM_DRV_KMODS = pv_cmdk pv_sd pv_rtls xdf xnf xpv xpvd -HVM_MISC_KMODS = hvm_bootstrap hvm_cmdk hvm_sd -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 diff --git a/usr/src/uts/i86pc/i86hvm/Makefile.rules b/usr/src/uts/i86pc/i86hvm/Makefile.rules deleted file mode 100644 index 12511cedeb..0000000000 --- a/usr/src/uts/i86pc/i86hvm/Makefile.rules +++ /dev/null @@ -1,57 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# - -# -# 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 1: 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) diff --git a/usr/src/uts/i86pc/i86hvm/Makefile.targ b/usr/src/uts/i86pc/i86hvm/Makefile.targ deleted file mode 100644 index 228fc17624..0000000000 --- a/usr/src/uts/i86pc/i86hvm/Makefile.targ +++ /dev/null @@ -1,68 +0,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. -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/hvm_bootstrap/Makefile b/usr/src/uts/i86pc/i86hvm/hvm_bootstrap/Makefile deleted file mode 100644 index 282d0240ec..0000000000 --- a/usr/src/uts/i86pc/i86hvm/hvm_bootstrap/Makefile +++ /dev/null @@ -1,75 +0,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 -# - -# -# uts/i86pc/hvm_bootstrap/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# 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) - -# Overrides -LDFLAGS += -dy - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/hvm_cmdk/Makefile b/usr/src/uts/i86pc/i86hvm/hvm_cmdk/Makefile deleted file mode 100644 index 0fce26368e..0000000000 --- a/usr/src/uts/i86pc/i86hvm/hvm_cmdk/Makefile +++ /dev/null @@ -1,91 +0,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 -# -# -# uts/i86pc/i86hvm/hvm_cmdk/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the xdc 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 = hvm_cmdk -OBJECTS = $(HVM_CMDK_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) - -# -# Overrides. -# -DEBUG_FLGS = -DEBUG_DEFS += $(DEBUG_FLGS) -LDFLAGS += -dy -Nmisc/dadk -Nmisc/strategy -Nmisc/cmlb - -# -# For now, disable these compiler warnings; maintainers should endeavor to -# investigate and remove these for maximum coverage. Please do not carry -# these forward to new Makefiles. -# - -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-type-limits -CERRWARN += -Wno-unused-function -CERRWARN += -Wno-uninitialized - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile b/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile deleted file mode 100644 index 26f0824d20..0000000000 --- a/usr/src/uts/i86pc/i86hvm/hvm_sd/Makefile +++ /dev/null @@ -1,83 +0,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 -# -# -# uts/i86pc/i86hvm/hvm_sd/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the xdc 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. -# -# Normally when compiling sd there are .conf file definitions -# but we don't bother with those here. -# -MODULE = hvm_sd -OBJECTS = $(HVM_SD_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) - -INC_PATH += -I$(UTSBASE)/intel/io/scsi/targets - -# -# Depends on scsi and cmlb -# -LDFLAGS += -dy -N misc/scsi -N misc/cmlb - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/io/hvm_bootstrap.c b/usr/src/uts/i86pc/i86hvm/io/hvm_bootstrap.c deleted file mode 100644 index d3e3d91399..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/hvm_bootstrap.c +++ /dev/null @@ -1,95 +0,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 - -/* - * 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); -} diff --git a/usr/src/uts/i86pc/i86hvm/io/pv_cmdk.c b/usr/src/uts/i86pc/i86hvm/io/pv_cmdk.c deleted file mode 100644 index bd6979b884..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/pv_cmdk.c +++ /dev/null @@ -1,674 +0,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 - -/* - * We're emulating (and possibly layering on top of) cmdk devices, so xdf - * disk unit mappings must match up with cmdk disk unit mappings'. - */ -#if !defined(XDF_PSHIFT) -#error "can't find definition for xdf unit mappings - XDF_PSHIFT" -#endif /* XDF_PSHIFT */ - -#if !defined(CMDK_UNITSHF) -#error "can't find definition for cmdk unit mappings - CMDK_UNITSHF" -#endif /* CMDK_UNITSHF */ - -#if ((XDF_PSHIFT - CMDK_UNITSHF) != 0) -#error "cmdk and xdf unit mappings don't match." -#endif /* ((XDF_PSHIFT - CMDK_UNITSHF) != 0) */ - -extern const struct dev_ops cmdk_ops; -extern void *cmdk_state; - -/* - * Globals required by xdf_shell.c - */ -const char *xdfs_c_name = "cmdk"; -const char *xdfs_c_linkinfo = "PV Common Direct Access Disk"; -void **xdfs_c_hvm_ss = &cmdk_state; -const size_t xdfs_c_hvm_ss_size = sizeof (struct cmdk); -const struct dev_ops *xdfs_c_hvm_dev_ops = &cmdk_ops; - -const xdfs_h2p_map_t xdfs_c_h2p_map[] = { - /* - * The paths mapping here are very specific to xen and qemu. When a - * domU is booted under xen in HVM mode, qemu is normally used to - * emulate up to four ide disks. These disks always have the four - * path listed below. To configure an emulated ide device, the - * xen domain configuration file normally has an entry that looks - * like this: - * disk = [ 'file:/foo.img,hda,w' ] - * - * The part we're interested in is the 'hda', which we'll call the - * xen disk device name here. The xen management tools (which parse - * the xen domain configuration file and launch qemu) makes the - * following assumptions about this value: - * hda == emulated ide disk 0 (ide bus 0, master) - * hdb == emulated ide disk 1 (ide bus 0, slave) - * hdc == emulated ide disk 2 (ide bus 1, master) - * hdd == emulated ide disk 3 (ide bus 1, slave) - * - * (Uncoincidentally, these xen disk device names actually map to - * the /dev filesystem names of ide disk devices in Linux. So in - * Linux /dev/hda is the first ide disk.) So for the first part of - * our mapping we've just hardcoded the cmdk paths that we know - * qemu will use. - * - * To understand the second half of the mapping (ie, the xdf device - * that each emulated cmdk device should be mapped two) we need to - * know the solaris device node address that will be assigned to - * each xdf device. (The device node address is the decimal - * number that comes after the "xdf@" in the device path.) - * - * So the question becomes, how do we know what the xenstore device - * id for emulated disk will be? Well, it turns out that since the - * xen management tools expect the disk device names to be Linux - * device names, those same management tools assign each disk a - * device id that matches the dev_t of the corresponding device - * under Linux. (Big shocker.) This xen device name-to-id mapping - * is currently all hard coded here: - * xen.hg/tools/python/xen/util/blkif.py`blkdev_name_to_number() - * - * So looking at the code above we can see the following xen disk - * device name to xenstore device id mappings: - * 'hda' == 0t768 == ((3 * 256) + (0 * 64)) - * 'hdb' == 0t832 == ((3 * 256) + (1 * 64)) - * 'hdc' == 0t5632 == ((22 * 256) + (0 * 64)) - * 'hdd' == 0t5696 == ((22 * 256) + (1 * 64)) - */ - { "/pci@0,0/pci-ide@1,1/ide@0/cmdk@0,0", "/xpvd/xdf@768" }, - { "/pci@0,0/pci-ide@1,1/ide@0/cmdk@1,0", "/xpvd/xdf@832" }, - { "/pci@0,0/pci-ide@1,1/ide@1/cmdk@0,0", "/xpvd/xdf@5632" }, - { "/pci@0,0/pci-ide@1,1/ide@1/cmdk@1,0", "/xpvd/xdf@5696" }, - { NULL, 0 } -}; - -/* - * Private functions - */ -/* - * xdfs_get_modser() is basically a local copy of - * cmdk_get_modser() modified to work without the dadk layer. - * (which the non-pv version of the cmdk driver uses.) - */ -static int -xdfs_get_modser(xdfs_state_t *xsp, int ioccmd, char *buf, int len) -{ - struct scsi_device *scsi_device; - opaque_t ctlobjp; - dadk_ioc_string_t strarg; - char *s; - char ch; - boolean_t ret; - int i; - int tb; - - strarg.is_buf = buf; - strarg.is_size = len; - scsi_device = ddi_get_driver_private(xsp->xdfss_dip); - ctlobjp = scsi_device->sd_address.a_hba_tran; - if (CTL_IOCTL(ctlobjp, - ioccmd, (uintptr_t)&strarg, FNATIVE | FKIOCTL) != 0) - return (0); - - /* - * valid model/serial string must contain a non-zero non-space - * trim trailing spaces/NULL - */ - ret = B_FALSE; - s = buf; - for (i = 0; i < strarg.is_size; i++) { - ch = *s++; - if (ch != ' ' && ch != '\0') - tb = i + 1; - if (ch != ' ' && ch != '\0' && ch != '0') - ret = B_TRUE; - } - - if (ret == B_FALSE) - return (0); - - return (tb); -} - -/* - * xdfs_devid_modser() is basically a copy of cmdk_devid_modser() - * that has been modified to use local pv cmdk driver functions. - * - * Build a devid from the model and serial number - * Return DDI_SUCCESS or DDI_FAILURE. - */ -static int -xdfs_devid_modser(xdfs_state_t *xsp) -{ - int rc = DDI_FAILURE; - char *hwid; - int modlen; - int serlen; - - /* - * device ID is a concatenation of model number, '=', serial number. - */ - hwid = kmem_alloc(CMDK_HWIDLEN, KM_SLEEP); - modlen = xdfs_get_modser(xsp, DIOCTL_GETMODEL, hwid, CMDK_HWIDLEN); - if (modlen == 0) - goto err; - - hwid[modlen++] = '='; - serlen = xdfs_get_modser(xsp, DIOCTL_GETSERIAL, - hwid + modlen, CMDK_HWIDLEN - modlen); - if (serlen == 0) - goto err; - - hwid[modlen + serlen] = 0; - - /* Initialize the device ID, trailing NULL not included */ - rc = ddi_devid_init(xsp->xdfss_dip, DEVID_ATA_SERIAL, modlen + serlen, - hwid, (ddi_devid_t *)&xsp->xdfss_tgt_devid); - if (rc != DDI_SUCCESS) - goto err; - - kmem_free(hwid, CMDK_HWIDLEN); - return (DDI_SUCCESS); - -err: - kmem_free(hwid, CMDK_HWIDLEN); - return (DDI_FAILURE); -} - -/* - * xdfs_devid_read() is basically a local copy of - * cmdk_devid_read() modified to work without the dadk layer. - * (which the non-pv version of the cmdk driver uses.) - * - * Read a devid from on the first block of the last track of - * the last cylinder. Make sure what we read is a valid devid. - * Return DDI_SUCCESS or DDI_FAILURE. - */ -static int -xdfs_devid_read(xdfs_state_t *xsp) -{ - diskaddr_t blk; - struct dk_devid *dkdevidp; - uint_t *ip, chksum; - int i; - - if (cmlb_get_devid_block(xsp->xdfss_cmlbhandle, &blk, 0) != 0) - return (DDI_FAILURE); - - dkdevidp = kmem_zalloc(NBPSCTR, KM_SLEEP); - if (xdfs_lb_rdwr(xsp->xdfss_dip, - TG_READ, dkdevidp, blk, NBPSCTR, NULL) != 0) - goto err; - - /* Validate the revision */ - if ((dkdevidp->dkd_rev_hi != DK_DEVID_REV_MSB) || - (dkdevidp->dkd_rev_lo != DK_DEVID_REV_LSB)) - goto err; - - /* Calculate the checksum */ - chksum = 0; - ip = (uint_t *)dkdevidp; - for (i = 0; i < ((NBPSCTR - sizeof (int))/sizeof (int)); i++) - chksum ^= ip[i]; - if (DKD_GETCHKSUM(dkdevidp) != chksum) - goto err; - - /* Validate the device id */ - if (ddi_devid_valid((ddi_devid_t)dkdevidp->dkd_devid) != DDI_SUCCESS) - goto err; - - /* keep a copy of the device id */ - i = ddi_devid_sizeof((ddi_devid_t)dkdevidp->dkd_devid); - xsp->xdfss_tgt_devid = kmem_alloc(i, KM_SLEEP); - bcopy(dkdevidp->dkd_devid, xsp->xdfss_tgt_devid, i); - kmem_free(dkdevidp, NBPSCTR); - return (DDI_SUCCESS); - -err: - kmem_free(dkdevidp, NBPSCTR); - return (DDI_FAILURE); -} - -/* - * xdfs_devid_fabricate() is basically a local copy of - * cmdk_devid_fabricate() modified to work without the dadk layer. - * (which the non-pv version of the cmdk driver uses.) - * - * Create a devid and write it on the first block of the last track of - * the last cylinder. - * Return DDI_SUCCESS or DDI_FAILURE. - */ -static int -xdfs_devid_fabricate(xdfs_state_t *xsp) -{ - ddi_devid_t devid = NULL; /* devid made by ddi_devid_init */ - struct dk_devid *dkdevidp = NULL; /* devid struct stored on disk */ - diskaddr_t blk; - uint_t *ip, chksum; - int i; - - if (cmlb_get_devid_block(xsp->xdfss_cmlbhandle, &blk, 0) != 0) - return (DDI_FAILURE); - - if (ddi_devid_init(xsp->xdfss_dip, DEVID_FAB, 0, NULL, &devid) != - DDI_SUCCESS) - return (DDI_FAILURE); - - /* allocate a buffer */ - dkdevidp = kmem_zalloc(NBPSCTR, KM_SLEEP); - - /* Fill in the revision */ - dkdevidp->dkd_rev_hi = DK_DEVID_REV_MSB; - dkdevidp->dkd_rev_lo = DK_DEVID_REV_LSB; - - /* Copy in the device id */ - i = ddi_devid_sizeof(devid); - if (i > DK_DEVID_SIZE) - goto err; - bcopy(devid, dkdevidp->dkd_devid, i); - - /* Calculate the chksum */ - chksum = 0; - ip = (uint_t *)dkdevidp; - for (i = 0; i < ((NBPSCTR - sizeof (int))/sizeof (int)); i++) - chksum ^= ip[i]; - - /* Fill in the checksum */ - DKD_FORMCHKSUM(chksum, dkdevidp); - - if (xdfs_lb_rdwr(xsp->xdfss_dip, - TG_WRITE, dkdevidp, blk, NBPSCTR, NULL) != 0) - goto err; - - kmem_free(dkdevidp, NBPSCTR); - - xsp->xdfss_tgt_devid = devid; - return (DDI_SUCCESS); - -err: - if (dkdevidp != NULL) - kmem_free(dkdevidp, NBPSCTR); - if (devid != NULL) - ddi_devid_free(devid); - return (DDI_FAILURE); -} - -/* - * xdfs_rwcmd_copyin() is a duplicate of rwcmd_copyin(). - */ -static int -xdfs_rwcmd_copyin(struct dadkio_rwcmd *rwcmdp, caddr_t inaddr, int flag) -{ - switch (ddi_model_convert_from(flag)) { - case DDI_MODEL_ILP32: { - struct dadkio_rwcmd32 cmd32; - - if (ddi_copyin(inaddr, &cmd32, - sizeof (struct dadkio_rwcmd32), flag)) { - return (EFAULT); - } - - rwcmdp->cmd = cmd32.cmd; - rwcmdp->flags = cmd32.flags; - rwcmdp->blkaddr = (blkaddr_t)cmd32.blkaddr; - rwcmdp->buflen = cmd32.buflen; - rwcmdp->bufaddr = (caddr_t)(intptr_t)cmd32.bufaddr; - /* - * Note: we do not convert the 'status' field, - * as it should not contain valid data at this - * point. - */ - bzero(&rwcmdp->status, sizeof (rwcmdp->status)); - break; - } - case DDI_MODEL_NONE: { - if (ddi_copyin(inaddr, rwcmdp, - sizeof (struct dadkio_rwcmd), flag)) { - return (EFAULT); - } - } - } - return (0); -} - -/* - * xdfs_rwcmd_copyout() is a duplicate of rwcmd_copyout(). - */ -static int -xdfs_rwcmd_copyout(struct dadkio_rwcmd *rwcmdp, caddr_t outaddr, int flag) -{ - switch (ddi_model_convert_from(flag)) { - case DDI_MODEL_ILP32: { - struct dadkio_rwcmd32 cmd32; - - cmd32.cmd = rwcmdp->cmd; - cmd32.flags = rwcmdp->flags; - cmd32.blkaddr = rwcmdp->blkaddr; - cmd32.buflen = rwcmdp->buflen; - ASSERT64(((uintptr_t)rwcmdp->bufaddr >> 32) == 0); - cmd32.bufaddr = (caddr32_t)(uintptr_t)rwcmdp->bufaddr; - - cmd32.status.status = rwcmdp->status.status; - cmd32.status.resid = rwcmdp->status.resid; - cmd32.status.failed_blk_is_valid = - rwcmdp->status.failed_blk_is_valid; - cmd32.status.failed_blk = rwcmdp->status.failed_blk; - cmd32.status.fru_code_is_valid = - rwcmdp->status.fru_code_is_valid; - cmd32.status.fru_code = rwcmdp->status.fru_code; - - bcopy(rwcmdp->status.add_error_info, - cmd32.status.add_error_info, DADKIO_ERROR_INFO_LEN); - - if (ddi_copyout(&cmd32, outaddr, - sizeof (struct dadkio_rwcmd32), flag)) - return (EFAULT); - break; - } - case DDI_MODEL_NONE: { - if (ddi_copyout(rwcmdp, outaddr, - sizeof (struct dadkio_rwcmd), flag)) - return (EFAULT); - } - } - return (0); -} - -static int -xdfs_dioctl_rwcmd(dev_t dev, intptr_t arg, int flag) -{ - struct dadkio_rwcmd *rwcmdp; - struct iovec aiov; - struct uio auio; - struct buf *bp; - int rw, status; - - rwcmdp = kmem_alloc(sizeof (struct dadkio_rwcmd), KM_SLEEP); - status = xdfs_rwcmd_copyin(rwcmdp, (caddr_t)arg, flag); - - if (status != 0) - goto out; - - switch (rwcmdp->cmd) { - case DADKIO_RWCMD_READ: - case DADKIO_RWCMD_WRITE: - break; - default: - status = EINVAL; - goto out; - } - - bzero((caddr_t)&aiov, sizeof (struct iovec)); - aiov.iov_base = rwcmdp->bufaddr; - aiov.iov_len = rwcmdp->buflen; - - bzero((caddr_t)&auio, sizeof (struct uio)); - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_loffset = (offset_t)rwcmdp->blkaddr * (offset_t)XB_BSIZE; - auio.uio_resid = rwcmdp->buflen; - auio.uio_segflg = (flag & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE; - - /* - * Tell the xdf driver that this I/O request is using an absolute - * offset. - */ - bp = getrbuf(KM_SLEEP); - bp->b_private = (void *)XB_SLICE_NONE; - - rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ? B_WRITE : B_READ); - status = physio(xdfs_strategy, bp, dev, rw, xdfs_minphys, &auio); - - biofini(bp); - kmem_free(bp, sizeof (buf_t)); - - if (status == 0) - status = xdfs_rwcmd_copyout(rwcmdp, (caddr_t)arg, flag); - -out: - kmem_free(rwcmdp, sizeof (struct dadkio_rwcmd)); - return (status); -} - - -/* - * xdf_shell callback functions - */ -/*ARGSUSED*/ -int -xdfs_c_ioctl(xdfs_state_t *xsp, dev_t dev, int part, - int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp, boolean_t *done) -{ - *done = B_TRUE; - switch (cmd) { - default: - *done = B_FALSE; - return (0); - case DKIOCLOCK: - case DKIOCUNLOCK: - case FDEJECT: - case DKIOCEJECT: - case CDROMEJECT: { - /* we don't support ejectable devices */ - return (ENOTTY); - } - case DKIOCGETWCE: - case DKIOCSETWCE: { - /* we don't support write cache get/set */ - return (EIO); - } - case DKIOCADDBAD: { - /* - * This is for ata/ide bad block handling. It is supposed - * to cause the driver to re-read the bad block list and - * alternate map after it has been updated. Our driver - * will refuse to attach to any disk which has a bad blocks - * list defined, so there really isn't much to do here. - */ - return (0); - } - case DKIOCGETDEF: { - /* - * I can't actually find any code that utilizes this ioctl, - * hence we're leaving it explicitly unimplemented. - */ - ASSERT("ioctl cmd unsupported by xdf shell: DKIOCGETDEF"); - return (EIO); - } - case DIOCTL_RWCMD: { - /* - * This just seems to just be an alternate interface for - * reading and writing the disk. Great, another way to - * do the same thing... - */ - return (xdfs_dioctl_rwcmd(dev, arg, flag)); - } - case DKIOCINFO: { - int instance = ddi_get_instance(xsp->xdfss_dip); - dev_info_t *dip = xsp->xdfss_dip; - struct dk_cinfo info; - int rv; - - /* Pass on the ioctl request, save the response */ - if ((rv = ldi_ioctl(xsp->xdfss_tgt_lh[part], - cmd, (intptr_t)&info, FKIOCTL, credp, rvalp)) != 0) - return (rv); - - /* Update controller info */ - info.dki_cnum = ddi_get_instance(ddi_get_parent(dip)); - (void) strlcpy(info.dki_cname, - ddi_get_name(ddi_get_parent(dip)), sizeof (info.dki_cname)); - - /* Update unit info. */ - if (info.dki_ctype == DKC_VBD) - info.dki_ctype = DKC_DIRECT; - info.dki_unit = instance; - (void) strlcpy(info.dki_dname, - ddi_driver_name(dip), sizeof (info.dki_dname)); - info.dki_addr = 1; - - if (ddi_copyout(&info, (void *)arg, sizeof (info), flag)) - return (EFAULT); - return (0); - } - } /* switch (cmd) */ - /*NOTREACHED*/ -} - -/* - * xdfs_c_devid_setup() is a slightly modified copy of cmdk_devid_setup(). - * - * Create and register the devid. - * There are 4 different ways we can get a device id: - * 1. Already have one - nothing to do - * 2. Build one from the drive's model and serial numbers - * 3. Read one from the disk (first sector of last track) - * 4. Fabricate one and write it on the disk. - * If any of these succeeds, register the deviceid - */ -void -xdfs_c_devid_setup(xdfs_state_t *xsp) -{ - int rc; - - /* Try options until one succeeds, or all have failed */ - - /* 1. All done if already registered */ - - if (xsp->xdfss_tgt_devid != NULL) - return; - - /* 2. Build a devid from the model and serial number */ - rc = xdfs_devid_modser(xsp); - if (rc != DDI_SUCCESS) { - /* 3. Read devid from the disk, if present */ - rc = xdfs_devid_read(xsp); - - /* 4. otherwise make one up and write it on the disk */ - if (rc != DDI_SUCCESS) - rc = xdfs_devid_fabricate(xsp); - } - - /* If we managed to get a devid any of the above ways, register it */ - if (rc == DDI_SUCCESS) - (void) ddi_devid_register(xsp->xdfss_dip, xsp->xdfss_tgt_devid); -} - -int -xdfs_c_getpgeom(dev_info_t *dip, cmlb_geom_t *pgeom) -{ - struct scsi_device *scsi_device; - struct tgdk_geom tgdk_geom; - opaque_t ctlobjp; - int err; - - scsi_device = ddi_get_driver_private(dip); - ctlobjp = scsi_device->sd_address.a_hba_tran; - if ((err = CTL_IOCTL(ctlobjp, - DIOCTL_GETPHYGEOM, (uintptr_t)&tgdk_geom, FKIOCTL)) != 0) - return (err); - - /* This driver won't work if this isn't true */ - ASSERT(tgdk_geom.g_secsiz == XB_BSIZE); - - pgeom->g_ncyl = tgdk_geom.g_cyl; - pgeom->g_acyl = tgdk_geom.g_acyl; - pgeom->g_nhead = tgdk_geom.g_head; - pgeom->g_nsect = tgdk_geom.g_sec; - pgeom->g_secsize = tgdk_geom.g_secsiz; - pgeom->g_capacity = tgdk_geom.g_cap; - pgeom->g_intrlv = 1; - pgeom->g_rpm = 3600; - return (0); -} - -boolean_t -xdfs_c_bb_check(xdfs_state_t *xsp) -{ - struct alts_parttbl *ap; - diskaddr_t nblocks, blk; - uint32_t altused, altbase, altlast; - uint16_t vtoctag; - int alts; - - /* find slice with V_ALTSCTR tag */ - for (alts = 0; alts < NDKMAP; alts++) { - - if (cmlb_partinfo(xsp->xdfss_cmlbhandle, alts, - &nblocks, &blk, NULL, &vtoctag, 0) != 0) { - /* no partition table exists */ - return (B_FALSE); - } - - if ((vtoctag == V_ALTSCTR) && (nblocks > 1)) - break; - } - if (alts >= NDKMAP) - return (B_FALSE); /* no V_ALTSCTR slice defined */ - - /* read in ALTS label block */ - ap = kmem_zalloc(NBPSCTR, KM_SLEEP); - if (xdfs_lb_rdwr(xsp->xdfss_dip, TG_READ, ap, blk, NBPSCTR, NULL) != 0) - goto err; - - altused = ap->alts_ent_used; /* number of BB entries */ - altbase = ap->alts_ent_base; /* blk offset from begin slice */ - altlast = ap->alts_ent_end; /* blk offset to last block */ - - if ((altused == 0) || (altbase < 1) || - (altbase > altlast) || (altlast >= nblocks)) - goto err; - - /* we found bad block mappins */ - kmem_free(ap, NBPSCTR); - return (B_TRUE); - -err: - kmem_free(ap, NBPSCTR); - return (B_FALSE); -} - -char * -xdfs_c_cmlb_node_type(xdfs_state_t *xsp) -{ - return (xsp->xdfss_tgt_is_cd ? DDI_NT_CD : DDI_NT_BLOCK); -} - -/*ARGSUSED*/ -int -xdfs_c_cmlb_alter_behavior(xdfs_state_t *xsp) -{ - return (xsp->xdfss_tgt_is_cd ? - 0 : CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT); -} - -/*ARGSUSED*/ -void -xdfs_c_attach(xdfs_state_t *xsp) -{ -} diff --git a/usr/src/uts/i86pc/i86hvm/io/pv_rtls.c b/usr/src/uts/i86pc/i86hvm/io/pv_rtls.c deleted file mode 100644 index 8f97b77e43..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/pv_rtls.c +++ /dev/null @@ -1,79 +0,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 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 - -struct dev_ops pv_rtls_ops = { - DEVO_REV, - 0, - NULL, - nulldev, - nulldev, - NULL, - NULL, - nodev, - NULL, - NULL, - NULL, - ddi_quiesce_not_needed, /* quiesce */ -}; - -/* - * Module linkage information for the kernel. - */ -static struct modldrv modldrv = { - &mod_driverops, - "xVM rtls stub", - &pv_rtls_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); -} diff --git a/usr/src/uts/i86pc/i86hvm/io/pv_sd.c b/usr/src/uts/i86pc/i86hvm/io/pv_sd.c deleted file mode 100644 index 74edb42907..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/pv_sd.c +++ /dev/null @@ -1,187 +0,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 - -/* - * We're emulating (and possibly layering on top of) sd devices, so xdf - * disk unit mappings must match up with sd disk unit mappings'. - */ -#if !defined(XDF_PSHIFT) -#error "can't find definition for xdf unit mappings - XDF_PSHIFT" -#endif /* XDF_PSHIFT */ - -#if !defined(SDUNIT_SHIFT) -#error "can't find definition for cmdk unit mappings - SDUNIT_SHIFT" -#endif /* SDUNIT_SHIFT */ - -#if ((XDF_PSHIFT - SDUNIT_SHIFT) != 0) -#error "sd and xdf unit mappings don't match." -#endif /* ((XDF_PSHIFT - SDUNIT_SHIFT) != 0) */ - -extern const struct dev_ops sd_ops; -extern void *sd_state; - -/* - * Globals required by xdf_shell.c - */ -const char *xdfs_c_name = "sd"; -const char *xdfs_c_linkinfo = "PV SCSI Disk Driver"; -void **xdfs_c_hvm_ss = &sd_state; -const size_t xdfs_c_hvm_ss_size = sizeof (struct sd_lun); -const struct dev_ops *xdfs_c_hvm_dev_ops = &sd_ops; - -const xdfs_h2p_map_t xdfs_c_h2p_map[] = { - { "/pci@0,0/pci-ide@1,1/ide@0/sd@0,0", "/xpvd/xdf@768" }, - { "/pci@0,0/pci-ide@1,1/ide@0/sd@1,0", "/xpvd/xdf@832" }, - { "/pci@0,0/pci-ide@1,1/ide@1/sd@0,0", "/xpvd/xdf@5632" }, - { "/pci@0,0/pci-ide@1,1/ide@1/sd@1,0", "/xpvd/xdf@5696" }, - { NULL, 0 } -}; - -/*ARGSUSED*/ -int -xdfs_c_ioctl(xdfs_state_t *xsp, dev_t dev, int part, - int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp, boolean_t *done) -{ - dev_info_t *dip = xsp->xdfss_dip; - int instance = ddi_get_instance(dip); - int rv; - - *done = B_TRUE; - switch (cmd) { - case DKIOCINFO: { - struct dk_cinfo info; - - /* Pass on the ioctl request, save the response */ - if ((rv = ldi_ioctl(xsp->xdfss_tgt_lh[part], - cmd, (intptr_t)&info, FKIOCTL, credp, rvalp)) != 0) - return (rv); - - /* Update controller info */ - info.dki_cnum = ddi_get_instance(ddi_get_parent(dip)); - (void) strlcpy(info.dki_cname, - ddi_get_name(ddi_get_parent(dip)), sizeof (info.dki_cname)); - - /* Update unit info. */ - if (info.dki_ctype == DKC_VBD) { - /* - * Normally a real scsi device would report the - * controller type as DKC_SCSI_CCS. But we don't - * emulate a real scsi controller. (Which becomes - * apparent if anyone tries to issue us a uscsi(7i) - * command.) So instead of reporting DKC_SCSI_CCS, - * we report DKC_UNKNOWN. - */ - info.dki_ctype = DKC_UNKNOWN; - } - info.dki_unit = instance; - (void) strlcpy(info.dki_dname, - ddi_driver_name(dip), sizeof (info.dki_dname)); - info.dki_addr = 1; - - if (ddi_copyout(&info, (void *)arg, sizeof (info), flag)) - return (EFAULT); - - return (0); - } - default: - *done = B_FALSE; - return (0); - } /* switch (cmd) */ - /*NOTREACHED*/ -} - -/*ARGSUSED*/ -void -xdfs_c_devid_setup(xdfs_state_t *xsp) -{ - /* - * Currently we only support cdrom devices, which don't have - * devids associated with them. - */ - ASSERT("cdrom devices don't have a devid"); -} - -/*ARGSUSED*/ -int -xdfs_c_getpgeom(dev_info_t *dip, cmlb_geom_t *pgeom) -{ - /* - * Currently we only support cdrom devices, which don't have - * a physical geometry, so this routine should never get - * invoked. - */ - ASSERT("cdrom devices don't have any physical geometry"); - return (-1); -} - -/*ARGSUSED*/ -boolean_t -xdfs_c_bb_check(xdfs_state_t *xsp) -{ - /* - * Currently we only support cdrom devices, which don't have - * bad blocks, so this routine should never get invoked. - */ - ASSERT("cdrom devices don't support bad block mappings"); - return (B_TRUE); -} - -char * -xdfs_c_cmlb_node_type(xdfs_state_t *xsp) -{ - return (xsp->xdfss_tgt_is_cd ? DDI_NT_CD_CHAN : DDI_NT_BLOCK_CHAN); -} - -/*ARGSUSED*/ -int -xdfs_c_cmlb_alter_behavior(xdfs_state_t *xsp) -{ - return (0); -} - -void -xdfs_c_attach(xdfs_state_t *xsp) -{ - dev_info_t *dip = xsp->xdfss_dip; - int dtype = DTYPE_DIRECT; - - if (xsp->xdfss_tgt_is_cd) { - dtype = DTYPE_RODIRECT; - (void) ddi_prop_create(DDI_DEV_T_NONE, dip, - DDI_PROP_CANSLEEP, "removable-media", NULL, 0); - } - - /* - * We use ndi_* instead of ddi_* because it will result in - * INQUIRY_DEVICE_TYPE being a hardware property instead - * or a driver property - */ - (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, - INQUIRY_DEVICE_TYPE, dtype); -} diff --git a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c b/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c deleted file mode 100644 index 6255c5ddaf..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c +++ /dev/null @@ -1,1284 +0,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 - -/* - * General Notes - * - * We don't support disks with bad block mappins. We have this - * limitation because the underlying xdf driver doesn't support - * bad block remapping. If there is a need to support this feature - * it should be added directly to the xdf driver and we should just - * pass requests strait on through and let it handle the remapping. - * Also, it's probably worth pointing out that most modern disks do bad - * block remapping internally in the hardware so there's actually less - * of a chance of us ever discovering bad blocks. Also, in most cases - * this driver (and the xdf driver) will only be used with virtualized - * devices, so one might wonder why a virtual device would ever actually - * experience bad blocks. To wrap this up, you might be wondering how - * these bad block mappings get created and how they are managed. Well, - * there are two tools for managing bad block mappings, format(1M) and - * addbadsec(1M). Format(1M) can be used to do a surface scan of a disk - * to attempt to find bad block and create mappings for them. Format(1M) - * and addbadsec(1M) can also be used to edit existing mappings that may - * be saved on the disk. - * - * The underlying PV driver that this driver passes on requests to is the - * xdf driver. Since in most cases the xdf driver doesn't deal with - * physical disks it has it's own algorithm for assigning a physical - * geometry to a virtual disk (ie, cylinder count, head count, etc.) - * The default values chosen by the xdf driver may not match those - * assigned to a disk by a hardware disk emulator in an HVM environment. - * This is a problem since these physical geometry attributes affect - * things like the partition table, backup label location, etc. So - * to emulate disk devices correctly we need to know the physical geometry - * that was assigned to a disk at the time of it's initalization. - * Normally in an HVM environment this information will passed to - * the BIOS and operating system from the hardware emulator that is - * emulating the disk devices. In the case of a solaris dom0+xvm - * this would be qemu. So to work around this issue, this driver will - * query the emulated hardware to get the assigned physical geometry - * and then pass this geometry onto the xdf driver so that it can use it. - * But really, this information is essentially metadata about the disk - * that should be kept with the disk image itself. (Assuming or course - * that a disk image is the actual backingstore for this emulated device.) - * This metadata should also be made available to PV drivers via a common - * mechanism, probably the xenstore. The fact that this metadata isn't - * available outside of HVM domains means that it's difficult to move - * disks between HVM and PV domains, since a fully PV domain will have no - * way of knowing what the correct geometry of the target device is. - * (Short of reading the disk, looking for things like partition tables - * and labels, and taking a best guess at what the geometry was when - * the disk was initialized. Unsuprisingly, qemu actually does this.) - * - * This driver has to map xdf shell device instances into their corresponding - * xdf device instances. We have to do this to ensure that when a user - * accesses a emulated xdf shell device we map those accesses to the proper - * paravirtualized device. Basically what we need to know is how multiple - * 'disk' entries in a domU configuration file get mapped to emulated - * xdf shell devices and to xdf devices. The 'disk' entry to xdf instance - * mappings we know because those are done within the Solaris xvdi code - * and the xpvd nexus driver. But the config to emulated devices mappings - * are handled entirely within the xen management tool chain and the - * hardware emulator. Since all the tools that establish these mappings - * live in dom0, dom0 should really supply us with this information, - * probably via the xenstore. Unfortunatly it doesn't so, since there's - * no good way to determine this mapping dynamically, this driver uses - * a hard coded set of static mappings. These mappings are hardware - * emulator specific because each different hardware emulator could have - * a different device tree with different xdf shell device paths. This - * means that if we want to continue to use this static mapping approach - * to allow Solaris to run on different hardware emulators we'll have - * to analyze each of those emulators to determine what paths they - * use and hard code those paths into this driver. yech. This metadata - * really needs to be supplied to us by dom0. - * - * This driver access underlying xdf nodes. Unfortunatly, devices - * must create minor nodes during attach, and for disk devices to create - * minor nodes, they have to look at the label on the disk, so this means - * that disk drivers must be able to access a disk contents during - * attach. That means that this disk driver must be able to access - * underlying xdf nodes during attach. Unfortunatly, due to device tree - * locking restrictions, we cannot have an attach operation occuring on - * this device and then attempt to access another device which may - * cause another attach to occur in a different device tree branch - * since this could result in deadlock. Hence, this driver can only - * access xdf device nodes that we know are attached, and it can't use - * any ddi interfaces to access those nodes if those interfaces could - * trigger an attach of the xdf device. So this driver works around - * these restrictions by talking directly to xdf devices via - * xdf_hvm_hold(). This interface takes a pathname to an xdf device, - * and if that device is already attached then it returns the a held dip - * pointer for that device node. This prevents us from getting into - * deadlock situations, but now we need a mechanism to ensure that all - * the xdf device nodes this driver might access are attached before - * this driver tries to access them. This is accomplished via the - * hvmboot_rootconf() callback which is invoked just before root is - * mounted. hvmboot_rootconf() will attach xpvd and tell it to configure - * all xdf device visible to the system. All these xdf device nodes - * will also be marked with the "ddi-no-autodetach" property so that - * once they are configured, the will not be automatically unconfigured. - * The only way that they could be unconfigured is if the administrator - * explicitly attempts to unload required modules via rem_drv(1M) - * or modunload(1M). - */ - -/* - * 16 paritions + fdisk (see xdf.h) - */ -#define XDFS_DEV2UNIT(dev) XDF_INST((getminor((dev)))) -#define XDFS_DEV2PART(dev) XDF_PART((getminor((dev)))) - -#define OTYP_VALID(otyp) ((otyp == OTYP_BLK) || \ - (otyp == OTYP_CHR) || \ - (otyp == OTYP_LYR)) - -#define XDFS_NODES 4 - -#define XDFS_HVM_MODE(sp) (XDFS_HVM_STATE(sp)->xdfs_hs_mode) -#define XDFS_HVM_DIP(sp) (XDFS_HVM_STATE(sp)->xdfs_hs_dip) -#define XDFS_HVM_PATH(sp) (XDFS_HVM_STATE(sp)->xdfs_hs_path) -#define XDFS_HVM_STATE(sp) \ - ((xdfs_hvm_state_t *)(&((char *)(sp))[XDFS_HVM_STATE_OFFSET])) -#define XDFS_HVM_STATE_OFFSET (xdfs_ss_size - sizeof (xdfs_hvm_state_t)) -#define XDFS_HVM_SANE(sp) \ - ASSERT(XDFS_HVM_MODE(sp)); \ - ASSERT(XDFS_HVM_DIP(sp) != NULL); \ - ASSERT(XDFS_HVM_PATH(sp) != NULL); - - -typedef struct xdfs_hvm_state { - boolean_t xdfs_hs_mode; - dev_info_t *xdfs_hs_dip; - char *xdfs_hs_path; -} xdfs_hvm_state_t; - -/* local function and structure prototypes */ -static int xdfs_iodone(struct buf *); -static boolean_t xdfs_isopen_part(xdfs_state_t *, int); -static boolean_t xdfs_isopen(xdfs_state_t *); -static cmlb_tg_ops_t xdfs_lb_ops; - -/* - * Globals - */ -major_t xdfs_major; -#define xdfs_hvm_dev_ops (xdfs_c_hvm_dev_ops) -#define xdfs_hvm_cb_ops (xdfs_hvm_dev_ops->devo_cb_ops) - -/* - * Private globals - */ -volatile boolean_t xdfs_pv_disable = B_FALSE; -static void *xdfs_ssp; -static size_t xdfs_ss_size; - -/* - * Private helper functions - */ -static boolean_t -xdfs_tgt_hold(xdfs_state_t *xsp) -{ - mutex_enter(&xsp->xdfss_mutex); - ASSERT(xsp->xdfss_tgt_holds >= 0); - if (!xsp->xdfss_tgt_attached) { - mutex_exit(&xsp->xdfss_mutex); - return (B_FALSE); - } - xsp->xdfss_tgt_holds++; - mutex_exit(&xsp->xdfss_mutex); - return (B_TRUE); -} - -static void -xdfs_tgt_release(xdfs_state_t *xsp) -{ - mutex_enter(&xsp->xdfss_mutex); - ASSERT(xsp->xdfss_tgt_attached); - ASSERT(xsp->xdfss_tgt_holds > 0); - if (--xsp->xdfss_tgt_holds == 0) - cv_broadcast(&xsp->xdfss_cv); - mutex_exit(&xsp->xdfss_mutex); -} - -/*ARGSUSED*/ -static int -xdfs_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv; - - if (xsp == NULL) - return (ENXIO); - - if (!xdfs_tgt_hold(xsp)) - return (ENXIO); - - if (cmd == TG_GETVIRTGEOM) { - cmlb_geom_t pgeom, *vgeomp; - diskaddr_t capacity; - - /* - * The native xdf driver doesn't support this ioctl. - * Intead of passing it on, emulate it here so that the - * results look the same as what we get for a real xdf - * shell device. - * - * Get the real size of the device - */ - if ((rv = xdf_lb_getinfo(xsp->xdfss_tgt_dip, - TG_GETPHYGEOM, &pgeom, tg_cookie)) != 0) - goto out; - capacity = pgeom.g_capacity; - - /* - * If the controller returned us something that doesn't - * really fit into an Int 13/function 8 geometry - * result, just fail the ioctl. See PSARC 1998/313. - */ - if (capacity >= (63 * 254 * 1024)) { - rv = EINVAL; - goto out; - } - - vgeomp = (cmlb_geom_t *)arg; - vgeomp->g_capacity = capacity; - vgeomp->g_nsect = 63; - vgeomp->g_nhead = 254; - vgeomp->g_ncyl = capacity / (63 * 254); - vgeomp->g_acyl = 0; - vgeomp->g_secsize = 512; - vgeomp->g_intrlv = 1; - vgeomp->g_rpm = 3600; - rv = 0; - goto out; - } - - rv = xdf_lb_getinfo(xsp->xdfss_tgt_dip, cmd, arg, tg_cookie); - -out: - xdfs_tgt_release(xsp); - return (rv); -} - -static boolean_t -xdfs_isopen_part(xdfs_state_t *xsp, int part) -{ - int otyp; - - ASSERT(MUTEX_HELD(&xsp->xdfss_mutex)); - for (otyp = 0; (otyp < OTYPCNT); otyp++) { - if (xsp->xdfss_otyp_count[otyp][part] != 0) { - ASSERT(xsp->xdfss_tgt_attached); - ASSERT(xsp->xdfss_tgt_holds >= 0); - return (B_TRUE); - } - } - return (B_FALSE); -} - -static boolean_t -xdfs_isopen(xdfs_state_t *xsp) -{ - int part; - - ASSERT(MUTEX_HELD(&xsp->xdfss_mutex)); - for (part = 0; part < XDF_PEXT; part++) { - if (xdfs_isopen_part(xsp, part)) - return (B_TRUE); - } - return (B_FALSE); -} - -static int -xdfs_iodone(struct buf *bp) -{ - struct buf *bp_orig = bp->b_chain; - - /* Propegate back the io results */ - bp_orig->b_resid = bp->b_resid; - bioerror(bp_orig, geterror(bp)); - biodone(bp_orig); - - freerbuf(bp); - return (0); -} - -static int -xdfs_cmlb_attach(xdfs_state_t *xsp) -{ - return (cmlb_attach(xsp->xdfss_dip, &xdfs_lb_ops, - xsp->xdfss_tgt_is_cd ? DTYPE_RODIRECT : DTYPE_DIRECT, - xdf_is_rm(xsp->xdfss_tgt_dip), - B_TRUE, - xdfs_c_cmlb_node_type(xsp), - xdfs_c_cmlb_alter_behavior(xsp), - xsp->xdfss_cmlbhandle, 0)); -} - -static boolean_t -xdfs_tgt_probe(xdfs_state_t *xsp, dev_info_t *tgt_dip) -{ - cmlb_geom_t pgeom; - int tgt_instance = ddi_get_instance(tgt_dip); - - ASSERT(MUTEX_HELD(&xsp->xdfss_mutex)); - ASSERT(!xdfs_isopen(xsp)); - ASSERT(!xsp->xdfss_tgt_attached); - - xsp->xdfss_tgt_dip = tgt_dip; - xsp->xdfss_tgt_holds = 0; - xsp->xdfss_tgt_dev = makedevice(ddi_driver_major(tgt_dip), - XDF_MINOR(tgt_instance, 0)); - ASSERT((xsp->xdfss_tgt_dev & XDF_PMASK) == 0); - xsp->xdfss_tgt_is_cd = xdf_is_cd(tgt_dip); - - /* - * GROSS HACK ALERT! GROSS HACK ALERT! - * - * Before we can initialize the cmlb layer, we have to tell the - * underlying xdf device what it's physical geometry should be. - * See the block comments at the top of this file for more info. - */ - if (!xsp->xdfss_tgt_is_cd && - ((xdfs_c_getpgeom(xsp->xdfss_dip, &pgeom) != 0) || - (xdf_hvm_setpgeom(xsp->xdfss_tgt_dip, &pgeom) != 0))) - return (B_FALSE); - - /* - * Force the xdf front end driver to connect to the backend. From - * the solaris device tree perspective, the xdf driver devinfo node - * is already in the ATTACHED state. (Otherwise xdf_hvm_hold() - * would not have returned a dip.) But this doesn't mean that the - * xdf device has actually established a connection to it's back - * end driver. For us to be able to access the xdf device it needs - * to be connected. - */ - if (!xdf_hvm_connect(xsp->xdfss_tgt_dip)) { - cmn_err(CE_WARN, "pv driver failed to connect: %s", - xsp->xdfss_pv); - return (B_FALSE); - } - - if (xsp->xdfss_tgt_is_cd && !xdf_media_req_supported(tgt_dip)) { - /* - * Unfortunatly, the dom0 backend driver doesn't support - * important media request operations like eject, so fail - * the probe (this should cause us to fall back to emulated - * hvm device access, which does support things like eject). - */ - return (B_FALSE); - } - - /* create kstat for iostat(1M) */ - if (xdf_kstat_create(xsp->xdfss_tgt_dip, (char *)xdfs_c_name, - tgt_instance) != 0) - return (B_FALSE); - - /* - * Now we need to mark ourselves as attached and drop xdfss_mutex. - * We do this because the final steps in the attach process will - * need to access the underlying disk to read the label and - * possibly the devid. - */ - xsp->xdfss_tgt_attached = B_TRUE; - mutex_exit(&xsp->xdfss_mutex); - - if (!xsp->xdfss_tgt_is_cd && xdfs_c_bb_check(xsp)) { - cmn_err(CE_WARN, "pv disks with bad blocks are unsupported: %s", - xsp->xdfss_hvm); - mutex_enter(&xsp->xdfss_mutex); - xdf_kstat_delete(xsp->xdfss_tgt_dip); - xsp->xdfss_tgt_attached = B_FALSE; - return (B_FALSE); - } - - /* - * Initalize cmlb. Note that for partition information cmlb - * will access the underly xdf disk device directly via - * xdfs_lb_rdwr() and xdfs_lb_getinfo(). There are no - * layered driver handles associated with this access because - * it is a direct disk access that doesn't go through - * any of the device nodes exported by the xdf device (since - * all exported device nodes only reflect the portion of - * the device visible via the partition/slice that the node - * is associated with.) So while not observable via the LDI, - * this direct disk access is ok since we're actually holding - * the target device. - */ - if (xdfs_cmlb_attach(xsp) != 0) { - mutex_enter(&xsp->xdfss_mutex); - xdf_kstat_delete(xsp->xdfss_tgt_dip); - xsp->xdfss_tgt_attached = B_FALSE; - return (B_FALSE); - } - - /* setup devid string */ - xsp->xdfss_tgt_devid = NULL; - if (!xsp->xdfss_tgt_is_cd) - xdfs_c_devid_setup(xsp); - - (void) cmlb_validate(xsp->xdfss_cmlbhandle, 0, 0); - - /* Have the system report any newly created device nodes */ - ddi_report_dev(xsp->xdfss_dip); - - mutex_enter(&xsp->xdfss_mutex); - return (B_TRUE); -} - -static boolean_t -xdfs_tgt_detach(xdfs_state_t *xsp) -{ - ASSERT(MUTEX_HELD(&xsp->xdfss_mutex)); - ASSERT(xsp->xdfss_tgt_attached); - ASSERT(xsp->xdfss_tgt_holds >= 0); - - if ((xdfs_isopen(xsp)) || (xsp->xdfss_tgt_holds != 0)) - return (B_FALSE); - - ddi_devid_unregister(xsp->xdfss_dip); - if (xsp->xdfss_tgt_devid != NULL) - ddi_devid_free(xsp->xdfss_tgt_devid); - - xdf_kstat_delete(xsp->xdfss_tgt_dip); - xsp->xdfss_tgt_attached = B_FALSE; - return (B_TRUE); -} - -/* - * Xdf_shell interfaces that may be called from outside this file. - */ -void -xdfs_minphys(struct buf *bp) -{ - xdfmin(bp); -} - -/* - * Cmlb ops vector, allows the cmlb module to directly access the entire - * xdf disk device without going through any partitioning layers. - */ -int -xdfs_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr, - diskaddr_t start, size_t count, void *tg_cookie) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv; - - if (xsp == NULL) - return (ENXIO); - - if (!xdfs_tgt_hold(xsp)) - return (ENXIO); - - rv = xdf_lb_rdwr(xsp->xdfss_tgt_dip, - cmd, bufaddr, start, count, tg_cookie); - - xdfs_tgt_release(xsp); - return (rv); -} - -/* - * Driver PV and HVM cb_ops entry points - */ -/*ARGSUSED*/ -static int -xdfs_open(dev_t *dev_p, int flag, int otyp, cred_t *credp) -{ - ldi_ident_t li; - dev_t dev = *dev_p; - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - dev_t tgt_devt = xsp->xdfss_tgt_dev | part; - int err = 0; - - if ((otyp < 0) || (otyp >= OTYPCNT)) - return (EINVAL); - - if (XDFS_HVM_MODE(xsp)) { - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_open(dev_p, flag, otyp, credp)); - } - - /* allocate an ldi handle */ - VERIFY(ldi_ident_from_dev(*dev_p, &li) == 0); - - mutex_enter(&xsp->xdfss_mutex); - - /* - * We translate all device opens (chr, blk, and lyr) into - * block device opens. Why? Because for all the opens that - * come through this driver, we only keep around one LDI handle. - * So that handle can only be of one open type. The reason - * that we choose the block interface for this is that to use - * the block interfaces for a device the system needs to allocate - * buf_ts, which are associated with system memory which can act - * as a cache for device data. So normally when a block device - * is closed the system will ensure that all these pages get - * flushed out of memory. But if we were to open the device - * as a character device, then when we went to close the underlying - * device (even if we had invoked the block interfaces) any data - * remaining in memory wouldn't necessairly be flushed out - * before the device was closed. - */ - if (xsp->xdfss_tgt_lh[part] == NULL) { - ASSERT(!xdfs_isopen_part(xsp, part)); - - err = ldi_open_by_dev(&tgt_devt, OTYP_BLK, flag, credp, - &xsp->xdfss_tgt_lh[part], li); - - if (err != 0) { - mutex_exit(&xsp->xdfss_mutex); - ldi_ident_release(li); - return (err); - } - - /* Disk devices really shouldn't clone */ - ASSERT(tgt_devt == (xsp->xdfss_tgt_dev | part)); - } else { - ldi_handle_t lh_tmp; - - ASSERT(xdfs_isopen_part(xsp, part)); - - /* do ldi open/close to get flags and cred check */ - err = ldi_open_by_dev(&tgt_devt, OTYP_BLK, flag, credp, - &lh_tmp, li); - if (err != 0) { - mutex_exit(&xsp->xdfss_mutex); - ldi_ident_release(li); - return (err); - } - - /* Disk devices really shouldn't clone */ - ASSERT(tgt_devt == (xsp->xdfss_tgt_dev | part)); - (void) ldi_close(lh_tmp, flag, credp); - } - ldi_ident_release(li); - - xsp->xdfss_otyp_count[otyp][part]++; - - mutex_exit(&xsp->xdfss_mutex); - return (0); -} - -/*ARGSUSED*/ -static int -xdfs_close(dev_t dev, int flag, int otyp, cred_t *credp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int err = 0; - - ASSERT((otyp >= 0) && otyp < OTYPCNT); - - /* Sanity check the dev_t associated with this request. */ - ASSERT(getmajor(dev) == xdfs_major); - if (getmajor(dev) != xdfs_major) - return (ENXIO); - - if (XDFS_HVM_MODE(xsp)) { - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_close(dev, flag, otyp, credp)); - } - - /* - * Sanity check that that the device is actually open. On debug - * kernels we'll panic and on non-debug kernels we'll return failure. - */ - mutex_enter(&xsp->xdfss_mutex); - ASSERT(xdfs_isopen_part(xsp, part)); - if (!xdfs_isopen_part(xsp, part)) { - mutex_exit(&xsp->xdfss_mutex); - return (ENXIO); - } - - ASSERT(xsp->xdfss_tgt_lh[part] != NULL); - ASSERT(xsp->xdfss_otyp_count[otyp][part] > 0); - if (otyp == OTYP_LYR) { - xsp->xdfss_otyp_count[otyp][part]--; - } else { - xsp->xdfss_otyp_count[otyp][part] = 0; - } - - if (!xdfs_isopen_part(xsp, part)) { - err = ldi_close(xsp->xdfss_tgt_lh[part], flag, credp); - xsp->xdfss_tgt_lh[part] = NULL; - } - - mutex_exit(&xsp->xdfss_mutex); - - return (err); -} - -int -xdfs_strategy(struct buf *bp) -{ - dev_t dev = bp->b_edev; - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - dev_t tgt_devt; - struct buf *bp_clone; - - /* Sanity check the dev_t associated with this request. */ - ASSERT(getmajor(dev) == xdfs_major); - if (getmajor(dev) != xdfs_major) - goto err; - - if (XDFS_HVM_MODE(xsp)) { - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_strategy(bp)); - } - - /* - * Sanity checks that the dev_t associated with the buf we were - * passed corresponds to an open partition. On debug kernels we'll - * panic and on non-debug kernels we'll return failure. - */ - mutex_enter(&xsp->xdfss_mutex); - ASSERT(xdfs_isopen_part(xsp, part)); - if (!xdfs_isopen_part(xsp, part)) { - mutex_exit(&xsp->xdfss_mutex); - goto err; - } - mutex_exit(&xsp->xdfss_mutex); - - /* clone this buffer */ - tgt_devt = xsp->xdfss_tgt_dev | part; - bp_clone = bioclone(bp, 0, bp->b_bcount, tgt_devt, bp->b_blkno, - xdfs_iodone, NULL, KM_SLEEP); - bp_clone->b_chain = bp; - - /* - * If we're being invoked on behalf of the physio() call in - * xdfs_dioctl_rwcmd() then b_private will be set to - * XB_SLICE_NONE and we need to propegate this flag into the - * cloned buffer so that the xdf driver will see it. - */ - if (bp->b_private == (void *)XB_SLICE_NONE) - bp_clone->b_private = (void *)XB_SLICE_NONE; - - /* - * Pass on the cloned buffer. Note that we don't bother to check - * for failure because the xdf strategy routine will have to - * invoke biodone() if it wants to return an error, which means - * that the xdfs_iodone() callback will get invoked and it - * will propegate the error back up the stack and free the cloned - * buffer. - */ - ASSERT(xsp->xdfss_tgt_lh[part] != NULL); - return (ldi_strategy(xsp->xdfss_tgt_lh[part], bp_clone)); - -err: - bioerror(bp, ENXIO); - bp->b_resid = bp->b_bcount; - biodone(bp); - return (0); -} - -static int -xdfs_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (!XDFS_HVM_MODE(xsp)) - return (ldi_dump(xsp->xdfss_tgt_lh[part], addr, blkno, nblk)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_dump(dev, addr, blkno, nblk)); -} - -/*ARGSUSED*/ -static int -xdfs_read(dev_t dev, struct uio *uio, cred_t *credp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (!XDFS_HVM_MODE(xsp)) - return (ldi_read(xsp->xdfss_tgt_lh[part], uio, credp)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_read(dev, uio, credp)); -} - -/*ARGSUSED*/ -static int -xdfs_write(dev_t dev, struct uio *uio, cred_t *credp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (!XDFS_HVM_MODE(xsp)) - return (ldi_write(xsp->xdfss_tgt_lh[part], uio, credp)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_write(dev, uio, credp)); -} - -/*ARGSUSED*/ -static int -xdfs_aread(dev_t dev, struct aio_req *aio, cred_t *credp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (!XDFS_HVM_MODE(xsp)) - return (ldi_aread(xsp->xdfss_tgt_lh[part], aio, credp)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) || - (xdfs_hvm_cb_ops->cb_strategy == NULL) || - (xdfs_hvm_cb_ops->cb_strategy == nodev) || - (xdfs_hvm_cb_ops->cb_aread == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_aread(dev, aio, credp)); -} - -/*ARGSUSED*/ -static int -xdfs_awrite(dev_t dev, struct aio_req *aio, cred_t *credp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (!XDFS_HVM_MODE(xsp)) - return (ldi_awrite(xsp->xdfss_tgt_lh[part], aio, credp)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) || - (xdfs_hvm_cb_ops->cb_strategy == NULL) || - (xdfs_hvm_cb_ops->cb_strategy == nodev) || - (xdfs_hvm_cb_ops->cb_awrite == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_awrite(dev, aio, credp)); -} - -static int -xdfs_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, - int *rvalp) -{ - int instance = XDFS_DEV2UNIT(dev); - int part = XDFS_DEV2PART(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv; - boolean_t done; - - if (XDFS_HVM_MODE(xsp)) { - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL)) - return (ENOTSUP); - return (xdfs_hvm_cb_ops->cb_ioctl( - dev, cmd, arg, flag, credp, rvalp)); - } - - rv = xdfs_c_ioctl(xsp, dev, part, cmd, arg, flag, credp, rvalp, &done); - if (done) - return (rv); - rv = ldi_ioctl(xsp->xdfss_tgt_lh[part], cmd, arg, flag, credp, rvalp); - if (rv == 0) { - /* Force Geometry Validation */ - (void) cmlb_invalidate(xsp->xdfss_cmlbhandle, 0); - (void) cmlb_validate(xsp->xdfss_cmlbhandle, 0, 0); - } - return (rv); -} - -static int -xdfs_hvm_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, - int flags, char *name, caddr_t valuep, int *lengthp) -{ - int instance = ddi_get_instance(dip); - void *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - ASSERT(XDFS_HVM_MODE(xsp)); - - if ((xdfs_hvm_dev_ops == NULL) || (xdfs_hvm_cb_ops == NULL) || - (xdfs_hvm_cb_ops->cb_prop_op == NULL) || - (xdfs_hvm_cb_ops->cb_prop_op == nodev) || - (xdfs_hvm_cb_ops->cb_prop_op == nulldev)) - return (DDI_PROP_NOT_FOUND); - - return (xdfs_hvm_cb_ops->cb_prop_op(dev, dip, prop_op, - flags, name, valuep, lengthp)); -} - -static int -xdfs_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, - int flags, char *name, caddr_t valuep, int *lengthp) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv; - dev_info_t *tgt_dip; - dev_t tgt_devt; - - /* - * Sanity check that if a dev_t or dip were specified that they - * correspond to this device driver. On debug kernels we'll - * panic and on non-debug kernels we'll return failure. - */ - ASSERT(ddi_driver_major(dip) == xdfs_major); - ASSERT((dev == DDI_DEV_T_ANY) || (getmajor(dev) == xdfs_major)); - if ((ddi_driver_major(dip) != xdfs_major) || - ((dev != DDI_DEV_T_ANY) && (getmajor(dev) != xdfs_major))) - return (DDI_PROP_NOT_FOUND); - - /* - * This property lookup might be associated with a device node - * that is not yet attached, if so pass it onto ddi_prop_op(). - */ - if (xsp == NULL) - return (ddi_prop_op(dev, dip, prop_op, flags, - name, valuep, lengthp)); - - /* If we're accessing the device in hvm mode, pass this request on */ - if (XDFS_HVM_MODE(xsp)) - return (xdfs_hvm_prop_op(dev, dip, prop_op, - flags, name, valuep, lengthp)); - - /* - * Make sure we only lookup static properties. - * - * If there are static properties of the underlying xdf driver - * that we want to mirror, then we'll have to explicity look them - * up and define them during attach. There are a few reasons - * for this. Most importantly, most static properties are typed - * and all dynamic properties are untyped, ie, for dynamic - * properties the caller must know the type of the property and - * how to interpret the value of the property. the prop_op drivedr - * entry point is only designed for returning dynamic/untyped - * properties, so if we were to attempt to lookup and pass back - * static properties of the underlying device here then we would - * be losing the type information for those properties. Another - * reason we don't want to pass on static property requests is that - * static properties are enumerable in the device tree, where as - * dynamic ones are not. - */ - flags |= DDI_PROP_DYNAMIC; - - /* - * We can't use the ldi here to access the underlying device because - * the ldi actually opens the device, and that open might fail if the - * device has already been opened with the FEXCL flag. If we used - * the ldi here, it would also be possible for some other caller to - * try open the device with the FEXCL flag and get a failure back - * because we have it open to do a property query. Instad we'll - * grab a hold on the target dip. - */ - if (!xdfs_tgt_hold(xsp)) - return (DDI_PROP_NOT_FOUND); - - /* figure out dip the dev_t we're going to pass on down */ - tgt_dip = xsp->xdfss_tgt_dip; - if (dev == DDI_DEV_T_ANY) { - tgt_devt = DDI_DEV_T_ANY; - } else { - tgt_devt = xsp->xdfss_tgt_dev | XDFS_DEV2PART(dev); - } - - /* - * Cdev_prop_op() is not a public interface, and normally the caller - * is required to make sure that the target driver actually implements - * this interface before trying to invoke it. In this case we know - * that we're always accessing the xdf driver and it does have this - * interface defined, so we can skip the check. - */ - rv = cdev_prop_op(tgt_devt, tgt_dip, - prop_op, flags, name, valuep, lengthp); - - xdfs_tgt_release(xsp); - return (rv); -} - -/* - * Driver PV and HVM dev_ops entry points - */ -/*ARGSUSED*/ -static int -xdfs_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, - void **result) -{ - dev_t dev = (dev_t)arg; - int instance = XDFS_DEV2UNIT(dev); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - if (xsp == NULL) - return (DDI_FAILURE); - if (XDFS_HVM_MODE(xsp)) - *result = XDFS_HVM_DIP(xsp); - else - *result = (void *)xsp->xdfss_dip; - break; - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)(intptr_t)instance; - break; - default: - return (DDI_FAILURE); - } - return (DDI_SUCCESS); -} - -static int -xdfs_hvm_probe(dev_info_t *dip, char *path) -{ - int instance = ddi_get_instance(dip); - int rv = DDI_PROBE_SUCCESS; - void *xsp; - - ASSERT(path != NULL); - cmn_err(CE_WARN, "PV access to device disabled: %s", path); - - (void) ddi_soft_state_zalloc(xdfs_ssp, instance); - VERIFY((xsp = ddi_get_soft_state(xdfs_ssp, instance)) != NULL); - - if ((xdfs_hvm_dev_ops == NULL) || - (xdfs_hvm_dev_ops->devo_probe == NULL) || - ((rv = xdfs_hvm_dev_ops->devo_probe(dip)) == DDI_PROBE_FAILURE)) { - ddi_soft_state_free(xdfs_ssp, instance); - cmn_err(CE_WARN, "HVM probe of device failed: %s", path); - kmem_free(path, MAXPATHLEN); - return (DDI_PROBE_FAILURE); - } - - XDFS_HVM_MODE(xsp) = B_TRUE; - XDFS_HVM_DIP(xsp) = dip; - XDFS_HVM_PATH(xsp) = path; - - return (rv); -} - -static int -xdfs_probe(dev_info_t *dip) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp; - dev_info_t *tgt_dip; - char *path; - int i, pv_disable; - - /* if we've already probed the device then there's nothing todo */ - if (ddi_get_soft_state(xdfs_ssp, instance)) - return (DDI_PROBE_PARTIAL); - - /* Figure out our pathname */ - path = kmem_alloc(MAXPATHLEN, KM_SLEEP); - (void) ddi_pathname(dip, path); - - /* see if we should disable pv access mode */ - pv_disable = ddi_prop_get_int(DDI_DEV_T_ANY, - dip, DDI_PROP_NOTPROM, "pv_disable", 0); - - if (xdfs_pv_disable || pv_disable) - return (xdfs_hvm_probe(dip, path)); - - /* - * This xdf shell device layers on top of an xdf device. So the first - * thing we need to do is determine which xdf device instance this - * xdf shell instance should be layered on top of. - */ - for (i = 0; xdfs_c_h2p_map[i].xdfs_h2p_hvm != NULL; i++) { - if (strcmp(xdfs_c_h2p_map[i].xdfs_h2p_hvm, path) == 0) - break; - } - - if ((xdfs_c_h2p_map[i].xdfs_h2p_hvm == NULL) || - ((tgt_dip = xdf_hvm_hold(xdfs_c_h2p_map[i].xdfs_h2p_pv)) == NULL)) { - /* - * UhOh. We either don't know what xdf instance this xdf - * shell device should be mapped to or the xdf node assocaited - * with this instance isnt' attached. in either case fall - * back to hvm access. - */ - return (xdfs_hvm_probe(dip, path)); - } - - /* allocate and initialize our state structure */ - (void) ddi_soft_state_zalloc(xdfs_ssp, instance); - xsp = ddi_get_soft_state(xdfs_ssp, instance); - mutex_init(&xsp->xdfss_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&xsp->xdfss_cv, NULL, CV_DEFAULT, NULL); - mutex_enter(&xsp->xdfss_mutex); - - xsp->xdfss_dip = dip; - xsp->xdfss_pv = xdfs_c_h2p_map[i].xdfs_h2p_pv; - xsp->xdfss_hvm = xdfs_c_h2p_map[i].xdfs_h2p_hvm; - xsp->xdfss_tgt_attached = B_FALSE; - cmlb_alloc_handle((cmlb_handle_t *)&xsp->xdfss_cmlbhandle); - - if (!xdfs_tgt_probe(xsp, tgt_dip)) { - mutex_exit(&xsp->xdfss_mutex); - cmlb_free_handle(&xsp->xdfss_cmlbhandle); - ddi_soft_state_free(xdfs_ssp, instance); - ddi_release_devi(tgt_dip); - return (xdfs_hvm_probe(dip, path)); - } - mutex_exit(&xsp->xdfss_mutex); - - /* - * Add a zero-length attribute to tell the world we support - * kernel ioctls (for layered drivers). - */ - (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, - DDI_KERNEL_IOCTL, NULL, 0); - - kmem_free(path, MAXPATHLEN); - return (DDI_PROBE_SUCCESS); -} - -static int -xdfs_hvm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - void *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv = DDI_FAILURE; - - XDFS_HVM_SANE(xsp); - - if ((xdfs_hvm_dev_ops == NULL) || - (xdfs_hvm_dev_ops->devo_attach == NULL) || - ((rv = xdfs_hvm_dev_ops->devo_attach(dip, cmd)) != DDI_SUCCESS)) { - cmn_err(CE_WARN, "HVM attach of device failed: %s", - XDFS_HVM_PATH(xsp)); - kmem_free(XDFS_HVM_PATH(xsp), MAXPATHLEN); - ddi_soft_state_free(xdfs_ssp, instance); - return (rv); - } - - return (DDI_SUCCESS); -} - -/* - * Autoconfiguration Routines - */ -static int -xdfs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (xsp == NULL) - return (DDI_FAILURE); - if (XDFS_HVM_MODE(xsp)) - return (xdfs_hvm_attach(dip, cmd)); - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - xdfs_c_attach(xsp); - return (DDI_SUCCESS); -} - -static int -xdfs_hvm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - void *xsp = ddi_get_soft_state(xdfs_ssp, instance); - int rv; - - XDFS_HVM_SANE(xsp); - - if ((xdfs_hvm_dev_ops == NULL) || - (xdfs_hvm_dev_ops->devo_detach == NULL)) - return (DDI_FAILURE); - - if ((rv = xdfs_hvm_dev_ops->devo_detach(dip, cmd)) != DDI_SUCCESS) - return (rv); - - kmem_free(XDFS_HVM_PATH(xsp), MAXPATHLEN); - ddi_soft_state_free(xdfs_ssp, instance); - return (DDI_SUCCESS); -} - -static int -xdfs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (XDFS_HVM_MODE(xsp)) - return (xdfs_hvm_detach(dip, cmd)); - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - - mutex_enter(&xsp->xdfss_mutex); - if (!xdfs_tgt_detach(xsp)) { - mutex_exit(&xsp->xdfss_mutex); - return (DDI_FAILURE); - } - mutex_exit(&xsp->xdfss_mutex); - - cmlb_detach(xsp->xdfss_cmlbhandle, 0); - cmlb_free_handle(&xsp->xdfss_cmlbhandle); - ddi_release_devi(xsp->xdfss_tgt_dip); - ddi_soft_state_free(xdfs_ssp, instance); - ddi_prop_remove_all(dip); - return (DDI_SUCCESS); -} - -static int -xdfs_hvm_power(dev_info_t *dip, int component, int level) -{ - int instance = ddi_get_instance(dip); - void *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - XDFS_HVM_SANE(xsp); - - if ((xdfs_hvm_dev_ops == NULL) || - (xdfs_hvm_dev_ops->devo_power == NULL)) - return (DDI_FAILURE); - return (xdfs_hvm_dev_ops->devo_power(dip, component, level)); -} - -static int -xdfs_power(dev_info_t *dip, int component, int level) -{ - int instance = ddi_get_instance(dip); - xdfs_state_t *xsp = ddi_get_soft_state(xdfs_ssp, instance); - - if (XDFS_HVM_MODE(xsp)) - return (xdfs_hvm_power(dip, component, level)); - return (nodev()); -} - -/* - * Cmlb ops vector - */ -static cmlb_tg_ops_t xdfs_lb_ops = { - TG_DK_OPS_VERSION_1, - xdfs_lb_rdwr, - xdfs_lb_getinfo -}; - -/* - * Device driver ops vector - */ -static struct cb_ops xdfs_cb_ops = { - xdfs_open, /* open */ - xdfs_close, /* close */ - xdfs_strategy, /* strategy */ - nodev, /* print */ - xdfs_dump, /* dump */ - xdfs_read, /* read */ - xdfs_write, /* write */ - xdfs_ioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - xdfs_prop_op, /* cb_prop_op */ - 0, /* streamtab */ - D_64BIT | D_MP | D_NEW, /* Driver comaptibility flag */ - CB_REV, /* cb_rev */ - xdfs_aread, /* async read */ - xdfs_awrite /* async write */ -}; - -struct dev_ops xdfs_ops = { - DEVO_REV, /* devo_rev, */ - 0, /* refcnt */ - xdfs_getinfo, /* info */ - nulldev, /* identify */ - xdfs_probe, /* probe */ - xdfs_attach, /* attach */ - xdfs_detach, /* detach */ - nodev, /* reset */ - &xdfs_cb_ops, /* driver operations */ - NULL, /* bus operations */ - xdfs_power, /* power */ - ddi_quiesce_not_supported, /* devo_quiesce */ -}; - -/* - * Module linkage information for the kernel. - */ -static struct modldrv modldrv = { - &mod_driverops, /* Type of module. This one is a driver. */ - NULL, /* Module description. Set by _init() */ - &xdfs_ops, /* Driver ops. */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, (void *)&modldrv, NULL -}; - -int -_init(void) -{ - int rval; - - xdfs_major = ddi_name_to_major((char *)xdfs_c_name); - if (xdfs_major == (major_t)-1) - return (EINVAL); - - /* - * Determine the size of our soft state structure. The base - * size of the structure is the larger of the hvm clients state - * structure, or our shell state structure. Then we'll align - * the end of the structure to a pointer boundry and append - * a xdfs_hvm_state_t structure. This way the xdfs_hvm_state_t - * structure is always present and we can use it to determine the - * current device access mode (hvm or shell). - */ - xdfs_ss_size = MAX(xdfs_c_hvm_ss_size, sizeof (xdfs_state_t)); - xdfs_ss_size = P2ROUNDUP(xdfs_ss_size, sizeof (uintptr_t)); - xdfs_ss_size += sizeof (xdfs_hvm_state_t); - - /* - * In general ide usually supports 4 disk devices, this same - * limitation also applies to software emulating ide devices. - * so by default we pre-allocate 4 xdf shell soft state structures. - */ - if ((rval = ddi_soft_state_init(&xdfs_ssp, - xdfs_ss_size, XDFS_NODES)) != 0) - return (rval); - *xdfs_c_hvm_ss = xdfs_ssp; - - /* Install our module */ - if (modldrv.drv_linkinfo == NULL) - modldrv.drv_linkinfo = (char *)xdfs_c_linkinfo; - if ((rval = mod_install(&modlinkage)) != 0) { - ddi_soft_state_fini(&xdfs_ssp); - return (rval); - } - - return (0); -} - -int -_info(struct modinfo *modinfop) -{ - if (modldrv.drv_linkinfo == NULL) - modldrv.drv_linkinfo = (char *)xdfs_c_linkinfo; - return (mod_info(&modlinkage, modinfop)); -} - -int -_fini(void) -{ - int rval; - if ((rval = mod_remove(&modlinkage)) != 0) - return (rval); - ddi_soft_state_fini(&xdfs_ssp); - return (0); -} diff --git a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.h b/usr/src/uts/i86pc/i86hvm/io/xdf_shell.h deleted file mode 100644 index a7dd983e7b..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.h +++ /dev/null @@ -1,161 +0,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. - */ - -#ifndef _XDF_SHELL_H -#define _XDF_SHELL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* These interfaces are all dependant upon xdf */ -#include - -/* Include files required for this header file. */ -#include - -/* - * These include files are not strictly required to include this header - * file, but pretty much every xdf_shell client will need to include these - * header files, so just include them here. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * XDF Shell driver state structures - */ -typedef struct xdfs_state { - dev_info_t *xdfss_dip; - const char *xdfss_pv; - const char *xdfss_hvm; - - /* Members below are protected by xdfss_mutex */ - kmutex_t xdfss_mutex; - kcondvar_t xdfss_cv; - cmlb_handle_t xdfss_cmlbhandle; - int xdfss_otyp_count[OTYPCNT][XDF_PEXT]; - - /* Members below are only valid when xdfss_tgt_attached is true */ - dev_info_t *xdfss_tgt_dip; - boolean_t xdfss_tgt_attached; - int xdfss_tgt_holds; - dev_t xdfss_tgt_dev; - ddi_devid_t xdfss_tgt_devid; - boolean_t xdfss_tgt_locked; - boolean_t xdfss_tgt_is_cd; - ldi_handle_t xdfss_tgt_lh[XDF_PEXT]; -} xdfs_state_t; - -typedef struct xdfs_h2p_map { - const char *xdfs_h2p_hvm; - const char *xdfs_h2p_pv; -} xdfs_h2p_map_t; - -/* - * Globals defined by xdf_shell.c - */ -extern major_t xdfs_major; - -/* - * Functions defined by xdf_shell.c - */ -extern int xdfs_lb_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t, - void *); -extern int xdfs_strategy(struct buf *); -extern void xdfs_minphys(struct buf *); - -/* - * Globals that must be defined by xdf_shell.c clients - */ -extern const char *xdfs_c_name; -extern const char *xdfs_c_linkinfo; -extern void **xdfs_c_hvm_ss; -extern const size_t xdfs_c_hvm_ss_size; -extern const struct dev_ops *xdfs_c_hvm_dev_ops; -extern const xdfs_h2p_map_t xdfs_c_h2p_map[]; - -/* - * Functions that must be implemented by xdf_shell.c clients - */ - -/* - * xdfs_c_devid_setup() is invoked during device probe. If possible, it - * should create a devid for the associated disk device. This routine will - * not be invoked for cdrom devices. - */ -extern void xdfs_c_devid_setup(xdfs_state_t *); - -/* - * xdfs_c_bb_check() is invoked during device probe. It should check for - * the existance of bad blocks mappings in an alternate partition/slice and - * return B_FALSE if there are no bad block mappings found and return B_TRUE - * is there are bad block mappings found. The presence of bad block - * mappings will cause the device attach to fail. This routine will not be - * invoked for cdrom devices. - */ -extern boolean_t xdfs_c_bb_check(xdfs_state_t *); - -/* - * xdfs_c_getpgeom() is invoked during device probe. It should return the - * physical geometery of a disk device that is being attached. The failure - * of this routine will cause the device attach to fail. This routine will - * not be invoked for cdrom devices. - */ -extern int xdfs_c_getpgeom(dev_info_t *, cmlb_geom_t *); - -/* - * xdfs_c_cmlb_node_type() and xdfs_c_cmlb_alter_behavior() are invoked - * during device probe while initializing the cmlb module for the device - * node being probed. They should return a cmlb node type and cmlb alter - * behavior flag value that can be passed to cmlb_attach(). - */ -extern char *xdfs_c_cmlb_node_type(xdfs_state_t *); -extern int xdfs_c_cmlb_alter_behavior(xdfs_state_t *); - -/* - * xdfs_c_attach() is invoked during device attach. It provides an - * opportunity for the client to create properties or do anything else - * necessary for attach. - */ -extern void xdfs_c_attach(xdfs_state_t *); - -/* - * xdfs_c_getpgeom() is invoked to handle ioctl operations. - */ -extern int xdfs_c_ioctl(xdfs_state_t *, dev_t, int, - int, intptr_t, int, cred_t *, int *, boolean_t *); - -#ifdef __cplusplus -} -#endif - -#endif /* _XDF_SHELL_H */ diff --git a/usr/src/uts/i86pc/i86hvm/io/xpv/evtchn.c b/usr/src/uts/i86pc/i86hvm/io/xpv/evtchn.c deleted file mode 100644 index dbaa32c71e..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/xpv/evtchn.c +++ /dev/null @@ -1,398 +0,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. - */ - -/* - * 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)) */ -#ifdef __amd64 -#define EVTCHN_SHIFT 6 -#else /* __i386 */ -#define EVTCHN_SHIFT 5 -#endif - -/* 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"); - -} diff --git a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv.conf b/usr/src/uts/i86pc/i86hvm/io/xpv/xpv.conf deleted file mode 100644 index aa8b997152..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv.conf +++ /dev/null @@ -1,33 +0,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 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; diff --git a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c b/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c deleted file mode 100644 index e6c1b6f6a8..0000000000 --- a/usr/src/uts/i86pc/i86hvm/io/xpv/xpv_support.c +++ /dev/null @@ -1,816 +0,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. - */ - if (xenbus_printf(XBT_NULL, "guest/xpv", "version", "%d", - HVMPV_XPV_VERS)) - cmn_err(CE_WARN, "xpv: couldn't write version\n"); - - 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)); -} diff --git a/usr/src/uts/i86pc/i86hvm/pv_cmdk/Makefile b/usr/src/uts/i86pc/i86hvm/pv_cmdk/Makefile deleted file mode 100644 index 2dc5c4fa95..0000000000 --- a/usr/src/uts/i86pc/i86hvm/pv_cmdk/Makefile +++ /dev/null @@ -1,81 +0,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 -# -# -# uts/i86pc/pv_cmdk/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the xdc 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 = cmdk -OBJECTS = $(PV_CMDK_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) - -LDFLAGS += -dy -Nmisc/strategy -Nmisc/cmlb -Ndrv/xpvd -Ndrv/xdf -LDFLAGS += -Nmisc/hvm_cmdk - -CPPFLAGS += -D_EXTVTOC - -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-unused-variable - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/pv_rtls/Makefile b/usr/src/uts/i86pc/i86hvm/pv_rtls/Makefile deleted file mode 100644 index 94d79bf033..0000000000 --- a/usr/src/uts/i86pc/i86hvm/pv_rtls/Makefile +++ /dev/null @@ -1,75 +0,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 -# -# -# uts/i86pc/pv_rtls/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the null rtls module for xvm. -# -# 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 = rtls -OBJECTS = $(PV_RTLS_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) - -LDFLAGS += -dy - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/pv_sd/Makefile b/usr/src/uts/i86pc/i86hvm/pv_sd/Makefile deleted file mode 100644 index ddd9a1c1a9..0000000000 --- a/usr/src/uts/i86pc/i86hvm/pv_sd/Makefile +++ /dev/null @@ -1,78 +0,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 -# -# -# uts/i86pc/i86hvm/pv_sd/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the xdc 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 = sd -OBJECTS = $(PV_SD_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) - -LDFLAGS += -dy -Nmisc/strategy -Nmisc/cmlb -Ndrv/xpvd -Ndrv/xdf -LDFLAGS += -Nmisc/hvm_sd - -CERRWARN += -Wno-unused-variable - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/xdf/Makefile b/usr/src/uts/i86pc/i86hvm/xdf/Makefile deleted file mode 100644 index f357b4a50c..0000000000 --- a/usr/src/uts/i86pc/i86hvm/xdf/Makefile +++ /dev/null @@ -1,80 +0,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 -# - -# -# uts/i86pc/xdf/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# 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 += -dy -Nmisc/cmlb -Ndrv/xpvd -Ndrv/xpv - - -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-label -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 diff --git a/usr/src/uts/i86pc/i86hvm/xnf/Makefile b/usr/src/uts/i86pc/i86hvm/xnf/Makefile deleted file mode 100644 index 37e58bff02..0000000000 --- a/usr/src/uts/i86pc/i86hvm/xnf/Makefile +++ /dev/null @@ -1,84 +0,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 -# - -# -# uts/i86pc/xnf/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# 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 += -dy -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 diff --git a/usr/src/uts/i86pc/i86hvm/xpv/Makefile b/usr/src/uts/i86pc/i86hvm/xpv/Makefile deleted file mode 100644 index 45f0259f1d..0000000000 --- a/usr/src/uts/i86pc/i86hvm/xpv/Makefile +++ /dev/null @@ -1,83 +0,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 -# -# -# uts/i86pc/xpv/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# 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 += -dy -N mach/pcplusmp - -CERRWARN += -Wno-unused-label - -# -# 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 diff --git a/usr/src/uts/i86pc/i86hvm/xpvd/Makefile b/usr/src/uts/i86pc/i86hvm/xpvd/Makefile deleted file mode 100644 index 716c401a0c..0000000000 --- a/usr/src/uts/i86pc/i86hvm/xpvd/Makefile +++ /dev/null @@ -1,81 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# 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 += -dy -Ndrv/xpv - - -CERRWARN += -Wno-uninitialized - -# -# 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 diff --git a/usr/src/uts/i86xpv/Makefile b/usr/src/uts/i86xpv/Makefile deleted file mode 100644 index 778d21a187..0000000000 --- a/usr/src/uts/i86xpv/Makefile +++ /dev/null @@ -1,101 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2013 Nexenta Systems, Inc. All rights reserved. -# -# This makefile drives the production of all implementation architecture -# dependent modules for the i86xpv architecture. -# - -UTSBASE = .. - -include Makefile.i86xpv - -def := TARGET= def -all := TARGET= all -install := TARGET= install -clean := TARGET= clean -clobber := TARGET= clobber -modlist := TARGET= modlist -modlist modlist.intel := NO_STATE= -K $$MODSTATE$$$$ -check := TARGET= check - -.KEEP_STATE: - -.PARALLEL: $(PARALLEL_KMODS) $(XMODS) modlist modlist.intel - -INITIAL_TARGETS = \ - genassym \ - unix \ - cpu/scripts - -def all clean clobber: setup genassym unix .WAIT \ - $(KMODS) $(XMODS) - -install: install_platforms setup genassym unix .WAIT \ - $(KMODS) $(XMODS) - -# list the modules under i86xpv. -modlist: unix $(KMODS) $(XMODS) - -# list the modules for Install -k i86xpv. -modlist.karch: modlist modlist.intel - -modlist.intel: - @cd $(SRC)/uts/intel; pwd; $(MAKE) $(NO_STATE) modlist - -genassym unix $(KMODS): FRC - @cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET) - -setup: FRC - @cd cpu/scripts; pwd; $(MAKE) $(TARGET) - -$(XMODS): FRC - @if [ -f $@/Makefile ]; then \ - cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET); \ - else \ - true; \ - fi - -install_h check: FRC - -# -# Definitions for the /platform directory aliases. -# Currently none for i86xpv. -# -PLAT_LINKS = - -# -# Make the /platform directories. This is hardwired here because -# the first stage of the project (KBI) only implements the userland -# changes, but the only reasonable place to record the aliases is -# here in kernel land. -# -install_platforms: $(ROOT_PSM_DIR) $(USR_PSM_DIR) \ - $(ROOT_PLAT_LINKS) $(USR_PLAT_LINKS) \ - $(OEM_USR_PLAT_LINKS) - -FRC: - -include ../Makefile.targ diff --git a/usr/src/uts/i86xpv/Makefile.files b/usr/src/uts/i86xpv/Makefile.files deleted file mode 100644 index 3459907fc0..0000000000 --- a/usr/src/uts/i86xpv/Makefile.files +++ /dev/null @@ -1,257 +0,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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# This Makefile defines file modules in the directory uts/i86xpv -# and its children. These are the source files which are i86xpv -# "implementation architecture" dependent. -# - -# -# object lists -# -CORE_OBJS += \ - acpi_stubs.o \ - balloon.o \ - biosdisk.o \ - cbe.o \ - cmi.o \ - cmi_hw.o \ - cms.o \ - confunix.o \ - cpuid.o \ - cpuid_subr.o \ - cpupm.o \ - cpupm_mach.o \ - dis_tables.o \ - ddi_impl.o \ - dtrace_subr.o \ - dvma.o \ - fakebop.o \ - fpu_subr.o \ - fastboot.o \ - fb_swtch.o \ - graphics.o \ - hardclk.o \ - hat_i86.o \ - hat_kdi.o \ - hment.o \ - hold_page.o \ - hrtimers.o \ - htable.o \ - i86_mmu.o \ - ibft.o \ - instr_size.o \ - intr.o \ - kboot_mmu.o \ - kdi_subr.o \ - kdi_idt.o \ - kdi_idthdl.o \ - kdi_asm.o \ - lgrpplat.o \ - mach_kdi.o \ - mach_sysconfig.o \ - machdep.o \ - mem_config_stubs.o \ - memnode.o \ - microcode.o \ - mlsetup.o \ - mp_call.o \ - mp_implfuncs.o \ - mp_machdep.o \ - mp_startup.o \ - memscrub.o \ - notes.o \ - pci_bios.o \ - pci_cfgacc.o \ - pci_cfgacc_x86.o \ - pci_cfgspace.o \ - pci_mech1.o \ - pci_mech2.o \ - pci_neptune.o \ - pci_orion.o \ - pmem.o \ - ppage.o \ - startup.o \ - ssp.o \ - xpv_timestamp.o \ - todpc_subr.o \ - trap.o \ - vm_machdep.o \ - x_call.o - -# -# Add the SMBIOS subsystem object files directly to the list of objects -# built into unix itself; this is all common code except for smb_dev.c. -# -CORE_OBJS += $(SMBIOS_OBJS) - -# -# These get compiled twice: -# - once in the dboot (direct boot) identity mapped code -# - once for use during early startup in unix -# -BOOT_DRIVER_OBJS = \ - boot_console.o \ - boot_keyboard.o \ - boot_keyboard_table.o \ - boot_mmu.o \ - boot_vga.o \ - boot_xconsole.o \ - dboot_multiboot2.o \ - $(FONT_OBJS) - -CORE_OBJS += $(BOOT_DRIVER_OBJS) - -# -# Extra XEN files separated out for now. -# -CORE_OBJS += \ - cpr_driver.o \ - evtchn.o \ - gnttab.o \ - hypercall.o \ - hyperevent.o \ - hypersubr.o \ - mp_xen.o \ - panic_asm.o \ - xenguest.o \ - xenbus_client.o \ - xenbus_comms.o \ - xenbus_probe.o \ - xenbus_xs.o \ - xen_machdep.o \ - xen_mmu.o \ - xpv_panic.o \ - xvdi.o - -# -# locore.o is special. It must be the first file relocated so that it -# it is relocated just where its name implies. -# -SPECIAL_OBJS_32 += \ - locore.o \ - fast_trap_asm.o \ - interrupt.o \ - syscall_asm.o - -SPECIAL_OBJS_64 += \ - locore.o \ - fast_trap_asm.o \ - interrupt.o \ - syscall_asm_amd64.o - -SPECIAL_OBJS += $(SPECIAL_OBJS_$(CLASS)) - -# -# object files used to boot into full kernel -# -DBOOT_OBJS_32 = muldiv.o - -DBOOT_OBJS_64 = - -DBOOT_OBJS += \ - dboot_asm.o \ - dboot_printf.o \ - dboot_startkern.o \ - dboot_xen.o \ - hypercall.o \ - hypersubr.o \ - memcpy.o \ - memset.o \ - string.o \ - $(BOOT_DRIVER_OBJS) \ - $(DBOOT_OBJS_$(CLASS)) - -# -# driver & misc modules -# -BALLOON_OBJS += balloon_drv.o -DOMCAPS_OBJS += domcaps.o -EVTCHN_OBJS += evtchn_dev.o -GFX_PRIVATE_OBJS += gfx_private.o gfxp_pci.o gfxp_segmap.o \ - gfxp_devmap.o gfxp_vgatext.o gfxp_vm.o vgasubr.o -IOAT_OBJS += ioat.o ioat_rs.o ioat_ioctl.o ioat_chan.o -ISANEXUS_OBJS += isa.o dma_engine.o i8237A.o -PCI_E_NEXUS_OBJS += npe.o npe_misc.o -PCI_E_NEXUS_OBJS += pci_common.o pci_kstats.o pci_tools.o -PCINEXUS_OBJS += pci.o pci_common.o pci_kstats.o pci_tools.o -PRIVCMD_OBJS += seg_mf.o privcmd.o privcmd_hcall.o -ROOTNEX_OBJS += rootnex.o -XPVTOD_OBJS += xpvtod.o -XPV_AUTOCONFIG_OBJS += xpv_autoconfig.o -XPV_PSM_OBJS += xpv_psm.o mp_platform_common.o mp_platform_xpv.o \ - apic_regops.o psm_common.o xpv_intr.o -XPV_UPPC_OBJS += xpv_uppc.o psm_common.o -XENBUS_OBJS += xenbus_dev.o -XENCONS_OBJS += xencons.o -XPVD_OBJS += xpvd.o -XPVTAP_OBJS += xpvtap.o blk_common.o seg_mf.o -XNB_OBJS += xnb.o -XNBE_OBJS += xnbe.o -XNBO_OBJS += xnbo.o -XNBU_OBJS += xnbu.o -XNF_OBJS += xnf.o -XSVC_OBJS += xsvc.o -XDF_OBJS += xdf.o -XDB_OBJS += xdb.o -XDT_OBJS += xdt.o - -# -# Build up defines and paths. -# -INC_PATH += -I$(SRCTOP)/include -INC_PATH += -I$(SRCTOP)/arch/x86/kernel/platform/i86xpv/include -INC_PATH += -I$(SRCTOP)/arch/x86/kernel/platform/i86pc/include -INC_PATH += -I$(UTSBASE)/i86xpv -I$(UTSBASE)/i86pc -I$(SRC)/common \ - -I$(UTSBASE)/common/xen - -# -# Since the assym files are derived, the dependencies must be explicit for -# all files including this file. (This is only actually required in the -# instance when the .nse_depinfo file does not exist.) -# - -ASSYM_DEPS += \ - copy.o \ - desctbls_asm.o \ - ddi_i86_asm.o \ - exception.o \ - fast_trap_asm.o \ - float.o \ - hyperevent.o \ - i86_subr.o \ - kdi_asm.o \ - interrupt.o \ - lock_prim.o \ - locore.o \ - panic_asm.o \ - sseblk.o \ - swtch.o \ - syscall_asm.o \ - syscall_asm_amd64.o - -$(KDI_ASSYM_DEPS:%=$(OBJS_DIR)/%): $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h - -ASSYM_DEPS += kdi_asm.o diff --git a/usr/src/uts/i86xpv/Makefile.i86xpv b/usr/src/uts/i86xpv/Makefile.i86xpv deleted file mode 100644 index f80b22795b..0000000000 --- a/usr/src/uts/i86xpv/Makefile.i86xpv +++ /dev/null @@ -1,290 +0,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 -# - -# -# uts/i86xpv/Makefile.i86xpv -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# Copyright (c) 2013 Andrew Stormont. All rights reserved. -# - -# -# This makefile contains the common definitions for the i86xpv unix -# and all i86xpv implementation architecture dependent modules. -# - -# -# Machine type (implementation architecture): -# -PLATFORM = i86xpv - -# -# uname -m value -# -UNAME_M = i86pc - -# -# Everybody needs to know how to build modstubs.o and to locate unix.o -# -UNIX_DIR = $(UTSBASE)/$(PLATFORM)/unix -GENLIB_DIR = $(UTSBASE)/intel/genunix -MODSTUBS_DIR = $(UNIX_DIR) -DSF_DIR = $(UTSBASE)/$(PLATFORM)/genassym - -DTRACESTUBS_O = $(OBJS_DIR)/dtracestubs.o -DTRACESTUBS = $(OBJS_DIR)/libdtracestubs.so - -SYM_MOD = $(OBJS_DIR)/unix.sym - -UNIX_O = $(UNIX_DIR)/$(OBJS_DIR)/unix.o -MODSTUBS_O = $(MODSTUBS_DIR)/$(OBJS_DIR)/modstubs.o -GENLIB = $(GENLIB_DIR)/$(OBJS_DIR)/libgenunix.so - -# -# Include the makefiles which define build rule templates, the -# collection of files per module, and a few specific flags. Note -# that order is significant, just as with an include path. The -# first build rule template which matches the files name will be -# used. By including these in order from most machine dependent -# to most machine independent, we allow a machine dependent file -# to be used in preference over a machine independent version -# (Such as a machine specific optimization, which preserves the -# interfaces.) -# -include $(UTSBASE)/$(PLATFORM)/Makefile.files -include $(UTSBASE)/intel/Makefile.files -include $(UTSBASE)/common/Makefile.files - -# -# Include machine independent rules. Note that this does not imply -# that the resulting module from rules in Makefile.uts is machine -# independent. Only that the build rules are machine independent. -# -include $(UTSBASE)/Makefile.uts - -# -# Define supported builds -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# kernel-specific optimizations; override default in Makefile.master -# - -CFLAGS_XARCH_32 = $(i386_CFLAGS) -CFLAGS_XARCH_64 = $(amd64_CFLAGS) -CFLAGS_XARCH = $(CFLAGS_XARCH_$(CLASS)) - -COPTFLAG_32 = $(COPTFLAG) -COPTFLAG_64 = $(COPTFLAG64) -COPTIMIZE = $(COPTFLAG_$(CLASS)) - -CFLAGS = $(CFLAGS_XARCH) -CFLAGS += $(COPTIMIZE) -CFLAGS += -D_ASM_INLINES -CFLAGS += $(CFLAGS_uts) - -ASFLAGS_XARCH_32 = $(i386_ASFLAGS) -ASFLAGS_XARCH_64 = $(amd64_ASFLAGS) -ASFLAGS_XARCH = $(ASFLAGS_XARCH_$(CLASS)) - -ASFLAGS += $(ASFLAGS_XARCH) - -AS_INC_PATH += -I$(DSF_DIR)/$(OBJS_DIR) - -# -# The following must be defined for all implementations: -# -# MAPFILE: ld mapfile for the build of kernel/unix. -# MODSTUBS: Module stubs source file. -# GENASSYM_SRC: genassym.c - -MAPFILE = $(SRCTOP)/arch/x86/kernel/platform/i86xpv/mapfile-$(CLASS) -MODSTUBS = $(SRCTOP)/arch/x86/kernel/ml/modstubs.s -GENASSYM_SRC = $(UTSBASE)/i86pc/ml/genassym.c -OFFSETS_SRC = $(SRCTOP)/arch/x86/kernel/offsets.in -PLATFORM_OFFSETS_SRC = $(SRCTOP)/arch/x86/kernel/mach_offsets_$(CLASS).in -KDI_OFFSETS_SRC = $(SRCTOP)/arch/x86/kernel/kdi/offsets.in - -# -# Define the actual specific platforms -# -MACHINE_DEFS = -D__$(PLATFORM) -D__xpv -D_MACHDEP - -# -# Software workarounds for hardware "features" -# - -include $(UTSBASE)/i86pc/Makefile.workarounds - -# -# Debugging level -# -# Special knowledge of which special debugging options effect which -# file is used to optimize the build if these flags are changed. -# -# XXX: The above could possibly be done for more flags and files, but -# is left as an experiment to the interested reader. Be forewarned, -# that excessive use could lead to maintenance difficulties. -# -DEBUG_DEFS_OBJ32 = -DEBUG_DEFS_DBG32 = -DDEBUG -DEBUG_DEFS_OBJ64 = -DEBUG_DEFS_DBG64 = -DDEBUG -DEBUG_DEFS = $(DEBUG_DEFS_$(BUILD_TYPE)) - -DEBUG_COND_OBJ32 = $(POUND_SIGN) -DEBUG_COND_DBG32 = -DEBUG_COND_OBJ64 = $(POUND_SIGN) -DEBUG_COND_DBG64 = -IF_DEBUG_OBJ = $(DEBUG_COND_$(BUILD_TYPE))$(OBJS_DIR)/ - -$(IF_DEBUG_OBJ)trap.o := DEBUG_DEFS += -DTRAPDEBUG -DTRAPTRACE -$(IF_DEBUG_OBJ)syscall_asm.o := DEBUG_DEFS += -DSYSCALLTRACE -DTRAPTRACE -$(IF_DEBUG_OBJ)syscall_asm_amd64.o := DEBUG_DEFS += -DSYSCALLTRACE -DTRAPTRACE -$(IF_DEBUG_OBJ)fast_trap_asm.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)interrupt.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)intr.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)locore.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)mp_startup.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)machdep.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)exception.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)x_call.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)mp_call.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)cbe.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)hyperevent.o := DEBUG_DEFS += -DTRAPTRACE -$(IF_DEBUG_OBJ)evtchn.o := DEBUG_DEFS += -DTRAPTRACE - -# -# Collect the preprocessor definitions to be associated with *all* -# files. -# -ALL_DEFS = $(MACHINE_DEFS) $(WORKAROUND_DEFS) $(DEBUG_DEFS) \ - $(OPTION_DEFS) -GENASSYM_DEFS = $(MACHINE_DEFS) $(OPTION_DEFS) \ - -fno-eliminate-unused-debug-symbols \ - -fno-eliminate-unused-debug-types - -# -# ----- TRANSITIONAL SECTION -------------------------------------------------- -# - -# -# Not everything which *should* be a module is a module yet. The -# following is a list of such objects which are currently part of -# the base kernel but should soon become kmods. -# -# XXX: $(KMACCT_OBJS) is neither in the MT kernel nor was it ever -# made into a module. If it is made MT safe before being made -# into a module, it should be added to this list. It was in -# this list pre ON-4.0. -# -# -MACH_NOT_YET_KMODS = $(AUTOCONF_OBJS) - -# -# ----- END OF TRANSITIONAL SECTION ------------------------------------------- -# - -# -# The kernels modules which are "implementation architecture" -# specific for this machine are enumerated below. Note that most -# of these modules must exist (in one form or another) for each -# architecture. -# -# Machine Specific Driver Modules (/kernel/drv): -# DRV_KMODS are built both 32-bit and 64-bit -# DRV_KMODS_32 are built only 32-bit -# DRV_KMODS_64 are built only 64-bit -# - -DRV_KMODS += rootnex -DRV_KMODS += ioat -DRV_KMODS += isa -DRV_KMODS += pci -DRV_KMODS += pit_beep -DRV_KMODS += npe -DRV_KMODS += pci-ide -DRV_KMODS += xsvc -DRV_KMODS += xenbus -DRV_KMODS += xencons -DRV_KMODS += xpvd -DRV_KMODS += xnbe -DRV_KMODS += xnbo -DRV_KMODS += xnbu -DRV_KMODS += xnf -DRV_KMODS += xdb -DRV_KMODS += xdf -DRV_KMODS += privcmd -DRV_KMODS += domcaps -DRV_KMODS += evtchn -DRV_KMODS += balloon -DRV_KMODS += xpvtap -DRV_KMODS += xdt - -# -# CPU Modules -# -CPU_KMODS += generic_cpu -CPU_KMODS += amd_opteron -CPU_KMODS += genuineintel -CPU_KMODS += authenticamd - -# -# Exec Class Modules (/kernel/exec): -# -EXEC_KMODS += - -# -# File System Modules (/kernel/fs): -# -FS_KMODS += - -# -# Streams Modules (/kernel/strmod): -# -STRMOD_KMODS += - -# -# 'System' Modules (/kernel/sys): -# -SYS_KMODS += - -# -# 'Misc' Modules (/kernel/misc): -# -MISC_KMODS += xpv_autoconfig gfx_private xnb - -# 'Dacf' modules (/kernel/dacf) -# -DACF_KMODS += consconfig_dacf - -# -# 'Mach' Modules (/kernel/mach): -# -MACH_KMODS += xpv_psm xpv_uppc - -# -# 'TOD' modules (/platform/.../kernel/tod): -# -TOD_KMODS += xpvtod diff --git a/usr/src/uts/i86xpv/Makefile.rules b/usr/src/uts/i86xpv/Makefile.rules deleted file mode 100644 index c131a24c68..0000000000 --- a/usr/src/uts/i86xpv/Makefile.rules +++ /dev/null @@ -1,195 +0,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. -# - -# -# This Makefile defines the build rules for the directory uts/i86xpv -# and its children. These are the source files which are i86xpv -# "implementation architecture" dependent. -# -# 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, sun4u rules come before -# sparc rules come before common rules. -# -# - Lines whose initial directory components are equal are sorted -# alphabetically by the remaining components. -# - -# -# We share many files with the i86pc implementation to reduce -# the amount of merge work -# - -# -# Section 1: C object build rules -# -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/conf/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/cpu/generic_cpu/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/io/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/ioat/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/pci/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/pciex/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/intel/io/pciex/hotplug/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/io/psm/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/ml/%.s - $(COMPILE.s) -o $@ $< - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/os/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/vm/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/boot/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(SRCTOP)/arch/x86/kernel/platform/i86pc/boot/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/gfx_private/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/i86pc/io/xsvc/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/pciex/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# We need this one to make sure we share dtrace_subr.c with i86pc -# Otherwise we pick up kernel/os/dtrace_subr.c instead :( - -$(OBJS_DIR)/dtrace_subr.o: $(UTSBASE)/i86pc/os/dtrace_subr.c - $(COMPILE.c) -o $@ $(UTSBASE)/i86pc/os/dtrace_subr.c - $(CTFCONVERT_O) - -# -$(OBJS_DIR)/%.o: $(SRCTOP)/kernel/cpr/%.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) - -$(OBJS_DIR)/%.o: $(UTSBASE)/common/xen/dtrace/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# stuff for dboot -# -# This is different from i86pc - uses 64 bit compiler for 64 bit -# -# Note that we *don't* want to use the definitions that have been augmented -# by various bits of the context of the kernel build environment; so we -# start constructing flags and things afresh. - -DBOOT_OBJS_DIR= dboot/$(OBJS_DIR) - -DBOOT_XARCH_32 = $(i386_XARCH) -DBOOT_XARCH_64 = $(amd64_XARCH) -DBOOT_CFLAGS = $(DBOOT_XARCH_$(CLASS)) $(C99MODE) $(CERRWARN) \ - $(CCNOAUTOINLINE) -O - -DBOOT_AS_XARCH_32 = $(i386_AS_XARCH) -DBOOT_AS_XARCH_64 = $(amd64_AS_XARCH) -DBOOT_ASFLAGS = $(DBOOT_AS_XARCH_$(CLASS)) -D_ASM - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/common/xen/os/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(SRCTOP)/kernel/font/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(DBOOT_OBJS_DIR)/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/boot/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(SRCTOP)/arch/x86/kernel/platform/i86pc/boot/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/dboot/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(COMMONBASE)/util/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/os/%.c - $(CC) $(DBOOT_CFLAGS) $(DBOOT_DEFS) $(DBOOT_CC_INCL) -c -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/intel/ia32/ml/%.s - $(AS) $(DBOOT_ASFLAGS) $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(COMMONBASE)/util/i386/%.s - $(AS) $(DBOOT_ASFLAGS) $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86xpv/ml/%.s - $(AS) $(DBOOT_ASFLAGS) $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< - -$(DBOOT_OBJS_DIR)/%.o: $(UTSBASE)/i86pc/dboot/%.s - $(AS) $(DBOOT_ASFLAGS) $(DBOOT_DEFS) $(DBOOT_AS_INCL) -o $@ $< - -include $(UTSBASE)/i86pc/Makefile.rules - -DBOOT_DEFS += -D__xpv diff --git a/usr/src/uts/i86xpv/Makefile.targ b/usr/src/uts/i86xpv/Makefile.targ deleted file mode 100644 index 09ac6b0616..0000000000 --- a/usr/src/uts/i86xpv/Makefile.targ +++ /dev/null @@ -1,42 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This Makefile defines the set of all required, target containing -# included Makefiles for the i86xpv "implementation architecture". -# - -# -# Targets for all implementations: -# -include $(UTSBASE)/Makefile.targ - -# -# Target set for i86xpv (order is not important, as it is with the -# isomorphic Makefile.files set). -# -include $(UTSBASE)/i86xpv/Makefile.rules -include $(UTSBASE)/intel/Makefile.rules -include $(UTSBASE)/common/Makefile.rules - diff --git a/usr/src/uts/i86xpv/amd_opteron/Makefile b/usr/src/uts/i86xpv/amd_opteron/Makefile deleted file mode 100644 index b5bd20f236..0000000000 --- a/usr/src/uts/i86xpv/amd_opteron/Makefile +++ /dev/null @@ -1,95 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2013 Nexenta Systems, Inc. All rights reserved. -# Copyright 2016 Joyent, Inc. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = cpu_ms.AuthenticAMD.15 -# -OBJECTS = $(CPU_AO_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_CPU_DIR)/$(MODULE) - -SRCDIR = ../../i86pc/cpu/amd_opteron - -AO_MCA_DISP_C = $(OBJS_DIR)/ao_mca_disp.c -AO_MCA_DISP_SRC = $(SRCDIR)/ao_mca_disp.in -AO_GENDISP = ../cpu/scripts/ao_gendisp - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv -include $(UTSBASE)/i86pc/cpu/Makefile.files - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides and additions -# -$(OBJS_DIR)/ao_mca.o := CERRWARN += -Wno-unused-function -CLEANFILES += $(AO_MCA_DISP_C) -CPPFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -ASFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -LDFLAGS += -dy -N misc/acpica - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -# -# Create ao_mca_disp.c -# -$(AO_MCA_DISP_C): $(AO_MCA_DISP_SRC) $(AO_GENDISP) - $(AO_GENDISP) $(AO_MCA_DISP_SRC) >$@ - -$(OBJS_DIR)/%.o: $(OBJS_DIR)/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -# -# Include common targets. -# -include ../Makefile.targ diff --git a/usr/src/uts/i86xpv/authenticamd/Makefile b/usr/src/uts/i86xpv/authenticamd/Makefile deleted file mode 100644 index 7b57a0438f..0000000000 --- a/usr/src/uts/i86xpv/authenticamd/Makefile +++ /dev/null @@ -1,76 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = cpu_ms.AuthenticAMD -# -OBJECTS = $(CPU_AUTHAMD_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_CPU_DIR)/$(MODULE) - -SRCDIR = ../cpu/authenticamd - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv -include $(UTSBASE)/i86pc/cpu/Makefile.files - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides and additions -# -CPPFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -ASFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -LDFLAGS += -dy -N misc/acpica - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include ../Makefile.targ diff --git a/usr/src/uts/i86xpv/balloon/Makefile b/usr/src/uts/i86xpv/balloon/Makefile deleted file mode 100644 index 2332597ada..0000000000 --- a/usr/src/uts/i86xpv/balloon/Makefile +++ /dev/null @@ -1,75 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the balloon -# driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = balloon -OBJECTS = $(BALLOON_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/boot/boot_xconsole.c b/usr/src/uts/i86xpv/boot/boot_xconsole.c deleted file mode 100644 index 02624b16b8..0000000000 --- a/usr/src/uts/i86xpv/boot/boot_xconsole.c +++ /dev/null @@ -1,242 +0,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 - -shared_info_t *HYPERVISOR_shared_info; -void *HYPERVISOR_console_page; - -#if defined(_BOOT) -#include "dboot/dboot_printf.h" -char big_empty[MMU_PAGESIZE * 3]; /* room for 2 page aligned page */ -#endif /* _BOOT */ - -unsigned short video_fb_buf[32 * 1024 + MMU_PAGESIZE]; -unsigned char kb_status_buf[MMU_PAGESIZE * 2]; -unsigned short *video_fb = NULL; -unsigned char *kb_status = NULL; - -static volatile struct xencons_interface *cons_ifp; - -#define XR_FULL(r) ((r)->xr_in_cnt - (r)->xr_out_cnt == XR_SIZE) -#define XR_EMPTY(r) ((r)->xr_in_cnt == (r)->xr_out_cnt) - -#define PTE_BITS (PT_VALID | PT_WRITABLE) -#define PTE_DEV_BITS (PT_VALID | PT_WRITABLE | PT_NOCACHE | PT_NOCONSIST | \ - PT_FOREIGN) - -/* - * For some unfortunate reason, the hypervisor doesn't bother to include the - * shared info in the original virtual address space. This means we can't - * do any console I/O until we have manipulated some pagetables. So we have to - * do this bit of code with no ability to get debug output. - */ -/*ARGSUSED*/ -void -bcons_init_xen(char *cmdline) -{ -#ifdef _BOOT - int i = 0; - uintptr_t vaddr; - - /* - * find a page aligned virtual address in "big_empty" - */ - vaddr = (uintptr_t)&big_empty; - vaddr = (vaddr + MMU_PAGEOFFSET) & MMU_PAGEMASK; - HYPERVISOR_shared_info = (shared_info_t *)vaddr; - - /* - * Sets the "present" and "writable" bits in the PTE - * plus user for amd64. - */ - (void) HYPERVISOR_update_va_mapping(vaddr, - xen_info->shared_info | PTE_BITS, UVMF_INVLPG | UVMF_LOCAL); - - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - /* - * map the xen console ring buffers - */ - (void) HYPERVISOR_update_va_mapping(vaddr + MMU_PAGESIZE, - mmu_ptob((x86pte_t)xen_info->console.domU.mfn) | PTE_BITS, - UVMF_INVLPG | UVMF_LOCAL); - } else { - /* - * Xen will pass dom0 information about the current - * display settings via xen_info->console.dom0. This - * information includes what video mode we're in (vga - * or vesa) and some basic information about the video - * mode. (screen size, cursor location, etc.) We're - * just going to ignore all this info. Here's some - * reasons why: - * - * - Currently Solaris itself has no support for vesa. - * Also, the only way to boot Solaris is using our - * patched version of grub, which conveniently doesn't - * support vesa either. - * - * - By default when solaris boots up it clears the screen - * thereby removing any previously displayed grub/xen - * console messages, so we really don't care about the - * current vga settings. - * - * Initially we'll map device memory for the frame buffer - * and keyboard into some local memory that already has - * page table entries so that we can get very basic debug - * output. Later on when we're initializing page tables - * we'll map re-map these devices to be at their expected - * addresses. Note that these mappings created below will - * be torn down right before the kernel boots up when - * all the memory and mappings associated with dboot are - * released. - * - * Map the frame buffer. - */ - vaddr = (uintptr_t)&video_fb_buf; - vaddr = (vaddr + MMU_PAGEOFFSET) & MMU_PAGEMASK; - for (i = 0; i < 32 * 1024; i += MMU_PAGESIZE) - (void) HYPERVISOR_update_va_mapping(vaddr + i, - 0xb8000 + i | PTE_DEV_BITS, - UVMF_INVLPG | UVMF_LOCAL); - video_fb = (unsigned short *)vaddr; - - /* Map the keyboard */ - vaddr = (uintptr_t)&kb_status_buf; - vaddr = (vaddr + MMU_PAGEOFFSET) & MMU_PAGEMASK; - (void) HYPERVISOR_update_va_mapping(vaddr, 0x0 | PTE_DEV_BITS, - UVMF_INVLPG | UVMF_LOCAL); - kb_status = (unsigned char *)vaddr; - } - -#endif /* _BOOT */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - HYPERVISOR_console_page = - (void *)((uintptr_t)HYPERVISOR_shared_info + MMU_PAGESIZE); - } else { - HYPERVISOR_console_page = NULL; - } -} - - -/* - * This is the equivalent of polled I/O across the hypervisor CONSOLE - * channel to output 1 character at a time. - */ -void -bcons_putchar_xen(int c) -{ - evtchn_send_t send; - char buffer = (char)c; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - (void) HYPERVISOR_console_io(CONSOLEIO_write, 1, &buffer); - return; - } - - cons_ifp = (volatile struct xencons_interface *)HYPERVISOR_console_page; - - /* - * need to add carriage return for new lines - */ - if (c == '\n') - bcons_putchar_xen('\r'); - - /* - * We have to wait till we have an open transmit slot. - */ - while (cons_ifp->out_prod - cons_ifp->out_cons >= - sizeof (cons_ifp->out)) - (void) HYPERVISOR_yield(); - - cons_ifp->out[MASK_XENCONS_IDX(cons_ifp->out_prod, cons_ifp->out)] = - (char)c; - ++cons_ifp->out_prod; - - /* - * Signal Domain 0 that it has something to do for us. - */ - send.port = xen_info->console.domU.evtchn; - (void) HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); -} - -static uint_t have_char = 0; -static char buffered; - -/* - * See if there is a character on input. - */ -int -bcons_ischar_xen(void) -{ - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - if (have_char) - return (1); - if (HYPERVISOR_console_io(CONSOLEIO_read, 1, &buffered) > 0) - return (have_char = 1); - return (0); - } - - cons_ifp = (volatile struct xencons_interface *)HYPERVISOR_console_page; - if (cons_ifp->in_cons == cons_ifp->in_prod) - return (0); - return (1); -} - -/* - * get a console input character - */ -int -bcons_getchar_xen(void) -{ - evtchn_send_t send; - char c; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - while (have_char == 0) - (void) bcons_ischar_xen(); - have_char = 0; - return (buffered); - } - - cons_ifp = (volatile struct xencons_interface *)HYPERVISOR_console_page; - while (cons_ifp->in_cons == cons_ifp->in_prod) - (void) HYPERVISOR_yield(); - - c = cons_ifp->in[MASK_XENCONS_IDX(cons_ifp->in_cons, cons_ifp->in)]; - ++cons_ifp->in_cons; - - /* - * Signal Domain 0 that we ate a character. - */ - send.port = xen_info->console.domU.evtchn; - (void) HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); - return (c); -} diff --git a/usr/src/uts/i86xpv/consconfig_dacf/Makefile b/usr/src/uts/i86xpv/consconfig_dacf/Makefile deleted file mode 100644 index 80ec7a21c3..0000000000 --- a/usr/src/uts/i86xpv/consconfig_dacf/Makefile +++ /dev/null @@ -1,74 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the consconfig_dacf module. -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = consconfig_dacf -OBJECTS = $(CONSCONFIG_DACF_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DACF_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -LDFLAGS += -dy -Nmisc/usbser - -CERRWARN += -Wno-parentheses - -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_mca_xpv.c b/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_mca_xpv.c deleted file mode 100644 index fd2887b682..0000000000 --- a/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_mca_xpv.c +++ /dev/null @@ -1,305 +0,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. - */ - -#ifndef __xpv -#error "This file is for i86xpv only" -#endif - -#include -#include -#include -#include - -#include "../../i86pc/cpu/generic_cpu/gcpu.h" - -extern xpv_mca_panic_data_t *xpv_mca_panic_data; - -mc_info_t gcpu_mce_data; - -enum mctelem_direction { - MCTELEM_FORWARD, - MCTELEM_REVERSE -}; - -static uint32_t gcpu_xpv_hdl_lookupfails; -static uint32_t gcpu_xpv_bankhdr_found; -static uint32_t gcpu_xpv_spechdr_found; - -static uint32_t gcpu_xpv_mca_hcall_fails[16]; -static uint32_t gcpu_xpv_globalhdr_found; - -static cmi_mca_regs_t *gcpu_xpv_bankregs; -size_t gcpu_xpv_bankregs_sz; - -#define GCPU_XPV_ARCH_NREGS 3 - -void -gcpu_xpv_mca_init(int nbanks) -{ - if (gcpu_xpv_bankregs == NULL) { - gcpu_xpv_bankregs_sz = nbanks * GCPU_XPV_ARCH_NREGS * - sizeof (cmi_mca_regs_t); - - gcpu_xpv_bankregs = kmem_zalloc(gcpu_xpv_bankregs_sz, KM_SLEEP); - } -} - -static void -gcpu_xpv_proxy_logout(int what, struct mc_info *mi, struct mcinfo_common **micp, - int *idxp, cmi_mca_regs_t *bankregs, size_t bankregs_sz) -{ - struct mcinfo_global *mgi = (struct mcinfo_global *)(uintptr_t)*micp; - struct mcinfo_common *mic; - struct mcinfo_bank *mib; - cmi_hdl_t hdl = NULL; - cmi_mca_regs_t *mcrp; - gcpu_data_t *gcpu; - int idx = *idxp; - int tried = 0; - int nbanks, j; - - /* Skip over the MC_TYPE_GLOBAL record */ - ASSERT(mgi->common.type == MC_TYPE_GLOBAL); - mic = x86_mcinfo_next((struct mcinfo_common *)(uintptr_t)mgi); - idx++; - - /* - * Process all MC_TYPE_BANK and MC_TYPE_EXTENDED records that - * follow the MC_TYPE_GLOBAL record, ending when we reach any - * other record type or when we're out of record. - * - * We skip over MC_TYPE_EXTENDED for now - nothing consumes - * the extended MSR data even in native Solaris. - */ - while (idx < x86_mcinfo_nentries(mi) && - (mic->type == MC_TYPE_BANK || mic->type == MC_TYPE_EXTENDED)) { - if (mic->type == MC_TYPE_EXTENDED) { - gcpu_xpv_spechdr_found++; - goto next_record; - } else { - gcpu_xpv_bankhdr_found++; - } - - if (hdl == NULL && !tried++) { - if ((hdl = cmi_hdl_lookup(CMI_HDL_SOLARIS_xVM_MCA, - mgi->mc_socketid, mgi->mc_coreid, - mgi->mc_core_threadid)) == NULL) { - gcpu_xpv_hdl_lookupfails++; - goto next_record; - } else { - gcpu = cmi_hdl_getcmidata(hdl); - nbanks = gcpu->gcpu_mca.gcpu_mca_nbanks; - bzero(bankregs, bankregs_sz); - mcrp = bankregs; - } - } - - mib = (struct mcinfo_bank *)(uintptr_t)mic; - - mcrp->cmr_msrnum = IA32_MSR_MC(mib->mc_bank, STATUS); - mcrp->cmr_msrval = mib->mc_status; - mcrp++; - - mcrp->cmr_msrnum = IA32_MSR_MC(mib->mc_bank, ADDR); - mcrp->cmr_msrval = mib->mc_addr; - mcrp++; - - mcrp->cmr_msrnum = IA32_MSR_MC(mib->mc_bank, MISC); - mcrp->cmr_msrval = mib->mc_misc; - mcrp++; - -next_record: - idx++; - mic = x86_mcinfo_next(mic); - } - - /* - * If we found some telemetry and a handle to associate it with - * then "forward" that telemetry into the MSR interpose layer - * and then request logout which will find that interposed - * telemetry. Indicate that logout code should clear bank - * status registers so that it can invalidate them in the interpose - * layer - they won't actually make it as far as real MSR writes. - */ - if (hdl != NULL) { - cmi_mca_regs_t gsr; - gcpu_mce_status_t mce; - - gsr.cmr_msrnum = IA32_MSR_MCG_STATUS; - gsr.cmr_msrval = mgi->mc_gstatus; - cmi_hdl_msrforward(hdl, &gsr, 1); - - cmi_hdl_msrforward(hdl, bankregs, mcrp - bankregs); - gcpu_mca_logout(hdl, NULL, (uint64_t)-1, &mce, B_TRUE, what); - cmi_hdl_rele(hdl); - } - - /* - * We must move the index on at least one record or our caller - * may loop forever; our initial increment over the global - * record assures this. - */ - ASSERT(idx > *idxp); - *idxp = idx; - *micp = mic; -} - -/* - * Process a struct mc_info. - * - * There are x86_mcinfo_nentries(mi) entries. An entry of type - * MC_TYPE_GLOBAL precedes a number (potentially zero) of - * entries of type MC_TYPE_BANK for telemetry from MCA banks - * of the resource identified in the MC_TYPE_GLOBAL entry. - * I think there can be multiple MC_TYPE_GLOBAL entries per buffer. - */ -void -gcpu_xpv_mci_process(mc_info_t *mi, int type, - cmi_mca_regs_t *bankregs, size_t bankregs_sz) -{ - struct mcinfo_common *mic; - int idx; - - mic = x86_mcinfo_first(mi); - - idx = 0; - while (idx < x86_mcinfo_nentries(mi)) { - if (mic->type == MC_TYPE_GLOBAL) { - gcpu_xpv_globalhdr_found++; - gcpu_xpv_proxy_logout(type == XEN_MC_URGENT ? - GCPU_MPT_WHAT_MC_ERR : GCPU_MPT_WHAT_XPV_VIRQ, - mi, &mic, &idx, bankregs, bankregs_sz); - } else { - idx++; - mic = x86_mcinfo_next(mic); - } - } -} - -int -gcpu_xpv_telem_read(mc_info_t *mci, int type, uint64_t *idp) -{ - xen_mc_t xmc; - xen_mc_fetch_t *mcf = &xmc.u.mc_fetch; - long err; - - mcf->flags = type; - set_xen_guest_handle(mcf->data, mci); - - if ((err = HYPERVISOR_mca(XEN_MC_fetch, &xmc)) != 0) { - gcpu_xpv_mca_hcall_fails[err < 16 ? err : 0]++; - return (0); - } - - if (mcf->flags == XEN_MC_OK) { - *idp = mcf->fetch_id; - return (1); - } else { - *idp = 0; - return (0); - } -} - -void -gcpu_xpv_telem_ack(int type, uint64_t fetch_id) -{ - xen_mc_t xmc; - struct xen_mc_fetch *mcf = &xmc.u.mc_fetch; - - mcf->flags = type | XEN_MC_ACK; - mcf->fetch_id = fetch_id; - (void) HYPERVISOR_mca(XEN_MC_fetch, &xmc); -} - -static void -mctelem_traverse(void *head, enum mctelem_direction direction, - boolean_t urgent) -{ - char *tep = head, **ntepp; - int noff = (direction == MCTELEM_FORWARD) ? - xpv_mca_panic_data->mpd_fwdptr_offset : - xpv_mca_panic_data->mpd_revptr_offset; - - - while (tep != NULL) { - struct mc_info **mcip = (struct mc_info **) - (tep + xpv_mca_panic_data->mpd_dataptr_offset); - - gcpu_xpv_mci_process(*mcip, - urgent ? XEN_MC_URGENT : XEN_MC_NONURGENT, - gcpu_xpv_bankregs, gcpu_xpv_bankregs_sz); - - ntepp = (char **)(tep + noff); - tep = *ntepp; - } -} - -/* - * Callback made from panicsys. We may have reached panicsys from a - * Solaris-initiated panic or a hypervisor-initiated panic; for the - * latter we may not perform any hypercalls. Our task is to retrieve - * unprocessed MCA telemetry from the hypervisor and shovel it into - * errorqs for later processing during panic. - */ -void -gcpu_xpv_panic_callback(void) -{ - if (IN_XPV_PANIC()) { - xpv_mca_panic_data_t *ti = xpv_mca_panic_data; - - if (ti == NULL || - ti->mpd_magic != MCA_PANICDATA_MAGIC || - ti->mpd_version != MCA_PANICDATA_VERS) - return; - - mctelem_traverse(ti->mpd_urgent_processing, MCTELEM_FORWARD, - B_TRUE); - mctelem_traverse(ti->mpd_urgent_dangling, MCTELEM_REVERSE, - B_TRUE); - mctelem_traverse(ti->mpd_urgent_committed, MCTELEM_REVERSE, - B_TRUE); - - mctelem_traverse(ti->mpd_nonurgent_processing, MCTELEM_FORWARD, - B_FALSE); - mctelem_traverse(ti->mpd_nonurgent_dangling, MCTELEM_REVERSE, - B_FALSE); - mctelem_traverse(ti->mpd_nonurgent_committed, MCTELEM_REVERSE, - B_FALSE); - } else { - int types[] = { XEN_MC_URGENT, XEN_MC_NONURGENT }; - uint64_t fetch_id; - int i; - - for (i = 0; i < sizeof (types) / sizeof (types[0]); i++) { - while (gcpu_xpv_telem_read(&gcpu_mce_data, - types[i], &fetch_id)) { - gcpu_xpv_mci_process(&gcpu_mce_data, types[i], - gcpu_xpv_bankregs, gcpu_xpv_bankregs_sz); - gcpu_xpv_telem_ack(types[i], fetch_id); - } - } - } -} diff --git a/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_poll_xpv.c b/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_poll_xpv.c deleted file mode 100644 index 8bc46f8e3e..0000000000 --- a/usr/src/uts/i86xpv/cpu/generic_cpu/gcpu_poll_xpv.c +++ /dev/null @@ -1,200 +0,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. - */ - -/* - * "Polled" MCA events in an i86xpv dom0. A timeout runs in the hypervisor - * and checks MCA state. If it observes valid MCA state in a bank and if - * it sees that dom0 has registered a handler for the VIRQ_MCA then it - * raises that VIRQ to dom0. The interrupt handler performs a - * hypercall to retrieve the polled telemetry and then pushes that telemetry - * into the MSR interpose hash and calls the generic logout code which - * will then find the provided interposed MSR values when it performs - * cmi_hdl_rdmsr so logout code works unchanged for native or i86xpv dom0. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../i86pc/cpu/generic_cpu/gcpu.h" - -extern int *gcpu_xpv_telem_read(mc_info_t *, int, uint64_t *); -extern void gcpu_xpv_telem_ack(int, uint64_t); -extern void gcpu_xpv_mci_process(mc_info_t *, int, cmi_mca_regs_t *, size_t); - -int gcpu_xpv_mch_poll_interval_secs = 10; -int gcpu_xpv_virq_level = 3; - -static timeout_id_t gcpu_xpv_mch_poll_timeoutid; - -static int gcpu_xpv_virq_vect = -1; - -static mc_info_t gcpu_xpv_polldata; -static kmutex_t gcpu_xpv_polldata_lock; - -static cmi_mca_regs_t *gcpu_xpv_poll_bankregs; -static size_t gcpu_xpv_poll_bankregs_sz; - -static uint32_t gcpu_xpv_intr_unclaimed; -static uint32_t gcpu_xpv_mca_hcall_busy; - -static gcpu_poll_trace_ctl_t gcpu_xpv_poll_trace_ctl; - -#define GCPU_XPV_ARCH_NREGS 3 -#define GCPU_XPV_MCH_POLL_REARM ((void *)1) -#define GCPU_XPV_MCH_POLL_NO_REARM NULL - -static uint_t -gcpu_xpv_virq_intr(void) -{ - int types[] = { XEN_MC_URGENT, XEN_MC_NONURGENT }; - uint64_t fetch_id; - int count = 0; - int i; - - if (gcpu_xpv_virq_vect == -1 || gcpu_xpv_poll_bankregs_sz == 0) { - gcpu_xpv_intr_unclaimed++; - return (DDI_INTR_UNCLAIMED); - } - - if (!mutex_tryenter(&gcpu_xpv_polldata_lock)) { - gcpu_xpv_mca_hcall_busy++; - return (DDI_INTR_CLAIMED); - } - - for (i = 0; i < sizeof (types) / sizeof (types[0]); i++) { - while (gcpu_xpv_telem_read(&gcpu_xpv_polldata, types[i], - &fetch_id)) { - gcpu_poll_trace(&gcpu_xpv_poll_trace_ctl, - GCPU_MPT_WHAT_XPV_VIRQ, - x86_mcinfo_nentries(&gcpu_xpv_polldata)); - gcpu_xpv_mci_process(&gcpu_xpv_polldata, types[i], - gcpu_xpv_poll_bankregs, gcpu_xpv_poll_bankregs_sz); - gcpu_xpv_telem_ack(types[i], fetch_id); - count++; - } - } - - mutex_exit(&gcpu_xpv_polldata_lock); - - return (DDI_INTR_CLAIMED); -} - -static void -gcpu_xpv_mch_poll(void *arg) -{ - cmi_hdl_t hdl = cmi_hdl_any(); - - if (hdl != NULL) { - cmi_mc_logout(hdl, 0, 0); - cmi_hdl_rele(hdl); - } - - if (arg == GCPU_XPV_MCH_POLL_REARM && - gcpu_xpv_mch_poll_interval_secs != 0) { - gcpu_xpv_mch_poll_timeoutid = timeout(gcpu_xpv_mch_poll, - GCPU_XPV_MCH_POLL_REARM, - drv_usectohz(gcpu_xpv_mch_poll_interval_secs * MICROSEC)); - } -} - -/* - * gcpu_mca_poll_init is called from gcpu_mca_init for each cpu handle - * that we initialize for. It should prepare for polling by allocating - * control structures and the like, but must not kick polling off yet. - * - * Since we initialize all cpus in a serialized loop there is no race - * on allocating the bankregs structure, nor in free'ing and enlarging - * it if we find the number of MCA banks is not uniform in the system - * (unlikely) since polling is only started post mp startup. - */ - -void -gcpu_mca_poll_init(cmi_hdl_t hdl) -{ - gcpu_data_t *gcpu = cmi_hdl_getcmidata(hdl); - int nbanks = gcpu->gcpu_mca.gcpu_mca_nbanks; - size_t sz = nbanks * GCPU_XPV_ARCH_NREGS * sizeof (cmi_mca_regs_t); - - ASSERT(cmi_hdl_class(hdl) == CMI_HDL_SOLARIS_xVM_MCA); - - if (gcpu_xpv_poll_bankregs == NULL || sz > gcpu_xpv_poll_bankregs_sz) { - if (gcpu_xpv_poll_bankregs != NULL) { - kmem_free(gcpu_xpv_poll_bankregs, - gcpu_xpv_poll_bankregs_sz); - } else { - gcpu_poll_trace_init(&gcpu_xpv_poll_trace_ctl); - } - - gcpu_xpv_poll_bankregs_sz = sz; - gcpu_xpv_poll_bankregs = kmem_zalloc(sz, KM_SLEEP); - - } -} - -/* deconfigure gcpu_mca_poll_init() */ -void -gcpu_mca_poll_fini(cmi_hdl_t hdl) -{ -} - -void -gcpu_mca_poll_start(cmi_hdl_t hdl) -{ - ASSERT(cmi_hdl_class(hdl) == CMI_HDL_SOLARIS_xVM_MCA); - /* - * We are on the boot cpu (cpu 0), called at the end of its - * multiprocessor startup. - */ - if (gcpu_xpv_poll_bankregs_sz != 0 && gcpu_xpv_virq_vect == -1) { - /* - * The hypervisor will poll MCA state for us, but it cannot - * poll MCH state so we do that via a timeout. - */ - if (gcpu_xpv_mch_poll_interval_secs != 0) { - gcpu_xpv_mch_poll_timeoutid = - timeout(gcpu_xpv_mch_poll, GCPU_XPV_MCH_POLL_REARM, - drv_usectohz(gcpu_xpv_mch_poll_interval_secs * - MICROSEC)); - } - - /* - * Register handler for VIRQ_MCA; once this is in place - * the hypervisor will begin to forward polled MCA observations - * to us. - */ - gcpu_xpv_virq_vect = ec_bind_virq_to_irq(VIRQ_MCA, 0); - (void) add_avintr(NULL, gcpu_xpv_virq_level, - (avfunc)gcpu_xpv_virq_intr, "MCA", gcpu_xpv_virq_vect, - NULL, NULL, NULL, NULL); - } -} diff --git a/usr/src/uts/i86xpv/cpu/scripts/Makefile b/usr/src/uts/i86xpv/cpu/scripts/Makefile deleted file mode 100644 index e5c08d85f6..0000000000 --- a/usr/src/uts/i86xpv/cpu/scripts/Makefile +++ /dev/null @@ -1,46 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2013 Nexenta Systems, Inc. All rights reserved. -# - -PERLFILES= \ - ao_gendisp - -include ../../../Makefile.uts - -.KEEP_STATE: - -def all install setup: ao_gendisp.pl $(PERLFILES) - -# We are sharing the ao_gendisp source with the i86pc -AO_GENDISP_PL=../../../i86pc/cpu/scripts/ao_gendisp.pl -ao_gendisp.pl: $(AO_GENDISP_PL) - $(SYMLINK) $(AO_GENDISP_PL) $@ - -clean clobber: - $(RM) ao_gendisp.pl $(PERLFILES) - -include ../../../Makefile.targ diff --git a/usr/src/uts/i86xpv/domcaps/Makefile b/usr/src/uts/i86xpv/domcaps/Makefile deleted file mode 100644 index 7cf5270f7b..0000000000 --- a/usr/src/uts/i86xpv/domcaps/Makefile +++ /dev/null @@ -1,75 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the domcaps -# driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = domcaps -OBJECTS = $(DOMCAPS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/evtchn/Makefile b/usr/src/uts/i86xpv/evtchn/Makefile deleted file mode 100644 index 0494302159..0000000000 --- a/usr/src/uts/i86xpv/evtchn/Makefile +++ /dev/null @@ -1,75 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the evtchn -# driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = evtchn -OBJECTS = $(EVTCHN_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/genassym/Makefile b/usr/src/uts/i86xpv/genassym/Makefile deleted file mode 100644 index 31944c010a..0000000000 --- a/usr/src/uts/i86xpv/genassym/Makefile +++ /dev/null @@ -1,98 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# -# This makefile drives the production of assym.h through -# compile time intialized data. -# -# i86xpv implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/assym.h -KDI_ASSYM_H = $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h -GENASSYM = $(DSF_DIR)/$(OBJS_DIR)/genassym - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(ASSYM_H) $(KDI_ASSYM_H) - -# -# This is DSF_DIR. Use a short path. -# -DSF_DIR = . - - -# -# Overrides -# -CLEANFILES = $(GENASSYM) Nothing_to_remove -CLOBBERFILES = $(ASSYM_H) $(KDI_ASSYM_H) $(CLEANFILES) Nothing_to_remove - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: def - -# -# Create assym.h -# -$(GENASSYM): $(GENASSYM_SRC) - $(NATIVECC) $(NATIVE_CFLAGS) $(ALWAYS_DEFS) $(GENASSYM_DEFS) \ - $(NATIVE_INC_PATH) -o $@ $(GENASSYM_SRC) - -$(ASSYM_H): $(OFFSETS_SRC) $(PLATFORM_OFFSETS_SRC) $(GENASSYM) - $(OFFSETS_CREATE) <$(OFFSETS_SRC) >$@ - $(OFFSETS_CREATE) <$(PLATFORM_OFFSETS_SRC) >>$@ - $(GENASSYM) >>$@ - -$(KDI_ASSYM_H): $(KDI_OFFSETS_SRC) $(GENASSYM) - $(OFFSETS_CREATE) <$(KDI_OFFSETS_SRC) >$@ - $(GENASSYM) >>$@ - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/generic_cpu/Makefile b/usr/src/uts/i86xpv/generic_cpu/Makefile deleted file mode 100644 index 9de2c75cfc..0000000000 --- a/usr/src/uts/i86xpv/generic_cpu/Makefile +++ /dev/null @@ -1,74 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = cpu.generic -# -OBJECTS = $(CPU_GCPU_OBJS:%=$(OBJS_DIR)/%) -OBJECTS += $(CPU_GCPU_XPV_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_CPU_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv -include $(UTSBASE)/i86pc/cpu/Makefile.files - -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-unused-variable - -# -# 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 ../Makefile.targ diff --git a/usr/src/uts/i86xpv/genuineintel/Makefile b/usr/src/uts/i86xpv/genuineintel/Makefile deleted file mode 100644 index 08f7f7d19f..0000000000 --- a/usr/src/uts/i86xpv/genuineintel/Makefile +++ /dev/null @@ -1,76 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = cpu_ms.GenuineIntel -# -OBJECTS = $(CPU_GENINTEL_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_CPU_DIR)/$(MODULE) - -SRCDIR = ../../i86pc/cpu/genuineintel - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv -include $(UTSBASE)/i86pc/cpu/Makefile.files - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides and additions -# -CPPFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -ASFLAGS += -I$(SRCDIR) -I$(OBJS_DIR) -LDFLAGS += -dy -N misc/acpica - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include ../Makefile.targ diff --git a/usr/src/uts/i86xpv/gfx_private/Makefile b/usr/src/uts/i86xpv/gfx_private/Makefile deleted file mode 100644 index e2088d3b64..0000000000 --- a/usr/src/uts/i86xpv/gfx_private/Makefile +++ /dev/null @@ -1,85 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# Copyright 2015 Igor Kozhukhov -# - -# -# This makefile drives the production of the graphics private -# interface kernel module. -# -# i86xpv platform dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = gfx_private -OBJECTS = $(GFX_PRIVATE_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) - -# -# dependency -# -LDFLAGS += -dy -Nmisc/pci_autoconfig - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - - -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-parentheses - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/io/balloon_drv.c b/usr/src/uts/i86xpv/io/balloon_drv.c deleted file mode 100644 index c0a0e0de01..0000000000 --- a/usr/src/uts/i86xpv/io/balloon_drv.c +++ /dev/null @@ -1,197 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -/* - * A simple wrapper around the balloon kernel thread to allow userland - * programs access to the balloon status. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static dev_info_t *balloon_devi; - -/*ARGSUSED*/ -static int -balloon_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result) -{ - if (getminor((dev_t)arg) != BALLOON_MINOR) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = balloon_devi; - break; - case DDI_INFO_DEVT2INSTANCE: - *result = 0; - break; - default: - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static int -balloon_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR, - ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - balloon_devi = devi; - ddi_report_dev(devi); - return (DDI_SUCCESS); -} - -static int -balloon_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - ddi_remove_minor_node(devi, NULL); - balloon_devi = NULL; - return (DDI_SUCCESS); -} - -/*ARGSUSED1*/ -static int -balloon_open(dev_t *dev, int flag, int otyp, cred_t *cr) -{ - return (getminor(*dev) == BALLOON_MINOR ? 0 : ENXIO); -} - -/* - * When asked for one of the balloon values, we simply query the balloon thread. - */ -/*ARGSUSED*/ -static int -balloon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, - int *rval_p) -{ - int rval = 0; - size_t value; - - switch (cmd) { - case BLN_IOCTL_CURRENT: - case BLN_IOCTL_TARGET: - case BLN_IOCTL_LOW: - case BLN_IOCTL_HIGH: - case BLN_IOCTL_LIMIT: - value = balloon_values(cmd); - if (ddi_copyout((void *)&value, (void *)arg, sizeof (value), - mode)) - return (EFAULT); - break; - default: - rval = EINVAL; - break; - } - return (rval); -} - -static struct cb_ops balloon_cb_ops = { - balloon_open, - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - balloon_ioctl, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, - NULL, - D_64BIT | D_MP, - CB_REV, - NULL, - NULL -}; - -static struct dev_ops balloon_dv_ops = { - DEVO_REV, - 0, - balloon_getinfo, - nulldev, /* identify */ - nulldev, /* probe */ - balloon_attach, - balloon_detach, - nodev, /* reset */ - &balloon_cb_ops, - NULL, /* struct bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, - "balloon driver", - &balloon_dv_ops -}; - -static struct modlinkage modl = { - MODREV_1, - { - (void *)&modldrv, - NULL /* null termination */ - } -}; - -int -_init(void) -{ - return (mod_install(&modl)); -} - -int -_fini(void) -{ - return (mod_remove(&modl)); -} - -int -_info(struct modinfo *modinfo) -{ - return (mod_info(&modl, modinfo)); -} diff --git a/usr/src/uts/i86xpv/io/domcaps.c b/usr/src/uts/i86xpv/io/domcaps.c deleted file mode 100644 index 7a015c60f2..0000000000 --- a/usr/src/uts/i86xpv/io/domcaps.c +++ /dev/null @@ -1,187 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * This rather uninspiring device enables userland to discover if - * the current kernel is actually a dom0 or other domain e.g. domU. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static dev_info_t *domcaps_devi; - -/*ARGSUSED*/ -static int -domcaps_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result) -{ - if (getminor((dev_t)arg) != DOMCAPS_MINOR) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - *result = domcaps_devi; - break; - case DDI_INFO_DEVT2INSTANCE: - *result = 0; - break; - default: - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); -} - -static int -domcaps_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - if (ddi_create_minor_node(devi, ddi_get_name(devi), S_IFCHR, - ddi_get_instance(devi), DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - domcaps_devi = devi; - ddi_report_dev(devi); - return (DDI_SUCCESS); -} - -static int -domcaps_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - ddi_remove_minor_node(devi, NULL); - domcaps_devi = NULL; - return (DDI_SUCCESS); -} - -/*ARGSUSED1*/ -static int -domcaps_open(dev_t *dev, int flag, int otyp, cred_t *cr) -{ - return (getminor(*dev) == DOMCAPS_MINOR ? 0 : ENXIO); -} - -/*ARGSUSED*/ -static int -domcaps_read(dev_t dev, uio_t *uio, cred_t *cr) -{ - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - static char data[] = "control_d\n"; - size_t nbytes; - - if (uio->uio_loffset > sizeof (data)) - return (0); - nbytes = MIN(uio->uio_resid, sizeof (data) - uio->uio_loffset); - - return (uiomove(data + uio->uio_loffset, nbytes, - UIO_READ, uio)); - } - - return (0); -} - -static struct cb_ops domcaps_cb_ops = { - domcaps_open, - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - domcaps_read, - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, - NULL, - D_64BIT | D_MP, - CB_REV, - NULL, - NULL -}; - -static struct dev_ops domcaps_dv_ops = { - DEVO_REV, - 0, - domcaps_getinfo, - nulldev, /* identify */ - nulldev, /* probe */ - domcaps_attach, - domcaps_detach, - nodev, /* reset */ - &domcaps_cb_ops, - NULL, /* struct bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, - "hypervisor capabilities driver", - &domcaps_dv_ops -}; - -static struct modlinkage modl = { - MODREV_1, - { - (void *)&modldrv, - NULL /* null termination */ - } -}; - -int -_init(void) -{ - return (mod_install(&modl)); -} - -int -_fini(void) -{ - return (mod_remove(&modl)); -} - -int -_info(struct modinfo *modinfo) -{ - return (mod_info(&modl, modinfo)); -} diff --git a/usr/src/uts/i86xpv/io/privcmd.c b/usr/src/uts/i86xpv/io/privcmd.c deleted file mode 100644 index dcd629da39..0000000000 --- a/usr/src/uts/i86xpv/io/privcmd.c +++ /dev/null @@ -1,411 +0,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 - -static dev_info_t *privcmd_devi; - -/*ARGSUSED*/ -static int -privcmd_getinfo(dev_info_t *devi, ddi_info_cmd_t cmd, void *arg, void **result) -{ - switch (cmd) { - case DDI_INFO_DEVT2DEVINFO: - case DDI_INFO_DEVT2INSTANCE: - break; - default: - return (DDI_FAILURE); - } - - switch (getminor((dev_t)arg)) { - case PRIVCMD_MINOR: - break; - default: - return (DDI_FAILURE); - } - - if (cmd == DDI_INFO_DEVT2INSTANCE) - *result = 0; - else - *result = privcmd_devi; - return (DDI_SUCCESS); -} - -static int -privcmd_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) -{ - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - if (ddi_create_minor_node(devi, PRIVCMD_NODE, - S_IFCHR, PRIVCMD_MINOR, DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - privcmd_devi = devi; - ddi_report_dev(devi); - return (DDI_SUCCESS); -} - -static int -privcmd_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) -{ - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - ddi_remove_minor_node(devi, NULL); - privcmd_devi = NULL; - return (DDI_SUCCESS); -} - -/*ARGSUSED1*/ -static int -privcmd_open(dev_t *dev, int flag, int otyp, cred_t *cr) -{ - return (getminor(*dev) == PRIVCMD_MINOR ? 0 : ENXIO); -} - -/* - * Map a contiguous set of machine frames in a foreign domain. - * Used in the following way: - * - * privcmd_mmap_t p; - * privcmd_mmap_entry_t e; - * - * addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0); - * p.num = number of privcmd_mmap_entry_t's - * p.dom = domid; - * p.entry = &e; - * e.va = addr; - * e.mfn = mfn; - * e.npages = btopr(size); - * ioctl(fd, IOCTL_PRIVCMD_MMAP, &p); - */ -/*ARGSUSED2*/ -int -do_privcmd_mmap(void *uarg, int mode, cred_t *cr) -{ - privcmd_mmap_t __mmapcmd, *mmc = &__mmapcmd; - privcmd_mmap_entry_t *umme; - struct as *as = curproc->p_as; - struct seg *seg; - int i, error = 0; - - if (ddi_copyin(uarg, mmc, sizeof (*mmc), mode)) - return (EFAULT); - - DTRACE_XPV3(mmap__start, domid_t, mmc->dom, int, mmc->num, - privcmd_mmap_entry_t *, mmc->entry); - - if (mmc->dom == DOMID_SELF) { - error = ENOTSUP; /* Too paranoid? */ - goto done; - } - - for (umme = mmc->entry, i = 0; i < mmc->num; i++, umme++) { - privcmd_mmap_entry_t __mmapent, *mme = &__mmapent; - caddr_t addr; - - if (ddi_copyin(umme, mme, sizeof (*mme), mode)) { - error = EFAULT; - break; - } - - DTRACE_XPV3(mmap__entry, ulong_t, mme->va, ulong_t, mme->mfn, - ulong_t, mme->npages); - - if (mme->mfn == MFN_INVALID) { - error = EINVAL; - break; - } - - addr = (caddr_t)mme->va; - - /* - * Find the segment we want to mess with, then add - * the mfn range to the segment. - */ - AS_LOCK_ENTER(as, RW_READER); - if ((seg = as_findseg(as, addr, 0)) == NULL || - addr + mmu_ptob(mme->npages) > seg->s_base + seg->s_size) - error = EINVAL; - else - error = segmf_add_mfns(seg, addr, - mme->mfn, mme->npages, mmc->dom); - AS_LOCK_EXIT(as); - - if (error != 0) - break; - } - -done: - DTRACE_XPV1(mmap__end, int, error); - - return (error); -} - -/* - * Set up the address range to map to an array of mfns in - * a foreign domain. Used in the following way: - * - * privcmd_mmap_batch_t p; - * - * addr = mmap(NULL, size, prot, MAP_SHARED, fd, 0); - * p.num = number of pages - * p.dom = domid - * p.addr = addr; - * p.arr = array of mfns, indexed 0 .. p.num - 1 - * ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &p); - */ -/*ARGSUSED2*/ -static int -do_privcmd_mmapbatch(void *uarg, int mode, cred_t *cr) -{ - privcmd_mmapbatch_t __mmapbatch, *mmb = &__mmapbatch; - struct as *as = curproc->p_as; - struct seg *seg; - int i, error = 0; - caddr_t addr; - ulong_t *ulp; - - if (ddi_copyin(uarg, mmb, sizeof (*mmb), mode)) - return (EFAULT); - - DTRACE_XPV3(mmapbatch__start, domid_t, mmb->dom, int, mmb->num, - caddr_t, mmb->addr); - - addr = (caddr_t)mmb->addr; - AS_LOCK_ENTER(as, RW_READER); - if ((seg = as_findseg(as, addr, 0)) == NULL || - addr + ptob(mmb->num) > seg->s_base + seg->s_size) { - error = EINVAL; - goto done; - } - - for (i = 0, ulp = mmb->arr; - i < mmb->num; i++, addr += PAGESIZE, ulp++) { - mfn_t mfn; - - if (fulword(ulp, &mfn) != 0) { - error = EFAULT; - break; - } - - if (mfn == MFN_INVALID) { - /* - * This mfn is invalid and should not be added to - * segmf, as we'd only cause an immediate EFAULT when - * we tried to fault it in. - */ - mfn |= XEN_DOMCTL_PFINFO_XTAB; - continue; - } - - if (segmf_add_mfns(seg, addr, mfn, 1, mmb->dom) == 0) - continue; - - /* - * Tell the process that this MFN could not be mapped, so it - * won't later try to access it. - */ - mfn |= XEN_DOMCTL_PFINFO_XTAB; - if (sulword(ulp, mfn) != 0) { - error = EFAULT; - break; - } - } - -done: - AS_LOCK_EXIT(as); - - DTRACE_XPV3(mmapbatch__end, int, error, struct seg *, seg, caddr_t, - mmb->addr); - - return (error); -} - -/*ARGSUSED*/ -static int -privcmd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval) -{ - if (secpolicy_xvm_control(cr)) - return (EPERM); - - /* - * Everything is a -native- data type. - */ - if ((mode & FMODELS) != FNATIVE) - return (EOVERFLOW); - - switch (cmd) { - case IOCTL_PRIVCMD_HYPERCALL: - return (do_privcmd_hypercall((void *)arg, mode, cr, rval)); - case IOCTL_PRIVCMD_MMAP: - if (DOMAIN_IS_PRIVILEGED(xen_info)) - return (do_privcmd_mmap((void *)arg, mode, cr)); - break; - case IOCTL_PRIVCMD_MMAPBATCH: - if (DOMAIN_IS_PRIVILEGED(xen_info)) - return (do_privcmd_mmapbatch((void *)arg, mode, cr)); - break; - default: - break; - } - return (EINVAL); -} - -/* - * The real magic happens in the segmf segment driver. - */ -/*ARGSUSED8*/ -static int -privcmd_segmap(dev_t dev, off_t off, struct as *as, caddr_t *addrp, - off_t len, uint_t prot, uint_t maxprot, uint_t flags, cred_t *cr) -{ - struct segmf_crargs a; - int error; - - if (secpolicy_xvm_control(cr)) - return (EPERM); - - as_rangelock(as); - if ((flags & MAP_FIXED) == 0) { - map_addr(addrp, len, (offset_t)off, 0, flags); - if (*addrp == NULL) { - error = ENOMEM; - goto rangeunlock; - } - } else { - /* - * User specified address - */ - (void) as_unmap(as, *addrp, len); - } - - /* - * The mapping *must* be MAP_SHARED at offset 0. - * - * (Foreign pages are treated like device memory; the - * ioctl interface allows the backing objects to be - * arbitrarily redefined to point at any machine frame.) - */ - if ((flags & MAP_TYPE) != MAP_SHARED || off != 0) { - error = EINVAL; - goto rangeunlock; - } - - a.dev = dev; - a.prot = (uchar_t)prot; - a.maxprot = (uchar_t)maxprot; - error = as_map(as, *addrp, len, segmf_create, &a); - -rangeunlock: - as_rangeunlock(as); - return (error); -} - -static struct cb_ops privcmd_cb_ops = { - privcmd_open, - nulldev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - privcmd_ioctl, - nodev, /* devmap */ - nodev, /* mmap */ - privcmd_segmap, - nochpoll, /* poll */ - ddi_prop_op, - NULL, - D_64BIT | D_NEW | D_MP -}; - -static struct dev_ops privcmd_dv_ops = { - DEVO_REV, - 0, - privcmd_getinfo, - nulldev, /* identify */ - nulldev, /* probe */ - privcmd_attach, - privcmd_detach, - nodev, /* reset */ - &privcmd_cb_ops, - 0, /* struct bus_ops */ - NULL, /* power */ - ddi_quiesce_not_needed, /* quiesce */ -}; - -static struct modldrv modldrv = { - &mod_driverops, - "privcmd driver", - &privcmd_dv_ops -}; - -static struct modlinkage modl = { - MODREV_1, - &modldrv -}; - -int -_init(void) -{ - return (mod_install(&modl)); -} - -int -_fini(void) -{ - return (mod_remove(&modl)); -} - -int -_info(struct modinfo *modinfo) -{ - return (mod_info(&modl, modinfo)); -} diff --git a/usr/src/uts/i86xpv/io/privcmd_hcall.c b/usr/src/uts/i86xpv/io/privcmd_hcall.c deleted file mode 100644 index 0c9a6198ab..0000000000 --- a/usr/src/uts/i86xpv/io/privcmd_hcall.c +++ /dev/null @@ -1,1252 +0,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 2010 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 - -typedef struct import_export { - void * ie_uaddr; - void * ie_kaddr; - size_t ie_size; - uint32_t ie_flags; -} import_export_t; - -static import_export_t null_ie = {NULL, NULL, 0, 0}; - -#define IE_IMPORT 0x0001 /* Data needs to be copied in */ -#define IE_EXPORT 0x0002 /* Data needs to be copied out */ -#define IE_FREE 0x0004 -#define IE_IMPEXP (IE_IMPORT | IE_EXPORT) - -static void * -uaddr_from_handle(void *field) -{ - struct { void *p; } *hdl = field; - void *ptr; - - /*LINTED: constant in conditional context*/ - get_xen_guest_handle(ptr, (*hdl)); - return (ptr); -} - - -/* - * Import a buffer from user-space. If the caller provides a kernel - * address, we import to that address. If not, we kmem_alloc() the space - * ourselves. - */ -static int -import_buffer(import_export_t *iep, void *uaddr, void *kaddr, size_t size, - uint32_t flags) -{ - iep->ie_uaddr = uaddr; - iep->ie_size = size; - iep->ie_flags = flags & IE_EXPORT; - - if (size == 0 || uaddr == NULL) { - *iep = null_ie; - return (0); - } - - if (kaddr == NULL) { - iep->ie_kaddr = kmem_alloc(size, KM_SLEEP); - iep->ie_flags |= IE_FREE; - } else { - iep->ie_kaddr = kaddr; - iep->ie_flags &= ~IE_FREE; - } - - if ((flags & IE_IMPORT) && - (ddi_copyin(uaddr, iep->ie_kaddr, size, 0) != 0)) { - if (iep->ie_flags & IE_FREE) { - kmem_free(iep->ie_kaddr, iep->ie_size); - iep->ie_kaddr = NULL; - iep->ie_flags = 0; - } - return (-X_EFAULT); - } - - return (0); -} - -static void -export_buffer(import_export_t *iep, int *error) -{ - int copy_err = 0; - - if (iep->ie_size == 0 || iep->ie_uaddr == NULL) - return; - - /* - * If the buffer was marked for export initially, and if the - * hypercall completed successfully, resync the user-space buffer - * with our in-kernel buffer. - */ - if ((iep->ie_flags & IE_EXPORT) && (*error >= 0) && - (ddi_copyout(iep->ie_kaddr, iep->ie_uaddr, iep->ie_size, 0) != 0)) - copy_err = -X_EFAULT; - if (iep->ie_flags & IE_FREE) { - kmem_free(iep->ie_kaddr, iep->ie_size); - iep->ie_kaddr = NULL; - iep->ie_flags = 0; - } - - if (copy_err != 0 && *error >= 0) - *error = copy_err; -} - -/* - * Xen 'op' structures often include pointers disguised as 'handles', which - * refer to addresses in user space. This routine copies a buffer - * associated with an embedded pointer into kernel space, and replaces the - * pointer to userspace with a pointer to the new kernel buffer. - * - * Note: if Xen ever redefines the structure of a 'handle', this routine - * (specifically the definition of 'hdl') will need to be updated. - */ -static int -import_handle(import_export_t *iep, void *field, size_t size, int flags) -{ - struct { void *p; } *hdl = field; - void *ptr; - int err; - - ptr = uaddr_from_handle(field); - err = import_buffer(iep, ptr, NULL, size, (flags)); - if (err == 0) { - /*LINTED: constant in conditional context*/ - set_xen_guest_handle((*hdl), (void *)((iep)->ie_kaddr)); - } - return (err); -} - -static int -privcmd_HYPERVISOR_mmu_update(mmu_update_t *ureq, int count, int *scount, - domid_t domid) -{ - mmu_update_t *kreq, single_kreq; - import_export_t cnt_ie, req_ie; - int error, kscount, bytes; - - bytes = count * sizeof (*kreq); - kreq = (count == 1) ? &single_kreq : kmem_alloc(bytes, KM_SLEEP); - - error = import_buffer(&cnt_ie, scount, &kscount, sizeof (kscount), - IE_IMPEXP); - if (error != 0) - req_ie = null_ie; - else - error = import_buffer(&req_ie, ureq, kreq, bytes, IE_IMPEXP); - - DTRACE_XPV3(mmu__update__start, int, domid, int, count, mmu_update_t *, - ((error == -X_EFAULT) ? ureq : kreq)); - - if (error == 0) - error = HYPERVISOR_mmu_update(kreq, count, &kscount, domid); - export_buffer(&cnt_ie, &error); - export_buffer(&req_ie, &error); - if (count != 1) - kmem_free(kreq, bytes); - - DTRACE_XPV1(mmu__update__end, int, error); - return (error); -} - -static int -privcmd_HYPERVISOR_domctl(xen_domctl_t *opp) -{ - xen_domctl_t op; - import_export_t op_ie, sub_ie; - int error = 0; - - if ((error = import_buffer(&op_ie, opp, &op, sizeof (op), - IE_IMPEXP)) != 0) - return (error); - - sub_ie = null_ie; - - /* - * Check this first because our wrapper will forcibly overwrite it. - */ - if (op.interface_version != XEN_DOMCTL_INTERFACE_VERSION) { -#ifdef DEBUG - printf("domctl vers mismatch (cmd %d, found 0x%x, need 0x%x\n", - op.cmd, op.interface_version, XEN_DOMCTL_INTERFACE_VERSION); -#endif - error = -X_EACCES; - export_buffer(&op_ie, &error); - return (error); - } - - /* - * Now handle any domctl ops with embedded pointers elsewhere - * in the user address space that also need to be tacked down - * while the hypervisor futzes with them. - */ - switch (op.cmd) { - case XEN_DOMCTL_createdomain: - DTRACE_XPV1(dom__create__start, xen_domctl_t *, - &op.u.createdomain); - break; - - case XEN_DOMCTL_destroydomain: - DTRACE_XPV1(dom__destroy__start, domid_t, op.domain); - break; - - case XEN_DOMCTL_pausedomain: - DTRACE_XPV1(dom__pause__start, domid_t, op.domain); - break; - - case XEN_DOMCTL_unpausedomain: - DTRACE_XPV1(dom__unpause__start, domid_t, op.domain); - break; - - case XEN_DOMCTL_getmemlist: { - error = import_handle(&sub_ie, &op.u.getmemlist.buffer, - op.u.getmemlist.max_pfns * sizeof (xen_pfn_t), IE_EXPORT); - break; - } - - case XEN_DOMCTL_getpageframeinfo2: { - error = import_handle(&sub_ie, &op.u.getpageframeinfo2.array, - op.u.getpageframeinfo2.num * sizeof (ulong_t), IE_IMPEXP); - break; - } - - case XEN_DOMCTL_shadow_op: { - size_t size; - - size = roundup(howmany(op.u.shadow_op.pages, NBBY), - sizeof (ulong_t)); - error = import_handle(&sub_ie, - &op.u.shadow_op.dirty_bitmap, size, IE_IMPEXP); - break; - } - - case XEN_DOMCTL_setvcpucontext: { - vcpu_guest_context_t *taddr; - error = import_handle(&sub_ie, &op.u.vcpucontext.ctxt, - sizeof (vcpu_guest_context_t), IE_IMPORT); - if (error == -X_EFAULT) - /*LINTED: constant in conditional context*/ - get_xen_guest_handle_u(taddr, op.u.vcpucontext.ctxt); - else - taddr = sub_ie.ie_kaddr; - DTRACE_XPV2(setvcpucontext__start, domid_t, op.domain, - vcpu_guest_context_t *, taddr); - break; - } - - case XEN_DOMCTL_getvcpucontext: { - error = import_handle(&sub_ie, &op.u.vcpucontext.ctxt, - sizeof (vcpu_guest_context_t), IE_EXPORT); - break; - } - - - case XEN_DOMCTL_sethvmcontext: { - error = import_handle(&sub_ie, &op.u.hvmcontext.buffer, - op.u.hvmcontext.size, IE_IMPORT); - break; - } - - case XEN_DOMCTL_gethvmcontext: { -#if !defined(__GNUC__) && defined(__i386__) - if (op.u.hvmcontext.buffer.u.p != NULL) -#else - if (op.u.hvmcontext.buffer.p != NULL) -#endif - error = import_handle(&sub_ie, &op.u.hvmcontext.buffer, - op.u.hvmcontext.size, IE_EXPORT); - break; - } - - case XEN_DOMCTL_getdomaininfo: - case XEN_DOMCTL_getpageframeinfo: - case XEN_DOMCTL_max_mem: - case XEN_DOMCTL_resumedomain: - case XEN_DOMCTL_getvcpuinfo: - case XEN_DOMCTL_setvcpuaffinity: - case XEN_DOMCTL_getvcpuaffinity: - case XEN_DOMCTL_max_vcpus: - case XEN_DOMCTL_scheduler_op: - case XEN_DOMCTL_setdomainhandle: - case XEN_DOMCTL_setdebugging: - case XEN_DOMCTL_irq_permission: - case XEN_DOMCTL_iomem_permission: - case XEN_DOMCTL_ioport_permission: - case XEN_DOMCTL_hypercall_init: - case XEN_DOMCTL_arch_setup: - case XEN_DOMCTL_settimeoffset: - case XEN_DOMCTL_real_mode_area: - case XEN_DOMCTL_sendtrigger: - case XEN_DOMCTL_assign_device: - case XEN_DOMCTL_bind_pt_irq: - case XEN_DOMCTL_get_address_size: - case XEN_DOMCTL_set_address_size: - case XEN_DOMCTL_get_ext_vcpucontext: - case XEN_DOMCTL_set_ext_vcpucontext: - case XEN_DOMCTL_set_opt_feature: - case XEN_DOMCTL_memory_mapping: - case XEN_DOMCTL_ioport_mapping: - case XEN_DOMCTL_pin_mem_cacheattr: - case XEN_DOMCTL_test_assign_device: - case XEN_DOMCTL_set_target: - case XEN_DOMCTL_deassign_device: - case XEN_DOMCTL_set_cpuid: - case XEN_DOMCTL_get_device_group: - case XEN_DOMCTL_get_machine_address_size: - case XEN_DOMCTL_set_machine_address_size: - case XEN_DOMCTL_suppress_spurious_page_faults: - break; - - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_domctl %d\n", op.cmd); -#endif - error = -X_EINVAL; - } - - if (error == 0) - error = HYPERVISOR_domctl(&op); - - export_buffer(&op_ie, &error); - export_buffer(&sub_ie, &error); - - switch (op.cmd) { - case XEN_DOMCTL_createdomain: - DTRACE_XPV1(dom__create__end, int, error); - break; - case XEN_DOMCTL_destroydomain: - DTRACE_XPV1(dom__destroy__end, int, error); - break; - case XEN_DOMCTL_pausedomain: - DTRACE_XPV1(dom__pause__end, int, error); - break; - case XEN_DOMCTL_unpausedomain: - DTRACE_XPV1(dom__unpause__end, int, error); - break; - case XEN_DOMCTL_setvcpucontext: - DTRACE_XPV1(setvcpucontext__end, int, error); - break; - default: - ; - } - - return (error); -} - -static int -privcmd_HYPERVISOR_sysctl(xen_sysctl_t *opp) -{ - xen_sysctl_t op, dop; - import_export_t op_ie, sub_ie, sub2_ie; - int error = 0; - - if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0) - return (-X_EFAULT); - - sub_ie = null_ie; - sub2_ie = null_ie; - - /* - * Check this first because our wrapper will forcibly overwrite it. - */ - if (op.interface_version != XEN_SYSCTL_INTERFACE_VERSION) { - error = -X_EACCES; - export_buffer(&op_ie, &error); - return (error); - } - - switch (op.cmd) { - case XEN_SYSCTL_readconsole: { - error = import_handle(&sub_ie, &op.u.readconsole.buffer, - op.u.readconsole.count, IE_EXPORT); - break; - } - - case XEN_SYSCTL_debug_keys: { - error = import_handle(&sub_ie, &op.u.debug_keys.keys, - op.u.debug_keys.nr_keys, IE_IMPORT); - break; - } - - case XEN_SYSCTL_tbuf_op: - case XEN_SYSCTL_physinfo: { - if (uaddr_from_handle(&op.u.physinfo.cpu_to_node) != NULL && - op.u.physinfo.max_cpu_id != 0) { - error = import_handle(&sub_ie, - &op.u.physinfo.cpu_to_node, - op.u.physinfo.max_cpu_id * sizeof (uint32_t), - IE_EXPORT); - } - break; - } - case XEN_SYSCTL_sched_id: - case XEN_SYSCTL_availheap: - case XEN_SYSCTL_cpu_hotplug: - break; - case XEN_SYSCTL_get_pmstat: { - unsigned int maxs; - - switch (op.u.get_pmstat.type) { - case PMSTAT_get_pxstat: - /* - * This interface is broken. Xen always copies out - * all the state information, and the interface - * does not specify how much space the caller has - * reserved. So, the only thing to do is just mirror - * the hypervisor and libxc behavior, and use the - * maximum amount of data. - */ - dop.cmd = XEN_SYSCTL_get_pmstat; - dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION; - dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid; - dop.u.get_pmstat.type = PMSTAT_get_max_px; - error = HYPERVISOR_sysctl(&dop); - if (error != 0) - break; - - maxs = dop.u.get_pmstat.u.getpx.total; - if (maxs == 0) { - error = -X_EINVAL; - break; - } - - error = import_handle(&sub_ie, - &op.u.get_pmstat.u.getpx.trans_pt, - maxs * maxs * sizeof (uint64_t), IE_EXPORT); - if (error != 0) - break; - - error = import_handle(&sub2_ie, - &op.u.get_pmstat.u.getpx.pt, - maxs * sizeof (pm_px_val_t), IE_EXPORT); - break; - case PMSTAT_get_cxstat: - /* See above */ - dop.cmd = XEN_SYSCTL_get_pmstat; - dop.interface_version = XEN_SYSCTL_INTERFACE_VERSION; - dop.u.get_pmstat.cpuid = op.u.get_pmstat.cpuid; - dop.u.get_pmstat.type = PMSTAT_get_max_cx; - error = HYPERVISOR_sysctl(&dop); - if (error != 0) - break; - - maxs = dop.u.get_pmstat.u.getcx.nr; - if (maxs == 0) { - error = -X_EINVAL; - break; - } - - error = import_handle(&sub_ie, - &op.u.get_pmstat.u.getcx.triggers, - maxs * sizeof (uint64_t), IE_EXPORT); - if (error != 0) - break; - error = import_handle(&sub2_ie, - &op.u.get_pmstat.u.getcx.residencies, - maxs * sizeof (uint64_t), IE_EXPORT); - break; - - case PMSTAT_get_max_px: - case PMSTAT_reset_pxstat: - case PMSTAT_get_max_cx: - case PMSTAT_reset_cxstat: - break; - default: - error = -X_EINVAL; - break; - } - break; - } - - case XEN_SYSCTL_perfc_op: { - xen_sysctl_perfc_desc_t *scdp; - /* - * If 'desc' is NULL, then the caller is asking for - * the number of counters. If 'desc' is non-NULL, - * then we need to know how many counters there are - * before wiring down the output buffer appropriately. - */ - /*LINTED: constant in conditional context*/ - get_xen_guest_handle_u(scdp, op.u.perfc_op.desc); - if (scdp != NULL) { - static int numcounters = -1; - static int numvals = -1; - - if (numcounters == -1) { - dop.cmd = XEN_SYSCTL_perfc_op; - dop.interface_version = - XEN_SYSCTL_INTERFACE_VERSION; - dop.u.perfc_op.cmd = XEN_SYSCTL_PERFCOP_query; - /*LINTED: constant in conditional context*/ - set_xen_guest_handle_u(dop.u.perfc_op.desc, - NULL); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle_u(dop.u.perfc_op.val, - NULL); - - error = HYPERVISOR_sysctl(&dop); - if (error != 0) - break; - numcounters = dop.u.perfc_op.nr_counters; - numvals = dop.u.perfc_op.nr_vals; - } - ASSERT(numcounters != -1); - ASSERT(numvals != -1); - error = import_handle(&sub_ie, &op.u.perfc_op.desc, - (sizeof (xen_sysctl_perfc_desc_t) * numcounters), - IE_EXPORT); - error = import_handle(&sub2_ie, &op.u.perfc_op.val, - (sizeof (xen_sysctl_perfc_val_t) * numvals), - IE_EXPORT); - } - break; - } - - case XEN_SYSCTL_getdomaininfolist: { - error = import_handle(&sub_ie, &op.u.getdomaininfolist.buffer, - (op.u.getdomaininfolist.max_domains * - sizeof (xen_domctl_getdomaininfo_t)), IE_EXPORT); - break; - } - - case XEN_SYSCTL_getcpuinfo: - error = import_handle(&sub_ie, &op.u.getcpuinfo.info, - op.u.getcpuinfo.max_cpus * - sizeof (xen_sysctl_cpuinfo_t), IE_EXPORT); - break; - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_sysctl %d\n", op.cmd); -#endif - error = -X_EINVAL; - } - - if (error == 0) - error = HYPERVISOR_sysctl(&op); - - export_buffer(&op_ie, &error); - export_buffer(&sub_ie, &error); - export_buffer(&sub2_ie, &error); - - return (error); -} - -static int -privcmd_HYPERVISOR_platform_op(xen_platform_op_t *opp) -{ - import_export_t op_ie, sub_ie, sub2_ie; - xen_platform_op_t op; - int error; - - if (import_buffer(&op_ie, opp, &op, sizeof (op), IE_IMPEXP) != 0) - return (-X_EFAULT); - - sub_ie = null_ie; - sub2_ie = null_ie; - - /* - * Check this first because our wrapper will forcibly overwrite it. - */ - if (op.interface_version != XENPF_INTERFACE_VERSION) { - error = -X_EACCES; - export_buffer(&op_ie, &error); - return (error); - } - - /* - * Now handle any platform ops with embedded pointers elsewhere - * in the user address space that also need to be tacked down - * while the hypervisor futzes with them. - */ - switch (op.cmd) { - case XENPF_settime: - case XENPF_add_memtype: - case XENPF_del_memtype: - case XENPF_read_memtype: - case XENPF_platform_quirk: - case XENPF_enter_acpi_sleep: - case XENPF_change_freq: - case XENPF_panic_init: - break; - - case XENPF_microcode_update: - error = import_handle(&sub_ie, &op.u.microcode.data, - op.u.microcode.length, IE_IMPORT); - break; - case XENPF_getidletime: - error = import_handle(&sub_ie, &op.u.getidletime.cpumap_bitmap, - op.u.getidletime.cpumap_nr_cpus, IE_IMPEXP); - if (error != 0) - break; - - error = import_handle(&sub2_ie, &op.u.getidletime.idletime, - op.u.getidletime.cpumap_nr_cpus * sizeof (uint64_t), - IE_EXPORT); - break; - - case XENPF_set_processor_pminfo: { - size_t s; - - switch (op.u.set_pminfo.type) { - case XEN_PM_PX: - s = op.u.set_pminfo.u.perf.state_count * - sizeof (xen_processor_px_t); - if (op.u.set_pminfo.u.perf.flags & XEN_PX_PSS) { - error = import_handle(&sub_ie, - &op.u.set_pminfo.u.perf.states, s, - IE_IMPORT); - } - break; - case XEN_PM_CX: - s = op.u.set_pminfo.u.power.count * - sizeof (xen_processor_cx_t); - error = import_handle(&sub_ie, - &op.u.set_pminfo.u.power.states, s, IE_IMPORT); - break; - case XEN_PM_TX: - break; - default: - error = -X_EINVAL; - break; - } - break; - } - case XENPF_firmware_info: { - uint16_t len; - void *uaddr; - - switch (op.u.firmware_info.type) { - case XEN_FW_DISK_INFO: - /* - * Ugh.. another hokey interface. The first 16 bits - * of the buffer are also used as the (input) length. - */ - uaddr = uaddr_from_handle( - &op.u.firmware_info.u.disk_info.edd_params); - error = ddi_copyin(uaddr, &len, sizeof (len), 0); - if (error != 0) - break; - error = import_handle(&sub_ie, - &op.u.firmware_info.u.disk_info.edd_params, len, - IE_IMPEXP); - break; - case XEN_FW_VBEDDC_INFO: - error = import_handle(&sub_ie, - &op.u.firmware_info.u.vbeddc_info.edid, 128, - IE_EXPORT); - break; - case XEN_FW_DISK_MBR_SIGNATURE: - default: - break; - } - break; - } - default: - /* FIXME: see this with non-existed ID 38 ???? */ -#ifdef DEBUG - printf("unrecognized HYPERVISOR_platform_op %d pid %d\n", - op.cmd, curthread->t_procp->p_pid); -#endif - return (-X_EINVAL); - } - - if (error == 0) - error = HYPERVISOR_platform_op(&op); - - export_buffer(&op_ie, &error); - export_buffer(&sub_ie, &error); - export_buffer(&sub2_ie, &error); - - return (error); -} - -static int -privcmd_HYPERVISOR_memory_op(int cmd, void *arg) -{ - int error = 0; - import_export_t op_ie, sub_ie, gpfn_ie, mfn_ie; - union { - domid_t domid; - struct xen_memory_reservation resv; - struct xen_machphys_mfn_list xmml; - struct xen_add_to_physmap xatp; - struct xen_memory_map mm; - struct xen_foreign_memory_map fmm; - struct xen_pod_target pd; - } op_arg; - - op_ie = sub_ie = gpfn_ie = mfn_ie = null_ie; - - switch (cmd) { - case XENMEM_increase_reservation: - case XENMEM_decrease_reservation: - case XENMEM_populate_physmap: { - ulong_t *taddr; - - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.resv), - IE_IMPEXP) != 0) - return (-X_EFAULT); - - error = import_handle(&sub_ie, &op_arg.resv.extent_start, - (op_arg.resv.nr_extents * sizeof (ulong_t)), IE_IMPEXP); - - if (error == -X_EFAULT) - /*LINTED: constant in conditional context*/ - get_xen_guest_handle(taddr, op_arg.resv.extent_start); - else - taddr = sub_ie.ie_kaddr; - - switch (cmd) { - case XENMEM_increase_reservation: - DTRACE_XPV4(increase__reservation__start, - domid_t, op_arg.resv.domid, - ulong_t, op_arg.resv.nr_extents, - uint_t, op_arg.resv.extent_order, - ulong_t *, taddr); - break; - case XENMEM_decrease_reservation: - DTRACE_XPV4(decrease__reservation__start, - domid_t, op_arg.resv.domid, - ulong_t, op_arg.resv.nr_extents, - uint_t, op_arg.resv.extent_order, - ulong_t *, taddr); - break; - case XENMEM_populate_physmap: - DTRACE_XPV3(populate__physmap__start, - domid_t, op_arg.resv.domid, - ulong_t, op_arg.resv.nr_extents, - ulong_t *, taddr); - break; - } - - break; - } - - case XENMEM_maximum_ram_page: - break; - - case XENMEM_current_reservation: - case XENMEM_maximum_reservation: - case XENMEM_maximum_gpfn: - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.domid), - IE_IMPEXP) != 0) - return (-X_EFAULT); - break; - - case XENMEM_machphys_mfn_list: { - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xmml), - IE_IMPEXP) != 0) - return (-X_EFAULT); - - error = import_handle(&sub_ie, &op_arg.xmml.extent_start, - (op_arg.xmml.max_extents * sizeof (ulong_t)), IE_IMPEXP); - break; - } - - case XENMEM_add_to_physmap: - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.xatp), - IE_IMPEXP) != 0) - return (-X_EFAULT); - DTRACE_XPV4(add__to__physmap__start, domid_t, - op_arg.xatp.domid, uint_t, op_arg.xatp.space, ulong_t, - op_arg.xatp.idx, ulong_t, op_arg.xatp.gpfn); - break; - - case XENMEM_memory_map: - case XENMEM_machine_memory_map: { - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.mm), - IE_EXPORT) != 0) - return (-X_EFAULT); - - /* - * XXPV: ugh. e820entry is packed, but not in the kernel, since - * we remove all attributes; seems like this is a nice way to - * break mysteriously. - */ - error = import_handle(&sub_ie, &op_arg.mm.buffer, - (op_arg.mm.nr_entries * 20), IE_IMPEXP); - break; - } - - case XENMEM_set_memory_map: { - struct xen_memory_map *taddr; - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.fmm), - IE_IMPORT) != 0) - return (-X_EFAULT); - - /* - * As above. - */ - error = import_handle(&sub_ie, &op_arg.fmm.map.buffer, - (op_arg.fmm.map.nr_entries * 20), IE_IMPEXP); - - if (error == -X_EFAULT) - /*LINTED: constant in conditional context*/ - get_xen_guest_handle(taddr, op_arg.fmm.map.buffer); - else - taddr = sub_ie.ie_kaddr; - DTRACE_XPV3(set__memory__map__start, domid_t, - op_arg.fmm.domid, int, op_arg.fmm.map.nr_entries, - struct xen_memory_map *, taddr); - break; - } - - case XENMEM_set_pod_target: - case XENMEM_get_pod_target: - if (import_buffer(&op_ie, arg, &op_arg, sizeof (op_arg.pd), - IE_IMPEXP) != 0) - return (-X_EFAULT); - break; - - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_memory_op %d\n", cmd); -#endif - return (-X_EINVAL); - } - - if (error == 0) - error = HYPERVISOR_memory_op(cmd, - (arg == NULL) ? NULL: &op_arg); - - export_buffer(&op_ie, &error); - export_buffer(&sub_ie, &error); - export_buffer(&gpfn_ie, &error); - export_buffer(&mfn_ie, &error); - - switch (cmd) { - case XENMEM_increase_reservation: - DTRACE_XPV1(increase__reservation__end, int, error); - break; - case XENMEM_decrease_reservation: - DTRACE_XPV1(decrease__reservation__end, int, error); - break; - case XENMEM_populate_physmap: - DTRACE_XPV1(populate__physmap__end, int, error); - break; - case XENMEM_add_to_physmap: - DTRACE_XPV1(add__to__physmap__end, int, error); - break; - case XENMEM_set_memory_map: - DTRACE_XPV1(set__memory__map__end, int, error); - break; - } - return (error); -} - -static int -privcmd_HYPERVISOR_event_channel_op(int cmd, void *arg) -{ - int error; - size_t size; - import_export_t op_ie; - uint32_t flags; - - switch (cmd) { - case EVTCHNOP_alloc_unbound: - size = sizeof (evtchn_alloc_unbound_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_bind_interdomain: - size = sizeof (evtchn_bind_interdomain_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_bind_virq: - size = sizeof (evtchn_bind_virq_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_bind_pirq: - size = sizeof (evtchn_bind_pirq_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_bind_ipi: - size = sizeof (evtchn_bind_ipi_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_close: - size = sizeof (evtchn_close_t); - flags = IE_IMPORT; - break; - case EVTCHNOP_send: - size = sizeof (evtchn_send_t); - flags = IE_IMPORT; - break; - case EVTCHNOP_status: - size = sizeof (evtchn_status_t); - flags = IE_IMPEXP; - break; - case EVTCHNOP_bind_vcpu: - size = sizeof (evtchn_bind_vcpu_t); - flags = IE_IMPORT; - break; - case EVTCHNOP_unmask: - size = sizeof (evtchn_unmask_t); - flags = IE_IMPORT; - break; - case EVTCHNOP_reset: - size = sizeof (evtchn_reset_t); - flags = IE_IMPORT; - break; - - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_event_channel op %d\n", cmd); -#endif - return (-X_EINVAL); - } - - error = import_buffer(&op_ie, arg, NULL, size, flags); - - /* - * If there is sufficient demand, we can replace this void * with - * the proper op structure pointer. - */ - DTRACE_XPV2(evtchn__op__start, int, cmd, void *, - ((error == -X_EFAULT) ? arg : op_ie.ie_kaddr)); - - if (error == 0) - error = HYPERVISOR_event_channel_op(cmd, op_ie.ie_kaddr); - export_buffer(&op_ie, &error); - - DTRACE_XPV1(evtchn__op__end, int, error); - - return (error); -} - -static int -privcmd_HYPERVISOR_xen_version(int cmd, void *arg) -{ - int error; - int size = 0; - import_export_t op_ie; - uint32_t flags = IE_EXPORT; - - switch (cmd) { - case XENVER_version: - break; - case XENVER_extraversion: - size = sizeof (xen_extraversion_t); - break; - case XENVER_compile_info: - size = sizeof (xen_compile_info_t); - break; - case XENVER_capabilities: - size = sizeof (xen_capabilities_info_t); - break; - case XENVER_changeset: - size = sizeof (xen_changeset_info_t); - break; - case XENVER_platform_parameters: - size = sizeof (xen_platform_parameters_t); - break; - case XENVER_get_features: - flags = IE_IMPEXP; - size = sizeof (xen_feature_info_t); - break; - case XENVER_pagesize: - break; - case XENVER_guest_handle: - size = sizeof (xen_domain_handle_t); - break; - - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_xen_version op %d\n", cmd); -#endif - return (-X_EINVAL); - } - - error = import_buffer(&op_ie, arg, NULL, size, flags); - if (error == 0) - error = HYPERVISOR_xen_version(cmd, op_ie.ie_kaddr); - export_buffer(&op_ie, &error); - - return (error); -} - -static int -privcmd_HYPERVISOR_xsm_op(void *uacmctl) -{ - int error; - struct xen_acmctl *acmctl; - import_export_t op_ie; - - error = import_buffer(&op_ie, uacmctl, NULL, sizeof (*acmctl), - IE_IMPEXP); - if (error != 0) - return (error); - - acmctl = op_ie.ie_kaddr; - - if (acmctl->interface_version != ACM_INTERFACE_VERSION) { -#ifdef DEBUG - printf("acm vers mismatch (cmd %d, found 0x%x, need 0x%x\n", - acmctl->cmd, acmctl->interface_version, - ACM_INTERFACE_VERSION); -#endif - error = -X_EACCES; - export_buffer(&op_ie, &error); - return (error); - } - - /* FIXME: flask ops??? */ - - switch (acmctl->cmd) { - case ACMOP_setpolicy: - case ACMOP_getpolicy: - case ACMOP_dumpstats: - case ACMOP_getssid: - case ACMOP_getdecision: - case ACMOP_chgpolicy: - case ACMOP_relabeldoms: - /* flags = IE_IMPEXP; */ - break; - default: -#ifdef DEBUG - printf("unrecognized HYPERVISOR_xsm_op op %d\n", acmctl->cmd); -#endif - return (-X_EINVAL); - } - - if (error == 0) - error = HYPERVISOR_xsm_op(acmctl); - export_buffer(&op_ie, &error); - - return (error); -} - -static int -privcmd_HYPERVISOR_mmuext_op(struct mmuext_op *op, int count, uint_t *scount, - domid_t domid) -{ - int error, bytes; - uint_t kscount; - struct mmuext_op *kop, single_kop; - import_export_t op_ie, scnt_ie; - - op_ie = scnt_ie = null_ie; - error = 0; - - if (count >= 1) { - bytes = count * sizeof (*kop); - kop = (count == 1) ? &single_kop : kmem_alloc(bytes, KM_SLEEP); - error = import_buffer(&op_ie, op, kop, bytes, IE_IMPORT); - } - - DTRACE_XPV2(mmu__ext__op__start, int, count, struct mmuext_op *, - ((error == -X_EFAULT) ? op : kop)); - - if (scount != NULL && error == 0) - error = import_buffer(&scnt_ie, scount, &kscount, - sizeof (kscount), IE_EXPORT); - - if (error == 0) - error = HYPERVISOR_mmuext_op(kop, count, &kscount, domid); - export_buffer(&op_ie, &error); - export_buffer(&scnt_ie, &error); - - DTRACE_XPV1(mmu__ext__op__end, int, error); - - if (count > 1) - kmem_free(kop, bytes); - return (error); -} - -static int -privcmd_HYPERVISOR_hvm_op(int cmd, void *arg) -{ - int error; - int size = 0; - import_export_t arg_ie; - uint32_t flags = IE_IMPORT; - - switch (cmd) { - case HVMOP_set_param: - case HVMOP_get_param: - size = sizeof (struct xen_hvm_param); - flags = IE_IMPEXP; - break; - case HVMOP_set_pci_intx_level: - size = sizeof (struct xen_hvm_set_pci_intx_level); - break; - case HVMOP_set_isa_irq_level: - size = sizeof (struct xen_hvm_set_isa_irq_level); - break; - case HVMOP_set_pci_link_route: - size = sizeof (struct xen_hvm_set_pci_link_route); - break; - case HVMOP_track_dirty_vram: - size = sizeof (struct xen_hvm_track_dirty_vram); - break; - case HVMOP_modified_memory: - size = sizeof (struct xen_hvm_modified_memory); - break; - case HVMOP_set_mem_type: - size = sizeof (struct xen_hvm_set_mem_type); - break; - - default: -#ifdef DEBUG - printf("unrecognized HVM op 0x%x\n", cmd); -#endif - return (-X_EINVAL); - } - - error = import_buffer(&arg_ie, arg, NULL, size, flags); - if (error == 0) - error = HYPERVISOR_hvm_op(cmd, arg_ie.ie_kaddr); - export_buffer(&arg_ie, &error); - - return (error); -} - -static int -privcmd_HYPERVISOR_sched_op(int cmd, void *arg) -{ - int error; - int size = 0; - import_export_t op_ie; - struct sched_remote_shutdown op; - - switch (cmd) { - case SCHEDOP_remote_shutdown: - size = sizeof (struct sched_remote_shutdown); - break; - default: -#ifdef DEBUG - printf("unrecognized sched op 0x%x\n", cmd); -#endif - return (-X_EINVAL); - } - - error = import_buffer(&op_ie, arg, &op, size, IE_IMPORT); - if (error == 0) - error = HYPERVISOR_sched_op(cmd, (arg == NULL) ? NULL : &op); - export_buffer(&op_ie, &error); - - return (error); -} - -int allow_all_hypercalls = 0; -int privcmd_efault_debug = 0; - -/*ARGSUSED*/ -int -do_privcmd_hypercall(void *uarg, int mode, cred_t *cr, int *rval) -{ - privcmd_hypercall_t __hc, *hc = &__hc; - int error; - - if (ddi_copyin(uarg, hc, sizeof (*hc), mode)) - return (EFAULT); - - switch (hc->op) { - case __HYPERVISOR_mmu_update: - error = privcmd_HYPERVISOR_mmu_update( - (mmu_update_t *)hc->arg[0], (int)hc->arg[1], - (int *)hc->arg[2], (domid_t)hc->arg[3]); - break; - case __HYPERVISOR_domctl: - error = privcmd_HYPERVISOR_domctl( - (xen_domctl_t *)hc->arg[0]); - break; - case __HYPERVISOR_sysctl: - error = privcmd_HYPERVISOR_sysctl( - (xen_sysctl_t *)hc->arg[0]); - break; - case __HYPERVISOR_platform_op: - error = privcmd_HYPERVISOR_platform_op( - (xen_platform_op_t *)hc->arg[0]); - break; - case __HYPERVISOR_memory_op: - error = privcmd_HYPERVISOR_memory_op( - (int)hc->arg[0], (void *)hc->arg[1]); - break; - case __HYPERVISOR_event_channel_op: - error = privcmd_HYPERVISOR_event_channel_op( - (int)hc->arg[0], (void *)hc->arg[1]); - break; - case __HYPERVISOR_xen_version: - error = privcmd_HYPERVISOR_xen_version( - (int)hc->arg[0], (void *)hc->arg[1]); - break; - case __HYPERVISOR_mmuext_op: - error = privcmd_HYPERVISOR_mmuext_op( - (struct mmuext_op *)hc->arg[0], (int)hc->arg[1], - (uint_t *)hc->arg[2], (domid_t)hc->arg[3]); - break; - case __HYPERVISOR_xsm_op: - error = privcmd_HYPERVISOR_xsm_op((void *)hc->arg[0]); - break; - case __HYPERVISOR_hvm_op: - error = privcmd_HYPERVISOR_hvm_op( - (int)hc->arg[0], (void *)hc->arg[1]); - break; - case __HYPERVISOR_sched_op: - error = privcmd_HYPERVISOR_sched_op( - (int)hc->arg[0], (void *)hc->arg[1]); - break; - default: - if (allow_all_hypercalls) - error = __hypercall5(hc->op, hc->arg[0], hc->arg[1], - hc->arg[2], hc->arg[3], hc->arg[4]); - else { -#ifdef DEBUG - printf("unrecognized hypercall %ld\n", hc->op); -#endif - error = -X_EPERM; - } - break; - } - - if (error > 0) { - *rval = error; - error = 0; - } else if (error != 0) - error = xen_xlate_errcode(error); - - return (error); -} diff --git a/usr/src/uts/i86xpv/io/psm/mp_platform_xpv.c b/usr/src/uts/i86xpv/io/psm/mp_platform_xpv.c deleted file mode 100644 index 1c20832721..0000000000 --- a/usr/src/uts/i86xpv/io/psm/mp_platform_xpv.c +++ /dev/null @@ -1,2153 +0,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 (c) 2010, Oracle and/or its affiliates. All rights reserved. - */ -/* - * Copyright (c) 2010, Intel Corporation. - * All rights reserved. - * Copyright 2016 PALO, Richard. - */ - -/* - * PSMI 1.1 extensions are supported only in 2.6 and later versions. - * PSMI 1.2 extensions are supported only in 2.7 and later versions. - * PSMI 1.3 and 1.4 extensions are supported in Solaris 10. - * PSMI 1.5 extensions are supported in Solaris Nevada. - * PSMI 1.6 extensions are supported in Solaris Nevada. - * PSMI 1.7 extensions are supported in Solaris Nevada. - */ -#define PSMI_1_7 - -#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 -#include -#include -#include - - -/* - * Local Function Prototypes - */ -static void apic_mark_vector(uchar_t oldvector, uchar_t newvector); -static void apic_xlate_vector_free_timeout_handler(void *arg); -static int apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, - int new_bind_cpu, int apicindex, int intin_no, int which_irq, - struct ioapic_reprogram_data *drep); -static int apic_setup_irq_table(dev_info_t *dip, int irqno, - struct apic_io_intr *intrp, struct intrspec *ispec, iflag_t *intr_flagp, - int type); -static void apic_try_deferred_reprogram(int ipl, int vect); -static void delete_defer_repro_ent(int which_irq); -static void apic_ioapic_wait_pending_clear(int ioapicindex, - int intin_no); - -extern int apic_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, - int ipin, int *pci_irqp, iflag_t *intr_flagp); -extern int apic_handle_pci_pci_bridge(dev_info_t *idip, int child_devno, - int child_ipin, struct apic_io_intr **intrp); -extern uchar_t acpi_find_ioapic(int irq); -extern struct apic_io_intr *apic_find_io_intr_w_busid(int irqno, int busid); -extern int apic_find_bus_id(int bustype); -extern int apic_find_intin(uchar_t ioapic, uchar_t intin); -extern void apic_record_rdt_entry(apic_irq_t *irqptr, int irq); - -extern int apic_sci_vect; -extern iflag_t apic_sci_flags; -extern int apic_intr_policy; -extern char *psm_name; - -/* - * number of bits per byte, from - */ -#define UCHAR_MAX ((1 << NBBY) - 1) - -/* Max wait time (in repetitions) for flags to clear in an RDT entry. */ -extern int apic_max_reps_clear_pending; - -/* The irq # is implicit in the array index: */ -struct ioapic_reprogram_data apic_reprogram_info[APIC_MAX_VECTOR+1]; -/* - * APIC_MAX_VECTOR + 1 is the maximum # of IRQs as well. ioapic_reprogram_info - * is indexed by IRQ number, NOT by vector number. - */ - -extern int apic_int_busy_mark; -extern int apic_int_free_mark; -extern int apic_diff_for_redistribution; -extern int apic_sample_factor_redistribution; -extern int apic_redist_cpu_skip; -extern int apic_num_imbalance; -extern int apic_num_rebind; - -/* timeout for xlate_vector, mark_vector */ -int apic_revector_timeout = 16 * 10000; /* 160 millisec */ - -extern int apic_defconf; -extern int apic_irq_translate; - -extern int apic_use_acpi_madt_only; /* 1=ONLY use MADT from ACPI */ - -extern uchar_t apic_io_vectbase[MAX_IO_APIC]; - -extern boolean_t ioapic_mask_workaround[MAX_IO_APIC]; - -/* - * First available slot to be used as IRQ index into the apic_irq_table - * for those interrupts (like MSI/X) that don't have a physical IRQ. - */ -extern int apic_first_avail_irq; - -/* - * apic_defer_reprogram_lock ensures that only one processor is handling - * deferred interrupt programming at *_intr_exit time. - */ -static lock_t apic_defer_reprogram_lock; - -/* - * The current number of deferred reprogrammings outstanding - */ -uint_t apic_reprogram_outstanding = 0; - -#ifdef DEBUG -/* - * Counters that keep track of deferred reprogramming stats - */ -uint_t apic_intr_deferrals = 0; -uint_t apic_intr_deliver_timeouts = 0; -uint_t apic_last_ditch_reprogram_failures = 0; -uint_t apic_deferred_setup_failures = 0; -uint_t apic_defer_repro_total_retries = 0; -uint_t apic_defer_repro_successes = 0; -uint_t apic_deferred_spurious_enters = 0; -#endif - -extern int apic_io_max; -extern struct apic_io_intr *apic_io_intrp; - -uchar_t apic_vector_to_irq[APIC_MAX_VECTOR+1]; - -extern uint32_t eisa_level_intr_mask; - /* At least MSB will be set if EISA bus */ - -extern int apic_pci_bus_total; -extern uchar_t apic_single_pci_busid; - -/* - * Following declarations are for revectoring; used when ISRs at different - * IPLs share an irq. - */ -static lock_t apic_revector_lock; -int apic_revector_pending = 0; -static uchar_t *apic_oldvec_to_newvec; -static uchar_t *apic_newvec_to_oldvec; - -/* ACPI Interrupt Source Override Structure ptr */ -ACPI_MADT_INTERRUPT_OVERRIDE *acpi_isop; -extern int acpi_iso_cnt; - -/* - * Auto-configuration routines - */ - -/* - * Initialise vector->ipl and ipl->pri arrays. level_intr and irqtable - * are also set to NULL. vector->irq is set to a value which cannot map - * to a real irq to show that it is free. - */ -void -apic_init_common(void) -{ - int i, j, indx; - int *iptr; - - /* - * Initialize apic_ipls from apic_vectortoipl. This array is - * used in apic_intr_enter to determine the IPL to use for the - * corresponding vector. On some systems, due to hardware errata - * and interrupt sharing, the IPL may not correspond to the IPL listed - * in apic_vectortoipl (see apic_addspl and apic_delspl). - */ - for (i = 0; i < (APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL); i++) { - indx = i * APIC_VECTOR_PER_IPL; - - for (j = 0; j < APIC_VECTOR_PER_IPL; j++, indx++) - apic_ipls[indx] = apic_vectortoipl[i]; - } - - /* cpu 0 is always up (for now) */ - apic_cpus[0].aci_status = APIC_CPU_ONLINE | APIC_CPU_INTR_ENABLE; - - iptr = (int *)&apic_irq_table[0]; - for (i = 0; i <= APIC_MAX_VECTOR; i++) { - apic_level_intr[i] = 0; - *iptr++ = 0; - apic_vector_to_irq[i] = APIC_RESV_IRQ; - - /* These *must* be initted to B_TRUE! */ - apic_reprogram_info[i].done = B_TRUE; - apic_reprogram_info[i].irqp = NULL; - apic_reprogram_info[i].tries = 0; - apic_reprogram_info[i].bindcpu = 0; - } - - /* - * Allocate a dummy irq table entry for the reserved entry. - * This takes care of the race between removing an irq and - * clock detecting a CPU in that irq during interrupt load - * sampling. - */ - apic_irq_table[APIC_RESV_IRQ] = - kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); - - mutex_init(&airq_mutex, NULL, MUTEX_DEFAULT, NULL); -} - -void -ioapic_init_intr(int mask_apic) -{ - int ioapic_ix; - struct intrspec ispec; - apic_irq_t *irqptr; - int i, j; - ulong_t iflag; - - LOCK_INIT_CLEAR(&apic_revector_lock); - LOCK_INIT_CLEAR(&apic_defer_reprogram_lock); - - /* mask interrupt vectors */ - for (j = 0; j < apic_io_max && mask_apic; j++) { - int intin_max; - - ioapic_ix = j; - /* Bits 23-16 define the maximum redirection entries */ - intin_max = (ioapic_read(ioapic_ix, APIC_VERS_CMD) >> 16) - & 0xff; - for (i = 0; i <= intin_max; i++) - ioapic_write(ioapic_ix, APIC_RDT_CMD + 2 * i, AV_MASK); - } - - /* - * Hack alert: deal with ACPI SCI interrupt chicken/egg here - */ - if (apic_sci_vect > 0) { - /* - * acpica has already done add_avintr(); we just - * to finish the job by mimicing translate_irq() - * - * Fake up an intrspec and setup the tables - */ - ispec.intrspec_vec = apic_sci_vect; - ispec.intrspec_pri = SCI_IPL; - - if (apic_setup_irq_table(NULL, apic_sci_vect, NULL, - &ispec, &apic_sci_flags, DDI_INTR_TYPE_FIXED) < 0) { - cmn_err(CE_WARN, "!apic: SCI setup failed"); - return; - } - irqptr = apic_irq_table[apic_sci_vect]; - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - /* Program I/O APIC */ - (void) apic_setup_io_intr(irqptr, apic_sci_vect, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - irqptr->airq_share++; - } -} - -/* - * Add mask bits to disable interrupt vector from happening - * at or above IPL. In addition, it should remove mask bits - * to enable interrupt vectors below the given IPL. - * - * Both add and delspl are complicated by the fact that different interrupts - * may share IRQs. This can happen in two ways. - * 1. The same H/W line is shared by more than 1 device - * 1a. with interrupts at different IPLs - * 1b. with interrupts at same IPL - * 2. We ran out of vectors at a given IPL and started sharing vectors. - * 1b and 2 should be handled gracefully, except for the fact some ISRs - * will get called often when no interrupt is pending for the device. - * For 1a, we handle it at the higher IPL. - */ -/*ARGSUSED*/ -int -apic_addspl_common(int irqno, int ipl, int min_ipl, int max_ipl) -{ - uchar_t vector; - ulong_t iflag; - apic_irq_t *irqptr, *irqheadptr; - int irqindex; - - ASSERT(max_ipl <= UCHAR_MAX); - irqindex = IRQINDEX(irqno); - - if ((irqindex == -1) || (!apic_irq_table[irqindex])) - return (PSM_FAILURE); - - mutex_enter(&airq_mutex); - irqptr = irqheadptr = apic_irq_table[irqindex]; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_addspl: dip=0x%p type=%d irqno=0x%x " - "vector=0x%x\n", (void *)irqptr->airq_dip, - irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); - - while (irqptr) { - if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) - break; - irqptr = irqptr->airq_next; - } - irqptr->airq_share++; - - mutex_exit(&airq_mutex); - - /* return if it is not hardware interrupt */ - if (irqptr->airq_mps_intr_index == RESERVE_INDEX) - return (PSM_SUCCESS); - - /* Or if there are more interupts at a higher IPL */ - if (ipl != max_ipl) - return (PSM_SUCCESS); - - /* - * if apic_picinit() has not been called yet, just return. - * At the end of apic_picinit(), we will call setup_io_intr(). - */ - - if (!apic_picinit_called) - return (PSM_SUCCESS); - - /* - * Upgrade vector if max_ipl is not earlier ipl. If we cannot allocate, - * return failure. - */ - if (irqptr->airq_ipl != max_ipl && - !ioapic_mask_workaround[irqptr->airq_ioapicindex]) { - - vector = apic_allocate_vector(max_ipl, irqindex, 1); - if (vector == 0) { - irqptr->airq_share--; - return (PSM_FAILURE); - } - irqptr = irqheadptr; - apic_mark_vector(irqptr->airq_vector, vector); - while (irqptr) { - irqptr->airq_vector = vector; - irqptr->airq_ipl = (uchar_t)max_ipl; - /* - * reprogram irq being added and every one else - * who is not in the UNINIT state - */ - if ((VIRTIRQ(irqindex, irqptr->airq_share_id) == - irqno) || (irqptr->airq_temp_cpu != IRQ_UNINIT)) { - apic_record_rdt_entry(irqptr, irqindex); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqptr, irqindex, - B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - } - irqptr = irqptr->airq_next; - } - return (PSM_SUCCESS); - - } else if (irqptr->airq_ipl != max_ipl && - ioapic_mask_workaround[irqptr->airq_ioapicindex]) { - /* - * We cannot upgrade the vector, but we can change - * the IPL that this vector induces. - * - * Note that we subtract APIC_BASE_VECT from the vector - * here because this array is used in apic_intr_enter - * (no need to add APIC_BASE_VECT in that hot code - * path since we can do it in the rarely-executed path - * here). - */ - apic_ipls[irqptr->airq_vector - APIC_BASE_VECT] = - (uchar_t)max_ipl; - - irqptr = irqheadptr; - while (irqptr) { - irqptr->airq_ipl = (uchar_t)max_ipl; - irqptr = irqptr->airq_next; - } - - return (PSM_SUCCESS); - } - - ASSERT(irqptr); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqptr, irqindex, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - return (PSM_SUCCESS); -} - -/* - * Recompute mask bits for the given interrupt vector. - * If there is no interrupt servicing routine for this - * vector, this function should disable interrupt vector - * from happening at all IPLs. If there are still - * handlers using the given vector, this function should - * disable the given vector from happening below the lowest - * IPL of the remaining hadlers. - */ -/*ARGSUSED*/ -int -apic_delspl_common(int irqno, int ipl, int min_ipl, int max_ipl) -{ - uchar_t vector; - uint32_t bind_cpu; - int intin, irqindex; - int ioapic_ix; - apic_irq_t *irqptr, *preirqptr, *irqheadptr, *irqp; - ulong_t iflag; - - mutex_enter(&airq_mutex); - irqindex = IRQINDEX(irqno); - irqptr = preirqptr = irqheadptr = apic_irq_table[irqindex]; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_delspl: dip=0x%p type=%d irqno=0x%x " - "vector=0x%x\n", (void *)irqptr->airq_dip, - irqptr->airq_mps_intr_index, irqno, irqptr->airq_vector)); - - while (irqptr) { - if (VIRTIRQ(irqindex, irqptr->airq_share_id) == irqno) - break; - preirqptr = irqptr; - irqptr = irqptr->airq_next; - } - ASSERT(irqptr); - - irqptr->airq_share--; - - mutex_exit(&airq_mutex); - - /* - * If there are more interrupts at a higher IPL, we don't need - * to disable anything. - */ - if (ipl < max_ipl) - return (PSM_SUCCESS); - - /* return if it is not hardware interrupt */ - if (irqptr->airq_mps_intr_index == RESERVE_INDEX) - return (PSM_SUCCESS); - - if (!apic_picinit_called) { - /* - * Clear irq_struct. If two devices shared an intpt - * line & 1 unloaded before picinit, we are hosed. But, then - * we hope the machine survive. - */ - irqptr->airq_mps_intr_index = FREE_INDEX; - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_free_vector(irqptr->airq_vector); - return (PSM_SUCCESS); - } - /* - * Downgrade vector to new max_ipl if needed. If we cannot allocate, - * use old IPL. Not very elegant, but it should work. - */ - if ((irqptr->airq_ipl != max_ipl) && (max_ipl != PSM_INVALID_IPL) && - !ioapic_mask_workaround[irqptr->airq_ioapicindex]) { - apic_irq_t *irqp; - if (vector = apic_allocate_vector(max_ipl, irqno, 1)) { - apic_mark_vector(irqheadptr->airq_vector, vector); - irqp = irqheadptr; - while (irqp) { - irqp->airq_vector = vector; - irqp->airq_ipl = (uchar_t)max_ipl; - if (irqp->airq_temp_cpu != IRQ_UNINIT) { - apic_record_rdt_entry(irqp, irqindex); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - (void) apic_setup_io_intr(irqp, - irqindex, B_FALSE); - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - } - irqp = irqp->airq_next; - } - } - - } else if (irqptr->airq_ipl != max_ipl && - max_ipl != PSM_INVALID_IPL && - ioapic_mask_workaround[irqptr->airq_ioapicindex]) { - - /* - * We cannot downgrade the IPL of the vector below the vector's - * hardware priority. If we did, it would be possible for a - * higher-priority hardware vector to interrupt a CPU running at an IPL - * lower than the hardware priority of the interrupting vector (but - * higher than the soft IPL of this IRQ). When this happens, we would - * then try to drop the IPL BELOW what it was (effectively dropping - * below base_spl) which would be potentially catastrophic. - * - * (e.g. Suppose the hardware vector associated with this IRQ is 0x40 - * (hardware IPL of 4). Further assume that the old IPL of this IRQ - * was 4, but the new IPL is 1. If we forced vector 0x40 to result in - * an IPL of 1, it would be possible for the processor to be executing - * at IPL 3 and for an interrupt to come in on vector 0x40, interrupting - * the currently-executing ISR. When apic_intr_enter consults - * apic_irqs[], it will return 1, bringing the IPL of the CPU down to 1 - * so even though the processor was running at IPL 4, an IPL 1 - * interrupt will have interrupted it, which must not happen)). - * - * Effectively, this means that the hardware priority corresponding to - * the IRQ's IPL (in apic_ipls[]) cannot be lower than the vector's - * hardware priority. - * - * (In the above example, then, after removal of the IPL 4 device's - * interrupt handler, the new IPL will continue to be 4 because the - * hardware priority that IPL 1 implies is lower than the hardware - * priority of the vector used.) - */ - /* apic_ipls is indexed by vector, starting at APIC_BASE_VECT */ - const int apic_ipls_index = irqptr->airq_vector - - APIC_BASE_VECT; - const int vect_inherent_hwpri = irqptr->airq_vector >> - APIC_IPL_SHIFT; - - /* - * If there are still devices using this IRQ, determine the - * new ipl to use. - */ - if (irqptr->airq_share) { - int vect_desired_hwpri, hwpri; - - ASSERT(max_ipl < MAXIPL); - vect_desired_hwpri = apic_ipltopri[max_ipl] >> - APIC_IPL_SHIFT; - - /* - * If the desired IPL's hardware priority is lower - * than that of the vector, use the hardware priority - * of the vector to determine the new IPL. - */ - hwpri = (vect_desired_hwpri < vect_inherent_hwpri) ? - vect_inherent_hwpri : vect_desired_hwpri; - - /* - * Now, to get the right index for apic_vectortoipl, - * we need to subtract APIC_BASE_VECT from the - * hardware-vector-equivalent (in hwpri). Since hwpri - * is already shifted, we shift APIC_BASE_VECT before - * doing the subtraction. - */ - hwpri -= (APIC_BASE_VECT >> APIC_IPL_SHIFT); - - ASSERT(hwpri >= 0); - ASSERT(hwpri < MAXIPL); - max_ipl = apic_vectortoipl[hwpri]; - apic_ipls[apic_ipls_index] = max_ipl; - - irqp = irqheadptr; - while (irqp) { - irqp->airq_ipl = (uchar_t)max_ipl; - irqp = irqp->airq_next; - } - } else { - /* - * No more devices on this IRQ, so reset this vector's - * element in apic_ipls to the original IPL for this - * vector - */ - apic_ipls[apic_ipls_index] = - apic_vectortoipl[vect_inherent_hwpri]; - } - } - - /* - * If there are still active interrupts, we are done. - */ - if (irqptr->airq_share) - return (PSM_SUCCESS); - - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - if (irqptr->airq_mps_intr_index == MSI_INDEX) { - /* - * Disable the MSI vector - * Make sure we only disable on the last - * of the multi-MSI support - */ - if (i_ddi_intr_get_current_nenables(irqptr->airq_dip) == 1) { - apic_pci_msi_disable_mode(irqptr->airq_dip, - DDI_INTR_TYPE_MSI); - } - } else if (irqptr->airq_mps_intr_index == MSIX_INDEX) { - /* - * Disable the MSI-X vector - * needs to clear its mask and addr/data for each MSI-X - */ - apic_pci_msi_unconfigure(irqptr->airq_dip, DDI_INTR_TYPE_MSIX, - irqptr->airq_origirq); - /* - * Make sure we only disable on the last MSI-X - */ - if (i_ddi_intr_get_current_nenables(irqptr->airq_dip) == 1) { - apic_pci_msi_disable_mode(irqptr->airq_dip, - DDI_INTR_TYPE_MSIX); - } - } else { - /* - * The assumption here is that this is safe, even for - * systems with IOAPICs that suffer from the hardware - * erratum because all devices have been quiesced before - * they unregister their interrupt handlers. If that - * assumption turns out to be false, this mask operation - * can induce the same erratum result we're trying to - * avoid. - */ - ioapic_ix = irqptr->airq_ioapicindex; - intin = irqptr->airq_intin_no; - ioapic_write(ioapic_ix, APIC_RDT_CMD + 2 * intin, AV_MASK); - } - - /* - * This irq entry is the only one in the chain. - */ - if (irqheadptr->airq_next == NULL) { - ASSERT(irqheadptr == irqptr); - bind_cpu = irqptr->airq_temp_cpu; - if (((uint32_t)bind_cpu != IRQ_UNBOUND) && - ((uint32_t)bind_cpu != IRQ_UNINIT)) { - ASSERT(apic_cpu_in_range(bind_cpu)); - if (bind_cpu & IRQ_USER_BOUND) { - /* If hardbound, temp_cpu == cpu */ - bind_cpu &= ~IRQ_USER_BOUND; - apic_cpus[bind_cpu].aci_bound--; - } else - apic_cpus[bind_cpu].aci_temp_bound--; - } - irqptr->airq_temp_cpu = IRQ_UNINIT; - irqptr->airq_mps_intr_index = FREE_INDEX; - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - apic_free_vector(irqptr->airq_vector); - return (PSM_SUCCESS); - } - - /* - * If we get here, we are sharing the vector and there are more than - * one active irq entries in the chain. - */ - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - mutex_enter(&airq_mutex); - /* Remove the irq entry from the chain */ - if (irqptr == irqheadptr) { /* The irq entry is at the head */ - apic_irq_table[irqindex] = irqptr->airq_next; - } else { - preirqptr->airq_next = irqptr->airq_next; - } - /* Free the irq entry */ - kmem_free(irqptr, sizeof (apic_irq_t)); - mutex_exit(&airq_mutex); - - return (PSM_SUCCESS); -} - -/* - * apic_introp_xlate() replaces apic_translate_irq() and is - * called only from apic_intr_ops(). With the new ADII framework, - * the priority can no longer be retrieved through i_ddi_get_intrspec(). - * It has to be passed in from the caller. - * - * Return value: - * Success: irqno for the given device - * Failure: -1 - */ -int -apic_introp_xlate(dev_info_t *dip, struct intrspec *ispec, int type) -{ - char dev_type[16]; - int dev_len, pci_irq, newirq, bustype, devid, busid, i; - int irqno = ispec->intrspec_vec; - ddi_acc_handle_t cfg_handle; - uchar_t ipin; - struct apic_io_intr *intrp; - iflag_t intr_flag; - ACPI_SUBTABLE_HEADER *hp; - ACPI_MADT_INTERRUPT_OVERRIDE *isop; - apic_irq_t *airqp; - int parent_is_pci_or_pciex = 0; - int child_is_pciex = 0; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_introp_xlate: dip=0x%p name=%s " - "type=%d irqno=0x%x\n", (void *)dip, ddi_get_name(dip), type, - irqno)); - - dev_len = sizeof (dev_type); - if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, - &dev_len) == DDI_PROP_SUCCESS) { - if ((strcmp(dev_type, "pci") == 0) || - (strcmp(dev_type, "pciex") == 0)) - parent_is_pci_or_pciex = 1; - } - - if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "compatible", (caddr_t)dev_type, - &dev_len) == DDI_PROP_SUCCESS) { - if (strstr(dev_type, "pciex")) - child_is_pciex = 1; - } - - if (DDI_INTR_IS_MSI_OR_MSIX(type)) { - if ((airqp = apic_find_irq(dip, ispec, type)) != NULL) { - airqp->airq_iflag.bustype = - child_is_pciex ? BUS_PCIE : BUS_PCI; - return (apic_vector_to_irq[airqp->airq_vector]); - } - return (apic_setup_irq_table(dip, irqno, NULL, ispec, - NULL, type)); - } - - bustype = 0; - - /* check if we have already translated this irq */ - mutex_enter(&airq_mutex); - newirq = apic_min_device_irq; - for (; newirq <= apic_max_device_irq; newirq++) { - airqp = apic_irq_table[newirq]; - while (airqp) { - if ((airqp->airq_dip == dip) && - (airqp->airq_origirq == irqno) && - (airqp->airq_mps_intr_index != FREE_INDEX)) { - - mutex_exit(&airq_mutex); - return (VIRTIRQ(newirq, airqp->airq_share_id)); - } - airqp = airqp->airq_next; - } - } - mutex_exit(&airq_mutex); - - if (apic_defconf) - goto defconf; - - if ((dip == NULL) || (!apic_irq_translate && !apic_enable_acpi)) - goto nonpci; - - if (parent_is_pci_or_pciex) { - /* pci device */ - if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0) - goto nonpci; - if (busid == 0 && apic_pci_bus_total == 1) - busid = (int)apic_single_pci_busid; - - if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS) - return (-1); - ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA; - pci_config_teardown(&cfg_handle); - if (apic_enable_acpi && !apic_use_acpi_madt_only) { - if (apic_acpi_translate_pci_irq(dip, busid, devid, - ipin, &pci_irq, &intr_flag) != ACPI_PSM_SUCCESS) - return (-1); - - intr_flag.bustype = child_is_pciex ? BUS_PCIE : BUS_PCI; - return (apic_setup_irq_table(dip, pci_irq, NULL, ispec, - &intr_flag, type)); - } else { - pci_irq = ((devid & 0x1f) << 2) | (ipin & 0x3); - if ((intrp = apic_find_io_intr_w_busid(pci_irq, busid)) - == NULL) { - if ((pci_irq = apic_handle_pci_pci_bridge(dip, - devid, ipin, &intrp)) == -1) - return (-1); - } - return (apic_setup_irq_table(dip, pci_irq, intrp, ispec, - NULL, type)); - } - } else if (strcmp(dev_type, "isa") == 0) - bustype = BUS_ISA; - else if (strcmp(dev_type, "eisa") == 0) - bustype = BUS_EISA; - -nonpci: - if (apic_enable_acpi && !apic_use_acpi_madt_only) { - /* search iso entries first */ - if (acpi_iso_cnt != 0) { - hp = (ACPI_SUBTABLE_HEADER *)acpi_isop; - i = 0; - while (i < acpi_iso_cnt) { - if (hp->Type == - ACPI_MADT_TYPE_INTERRUPT_OVERRIDE) { - isop = - (ACPI_MADT_INTERRUPT_OVERRIDE *) hp; - if (isop->Bus == 0 && - isop->SourceIrq == irqno) { - newirq = isop->GlobalIrq; - intr_flag.intr_po = - isop->IntiFlags & - ACPI_MADT_POLARITY_MASK; - intr_flag.intr_el = - (isop->IntiFlags & - ACPI_MADT_TRIGGER_MASK) - >> 2; - intr_flag.bustype = BUS_ISA; - - return (apic_setup_irq_table( - dip, newirq, NULL, ispec, - &intr_flag, type)); - - } - i++; - } - hp = (ACPI_SUBTABLE_HEADER *)(((char *)hp) + - hp->Length); - } - } - intr_flag.intr_po = INTR_PO_ACTIVE_HIGH; - intr_flag.intr_el = INTR_EL_EDGE; - intr_flag.bustype = BUS_ISA; - return (apic_setup_irq_table(dip, irqno, NULL, ispec, - &intr_flag, type)); - } else { - if (bustype == 0) /* not initialized */ - bustype = eisa_level_intr_mask ? BUS_EISA : BUS_ISA; - for (i = 0; i < 2; i++) { - if (((busid = apic_find_bus_id(bustype)) != -1) && - ((intrp = apic_find_io_intr_w_busid(irqno, busid)) - != NULL)) { - if ((newirq = apic_setup_irq_table(dip, irqno, - intrp, ispec, NULL, type)) != -1) { - return (newirq); - } - goto defconf; - } - bustype = (bustype == BUS_EISA) ? BUS_ISA : BUS_EISA; - } - } - -/* MPS default configuration */ -defconf: - newirq = apic_setup_irq_table(dip, irqno, NULL, ispec, NULL, type); - if (newirq == -1) - return (-1); - ASSERT(IRQINDEX(newirq) == irqno); - ASSERT(apic_irq_table[irqno]); - return (newirq); -} - -/* - * Attempt to share vector with someone else - */ -static int -apic_share_vector(int irqno, iflag_t *intr_flagp, short intr_index, int ipl, - uchar_t ioapicindex, uchar_t ipin, apic_irq_t **irqptrp) -{ -#ifdef DEBUG - apic_irq_t *tmpirqp = NULL; -#endif /* DEBUG */ - apic_irq_t *irqptr, dummyirq; - int newirq, chosen_irq = -1, share = 127; - int lowest, highest, i; - uchar_t share_id; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_share_vector: irqno=0x%x " - "intr_index=0x%x ipl=0x%x\n", irqno, intr_index, ipl)); - - highest = apic_ipltopri[ipl] + APIC_VECTOR_MASK; - lowest = apic_ipltopri[ipl-1] + APIC_VECTOR_PER_IPL; - - if (highest < lowest) /* Both ipl and ipl-1 map to same pri */ - lowest -= APIC_VECTOR_PER_IPL; - dummyirq.airq_mps_intr_index = intr_index; - dummyirq.airq_ioapicindex = ioapicindex; - dummyirq.airq_intin_no = ipin; - if (intr_flagp) - dummyirq.airq_iflag = *intr_flagp; - apic_record_rdt_entry(&dummyirq, irqno); - for (i = lowest; i <= highest; i++) { - newirq = apic_vector_to_irq[i]; - if (newirq == APIC_RESV_IRQ) - continue; - irqptr = apic_irq_table[newirq]; - - if ((dummyirq.airq_rdt_entry & 0xFF00) != - (irqptr->airq_rdt_entry & 0xFF00)) - /* not compatible */ - continue; - - if (irqptr->airq_share < share) { - share = irqptr->airq_share; - chosen_irq = newirq; - } - } - if (chosen_irq != -1) { - /* - * Assign a share id which is free or which is larger - * than the largest one. - */ - share_id = 1; - mutex_enter(&airq_mutex); - irqptr = apic_irq_table[chosen_irq]; - while (irqptr) { - if (irqptr->airq_mps_intr_index == FREE_INDEX) { - share_id = irqptr->airq_share_id; - break; - } - if (share_id <= irqptr->airq_share_id) - share_id = irqptr->airq_share_id + 1; -#ifdef DEBUG - tmpirqp = irqptr; -#endif /* DEBUG */ - irqptr = irqptr->airq_next; - } - if (!irqptr) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - irqptr->airq_next = - apic_irq_table[chosen_irq]->airq_next; - apic_irq_table[chosen_irq]->airq_next = irqptr; -#ifdef DEBUG - tmpirqp = apic_irq_table[chosen_irq]; -#endif /* DEBUG */ - } - irqptr->airq_mps_intr_index = intr_index; - irqptr->airq_ioapicindex = ioapicindex; - irqptr->airq_intin_no = ipin; - if (intr_flagp) - irqptr->airq_iflag = *intr_flagp; - irqptr->airq_vector = apic_irq_table[chosen_irq]->airq_vector; - irqptr->airq_share_id = share_id; - apic_record_rdt_entry(irqptr, irqno); - *irqptrp = irqptr; -#ifdef DEBUG - /* shuffle the pointers to test apic_delspl path */ - if (tmpirqp) { - tmpirqp->airq_next = irqptr->airq_next; - irqptr->airq_next = apic_irq_table[chosen_irq]; - apic_irq_table[chosen_irq] = irqptr; - } -#endif /* DEBUG */ - mutex_exit(&airq_mutex); - return (VIRTIRQ(chosen_irq, share_id)); - } - return (-1); -} - -/* - * Allocate/Initialize the apic_irq_table[] entry for given irqno. If the entry - * is used already, we will try to allocate a new irqno. - * - * Return value: - * Success: irqno - * Failure: -1 - */ -static int -apic_setup_irq_table(dev_info_t *dip, int irqno, struct apic_io_intr *intrp, - struct intrspec *ispec, iflag_t *intr_flagp, int type) -{ - int origirq = ispec->intrspec_vec; - uchar_t ipl = ispec->intrspec_pri; - int newirq, intr_index; - uchar_t ipin, ioapic, ioapicindex, vector; - apic_irq_t *irqptr; - major_t major; - dev_info_t *sdip; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_setup_irq_table: dip=0x%p type=%d " - "irqno=0x%x origirq=0x%x\n", (void *)dip, type, irqno, origirq)); - - ASSERT(ispec != NULL); - - major = (dip != NULL) ? ddi_driver_major(dip) : 0; - - if (DDI_INTR_IS_MSI_OR_MSIX(type)) { - /* MSI/X doesn't need to setup ioapic stuffs */ - ioapicindex = 0xff; - ioapic = 0xff; - ipin = (uchar_t)0xff; - intr_index = (type == DDI_INTR_TYPE_MSI) ? MSI_INDEX : - MSIX_INDEX; - mutex_enter(&airq_mutex); - if ((irqno = apic_allocate_irq(apic_first_avail_irq)) == -1) { - mutex_exit(&airq_mutex); - /* need an irq for MSI/X to index into autovect[] */ - cmn_err(CE_WARN, "No interrupt irq: %s instance %d", - ddi_get_name(dip), ddi_get_instance(dip)); - return (-1); - } - mutex_exit(&airq_mutex); - - } else if (intrp != NULL) { - intr_index = (int)(intrp - apic_io_intrp); - ioapic = intrp->intr_destid; - ipin = intrp->intr_destintin; - /* Find ioapicindex. If destid was ALL, we will exit with 0. */ - for (ioapicindex = apic_io_max - 1; ioapicindex; ioapicindex--) - if (apic_io_id[ioapicindex] == ioapic) - break; - ASSERT((ioapic == apic_io_id[ioapicindex]) || - (ioapic == INTR_ALL_APIC)); - - /* check whether this intin# has been used by another irqno */ - if ((newirq = apic_find_intin(ioapicindex, ipin)) != -1) { - return (newirq); - } - - } else if (intr_flagp != NULL) { - /* ACPI case */ - intr_index = ACPI_INDEX; - ioapicindex = acpi_find_ioapic(irqno); - ASSERT(ioapicindex != 0xFF); - ioapic = apic_io_id[ioapicindex]; - ipin = irqno - apic_io_vectbase[ioapicindex]; - if (apic_irq_table[irqno] && - apic_irq_table[irqno]->airq_mps_intr_index == ACPI_INDEX) { - ASSERT(apic_irq_table[irqno]->airq_intin_no == ipin && - apic_irq_table[irqno]->airq_ioapicindex == - ioapicindex); - return (irqno); - } - - } else { - /* default configuration */ - ioapicindex = 0; - ioapic = apic_io_id[ioapicindex]; - ipin = (uchar_t)irqno; - intr_index = DEFAULT_INDEX; - } - - if (ispec == NULL) { - APIC_VERBOSE_IOAPIC((CE_WARN, "No intrspec for irqno = %x\n", - irqno)); - } else if ((vector = apic_allocate_vector(ipl, irqno, 0)) == 0) { - if ((newirq = apic_share_vector(irqno, intr_flagp, intr_index, - ipl, ioapicindex, ipin, &irqptr)) != -1) { - irqptr->airq_ipl = ipl; - irqptr->airq_origirq = (uchar_t)origirq; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - sdip = apic_irq_table[IRQINDEX(newirq)]->airq_dip; - /* This is OK to do really */ - if (sdip == NULL) { - cmn_err(CE_WARN, "Sharing vectors: %s" - " instance %d and SCI", - ddi_get_name(dip), ddi_get_instance(dip)); - } else { - cmn_err(CE_WARN, "Sharing vectors: %s" - " instance %d and %s instance %d", - ddi_get_name(sdip), ddi_get_instance(sdip), - ddi_get_name(dip), ddi_get_instance(dip)); - } - return (newirq); - } - /* try high priority allocation now that share has failed */ - if ((vector = apic_allocate_vector(ipl, irqno, 1)) == 0) { - cmn_err(CE_WARN, "No interrupt vector: %s instance %d", - ddi_get_name(dip), ddi_get_instance(dip)); - return (-1); - } - } - - mutex_enter(&airq_mutex); - if (apic_irq_table[irqno] == NULL) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_irq_table[irqno] = irqptr; - } else { - irqptr = apic_irq_table[irqno]; - if (irqptr->airq_mps_intr_index != FREE_INDEX) { - /* - * The slot is used by another irqno, so allocate - * a free irqno for this interrupt - */ - newirq = apic_allocate_irq(apic_first_avail_irq); - if (newirq == -1) { - mutex_exit(&airq_mutex); - return (-1); - } - irqno = newirq; - irqptr = apic_irq_table[irqno]; - if (irqptr == NULL) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), - KM_SLEEP); - irqptr->airq_temp_cpu = IRQ_UNINIT; - apic_irq_table[irqno] = irqptr; - } - vector = apic_modify_vector(vector, newirq); - } - } - apic_max_device_irq = max(irqno, apic_max_device_irq); - apic_min_device_irq = min(irqno, apic_min_device_irq); - mutex_exit(&airq_mutex); - irqptr->airq_ioapicindex = ioapicindex; - irqptr->airq_intin_no = ipin; - irqptr->airq_ipl = ipl; - irqptr->airq_vector = vector; - irqptr->airq_origirq = (uchar_t)origirq; - irqptr->airq_share_id = 0; - irqptr->airq_mps_intr_index = (short)intr_index; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - irqptr->airq_cpu = apic_bind_intr(dip, irqno, ioapic, ipin); - if (intr_flagp) - irqptr->airq_iflag = *intr_flagp; - - if (!DDI_INTR_IS_MSI_OR_MSIX(type)) { - /* setup I/O APIC entry for non-MSI/X interrupts */ - apic_record_rdt_entry(irqptr, irqno); - } - return (irqno); -} - -/* - * return the cpu to which this intr should be bound. - * Check properties or any other mechanism to see if user wants it - * bound to a specific CPU. If so, return the cpu id with high bit set. - * If not, use the policy to choose a cpu and return the id. - */ -uint32_t -apic_bind_intr(dev_info_t *dip, int irq, uchar_t ioapicid, uchar_t intin) -{ - int instance, instno, prop_len, bind_cpu, count; - uint_t i, rc; - uint32_t cpu; - major_t major; - char *name, *drv_name, *prop_val, *cptr; - char prop_name[32]; - ulong_t iflag; - - - if (apic_intr_policy == INTR_LOWEST_PRIORITY) - return (IRQ_UNBOUND); - - if (apic_nproc == 1) - return (0); - - drv_name = NULL; - rc = DDI_PROP_NOT_FOUND; - major = (major_t)-1; - if (dip != NULL) { - name = ddi_get_name(dip); - major = ddi_name_to_major(name); - drv_name = ddi_major_to_name(major); - instance = ddi_get_instance(dip); - if (apic_intr_policy == INTR_ROUND_ROBIN_WITH_AFFINITY) { - i = apic_min_device_irq; - for (; i <= apic_max_device_irq; i++) { - - if ((i == irq) || (apic_irq_table[i] == NULL) || - (apic_irq_table[i]->airq_mps_intr_index - == FREE_INDEX)) - continue; - - if ((apic_irq_table[i]->airq_major == major) && - (!(apic_irq_table[i]->airq_cpu & - IRQ_USER_BOUND))) { - - cpu = apic_irq_table[i]->airq_cpu; - - cmn_err(CE_CONT, - "!%s: %s (%s) instance #%d " - "irq 0x%x vector 0x%x ioapic 0x%x " - "intin 0x%x is bound to cpu %d\n", - psm_name, - name, drv_name, instance, irq, - apic_irq_table[irq]->airq_vector, - ioapicid, intin, cpu); - return (cpu); - } - } - } - /* - * search for "drvname"_intpt_bind_cpus property first, the - * syntax of the property should be "a[,b,c,...]" where - * instance 0 binds to cpu a, instance 1 binds to cpu b, - * instance 3 binds to cpu c... - * ddi_getlongprop() will search /option first, then / - * if "drvname"_intpt_bind_cpus doesn't exist, then find - * intpt_bind_cpus property. The syntax is the same, and - * it applies to all the devices if its "drvname" specific - * property doesn't exist - */ - (void) strcpy(prop_name, drv_name); - (void) strcat(prop_name, "_intpt_bind_cpus"); - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, prop_name, - (caddr_t)&prop_val, &prop_len); - if (rc != DDI_PROP_SUCCESS) { - rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, - "intpt_bind_cpus", (caddr_t)&prop_val, &prop_len); - } - } - if (rc == DDI_PROP_SUCCESS) { - for (i = count = 0; i < (prop_len - 1); i++) - if (prop_val[i] == ',') - count++; - if (prop_val[i-1] != ',') - count++; - /* - * if somehow the binding instances defined in the - * property are not enough for this instno., then - * reuse the pattern for the next instance until - * it reaches the requested instno - */ - instno = instance % count; - i = 0; - cptr = prop_val; - while (i < instno) - if (*cptr++ == ',') - i++; - bind_cpu = stoi(&cptr); - kmem_free(prop_val, prop_len); - /* if specific CPU is bogus, then default to next cpu */ - if (!apic_cpu_in_range(bind_cpu)) { - cmn_err(CE_WARN, "%s: %s=%s: CPU %d not present", - psm_name, prop_name, prop_val, bind_cpu); - rc = DDI_PROP_NOT_FOUND; - } else { - /* indicate that we are bound at user request */ - bind_cpu |= IRQ_USER_BOUND; - } - /* - * no need to check apic_cpus[].aci_status, if specific CPU is - * not up, then post_cpu_start will handle it. - */ - } - if (rc != DDI_PROP_SUCCESS) { - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - bind_cpu = apic_get_next_bind_cpu(); - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - } - - if (drv_name != NULL) - cmn_err(CE_CONT, "!%s: %s (%s) instance %d irq 0x%x " - "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", - psm_name, name, drv_name, instance, irq, - apic_irq_table[irq]->airq_vector, ioapicid, intin, - bind_cpu & ~IRQ_USER_BOUND); - else - cmn_err(CE_CONT, "!%s: irq 0x%x " - "vector 0x%x ioapic 0x%x intin 0x%x is bound to cpu %d\n", - psm_name, irq, apic_irq_table[irq]->airq_vector, ioapicid, - intin, bind_cpu & ~IRQ_USER_BOUND); - - return ((uint32_t)bind_cpu); -} - -/* - * Mark vector as being in the process of being deleted. Interrupts - * may still come in on some CPU. The moment an interrupt comes with - * the new vector, we know we can free the old one. Called only from - * addspl and delspl with interrupts disabled. Because an interrupt - * can be shared, but no interrupt from either device may come in, - * we also use a timeout mechanism, which we arbitrarily set to - * apic_revector_timeout microseconds. - */ -static void -apic_mark_vector(uchar_t oldvector, uchar_t newvector) -{ - ulong_t iflag; - - iflag = intr_clear(); - lock_set(&apic_revector_lock); - if (!apic_oldvec_to_newvec) { - apic_oldvec_to_newvec = - kmem_zalloc(sizeof (newvector) * APIC_MAX_VECTOR * 2, - KM_NOSLEEP); - - if (!apic_oldvec_to_newvec) { - /* - * This failure is not catastrophic. - * But, the oldvec will never be freed. - */ - apic_error |= APIC_ERR_MARK_VECTOR_FAIL; - lock_clear(&apic_revector_lock); - intr_restore(iflag); - return; - } - apic_newvec_to_oldvec = &apic_oldvec_to_newvec[APIC_MAX_VECTOR]; - } - - /* See if we already did this for drivers which do double addintrs */ - if (apic_oldvec_to_newvec[oldvector] != newvector) { - apic_oldvec_to_newvec[oldvector] = newvector; - apic_newvec_to_oldvec[newvector] = oldvector; - apic_revector_pending++; - } - lock_clear(&apic_revector_lock); - intr_restore(iflag); - (void) timeout(apic_xlate_vector_free_timeout_handler, - (void *)(uintptr_t)oldvector, drv_usectohz(apic_revector_timeout)); -} - -/* - * xlate_vector is called from intr_enter if revector_pending is set. - * It will xlate it if needed and mark the old vector as free. - */ -uchar_t -apic_xlate_vector(uchar_t vector) -{ - uchar_t newvector, oldvector = 0; - - lock_set(&apic_revector_lock); - /* Do we really need to do this ? */ - if (!apic_revector_pending) { - lock_clear(&apic_revector_lock); - return (vector); - } - if ((newvector = apic_oldvec_to_newvec[vector]) != 0) - oldvector = vector; - else { - /* - * The incoming vector is new . See if a stale entry is - * remaining - */ - if ((oldvector = apic_newvec_to_oldvec[vector]) != 0) - newvector = vector; - } - - if (oldvector) { - apic_revector_pending--; - apic_oldvec_to_newvec[oldvector] = 0; - apic_newvec_to_oldvec[newvector] = 0; - apic_free_vector(oldvector); - lock_clear(&apic_revector_lock); - /* There could have been more than one reprogramming! */ - return (apic_xlate_vector(newvector)); - } - lock_clear(&apic_revector_lock); - return (vector); -} - -void -apic_xlate_vector_free_timeout_handler(void *arg) -{ - ulong_t iflag; - uchar_t oldvector, newvector; - - oldvector = (uchar_t)(uintptr_t)arg; - iflag = intr_clear(); - lock_set(&apic_revector_lock); - if ((newvector = apic_oldvec_to_newvec[oldvector]) != 0) { - apic_free_vector(oldvector); - apic_oldvec_to_newvec[oldvector] = 0; - apic_newvec_to_oldvec[newvector] = 0; - apic_revector_pending--; - } - - lock_clear(&apic_revector_lock); - intr_restore(iflag); -} - -/* - * Bind interrupt corresponding to irq_ptr to bind_cpu. - * Must be called with interrupts disabled and apic_ioapic_lock held - */ -int -apic_rebind(apic_irq_t *irq_ptr, int bind_cpu, - struct ioapic_reprogram_data *drep) -{ - int ioapicindex, intin_no; - uint32_t airq_temp_cpu; - apic_cpus_info_t *cpu_infop; - uint32_t rdt_entry; - int which_irq; - ioapic_rdt_t irdt; - - which_irq = apic_vector_to_irq[irq_ptr->airq_vector]; - - intin_no = irq_ptr->airq_intin_no; - ioapicindex = irq_ptr->airq_ioapicindex; - airq_temp_cpu = irq_ptr->airq_temp_cpu; - if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != IRQ_UNBOUND) { - if (airq_temp_cpu & IRQ_USER_BOUND) - /* Mask off high bit so it can be used as array index */ - airq_temp_cpu &= ~IRQ_USER_BOUND; - - ASSERT(apic_cpu_in_range(airq_temp_cpu)); - } - - /* - * Can't bind to a CPU that's not accepting interrupts: - */ - cpu_infop = &apic_cpus[bind_cpu & ~IRQ_USER_BOUND]; - if (!(cpu_infop->aci_status & APIC_CPU_INTR_ENABLE)) - return (1); - - /* - * If we are about to change the interrupt vector for this interrupt, - * and this interrupt is level-triggered, attached to an IOAPIC, - * has been delivered to a CPU and that CPU has not handled it - * yet, we cannot reprogram the IOAPIC now. - */ - if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { - - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, - intin_no); - - if ((irq_ptr->airq_vector != RDT_VECTOR(rdt_entry)) && - apic_check_stuck_interrupt(irq_ptr, airq_temp_cpu, - bind_cpu, ioapicindex, intin_no, which_irq, drep) != 0) { - - return (0); - } - - /* - * NOTE: We do not unmask the RDT here, as an interrupt MAY - * still come in before we have a chance to reprogram it below. - * The reprogramming below will simultaneously change and - * unmask the RDT entry. - */ - - if ((uint32_t)bind_cpu == IRQ_UNBOUND) { - irdt.ir_lo = AV_LDEST | AV_LOPRI | - irq_ptr->airq_rdt_entry; - - WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapicindex, intin_no, - AV_TOALL); - - if (airq_temp_cpu != IRQ_UNINIT && airq_temp_cpu != - IRQ_UNBOUND) - apic_cpus[airq_temp_cpu].aci_temp_bound--; - - /* - * Write the vector, trigger, and polarity portion of - * the RDT - */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, intin_no, - irdt.ir_lo); - - irq_ptr->airq_temp_cpu = IRQ_UNBOUND; - return (0); - } - } - - if (bind_cpu & IRQ_USER_BOUND) { - cpu_infop->aci_bound++; - } else { - cpu_infop->aci_temp_bound++; - } - ASSERT(apic_cpu_in_range(bind_cpu)); - - if ((airq_temp_cpu != IRQ_UNBOUND) && (airq_temp_cpu != IRQ_UNINIT)) { - apic_cpus[airq_temp_cpu].aci_temp_bound--; - } - if (!APIC_IS_MSI_OR_MSIX_INDEX(irq_ptr->airq_mps_intr_index)) { - - irdt.ir_lo = AV_PDEST | AV_FIXED | irq_ptr->airq_rdt_entry; - irdt.ir_hi = cpu_infop->aci_local_id; - - /* Write the RDT entry -- bind to a specific CPU: */ - WRITE_IOAPIC_RDT_ENTRY_HIGH_DWORD(ioapicindex, intin_no, - irdt.ir_hi << APIC_ID_BIT_OFFSET); - - /* Write the vector, trigger, and polarity portion of the RDT */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapicindex, intin_no, - irdt.ir_lo); - - } else { - int type = (irq_ptr->airq_mps_intr_index == MSI_INDEX) ? - DDI_INTR_TYPE_MSI : DDI_INTR_TYPE_MSIX; - if (type == DDI_INTR_TYPE_MSI) { - if (irq_ptr->airq_ioapicindex == - irq_ptr->airq_origirq) { - /* first one */ - DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " - "apic_pci_msi_enable_vector\n")); - apic_pci_msi_enable_vector(irq_ptr, - type, which_irq, irq_ptr->airq_vector, - irq_ptr->airq_intin_no, - cpu_infop->aci_local_id); - } - if ((irq_ptr->airq_ioapicindex + - irq_ptr->airq_intin_no - 1) == - irq_ptr->airq_origirq) { /* last one */ - DDI_INTR_IMPLDBG((CE_CONT, "apic_rebind: call " - "apic_pci_msi_enable_mode\n")); - apic_pci_msi_enable_mode(irq_ptr->airq_dip, - type, which_irq); - } - } else { /* MSI-X */ - apic_pci_msi_enable_vector(irq_ptr, type, - irq_ptr->airq_origirq, irq_ptr->airq_vector, 1, - cpu_infop->aci_local_id); - apic_pci_msi_enable_mode(irq_ptr->airq_dip, type, - irq_ptr->airq_origirq); - } - } - irq_ptr->airq_temp_cpu = (uint32_t)bind_cpu; - apic_redist_cpu_skip &= ~(1 << (bind_cpu & ~IRQ_USER_BOUND)); - return (0); -} - -static void -apic_last_ditch_clear_remote_irr(int ioapic_ix, int intin_no) -{ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) - & AV_REMOTE_IRR) != 0) { - /* - * Trying to clear the bit through normal - * channels has failed. So as a last-ditch - * effort, try to set the trigger mode to - * edge, then to level. This has been - * observed to work on many systems. - */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no, - READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no) & ~AV_LEVEL); - - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no, - READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no) | AV_LEVEL); - - /* - * If the bit's STILL set, this interrupt may - * be hosed. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no) & AV_REMOTE_IRR) != 0) { - - prom_printf("%s: Remote IRR still " - "not clear for IOAPIC %d intin %d.\n" - "\tInterrupts to this pin may cease " - "functioning.\n", psm_name, ioapic_ix, - intin_no); -#ifdef DEBUG - apic_last_ditch_reprogram_failures++; -#endif - } - } -} - -/* - * This function is protected by apic_ioapic_lock coupled with the - * fact that interrupts are disabled. - */ -static void -delete_defer_repro_ent(int which_irq) -{ - ASSERT(which_irq >= 0); - ASSERT(which_irq <= 255); - ASSERT(LOCK_HELD(&apic_ioapic_lock)); - - if (apic_reprogram_info[which_irq].done) - return; - - apic_reprogram_info[which_irq].done = B_TRUE; - -#ifdef DEBUG - apic_defer_repro_total_retries += - apic_reprogram_info[which_irq].tries; - - apic_defer_repro_successes++; -#endif - - if (--apic_reprogram_outstanding == 0) { - - setlvlx = psm_intr_exit_fn(); - } -} - - -/* - * Interrupts must be disabled during this function to prevent - * self-deadlock. Interrupts are disabled because this function - * is called from apic_check_stuck_interrupt(), which is called - * from apic_rebind(), which requires its caller to disable interrupts. - */ -static void -add_defer_repro_ent(apic_irq_t *irq_ptr, int which_irq, int new_bind_cpu) -{ - ASSERT(which_irq >= 0); - ASSERT(which_irq <= 255); - ASSERT(!interrupts_enabled()); - - /* - * On the off-chance that there's already a deferred - * reprogramming on this irq, check, and if so, just update the - * CPU and irq pointer to which the interrupt is targeted, then return. - */ - if (!apic_reprogram_info[which_irq].done) { - apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; - apic_reprogram_info[which_irq].irqp = irq_ptr; - return; - } - - apic_reprogram_info[which_irq].irqp = irq_ptr; - apic_reprogram_info[which_irq].bindcpu = new_bind_cpu; - apic_reprogram_info[which_irq].tries = 0; - /* - * This must be the last thing set, since we're not - * grabbing any locks, apic_try_deferred_reprogram() will - * make its decision about using this entry iff done - * is false. - */ - apic_reprogram_info[which_irq].done = B_FALSE; - - /* - * If there were previously no deferred reprogrammings, change - * setlvlx to call apic_try_deferred_reprogram() - */ - if (++apic_reprogram_outstanding == 1) { - - setlvlx = apic_try_deferred_reprogram; - } -} - -static void -apic_try_deferred_reprogram(int prev_ipl, int irq) -{ - int reproirq; - ulong_t iflag; - struct ioapic_reprogram_data *drep; - - (*psm_intr_exit_fn())(prev_ipl, irq); - - if (!lock_try(&apic_defer_reprogram_lock)) { - return; - } - - /* - * Acquire the apic_ioapic_lock so that any other operations that - * may affect the apic_reprogram_info state are serialized. - * It's still possible for the last deferred reprogramming to clear - * between the time we entered this function and the time we get to - * the for loop below. In that case, *setlvlx will have been set - * back to *_intr_exit and drep will be NULL. (There's no way to - * stop that from happening -- we would need to grab a lock before - * calling *setlvlx, which is neither realistic nor prudent). - */ - iflag = intr_clear(); - lock_set(&apic_ioapic_lock); - - /* - * For each deferred RDT entry, try to reprogram it now. Note that - * there is no lock acquisition to read apic_reprogram_info because - * '.done' is set only after the other fields in the structure are set. - */ - - drep = NULL; - for (reproirq = 0; reproirq <= APIC_MAX_VECTOR; reproirq++) { - if (apic_reprogram_info[reproirq].done == B_FALSE) { - drep = &apic_reprogram_info[reproirq]; - break; - } - } - - /* - * Either we found a deferred action to perform, or - * we entered this function spuriously, after *setlvlx - * was restored to point to *_intr_exit. Any other - * permutation is invalid. - */ - ASSERT(drep != NULL || *setlvlx == psm_intr_exit_fn()); - - /* - * Though we can't really do anything about errors - * at this point, keep track of them for reporting. - * Note that it is very possible for apic_setup_io_intr - * to re-register this very timeout if the Remote IRR bit - * has not yet cleared. - */ - -#ifdef DEBUG - if (drep != NULL) { - if (apic_setup_io_intr(drep, reproirq, B_TRUE) != 0) { - apic_deferred_setup_failures++; - } - } else { - apic_deferred_spurious_enters++; - } -#else - if (drep != NULL) - (void) apic_setup_io_intr(drep, reproirq, B_TRUE); -#endif - - lock_clear(&apic_ioapic_lock); - intr_restore(iflag); - - lock_clear(&apic_defer_reprogram_lock); -} - -static void -apic_ioapic_wait_pending_clear(int ioapic_ix, int intin_no) -{ - int waited; - - /* - * Wait for the delivery pending bit to clear. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) & - (AV_LEVEL|AV_PENDING)) == (AV_LEVEL|AV_PENDING)) { - - /* - * If we're still waiting on the delivery of this interrupt, - * continue to wait here until it is delivered (this should be - * a very small amount of time, but include a timeout just in - * case). - */ - for (waited = 0; waited < apic_max_reps_clear_pending; - waited++) { - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no) & AV_PENDING) == 0) { - break; - } - } - } -} - - -/* - * Checks to see if the IOAPIC interrupt entry specified has its Remote IRR - * bit set. Calls functions that modify the function that setlvlx points to, - * so that the reprogramming can be retried very shortly. - * - * This function will mask the RDT entry if the interrupt is level-triggered. - * (The caller is responsible for unmasking the RDT entry.) - * - * Returns non-zero if the caller should defer IOAPIC reprogramming. - */ -static int -apic_check_stuck_interrupt(apic_irq_t *irq_ptr, int old_bind_cpu, - int new_bind_cpu, int ioapic_ix, int intin_no, int which_irq, - struct ioapic_reprogram_data *drep) -{ - int32_t rdt_entry; - int waited; - int reps = 0; - - /* - * Wait for the delivery pending bit to clear. - */ - do { - ++reps; - - apic_ioapic_wait_pending_clear(ioapic_ix, intin_no); - - /* - * Mask the RDT entry, but only if it's a level-triggered - * interrupt - */ - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no); - if ((rdt_entry & (AV_LEVEL|AV_MASK)) == AV_LEVEL) { - - /* Mask it */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no, - AV_MASK | rdt_entry); - } - - if ((rdt_entry & AV_LEVEL) == AV_LEVEL) { - /* - * If there was a race and an interrupt was injected - * just before we masked, check for that case here. - * Then, unmask the RDT entry and try again. If we're - * on our last try, don't unmask (because we want the - * RDT entry to remain masked for the rest of the - * function). - */ - rdt_entry = READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no); - if ((rdt_entry & AV_PENDING) && - (reps < apic_max_reps_clear_pending)) { - /* Unmask it */ - WRITE_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no, rdt_entry & ~AV_MASK); - } - } - - } while ((rdt_entry & AV_PENDING) && - (reps < apic_max_reps_clear_pending)); - -#ifdef DEBUG - if (rdt_entry & AV_PENDING) - apic_intr_deliver_timeouts++; -#endif - - /* - * If the remote IRR bit is set, then the interrupt has been sent - * to a CPU for processing. We have no choice but to wait for - * that CPU to process the interrupt, at which point the remote IRR - * bit will be cleared. - */ - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, intin_no) & - (AV_LEVEL|AV_REMOTE_IRR)) == (AV_LEVEL|AV_REMOTE_IRR)) { - - /* - * If the CPU that this RDT is bound to is NOT the current - * CPU, wait until that CPU handles the interrupt and ACKs - * it. If this interrupt is not bound to any CPU (that is, - * if it's bound to the logical destination of "anyone"), it - * may have been delivered to the current CPU so handle that - * case by deferring the reprogramming (below). - */ - if ((old_bind_cpu != IRQ_UNBOUND) && - (old_bind_cpu != IRQ_UNINIT) && - (old_bind_cpu != psm_get_cpu_id())) { - for (waited = 0; waited < apic_max_reps_clear_pending; - waited++) { - if ((READ_IOAPIC_RDT_ENTRY_LOW_DWORD(ioapic_ix, - intin_no) & AV_REMOTE_IRR) == 0) { - - delete_defer_repro_ent(which_irq); - - /* Remote IRR has cleared! */ - return (0); - } - } - } - - /* - * If we waited and the Remote IRR bit is still not cleared, - * AND if we've invoked the timeout APIC_REPROGRAM_MAX_TIMEOUTS - * times for this interrupt, try the last-ditch workaround: - */ - if (drep && drep->tries >= APIC_REPROGRAM_MAX_TRIES) { - - apic_last_ditch_clear_remote_irr(ioapic_ix, intin_no); - - /* Mark this one as reprogrammed: */ - delete_defer_repro_ent(which_irq); - - return (0); - } else { -#ifdef DEBUG - apic_intr_deferrals++; -#endif - - /* - * If waiting for the Remote IRR bit (above) didn't - * allow it to clear, defer the reprogramming. - * Add a new deferred-programming entry if the - * caller passed a NULL one (and update the existing one - * in case anything changed). - */ - add_defer_repro_ent(irq_ptr, which_irq, new_bind_cpu); - if (drep) - drep->tries++; - - /* Inform caller to defer IOAPIC programming: */ - return (1); - } - - } - - /* Remote IRR is clear */ - delete_defer_repro_ent(which_irq); - - return (0); -} - -/* - * Called to migrate all interrupts at an irq to another cpu. - * Must be called with interrupts disabled and apic_ioapic_lock held - */ -int -apic_rebind_all(apic_irq_t *irq_ptr, int bind_cpu) -{ - apic_irq_t *irqptr = irq_ptr; - int retval = 0; - - while (irqptr) { - if (irqptr->airq_temp_cpu != IRQ_UNINIT) - retval |= apic_rebind(irqptr, bind_cpu, NULL); - irqptr = irqptr->airq_next; - } - - return (retval); -} - -/* - * apic_intr_redistribute does all the messy computations for identifying - * which interrupt to move to which CPU. Currently we do just one interrupt - * at a time. This reduces the time we spent doing all this within clock - * interrupt. When it is done in idle, we could do more than 1. - * First we find the most busy and the most free CPU (time in ISR only) - * skipping those CPUs that has been identified as being ineligible (cpu_skip) - * Then we look for IRQs which are closest to the difference between the - * most busy CPU and the average ISR load. We try to find one whose load - * is less than difference.If none exists, then we chose one larger than the - * difference, provided it does not make the most idle CPU worse than the - * most busy one. In the end, we clear all the busy fields for CPUs. For - * IRQs, they are cleared as they are scanned. - */ -void -apic_intr_redistribute(void) -{ - int busiest_cpu, most_free_cpu; - int cpu_free, cpu_busy, max_busy, min_busy; - int min_free, diff; - int average_busy, cpus_online; - int i, busy; - ulong_t iflag; - apic_cpus_info_t *cpu_infop; - apic_irq_t *min_busy_irq = NULL; - apic_irq_t *max_busy_irq = NULL; - - busiest_cpu = most_free_cpu = -1; - cpu_free = cpu_busy = max_busy = average_busy = 0; - min_free = apic_sample_factor_redistribution; - cpus_online = 0; - /* - * Below we will check for CPU_INTR_ENABLE, bound, temp_bound, temp_cpu - * without ioapic_lock. That is OK as we are just doing statistical - * sampling anyway and any inaccuracy now will get corrected next time - * The call to rebind which actually changes things will make sure - * we are consistent. - */ - for (i = 0; i < apic_nproc; i++) { - if (apic_cpu_in_range(i) && - !(apic_redist_cpu_skip & (1 << i)) && - (apic_cpus[i].aci_status & APIC_CPU_INTR_ENABLE)) { - - cpu_infop = &apic_cpus[i]; - /* - * If no unbound interrupts or only 1 total on this - * CPU, skip - */ - if (!cpu_infop->aci_temp_bound || - (cpu_infop->aci_bound + cpu_infop->aci_temp_bound) - == 1) { - apic_redist_cpu_skip |= 1 << i; - continue; - } - - busy = cpu_infop->aci_busy; - average_busy += busy; - cpus_online++; - if (max_busy < busy) { - max_busy = busy; - busiest_cpu = i; - } - if (min_free > busy) { - min_free = busy; - most_free_cpu = i; - } - if (busy > apic_int_busy_mark) { - cpu_busy |= 1 << i; - } else { - if (busy < apic_int_free_mark) - cpu_free |= 1 << i; - } - } - } - if ((cpu_busy && cpu_free) || - (max_busy >= (min_free + apic_diff_for_redistribution))) { - - apic_num_imbalance++; -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf( - "redistribute busy=%x free=%x max=%x min=%x", - cpu_busy, cpu_free, max_busy, min_free); - } -#endif /* DEBUG */ - - - average_busy /= cpus_online; - - diff = max_busy - average_busy; - min_busy = max_busy; /* start with the max possible value */ - max_busy = 0; - min_busy_irq = max_busy_irq = NULL; - i = apic_min_device_irq; - for (; i <= apic_max_device_irq; i++) { - apic_irq_t *irq_ptr; - /* Change to linked list per CPU ? */ - if ((irq_ptr = apic_irq_table[i]) == NULL) - continue; - /* Check for irq_busy & decide which one to move */ - /* Also zero them for next round */ - if ((irq_ptr->airq_temp_cpu == busiest_cpu) && - irq_ptr->airq_busy) { - if (irq_ptr->airq_busy < diff) { - /* - * Check for least busy CPU, - * best fit or what ? - */ - if (max_busy < irq_ptr->airq_busy) { - /* - * Most busy within the - * required differential - */ - max_busy = irq_ptr->airq_busy; - max_busy_irq = irq_ptr; - } - } else { - if (min_busy > irq_ptr->airq_busy) { - /* - * least busy, but more than - * the reqd diff - */ - if (min_busy < - (diff + average_busy - - min_free)) { - /* - * Making sure new cpu - * will not end up - * worse - */ - min_busy = - irq_ptr->airq_busy; - - min_busy_irq = irq_ptr; - } - } - } - } - irq_ptr->airq_busy = 0; - } - - if (max_busy_irq != NULL) { -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf("rebinding %x to %x", - max_busy_irq->airq_vector, most_free_cpu); - } -#endif /* DEBUG */ - iflag = intr_clear(); - if (lock_try(&apic_ioapic_lock)) { - if (apic_rebind_all(max_busy_irq, - most_free_cpu) == 0) { - /* Make change permenant */ - max_busy_irq->airq_cpu = - (uint32_t)most_free_cpu; - } - lock_clear(&apic_ioapic_lock); - } - intr_restore(iflag); - - } else if (min_busy_irq != NULL) { -#ifdef DEBUG - if (apic_verbose & APIC_VERBOSE_IOAPIC_FLAG) { - prom_printf("rebinding %x to %x", - min_busy_irq->airq_vector, most_free_cpu); - } -#endif /* DEBUG */ - - iflag = intr_clear(); - if (lock_try(&apic_ioapic_lock)) { - if (apic_rebind_all(min_busy_irq, - most_free_cpu) == 0) { - /* Make change permenant */ - min_busy_irq->airq_cpu = - (uint32_t)most_free_cpu; - } - lock_clear(&apic_ioapic_lock); - } - intr_restore(iflag); - - } else { - if (cpu_busy != (1 << busiest_cpu)) { - apic_redist_cpu_skip |= 1 << busiest_cpu; - /* - * We leave cpu_skip set so that next time we - * can choose another cpu - */ - } - } - apic_num_rebind++; - } else { - /* - * found nothing. Could be that we skipped over valid CPUs - * or we have balanced everything. If we had a variable - * ticks_for_redistribution, it could be increased here. - * apic_int_busy, int_free etc would also need to be - * changed. - */ - if (apic_redist_cpu_skip) - apic_redist_cpu_skip = 0; - } - for (i = 0; i < apic_nproc; i++) { - if (apic_cpu_in_range(i)) { - apic_cpus[i].aci_busy = 0; - } - } -} - -void -apic_cleanup_busy(void) -{ - int i; - apic_irq_t *irq_ptr; - - for (i = 0; i < apic_nproc; i++) { - if (apic_cpu_in_range(i)) { - apic_cpus[i].aci_busy = 0; - } - } - - for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { - if ((irq_ptr = apic_irq_table[i]) != NULL) - irq_ptr->airq_busy = 0; - } -} - -int -apic_ioapic_method_probe() -{ - return (PSM_SUCCESS); -} diff --git a/usr/src/uts/i86xpv/io/psm/xpv_intr.c b/usr/src/uts/i86xpv/io/psm/xpv_intr.c deleted file mode 100644 index 99fc66866c..0000000000 --- a/usr/src/uts/i86xpv/io/psm/xpv_intr.c +++ /dev/null @@ -1,363 +0,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 (c) 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Multiple vector support for MSI */ -int apic_multi_msi_enable = 1; - -/* Multiple vector support for MSI-X */ -int apic_msix_enable = 1; - -/* - * check whether the system supports MSI - * - * If PCI-E capability is found, then this must be a PCI-E system. - * Since MSI is required for PCI-E system, it returns PSM_SUCCESS - * to indicate this system supports MSI. - */ -int -apic_check_msi_support() -{ - dev_info_t *cdip; - char dev_type[16]; - int dev_len; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support:\n")); - - /* - * check whether the first level children of root_node have - * PCI-E capability - */ - for (cdip = ddi_get_child(ddi_root_node()); cdip != NULL; - cdip = ddi_get_next_sibling(cdip)) { - - DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: cdip: 0x%p," - " driver: %s, binding: %s, nodename: %s\n", (void *)cdip, - ddi_driver_name(cdip), ddi_binding_name(cdip), - ddi_node_name(cdip))); - dev_len = sizeof (dev_type); - if (ddi_getlongprop_buf(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, - "device_type", (caddr_t)dev_type, &dev_len) - != DDI_PROP_SUCCESS) - continue; - if (strcmp(dev_type, "pciex") == 0) - return (PSM_SUCCESS); - } - - /* MSI is not supported on this system */ - DDI_INTR_IMPLDBG((CE_CONT, "apic_check_msi_support: no 'pciex' " - "device_type found\n")); - return (PSM_FAILURE); -} - - -/* - * It finds the apic_irq_t associates with the dip, ispec and type. - */ -apic_irq_t * -apic_find_irq(dev_info_t *dip, struct intrspec *ispec, int type) -{ - apic_irq_t *irqp; - int i; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_find_irq: dip=0x%p vec=0x%x " - "ipl=0x%x type=0x%x\n", (void *)dip, ispec->intrspec_vec, - ispec->intrspec_pri, type)); - - for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { - for (irqp = apic_irq_table[i]; irqp; irqp = irqp->airq_next) { - if ((irqp->airq_dip == dip) && - (irqp->airq_origirq == ispec->intrspec_vec) && - (irqp->airq_ipl == ispec->intrspec_pri)) { - if (type == DDI_INTR_TYPE_MSI) { - if (irqp->airq_mps_intr_index == - MSI_INDEX) - return (irqp); - } else if (type == DDI_INTR_TYPE_MSIX) { - if (irqp->airq_mps_intr_index == - MSIX_INDEX) - return (irqp); - } else - return (irqp); - } - } - } - DDI_INTR_IMPLDBG((CE_CONT, "apic_find_irq: return NULL\n")); - return (NULL); -} - - -int -apic_get_vector_intr_info(int vecirq, apic_get_intr_t *intr_params_p) -{ - struct autovec *av_dev; - uchar_t irqno; - int i; - apic_irq_t *irq_p; - - /* Sanity check the vector/irq argument. */ - ASSERT((vecirq >= 0) || (vecirq <= APIC_MAX_VECTOR)); - - mutex_enter(&airq_mutex); - - /* - * Convert the vecirq arg to an irq using vector_to_irq table - * if the arg is a vector. Pass thru if already an irq. - */ - if ((intr_params_p->avgi_req_flags & PSMGI_INTRBY_FLAGS) == - PSMGI_INTRBY_VEC) - irqno = apic_vector_to_irq[vecirq]; - else - irqno = vecirq; - - irq_p = apic_irq_table[irqno]; - - if ((irq_p == NULL) || - ((irq_p->airq_mps_intr_index != RESERVE_INDEX) && - ((irq_p->airq_temp_cpu == IRQ_UNBOUND) || - (irq_p->airq_temp_cpu == IRQ_UNINIT)))) { - mutex_exit(&airq_mutex); - return (PSM_FAILURE); - } - - if (intr_params_p->avgi_req_flags & PSMGI_REQ_CPUID) { - - /* Get the (temp) cpu from apic_irq table, indexed by irq. */ - intr_params_p->avgi_cpu_id = irq_p->airq_temp_cpu; - - /* Return user bound info for intrd. */ - if (intr_params_p->avgi_cpu_id & IRQ_USER_BOUND) { - intr_params_p->avgi_cpu_id &= ~IRQ_USER_BOUND; - intr_params_p->avgi_cpu_id |= PSMGI_CPU_USER_BOUND; - } - } - - if (intr_params_p->avgi_req_flags & PSMGI_REQ_VECTOR) - intr_params_p->avgi_vector = irq_p->airq_vector; - - if (intr_params_p->avgi_req_flags & - (PSMGI_REQ_NUM_DEVS | PSMGI_REQ_GET_DEVS)) - /* Get number of devices from apic_irq table shared field. */ - intr_params_p->avgi_num_devs = irq_p->airq_share; - - if (intr_params_p->avgi_req_flags & PSMGI_REQ_GET_DEVS) { - - intr_params_p->avgi_req_flags |= PSMGI_REQ_NUM_DEVS; - - /* Some devices have NULL dip. Don't count these. */ - if (intr_params_p->avgi_num_devs > 0) { - for (i = 0, av_dev = autovect[irqno].avh_link; - av_dev; av_dev = av_dev->av_link) - if (av_dev->av_vector && av_dev->av_dip) - i++; - intr_params_p->avgi_num_devs = - MIN(intr_params_p->avgi_num_devs, i); - } - - /* There are no viable dips to return. */ - if (intr_params_p->avgi_num_devs == 0) - intr_params_p->avgi_dip_list = NULL; - - else { /* Return list of dips */ - - /* Allocate space in array for that number of devs. */ - intr_params_p->avgi_dip_list = kmem_zalloc( - intr_params_p->avgi_num_devs * - sizeof (dev_info_t *), - KM_SLEEP); - - /* - * Loop through the device list of the autovec table - * filling in the dip array. - * - * Note that the autovect table may have some special - * entries which contain NULL dips. These will be - * ignored. - */ - for (i = 0, av_dev = autovect[irqno].avh_link; - av_dev; av_dev = av_dev->av_link) - if (av_dev->av_vector && av_dev->av_dip) - intr_params_p->avgi_dip_list[i++] = - av_dev->av_dip; - } - } - - mutex_exit(&airq_mutex); - - return (PSM_SUCCESS); -} - - -/* - * apic_pci_msi_enable_vector: - * Set the address/data fields in the MSI/X capability structure - * XXX: MSI-X support - */ -/* ARGSUSED */ -void -apic_pci_msi_enable_vector(apic_irq_t *irq_ptr, int type, int inum, int vector, - int count, int target_apic_id) -{ - uint64_t msi_addr, msi_data; - ushort_t msi_ctrl; - dev_info_t *dip = irq_ptr->airq_dip; - int cap_ptr = i_ddi_get_msi_msix_cap_ptr(dip); - ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(dip); - - DDI_INTR_IMPLDBG((CE_CONT, "apic_pci_msi_enable_vector: dip=0x%p\n" - "\tdriver = %s, inum=0x%x vector=0x%x apicid=0x%x\n", (void *)dip, - ddi_driver_name(dip), inum, vector, target_apic_id)); - - ASSERT((handle != NULL) && (cap_ptr != 0)); - - /* MSI Address */ - msi_addr = (MSI_ADDR_HDR | - (target_apic_id << MSI_ADDR_DEST_SHIFT)); - msi_addr |= ((MSI_ADDR_RH_FIXED << MSI_ADDR_RH_SHIFT) | - (MSI_ADDR_DM_PHYSICAL << MSI_ADDR_DM_SHIFT)); - - /* MSI Data: MSI is edge triggered according to spec */ - msi_data = ((MSI_DATA_TM_EDGE << MSI_DATA_TM_SHIFT) | vector); - - DDI_INTR_IMPLDBG((CE_CONT, "apic_pci_msi_enable_vector: addr=0x%lx " - "data=0x%lx\n", (long)msi_addr, (long)msi_data)); - - if (type == DDI_INTR_TYPE_MSI) { - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL); - - /* Set the bits to inform how many MSIs are enabled */ - msi_ctrl |= ((highbit(count) -1) << PCI_MSI_MME_SHIFT); - pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl); - } -} - - -/* - * apic_pci_msi_disable_mode: - */ -void -apic_pci_msi_disable_mode(dev_info_t *rdip, int type) -{ - ushort_t msi_ctrl; - int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip); - ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip); - - ASSERT((handle != NULL) && (cap_ptr != 0)); - - if (type == DDI_INTR_TYPE_MSI) { - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL); - if (!(msi_ctrl & PCI_MSI_ENABLE_BIT)) - return; - - msi_ctrl &= ~PCI_MSI_ENABLE_BIT; /* MSI disable */ - pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl); - - } else if (type == DDI_INTR_TYPE_MSIX) { - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSIX_CTRL); - if (msi_ctrl & PCI_MSIX_ENABLE_BIT) { - msi_ctrl &= ~PCI_MSIX_ENABLE_BIT; - pci_config_put16(handle, cap_ptr + PCI_MSIX_CTRL, - msi_ctrl); - } - } -} - - -/* - * apic_pci_msi_enable_mode: - */ -void -apic_pci_msi_enable_mode(dev_info_t *rdip, int type, int inum) -{ - ushort_t msi_ctrl; - int cap_ptr = i_ddi_get_msi_msix_cap_ptr(rdip); - ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(rdip); - - ASSERT((handle != NULL) && (cap_ptr != 0)); - - if (type == DDI_INTR_TYPE_MSI) { - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL); - if ((msi_ctrl & PCI_MSI_ENABLE_BIT)) - return; - - msi_ctrl |= PCI_MSI_ENABLE_BIT; - pci_config_put16(handle, cap_ptr + PCI_MSI_CTRL, msi_ctrl); - - } else if (type == DDI_INTR_TYPE_MSIX) { - uintptr_t off; - uint32_t mask; - ddi_intr_msix_t *msix_p; - - msix_p = i_ddi_get_msix(rdip); - - ASSERT(msix_p != NULL); - - /* Offset into "inum"th entry in the MSI-X table & clear mask */ - off = (uintptr_t)msix_p->msix_tbl_addr + (inum * - PCI_MSIX_VECTOR_SIZE) + PCI_MSIX_VECTOR_CTRL_OFFSET; - - mask = ddi_get32(msix_p->msix_tbl_hdl, (uint32_t *)off); - - ddi_put32(msix_p->msix_tbl_hdl, (uint32_t *)off, (mask & ~1)); - - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSIX_CTRL); - - if (!(msi_ctrl & PCI_MSIX_ENABLE_BIT)) { - msi_ctrl |= PCI_MSIX_ENABLE_BIT; - pci_config_put16(handle, cap_ptr + PCI_MSIX_CTRL, - msi_ctrl); - } - } -} - - -/* - * We let the hypervisor deal with msi configutation - * so just stub this out. - */ - -/* ARGSUSED */ -void -apic_pci_msi_unconfigure(dev_info_t *rdip, int type, int inum) -{ -} diff --git a/usr/src/uts/i86xpv/io/psm/xpv_psm.c b/usr/src/uts/i86xpv/io/psm/xpv_psm.c deleted file mode 100644 index 1490baac60..0000000000 --- a/usr/src/uts/i86xpv/io/psm/xpv_psm.c +++ /dev/null @@ -1,1705 +0,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. - */ - -#define PSMI_1_7 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * Global Data - */ - -int xen_psm_verbose = 0; - -/* As of now we don't support x2apic in xVM */ -volatile uint32_t *apicadr = NULL; /* dummy, so common code will link */ -int apic_error = 0; -int apic_verbose = 0; -cpuset_t apic_cpumask; -int apic_forceload = 0; -uchar_t apic_vectortoipl[APIC_AVAIL_VECTOR / APIC_VECTOR_PER_IPL] = { - 3, 4, 5, 5, 6, 6, 9, 10, 11, 12, 13, 14, 15, 15 -}; -uchar_t apic_ipltopri[MAXIPL + 1]; -uchar_t apic_ipls[APIC_AVAIL_VECTOR]; -uint_t apic_picinit_called; -apic_cpus_info_t *apic_cpus; -int xen_psm_intr_policy = INTR_ROUND_ROBIN_WITH_AFFINITY; -/* use to make sure only one cpu handles the nmi */ -static lock_t xen_psm_nmi_lock; -int xen_psm_kmdb_on_nmi = 0; /* 0 - no, 1 - yes enter kmdb */ -int xen_psm_panic_on_nmi = 0; -int xen_psm_num_nmis = 0; - -cpuset_t xen_psm_cpus_online; /* online cpus */ -int xen_psm_ncpus = 1; /* cpu count */ -int xen_psm_next_bind_cpu; /* next cpu to bind an interrupt to */ - -int xen_support_msi = 0; - -static int xen_clock_irq = INVALID_IRQ; - -/* flag definitions for xen_psm_verbose */ -#define XEN_PSM_VERBOSE_IRQ_FLAG 0x00000001 -#define XEN_PSM_VERBOSE_POWEROFF_FLAG 0x00000002 -#define XEN_PSM_VERBOSE_POWEROFF_PAUSE_FLAG 0x00000004 - -#define XEN_PSM_VERBOSE_IRQ(fmt) \ - if (xen_psm_verbose & XEN_PSM_VERBOSE_IRQ_FLAG) \ - cmn_err fmt; - -#define XEN_PSM_VERBOSE_POWEROFF(fmt) \ - if (xen_psm_verbose & XEN_PSM_VERBOSE_POWEROFF_FLAG) \ - prom_printf fmt; - -/* - * Dummy apic array to point common routines at that want to do some apic - * manipulation. Xen doesn't allow guest apic access so we point at these - * memory locations to fake out those who want to do apic fiddling. - */ -uint32_t xen_psm_dummy_apic[APIC_IRR_REG + 1]; - -static struct psm_info xen_psm_info; -static void xen_psm_setspl(int); - -int -apic_alloc_msi_vectors(dev_info_t *dip, int inum, int count, int pri, - int behavior); -int -apic_alloc_msix_vectors(dev_info_t *dip, int inum, int count, int pri, - int behavior); - -/* - * Local support routines - */ - -/* - * Select vcpu to bind xen virtual device interrupt to. - */ -/*ARGSUSED*/ -int -xen_psm_bind_intr(int irq) -{ - int bind_cpu; - apic_irq_t *irqptr; - - bind_cpu = IRQ_UNBOUND; - if (xen_psm_intr_policy == INTR_LOWEST_PRIORITY) - return (bind_cpu); - if (irq <= APIC_MAX_VECTOR) - irqptr = apic_irq_table[irq]; - else - irqptr = NULL; - if (irqptr && (irqptr->airq_cpu != IRQ_UNBOUND)) - bind_cpu = irqptr->airq_cpu & ~IRQ_USER_BOUND; - if (bind_cpu != IRQ_UNBOUND) { - if (!CPU_IN_SET(xen_psm_cpus_online, bind_cpu)) - bind_cpu = 0; - goto done; - } - if (xen_psm_intr_policy == INTR_ROUND_ROBIN_WITH_AFFINITY) { - do { - bind_cpu = xen_psm_next_bind_cpu++; - if (xen_psm_next_bind_cpu >= xen_psm_ncpus) - xen_psm_next_bind_cpu = 0; - } while (!CPU_IN_SET(xen_psm_cpus_online, bind_cpu)); - } else { - bind_cpu = 0; - } -done: - return (bind_cpu); -} - -/* - * Autoconfiguration Routines - */ - -static int -xen_psm_probe(void) -{ - int ret = PSM_SUCCESS; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) - ret = apic_probe_common(xen_psm_info.p_mach_idstring); - return (ret); -} - -static void -xen_psm_softinit(void) -{ - /* LINTED logical expression always true: op "||" */ - ASSERT((1 << EVTCHN_SHIFT) == NBBY * sizeof (ulong_t)); - CPUSET_ATOMIC_ADD(xen_psm_cpus_online, 0); - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - apic_init_common(); - } -} - -#define XEN_NSEC_PER_TICK 10 /* XXX - assume we have a 100 Mhz clock */ - -/*ARGSUSED*/ -static int -xen_psm_clkinit(int hertz) -{ - extern enum tod_fault_type tod_fault(enum tod_fault_type, int); - extern int dosynctodr; - - /* - * domU cannot set the TOD hardware, fault the TOD clock now to - * indicate that and turn off attempts to sync TOD hardware - * with the hires timer. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - mutex_enter(&tod_lock); - (void) tod_fault(TOD_RDONLY, 0); - dosynctodr = 0; - mutex_exit(&tod_lock); - } - /* - * The hypervisor provides a timer based on the local APIC timer. - * The interface supports requests of nanosecond resolution. - * A common frequency of the apic clock is 100 Mhz which - * gives a resolution of 10 nsec per tick. What we would really like - * is a way to get the ns per tick value from xen. - * XXPV - This is an assumption that needs checking and may change - */ - return (XEN_NSEC_PER_TICK); -} - -static void -xen_psm_hrtimeinit(void) -{ - extern int gethrtime_hires; - gethrtime_hires = 1; -} - -/* xen_psm NMI handler */ -/*ARGSUSED*/ -static void -xen_psm_nmi_intr(caddr_t arg, struct regs *rp) -{ - xen_psm_num_nmis++; - - if (!lock_try(&xen_psm_nmi_lock)) - return; - - if (xen_psm_kmdb_on_nmi && psm_debugger()) { - debug_enter("NMI received: entering kmdb\n"); - } else if (xen_psm_panic_on_nmi) { - /* Keep panic from entering kmdb. */ - nopanicdebug = 1; - panic("NMI received\n"); - } else { - /* - * prom_printf is the best shot we have of something which is - * problem free from high level/NMI type of interrupts - */ - prom_printf("NMI received\n"); - } - - lock_clear(&xen_psm_nmi_lock); -} - -static void -xen_psm_picinit() -{ - int cpu, irqno; - cpuset_t cpus; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - /* set a flag so we know we have run xen_psm_picinit() */ - apic_picinit_called = 1; - LOCK_INIT_CLEAR(&apic_ioapic_lock); - - /* XXPV - do we need to do this? */ - picsetup(); /* initialise the 8259 */ - - /* enable apic mode if imcr present */ - /* XXPV - do we need to do this either? */ - if (apic_imcrp) { - outb(APIC_IMCR_P1, (uchar_t)APIC_IMCR_SELECT); - outb(APIC_IMCR_P2, (uchar_t)APIC_IMCR_APIC); - } - - ioapic_init_intr(IOAPIC_NOMASK); - /* - * We never called xen_psm_addspl() when the SCI - * interrupt was added because that happened before the - * PSM module was loaded. Fix that up here by doing - * any missed operations (e.g. bind to CPU) - */ - if ((irqno = apic_sci_vect) > 0) { - if ((cpu = xen_psm_bind_intr(irqno)) == IRQ_UNBOUND) { - CPUSET_ZERO(cpus); - CPUSET_OR(cpus, xen_psm_cpus_online); - } else { - CPUSET_ONLY(cpus, cpu & ~IRQ_USER_BOUND); - } - ec_set_irq_affinity(irqno, cpus); - apic_irq_table[irqno]->airq_temp_cpu = - (uchar_t)(cpu & ~IRQ_USER_BOUND); - ec_enable_irq(irqno); - } - } - - /* add nmi handler - least priority nmi handler */ - LOCK_INIT_CLEAR(&xen_psm_nmi_lock); - - if (!psm_add_nmintr(0, (avfunc) xen_psm_nmi_intr, - "xVM_psm NMI handler", NULL)) - cmn_err(CE_WARN, "xVM_psm: Unable to add nmi handler"); -} - - -/* - * generates an interprocessor interrupt to another CPU - */ -static void -xen_psm_send_ipi(int cpun, int ipl) -{ - ulong_t flag = intr_clear(); - - ec_send_ipi(ipl, cpun); - intr_restore(flag); -} - -/*ARGSUSED*/ -static int -xen_psm_addspl(int irqno, int ipl, int min_ipl, int max_ipl) -{ - int cpu, ret; - cpuset_t cpus; - - /* - * We are called at splhi() so we can't call anything that might end - * up trying to context switch. - */ - if (irqno >= PIRQ_BASE && irqno < NR_PIRQS && - DOMAIN_IS_INITDOMAIN(xen_info)) { - /* - * Priority/affinity/enable for PIRQ's is set in ec_setup_pirq() - */ - ret = apic_addspl_common(irqno, ipl, min_ipl, max_ipl); - } else { - /* - * Set priority/affinity/enable for non PIRQs - */ - ret = ec_set_irq_priority(irqno, ipl); - ASSERT(ret == 0); - if ((cpu = xen_psm_bind_intr(irqno)) == IRQ_UNBOUND) { - CPUSET_ZERO(cpus); - CPUSET_OR(cpus, xen_psm_cpus_online); - } else { - CPUSET_ONLY(cpus, cpu & ~IRQ_USER_BOUND); - } - ec_set_irq_affinity(irqno, cpus); - ec_enable_irq(irqno); - } - return (ret); -} - -/* - * Acquire ownership of this irq on this cpu - */ -void -xen_psm_acquire_irq(int irq) -{ - ulong_t flags; - int cpuid; - - /* - * If the irq is currently being serviced by another cpu - * we busy-wait for the other cpu to finish. Take any - * pending interrupts before retrying. - */ - do { - flags = intr_clear(); - cpuid = ec_block_irq(irq); - intr_restore(flags); - } while (cpuid != CPU->cpu_id); -} - -/*ARGSUSED*/ -static int -xen_psm_delspl(int irqno, int ipl, int min_ipl, int max_ipl) -{ - apic_irq_t *irqptr; - int err = PSM_SUCCESS; - - if (irqno >= PIRQ_BASE && irqno < NR_PIRQS && - DOMAIN_IS_INITDOMAIN(xen_info)) { - irqptr = apic_irq_table[irqno]; - /* - * unbind if no more sharers of this irq/evtchn - */ - if (irqptr->airq_share == 1) { - xen_psm_acquire_irq(irqno); - ec_unbind_irq(irqno); - } - err = apic_delspl_common(irqno, ipl, min_ipl, max_ipl); - /* - * If still in use reset priority - */ - if (!err && irqptr->airq_share != 0) { - err = ec_set_irq_priority(irqno, max_ipl); - return (err); - } - } else { - xen_psm_acquire_irq(irqno); - ec_unbind_irq(irqno); - } - return (err); -} - -static processorid_t -xen_psm_get_next_processorid(processorid_t id) -{ - if (id == -1) - return (0); - - for (id++; id < NCPU; id++) { - switch (-HYPERVISOR_vcpu_op(VCPUOP_is_up, id, NULL)) { - case 0: /* yeah, that one's there */ - return (id); - default: - case X_EINVAL: /* out of range */ - return (-1); - case X_ENOENT: /* not present in the domain */ - /* - * It's not clear that we -need- to keep looking - * at this point, if, e.g., we can guarantee - * the hypervisor always keeps a contiguous range - * of vcpus around this is equivalent to "out of range". - * - * But it would be sad to miss a vcpu we're - * supposed to be using .. - */ - break; - } - } - - return (-1); -} - -/* - * XXPV - undo the start cpu op change; return to ignoring this value - * - also tweak error handling in main startup loop - */ -/*ARGSUSED*/ -static int -xen_psm_cpu_start(processorid_t id, caddr_t arg) -{ - int ret; - - ASSERT(id > 0); - CPUSET_ATOMIC_ADD(xen_psm_cpus_online, id); - ec_bind_cpu_ipis(id); - (void) ec_bind_virq_to_irq(VIRQ_TIMER, id); - if ((ret = xen_vcpu_up(id)) == 0) - xen_psm_ncpus++; - else - ret = EINVAL; - return (ret); -} - -/* - * Allocate an irq for inter cpu signaling - */ -/*ARGSUSED*/ -static int -xen_psm_get_ipivect(int ipl, int type) -{ - return (ec_bind_ipi_to_irq(ipl, 0)); -} - -/*ARGSUSED*/ -static int -xen_psm_get_clockirq(int ipl) -{ - if (xen_clock_irq != INVALID_IRQ) - return (xen_clock_irq); - - xen_clock_irq = ec_bind_virq_to_irq(VIRQ_TIMER, 0); - return (xen_clock_irq); -} - -/*ARGSUSED*/ -static void -xen_psm_shutdown(int cmd, int fcn) -{ - XEN_PSM_VERBOSE_POWEROFF(("xen_psm_shutdown(%d,%d);\n", cmd, fcn)); - - switch (cmd) { - case A_SHUTDOWN: - switch (fcn) { - case AD_BOOT: - case AD_IBOOT: - (void) HYPERVISOR_shutdown(SHUTDOWN_reboot); - break; - case AD_POWEROFF: - /* fall through if domU or if poweroff fails */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - if (apic_enable_acpi) - (void) acpi_poweroff(); - /* FALLTHRU */ - case AD_HALT: - default: - (void) HYPERVISOR_shutdown(SHUTDOWN_poweroff); - break; - } - break; - case A_REBOOT: - (void) HYPERVISOR_shutdown(SHUTDOWN_reboot); - break; - default: - return; - } -} - - -static int -xen_psm_translate_irq(dev_info_t *dip, int irqno) -{ - if (dip == NULL) { - XEN_PSM_VERBOSE_IRQ((CE_CONT, "!xen_psm: irqno = %d" - " dip = NULL\n", irqno)); - return (irqno); - } - return (irqno); -} - -/* - * xen_psm_intr_enter() acks the event that triggered the interrupt and - * returns the new priority level, - */ -/*ARGSUSED*/ -static int -xen_psm_intr_enter(int ipl, int *vector) -{ - int newipl; - uint_t intno; - cpu_t *cpu = CPU; - - intno = (*vector); - - ASSERT(intno < NR_IRQS); - ASSERT(cpu->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask != 0); - - if (!ec_is_edge_pirq(intno)) - ec_clear_irq(intno); - - newipl = autovect[intno].avh_hi_pri; - if (newipl == 0) { - /* - * (newipl == 0) means we have no service routines for this - * vector. We will treat this as a spurious interrupt. - * We have cleared the pending bit already, clear the event - * mask and return a spurious interrupt. This case can happen - * when an interrupt delivery is racing with the removal of - * of the service routine for that interrupt. - */ - ec_unmask_irq(intno); - newipl = -1; /* flag spurious interrupt */ - } else if (newipl <= cpu->cpu_pri) { - /* - * (newipl <= cpu->cpu_pri) means that we must be trying to - * service a vector that was shared with a higher priority - * isr. The higher priority handler has been removed and - * we need to service this int. We can't return a lower - * priority than current cpu priority. Just synthesize a - * priority to return that should be acceptable. - * It should never happen that we synthesize a priority that - * moves us from low-priority to high-priority that would make - * a us incorrectly run on the high priority stack. - */ - newipl = cpu->cpu_pri + 1; /* synthetic priority */ - ASSERT(newipl != LOCK_LEVEL + 1); - } - return (newipl); -} - - -/* - * xen_psm_intr_exit() restores the old interrupt - * priority level after processing an interrupt. - * It is called with interrupts disabled, and does not enable interrupts. - */ -/* ARGSUSED */ -static void -xen_psm_intr_exit(int ipl, int vector) -{ - ec_try_unmask_irq(vector); - xen_psm_setspl(ipl); -} - -intr_exit_fn_t -psm_intr_exit_fn(void) -{ - return (xen_psm_intr_exit); -} - -/* - * Check if new ipl level allows delivery of previously unserviced events - */ -static void -xen_psm_setspl(int ipl) -{ - struct cpu *cpu = CPU; - volatile vcpu_info_t *vci = cpu->cpu_m.mcpu_vcpu_info; - uint16_t pending; - - ASSERT(vci->evtchn_upcall_mask != 0); - - /* - * If new ipl level will enable any pending interrupts, setup so the - * upcoming sti will cause us to get an upcall. - */ - pending = cpu->cpu_m.mcpu_intr_pending & ~((1 << (ipl + 1)) - 1); - if (pending) { - int i; - ulong_t pending_sels = 0; - volatile ulong_t *selp; - struct xen_evt_data *cpe = cpu->cpu_m.mcpu_evt_pend; - - for (i = bsrw_insn(pending); i > ipl; i--) - pending_sels |= cpe->pending_sel[i]; - ASSERT(pending_sels); - selp = (volatile ulong_t *)&vci->evtchn_pending_sel; - atomic_or_ulong(selp, pending_sels); - vci->evtchn_upcall_pending = 1; - } -} - -/* - * This function provides external interface to the nexus for all - * functionality related to the new DDI interrupt framework. - * - * Input: - * dip - pointer to the dev_info structure of the requested device - * hdlp - pointer to the internal interrupt handle structure for the - * requested interrupt - * intr_op - opcode for this call - * result - pointer to the integer that will hold the result to be - * passed back if return value is PSM_SUCCESS - * - * Output: - * return value is either PSM_SUCCESS or PSM_FAILURE - */ -int -xen_intr_ops(dev_info_t *dip, ddi_intr_handle_impl_t *hdlp, - psm_intr_op_t intr_op, int *result) -{ - int cap; - int err; - int new_priority; - apic_irq_t *irqp; - struct intrspec *ispec; - - DDI_INTR_IMPLDBG((CE_CONT, "xen_intr_ops: dip: %p hdlp: %p " - "intr_op: %x\n", (void *)dip, (void *)hdlp, intr_op)); - - switch (intr_op) { - case PSM_INTR_OP_CHECK_MSI: - /* - * Till PCI passthru is supported, only dom0 has MSI/MSIX - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - *result = hdlp->ih_type & ~(DDI_INTR_TYPE_MSI | - DDI_INTR_TYPE_MSIX); - break; - } - /* - * Check MSI/X is supported or not at APIC level and - * masked off the MSI/X bits in hdlp->ih_type if not - * supported before return. If MSI/X is supported, - * leave the ih_type unchanged and return. - * - * hdlp->ih_type passed in from the nexus has all the - * interrupt types supported by the device. - */ - if (xen_support_msi == 0) { - /* - * if xen_support_msi is not set, call - * apic_check_msi_support() to check whether msi - * is supported first - */ - if (apic_check_msi_support() == PSM_SUCCESS) - xen_support_msi = 1; - else - xen_support_msi = -1; - } - if (xen_support_msi == 1) - *result = hdlp->ih_type; - else - *result = hdlp->ih_type & ~(DDI_INTR_TYPE_MSI | - DDI_INTR_TYPE_MSIX); - break; - case PSM_INTR_OP_ALLOC_VECTORS: - if (hdlp->ih_type == DDI_INTR_TYPE_MSI) - *result = apic_alloc_msi_vectors(dip, hdlp->ih_inum, - hdlp->ih_scratch1, hdlp->ih_pri, - (int)(uintptr_t)hdlp->ih_scratch2); - else - *result = apic_alloc_msix_vectors(dip, hdlp->ih_inum, - hdlp->ih_scratch1, hdlp->ih_pri, - (int)(uintptr_t)hdlp->ih_scratch2); - break; - case PSM_INTR_OP_FREE_VECTORS: - apic_free_vectors(dip, hdlp->ih_inum, hdlp->ih_scratch1, - hdlp->ih_pri, hdlp->ih_type); - break; - case PSM_INTR_OP_NAVAIL_VECTORS: - /* - * XXPV - maybe we should make this be: - * min(APIC_VECTOR_PER_IPL, count of all avail vectors); - */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - *result = APIC_VECTOR_PER_IPL; - else - *result = 1; - break; - case PSM_INTR_OP_XLATE_VECTOR: - ispec = ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp; - if (ispec->intrspec_vec >= PIRQ_BASE && - ispec->intrspec_vec < NR_PIRQS && - DOMAIN_IS_INITDOMAIN(xen_info)) { - *result = apic_introp_xlate(dip, ispec, hdlp->ih_type); - } else { - *result = ispec->intrspec_vec; - } - break; - case PSM_INTR_OP_GET_PENDING: - /* XXPV - is this enough for dom0 or do we need to ref ioapic */ - *result = ec_pending_irq(hdlp->ih_vector); - break; - case PSM_INTR_OP_CLEAR_MASK: - /* XXPV - is this enough for dom0 or do we need to set ioapic */ - if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) - return (PSM_FAILURE); - ec_enable_irq(hdlp->ih_vector); - break; - case PSM_INTR_OP_SET_MASK: - /* XXPV - is this enough for dom0 or do we need to set ioapic */ - if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) - return (PSM_FAILURE); - ec_disable_irq(hdlp->ih_vector); - break; - case PSM_INTR_OP_GET_CAP: - cap = DDI_INTR_FLAG_PENDING | DDI_INTR_FLAG_EDGE; - if (hdlp->ih_type == DDI_INTR_TYPE_FIXED) - cap |= DDI_INTR_FLAG_MASKABLE; - *result = cap; - break; - case PSM_INTR_OP_GET_SHARED: - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) - return (PSM_FAILURE); - ispec = ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp; - if ((irqp = apic_find_irq(dip, ispec, hdlp->ih_type)) - == NULL) - return (PSM_FAILURE); - *result = (irqp->airq_share > 1) ? 1: 0; - } else { - return (PSM_FAILURE); - } - break; - case PSM_INTR_OP_SET_PRI: - new_priority = *(int *)result; - err = ec_set_irq_priority(hdlp->ih_vector, new_priority); - if (err != 0) - return (PSM_FAILURE); - break; - case PSM_INTR_OP_GET_INTR: - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return (PSM_FAILURE); - /* - * The interrupt handle given here has been allocated - * specifically for this command, and ih_private carries - * a pointer to a apic_get_intr_t. - */ - if (apic_get_vector_intr_info( - hdlp->ih_vector, hdlp->ih_private) != PSM_SUCCESS) - return (PSM_FAILURE); - break; - case PSM_INTR_OP_SET_CAP: - /* FALLTHRU */ - default: - return (PSM_FAILURE); - } - return (PSM_SUCCESS); -} - -static void -xen_psm_rebind_irq(int irq) -{ - cpuset_t ncpu; - processorid_t newcpu; - apic_irq_t *irqptr; - - newcpu = xen_psm_bind_intr(irq); - if (newcpu == IRQ_UNBOUND) { - CPUSET_ZERO(ncpu); - CPUSET_OR(ncpu, xen_psm_cpus_online); - } else { - CPUSET_ONLY(ncpu, newcpu & ~IRQ_USER_BOUND); - } - ec_set_irq_affinity(irq, ncpu); - if (irq <= APIC_MAX_VECTOR) { - irqptr = apic_irq_table[irq]; - ASSERT(irqptr != NULL); - irqptr->airq_temp_cpu = (uchar_t)newcpu; - } -} - -/* - * Disable all device interrupts for the given cpu. - * High priority interrupts are not disabled and will still be serviced. - */ -static int -xen_psm_disable_intr(processorid_t cpun) -{ - int irq; - - /* - * Can't offline VCPU 0 on this hypervisor. There's no reason - * anyone would want to given that the CPUs are virtual. Also note - * that the hypervisor requires suspend/resume to be on VCPU 0. - */ - if (cpun == 0) - return (PSM_FAILURE); - - CPUSET_ATOMIC_DEL(xen_psm_cpus_online, cpun); - for (irq = 0; irq < NR_IRQS; irq++) { - if (!ec_irq_needs_rebind(irq, cpun)) - continue; - xen_psm_rebind_irq(irq); - } - return (PSM_SUCCESS); -} - -static void -xen_psm_enable_intr(processorid_t cpun) -{ - int irq; - - if (cpun == 0) - return; - - CPUSET_ATOMIC_ADD(xen_psm_cpus_online, cpun); - - /* - * Rebalance device interrupts among online processors - */ - for (irq = 0; irq < NR_IRQS; irq++) { - if (!ec_irq_rebindable(irq)) - continue; - xen_psm_rebind_irq(irq); - } - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - apic_cpus[cpun].aci_status |= APIC_CPU_INTR_ENABLE; - } -} - -static int -xen_psm_post_cpu_start() -{ - processorid_t cpun; - - cpun = psm_get_cpu_id(); - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - /* - * Non-virtualized environments can call psm_post_cpu_start - * from Suspend/Resume with the APIC_CPU_INTR_ENABLE bit set. - * xen_psm_post_cpu_start() is only called from boot. - */ - apic_cpus[cpun].aci_status |= APIC_CPU_ONLINE; - } - return (PSM_SUCCESS); -} - -/* - * This function will reprogram the timer. - * - * When in oneshot mode the argument is the absolute time in future at which to - * generate the interrupt. - * - * When in periodic mode, the argument is the interval at which the - * interrupts should be generated. There is no need to support the periodic - * mode timer change at this time. - * - * Note that we must be careful to convert from hrtime to Xen system time (see - * xpv_timestamp.c). - */ -static void -xen_psm_timer_reprogram(hrtime_t timer_req) -{ - hrtime_t now, timer_new, time_delta, xen_time; - ulong_t flags; - - flags = intr_clear(); - /* - * We should be called from high PIL context (CBE_HIGH_PIL), - * so kpreempt is disabled. - */ - - now = xpv_gethrtime(); - xen_time = xpv_getsystime(); - if (timer_req <= now) { - /* - * requested to generate an interrupt in the past - * generate an interrupt as soon as possible - */ - time_delta = XEN_NSEC_PER_TICK; - } else - time_delta = timer_req - now; - - timer_new = xen_time + time_delta; - if (HYPERVISOR_set_timer_op(timer_new) != 0) - panic("can't set hypervisor timer?"); - intr_restore(flags); -} - -/* - * This function will enable timer interrupts. - */ -static void -xen_psm_timer_enable(void) -{ - ec_unmask_irq(xen_clock_irq); -} - -/* - * This function will disable timer interrupts on the current cpu. - */ -static void -xen_psm_timer_disable(void) -{ - (void) ec_block_irq(xen_clock_irq); - /* - * If the clock irq is pending on this cpu then we need to - * clear the pending interrupt. - */ - ec_unpend_irq(xen_clock_irq); -} - -/* - * - * The following functions are in the platform specific file so that they - * can be different functions depending on whether we are running on - * bare metal or a hypervisor. - */ - -/* - * Allocate a free vector for irq at ipl. - */ -/* ARGSUSED */ -uchar_t -apic_allocate_vector(int ipl, int irq, int pri) -{ - physdev_irq_t irq_op; - uchar_t vector; - int rc; - - irq_op.irq = irq; - - if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) - != 0) - panic("Hypervisor alloc vector failed err: %d", -rc); - vector = irq_op.vector; - /* - * No need to worry about vector colliding with our reserved vectors - * e.g. T_FASTTRAP, xen can differentiate between hardware and software - * generated traps and handle them properly. - */ - apic_vector_to_irq[vector] = (uchar_t)irq; - return (vector); -} - -/* Mark vector as not being used by any irq */ -void -apic_free_vector(uchar_t vector) -{ - apic_vector_to_irq[vector] = APIC_RESV_IRQ; -} - -/* - * This function returns the no. of vectors available for the pri. - * dip is not used at this moment. If we really don't need that, - * it will be removed. Since priority is not limited by hardware - * when running on the hypervisor we simply return the maximum no. - * of available contiguous vectors. - */ -/*ARGSUSED*/ -int -apic_navail_vector(dev_info_t *dip, int pri) -{ - int lowest, highest, i, navail, count; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_navail_vector: dip: %p, pri: %x\n", - (void *)dip, pri)); - - highest = APIC_MAX_VECTOR; - lowest = APIC_BASE_VECT; - navail = count = 0; - - /* It has to be contiguous */ - for (i = lowest; i < highest; i++) { - count = 0; - while ((apic_vector_to_irq[i] == APIC_RESV_IRQ) && - (i < highest)) { - count++; - i++; - } - if (count > navail) - navail = count; - } - return (navail); -} - -static physdev_manage_pci_t *managed_devlist; -static int mdev_cnt; -static int mdev_size = 128; -static uchar_t msi_vector_to_pirq[APIC_MAX_VECTOR+1]; - -/* - * Add devfn on given bus to devices managed by hypervisor - */ -static int -xen_manage_device(uint8_t bus, uint8_t devfn) -{ - physdev_manage_pci_t manage_pci, *newlist; - int rc, i, oldsize; - - /* - * Check if bus/devfn already managed. If so just return success. - */ - if (managed_devlist == NULL) { - managed_devlist = kmem_alloc(sizeof (physdev_manage_pci_t) * - mdev_size, KM_NOSLEEP); - if (managed_devlist == NULL) { - cmn_err(CE_WARN, - "Can't alloc space for managed device list"); - return (0); - } - }; - for (i = 0; i < mdev_cnt; i++) { - if (managed_devlist[i].bus == bus && - managed_devlist[i].devfn == devfn) - return (1); /* device already managed */ - } - manage_pci.bus = bus; - manage_pci.devfn = devfn; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add, &manage_pci); - if (rc < 0) { - cmn_err(CE_WARN, - "hypervisor add pci device call failed bus:0x%x" - " devfn:0x%x", bus, devfn); - return (0); - } - /* - * Add device to the managed device list - */ - if (i == mdev_size) { - /* - * grow the managed device list - */ - oldsize = mdev_size * sizeof (physdev_manage_pci_t); - mdev_size *= 2; - newlist = kmem_alloc(sizeof (physdev_manage_pci_t) * mdev_size, - KM_NOSLEEP); - if (newlist == NULL) { - cmn_err(CE_WARN, "Can't grow managed device list"); - return (0); - } - bcopy(managed_devlist, newlist, oldsize); - kmem_free(managed_devlist, oldsize); - managed_devlist = newlist; - } - managed_devlist[i].bus = bus; - managed_devlist[i].devfn = devfn; - mdev_cnt++; - return (1); -} - -/* - * allocate an apic irq struct for an MSI interrupt - */ -static int -msi_allocate_irq(int irq) -{ - apic_irq_t *irqptr = apic_irq_table[irq]; - - if (irqptr == NULL) { - irqptr = kmem_zalloc(sizeof (apic_irq_t), KM_NOSLEEP); - if (irqptr == NULL) { - cmn_err(CE_WARN, "xpv_psm: NO memory to allocate IRQ"); - return (-1); - } - apic_irq_table[irq] = irqptr; - } else { - if (irq == APIC_RESV_IRQ && irqptr->airq_mps_intr_index == 0) - irqptr->airq_mps_intr_index = FREE_INDEX; - if (irqptr->airq_mps_intr_index != FREE_INDEX) { - cmn_err(CE_WARN, "xpv_psm: MSI IRQ already in use"); - return (-1); - } - } - irqptr->airq_mps_intr_index = FREE_INDEX; - return (irq); -} - -/* - * read MSI/MSIX vector out of config space - */ -static uchar_t -xpv_psm_get_msi_vector(dev_info_t *dip, int type, int entry) -{ - uint64_t msi_data = 0; - int cap_ptr = i_ddi_get_msi_msix_cap_ptr(dip); - ddi_acc_handle_t handle = i_ddi_get_pci_config_handle(dip); - ushort_t msi_ctrl; - uchar_t vector; - - ASSERT((handle != NULL) && (cap_ptr != 0)); - if (type == DDI_INTR_TYPE_MSI) { - msi_ctrl = pci_config_get16(handle, cap_ptr + PCI_MSI_CTRL); - /* - * Get vector - */ - if (msi_ctrl & PCI_MSI_64BIT_MASK) { - msi_data = pci_config_get16(handle, - cap_ptr + PCI_MSI_64BIT_DATA); - } else { - msi_data = pci_config_get16(handle, - cap_ptr + PCI_MSI_32BIT_DATA); - } - vector = (msi_data & 0xff) + entry; - } else if (type == DDI_INTR_TYPE_MSIX) { - uintptr_t off; - ddi_intr_msix_t *msix_p = i_ddi_get_msix(dip); - - /* Offset into the given entry in the MSI-X table */ - off = (uintptr_t)msix_p->msix_tbl_addr + - (entry * PCI_MSIX_VECTOR_SIZE); - - msi_data = ddi_get32(msix_p->msix_tbl_hdl, - (uint32_t *)(off + PCI_MSIX_DATA_OFFSET)); - vector = msi_data & 0xff; - } - return (vector); -} - - -static void -get_busdevfn(dev_info_t *dip, int *busp, int *devfnp) -{ - pci_regspec_t *regspec; - int reglen; - - /* - * Get device reg spec, first word has PCI bus and - * device/function info we need. - */ - if (ddi_getlongprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, "reg", - (caddr_t)®spec, ®len) != DDI_SUCCESS) { - cmn_err(CE_WARN, - "get_busdevfn() failed to get regspec."); - return; - } - /* - * get PCI bus # from reg spec for device - */ - *busp = PCI_REG_BUS_G(regspec[0].pci_phys_hi); - /* - * get combined device/function from reg spec for device. - */ - *devfnp = (regspec[0].pci_phys_hi & (PCI_REG_FUNC_M | PCI_REG_DEV_M)) >> - PCI_REG_FUNC_SHIFT; - - kmem_free(regspec, reglen); -} - -/* - * This function allocates "count" MSI vector(s) for the given "dip/pri/type" - */ -int -apic_alloc_msi_vectors(dev_info_t *dip, int inum, int count, int pri, - int behavior) -{ - int rcount, i, rc, irqno; - uchar_t vector, cpu; - major_t major; - apic_irq_t *irqptr; - physdev_map_pirq_t map_irq; - int busnum, devfn; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_msi_vectors: dip=0x%p " - "inum=0x%x pri=0x%x count=0x%x behavior=%d\n", - (void *)dip, inum, pri, count, behavior)); - - if (count > 1) { - if (behavior == DDI_INTR_ALLOC_STRICT && - apic_multi_msi_enable == 0) - return (0); - if (apic_multi_msi_enable == 0) - count = 1; - } - - if ((rcount = apic_navail_vector(dip, pri)) > count) - rcount = count; - else if (rcount == 0 || (rcount < count && - behavior == DDI_INTR_ALLOC_STRICT)) - return (0); - - /* if not ISP2, then round it down */ - if (!ISP2(rcount)) - rcount = 1 << (highbit(rcount) - 1); - - /* - * get PCI bus # and devfn from reg spec for device - */ - get_busdevfn(dip, &busnum, &devfn); - - /* - * Tell xen about this pci device - */ - if (!xen_manage_device(busnum, devfn)) - return (0); - - mutex_enter(&airq_mutex); - - major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; - for (i = 0; i < rcount; i++) { - /* - * use PHYSDEVOP_map_pirq to have xen map MSI to a pirq - */ - map_irq.domid = DOMID_SELF; - map_irq.type = MAP_PIRQ_TYPE_MSI; - map_irq.index = -rcount; /* hypervisor auto allocates vectors */ - map_irq.pirq = -1; - map_irq.bus = busnum; - map_irq.devfn = devfn; - map_irq.entry_nr = i; - map_irq.table_base = 0; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); - irqno = map_irq.pirq; - if (rc < 0) { - mutex_exit(&airq_mutex); - cmn_err(CE_WARN, "map MSI irq failed err: %d", -rc); - return (i); - } - if (irqno < 0) { - mutex_exit(&airq_mutex); - cmn_err(CE_NOTE, - "!hypervisor not configured for MSI support"); - xen_support_msi = -1; - return (0); - } - - /* - * Find out what vector the hypervisor assigned - */ - vector = xpv_psm_get_msi_vector(dip, DDI_INTR_TYPE_MSI, i); - - if (msi_allocate_irq(irqno) < 0) { - mutex_exit(&airq_mutex); - return (i); - } - apic_max_device_irq = max(irqno, apic_max_device_irq); - apic_min_device_irq = min(irqno, apic_min_device_irq); - irqptr = apic_irq_table[irqno]; - ASSERT(irqptr != NULL); -#ifdef DEBUG - if (apic_vector_to_irq[vector] != APIC_RESV_IRQ) - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_msi_vectors: " - "apic_vector_to_irq is not APIC_RESV_IRQ\n")); -#endif - apic_vector_to_irq[vector] = (uchar_t)irqno; - msi_vector_to_pirq[vector] = (uchar_t)irqno; - - irqptr->airq_vector = vector; - irqptr->airq_ioapicindex = (uchar_t)inum; /* start */ - irqptr->airq_intin_no = (uchar_t)rcount; - irqptr->airq_ipl = pri; - irqptr->airq_origirq = (uchar_t)(inum + i); - irqptr->airq_share_id = 0; - irqptr->airq_mps_intr_index = MSI_INDEX; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - if (i == 0) /* they all bind to the same cpu */ - cpu = irqptr->airq_cpu = xen_psm_bind_intr(irqno); - else - irqptr->airq_cpu = cpu; - DDI_INTR_IMPLDBG((CE_CONT, "apic_alloc_msi_vectors: irq=0x%x " - "dip=0x%p vector=0x%x origirq=0x%x pri=0x%x\n", irqno, - (void *)irqptr->airq_dip, irqptr->airq_vector, - irqptr->airq_origirq, pri)); - } - mutex_exit(&airq_mutex); - return (rcount); -} - -/* - * This function allocates "count" MSI-X vector(s) for the given "dip/pri/type" - */ -int -apic_alloc_msix_vectors(dev_info_t *dip, int inum, int count, int pri, - int behavior) -{ - int rcount, i, rc; - major_t major; - physdev_map_pirq_t map_irq; - int busnum, devfn; - ddi_intr_msix_t *msix_p = i_ddi_get_msix(dip); - uint64_t table_base; - pfn_t pfnum; - - if (msix_p == NULL) { - msix_p = pci_msix_init(dip); - if (msix_p != NULL) { - i_ddi_set_msix(dip, msix_p); - } else { - cmn_err(CE_WARN, "apic_alloc_msix_vectors()" - " msix_init failed"); - return (0); - } - } - /* - * Hypervisor wants PCI config space address of msix table base - */ - pfnum = hat_getpfnum(kas.a_hat, (caddr_t)msix_p->msix_tbl_addr) & - ~PFN_IS_FOREIGN_MFN; - table_base = (uint64_t)((pfnum << PAGESHIFT) - msix_p->msix_tbl_offset | - ((uintptr_t)msix_p->msix_tbl_addr & PAGEOFFSET)); - /* - * get PCI bus # and devfn from reg spec for device - */ - get_busdevfn(dip, &busnum, &devfn); - - /* - * Tell xen about this pci device - */ - if (!xen_manage_device(busnum, devfn)) - return (0); - mutex_enter(&airq_mutex); - - if ((rcount = apic_navail_vector(dip, pri)) > count) - rcount = count; - else if (rcount == 0 || (rcount < count && - behavior == DDI_INTR_ALLOC_STRICT)) { - rcount = 0; - goto out; - } - - major = (dip != NULL) ? ddi_name_to_major(ddi_get_name(dip)) : 0; - for (i = 0; i < rcount; i++) { - int irqno; - uchar_t vector; - apic_irq_t *irqptr; - - /* - * use PHYSDEVOP_map_pirq to have xen map MSI-X to a pirq - */ - map_irq.domid = DOMID_SELF; - map_irq.type = MAP_PIRQ_TYPE_MSI; - map_irq.index = -1; /* hypervisor auto allocates vector */ - map_irq.pirq = -1; - map_irq.bus = busnum; - map_irq.devfn = devfn; - map_irq.entry_nr = i; - map_irq.table_base = table_base; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); - irqno = map_irq.pirq; - if (rc < 0) { - mutex_exit(&airq_mutex); - cmn_err(CE_WARN, "map MSI irq failed err: %d", -rc); - return (i); - } - if (irqno < 0) { - mutex_exit(&airq_mutex); - cmn_err(CE_NOTE, - "!hypervisor not configured for MSI support"); - xen_support_msi = -1; - return (0); - } - /* - * Find out what vector the hypervisor assigned - */ - vector = xpv_psm_get_msi_vector(dip, DDI_INTR_TYPE_MSIX, i); - - if (msi_allocate_irq(irqno) < 0) { - mutex_exit(&airq_mutex); - return (i); - } - apic_vector_to_irq[vector] = (uchar_t)irqno; - msi_vector_to_pirq[vector] = (uchar_t)irqno; - apic_max_device_irq = max(irqno, apic_max_device_irq); - apic_min_device_irq = min(irqno, apic_min_device_irq); - irqptr = apic_irq_table[irqno]; - ASSERT(irqptr != NULL); - irqptr->airq_vector = (uchar_t)vector; - irqptr->airq_ipl = pri; - irqptr->airq_origirq = (uchar_t)(inum + i); - irqptr->airq_share_id = 0; - irqptr->airq_mps_intr_index = MSIX_INDEX; - irqptr->airq_dip = dip; - irqptr->airq_major = major; - irqptr->airq_cpu = IRQ_UNBOUND; /* will be bound when addspl */ - } -out: - mutex_exit(&airq_mutex); - return (rcount); -} - - -/* - * This finds the apic_irq_t associated with the dip, ispec and type. - * The entry should have already been freed, but it can not have been - * reused yet since the hypervisor can not have reassigned the pirq since - * we have not freed that yet. - */ -static apic_irq_t * -msi_find_irq(dev_info_t *dip, struct intrspec *ispec) -{ - apic_irq_t *irqp; - int i; - - for (i = apic_min_device_irq; i <= apic_max_device_irq; i++) { - if ((irqp = apic_irq_table[i]) == NULL) - continue; - if ((irqp->airq_dip == dip) && - (irqp->airq_origirq == ispec->intrspec_vec) && - (irqp->airq_ipl == ispec->intrspec_pri)) { - return (irqp); - } - } - return (NULL); -} - -void -apic_free_vectors(dev_info_t *dip, int inum, int count, int pri, int type) -{ - int i, rc; - physdev_unmap_pirq_t unmap_pirq; - apic_irq_t *irqptr; - struct intrspec ispec; - - DDI_INTR_IMPLDBG((CE_CONT, "apic_free_vectors: dip: %p inum: %x " - "count: %x pri: %x type: %x\n", - (void *)dip, inum, count, pri, type)); - - /* for MSI/X only */ - if (!DDI_INTR_IS_MSI_OR_MSIX(type)) - return; - - for (i = 0; i < count; i++) { - DDI_INTR_IMPLDBG((CE_CONT, "apic_free_vectors: inum=0x%x " - "pri=0x%x count=0x%x\n", inum, pri, count)); - ispec.intrspec_vec = inum + i; - ispec.intrspec_pri = pri; - if ((irqptr = msi_find_irq(dip, &ispec)) == NULL) { - cmn_err(CE_WARN, - "couldn't find irq %s,%s dip: 0x%p vec: %x pri: %x", - ddi_get_name(dip), ddi_get_name_addr(dip), - (void *)dip, inum + i, pri); - continue; - } - /* - * use PHYSDEVOP_unmap_pirq to have xen unmap MSI from a pirq - */ - unmap_pirq.domid = DOMID_SELF; - unmap_pirq.pirq = msi_vector_to_pirq[irqptr->airq_vector]; - rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_pirq); - if (rc < 0) { - cmn_err(CE_WARN, "unmap pirq failed"); - return; - } - irqptr->airq_mps_intr_index = FREE_INDEX; - apic_vector_to_irq[irqptr->airq_vector] = APIC_RESV_IRQ; - } -} - -/* - * The hypervisor doesn't permit access to local apics directly - */ -/* ARGSUSED */ -uint32_t * -mapin_apic(uint32_t addr, size_t len, int flags) -{ - /* - * Return a pointer to a memory area to fake out the - * probe code that wants to read apic registers. - * The dummy values will end up being ignored by xen - * later on when they are used anyway. - */ - xen_psm_dummy_apic[APIC_VERS_REG] = APIC_INTEGRATED_VERS; - return (xen_psm_dummy_apic); -} - -/* ARGSUSED */ -uint32_t * -mapin_ioapic(uint32_t addr, size_t len, int flags) -{ - /* - * Return non-null here to fake out configure code that calls this. - * The i86xpv platform will not reference through the returned value.. - */ - return ((uint32_t *)0x1); -} - -/* ARGSUSED */ -void -mapout_apic(caddr_t addr, size_t len) -{ -} - -/* ARGSUSED */ -void -mapout_ioapic(caddr_t addr, size_t len) -{ -} - -uint32_t -ioapic_read(int apic_ix, uint32_t reg) -{ - physdev_apic_t apic; - - apic.apic_physbase = (unsigned long)apic_physaddr[apic_ix]; - apic.reg = reg; - if (HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic)) - panic("read ioapic %d reg %d failed", apic_ix, reg); - return (apic.value); -} - -void -ioapic_write(int apic_ix, uint32_t reg, uint32_t value) -{ - physdev_apic_t apic; - - apic.apic_physbase = (unsigned long)apic_physaddr[apic_ix]; - apic.reg = reg; - apic.value = value; - if (HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic)) - panic("write ioapic %d reg %d failed", apic_ix, reg); -} - -/* - * This function was added as part of x2APIC support in pcplusmp. - */ -void -ioapic_write_eoi(int apic_ix, uint32_t value) -{ - physdev_apic_t apic; - - apic.apic_physbase = (unsigned long)apic_physaddr[apic_ix]; - apic.reg = APIC_IO_EOI; - apic.value = value; - if (HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic)) - panic("write ioapic reg : APIC_IO_EOI %d failed", apic_ix); -} - -/* - * This function was added as part of x2APIC support in pcplusmp to resolve - * undefined symbol in xpv_psm. - */ -void -x2apic_update_psm() -{ -} - -/* - * This function was added as part of x2APIC support in pcplusmp to resolve - * undefined symbol in xpv_psm. - */ -void -apic_ret() -{ -} - -/* - * Call rebind to do the actual programming. - */ -int -apic_setup_io_intr(void *p, int irq, boolean_t deferred) -{ - apic_irq_t *irqptr; - struct ioapic_reprogram_data *drep = NULL; - int rv, cpu; - cpuset_t cpus; - - if (deferred) { - drep = (struct ioapic_reprogram_data *)p; - ASSERT(drep != NULL); - irqptr = drep->irqp; - } else { - irqptr = (apic_irq_t *)p; - } - ASSERT(irqptr != NULL); - /* - * Set cpu based on xen idea of online cpu's not apic tables. - * Note that xen ignores/sets to it's own preferred value the - * target cpu field when programming ioapic anyway. - */ - if (irqptr->airq_mps_intr_index == MSI_INDEX) - cpu = irqptr->airq_cpu; /* MSI cpus are already set */ - else { - cpu = xen_psm_bind_intr(irq); - irqptr->airq_cpu = cpu; - } - if (cpu == IRQ_UNBOUND) { - CPUSET_ZERO(cpus); - CPUSET_OR(cpus, xen_psm_cpus_online); - } else { - CPUSET_ONLY(cpus, cpu & ~IRQ_USER_BOUND); - } - rv = apic_rebind(irqptr, cpu, drep); - if (rv) { - /* CPU is not up or interrupt is disabled. Fall back to 0 */ - cpu = 0; - irqptr->airq_cpu = cpu; - rv = apic_rebind(irqptr, cpu, drep); - } - /* - * If rebind successful bind the irq to an event channel - */ - if (rv == 0) { - ec_setup_pirq(irq, irqptr->airq_ipl, &cpus); - CPUSET_FIND(cpus, cpu); - apic_irq_table[irq]->airq_temp_cpu = cpu & ~IRQ_USER_BOUND; - } - return (rv); -} - -/* - * Allocate a new vector for the given irq - */ -/* ARGSUSED */ -uchar_t -apic_modify_vector(uchar_t vector, int irq) -{ - return (apic_allocate_vector(0, irq, 0)); -} - -/* - * The rest of the file is just generic psm module boilerplate - */ - -static struct psm_ops xen_psm_ops = { - xen_psm_probe, /* psm_probe */ - - xen_psm_softinit, /* psm_init */ - xen_psm_picinit, /* psm_picinit */ - xen_psm_intr_enter, /* psm_intr_enter */ - xen_psm_intr_exit, /* psm_intr_exit */ - xen_psm_setspl, /* psm_setspl */ - xen_psm_addspl, /* psm_addspl */ - xen_psm_delspl, /* psm_delspl */ - xen_psm_disable_intr, /* psm_disable_intr */ - xen_psm_enable_intr, /* psm_enable_intr */ - (int (*)(int))NULL, /* psm_softlvl_to_irq */ - (void (*)(int))NULL, /* psm_set_softintr */ - (void (*)(processorid_t))NULL, /* psm_set_idlecpu */ - (void (*)(processorid_t))NULL, /* psm_unset_idlecpu */ - - xen_psm_clkinit, /* psm_clkinit */ - xen_psm_get_clockirq, /* psm_get_clockirq */ - xen_psm_hrtimeinit, /* psm_hrtimeinit */ - xpv_gethrtime, /* psm_gethrtime */ - - xen_psm_get_next_processorid, /* psm_get_next_processorid */ - xen_psm_cpu_start, /* psm_cpu_start */ - xen_psm_post_cpu_start, /* psm_post_cpu_start */ - xen_psm_shutdown, /* psm_shutdown */ - xen_psm_get_ipivect, /* psm_get_ipivect */ - xen_psm_send_ipi, /* psm_send_ipi */ - - xen_psm_translate_irq, /* psm_translate_irq */ - - (void (*)(int, char *))NULL, /* psm_notify_error */ - (void (*)(int msg))NULL, /* psm_notify_func */ - xen_psm_timer_reprogram, /* psm_timer_reprogram */ - xen_psm_timer_enable, /* psm_timer_enable */ - xen_psm_timer_disable, /* psm_timer_disable */ - (void (*)(void *arg))NULL, /* psm_post_cyclic_setup */ - (void (*)(int, int))NULL, /* psm_preshutdown */ - xen_intr_ops, /* Advanced DDI Interrupt framework */ - (int (*)(psm_state_request_t *))NULL, /* psm_state */ - (int (*)(psm_cpu_request_t *))NULL /* psm_cpu_ops */ -}; - -static struct psm_info xen_psm_info = { - PSM_INFO_VER01_5, /* version */ - PSM_OWN_EXCLUSIVE, /* ownership */ - &xen_psm_ops, /* operation */ - "xVM_psm", /* machine name */ - "platform module" /* machine descriptions */ -}; - -static void *xen_psm_hdlp; - -int -_init(void) -{ - return (psm_mod_init(&xen_psm_hdlp, &xen_psm_info)); -} - -int -_fini(void) -{ - return (psm_mod_fini(&xen_psm_hdlp, &xen_psm_info)); -} - -int -_info(struct modinfo *modinfop) -{ - return (psm_mod_info(&xen_psm_hdlp, &xen_psm_info, modinfop)); -} diff --git a/usr/src/uts/i86xpv/io/psm/xpv_uppc.c b/usr/src/uts/i86xpv/io/psm/xpv_uppc.c deleted file mode 100644 index d50b7f504e..0000000000 --- a/usr/src/uts/i86xpv/io/psm/xpv_uppc.c +++ /dev/null @@ -1,924 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#define PSMI_1_7 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * Global Data - */ -int xen_uppc_use_acpi = 1; /* Use ACPI by default */ -int xen_uppc_enable_acpi = 0; - -static int xen_clock_irq = -1; - -/* - * For interrupt link devices, if xen_uppc_unconditional_srs is set, an irq - * resource will be assigned (via _SRS). If it is not set, use the current - * irq setting (via _CRS), but only if that irq is in the set of possible - * irqs (returned by _PRS) for the device. - */ -int xen_uppc_unconditional_srs = 1; - -/* - * For interrupt link devices, if xen_uppc_prefer_crs is set when we are - * assigning an IRQ resource to a device, prefer the current IRQ setting - * over other possible irq settings under same conditions. - */ -int xen_uppc_prefer_crs = 1; - -int xen_uppc_verbose = 0; - -/* flag definitions for xen_uppc_verbose */ -#define XEN_UPPC_VERBOSE_IRQ_FLAG 0x00000001 -#define XEN_UPPC_VERBOSE_POWEROFF_FLAG 0x00000002 -#define XEN_UPPC_VERBOSE_POWEROFF_PAUSE_FLAG 0x00000004 - -#define XEN_UPPC_VERBOSE_IRQ(fmt) \ - if (xen_uppc_verbose & XEN_UPPC_VERBOSE_IRQ_FLAG) \ - cmn_err fmt; - -#define XEN_UPPC_VERBOSE_POWEROFF(fmt) \ - if (xen_uppc_verbose & XEN_UPPC_VERBOSE_POWEROFF_FLAG) \ - prom_printf fmt; - -uchar_t xen_uppc_reserved_irqlist[MAX_ISA_IRQ + 1]; - -static uint16_t xen_uppc_irq_shared_table[MAX_ISA_IRQ + 1]; - -/* - * Contains SCI irqno from FADT after initialization - */ -static int xen_uppc_sci = -1; - -static struct psm_info xen_uppc_info; - -/* - * Local support routines - */ - -static int -xen_uppc_init_acpi(void) -{ - int verboseflags = 0; - int sci; - iflag_t sci_flags; - - /* - * Process SCI configuration here; this may return - * an error if acpi-user-options has specified - * legacy mode (use ACPI without ACPI mode or SCI) - */ - if (acpica_get_sci(&sci, &sci_flags) != AE_OK) - sci = -1; - - /* - * Initialize sub-system - if error is returns, ACPI is not - * used. - */ - if (acpica_init() != AE_OK) - return (0); - - /* - * uppc implies system is in PIC mode; set edge/level - * via ELCR based on return value from get_sci; this - * will default to level/low if no override present, - * as recommended by Intel ACPI CA team. - */ - if (sci >= 0) { - ASSERT((sci_flags.intr_el == INTR_EL_LEVEL) || - (sci_flags.intr_el == INTR_EL_EDGE)); - - psm_set_elcr(sci, sci_flags.intr_el == INTR_EL_LEVEL); - } - - /* - * Remember SCI for later use - */ - xen_uppc_sci = sci; - - if (xen_uppc_verbose & XEN_UPPC_VERBOSE_IRQ_FLAG) - verboseflags |= PSM_VERBOSE_IRQ_FLAG; - - if (xen_uppc_verbose & XEN_UPPC_VERBOSE_POWEROFF_FLAG) - verboseflags |= PSM_VERBOSE_POWEROFF_FLAG; - - if (xen_uppc_verbose & XEN_UPPC_VERBOSE_POWEROFF_PAUSE_FLAG) - verboseflags |= PSM_VERBOSE_POWEROFF_PAUSE_FLAG; - - if (acpi_psm_init(xen_uppc_info.p_mach_idstring, verboseflags) == - ACPI_PSM_FAILURE) { - return (0); - } - - return (1); -} - -/* - * Autoconfiguration Routines - */ - -static int -xen_uppc_probe(void) -{ - - return (PSM_SUCCESS); -} - -static void -xen_uppc_softinit(void) -{ - int i; - - /* LINTED logical expression always true: op "||" */ - ASSERT((1 << EVTCHN_SHIFT) == NBBY * sizeof (ulong_t)); - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - if (xen_uppc_use_acpi && xen_uppc_init_acpi()) { - build_reserved_irqlist((uchar_t *) - xen_uppc_reserved_irqlist); - for (i = 0; i <= MAX_ISA_IRQ; i++) - xen_uppc_irq_shared_table[i] = 0; - xen_uppc_enable_acpi = 1; - } - } -} - - -#define XEN_NSEC_PER_TICK 10 /* XXX - assume we have a 100 Mhz clock */ - -/*ARGSUSED*/ -static int -xen_uppc_clkinit(int hertz) -{ - extern enum tod_fault_type tod_fault(enum tod_fault_type, int); - extern int dosynctodr; - - /* - * domU cannot set the TOD hardware, fault the TOD clock now to - * indicate that and turn off attempts to sync TOD hardware - * with the hires timer. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - mutex_enter(&tod_lock); - (void) tod_fault(TOD_RDONLY, 0); - dosynctodr = 0; - mutex_exit(&tod_lock); - } - /* - * The hypervisor provides a timer based on the local APIC timer. - * The interface supports requests of nanosecond resolution. - * A common frequency of the apic clock is 100 Mhz which - * gives a resolution of 10 nsec per tick. What we would really like - * is a way to get the ns per tick value from xen. - * XXPV - This is an assumption that needs checking and may change - */ - return (XEN_NSEC_PER_TICK); -} - -static void -xen_uppc_picinit() -{ - int irqno; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { -#if 0 - /* hypervisor initializes the 8259, don't mess with it */ - picsetup(); /* initialise the 8259 */ -#endif - /* - * We never called xen_uppc_addspl() when the SCI - * interrupt was added because that happened before the - * PSM module was loaded. Fix that up here by doing - * any missed operations (e.g. bind to CPU) - */ - if ((irqno = xen_uppc_sci) >= 0) { - ec_enable_irq(irqno); - } - } -} - - -/*ARGSUSED*/ -static int -xen_uppc_addspl(int irqno, int ipl, int min_ipl, int max_ipl) -{ - int ret = PSM_SUCCESS; - cpuset_t cpus; - - if (irqno >= 0 && irqno <= MAX_ISA_IRQ) - atomic_inc_16(&xen_uppc_irq_shared_table[irqno]); - - /* - * We are called at splhi() so we can't call anything that might end - * up trying to context switch. - */ - if (irqno >= PIRQ_BASE && irqno < NR_PIRQS && - DOMAIN_IS_INITDOMAIN(xen_info)) { - CPUSET_ZERO(cpus); - CPUSET_ADD(cpus, 0); - ec_setup_pirq(irqno, ipl, &cpus); - } else { - /* - * Set priority/affinity/enable for non PIRQs - */ - ret = ec_set_irq_priority(irqno, ipl); - ASSERT(ret == 0); - CPUSET_ZERO(cpus); - CPUSET_ADD(cpus, 0); - ec_set_irq_affinity(irqno, cpus); - ec_enable_irq(irqno); - } - - return (ret); -} - -/*ARGSUSED*/ -static int -xen_uppc_delspl(int irqno, int ipl, int min_ipl, int max_ipl) -{ - int err = PSM_SUCCESS; - - if (irqno >= 0 && irqno <= MAX_ISA_IRQ) - atomic_dec_16(&xen_uppc_irq_shared_table[irqno]); - - if (irqno >= PIRQ_BASE && irqno < NR_PIRQS && - DOMAIN_IS_INITDOMAIN(xen_info)) { - if (max_ipl == PSM_INVALID_IPL) { - /* - * unbind if no more sharers of this irq/evtchn - */ - (void) ec_block_irq(irqno); - ec_unbind_irq(irqno); - } else { - /* - * If still in use reset priority - */ - err = ec_set_irq_priority(irqno, max_ipl); - } - } else { - (void) ec_block_irq(irqno); - ec_unbind_irq(irqno); - } - return (err); -} - -static processorid_t -xen_uppc_get_next_processorid(processorid_t id) -{ - if (id == -1) - return (0); - return (-1); -} - -/*ARGSUSED*/ -static int -xen_uppc_get_clockirq(int ipl) -{ - if (xen_clock_irq != -1) - return (xen_clock_irq); - - xen_clock_irq = ec_bind_virq_to_irq(VIRQ_TIMER, 0); - return (xen_clock_irq); -} - -/*ARGSUSED*/ -static void -xen_uppc_shutdown(int cmd, int fcn) -{ - XEN_UPPC_VERBOSE_POWEROFF(("xen_uppc_shutdown(%d,%d);\n", cmd, fcn)); - - switch (cmd) { - case A_SHUTDOWN: - switch (fcn) { - case AD_BOOT: - case AD_IBOOT: - (void) HYPERVISOR_shutdown(SHUTDOWN_reboot); - break; - case AD_POWEROFF: - /* fall through if domU or if poweroff fails */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - if (xen_uppc_enable_acpi) - (void) acpi_poweroff(); - /* FALLTHRU */ - case AD_HALT: - default: - (void) HYPERVISOR_shutdown(SHUTDOWN_poweroff); - break; - } - break; - case A_REBOOT: - (void) HYPERVISOR_shutdown(SHUTDOWN_reboot); - break; - default: - return; - } -} - - -/* - * This function will reprogram the timer. - * - * When in oneshot mode the argument is the absolute time in future at which to - * generate the interrupt. - * - * When in periodic mode, the argument is the interval at which the - * interrupts should be generated. There is no need to support the periodic - * mode timer change at this time. - * - * Note that we must be careful to convert from hrtime to Xen system time (see - * xpv_timestamp.c). - */ -static void -xen_uppc_timer_reprogram(hrtime_t timer_req) -{ - hrtime_t now, timer_new, time_delta, xen_time; - ulong_t flags; - - flags = intr_clear(); - /* - * We should be called from high PIL context (CBE_HIGH_PIL), - * so kpreempt is disabled. - */ - - now = xpv_gethrtime(); - xen_time = xpv_getsystime(); - if (timer_req <= now) { - /* - * requested to generate an interrupt in the past - * generate an interrupt as soon as possible - */ - time_delta = XEN_NSEC_PER_TICK; - } else - time_delta = timer_req - now; - - timer_new = xen_time + time_delta; - if (HYPERVISOR_set_timer_op(timer_new) != 0) - panic("can't set hypervisor timer?"); - intr_restore(flags); -} - -/* - * This function will enable timer interrupts. - */ -static void -xen_uppc_timer_enable(void) -{ - ec_unmask_irq(xen_clock_irq); -} - -/* - * This function will disable timer interrupts on the current cpu. - */ -static void -xen_uppc_timer_disable(void) -{ - (void) ec_block_irq(xen_clock_irq); - /* - * If the clock irq is pending on this cpu then we need to - * clear the pending interrupt. - */ - ec_unpend_irq(xen_clock_irq); -} - - -/* - * Configures the irq for the interrupt link device identified by - * acpipsmlnkp. - * - * Gets the current and the list of possible irq settings for the - * device. If xen_uppc_unconditional_srs is not set, and the current - * resource setting is in the list of possible irq settings, - * current irq resource setting is passed to the caller. - * - * Otherwise, picks an irq number from the list of possible irq - * settings, and sets the irq of the device to this value. - * If prefer_crs is set, among a set of irq numbers in the list that have - * the least number of devices sharing the interrupt, we pick current irq - * resource setting if it is a member of this set. - * - * Passes the irq number in the value pointed to by pci_irqp, and - * polarity and sensitivity in the structure pointed to by dipintrflagp - * to the caller. - * - * Note that if setting the irq resource failed, but successfuly obtained - * the current irq resource settings, passes the current irq resources - * and considers it a success. - * - * Returns: - * ACPI_PSM_SUCCESS on success. - * - * ACPI_PSM_FAILURE if an error occured during the configuration or - * if a suitable irq was not found for this device, or if setting the - * irq resource and obtaining the current resource fails. - * - */ -static int -xen_uppc_acpi_irq_configure(acpi_psm_lnk_t *acpipsmlnkp, dev_info_t *dip, - int *pci_irqp, iflag_t *dipintr_flagp) -{ - int i, min_share, foundnow, done = 0; - int32_t irq; - int32_t share_irq = -1; - int32_t chosen_irq = -1; - int cur_irq = -1; - acpi_irqlist_t *irqlistp; - acpi_irqlist_t *irqlistent; - - if ((acpi_get_possible_irq_resources(acpipsmlnkp, &irqlistp)) - == ACPI_PSM_FAILURE) { - XEN_UPPC_VERBOSE_IRQ((CE_WARN, "!xVM_uppc: Unable to determine " - "or assign IRQ for device %s, instance #%d: The system was " - "unable to get the list of potential IRQs from ACPI.", - ddi_get_name(dip), ddi_get_instance(dip))); - - return (ACPI_PSM_FAILURE); - } - - if ((acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, - dipintr_flagp) == ACPI_PSM_SUCCESS) && - (!xen_uppc_unconditional_srs) && - (cur_irq > 0)) { - - if (acpi_irqlist_find_irq(irqlistp, cur_irq, NULL) - == ACPI_PSM_SUCCESS) { - - acpi_free_irqlist(irqlistp); - ASSERT(pci_irqp != NULL); - *pci_irqp = cur_irq; - return (ACPI_PSM_SUCCESS); - } - XEN_UPPC_VERBOSE_IRQ((CE_WARN, "!xVM_uppc: Could not find the " - "current irq %d for device %s, instance #%d in ACPI's " - "list of possible irqs for this device. Picking one from " - " the latter list.", cur_irq, ddi_get_name(dip), - ddi_get_instance(dip))); - - } - - irqlistent = irqlistp; - min_share = 255; - - while (irqlistent != NULL) { - - for (foundnow = 0, i = 0; i < irqlistent->num_irqs; i++) { - - irq = irqlistp->irqs[i]; - - if ((irq > MAX_ISA_IRQ) || - (irqlistent->intr_flags.intr_el == INTR_EL_EDGE) || - (irq == 0)) - continue; - - if (xen_uppc_reserved_irqlist[irq]) - continue; - - if (xen_uppc_irq_shared_table[irq] == 0) { - chosen_irq = irq; - foundnow = 1; - if (!(xen_uppc_prefer_crs) || - (irq == cur_irq)) { - done = 1; - break; - } - } - - if ((xen_uppc_irq_shared_table[irq] < min_share) || - ((xen_uppc_irq_shared_table[irq] == min_share) && - (cur_irq == irq) && (xen_uppc_prefer_crs))) { - min_share = xen_uppc_irq_shared_table[irq]; - share_irq = irq; - foundnow = 1; - } - } - - /* If we found an IRQ in the inner loop, save the details */ - if (foundnow && ((chosen_irq != -1) || (share_irq != -1))) { - /* - * Copy the acpi_prs_private_t and flags from this - * irq list entry, since we found an irq from this - * entry. - */ - acpipsmlnkp->acpi_prs_prv = irqlistent->acpi_prs_prv; - *dipintr_flagp = irqlistent->intr_flags; - } - - if (done) - break; - - /* Load the next entry in the irqlist */ - irqlistent = irqlistent->next; - } - - acpi_free_irqlist(irqlistp); - - if (chosen_irq != -1) - irq = chosen_irq; - else if (share_irq != -1) - irq = share_irq; - else { - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: Could not find a " - "suitable irq from the list of possible irqs for device " - "%s, instance #%d in ACPI's list of possible\n", - ddi_get_name(dip), ddi_get_instance(dip))); - - return (ACPI_PSM_FAILURE); - } - - - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: Setting irq %d " - "for device %s instance #%d\n", irq, ddi_get_name(dip), - ddi_get_instance(dip))); - - if ((acpi_set_irq_resource(acpipsmlnkp, irq)) == ACPI_PSM_SUCCESS) { - /* - * setting irq was successful, check to make sure CRS - * reflects that. If CRS does not agree with what we - * set, return the irq that was set. - */ - - if (acpi_get_current_irq_resource(acpipsmlnkp, &cur_irq, - dipintr_flagp) == ACPI_PSM_SUCCESS) { - - if (cur_irq != irq) - XEN_UPPC_VERBOSE_IRQ((CE_WARN, "!xVM_uppc: " - "IRQ resource set (irqno %d) for device %s " - "instance #%d, differs from current " - "setting irqno %d", - irq, ddi_get_name(dip), - ddi_get_instance(dip), cur_irq)); - } - /* - * return the irq that was set, and not what CRS reports, - * since CRS has been seen to be bogus on some systems - */ - cur_irq = irq; - } else { - XEN_UPPC_VERBOSE_IRQ((CE_WARN, "!xVM_uppc: set resource irq %d " - "failed for device %s instance #%d", - irq, ddi_get_name(dip), ddi_get_instance(dip))); - if (cur_irq == -1) - return (ACPI_PSM_FAILURE); - } - - ASSERT(pci_irqp != NULL); - *pci_irqp = cur_irq; - return (ACPI_PSM_SUCCESS); -} - - -static int -xen_uppc_acpi_translate_pci_irq(dev_info_t *dip, int busid, int devid, - int ipin, int *pci_irqp, iflag_t *intr_flagp) -{ - int status; - acpi_psm_lnk_t acpipsmlnk; - - if ((status = acpi_get_irq_cache_ent(busid, devid, ipin, pci_irqp, - intr_flagp)) == ACPI_PSM_SUCCESS) { - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: Found irqno %d " - "from cache for device %s, instance #%d\n", *pci_irqp, - ddi_get_name(dip), ddi_get_instance(dip))); - return (status); - } - - bzero(&acpipsmlnk, sizeof (acpi_psm_lnk_t)); - - if ((status = acpi_translate_pci_irq(dip, ipin, pci_irqp, - intr_flagp, &acpipsmlnk)) == ACPI_PSM_FAILURE) { - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: " - " acpi_translate_pci_irq failed for device %s, instance" - " #%d\n", ddi_get_name(dip), ddi_get_instance(dip))); - - return (status); - } - - if (status == ACPI_PSM_PARTIAL && acpipsmlnk.lnkobj != NULL) { - status = xen_uppc_acpi_irq_configure(&acpipsmlnk, dip, pci_irqp, - intr_flagp); - if (status != ACPI_PSM_SUCCESS) { - status = acpi_get_current_irq_resource(&acpipsmlnk, - pci_irqp, intr_flagp); - } - } - - if (status == ACPI_PSM_SUCCESS) { - acpi_new_irq_cache_ent(busid, devid, ipin, *pci_irqp, - intr_flagp, &acpipsmlnk); - psm_set_elcr(*pci_irqp, 1); /* set IRQ to PCI mode */ - - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: [ACPI] " - "new irq %d for device %s, instance #%d\n", - *pci_irqp, ddi_get_name(dip), ddi_get_instance(dip))); - } - - return (status); -} - - -/*ARGSUSED*/ -static int -xen_uppc_translate_irq(dev_info_t *dip, int irqno) -{ - char dev_type[16]; - int dev_len, pci_irq, devid, busid; - ddi_acc_handle_t cfg_handle; - uchar_t ipin, iline; - iflag_t intr_flag; - - if (dip == NULL) { - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: irqno = %d" - " dip = NULL\n", irqno)); - return (irqno); - } - - if (!xen_uppc_enable_acpi) { - return (irqno); - } - - dev_len = sizeof (dev_type); - if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip), - DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, - &dev_len) != DDI_PROP_SUCCESS) { - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: irqno %d" - " device %s instance %d no device_type\n", irqno, - ddi_get_name(dip), ddi_get_instance(dip))); - return (irqno); - } - - if ((strcmp(dev_type, "pci") == 0) || - (strcmp(dev_type, "pciex") == 0)) { - - /* pci device */ - if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0) - return (irqno); - - if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS) - return (irqno); - - ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA; - iline = pci_config_get8(cfg_handle, PCI_CONF_ILINE); - if (xen_uppc_acpi_translate_pci_irq(dip, busid, devid, - ipin, &pci_irq, &intr_flag) == ACPI_PSM_SUCCESS) { - - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: [ACPI] " - "new irq %d old irq %d device %s, instance %d\n", - pci_irq, irqno, ddi_get_name(dip), - ddi_get_instance(dip))); - - /* - * Make sure pci_irq is within range. - * Otherwise, fall through and return irqno. - */ - if (pci_irq <= MAX_ISA_IRQ) { - if (iline != pci_irq) { - /* - * Update the device's ILINE byte, - * in case uppc_acpi_translate_pci_irq - * has choosen a different pci_irq - * than the BIOS has configured. - * Some chipsets use the value in - * ILINE to control interrupt routing, - * in conflict with the PCI spec. - */ - pci_config_put8(cfg_handle, - PCI_CONF_ILINE, pci_irq); - } - pci_config_teardown(&cfg_handle); - return (pci_irq); - } - } - pci_config_teardown(&cfg_handle); - - /* FALLTHRU to common case - returning irqno */ - } else { - /* non-PCI; assumes ISA-style edge-triggered */ - psm_set_elcr(irqno, 0); /* set IRQ to ISA mode */ - - XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: non-pci," - "irqno %d device %s instance %d\n", irqno, - ddi_get_name(dip), ddi_get_instance(dip))); - } - - return (irqno); -} - -/* - * xen_uppc_intr_enter() acks the event that triggered the interrupt and - * returns the new priority level, - */ -/*ARGSUSED*/ -static int -xen_uppc_intr_enter(int ipl, int *vector) -{ - int newipl; - uint_t intno; - cpu_t *cpu = CPU; - - intno = (*vector); - - ASSERT(intno < NR_IRQS); - ASSERT(cpu->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask != 0); - - ec_clear_irq(intno); - - newipl = autovect[intno].avh_hi_pri; - if (newipl == 0) { - /* - * (newipl == 0) means we have no service routines for this - * vector. We will treat this as a spurious interrupt. - * We have cleared the pending bit already, clear the event - * mask and return a spurious interrupt. This case can happen - * when an interrupt delivery is racing with the removal of - * of the service routine for that interrupt. - */ - ec_unmask_irq(intno); - newipl = -1; /* flag spurious interrupt */ - } else if (newipl <= cpu->cpu_pri) { - /* - * (newipl <= cpu->cpu_pri) means that we must be trying to - * service a vector that was shared with a higher priority - * isr. The higher priority handler has been removed and - * we need to service this int. We can't return a lower - * priority than current cpu priority. Just synthesize a - * priority to return that should be acceptable. - */ - newipl = cpu->cpu_pri + 1; /* synthetic priority */ - } - return (newipl); -} - - -static void xen_uppc_setspl(int); - -/* - * xen_uppc_intr_exit() restores the old interrupt - * priority level after processing an interrupt. - * It is called with interrupts disabled, and does not enable interrupts. - */ -/* ARGSUSED */ -static void -xen_uppc_intr_exit(int ipl, int vector) -{ - ec_try_unmask_irq(vector); - xen_uppc_setspl(ipl); -} - -intr_exit_fn_t -psm_intr_exit_fn(void) -{ - return (xen_uppc_intr_exit); -} - -/* - * Check if new ipl level allows delivery of previously unserviced events - */ -static void -xen_uppc_setspl(int ipl) -{ - struct cpu *cpu = CPU; - volatile vcpu_info_t *vci = cpu->cpu_m.mcpu_vcpu_info; - uint16_t pending; - - ASSERT(vci->evtchn_upcall_mask != 0); - - /* - * If new ipl level will enable any pending interrupts, setup so the - * upcoming sti will cause us to get an upcall. - */ - pending = cpu->cpu_m.mcpu_intr_pending & ~((1 << (ipl + 1)) - 1); - if (pending) { - int i; - ulong_t pending_sels = 0; - volatile ulong_t *selp; - struct xen_evt_data *cpe = cpu->cpu_m.mcpu_evt_pend; - - for (i = bsrw_insn(pending); i > ipl; i--) - pending_sels |= cpe->pending_sel[i]; - ASSERT(pending_sels); - selp = (volatile ulong_t *)&vci->evtchn_pending_sel; - atomic_or_ulong(selp, pending_sels); - vci->evtchn_upcall_pending = 1; - } -} - -/* - * The rest of the file is just generic psm module boilerplate - */ - -static struct psm_ops xen_uppc_ops = { - xen_uppc_probe, /* psm_probe */ - - xen_uppc_softinit, /* psm_init */ - xen_uppc_picinit, /* psm_picinit */ - xen_uppc_intr_enter, /* psm_intr_enter */ - xen_uppc_intr_exit, /* psm_intr_exit */ - xen_uppc_setspl, /* psm_setspl */ - xen_uppc_addspl, /* psm_addspl */ - xen_uppc_delspl, /* psm_delspl */ - (int (*)(processorid_t))NULL, /* psm_disable_intr */ - (void (*)(processorid_t))NULL, /* psm_enable_intr */ - (int (*)(int))NULL, /* psm_softlvl_to_irq */ - (void (*)(int))NULL, /* psm_set_softintr */ - (void (*)(processorid_t))NULL, /* psm_set_idlecpu */ - (void (*)(processorid_t))NULL, /* psm_unset_idlecpu */ - - xen_uppc_clkinit, /* psm_clkinit */ - xen_uppc_get_clockirq, /* psm_get_clockirq */ - (void (*)(void))NULL, /* psm_hrtimeinit */ - xpv_gethrtime, /* psm_gethrtime */ - - xen_uppc_get_next_processorid, /* psm_get_next_processorid */ - (int (*)(processorid_t, caddr_t))NULL, /* psm_cpu_start */ - (int (*)(void))NULL, /* psm_post_cpu_start */ - xen_uppc_shutdown, /* psm_shutdown */ - (int (*)(int, int))NULL, /* psm_get_ipivect */ - (void (*)(processorid_t, int))NULL, /* psm_send_ipi */ - - xen_uppc_translate_irq, /* psm_translate_irq */ - - (void (*)(int, char *))NULL, /* psm_notify_error */ - (void (*)(int msg))NULL, /* psm_notify_func */ - xen_uppc_timer_reprogram, /* psm_timer_reprogram */ - xen_uppc_timer_enable, /* psm_timer_enable */ - xen_uppc_timer_disable, /* psm_timer_disable */ - (void (*)(void *arg))NULL, /* psm_post_cyclic_setup */ - (void (*)(int, int))NULL, /* psm_preshutdown */ - - (int (*)(dev_info_t *, ddi_intr_handle_impl_t *, - psm_intr_op_t, int *))NULL, /* psm_intr_ops */ - (int (*)(psm_state_request_t *))NULL, /* psm_state */ - (int (*)(psm_cpu_request_t *))NULL /* psm_cpu_ops */ -}; - -static struct psm_info xen_uppc_info = { - PSM_INFO_VER01_5, /* version */ - PSM_OWN_SYS_DEFAULT, /* ownership */ - &xen_uppc_ops, /* operation */ - "xVM_uppc", /* machine name */ - "UniProcessor PC" /* machine descriptions */ -}; - -static void *xen_uppc_hdlp; - -int -_init(void) -{ - return (psm_mod_init(&xen_uppc_hdlp, &xen_uppc_info)); -} - -int -_fini(void) -{ - return (psm_mod_fini(&xen_uppc_hdlp, &xen_uppc_info)); -} - -int -_info(struct modinfo *modinfop) -{ - return (psm_mod_info(&xen_uppc_hdlp, &xen_uppc_info, modinfop)); -} diff --git a/usr/src/uts/i86xpv/io/xpvtod.c b/usr/src/uts/i86xpv/io/xpvtod.c deleted file mode 100644 index 8bc9d68994..0000000000 --- a/usr/src/uts/i86xpv/io/xpvtod.c +++ /dev/null @@ -1,191 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * tod driver module for i86xpv - */ - -static timestruc_t -todxen_get(tod_ops_t *top) -{ - todinfo_t tod; - timestruc_t ts, wcts; - shared_info_t *si = HYPERVISOR_shared_info; - uint32_t xen_wc_version; - hrtime_t now; - - ASSERT(MUTEX_HELD(&tod_lock)); - - /* - * Pick up the wallclock base time - */ - do { - xen_wc_version = si->wc_version; - - membar_consumer(); - - wcts.tv_sec = si->wc_sec; - wcts.tv_nsec = si->wc_nsec; - - membar_consumer(); - - } while ((si->wc_version & 1) | (xen_wc_version ^ si->wc_version)); - - /* - * Compute the TOD as the wallclock (boot) time plus time-since-boot - * (/not/ hrtime!) and normalize. - */ - now = xpv_getsystime() + - (hrtime_t)wcts.tv_nsec + (hrtime_t)wcts.tv_sec * NANOSEC; - ts.tv_sec = (time_t)(now / NANOSEC); - ts.tv_nsec = (long)(now % NANOSEC); - - /* - * Apply GMT lag correction from /etc/rtc_config to get UTC time - */ - ts.tv_sec += ggmtl(); - - /* - * Validate the TOD in case of total insanity - */ - tod = utc_to_tod(ts.tv_sec); - if (tod.tod_year < 69) { - static int range_warn = 1; /* warn only once */ - - if (range_warn) { - /* - * If we're dom0, go invoke the underlying driver; the - * routine should complain if it discovers something - * wrong. - */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - (void) TODOP_GET(top->tod_next); - - /* - * Check the virtual hardware. - */ - if (tod.tod_year > 38) - cmn_err(CE_WARN, - "hypervisor wall clock is out " - "of range -- time needs to be reset"); - range_warn = 0; - } - tod.tod_year += 100; - ts.tv_sec = tod_to_utc(tod); - } - - return (ts); -} - -/* - * On dom0, invoke the underlying driver to update the physical RTC, - * and tell the hypervisor to update its idea of global time. - * - * On domU, we don't have permission to update the machine's physical RTC, - * so quietly ignore the attempt. - */ -static void -todxen_set(tod_ops_t *top, timestruc_t ts) -{ - xen_platform_op_t op; - - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - ASSERT(MUTEX_HELD(&tod_lock)); - TODOP_SET(top->tod_next, ts); - - op.cmd = XENPF_settime; - op.interface_version = XENPF_INTERFACE_VERSION; - op.u.settime.secs = ts.tv_sec - ggmtl(); - op.u.settime.nsecs = ts.tv_nsec; - op.u.settime.system_time = xpv_getsystime(); - (void) HYPERVISOR_platform_op(&op); - } -} - -static tod_ops_t todxen_ops = { - TOD_OPS_VERSION, - todxen_get, - todxen_set, - NULL -}; - -static struct modlmisc modlmisc = { - &mod_miscops, - "TOD module for i86xpv" -}; - -static struct modlinkage modl = { - MODREV_1, - &modlmisc -}; - -int -_init(void) -{ - /* - * In future we might need to do something more sophisticated - * for versioning, i.e. dealing with older hardware TOD modules - * underneath us, but for now, anything else but "same" is a - * fatal error. - */ - if (tod_ops->tod_version != todxen_ops.tod_version) - panic("TOD module version mismatch"); - - /* - * Stitch the ops vector linkage together, with this module - * sitting on the "front" of the ops list. - */ - todxen_ops.tod_next = tod_ops; - tod_ops = &todxen_ops; - - return (mod_install(&modl)); -} - -int -_fini(void) -{ - return (EBUSY); -} - -int -_info(struct modinfo *modinfo) -{ - return (mod_info(&modl, modinfo)); -} diff --git a/usr/src/uts/i86xpv/ioat/Makefile b/usr/src/uts/i86xpv/ioat/Makefile deleted file mode 100644 index b7aac59f9d..0000000000 --- a/usr/src/uts/i86xpv/ioat/Makefile +++ /dev/null @@ -1,91 +0,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 -# -# -# uts/i86xpv/ioat/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the ioat driver kernel -# module. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = ioat -OBJECTS = $(IOAT_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io/ioat - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - - -CERRWARN += -Wno-unused-label -CERRWARN += -Wno-uninitialized - -# -# Dependency -# -LDFLAGS += -dy -Nmisc/dcopy - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = $(OBJS_DIR) -CLEANFILES += $(MODSTUBS_O) - -# -# 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)/i86xpv/Makefile.targ - diff --git a/usr/src/uts/i86xpv/isa/Makefile b/usr/src/uts/i86xpv/isa/Makefile deleted file mode 100644 index 67558c7386..0000000000 --- a/usr/src/uts/i86xpv/isa/Makefile +++ /dev/null @@ -1,117 +0,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. -# -# Copyright 2016 Joyent, Inc. -# -# This makefile drives the production of the ISA nexus driver -# -# i86xpv 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 = isa -OBJECTS = $(ISANEXUS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -INC_PATH += -I$(UTSBASE)/i86pc/sys/acpi - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Dependency -LDFLAGS += -dy -Nmisc/acpica -Nmisc/busra -Nmisc/pci_autoconfig - -# -# Define our version of dma_engine and i8237A interfaces -# -$(OBJECTS) := CPPFLAGS += -Di_dmae_init=$(MODULE)_i_dmae_init -$(OBJECTS) := CPPFLAGS += -Di_dmae_acquire=$(MODULE)_i_dmae_acquire -$(OBJECTS) := CPPFLAGS += -Di_dmae_free=$(MODULE)_i_dmae_free -$(OBJECTS) := CPPFLAGS += -Di_dmae_get_best_mode=$(MODULE)_i_dmae_get_best_mode -$(OBJECTS) := CPPFLAGS += -D_dmae_nxcookie=$(MODULE)__dmae_nxcookie -$(OBJECTS) := CPPFLAGS += -Di_dmae_prog=$(MODULE)_i_dmae_prog -$(OBJECTS) := CPPFLAGS += -Di_dmae_swsetup=$(MODULE)_i_dmae_swsetup -$(OBJECTS) := CPPFLAGS += -Di_dmae_swsetup=$(MODULE)_i_dmae_swsetup -$(OBJECTS) := CPPFLAGS += -Di_dmae_swstart=$(MODULE)_i_dmae_swstart -$(OBJECTS) := CPPFLAGS += -Di_dmae_stop=$(MODULE)_i_dmae_stop -$(OBJECTS) := CPPFLAGS += -Di_dmae_enable=$(MODULE)_i_dmae_enable -$(OBJECTS) := CPPFLAGS += -Di_dmae_disable=$(MODULE)_i_dmae_disable -$(OBJECTS) := CPPFLAGS += -Di_dmae_get_chan_stat=$(MODULE)_i_dmae_get_chan_stat -$(OBJECTS) := CPPFLAGS += -Dd37A_init=$(MODULE)_d37A_init -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_valid=$(MODULE)_d37A_dma_valid -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_release=$(MODULE)_d37A_dma_release -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_disable=$(MODULE)_d37A_dma_disable -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_enable=$(MODULE)_d37A_dma_enable -$(OBJECTS) := CPPFLAGS += -Dd37A_get_best_mode=$(MODULE)_d37A_get_best_mode -$(OBJECTS) := CPPFLAGS += -Dd37A_intr=$(MODULE)_d37A_intr -$(OBJECTS) := CPPFLAGS += -DdEISA_setchain=$(MODULE)_dEISA_setchain -$(OBJECTS) := CPPFLAGS += -Dd37A_prog_chan=$(MODULE)_d37A_prog_chan -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_swsetup=$(MODULE)_d37A_dma_swsetup -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_swstart=$(MODULE)_d37A_dma_swstart -$(OBJECTS) := CPPFLAGS += -Dd37A_dma_stop=$(MODULE)_d37A_dma_stop -$(OBJECTS) := CPPFLAGS += -Dd37A_get_chan_stat=$(MODULE)_d37A_get_chan_stat -$(OBJECTS) := CPPFLAGS += -Dd37A_set_mode=$(MODULE)_d37A_set_mode -$(OBJECTS) := CPPFLAGS += -Dd37A_write_addr=$(MODULE)_d37A_write_addr -$(OBJECTS) := CPPFLAGS += -Dd37A_read_addr=$(MODULE)_d37A_read_addr -$(OBJECTS) := CPPFLAGS += -Dd37A_write_count=$(MODULE)_d37A_write_count -$(OBJECTS) := CPPFLAGS += -Dd37A_read_count=$(MODULE)_d37A_read_count - -$(OBJS_DIR)/isa.o := CERRWARN += -Wno-unused-function -CERRWARN += -Wno-unused-variable - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/ml/hyperevent.s b/usr/src/uts/i86xpv/ml/hyperevent.s deleted file mode 100644 index c8a0667c08..0000000000 --- a/usr/src/uts/i86xpv/ml/hyperevent.s +++ /dev/null @@ -1,235 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "assym.h" - - - /* - * The stack frame for events is exactly that of an x86 hardware - * interrupt. - * - * The stack frame for a failsafe callback is augmented with saved - * values for segment registers: - * - * i386 - * %ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss ] - * - * On amd64 the stack frame for events is exactly that of an hardware - * interrupt with the addition of rcx and r11. - * - * The stack frame for a failsafe callback is augmented with saved - * values for segment registers: - * - * amd64 - * %rcx, %r11, %ds, %es, %fs, %gs, %rip, %cs, %rflags, - * [, %oldrsp, %oldss ] - * - * The hypervisor does this to allow the guest OS to handle returns - * to processes which have bad segment registers. - * - * [See comments in xen/arch/x86/[x86_64,x86_32]/entry.S] - * - * We will construct a fully fledged 'struct regs' and call trap - * with a #gp fault. - */ - -#if defined(__amd64) - - ENTRY(xen_failsafe_callback) - - /* - * The saved values of rcx and r11 are on the top of the stack. - * pop them and let INTR_PUSH save them. We drop ds, es, fs and - * gs since the hypervisor will have already loaded these for us. - * If any were bad and faulted the hypervisor would have loaded - * them with the null selctor. - */ - XPV_TRAP_POP /* rcx, r11 */ - - /* - * XXPV - * If the current segregs are provided for us on the stack by - * the hypervisor then we should simply move them into their proper - * location in the regs struct? - */ - addq $_CONST(_MUL(4, CLONGSIZE)), %rsp - - /* - * XXPV - * It would be nice to somehow figure out which selector caused - * #gp fault. - */ - - pushq $0 /* dummy error */ - pushq $T_GPFLT - - INTR_PUSH - INTGATE_INIT_KERNEL_FLAGS - - /* - * We're here because HYPERVISOR_IRET to userland failed due to a - * bad %cs value. Rewrite %cs, %ss and %rip on the stack so trap - * will know to handle this with kern_gpfault and kill the currently - * running process. - */ - movq $KCS_SEL, REGOFF_CS(%rsp) - movq $KDS_SEL, REGOFF_SS(%rsp) - leaq nopop_sys_rtt_syscall(%rip), %rdi - movq %rdi, REGOFF_RIP(%rsp) - - TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */ - TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ - TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ - - movq %rsp, %rbp - - TRACE_STACK(%rdi) - - movq %rbp, %rdi - - ENABLE_INTR_FLAGS - - movq %rbp, %rdi - xorl %esi, %esi - movl %gs:CPU_ID, %edx - call trap /* trap(rp, addr, cpuid) handles all trap */ - jmp _sys_rtt - SET_SIZE(xen_failsafe_callback) - -#elif defined(__i386) - - ENTRY(xen_failsafe_callback) - - /* - * drop ds, es, fs and gs - */ - addl $_CONST(_MUL(4, CLONGSIZE)), %esp /* see comment for 64-bit */ - - pushl $0 /* dummy error (see comment for 64-bit) */ - pushl $T_GPFLT - - INTR_PUSH - INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ - - /* - * The fact were here is because HYPERVISOR_IRET to userland - * failed due to a bad %cs value. Rewrite %cs, %ss and %eip - * on the stack so trap will know to handle this with - * kern_gpfault and kill the currently running process. - */ - movl $KCS_SEL, REGOFF_CS(%esp) - movl $KDS_SEL, REGOFF_SS(%esp) - leal nopop_sys_rtt_syscall, %edi - movl %edi, REGOFF_EIP(%esp) - - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ - - movl %esp, %ebp - - TRACE_STACK(%edi) - - ENABLE_INTR_FLAGS - - pushl %gs:CPU_ID - pushl $0 - pushl %ebp - call trap /* trap(rp, addr, cpuid) handles all traps */ - addl $12, %esp - jmp _sys_rtt - SET_SIZE(xen_failsafe_callback) - -#endif /* __i386 */ - -#if defined(__amd64) - - ENTRY(xen_callback) - XPV_TRAP_POP - - pushq $0 /* dummy error */ - pushq $T_AST - - INTR_PUSH - INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ - - TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */ - TRACE_REGS(%rdi, %rsp, %rbx, %rcx) /* Uses label 9 */ - TRACE_STAMP(%rdi) /* Clobbers %eax, %edx, uses 9 */ - - movq %rsp, %rbp - - TRACE_STACK(%rdi) - - movq %rdi, %rsi /* rsi = trap trace recode pointer */ - movq %rbp, %rdi /* rdi = struct regs pointer */ - call xen_callback_handler - - jmp _sys_rtt_ints_disabled - /*NOTREACHED*/ - - SET_SIZE(xen_callback) - -#elif defined(__i386) - - ENTRY(xen_callback) - pushl $0 /* dummy error */ - pushl $T_AST - - INTR_PUSH - INTGATE_INIT_KERNEL_FLAGS /* (set kernel flag values) */ - - TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */ - TRACE_REGS(%edi, %esp, %ebx, %ecx) /* Uses label 9 */ - TRACE_STAMP(%edi) /* Clobbers %eax, %edx, uses 9 */ - - movl %esp, %ebp - - TRACE_STACK(%edi) - - pushl %edi /* pass trap trace record pointer */ - pushl %ebp /* pass struct regs pointer */ - call xen_callback_handler - addl $8, %esp - - jmp _sys_rtt_ints_disabled - /*NOTREACHED*/ - - SET_SIZE(xen_callback) - -#endif /* __i386 */ diff --git a/usr/src/uts/i86xpv/ml/panic_asm.s b/usr/src/uts/i86xpv/ml/panic_asm.s deleted file mode 100644 index 99f76ba30b..0000000000 --- a/usr/src/uts/i86xpv/ml/panic_asm.s +++ /dev/null @@ -1,372 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "assym.h" - - -#if defined(__amd64) - ENTRY_NP(xpv_panic_getcr3) - movq %cr3, %rax - ret - SET_SIZE(xpv_panic_getcr3) - - ENTRY_NP(xpv_panic_setcr3) - movq %rdi, %cr3 - ret - SET_SIZE(xpv_panic_setcr3) - - ENTRY(xpv_panic_reload_cr3) - movq %cr3, %rdi - movq %rdi, %cr3 - ret - SET_SIZE(xpv_panic_reload_cr3) - - ENTRY_NP(xpv_panic_prep) - pushq %rbp - movq %rsp, %rbp - - subq $REGSIZE, %rsp - movq %rax, REGOFF_RAX(%rsp) - movq %rbx, REGOFF_RBX(%rsp) - movq %rsp, %rax - addq $REGSIZE, %rax - movq (%rax), %rbx - movq %rbx, REGOFF_RBP(%rsp) - movq 8(%rax), %rbx - movq %rbx, REGOFF_TRAPNO(%rsp) - movq 16(%rax), %rbx - movq %rbx, REGOFF_ERR(%rsp) - movq 24(%rax), %rbx - movq %rbx, REGOFF_RIP(%rsp) - movq 32(%rax), %rbx - movq %rbx, REGOFF_CS(%rsp) - movq 40(%rax), %rbx - movq %rbx, REGOFF_RFL(%rsp) - addq $56, %rax - movq %rax, REGOFF_RSP(%rsp) - xorl %eax, %eax - movw %gs, %ax - mov %rax, REGOFF_GS(%rsp) - movw %fs, %ax - mov %rax, REGOFF_FS(%rsp) - movw %es, %ax - mov %rax, REGOFF_ES(%rsp) - movw %ds, %ax - mov %rax, REGOFF_DS(%rsp) - movw %ss, %ax - mov %rax, REGOFF_SS(%rsp) - movq %rcx, REGOFF_RCX(%rsp) - movq %rdx, REGOFF_RDX(%rsp) - movq %rdi, REGOFF_RDI(%rsp) - movq %rsi, REGOFF_RSI(%rsp) - movq %r8, REGOFF_R8(%rsp) - movq %r9, REGOFF_R9(%rsp) - movq %r10, REGOFF_R10(%rsp) - movq %r11, REGOFF_R11(%rsp) - movq %r12, REGOFF_R12(%rsp) - movq %r13, REGOFF_R13(%rsp) - movq %r14, REGOFF_R14(%rsp) - movq %r15, REGOFF_R15(%rsp) - - movq %rsp, %rdi - call xpv_die - SET_SIZE(xpv_panic_prep) - - /* - * Switch to the Solaris panic stack and jump into the Xen panic - * handling code. - */ - ENTRY_NP(xpv_panic_hdlr) - leaq panic_stack(%rip), %rsp - addq $PANICSTKSIZE, %rsp - call xpv_do_panic - SET_SIZE(xpv_panic_hdlr) - - ENTRY_NP(xpv_surprise_intr) - pushq %rbp - movq %rsp, %rbp - subq $REGOFF_TRAPNO, %rsp - __SAVE_REGS - movq %rsp, %rdi - addq $REGOFF_TRAPNO, %rdi - call xpv_interrupt - __RESTORE_REGS - addq $REGOFF_TRAPNO, %rsp - popq %rbp - iretq - SET_SIZE(xpv_surprise_intr) - - ENTRY_NP(xpv_timer_trap) - pushq %rbp - movq %rsp, %rbp - subq $REGOFF_TRAPNO, %rsp - __SAVE_REGS - movq %rsp, %rdi - addq $REGOFF_TRAPNO, %rdi - call xpv_timer_tick - __RESTORE_REGS - addq $REGOFF_TRAPNO, %rsp - popq %rbp - iretq - SET_SIZE(xpv_timer_trap) - -#elif defined(__i386) - - ENTRY_NP(xpv_panic_setcr3) - movl 4(%esp), %eax - movl %eax, %cr3 - ret - SET_SIZE(xpv_panic_setcr3) - - ENTRY(xpv_panic_reload_cr3) - movl %cr3, %eax - movl %eax, %cr3 - ret - SET_SIZE(xpv_panic_reload_cr3) - - /* - * Stack on entry: - * +------------+ - * | EFLAGS | - * | CS | - * | EIP | - * | Error | - * | Trap | <---- %esp - * +------------+ - */ - ENTRY_NP(xpv_panic_prep) - pushl %ebp - movl %esp, %ebp - - subl $REGSIZE, %esp - movl %eax, REGOFF_EAX(%esp) - movl %ebx, REGOFF_EBX(%esp) - movl %esp, %eax - addl $REGSIZE, %eax - movl (%eax), %ebx - movl %ebx, REGOFF_EBP(%esp) - movl 4(%eax), %ebx - movl %ebx, REGOFF_TRAPNO(%esp) - movl 8(%eax), %ebx - movl %ebx, REGOFF_ERR(%esp) - movl 12(%eax), %ebx - movl %ebx, REGOFF_EIP(%esp) - movl 16(%eax), %ebx - movl %ebx, REGOFF_CS(%esp) - movl 20(%eax), %ebx - movl %ebx, REGOFF_EFL(%esp) - addl $28, %eax - movl %eax, REGOFF_ESP(%esp) - xorl %eax, %eax - movw %gs, %ax - mov %eax, REGOFF_GS(%esp) - movw %fs, %ax - mov %eax, REGOFF_FS(%esp) - movw %es, %ax - mov %eax, REGOFF_ES(%esp) - movw %ds, %ax - mov %eax, REGOFF_DS(%esp) - movw %ss, %ax - mov %eax, REGOFF_SS(%esp) - movl %ecx, REGOFF_ECX(%esp) - movl %edx, REGOFF_EDX(%esp) - movl %edi, REGOFF_EDI(%esp) - movl %esi, REGOFF_ESI(%esp) - pushl %esp - call xpv_die - SET_SIZE(xpv_panic_prep) - - /* - * Switch to the Solaris panic stack and jump into the Xen panic - * handling code. - */ - ENTRY_NP(xpv_panic_hdlr) - movl 4(%esp), %eax - lea panic_stack, %esp - add $PANICSTKSIZE, %esp - pushl %eax - call xpv_do_panic - SET_SIZE(xpv_panic_hdlr) - - ENTRY_NP(xpv_surprise_intr) - push %ebp - movl %esp, %ebp - pusha - call xpv_interrupt - popa - pop %ebp - iret - SET_SIZE(xpv_surprise_intr) - - ENTRY_NP(xpv_timer_trap) - push %ebp - movl %esp, %ebp - pusha - call xpv_timer_tick - popa - pop %ebp - iret - SET_SIZE(xpv_timer_trap) - -#endif /* __i386 */ - - ENTRY_NP(xpv_panic_sti) - sti - ret - SET_SIZE(xpv_panic_sti) - - ENTRY_NP(xpv_panic_halt) - sti - hlt - ret - SET_SIZE(xpv_panic_halt) - - ENTRY_NP(xpv_panic_resetgs) - movl $KGS_SEL, %eax - movw %ax, %gs - ret - SET_SIZE(xpv_panic_resetgs) - - ENTRY_NP(xpv_invaltrap) - push $0xbad0 - push $0x0bad - jmp xpv_panic_prep - SET_SIZE(xpv_invaltrap) - - ENTRY_NP(xpv_div0trap) - push $0 - push $T_ZERODIV - jmp xpv_panic_prep - SET_SIZE(xpv_div0trap) - - ENTRY_NP(xpv_dbgtrap) - push $0 - push $T_SGLSTP - jmp xpv_panic_prep - SET_SIZE(xpv_dbgtrap) - - ENTRY_NP(xpv_nmiint) - push $0 - push $T_NMIFLT - jmp xpv_panic_prep - SET_SIZE(xpv_nmiint) - - ENTRY_NP(xpv_brktrap) - /* XXX: check for error */ - push $T_BPTFLT - jmp xpv_panic_prep - SET_SIZE(xpv_brktrap) - - ENTRY_NP(xpv_ovflotrap) - push $0 - push $T_OVFLW - jmp xpv_panic_prep - SET_SIZE(xpv_ovflotrap) - - ENTRY_NP(xpv_boundstrap) - push $0 - push $T_BOUNDFLT - jmp xpv_panic_prep - SET_SIZE(xpv_boundstrap) - - ENTRY_NP(xpv_invoptrap) - push $T_ILLINST - jmp xpv_panic_prep - SET_SIZE(xpv_invoptrap) - - ENTRY_NP(xpv_ndptrap) - push $0 - push $T_NOEXTFLT - jmp xpv_panic_prep - SET_SIZE(xpv_ndptrap) - - ENTRY_NP(xpv_syserrtrap) - /* XXX: check for error */ - push $T_DBLFLT - jmp xpv_panic_prep - SET_SIZE(xpv_syserrtrap) - - ENTRY_NP(xpv_invtsstrap) - push $T_TSSFLT - jmp xpv_panic_prep - SET_SIZE(xpv_invtsstrap) - - ENTRY_NP(xpv_segnptrap) - push $T_SEGFLT - jmp xpv_panic_prep - SET_SIZE(xpv_segnptrap) - - ENTRY_NP(xpv_stktrap) - push $T_STKFLT - jmp xpv_panic_prep - SET_SIZE(xpv_stktrap) - - ENTRY_NP(xpv_gptrap) - push $T_GPFLT - jmp xpv_panic_prep - SET_SIZE(xpv_gptrap) - - ENTRY_NP(xpv_pftrap) - push $T_PGFLT - jmp xpv_panic_prep - SET_SIZE(xpv_pftrap) - - ENTRY_NP(xpv_ndperr) - push $0 - push $T_EXTERRFLT - jmp xpv_panic_prep - SET_SIZE(xpv_ndperr) - - ENTRY_NP(xpv_achktrap) - push $T_ALIGNMENT - jmp xpv_panic_prep - SET_SIZE(xpv_achktrap) - - ENTRY_NP(xpv_mcetrap) - push $0 - push $T_MCE - jmp xpv_panic_prep - SET_SIZE(xpv_mcetrap) - - ENTRY_NP(xpv_xmtrap) - push $0 - push $T_SIMDFPE - jmp xpv_panic_prep - SET_SIZE(xpv_xmtrap) - diff --git a/usr/src/uts/i86xpv/ml/xenguest.s b/usr/src/uts/i86xpv/ml/xenguest.s deleted file mode 100644 index ef47161772..0000000000 --- a/usr/src/uts/i86xpv/ml/xenguest.s +++ /dev/null @@ -1,57 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - - -#include - -/* - * A note is a name/value pair that belongs to some class. - */ -#define NOTE(class, id, type, value) \ - .align 4; \ - .4byte 2f - 1f; \ - .4byte 4f - 3f; \ - .4byte id; \ -1: ; \ - .string class; \ -2: ; \ - .align 4; \ -3: ; \ - type value; \ -4: ; - - .section .note - NOTE("Xen", XEN_ELFNOTE_LOADER, .string, "generic") - NOTE("Xen", XEN_ELFNOTE_XEN_VERSION, .string, "xen-3.0") - NOTE("Xen", XEN_ELFNOTE_GUEST_OS, .string, "Solaris") - NOTE("Xen", XEN_ELFNOTE_VIRT_BASE, .4byte, 0x40000000) - NOTE("Xen", XEN_ELFNOTE_PADDR_OFFSET, .4byte, 0x40000000) -#if defined(__i386) - NOTE("Xen", XEN_ELFNOTE_PAE_MODE, .string, "yes,bimodal") -#endif - diff --git a/usr/src/uts/i86xpv/npe/Makefile b/usr/src/uts/i86xpv/npe/Makefile deleted file mode 100644 index dd94e2bd9e..0000000000 --- a/usr/src/uts/i86xpv/npe/Makefile +++ /dev/null @@ -1,94 +0,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. -# -# Copyright 2016 Joyent, Inc. -# -# This makefile drives the production of the PCI-E nexus driver -# -# i86xpv 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 = npe -OBJECTS = $(PCI_E_NEXUS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# depends on misc/acpica and misc/pcie -# -# acpica supplies ACPI access routines -# -# pcie supplies PCI Express fabric error support -# -LDFLAGS += -dy -Nmisc/acpica -Nmisc/pcie - -# -# Name of the module is needed by the source, to distinguish from other -# PCI/PCI-express nexi -# -CFLAGS += -D_MODULE_NAME="\"$(MODULE)\"" - - -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-function - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/os/balloon.c b/usr/src/uts/i86xpv/os/balloon.c deleted file mode 100644 index c270fb5c6d..0000000000 --- a/usr/src/uts/i86xpv/os/balloon.c +++ /dev/null @@ -1,1061 +0,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. - * Copyright 2016 PALO, Richard. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This file implements a balloon thread, which controls a domain's memory - * reservation, or the amount of memory a domain is currently allocated. - * The hypervisor provides the current memory reservation through xenbus, - * so we register a watch on this. We will then be signalled when the - * reservation changes. If it goes up, we map the new mfn's to our pfn's - * (allocating page_t's if necessary), and release them into the system. - * If the reservation goes down, we grab pages and release them back to - * the hypervisor, saving the page_t's for later use. - */ - -/* - * Various structures needed by the balloon thread - */ -static bln_stats_t bln_stats; -static kthread_t *bln_thread; -static kmutex_t bln_mutex; -static kcondvar_t bln_cv; -static struct xenbus_watch bln_watch; -static mfn_t new_high_mfn; - -/* - * For holding spare page_t structures - keep a singly-linked list. - * The list may hold both valid (pagenum < mfn_count) and invalid - * (pagenum >= mfn_count) page_t's. Valid page_t's should be inserted - * at the front, and invalid page_t's at the back. Removal should - * always be from the front. This is a singly-linked list using - * p_next, so p_prev is always NULL. - */ -static page_t *bln_spare_list_front, *bln_spare_list_back; - -int balloon_zero_memory = 1; -size_t balloon_minkmem = (8 * 1024 * 1024); - -/* - * reassign_pfn() calls update_contig_pfnlist(), which can cause a large - * slowdown when calling multiple times. If we're reassigning less than the - * quota defined here, we just accept the slowdown. If the count is greater - * than the quota, we tell the contig alloc code to stop its accounting until - * we're done. Setting the quota to less than 2 is not supported. - * - * Note that we define our own wrapper around the external - * clear_and_lock_contig_pfnlist(), but we just use the version of - * unlock_contig_pfnlist() in vm_machdep.c. - */ -uint_t bln_contig_list_quota = 50; - -extern void clear_and_lock_contig_pfnlist(void); -extern void unlock_contig_pfnlist(void); - -/* - * Lock the pfnlist if necessary (see above), and return whether we locked it. - */ -static int -balloon_lock_contig_pfnlist(int count) -{ - if (count > bln_contig_list_quota) { - clear_and_lock_contig_pfnlist(); - return (1); - } else { - return (0); - } -} - -/* - * The page represented by pp is being given back to the hypervisor. - * Add the page_t structure to our spare list. - */ -static void -balloon_page_add(page_t *pp) -{ - /* - * We need to keep the page exclusively locked - * to prevent swrand from grabbing it. - */ - ASSERT(PAGE_EXCL(pp)); - ASSERT(MUTEX_HELD(&bln_mutex)); - - pp->p_prev = NULL; - if (bln_spare_list_front == NULL) { - bln_spare_list_front = bln_spare_list_back = pp; - pp->p_next = NULL; - } else if (pp->p_pagenum >= mfn_count) { - /* - * The pfn is invalid, so add at the end of list. Since these - * adds should *only* be done by balloon_init_new_pages(), and - * that does adds in order, the following ASSERT should - * never trigger. - */ - ASSERT(pp->p_pagenum > bln_spare_list_back->p_pagenum); - bln_spare_list_back->p_next = pp; - pp->p_next = NULL; - bln_spare_list_back = pp; - } else { - /* Add at beginning of list */ - pp->p_next = bln_spare_list_front; - bln_spare_list_front = pp; - } -} - -/* - * Return a page_t structure from our spare list, or NULL if none are available. - */ -static page_t * -balloon_page_sub(void) -{ - page_t *pp; - - ASSERT(MUTEX_HELD(&bln_mutex)); - if (bln_spare_list_front == NULL) { - return (NULL); - } - - pp = bln_spare_list_front; - ASSERT(PAGE_EXCL(pp)); - ASSERT(pp->p_pagenum <= mfn_count); - if (pp->p_pagenum == mfn_count) { - return (NULL); - } - - bln_spare_list_front = pp->p_next; - if (bln_spare_list_front == NULL) - bln_spare_list_back = NULL; - pp->p_next = NULL; - return (pp); -} - -/* - * NOTE: We currently do not support growing beyond the boot memory size, - * so the following function will not be called. It is left in here with - * the hope that someday this restriction can be lifted, and this code can - * be used. - */ - -/* - * This structure is placed at the start of every block of new pages - */ -typedef struct { - struct memseg memseg; - struct memlist memlist; - page_t pages[1]; -} mem_structs_t; - -/* - * To make the math below slightly less confusing, we calculate the first - * two parts here. page_t's are handled separately, so they are not included. - */ -#define MEM_STRUCT_SIZE (sizeof (struct memseg) + sizeof (struct memlist)) - -/* - * We want to add memory, but have no spare page_t structures. Use some of - * our new memory for the page_t structures. - * - * Somewhat similar to kphysm_add_memory_dynamic(), but simpler. - */ -static int -balloon_init_new_pages(mfn_t framelist[], pgcnt_t count) -{ - pgcnt_t metapgs, totalpgs, num_pages; - paddr_t metasz; - pfn_t meta_start; - page_t *page_array; - caddr_t va; - int i, rv, locked; - mem_structs_t *mem; - struct memseg *segp; - - /* Calculate the number of pages we're going to add */ - totalpgs = bln_stats.bln_new_target - bln_stats.bln_current_pages; - - /* - * The following calculates the number of "meta" pages -- the pages - * that will be required to hold page_t structures for all new pages. - * Proof of this calculation is left up to the reader. - */ - metapgs = totalpgs - (((uint64_t)(totalpgs) << PAGESHIFT) / - (PAGESIZE + sizeof (page_t))); - - /* - * Given the number of page_t structures we need, is there also - * room in our meta pages for a memseg and memlist struct? - * If not, we'll need one more meta page. - */ - if ((metapgs << PAGESHIFT) < (totalpgs * sizeof (page_t) + - MEM_STRUCT_SIZE)) - metapgs++; - - /* - * metapgs is calculated from totalpgs, which may be much larger than - * count. If we don't have enough pages, all of the pages in this - * batch will be made meta pages, and a future trip through - * balloon_inc_reservation() will add the rest of the meta pages. - */ - if (metapgs > count) - metapgs = count; - - /* - * Figure out the number of page_t structures that can fit in metapgs - * - * This will cause us to initialize more page_t structures than we - * need - these may be used in future memory increases. - */ - metasz = pfn_to_pa(metapgs); - num_pages = (metasz - MEM_STRUCT_SIZE) / sizeof (page_t); - - DTRACE_PROBE3(balloon__alloc__stats, pgcnt_t, totalpgs, pgcnt_t, - num_pages, pgcnt_t, metapgs); - - /* - * We only increment mfn_count by count, not num_pages, to keep the - * space of all valid pfns contiguous. This means we create page_t - * structures with invalid pagenums -- we deal with this situation - * in balloon_page_sub. - */ - mfn_count += count; - - /* - * Get a VA for the pages that will hold page_t and other structures. - * The memseg and memlist structures will go at the beginning, with - * the page_t structures following. - */ - va = (caddr_t)vmem_alloc(heap_arena, metasz, VM_SLEEP); - /* LINTED: improper alignment */ - mem = (mem_structs_t *)va; - page_array = mem->pages; - - meta_start = bln_stats.bln_max_pages; - - /* - * Set the mfn to pfn mapping for the meta pages. - */ - locked = balloon_lock_contig_pfnlist(metapgs); - for (i = 0; i < metapgs; i++) { - reassign_pfn(bln_stats.bln_max_pages + i, framelist[i]); - } - if (locked) - unlock_contig_pfnlist(); - - /* - * For our meta pages, map them in and zero the page. - * This will be the first time touching the new pages. - */ - hat_devload(kas.a_hat, va, metasz, bln_stats.bln_max_pages, - PROT_READ | PROT_WRITE, - HAT_LOAD | HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST); - bzero(va, metasz); - - /* - * Initialize the page array for the new pages. - */ - for (i = 0; i < metapgs; i++) { - page_array[i].p_pagenum = bln_stats.bln_max_pages++; - page_array[i].p_offset = (uoff_t)-1; - page_iolock_init(&page_array[i]); - rv = page_lock(&page_array[i], SE_EXCL, NULL, P_NO_RECLAIM); - ASSERT(rv == 1); - } - - /* - * For the rest of the pages, initialize the page_t struct and - * add them to the free list - */ - for (i = metapgs; i < num_pages; i++) { - page_array[i].p_pagenum = bln_stats.bln_max_pages++; - page_array[i].p_offset = (uoff_t)-1; - page_iolock_init(&page_array[i]); - rv = page_lock(&page_array[i], SE_EXCL, NULL, P_NO_RECLAIM); - ASSERT(rv == 1); - balloon_page_add(&page_array[i]); - } - - /* - * Remember where I said that we don't call this function? The missing - * code right here is why. We need to set up kpm mappings for any new - * pages coming in. However, if someone starts up a domain with small - * memory, then greatly increases it, we could get in some horrible - * deadlock situations as we steal page tables for kpm use, and - * userland applications take them right back before we can use them - * to set up our new memory. Once a way around that is found, and a - * few other changes are made, we'll be able to enable this code. - */ - - /* - * Update kernel structures, part 1: memsegs list - */ - mem->memseg.pages_base = meta_start; - mem->memseg.pages_end = bln_stats.bln_max_pages - 1; - mem->memseg.pages = &page_array[0]; - mem->memseg.epages = &page_array[num_pages - 1]; - mem->memseg.next = NULL; - memsegs_lock(1); - for (segp = memsegs; segp->next != NULL; segp = segp->next) - ; - segp->next = &mem->memseg; - memsegs_unlock(1); - - /* - * Update kernel structures, part 2: mem_node array - */ - mem_node_add_slice(meta_start, bln_stats.bln_max_pages); - - /* - * Update kernel structures, part 3: phys_install array - * (*sigh* how many of these things do we need?) - */ - memlist_write_lock(); - memlist_add(pfn_to_pa(meta_start), num_pages, &mem->memlist, - &phys_install); - memlist_write_unlock(); - - build_pfn_hash(); - - return (metapgs); -} - -/* How many ulong_t's can we fit on a page? */ -#define FRAME_ARRAY_SIZE (PAGESIZE / sizeof (ulong_t)) - -/* - * These are too large to declare on the stack, so we make them static instead - */ -static ulong_t mfn_frames[FRAME_ARRAY_SIZE]; -static pfn_t pfn_frames[FRAME_ARRAY_SIZE]; - -/* - * This function is called when our reservation is increasing. Make a - * hypervisor call to get our new pages, then integrate them into the system. - */ -static spgcnt_t -balloon_inc_reservation(ulong_t credit) -{ - int i, cnt, locked; - int meta_pg_start, meta_pg_end; - long rv; - page_t *pp; - page_t *new_list_front, *new_list_back; - - /* Make sure we're single-threaded. */ - ASSERT(MUTEX_HELD(&bln_mutex)); - - rv = 0; - new_list_front = new_list_back = NULL; - meta_pg_start = meta_pg_end = 0; - bzero(mfn_frames, PAGESIZE); - - if (credit > FRAME_ARRAY_SIZE) - credit = FRAME_ARRAY_SIZE; - - xen_block_migrate(); - rv = balloon_alloc_pages(credit, mfn_frames); - - if (rv < 0) { - xen_allow_migrate(); - return (0); - } - for (i = 0; i < rv; i++) { - if (mfn_frames[i] > new_high_mfn) - new_high_mfn = mfn_frames[i]; - - pp = balloon_page_sub(); - if (pp == NULL) { - /* - * We pass the index into the current mfn array, - * then move the counter past the mfns we used - */ - meta_pg_start = i; - cnt = balloon_init_new_pages(&mfn_frames[i], rv - i); - i += cnt; - meta_pg_end = i; - if (i < rv) { - pp = balloon_page_sub(); - } else { - ASSERT(i == rv); - } - } - if (pp == NULL) { - break; - } - - if (new_list_back == NULL) { - new_list_front = new_list_back = pp; - } else { - new_list_back->p_next = pp; - new_list_back = pp; - } - pp->p_next = NULL; - } - cnt = i; - locked = balloon_lock_contig_pfnlist(cnt); - for (i = 0, pp = new_list_front; i < meta_pg_start; - i++, pp = pp->p_next) { - reassign_pfn(pp->p_pagenum, mfn_frames[i]); - } - for (i = meta_pg_end; i < cnt; i++, pp = pp->p_next) { - reassign_pfn(pp->p_pagenum, mfn_frames[i]); - } - if (locked) - unlock_contig_pfnlist(); - - /* - * Make sure we don't allow pages without pfn->mfn mappings - * into the system. - */ - ASSERT(pp == NULL); - - while (new_list_front != NULL) { - pp = new_list_front; - new_list_front = pp->p_next; - page_free(pp, 1); - } - - /* - * Variable review: at this point, rv contains the number of pages - * the hypervisor gave us. cnt contains the number of pages for which - * we had page_t structures. i contains the number of pages - * where we set up pfn <-> mfn mappings. If this ASSERT trips, that - * means we somehow lost page_t's from our local list. - */ - ASSERT(cnt == i); - if (cnt < rv) { - /* - * We couldn't get page structures. - * - * This shouldn't happen, but causes no real harm if it does. - * On debug kernels, we'll flag it. On all kernels, we'll - * give back the pages we couldn't assign. - * - * Since these pages are new to the system and haven't been - * used, we don't bother zeroing them. - */ -#ifdef DEBUG - cmn_err(CE_WARN, "Could only assign %d of %ld pages", cnt, rv); -#endif /* DEBUG */ - - (void) balloon_free_pages(rv - cnt, &mfn_frames[i], NULL, NULL); - - rv = cnt; - } - - xen_allow_migrate(); - page_unresv(rv - (meta_pg_end - meta_pg_start)); - return (rv); -} - -/* - * This function is called when we want to decrease the memory reservation - * of our domain. Allocate the memory and make a hypervisor call to give - * it back. - */ -static spgcnt_t -balloon_dec_reservation(ulong_t debit) -{ - int i, locked; - long rv; - ulong_t request; - page_t *pp; - - bzero(mfn_frames, sizeof (mfn_frames)); - bzero(pfn_frames, sizeof (pfn_frames)); - - if (debit > FRAME_ARRAY_SIZE) { - debit = FRAME_ARRAY_SIZE; - } - request = debit; - - /* - * Don't bother if there isn't a safe amount of kmem left. - */ - if (kmem_avail() < balloon_minkmem) { - kmem_reap(); - if (kmem_avail() < balloon_minkmem) - return (0); - } - - if (page_resv(request, KM_NOSLEEP) == 0) { - return (0); - } - xen_block_migrate(); - for (i = 0; i < debit; i++) { - pp = page_get_high_mfn(new_high_mfn); - new_high_mfn = 0; - if (pp == NULL) { - /* - * Call kmem_reap(), then try once more, - * but only if there is a safe amount of - * kmem left. - */ - kmem_reap(); - if (kmem_avail() < balloon_minkmem || - (pp = page_get_high_mfn(0)) == NULL) { - debit = i; - break; - } - } - ASSERT(PAGE_EXCL(pp)); - ASSERT(!hat_page_is_mapped(pp)); - - balloon_page_add(pp); - pfn_frames[i] = pp->p_pagenum; - mfn_frames[i] = pfn_to_mfn(pp->p_pagenum); - } - if (debit == 0) { - xen_allow_migrate(); - page_unresv(request); - return (0); - } - - /* - * We zero all the pages before we start reassigning them in order to - * minimize the time spent holding the lock on the contig pfn list. - */ - if (balloon_zero_memory) { - for (i = 0; i < debit; i++) { - pfnzero(pfn_frames[i], 0, PAGESIZE); - } - } - - /* - * Remove all mappings for the pfns from the system - */ - locked = balloon_lock_contig_pfnlist(debit); - for (i = 0; i < debit; i++) { - reassign_pfn(pfn_frames[i], MFN_INVALID); - } - if (locked) - unlock_contig_pfnlist(); - - rv = balloon_free_pages(debit, mfn_frames, NULL, NULL); - - if (rv < 0) { - cmn_err(CE_WARN, "Attempt to return pages to the hypervisor " - "failed - up to %lu pages lost (error = %ld)", debit, rv); - rv = 0; - } else if (rv != debit) { - panic("Unexpected return value (%ld) from decrease reservation " - "hypervisor call", rv); - } - - xen_allow_migrate(); - if (debit != request) - page_unresv(request - debit); - return (rv); -} - -/* - * This function is the callback which is called when the memory/target - * node is changed. When it is fired, we will read a new reservation - * target for our domain and signal the worker thread to make the change. - * - * If the reservation is larger than we can handle, we issue a warning. dom0 - * does this automatically every boot, so we skip the first warning on dom0. - */ -/*ARGSUSED*/ -static void -balloon_handler(struct xenbus_watch *watch, const char **vec, uint_t len) -{ - ulong_t new_target_kb; - pgcnt_t new_target_pages; - int rv; - static uchar_t warning_cnt = 0; - - rv = xenbus_scanf(0, "memory", "target", "%lu", &new_target_kb); - if (rv != 0) { - return; - } - - /* new_target is in kB - change this to pages */ - new_target_pages = kbtop(new_target_kb); - - DTRACE_PROBE1(balloon__new__target, pgcnt_t, new_target_pages); - - /* - * Unfortunately, dom0 may give us a target that is larger than - * our max limit. Re-check the limit, and, if the new target is - * too large, adjust it downwards. - */ - mutex_enter(&bln_mutex); - if (new_target_pages > bln_stats.bln_max_pages) { - DTRACE_PROBE2(balloon__target__too__large, pgcnt_t, - new_target_pages, pgcnt_t, bln_stats.bln_max_pages); - if (!DOMAIN_IS_INITDOMAIN(xen_info) || warning_cnt != 0) { - cmn_err(CE_WARN, "New balloon target (0x%lx pages) is " - "larger than original memory size (0x%lx pages). " - "Ballooning beyond original memory size is not " - "allowed.", - new_target_pages, bln_stats.bln_max_pages); - } - warning_cnt = 1; - bln_stats.bln_new_target = bln_stats.bln_max_pages; - } else { - bln_stats.bln_new_target = new_target_pages; - } - - mutex_exit(&bln_mutex); - cv_signal(&bln_cv); -} - -/* - * bln_wait_sec can be used to throttle the hv calls, but by default it's - * turned off. If a balloon attempt fails, the wait time is forced on, and - * then is exponentially increased as further attempts fail. - */ -uint_t bln_wait_sec = 0; -uint_t bln_wait_shift = 1; - -/* - * This is the main balloon thread. Wait on the cv. When woken, if our - * reservation has changed, call the appropriate function to adjust the - * reservation. - */ -static void -balloon_worker_thread(void) -{ - uint_t bln_wait; - callb_cpr_t cprinfo; - spgcnt_t rv; - - bln_wait = bln_wait_sec; - - CALLB_CPR_INIT(&cprinfo, &bln_mutex, callb_generic_cpr, "balloon"); - for (;;) { - rv = 0; - - mutex_enter(&bln_mutex); - CALLB_CPR_SAFE_BEGIN(&cprinfo); - if (bln_stats.bln_new_target != bln_stats.bln_current_pages) { - /* - * We weren't able to fully complete the request - * last time through, so try again. - */ - (void) cv_reltimedwait(&bln_cv, &bln_mutex, - (bln_wait * hz), TR_CLOCK_TICK); - } else { - cv_wait(&bln_cv, &bln_mutex); - } - CALLB_CPR_SAFE_END(&cprinfo, &bln_mutex); - - if (bln_stats.bln_new_target != bln_stats.bln_current_pages) { - if (bln_stats.bln_new_target < - bln_stats.bln_current_pages) { - /* reservation shrunk */ - rv = -balloon_dec_reservation( - bln_stats.bln_current_pages - - bln_stats.bln_new_target); - } else if (bln_stats.bln_new_target > - bln_stats.bln_current_pages) { - /* reservation grew */ - rv = balloon_inc_reservation( - bln_stats.bln_new_target - - bln_stats.bln_current_pages); - } - } - if (rv == 0) { - if (bln_wait == 0) { - bln_wait = 1; - } else { - bln_wait <<= bln_wait_shift; - } - } else { - bln_stats.bln_current_pages += rv; - bln_wait = bln_wait_sec; - } - if (bln_stats.bln_current_pages < bln_stats.bln_low) - bln_stats.bln_low = bln_stats.bln_current_pages; - else if (bln_stats.bln_current_pages > bln_stats.bln_high) - bln_stats.bln_high = bln_stats.bln_current_pages; - mutex_exit(&bln_mutex); - } -} - -/* - * Called after balloon_init(), which is below. The xenbus thread is up - * and running, so we can register our watch and create the balloon thread. - */ -static void -balloon_config_watch(int state) -{ - if (state != XENSTORE_UP) - return; - - bln_watch.node = "memory/target"; - bln_watch.callback = balloon_handler; - if (register_xenbus_watch(&bln_watch)) { - cmn_err(CE_WARN, "Failed to register balloon watcher; balloon " - "thread will be disabled"); - return; - } - - if (bln_thread == NULL) - bln_thread = thread_create(NULL, 0, balloon_worker_thread, - NULL, 0, &p0, TS_RUN, minclsyspri); -} - -/* - * Basic initialization of the balloon thread. Set all of our variables, - * and register a callback for later when we can register a xenbus watch. - */ -void -balloon_init(pgcnt_t nr_pages) -{ - domid_t domid = DOMID_SELF; - - bln_stats.bln_current_pages = bln_stats.bln_low = nr_pages; - bln_stats.bln_new_target = bln_stats.bln_high = nr_pages; - bln_stats.bln_max_pages = nr_pages; - cv_init(&bln_cv, NULL, CV_DEFAULT, NULL); - - bln_stats.bln_hard_limit = (spgcnt_t)HYPERVISOR_memory_op( - XENMEM_maximum_reservation, &domid); - - (void) xs_register_xenbus_callback(balloon_config_watch); -} - -/* - * These functions are called from the network drivers when they gain a page - * or give one away. We simply update our count. Note that the counter - * tracks the number of pages we give away, so we need to subtract any - * amount passed to balloon_drv_added. - */ -void -balloon_drv_added(int64_t delta) -{ - atomic_add_long((ulong_t *)&bln_stats.bln_hv_pages, -delta); -} - -void -balloon_drv_subtracted(int64_t delta) -{ - atomic_add_long((ulong_t *)&bln_stats.bln_hv_pages, delta); -} - -/* - * balloon_alloc_pages() - * Allocate page_cnt mfns. mfns storage provided by the caller. Returns - * the number of pages allocated, which could be less than page_cnt, or - * a negative number if an error occurred. - */ -long -balloon_alloc_pages(uint_t page_cnt, mfn_t *mfns) -{ - xen_memory_reservation_t memres; - long rv; - - bzero(&memres, sizeof (memres)); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(memres.extent_start, mfns); - memres.domid = DOMID_SELF; - memres.nr_extents = page_cnt; - - rv = HYPERVISOR_memory_op(XENMEM_increase_reservation, &memres); - if (rv > 0) - atomic_add_long((ulong_t *)&bln_stats.bln_hv_pages, -rv); - return (rv); -} - -/* - * balloon_free_pages() - * free page_cnt pages, using any combination of mfns, pfns, and kva as long - * as they refer to the same mapping. If an array of mfns is passed in, we - * assume they were already cleared. Otherwise, we need to zero the pages - * before giving them back to the hypervisor. kva space is not free'd up in - * case the caller wants to re-use it. - */ -long -balloon_free_pages(uint_t page_cnt, mfn_t *mfns, caddr_t kva, pfn_t *pfns) -{ - xen_memory_reservation_t memdec; - mfn_t mfn; - pfn_t pfn; - uint_t i; - long e; - - -#if DEBUG - /* make sure kva is page aligned and maps to first pfn */ - if (kva != NULL) { - ASSERT(((uintptr_t)kva & PAGEOFFSET) == 0); - if (pfns != NULL) { - ASSERT(hat_getpfnum(kas.a_hat, kva) == pfns[0]); - } - } -#endif - - /* if we have a kva, we can clean all pages with just one bzero */ - if ((kva != NULL) && balloon_zero_memory) { - bzero(kva, (page_cnt * PAGESIZE)); - } - - /* if we were given a kva and/or a pfn */ - if ((kva != NULL) || (pfns != NULL)) { - - /* - * All the current callers only pass 1 page when using kva or - * pfns, and use mfns when passing multiple pages. If that - * assumption is changed, the following code will need some - * work. The following ASSERT() guarantees we're respecting - * the io locking quota. - */ - ASSERT(page_cnt < bln_contig_list_quota); - - /* go through all the pages */ - for (i = 0; i < page_cnt; i++) { - - /* get the next pfn */ - if (pfns == NULL) { - pfn = hat_getpfnum(kas.a_hat, - (kva + (PAGESIZE * i))); - } else { - pfn = pfns[i]; - } - - /* - * if we didn't already zero this page, do it now. we - * need to do this *before* we give back the MFN - */ - if ((kva == NULL) && (balloon_zero_memory)) { - pfnzero(pfn, 0, PAGESIZE); - } - - /* - * unmap the pfn. We don't free up the kva vmem space - * so the caller can re-use it. The page must be - * unmapped before it is given back to the hypervisor. - */ - if (kva != NULL) { - hat_unload(kas.a_hat, (kva + (PAGESIZE * i)), - PAGESIZE, HAT_UNLOAD_UNMAP); - } - - /* grab the mfn before the pfn is marked as invalid */ - mfn = pfn_to_mfn(pfn); - - /* mark the pfn as invalid */ - reassign_pfn(pfn, MFN_INVALID); - - /* - * if we weren't given an array of MFNs, we need to - * free them up one at a time. Otherwise, we'll wait - * until later and do it in one hypercall - */ - if (mfns == NULL) { - bzero(&memdec, sizeof (memdec)); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(memdec.extent_start, &mfn); - memdec.domid = DOMID_SELF; - memdec.nr_extents = 1; - e = HYPERVISOR_memory_op( - XENMEM_decrease_reservation, &memdec); - if (e != 1) { - cmn_err(CE_PANIC, "balloon: unable to " - "give a page back to the " - "hypervisor.\n"); - } - } - } - } - - /* - * if we were passed in MFNs, we haven't free'd them up yet. We can - * do it with one call. - */ - if (mfns != NULL) { - bzero(&memdec, sizeof (memdec)); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(memdec.extent_start, mfns); - memdec.domid = DOMID_SELF; - memdec.nr_extents = page_cnt; - e = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &memdec); - if (e != page_cnt) { - cmn_err(CE_PANIC, "balloon: unable to give pages back " - "to the hypervisor.\n"); - } - } - - atomic_add_long((ulong_t *)&bln_stats.bln_hv_pages, page_cnt); - return (page_cnt); -} - - -/* - * balloon_replace_pages() - * Try to replace nextexts blocks of 2^order pages. addr_bits specifies - * how many bits of address the pages must be within (i.e. 16 would mean - * that the pages cannot have an address > 64k). The constrints are on - * what the hypervisor gives us -- we are free to give any pages in - * exchange. The array pp is the pages we are giving away. The caller - * provides storage space for mfns, which hold the new physical pages. - */ -long -balloon_replace_pages(uint_t nextents, page_t **pp, uint_t addr_bits, - uint_t order, mfn_t *mfns) -{ - xen_memory_reservation_t memres; - long fallback_cnt; - long cnt; - uint_t i, j, page_cnt, extlen; - long e; - int locked; - - - /* - * we shouldn't be allocating constrained pages on a guest. It doesn't - * make any sense. They won't be constrained after a migration. - */ - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - extlen = 1 << order; - page_cnt = nextents * extlen; - /* Give back the current pages to the hypervisor */ - for (i = 0; i < page_cnt; i++) { - cnt = balloon_free_pages(1, NULL, NULL, &pp[i]->p_pagenum); - if (cnt != 1) { - cmn_err(CE_PANIC, "balloon: unable to give a page back " - "to the hypervisor.\n"); - } - } - - /* - * try to allocate the new pages using addr_bits and order. If we can't - * get all of the pages, try to get the remaining pages with no - * constraints and, if that was successful, return the number of - * constrained pages we did allocate. - */ - bzero(&memres, sizeof (memres)); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(memres.extent_start, mfns); - memres.domid = DOMID_SELF; - memres.nr_extents = nextents; - memres.mem_flags = XENMEMF_address_bits(addr_bits); - memres.extent_order = order; - cnt = HYPERVISOR_memory_op(XENMEM_increase_reservation, &memres); - /* assign the new MFNs to the current PFNs */ - locked = balloon_lock_contig_pfnlist(cnt * extlen); - for (i = 0; i < cnt; i++) { - for (j = 0; j < extlen; j++) { - reassign_pfn(pp[i * extlen + j]->p_pagenum, - mfns[i] + j); - } - } - if (locked) - unlock_contig_pfnlist(); - if (cnt != nextents) { - if (cnt < 0) { - cnt = 0; - } - - /* - * We couldn't get enough memory to satisfy our requirements. - * The above loop will assign the parts of the request that - * were successful (this part may be 0). We need to fill - * in the rest. The bzero below clears out extent_order and - * address_bits, so we'll take anything from the hypervisor - * to replace the pages we gave away. - */ - fallback_cnt = page_cnt - cnt * extlen; - bzero(&memres, sizeof (memres)); - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(memres.extent_start, mfns); - memres.domid = DOMID_SELF; - memres.nr_extents = fallback_cnt; - e = HYPERVISOR_memory_op(XENMEM_increase_reservation, &memres); - if (e != fallback_cnt) { - cmn_err(CE_PANIC, "balloon: unable to recover from " - "failed increase_reservation.\n"); - } - locked = balloon_lock_contig_pfnlist(fallback_cnt); - for (i = 0; i < fallback_cnt; i++) { - uint_t offset = page_cnt - fallback_cnt; - - /* - * We already used pp[0...(cnt * extlen)] before, - * so start at the next entry in the pp array. - */ - reassign_pfn(pp[i + offset]->p_pagenum, mfns[i]); - } - if (locked) - unlock_contig_pfnlist(); - } - - /* - * balloon_free_pages increments our counter. Decrement it here. - */ - atomic_add_long((ulong_t *)&bln_stats.bln_hv_pages, -(long)page_cnt); - - /* - * return the number of extents we were able to replace. If we got - * this far, we know all the pp's are valid. - */ - return (cnt); -} - - -/* - * Called from the driver - return the requested stat. - */ -size_t -balloon_values(int cmd) -{ - switch (cmd) { - case BLN_IOCTL_CURRENT: - return (ptokb(bln_stats.bln_current_pages)); - case BLN_IOCTL_TARGET: - return (ptokb(bln_stats.bln_new_target)); - case BLN_IOCTL_LOW: - return (ptokb(bln_stats.bln_low)); - case BLN_IOCTL_HIGH: - return (ptokb(bln_stats.bln_high)); - case BLN_IOCTL_LIMIT: - return (ptokb(bln_stats.bln_hard_limit)); - default: - panic("Unexpected cmd %d in balloon_values()\n", cmd); - } - /*NOTREACHED*/ -} diff --git a/usr/src/uts/i86xpv/os/evtchn.c b/usr/src/uts/i86xpv/os/evtchn.c deleted file mode 100644 index ef68c16437..0000000000 --- a/usr/src/uts/i86xpv/os/evtchn.c +++ /dev/null @@ -1,1605 +0,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. - */ - -/* - * evtchn.c - * - * Communication via hypervisor event channels. - * - * Copyright (c) 2002-2005, K A Fraser - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -/* some parts derived from netbsd's hypervisor_machdep.c 1.2.2.2 */ - -/* - * - * Copyright (c) 2004 Christian Limpach. - * 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. - * 3. This section intentionally left blank. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - */ -/* - * Section 3 of the above license was updated in response to bug 6379571. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This file manages our association between hypervisor event channels and - * Solaris's IRQs. This is a one-to-one mapping, with the exception of - * IPI IRQs, for which there is one event channel per CPU participating - * in the IPI, and the clock VIRQ which also has an event channel per cpu - * and the IRQ for /dev/xen/evtchn. The IRQ types are: - * - * IRQT_VIRQ: - * The hypervisor's standard virtual IRQ, used for the clock timer, for - * example. This code allows any cpu to bind to one of these, although - * some are treated specially (i.e. VIRQ_DEBUG). - * Event channel binding is done via EVTCHNOP_bind_virq. - * - * IRQT_PIRQ: - * These associate a physical IRQ with an event channel via - * EVTCHNOP_bind_pirq. - * - * IRQT_IPI: - * A cross-call IRQ. Maps to "ncpus" event channels, each of which is - * bound to exactly one of the vcpus. We do not currently support - * unbinding of IPIs (since Solaris doesn't need it). Uses - * EVTCHNOP_bind_ipi. - * - * IRQT_EVTCHN: - * A "normal" binding to an event channel, typically used by the frontend - * drivers to bind to the their backend event channel. - * - * IRQT_DEV_EVTCHN: - * This is a one-time IRQ used by /dev/xen/evtchn. Unlike other IRQs, we - * have a one-IRQ to many-evtchn mapping. We only track evtchn->irq for - * these event channels, which are managed via ec_irq_add/rm_evtchn(). - * We enforce that IRQT_DEV_EVTCHN's representative evtchn (->ii_evtchn) - * is zero, and make any calls to irq_evtchn() an error, to prevent - * accidentally attempting to use the illegal evtchn 0. - * - * Suspend/resume - * - * During a suspend/resume cycle, we need to tear down the event channels. - * All other mapping data is kept. The drivers will remove their own event - * channels via xendev on receiving a DDI_SUSPEND. This leaves us with - * the IPIs and VIRQs, which we handle in ec_suspend() and ec_resume() - * below. - * - * CPU binding - * - * When an event channel is bound to a CPU, we set a bit in a mask present - * in the machcpu (evt_affinity) to indicate that this CPU can accept this - * event channel. For both IPIs and VIRQs, this binding is fixed at - * allocation time and we never modify it. All other event channels are - * bound via the PSM either as part of add_avintr(), or interrupt - * redistribution (xen_psm_dis/enable_intr()) as a result of CPU - * offline/online. - * - * Locking - * - * Updates are done holding the ec_lock. The xen_callback_handler() - * routine reads the mapping data in a lockless fashion. Additionally - * suspend takes ec_lock to prevent update races during a suspend/resume - * cycle. The IPI info is also examined without the lock; this is OK - * since we only ever change IPI info during initial setup and resume. - */ - -#define IRQ_IS_CPUPOKE(irq) (ipi_info[XC_CPUPOKE_PIL].mi_irq == (irq)) - -#define EVTCHN_MASKED(ev) \ - (HYPERVISOR_shared_info->evtchn_mask[(ev) >> EVTCHN_SHIFT] & \ - (1ul << ((ev) & ((1ul << EVTCHN_SHIFT) - 1)))) - -static short evtchn_to_irq[NR_EVENT_CHANNELS]; -static cpuset_t evtchn_cpus[NR_EVENT_CHANNELS]; -static int evtchn_owner[NR_EVENT_CHANNELS]; -#ifdef DEBUG -static kthread_t *evtchn_owner_thread[NR_EVENT_CHANNELS]; -#endif - -static irq_info_t irq_info[NR_IRQS]; -static mec_info_t ipi_info[MAXIPL]; -static mec_info_t virq_info[NR_VIRQS]; - -/* - * See the locking description above. - */ -kmutex_t ec_lock; - -/* - * Bitmap indicating which PIRQs require the hypervisor to be notified - * on unmask. - */ -static unsigned long pirq_needs_eoi[NR_PIRQS / (sizeof (unsigned long) * NBBY)]; - -static int ec_debug_irq = INVALID_IRQ; -int ec_dev_irq = INVALID_IRQ; - -int -xen_bind_virq(unsigned int virq, processorid_t cpu, int *port) -{ - evtchn_bind_virq_t bind; - int err; - - bind.virq = virq; - bind.vcpu = cpu; - if ((err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &bind)) == 0) - *port = bind.port; - 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; - 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); -} - -int -xen_alloc_unbound_evtchn(int domid, int *evtchnp) -{ - evtchn_alloc_unbound_t alloc; - int err; - - alloc.dom = DOMID_SELF; - alloc.remote_dom = 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) ec_mask_evtchn(*evtchnp); - } else { - err = xen_xlate_errcode(err); - } - - return (err); -} - -static int -xen_close_evtchn(int evtchn) -{ - evtchn_close_t close; - int err; - - close.port = evtchn; - err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); - if (err) - err = xen_xlate_errcode(err); - return (err); -} - -static int -xen_bind_ipi(processorid_t cpu) -{ - evtchn_bind_ipi_t bind; - - ASSERT(MUTEX_HELD(&ec_lock)); - - bind.vcpu = cpu; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind) != 0) - panic("xen_bind_ipi() failed"); - return (bind.port); -} - -/* Send future instances of this interrupt to other vcpu. */ -static void -xen_bind_vcpu(int evtchn, int cpu) -{ - evtchn_bind_vcpu_t bind; - - ASSERT(MUTEX_HELD(&ec_lock)); - - bind.port = evtchn; - bind.vcpu = cpu; - if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind) != 0) - panic("xen_bind_vcpu() failed"); -} - -static int -xen_bind_pirq(int pirq) -{ - evtchn_bind_pirq_t bind; - int ret; - - bind.pirq = pirq; - bind.flags = BIND_PIRQ__WILL_SHARE; - if ((ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind)) != 0) - panic("xen_bind_pirq() failed (err %d)", ret); - return (bind.port); -} - -/* unmask an evtchn and send upcall to appropriate vcpu if pending bit is set */ -static void -xen_evtchn_unmask(int evtchn) -{ - evtchn_unmask_t unmask; - - unmask.port = evtchn; - if (HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask) != 0) - panic("xen_evtchn_unmask() failed"); -} - -static void -update_evtchn_affinity(int evtchn) -{ - cpu_t *cp; - struct xen_evt_data *cpe; - - ASSERT(evtchn_to_irq[evtchn] != INVALID_IRQ); - ASSERT(MUTEX_HELD(&ec_lock)); - - /* - * Use lockless search of cpu_list, similar to mutex_vector_enter(). - */ - kpreempt_disable(); - cp = cpu_list; - do { - cpe = cp->cpu_m.mcpu_evt_pend; - if (CPU_IN_SET(evtchn_cpus[evtchn], cp->cpu_id)) - SET_EVTCHN_BIT(evtchn, cpe->evt_affinity); - else - CLEAR_EVTCHN_BIT(evtchn, cpe->evt_affinity); - } while ((cp = cp->cpu_next) != cpu_list); - kpreempt_enable(); -} - -static void -bind_evtchn_to_cpuset(int evtchn, cpuset_t cpus) -{ - ASSERT(evtchn_to_irq[evtchn] != INVALID_IRQ); - - CPUSET_ZERO(evtchn_cpus[evtchn]); - CPUSET_OR(evtchn_cpus[evtchn], cpus); - update_evtchn_affinity(evtchn); -} - -static void -clear_evtchn_affinity(int evtchn) -{ - CPUSET_ZERO(evtchn_cpus[evtchn]); - update_evtchn_affinity(evtchn); -} - -static void -alloc_irq_evtchn(int irq, int index, int evtchn, int cpu) -{ - irq_info_t *irqp = &irq_info[irq]; - - switch (irqp->ii_type) { - case IRQT_IPI: - ipi_info[index].mi_evtchns[cpu] = evtchn; - irqp->ii_u.index = index; - break; - case IRQT_VIRQ: - virq_info[index].mi_evtchns[cpu] = evtchn; - irqp->ii_u.index = index; - break; - default: - irqp->ii_u.evtchn = evtchn; - break; - } - - evtchn_to_irq[evtchn] = irq; - - /* - * If a CPU is not specified, we expect to bind it to a CPU later via - * the PSM. - */ - if (cpu != -1) { - cpuset_t tcpus; - CPUSET_ONLY(tcpus, cpu); - bind_evtchn_to_cpuset(evtchn, tcpus); - } -} - -static int -alloc_irq(int type, int index, int evtchn, int cpu) -{ - int irq; - irq_info_t *irqp; - - ASSERT(MUTEX_HELD(&ec_lock)); - ASSERT(type != IRQT_IPI || cpu != -1); - - for (irq = 0; irq < NR_IRQS; irq++) { - if (irq_info[irq].ii_type == IRQT_UNBOUND) - break; - } - - if (irq == NR_IRQS) - panic("No available IRQ to bind to: increase NR_IRQS!\n"); - - irqp = &irq_info[irq]; - - irqp->ii_type = type; - /* - * Set irq/has_handler field to zero which means handler not installed - */ - irqp->ii_u2.has_handler = 0; - - alloc_irq_evtchn(irq, index, evtchn, cpu); - return (irq); -} - -static int -irq_evtchn(irq_info_t *irqp) -{ - int evtchn; - - ASSERT(irqp->ii_type != IRQT_DEV_EVTCHN); - - switch (irqp->ii_type) { - case IRQT_IPI: - ASSERT(irqp->ii_u.index != 0); - evtchn = ipi_info[irqp->ii_u.index].mi_evtchns[CPU->cpu_id]; - break; - case IRQT_VIRQ: - evtchn = virq_info[irqp->ii_u.index].mi_evtchns[CPU->cpu_id]; - break; - default: - evtchn = irqp->ii_u.evtchn; - break; - } - - return (evtchn); -} - -int -ec_is_edge_pirq(int irq) -{ - return (irq_info[irq].ii_type == IRQT_PIRQ && - !TEST_EVTCHN_BIT(irq, &pirq_needs_eoi[0])); -} - -static void -unbind_evtchn(ushort_t *evtchnp) -{ - int err; - - ASSERT(MUTEX_HELD(&ec_lock)); - - ASSERT(*evtchnp != 0); - - err = xen_close_evtchn(*evtchnp); - ASSERT(err == 0); - clear_evtchn_affinity(*evtchnp); - evtchn_to_irq[*evtchnp] = INVALID_IRQ; - *evtchnp = 0; -} - -static void -pirq_unmask_notify(int pirq) -{ - struct physdev_eoi eoi; - - if (TEST_EVTCHN_BIT(pirq, &pirq_needs_eoi[0])) { - eoi.irq = pirq; - (void) HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); - } -} - -static void -pirq_query_unmask(int pirq) -{ - struct physdev_irq_status_query irq_status; - - irq_status.irq = pirq; - (void) HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status); - CLEAR_EVTCHN_BIT(pirq, &pirq_needs_eoi[0]); - if (irq_status.flags & XENIRQSTAT_needs_eoi) - SET_EVTCHN_BIT(pirq, &pirq_needs_eoi[0]); -} - -static void -end_pirq(int irq) -{ - int evtchn = irq_evtchn(&irq_info[irq]); - - /* - * If it is an edge-triggered interrupt we have already unmasked - */ - if (TEST_EVTCHN_BIT(irq, &pirq_needs_eoi[0])) { - ec_unmask_evtchn(evtchn); - pirq_unmask_notify(IRQ_TO_PIRQ(irq)); - } -} - -/* - * Bind an event channel to a vcpu - */ -void -ec_bind_vcpu(int evtchn, int cpu) -{ - mutex_enter(&ec_lock); - xen_bind_vcpu(evtchn, cpu); - mutex_exit(&ec_lock); -} - -/* - * Set up a physical device irq to be associated with an event channel. - */ -void -ec_setup_pirq(int irq, int ipl, cpuset_t *cpusp) -{ - int evtchn; - irq_info_t *irqp = &irq_info[irq]; - - /* - * Test if this PIRQ is already bound to an evtchn, - * which means it is a shared IRQ and we don't want to - * bind and do some initial setup that has already been - * done for this irq on a previous trip through this code. - */ - if (irqp->ii_u.evtchn == INVALID_EVTCHN) { - evtchn = xen_bind_pirq(irq); - - pirq_query_unmask(IRQ_TO_PIRQ(irq)); - - irqp->ii_type = IRQT_PIRQ; - irqp->ii_u.evtchn = evtchn; - - evtchn_to_irq[evtchn] = irq; - irqp->ii_u2.ipl = ipl; - ec_set_irq_affinity(irq, *cpusp); - ec_enable_irq(irq); - pirq_unmask_notify(IRQ_TO_PIRQ(irq)); - } else { - ASSERT(irqp->ii_u2.ipl != 0); - cmn_err(CE_NOTE, "!IRQ%d is shared", irq); - if (ipl > irqp->ii_u2.ipl) - irqp->ii_u2.ipl = ipl; - *cpusp = evtchn_cpus[irqp->ii_u.evtchn]; - } -} - -void -ec_unbind_irq(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - mec_info_t *virqp; - int drop_lock = 0; - int type, i; - - /* - * Nasty, but we need this during suspend. - */ - if (mutex_owner(&ec_lock) != curthread) { - mutex_enter(&ec_lock); - drop_lock = 1; - } - - type = irqp->ii_type; - - ASSERT((type == IRQT_EVTCHN) || (type == IRQT_PIRQ) || - (type == IRQT_VIRQ)); - - if ((type == IRQT_EVTCHN) || (type == IRQT_PIRQ)) { - /* There's only one event channel associated with this irq */ - unbind_evtchn(&irqp->ii_u.evtchn); - } else if (type == IRQT_VIRQ) { - /* - * Each cpu on the system can have it's own event channel - * associated with a virq. Unbind them all. - */ - virqp = &virq_info[irqp->ii_u.index]; - for (i = 0; i < NCPU; i++) { - if (virqp->mi_evtchns[i] != 0) - unbind_evtchn(&virqp->mi_evtchns[i]); - } - /* Mark the virq structure as invalid. */ - virqp->mi_irq = INVALID_IRQ; - } - - bzero(irqp, sizeof (*irqp)); - /* Re-reserve PIRQ. */ - if (type == IRQT_PIRQ) - irqp->ii_type = IRQT_PIRQ; - - if (drop_lock) - mutex_exit(&ec_lock); -} - -/* - * Rebind an event channel for delivery to a CPU. - */ -void -ec_set_irq_affinity(int irq, cpuset_t dest) -{ - int evtchn, tcpu; - irq_info_t *irqp = &irq_info[irq]; - - mutex_enter(&ec_lock); - - ASSERT(irq < NR_IRQS); - ASSERT(irqp->ii_type != IRQT_UNBOUND); - - /* - * Binding is done at allocation time for these types, so we should - * never modify them. - */ - if (irqp->ii_type == IRQT_IPI || irqp->ii_type == IRQT_VIRQ || - irqp->ii_type == IRQT_DEV_EVTCHN) { - mutex_exit(&ec_lock); - return; - } - - CPUSET_FIND(dest, tcpu); - ASSERT(tcpu != CPUSET_NOTINSET); - - evtchn = irq_evtchn(irqp); - - xen_bind_vcpu(evtchn, tcpu); - - bind_evtchn_to_cpuset(evtchn, dest); - - mutex_exit(&ec_lock); - - /* - * Now send the new target processor a NOP IPI. - * It will check for any pending interrupts, and so service any that - * got delivered to the wrong processor by mistake. - */ - if (ncpus > 1) - poke_cpu(tcpu); -} - -int -ec_set_irq_priority(int irq, int pri) -{ - irq_info_t *irqp; - - if (irq >= NR_IRQS) - return (-1); - - irqp = &irq_info[irq]; - - if (irqp->ii_type == IRQT_UNBOUND) - return (-1); - - irqp->ii_u2.ipl = pri; - - return (0); -} - -void -ec_clear_irq_priority(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - - ASSERT(irq < NR_IRQS); - ASSERT(irqp->ii_type != IRQT_UNBOUND); - - irqp->ii_u2.ipl = 0; -} - -int -ec_bind_evtchn_to_irq(int evtchn) -{ - mutex_enter(&ec_lock); - - ASSERT(evtchn_to_irq[evtchn] == INVALID_IRQ); - - (void) alloc_irq(IRQT_EVTCHN, 0, evtchn, -1); - - mutex_exit(&ec_lock); - return (evtchn_to_irq[evtchn]); -} - -int -ec_bind_virq_to_irq(int virq, int cpu) -{ - int err; - int evtchn; - mec_info_t *virqp; - - virqp = &virq_info[virq]; - mutex_enter(&ec_lock); - - err = xen_bind_virq(virq, cpu, &evtchn); - ASSERT(err == 0); - - ASSERT(evtchn_to_irq[evtchn] == INVALID_IRQ); - - if (virqp->mi_irq == INVALID_IRQ) { - virqp->mi_irq = alloc_irq(IRQT_VIRQ, virq, evtchn, cpu); - } else { - alloc_irq_evtchn(virqp->mi_irq, virq, evtchn, cpu); - } - - mutex_exit(&ec_lock); - - return (virqp->mi_irq); -} - -int -ec_bind_ipi_to_irq(int ipl, int cpu) -{ - int evtchn; - ulong_t flags; - mec_info_t *ipip; - - mutex_enter(&ec_lock); - - ipip = &ipi_info[ipl]; - - evtchn = xen_bind_ipi(cpu); - - ASSERT(evtchn_to_irq[evtchn] == INVALID_IRQ); - - if (ipip->mi_irq == INVALID_IRQ) { - ipip->mi_irq = alloc_irq(IRQT_IPI, ipl, evtchn, cpu); - } else { - alloc_irq_evtchn(ipip->mi_irq, ipl, evtchn, cpu); - } - - /* - * Unmask the new evtchn so that it can be seen by the target cpu - */ - flags = intr_clear(); - ec_unmask_evtchn(evtchn); - intr_restore(flags); - - mutex_exit(&ec_lock); - return (ipip->mi_irq); -} - -/* - * When bringing up a CPU, bind to all the IPIs that CPU0 bound. - */ -void -ec_bind_cpu_ipis(int cpu) -{ - int i; - - for (i = 0; i < MAXIPL; i++) { - mec_info_t *ipip = &ipi_info[i]; - if (ipip->mi_irq == INVALID_IRQ) - continue; - - (void) ec_bind_ipi_to_irq(i, cpu); - } -} - -/* - * Can this IRQ be rebound to another CPU? - */ -int -ec_irq_rebindable(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - - if (irqp->ii_u.evtchn == 0) - return (0); - - return (irqp->ii_type == IRQT_EVTCHN || irqp->ii_type == IRQT_PIRQ); -} - -/* - * Should this IRQ be unbound from this CPU (which is being offlined) to - * another? - */ -int -ec_irq_needs_rebind(int irq, int cpu) -{ - irq_info_t *irqp = &irq_info[irq]; - - return (ec_irq_rebindable(irq) && - CPU_IN_SET(evtchn_cpus[irqp->ii_u.evtchn], cpu)); -} - -void -ec_send_ipi(int ipl, int cpu) -{ - mec_info_t *ipip = &ipi_info[ipl]; - - ASSERT(ipip->mi_irq != INVALID_IRQ); - - ec_notify_via_evtchn(ipip->mi_evtchns[cpu]); -} - -void -ec_try_ipi(int ipl, int cpu) -{ - mec_info_t *ipip = &ipi_info[ipl]; - - if (ipip->mi_irq == INVALID_IRQ || ipip->mi_irq == 0) - return; - - ec_notify_via_evtchn(ipip->mi_evtchns[cpu]); -} - -void -ec_irq_add_evtchn(int irq, int evtchn) -{ - mutex_enter(&ec_lock); - - /* - * See description of IRQT_DEV_EVTCHN above. - */ - ASSERT(irq == ec_dev_irq); - - alloc_irq_evtchn(irq, 0, evtchn, 0); - /* - * We enforce that the representative event channel for IRQT_DEV_EVTCHN - * is zero, so PSM operations on it have no effect. - */ - irq_info[irq].ii_u.evtchn = 0; - mutex_exit(&ec_lock); -} - -void -ec_irq_rm_evtchn(int irq, int evtchn) -{ - ushort_t ec = evtchn; - - mutex_enter(&ec_lock); - ASSERT(irq == ec_dev_irq); - unbind_evtchn(&ec); - mutex_exit(&ec_lock); -} - -/* - * Allocate an /dev/xen/evtchn IRQ. See the big comment at the top - * for an explanation. - */ -int -ec_dev_alloc_irq(void) -{ - int i; - irq_info_t *irqp; - - for (i = 0; i < NR_IRQS; i++) { - if (irq_info[i].ii_type == IRQT_UNBOUND) - break; - } - - ASSERT(i != NR_IRQS); - - irqp = &irq_info[i]; - irqp->ii_type = IRQT_DEV_EVTCHN; - irqp->ii_u2.ipl = IPL_EVTCHN; - /* - * Force the evtchn to zero for the special evtchn device irq - */ - irqp->ii_u.evtchn = 0; - return (i); -} - -void -ec_enable_irq(unsigned int irq) -{ - ulong_t flag; - irq_info_t *irqp = &irq_info[irq]; - - if (irqp->ii_type == IRQT_DEV_EVTCHN) - return; - - flag = intr_clear(); - ec_unmask_evtchn(irq_evtchn(irqp)); - intr_restore(flag); -} - -void -ec_disable_irq(unsigned int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - - if (irqp->ii_type == IRQT_DEV_EVTCHN) - return; - - /* - * Spin till we are the one to mask the evtchn - * Ensures no one else can be servicing this evtchn. - */ - while (!ec_mask_evtchn(irq_evtchn(irqp))) - SMT_PAUSE(); -} - -static int -ec_evtchn_pending(uint_t ev) -{ - uint_t evi; - shared_info_t *si = HYPERVISOR_shared_info; - - evi = ev >> EVTCHN_SHIFT; - ev &= (1ul << EVTCHN_SHIFT) - 1; - return ((si->evtchn_pending[evi] & (1ul << ev)) != 0); -} - -int -ec_pending_irq(unsigned int irq) -{ - int evtchn = irq_evtchn(&irq_info[irq]); - - return (ec_evtchn_pending(evtchn)); -} - -void -ec_clear_irq(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - int evtchn; - - if (irqp->ii_type == IRQT_DEV_EVTCHN) - return; - - ASSERT(irqp->ii_type != IRQT_UNBOUND); - - evtchn = irq_evtchn(irqp); - - ASSERT(EVTCHN_MASKED(evtchn)); - ec_clear_evtchn(evtchn); -} - -void -ec_unmask_irq(int irq) -{ - ulong_t flags; - irq_info_t *irqp = &irq_info[irq]; - - flags = intr_clear(); - switch (irqp->ii_type) { - case IRQT_PIRQ: - end_pirq(irq); - break; - case IRQT_DEV_EVTCHN: - break; - default: - ec_unmask_evtchn(irq_evtchn(irqp)); - break; - } - intr_restore(flags); -} - -void -ec_try_unmask_irq(int irq) -{ - ulong_t flags; - irq_info_t *irqp = &irq_info[irq]; - int evtchn; - - flags = intr_clear(); - switch (irqp->ii_type) { - case IRQT_PIRQ: - end_pirq(irq); - break; - case IRQT_DEV_EVTCHN: - break; - default: - if ((evtchn = irq_evtchn(irqp)) != 0) - ec_unmask_evtchn(evtchn); - break; - } - intr_restore(flags); -} - -/* - * Poll until an event channel is ready or 'check_func' returns true. This can - * only be used in a situation where interrupts are masked, otherwise we have a - * classic time-of-check vs. time-of-use race. - */ -void -ec_wait_on_evtchn(int evtchn, int (*check_func)(void *), void *arg) -{ - if (DOMAIN_IS_INITDOMAIN(xen_info)) { - while (!check_func(arg)) - (void) HYPERVISOR_yield(); - return; - } - - ASSERT(CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask != 0); - - for (;;) { - evtchn_port_t ports[1]; - - ports[0] = evtchn; - - ec_clear_evtchn(evtchn); - - if (check_func(arg)) - return; - - (void) HYPERVISOR_poll(ports, 1, 0); - } -} - -void -ec_wait_on_ipi(int ipl, int (*check_func)(void *), void *arg) -{ - mec_info_t *ipip = &ipi_info[ipl]; - - if (ipip->mi_irq == INVALID_IRQ || ipip->mi_irq == 0) - return; - - ec_wait_on_evtchn(ipip->mi_evtchns[CPU->cpu_id], check_func, arg); -} - -void -ec_suspend(void) -{ - irq_info_t *irqp; - ushort_t *evtchnp; - int i; - int c; - - ASSERT(MUTEX_HELD(&ec_lock)); - - for (i = 0; i < MAXIPL; i++) { - if (ipi_info[i].mi_irq == INVALID_IRQ) - continue; - - for (c = 0; c < NCPU; c++) { - if (cpu[c] == NULL) - continue; - - if (CPU_IN_SET(cpu_suspend_lost_set, c)) - continue; - - evtchnp = &ipi_info[i].mi_evtchns[c]; - ASSERT(*evtchnp != 0); - unbind_evtchn(evtchnp); - } - } - - for (i = 0; i < NR_VIRQS; i++) { - if (virq_info[i].mi_irq == INVALID_IRQ) - continue; - - /* - * If we're sharing a single event channel across all CPUs, we - * should only unbind once. - */ - if (virq_info[i].mi_shared) { - evtchnp = &virq_info[i].mi_evtchns[0]; - unbind_evtchn(evtchnp); - for (c = 1; c < NCPU; c++) - virq_info[i].mi_evtchns[c] = 0; - } else { - for (c = 0; c < NCPU; c++) { - if (cpu[c] == NULL) - continue; - - evtchnp = &virq_info[i].mi_evtchns[c]; - if (*evtchnp != 0) - unbind_evtchn(evtchnp); - } - } - } - - for (i = 0; i < NR_IRQS; i++) { - irqp = &irq_info[i]; - - switch (irqp->ii_type) { - case IRQT_EVTCHN: - case IRQT_DEV_EVTCHN: - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - break; - case IRQT_PIRQ: - if (irqp->ii_u.evtchn != 0) - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - break; - default: - break; - } - } -} - -/* - * The debug irq is special, we only have one evtchn and irq but we allow all - * cpus to service it. It's marked as shared and we propogate the event - * channel into all CPUs by hand. - */ -static void -share_virq(mec_info_t *virqp) -{ - int evtchn = virqp->mi_evtchns[0]; - cpuset_t tset; - int i; - - ASSERT(evtchn != 0); - - virqp->mi_shared = 1; - - for (i = 1; i < NCPU; i++) - virqp->mi_evtchns[i] = evtchn; - CPUSET_ALL(tset); - bind_evtchn_to_cpuset(evtchn, tset); -} - -static void -virq_resume(int virq) -{ - mec_info_t *virqp = &virq_info[virq]; - int evtchn; - int i, err; - - for (i = 0; i < NCPU; i++) { - cpuset_t tcpus; - - if (cpu[i] == NULL || CPU_IN_SET(cpu_suspend_lost_set, i)) - continue; - - err = xen_bind_virq(virq, i, &evtchn); - ASSERT(err == 0); - - virqp->mi_evtchns[i] = evtchn; - evtchn_to_irq[evtchn] = virqp->mi_irq; - CPUSET_ONLY(tcpus, i); - bind_evtchn_to_cpuset(evtchn, tcpus); - ec_unmask_evtchn(evtchn); - /* - * only timer VIRQ is bound to all cpus - */ - if (virq != VIRQ_TIMER) - break; - } - - if (virqp->mi_shared) - share_virq(virqp); -} - -static void -ipi_resume(int ipl) -{ - mec_info_t *ipip = &ipi_info[ipl]; - int i; - - for (i = 0; i < NCPU; i++) { - cpuset_t tcpus; - int evtchn; - - if (cpu[i] == NULL || CPU_IN_SET(cpu_suspend_lost_set, i)) - continue; - - evtchn = xen_bind_ipi(i); - ipip->mi_evtchns[i] = evtchn; - evtchn_to_irq[evtchn] = ipip->mi_irq; - CPUSET_ONLY(tcpus, i); - bind_evtchn_to_cpuset(evtchn, tcpus); - ec_unmask_evtchn(evtchn); - } -} - -void -ec_resume(void) -{ - int i; - - /* New event-channel space is not 'live' yet. */ - for (i = 0; i < NR_EVENT_CHANNELS; i++) - (void) ec_mask_evtchn(i); - - for (i = 0; i < MAXIPL; i++) { - if (ipi_info[i].mi_irq == INVALID_IRQ) - continue; - ipi_resume(i); - } - - for (i = 0; i < NR_VIRQS; i++) { - if (virq_info[i].mi_irq == INVALID_IRQ) - continue; - virq_resume(i); - } -} - -int -ec_init(void) -{ - int i; - mutex_init(&ec_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL7)); - - for (i = 0; i < NR_EVENT_CHANNELS; i++) { - CPUSET_ZERO(evtchn_cpus[i]); - evtchn_to_irq[i] = INVALID_IRQ; - (void) ec_mask_evtchn(i); - } - - for (i = 0; i < MAXIPL; i++) - ipi_info[i].mi_irq = INVALID_IRQ; - - for (i = 0; i < NR_VIRQS; i++) - virq_info[i].mi_irq = INVALID_IRQ; - - /* - * Phys IRQ space is statically bound (1:1 mapping), grab the IRQs - * now. - */ - for (i = PIRQ_BASE; i < NR_PIRQS; i++) { - irq_info[PIRQ_TO_IRQ(i)].ii_type = IRQT_PIRQ; - } - - return (0); -} - -void -ec_init_debug_irq() -{ - int irq; - - irq = ec_bind_virq_to_irq(VIRQ_DEBUG, 0); - (void) add_avintr(NULL, IPL_DEBUG, (avfunc)xen_debug_handler, - "debug", irq, NULL, NULL, NULL, NULL); - - mutex_enter(&ec_lock); - share_virq(&virq_info[irq_info[irq].ii_u.index]); - mutex_exit(&ec_lock); - ec_debug_irq = irq; -} - -#define UNBLOCKED_EVENTS(si, ix, cpe, cpu_id) \ - ((si)->evtchn_pending[ix] & ~(si)->evtchn_mask[ix] & \ - (cpe)->evt_affinity[ix]) - - -/* - * This is the entry point for processing events from xen - * - * (See the commentary associated with the shared_info_st structure - * in hypervisor-if.h) - * - * Since the event channel mechanism doesn't really implement the - * concept of priority like hardware interrupt controllers, we simulate - * that in software here using the cpu priority field and the pending - * interrupts field. Events/interrupts that are not able to be serviced - * now because they are at a lower priority than the current cpu priority - * cause a level bit to be recorded in the pending interrupts word. When - * the priority is lowered (either by spl or interrupt exit code) the pending - * levels are checked and an upcall is scheduled if there are events/interrupts - * that have become deliverable. - */ -void -xen_callback_handler(struct regs *rp, trap_trace_rec_t *ttp) -{ - ulong_t pending_sels, pe, selbit; - int i, j, port, pri, curpri, irq, sipri; - uint16_t pending_ints, sip; - struct cpu *cpu = CPU; - volatile shared_info_t *si = HYPERVISOR_shared_info; - volatile vcpu_info_t *vci = cpu->cpu_m.mcpu_vcpu_info; - volatile struct xen_evt_data *cpe = cpu->cpu_m.mcpu_evt_pend; - volatile uint16_t *cpu_ipp = &cpu->cpu_m.mcpu_intr_pending; - extern void dosoftint(struct regs *); - - ASSERT(rp->r_trapno == T_AST && rp->r_err == 0); - ASSERT(&si->vcpu_info[cpu->cpu_id] == vci); - ASSERT_STACK_ALIGNED(); - - vci->evtchn_upcall_pending = 0; - - /* - * To expedite scanning of pending notifications, any 0->1 - * pending transition on an unmasked channel causes a - * corresponding bit in evtchn_pending_sel to be set. - * Each bit in the selector covers a 32-bit word in - * the evtchn_pending[] array. - */ - membar_enter(); - do { - pending_sels = vci->evtchn_pending_sel; - } while (atomic_cas_ulong((volatile ulong_t *)&vci->evtchn_pending_sel, - pending_sels, 0) != pending_sels); - - pending_ints = *cpu_ipp; - while ((i = ffs(pending_sels)) != 0) { - i--; - selbit = 1ul << i; - pending_sels &= ~selbit; - - membar_enter(); - while ((pe = UNBLOCKED_EVENTS(si, i, cpe, cpu->cpu_id)) != 0) { - j = ffs(pe) - 1; - pe &= ~(1ul << j); - - port = (i << EVTCHN_SHIFT) + j; - - irq = evtchn_to_irq[port]; - - /* - * If no irq set, just ignore the event. - * On e.g. netbsd they call evtchn_device_upcall(port) - * We require the evtchn driver to install a handler - * so there will be an irq associated with user mode - * evtchns. - */ - if (irq == INVALID_IRQ) { - ec_clear_evtchn(port); - continue; - } - - /* - * If there's no handler, it could be a poke, so just - * accept the event and continue. - */ - if (!irq_info[irq].ii_u2.has_handler) { -#ifdef TRAPTRACE - ttp->ttr_ipl = 0xff; - if (IRQ_IS_CPUPOKE(irq)) { - ttp->ttr_ipl = XC_CPUPOKE_PIL; - ttp->ttr_marker = TT_INTERRUPT; - } - ttp->ttr_pri = cpu->cpu_pri; - ttp->ttr_spl = cpu->cpu_base_spl; - ttp->ttr_vector = 0xff; -#endif /* TRAPTRACE */ - if (ec_mask_evtchn(port)) { - ec_clear_evtchn(port); - ec_unmask_evtchn(port); - continue; - } - } - - pri = irq_info[irq].ii_u2.ipl; - - /* - * If we are the cpu that successfully masks - * the event, then record it as a pending event - * for this cpu to service - */ - if (ec_mask_evtchn(port)) { - if (ec_evtchn_pending(port)) { - cpe->pending_sel[pri] |= selbit; - cpe->pending_evts[pri][i] |= (1ul << j); - pending_ints |= 1 << pri; - /* - * We have recorded a pending interrupt - * for this cpu. If it is an edge - * triggered interrupt then we go ahead - * and clear the pending and mask bits - * from the shared info to avoid having - * the hypervisor see the pending event - * again and possibly disabling the - * interrupt. This should also help - * keep us from missing an interrupt. - */ - if (ec_is_edge_pirq(irq)) { - ec_clear_evtchn(port); - ec_unmask_evtchn(port); - } - } else { - /* - * another cpu serviced this event - * before us, clear the mask. - */ - ec_unmask_evtchn(port); - } - } - } - } - *cpu_ipp = pending_ints; - if (pending_ints == 0) - return; - /* - * We have gathered all the pending events/interrupts, - * go service all the ones we can from highest priority to lowest. - * Note: This loop may not actually complete and service all - * pending interrupts since one of the interrupt threads may - * block and the pinned thread runs. In that case, when we - * exit the interrupt thread that blocked we will check for - * any unserviced interrupts and re-post an upcall to process - * any unserviced pending events. - */ -restart: - curpri = cpu->cpu_pri; - pri = bsrw_insn(*cpu_ipp); - while (pri > curpri) { - while ((pending_sels = cpe->pending_sel[pri]) != 0) { - i = ffs(pending_sels) - 1; - while ((pe = cpe->pending_evts[pri][i]) != 0) { - j = ffs(pe) - 1; - port = (i << EVTCHN_SHIFT) + j; - pe &= ~(1ul << j); - cpe->pending_evts[pri][i] = pe; - if (pe == 0) { - /* - * Must reload pending selector bits - * here as they could have changed on - * a previous trip around the inner loop - * while we were interrupt enabled - * in a interrupt service routine. - */ - pending_sels = cpe->pending_sel[pri]; - pending_sels &= ~(1ul << i); - cpe->pending_sel[pri] = pending_sels; - if (pending_sels == 0) - *cpu_ipp &= ~(1 << pri); - } - irq = evtchn_to_irq[port]; - if (irq == INVALID_IRQ) { - /* - * No longer a handler for this event - * channel. Clear the event and - * ignore it, unmask the event. - */ - ec_clear_evtchn(port); - ec_unmask_evtchn(port); - continue; - } - if (irq == ec_dev_irq) { - ASSERT(cpu->cpu_m.mcpu_ec_mbox == 0); - cpu->cpu_m.mcpu_ec_mbox = port; - } - /* - * Set up the regs struct to - * look like a normal hardware int - * and do normal interrupt handling. - */ - rp->r_trapno = irq; - do_interrupt(rp, ttp); - /* - * Check for cpu priority change - * Can happen if int thread blocks - */ - if (cpu->cpu_pri != curpri) - goto restart; - } - } - /* - * Dispatch any soft interrupts that are - * higher priority than any hard ones remaining. - */ - pri = bsrw_insn(*cpu_ipp); - sip = (uint16_t)cpu->cpu_softinfo.st_pending; - if (sip != 0) { - sipri = bsrw_insn(sip); - if (sipri > pri && sipri > cpu->cpu_pri) { - dosoftint(rp); - /* - * Check for cpu priority change - * Can happen if softint thread blocks - */ - if (cpu->cpu_pri != curpri) - goto restart; - } - } - } - /* - * Deliver any pending soft interrupts. - */ - if (cpu->cpu_softinfo.st_pending) - dosoftint(rp); -} - - -void -ec_unmask_evtchn(unsigned int ev) -{ - uint_t evi, evb; - volatile shared_info_t *si = HYPERVISOR_shared_info; - volatile vcpu_info_t *vci = CPU->cpu_m.mcpu_vcpu_info; - volatile ulong_t *ulp; - - ASSERT(!interrupts_enabled()); - /* - * Check if we need to take slow path - */ - if (!CPU_IN_SET(evtchn_cpus[ev], CPU->cpu_id)) { - xen_evtchn_unmask(ev); - return; - } - evi = ev >> EVTCHN_SHIFT; - evb = ev & ((1ul << EVTCHN_SHIFT) - 1); - ulp = (volatile ulong_t *)&si->evtchn_mask[evi]; - atomic_and_ulong(ulp, ~(1ul << evb)); - /* - * The following is basically the equivalent of - * 'hw_resend_irq'. Just like a real IO-APIC we 'lose the - * interrupt edge' if the channel is masked. - * XXPV - slight race if upcall was about to be set, we may get - * an extra upcall. - */ - membar_enter(); - if (si->evtchn_pending[evi] & (1ul << evb)) { - membar_consumer(); - ulp = (volatile ulong_t *)&vci->evtchn_pending_sel; - if (!(*ulp & (1ul << evi))) { - atomic_or_ulong(ulp, (1ul << evi)); - } - vci->evtchn_upcall_pending = 1; - } -} - -/* - * Set a bit in an evtchan mask word, return true if we are the cpu that - * set the bit. - */ -int -ec_mask_evtchn(unsigned int ev) -{ - uint_t evi, evb; - ulong_t new, old, bit; - volatile shared_info_t *si = HYPERVISOR_shared_info; - volatile ulong_t *maskp; - int masked; - - kpreempt_disable(); - evi = ev >> EVTCHN_SHIFT; - evb = ev & ((1ul << EVTCHN_SHIFT) - 1); - bit = 1ul << evb; - maskp = (volatile ulong_t *)&si->evtchn_mask[evi]; - do { - old = si->evtchn_mask[evi]; - new = old | bit; - } while (atomic_cas_ulong(maskp, old, new) != old); - masked = (old & bit) == 0; - if (masked) { - evtchn_owner[ev] = CPU->cpu_id; -#ifdef DEBUG - evtchn_owner_thread[ev] = curthread; -#endif - } - kpreempt_enable(); - return (masked); -} - -void -ec_clear_evtchn(unsigned int ev) -{ - uint_t evi; - shared_info_t *si = HYPERVISOR_shared_info; - volatile ulong_t *pendp; - - evi = ev >> EVTCHN_SHIFT; - ev &= (1ul << EVTCHN_SHIFT) - 1; - pendp = (volatile ulong_t *)&si->evtchn_pending[evi]; - atomic_and_ulong(pendp, ~(1ul << ev)); -} - -void -ec_notify_via_evtchn(unsigned int port) -{ - evtchn_send_t send; - - ASSERT(port != INVALID_EVTCHN); - - send.port = port; - (void) HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); -} - -int -ec_block_irq(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - int evtchn; - - - evtchn = irq_evtchn(irqp); - (void) ec_mask_evtchn(evtchn); - return (evtchn_owner[evtchn]); -} - -/* - * Make a event that is pending for delivery on the current cpu "go away" - * without servicing the interrupt. - */ -void -ec_unpend_irq(int irq) -{ - irq_info_t *irqp = &irq_info[irq]; - int pri = irqp->ii_u2.ipl; - ulong_t flags; - uint_t evtchn, evi, bit; - unsigned long pe, pending_sels; - struct xen_evt_data *cpe; - - /* - * The evtchn must be masked - */ - evtchn = irq_evtchn(irqp); - ASSERT(EVTCHN_MASKED(evtchn)); - evi = evtchn >> EVTCHN_SHIFT; - bit = evtchn & (1ul << EVTCHN_SHIFT) - 1; - flags = intr_clear(); - cpe = CPU->cpu_m.mcpu_evt_pend; - pe = cpe->pending_evts[pri][evi] & ~(1ul << bit); - cpe->pending_evts[pri][evi] = pe; - if (pe == 0) { - pending_sels = cpe->pending_sel[pri]; - pending_sels &= ~(1ul << evi); - cpe->pending_sel[pri] = pending_sels; - if (pending_sels == 0) - CPU->cpu_m.mcpu_intr_pending &= ~(1 << pri); - } - intr_restore(flags); -} diff --git a/usr/src/uts/i86xpv/os/mach_kdi.c b/usr/src/uts/i86xpv/os/mach_kdi.c deleted file mode 100644 index b12d30722d..0000000000 --- a/usr/src/uts/i86xpv/os/mach_kdi.c +++ /dev/null @@ -1,262 +0,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 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Kernel/Debugger Interface (KDI) routines. Called during debugger under - * various system states (boot, while running, while the debugger has control). - * Functions intended for use while the debugger has control may not grab any - * locks or perform any functions that assume the availability of other system - * services. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static volatile int kdi_slaves_go; - -/* - * These are not safe against dropping into kmdb when fbt::: is active. This is - * also broken on i86pc... - */ - -void -kdi_idtr_write(desctbr_t *idtr) -{ - gate_desc_t *idt = (gate_desc_t *)idtr->dtr_base; - uint_t nidt = (idtr->dtr_limit + 1) / sizeof (*idt); - uint_t vec; - - for (vec = 0; vec < nidt; vec++, idt++) - xen_idt_write(idt, vec); -} - -void -kdi_idt_write(gate_desc_t *gate, uint_t vec) -{ - gate_desc_t *idt = CPU->cpu_m.mcpu_idt; - - /* - * See kdi_idtr_set(). - */ - if (idt != NULL) - idt[vec] = *gate; - - xen_idt_write(gate, vec); -} - -ulong_t -kdi_dreg_get(int reg) -{ - return (__hypercall1(__HYPERVISOR_get_debugreg, (long)reg)); -} - -void -kdi_dreg_set(int reg, ulong_t value) -{ - (void) __hypercall2(__HYPERVISOR_set_debugreg, (long)reg, value); -} - -void -kdi_flush_caches(void) -{ -} - -/* - * To avoid domains sucking up CPU while sitting in kmdb, we make all the slave - * CPUs wait for a wake-up evtchn. The master CPU, meanwhile, sleeps for - * console activity. - */ - -extern void kdi_slave_entry(void); - -void -kdi_stop_slaves(int cpu, int doxc) -{ - if (doxc) - kdi_xc_others(cpu, kdi_slave_entry); - kdi_slaves_go = 0; -} - -void -kdi_start_slaves(void) -{ - int c; - - kdi_slaves_go = 1; - - for (c = 0; c < NCPU; c++) { - if (cpu[c] == NULL || !(cpu[c]->cpu_flags & CPU_READY)) - continue; - ec_try_ipi(XC_CPUPOKE_PIL, c); - } -} - -/*ARGSUSED*/ -static int -check_slave(void *arg) -{ - return (kdi_slaves_go == 1); -} - -void -kdi_slave_wait(void) -{ - if (!(cpu[CPU->cpu_id]->cpu_flags & CPU_READY)) - return; - - ec_wait_on_ipi(XC_CPUPOKE_PIL, check_slave, NULL); -} - -/* - * Caution. - * These routines are called -extremely- early, during kmdb initialization. - * - * Many common kernel functions assume that %gs has been initialized, - * and fail horribly if it hasn't. At this point, the boot code has - * reserved a descriptor for us (KMDBGS_SEL) in it's GDT; arrange for it - * to point at a dummy cpu_t, temporarily at least. - * - * Note that kmdb entry relies on the fake cpu_t having zero cpu_idt/cpu_id. - */ - -#if defined(__amd64) - -void * -boot_kdi_tmpinit(void) -{ - cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP); - user_desc_t *bgdt; - uint64_t gdtpa; - ulong_t ma[1]; - - cpu->cpu_self = cpu; - - /* - * (Note that we had better switch to a -new- GDT before - * we discard the KM_TMP mappings, or disaster will ensue.) - */ - bgdt = kobj_zalloc(PAGESIZE, KM_TMP); - ASSERT(((uintptr_t)bgdt & PAGEOFFSET) == 0); - - init_boot_gdt(bgdt); - - gdtpa = pfn_to_pa(va_to_pfn(bgdt)); - ma[0] = (ulong_t)(pa_to_ma(gdtpa) >> PAGESHIFT); - kbm_read_only((uintptr_t)bgdt, gdtpa); - if (HYPERVISOR_set_gdt(ma, PAGESIZE / sizeof (user_desc_t))) - panic("boot_kdi_tmpinit:HYPERVISOR_set_gdt() failed"); - - load_segment_registers(B64CODE_SEL, 0, 0, B32DATA_SEL); - - /* - * Now point %gsbase to our temp cpu structure. - */ - xen_set_segment_base(SEGBASE_GS_KERNEL, (ulong_t)cpu); - return (0); -} - -/*ARGSUSED*/ -void -boot_kdi_tmpfini(void *old) -{ - /* - * This breaks, why do we need it anyway? - */ -#if 0 /* XXPV */ - load_segment_registers(B64CODE_SEL, 0, KMDBGS_SEL, B32DATA_SEL); -#endif -} - -#elif defined(__i386) - -/* - * Sigh. We're called before we've initialized the kernels GDT, living - * off the hypervisor's default GDT. For kmdb's sake, we switch now to - * a GDT that looks like dboot's GDT; very shortly we'll initialize and - * switch to the kernel's GDT. - */ - -void * -boot_kdi_tmpinit(void) -{ - cpu_t *cpu = kobj_zalloc(sizeof (*cpu), KM_TMP); - user_desc_t *bgdt; - uint64_t gdtpa; - ulong_t ma[1]; - - cpu->cpu_self = cpu; - - /* - * (Note that we had better switch to a -new- GDT before - * we discard the KM_TMP mappings, or disaster will ensue.) - */ - bgdt = kobj_zalloc(PAGESIZE, KM_TMP); - - ASSERT(((uintptr_t)bgdt & PAGEOFFSET) == 0); - gdtpa = pfn_to_pa(va_to_pfn(bgdt)); - - init_boot_gdt(bgdt); - - set_usegd(&bgdt[GDT_BGSTMP], - cpu, sizeof (*cpu), SDT_MEMRWA, SEL_KPL, SDP_BYTES, SDP_OP32); - - ma[0] = (ulong_t)(pa_to_ma(gdtpa) >> PAGESHIFT); - kbm_read_only((uintptr_t)bgdt, gdtpa); - if (HYPERVISOR_set_gdt(ma, PAGESIZE / sizeof (user_desc_t))) - panic("boot_kdi_tmpinit:HYPERVISOR_set_gdt() failed"); - - load_segment_registers(B32CODE_SEL, B32DATA_SEL, B32DATA_SEL, 0, - KMDBGS_SEL, B32DATA_SEL); - return (0); -} - -/*ARGSUSED*/ -void -boot_kdi_tmpfini(void *old) -{ - load_segment_registers(B32CODE_SEL, B32DATA_SEL, B32DATA_SEL, 0, - 0, B32DATA_SEL); -} - -#endif /* __i386 */ diff --git a/usr/src/uts/i86xpv/os/mp_xen.c b/usr/src/uts/i86xpv/os/mp_xen.c deleted file mode 100644 index a91834b113..0000000000 --- a/usr/src/uts/i86xpv/os/mp_xen.c +++ /dev/null @@ -1,1057 +0,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. - */ - -/* - * Virtual CPU management. - * - * VCPUs can be controlled in one of two ways; through the domain itself - * (psradm, p_online(), etc.), and via changes in xenstore (vcpu_config()). - * Unfortunately, the terminology is used in different ways; they work out as - * follows: - * - * P_ONLINE: the VCPU is up and running, taking interrupts and running threads - * - * P_OFFLINE: the VCPU is up and running, but quiesced (i.e. blocked in the - * hypervisor on the idle thread). It must be up since a downed VCPU cannot - * receive interrupts, and we require this for offline CPUs in Solaris. - * - * P_POWEROFF: the VCPU is down (we never called xen_vcpu_up(), or called - * xen_vcpu_down() for it). It can't take interrupts or run anything, though - * if it has run previously, its software state (cpu_t, machcpu structures, IPI - * event channels, etc.) will still exist. - * - * The hypervisor has two notions of CPU states as represented in the store: - * - * "offline": the VCPU is down. Corresponds to P_POWEROFF. - * - * "online": the VCPU is running. Corresponds to a CPU state other than - * P_POWEROFF. - * - * Currently, only a notification via xenstore can bring a CPU into a - * P_POWEROFF state, and only the domain can change between P_ONLINE, P_NOINTR, - * P_OFFLINE, etc. We need to be careful to treat xenstore notifications - * idempotently, as we'll get 'duplicate' entries when we resume a domain. - * - * Note that the xenstore configuration is strictly advisory, in that a domain - * can choose to ignore it and still power up a VCPU in the offline state. To - * play nice, we don't allow it. Thus, any attempt to power on/off a CPU is - * ENOTSUP from within Solaris. - * - * Powering off a VCPU and suspending the domain use similar code. The - * difficulty here is that we must ensure that each VCPU is in a stable - * state: it must have a saved PCB, and not be responding to interrupts - * (since we are just about to remove its ability to run on a real CPU, - * possibly forever). However, an offline CPU in Solaris can take - * cross-call interrupts, as mentioned, so we must go through a - * two-stage process. First, we use the standard Solaris pause_cpus(). - * This ensures that all CPUs are either in mach_cpu_pause() or - * mach_cpu_idle(), and nothing will cross-call them. - * - * Powered-off-CPUs are already safe, as we own the cpu_lock needed to - * bring them back up, and in state CPU_PHASE_POWERED_OFF. - * - * Running CPUs are spinning in mach_cpu_pause() waiting for either - * PAUSE_IDLE or CPU_PHASE_WAIT_SAFE. - * - * Offline CPUs are either running the idle thread and periodically - * checking for CPU_PHASE_WAIT_SAFE, or blocked in the hypervisor. - * - * Thus, we set CPU_PHASE_WAIT_SAFE for every powered-on CPU, as well as - * poking them to make sure they're not blocked[1]. When every CPU has - * responded by reaching a safe state and setting CPU_PHASE_SAFE, we - * know we can suspend, or power-off a CPU, without problems. - * - * [1] note that we have to repeatedly poke offline CPUs: it's the only - * way to ensure that the CPU doesn't miss the state change before - * dropping into HYPERVISOR_block(). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -extern cpuset_t cpu_ready_set; - -#define CPU_PHASE_NONE 0 -#define CPU_PHASE_WAIT_SAFE 1 -#define CPU_PHASE_SAFE 2 -#define CPU_PHASE_POWERED_OFF 3 - -/* - * We can only poke CPUs during barrier enter 256 times a second at - * most. - */ -#define POKE_TIMEOUT (NANOSEC / 256) - -static taskq_t *cpu_config_tq; -static int cpu_phase[NCPU]; - -static void vcpu_config_event(struct xenbus_watch *, const char **, uint_t); -static int xen_vcpu_initialize(processorid_t, vcpu_guest_context_t *); - -/* - * Return whether or not the vcpu is actually running on a pcpu - */ -int -vcpu_on_pcpu(processorid_t cpu) -{ - struct vcpu_runstate_info runstate; - int ret = VCPU_STATE_UNKNOWN; - - ASSERT(cpu < NCPU); - /* - * Don't bother with hypercall if we are asking about ourself - */ - if (cpu == CPU->cpu_id) - return (VCPU_ON_PCPU); - if (HYPERVISOR_vcpu_op(VCPUOP_get_runstate_info, cpu, &runstate) != 0) - goto out; - - switch (runstate.state) { - case RUNSTATE_running: - ret = VCPU_ON_PCPU; - break; - - case RUNSTATE_runnable: - case RUNSTATE_offline: - case RUNSTATE_blocked: - ret = VCPU_NOT_ON_PCPU; - break; - - default: - break; - } - -out: - return (ret); -} - -/* - * These routines allocate any global state that might be needed - * while starting cpus. For virtual cpus, there is no such state. - */ -int -mach_cpucontext_init(void) -{ - return (0); -} - -void -do_cpu_config_watch(int state) -{ - static struct xenbus_watch cpu_config_watch; - - if (state != XENSTORE_UP) - return; - cpu_config_watch.node = "cpu"; - cpu_config_watch.callback = vcpu_config_event; - if (register_xenbus_watch(&cpu_config_watch)) { - taskq_destroy(cpu_config_tq); - cmn_err(CE_WARN, "do_cpu_config_watch: " - "failed to set vcpu config watch"); - } - -} - -/* - * This routine is called after all the "normal" MP startup has - * been done; a good place to start watching xen store for virtual - * cpu hot plug events. - */ -void -mach_cpucontext_fini(void) -{ - - cpu_config_tq = taskq_create("vcpu config taskq", 1, - maxclsyspri - 1, 1, 1, TASKQ_PREPOPULATE); - - (void) xs_register_xenbus_callback(do_cpu_config_watch); -} - -/* - * Fill in the remaining CPU context and initialize it. - */ -static int -mp_set_cpu_context(vcpu_guest_context_t *vgc, cpu_t *cp) -{ - uint_t vec, iopl; - - vgc->flags = VGCF_IN_KERNEL; - - /* - * fpu_ctx we leave as zero; on first fault we'll store - * sse_initial into it anyway. - */ - -#if defined(__amd64) - vgc->user_regs.cs = KCS_SEL | SEL_KPL; /* force to ring 3 */ -#else - vgc->user_regs.cs = KCS_SEL; -#endif - vgc->user_regs.ds = KDS_SEL; - vgc->user_regs.es = KDS_SEL; - vgc->user_regs.ss = KDS_SEL; - vgc->kernel_ss = KDS_SEL; - - /* - * Allow I/O privilege level for Dom0 kernel. - */ - if (DOMAIN_IS_INITDOMAIN(xen_info)) - iopl = (PS_IOPL & 0x1000); /* ring 1 */ - else - iopl = 0; - -#if defined(__amd64) - vgc->user_regs.fs = 0; - vgc->user_regs.gs = 0; - vgc->user_regs.rflags = F_OFF | iopl; -#elif defined(__i386) - vgc->user_regs.fs = KFS_SEL; - vgc->user_regs.gs = KGS_SEL; - vgc->user_regs.eflags = F_OFF | iopl; - vgc->event_callback_cs = vgc->user_regs.cs; - vgc->failsafe_callback_cs = vgc->user_regs.cs; -#endif - - /* - * Initialize the trap_info_t from the IDT - */ - ASSERT(NIDT == sizeof (vgc->trap_ctxt) / sizeof (vgc->trap_ctxt[0])); - for (vec = 0; vec < NIDT; vec++) { - trap_info_t *ti = &vgc->trap_ctxt[vec]; - - if (xen_idt_to_trap_info(vec, - &cp->cpu_m.mcpu_idt[vec], ti) == 0) { - ti->cs = KCS_SEL; - ti->vector = vec; - } - } - - /* - * No LDT - */ - - /* - * (We assert in various places that the GDT is (a) aligned on a - * page boundary and (b) one page long, so this really should fit..) - */ -#ifdef CRASH_XEN - vgc->gdt_frames[0] = pa_to_ma(mmu_btop(cp->cpu_m.mcpu_gdtpa)); -#else - vgc->gdt_frames[0] = pfn_to_mfn(mmu_btop(cp->cpu_m.mcpu_gdtpa)); -#endif - vgc->gdt_ents = NGDT; - - vgc->ctrlreg[0] = CR0_ENABLE_FPU_FLAGS(getcr0()); - -#if defined(__i386) - if (mmu.pae_hat) - vgc->ctrlreg[3] = - xen_pfn_to_cr3(pfn_to_mfn(kas.a_hat->hat_htable->ht_pfn)); - else -#endif - vgc->ctrlreg[3] = - pa_to_ma(mmu_ptob(kas.a_hat->hat_htable->ht_pfn)); - - vgc->ctrlreg[4] = getcr4(); - - vgc->event_callback_eip = (uintptr_t)xen_callback; - vgc->failsafe_callback_eip = (uintptr_t)xen_failsafe_callback; - vgc->flags |= VGCF_failsafe_disables_events; - -#if defined(__amd64) - /* - * XXPV should this be moved to init_cpu_syscall? - */ - vgc->syscall_callback_eip = (uintptr_t)sys_syscall; - vgc->flags |= VGCF_syscall_disables_events; - - ASSERT(vgc->user_regs.gs == 0); - vgc->gs_base_kernel = (uintptr_t)cp; -#endif - - return (xen_vcpu_initialize(cp->cpu_id, vgc)); -} - -/* - * Create a guest virtual cpu context so that the virtual cpu - * springs into life in the domain just about to call mp_startup() - * - * Virtual CPUs must be initialized once in the lifetime of the domain; - * after that subsequent attempts to start them will fail with X_EEXIST. - * - * Thus 'alloc' -really- creates and initializes the virtual - * CPU context just once. Once the initialisation succeeds, we never - * free it, nor the regular cpu_t to which it refers. - */ -void * -mach_cpucontext_alloc(struct cpu *cp) -{ - kthread_t *tp = cp->cpu_thread; - vcpu_guest_context_t vgc; - - int err = 1; - - /* - * First, augment the incoming cpu structure - * - vcpu pointer reference - * - pending event storage area - * - physical address of GDT - */ - cp->cpu_m.mcpu_vcpu_info = - &HYPERVISOR_shared_info->vcpu_info[cp->cpu_id]; - cp->cpu_m.mcpu_evt_pend = kmem_zalloc( - sizeof (struct xen_evt_data), KM_SLEEP); - cp->cpu_m.mcpu_gdtpa = - mmu_ptob(hat_getpfnum(kas.a_hat, (caddr_t)cp->cpu_gdt)); - - if ((err = xen_gdt_setprot(cp, PROT_READ)) != 0) - goto done; - - /* - * Now set up the vcpu context so that we can start this vcpu - * in the kernel at tp->t_pc (mp_startup). Note that the - * thread will thread_exit() shortly after performing the - * initialization; in particular, we will *never* take a - * privilege transition on this thread. - */ - - bzero(&vgc, sizeof (vgc)); - -#ifdef __amd64 - vgc.user_regs.rip = tp->t_pc; - vgc.user_regs.rsp = tp->t_sp; - vgc.user_regs.rbp = tp->t_sp - 2 * sizeof (greg_t); -#else - vgc.user_regs.eip = tp->t_pc; - vgc.user_regs.esp = tp->t_sp; - vgc.user_regs.ebp = tp->t_sp - 2 * sizeof (greg_t); -#endif - /* - * XXPV Fix resume, if Russ didn't already fix it. - * - * Note that resume unconditionally puts t->t_stk + sizeof (regs) - * into kernel_sp via HYPERVISOR_stack_switch. This anticipates - * that only lwps take traps that switch to the kernel stack; - * part of creating an lwp adjusts the stack by subtracting - * sizeof (struct regs) off t_stk. - * - * The more interesting question is, why do we do all the work - * of a fully fledged lwp for a plain thread? In particular - * we don't have to call HYPERVISOR_stack_switch for lwp-less threads - * or futz with the LDT. This should probably all be done with - * an lwp context operator to keep pure thread context switch fast. - */ - vgc.kernel_sp = (ulong_t)tp->t_stk; - - err = mp_set_cpu_context(&vgc, cp); - -done: - if (err) { - mach_cpucontext_free(cp, NULL, err); - return (NULL); - } - return (cp); -} - -/* - * By the time we are called either we have successfully started - * the cpu, or our attempt to start it has failed. - */ - -/*ARGSUSED*/ -void -mach_cpucontext_free(struct cpu *cp, void *arg, int err) -{ - switch (err) { - case 0: - break; - case ETIMEDOUT: - /* - * The vcpu context is loaded into the hypervisor, and - * we've tried to start it, but the vcpu has not been set - * running yet, for whatever reason. We arrange to -not- - * free any data structures it may be referencing. In - * particular, we've already told the hypervisor about - * the GDT, and so we can't map it read-write again. - */ - break; - default: - (void) xen_gdt_setprot(cp, PROT_READ | PROT_WRITE); - kmem_free(cp->cpu_m.mcpu_evt_pend, - sizeof (struct xen_evt_data)); - break; - } -} - -/* - * Reset this CPU's context. Clear out any pending evtchn data, since event - * channel numbers will all change when we resume. - */ -void -mach_cpucontext_reset(cpu_t *cp) -{ - bzero(cp->cpu_m.mcpu_evt_pend, sizeof (struct xen_evt_data)); - /* mcpu_intr_pending ? */ -} - -static void -pcb_to_user_regs(label_t *pcb, vcpu_guest_context_t *vgc) -{ -#ifdef __amd64 - vgc->user_regs.rip = pcb->val[REG_LABEL_PC]; - vgc->user_regs.rsp = pcb->val[REG_LABEL_SP]; - vgc->user_regs.rbp = pcb->val[REG_LABEL_BP]; - vgc->user_regs.rbx = pcb->val[REG_LABEL_RBX]; - vgc->user_regs.r12 = pcb->val[REG_LABEL_R12]; - vgc->user_regs.r13 = pcb->val[REG_LABEL_R13]; - vgc->user_regs.r14 = pcb->val[REG_LABEL_R14]; - vgc->user_regs.r15 = pcb->val[REG_LABEL_R15]; -#else /* __amd64 */ - vgc->user_regs.eip = pcb->val[REG_LABEL_PC]; - vgc->user_regs.esp = pcb->val[REG_LABEL_SP]; - vgc->user_regs.ebp = pcb->val[REG_LABEL_BP]; - vgc->user_regs.ebx = pcb->val[REG_LABEL_EBX]; - vgc->user_regs.esi = pcb->val[REG_LABEL_ESI]; - vgc->user_regs.edi = pcb->val[REG_LABEL_EDI]; -#endif /* __amd64 */ -} - -/* - * Restore the context of a CPU during resume. This context is always - * inside enter_safe_phase(), below. - */ -void -mach_cpucontext_restore(cpu_t *cp) -{ - vcpu_guest_context_t vgc; - int err; - - ASSERT(cp->cpu_thread == cp->cpu_pause_thread || - cp->cpu_thread == cp->cpu_idle_thread); - - bzero(&vgc, sizeof (vgc)); - - pcb_to_user_regs(&cp->cpu_thread->t_pcb, &vgc); - - /* - * We're emulating a longjmp() here: in particular, we need to bump the - * stack pointer to account for the pop of xIP that returning from - * longjmp() normally would do, and set the return value in xAX to 1. - */ -#ifdef __amd64 - vgc.user_regs.rax = 1; - vgc.user_regs.rsp += sizeof (ulong_t); -#else - vgc.user_regs.eax = 1; - vgc.user_regs.esp += sizeof (ulong_t); -#endif - - vgc.kernel_sp = cp->cpu_thread->t_sp; - - err = mp_set_cpu_context(&vgc, cp); - - ASSERT(err == 0); -} - -/* - * Reach a point at which the CPU can be safely powered-off or - * suspended. Nothing can wake this CPU out of the loop. - */ -static void -enter_safe_phase(void) -{ - ulong_t flags = intr_clear(); - - if (setjmp(&curthread->t_pcb) == 0) { - cpu_phase[CPU->cpu_id] = CPU_PHASE_SAFE; - while (cpu_phase[CPU->cpu_id] == CPU_PHASE_SAFE) - SMT_PAUSE(); - } - - ASSERT(!interrupts_enabled()); - - intr_restore(flags); -} - -/* - * Offline CPUs run this code even under a pause_cpus(), so we must - * check if we need to enter the safe phase. - */ -void -mach_cpu_idle(void) -{ - if (IN_XPV_PANIC()) { - xpv_panic_halt(); - } else { - (void) HYPERVISOR_block(); - if (cpu_phase[CPU->cpu_id] == CPU_PHASE_WAIT_SAFE) - enter_safe_phase(); - } -} - -/* - * Spin until either start_cpus() wakes us up, or we get a request to - * enter the safe phase (followed by a later start_cpus()). - */ -void -mach_cpu_pause(volatile char *safe) -{ - *safe = PAUSE_WAIT; - membar_enter(); - - while (*safe != PAUSE_IDLE) { - if (cpu_phase[CPU->cpu_id] == CPU_PHASE_WAIT_SAFE) - enter_safe_phase(); - SMT_PAUSE(); - } -} - -void -mach_cpu_halt(char *msg) -{ - if (msg) - prom_printf("%s\n", msg); - (void) xen_vcpu_down(CPU->cpu_id); -} - -/*ARGSUSED*/ -int -mp_cpu_poweron(struct cpu *cp) -{ - return (ENOTSUP); -} - -/*ARGSUSED*/ -int -mp_cpu_poweroff(struct cpu *cp) -{ - return (ENOTSUP); -} - -void -mp_enter_barrier(void) -{ - hrtime_t last_poke_time = 0; - int poke_allowed = 0; - int done = 0; - int i; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - pause_cpus(NULL, NULL); - - while (!done) { - done = 1; - poke_allowed = 0; - - if (xpv_gethrtime() - last_poke_time > POKE_TIMEOUT) { - last_poke_time = xpv_gethrtime(); - poke_allowed = 1; - } - - for (i = 0; i < NCPU; i++) { - cpu_t *cp = cpu_get(i); - - if (cp == NULL || cp == CPU) - continue; - - switch (cpu_phase[i]) { - case CPU_PHASE_NONE: - cpu_phase[i] = CPU_PHASE_WAIT_SAFE; - poke_cpu(i); - done = 0; - break; - - case CPU_PHASE_WAIT_SAFE: - if (poke_allowed) - poke_cpu(i); - done = 0; - break; - - case CPU_PHASE_SAFE: - case CPU_PHASE_POWERED_OFF: - break; - } - } - - SMT_PAUSE(); - } -} - -void -mp_leave_barrier(void) -{ - int i; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - for (i = 0; i < NCPU; i++) { - cpu_t *cp = cpu_get(i); - - if (cp == NULL || cp == CPU) - continue; - - switch (cpu_phase[i]) { - /* - * If we see a CPU in one of these phases, something has - * gone badly wrong with the guarantees - * mp_enter_barrier() is supposed to provide. Rather - * than attempt to stumble along (and since we can't - * panic properly in this context), we tell the - * hypervisor we've crashed. - */ - case CPU_PHASE_NONE: - case CPU_PHASE_WAIT_SAFE: - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - break; - - case CPU_PHASE_POWERED_OFF: - break; - - case CPU_PHASE_SAFE: - cpu_phase[i] = CPU_PHASE_NONE; - } - } - - start_cpus(); -} - -static int -poweroff_vcpu(struct cpu *cp) -{ - int error; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - ASSERT(CPU->cpu_id != cp->cpu_id); - ASSERT(cp->cpu_flags & CPU_QUIESCED); - - mp_enter_barrier(); - - if ((error = xen_vcpu_down(cp->cpu_id)) == 0) { - ASSERT(cpu_phase[cp->cpu_id] == CPU_PHASE_SAFE); - - CPUSET_DEL(cpu_ready_set, cp->cpu_id); - - cp->cpu_flags |= CPU_POWEROFF | CPU_OFFLINE; - cp->cpu_flags &= - ~(CPU_RUNNING | CPU_READY | CPU_EXISTS | CPU_ENABLE); - - cpu_phase[cp->cpu_id] = CPU_PHASE_POWERED_OFF; - - cpu_set_state(cp); - } - - mp_leave_barrier(); - - return (error); -} - -static int -vcpu_config_poweroff(processorid_t id) -{ - int oldstate; - int error; - cpu_t *cp; - - mutex_enter(&cpu_lock); - - if ((cp = cpu_get(id)) == NULL) { - mutex_exit(&cpu_lock); - return (ESRCH); - } - - if (cpu_get_state(cp) == P_POWEROFF) { - mutex_exit(&cpu_lock); - return (0); - } - - mutex_exit(&cpu_lock); - - do { - error = p_online_internal(id, P_OFFLINE, - &oldstate); - - if (error != 0) - break; - - /* - * So we just changed it to P_OFFLINE. But then we dropped - * cpu_lock, so now it is possible for another thread to change - * the cpu back to a different, non-quiesced state e.g. - * P_ONLINE. - */ - mutex_enter(&cpu_lock); - if ((cp = cpu_get(id)) == NULL) - error = ESRCH; - else { - if (cp->cpu_flags & CPU_QUIESCED) - error = poweroff_vcpu(cp); - else - error = EBUSY; - } - mutex_exit(&cpu_lock); - } while (error == EBUSY); - - return (error); -} - -/* - * Add a new virtual cpu to the domain. - */ -static int -vcpu_config_new(processorid_t id) -{ - extern int start_cpu(processorid_t); - int error; - - if (ncpus == 1) { - printf("cannot (yet) add cpus to a single-cpu domain\n"); - return (ENOTSUP); - } - - affinity_set(CPU_CURRENT); - error = start_cpu(id); - affinity_clear(); - return (error); -} - -static int -poweron_vcpu(struct cpu *cp) -{ - int error; - - ASSERT(MUTEX_HELD(&cpu_lock)); - - if (HYPERVISOR_vcpu_op(VCPUOP_is_up, cp->cpu_id, NULL) != 0) { - printf("poweron_vcpu: vcpu%d is not available!\n", - cp->cpu_id); - return (ENXIO); - } - - if ((error = xen_vcpu_up(cp->cpu_id)) == 0) { - CPUSET_ADD(cpu_ready_set, cp->cpu_id); - cp->cpu_flags |= CPU_EXISTS | CPU_READY | CPU_RUNNING; - cp->cpu_flags &= ~CPU_POWEROFF; - /* - * There are some nasty races possible here. - * Tell the vcpu it's up one more time. - * XXPV Is this enough? Is this safe? - */ - (void) xen_vcpu_up(cp->cpu_id); - - cpu_phase[cp->cpu_id] = CPU_PHASE_NONE; - - cpu_set_state(cp); - } - return (error); -} - -static int -vcpu_config_poweron(processorid_t id) -{ - cpu_t *cp; - int oldstate; - int error; - - if (id >= ncpus) - return (vcpu_config_new(id)); - - mutex_enter(&cpu_lock); - - if ((cp = cpu_get(id)) == NULL) { - mutex_exit(&cpu_lock); - return (ESRCH); - } - - if (cpu_get_state(cp) != P_POWEROFF) { - mutex_exit(&cpu_lock); - return (0); - } - - if ((error = poweron_vcpu(cp)) != 0) { - mutex_exit(&cpu_lock); - return (error); - } - - mutex_exit(&cpu_lock); - - return (p_online_internal(id, P_ONLINE, &oldstate)); -} - -#define REPORT_LEN 128 - -static void -vcpu_config_report(processorid_t id, uint_t newstate, int error) -{ - char *report = kmem_alloc(REPORT_LEN, KM_SLEEP); - size_t len; - char *ps; - - switch (newstate) { - case P_ONLINE: - ps = PS_ONLINE; - break; - case P_POWEROFF: - ps = PS_POWEROFF; - break; - default: - cmn_err(CE_PANIC, "unknown state %u\n", newstate); - break; - } - - len = snprintf(report, REPORT_LEN, - "cpu%d: externally initiated %s", id, ps); - - if (!error) { - cmn_err(CE_CONT, "!%s\n", report); - kmem_free(report, REPORT_LEN); - return; - } - - len += snprintf(report + len, REPORT_LEN - len, - " failed, error %d: ", error); - switch (error) { - case EEXIST: - len += snprintf(report + len, REPORT_LEN - len, - "cpu already %s", ps ? ps : "?"); - break; - case ESRCH: - len += snprintf(report + len, REPORT_LEN - len, - "cpu not found"); - break; - case EINVAL: - case EALREADY: - break; - case EPERM: - len += snprintf(report + len, REPORT_LEN - len, - "insufficient privilege (0x%x)", id); - break; - case EBUSY: - switch (newstate) { - case P_ONLINE: - /* - * This return comes from mp_cpu_start - - * we cannot 'start' the boot CPU. - */ - len += snprintf(report + len, REPORT_LEN - len, - "already running"); - break; - case P_POWEROFF: - len += snprintf(report + len, REPORT_LEN - len, - "bound lwps?"); - break; - default: - break; - } - default: - break; - } - - cmn_err(CE_CONT, "%s\n", report); - kmem_free(report, REPORT_LEN); -} - -static void -vcpu_config(void *arg) -{ - int id = (int)(uintptr_t)arg; - int error; - char dir[16]; - char *state; - - if ((uint_t)id >= max_ncpus) { - cmn_err(CE_WARN, - "vcpu_config: cpu%d does not fit in this domain", id); - return; - } - - (void) snprintf(dir, sizeof (dir), "cpu/%d", id); - state = kmem_alloc(MAXPATHLEN, KM_SLEEP); - if (xenbus_scanf(XBT_NULL, dir, "availability", "%s", state) == 0) { - if (strcmp(state, "online") == 0) { - error = vcpu_config_poweron(id); - vcpu_config_report(id, P_ONLINE, error); - } else if (strcmp(state, "offline") == 0) { - error = vcpu_config_poweroff(id); - vcpu_config_report(id, P_POWEROFF, error); - } else { - cmn_err(CE_WARN, - "cpu%d: unknown target state '%s'", id, state); - } - } else - cmn_err(CE_WARN, - "cpu%d: unable to read target state from xenstore", id); - - kmem_free(state, MAXPATHLEN); -} - -/*ARGSUSED*/ -static void -vcpu_config_event(struct xenbus_watch *watch, const char **vec, uint_t len) -{ - const char *path = vec[XS_WATCH_PATH]; - processorid_t id; - char *s; - - if ((s = strstr(path, "cpu/")) != NULL && - sscanf(s, "cpu/%d", &id) == 1) { - /* - * Run the virtual CPU configuration on a separate thread to - * avoid blocking on this event for too long (and for now, - * to ensure configuration requests are serialized.) - */ - (void) taskq_dispatch(cpu_config_tq, - vcpu_config, (void *)(uintptr_t)id, 0); - } -} - -static int -xen_vcpu_initialize(processorid_t id, vcpu_guest_context_t *vgc) -{ - int err; - - if ((err = HYPERVISOR_vcpu_op(VCPUOP_initialise, id, vgc)) != 0) { - char *str; - int level = CE_WARN; - - switch (err) { - case -X_EINVAL: - /* - * This interface squashes multiple error sources - * to one error code. In particular, an X_EINVAL - * code can mean: - * - * - the vcpu id is out of range - * - cs or ss are in ring 0 - * - cr3 is wrong - * - an entry in the new gdt is above the - * reserved entry - * - a frame underneath the new gdt is bad - */ - str = "something is wrong :("; - break; - case -X_ENOENT: - str = "no such cpu"; - break; - case -X_ENOMEM: - str = "no mem to copy ctxt"; - break; - case -X_EFAULT: - str = "bad address"; - break; - case -X_EEXIST: - /* - * Hmm. This error is returned if the vcpu has already - * been initialized once before in the lifetime of this - * domain. This is a logic error in the kernel. - */ - level = CE_PANIC; - str = "already initialized"; - break; - default: - level = CE_PANIC; - str = ""; - break; - } - - cmn_err(level, "vcpu%d: failed to init: error %d: %s", - id, -err, str); - } - return (err); -} - -long -xen_vcpu_up(processorid_t id) -{ - long err; - - if ((err = HYPERVISOR_vcpu_op(VCPUOP_up, id, NULL)) != 0) { - char *str; - - switch (err) { - case -X_ENOENT: - str = "no such cpu"; - break; - case -X_EINVAL: - /* - * Perhaps this is diagnostic overkill. - */ - if (HYPERVISOR_vcpu_op(VCPUOP_is_up, id, NULL) < 0) - str = "bad cpuid"; - else - str = "not initialized"; - break; - default: - str = ""; - break; - } - - printf("vcpu%d: failed to start: error %d: %s\n", - id, -(int)err, str); - return (EBFONT); /* deliberately silly */ - } - return (err); -} - -long -xen_vcpu_down(processorid_t id) -{ - long err; - - if ((err = HYPERVISOR_vcpu_op(VCPUOP_down, id, NULL)) != 0) { - /* - * X_ENOENT: no such cpu - * X_EINVAL: bad cpuid - */ - panic("vcpu%d: failed to stop: error %d", id, -(int)err); - } - - return (err); -} diff --git a/usr/src/uts/i86xpv/os/xen_machdep.c b/usr/src/uts/i86xpv/os/xen_machdep.c deleted file mode 100644 index cf2e0d5241..0000000000 --- a/usr/src/uts/i86xpv/os/xen_machdep.c +++ /dev/null @@ -1,1397 +0,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. - */ - -/* derived from netbsd's xen_machdep.c 1.1.2.1 */ - -/* - * - * Copyright (c) 2004 Christian Limpach. - * 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. - * 3. This section intentionally left blank. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. - */ -/* - * Section 3 of the above license was updated in response to bug 6379571. - */ - -#include - -/* XXX 3.3. TODO remove this 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 -#include -#include -#include -#include -#include - -#ifdef DEBUG -#define SUSPEND_DEBUG if (xen_suspend_debug) xen_printf -#else -#define SUSPEND_DEBUG(...) -#endif - -int cpr_debug; -cpuset_t cpu_suspend_lost_set; -static int xen_suspend_debug; - -uint_t xen_phys_ncpus; -xen_mc_logical_cpu_t *xen_phys_cpus; -int xen_physinfo_debug = 0; - -/* - * Determine helpful version information. - * - * (And leave copies in the data segment so we can look at them later - * with e.g. kmdb.) - */ - -typedef enum xen_version { - XENVER_BOOT_IDX, - XENVER_CURRENT_IDX -} xen_version_t; - -struct xenver { - ulong_t xv_major; - ulong_t xv_minor; - ulong_t xv_revision; - xen_extraversion_t xv_ver; - ulong_t xv_is_xvm; - xen_changeset_info_t xv_chgset; - xen_compile_info_t xv_build; - xen_capabilities_info_t xv_caps; -} xenver[2]; - -#define XENVER_BOOT(m) (xenver[XENVER_BOOT_IDX].m) -#define XENVER_CURRENT(m) (xenver[XENVER_CURRENT_IDX].m) - -/* - * Update the xenver data. We maintain two copies, boot and - * current. If we are setting the boot, then also set current. - */ -static void -xen_set_version(xen_version_t idx) -{ - ulong_t ver; - - bzero(&xenver[idx], sizeof (xenver[idx])); - - ver = HYPERVISOR_xen_version(XENVER_version, 0); - - xenver[idx].xv_major = BITX(ver, 31, 16); - xenver[idx].xv_minor = BITX(ver, 15, 0); - - (void) HYPERVISOR_xen_version(XENVER_extraversion, &xenver[idx].xv_ver); - - /* - * The revision is buried in the extraversion information that is - * maintained by the hypervisor. For our purposes we expect that - * the revision number is: - * - the second character in the extraversion information - * - one character long - * - numeric digit - * If it isn't then we can't extract the revision and we leave it - * set to 0. - */ - if (strlen(xenver[idx].xv_ver) > 1 && isdigit(xenver[idx].xv_ver[1])) - xenver[idx].xv_revision = xenver[idx].xv_ver[1] - '0'; - else - cmn_err(CE_WARN, "Cannot extract revision on this hypervisor " - "version: v%s, unexpected version format", - xenver[idx].xv_ver); - - xenver[idx].xv_is_xvm = 0; - - if (strstr(xenver[idx].xv_ver, "-xvm") != NULL) - xenver[idx].xv_is_xvm = 1; - - (void) HYPERVISOR_xen_version(XENVER_changeset, - &xenver[idx].xv_chgset); - - (void) HYPERVISOR_xen_version(XENVER_compile_info, - &xenver[idx].xv_build); - /* - * Capabilities are a set of space separated ascii strings - * e.g. 'xen-3.1-x86_32p' or 'hvm-3.2-x86_64' - */ - (void) HYPERVISOR_xen_version(XENVER_capabilities, - &xenver[idx].xv_caps); - - cmn_err(CE_CONT, "?v%lu.%lu%s chgset '%s'\n", xenver[idx].xv_major, - xenver[idx].xv_minor, xenver[idx].xv_ver, xenver[idx].xv_chgset); - - if (idx == XENVER_BOOT_IDX) - bcopy(&xenver[XENVER_BOOT_IDX], &xenver[XENVER_CURRENT_IDX], - sizeof (xenver[XENVER_BOOT_IDX])); -} - -typedef enum xen_hypervisor_check { - XEN_RUN_CHECK, - XEN_SUSPEND_CHECK -} xen_hypervisor_check_t; - -/* - * To run the hypervisor must be 3.0.4 or better. To suspend/resume - * we need 3.0.4 or better and if it is 3.0.4. then it must be provided - * by the Solaris xVM project. - * Checking can be disabled for testing purposes by setting the - * xen_suspend_debug variable. - */ -static int -xen_hypervisor_supports_solaris(xen_hypervisor_check_t check) -{ - if (xen_suspend_debug == 1) - return (1); - if (XENVER_CURRENT(xv_major) < 3) - return (0); - if (XENVER_CURRENT(xv_major) > 3) - return (1); - if (XENVER_CURRENT(xv_minor) > 0) - return (1); - if (XENVER_CURRENT(xv_revision) < 4) - return (0); - if (check == XEN_SUSPEND_CHECK && XENVER_CURRENT(xv_revision) == 4 && - !XENVER_CURRENT(xv_is_xvm)) - return (0); - - return (1); -} - -/* - * If the hypervisor is -xvm, or 3.1.2 or higher, we don't need the - * workaround. - */ -static void -xen_pte_workaround(void) -{ -#if defined(__amd64) - extern int pt_kern; - - if (XENVER_CURRENT(xv_major) != 3) - return; - if (XENVER_CURRENT(xv_minor) > 1) - return; - if (XENVER_CURRENT(xv_minor) == 1 && - XENVER_CURRENT(xv_revision) > 1) - return; - if (XENVER_CURRENT(xv_is_xvm)) - return; - - pt_kern = PT_USER; -#endif -} - -void -xen_set_callback(void (*func)(void), uint_t type, uint_t flags) -{ - struct callback_register cb; - - bzero(&cb, sizeof (cb)); -#if defined(__amd64) - cb.address = (ulong_t)func; -#elif defined(__i386) - cb.address.cs = KCS_SEL; - cb.address.eip = (ulong_t)func; -#endif - cb.type = type; - cb.flags = flags; - - /* - * XXPV always ignore return value for NMI - */ - if (HYPERVISOR_callback_op(CALLBACKOP_register, &cb) != 0 && - type != CALLBACKTYPE_nmi) - panic("HYPERVISOR_callback_op failed"); -} - -void -xen_init_callbacks(void) -{ - /* - * register event (interrupt) handler. - */ - xen_set_callback(xen_callback, CALLBACKTYPE_event, 0); - - /* - * failsafe handler. - */ - xen_set_callback(xen_failsafe_callback, CALLBACKTYPE_failsafe, - CALLBACKF_mask_events); - - /* - * NMI handler. - */ - xen_set_callback(nmiint, CALLBACKTYPE_nmi, 0); - - /* - * system call handler - * XXPV move to init_cpu_syscall? - */ -#if defined(__amd64) - xen_set_callback(sys_syscall, CALLBACKTYPE_syscall, - CALLBACKF_mask_events); -#endif /* __amd64 */ -} - - -/* - * cmn_err() followed by a 1/4 second delay; this gives the - * logging service a chance to flush messages and helps avoid - * intermixing output from prom_printf(). - * XXPV: doesn't exactly help us on UP though. - */ -/*PRINTFLIKE2*/ -void -cpr_err(int ce, const char *fmt, ...) -{ - va_list adx; - - va_start(adx, fmt); - vcmn_err(ce, fmt, adx); - va_end(adx); - drv_usecwait(MICROSEC >> 2); -} - -void -xen_suspend_devices(void) -{ - int rc; - - SUSPEND_DEBUG("xen_suspend_devices\n"); - - if ((rc = cpr_suspend_devices(ddi_root_node())) != 0) - panic("failed to suspend devices: %d", rc); -} - -void -xen_resume_devices(void) -{ - int rc; - - SUSPEND_DEBUG("xen_resume_devices\n"); - - if ((rc = cpr_resume_devices(ddi_root_node(), 0)) != 0) - panic("failed to resume devices: %d", rc); -} - -/* - * The list of mfn pages is out of date. Recompute it. - */ -static void -rebuild_mfn_list(void) -{ - int i = 0; - size_t sz; - size_t off; - pfn_t pfn; - - SUSPEND_DEBUG("rebuild_mfn_list\n"); - - sz = ((mfn_count * sizeof (mfn_t)) + MMU_PAGEOFFSET) & MMU_PAGEMASK; - - for (off = 0; off < sz; off += MMU_PAGESIZE) { - size_t j = mmu_btop(off); - if (((j * sizeof (mfn_t)) & MMU_PAGEOFFSET) == 0) { - pfn = hat_getpfnum(kas.a_hat, - (caddr_t)&mfn_list_pages[j]); - mfn_list_pages_page[i++] = pfn_to_mfn(pfn); - } - - pfn = hat_getpfnum(kas.a_hat, (caddr_t)mfn_list + off); - mfn_list_pages[j] = pfn_to_mfn(pfn); - } - - pfn = hat_getpfnum(kas.a_hat, (caddr_t)mfn_list_pages_page); - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list - = pfn_to_mfn(pfn); -} - -static void -suspend_cpus(void) -{ - int i; - - SUSPEND_DEBUG("suspend_cpus\n"); - - mp_enter_barrier(); - - for (i = 1; i < ncpus; i++) { - if (!CPU_IN_SET(cpu_suspend_lost_set, i)) { - SUSPEND_DEBUG("xen_vcpu_down %d\n", i); - (void) xen_vcpu_down(i); - } - - mach_cpucontext_reset(cpu[i]); - } -} - -static void -resume_cpus(void) -{ - int i; - - for (i = 1; i < ncpus; i++) { - if (cpu[i] == NULL) - continue; - - if (!CPU_IN_SET(cpu_suspend_lost_set, i)) { - SUSPEND_DEBUG("xen_vcpu_up %d\n", i); - mach_cpucontext_restore(cpu[i]); - (void) xen_vcpu_up(i); - } - } - - mp_leave_barrier(); -} - -/* - * Top level routine to direct suspend/resume of a domain. - */ -void -xen_suspend_domain(void) -{ - extern void rtcsync(void); - extern hrtime_t hres_last_tick; - mfn_t start_info_mfn; - ulong_t flags; - pfn_t pfn; - int i; - - /* - * Check that we are happy to suspend on this hypervisor. - */ - if (xen_hypervisor_supports_solaris(XEN_SUSPEND_CHECK) == 0) { - cpr_err(CE_WARN, "Cannot suspend on this hypervisor " - "version: v%lu.%lu%s, need at least version v3.0.4 or " - "-xvm based hypervisor", XENVER_CURRENT(xv_major), - XENVER_CURRENT(xv_minor), XENVER_CURRENT(xv_ver)); - return; - } - - /* - * XXPV - Are we definitely OK to suspend by the time we've connected - * the handler? - */ - - cpr_err(CE_NOTE, "Domain suspending for save/migrate"); - - SUSPEND_DEBUG("xen_suspend_domain\n"); - - /* - * suspend interrupts and devices - * XXPV - we use suspend/resume for both save/restore domains (like sun - * cpr) and for migration. Would be nice to know the difference if - * possible. For save/restore where down time may be a long time, we - * may want to do more of the things that cpr does. (i.e. notify user - * processes, shrink memory footprint for faster restore, etc.) - */ - xen_suspend_devices(); - SUSPEND_DEBUG("xenbus_suspend\n"); - xenbus_suspend(); - - pfn = hat_getpfnum(kas.a_hat, (caddr_t)xen_info); - start_info_mfn = pfn_to_mfn(pfn); - - /* - * XXPV: cpu hotplug can hold this under a xenbus watch. Are we safe - * wrt xenbus being suspended here? - */ - mutex_enter(&cpu_lock); - - /* - * Suspend must be done on vcpu 0, as no context for other CPUs is - * saved. - * - * XXPV - add to taskq API ? - */ - thread_affinity_set(curthread, 0); - kpreempt_disable(); - - SUSPEND_DEBUG("xen_start_migrate\n"); - xen_start_migrate(); - if (ncpus > 1) - suspend_cpus(); - - /* - * 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 suspend_cpus(). - */ - mutex_enter(&ec_lock); - - /* - * From here on in, we can't take locks. - */ - SUSPEND_DEBUG("ec_suspend\n"); - ec_suspend(); - SUSPEND_DEBUG("gnttab_suspend\n"); - gnttab_suspend(); - - flags = intr_clear(); - - xpv_time_suspend(); - - /* - * Currently, the hypervisor incorrectly fails to bring back - * powered-down VCPUs. Thus we need to record any powered-down VCPUs - * to prevent any attempts to operate on them. But we have to do this - * *after* the very first time we do ec_suspend(). - */ - for (i = 1; i < ncpus; i++) { - if (cpu[i] == NULL) - continue; - - if (cpu_get_state(cpu[i]) == P_POWEROFF) - CPUSET_ATOMIC_ADD(cpu_suspend_lost_set, i); - } - - /* - * The dom0 save/migrate code doesn't automatically translate - * these into PFNs, but expects them to be, so we do it here. - * We don't use mfn_to_pfn() because so many OS services have - * been disabled at this point. - */ - xen_info->store_mfn = mfn_to_pfn_mapping[xen_info->store_mfn]; - xen_info->console.domU.mfn = - mfn_to_pfn_mapping[xen_info->console.domU.mfn]; - - if (CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask == 0) { - prom_printf("xen_suspend_domain(): " - "CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask not set\n"); - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - } - - if (HYPERVISOR_update_va_mapping((uintptr_t)HYPERVISOR_shared_info, - 0, UVMF_INVLPG)) { - prom_printf("xen_suspend_domain(): " - "HYPERVISOR_update_va_mapping() failed\n"); - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - } - - SUSPEND_DEBUG("HYPERVISOR_suspend\n"); - - /* - * At this point we suspend and sometime later resume. - */ - if (HYPERVISOR_suspend(start_info_mfn)) { - prom_printf("xen_suspend_domain(): " - "HYPERVISOR_suspend() failed\n"); - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - } - - /* - * Point HYPERVISOR_shared_info to its new value. - */ - if (HYPERVISOR_update_va_mapping((uintptr_t)HYPERVISOR_shared_info, - xen_info->shared_info | PT_NOCONSIST | PT_VALID | PT_WRITABLE, - UVMF_INVLPG)) - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - - if (xen_info->nr_pages != mfn_count) { - prom_printf("xen_suspend_domain(): number of pages" - " changed, was 0x%lx, now 0x%lx\n", mfn_count, - xen_info->nr_pages); - (void) HYPERVISOR_shutdown(SHUTDOWN_crash); - } - - xpv_time_resume(); - - cached_max_mfn = 0; - - SUSPEND_DEBUG("gnttab_resume\n"); - gnttab_resume(); - - /* XXPV: add a note that this must be lockless. */ - SUSPEND_DEBUG("ec_resume\n"); - ec_resume(); - - intr_restore(flags); - - if (ncpus > 1) - resume_cpus(); - - mutex_exit(&ec_lock); - xen_end_migrate(); - mutex_exit(&cpu_lock); - - /* - * Now we can take locks again. - */ - - /* - * Force the tick value used for tv_nsec in hres_tick() to be up to - * date. rtcsync() will reset the hrestime value appropriately. - */ - hres_last_tick = xpv_gethrtime(); - - /* - * XXPV: we need to have resumed the CPUs since this takes locks, but - * can remote CPUs see bad state? Presumably yes. Should probably nest - * taking of todlock inside of cpu_lock, or vice versa, then provide an - * unlocked version. Probably need to call clkinitf to reset cpu freq - * and re-calibrate if we migrated to a different speed cpu. Also need - * to make a (re)init_cpu_info call to update processor info structs - * and device tree info. That remains to be written at the moment. - */ - rtcsync(); - - rebuild_mfn_list(); - - SUSPEND_DEBUG("xenbus_resume\n"); - xenbus_resume(); - SUSPEND_DEBUG("xenbus_resume_devices\n"); - xen_resume_devices(); - - thread_affinity_clear(curthread); - kpreempt_enable(); - - SUSPEND_DEBUG("finished xen_suspend_domain\n"); - - /* - * We have restarted our suspended domain, update the hypervisor - * details. NB: This must be done at the end of this function, - * since we need the domain to be completely resumed before - * these functions will work correctly. - */ - xen_set_version(XENVER_CURRENT_IDX); - - /* - * We can check and report a warning, but we don't stop the - * process. - */ - if (xen_hypervisor_supports_solaris(XEN_SUSPEND_CHECK) == 0) - cmn_err(CE_WARN, "Found hypervisor version: v%lu.%lu%s " - "but need at least version v3.0.4", - XENVER_CURRENT(xv_major), XENVER_CURRENT(xv_minor), - XENVER_CURRENT(xv_ver)); - - cmn_err(CE_NOTE, "domain restore/migrate completed"); -} - -/*ARGSUSED*/ -int -xen_debug_handler(void *arg) -{ - debug_enter("External debug event received"); - - /* - * If we've not got KMDB loaded, output some stuff difficult to capture - * from a domain core. - */ - if (!(boothowto & RB_DEBUG)) { - shared_info_t *si = HYPERVISOR_shared_info; - int i; - - prom_printf("evtchn_pending [ "); - for (i = 0; i < 8; i++) - prom_printf("%lx ", si->evtchn_pending[i]); - prom_printf("]\nevtchn_mask [ "); - for (i = 0; i < 8; i++) - prom_printf("%lx ", si->evtchn_mask[i]); - prom_printf("]\n"); - - for (i = 0; i < ncpus; i++) { - vcpu_info_t *vcpu = &si->vcpu_info[i]; - if (cpu[i] == NULL) - continue; - prom_printf("CPU%d pending %d mask %d sel %lx\n", - i, vcpu->evtchn_upcall_pending, - vcpu->evtchn_upcall_mask, - vcpu->evtchn_pending_sel); - } - } - - return (0); -} - -/*ARGSUSED*/ -static void -xen_sysrq_handler(struct xenbus_watch *watch, const char **vec, - unsigned int len) -{ - xenbus_transaction_t xbt; - char key = '\0'; - int ret; - -retry: - if (xenbus_transaction_start(&xbt)) { - cmn_err(CE_WARN, "failed to start sysrq transaction"); - return; - } - - if ((ret = xenbus_scanf(xbt, "control", "sysrq", "%c", &key)) != 0) { - /* - * ENOENT happens in response to our own xenbus_rm. - * XXPV - this happens spuriously on boot? - */ - if (ret != ENOENT) - cmn_err(CE_WARN, "failed to read sysrq: %d", ret); - goto out; - } - - if ((ret = xenbus_rm(xbt, "control", "sysrq")) != 0) { - cmn_err(CE_WARN, "failed to reset sysrq: %d", ret); - goto out; - } - - if (xenbus_transaction_end(xbt, 0) == EAGAIN) - goto retry; - - /* - * Somewhat arbitrary - on Linux this means 'reboot'. We could just - * accept any key, but this might increase the risk of sending a - * harmless sysrq to the wrong domain... - */ - if (key == 'b') - (void) xen_debug_handler(NULL); - else - cmn_err(CE_WARN, "Ignored sysrq %c", key); - return; - -out: - (void) xenbus_transaction_end(xbt, 1); -} - -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) - -static const char *cmd_strings[SHUTDOWN_MAX] = { - "poweroff", - "reboot", - "suspend", - "halt" -}; - -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); - } - - /* - * XXPV Should we check the value of xenbus_write() too, or are all - * errors automatically folded into xenbus_transaction_end() ?? - */ - (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 struct xenbus_watch shutdown_watch; -static struct xenbus_watch sysrq_watch; - -void -xen_late_startup(void) -{ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - 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"); - - sysrq_watch.node = "control/sysrq"; - sysrq_watch.callback = xen_sysrq_handler; - if (register_xenbus_watch(&sysrq_watch)) - cmn_err(CE_WARN, "Failed to set sysrq watcher"); - } - balloon_init(xen_info->nr_pages); -} - -#ifdef DEBUG -#define XEN_PRINTF_BUFSIZE 1024 - -char xen_printf_buffer[XEN_PRINTF_BUFSIZE]; - -/* - * Printf function that calls hypervisor directly. For DomU it only - * works when running on a xen hypervisor built with debug on. Works - * always since no I/O ring interaction is needed. - */ -/*PRINTFLIKE1*/ -void -xen_printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - (void) vsnprintf(xen_printf_buffer, XEN_PRINTF_BUFSIZE, fmt, ap); - va_end(ap); - - (void) HYPERVISOR_console_io(CONSOLEIO_write, - strlen(xen_printf_buffer), xen_printf_buffer); -} -#else -void -xen_printf(const char *fmt, ...) -{ -} -#endif /* DEBUG */ - -void -startup_xen_version(void) -{ - xen_set_version(XENVER_BOOT_IDX); - if (xen_hypervisor_supports_solaris(XEN_RUN_CHECK) == 0) - cmn_err(CE_WARN, "Found hypervisor version: v%lu.%lu%s " - "but need at least version v3.0.4", - XENVER_CURRENT(xv_major), XENVER_CURRENT(xv_minor), - XENVER_CURRENT(xv_ver)); - xen_pte_workaround(); -} - -int xen_mca_simulate_mc_physinfo_failure = 0; - -void -startup_xen_mca(void) -{ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return; - - xen_phys_ncpus = 0; - xen_phys_cpus = NULL; - - if (xen_mca_simulate_mc_physinfo_failure || - xen_get_mc_physcpuinfo(NULL, &xen_phys_ncpus) != 0) { - cmn_err(CE_WARN, - "%sxen_get_mc_physinfo failure during xen MCA startup: " - "there will be no machine check support", - xen_mca_simulate_mc_physinfo_failure ? "(simulated) " : ""); - return; - } - - xen_phys_cpus = kmem_alloc(xen_phys_ncpus * - sizeof (xen_mc_logical_cpu_t), KM_NOSLEEP); - - if (xen_phys_cpus == NULL) { - cmn_err(CE_WARN, - "xen_get_mc_physinfo failure: can't allocate CPU array"); - return; - } - - if (xen_get_mc_physcpuinfo(xen_phys_cpus, &xen_phys_ncpus) != 0) { - cmn_err(CE_WARN, "xen_get_mc_physinfo failure: no " - "physical CPU info"); - kmem_free(xen_phys_cpus, - xen_phys_ncpus * sizeof (xen_mc_logical_cpu_t)); - xen_phys_ncpus = 0; - xen_phys_cpus = NULL; - } - - if (xen_physinfo_debug) { - xen_mc_logical_cpu_t *xcp; - unsigned i; - - cmn_err(CE_NOTE, "xvm mca: %u physical cpus:\n", - xen_phys_ncpus); - for (i = 0; i < xen_phys_ncpus; i++) { - xcp = &xen_phys_cpus[i]; - cmn_err(CE_NOTE, "cpu%u: (%u, %u, %u) apid %u", - xcp->mc_cpunr, xcp->mc_chipid, xcp->mc_coreid, - xcp->mc_threadid, xcp->mc_apicid); - } - } -} - -/* - * Miscellaneous hypercall wrappers with slightly more verbose diagnostics. - */ - -void -xen_set_gdt(ulong_t *frame_list, int entries) -{ - int err; - if ((err = HYPERVISOR_set_gdt(frame_list, entries)) != 0) { - /* - * X_EINVAL: reserved entry or bad frames - * X_EFAULT: bad address - */ - panic("xen_set_gdt(%p, %d): error %d", - (void *)frame_list, entries, -(int)err); - } -} - -void -xen_set_ldt(user_desc_t *ldt, uint_t nsels) -{ - struct mmuext_op op; - long err; - - op.cmd = MMUEXT_SET_LDT; - op.arg1.linear_addr = (uintptr_t)ldt; - op.arg2.nr_ents = nsels; - - if ((err = HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) != 0) { - panic("xen_set_ldt(%p, %d): error %d", - (void *)ldt, nsels, -(int)err); - } -} - -void -xen_stack_switch(ulong_t ss, ulong_t esp) -{ - long err; - - if ((err = HYPERVISOR_stack_switch(ss, esp)) != 0) { - /* - * X_EPERM: bad selector - */ - panic("xen_stack_switch(%lx, %lx): error %d", ss, esp, - -(int)err); - } -} - -long -xen_set_trap_table(trap_info_t *table) -{ - long err; - - if ((err = HYPERVISOR_set_trap_table(table)) != 0) { - /* - * X_EFAULT: bad address - * X_EPERM: bad selector - */ - panic("xen_set_trap_table(%p): error %d", (void *)table, - -(int)err); - } - return (err); -} - -#if defined(__amd64) -void -xen_set_segment_base(int reg, ulong_t value) -{ - long err; - - if ((err = HYPERVISOR_set_segment_base(reg, value)) != 0) { - /* - * X_EFAULT: bad address - * X_EINVAL: bad type - */ - panic("xen_set_segment_base(%d, %lx): error %d", - reg, value, -(int)err); - } -} -#endif /* __amd64 */ - -/* - * Translate a hypervisor errcode to a Solaris error code. - */ -int -xen_xlate_errcode(int error) -{ - switch (-error) { - - /* - * Translate hypervisor errno's into native errno's - */ - -#define CASE(num) case X_##num: error = num; break - - 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); CASE(EAGAIN); - -#undef CASE - - default: - panic("xen_xlate_errcode: unknown error %d", error); - } - - return (error); -} - -/* - * Raise PS_IOPL on current vcpu to user level. - * Caller responsible for preventing kernel preemption. - */ -void -xen_enable_user_iopl(void) -{ - physdev_set_iopl_t set_iopl; - set_iopl.iopl = 3; /* user ring 3 */ - (void) HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); -} - -/* - * Drop PS_IOPL on current vcpu to kernel level - */ -void -xen_disable_user_iopl(void) -{ - physdev_set_iopl_t set_iopl; - set_iopl.iopl = 1; /* kernel pseudo ring 1 */ - (void) HYPERVISOR_physdev_op(PHYSDEVOP_set_iopl, &set_iopl); -} - -int -xen_gdt_setprot(cpu_t *cp, uint_t prot) -{ - int err; -#if defined(__amd64) - int pt_bits = PT_VALID; - if (prot & PROT_WRITE) - pt_bits |= PT_WRITABLE; -#endif - - if ((err = as_setprot(&kas, (caddr_t)cp->cpu_gdt, - MMU_PAGESIZE, prot)) != 0) - goto done; - -#if defined(__amd64) - err = xen_kpm_page(mmu_btop(cp->cpu_m.mcpu_gdtpa), pt_bits); -#endif - -done: - if (err) { - cmn_err(CE_WARN, "cpu%d: xen_gdt_setprot(%s) failed: error %d", - cp->cpu_id, (prot & PROT_WRITE) ? "writable" : "read-only", - err); - } - - return (err); -} - -int -xen_ldt_setprot(user_desc_t *ldt, size_t lsize, uint_t prot) -{ - int err; - caddr_t lva = (caddr_t)ldt; -#if defined(__amd64) - int pt_bits = PT_VALID; - pgcnt_t npgs; - if (prot & PROT_WRITE) - pt_bits |= PT_WRITABLE; -#endif /* __amd64 */ - - if ((err = as_setprot(&kas, (caddr_t)ldt, lsize, prot)) != 0) - goto done; - -#if defined(__amd64) - - ASSERT(IS_P2ALIGNED(lsize, PAGESIZE)); - npgs = mmu_btop(lsize); - while (npgs--) { - if ((err = xen_kpm_page(hat_getpfnum(kas.a_hat, lva), - pt_bits)) != 0) - break; - lva += PAGESIZE; - } -#endif /* __amd64 */ - -done: - if (err) { - cmn_err(CE_WARN, "xen_ldt_setprot(%p, %s) failed: error %d", - (void *)lva, - (prot & PROT_WRITE) ? "writable" : "read-only", err); - } - - return (err); -} - -int -xen_get_mc_physcpuinfo(xen_mc_logical_cpu_t *log_cpus, uint_t *ncpus) -{ - xen_mc_t xmc; - struct xen_mc_physcpuinfo *cpi = &xmc.u.mc_physcpuinfo; - - cpi->ncpus = *ncpus; - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(cpi->info, log_cpus); - - if (HYPERVISOR_mca(XEN_MC_physcpuinfo, &xmc) != 0) - return (-1); - - *ncpus = cpi->ncpus; - return (0); -} - -void -print_panic(const char *str) -{ - xen_printf(str); -} - -/* - * Interfaces to iterate over real cpu information, but only that info - * which we choose to expose here. These are of interest to dom0 - * only (and the backing hypercall should not work for domu). - */ - -xen_mc_lcpu_cookie_t -xen_physcpu_next(xen_mc_lcpu_cookie_t cookie) -{ - xen_mc_logical_cpu_t *xcp = (xen_mc_logical_cpu_t *)cookie; - - if (!DOMAIN_IS_INITDOMAIN(xen_info)) - return (NULL); - - if (cookie == NULL) - return ((xen_mc_lcpu_cookie_t)xen_phys_cpus); - - if (xcp == xen_phys_cpus + xen_phys_ncpus - 1) - return (NULL); - else - return ((xen_mc_lcpu_cookie_t)++xcp); -} - -#define COOKIE2XCP(c) ((xen_mc_logical_cpu_t *)(c)) - -const char * -xen_physcpu_vendorstr(xen_mc_lcpu_cookie_t cookie) -{ - xen_mc_logical_cpu_t *xcp = COOKIE2XCP(cookie); - - return ((const char *)&xcp->mc_vendorid[0]); -} - -int -xen_physcpu_family(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_family); -} - -int -xen_physcpu_model(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_model); -} - -int -xen_physcpu_stepping(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_step); -} - -id_t -xen_physcpu_chipid(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_chipid); -} - -id_t -xen_physcpu_coreid(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_coreid); -} - -id_t -xen_physcpu_strandid(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_threadid); -} - -id_t -xen_physcpu_initial_apicid(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_clusterid); -} - -id_t -xen_physcpu_logical_id(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_cpunr); -} - -boolean_t -xen_physcpu_is_cmt(xen_mc_lcpu_cookie_t cookie) -{ - return (COOKIE2XCP(cookie)->mc_nthreads > 1); -} - -uint64_t -xen_physcpu_mcg_cap(xen_mc_lcpu_cookie_t cookie) -{ - xen_mc_logical_cpu_t *xcp = COOKIE2XCP(cookie); - - /* - * Need to #define the indices, or search through the array. - */ - return (xcp->mc_msrvalues[0].value); -} - -int -xen_map_gref(uint_t cmd, gnttab_map_grant_ref_t *mapop, uint_t count, - boolean_t uvaddr) -{ - long rc; - uint_t i; - - ASSERT(cmd == GNTTABOP_map_grant_ref); - -#if !defined(_BOOT) - if (uvaddr == B_FALSE) { - for (i = 0; i < count; ++i) { - mapop[i].flags |= (PT_FOREIGN <<_GNTMAP_guest_avail0); - } - } -#endif - - rc = HYPERVISOR_grant_table_op(cmd, mapop, count); - - return (rc); -} - -static int -xpv_get_physinfo(xen_sysctl_physinfo_t *pi) -{ - xen_sysctl_t op; - struct sp { void *p; } *sp = (struct sp *)&op.u.physinfo.cpu_to_node; - int ret; - - bzero(&op, sizeof (op)); - op.cmd = XEN_SYSCTL_physinfo; - op.interface_version = XEN_SYSCTL_INTERFACE_VERSION; - /*LINTED: constant in conditional context*/ - set_xen_guest_handle(*sp, NULL); - - ret = HYPERVISOR_sysctl(&op); - - if (ret != 0) - return (xen_xlate_errcode(ret)); - - bcopy(&op.u.physinfo, pi, sizeof (op.u.physinfo)); - return (0); -} - -/* - * On dom0, we can determine the number of physical cpus on the machine. - * This number is important when figuring out what workarounds are - * appropriate, so compute it now. - */ -uint_t -xpv_nr_phys_cpus(void) -{ - static uint_t nphyscpus = 0; - - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - if (nphyscpus == 0) { - xen_sysctl_physinfo_t pi; - int ret; - - if ((ret = xpv_get_physinfo(&pi)) != 0) - panic("xpv_get_physinfo() failed: %d\n", ret); - nphyscpus = pi.nr_cpus; - } - return (nphyscpus); -} - -pgcnt_t -xpv_nr_phys_pages(void) -{ - xen_sysctl_physinfo_t pi; - int ret; - - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - if ((ret = xpv_get_physinfo(&pi)) != 0) - panic("xpv_get_physinfo() failed: %d\n", ret); - - return ((pgcnt_t)pi.total_pages); -} - -uint64_t -xpv_cpu_khz(void) -{ - xen_sysctl_physinfo_t pi; - int ret; - - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - if ((ret = xpv_get_physinfo(&pi)) != 0) - panic("xpv_get_physinfo() failed: %d\n", ret); - return ((uint64_t)pi.cpu_khz); -} diff --git a/usr/src/uts/i86xpv/os/xen_mmu.c b/usr/src/uts/i86xpv/os/xen_mmu.c deleted file mode 100644 index 5b4fe17e81..0000000000 --- a/usr/src/uts/i86xpv/os/xen_mmu.c +++ /dev/null @@ -1,453 +0,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 - -start_info_t *xen_info; -ulong_t mfn_count; -mfn_t *mfn_list; -mfn_t *mfn_list_pages; /* pages that make a table of mfn's */ - /* that make up the pa_to_ma table */ -mfn_t *mfn_list_pages_page; /* page of mfn's for mfn_list_pages */ -mfn_t cached_max_mfn; -uintptr_t xen_virt_start; -pfn_t *mfn_to_pfn_mapping; -caddr_t xb_addr; /* virtual addr for the store_mfn page */ - - -/* - * We need to prevent migration or suspension of a domU while it's - * manipulating MFN values, as the MFN values will spontaneously - * change. The next 4 routines provide a mechanism for that. - * The basic idea is to use reader/writer mutex, readers are any thread - * that is manipulating MFNs. Only the thread which is going to actually call - * HYPERVISOR_suspend() will become a writer. - * - * Since various places need to manipulate MFNs and also call the HAT, - * we track if a thread acquires reader status and allow it to recursively - * do so again. This prevents deadlocks if a migration request - * is started and waits for some reader, but then the previous reader needs - * to call into the HAT. - */ -#define NUM_M2P_LOCKS 128 -static struct { - krwlock_t m2p_rwlock; - char m2p_pad[64 - sizeof (krwlock_t)]; /* 64 byte cache line size */ -} m2p_lock[NUM_M2P_LOCKS]; - -#define XM2P_HASH ((uintptr_t)curthread->t_tid & (NUM_M2P_LOCKS - 1)) - -void -xen_block_migrate(void) -{ - if (!DOMAIN_IS_INITDOMAIN(xen_info) && - ++curthread->t_xpvcntr == 1) - rw_enter(&m2p_lock[XM2P_HASH].m2p_rwlock, RW_READER); -} - -void -xen_allow_migrate(void) -{ - if (!DOMAIN_IS_INITDOMAIN(xen_info) && - --curthread->t_xpvcntr == 0) - rw_exit(&m2p_lock[XM2P_HASH].m2p_rwlock); -} - -void -xen_start_migrate(void) -{ - int i; - - ASSERT(curthread->t_xpvcntr == 0); - ++curthread->t_xpvcntr; /* this allows calls into HAT */ - for (i = 0; i < NUM_M2P_LOCKS; ++i) - rw_enter(&m2p_lock[i].m2p_rwlock, RW_WRITER); -} - -void -xen_end_migrate(void) -{ - int i; - - for (i = 0; i < NUM_M2P_LOCKS; ++i) - rw_exit(&m2p_lock[i].m2p_rwlock); - ASSERT(curthread->t_xpvcntr == 1); - --curthread->t_xpvcntr; -} - -/*ARGSUSED*/ -void -set_pteval(paddr_t table, uint_t index, uint_t level, x86pte_t pteval) -{ - mmu_update_t t; - maddr_t mtable = pa_to_ma(table); - int retcnt; - - t.ptr = (mtable + index * pte_size) | MMU_NORMAL_PT_UPDATE; - t.val = pteval; - if (HYPERVISOR_mmu_update(&t, 1, &retcnt, DOMID_SELF) || retcnt != 1) - bop_panic("HYPERVISOR_mmu_update() failed"); -} - -/* - * The start_info_t and mfn_list are initially mapped in low "boot" memory. - * Each has a page aligned address and size. We relocate them up into the - * kernel's normal address space at this point in time. We also create - * the arrays that let the hypervisor suspend/resume a domain. - */ -void -xen_relocate_start_info(void) -{ - maddr_t mach_addr; - size_t sz; - size_t sz2; - offset_t off; - uintptr_t addr; - uintptr_t old; - int i, j; - - /* - * In dom0, we have to account for the console_info structure - * which might immediately follow the start_info in memory. - */ - sz = sizeof (start_info_t); - if (DOMAIN_IS_INITDOMAIN(xen_info) && - xen_info->console.dom0.info_off >= sizeof (start_info_t)) { - sz += xen_info->console.dom0.info_off - sizeof (start_info_t) + - xen_info->console.dom0.info_size; - } - sz = P2ROUNDUP(sz, MMU_PAGESIZE); - addr = (uintptr_t)vmem_alloc(heap_arena, sz, VM_SLEEP); - for (off = 0; off < sz; off += MMU_PAGESIZE) { - mach_addr = pa_to_ma(pfn_to_pa(va_to_pfn( - (caddr_t)xen_info + off))); - kbm_map_ma(mach_addr + off, addr + off, 0); - } - boot_mapin((caddr_t)addr, sz); - old = (uintptr_t)xen_info; - xen_info = (start_info_t *)addr; - for (off = 0; off < sz; off += MMU_PAGESIZE) - kbm_unmap(old + off); - - /* - * Relocate the mfn_list, any number of pages. - */ - sz = P2ROUNDUP(mfn_count * sizeof (mfn_t), MMU_PAGESIZE); - addr = (uintptr_t)vmem_xalloc(heap_arena, sz, MMU_PAGESIZE, 0, - 0, 0, 0, VM_SLEEP); - for (off = 0; off < sz; off += MMU_PAGESIZE) { - mach_addr = - pa_to_ma(pfn_to_pa(va_to_pfn((caddr_t)mfn_list + off))); - kbm_map_ma(mach_addr, addr + off, 0); - } - boot_mapin((caddr_t)addr, sz); - old = (uintptr_t)mfn_list; - mfn_list = (mfn_t *)addr; - xen_info->mfn_list = (mfn_t)addr; - for (off = 0; off < sz; off += MMU_PAGESIZE) - kbm_unmap(old + off); - - /* - * Create the lists of mfn_list pages needed by suspend/resume. - * Note we skip this for domain 0 as it can't suspend/resume. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - sz2 = P2ROUNDUP(mmu_btop(sz) * sizeof (mfn_t), MMU_PAGESIZE); - mfn_list_pages = kmem_zalloc(sz2, VM_SLEEP); - mfn_list_pages_page = kmem_zalloc(MMU_PAGESIZE, VM_SLEEP); - i = 0; - for (off = 0; off < sz; off += MMU_PAGESIZE) { - j = mmu_btop(off); - if (((j * sizeof (mfn_t)) & MMU_PAGEOFFSET) == 0) { - mfn_list_pages_page[i++] = - pfn_to_mfn(va_to_pfn(&mfn_list_pages[j])); - } - mfn_list_pages[j] = - pfn_to_mfn(va_to_pfn((caddr_t)mfn_list + off)); - } - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = - pfn_to_mfn(va_to_pfn(mfn_list_pages_page)); - HYPERVISOR_shared_info->arch.max_pfn = xen_info->nr_pages; - } - - /* - * Remap the shared info (for I/O) into high memory, too. - */ - sz = MMU_PAGESIZE; - addr = (uintptr_t)vmem_alloc(heap_arena, sz, VM_SLEEP); - kbm_map_ma(xen_info->shared_info, addr, 0); - /* shared info has no PFN so don't do: boot_mapin((caddr_t)addr, sz) */ - old = (uintptr_t)HYPERVISOR_shared_info; - HYPERVISOR_shared_info = (void *)addr; - kbm_unmap(old); - - /* - * Remap the console info into high memory, too. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - sz = MMU_PAGESIZE; - addr = (uintptr_t)vmem_alloc(heap_arena, sz, VM_SLEEP); - kbm_map_ma(pfn_to_pa(xen_info->console.domU.mfn), addr, 0); - boot_mapin((caddr_t)addr, sz); - old = (uintptr_t)HYPERVISOR_console_page; - HYPERVISOR_console_page = (void *)addr; - kbm_unmap(old); - } else { - HYPERVISOR_console_page = NULL; - } - - /* - * On domUs we need to have the xenbus page (store_mfn) mapped into - * the kernel. This is referenced as xb_addr. - */ - if (!DOMAIN_IS_INITDOMAIN(xen_info)) { - xb_addr = vmem_alloc(heap_arena, MMU_PAGESIZE, VM_SLEEP); - kbm_map_ma(mfn_to_ma(xen_info->store_mfn), - (uintptr_t)xb_addr, 0); - boot_mapin(xb_addr, MMU_PAGESIZE); - } -} - -/* - * Generate the pfn value to use for a foreign mfn. - */ -pfn_t -xen_assign_pfn(mfn_t mfn) -{ - pfn_t pfn; - -#ifdef DEBUG - /* - * make sure this MFN isn't in our list of MFNs - */ - on_trap_data_t otd; - uint_t on_trap_ready = (t0.t_stk != NULL); - - if (on_trap_ready) { - if (on_trap(&otd, OT_DATA_ACCESS) == 0) { - pfn = mfn_to_pfn_mapping[mfn]; - if (pfn < mfn_count && mfn_list[pfn] == mfn) - panic("xen_assign_pfn() mfn belongs to us"); - } - no_trap(); - } -#endif /* DEBUG */ - - if (mfn == MFN_INVALID) - panic("xen_assign_pfn(MFN_INVALID) not allowed"); - pfn = (pfn_t)mfn | PFN_IS_FOREIGN_MFN; - if (pfn == mfn) - panic("xen_assign_pfn(mfn) PFN_IS_FOREIGN_MFN bit already set"); - return (pfn); -} - -void -xen_release_pfn(pfn_t pfn) -{ - if (pfn == PFN_INVALID) - panic("xen_release_pfn(PFN_INVALID) not allowed"); - if ((pfn & PFN_IS_FOREIGN_MFN) == 0) - panic("mfn high bit not set"); -} - -uint_t -pfn_is_foreign(pfn_t pfn) -{ - if (pfn == PFN_INVALID) - return (0); - return ((pfn & PFN_IS_FOREIGN_MFN) != 0); -} - -pfn_t -pte2pfn(x86pte_t pte, level_t l) -{ - mfn_t mfn = PTE2MFN(pte, l); - - if ((pte & PT_SOFTWARE) >= PT_FOREIGN) - return ((pfn_t)mfn | PFN_IS_FOREIGN_MFN); - return (mfn_to_pfn(mfn)); -} - -mfn_t -pfn_to_mfn(pfn_t pfn) -{ - if (pfn == PFN_INVALID) - panic("pfn_to_mfn(PFN_INVALID) not allowed"); - - if (pfn & PFN_IS_FOREIGN_MFN) - return (pfn & ~PFN_IS_FOREIGN_MFN); - - if (pfn >= mfn_count) - panic("pfn_to_mfn(): illegal PFN 0x%lx", pfn); - - return (mfn_list[pfn]); -} - -/* - * This routine translates an MFN back into the corresponding PFN value. - * It has to be careful since the mfn_to_pfn_mapping[] might fault - * as that table is sparse. It also has to check for non-faulting, but out of - * range that exceed the table. - */ -pfn_t -mfn_to_pfn(mfn_t mfn) -{ - pfn_t pfn; - on_trap_data_t otd; - uint_t on_trap_ready = (t0.t_stk != NULL); - - /* - * Cleared at a suspend or migrate - */ - if (cached_max_mfn == 0) - cached_max_mfn = - HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL); - - if (cached_max_mfn < mfn) - return ((pfn_t)mfn | PFN_IS_FOREIGN_MFN); - - if (on_trap_ready && on_trap(&otd, OT_DATA_ACCESS)) { - pfn = (pfn_t)mfn | PFN_IS_FOREIGN_MFN; - } else { - pfn = mfn_to_pfn_mapping[mfn]; - - if (pfn == PFN_INVALID || pfn >= mfn_count || - pfn_to_mfn(pfn) != mfn) - pfn = (pfn_t)mfn | PFN_IS_FOREIGN_MFN; - } - - if (on_trap_ready) - no_trap(); - - /* - * If khat_running is set then we should be checking - * in domUs that migration is blocked while using the - * mfn_to_pfn_mapping[] table. - */ - ASSERT(!khat_running || DOMAIN_IS_INITDOMAIN(xen_info) || - rw_read_held(&m2p_lock[XM2P_HASH].m2p_rwlock)); - - return (pfn); -} - -/* - * From a pseudo-physical address, find the corresponding machine address. - */ -maddr_t -pa_to_ma(paddr_t pa) -{ - mfn_t mfn = pfn_to_mfn(mmu_btop(pa)); - - if (mfn == MFN_INVALID) - panic("pa_to_ma() got MFN_INVALID"); - return (mfn_to_ma(mfn) + (pa & MMU_PAGEOFFSET)); -} - -/* - * From a machine address, find the corresponding pseudo-physical address. - */ -paddr_t -ma_to_pa(maddr_t ma) -{ - pfn_t pfn = mfn_to_pfn(mmu_btop(ma)); - - if (pfn == PFN_INVALID) - panic("ma_to_pa() got PFN_INVALID"); - return (pfn_to_pa(pfn) + (ma & MMU_PAGEOFFSET)); -} - -/* - * When calling reassign_pfn(), the page must be (at least) read locked - * to make sure swrand does not try to grab it. - */ -#ifdef DEBUG -#define CHECK_PAGE_LOCK(pfn) { \ - page_t *pp = page_numtopp_nolock(pfn); \ - if ((pp != NULL) && (!PAGE_LOCKED(pp))) { \ - panic("reassign_pfn() called with unlocked page (pfn 0x%lx)", \ - pfn); \ - } \ -} -#else /* DEBUG */ -#define CHECK_PAGE_LOCK(pfn) -#endif /* DEBUG */ - -/* - * Reassign a new machine page to back a physical address. - */ -void -reassign_pfn(pfn_t pfn, mfn_t mfn) -{ - int mmu_update_return; - mmu_update_t t; - extern void update_contig_pfnlist(pfn_t, mfn_t, mfn_t); - - ASSERT(pfn != PFN_INVALID); - ASSERT(!pfn_is_foreign(pfn)); - - ASSERT(pfn < mfn_count); - update_contig_pfnlist(pfn, mfn_list[pfn], mfn); - if (mfn == MFN_INVALID) { - CHECK_PAGE_LOCK(pfn); - if (kpm_vbase != NULL && xen_kpm_page(pfn, 0) < 0) - panic("reassign_pfn(): failed to remove kpm mapping"); - mfn_list[pfn] = mfn; - return; - } - - /* - * Verify that previously given away pages are still page locked. - */ - if (mfn_list[pfn] == MFN_INVALID) { - CHECK_PAGE_LOCK(pfn); - } - mfn_list[pfn] = mfn; - - t.ptr = mfn_to_ma(mfn) | MMU_MACHPHYS_UPDATE; - t.val = pfn; - - if (HYPERVISOR_mmu_update(&t, 1, &mmu_update_return, DOMID_SELF)) - panic("HYPERVISOR_mmu_update() failed"); - ASSERT(mmu_update_return == 1); - - if (kpm_vbase != NULL && xen_kpm_page(pfn, PT_VALID | PT_WRITABLE) < 0) - panic("reassign_pfn(): failed to enable kpm mapping"); -} diff --git a/usr/src/uts/i86xpv/os/xpv_panic.c b/usr/src/uts/i86xpv/os/xpv_panic.c deleted file mode 100644 index 2b67bff1dd..0000000000 --- a/usr/src/uts/i86xpv/os/xpv_panic.c +++ /dev/null @@ -1,1027 +0,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 (c) 2012 Gary Mills - * Copyright 2016 PALO, Richard. - * - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* XXX: need to add a PAE version too, if we ever support both PAE and non */ -#if defined(__i386) -#define XPV_FILENAME "/boot/xen-syms" -#else -#define XPV_FILENAME "/boot/amd64/xen-syms" -#endif -#define XPV_MODNAME "xpv" - -int xpv_panicking = 0; - -struct module *xpv_module; -struct modctl *xpv_modctl; - -#define ALIGN(x, a) ((a) == 0 ? (uintptr_t)(x) : \ - (((uintptr_t)(x) + (uintptr_t)(a) - 1l) & ~((uintptr_t)(a) - 1l))) - -/* Pointer to the xpv_panic_info structure handed to us by Xen. */ -static struct panic_info *xpv_panic_info = NULL; - -/* Timer support */ -#define NSEC_SHIFT 5 -#define T_XPV_TIMER 0xd1 -#define XPV_TIMER_INTERVAL 1000 /* 1000 microseconds */ -static uint32_t *xpv_apicadr = NULL; -static uint_t nsec_scale; - -/* IDT support */ -#pragma align 16(xpv_panic_idt) -static gate_desc_t xpv_panic_idt[NIDT]; /* interrupt descriptor table */ - -/* Xen pagetables mapped into our HAT's ptable windows */ -static pfn_t ptable_pfn[MAX_NUM_LEVEL]; - -/* Number of MMU_PAGESIZE pages we're adding to the Solaris dump */ -static int xpv_dump_pages; - -/* - * There are up to two large swathes of RAM that we don't want to include - * in the dump: those that comprise the Xen version of segkpm. On 32-bit - * systems there is no such region of memory. On 64-bit systems, there - * should be just a single contiguous region that corresponds to all of - * physical memory. The tricky bit is that Xen's heap sometimes lives in - * the middle of their segkpm, and is mapped using only kpm-like addresses. - * In that case, we need to skip the swathes before and after Xen's heap. - */ -uintptr_t kpm1_low = 0; -uintptr_t kpm1_high = 0; -uintptr_t kpm2_low = 0; -uintptr_t kpm2_high = 0; - -/* - * Some commonly used values that we don't want to recompute over and over. - */ -static int xpv_panic_nptes[MAX_NUM_LEVEL]; -static ulong_t xpv_panic_cr3; -static uintptr_t xpv_end; - -static void xpv_panic_console_print(const char *fmt, ...); -static void (*xpv_panic_printf)(const char *, ...) = xpv_panic_console_print; - -#define CONSOLE_BUF_SIZE 256 -static char console_buffer[CONSOLE_BUF_SIZE]; -static boolean_t use_polledio; - -/* - * Pointers to machine check panic info (if any). - */ -xpv_mca_panic_data_t *xpv_mca_panic_data = NULL; - -static void -xpv_panic_putc(int m) -{ - struct cons_polledio *c = cons_polledio; - - /* This really shouldn't happen */ - if (boot_console_type(NULL) == CONS_HYPERVISOR) - return; - - if (use_polledio == B_TRUE) - c->cons_polledio_putchar(c->cons_polledio_argument, m); - else - bcons_putchar(m); -} - -static void -xpv_panic_puts(char *msg) -{ - char *m; - - dump_timeleft = dump_timeout; - for (m = msg; *m; m++) - xpv_panic_putc((int)*m); -} - -static void -xpv_panic_console_print(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - (void) vsnprintf(console_buffer, sizeof (console_buffer), fmt, ap); - va_end(ap); - - xpv_panic_puts(console_buffer); -} - -static void -xpv_panic_map(int level, pfn_t pfn) -{ - x86pte_t pte, *pteptr; - - /* - * The provided pfn represents a level 'level' page table. Map it - * into the 'level' slot in the list of page table windows. - */ - pteptr = (x86pte_t *)PWIN_PTE_VA(level); - pte = pfn_to_pa(pfn) | PT_VALID; - - XPV_ALLOW_PAGETABLE_UPDATES(); - if (mmu.pae_hat) - *pteptr = pte; - else - *(x86pte32_t *)pteptr = pte; - XPV_DISALLOW_PAGETABLE_UPDATES(); - - mmu_tlbflush_entry(PWIN_VA(level)); -} - -/* - * Walk the page tables to find the pfn mapped by the given va. - */ -static pfn_t -xpv_va_walk(uintptr_t *vaddr) -{ - int l, idx; - pfn_t pfn; - x86pte_t pte; - x86pte_t *ptep; - uintptr_t va = *vaddr; - uintptr_t scan_va; - caddr_t ptable_window; - static pfn_t toplevel_pfn; - static uintptr_t lastva; - - /* - * If we do anything other than a simple scan through memory, don't - * trust the mapped page tables. - */ - if (va != lastva + MMU_PAGESIZE) - for (l = mmu.max_level; l >= 0; l--) - ptable_pfn[l] = PFN_INVALID; - - toplevel_pfn = mmu_btop(xpv_panic_cr3); - - while (va < xpv_end && va >= *vaddr) { - /* Find the lowest table with any entry for va */ - pfn = toplevel_pfn; - for (l = mmu.max_level; l >= 0; l--) { - if (ptable_pfn[l] != pfn) { - xpv_panic_map(l, pfn); - ptable_pfn[l] = pfn; - } - - /* - * Search this pagetable for any mapping to an - * address >= va. - */ - ptable_window = PWIN_VA(l); - if (l == mmu.max_level && mmu.pae_hat) - ptable_window += - (xpv_panic_cr3 & MMU_PAGEOFFSET); - - idx = (va >> LEVEL_SHIFT(l)) & (xpv_panic_nptes[l] - 1); - scan_va = va; - while (idx < xpv_panic_nptes[l] && scan_va < xpv_end && - scan_va >= *vaddr) { - ptep = (x86pte_t *)(ptable_window + - (idx << mmu.pte_size_shift)); - pte = GET_PTE(ptep); - if (pte & PTE_VALID) - break; - idx++; - scan_va += mmu.level_size[l]; - } - - /* - * If there are no valid mappings in this table, we - * can skip to the end of the VA range it covers. - */ - if (idx == xpv_panic_nptes[l]) { - va = NEXT_ENTRY_VA(va, l + 1); - break; - } - - va = scan_va; - /* - * See if we've hit the end of the range. - */ - if (va >= xpv_end || va < *vaddr) - break; - - /* - * If this mapping is for a pagetable, we drop down - * to the next level in the hierarchy and look for - * a mapping in it. - */ - pfn = PTE2MFN(pte, l); - if (!PTE_ISPAGE(pte, l)) - continue; - - /* - * The APIC page is magic. Nothing to see here; - * move along. - */ - if (((uintptr_t)xpv_apicadr & MMU_PAGEMASK) == - (va & MMU_PAGEMASK)) { - va += MMU_PAGESIZE; - break; - } - - /* - * See if the address is within one of the two - * kpm-like regions we want to skip. - */ - if (va >= kpm1_low && va < kpm1_high) { - va = kpm1_high; - break; - } - if (va >= kpm2_low && va < kpm2_high) { - va = kpm2_high; - break; - } - - /* - * The Xen panic code only handles small pages. If - * this mapping is for a large page, we need to - * identify the consituent page that covers the - * specific VA we were looking for. - */ - if (l > 0) { - if (l > 1) - panic("Xen panic can't cope with " - "giant pages."); - idx = (va >> LEVEL_SHIFT(0)) & - (xpv_panic_nptes[0] - 1); - pfn += idx; - } - - *vaddr = va; - lastva = va; - return (pfn | PFN_IS_FOREIGN_MFN); - } - } - return (PFN_INVALID); -} - -/* - * Walk through the Xen VA space, finding pages that are mapped in. - * - * These pages all have MFNs rather than PFNs, meaning they may be outside - * the physical address space the kernel knows about, or they may collide - * with PFNs the kernel is using. - * - * The obvious trick of just adding the PFN_IS_FOREIGN_MFN bit to the MFNs - * to avoid collisions doesn't work. The pages need to be written to disk - * in PFN-order or savecore gets confused. We can't allocate memory to - * contruct a sorted pfn->VA reverse mapping, so we have to write the pages - * to disk in VA order. - * - * To square this circle, we simply make up PFNs for each of Xen's pages. - * We assign each mapped page a fake PFN in ascending order. These fake - * PFNs each have the FOREIGN bit set, ensuring that they fall outside the - * range of Solaris PFNs written by the kernel. - */ -int -dump_xpv_addr() -{ - uintptr_t va; - mem_vtop_t mem_vtop; - - xpv_dump_pages = 0; - va = xen_virt_start; - - while (xpv_va_walk(&va) != PFN_INVALID) { - mem_vtop.m_as = &kas; - mem_vtop.m_va = (void *)va; - mem_vtop.m_pfn = (pfn_t)xpv_dump_pages | PFN_IS_FOREIGN_MFN; - - dumpvp_write(&mem_vtop, sizeof (mem_vtop_t)); - xpv_dump_pages++; - - va += MMU_PAGESIZE; - } - - /* - * Add the shared_info page. This page actually ends up in the - * dump twice: once for the Xen va and once for the Solaris va. - * This isn't ideal, but we don't know the address Xen is using for - * the page, so we can't share it. - */ - mem_vtop.m_as = &kas; - mem_vtop.m_va = HYPERVISOR_shared_info; - mem_vtop.m_pfn = (pfn_t)xpv_dump_pages | PFN_IS_FOREIGN_MFN; - dumpvp_write(&mem_vtop, sizeof (mem_vtop_t)); - xpv_dump_pages++; - - return (xpv_dump_pages); -} - -void -dump_xpv_pfn() -{ - pfn_t pfn; - int cnt; - - for (cnt = 0; cnt < xpv_dump_pages; cnt++) { - pfn = (pfn_t)cnt | PFN_IS_FOREIGN_MFN; - dumpvp_write(&pfn, sizeof (pfn)); - } -} - -int -dump_xpv_data(void *dump_cbuf) -{ - uintptr_t va; - uint32_t csize; - int cnt = 0; - - /* - * XXX: we should probably run this data through a UE check. The - * catch is that the UE code relies on on_trap() and getpfnum() - * working. - */ - va = xen_virt_start; - - while (xpv_va_walk(&va) != PFN_INVALID) { - csize = (uint32_t)compress((void *)va, dump_cbuf, PAGESIZE); - dumpvp_write(&csize, sizeof (uint32_t)); - dumpvp_write(dump_cbuf, csize); - if (dump_ioerr) { - dumphdr->dump_flags &= ~DF_COMPLETE; - return (cnt); - } - cnt++; - va += MMU_PAGESIZE; - } - - /* - * Finally, dump the shared_info page - */ - csize = (uint32_t)compress((void *)HYPERVISOR_shared_info, dump_cbuf, - PAGESIZE); - dumpvp_write(&csize, sizeof (uint32_t)); - dumpvp_write(dump_cbuf, csize); - if (dump_ioerr) - dumphdr->dump_flags &= ~DF_COMPLETE; - cnt++; - - return (cnt); -} - -static void * -showstack(void *fpreg, int xpv_only) -{ - struct frame *fpp; - ulong_t off; - char *sym; - uintptr_t pc, fp, lastfp; - uintptr_t minaddr = min(KERNELBASE, xen_virt_start); - - fp = (uintptr_t)fpreg; - if (fp < minaddr) { - xpv_panic_printf("Bad frame ptr: 0x%p\n", fpreg); - return (fpreg); - } - - do { - fpp = (struct frame *)fp; - pc = fpp->fr_savpc; - - if ((xpv_only != 0) && - (fp > xpv_end || fp < xen_virt_start)) - break; - if ((sym = kobj_getsymname(pc, &off)) != NULL) - xpv_panic_printf("%08lx %s:%s+%lx\n", fp, - mod_containing_pc((caddr_t)pc), sym, off); - else if ((pc >= xen_virt_start) && (pc <= xpv_end)) - xpv_panic_printf("%08lx 0x%lx (in Xen)\n", fp, pc); - else - xpv_panic_printf("%08lx %lx\n", fp, pc); - - lastfp = fp; - fp = fpp->fr_savfp; - - /* - * Xen marks an exception frame by inverting the frame - * pointer. - */ - if (fp < lastfp) { - if ((~fp > minaddr) && ((~fp) ^ lastfp) < 0xfff) - fp = ~fp; - } - } while (fp > lastfp); - return ((void *)fp); -} - -void * -xpv_traceback(void *fpreg) -{ - return (showstack(fpreg, 1)); -} - -#if defined(__amd64) -static void -xpv_panic_hypercall(ulong_t call) -{ - panic("Illegally issued hypercall %d during panic!\n", (int)call); -} -#endif - -void -xpv_die(struct regs *rp) -{ - struct panic_trap_info ti; - struct cregs creg; - - ti.trap_regs = rp; - ti.trap_type = rp->r_trapno; - - curthread->t_panic_trap = &ti; - if (ti.trap_type == T_PGFLT) { - getcregs(&creg); - ti.trap_addr = (caddr_t)creg.cr_cr2; - panic("Fatal pagefault at 0x%lx. fault addr=0x%p rp=0x%p", - rp->r_pc, (void *)ti.trap_addr, (void *)rp); - } else { - ti.trap_addr = (caddr_t)rp->r_pc; - panic("Fatal trap %ld at 0x%lx. rp=0x%p", rp->r_trapno, - rp->r_pc, (void *)rp); - } -} - -/* - * Build IDT to handle a Xen panic - */ -static void -switch_to_xpv_panic_idt() -{ - int i; - desctbr_t idtr; - gate_desc_t *idt = xpv_panic_idt; - selector_t cs = get_cs_register(); - - for (i = 0; i < 32; i++) - set_gatesegd(&idt[i], &xpv_invaltrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - - set_gatesegd(&idt[T_ZERODIV], &xpv_div0trap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_SGLSTP], &xpv_dbgtrap, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_NMIFLT], &xpv_nmiint, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_BOUNDFLT], &xpv_boundstrap, cs, SDT_SYSIGT, - TRP_XPL, 0); - set_gatesegd(&idt[T_ILLINST], &xpv_invoptrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_NOEXTFLT], &xpv_ndptrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_TSSFLT], &xpv_invtsstrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_SEGFLT], &xpv_segnptrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_STKFLT], &xpv_stktrap, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_GPFLT], &xpv_gptrap, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_PGFLT], &xpv_pftrap, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_EXTERRFLT], &xpv_ndperr, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_ALIGNMENT], &xpv_achktrap, cs, SDT_SYSIGT, TRP_XPL, - 0); - set_gatesegd(&idt[T_MCE], &xpv_mcetrap, cs, SDT_SYSIGT, TRP_XPL, 0); - set_gatesegd(&idt[T_SIMDFPE], &xpv_xmtrap, cs, SDT_SYSIGT, TRP_XPL, 0); - - /* - * We have no double fault handler. Any single fault represents a - * catastrophic failure for us, so there is no attempt to handle - * them cleanly: we just print a message and reboot. If we - * encounter a second fault while doing that, there is nothing - * else we can do. - */ - - /* - * Be prepared to absorb any stray device interrupts received - * while writing the core to disk. - */ - for (i = 33; i < NIDT; i++) - set_gatesegd(&idt[i], &xpv_surprise_intr, cs, SDT_SYSIGT, - TRP_XPL, 0); - - /* The one interrupt we expect to get is from the APIC timer. */ - set_gatesegd(&idt[T_XPV_TIMER], &xpv_timer_trap, cs, SDT_SYSIGT, - TRP_XPL, 0); - - idtr.dtr_base = (uintptr_t)xpv_panic_idt; - idtr.dtr_limit = sizeof (xpv_panic_idt) - 1; - wr_idtr(&idtr); - -#if defined(__amd64) - /* Catch any hypercalls. */ - wrmsr(MSR_AMD_LSTAR, (uintptr_t)xpv_panic_hypercall); - wrmsr(MSR_AMD_CSTAR, (uintptr_t)xpv_panic_hypercall); -#endif -} - -static void -xpv_apic_clkinit() -{ - uint_t apic_ticks = 0; - - /* - * Measure how many APIC ticks there are within a fixed time - * period. We're going to be fairly coarse here. This timer is - * just being used to detect a stalled panic, so as long as we have - * the right order of magnitude, everything should be fine. - */ - xpv_apicadr[APIC_SPUR_INT_REG] = AV_UNIT_ENABLE | APIC_SPUR_INTR; - xpv_apicadr[APIC_LOCAL_TIMER] = AV_MASK; - xpv_apicadr[APIC_INT_VECT0] = AV_MASK; /* local intr reg 0 */ - - xpv_apicadr[APIC_DIVIDE_REG] = 0; - xpv_apicadr[APIC_INIT_COUNT] = APIC_MAXVAL; - drv_usecwait(XPV_TIMER_INTERVAL); - apic_ticks = APIC_MAXVAL - xpv_apicadr[APIC_CURR_COUNT]; - - /* - * apic_ticks now represents roughly how many apic ticks comprise - * one timeout interval. Program the timer to send us an interrupt - * every time that interval expires. - */ - xpv_apicadr[APIC_LOCAL_TIMER] = T_XPV_TIMER | AV_PERIODIC; - xpv_apicadr[APIC_INIT_COUNT] = apic_ticks; - xpv_apicadr[APIC_EOI_REG] = 0; -} - -void -xpv_timer_tick(void) -{ - static int ticks = 0; - - if (ticks++ >= MICROSEC / XPV_TIMER_INTERVAL) { - ticks = 0; - if (dump_timeleft && (--dump_timeleft == 0)) - panic("Xen panic timeout\n"); - } - xpv_apicadr[APIC_EOI_REG] = 0; -} - -void -xpv_interrupt(void) -{ -#ifdef DEBUG - static int cnt = 0; - - if (cnt++ < 10) - xpv_panic_printf("Unexpected interrupt received.\n"); - if ((cnt < 1000) && ((cnt % 100) == 0)) - xpv_panic_printf("%d unexpected interrupts received.\n", cnt); -#endif - - xpv_apicadr[APIC_EOI_REG] = 0; -} - -/* - * Managing time in panic context is trivial. We only have a single CPU, - * we never get rescheduled, we never get suspended. We just need to - * convert clock ticks into nanoseconds. - */ -static hrtime_t -xpv_panic_gethrtime(void) -{ - hrtime_t tsc, hrt; - unsigned int *l = (unsigned int *)&(tsc); - - tsc = __rdtsc_insn(); - hrt = (mul32(l[1], nsec_scale) << NSEC_SHIFT) + - (mul32(l[0], nsec_scale) >> (32 - NSEC_SHIFT)); - - return (hrt); -} - -static void -xpv_panic_time_init() -{ - nsec_scale = - CPU->cpu_m.mcpu_vcpu_info->time.tsc_to_system_mul >> NSEC_SHIFT; - - gethrtimef = xpv_panic_gethrtime; -} - -static void -xpv_panicsys(struct regs *rp, char *fmt, ...) -{ - extern void panicsys(const char *, va_list, struct regs *, int); - va_list alist; - - va_start(alist, fmt); - panicsys(fmt, alist, rp, 1); - va_end(alist); -} - -void -xpv_do_panic(void *arg) -{ - struct panic_info *pip = (struct panic_info *)arg; - int l; - struct cregs creg; -#if defined(__amd64) - extern uintptr_t postbootkernelbase; -#endif - - if (xpv_panicking++ > 0) - panic("multiple calls to xpv_do_panic()"); - - /* - * Indicate to the underlying panic framework that a panic has been - * initiated. This is ordinarily done as part of vpanic(). Since - * we already have all the register state saved by the hypervisor, - * we skip that and jump straight into the panic processing code. - * - * XXX If another thread grabs and wins the panic_quiesce trigger - * then we'll have two threads in panicsys believing they are in - * charge of the panic attempt! - */ - (void) panic_trigger(&panic_quiesce); - -#if defined(__amd64) - /* - * bzero() and bcopy() get unhappy when asked to operate on - * addresses outside of the kernel. At this point Xen is really a - * part of the kernel, so we update the routines' notion of where - * the kernel starts. - */ - postbootkernelbase = xen_virt_start; -#endif - -#if defined(HYPERVISOR_VIRT_END) - xpv_end = HYPERVISOR_VIRT_END; -#else - xpv_end = (uintptr_t)UINTPTR_MAX - sizeof (uintptr_t); -#endif - - /* - * If we were redirecting console output to the hypervisor, we have - * to stop. - */ - use_polledio = B_FALSE; - if (boot_console_type(NULL) == CONS_HYPERVISOR) { - bcons_device_change(CONS_HYPERVISOR); - } else if (cons_polledio != NULL && - cons_polledio->cons_polledio_putchar != NULL) { - if (cons_polledio->cons_polledio_enter != NULL) - cons_polledio->cons_polledio_enter( - cons_polledio->cons_polledio_argument); - use_polledio = 1; - } - - /* Make sure we handle all console output from here on. */ - sysp->bsvc_putchar = xpv_panic_putc; - - /* - * If we find an unsupported panic_info structure, there's not much - * we can do other than complain, plow on, and hope for the best. - */ - if (pip->pi_version != PANIC_INFO_VERSION) - xpv_panic_printf("Warning: Xen is using an unsupported " - "version of the panic_info structure.\n"); - - xpv_panic_info = pip; - -#if defined(__amd64) - kpm1_low = (uintptr_t)xpv_panic_info->pi_ram_start; - if (xpv_panic_info->pi_xen_start == NULL) { - kpm1_high = (uintptr_t)xpv_panic_info->pi_ram_end; - } else { - kpm1_high = (uintptr_t)xpv_panic_info->pi_xen_start; - kpm2_low = (uintptr_t)xpv_panic_info->pi_xen_end; - kpm2_high = (uintptr_t)xpv_panic_info->pi_ram_end; - } -#endif - - /* - * Make sure we are running on the Solaris %gs. The Xen panic code - * should already have set up the GDT properly. - */ - xpv_panic_resetgs(); -#if defined(__amd64) - wrmsr(MSR_AMD_GSBASE, (uint64_t)&cpus[0]); -#endif - - xpv_panic_time_init(); - - /* - * Switch to our own IDT, avoiding any accidental returns to Xen - * world. - */ - switch_to_xpv_panic_idt(); - - /* - * Initialize the APIC timer, which is used to detect a hung dump - * attempt. - */ - xpv_apicadr = pip->pi_apic; - xpv_apic_clkinit(); - - /* - * Set up a few values that we'll need repeatedly. - */ - getcregs(&creg); - xpv_panic_cr3 = creg.cr_cr3; - for (l = mmu.max_level; l >= 0; l--) - xpv_panic_nptes[l] = mmu.ptes_per_table; -#ifdef __i386 - if (mmu.pae_hat) - xpv_panic_nptes[mmu.max_level] = 4; -#endif - - /* Add the fake Xen module to the module list */ - if (xpv_module != NULL) { - extern int last_module_id; - - xpv_modctl->mod_id = last_module_id++; - xpv_modctl->mod_next = &modules; - xpv_modctl->mod_prev = modules.mod_prev; - modules.mod_prev->mod_next = xpv_modctl; - modules.mod_prev = xpv_modctl; - } - - if (pip->pi_mca.mpd_magic == MCA_PANICDATA_MAGIC) - xpv_mca_panic_data = &pip->pi_mca; - - xpv_panic_printf = printf; - xpv_panicsys((struct regs *)pip->pi_regs, pip->pi_panicstr); - xpv_panic_printf("Failed to reboot following panic.\n"); - for (;;) - ; -} - -/* - * Set up the necessary data structures to pretend that the Xen hypervisor - * is a loadable module, allowing mdb to find the Xen symbols in a crash - * dump. Since these symbols all map to VA space Solaris doesn't normally - * have access to, we don't link these structures into the kernel's lists - * until/unless we hit a Xen panic. - * - * The observant reader will note a striking amount of overlap between this - * code and that found in krtld. While it would be handy if we could just - * ask krtld to do this work for us, it's not that simple. Among the - * complications: we're not actually loading the text here (grub did it at - * boot), the .text section is writable, there are no relocations to do, - * none of the module text/data is in readable memory, etc. Training krtld - * to deal with this weird module is as complicated, and more risky, than - * reimplementing the necessary subset of it here. - */ -static void -init_xen_module() -{ - struct _buf *file = NULL; - struct module *mp; - struct modctl *mcp; - int i, shn; - Shdr *shp, *ctf_shp; - char *names = NULL; - size_t n, namesize, text_align, data_align; -#if defined(__amd64) - const char machine = EM_AMD64; -#else - const char machine = EM_386; -#endif - - /* Allocate and init the module structure */ - mp = kmem_zalloc(sizeof (*mp), KM_SLEEP); - mp->filename = kobj_zalloc(strlen(XPV_FILENAME) + 1, KM_SLEEP); - (void) strcpy(mp->filename, XPV_FILENAME); - - /* Allocate and init the modctl structure */ - mcp = kmem_zalloc(sizeof (*mcp), KM_SLEEP); - mcp->mod_modname = kobj_zalloc(strlen(XPV_MODNAME) + 1, KM_SLEEP); - (void) strcpy(mcp->mod_modname, XPV_MODNAME); - mcp->mod_filename = kobj_zalloc(strlen(XPV_FILENAME) + 1, KM_SLEEP); - (void) strcpy(mcp->mod_filename, XPV_FILENAME); - mcp->mod_inprogress_thread = (kthread_id_t)-1; - mcp->mod_ref = 1; - mcp->mod_loaded = 1; - mcp->mod_loadcnt = 1; - mcp->mod_mp = mp; - - /* - * Try to open a Xen image that hasn't had its symbol and CTF - * information stripped off. - */ - file = kobj_open_file(XPV_FILENAME); - if (file == (struct _buf *)-1) { - file = NULL; - goto err; - } - - /* - * Read the header and ensure that this is an ELF file for the - * proper ISA. If it's not, somebody has done something very - * stupid. Why bother? See Mencken. - */ - if (kobj_read_file(file, (char *)&mp->hdr, sizeof (mp->hdr), 0) < 0) - goto err; - for (i = 0; i < SELFMAG; i++) - if (mp->hdr.e_ident[i] != ELFMAG[i]) - goto err; - if ((mp->hdr.e_ident[EI_DATA] != ELFDATA2LSB) || - (mp->hdr.e_machine != machine)) - goto err; - - /* Read in the section headers */ - n = mp->hdr.e_shentsize * mp->hdr.e_shnum; - mp->shdrs = kmem_zalloc(n, KM_SLEEP); - if (kobj_read_file(file, mp->shdrs, n, mp->hdr.e_shoff) < 0) - goto err; - - /* Read the section names */ - shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize); - namesize = shp->sh_size; - names = kmem_zalloc(shp->sh_size, KM_SLEEP); - if (kobj_read_file(file, names, shp->sh_size, shp->sh_offset) < 0) - goto err; - - /* - * Fill in the text and data size fields. - */ - ctf_shp = NULL; - text_align = data_align = 0; - for (shn = 1; shn < mp->hdr.e_shnum; shn++) { - shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize); - - /* Sanity check the offset of the section name */ - if (shp->sh_name >= namesize) - continue; - - /* If we find the symtab section, remember it for later. */ - if (shp->sh_type == SHT_SYMTAB) { - mp->symtbl_section = shn; - mp->symhdr = shp; - continue; - } - - /* If we find the CTF section, remember it for later. */ - if ((shp->sh_size != 0) && - (strcmp(names + shp->sh_name, ".SUNW_ctf") == 0)) { - ctf_shp = shp; - continue; - } - - if (!(shp->sh_flags & SHF_ALLOC)) - continue; - - /* - * Xen marks its text section as writable, so we need to - * look for the name - not just the flag. - */ - if ((strcmp(&names[shp->sh_name], ".text") != 0) && - (shp->sh_flags & SHF_WRITE) != 0) { - if (shp->sh_addralign > data_align) - data_align = shp->sh_addralign; - mp->data_size = ALIGN(mp->data_size, data_align); - mp->data_size += ALIGN(shp->sh_size, 8); - if (mp->data == NULL || mp->data > (char *)shp->sh_addr) - mp->data = (char *)shp->sh_addr; - } else { - if (shp->sh_addralign > text_align) - text_align = shp->sh_addralign; - mp->text_size = ALIGN(mp->text_size, text_align); - mp->text_size += ALIGN(shp->sh_size, 8); - if (mp->text == NULL || mp->text > (char *)shp->sh_addr) - mp->text = (char *)shp->sh_addr; - } - } - kmem_free(names, namesize); - names = NULL; - shp = NULL; - mcp->mod_text = mp->text; - mcp->mod_text_size = mp->text_size; - - /* - * If we have symbol table and string table sections, read them in - * now. If we don't, we just plow on. We'll still get a valid - * core dump, but finding anything useful will be just a bit - * harder. - * - * Note: we don't bother with a hash table. We'll never do a - * symbol lookup unless we crash, and then mdb creates its own. We - * also don't try to perform any relocations. Xen should be loaded - * exactly where the ELF file indicates, and the symbol information - * in the file should be complete and correct already. Static - * linking ain't all bad. - */ - if ((mp->symhdr != NULL) && (mp->symhdr->sh_link < mp->hdr.e_shnum)) { - mp->strhdr = (Shdr *) - (mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize); - mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize; - - /* Allocate space for the symbol table and strings. */ - mp->symsize = mp->symhdr->sh_size + - mp->nsyms * sizeof (symid_t) + mp->strhdr->sh_size; - mp->symspace = kmem_zalloc(mp->symsize, KM_SLEEP); - mp->symtbl = mp->symspace; - mp->strings = (char *)(mp->symtbl + mp->symhdr->sh_size); - - if ((kobj_read_file(file, mp->symtbl, - mp->symhdr->sh_size, mp->symhdr->sh_offset) < 0) || - (kobj_read_file(file, mp->strings, - mp->strhdr->sh_size, mp->strhdr->sh_offset) < 0)) - goto err; - } - - /* - * Read in the CTF section - */ - if ((ctf_shp != NULL) && ((moddebug & MODDEBUG_NOCTF) == 0)) { - mp->ctfdata = kmem_zalloc(ctf_shp->sh_size, KM_SLEEP); - mp->ctfsize = ctf_shp->sh_size; - if (kobj_read_file(file, mp->ctfdata, mp->ctfsize, - ctf_shp->sh_offset) < 0) - goto err; - } - - kobj_close_file(file); - - xpv_module = mp; - xpv_modctl = mcp; - return; - -err: - cmn_err(CE_WARN, "Failed to initialize xpv module."); - if (file != NULL) - kobj_close_file(file); - - kmem_free(mp->filename, strlen(XPV_FILENAME) + 1); - if (mp->shdrs != NULL) - kmem_free(mp->shdrs, mp->hdr.e_shentsize * mp->hdr.e_shnum); - if (mp->symspace != NULL) - kmem_free(mp->symspace, mp->symsize); - if (mp->ctfdata != NULL) - kmem_free(mp->ctfdata, mp->ctfsize); - kmem_free(mp, sizeof (*mp)); - kmem_free(mcp->mod_filename, strlen(XPV_FILENAME) + 1); - kmem_free(mcp->mod_modname, strlen(XPV_MODNAME) + 1); - kmem_free(mcp, sizeof (*mcp)); - if (names != NULL) - kmem_free(names, namesize); -} - -void -xpv_panic_init() -{ - xen_platform_op_t op; - int i; - - ASSERT(DOMAIN_IS_INITDOMAIN(xen_info)); - - for (i = 0; i < mmu.num_level; i++) - ptable_pfn[i] = PFN_INVALID; - - /* Let Xen know where to jump if/when it panics. */ - op.cmd = XENPF_panic_init; - op.interface_version = XENPF_INTERFACE_VERSION; - op.u.panic_init.panic_addr = (unsigned long)xpv_panic_hdlr; - - (void) HYPERVISOR_platform_op(&op); - - init_xen_module(); -} diff --git a/usr/src/uts/i86xpv/os/xpv_timestamp.c b/usr/src/uts/i86xpv/os/xpv_timestamp.c deleted file mode 100644 index 8b7d226305..0000000000 --- a/usr/src/uts/i86xpv/os/xpv_timestamp.c +++ /dev/null @@ -1,172 +0,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. - * Copyright 2016 Joyent, Inc. - */ - -#include -#include -#include -#include -#include - -#include - -/* - * On the hypervisor, we have a virtualized system time based upon the - * information provided for each VCPU, which is updated every time it is - * scheduled onto a real CPU. Thus, none of the traditional code in - * i86pc/os/timestamp.c applies, our gethrtime() implementation is run through - * the PSM, and there is no scaling step to apply. - * - * However, the platform does not guarantee monotonicity; thus we have to fake - * this up, which is a deeply unpleasant thing to have to do. - * - * Note that the virtualized interface still relies on the current TSC to - * calculate the time in nanoseconds since the VCPU was scheduled, and is thus - * subject to all the problems with that. For the most part, the hypervisor is - * supposed to deal with them. - * - * Another wrinkle involves suspend/resume/migration. If we come back and time - * is apparently less, we may have resumed on a different machine or on the - * same machine after a reboot. In this case we need to maintain an addend to - * ensure time continues reasonably. Otherwise we could end up taking a very - * long time to expire cyclics in the heap. Thus we have two functions: - * - * xpv_getsystime() - * - * The unadulterated system time from the hypervisor. This is only to be - * used when programming the hypervisor (setting a timer or calculating - * the TOD). - * - * xpv_gethrtime() - * - * This is the monotonic hrtime counter to be used by everything else such - * as the cyclic subsystem. We should never pass an hrtime directly into - * a hypervisor interface, as hrtime_addend may well be non-zero. - */ - -int hrtime_fake_mt = 1; -static volatile hrtime_t hrtime_last; -static hrtime_t hrtime_suspend_time; -static hrtime_t hrtime_addend; - -volatile uint32_t hres_lock; -hrtime_t hres_last_tick; -int64_t hrestime_adj; -volatile timestruc_t hrestime; - -/* - * These functions are used in DTrace probe context, and must be removed from - * fbt consideration. Currently fbt ignores all weak symbols, so this will - * achieve that. - */ -#pragma weak xpv_gethrtime = dtrace_xpv_gethrtime -#pragma weak xpv_getsystime = dtrace_xpv_getsystime -#pragma weak dtrace_gethrtime = dtrace_xpv_gethrtime -#pragma weak tsc_read = dtrace_xpv_gethrtime - -hrtime_t -dtrace_xpv_getsystime(void) -{ - vcpu_time_info_t *src; - vcpu_time_info_t __vti, *dst = &__vti; - uint64_t tsc_delta; - uint64_t tsc; - hrtime_t result; - uint32_t stamp; - - src = &CPU->cpu_m.mcpu_vcpu_info->time; - - /* - * Loop until version has not been changed during our update, and a Xen - * update is not under way (lowest bit is set). - */ - do { - dst->version = src->version; - stamp = CPU->cpu_m.mcpu_istamp; - - membar_consumer(); - - dst->tsc_timestamp = src->tsc_timestamp; - dst->system_time = src->system_time; - dst->tsc_to_system_mul = src->tsc_to_system_mul; - dst->tsc_shift = src->tsc_shift; - - /* - * Note that this use of the -actual- TSC register - * should probably be the SOLE one in the system on this - * paravirtualized platform. - */ - tsc = __rdtsc_insn(); - tsc_delta = tsc - dst->tsc_timestamp; - - membar_consumer(); - - } while (((src->version & 1) | (dst->version ^ src->version)) || - CPU->cpu_m.mcpu_istamp != stamp); - - if (dst->tsc_shift >= 0) - tsc_delta <<= dst->tsc_shift; - else if (dst->tsc_shift < 0) - tsc_delta >>= -dst->tsc_shift; - - result = dst->system_time + - ((uint64_t)(tsc_delta * (uint64_t)dst->tsc_to_system_mul) >> 32); - - return (result); -} - -hrtime_t -dtrace_xpv_gethrtime(void) -{ - hrtime_t result = xpv_getsystime() + hrtime_addend; - - if (hrtime_fake_mt) { - hrtime_t last; - do { - last = hrtime_last; - if (result < last) - result = last + 1; - } while (atomic_cas_64((volatile uint64_t *)&hrtime_last, - last, result) != last); - } - - return (result); -} - -void -xpv_time_suspend(void) -{ - hrtime_suspend_time = xpv_getsystime(); -} - -void -xpv_time_resume(void) -{ - hrtime_t delta = xpv_getsystime() - hrtime_suspend_time; - - if (delta < 0) - hrtime_addend += -delta; -} diff --git a/usr/src/uts/i86xpv/pci-ide/Makefile b/usr/src/uts/i86xpv/pci-ide/Makefile deleted file mode 100644 index 0dbccb26f1..0000000000 --- a/usr/src/uts/i86xpv/pci-ide/Makefile +++ /dev/null @@ -1,89 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. -# - -# -# This makefile drives the production of the pci-ide "drv" -# kernel module. -# -# i86xpv 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 = pci-ide -OBJECTS = $(PCIIDE_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/io/pci-ide - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(CONFMOD) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# Overrides. -# -DEBUG_FLGS = -DEBUG_DEFS += $(DEBUG_FLGS) - -INC_PATH += -I$(UTSBASE)/common/io/pci-ide - -CERRWARN += -Wno-switch -CERRWARN += -Wno-unused-function - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/pci/Makefile b/usr/src/uts/i86xpv/pci/Makefile deleted file mode 100644 index c8ef5052d4..0000000000 --- a/usr/src/uts/i86xpv/pci/Makefile +++ /dev/null @@ -1,92 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. -# - -# -# This makefile drives the production of the PCI nexus driver -# -# i86xpv 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 = pci -OBJECTS = $(PCINEXUS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# depends on misc/pci_autoconfig misc/pcihp -# -LDFLAGS += -dy -Nmisc/pcihp - -# -# Name of the module is needed by the source, to distinguish from other -# PCI/PCI-express nexi -# -CFLAGS += -D_MODULE_NAME="\"$(MODULE)\"" - - -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-function - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/pit_beep/Makefile b/usr/src/uts/i86xpv/pit_beep/Makefile deleted file mode 100644 index d71f06d842..0000000000 --- a/usr/src/uts/i86xpv/pit_beep/Makefile +++ /dev/null @@ -1,72 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# uts/intel/pit_beep/Makefile -# -# This makefile drives the production of the pit_beep driver. -# -# i86xpv 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 = pit_beep -OBJECTS = $(PIT_BEEP_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/intel/io - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(CONFMOD) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -.KEEP_STATE: - -all: $(ALL_DEPS) - -def: $(DEF_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/privcmd/Makefile b/usr/src/uts/i86xpv/privcmd/Makefile deleted file mode 100644 index d98759b648..0000000000 --- a/usr/src/uts/i86xpv/privcmd/Makefile +++ /dev/null @@ -1,78 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the privcmd -# driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = privcmd -OBJECTS = $(PRIVCMD_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - - -CERRWARN += -Wno-uninitialized - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/rootnex/Makefile b/usr/src/uts/i86xpv/rootnex/Makefile deleted file mode 100644 index 4318656008..0000000000 --- a/usr/src/uts/i86xpv/rootnex/Makefile +++ /dev/null @@ -1,87 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. -# - -# -# This makefile drives the production of the rootnex driver -# -# i86xpv 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 = rootnex -OBJECTS = $(ROOTNEX_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides. -# -LDFLAGS += -dy - - -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-unused-label -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-function - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/unix/Makefile b/usr/src/uts/i86xpv/unix/Makefile deleted file mode 100644 index 177095c2c1..0000000000 --- a/usr/src/uts/i86xpv/unix/Makefile +++ /dev/null @@ -1,188 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of unix (and unix.o). -# -# i86xpv implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -UNIX = unix -DBOOT = dboot - -OBJECTS = $(SPECIAL_OBJS:%=$(OBJS_DIR)/%) \ - $(CORE_OBJS:%=$(OBJS_DIR)/%) \ - $(KRTLD_OBJS:%=$(OBJS_DIR)/%) \ - $(MACH_NOT_YET_KMODS:%=$(OBJS_DIR)/%) - -ROOTMODULE = $(ROOT_PSM_KERN_DIR)/$(UNIX) - -UNIX_BIN = $(OBJS_DIR)/$(UNIX) - -LIBS = $(GENLIB) - -GENUNIX = genunix -GENUNIX_DIR = ../../intel/$(GENUNIX) - -LIBOPTS = -L $(GENUNIX_DIR)/$(OBJS_DIR) -l $(GENUNIX) - -CTFEXTRAOBJS = $(OBJS_DIR)/vers.o - -DBOOT_OBJS_DIR = dboot/$(OBJS_DIR) -DBOOT_OBJECTS = $(DBOOT_OBJS:%=$(DBOOT_OBJS_DIR)/%) -DBOOT_BIN = $(DBOOT_OBJS_DIR)/$(DBOOT) -DBOOT_O = $(OBJS_DIR)/$(DBOOT).o -DBOOT_S = $(DBOOT_O:%.o=%.s) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(UNIX_BIN) -INSTALL_TARGET = $(UNIX_BIN) $(ROOTMODULE) - -# -# This is UNIX_DIR. Use a short path. -# -UNIX_DIR = . - -# -# Overrides -# -CLEANFILES += \ - $(UNIX_O) $(MODSTUBS_O) \ - $(OBJS_DIR)/vers.c $(OBJS_DIR)/vers.o \ - $(OBJS_DIR)/dtracestubs.s \ - $(DTRACESTUBS_O) $(DTRACESTUBS) - -CLEANFILES += \ - $(DBOOT_O) $(DBOOT_S) \ - $(DBOOT_OBJECTS) \ - $(DBOOT_BIN) - -CLEANFILES += \ - $(DBOOT_OBJS_DIR)/$(VGATEXT_FONT).c \ - $(OBJS_DIR)/$(VGATEXT_FONT).c - -CLEANFILES += \ - $(OBJS_DIR)/fb_swtch_src.o \ - $(OBJS_DIR)/fb_swtch_src \ - $(OBJS_DIR)/fb_swtch.s - -CLEANFILES += \ - $(ZLIB_OBJS:%.o=$(OBJS_DIR)/%.o) \ - $(ZLIB_OBJS:%.o=$(OBJS_DIR)/%.ln) - -CLOBBERFILES = $(CLEANFILES) $(UNIX_BIN) - -# instr_size needs a special header -$(OBJS_DIR)/instr_size.o := EXTRA_OPTIONS = -I$(SRC)/common/dis/i386 -$(OBJS_DIR)/instr_size.ln := EXTRA_OPTIONS = -I$(SRC)/common/dis/i386 - -CFLAGS += -DDIS_MEM - -# -# For now, disable these compiler warnings; maintainers should endeavor to -# investigate and remove these for maximum coverage. Please do not carry -# these forward to new Makefiles. -# - -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-char-subscripts -CERRWARN += -Wno-unused-variable -CERRWARN += -Wno-unused-function -CERRWARN += -Wno-unused-label -CERRWARN += -Wno-type-limits -CERRWARN += -Wno-clobbered -CERRWARN += -Wno-unused-value -CERRWARN += -Wno-empty-body - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -MAPFILE_32 = $(MAPFILE) -MAPFILE_64 = $(MAPFILE).amd64 - -MAPFILE_NAME = $(MAPFILE_$(CLASS)) - -$(UNIX_BIN): $(UNIX_O) $(MODSTUBS_O) $(MAPFILE_NAME) \ - $(GENLIB) $(DTRACESTUBS) $(DBOOT_O) - $(LD) -dy -b -o $@ -e dboot_image -znointerp -M $(MAPFILE_NAME) \ - $(UNIX_O) $(DBOOT_O) $(MODSTUBS_O) $(LIBOPTS) \ - $(DTRACESTUBS) - $(CTFMERGE_MODULE) - $(POST_PROCESS) - -$(UNIX_O): $(OBJECTS) $(OBJS_DIR)/vers.o - $(LD) -r -o $@ $(OBJECTS) $(OBJS_DIR)/vers.o - -$(DBOOT_BIN): $(DBOOT_OBJS_DIR) $(DBOOT_OBJECTS) dboot/Mapfile.dboot - $(LD) -dn -e _start -M dboot/Mapfile.dboot \ - -o $(DBOOT_BIN) $(DBOOT_OBJECTS) - -$(DBOOT_O): $(DBOOT_BIN) - @echo " .data" > $(DBOOT_S) - @echo " .globl dboot_image" >> $(DBOOT_S) - @echo "dboot_image:" >> $(DBOOT_S) - $(ELFEXTRACT) $(DBOOT_BIN) >> $(DBOOT_S) - $(COMPILE.s) -o $(DBOOT_O) $(DBOOT_S) - -$(DBOOT_OBJS_DIR): - -@mkdir -p $@ 2> /dev/null - -# -# Special rules for generating assym.h for inclusion in assembly files. -# -$(DSF_DIR)/$(OBJS_DIR)/assym.h $(DSF_DIR)/$(OBJS_DIR)/kdi_assym.h: FRC - @cd $(DSF_DIR); $(MAKE) all.targ - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/unix/dboot/Mapfile.dboot b/usr/src/uts/i86xpv/unix/dboot/Mapfile.dboot deleted file mode 100644 index 955ce1e60c..0000000000 --- a/usr/src/uts/i86xpv/unix/dboot/Mapfile.dboot +++ /dev/null @@ -1,59 +0,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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. -# - -$mapfile_version 2 - -LOAD_SEGMENT dboot { - NOHDR; - FLAGS = READ WRITE EXECUTE; - VADDR = 0x40800000; - PADDR = 0x40800000; - ALIGN = 0x1000; - - # - # Make sure that dboot_xen.s`_start is the first thing in the dboot - # .text segment, since when we boot that's where the boot loader will - # start execution - # - ASSIGN_SECTION is_text { - IS_NAME = .text; - FILE_BASENAME = dboot_xen.o; - }; - ASSIGN_SECTION is_progbits { - TYPE = PROGBITS; - FLAGS = ALLOC; - }; - ASSIGN_SECTION is_nobits { - TYPE = NOBITS; - FLAGS = ALLOC; - }; - IS_ORDER = is_text is_progbits is_nobits; -}; - -LOAD_SEGMENT otherstuff { - ASSIGN_SECTION { - FLAGS = ALLOC; - }; -}; diff --git a/usr/src/uts/i86xpv/vm/seg_mf.c b/usr/src/uts/i86xpv/vm/seg_mf.c deleted file mode 100644 index 54a60cf2a1..0000000000 --- a/usr/src/uts/i86xpv/vm/seg_mf.c +++ /dev/null @@ -1,753 +0,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 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Machine frame segment driver. This segment driver allows dom0 processes to - * map pages of other domains or Xen (e.g. during save/restore). ioctl()s on - * the privcmd driver provide the MFN values backing each mapping, and we map - * them into the process's address space at this time. Demand-faulting is not - * supported by this driver due to the requirements upon some of the ioctl()s. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define VTOCVP(vp) (VTOS(vp)->s_commonvp) - -typedef struct segmf_mfn_s { - mfn_t m_mfn; -} segmf_mfn_t; - -/* g_flags */ -#define SEGMF_GFLAGS_WR 0x1 -#define SEGMF_GFLAGS_MAPPED 0x2 -typedef struct segmf_gref_s { - uint64_t g_ptep; - grant_ref_t g_gref; - uint32_t g_flags; - grant_handle_t g_handle; -} segmf_gref_t; - -typedef union segmf_mu_u { - segmf_mfn_t m; - segmf_gref_t g; -} segmf_mu_t; - -typedef enum { - SEGMF_MAP_EMPTY = 0, - SEGMF_MAP_MFN, - SEGMF_MAP_GREF -} segmf_map_type_t; - -typedef struct segmf_map_s { - segmf_map_type_t t_type; - segmf_mu_t u; -} segmf_map_t; - -struct segmf_data { - kmutex_t lock; - struct vnode *vp; - uchar_t prot; - uchar_t maxprot; - size_t softlockcnt; - domid_t domid; - segmf_map_t *map; -}; - -static const struct seg_ops segmf_ops; - -static int segmf_fault_gref_range(struct seg *seg, caddr_t addr, size_t len); - -static struct segmf_data * -segmf_data_zalloc(struct seg *seg) -{ - struct segmf_data *data = kmem_zalloc(sizeof (*data), KM_SLEEP); - - mutex_init(&data->lock, "segmf.lock", MUTEX_DEFAULT, NULL); - seg->s_ops = &segmf_ops; - seg->s_data = data; - return (data); -} - -int -segmf_create(struct seg *seg, void *args) -{ - struct segmf_crargs *a = args; - struct segmf_data *data; - struct as *as = seg->s_as; - pgcnt_t i, npages = seg_pages(seg); - int error; - - hat_map(as->a_hat, seg->s_base, seg->s_size, HAT_MAP); - - data = segmf_data_zalloc(seg); - data->vp = specfind(a->dev, VCHR); - data->prot = a->prot; - data->maxprot = a->maxprot; - - data->map = kmem_alloc(npages * sizeof (segmf_map_t), KM_SLEEP); - for (i = 0; i < npages; i++) { - data->map[i].t_type = SEGMF_MAP_EMPTY; - } - - error = fop_addmap(VTOCVP(data->vp), 0, as, seg->s_base, seg->s_size, - data->prot, data->maxprot, MAP_SHARED, CRED(), NULL); - - if (error != 0) - hat_unload(as->a_hat, - seg->s_base, seg->s_size, HAT_UNLOAD_UNMAP); - return (error); -} - -/* - * Duplicate a seg and return new segment in newseg. - */ -static int -segmf_dup(struct seg *seg, struct seg *newseg) -{ - struct segmf_data *data = seg->s_data; - struct segmf_data *ndata; - pgcnt_t npages = seg_pages(newseg); - size_t sz; - - ndata = segmf_data_zalloc(newseg); - - VN_HOLD(data->vp); - ndata->vp = data->vp; - ndata->prot = data->prot; - ndata->maxprot = data->maxprot; - ndata->domid = data->domid; - - sz = npages * sizeof (segmf_map_t); - ndata->map = kmem_alloc(sz, KM_SLEEP); - bcopy(data->map, ndata->map, sz); - - return (fop_addmap(VTOCVP(ndata->vp), 0, newseg->s_as, - newseg->s_base, newseg->s_size, ndata->prot, ndata->maxprot, - MAP_SHARED, CRED(), NULL)); -} - -/* - * We only support unmapping the whole segment, and we automatically unlock - * what we previously soft-locked. - */ -static int -segmf_unmap(struct seg *seg, caddr_t addr, size_t len) -{ - struct segmf_data *data = seg->s_data; - offset_t off; - - if (addr < seg->s_base || addr + len > seg->s_base + seg->s_size || - (len & PAGEOFFSET) || ((uintptr_t)addr & PAGEOFFSET)) - panic("segmf_unmap"); - - if (addr != seg->s_base || len != seg->s_size) - return (ENOTSUP); - - hat_unload(seg->s_as->a_hat, addr, len, - HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK); - - off = (offset_t)seg_page(seg, addr); - - ASSERT(data->vp != NULL); - - (void) fop_delmap(VTOCVP(data->vp), off, seg->s_as, addr, len, - data->prot, data->maxprot, MAP_SHARED, CRED(), NULL); - - seg_free(seg); - return (0); -} - -static void -segmf_free(struct seg *seg) -{ - struct segmf_data *data = seg->s_data; - pgcnt_t npages = seg_pages(seg); - - kmem_free(data->map, npages * sizeof (segmf_map_t)); - VN_RELE(data->vp); - mutex_destroy(&data->lock); - kmem_free(data, sizeof (*data)); -} - -static int segmf_faultpage_debug = 0; -/*ARGSUSED*/ -static int -segmf_faultpage(struct hat *hat, struct seg *seg, caddr_t addr, - enum fault_type type, uint_t prot) -{ - struct segmf_data *data = seg->s_data; - uint_t hat_flags = HAT_LOAD_NOCONSIST; - mfn_t mfn; - x86pte_t pte; - segmf_map_t *map; - uint_t idx; - - - idx = seg_page(seg, addr); - map = &data->map[idx]; - ASSERT(map->t_type == SEGMF_MAP_MFN); - - mfn = map->u.m.m_mfn; - - if (type == F_SOFTLOCK) { - mutex_enter(&freemem_lock); - data->softlockcnt++; - mutex_exit(&freemem_lock); - hat_flags |= HAT_LOAD_LOCK; - } else - hat_flags |= HAT_LOAD; - - if (segmf_faultpage_debug > 0) { - uprintf("segmf_faultpage: addr %p domid %x mfn %lx prot %x\n", - (void *)addr, data->domid, mfn, prot); - segmf_faultpage_debug--; - } - - /* - * Ask the HAT to load a throwaway mapping to page zero, then - * overwrite it with our foreign domain mapping. It gets removed - * later via hat_unload() - */ - hat_devload(hat, addr, MMU_PAGESIZE, (pfn_t)0, - PROT_READ | HAT_UNORDERED_OK, hat_flags); - - pte = mmu_ptob((x86pte_t)mfn) | PT_VALID | PT_USER | PT_FOREIGN; - if (prot & PROT_WRITE) - pte |= PT_WRITABLE; - - if (HYPERVISOR_update_va_mapping_otherdomain((uintptr_t)addr, pte, - UVMF_INVLPG | UVMF_ALL, data->domid) != 0) { - hat_flags = HAT_UNLOAD_UNMAP; - - if (type == F_SOFTLOCK) { - hat_flags |= HAT_UNLOAD_UNLOCK; - mutex_enter(&freemem_lock); - data->softlockcnt--; - mutex_exit(&freemem_lock); - } - - hat_unload(hat, addr, MMU_PAGESIZE, hat_flags); - return (FC_MAKE_ERR(EFAULT)); - } - - return (0); -} - -static int -seg_rw_to_prot(enum seg_rw rw) -{ - switch (rw) { - case S_READ: - return (PROT_READ); - case S_WRITE: - return (PROT_WRITE); - case S_EXEC: - return (PROT_EXEC); - case S_OTHER: - default: - break; - } - return (PROT_READ | PROT_WRITE | PROT_EXEC); -} - -static void -segmf_softunlock(struct hat *hat, struct seg *seg, caddr_t addr, size_t len) -{ - struct segmf_data *data = seg->s_data; - - hat_unlock(hat, addr, len); - - mutex_enter(&freemem_lock); - ASSERT(data->softlockcnt >= btopr(len)); - data->softlockcnt -= btopr(len); - mutex_exit(&freemem_lock); - - if (data->softlockcnt == 0) { - struct as *as = seg->s_as; - - if (AS_ISUNMAPWAIT(as)) { - mutex_enter(&as->a_contents); - if (AS_ISUNMAPWAIT(as)) { - AS_CLRUNMAPWAIT(as); - cv_broadcast(&as->a_cv); - } - mutex_exit(&as->a_contents); - } - } -} - -static int -segmf_fault_range(struct hat *hat, struct seg *seg, caddr_t addr, size_t len, - enum fault_type type, enum seg_rw rw) -{ - struct segmf_data *data = seg->s_data; - int error = 0; - caddr_t a; - - if ((data->prot & seg_rw_to_prot(rw)) == 0) - return (FC_PROT); - - /* loop over the address range handling each fault */ - - for (a = addr; a < addr + len; a += PAGESIZE) { - error = segmf_faultpage(hat, seg, a, type, data->prot); - if (error != 0) - break; - } - - if (error != 0 && type == F_SOFTLOCK) { - size_t done = (size_t)(a - addr); - - /* - * Undo what's been done so far. - */ - if (done > 0) - segmf_softunlock(hat, seg, addr, done); - } - - return (error); -} - -/* - * We never demand-fault for seg_mf. - */ -/*ARGSUSED*/ -static int -segmf_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len, - enum fault_type type, enum seg_rw rw) -{ - return (FC_MAKE_ERR(EFAULT)); -} - -/*ARGSUSED*/ -static int -segmf_faulta(struct seg *seg, caddr_t addr) -{ - return (0); -} - -/*ARGSUSED*/ -static int -segmf_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) -{ - return (EINVAL); -} - -/*ARGSUSED*/ -static int -segmf_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) -{ - return (EINVAL); -} - -/*ARGSUSED*/ -static int -segmf_kluster(struct seg *seg, caddr_t addr, ssize_t delta) -{ - return (-1); -} - -/*ARGSUSED*/ -static int -segmf_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags) -{ - return (0); -} - -/* - * XXPV Hmm. Should we say that mf mapping are "in core?" - */ - -/*ARGSUSED*/ -static size_t -segmf_incore(struct seg *seg, caddr_t addr, size_t len, char *vec) -{ - size_t v; - - for (v = 0, len = (len + PAGEOFFSET) & PAGEMASK; len; - len -= PAGESIZE, v += PAGESIZE) - *vec++ = 1; - return (v); -} - -/*ARGSUSED*/ -static int -segmf_lockop(struct seg *seg, caddr_t addr, - size_t len, int attr, int op, ulong_t *lockmap, size_t pos) -{ - return (0); -} - -static int -segmf_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv) -{ - struct segmf_data *data = seg->s_data; - pgcnt_t pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1; - - if (pgno != 0) { - do - protv[--pgno] = data->prot; - while (pgno != 0) - ; - } - return (0); -} - -static uoff_t -segmf_getoffset(struct seg *seg, caddr_t addr) -{ - return (addr - seg->s_base); -} - -/*ARGSUSED*/ -static int -segmf_gettype(struct seg *seg, caddr_t addr) -{ - return (MAP_SHARED); -} - -/*ARGSUSED1*/ -static int -segmf_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp) -{ - struct segmf_data *data = seg->s_data; - - *vpp = VTOCVP(data->vp); - return (0); -} - -/*ARGSUSED*/ -static int -segmf_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav) -{ - return (0); -} - -/*ARGSUSED*/ -static int -segmf_pagelock(struct seg *seg, caddr_t addr, size_t len, - struct page ***ppp, enum lock_type type, enum seg_rw rw) -{ - return (ENOTSUP); -} - -static int -segmf_getmemid(struct seg *seg, caddr_t addr, memid_t *memid) -{ - struct segmf_data *data = seg->s_data; - - memid->val[0] = (uintptr_t)VTOCVP(data->vp); - memid->val[1] = (uintptr_t)seg_page(seg, addr); - return (0); -} - -/* - * Add a set of contiguous foreign MFNs to the segment. soft-locking them. The - * pre-faulting is necessary due to live migration; in particular we must - * return an error in response to IOCTL_PRIVCMD_MMAPBATCH rather than faulting - * later on a bad MFN. Whilst this isn't necessary for the other MMAP - * ioctl()s, we lock them too, as they should be transitory. - */ -int -segmf_add_mfns(struct seg *seg, caddr_t addr, mfn_t mfn, - pgcnt_t pgcnt, domid_t domid) -{ - struct segmf_data *data = seg->s_data; - pgcnt_t base; - faultcode_t fc; - pgcnt_t i; - int error = 0; - - if (seg->s_ops != &segmf_ops) - return (EINVAL); - - /* - * Don't mess with dom0. - * - * Only allow the domid to be set once for the segment. - * After that attempts to add mappings to this segment for - * other domains explicitly fails. - */ - - if (domid == 0 || domid == DOMID_SELF) - return (EACCES); - - mutex_enter(&data->lock); - - if (data->domid == 0) - data->domid = domid; - - if (data->domid != domid) { - error = EINVAL; - goto out; - } - - base = seg_page(seg, addr); - - for (i = 0; i < pgcnt; i++) { - data->map[base + i].t_type = SEGMF_MAP_MFN; - data->map[base + i].u.m.m_mfn = mfn++; - } - - fc = segmf_fault_range(seg->s_as->a_hat, seg, addr, - pgcnt * MMU_PAGESIZE, F_SOFTLOCK, S_OTHER); - - if (fc != 0) { - error = fc_decode(fc); - for (i = 0; i < pgcnt; i++) { - data->map[base + i].t_type = SEGMF_MAP_EMPTY; - } - } - -out: - mutex_exit(&data->lock); - return (error); -} - -int -segmf_add_grefs(struct seg *seg, caddr_t addr, uint_t flags, - grant_ref_t *grefs, uint_t cnt, domid_t domid) -{ - struct segmf_data *data; - segmf_map_t *map; - faultcode_t fc; - uint_t idx; - uint_t i; - int e; - - if (seg->s_ops != &segmf_ops) - return (EINVAL); - - /* - * Don't mess with dom0. - * - * Only allow the domid to be set once for the segment. - * After that attempts to add mappings to this segment for - * other domains explicitly fails. - */ - - if (domid == 0 || domid == DOMID_SELF) - return (EACCES); - - data = seg->s_data; - idx = seg_page(seg, addr); - map = &data->map[idx]; - e = 0; - - mutex_enter(&data->lock); - - if (data->domid == 0) - data->domid = domid; - - if (data->domid != domid) { - e = EINVAL; - goto out; - } - - /* store away the grefs passed in then fault in the pages */ - for (i = 0; i < cnt; i++) { - map[i].t_type = SEGMF_MAP_GREF; - map[i].u.g.g_gref = grefs[i]; - map[i].u.g.g_handle = 0; - map[i].u.g.g_flags = 0; - if (flags & SEGMF_GREF_WR) { - map[i].u.g.g_flags |= SEGMF_GFLAGS_WR; - } - } - fc = segmf_fault_gref_range(seg, addr, cnt); - if (fc != 0) { - e = fc_decode(fc); - for (i = 0; i < cnt; i++) { - data->map[i].t_type = SEGMF_MAP_EMPTY; - } - } - -out: - mutex_exit(&data->lock); - return (e); -} - -int -segmf_release_grefs(struct seg *seg, caddr_t addr, uint_t cnt) -{ - gnttab_unmap_grant_ref_t mapop[SEGMF_MAX_GREFS]; - struct segmf_data *data; - segmf_map_t *map; - uint_t idx; - long e; - int i; - int n; - - - if (cnt > SEGMF_MAX_GREFS) { - return (-1); - } - - idx = seg_page(seg, addr); - data = seg->s_data; - map = &data->map[idx]; - - bzero(mapop, sizeof (gnttab_unmap_grant_ref_t) * cnt); - - /* - * for each entry which isn't empty and is currently mapped, - * set it up for an unmap then mark them empty. - */ - n = 0; - for (i = 0; i < cnt; i++) { - ASSERT(map[i].t_type != SEGMF_MAP_MFN); - if ((map[i].t_type == SEGMF_MAP_GREF) && - (map[i].u.g.g_flags & SEGMF_GFLAGS_MAPPED)) { - mapop[n].handle = map[i].u.g.g_handle; - mapop[n].host_addr = map[i].u.g.g_ptep; - mapop[n].dev_bus_addr = 0; - n++; - } - map[i].t_type = SEGMF_MAP_EMPTY; - } - - /* if there's nothing to unmap, just return */ - if (n == 0) { - return (0); - } - - e = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &mapop, n); - if (e != 0) { - return (-1); - } - - return (0); -} - - -void -segmf_add_gref_pte(struct seg *seg, caddr_t addr, uint64_t pte_ma) -{ - struct segmf_data *data; - uint_t idx; - - idx = seg_page(seg, addr); - data = seg->s_data; - - data->map[idx].u.g.g_ptep = pte_ma; -} - - -static int -segmf_fault_gref_range(struct seg *seg, caddr_t addr, size_t cnt) -{ - gnttab_map_grant_ref_t mapop[SEGMF_MAX_GREFS]; - struct segmf_data *data; - segmf_map_t *map; - uint_t idx; - int e; - int i; - - - if (cnt > SEGMF_MAX_GREFS) { - return (-1); - } - - data = seg->s_data; - idx = seg_page(seg, addr); - map = &data->map[idx]; - - bzero(mapop, sizeof (gnttab_map_grant_ref_t) * cnt); - - ASSERT(map->t_type == SEGMF_MAP_GREF); - - /* - * map in each page passed in into the user apps AS. We do this by - * passing the MA of the actual pte of the mapping to the hypervisor. - */ - for (i = 0; i < cnt; i++) { - mapop[i].host_addr = map[i].u.g.g_ptep; - mapop[i].dom = data->domid; - mapop[i].ref = map[i].u.g.g_gref; - mapop[i].flags = GNTMAP_host_map | GNTMAP_application_map | - GNTMAP_contains_pte; - if (!(map[i].u.g.g_flags & SEGMF_GFLAGS_WR)) { - mapop[i].flags |= GNTMAP_readonly; - } - } - e = xen_map_gref(GNTTABOP_map_grant_ref, mapop, cnt, B_TRUE); - if ((e != 0) || (mapop[0].status != GNTST_okay)) { - return (FC_MAKE_ERR(EFAULT)); - } - - /* save handle for segmf_release_grefs() and mark it as mapped */ - for (i = 0; i < cnt; i++) { - ASSERT(mapop[i].status == GNTST_okay); - map[i].u.g.g_handle = mapop[i].handle; - map[i].u.g.g_flags |= SEGMF_GFLAGS_MAPPED; - } - - return (0); -} - -static const struct seg_ops segmf_ops = { - .dup = segmf_dup, - .unmap = segmf_unmap, - .free = segmf_free, - .fault = segmf_fault, - .faulta = segmf_faulta, - .setprot = segmf_setprot, - .checkprot = segmf_checkprot, - .kluster = segmf_kluster, - .sync = segmf_sync, - .incore = segmf_incore, - .lockop = segmf_lockop, - .getprot = segmf_getprot, - .getoffset = segmf_getoffset, - .gettype = segmf_gettype, - .getvp = segmf_getvp, - .advise = segmf_advise, - .pagelock = segmf_pagelock, - .getmemid = segmf_getmemid, -}; diff --git a/usr/src/uts/i86xpv/xdb/Makefile b/usr/src/uts/i86xpv/xdb/Makefile deleted file mode 100644 index 00894261d6..0000000000 --- a/usr/src/uts/i86xpv/xdb/Makefile +++ /dev/null @@ -1,82 +0,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 -# - -# -# uts/i86xpv/xdb/Makefile -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# -# i86xpv architecture dependent -# -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xdb -OBJECTS = $(XDB_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - - -CERRWARN += -Wno-switch - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xdf/Makefile b/usr/src/uts/i86xpv/xdf/Makefile deleted file mode 100644 index f31a220ca6..0000000000 --- a/usr/src/uts/i86xpv/xdf/Makefile +++ /dev/null @@ -1,80 +0,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 -# - -# -# uts/i86xpv/xdf/Makefile -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# i86xpv 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_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# Overrides -LDFLAGS += -dy -Nmisc/cmlb - - -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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xdt/Makefile b/usr/src/uts/i86xpv/xdt/Makefile deleted file mode 100644 index c95b43a8e9..0000000000 --- a/usr/src/uts/i86xpv/xdt/Makefile +++ /dev/null @@ -1,55 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -UTSBASE = ../.. - -MODULE = xdt -OBJECTS = $(XDT_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/xen/dtrace - -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -LDFLAGS += -dy -Ndrv/dtrace - -CERRWARN += -Wno-uninitialized - -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -install: $(INSTALL_DEPS) - -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xenbus/Makefile b/usr/src/uts/i86xpv/xenbus/Makefile deleted file mode 100644 index 5579d1e09d..0000000000 --- a/usr/src/uts/i86xpv/xenbus/Makefile +++ /dev/null @@ -1,81 +0,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 -# - -# -# uts/i86xpv/xenbus/Makefile -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the xenbus -# xenstore driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xenbus -OBJECTS = $(XENBUS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - - -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-unused-variable - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xencons/Makefile b/usr/src/uts/i86xpv/xencons/Makefile deleted file mode 100644 index a345a55526..0000000000 --- a/usr/src/uts/i86xpv/xencons/Makefile +++ /dev/null @@ -1,82 +0,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 -# - -# -# uts/i86xpv/xencons/Makefile -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the xencons -# console driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xencons -OBJECTS = $(XENCONS_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/xen/io - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - - -CERRWARN += -Wno-unused-label -CERRWARN += -Wno-unused-variable - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xnb/Makefile b/usr/src/uts/i86xpv/xnb/Makefile deleted file mode 100644 index 0621521950..0000000000 --- a/usr/src/uts/i86xpv/xnb/Makefile +++ /dev/null @@ -1,94 +0,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 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# -# This makefile drives the production of the xnb -# network driver support module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xnb -OBJECTS = $(XNB_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# Module depends on mac. -# -LDFLAGS += -dy -N misc/mac - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - - -CERRWARN += -Wno-uninitialized - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xnbe/Makefile b/usr/src/uts/i86xpv/xnbe/Makefile deleted file mode 100644 index 7ca9c93d08..0000000000 --- a/usr/src/uts/i86xpv/xnbe/Makefile +++ /dev/null @@ -1,91 +0,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. -# -# -# This makefile drives the production of the xnbe -# network driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xnbe -OBJECTS = $(XNBE_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# Driver depends on MAC and IP. -# -#LDFLAGS += -dy -N misc/mac -N drv/ip - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xnbo/Makefile b/usr/src/uts/i86xpv/xnbo/Makefile deleted file mode 100644 index f942e7818a..0000000000 --- a/usr/src/uts/i86xpv/xnbo/Makefile +++ /dev/null @@ -1,91 +0,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. -# -# -# This makefile drives the production of the xnbo -# network driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xnbo -OBJECTS = $(XNBO_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# Driver depends on xnb and mac. -# -LDFLAGS += -dy -N misc/xnb -N misc/mac - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xnbu/Makefile b/usr/src/uts/i86xpv/xnbu/Makefile deleted file mode 100644 index ff04d425ff..0000000000 --- a/usr/src/uts/i86xpv/xnbu/Makefile +++ /dev/null @@ -1,91 +0,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. -# -# -# This makefile drives the production of the xnbu -# network driver kernel module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xnbu -OBJECTS = $(XNBU_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -# -# Driver depends on xnb and mac. -# -LDFLAGS += -dy -N misc/xnb -N misc/mac - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xnf/Makefile b/usr/src/uts/i86xpv/xnf/Makefile deleted file mode 100644 index 1158ed17c5..0000000000 --- a/usr/src/uts/i86xpv/xnf/Makefile +++ /dev/null @@ -1,88 +0,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 -# - -# -# uts/i86xpv/xnf/Makefile -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the xve -# network driver kernel module. -# -# i86xpv 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_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Driver depends on MAC & IP -# -LDFLAGS += -dy -N misc/mac -N drv/ip - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpv_autoconfig/Makefile b/usr/src/uts/i86xpv/xpv_autoconfig/Makefile deleted file mode 100644 index 9a865f6a17..0000000000 --- a/usr/src/uts/i86xpv/xpv_autoconfig/Makefile +++ /dev/null @@ -1,75 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the xpv autoconfiguration -# kernel module. -# -# i86xpv platform dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xpv_autoconfig -OBJECTS = $(XPV_AUTOCONFIG_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_MISC_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpv_psm/Makefile b/usr/src/uts/i86xpv/xpv_psm/Makefile deleted file mode 100644 index fde801afe3..0000000000 --- a/usr/src/uts/i86xpv/xpv_psm/Makefile +++ /dev/null @@ -1,95 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. -# - -# -# This makefile drives the production of the xpv_psm mach -# kernel module. -# -# i86xpv 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_psm -OBJECTS = $(XPV_PSM_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_MACH_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides. -# -DEBUG_FLGS = -DEBUG_DEFS += $(DEBUG_FLGS) - -# -# -# Depends on ACPI CA interpreter -# -LDFLAGS += -dy -N misc/acpica - - -CERRWARN += -Wno-type-limits -CERRWARN += -Wno-parentheses -CERRWARN += -Wno-uninitialized -CERRWARN += -Wno-empty-body -CERRWARN += -Wno-unused-function - -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpv_uppc/Makefile b/usr/src/uts/i86xpv/xpv_uppc/Makefile deleted file mode 100644 index 3d38ec7205..0000000000 --- a/usr/src/uts/i86xpv/xpv_uppc/Makefile +++ /dev/null @@ -1,89 +0,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 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# Copyright 2016 Joyent, Inc. -# -# This makefile drives the production of the xpv_uppc mach -# kernel module. -# -# i86xpv 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_uppc -OBJECTS = $(XPV_UPPC_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_MACH_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides. -# -DEBUG_FLGS = -DEBUG_DEFS += $(DEBUG_FLGS) - -CERRWARN += -Wno-unused-function - -# -# -# Depends on ACPI CA interpreter -# -LDFLAGS += -dy -N misc/acpica - - -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpvd/Makefile b/usr/src/uts/i86xpv/xpvd/Makefile deleted file mode 100644 index f5e0c76087..0000000000 --- a/usr/src/uts/i86xpv/xpvd/Makefile +++ /dev/null @@ -1,77 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the xpvd nexus driver -# -# i86xpv 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_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - - -CERRWARN += -Wno-uninitialized - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpvtap/Makefile b/usr/src/uts/i86xpv/xpvtap/Makefile deleted file mode 100644 index 7769a37954..0000000000 --- a/usr/src/uts/i86xpv/xpvtap/Makefile +++ /dev/null @@ -1,92 +0,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. -# - -# -# This makefile drives the production of the xpvtap -# driver module. -# -# i86xpv architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xpvtap -OBJECTS = $(XPVTAP_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS64) -ALL_BUILDS = $(ALL_BUILDS64) - -LDFLAGS += - -# -# use Solaris specific code in xen public header files -# -CFLAGS += -D_SOLARIS - - -CERRWARN += -Wno-unused-label - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -# This build only 64-bit -clean: $(CLEAN_DEPS) clean.debug32 - -clobber: $(CLOBBER_DEPS) clobber.debug32 - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xpvtod/Makefile b/usr/src/uts/i86xpv/xpvtod/Makefile deleted file mode 100644 index 6789721e7d..0000000000 --- a/usr/src/uts/i86xpv/xpvtod/Makefile +++ /dev/null @@ -1,75 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of xpvtod kernel module. -# -# i86xpv 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 = xpvtod -OBJECTS = $(XPVTOD_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_TOD_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# 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)/i86xpv/Makefile.targ diff --git a/usr/src/uts/i86xpv/xsvc/Makefile b/usr/src/uts/i86xpv/xsvc/Makefile deleted file mode 100644 index 4554bd6118..0000000000 --- a/usr/src/uts/i86xpv/xsvc/Makefile +++ /dev/null @@ -1,88 +0,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 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# This makefile drives the production of the xsvc driver kernel -# module. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = xsvc -OBJECTS = $(XSVC_OBJS:%=$(OBJS_DIR)/%) -ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/i86pc/io/xsvc - -# -# Include common rules. -# -include $(UTSBASE)/i86xpv/Makefile.i86xpv - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFFILE) -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# Dependency -# -LDFLAGS += -dy - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = $(OBJS_DIR) -CLEANFILES += $(MODSTUBS_O) - -CERRWARN += -Wno-uninitialized - -# -# 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)/i86xpv/Makefile.targ - diff --git a/usr/src/uts/intel/Makefile b/usr/src/uts/intel/Makefile index 8ae7fb5cdb..dfba5a5e17 100644 --- a/usr/src/uts/intel/Makefile +++ b/usr/src/uts/intel/Makefile @@ -77,7 +77,7 @@ CLOBBERFILES += $(PRIVS_C) # Prerequisites # # The uts/Makefile defines build parallelism for x86 platforms such that i86pc, -# i86xpv and intel are all built in parallel. This requires building certain +# and intel are all built in parallel. This requires building certain # parts before the parallel build can start. The uts/Makefile appends the # '.prereq' string to the original target and executes this Makefile to build # any prerequisites needed before the full parallel build can start. After that -- 2.11.4.GIT