Blame sparc64.c

Packit Service 501009
/* sparc64.c - core analysis suite
Packit Service 501009
 *
Packit Service 501009
 * Copyright (C) 2016 Oracle Corporation
Packit Service 501009
 *
Packit Service 501009
 * This program is free software; you can redistribute it and/or modify
Packit Service 501009
 * it under the terms of the GNU General Public License as published by
Packit Service 501009
 * the Free Software Foundation; either version 2 of the License, or
Packit Service 501009
 * (at your option) any later version.
Packit Service 501009
 *
Packit Service 501009
 * This program is distributed in the hope that it will be useful,
Packit Service 501009
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 501009
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 501009
 * GNU General Public License for more details.
Packit Service 501009
 */
Packit Service 501009
#ifdef SPARC64
Packit Service 501009
Packit Service 501009
#include "defs.h"
Packit Service 501009
#include <stdio.h>
Packit Service 501009
#include <elf.h>
Packit Service 501009
#include <asm/ptrace.h>
Packit Service 501009
#include <linux/const.h>
Packit Service 501009
Packit Service 501009
/* TT (Trap Type) is encoded into magic pt_regs field */
Packit Service 501009
#define	MAGIC_TT_MASK		(0x1ff)
Packit Service 501009
Packit Service 501009
static const unsigned long not_valid_pte = ~0UL;
Packit Service 501009
static struct machine_specific sparc64_machine_specific;
Packit Service 501009
static unsigned long sparc64_ksp_offset;
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
__va(unsigned long paddr)
Packit Service 501009
{
Packit Service 501009
	return paddr + PAGE_OFFSET;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
__pa(unsigned long vaddr)
Packit Service 501009
{
Packit Service 501009
	return vaddr - PAGE_OFFSET;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_parse_cmdline_args(void)
Packit Service 501009
{
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/* This interface might not be required. */
Packit Service 501009
static void
Packit Service 501009
sparc64_clear_machdep_cache(void)
Packit Service 501009
{
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  "mach" command output.
Packit Service 501009
 */
Packit Service 501009
static void
Packit Service 501009
sparc64_display_machine_stats(void)
Packit Service 501009
{
Packit Service 501009
	int c;
Packit Service 501009
	struct new_utsname *uts;
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	ulong mhz;
Packit Service 501009
Packit Service 501009
	uts = &kt->utsname;
Packit Service 501009
Packit Service 501009
	fprintf(fp, "          MACHINE TYPE: %s\n", uts->machine);
Packit Service 501009
	fprintf(fp, "           MEMORY SIZE: %s\n", get_memory_size(buf));
Packit Service 501009
	fprintf(fp, "                  CPUS: %d\n", kt->cpus);
Packit Service 501009
	fprintf(fp, "       PROCESSOR SPEED: ");
Packit Service 501009
	if ((mhz = machdep->processor_speed()))
Packit Service 501009
		fprintf(fp, "%ld Mhz\n", mhz);
Packit Service 501009
	else
Packit Service 501009
		fprintf(fp, "(unknown)\n");
Packit Service 501009
	fprintf(fp, "                    HZ: %d\n", machdep->hz);
Packit Service 501009
	fprintf(fp, "             PAGE SIZE: %ld\n", PAGE_SIZE);
Packit Service 501009
	fprintf(fp, "   KERNEL VIRTUAL BASE: %lx\n", machdep->kvbase);
Packit Service 501009
	fprintf(fp, "   KERNEL VMALLOC BASE: %lx\n", SPARC64_VMALLOC_START);
Packit Service 501009
	fprintf(fp, "   KERNEL MODULES BASE: %lx\n", SPARC64_MODULES_VADDR);
Packit Service 501009
	fprintf(fp, "     KERNEL STACK SIZE: %ld\n", STACKSIZE());
Packit Service 501009
Packit Service 501009
	fprintf(fp, "HARD IRQ STACK SIZE: %ld\n", THREAD_SIZE);
Packit Service 501009
	fprintf(fp, "    HARD IRQ STACKS:\n");
Packit Service 501009
Packit Service 501009
	for (c = 0; c < kt->cpus; c++) {
Packit Service 501009
		if (!tt->hardirq_ctx[c])
Packit Service 501009
			continue;
Packit Service 501009
		sprintf(buf, "CPU %d", c);
Packit Service 501009
		fprintf(fp, "%19s: %lx\n", buf, tt->hardirq_ctx[c]);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "SOFT IRQ STACK SIZE: %ld\n", THREAD_SIZE);
Packit Service 501009
	fprintf(fp, "    SOFT IRQ STACKS:\n");
Packit Service 501009
	for (c = 0; c < kt->cpus; c++) {
Packit Service 501009
		if (!tt->softirq_ctx[c])
Packit Service 501009
			continue;
Packit Service 501009
		sprintf(buf, "CPU %d", c);
Packit Service 501009
		fprintf(fp, "%19s: %lx\n", buf, tt->softirq_ctx[c]);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_display_memmap(void)
Packit Service 501009
{
Packit Service 501009
	unsigned long iomem_resource;
Packit Service 501009
	unsigned long resource;
Packit Service 501009
	unsigned long start, end, nameptr;
Packit Service 501009
	int size = STRUCT_SIZE("resource");
Packit Service 501009
	char *buf;
Packit Service 501009
	char name[32];
Packit Service 501009
Packit Service 501009
	buf = GETBUF(size);
Packit Service 501009
	iomem_resource = symbol_value("iomem_resource");
Packit Service 501009
Packit Service 501009
	readmem(iomem_resource + MEMBER_OFFSET("resource", "child"), KVADDR,
Packit Service 501009
		&resource, sizeof(resource), "iomem_resource", FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
	fprintf(fp, "      PHYSICAL ADDRESS RANGE         TYPE\n");
Packit Service 501009
Packit Service 501009
	while (resource) {
Packit Service 501009
		readmem(resource, KVADDR, buf, size, "resource",
Packit Service 501009
			FAULT_ON_ERROR);
Packit Service 501009
		start = ULONG(buf + MEMBER_OFFSET("resource", "start"));
Packit Service 501009
		end = ULONG(buf + MEMBER_OFFSET("resource", "end"));
Packit Service 501009
		nameptr = ULONG(buf + MEMBER_OFFSET("resource", "name"));
Packit Service 501009
Packit Service 501009
		readmem(nameptr, KVADDR, name, sizeof(name), "resource.name",
Packit Service 501009
			FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
		fprintf(fp, "%016lx - %016lx  %-32s\n", start, end, name);
Packit Service 501009
Packit Service 501009
		resource = ULONG(buf + MEMBER_OFFSET("resource", "sibling"));
Packit Service 501009
	}
Packit Service 501009
	FREEBUF(buf);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_cmd_mach(void)
Packit Service 501009
{
Packit Service 501009
	int c;
Packit Service 501009
	int mflag = 0;
Packit Service 501009
Packit Service 501009
	while ((c = getopt(argcnt, args, "cdmx")) != EOF) {
Packit Service 501009
		switch (c) {
Packit Service 501009
		case 'm':
Packit Service 501009
			mflag++;
Packit Service 501009
			sparc64_display_memmap();
Packit Service 501009
			break;
Packit Service 501009
		case 'c':
Packit Service 501009
			fprintf(fp, "SPARC64: '-%c' option is not supported\n",
Packit Service 501009
				c);
Packit Service 501009
			return;
Packit Service 501009
		case 'd':
Packit Service 501009
		case 'x':
Packit Service 501009
			/* Just ignore these */
Packit Service 501009
			break;
Packit Service 501009
		default:
Packit Service 501009
			argerrs++;
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (argerrs)
Packit Service 501009
		cmd_usage(pc->curcmd, SYNOPSIS);
Packit Service 501009
Packit Service 501009
	if (!mflag)
Packit Service 501009
		sparc64_display_machine_stats();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
struct sparc64_mem_ranges {
Packit Service 501009
	unsigned long start;
Packit Service 501009
	unsigned long end;
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
#define NR_PHYS_RANGES	(128)
Packit Service 501009
static unsigned int nr_phys_ranges;
Packit Service 501009
struct sparc64_mem_ranges phys_ranges[NR_PHYS_RANGES];
Packit Service 501009
Packit Service 501009
#define NR_IMAGE_RANGES (16)
Packit Service 501009
static unsigned int nr_kimage_ranges;
Packit Service 501009
struct sparc64_mem_ranges kimage_ranges[NR_IMAGE_RANGES];
Packit Service 501009
Packit Service 501009
/* There are three live cases:
Packit Service 501009
 *  one) normal kernel
Packit Service 501009
 *  two) --load-panic kernel
Packit Service 501009
 *  and
Packit Service 501009
 *  three) --load kernel
Packit Service 501009
 * One and two can be treated the same because the kernel is physically
Packit Service 501009
 * contiguous. Three isn't contiguous. The kernel is allocated in order
Packit Service 501009
 * nine allocation pages. We don't handle case three yet.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_phys_live_valid(unsigned long paddr)
Packit Service 501009
{
Packit Service 501009
	unsigned int nr;
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
Packit Service 501009
	for (nr = 0; nr != nr_phys_ranges; nr++) {
Packit Service 501009
		if (paddr >= phys_ranges[nr].start &&
Packit Service 501009
			paddr < phys_ranges[nr].end) {
Packit Service 501009
			rc = TRUE;
Packit Service 501009
			break;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_phys_kdump_valid(unsigned long paddr)
Packit Service 501009
{
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_verify_paddr(unsigned long paddr)
Packit Service 501009
{
Packit Service 501009
	int rc;
Packit Service 501009
Packit Service 501009
	if (ACTIVE())
Packit Service 501009
		rc = sparc64_phys_live_valid(paddr);
Packit Service 501009
	else
Packit Service 501009
		rc = sparc64_phys_kdump_valid(paddr);
Packit Service 501009
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc6_phys_base_live_limits(void)
Packit Service 501009
{
Packit Service 501009
	if (nr_phys_ranges >= NR_PHYS_RANGES)
Packit Service 501009
		error(FATAL, "sparc6_phys_base_live_limits: "
Packit Service 501009
			"NR_PHYS_RANGES exceeded.\n");
Packit Service 501009
	else if (nr_kimage_ranges >= NR_IMAGE_RANGES)
Packit Service 501009
		error(FATAL, "sparc6_phys_base_live_limits: "
Packit Service 501009
			"NR_IMAGE_RANGES exceeded.\n");
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_phys_base_live_valid(void)
Packit Service 501009
{
Packit Service 501009
	if (!nr_phys_ranges)
Packit Service 501009
		error(FATAL, "No physical memory ranges.");
Packit Service 501009
	else if (!nr_kimage_ranges)
Packit Service 501009
		error(FATAL, "No vmlinux memory ranges.");
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_phys_base_live(void)
Packit Service 501009
{
Packit Service 501009
	char line[BUFSIZE];
Packit Service 501009
	FILE *fp;
Packit Service 501009
Packit Service 501009
	fp = fopen("/proc/iomem", "r");
Packit Service 501009
	if (fp == NULL)
Packit Service 501009
		error(FATAL, "Can't open /proc/iomem. We can't proceed.");
Packit Service 501009
Packit Service 501009
	while (fgets(line, sizeof(line), fp) != 0) {
Packit Service 501009
		unsigned long start, end;
Packit Service 501009
		int count, consumed;
Packit Service 501009
		char *ch;
Packit Service 501009
Packit Service 501009
		sparc6_phys_base_live_limits();
Packit Service 501009
		count = sscanf(line, "%lx-%lx : %n", &start, &end, &consumed);
Packit Service 501009
		if (count != 2)
Packit Service 501009
			continue;
Packit Service 501009
		ch = line + consumed;
Packit Service 501009
		if (memcmp(ch, "System RAM\n", 11) == 0) {
Packit Service 501009
			end = end + 1;
Packit Service 501009
			phys_ranges[nr_phys_ranges].start = start;
Packit Service 501009
			phys_ranges[nr_phys_ranges].end = end;
Packit Service 501009
			nr_phys_ranges++;
Packit Service 501009
		} else if ((memcmp(ch, "Kernel code\n", 12) == 0) ||
Packit Service 501009
				(memcmp(ch, "Kernel data\n", 12) == 0) ||
Packit Service 501009
				(memcmp(ch, "Kernel bss\n", 11) == 0)) {
Packit Service 501009
			kimage_ranges[nr_kimage_ranges].start = start;
Packit Service 501009
			kimage_ranges[nr_kimage_ranges].end = end;
Packit Service 501009
			nr_kimage_ranges++;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	(void) fclose(fp);
Packit Service 501009
	sparc64_phys_base_live_valid();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_phys_base_kdump(void)
Packit Service 501009
{
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_phys_base(void)
Packit Service 501009
{
Packit Service 501009
	if (ACTIVE())
Packit Service 501009
		return sparc64_phys_base_live();
Packit Service 501009
	else
Packit Service 501009
		return sparc64_phys_base_kdump();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long kva_start, kva_end;
Packit Service 501009
static unsigned long kpa_start, kpa_end;
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_kimage_limits_live(void)
Packit Service 501009
{
Packit Service 501009
	kpa_start = kimage_ranges[0].start;
Packit Service 501009
	kpa_end = kpa_start + (kva_end - kva_start);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_kimage_limits_kdump(void)
Packit Service 501009
{
Packit Service 501009
	unsigned long phys_base;
Packit Service 501009
Packit Service 501009
	if (DISKDUMP_DUMPFILE()) {
Packit Service 501009
		if (diskdump_phys_base(&phys_base)) {
Packit Service 501009
			kpa_start = phys_base | (kva_start & 0xffff);
Packit Service 501009
			kpa_end = kpa_start + (kva_end - kva_start);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
	fprintf(stderr, "Can't determine phys_base\n");
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
kimage_va_translate(unsigned long addr)
Packit Service 501009
{
Packit Service 501009
	unsigned long paddr = (addr - kva_start) + kpa_start;
Packit Service 501009
Packit Service 501009
	return paddr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
kimage_va_range(unsigned long addr)
Packit Service 501009
{
Packit Service 501009
	if (addr >= kva_start && addr < kva_end)
Packit Service 501009
		return TRUE;
Packit Service 501009
	else
Packit Service 501009
		return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_kimage_limits(void)
Packit Service 501009
{
Packit Service 501009
	kva_start = symbol_value("_stext");
Packit Service 501009
	kva_end = symbol_value("_end");
Packit Service 501009
Packit Service 501009
	if (ACTIVE())
Packit Service 501009
		sparc64_kimage_limits_live();
Packit Service 501009
	else
Packit Service 501009
		sparc64_kimage_limits_kdump();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_is_linear_mapped(unsigned long vaddr)
Packit Service 501009
{
Packit Service 501009
	return (vaddr & PAGE_OFFSET) == PAGE_OFFSET;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
pte_to_pa(unsigned long pte)
Packit Service 501009
{
Packit Service 501009
	unsigned long paddr = pte & _PAGE_PFN_MASK;
Packit Service 501009
Packit Service 501009
	return paddr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
fetch_page_table_level(unsigned long pte_kva, unsigned long vaddr,
Packit Service 501009
		       unsigned int shift, unsigned int mask, const char *name,
Packit Service 501009
		       int verbose)
Packit Service 501009
{
Packit Service 501009
	unsigned int pte_index = (vaddr >> shift) & mask;
Packit Service 501009
	unsigned long page_table[PTES_PER_PAGE];
Packit Service 501009
	unsigned long pte = 0UL;
Packit Service 501009
	int rc;
Packit Service 501009
Packit Service 501009
	rc = readmem(pte_kva, KVADDR, page_table, sizeof(page_table),
Packit Service 501009
		     (char *)name, RETURN_ON_ERROR);
Packit Service 501009
	if (!rc)
Packit Service 501009
		goto out;
Packit Service 501009
	pte = page_table[pte_index];
Packit Service 501009
	if (verbose)
Packit Service 501009
		fprintf(fp,
Packit Service 501009
			"%s(0x%.16lx) fetch of pte @index[0x%.4x]=0x%.16lx\n",
Packit Service 501009
			name, pte_kva, pte_index, pte);
Packit Service 501009
out:
Packit Service 501009
	return pte;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
pmd_is_huge(unsigned long pmd, unsigned long vaddr, int verbose)
Packit Service 501009
{
Packit Service 501009
	unsigned long hpage_mask;
Packit Service 501009
	unsigned long paddr = 0UL;
Packit Service 501009
Packit Service 501009
	if ((pmd & PAGE_PMD_HUGE) == 0UL)
Packit Service 501009
		goto out;
Packit Service 501009
	hpage_mask = ~((1UL << HPAGE_SHIFT) - 1UL);
Packit Service 501009
	paddr = pte_to_pa(pmd) + (vaddr & ~hpage_mask);
Packit Service 501009
	if (verbose)
Packit Service 501009
		fprintf(fp, "Huge Page/THP pmd=0x%.16lx paddr=0x%.16lx\n",
Packit Service 501009
			pmd, paddr);
Packit Service 501009
out:
Packit Service 501009
	return paddr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
sparc64_page_table_walk(unsigned long pgd, unsigned long vaddr, int verbose)
Packit Service 501009
{
Packit Service 501009
	static const char *pgd_text = "pgd fetch";
Packit Service 501009
	static const char *pud_text = "pud fetch";
Packit Service 501009
	static const char *pmd_text = "pmd fetch";
Packit Service 501009
	static const char *pte_text = "pte fetch";
Packit Service 501009
	unsigned long kva = pgd;
Packit Service 501009
	unsigned long paddr;
Packit Service 501009
	unsigned long pte;
Packit Service 501009
Packit Service 501009
	if (!sparc64_is_linear_mapped(kva))
Packit Service 501009
		error(FATAL,
Packit Service 501009
			"sparc64_page_table_walk: pgd must be identity mapped"
Packit Service 501009
			" but isn't (0xlx).", pgd);
Packit Service 501009
Packit Service 501009
	pte = fetch_page_table_level(kva, vaddr, PGDIR_SHIFT,
Packit Service 501009
				     PTES_PER_PAGE_MASK, pgd_text, verbose);
Packit Service 501009
	if (!pte)
Packit Service 501009
		goto bad;
Packit Service 501009
	kva = __va(pte);
Packit Service 501009
Packit Service 501009
	pte = fetch_page_table_level(kva, vaddr, PUD_SHIFT, PTES_PER_PAGE_MASK,
Packit Service 501009
				     pud_text, verbose);
Packit Service 501009
	if (!pte)
Packit Service 501009
		goto bad;
Packit Service 501009
Packit Service 501009
	kva = __va(pte);
Packit Service 501009
	pte = fetch_page_table_level(kva, vaddr, PMD_SHIFT,
Packit Service 501009
				     PTES_PER_PAGE_MASK, pmd_text, verbose);
Packit Service 501009
	if (!pte)
Packit Service 501009
		goto bad;
Packit Service 501009
	/* Check for a huge/THP page */
Packit Service 501009
	paddr = pmd_is_huge(pte, vaddr, verbose);
Packit Service 501009
	if (paddr)
Packit Service 501009
		goto out;
Packit Service 501009
	kva = __va(pte);
Packit Service 501009
	pte = fetch_page_table_level(kva, vaddr, PAGE_SHIFT,
Packit Service 501009
				     PTRS_PER_PTE - 1, pte_text, verbose);
Packit Service 501009
	if ((pte & _PAGE_VALID) == 0UL)
Packit Service 501009
		goto bad;
Packit Service 501009
	paddr = pte_to_pa(pte);
Packit Service 501009
	paddr = paddr | (vaddr & ~PAGE_MASK);
Packit Service 501009
out:
Packit Service 501009
	return paddr;
Packit Service 501009
bad:
Packit Service 501009
	return not_valid_pte;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_init_kernel_pgd(void)
Packit Service 501009
{
Packit Service 501009
	int cpu, rc;
Packit Service 501009
	ulong v;
Packit Service 501009
Packit Service 501009
	v = symbol_value("init_mm");
Packit Service 501009
	rc = readmem(v + OFFSET(mm_struct_pgd), KVADDR, &v, sizeof(v),
Packit Service 501009
		"init_mm.pgd", RETURN_ON_ERROR);
Packit Service 501009
	if (!rc) {
Packit Service 501009
		error(WARNING, "Can not determine pgd location.\n");
Packit Service 501009
		goto out;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	for (cpu = 0; cpu < NR_CPUS; cpu++)
Packit Service 501009
		vt->kernel_pgd[cpu] = v;
Packit Service 501009
out:
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_get_smp_cpus(void)
Packit Service 501009
{
Packit Service 501009
	int ncpu = MAX(get_cpus_online(), get_highest_cpu_online() + 1);
Packit Service 501009
Packit Service 501009
	return ncpu;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
sparc64_vmalloc_start(void)
Packit Service 501009
{
Packit Service 501009
	return SPARC64_VMALLOC_START;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
sparc64_IS_VMALLOC_ADDR(ulong vaddr)
Packit Service 501009
{
Packit Service 501009
	return (vaddr >= SPARC64_VMALLOC_START) &&
Packit Service 501009
		(vaddr < machdep->machspec->vmalloc_end);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
pt_clear_cache(void)
Packit Service 501009
{
Packit Service 501009
	machdep->last_pgd_read = 0UL;
Packit Service 501009
	machdep->last_pud_read = 0UL;
Packit Service 501009
	machdep->last_pmd_read = 0UL;
Packit Service 501009
	machdep->last_ptbl_read = 0UL;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
pt_level_alloc(char **lvl, char *name)
Packit Service 501009
{
Packit Service 501009
	size_t sz = PAGE_SIZE;
Packit Service 501009
	void *pointer = malloc(sz);
Packit Service 501009
Packit Service 501009
	if (!pointer)
Packit Service 501009
		error(FATAL, name);
Packit Service 501009
	*lvl = pointer;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_verify_symbol(const char *name, unsigned long value, char type)
Packit Service 501009
{
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_verify_line_number(unsigned long pc, unsigned long low,
Packit Service 501009
			   unsigned long high)
Packit Service 501009
{
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_dis_filter(ulong vaddr, char *inbuf, unsigned int radix)
Packit Service 501009
{
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
struct eframe {
Packit Service 501009
	struct sparc_stackf sf;
Packit Service 501009
	struct pt_regs pr;
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
/* Need to handle hardirq and softirq stacks. */
Packit Service 501009
static int
Packit Service 501009
kstack_valid(struct bt_info *bt, unsigned long sp)
Packit Service 501009
{
Packit Service 501009
	unsigned long thread_info = SIZE(thread_info);
Packit Service 501009
	unsigned long base = bt->stackbase + thread_info;
Packit Service 501009
	unsigned long top = bt->stacktop - sizeof(struct eframe);
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
Packit Service 501009
	if (sp & (16U - 1))
Packit Service 501009
		goto out;
Packit Service 501009
Packit Service 501009
	if ((sp >= base) && (sp <= top))
Packit Service 501009
		rc = TRUE;
Packit Service 501009
out:
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_print_eframe(struct bt_info *bt)
Packit Service 501009
{
Packit Service 501009
	struct eframe k_entry;
Packit Service 501009
	struct pt_regs *regs = &k_entry.pr;
Packit Service 501009
	unsigned long efp;
Packit Service 501009
	unsigned int tt;
Packit Service 501009
	int rc;
Packit Service 501009
	struct reg_window window;
Packit Service 501009
	unsigned long rw;
Packit Service 501009
Packit Service 501009
	efp = bt->stkptr + STACK_BIAS - TRACEREG_SZ - STACKFRAME_SZ;
Packit Service 501009
	if (!kstack_valid(bt, efp))
Packit Service 501009
		goto try_stacktop;
Packit Service 501009
Packit Service 501009
	rc = readmem(efp, KVADDR, &k_entry, sizeof(k_entry),
Packit Service 501009
		     "Stack frame and pt_regs.", RETURN_ON_ERROR);
Packit Service 501009
	if (rc && ((regs->magic & ~MAGIC_TT_MASK) == PT_REGS_MAGIC))
Packit Service 501009
		goto print_frame;
Packit Service 501009
Packit Service 501009
try_stacktop:
Packit Service 501009
	efp = bt->stacktop - sizeof(struct eframe);
Packit Service 501009
	rc = readmem(efp, KVADDR, &k_entry, sizeof(k_entry),
Packit Service 501009
		"Stack frame and pt_regs.", RETURN_ON_ERROR);
Packit Service 501009
	if (!rc)
Packit Service 501009
		goto out;
Packit Service 501009
	/* Kernel thread or not in kernel any longer? */
Packit Service 501009
	if ((regs->magic & ~MAGIC_TT_MASK) != PT_REGS_MAGIC)
Packit Service 501009
		goto out;
Packit Service 501009
Packit Service 501009
print_frame:
Packit Service 501009
	tt = regs->magic & MAGIC_TT_MASK;
Packit Service 501009
	fprintf(fp, "TSTATE=0x%lx TT=0x%x TPC=0x%lx TNPC=0x%lx\n",
Packit Service 501009
		regs->tstate, tt, regs->tpc, regs->tnpc);
Packit Service 501009
	fprintf(fp, " g0=0x%.16lx  g1=0x%.16lx  g2=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[0],
Packit Service 501009
		regs->u_regs[1],
Packit Service 501009
		regs->u_regs[2]);
Packit Service 501009
	fprintf(fp, " g3=0x%.16lx  g4=0x%.16lx  g5=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[3],
Packit Service 501009
		regs->u_regs[4],
Packit Service 501009
		regs->u_regs[5]);
Packit Service 501009
#define	___INS	(8)
Packit Service 501009
	fprintf(fp, " g6=0x%.16lx  g7=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[6],
Packit Service 501009
		regs->u_regs[7]);
Packit Service 501009
	fprintf(fp, " o0=0x%.16lx  o1=0x%.16lx  o2=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[___INS+0],
Packit Service 501009
		regs->u_regs[___INS+1],
Packit Service 501009
		regs->u_regs[___INS+2]);
Packit Service 501009
	fprintf(fp, " o3=0x%.16lx  o4=0x%.16lx  o5=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[___INS+3],
Packit Service 501009
		regs->u_regs[___INS+4],
Packit Service 501009
		regs->u_regs[___INS+5]);
Packit Service 501009
	fprintf(fp, " sp=0x%.16lx  ret_pc=0x%.16lx\n",
Packit Service 501009
		regs->u_regs[___INS+6],
Packit Service 501009
		regs->u_regs[___INS+7]);
Packit Service 501009
#undef	___INS
Packit Service 501009
	rw = bt->stkptr + STACK_BIAS;
Packit Service 501009
	if (!kstack_valid(bt, rw))
Packit Service 501009
		goto out;
Packit Service 501009
	rc = readmem(rw, KVADDR, &window, sizeof(window),
Packit Service 501009
		     "Register window.", RETURN_ON_ERROR);
Packit Service 501009
	if (!rc)
Packit Service 501009
		goto out;
Packit Service 501009
	fprintf(fp, " l0=0x%.16lx  l1=0x%.16lx  l2=0x%.16lx\n",
Packit Service 501009
		window.locals[0], window.locals[1], window.locals[2]);
Packit Service 501009
	fprintf(fp, " l3=0x%.16lx  l4=0x%.16lx  l5=0x%.16lx\n",
Packit Service 501009
		window.locals[3], window.locals[4], window.locals[5]);
Packit Service 501009
	fprintf(fp, " l6=0x%.16lx  l7=0x%.16lx\n",
Packit Service 501009
		window.locals[6], window.locals[7]);
Packit Service 501009
	fprintf(fp, " i0=0x%.16lx  i1=0x%.16lx  i2=0x%.16lx\n",
Packit Service 501009
		window.ins[0], window.ins[1], window.ins[2]);
Packit Service 501009
	fprintf(fp, " i3=0x%.16lx  i4=0x%.16lx  i5=0x%.16lx\n",
Packit Service 501009
		window.ins[3], window.ins[4], window.ins[5]);
Packit Service 501009
	fprintf(fp, " i6=0x%.16lx  i7=0x%.16lx\n",
Packit Service 501009
		window.ins[6], window.ins[7]);
Packit Service 501009
out:
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_eframe_search(struct bt_info *bt)
Packit Service 501009
{
Packit Service 501009
	sparc64_print_eframe(bt);
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_print_frame(struct bt_info *bt, int cnt, unsigned long ip,
Packit Service 501009
		    unsigned long ksp)
Packit Service 501009
{
Packit Service 501009
	char *symbol = closest_symbol(ip);
Packit Service 501009
Packit Service 501009
	fprintf(fp, "#%d [%lx] %s at %lx\n", cnt, ksp, symbol, ip);
Packit Service 501009
Packit Service 501009
	if (bt->flags & BT_LINE_NUMBERS) {
Packit Service 501009
		char buf[BUFSIZE];
Packit Service 501009
Packit Service 501009
		get_line_number(ip, buf, FALSE);
Packit Service 501009
		if (strlen(buf))
Packit Service 501009
			fprintf(fp, "\t%s\n", buf);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_back_trace(struct bt_info *bt)
Packit Service 501009
{
Packit Service 501009
	unsigned long ip = bt->instptr;
Packit Service 501009
	unsigned long ksp = bt->stkptr;
Packit Service 501009
	struct reg_window window;
Packit Service 501009
	int cnt = 0;
Packit Service 501009
	int rc;
Packit Service 501009
Packit Service 501009
	do {
Packit Service 501009
		if (!kstack_valid(bt, ksp + STACK_BIAS))
Packit Service 501009
			break;
Packit Service 501009
		rc = readmem(ksp + STACK_BIAS, KVADDR, &window, sizeof(window),
Packit Service 501009
			"KSP window fetch.", RETURN_ON_ERROR);
Packit Service 501009
		if (!rc)
Packit Service 501009
			goto out;
Packit Service 501009
		sparc64_print_frame(bt, cnt, ip, ksp);
Packit Service 501009
		ksp = window.ins[6];
Packit Service 501009
		ip = window.ins[7];
Packit Service 501009
		cnt++;
Packit Service 501009
	} while (cnt != 50);
Packit Service 501009
	sparc64_print_eframe(bt);
Packit Service 501009
out:
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
sparc64_processor_speed(void)
Packit Service 501009
{
Packit Service 501009
	int cpu;
Packit Service 501009
	unsigned long clock_tick;
Packit Service 501009
	struct syment *sp;
Packit Service 501009
Packit Service 501009
	if (!MEMBER_EXISTS("cpuinfo_sparc", "clock_tick")) {
Packit Service 501009
		error(WARNING, "sparc64 expects clock_tick\n");
Packit Service 501009
		return 0UL;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sp = per_cpu_symbol_search("__cpu_data");
Packit Service 501009
	if (!sp)
Packit Service 501009
		return 0UL;
Packit Service 501009
	for (cpu = 0; cpu < kt->cpus; cpu++) {
Packit Service 501009
		if (!in_cpu_map(ONLINE, cpu))
Packit Service 501009
			continue;
Packit Service 501009
		if (!readmem(sp->value + kt->__per_cpu_offset[cpu] +
Packit Service 501009
			     MEMBER_OFFSET("cpuinfo_sparc", "clock_tick"),
Packit Service 501009
			     KVADDR, &clock_tick, sizeof(clock_tick),
Packit Service 501009
			     "clock_tick", QUIET|RETURN_ON_ERROR))
Packit Service 501009
			continue;
Packit Service 501009
		return clock_tick/1000000;
Packit Service 501009
	}
Packit Service 501009
	return 0UL;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
sparc64_get_task_pgd(ulong task)
Packit Service 501009
{
Packit Service 501009
	struct task_context *tc = task_to_context(task);
Packit Service 501009
	ulong pgd = NO_TASK;
Packit Service 501009
Packit Service 501009
	if (!tc)
Packit Service 501009
		goto out;
Packit Service 501009
	readmem(tc->mm_struct + OFFSET(mm_struct_pgd), KVADDR,
Packit Service 501009
		&pgd, sizeof(unsigned long), "User pgd.", RETURN_ON_ERROR);
Packit Service 501009
out:
Packit Service 501009
	return pgd;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_uvtop(struct task_context *tc, ulong va, physaddr_t *ppaddr,
Packit Service 501009
	      int verbose)
Packit Service 501009
{
Packit Service 501009
	unsigned long pgd = sparc64_get_task_pgd(tc->task);
Packit Service 501009
	unsigned long paddr;
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
Packit Service 501009
	if (pgd == NO_TASK)
Packit Service 501009
		goto out;
Packit Service 501009
	paddr = sparc64_page_table_walk(pgd, va, verbose);
Packit Service 501009
	/* For now not_valid_pte skips checking for swap pte. */
Packit Service 501009
	if (paddr == not_valid_pte) {
Packit Service 501009
		*ppaddr = 0UL;
Packit Service 501009
		goto out;
Packit Service 501009
	}
Packit Service 501009
	*ppaddr = paddr;
Packit Service 501009
	rc = TRUE;
Packit Service 501009
out:
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
sparc64_vmalloc_translate(unsigned long vaddr, int verbose)
Packit Service 501009
{
Packit Service 501009
	unsigned long paddr = sparc64_page_table_walk(vt->kernel_pgd[0],
Packit Service 501009
							vaddr, verbose);
Packit Service 501009
Packit Service 501009
	return paddr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static unsigned long
Packit Service 501009
sparc64_linear_translate(unsigned long vaddr)
Packit Service 501009
{
Packit Service 501009
	unsigned long paddr = __pa(vaddr);
Packit Service 501009
Packit Service 501009
	if (sparc64_verify_paddr(paddr) == FALSE)
Packit Service 501009
		error(FATAL,
Packit Service 501009
			"sparc64_linear_translate: This physical address"
Packit Service 501009
			" (0x%lx) is invalid.", paddr);
Packit Service 501009
Packit Service 501009
	return paddr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_is_vmalloc_mapped(unsigned long vaddr)
Packit Service 501009
{
Packit Service 501009
	struct machine_specific *ms = &sparc64_machine_specific;
Packit Service 501009
	int rc = 0;
Packit Service 501009
Packit Service 501009
	if ((vaddr >= SPARC64_MODULES_VADDR && vaddr < SPARC64_MODULES_END) ||
Packit Service 501009
		(vaddr >= SPARC64_VMALLOC_START && vaddr < ms->vmalloc_end))
Packit Service 501009
		rc = 1;
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_is_kvaddr(ulong vaddr)
Packit Service 501009
{
Packit Service 501009
	return kimage_va_range(vaddr) ||
Packit Service 501009
	       sparc64_is_linear_mapped(vaddr) ||
Packit Service 501009
	       sparc64_is_vmalloc_mapped(vaddr);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_kvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr,
Packit Service 501009
	      int verbose)
Packit Service 501009
{
Packit Service 501009
	unsigned long phys_addr;
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
Packit Service 501009
	if (kimage_va_range(vaddr)) {
Packit Service 501009
		phys_addr = kimage_va_translate(vaddr);
Packit Service 501009
	} else if (sparc64_is_vmalloc_mapped(vaddr)) {
Packit Service 501009
		phys_addr = sparc64_vmalloc_translate(vaddr, verbose);
Packit Service 501009
		if (phys_addr == not_valid_pte)
Packit Service 501009
			goto out;
Packit Service 501009
	} else if (sparc64_is_linear_mapped(vaddr)) {
Packit Service 501009
		phys_addr = sparc64_linear_translate(vaddr);
Packit Service 501009
	} else {
Packit Service 501009
		error(WARNING,
Packit Service 501009
		"This is an invalid kernel virtual address=0x%lx.",
Packit Service 501009
			vaddr);
Packit Service 501009
		goto out;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	*paddr = phys_addr;
Packit Service 501009
	rc = TRUE;
Packit Service 501009
out:
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_is_task_addr(ulong task)
Packit Service 501009
{
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
	int cpu;
Packit Service 501009
Packit Service 501009
	if (sparc64_is_linear_mapped(task) || kimage_va_range(task))
Packit Service 501009
		rc = TRUE;
Packit Service 501009
	else {
Packit Service 501009
		for (cpu = 0; cpu < kt->cpus; cpu++)
Packit Service 501009
			if (task == tt->idle_threads[cpu]) {
Packit Service 501009
				rc = TRUE;
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
	}
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_is_uvaddr(ulong vaddr, struct task_context *tc)
Packit Service 501009
{
Packit Service 501009
	return vaddr < SPARC64_USERSPACE_TOP;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static const char
Packit Service 501009
*pte_page_size(unsigned long pte)
Packit Service 501009
{
Packit Service 501009
	static const char *_4Mb = "4Mb";
Packit Service 501009
	static const char *_64Kb = "64Kb";
Packit Service 501009
	static const char *_8Kb = "8Kb";
Packit Service 501009
	static const char *_ns = "Not Supported";
Packit Service 501009
	const char *result;
Packit Service 501009
Packit Service 501009
	switch (pte & _PAGE_SZALL_4V) {
Packit Service 501009
	case _PAGE_SZ8K_4V:
Packit Service 501009
		result = _8Kb;
Packit Service 501009
		break;
Packit Service 501009
	case _PAGE_SZ64K_4V:
Packit Service 501009
		result = _64Kb;
Packit Service 501009
		break;
Packit Service 501009
	case _PAGE_SZ4MB_4V:
Packit Service 501009
		result = _4Mb;
Packit Service 501009
		break;
Packit Service 501009
	default:
Packit Service 501009
		result = _ns;
Packit Service 501009
	}
Packit Service 501009
	return result;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_translate_pte(unsigned long pte, void *physaddr, ulonglong unused)
Packit Service 501009
{
Packit Service 501009
	unsigned long paddr = pte_to_pa(pte);
Packit Service 501009
	int rc = FALSE;
Packit Service 501009
	int cnt = 0;
Packit Service 501009
Packit Service 501009
	/* Once again not handling swap pte.*/
Packit Service 501009
	if ((pte & _PAGE_VALID) == 0UL)
Packit Service 501009
		goto out;
Packit Service 501009
	if (pte & _PAGE_NFO_4V)
Packit Service 501009
		fprintf(fp, "%sNoFaultOn", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_MODIFIED_4V)
Packit Service 501009
		fprintf(fp, "%sModified", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_ACCESSED_4V)
Packit Service 501009
		fprintf(fp, "%sAccessed", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_READ_4V)
Packit Service 501009
		fprintf(fp, "%sReadSoftware", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_WRITE_4V)
Packit Service 501009
		fprintf(fp, "%sWriteSoftware", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_P_4V)
Packit Service 501009
		fprintf(fp, "%sPriv", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_EXEC_4V)
Packit Service 501009
		fprintf(fp, "%sExecute", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_W_4V)
Packit Service 501009
		fprintf(fp, "%sWritable", cnt++ ? "|" : "");
Packit Service 501009
	if (pte & _PAGE_PRESENT_4V)
Packit Service 501009
		fprintf(fp, "%sPresent", cnt++ ? "|" : "");
Packit Service 501009
	fprintf(fp, "|PageSize(%s)\n", pte_page_size(pte));
Packit Service 501009
	if (physaddr)
Packit Service 501009
		*(unsigned long *)physaddr = paddr;
Packit Service 501009
	rc = TRUE;
Packit Service 501009
out:
Packit Service 501009
	return rc;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_get_frame(struct bt_info *bt, unsigned long *r14, unsigned long *r15)
Packit Service 501009
{
Packit Service 501009
	unsigned long ksp_offset = sparc64_ksp_offset + bt->tc->thread_info;
Packit Service 501009
	unsigned long ksp;
Packit Service 501009
	int rc;
Packit Service 501009
Packit Service 501009
	/* We need thread_info's ksp. This is the stack for sleeping threads
Packit Service 501009
	 * and captured during switch_to. The rest is fetchable from there.
Packit Service 501009
	 */
Packit Service 501009
	rc = readmem(ksp_offset, KVADDR, &ksp, sizeof(ksp), "KSP Fetch.",
Packit Service 501009
		RETURN_ON_ERROR);
Packit Service 501009
	if (!rc)
Packit Service 501009
		goto out;
Packit Service 501009
	*r14 = ksp;
Packit Service 501009
	*r15 = symbol_value("switch_to_pc");
Packit Service 501009
out:
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_get_dumpfile_stack_frame(struct bt_info *bt, unsigned long *psp,
Packit Service 501009
				 unsigned long *ppc)
Packit Service 501009
{
Packit Service 501009
	unsigned long *pt_regs;
Packit Service 501009
Packit Service 501009
	pt_regs = (unsigned long *)bt->machdep;
Packit Service 501009
Packit Service 501009
	if (!pt_regs)
Packit Service 501009
		fprintf(fp, "0%lx: registers not saved\n", bt->task);
Packit Service 501009
Packit Service 501009
	/* pt_regs can be unaligned */
Packit Service 501009
	BCOPY(&pt_regs[30], psp, sizeof(ulong));
Packit Service 501009
	BCOPY(&pt_regs[33], ppc, sizeof(ulong));
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_get_stack_frame(struct bt_info *bt, unsigned long *pcp,
Packit Service 501009
			unsigned long *psp)
Packit Service 501009
{
Packit Service 501009
	unsigned long r14, r15;
Packit Service 501009
Packit Service 501009
	if (DUMPFILE() && is_task_active(bt->task))
Packit Service 501009
		sparc64_get_dumpfile_stack_frame(bt, &r14, &r15);
Packit Service 501009
	else
Packit Service 501009
		sparc64_get_frame(bt, &r14, &r15);
Packit Service 501009
	if (pcp)
Packit Service 501009
		*pcp = r15;
Packit Service 501009
	if (psp)
Packit Service 501009
		*psp = r14;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
sparc64_get_kvaddr_ranges(struct vaddr_range *vrp)
Packit Service 501009
{
Packit Service 501009
	struct machine_specific *ms = &sparc64_machine_specific;
Packit Service 501009
Packit Service 501009
	vrp[0].type = KVADDR_UNITY_MAP;
Packit Service 501009
	vrp[0].start = ms->page_offset;
Packit Service 501009
	vrp[0].end = ~0ULL;
Packit Service 501009
	vrp[1].type = KVADDR_VMALLOC;
Packit Service 501009
	vrp[1].start = SPARC64_VMALLOC_START;
Packit Service 501009
	vrp[1].end = ms->vmalloc_end;
Packit Service 501009
	vrp[2].type = KVADDR_START_MAP;
Packit Service 501009
	vrp[2].start = symbol_value("_start");
Packit Service 501009
	vrp[2].end = symbol_value("_end");
Packit Service 501009
	vrp[3].type = KVADDR_MODULES;
Packit Service 501009
	vrp[3].start = SPARC64_MODULES_VADDR;
Packit Service 501009
	vrp[3].end = SPARC64_MODULES_END;
Packit Service 501009
	return 4;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_get_crash_notes(void)
Packit Service 501009
{
Packit Service 501009
	unsigned long *notes_ptrs, size, crash_notes_address;
Packit Service 501009
	int ret;
Packit Service 501009
Packit Service 501009
	if (!symbol_exists("crash_notes")) {
Packit Service 501009
		error(WARNING, "Could not retrieve crash_notes.");
Packit Service 501009
		goto out;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	crash_notes_address = symbol_value("crash_notes");
Packit Service 501009
	size = kt->cpus * sizeof(notes_ptrs[0]);
Packit Service 501009
	notes_ptrs = (unsigned long *) GETBUF(size);
Packit Service 501009
	ret = readmem(crash_notes_address, KVADDR, notes_ptrs, size,
Packit Service 501009
		"crash_notes", RETURN_ON_ERROR);
Packit Service 501009
	if (!ret)
Packit Service 501009
		goto out2;
Packit Service 501009
out2:
Packit Service 501009
	FREEBUF(notes_ptrs);
Packit Service 501009
out:
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_init_kstack_info(void)
Packit Service 501009
{
Packit Service 501009
	sparc64_ksp_offset = MEMBER_OFFSET("thread_info", "ksp");
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_init_irq_stacks(void)
Packit Service 501009
{
Packit Service 501009
	void *irq_stack;
Packit Service 501009
	unsigned long stack_size;
Packit Service 501009
Packit Service 501009
	stack_size = get_array_length("hardirq_stack", NULL, 0) *
Packit Service 501009
		     sizeof(unsigned long);
Packit Service 501009
	irq_stack = malloc(stack_size);
Packit Service 501009
	if (!irq_stack)
Packit Service 501009
		error(FATAL, "malloc failure in sparc64_init_irq_stacks");
Packit Service 501009
Packit Service 501009
	get_symbol_data("hardirq_stack", stack_size, irq_stack);
Packit Service 501009
	tt->hardirq_ctx = irq_stack;
Packit Service 501009
Packit Service 501009
	stack_size = get_array_length("softirq_stack", NULL, 0) *
Packit Service 501009
		     sizeof(unsigned long);
Packit Service 501009
	irq_stack = malloc(stack_size);
Packit Service 501009
	if (!irq_stack)
Packit Service 501009
		error(FATAL, "malloc failure in sparc64_init_irq_stacks");
Packit Service 501009
Packit Service 501009
	get_symbol_data("softirq_stack", stack_size, irq_stack);
Packit Service 501009
	tt->softirq_ctx = irq_stack;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_init_vmemmap_info(void)
Packit Service 501009
{
Packit Service 501009
	struct machine_specific *ms = &sparc64_machine_specific;
Packit Service 501009
	unsigned long page_struct_size = STRUCT_SIZE("page");
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 * vmemmap memory is addressed as vmalloc memory, so we
Packit Service 501009
	 * treat it as an etension of the latter.
Packit Service 501009
	 */
Packit Service 501009
	ms->vmalloc_end +=
Packit Service 501009
		((1UL << (machdep->max_physmem_bits - PAGE_SHIFT)) *
Packit Service 501009
		 page_struct_size);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
sparc64_init_cpu_info(void)
Packit Service 501009
{
Packit Service 501009
	unsigned long trap_block, per_cpu_base_offset, per_cpu_base;
Packit Service 501009
	unsigned long trap_per_cpu;
Packit Service 501009
	int cpu;
Packit Service 501009
Packit Service 501009
	if (!symbol_exists("trap_block"))
Packit Service 501009
		error(FATAL, "sparc64 requires trap_block symbol.\n");
Packit Service 501009
Packit Service 501009
	trap_block = symbol_value("trap_block");
Packit Service 501009
	if (!MEMBER_EXISTS("trap_per_cpu", "__per_cpu_base"))
Packit Service 501009
		error(FATAL, "sparc64 requires __per_cpu_base.\n");
Packit Service 501009
	trap_per_cpu = STRUCT_SIZE("trap_per_cpu");
Packit Service 501009
	per_cpu_base_offset = MEMBER_OFFSET("trap_per_cpu", "__per_cpu_base");
Packit Service 501009
	for (cpu = 0; cpu < NR_CPUS; cpu++,
Packit Service 501009
		trap_block = trap_block + trap_per_cpu) {
Packit Service 501009
Packit Service 501009
		if (!in_cpu_map(POSSIBLE, cpu))
Packit Service 501009
			continue;
Packit Service 501009
		readmem(trap_block + per_cpu_base_offset, KVADDR,
Packit Service 501009
			&per_cpu_base, sizeof(per_cpu_base),
Packit Service 501009
			"sparc64: per_cpu_base", FAULT_ON_ERROR);
Packit Service 501009
		kt->__per_cpu_offset[cpu] = per_cpu_base;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
sparc64_init(int when)
Packit Service 501009
{
Packit Service 501009
	struct machine_specific *ms = &sparc64_machine_specific;
Packit Service 501009
Packit Service 501009
	switch (when) {
Packit Service 501009
	case SETUP_ENV:
Packit Service 501009
		machdep->process_elf_notes = process_elf64_notes;
Packit Service 501009
		break;
Packit Service 501009
	case PRE_SYMTAB:
Packit Service 501009
		machdep->machspec = ms;
Packit Service 501009
		machdep->verify_paddr = sparc64_verify_paddr;
Packit Service 501009
		machdep->verify_symbol = sparc64_verify_symbol;
Packit Service 501009
		machdep->verify_line_number = sparc64_verify_line_number;
Packit Service 501009
Packit Service 501009
		if (pc->flags & KERNEL_DEBUG_QUERY)
Packit Service 501009
			return;
Packit Service 501009
		machdep->flags |= MACHDEP_BT_TEXT;
Packit Service 501009
		if (machdep->cmdline_args[0])
Packit Service 501009
			sparc64_parse_cmdline_args();
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case PRE_GDB:
Packit Service 501009
		machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
Packit Service 501009
Packit Service 501009
		machdep->pagesize = memory_page_size();
Packit Service 501009
		machdep->pageshift = ffs(machdep->pagesize) - 1;
Packit Service 501009
		machdep->pageoffset = machdep->pagesize - 1;
Packit Service 501009
		machdep->pagemask = ~((ulonglong) machdep->pageoffset);
Packit Service 501009
		machdep->stacksize = machdep->pagesize * 2;
Packit Service 501009
Packit Service 501009
		machdep->eframe_search = sparc64_eframe_search;
Packit Service 501009
		machdep->back_trace = sparc64_back_trace;
Packit Service 501009
		machdep->processor_speed = sparc64_processor_speed;
Packit Service 501009
Packit Service 501009
		machdep->uvtop = sparc64_uvtop;
Packit Service 501009
		machdep->kvtop = sparc64_kvtop;
Packit Service 501009
		machdep->get_task_pgd = sparc64_get_task_pgd;
Packit Service 501009
Packit Service 501009
		machdep->dump_irq = generic_dump_irq;
Packit Service 501009
Packit Service 501009
		machdep->get_stack_frame = sparc64_get_stack_frame;
Packit Service 501009
		machdep->get_stackbase = generic_get_stackbase;
Packit Service 501009
		machdep->get_stacktop = generic_get_stacktop;
Packit Service 501009
		machdep->translate_pte = sparc64_translate_pte;
Packit Service 501009
		machdep->memory_size = generic_memory_size;
Packit Service 501009
Packit Service 501009
		machdep->vmalloc_start = sparc64_vmalloc_start;
Packit Service 501009
		machdep->is_task_addr = sparc64_is_task_addr;
Packit Service 501009
		machdep->is_kvaddr = sparc64_is_kvaddr;
Packit Service 501009
		machdep->is_uvaddr = sparc64_is_uvaddr;
Packit Service 501009
		machdep->dis_filter = sparc64_dis_filter;
Packit Service 501009
		machdep->get_smp_cpus = sparc64_get_smp_cpus;
Packit Service 501009
		machdep->clear_machdep_cache = sparc64_clear_machdep_cache;
Packit Service 501009
		machdep->get_kvaddr_ranges = sparc64_get_kvaddr_ranges;
Packit Service 501009
		machdep->cmd_mach = sparc64_cmd_mach;
Packit Service 501009
		machdep->init_kernel_pgd = sparc64_init_kernel_pgd;
Packit Service 501009
		machdep->value_to_symbol = generic_machdep_value_to_symbol;
Packit Service 501009
		machdep->get_irq_affinity = generic_get_irq_affinity;
Packit Service 501009
		machdep->show_interrupts = generic_show_interrupts;
Packit Service 501009
Packit Service 501009
		pt_level_alloc(&machdep->pgd, "Can't malloc pgd space.");
Packit Service 501009
		pt_level_alloc(&machdep->pud, "Can't malloc pud space.");
Packit Service 501009
		pt_level_alloc(&machdep->pmd, "Can't malloc pmd space.");
Packit Service 501009
		pt_level_alloc(&machdep->ptbl, "Can't malloc ptbl space.");
Packit Service 501009
		pt_clear_cache();
Packit Service 501009
		sparc64_phys_base();
Packit Service 501009
		sparc64_kimage_limits();
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case POST_GDB:
Packit Service 501009
		get_symbol_data("PAGE_OFFSET", sizeof(unsigned long),
Packit Service 501009
				&ms->page_offset);
Packit Service 501009
		machdep->kvbase = symbol_value("_stext");
Packit Service 501009
		machdep->identity_map_base = (ulong) PAGE_OFFSET;
Packit Service 501009
		machdep->ptrs_per_pgd = PTRS_PER_PGD;
Packit Service 501009
		get_symbol_data("VMALLOC_END", sizeof(unsigned long),
Packit Service 501009
				&ms->vmalloc_end);
Packit Service 501009
		machdep->section_size_bits = _SECTION_SIZE_BITS;
Packit Service 501009
		if (kernel_symbol_exists("nr_irqs"))
Packit Service 501009
			get_symbol_data("nr_irqs", sizeof(unsigned int),
Packit Service 501009
			&machdep->nr_irqs);
Packit Service 501009
		sparc64_init_vmemmap_info();
Packit Service 501009
		sparc64_init_cpu_info();
Packit Service 501009
		sparc64_init_kstack_info();
Packit Service 501009
		sparc64_init_irq_stacks();
Packit Service 501009
		break;
Packit Service 501009
	case POST_VM:
Packit Service 501009
		if (!ACTIVE())
Packit Service 501009
			sparc64_get_crash_notes();
Packit Service 501009
		break;
Packit Service 501009
	case POST_INIT:
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case LOG_ONLY:
Packit Service 501009
		machdep->machspec = ms;
Packit Service 501009
		machdep->kvbase = kt->vmcoreinfo._stext_SYMBOL;
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
sparc64_dump_machdep_table(ulong arg)
Packit Service 501009
{
Packit Service 501009
	int i, others;
Packit Service 501009
Packit Service 501009
	others = 0;
Packit Service 501009
	fprintf(fp, "              flags: %lx (", machdep->flags);
Packit Service 501009
	if (machdep->flags & MACHDEP_BT_TEXT)
Packit Service 501009
		fprintf(fp, "%sMACHDEP_BT_TEXT", others++ ? "|" : "");
Packit Service 501009
	fprintf(fp, ")\n");
Packit Service 501009
Packit Service 501009
	fprintf(fp, "             kvbase: %lx\n", machdep->kvbase);
Packit Service 501009
	fprintf(fp, "  identity_map_base: %lx\n", machdep->identity_map_base);
Packit Service 501009
	fprintf(fp, "           pagesize: %d\n", machdep->pagesize);
Packit Service 501009
	fprintf(fp, "          pageshift: %d\n", machdep->pageshift);
Packit Service 501009
	fprintf(fp, "           pagemask: %llx\n", machdep->pagemask);
Packit Service 501009
	fprintf(fp, "         pageoffset: %lx\n", machdep->pageoffset);
Packit Service 501009
	fprintf(fp, "          stacksize: %ld\n", machdep->stacksize);
Packit Service 501009
	fprintf(fp, "                 hz: %d\n", machdep->hz);
Packit Service 501009
	fprintf(fp, "                mhz: %ld\n", machdep->mhz);
Packit Service 501009
	fprintf(fp, "            memsize: %ld (0x%lx)\n",
Packit Service 501009
		machdep->memsize, machdep->memsize);
Packit Service 501009
	fprintf(fp, "               bits: %d\n", machdep->bits);
Packit Service 501009
	fprintf(fp, "            nr_irqs: %d\n", machdep->nr_irqs);
Packit Service 501009
	fprintf(fp, "      eframe_search: sparc64_eframe_search()\n");
Packit Service 501009
	fprintf(fp, "         back_trace: sparc64_back_trace()\n");
Packit Service 501009
	fprintf(fp, "    processor_speed: sparc64_processor_speed()\n");
Packit Service 501009
	fprintf(fp, "              uvtop: sparc64_uvtop()\n");
Packit Service 501009
	fprintf(fp, "              kvtop: sparc64_kvtop()\n");
Packit Service 501009
	fprintf(fp, "       get_task_pgd: sparc64_get_task_pgd()\n");
Packit Service 501009
	fprintf(fp, "           dump_irq: generic_dump_irq()\n");
Packit Service 501009
	fprintf(fp, "    get_stack_frame: sparc64_get_stack_frame()\n");
Packit Service 501009
	fprintf(fp, "      get_stackbase: generic_get_stackbase()\n");
Packit Service 501009
	fprintf(fp, "       get_stacktop: generic_get_stacktop()\n");
Packit Service 501009
	fprintf(fp, "      translate_pte: sparc64_translate_pte()\n");
Packit Service 501009
	fprintf(fp, "        memory_size: generic_memory_size()\n");
Packit Service 501009
	fprintf(fp, "      vmalloc_start: sparc64_vmalloc_start()\n");
Packit Service 501009
	fprintf(fp, "       is_task_addr: sparc64_is_task_addr()\n");
Packit Service 501009
	fprintf(fp, "      verify_symbol: sparc64_verify_symbol()\n");
Packit Service 501009
	fprintf(fp, "         dis_filter: sparc64_dis_filter()\n");
Packit Service 501009
	fprintf(fp, "           cmd_mach: sparc64_cmd_mach()\n");
Packit Service 501009
	fprintf(fp, "       get_smp_cpus: sparc64_get_smp_cpus()\n");
Packit Service 501009
	fprintf(fp, "          is_kvaddr: sparc64_is_kvaddr()\n");
Packit Service 501009
	fprintf(fp, "          is_uvaddr: sparc64_is_uvaddr()\n");
Packit Service 501009
	fprintf(fp, "       verify_paddr: sparc64_verify_paddr()\n");
Packit Service 501009
	fprintf(fp, "  get_kvaddr_ranges: sparc64_get_kvaddr_ranges()\n");
Packit Service 501009
	fprintf(fp, "   get_irq_affinity: generic_get_irq_affinity()\n");
Packit Service 501009
	fprintf(fp, "    show_interrupts: generic_show_interrupts()\n");
Packit Service 501009
	fprintf(fp, " xendump_p2m_create: NULL\n");
Packit Service 501009
	fprintf(fp, "xen_kdump_p2m_create: NULL\n");
Packit Service 501009
	fprintf(fp, "  line_number_hooks: NULL\n");
Packit Service 501009
	fprintf(fp, "      last_pgd_read: %lx\n", machdep->last_pgd_read);
Packit Service 501009
	fprintf(fp, "      last_pmd_read: %lx\n", machdep->last_pmd_read);
Packit Service 501009
	fprintf(fp, "     last_ptbl_read: %lx\n", machdep->last_ptbl_read);
Packit Service 501009
	fprintf(fp, "clear_machdep_cache: sparc64_clear_machdep_cache()\n");
Packit Service 501009
	fprintf(fp, "                pgd: %lx\n", (ulong)machdep->pgd);
Packit Service 501009
	fprintf(fp, "                pmd: %lx\n", (ulong)machdep->pmd);
Packit Service 501009
	fprintf(fp, "               ptbl: %lx\n", (ulong)machdep->ptbl);
Packit Service 501009
	fprintf(fp, "       ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd);
Packit Service 501009
	fprintf(fp, "  section_size_bits: %ld\n", machdep->section_size_bits);
Packit Service 501009
	fprintf(fp, "   max_physmem_bits: %ld\n", machdep->max_physmem_bits);
Packit Service 501009
	fprintf(fp, "  sections_per_root: %ld\n", machdep->sections_per_root);
Packit Service 501009
	for (i = 0; i < MAX_MACHDEP_ARGS; i++) {
Packit Service 501009
		fprintf(fp, "    cmdline_args[%d]: %s\n", i,
Packit Service 501009
			machdep->cmdline_args[i] ?
Packit Service 501009
			machdep->cmdline_args[i] : "(unused)");
Packit Service 501009
	}
Packit Service 501009
	fprintf(fp, "           machspec: %lx\n", (ulong)machdep->machspec);
Packit Service 501009
	fprintf(fp, "          page_offset: %lx\n",
Packit Service 501009
		machdep->machspec->page_offset);
Packit Service 501009
	fprintf(fp, "          vmalloc_end: %lx\n",
Packit Service 501009
		machdep->machspec->vmalloc_end);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
#endif /* SPARC64 */