843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
0d928757379972073af9fb22bdc827b74e8ba6acGary Mills * Copyright (c) 2012 Gary Mills
a9ba5504895c94d55fd9eb409fdb92f2385c9515Richard PALO * Copyright 2016 PALO, Richard.
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystems * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystems#include <sys/apic_timer.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* XXX: need to add a PAE version too, if we ever support both PAE and non */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (((uintptr_t)(x) + (uintptr_t)(a) - 1l) & ~((uintptr_t)(a) - 1l)))
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Pointer to the xpv_panic_info structure handed to us by Xen. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Timer support */
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define XPV_TIMER_INTERVAL 1000 /* 1000 microseconds */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* IDT support */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic gate_desc_t xpv_panic_idt[NIDT]; /* interrupt descriptor table */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Xen pagetables mapped into our HAT's ptable windows */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Number of MMU_PAGESIZE pages we're adding to the Solaris dump */
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * There are up to two large swathes of RAM that we don't want to include
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * in the dump: those that comprise the Xen version of segkpm. On 32-bit
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * systems there is no such region of memory. On 64-bit systems, there
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * should be just a single contiguous region that corresponds to all of
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * physical memory. The tricky bit is that Xen's heap sometimes lives in
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * the middle of their segkpm, and is mapped using only kpm-like addresses.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * In that case, we need to skip the swathes before and after Xen's heap.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Some commonly used values that we don't want to recompute over and over.
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xpv_panic_console_print(const char *fmt, ...);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void (*xpv_panic_printf)(const char *, ...) = xpv_panic_console_print;
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * Pointers to machine check panic info (if any).
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Yexpv_mca_panic_data_t *xpv_mca_panic_data = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* This really shouldn't happen */
843e19887f64dde75055cf8842fc4db2171eff45johnlev c->cons_polledio_putchar(c->cons_polledio_argument, m);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (m = msg; *m; m++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) vsnprintf(console_buffer, sizeof (console_buffer), fmt, ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The provided pfn represents a level 'level' page table. Map it
843e19887f64dde75055cf8842fc4db2171eff45johnlev * into the 'level' slot in the list of page table windows.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Walk the page tables to find the pfn mapped by the given va.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we do anything other than a simple scan through memory, don't
843e19887f64dde75055cf8842fc4db2171eff45johnlev * trust the mapped page tables.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Find the lowest table with any entry for va */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Search this pagetable for any mapping to an
843e19887f64dde75055cf8842fc4db2171eff45johnlev * address >= va.
843e19887f64dde75055cf8842fc4db2171eff45johnlev idx = (va >> LEVEL_SHIFT(l)) & (xpv_panic_nptes[l] - 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (idx < xpv_panic_nptes[l] && scan_va < xpv_end &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If there are no valid mappings in this table, we
843e19887f64dde75055cf8842fc4db2171eff45johnlev * can skip to the end of the VA range it covers.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * See if we've hit the end of the range.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If this mapping is for a pagetable, we drop down
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to the next level in the hierarchy and look for
843e19887f64dde75055cf8842fc4db2171eff45johnlev * a mapping in it.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The APIC page is magic. Nothing to see here;
843e19887f64dde75055cf8842fc4db2171eff45johnlev * move along.
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * See if the address is within one of the two
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab * kpm-like regions we want to skip.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The Xen panic code only handles small pages. If
843e19887f64dde75055cf8842fc4db2171eff45johnlev * this mapping is for a large page, we need to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * identify the consituent page that covers the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * specific VA we were looking for.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (l > 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev "giant pages.");
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Walk through the Xen VA space, finding pages that are mapped in.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * These pages all have MFNs rather than PFNs, meaning they may be outside
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the physical address space the kernel knows about, or they may collide
843e19887f64dde75055cf8842fc4db2171eff45johnlev * with PFNs the kernel is using.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The obvious trick of just adding the PFN_IS_FOREIGN_MFN bit to the MFNs
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to avoid collisions doesn't work. The pages need to be written to disk
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in PFN-order or savecore gets confused. We can't allocate memory to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * contruct a sorted pfn->VA reverse mapping, so we have to write the pages
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to disk in VA order.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * To square this circle, we simply make up PFNs for each of Xen's pages.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We assign each mapped page a fake PFN in ascending order. These fake
843e19887f64dde75055cf8842fc4db2171eff45johnlev * PFNs each have the FOREIGN bit set, ensuring that they fall outside the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * range of Solaris PFNs written by the kernel.
843e19887f64dde75055cf8842fc4db2171eff45johnlev mem_vtop.m_pfn = (pfn_t)xpv_dump_pages | PFN_IS_FOREIGN_MFN;
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add the shared_info page. This page actually ends up in the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * dump twice: once for the Xen va and once for the Solaris va.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This isn't ideal, but we don't know the address Xen is using for
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the page, so we can't share it.
843e19887f64dde75055cf8842fc4db2171eff45johnlev mem_vtop.m_pfn = (pfn_t)xpv_dump_pages | PFN_IS_FOREIGN_MFN;
843e19887f64dde75055cf8842fc4db2171eff45johnlev * XXX: we should probably run this data through a UE check. The
843e19887f64dde75055cf8842fc4db2171eff45johnlev * catch is that the UE code relies on on_trap() and getpfnum()
843e19887f64dde75055cf8842fc4db2171eff45johnlev csize = (uint32_t)compress((void *)va, dump_cbuf, PAGESIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Finally, dump the shared_info page
843e19887f64dde75055cf8842fc4db2171eff45johnlev csize = (uint32_t)compress((void *)HYPERVISOR_shared_info, dump_cbuf,
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void *
843e19887f64dde75055cf8842fc4db2171eff45johnlev uintptr_t minaddr = min(KERNELBASE, xen_virt_start);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xpv_only != 0) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen marks an exception frame by inverting the frame
843e19887f64dde75055cf8842fc4db2171eff45johnlev return ((void *)fp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev panic("Illegally issued hypercall %d during panic!\n", (int)call);
843e19887f64dde75055cf8842fc4db2171eff45johnlev panic("Fatal pagefault at 0x%lx. fault addr=0x%p rp=0x%p",
843e19887f64dde75055cf8842fc4db2171eff45johnlev panic("Fatal trap %ld at 0x%lx. rp=0x%p", rp->r_trapno,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Build IDT to handle a Xen panic
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < 32; i++)
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[i], &xpv_invaltrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_ZERODIV], &xpv_div0trap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_SGLSTP], &xpv_dbgtrap, cs, SDT_SYSIGT, TRP_XPL, 0);
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_NMIFLT], &xpv_nmiint, cs, SDT_SYSIGT, TRP_XPL, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev set_gatesegd(&idt[T_BOUNDFLT], &xpv_boundstrap, cs, SDT_SYSIGT,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_ILLINST], &xpv_invoptrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_NOEXTFLT], &xpv_ndptrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_TSSFLT], &xpv_invtsstrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_SEGFLT], &xpv_segnptrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_STKFLT], &xpv_stktrap, cs, SDT_SYSIGT, TRP_XPL, 0);
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_GPFLT], &xpv_gptrap, cs, SDT_SYSIGT, TRP_XPL, 0);
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_PGFLT], &xpv_pftrap, cs, SDT_SYSIGT, TRP_XPL, 0);
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_EXTERRFLT], &xpv_ndperr, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_ALIGNMENT], &xpv_achktrap, cs, SDT_SYSIGT, TRP_XPL,
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_MCE], &xpv_mcetrap, cs, SDT_SYSIGT, TRP_XPL, 0);
9844da31e6f9a1bffcbbb9ec7926f759ee04c460Seth Goldberg set_gatesegd(&idt[T_SIMDFPE], &xpv_xmtrap, cs, SDT_SYSIGT, TRP_XPL, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We have no double fault handler. Any single fault represents a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * catastrophic failure for us, so there is no attempt to handle
843e19887f64dde75055cf8842fc4db2171eff45johnlev * them cleanly: we just print a message and reboot. If we
843e19887f64dde75055cf8842fc4db2171eff45johnlev * encounter a second fault while doing that, there is nothing
843e19887f64dde75055cf8842fc4db2171eff45johnlev * else we can do.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Be prepared to absorb any stray device interrupts received
843e19887f64dde75055cf8842fc4db2171eff45johnlev * while writing the core to disk.
843e19887f64dde75055cf8842fc4db2171eff45johnlev set_gatesegd(&idt[i], &xpv_surprise_intr, cs, SDT_SYSIGT,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* The one interrupt we expect to get is from the APIC timer. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev set_gatesegd(&idt[T_XPV_TIMER], &xpv_timer_trap, cs, SDT_SYSIGT,
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Catch any hypercalls. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev wrmsr(MSR_AMD_LSTAR, (uintptr_t)xpv_panic_hypercall);
843e19887f64dde75055cf8842fc4db2171eff45johnlev wrmsr(MSR_AMD_CSTAR, (uintptr_t)xpv_panic_hypercall);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Measure how many APIC ticks there are within a fixed time
843e19887f64dde75055cf8842fc4db2171eff45johnlev * period. We're going to be fairly coarse here. This timer is
843e19887f64dde75055cf8842fc4db2171eff45johnlev * just being used to detect a stalled panic, so as long as we have
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the right order of magnitude, everything should be fine.
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_apicadr[APIC_SPUR_INT_REG] = AV_UNIT_ENABLE | APIC_SPUR_INTR;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_apicadr[APIC_INT_VECT0] = AV_MASK; /* local intr reg 0 */
843e19887f64dde75055cf8842fc4db2171eff45johnlev apic_ticks = APIC_MAXVAL - xpv_apicadr[APIC_CURR_COUNT];
843e19887f64dde75055cf8842fc4db2171eff45johnlev * apic_ticks now represents roughly how many apic ticks comprise
843e19887f64dde75055cf8842fc4db2171eff45johnlev * one timeout interval. Program the timer to send us an interrupt
843e19887f64dde75055cf8842fc4db2171eff45johnlev * every time that interval expires.
41afdfa77f9af46beb3aaab2eccc0d9afe660d31Krishnendu Sadhukhan - Sun Microsystems xpv_apicadr[APIC_LOCAL_TIMER] = T_XPV_TIMER | AV_PERIODIC;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_panic_printf("Unexpected interrupt received.\n");
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_panic_printf("%d unexpected interrupts received.\n", cnt);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Managing time in panic context is trivial. We only have a single CPU,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * we never get rescheduled, we never get suspended. We just need to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * convert clock ticks into nanoseconds.
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int *l = (unsigned int *)&(tsc);
843e19887f64dde75055cf8842fc4db2171eff45johnlev CPU->cpu_m.mcpu_vcpu_info->time.tsc_to_system_mul >> NSEC_SHIFT;
843e19887f64dde75055cf8842fc4db2171eff45johnlev extern void panicsys(const char *, va_list, struct regs *, int);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Indicate to the underlying panic framework that a panic has been
843e19887f64dde75055cf8842fc4db2171eff45johnlev * initiated. This is ordinarily done as part of vpanic(). Since
843e19887f64dde75055cf8842fc4db2171eff45johnlev * we already have all the register state saved by the hypervisor,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * we skip that and jump straight into the panic processing code.
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * XXX If another thread grabs and wins the panic_quiesce trigger
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * then we'll have two threads in panicsys believing they are in
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye * charge of the panic attempt!
843e19887f64dde75055cf8842fc4db2171eff45johnlev * bzero() and bcopy() get unhappy when asked to operate on
843e19887f64dde75055cf8842fc4db2171eff45johnlev * addresses outside of the kernel. At this point Xen is really a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * part of the kernel, so we update the routines' notion of where
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the kernel starts.
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_end = (uintptr_t)UINTPTR_MAX - sizeof (uintptr_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we were redirecting console output to the hypervisor, we have
0d928757379972073af9fb22bdc827b74e8ba6acGary Mills if (boot_console_type(NULL) == CONS_HYPERVISOR) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Make sure we handle all console output from here on. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we find an unsupported panic_info structure, there's not much
843e19887f64dde75055cf8842fc4db2171eff45johnlev * we can do other than complain, plow on, and hope for the best.
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_panic_printf("Warning: Xen is using an unsupported "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "version of the panic_info structure.\n");
a576ab5b6e08c47732b3dedca9eaa8a8cbb85720rab#if defined(__amd64)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Make sure we are running on the Solaris %gs. The Xen panic code
843e19887f64dde75055cf8842fc4db2171eff45johnlev * should already have set up the GDT properly.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Switch to our own IDT, avoiding any accidental returns to Xen
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Initialize the APIC timer, which is used to detect a hung dump
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set up a few values that we'll need repeatedly.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Add the fake Xen module to the module list */
e4b86885570d77af552e9cf94f142f4d744fb8c8Cheng Sean Ye if (pip->pi_mca.mpd_magic == MCA_PANICDATA_MAGIC)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_panicsys((struct regs *)pip->pi_regs, pip->pi_panicstr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xpv_panic_printf("Failed to reboot following panic.\n");
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Set up the necessary data structures to pretend that the Xen hypervisor
843e19887f64dde75055cf8842fc4db2171eff45johnlev * is a loadable module, allowing mdb to find the Xen symbols in a crash
843e19887f64dde75055cf8842fc4db2171eff45johnlev * dump. Since these symbols all map to VA space Solaris doesn't normally
843e19887f64dde75055cf8842fc4db2171eff45johnlev * have access to, we don't link these structures into the kernel's lists
843e19887f64dde75055cf8842fc4db2171eff45johnlev * until/unless we hit a Xen panic.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The observant reader will note a striking amount of overlap between this
843e19887f64dde75055cf8842fc4db2171eff45johnlev * code and that found in krtld. While it would be handy if we could just
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ask krtld to do this work for us, it's not that simple. Among the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * complications: we're not actually loading the text here (grub did it at
843e19887f64dde75055cf8842fc4db2171eff45johnlev * boot), the .text section is writable, there are no relocations to do,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * none of the module text/data is in readable memory, etc. Training krtld
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to deal with this weird module is as complicated, and more risky, than
843e19887f64dde75055cf8842fc4db2171eff45johnlev * reimplementing the necessary subset of it here.
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Allocate and init the module structure */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mp->filename = kobj_zalloc(strlen(XPV_FILENAME) + 1, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Allocate and init the modctl structure */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mcp->mod_modname = kobj_zalloc(strlen(XPV_MODNAME) + 1, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mcp->mod_filename = kobj_zalloc(strlen(XPV_FILENAME) + 1, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Try to open a Xen image that hasn't had its symbol and CTF
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information stripped off.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Read the header and ensure that this is an ELF file for the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * proper ISA. If it's not, somebody has done something very
843e19887f64dde75055cf8842fc4db2171eff45johnlev * stupid. Why bother? See Mencken.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (kobj_read_file(file, (char *)&mp->hdr, sizeof (mp->hdr), 0) < 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < SELFMAG; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Read in the section headers */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (kobj_read_file(file, mp->shdrs, n, mp->hdr.e_shoff) < 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Read the section names */
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp = (Shdr *)(mp->shdrs + mp->hdr.e_shstrndx * mp->hdr.e_shentsize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (kobj_read_file(file, names, shp->sh_size, shp->sh_offset) < 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Fill in the text and data size fields.
843e19887f64dde75055cf8842fc4db2171eff45johnlev shp = (Shdr *)(mp->shdrs + shn * mp->hdr.e_shentsize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Sanity check the offset of the section name */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* If we find the symtab section, remember it for later. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* If we find the CTF section, remember it for later. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen marks its text section as writable, so we need to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * look for the name - not just the flag.
a9ba5504895c94d55fd9eb409fdb92f2385c9515Richard PALO if ((strcmp(&names[shp->sh_name], ".text") != 0) &&
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mp->data == NULL || mp->data > (char *)shp->sh_addr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mp->text == NULL || mp->text > (char *)shp->sh_addr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we have symbol table and string table sections, read them in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * now. If we don't, we just plow on. We'll still get a valid
843e19887f64dde75055cf8842fc4db2171eff45johnlev * core dump, but finding anything useful will be just a bit
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Note: we don't bother with a hash table. We'll never do a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * symbol lookup unless we crash, and then mdb creates its own. We
843e19887f64dde75055cf8842fc4db2171eff45johnlev * also don't try to perform any relocations. Xen should be loaded
843e19887f64dde75055cf8842fc4db2171eff45johnlev * exactly where the ELF file indicates, and the symbol information
843e19887f64dde75055cf8842fc4db2171eff45johnlev * in the file should be complete and correct already. Static
843e19887f64dde75055cf8842fc4db2171eff45johnlev * linking ain't all bad.
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((mp->symhdr != NULL) && (mp->symhdr->sh_link < mp->hdr.e_shnum)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (mp->shdrs + mp->symhdr->sh_link * mp->hdr.e_shentsize);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mp->nsyms = mp->symhdr->sh_size / mp->symhdr->sh_entsize;
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Allocate space for the symbol table and strings. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mp->strings = (char *)(mp->symtbl + mp->symhdr->sh_size);
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Read in the CTF section
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((ctf_shp != NULL) && ((moddebug & MODDEBUG_NOCTF) == 0)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "Failed to initialize xpv module.");
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(mp->shdrs, mp->hdr.e_shentsize * mp->hdr.e_shnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(mcp->mod_filename, strlen(XPV_FILENAME) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(mcp->mod_modname, strlen(XPV_MODNAME) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Let Xen know where to jump if/when it panics. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev op.u.panic_init.panic_addr = (unsigned long)xpv_panic_hdlr;