#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.7 2025/12/21 07:00:27 skrll Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_modular.h"
#include <sys/param.h>
#include <sys/boot_flag.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/kcore.h>
#include <sys/kernel.h>
#include <sys/ksyms.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/reboot.h>
#include <sys/termios.h>
#include <uvm/uvm_extern.h>
#include <dev/cons.h>
#include <dev/ic/comvar.h>
#include <dev/ic/ns16450reg.h>
#include <evbmips/mipssim/mipssimreg.h>
#include <evbmips/mipssim/mipssimvar.h>
#include "ksyms.h"
#if NKSYMS || defined(DDB) || defined(MODULAR)
#include <mips/db_machdep.h>
#include <ddb/db_extern.h>
#endif
#include <mips/cache.h>
#include <mips/locore.h>
#include <mips/cpuregs.h>
#define COMCNRATE 115200
#define COM_FREQ 1843200
#ifdef _LP64
#define CPU_FREQ 6
#else
#define CPU_FREQ 12
#endif
struct vm_map *phys_map = NULL;
struct mipssim_config mipssim_configuration;
int mem_cluster_cnt;
phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
void mach_init(u_long, u_long, u_long, u_long);
static void mach_init_memory(void);
static void uart_putc(dev_t, int);
static struct consdev early_console = {
.cn_putc = uart_putc,
.cn_dev = makedev(0, 0),
.cn_pri = CN_DEAD
};
static void
uart_putc(dev_t dev, int c)
{
volatile uint8_t *data = (void *)MIPS_PHYS_TO_KSEG1(
MIPSSIM_ISA_IO_BASE + MIPSSIM_UART0_ADDR + com_data);
*data = (uint8_t)c;
}
static void
cal_timer(void)
{
uint32_t cntfreq;
cntfreq = curcpu()->ci_cpu_freq = CPU_FREQ * 1000 * 1000;
if (mips_options.mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT)
cntfreq /= 2;
curcpu()->ci_cctr_freq = cntfreq;
curcpu()->ci_cycles_per_hz = (cntfreq + hz / 2) / hz;
curcpu()->ci_divisor_delay = ((cntfreq + 500000) / 1000000);
}
void
mach_init(u_long arg0, u_long arg1, u_long arg2, u_long arg3)
{
struct mipssim_config *mcp = &mipssim_configuration;
void *kernend;
extern char edata[], end[];
kernend = (void *)mips_round_page(end);
memset(edata, 0, end - edata);
cn_tab = &early_console;
cpu_setmodel("MIPSSIM");
mips_vector_init(NULL, false);
cal_timer();
uvm_md_init();
mipssim_bus_io_init(&mcp->mc_iot, mcp);
mipssim_dma_init(mcp);
if (comcnattach(&mcp->mc_iot, MIPSSIM_UART0_ADDR, COMCNRATE,
COM_FREQ, COM_TYPE_NORMAL,
(TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8) != 0)
panic("unable to initialize serial console");
boothowto = RB_AUTOBOOT;
#ifdef KADB
boothowto |= RB_KDB;
#endif
mach_init_memory();
mips_page_physload(MIPS_KSEG0_START, (vaddr_t)kernend,
mem_clusters, mem_cluster_cnt, NULL, 0);
mips_init_msgbuf();
pmap_bootstrap();
mips_init_lwp0_uarea();
#ifdef DDB
if (boothowto & RB_KDB)
Debugger();
#endif
}
static void
mach_init_memory(void)
{
struct lwp *l = curlwp;
struct pcb dummypcb;
psize_t memsize;
size_t addr;
uint32_t *memptr;
extern char end[];
#ifdef MIPS64
size_t highaddr;
#endif
l->l_addr = &dummypcb;
memsize = roundup2(MIPS_KSEG0_TO_PHYS((uintptr_t)(end)), 1024 * 1024);
for (addr = memsize; addr < MIPSSIM_ISA_IO_BASE; addr += 1024 * 1024) {
#ifdef MEM_DEBUG
printf("test %zd MB\n", addr / 1024 * 1024);
#endif
memptr = (void *)MIPS_PHYS_TO_KSEG1(addr - sizeof(*memptr));
if (badaddr(memptr, sizeof(uint32_t)) < 0)
break;
memsize = addr;
}
l->l_addr = NULL;
physmem = btoc(memsize);
mem_clusters[0].start = PAGE_SIZE;
mem_clusters[0].size = memsize - PAGE_SIZE;
mem_cluster_cnt = 1;
#ifdef _LP64
l->l_addr = &dummypcb;
for (highaddr = addr = MIPSSIM_MORE_MEM_BASE;
addr < MIPSSIM_MORE_MEM_END;
addr += 1024 * 1024) {
memptr = (void *)MIPS_PHYS_TO_XKPHYS(CCA_CACHEABLE,
addr - sizeof(*memptr));
if (badaddr(memptr, sizeof(uint32_t)) < 0)
break;
highaddr = addr;
#ifdef MEM_DEBUG
printf("probed %zd MB\n", (addr - MIPSSIM_MORE_MEM_BASE)
/ 1024 * 1024);
#endif
}
l->l_addr = NULL;
if (highaddr != MIPSSIM_MORE_MEM_BASE) {
mem_clusters[1].start = MIPSSIM_MORE_MEM_BASE;
mem_clusters[1].size = highaddr - MIPSSIM_MORE_MEM_BASE;
mem_cluster_cnt++;
physmem += btoc(mem_clusters[1].size);
memsize += mem_clusters[1].size;
}
#endif
printf("Memory size: 0x%" PRIxPSIZE " (%" PRIdPSIZE " MB)\n",
memsize, memsize / 1024 / 1024);
}
void
consinit(void)
{
}
void
cpu_startup(void)
{
cpu_startup_common();
}
void
cpu_reboot(int howto, char *bootstr)
{
static int waittime = -1;
savectx(curpcb);
if (boothowto & RB_HALT)
howto |= RB_HALT;
boothowto = howto;
if (cold) {
boothowto |= RB_HALT;
goto haltsys;
}
if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) {
waittime = 0;
vfs_shutdown();
}
splhigh();
if (boothowto & RB_DUMP)
dumpsys();
haltsys:
doshutdownhooks();
if (boothowto & RB_HALT) {
printf("\n");
printf("The operating system has halted.\n");
printf("Please press any key to reboot.\n\n");
cnpollc(true);
cngetc();
cnpollc(false);
}
printf("resetting...\n\n");
__asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC));
printf("Oops, back from reset\n\nSpinning...");
for (;;)
;
}