#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/disp.h>
#include <sys/promif.h>
#include <sys/clock.h>
#include <sys/cpuvar.h>
#include <sys/stack.h>
#include <vm/as.h>
#include <vm/hat.h>
#include <sys/reboot.h>
#include <sys/avintr.h>
#include <sys/vtrace.h>
#include <sys/proc.h>
#include <sys/thread.h>
#include <sys/cpupart.h>
#include <sys/pset.h>
#include <sys/copyops.h>
#include <sys/pg.h>
#include <sys/disp.h>
#include <sys/debug.h>
#include <sys/sunddi.h>
#include <sys/x86_archext.h>
#include <sys/privregs.h>
#include <sys/machsystm.h>
#include <sys/ontrap.h>
#include <sys/bootconf.h>
#include <sys/boot_console.h>
#include <sys/kdi_machimpl.h>
#include <sys/archsystm.h>
#include <sys/promif.h>
#include <sys/pci_cfgspace.h>
#include <sys/apic.h>
#include <sys/apic_common.h>
#include <sys/bootvfs.h>
#include <sys/tsc.h>
#include <sys/smt.h>
#ifdef __xpv
#include <sys/hypervisor.h>
#else
#include <sys/xpv_support.h>
#endif
extern uint32_t cpuid_feature_ecx_include;
extern uint32_t cpuid_feature_ecx_exclude;
extern uint32_t cpuid_feature_edx_include;
extern uint32_t cpuid_feature_edx_exclude;
nmi_action_t nmi_action = NMI_ACTION_UNSET;
static void
set_console_mode(uint8_t val)
{
struct bop_regs rp = {0};
rp.eax.byte.ah = 0x0;
rp.eax.byte.al = val;
rp.ebx.word.bx = 0x0;
BOP_DOINT(bootops, 0x10, &rp);
}
void
mlsetup(struct regs *rp)
{
u_longlong_t prop_value;
char prop_str[BP_MAX_STRLEN];
extern struct classfuncs sys_classfuncs;
extern disp_t cpu0_disp;
extern char t0stack[];
extern int post_fastreboot;
extern uint64_t plat_dr_options;
ASSERT_STACK_ALIGNED();
cpu[0]->cpu_self = cpu[0];
#if defined(__xpv)
cpu[0]->cpu_m.mcpu_vcpu_info = &HYPERVISOR_shared_info->vcpu_info[0];
#endif
if (bootprop_getval("cpuid_feature_ecx_include", &prop_value) != 0)
cpuid_feature_ecx_include = 0;
else
cpuid_feature_ecx_include = (uint32_t)prop_value;
if (bootprop_getval("cpuid_feature_ecx_exclude", &prop_value) != 0)
cpuid_feature_ecx_exclude = 0;
else
cpuid_feature_ecx_exclude = (uint32_t)prop_value;
if (bootprop_getval("cpuid_feature_edx_include", &prop_value) != 0)
cpuid_feature_edx_include = 0;
else
cpuid_feature_edx_include = (uint32_t)prop_value;
if (bootprop_getval("cpuid_feature_edx_exclude", &prop_value) != 0)
cpuid_feature_edx_exclude = 0;
else
cpuid_feature_edx_exclude = (uint32_t)prop_value;
#if !defined(__xpv)
if (bootprop_getstr("nmi", prop_str, sizeof (prop_str)) == 0) {
if (strcmp(prop_str, "ignore") == 0) {
nmi_action = NMI_ACTION_IGNORE;
} else if (strcmp(prop_str, "panic") == 0) {
nmi_action = NMI_ACTION_PANIC;
} else if (strcmp(prop_str, "kmdb") == 0) {
nmi_action = NMI_ACTION_KMDB;
} else {
prom_printf("unix: ignoring unknown nmi=%s\n",
prop_str);
}
}
if (bootprop_getval("kpti", &prop_value) == 0) {
kpti_enable = (uint64_t)(prop_value == 1);
prom_printf("unix: forcing kpti to %s due to boot argument\n",
(kpti_enable == 1) ? "ON" : "OFF");
} else {
kpti_enable = 1;
}
if (bootprop_getval("pcid", &prop_value) == 0 && prop_value == 0) {
prom_printf("unix: forcing pcid to OFF due to boot argument\n");
x86_use_pcid = 0;
} else if (kpti_enable != 1) {
x86_use_pcid = 0;
}
if (bootprop_getstr("smt_enabled", prop_str, sizeof (prop_str)) == 0) {
if (strcasecmp(prop_str, "false") == 0 ||
strcmp(prop_str, "0") == 0)
smt_boot_disable = 1;
}
#endif
init_desctbls();
t0.t_stk = (caddr_t)rp - MINFRAME;
t0.t_stkbase = t0stack;
t0.t_pri = maxclsyspri - 3;
t0.t_schedflag = TS_LOAD | TS_DONT_SWAP;
t0.t_procp = &p0;
t0.t_plockp = &p0lock.pl_lock;
t0.t_lwp = &lwp0;
t0.t_forw = &t0;
t0.t_back = &t0;
t0.t_next = &t0;
t0.t_prev = &t0;
t0.t_cpu = cpu[0];
t0.t_disp_queue = &cpu0_disp;
t0.t_bind_cpu = PBIND_NONE;
t0.t_bind_pset = PS_NONE;
t0.t_bindflag = (uchar_t)default_binding_mode;
t0.t_cpupart = &cp_default;
t0.t_clfuncs = &sys_classfuncs.thread;
t0.t_copyops = NULL;
THREAD_ONPROC(&t0, CPU);
lwp0.lwp_thread = &t0;
lwp0.lwp_regs = (void *)rp;
lwp0.lwp_procp = &p0;
t0.t_tid = p0.p_lwpcnt = p0.p_lwprcnt = p0.p_lwpid = 1;
p0.p_exec = NULL;
p0.p_stat = SRUN;
p0.p_flag = SSYS;
p0.p_tlist = &t0;
p0.p_stksize = 2*PAGESIZE;
p0.p_stkpageszc = 0;
p0.p_as = &kas;
p0.p_lockp = &p0lock;
p0.p_brkpageszc = 0;
p0.p_t1_lgrpid = LGRP_NONE;
p0.p_tr_lgrpid = LGRP_NONE;
psecflags_default(&p0.p_secflags);
sigorset(&p0.p_ignore, &ignoredefault);
CPU->cpu_thread = &t0;
bzero(&cpu0_disp, sizeof (disp_t));
CPU->cpu_disp = &cpu0_disp;
CPU->cpu_disp->disp_cpu = CPU;
CPU->cpu_dispthread = &t0;
CPU->cpu_idle_thread = &t0;
CPU->cpu_flags = CPU_READY | CPU_RUNNING | CPU_EXISTS | CPU_ENABLE;
CPU->cpu_dispatch_pri = t0.t_pri;
CPU->cpu_id = 0;
CPU->cpu_pri = 12;
cpuid_execpass(cpu[0], CPUID_PASS_PRELUDE, x86_featureset);
#if defined(__xpv)
if (DOMAIN_IS_INITDOMAIN(xen_info))
pci_cfgspace_init();
#else
pci_cfgspace_init();
determine_platform();
#endif
cpuid_execpass(cpu[0], CPUID_PASS_IDENT, NULL);
ucode_init();
ucode_check_boot();
cpuid_execpass(cpu[0], CPUID_PASS_BASIC, x86_featureset);
#if !defined(__xpv)
if ((get_hwenv() & HW_XEN_HVM) != 0)
xen_hvm_init();
if (get_hwenv() == HW_NATIVE &&
cpuid_getvendor(CPU) == X86_VENDOR_Intel &&
cpuid_getfamily(CPU) == 6 &&
(cpuid_getmodel(CPU) == 0x2d || cpuid_getmodel(CPU) == 0x3e) &&
is_x86_feature(x86_featureset, X86FSET_TSC)) {
(void) wrmsr(REG_TSC, 0UL);
}
if ((get_hwenv() & HW_XEN_HVM) == 0 &&
is_x86_feature(x86_featureset, X86FSET_TSCP)) {
patch_tsc_read(TSC_TSCP);
} else if (is_x86_feature(x86_featureset, X86FSET_LFENCE_SER)) {
ASSERT(is_x86_feature(x86_featureset, X86FSET_SSE2));
patch_tsc_read(TSC_RDTSC_LFENCE);
}
#endif
#if !defined(__xpv)
patch_memops(cpuid_getvendor(CPU));
#endif
#if !defined(__xpv)
if (is_x86_feature(x86_featureset, X86FSET_TSC))
setcr4(getcr4() & ~CR4_TSD);
if (is_x86_feature(x86_featureset, X86FSET_TSCP))
(void) wrmsr(MSR_AMD_TSCAUX, 0);
if (is_x86_feature(x86_featureset, X86FSET_DE))
setcr4(getcr4() | CR4_DE);
if (is_x86_feature(x86_featureset, X86FSET_SMEP))
setcr4(getcr4() | CR4_SMEP);
#endif
init_mstate(&t0, LMS_SYSTEM);
init_cpu_mstate(CPU, CMS_SYSTEM);
cpu_list_init(CPU);
pg_cpu_bootstrap(CPU);
if (boothowto & RB_DEBUG)
kdi_idt_sync();
if (BOP_GETPROPLEN(bootops, "efi-systab") < 0) {
if (post_fastreboot &&
boot_console_type(NULL) == CONS_SCREEN_TEXT) {
set_console_mode(0x3);
}
}
if (boothowto & RB_DEBUGENTER)
kmdb_enter();
cpu_vm_data_init(CPU);
rp->r_fp = 0;
prom_init("kernel", (void *)NULL);
if (bootprop_getval(PLAT_DR_OPTIONS_NAME, &prop_value) == 0) {
plat_dr_options = (uint64_t)prop_value;
}
#if defined(__xpv)
plat_dr_options = 0;
#else
plat_dr_options &= ~PLAT_DR_FEATURE_ENABLED;
#endif
if (bootprop_getval(PLAT_DR_PHYSMAX_NAME, &prop_value) == 0) {
plat_dr_physmax = ((uint64_t)prop_value) >> PAGESHIFT;
}
if (bootprop_getval(BOOT_NCPUS_NAME, &prop_value) != 0) {
boot_ncpus = NCPU;
} else {
boot_ncpus = (int)prop_value;
if (boot_ncpus <= 0 || boot_ncpus > NCPU)
boot_ncpus = NCPU;
}
if (plat_dr_support_cpu() == 0) {
max_ncpus = boot_max_ncpus = boot_ncpus;
} else {
if (bootprop_getval(PLAT_MAX_NCPUS_NAME, &prop_value) != 0) {
max_ncpus = NCPU;
} else {
max_ncpus = (int)prop_value;
if (max_ncpus <= 0 || max_ncpus > NCPU) {
max_ncpus = NCPU;
}
if (boot_ncpus > max_ncpus) {
boot_ncpus = max_ncpus;
}
}
if (bootprop_getval(BOOT_MAX_NCPUS_NAME, &prop_value) != 0) {
boot_max_ncpus = boot_ncpus;
} else {
boot_max_ncpus = (int)prop_value;
if (boot_max_ncpus <= 0 || boot_max_ncpus > NCPU) {
boot_max_ncpus = boot_ncpus;
} else if (boot_max_ncpus > max_ncpus) {
boot_max_ncpus = max_ncpus;
}
}
}
lgrp_init(LGRP_INIT_STAGE1);
if (boothowto & RB_HALT) {
prom_printf("unix: kernel halted by -h flag\n");
prom_enter_mon();
}
ASSERT_STACK_ALIGNED();
if (workaround_errata(CPU) != 0)
panic("critical workaround(s) missing for boot cpu");
}
void
mach_modpath(char *path, const char *filename)
{
int len;
char *p;
const char isastr[] = "/amd64";
size_t isalen = strlen(isastr);
len = strlen(SYSTEM_BOOT_PATH "/kernel");
(void) strcpy(path, SYSTEM_BOOT_PATH "/kernel ");
path += len + 1;
if ((p = strrchr(filename, '/')) == NULL)
return;
while (p > filename && *(p - 1) == '/')
p--;
if (p == filename)
p++;
len = p - filename;
if (len > isalen &&
strncmp(&filename[len - isalen], isastr, isalen) == 0)
p -= isalen;
len += (p - filename) + 1 + strlen(MOD_DEFPATH) + 1;
(void) strncpy(path, filename, p - filename);
}