Index: head/sys/conf/options.powerpc =================================================================== --- head/sys/conf/options.powerpc (revision 328041) +++ head/sys/conf/options.powerpc (revision 328042) @@ -1,37 +1,37 @@ # $FreeBSD$ # Options specific to the powerpc platform kernels AIM opt_global.h BOOKE opt_global.h BOOKE_E500 opt_global.h BOOKE_PPC4XX opt_global.h CELL POWERPC POWERPC64 POWERPCSPE FPU_EMU COMPAT_FREEBSD32 opt_compat.h GFB_DEBUG opt_gfb.h GFB_NO_FONT_LOADING opt_gfb.h GFB_NO_MODE_CHANGE opt_gfb.h MPC85XX opt_platform.h POWERMAC opt_platform.h PS3 opt_platform.h MAMBO -POWERNV +POWERNV opt_platform.h PSERIES PSIM SC_OFWFB opt_ofwfb.h OFWCONS_POLL_HZ opt_ofw.h # AGP debugging support AGP_DEBUG opt_agp.h MIKROTIK Index: head/sys/powerpc/conf/GENERIC64 =================================================================== --- head/sys/powerpc/conf/GENERIC64 (revision 328041) +++ head/sys/powerpc/conf/GENERIC64 (revision 328042) @@ -1,223 +1,223 @@ # # GENERIC -- Generic kernel configuration file for FreeBSD/powerpc # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # https://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (https://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ cpu AIM ident GENERIC machine powerpc powerpc64 makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Platform support options POWERMAC #NewWorld Apple PowerMacs options PS3 #Sony Playstation 3 options MAMBO #IBM Mambo Full System Simulator options PSERIES #PAPR-compliant systems (e.g. IBM p) -options POWERNV #Non-virtualized OpenPOWER systems +options POWERNV #Non-virtualized OpenPOWER systems options FDT #Flattened Device Tree options SCHED_ULE #ULE scheduler options PREEMPTION #Enable kernel thread preemption options VIMAGE # Subsystem virtualization, e.g. VNET options INET #InterNETworking options INET6 #IPv6 communications protocols options TCP_HHOOK # hhook(9) framework for TCP options SCTP #Stream Control Transmission Protocol options FFS #Berkeley Fast Filesystem options SOFTUPDATES #Enable FFS soft updates support options UFS_ACL #Support for access control lists options UFS_DIRHASH #Improve performance on big directories options UFS_GJOURNAL #Enable gjournal-based UFS journaling options QUOTA #Enable disk quotas for UFS options MD_ROOT #MD is a potential root device options NFSCL #Network Filesystem Client options NFSD #Network Filesystem Server options NFSLOCKD #Network Lock Manager options NFS_ROOT #NFS usable as root device options MSDOSFS #MSDOS Filesystem options CD9660 #ISO 9660 Filesystem options PROCFS #Process filesystem (requires PSEUDOFS) options PSEUDOFS #Pseudo-filesystem framework options GEOM_PART_APM #Apple Partition Maps. options GEOM_PART_GPT #GUID Partition Tables. options GEOM_LABEL #Provides labelization options COMPAT_FREEBSD32 #Compatible with FreeBSD/powerpc binaries options COMPAT_FREEBSD5 #Compatible with FreeBSD5 options COMPAT_FREEBSD6 #Compatible with FreeBSD6 options COMPAT_FREEBSD7 #Compatible with FreeBSD7 options COMPAT_FREEBSD9 # Compatible with FreeBSD9 options COMPAT_FREEBSD10 # Compatible with FreeBSD10 options COMPAT_FREEBSD11 # Compatible with FreeBSD11 options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI options KTRACE #ktrace(1) syscall trace support options STACK #stack(9) support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing options CAPABILITY_MODE # Capsicum capability mode options CAPABILITIES # Capsicum capabilities options MAC # TrustedBSD MAC Framework options KDTRACE_HOOKS # Kernel DTrace hooks options DDB_CTF # Kernel ELF linker loads CTF data options INCLUDE_CONFIG_FILE # Include this file in kernel # Debugging support. Always need this: options KDB # Enable kernel debugger support. options KDB_TRACE # Print a stack trace for a panic. # For full debugger support use (turn off in stable branch): options DDB #Support DDB #options DEADLKRES #Enable the deadlock resolver options INVARIANTS #Enable calls of extra sanity checking options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS options WITNESS #Enable checks to detect deadlocks and cycles options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones # Make an SMP-capable kernel by default options SMP # Symmetric MultiProcessor Kernel # CPU frequency control device cpufreq # Standard busses device pci options PCI_HP # PCI-Express native HotPlug device agp # ATA controllers device ahci # AHCI-compatible SATA controllers device ata # Legacy ATA/SATA controllers device mvs # Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA device siis # SiliconImage SiI3124/SiI3132/SiI3531 SATA # SCSI Controllers device ahc # AHA2940 and onboard AIC7xxx devices options AHC_ALLOW_MEMIO # Attempt to use memory mapped I/O device isp # Qlogic family device ispfw # Firmware module for Qlogic host adapters device mpt # LSI-Logic MPT-Fusion device mps # LSI-Logic MPT-Fusion 2 device sym # NCR/Symbios/LSI Logic 53C8XX/53C1010/53C1510D # ATA/SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device sa # Sequential Access (tape etc) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # vt is the default console driver, resembling an SCO console device vt # Core console driver device kbdmux # Serial (COM) ports device scc device uart device uart_z8530 # Ethernet hardware device em # Intel PRO/1000 Gigabit Ethernet Family device ix # Intel PRO/10GbE PCIE PF Ethernet Family device ixv # Intel PRO/10GbE PCIE VF Ethernet Family device glc # Sony Playstation 3 Ethernet device llan # IBM pSeries Virtual Ethernet # PCI Ethernet NICs that use the common MII bus controller code. device miibus # MII bus support device bge # Broadcom BCM570xx Gigabit Ethernet device gem # Sun GEM/Sun ERI/Apple GMAC device dc # DEC/Intel 21143 and various workalikes device fxp # Intel EtherExpress PRO/100B (82557, 82558) device re # RealTek 8139C+/8169/8169S/8110S device rl # RealTek 8129/8139 # Pseudo devices. device loop # Network loopback device random # Entropy device device ether # Ethernet support device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device ofwd # Open Firmware disks device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! # Note that 'bpf' is required for DHCP. device bpf #Berkeley packet filter # USB support options USB_DEBUG # enable debug msgs device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface device ehci # EHCI PCI->USB interface device xhci # XHCI PCI->USB interface device usb # USB Bus (required) device uhid # "Human Interface Devices" device ukbd # Keyboard options KBD_INSTALL_CDEV # install a CDEV entry in /dev device ulpt # Printer device umass # Disks/Mass storage - Requires scbus and da0 device ums # Mouse device urio # Diamond Rio 500 MP3 player # USB Ethernet device aue # ADMtek USB Ethernet device axe # ASIX Electronics USB Ethernet device cdce # Generic USB over Ethernet device cue # CATC USB Ethernet device kue # Kawasaki LSI USB Ethernet # Wireless NIC cards options IEEE80211_SUPPORT_MESH options AH_SUPPORT_AR5416 # FireWire support device firewire # FireWire bus code device sbp # SCSI over FireWire (Requires scbus and da) device fwe # Ethernet over FireWire (non-standard!) # Misc device iicbus # I2C bus code device kiic # Keywest I2C device ad7417 # PowerMac7,2 temperature sensor device ds1631 # PowerMac11,2 temperature sensor device ds1775 # PowerMac7,2 temperature sensor device fcu # Apple Fan Control Unit device max6690 # PowerMac7,2 temperature sensor device powermac_nvram # Open Firmware configuration NVRAM device smu # Apple System Management Unit device atibl # ATI-based backlight driver for PowerBooks/iBooks device nvbl # nVidia-based backlight driver for PowerBooks/iBooks # ADB support device adb device pmu # Sound support device sound # Generic sound driver (required) device snd_ai2s # Apple I2S audio device snd_uaudio # USB Audio Index: head/sys/powerpc/powernv/opal.h =================================================================== --- head/sys/powerpc/powernv/opal.h (revision 328041) +++ head/sys/powerpc/powernv/opal.h (revision 328042) @@ -1,80 +1,82 @@ /*- * Copyright (c) 2015 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _POWERNV_OPAL_H #define _POWERNV_OPAL_H #include #include /* Check if OPAL is correctly instantiated. Will try to instantiate it. */ int opal_check(void); /* Call an OPAL method. Any pointers passed must be real-mode accessible! */ int opal_call(uint64_t token, ...); #define OPAL_CONSOLE_WRITE 1 #define OPAL_CONSOLE_READ 2 #define OPAL_RTC_READ 3 #define OPAL_RTC_WRITE 4 #define OPAL_CEC_POWER_DOWN 5 #define OPAL_CEC_REBOOT 6 #define OPAL_HANDLE_INTERRUPT 9 #define OPAL_POLL_EVENTS 10 #define OPAL_PCI_CONFIG_READ_BYTE 13 #define OPAL_PCI_CONFIG_READ_HALF_WORD 14 #define OPAL_PCI_CONFIG_READ_WORD 15 #define OPAL_PCI_CONFIG_WRITE_BYTE 16 #define OPAL_PCI_CONFIG_WRITE_HALF_WORD 17 #define OPAL_PCI_CONFIG_WRITE_WORD 18 #define OPAL_PCI_EEH_FREEZE_CLEAR 26 #define OPAL_PCI_PHB_MMIO_ENABLE 27 #define OPAL_PCI_SET_PHB_MEM_WINDOW 28 #define OPAL_PCI_MAP_PE_MMIO_WINDOW 29 #define OPAL_PCI_SET_XIVE_PE 37 #define OPAL_PCI_RESET 49 #define OPAL_PCI_POLL 62 +#define OPAL_SET_XIVE 19 +#define OPAL_GET_XIVE 20 #define OPAL_PCI_SET_PE 31 #define OPAL_GET_MSI_32 39 #define OPAL_GET_MSI_64 40 #define OPAL_PCI_MSI_EOI 63 #define OPAL_START_CPU 41 #define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45 #define OPAL_RETURN_CPU 69 #define OPAL_REINIT_CPUS 70 /* For OPAL_PCI_SET_PE */ #define OPAL_UNMAP_PE 0 #define OPAL_MAP_PE 1 #define OPAL_SUCCESS 0 #define OPAL_PARAMETER -1 #define OPAL_CLOSED -5 #define OPAL_BUSY_EVENT -12 #endif Index: head/sys/powerpc/pseries/xics.c =================================================================== --- head/sys/powerpc/pseries/xics.c (revision 328041) +++ head/sys/powerpc/pseries/xics.c (revision 328042) @@ -1,334 +1,484 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright 2011 Nathan Whitehorn * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#ifdef POWERNV +#include +#endif + #include "phyp-hvcall.h" #include "pic_if.h" #define XICP_PRIORITY 5 /* Random non-zero number */ #define XICP_IPI 2 #define MAX_XICP_IRQS (1<<24) /* 24-bit XIRR field */ static int xicp_probe(device_t); static int xicp_attach(device_t); static int xics_probe(device_t); static int xics_attach(device_t); static void xicp_bind(device_t dev, u_int irq, cpuset_t cpumask); static void xicp_dispatch(device_t, struct trapframe *); static void xicp_enable(device_t, u_int, u_int); static void xicp_eoi(device_t, u_int); static void xicp_ipi(device_t, u_int); static void xicp_mask(device_t, u_int); static void xicp_unmask(device_t, u_int); static device_method_t xicp_methods[] = { /* Device interface */ DEVMETHOD(device_probe, xicp_probe), DEVMETHOD(device_attach, xicp_attach), /* PIC interface */ DEVMETHOD(pic_bind, xicp_bind), DEVMETHOD(pic_dispatch, xicp_dispatch), DEVMETHOD(pic_enable, xicp_enable), DEVMETHOD(pic_eoi, xicp_eoi), DEVMETHOD(pic_ipi, xicp_ipi), DEVMETHOD(pic_mask, xicp_mask), DEVMETHOD(pic_unmask, xicp_unmask), - { 0, 0 }, + DEVMETHOD_END }; static device_method_t xics_methods[] = { /* Device interface */ DEVMETHOD(device_probe, xics_probe), DEVMETHOD(device_attach, xics_attach), - { 0, 0 }, + DEVMETHOD_END }; struct xicp_softc { struct mtx sc_mtx; + struct resource *mem[MAXCPU]; + int cpu_range[2]; + int ibm_int_on; int ibm_int_off; int ibm_get_xive; int ibm_set_xive; /* XXX: inefficient -- hash table? tree? */ struct { int irq; int vector; + int cpu; } intvecs[256]; int nintvecs; }; static driver_t xicp_driver = { "xicp", xicp_methods, sizeof(struct xicp_softc) }; static driver_t xics_driver = { "xics", xics_methods, 0 }; static devclass_t xicp_devclass; static devclass_t xics_devclass; EARLY_DRIVER_MODULE(xicp, ofwbus, xicp_driver, xicp_devclass, 0, 0, BUS_PASS_INTERRUPT-1); EARLY_DRIVER_MODULE(xics, ofwbus, xics_driver, xics_devclass, 0, 0, BUS_PASS_INTERRUPT); +#ifdef POWERNV +static struct resource * +xicp_mem_for_cpu(int cpu) +{ + device_t dev; + struct xicp_softc *sc; + int i; + + for (i = 0; (dev = devclass_get_device(xicp_devclass, i)) != NULL; i++){ + sc = device_get_softc(dev); + if (cpu >= sc->cpu_range[0] && cpu < sc->cpu_range[1]) + return (sc->mem[cpu - sc->cpu_range[0]]); + } + + return (NULL); +} +#endif + static int xicp_probe(device_t dev) { - if (ofw_bus_get_name(dev) == NULL || strcmp(ofw_bus_get_name(dev), - "interrupt-controller") != 0) - return (ENXIO); if (!ofw_bus_is_compatible(dev, "ibm,ppc-xicp")) return (ENXIO); - device_set_desc(dev, "PAPR virtual interrupt controller"); + device_set_desc(dev, "External Interrupt Presentation Controller"); return (BUS_PROBE_GENERIC); } static int xics_probe(device_t dev) { - if (ofw_bus_get_name(dev) == NULL || strcmp(ofw_bus_get_name(dev), - "interrupt-controller") != 0) - return (ENXIO); if (!ofw_bus_is_compatible(dev, "ibm,ppc-xics")) return (ENXIO); - device_set_desc(dev, "PAPR virtual interrupt source"); + device_set_desc(dev, "External Interrupt Source Controller"); return (BUS_PROBE_GENERIC); } static int xicp_attach(device_t dev) { struct xicp_softc *sc = device_get_softc(dev); phandle_t phandle = ofw_bus_get_node(dev); + if (rtas_exists()) { + sc->ibm_int_on = rtas_token_lookup("ibm,int-on"); + sc->ibm_int_off = rtas_token_lookup("ibm,int-off"); + sc->ibm_set_xive = rtas_token_lookup("ibm,set-xive"); + sc->ibm_get_xive = rtas_token_lookup("ibm,get-xive"); +#ifdef POWERNV + } else if (opal_check() == 0) { + /* No init needed */ +#endif + } else { + device_printf(dev, "Cannot attach without RTAS or OPAL\n"); + return (ENXIO); + } + + if (OF_hasprop(phandle, "ibm,interrupt-server-ranges")) { + OF_getencprop(phandle, "ibm,interrupt-server-ranges", + sc->cpu_range, sizeof(sc->cpu_range)); + sc->cpu_range[1] += sc->cpu_range[0]; + device_printf(dev, "Handling CPUs %d-%d\n", sc->cpu_range[0], + sc->cpu_range[1]-1); + } else { + sc->cpu_range[0] = 0; + sc->cpu_range[1] = mp_ncpus; + } + +#ifdef POWERNV + if (mfmsr() & PSL_HV) { + int i; + + for (i = 0; i < sc->cpu_range[1] - sc->cpu_range[0]; i++) { + sc->mem[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &i, RF_ACTIVE); + if (sc->mem[i] == NULL) { + device_printf(dev, "Could not alloc mem " + "resource %d\n", i); + return (ENXIO); + } + + /* Unmask interrupts on all cores */ + bus_write_1(sc->mem[i], 4, 0xff); + bus_write_1(sc->mem[i], 12, 0xff); + } + } +#endif + mtx_init(&sc->sc_mtx, "XICP", NULL, MTX_DEF); sc->nintvecs = 0; - sc->ibm_int_on = rtas_token_lookup("ibm,int-on"); - sc->ibm_int_off = rtas_token_lookup("ibm,int-off"); - sc->ibm_set_xive = rtas_token_lookup("ibm,set-xive"); - sc->ibm_get_xive = rtas_token_lookup("ibm,get-xive"); - powerpc_register_pic(dev, OF_xref_from_node(phandle), MAX_XICP_IRQS, 1 /* Number of IPIs */, FALSE); root_pic = dev; return (0); } static int xics_attach(device_t dev) { phandle_t phandle = ofw_bus_get_node(dev); /* The XICP (root PIC) will handle all our interrupts */ powerpc_register_pic(root_pic, OF_xref_from_node(phandle), MAX_XICP_IRQS, 1 /* Number of IPIs */, FALSE); return (0); } /* * PIC I/F methods. */ static void xicp_bind(device_t dev, u_int irq, cpuset_t cpumask) { struct xicp_softc *sc = device_get_softc(dev); cell_t status, cpu; int ncpus, i, error; /* * This doesn't appear to actually support affinity groups, so pick a * random CPU. */ ncpus = 0; CPU_FOREACH(cpu) if (CPU_ISSET(cpu, &cpumask)) ncpus++; i = mftb() % ncpus; ncpus = 0; CPU_FOREACH(cpu) { if (!CPU_ISSET(cpu, &cpumask)) continue; if (ncpus == i) break; ncpus++; } + /* XXX: super inefficient */ + for (i = 0; i < sc->nintvecs; i++) { + if (sc->intvecs[i].irq == irq) { + sc->intvecs[i].cpu = cpu; + break; + } + } + KASSERT(i < sc->nintvecs, ("Binding non-configured interrupt")); - error = rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, - XICP_PRIORITY, &status); + if (rtas_exists()) + error = rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, + XICP_PRIORITY, &status); +#ifdef POWERNV + else + error = opal_call(OPAL_SET_XIVE, irq, cpu << 2, XICP_PRIORITY); +#endif + if (error < 0) panic("Cannot bind interrupt %d to CPU %d", irq, cpu); } static void xicp_dispatch(device_t dev, struct trapframe *tf) { struct xicp_softc *sc; + struct resource *regs = NULL; uint64_t xirr, junk; int i; +#ifdef POWERNV + if (mfmsr() & PSL_HV) { + regs = xicp_mem_for_cpu(PCPU_GET(cpuid)); + KASSERT(regs != NULL, + ("Can't find regs for CPU %d", PCPU_GET(cpuid))); + } +#endif + sc = device_get_softc(dev); for (;;) { /* Return value in R4, use the PFT call */ - phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk); + if (regs) { + xirr = bus_read_4(regs, 4); + } else { + /* Return value in R4, use the PFT call */ + phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk); + } xirr &= 0x00ffffff; if (xirr == 0) { /* No more pending interrupts? */ - phyp_hcall(H_CPPR, (uint64_t)0xff); + if (regs) + bus_write_1(regs, 4, 0xff); + else + phyp_hcall(H_CPPR, (uint64_t)0xff); break; } if (xirr == XICP_IPI) { /* Magic number for IPIs */ xirr = MAX_XICP_IRQS; /* Map to FreeBSD magic */ - phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(cpuid)), - 0xff); /* Clear IPI */ + + /* Clear IPI */ + if (regs) + bus_write_1(regs, 12, 0xff); + else + phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(cpuid)), + 0xff); } /* XXX: super inefficient */ for (i = 0; i < sc->nintvecs; i++) { if (sc->intvecs[i].irq == xirr) break; } KASSERT(i < sc->nintvecs, ("Unmapped XIRR")); powerpc_dispatch_intr(sc->intvecs[i].vector, tf); } } static void xicp_enable(device_t dev, u_int irq, u_int vector) { struct xicp_softc *sc; cell_t status, cpu; sc = device_get_softc(dev); KASSERT(sc->nintvecs + 1 < nitems(sc->intvecs), ("Too many XICP interrupts")); + /* Bind to this CPU to start: distrib. ID is last entry in gserver# */ + cpu = PCPU_GET(cpuid); + mtx_lock(&sc->sc_mtx); sc->intvecs[sc->nintvecs].irq = irq; sc->intvecs[sc->nintvecs].vector = vector; + sc->intvecs[sc->nintvecs].cpu = cpu; mb(); sc->nintvecs++; mtx_unlock(&sc->sc_mtx); /* IPIs are also enabled */ if (irq == MAX_XICP_IRQS) return; - /* Bind to this CPU to start: distrib. ID is last entry in gserver# */ - cpu = PCPU_GET(cpuid); - rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, XICP_PRIORITY, - &status); - xicp_unmask(dev, irq); + if (rtas_exists()) { + rtas_call_method(sc->ibm_set_xive, 3, 1, irq, cpu, + XICP_PRIORITY, &status); + xicp_unmask(dev, irq); +#ifdef POWERNV + } else { + status = opal_call(OPAL_SET_XIVE, irq, cpu << 2, XICP_PRIORITY); + /* Unmask implicit for OPAL */ + + if (status != 0) + panic("OPAL_SET_XIVE IRQ %d -> cpu %d failed: %d", irq, + cpu, status); +#endif + } } static void xicp_eoi(device_t dev, u_int irq) { uint64_t xirr; if (irq == MAX_XICP_IRQS) /* Remap IPI interrupt to internal value */ irq = XICP_IPI; xirr = irq | (XICP_PRIORITY << 24); - phyp_hcall(H_EOI, xirr); +#ifdef POWERNV + if (mfmsr() & PSL_HV) + bus_write_4(xicp_mem_for_cpu(PCPU_GET(cpuid)), 4, xirr); + else +#endif + phyp_hcall(H_EOI, xirr); } static void xicp_ipi(device_t dev, u_int cpu) { - phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY); +#ifdef POWERNV + if (mfmsr() & PSL_HV) + bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY); + else +#endif + phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY); } static void xicp_mask(device_t dev, u_int irq) { struct xicp_softc *sc = device_get_softc(dev); cell_t status; if (irq == MAX_XICP_IRQS) return; - rtas_call_method(sc->ibm_int_off, 1, 1, irq, &status); + if (rtas_exists()) { + rtas_call_method(sc->ibm_int_off, 1, 1, irq, &status); +#ifdef POWERNV + } else { + int i; + + for (i = 0; i < sc->nintvecs; i++) { + if (sc->intvecs[i].irq == irq) { + break; + } + } + KASSERT(i < sc->nintvecs, ("Masking unconfigured interrupt")); + opal_call(OPAL_SET_XIVE, irq, sc->intvecs[i].cpu << 2, 0xff); +#endif + } } static void xicp_unmask(device_t dev, u_int irq) { struct xicp_softc *sc = device_get_softc(dev); cell_t status; if (irq == MAX_XICP_IRQS) return; - rtas_call_method(sc->ibm_int_on, 1, 1, irq, &status); + if (rtas_exists()) { + rtas_call_method(sc->ibm_int_on, 1, 1, irq, &status); +#ifdef POWERNV + } else { + int i; + + for (i = 0; i < sc->nintvecs; i++) { + if (sc->intvecs[i].irq == irq) { + break; + } + } + KASSERT(i < sc->nintvecs, ("Unmasking unconfigured interrupt")); + opal_call(OPAL_SET_XIVE, irq, sc->intvecs[i].cpu << 2, + XICP_PRIORITY); +#endif + } }