Add kernel dump support, based on the ia64 version (which was committed
as sparc64/sparc64/dump_machdep.c a while back). Other than ia64 (which uses ELF), sparc64 uses a homegrown format for the dumps (headers are required because the physical address and size of the tsb must be noted, and because physical memory may be discontiguous); ELF would not offer any advantages here. Reviewed by: jake
This commit is contained in:
parent
58f07abfc9
commit
e381d2455b
sys
conf
kern
sparc64
sys
@ -40,6 +40,7 @@ sparc64/sparc64/db_disasm.c optional ddb
|
||||
sparc64/sparc64/db_interface.c optional ddb
|
||||
sparc64/sparc64/db_trace.c optional ddb
|
||||
sparc64/sparc64/db_hwwatch.c optional ddb
|
||||
sparc64/sparc64/dump_machdep.c standard
|
||||
sparc64/sparc64/elf_machdep.c standard
|
||||
# locore.S and exception.S need to be handled in the Makefile to put them
|
||||
# first. Otherwise they're normal.
|
||||
|
@ -572,7 +572,7 @@ set_dumper(struct dumperinfo *di)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(__powerpc__) || defined(__sparc64__)
|
||||
#if defined(__powerpc__)
|
||||
void
|
||||
dumpsys(struct dumperinfo *di __unused)
|
||||
{
|
||||
|
51
sys/sparc64/include/kerneldump.h
Normal file
51
sys/sparc64/include/kerneldump.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
|
||||
* 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 ``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 _MACHINE_KERNELDUMP_H_
|
||||
#define _MACHINE_KERNELDUMP_H_
|
||||
|
||||
struct sparc64_dump_reg {
|
||||
vm_offset_t dr_pa;
|
||||
vm_offset_t dr_size;
|
||||
vm_offset_t dr_offs;
|
||||
};
|
||||
|
||||
/*
|
||||
* Kernel dump format for sparc64. This does not use ELF because it is of no
|
||||
* avail (only libkvm knows how to translate addresses properly anyway) and
|
||||
* would require some ugly hacks.
|
||||
*/
|
||||
struct sparc64_dump_hdr {
|
||||
vm_offset_t dh_hdr_size;
|
||||
vm_offset_t dh_tsb_pa;
|
||||
vm_size_t dh_tsb_size;
|
||||
vm_size_t dh_tsb_mask;
|
||||
int dh_nregions;
|
||||
struct sparc64_dump_reg dh_regions[];
|
||||
};
|
||||
|
||||
#endif /* _MACHINE_KERNELDUMP_H_ */
|
43
sys/sparc64/include/ofw_mem.h
Normal file
43
sys/sparc64/include/ofw_mem.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Jake Burkholder.
|
||||
* 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 _MACHINE_OFW_MEM_H_
|
||||
#define _MACHINE_OFW_MEM_H_
|
||||
|
||||
struct ofw_mem_region {
|
||||
vm_offset_t mr_start;
|
||||
vm_offset_t mr_size;
|
||||
};
|
||||
|
||||
struct ofw_map {
|
||||
vm_offset_t om_start;
|
||||
vm_offset_t om_size;
|
||||
u_long om_tte;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Marcel Moolenaar
|
||||
* Copyright (c) 2002 Thomas Moestl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -29,28 +30,31 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kerneldump.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/efi.h>
|
||||
#include <machine/elf.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
CTASSERT(sizeof(struct kerneldumpheader) == 512);
|
||||
#include <machine/metadata.h>
|
||||
#include <machine/kerneldump.h>
|
||||
#include <machine/ofw_mem.h>
|
||||
#include <machine/tsb.h>
|
||||
|
||||
#define MD_ALIGN(x) (((off_t)(x) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK)
|
||||
#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
|
||||
CTASSERT(sizeof(struct kerneldumpheader) == DEV_BSIZE);
|
||||
|
||||
typedef int callback_t(EFI_MEMORY_DESCRIPTOR*, int, void*);
|
||||
extern struct ofw_mem_region sparc64_memreg[];
|
||||
extern int sparc64_nmemreg;
|
||||
|
||||
static struct kerneldumpheader kdh;
|
||||
static off_t dumplo, fileofs;
|
||||
static off_t dumplo, dumppos;
|
||||
|
||||
/* Handle buffered writes. */
|
||||
static char buffer[DEV_BSIZE];
|
||||
static size_t fragsz;
|
||||
static vm_size_t fragsz;
|
||||
|
||||
#define MAXDUMPSZ (MAXDUMPPGS << PAGE_SHIFT)
|
||||
|
||||
/* XXX should be MI */
|
||||
static void
|
||||
@ -88,7 +92,7 @@ buf_write(struct dumperinfo *di, char *ptr, size_t sz)
|
||||
ptr += len;
|
||||
sz -= len;
|
||||
if (fragsz == DEV_BSIZE) {
|
||||
error = di->dumper(di->priv, buffer, NULL, dumplo,
|
||||
error = di->dumper(di->priv, buffer, 0, dumplo,
|
||||
DEV_BSIZE);
|
||||
if (error)
|
||||
return error;
|
||||
@ -108,192 +112,136 @@ buf_flush(struct dumperinfo *di)
|
||||
if (fragsz == 0)
|
||||
return (0);
|
||||
|
||||
error = di->dumper(di->priv, buffer, NULL, dumplo, DEV_BSIZE);
|
||||
error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
|
||||
dumplo += DEV_BSIZE;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
cb_dumpdata(EFI_MEMORY_DESCRIPTOR *mdp, int seqnr, void *arg)
|
||||
reg_write(struct dumperinfo *di, vm_offset_t pa, vm_size_t size)
|
||||
{
|
||||
struct dumperinfo *di = (struct dumperinfo*)arg;
|
||||
vm_offset_t pa;
|
||||
uint64_t pgs;
|
||||
size_t counter, sz;
|
||||
int error, twiddle;
|
||||
struct sparc64_dump_reg r;
|
||||
|
||||
error = 0; /* catch case in which mdp->NumberOfPages is 0 */
|
||||
counter = 0; /* Update twiddle every 16MB */
|
||||
twiddle = 0;
|
||||
pgs = mdp->NumberOfPages;
|
||||
pa = IA64_PHYS_TO_RR7(mdp->PhysicalStart);
|
||||
r.dr_pa = pa;
|
||||
r.dr_size = size;
|
||||
r.dr_offs = dumppos;
|
||||
dumppos += size;
|
||||
return (buf_write(di, (char *)&r, sizeof(r)));
|
||||
}
|
||||
|
||||
printf(" chunk %d: %ld pages ", seqnr, (long)pgs);
|
||||
static int
|
||||
blk_dump(struct dumperinfo *di, vm_offset_t pa, vm_size_t size)
|
||||
{
|
||||
vm_size_t pos, npg, rsz;
|
||||
void *va;
|
||||
int c, counter, error, i, twiddle;
|
||||
|
||||
while (pgs) {
|
||||
sz = (pgs > (DFLTPHYS >> EFI_PAGE_SHIFT))
|
||||
? DFLTPHYS : pgs << EFI_PAGE_SHIFT;
|
||||
counter += sz;
|
||||
if (counter >> 24) {
|
||||
printf(" chunk at %#lx: %ld bytes ", (u_long)pa, (long)size);
|
||||
|
||||
va = NULL;
|
||||
error = counter = twiddle = 0;
|
||||
for (pos = 0; pos < size; pos += MAXDUMPSZ, counter++) {
|
||||
if (counter % 128 == 0)
|
||||
printf("%c\b", "|/-\\"[twiddle++ & 3]);
|
||||
counter &= (1<<24) - 1;
|
||||
}
|
||||
error = di->dumper(di->priv, (void*)pa, NULL, dumplo, sz);
|
||||
rsz = size - pos;
|
||||
rsz = (rsz > MAXDUMPSZ) ? MAXDUMPSZ : rsz;
|
||||
npg = rsz >> PAGE_SHIFT;
|
||||
for (i = 0; i < npg; i++)
|
||||
va = pmap_kenter_temporary(pa + pos + i * PAGE_SIZE, i);
|
||||
error = di->dumper(di->priv, va, 0, dumplo, rsz);
|
||||
if (error)
|
||||
break;
|
||||
dumplo += sz;
|
||||
pgs -= sz >> EFI_PAGE_SHIFT;
|
||||
pa += sz;
|
||||
dumplo += rsz;
|
||||
|
||||
/* Check for user abort. */
|
||||
c = cncheckc();
|
||||
if (c == 0x03)
|
||||
return (ECANCELED);
|
||||
if (c != -1)
|
||||
printf("(CTRL-C to abort) ");
|
||||
}
|
||||
printf("... %s\n", (error) ? "fail" : "ok");
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
cb_dumphdr(EFI_MEMORY_DESCRIPTOR *mdp, int seqnr, void *arg)
|
||||
{
|
||||
struct dumperinfo *di = (struct dumperinfo*)arg;
|
||||
Elf64_Phdr phdr;
|
||||
int error;
|
||||
|
||||
bzero(&phdr, sizeof(phdr));
|
||||
phdr.p_type = PT_LOAD;
|
||||
phdr.p_flags = PF_R; /* XXX */
|
||||
phdr.p_offset = fileofs;
|
||||
phdr.p_vaddr = mdp->VirtualStart; /* XXX probably bogus. */
|
||||
phdr.p_paddr = mdp->PhysicalStart;
|
||||
phdr.p_filesz = mdp->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
phdr.p_memsz = mdp->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
phdr.p_align = EFI_PAGE_SIZE;
|
||||
|
||||
error = buf_write(di->priv, (char*)&phdr, sizeof(phdr));
|
||||
fileofs += phdr.p_filesz;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
cb_size(EFI_MEMORY_DESCRIPTOR *mdp, int seqnr, void *arg)
|
||||
{
|
||||
uint64_t *sz = (uint64_t*)arg;
|
||||
|
||||
*sz += (uint64_t)mdp->NumberOfPages << EFI_PAGE_SHIFT;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
foreach_chunk(callback_t cb, void *arg)
|
||||
{
|
||||
EFI_MEMORY_DESCRIPTOR *mdp;
|
||||
int error, i, mdcount, seqnr;
|
||||
|
||||
mdp = (EFI_MEMORY_DESCRIPTOR *)IA64_PHYS_TO_RR7(bootinfo.bi_memmap);
|
||||
mdcount = bootinfo.bi_memmap_size / bootinfo.bi_memdesc_size;
|
||||
|
||||
if (mdp == NULL || mdcount == 0)
|
||||
return (0);
|
||||
|
||||
for (i = 0, seqnr = 0; i < mdcount; i++) {
|
||||
if (mdp->Type == EfiConventionalMemory) {
|
||||
error = (*cb)(mdp, seqnr++, arg);
|
||||
if (error)
|
||||
return (-error);
|
||||
}
|
||||
mdp = NextMemoryDescriptor(mdp, bootinfo.bi_memdesc_size);
|
||||
}
|
||||
|
||||
return (seqnr);
|
||||
}
|
||||
|
||||
void
|
||||
dumpsys(struct dumperinfo *di)
|
||||
{
|
||||
Elf64_Ehdr ehdr;
|
||||
uint64_t dumpsize;
|
||||
off_t hdrgap;
|
||||
size_t hdrsz;
|
||||
int error;
|
||||
|
||||
bzero(&ehdr, sizeof(ehdr));
|
||||
ehdr.e_ident[EI_MAG0] = ELFMAG0;
|
||||
ehdr.e_ident[EI_MAG1] = ELFMAG1;
|
||||
ehdr.e_ident[EI_MAG2] = ELFMAG2;
|
||||
ehdr.e_ident[EI_MAG3] = ELFMAG3;
|
||||
ehdr.e_ident[EI_CLASS] = ELFCLASS64;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
#else
|
||||
ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
|
||||
#endif
|
||||
ehdr.e_ident[EI_VERSION] = EV_CURRENT;
|
||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
|
||||
ehdr.e_type = ET_CORE;
|
||||
ehdr.e_machine = EM_IA_64;
|
||||
ehdr.e_phoff = sizeof(ehdr);
|
||||
ehdr.e_flags = EF_IA_64_ABSOLUTE; /* XXX misuse? */
|
||||
ehdr.e_ehsize = sizeof(ehdr);
|
||||
ehdr.e_phentsize = sizeof(Elf64_Phdr);
|
||||
ehdr.e_shentsize = sizeof(Elf64_Shdr);
|
||||
struct sparc64_dump_hdr hdr;
|
||||
vm_size_t size, totsize, hdrsize;
|
||||
int error, i, nreg;
|
||||
|
||||
/* Calculate dump size. */
|
||||
dumpsize = 0L;
|
||||
ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
|
||||
hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
|
||||
fileofs = MD_ALIGN(hdrsz);
|
||||
dumpsize += fileofs;
|
||||
hdrgap = fileofs - DEV_ALIGN(hdrsz);
|
||||
size = 0;
|
||||
nreg = sparc64_nmemreg;
|
||||
for (i = 0; i < sparc64_nmemreg; i++)
|
||||
size += sparc64_memreg[i].mr_size;
|
||||
/* Account for the header size. */
|
||||
hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg,
|
||||
DEV_BSIZE);
|
||||
size += hdrsize;
|
||||
|
||||
totsize = size + 2 * sizeof(kdh);
|
||||
if (totsize > di->mediasize) {
|
||||
printf("Insufficient space on device (need %ld, have %ld), "
|
||||
"refusing to dump.\n", (long)totsize,
|
||||
(long)di->mediasize);
|
||||
error = ENOSPC;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Determine dump offset on device. */
|
||||
dumplo = di->mediaoffset + di->mediasize - dumpsize;
|
||||
dumplo -= sizeof(kdh) * 2;
|
||||
dumplo = di->mediaoffset + di->mediasize - totsize;
|
||||
|
||||
mkdumpheader(&kdh, KERNELDUMP_IA64_VERSION, dumpsize, di->blocksize);
|
||||
mkdumpheader(&kdh, KERNELDUMP_SPARC64_VERSION, size, di->blocksize);
|
||||
|
||||
printf("Dumping %llu MB (%d chunks)\n", dumpsize >> 20, ehdr.e_phnum);
|
||||
printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg);
|
||||
|
||||
/* Dump leader */
|
||||
error = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof(kdh));
|
||||
error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
|
||||
if (error)
|
||||
goto fail;
|
||||
dumplo += sizeof(kdh);
|
||||
|
||||
/* Dump ELF header */
|
||||
error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
|
||||
if (error)
|
||||
/* Dump the private header. */
|
||||
hdr.dh_hdr_size = hdrsize;
|
||||
hdr.dh_tsb_pa = tsb_kernel_phys;
|
||||
hdr.dh_tsb_size = tsb_kernel_size;
|
||||
hdr.dh_tsb_mask = tsb_kernel_mask;
|
||||
hdr.dh_nregions = nreg;
|
||||
|
||||
if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0)
|
||||
goto fail;
|
||||
|
||||
/* Dump program headers */
|
||||
error = foreach_chunk(cb_dumphdr, di);
|
||||
if (error < 0)
|
||||
goto fail;
|
||||
dumppos = hdrsize;
|
||||
/* Now, write out the region descriptors. */
|
||||
for (i = 0; i < sparc64_nmemreg; i++) {
|
||||
error = reg_write(di, sparc64_memreg[i].mr_start,
|
||||
sparc64_memreg[i].mr_size);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
}
|
||||
buf_flush(di);
|
||||
|
||||
/*
|
||||
* All headers are written using blocked I/O, so we know the
|
||||
* current offset is (still) block aligned. Skip the alignement
|
||||
* in the file to have the segment contents aligned at page
|
||||
* boundary. We cannot use MD_ALIGN on dumplo, because we don't
|
||||
* care and may very well be unaligned within the dump device.
|
||||
*/
|
||||
dumplo += hdrgap;
|
||||
|
||||
/* Dump memory chunks (updates dumplo) */
|
||||
error = foreach_chunk(cb_dumpdata, di);
|
||||
if (error < 0)
|
||||
goto fail;
|
||||
/* Dump memory chunks. */
|
||||
for (i = 0; i < sparc64_nmemreg; i++) {
|
||||
error = blk_dump(di, sparc64_memreg[i].mr_start,
|
||||
sparc64_memreg[i].mr_size);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Dump trailer */
|
||||
error = di->dumper(di->priv, &kdh, NULL, dumplo, sizeof(kdh));
|
||||
error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
/* Signal completion, signoff and exit stage left. */
|
||||
di->dumper(di->priv, NULL, NULL, 0, 0);
|
||||
di->dumper(di->priv, NULL, 0, 0, 0);
|
||||
printf("\nDump complete\n");
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (error < 0)
|
||||
error = -error;
|
||||
/* XXX It should look more like VMS :-) */
|
||||
printf("** DUMP FAILED (ERROR %d) **\n", error);
|
||||
}
|
||||
|
@ -96,6 +96,7 @@
|
||||
#include <machine/instr.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/metadata.h>
|
||||
#include <machine/ofw_mem.h>
|
||||
#include <machine/smp.h>
|
||||
#include <machine/tlb.h>
|
||||
#include <machine/tte.h>
|
||||
@ -107,17 +108,6 @@
|
||||
#define PMAP_SHPGPERPROC 200
|
||||
#endif
|
||||
|
||||
struct mem_region {
|
||||
vm_offset_t mr_start;
|
||||
vm_offset_t mr_size;
|
||||
};
|
||||
|
||||
struct ofw_map {
|
||||
vm_offset_t om_start;
|
||||
vm_offset_t om_size;
|
||||
u_long om_tte;
|
||||
};
|
||||
|
||||
/*
|
||||
* Virtual and physical address of message buffer.
|
||||
*/
|
||||
@ -136,7 +126,9 @@ int pmap_pagedaemon_waken;
|
||||
* Map of physical memory reagions.
|
||||
*/
|
||||
vm_offset_t phys_avail[128];
|
||||
static struct mem_region mra[128];
|
||||
static struct ofw_mem_region mra[128];
|
||||
struct ofw_mem_region sparc64_memreg[128];
|
||||
int sparc64_nmemreg;
|
||||
static struct ofw_map translations[128];
|
||||
static int translations_size;
|
||||
|
||||
@ -149,6 +141,8 @@ vm_offset_t kernel_vm_end;
|
||||
|
||||
vm_offset_t vm_max_kernel_address;
|
||||
|
||||
static vm_offset_t crashdumpmap;
|
||||
|
||||
/*
|
||||
* Kernel pmap.
|
||||
*/
|
||||
@ -235,8 +229,8 @@ static int om_cmp(const void *a, const void *b);
|
||||
static int
|
||||
mr_cmp(const void *a, const void *b)
|
||||
{
|
||||
const struct mem_region *mra;
|
||||
const struct mem_region *mrb;
|
||||
const struct ofw_mem_region *mra;
|
||||
const struct ofw_mem_region *mrb;
|
||||
|
||||
mra = a;
|
||||
mrb = b;
|
||||
@ -316,6 +310,19 @@ pmap_bootstrap(vm_offset_t ekva)
|
||||
tsb_kernel_size = virtsz >> (PAGE_SHIFT - TTE_SHIFT);
|
||||
tsb_kernel_mask = (tsb_kernel_size >> TTE_SHIFT) - 1;
|
||||
|
||||
/*
|
||||
* Get the available physical memory ranges from /memory/reg. These
|
||||
* are only used for kernel dumps, but it may not be wise to do prom
|
||||
* calls in that situation.
|
||||
*/
|
||||
if ((sz = OF_getproplen(pmem, "reg")) == -1)
|
||||
panic("pmap_bootstrap: getproplen /memory/reg");
|
||||
if (sizeof(sparc64_memreg) < sz)
|
||||
panic("pmap_bootstrap: sparc64_memreg too small");
|
||||
if (OF_getprop(pmem, "reg", sparc64_memreg, sz) == -1)
|
||||
panic("pmap_bootstrap: getprop /memory/reg");
|
||||
sparc64_nmemreg = sz / sizeof(*sparc64_memreg);
|
||||
|
||||
/*
|
||||
* Set the start and end of kva. The kernel is loaded at the first
|
||||
* available 4 meg super page, so round up to the end of the page.
|
||||
@ -459,6 +466,12 @@ pmap_bootstrap(vm_offset_t ekva)
|
||||
msgbufp = (struct msgbuf *)virtual_avail;
|
||||
virtual_avail += round_page(MSGBUF_SIZE);
|
||||
|
||||
/*
|
||||
* Allocate virtual address space to map pages during a kernel dump.
|
||||
*/
|
||||
crashdumpmap = virtual_avail;
|
||||
virtual_avail += MAXDUMPPGS * PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Initialize the kernel pmap (which is statically allocated).
|
||||
*/
|
||||
@ -813,13 +826,21 @@ pmap_kenter_flags(vm_offset_t va, vm_offset_t pa, u_long flags)
|
||||
|
||||
/*
|
||||
* Make a temporary mapping for a physical address. This is only intended
|
||||
* to be used for panic dumps.
|
||||
* to be used for panic dumps. Caching issues can be ignored completely here,
|
||||
* because pages mapped this way are only read.
|
||||
*/
|
||||
void *
|
||||
pmap_kenter_temporary(vm_offset_t pa, int i)
|
||||
{
|
||||
struct tte *tp;
|
||||
vm_offset_t va;
|
||||
|
||||
panic("pmap_kenter_temporary");
|
||||
va = crashdumpmap + i * PAGE_SIZE;
|
||||
tlb_page_demap(kernel_pmap, va);
|
||||
tp = tsb_kvtotte(va);
|
||||
tp->tte_vpn = TV_VPN(va, TS_8K);
|
||||
tp->tte_data = TD_V | TD_8K | TD_PA(pa) | TD_REF | TD_CP | TD_CV | TD_P;
|
||||
return ((void *)crashdumpmap);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -68,6 +68,7 @@ struct kerneldumpheader {
|
||||
#define KERNELDUMP_ALPHA_VERSION 1
|
||||
#define KERNELDUMP_I386_VERSION 1
|
||||
#define KERNELDUMP_IA64_VERSION 1
|
||||
#define KERNELDUMP_SPARC64_VERSION 1
|
||||
uint64_t dumplength; /* excl headers */
|
||||
uint64_t dumptime;
|
||||
uint32_t blocksize;
|
||||
|
Loading…
x
Reference in New Issue
Block a user