diff options
author | mrj <none@none> | 2008-04-04 09:45:16 -0700 |
---|---|---|
committer | mrj <none@none> | 2008-04-04 09:45:16 -0700 |
commit | cc7a88b54b4969574f03e1a1225bb13be487f5db (patch) | |
tree | d535317456dd0c45643fdb009061390fe159b15f /usr/src | |
parent | 94d96ab1f6a4c14b9fcb7e2e35061cca8d06fde6 (diff) | |
download | illumos-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/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/Makefile | 30 | ||||
-rw-r--r-- | usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/amd64/Makefile | 46 | ||||
-rw-r--r-- | usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/ia32/Makefile | 45 | ||||
-rw-r--r-- | usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c | 492 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWcakrx.i/postinstall | 39 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWcakrx.i/preremove | 36 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWcakrx.i/prototype_com | 8 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWmdb/prototype_i386 | 4 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWmdbr/prototype_i386 | 4 | ||||
-rw-r--r-- | usr/src/tools/scripts/bfu.sh | 14 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/mp_implfuncs.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/Makefile.files | 1 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/Makefile.i86xpv.shared | 4 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/io/psm/xpv_psm.c | 4 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/io/psm/xpv_uppc.c | 924 | ||||
-rw-r--r-- | usr/src/uts/i86xpv/xpv_uppc/Makefile | 99 | ||||
-rw-r--r-- | usr/src/uts/intel/ia32/ml/i86_subr.s | 2 |
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 |