summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authormrj <none@none>2008-04-04 09:45:16 -0700
committermrj <none@none>2008-04-04 09:45:16 -0700
commitcc7a88b54b4969574f03e1a1225bb13be487f5db (patch)
treed535317456dd0c45643fdb009061390fe159b15f /usr/src
parent94d96ab1f6a4c14b9fcb7e2e35061cca8d06fde6 (diff)
downloadillumos-joyent-cc7a88b54b4969574f03e1a1225bb13be487f5db.tar.gz
6684164 fix for 6545999 breaks 32-bit dom0
6683443 xVM panics during boot on systems without acpi Contributed by Juergen Keil (jk@tools.de)
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/Makefile4
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile30
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile46
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/ia32/Makefile45
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c492
-rw-r--r--usr/src/pkgdefs/SUNWcakrx.i/postinstall39
-rw-r--r--usr/src/pkgdefs/SUNWcakrx.i/preremove36
-rw-r--r--usr/src/pkgdefs/SUNWcakrx.i/prototype_com8
-rw-r--r--usr/src/pkgdefs/SUNWmdb/prototype_i3864
-rw-r--r--usr/src/pkgdefs/SUNWmdbr/prototype_i3864
-rw-r--r--usr/src/tools/scripts/bfu.sh14
-rw-r--r--usr/src/uts/i86pc/os/mp_implfuncs.c4
-rw-r--r--usr/src/uts/i86xpv/Makefile.files1
-rw-r--r--usr/src/uts/i86xpv/Makefile.i86xpv.shared4
-rw-r--r--usr/src/uts/i86xpv/io/psm/xpv_psm.c4
-rw-r--r--usr/src/uts/i86xpv/io/psm/xpv_uppc.c924
-rw-r--r--usr/src/uts/i86xpv/xpv_uppc/Makefile99
-rw-r--r--usr/src/uts/intel/ia32/ml/i86_subr.s2
18 files changed, 1748 insertions, 12 deletions
diff --git a/usr/src/cmd/mdb/i86xpv/modules/Makefile b/usr/src/cmd/mdb/i86xpv/modules/Makefile
index d00ea0d3ac..2df43b2ad4 100644
--- a/usr/src/cmd/mdb/i86xpv/modules/Makefile
+++ b/usr/src/cmd/mdb/i86xpv/modules/Makefile
@@ -20,10 +20,10 @@
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# 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
+SUBDIRS = unix xpv xpv_psm xpv_uppc
include ../../Makefile.subdirs
diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile
new file mode 100644
index 0000000000..aa4e7f72e0
--- /dev/null
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile
@@ -0,0 +1,30 @@
+#
+# 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
+SUBDIRS = ia32
+$(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
new file mode 100644
index 0000000000..3e2bc789c1
--- /dev/null
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile
@@ -0,0 +1,46 @@
+#
+# 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"
+
+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$(SRC)/uts/i86xpv
+CPPFLAGS += -I$(SRC)/uts/i86pc
+CPPFLAGS += -I$(SRC)/uts/intel
diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/ia32/Makefile b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/ia32/Makefile
new file mode 100644
index 0000000000..f91d8ee72c
--- /dev/null
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/ia32/Makefile
@@ -0,0 +1,45 @@
+#
+# 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"
+
+MODULE = xpv_uppc.so
+MDBTGT = kvm
+
+MODSRCS = xpv_uppc.c intr_common.c
+
+include ../../../../../Makefile.cmd
+include ../../../../intel/Makefile.ia32
+include ../../../Makefile.i86xpv
+include ../../../../Makefile.module
+
+MODSRCS_DIR = ../../../../i86pc/modules/common
+
+CPPFLAGS += -DMP -D_MACHDEP -D__xpv
+CPPFLAGS += -I../../../../common
+CPPFLAGS += -I../../../../i86pc/modules/common
+CPPFLAGS += -I$(SRC)/uts/common
+CPPFLAGS += -I$(SRC)/uts/i86xpv
+CPPFLAGS += -I$(SRC)/uts/i86pc
+CPPFLAGS += -I$(SRC)/uts/intel
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
new file mode 100644
index 0000000000..32410bcebb
--- /dev/null
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c
@@ -0,0 +1,492 @@
+/*
+ * 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 <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
+#include <mdb/mdb_ctf.h>
+#include <sys/evtchn_impl.h>
+
+#include "intr_common.h"
+
+static 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",
+ shared_info_addr, 0) == -1) {
+ mdb_warn("failed to read shared_info");
+ 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("%<u>CPU ");
+ else
+ mdb_printf("%<u>IRQ Vect Evtchn IPL(lo/hi) Bus Type Share ");
+ mdb_printf("%s %</u>\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("%<u>Type Evtchn IRQ IPL(lo/hi) CPU "
+ "Masked Pending ");
+ mdb_printf("%s %</u>\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 %<u>addr%</u> 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 <driver_name><instance#>\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/pkgdefs/SUNWcakrx.i/postinstall b/usr/src/pkgdefs/SUNWcakrx.i/postinstall
new file mode 100644
index 0000000000..558fbae354
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWcakrx.i/postinstall
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PATH="/usr/bin:/usr/sbin:${PATH}"
+export PATH
+
+# Check xpv_psm entry exists in etc/mach
+grep -w "xpv_psm" $BASEDIR/etc/mach > /dev/null 2>&1
+if [ $? -ne 0 ]
+then
+ echo "xpv_psm" >> $BASEDIR/etc/mach
+fi
+
+exit 0
diff --git a/usr/src/pkgdefs/SUNWcakrx.i/preremove b/usr/src/pkgdefs/SUNWcakrx.i/preremove
new file mode 100644
index 0000000000..6f37c68d1d
--- /dev/null
+++ b/usr/src/pkgdefs/SUNWcakrx.i/preremove
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# 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
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PATH="/usr/bin:/usr/sbin:${PATH}"
+export PATH
+
+# Remove xpv_psm entry in etc/mach
+grep -v -w "xpv_psm" $BASEDIR/etc/mach > /tmp/mach$$
+mv /tmp/mach$$ $BASEDIR/etc/mach
+
+exit 0
diff --git a/usr/src/pkgdefs/SUNWcakrx.i/prototype_com b/usr/src/pkgdefs/SUNWcakrx.i/prototype_com
index 355f8e76e1..d652f715dd 100644
--- a/usr/src/pkgdefs/SUNWcakrx.i/prototype_com
+++ b/usr/src/pkgdefs/SUNWcakrx.i/prototype_com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -39,6 +39,10 @@
i pkginfo
i copyright
+# installation scripts
+i postinstall
+i preremove
+
#
# source locations relative to the prototype file
#
@@ -70,6 +74,7 @@ f none platform/i86xpv/kernel/drv/xnf 755 root sys
f none platform/i86xpv/kernel/drv/xpvd 755 root sys
d none platform/i86xpv/kernel/mach 755 root sys
f none platform/i86xpv/kernel/mach/xpv_psm 755 root sys
+f none platform/i86xpv/kernel/mach/xpv_uppc 755 root sys
d none platform/i86xpv/kernel/misc 755 root sys
f none platform/i86xpv/kernel/misc/gfx_private 755 root sys
f none platform/i86xpv/kernel/misc/pcie 755 root sys
@@ -101,6 +106,7 @@ f none platform/i86xpv/kernel/drv/amd64/xnf 755 root sys
f none platform/i86xpv/kernel/drv/amd64/xpvd 755 root sys
d none platform/i86xpv/kernel/mach/amd64 755 root sys
f none platform/i86xpv/kernel/mach/amd64/xpv_psm 755 root sys
+f none platform/i86xpv/kernel/mach/amd64/xpv_uppc 755 root sys
d none platform/i86xpv/kernel/misc/amd64 755 root sys
f none platform/i86xpv/kernel/misc/amd64/gfx_private 755 root sys
f none platform/i86xpv/kernel/misc/amd64/pcie 755 root sys
diff --git a/usr/src/pkgdefs/SUNWmdb/prototype_i386 b/usr/src/pkgdefs/SUNWmdb/prototype_i386
index 4e0b41fe11..321120345f 100644
--- a/usr/src/pkgdefs/SUNWmdb/prototype_i386
+++ b/usr/src/pkgdefs/SUNWmdb/prototype_i386
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -56,9 +56,11 @@ d none usr/platform/i86xpv/lib/mdb/kvm/amd64 755 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/amd64/unix.so 555 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/amd64/xpv.so 555 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/amd64/xpv_psm.so 555 root sys
+f none usr/platform/i86xpv/lib/mdb/kvm/amd64/xpv_uppc.so 555 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/unix.so 555 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/xpv.so 555 root sys
f none usr/platform/i86xpv/lib/mdb/kvm/xpv_psm.so 555 root sys
+f none usr/platform/i86xpv/lib/mdb/kvm/xpv_uppc.so 555 root sys
d none usr/lib/mdb/kvm/amd64 755 root sys
f none usr/lib/mdb/kvm/amd64/arp.so 555 root sys
f none usr/lib/mdb/kvm/amd64/audiosup.so 555 root sys
diff --git a/usr/src/pkgdefs/SUNWmdbr/prototype_i386 b/usr/src/pkgdefs/SUNWmdbr/prototype_i386
index 53fae018c3..a0c04d3ff9 100644
--- a/usr/src/pkgdefs/SUNWmdbr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWmdbr/prototype_i386
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -107,5 +107,7 @@ d none platform/i86xpv/kernel/kmdb 755 root sys
d none platform/i86xpv/kernel/kmdb/amd64 755 root sys
f none platform/i86xpv/kernel/kmdb/amd64/unix 555 root sys
f none platform/i86xpv/kernel/kmdb/amd64/xpv_psm 555 root sys
+f none platform/i86xpv/kernel/kmdb/amd64/xpv_uppc 555 root sys
f none platform/i86xpv/kernel/kmdb/unix 555 root sys
f none platform/i86xpv/kernel/kmdb/xpv_psm 555 root sys
+f none platform/i86xpv/kernel/kmdb/xpv_uppc 555 root sys
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index 410746daf2..1df3a45c4b 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -750,6 +750,18 @@ update_mptconf_i386()
fi
}
+# update x86 etc/mach file after xVM_uppc is added,
+# which makes xpv_psm a non-default psm module
+update_etc_mach_i386()
+{
+ etc_mach=$rootprefix/etc/mach
+ test -f $etc_mach || return
+ grep -w "xpv_psm" $etc_mach > /dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo 'xpv_psm' >> $etc_mach
+ fi
+}
+
update_policy_conf() {
# update /etc/security/policy.conf with the default
# Solaris crypt(3c) policy.
@@ -7653,6 +7665,8 @@ mondo_loop() {
if [ $target_isa = i386 ]; then
update_mptconf_i386
+
+ update_etc_mach_i386
fi
if [ $zone != global ]; then
diff --git a/usr/src/uts/i86pc/os/mp_implfuncs.c b/usr/src/uts/i86pc/os/mp_implfuncs.c
index ce96e0960f..4b9400e3a3 100644
--- a/usr/src/uts/i86pc/os/mp_implfuncs.c
+++ b/usr/src/uts/i86pc/os/mp_implfuncs.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -349,7 +349,7 @@ mod_infopsm(struct modlpsm *modl, struct modlinkage *modlp, int *p0)
}
#if defined(__xpv)
-#define DEFAULT_PSM_MODULE "xpv_psm"
+#define DEFAULT_PSM_MODULE "xpv_uppc"
#else
#define DEFAULT_PSM_MODULE "uppc"
#endif
diff --git a/usr/src/uts/i86xpv/Makefile.files b/usr/src/uts/i86xpv/Makefile.files
index 541dac2efa..974f7038b5 100644
--- a/usr/src/uts/i86xpv/Makefile.files
+++ b/usr/src/uts/i86xpv/Makefile.files
@@ -194,6 +194,7 @@ ROOTNEX_OBJS += rootnex.o
XPVTOD_OBJS += xpvtod.o
XPV_AUTOCONFIG_OBJS += xpv_autoconfig.o
XPV_PSM_OBJS += xpv_psm.o mp_platform_common.o apic_introp.o psm_common.o
+XPV_UPPC_OBJS += xpv_uppc.o psm_common.o
XENBUS_OBJS += xenbus_dev.o
XENCONS_OBJS += xencons.o
XPVD_OBJS += xpvd.o
diff --git a/usr/src/uts/i86xpv/Makefile.i86xpv.shared b/usr/src/uts/i86xpv/Makefile.i86xpv.shared
index ca9e71821c..506c8035a0 100644
--- a/usr/src/uts/i86xpv/Makefile.i86xpv.shared
+++ b/usr/src/uts/i86xpv/Makefile.i86xpv.shared
@@ -22,7 +22,7 @@
#
# uts/i86xpv/Makefile.i86xpv.shared
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -296,7 +296,7 @@ DACF_KMODS += consconfig_dacf
#
# 'Mach' Modules (/kernel/mach):
#
-MACH_KMODS += xpv_psm
+MACH_KMODS += xpv_psm xpv_uppc
#
# 'TOD' modules (/platform/.../kernel/tod):
diff --git a/usr/src/uts/i86xpv/io/psm/xpv_psm.c b/usr/src/uts/i86xpv/io/psm/xpv_psm.c
index 4137ff1f6a..6d6b7e59a2 100644
--- a/usr/src/uts/i86xpv/io/psm/xpv_psm.c
+++ b/usr/src/uts/i86xpv/io/psm/xpv_psm.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1205,7 +1205,7 @@ static struct psm_ops xen_psm_ops = {
static struct psm_info xen_psm_info = {
PSM_INFO_VER01_5, /* version */
- PSM_OWN_SYS_DEFAULT, /* ownership */
+ PSM_OWN_EXCLUSIVE, /* ownership */
&xen_psm_ops, /* operation */
"xVM_psm", /* machine name */
"platform module %I%" /* machine descriptions */
diff --git a/usr/src/uts/i86xpv/io/psm/xpv_uppc.c b/usr/src/uts/i86xpv/io/psm/xpv_uppc.c
new file mode 100644
index 0000000000..cfd16bd9f3
--- /dev/null
+++ b/usr/src/uts/i86xpv/io/psm/xpv_uppc.c
@@ -0,0 +1,924 @@
+/*
+ * 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"
+
+#define PSMI_1_5
+
+#include <sys/mutex.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/clock.h>
+#include <sys/machlock.h>
+#include <sys/smp_impldefs.h>
+#include <sys/uadmin.h>
+#include <sys/promif.h>
+#include <sys/psm.h>
+#include <sys/psm_common.h>
+#include <sys/atomic.h>
+#include <sys/archsystm.h>
+#include <sys/mach_intr.h>
+#include <sys/hypervisor.h>
+#include <sys/evtchn_impl.h>
+#include <sys/modctl.h>
+#include <sys/trap.h>
+#include <sys/panic.h>
+
+#include <xen/public/vcpu.h>
+#include <xen/public/physdev.h>
+
+
+/*
+ * 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_add_16(&xen_uppc_irq_shared_table[irqno], 1);
+
+ /*
+ * 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_add_16(&xen_uppc_irq_shared_table[irqno], -1);
+
+ 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 */
+};
+
+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/xpv_uppc/Makefile b/usr/src/uts/i86xpv/xpv_uppc/Makefile
new file mode 100644
index 0000000000..d66402e579
--- /dev/null
+++ b/usr/src/uts/i86xpv/xpv_uppc/Makefile
@@ -0,0 +1,99 @@
+#
+# 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 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)/%)
+LINTS = $(XPV_UPPC_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_PSM_MACH_DIR)/$(MODULE)
+
+#
+# Include common rules.
+#
+include $(UTSBASE)/i86xpv/Makefile.i86xpv
+
+#
+# Define targets
+#
+ALL_TARGET = $(BINARY)
+LINT_TARGET = $(MODULE).lint
+INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+
+#
+# Overrides.
+#
+DEBUG_FLGS =
+DEBUG_DEFS += $(DEBUG_FLGS)
+
+#
+#
+# Depends on ACPI CA interpreter
+#
+LDFLAGS += -dy -N misc/acpica
+
+LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV
+LINTTAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED
+LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
+LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON
+
+# Default build targets.
+#
+.KEEP_STATE:
+
+def: $(DEF_DEPS)
+
+all: $(ALL_DEPS)
+
+clean: $(CLEAN_DEPS)
+
+clobber: $(CLOBBER_DEPS)
+
+lint: $(LINT_DEPS)
+
+modlintlib: $(MODLINTLIB_DEPS)
+
+clean.lint: $(CLEAN_LINT_DEPS)
+
+install: $(INSTALL_DEPS)
+
+#
+# Include common targets.
+#
+include $(UTSBASE)/i86xpv/Makefile.targ
diff --git a/usr/src/uts/intel/ia32/ml/i86_subr.s b/usr/src/uts/intel/ia32/ml/i86_subr.s
index 7cac692a8b..2e528f3534 100644
--- a/usr/src/uts/intel/ia32/ml/i86_subr.s
+++ b/usr/src/uts/intel/ia32/ml/i86_subr.s
@@ -2111,7 +2111,7 @@ restore_int_flag(ulong_t i)
* to change the state of the IF bit will be ignored.
* The virtual IF bit is tweaked by CLI and STI.
*/
- IE_TO_EVENT_MASK(%edx, %eax)
+ IE_TO_EVENT_MASK(%edx, 4(%esp))
#else
sti
#endif