/* $NetBSD: booke_machdep.c,v 1.35 2024/03/05 14:15:34 thorpej Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
* Agency and which was developed by Matt Thomas of 3am Software Foundry.
*
* This material is based upon work supported by the Defense Advanced Research
* Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
* Contract No. N66001-09-C-2073.
* Approved for Public Release, Distribution Unlimited
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* This should probably be in autoconf! XXX
*/
char machine[] = MACHINE; /* from <machine/param.h> */
char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */
/*
* Halt or reboot the machine after syncing/dumping according to howto.
*/
void
cpu_reboot(int howto, char *what)
{
static int syncing;
static char str[256];
char *ap = str, *ap1 = ap;
if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
/* Power off here if we know how...*/
}
if (howto & RB_HALT) {
printf("The operating system has halted.\n"
"Press any key to reboot.\n\n");
cnpollc(1); /* For proper keyboard command handling */
cngetc();
cnpollc(0);
}
printf("rebooting\n\n");
if (what && *what) {
if (strlen(what) > sizeof str - 5)
printf("boot string too large, ignored\n");
else {
strcpy(str, what);
ap1 = ap = str + strlen(str);
*ap++ = ' ';
}
}
*ap++ = '-';
if (howto & RB_SINGLE)
*ap++ = 's';
if (howto & RB_KDB)
*ap++ = 'd';
*ap++ = 0;
if (ap[-2] == '-')
*ap1 = 0;
/* flush cache for msgbuf */
dcache_wb(msgbuf_paddr, round_page(MSGBUFSIZE));
printf("%s: md_cpu_reset() failed!\n", __func__);
#ifdef DDB
for (;;)
Debugger();
#else
for (;;)
/* nothing */;
#endif
}
/*
* mapiodev:
*
* Allocate vm space and mapin the I/O address. Use reserved TLB
* mapping if one is found.
*/
void *
mapiodev(paddr_t pa, psize_t len, bool prefetchable)
{
const vsize_t off = pa & PAGE_MASK;
/*
* See if we have reserved TLB entry for the pa. This needs to be
* true for console as we can't use uvm during early bootstrap.
*/
void * const p = tlb_mapiodev(pa, len, prefetchable);
if (p != NULL)
return p;
if (fake_mapiodev)
panic("mapiodev: no TLB entry reserved for %llx+%llx",
(long long)pa, (long long)len);
const paddr_t orig_pa = pa;
const psize_t orig_len = len;
vsize_t align = 0;
pa = trunc_page(pa);
len = round_page(off + len);
/*
* If we are allocating a large amount (>= 1MB) try to get an
* aligned VA region for it so try to do a large mapping for it.
*/
if ((len & (len - 1)) == 0 && len >= 0x100000)
align = len;
vaddr_t va = uvm_km_alloc(kernel_map, len, align, UVM_KMF_VAONLY);
if (va == 0 && align > 0) {
/*
* Large aligned request failed. Let's just get anything.
*/
align = 0;
va = uvm_km_alloc(kernel_map, len, align, UVM_KMF_VAONLY);
}
if (va == 0)
return NULL;
if (align) {
/*
* Now try to map that via one big TLB entry.
*/
pt_entry_t pte = pte_make_kenter_pa(pa, NULL,
VM_PROT_READ|VM_PROT_WRITE,
prefetchable ? 0 : PMAP_NOCACHE);
if (!tlb_ioreserve(va, len, pte)) {
void * const p0 = tlb_mapiodev(orig_pa, orig_len,
prefetchable);
KASSERT(p0 != NULL);
return p0;
}
}
for (va += len, pa += len; len > 0; len -= PAGE_SIZE) {
va -= PAGE_SIZE;
pa -= PAGE_SIZE;
pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE,
prefetchable ? 0 : PMAP_NOCACHE);
}
pmap_update(pmap_kernel());
return (void *)(va + off);
}
void
unmapiodev(vaddr_t va, vsize_t len)
{
/* Nothing to do for reserved (ie. not uvm_km_alloc'd) mappings. */
if (va < VM_MIN_KERNEL_ADDRESS || va > VM_MAX_KERNEL_ADDRESS) {
tlb_unmapiodev(va, len);
return;
}
len = round_page((va & PAGE_MASK) + len);
va = trunc_page(va);
pmap_kremove(va, len);
uvm_km_free(kernel_map, va, len, UVM_KMF_VAONLY);
}
for (CPU_INFO_FOREACH(cii, ci)) {
/*
* Skip this CPU if it didn't successfully hatch.
*/
if (!kcpuset_isset(csi->cpus_hatched, cpu_index(ci)))
continue;