/*-
* Initial implementation:
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
*
* As long as the above copyright statement and this notice remain
* unchanged, you can do what ever you want with this file.
*/
/*-
* Copyright (c) 2008 - 2012 Marius Strobl <marius@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
*
* 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.
*/
__FBSDID("$FreeBSD$");
/*
*
* - implements copyin and readin functions that map kernel
* pages on demand. The machine independent code does not
* know the size of the kernel early enough to pre-enter
* TTEs and install just one 4MB mapping seemed to limiting
* to me.
*/
#include <stand.h>
#ifdef LOADER_ZFS_SUPPORT
#endif
#include <machine/fireplane.h>
#include <machine/metadata.h>
#include "bootstrap.h"
#include "libofw.h"
#include "dev_net.h"
enum {
};
/* At least Sun Fire V1280 require page sized allocations to be claimed. */
static struct mmu_ops {
void (*tlb_init)(void);
} *mmu_ops;
void *openfirmware);
static void itlb_relocate_locked0_sun4u(void);
static int sparc64_autoload(void);
static vm_offset_t init_heap(void);
const char *cpu_cpuid_prop_sun4u(void);
uint32_t cpu_get_mid_sun4u(void);
static void tlb_init_sun4u(void);
#ifdef LOADER_DEBUG
static void pmap_print_tlb_sun4u(void);
#endif
/* sun4u */
static int cpu_impl;
#ifdef LOADER_ZFS_SUPPORT
#endif
/*
* Machine dependent structures that the machine independent
* loader part uses.
*/
#ifdef LOADER_DISK_SUPPORT
&ofwdisk,
#endif
#ifdef LOADER_NET_SUPPORT
&netdev,
#endif
#ifdef LOADER_ZFS_SUPPORT
&zfs_dev,
#endif
};
};
};
#ifdef LOADER_ZFS_SUPPORT
#endif
#ifdef LOADER_UFS_SUPPORT
#endif
#ifdef LOADER_CD9660_SUPPORT
#endif
#ifdef LOADER_ZIP_SUPPORT
#endif
#ifdef LOADER_GZIP_SUPPORT
#endif
#ifdef LOADER_BZIP2_SUPPORT
#endif
#ifdef LOADER_NFS_SUPPORT
#endif
#ifdef LOADER_TFTP_SUPPORT
#endif
};
#ifdef LOADER_NET_SUPPORT
&ofwnet,
#endif
};
extern struct console ofwconsole;
};
#ifdef LOADER_DEBUG
static int
{
(mask << LSU_PM_SHIFT);
return (0);
}
static int
{
/* Test for misaligned watch points. */
return (-1);
}
static int
{
(mask << LSU_VM_SHIFT);
return (0);
}
static int
{
/* Test for misaligned watch points. */
return (-1);
}
#endif
/*
* archsw functions
*/
static int
sparc64_autoload(void)
{
return (0);
}
static ssize_t
{
}
static ssize_t
{
return (len);
}
/*
* other MD functions
*/
static vm_offset_t
{
return ((vm_offset_t)-1);
return (mva);
}
static vm_offset_t
{
&phys_hi) == -1)
return ((vm_offset_t)-1);
}
static int
{
}
static void
{
}
static int
{
Elf_Ehdr *e;
int error;
return (EFTYPE);
return (error);
#ifdef LOADER_DEBUG
#endif
dev_cleanup();
}
static inline u_long
{
/*
* We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to
* work around errata of USIII and beyond.
*/
return (data);
}
static inline u_long
{
/*
* We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to
* work around errata of USIII and beyond.
*/
return (data);
}
static vm_offset_t
{
for (i = 0; i < dtlb_slot_max; i++) {
continue;
if (cpu_impl == CPU_IMPL_SPARC64V ||
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
return (-1);
}
static vm_offset_t
{
int i;
for (i = 0; i < itlb_slot_max; i++) {
continue;
if (cpu_impl == CPU_IMPL_SPARC64V ||
return (reg & TD_PA_CH_MASK);
return (reg & TD_PA_SF_MASK);
}
return (-1);
}
static int
{
virt));
}
static int
{
panic("%s: won't enter locked TLB entry at index 0 on USIII+",
__func__);
virt));
}
static void
{
int i;
if (cpu_impl != CPU_IMPL_ULTRASPARCIIIp)
return;
return;
}
/* Flush the mapping of slot 0. */
flush(0); /* The USIII-family ignores the address. */
/*
* Search a replacement slot != 0 and enter the data and tag
* that formerly were in slot 0.
*/
for (i = 1; i < itlb_slot_max; i++) {
continue;
data);
flush(0); /* The USIII-family ignores the address. */
break;
}
if (i == itlb_slot_max)
}
static int
{
va &= ~PAGE_MASK_4M;
while (len) {
/* Allocate a physical page, claim the virtual area. */
panic("%s: can't claim virtual page "
"(wanted %#lx, got %#lx)",
/*
* The mappings may have changed, be paranoid.
*/
continue;
}
/*
* Actually, we can only allocate two pages less at
* most (depending on the kernel TSB size).
*/
if (dtlb_slot >= dtlb_slot_max)
if (itlb_slot >= itlb_slot_max)
panic("%s: can't enter dTLB slot %d data "
va);
dtlb_slot++;
panic("%s: can't enter iTLB slot %d data "
va);
itlb_slot++;
}
va += PAGE_SIZE_4M;
}
return (0);
}
static vm_offset_t
init_heap(void)
{
/* There is no need for continuous physical heap memory. */
return (heapva);
}
static phandle_t
{
if (child > 0) {
if (child > 0)
return (child);
} else {
sizeof(type)) <= 0)
continue;
continue;
sizeof(cpuid)) <= 0)
continue;
return (node);
}
}
return (0);
}
const char *
cpu_cpuid_prop_sun4u(void)
{
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
return ("upa-portid");
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
return ("portid");
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
return ("cpuid");
default:
return ("");
}
}
cpu_get_mid_sun4u(void)
{
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_SPARC64V:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
default:
return (0);
}
}
static void
tlb_init_sun4u(void)
{
switch (cpu_impl) {
case CPU_IMPL_SPARC64:
case CPU_IMPL_ULTRASPARCI:
case CPU_IMPL_ULTRASPARCII:
case CPU_IMPL_ULTRASPARCIIi:
case CPU_IMPL_ULTRASPARCIIe:
break;
case CPU_IMPL_ULTRASPARCIII:
case CPU_IMPL_ULTRASPARCIIIp:
case CPU_IMPL_ULTRASPARCIIIi:
case CPU_IMPL_ULTRASPARCIIIip:
case CPU_IMPL_ULTRASPARCIV:
case CPU_IMPL_ULTRASPARCIVp:
break;
case CPU_IMPL_SPARC64V:
break;
}
if (bsp == 0)
sizeof(dtlb_slot_max)) == -1 ||
sizeof(itlb_slot_max)) == -1)
if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) {
#ifdef LOADER_DEBUG
printf("pre fixup:\n");
#endif
/*
* Relocate the locked entry in it16 slot 0 (if existent)
* as part of working around Cheetah+ erratum 34.
*/
#ifdef LOADER_DEBUG
printf("post fixup:\n");
#endif
}
}
#ifdef LOADER_ZFS_SUPPORT
static void
sparc64_zfs_probe(void)
{
/* Get the GUID of the ZFS pool on the boot device. */
guid = 0;
/*
* Get the GUIDs of the ZFS pools on any additional disks listed in
* the boot-device environment variable.
*/
goto out;
if (len <= 0)
goto out;
goto out;
goto out;
if (*dev == '\0')
continue;
/*
* Don't probe the boot disk twice. Note that bootpath
* includes the partition specifier.
*/
continue;
sizeof(type)) == -1)
continue;
continue;
/* Find freebsd-zfs slices in the VTOC. */
if (fd == -1)
continue;
continue;
}
continue;
break;
}
}
out:
if (guid != 0) {
zfs_currdev.root_guid = 0;
}
}
#endif /* LOADER_ZFS_SUPPORT */
int
{
/*
* Tell the Open Firmware functions where they find the OFW gate.
*/
#ifdef LOADER_ZFS_SUPPORT
#endif
OF_exit();
/*
* Probe for a console.
*/
cons_probe();
mmu_ops = &mmu_ops_sun4u;
/*
* Set up the current device.
*/
/*
* Initialize devices.
*/
#ifdef LOADER_ZFS_SUPPORT
if (zfs_currdev.pool_guid != 0) {
sizeof(bootpath) - 1);
} else
#endif
/*
* Sun compatible bootable CD-ROMs have a disk label placed before
* the ISO 9660 data, with the actual file system being in the first
* partition, while the other partitions contain pseudo disk labels
* with embedded boot blocks for different architectures, which may
* be followed by UFS file systems.
* The firmware will set the boot path to the partition it boots from
* from the ISO 9660 file system ('a'), so the boot path needs to be
* altered.
*/
printf("\n");
/* Give control to the machine independent loader code. */
return (1);
}
static int
{
mallocstats();
return(CMD_OK);
}
static int
{
int i;
(devsw[i]->dv_cleanup)();
printf("Rebooting...\n");
OF_exit();
}
/* provide this for panic, as it's not in the startup code */
void
{
OF_exit();
}
#ifdef LOADER_DEBUG
static const char *const page_sizes[] = {
" 8k", " 64k", "512k", " 4m"
};
static void
{
printf("%s %s ",
printf("pa=0x%lx va=0x%lx ctx=%ld\n",
}
static void
pmap_print_tlb_sun4u(void)
{
int i;
for (i = 0; i < itlb_slot_max; i++) {
continue;
printf("iTLB-%2u: ", i);
}
for (i = 0; i < dtlb_slot_max; i++) {
continue;
printf("dTLB-%2u: ", i);
}
}
#endif