#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.125 2025/12/20 10:51:01 skrll Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_modular.h"
#include "opt_execfmt.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/boot_flag.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/kcore.h>
#include <sys/ksyms.h>
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <uvm/uvm_extern.h>
#include <machine/bootinfo.h>
#include <mips/locore.h>
#include <mips/psl.h>
#include <dev/cons.h>
#include <cobalt/dev/gtreg.h>
#ifdef KGDB
#include <sys/kgdb.h>
#endif
#include "ksyms.h"
#if NKSYMS || defined(DDB) || defined(MODULAR)
#include <mips/db_machdep.h>
#include <ddb/db_extern.h>
#include <sys/exec_elf.h>
#endif
struct vm_map *phys_map = NULL;
void *bootinfo = NULL;
char bootstring[512];
int netboot;
char *nfsroot_bstr = NULL;
char *root_bstr = NULL;
int bootunit = -1;
int bootpart = -1;
#if 0
struct extent *cobalt_io_ex = NULL;
struct extent *cobalt_mem_ex = NULL;
struct mips_bus_space bonito_iot;
struct mips_bus_space bonito_memt;
struct mips_bus_dma_tag bonito_dmat;
struct mips_pci_chipset bonito_pc;
#endif
int cpuspeed;
u_int cobalt_id;
static const char * const cobalt_model[] =
{
[COBALT_ID_QUBE2700] = "Cobalt Qube 2700",
[COBALT_ID_RAQ] = "Cobalt RaQ",
[COBALT_ID_QUBE2] = "Cobalt Qube 2",
[COBALT_ID_RAQ2] = "Cobalt RaQ 2"
};
#define COBALT_MODELS __arraycount(cobalt_model)
phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
int mem_cluster_cnt;
void mach_init(int32_t, u_int, int32_t);
void decode_bootstring(void);
static char *strtok_light(char *, const char);
static u_int read_board_id(void);
extern char *esym;
struct mips_bus_space cobalt_bs;
void mainbus_bus_mem_init(bus_space_tag_t, void *);
void
mach_init(int32_t memsize32, u_int bim, int32_t bip32)
{
intptr_t memsize = (int32_t)memsize32;
char *kernend;
char *bip = (char *)(intptr_t)(int32_t)bip32;
u_long first, last;
extern char edata[], end[];
const char *bi_msg;
#if NKSYMS || defined(DDB) || defined(MODULAR)
char *ssym = 0;
struct btinfo_symtab *bi_syms;
#endif
struct btinfo_howto *bi_howto;
if (memcmp(((Elf_Ehdr *)end)->e_ident, ELFMAG, SELFMAG) == 0 &&
((Elf_Ehdr *)end)->e_ident[EI_CLASS] == ELFCLASS) {
esym = end;
#if NKSYMS || defined(DDB) || defined(MODULAR)
esym += ((Elf_Ehdr *)end)->e_entry;
#endif
kernend = (char *)mips_round_page(esym);
#if 0
memset(edata, 0, end - edata);
#endif
} else {
kernend = (void *)mips_round_page(end);
memset(edata, 0, kernend - edata);
}
mips_vector_init(NULL, false);
mainbus_bus_mem_init(&cobalt_bs, NULL);
if (bim == BOOTINFO_MAGIC) {
struct btinfo_magic *bi_magic;
bootinfo = bip;
bi_magic = lookup_bootinfo(BTINFO_MAGIC);
if (bi_magic == NULL) {
bi_msg = "missing bootinfo structure";
bim = (uintptr_t)bip;
} else if (bi_magic->magic != BOOTINFO_MAGIC) {
bi_msg = "invalid bootinfo structure";
bim = bi_magic->magic;
} else
bi_msg = NULL;
} else {
bi_msg = "invalid bootinfo (standalone boot?)";
}
#if NKSYMS || defined(DDB) || defined(MODULAR)
bi_syms = lookup_bootinfo(BTINFO_SYMTAB);
if (bi_syms != NULL) {
ssym = (void *)(intptr_t)bi_syms->ssym;
esym = (void *)(intptr_t)bi_syms->esym;
kernend = (void *)mips_round_page(esym);
}
#endif
bi_howto = lookup_bootinfo(BTINFO_HOWTO);
if (bi_howto != NULL)
boothowto = bi_howto->bi_howto;
cobalt_id = read_board_id();
if (cobalt_id >= COBALT_MODELS || cobalt_model[cobalt_id] == NULL)
cpu_setmodel("Cobalt unknown model (board ID %u)",
cobalt_id);
else
cpu_setmodel("%s", cobalt_model[cobalt_id]);
switch (cobalt_id) {
case COBALT_ID_QUBE2700:
case COBALT_ID_RAQ:
cpuspeed = 150;
break;
case COBALT_ID_QUBE2:
case COBALT_ID_RAQ2:
cpuspeed = 250;
break;
default:
cpuspeed = 250;
break;
}
curcpu()->ci_cpu_freq = cpuspeed * 1000 * 1000;
curcpu()->ci_cycles_per_hz = (curcpu()->ci_cpu_freq + hz / 2) / hz;
curcpu()->ci_divisor_delay =
((curcpu()->ci_cpu_freq + (1000000 / 2)) / 1000000);
curcpu()->ci_cycles_per_hz /= 2;
curcpu()->ci_divisor_delay /= 2;
physmem = btoc(memsize - MIPS_KSEG0_START);
consinit();
KASSERT(&lwp0 == curlwp);
if (bi_msg != NULL)
printf("%s: magic=%#x bip=%p\n", bi_msg, bim, bip);
uvm_md_init();
mem_clusters[0].start = 0;
mem_clusters[0].size = ctob(physmem) - 512;
mem_cluster_cnt = 1;
memcpy(bootstring, (char *)(memsize - 512), 512);
memset((char *)(memsize - 512), 0, 512);
bootstring[511] = '\0';
decode_bootstring();
#if NKSYMS || defined(DDB) || defined(MODULAR)
if ((bi_syms != NULL) && (esym != NULL))
ksyms_addsyms_elf(esym - ssym, ssym, esym);
#endif
KASSERT(&lwp0 == curlwp);
first = round_page(MIPS_KSEG0_TO_PHYS(kernend));
last = mem_clusters[0].start + mem_clusters[0].size;
uvm_page_physload(atop(first), atop(last), atop(first), atop(last),
VM_FREELIST_DEFAULT);
mips_init_msgbuf();
pmap_bootstrap();
mips_init_lwp0_uarea();
#ifdef DDB
if (boothowto & RB_KDB)
Debugger();
#endif
#ifdef KGDB
if (boothowto & RB_KDB)
kgdb_connect(0);
#endif
}
void
cpu_startup(void)
{
cpu_startup_common();
}
static int waittime = -1;
void
cpu_reboot(int howto, char *bootstr)
{
savectx(curpcb);
if (cold) {
howto |= RB_HALT;
goto haltsys;
}
if (boothowto & RB_HALT)
howto |= RB_HALT;
boothowto = howto;
if ((howto & RB_NOSYNC) == 0 && (waittime < 0)) {
waittime = 0;
vfs_shutdown();
}
splhigh();
if (howto & RB_DUMP)
dumpsys();
haltsys:
doshutdownhooks();
pmf_system_shutdown(boothowto);
if (howto & 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("rebooting...\n\n");
delay(500000);
*(volatile char *)MIPS_PHYS_TO_KSEG1(LED_ADDR) = LED_RESET;
printf("WARNING: reboot failed!\n");
for (;;)
;
}
void
decode_bootstring(void)
{
char *work;
char *equ;
int i;
work = strtok_light(bootstring, ' ');
while (work != NULL) {
if (work[0] == '-') {
i = 1;
while (work[i] != ' ' && work[i] != '\0') {
BOOT_FLAG(work[i], boothowto);
i++;
}
} else
if ((equ = strchr(work, '=')) != NULL) {
if (memcmp("nfsroot=", work, 8) == 0) {
nfsroot_bstr = (equ + 1);
} else
if (memcmp("root=", work, 5) == 0) {
root_bstr = (equ + 1);
}
} else
if (memcmp("single", work, 5) == 0) {
boothowto |= RB_SINGLE;
} else
if (memcmp("ro", work, 2) == 0) {
}
work = strtok_light(NULL, ' ');
}
if (root_bstr != NULL) {
if ((memcmp("/dev/hd", root_bstr, 7) == 0) &&
(strlen(root_bstr) == 9) ){
bootunit = root_bstr[7] - 'a';
bootpart = root_bstr[8] - '1';
}
}
if (nfsroot_bstr != NULL)
netboot = 1;
}
static char *
strtok_light(char *str, const char sep)
{
static char *proc;
char *head;
char *work;
if (str != NULL)
proc = str;
if (proc == NULL)
return proc;
head = proc;
work = strchr(proc, sep);
if (work == NULL) {
proc = work;
} else {
proc = (work + 1);
*work = '\0';
}
return head;
}
void *
lookup_bootinfo(unsigned int type)
{
struct btinfo_common *bt;
char *help = bootinfo;
if (help == NULL) {
printf("##### help == NULL\n");
return NULL;
}
do {
bt = (struct btinfo_common *)help;
printf("Type %d @%p\n", bt->type, (void *)(intptr_t)bt);
if (bt->type == type)
return (void *)help;
help += bt->next;
} while (bt->next != 0 &&
(uintptr_t)help < (uintptr_t)bootinfo + BOOTINFO_SIZE);
return NULL;
}
static u_int
read_board_id(void)
{
volatile uint32_t *pcicfg_addr, *pcicfg_data;
uint32_t reg;
#define PCIB_PCI_BUS 0
#define PCIB_PCI_DEV 9
#define PCIB_PCI_FUNC 0
#define PCIB_BOARD_ID_REG 0x94
#define COBALT_BOARD_ID(reg) ((reg & 0x000000f0) >> 4)
pcicfg_addr = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_ADDR);
pcicfg_data = (uint32_t *)MIPS_PHYS_TO_KSEG1(GT_BASE + GT_PCICFG_DATA);
*pcicfg_addr = PCICFG_ENABLE |
(PCIB_PCI_BUS << 16) | (PCIB_PCI_DEV << 11) | (PCIB_PCI_FUNC << 8) |
PCIB_BOARD_ID_REG;
reg = *pcicfg_data;
*pcicfg_addr = 0;
return COBALT_BOARD_ID(reg);
}