mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-05 09:14:03 +00:00
Clean up some low level bootstrap code:
- stop using the evil 'struct trapframe' argument for mi_startup() (formerly main()). There are much better ways of doing it. - do not use prepare_usermode() - setregs() in execve() will do it all for us as long as the p_md.md_regs pointer is set. (which is now done in machdep.c rather than init_main.c. The Alpha port did it this way all along and is much cleaner). - collect all the magic %cr0 etc register settings into one place and have the AP's call that instead of using magic numbers (!!) that keep changing over and over again. - Make it safe to call kthread_create() earlier, including during the device probe sequence. It doesn't need the callback mechanism that NetBSD's version uses. - kthreads created this way are root-less as they exist before the root filesystem is mounted. init(1) is set up so that it aquires the root pointers prior to running. If other kthreads want filesystem acccess we can make this code more generic. - set all threads start times once we have decided what time it is. - init uses a trampoline rather than the evil prepare_usermode() hack. - kern_descrip.c has a couple of tweaks to deal with forking when there is no rootdir or cwd etc. - adjust the early SYSINIT() sequence so that a few prereqisites are in place. eg: make sure the run queue is initialized before doing forks. With this, the USB code can easily create a kthread to do the device tree discovery. (I have tested it, it works nicely). There are still some open issues before this is truely useful. - tsleep() does not like working before the clock is running. It sort-of tries to spin wait, but it can do more useful things now. - stopping a kthread in kld code at unload time is "interesting" but we have a solution for that. The Alpha code needs no changes for this. It already uses pretty much the same strategies, but a little cleaner.
This commit is contained in:
parent
c47f9a08fc
commit
37b087a645
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64529
@ -361,55 +361,10 @@ begin:
|
||||
call _init386 /* wire 386 chip for unix operation */
|
||||
popl %esi
|
||||
|
||||
.globl __ucodesel,__udatasel
|
||||
|
||||
pushl $0 /* unused */
|
||||
pushl __udatasel /* ss */
|
||||
pushl $0 /* esp - filled in by execve() */
|
||||
pushl $PSL_USER /* eflags (IOPL 0, int enab) */
|
||||
pushl __ucodesel /* cs */
|
||||
pushl $0 /* eip - filled in by execve() */
|
||||
subl $(13*4),%esp /* space for rest of registers */
|
||||
|
||||
pushl %esp /* call main with frame pointer */
|
||||
call _mi_startup /* autoconfiguration, mountroot etc */
|
||||
|
||||
hlt /* never returns to here */
|
||||
|
||||
/*
|
||||
* When starting init, call this to configure the process for user
|
||||
* mode. This will be inherited by other processes.
|
||||
*/
|
||||
NON_GPROF_ENTRY(prepare_usermode)
|
||||
/*
|
||||
* Now we've run main() and determined what cpu-type we are, we can
|
||||
* enable write protection and alignment checking on i486 cpus and
|
||||
* above.
|
||||
*/
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
cmpl $CPUCLASS_386,_cpu_class
|
||||
je 1f
|
||||
movl %cr0,%eax /* get control word */
|
||||
orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
|
||||
movl %eax,%cr0 /* and do it */
|
||||
1:
|
||||
#endif
|
||||
/*
|
||||
* on return from main(), we are process 1
|
||||
* set up address space and stack so that we can 'return' to user mode
|
||||
*/
|
||||
movl __ucodesel,%eax
|
||||
movl __udatasel,%ecx
|
||||
|
||||
#if 0 /* ds/es/fs are in trap frame */
|
||||
mov %cx,%ds
|
||||
mov %cx,%es
|
||||
mov %cx,%fs
|
||||
#endif
|
||||
mov %cx,%gs /* and ds to gs */
|
||||
ret /* goto user! */
|
||||
|
||||
|
||||
/*
|
||||
* Signal trampoline, copied to top of user stack
|
||||
*/
|
||||
|
@ -361,55 +361,10 @@ begin:
|
||||
call _init386 /* wire 386 chip for unix operation */
|
||||
popl %esi
|
||||
|
||||
.globl __ucodesel,__udatasel
|
||||
|
||||
pushl $0 /* unused */
|
||||
pushl __udatasel /* ss */
|
||||
pushl $0 /* esp - filled in by execve() */
|
||||
pushl $PSL_USER /* eflags (IOPL 0, int enab) */
|
||||
pushl __ucodesel /* cs */
|
||||
pushl $0 /* eip - filled in by execve() */
|
||||
subl $(13*4),%esp /* space for rest of registers */
|
||||
|
||||
pushl %esp /* call main with frame pointer */
|
||||
call _mi_startup /* autoconfiguration, mountroot etc */
|
||||
|
||||
hlt /* never returns to here */
|
||||
|
||||
/*
|
||||
* When starting init, call this to configure the process for user
|
||||
* mode. This will be inherited by other processes.
|
||||
*/
|
||||
NON_GPROF_ENTRY(prepare_usermode)
|
||||
/*
|
||||
* Now we've run main() and determined what cpu-type we are, we can
|
||||
* enable write protection and alignment checking on i486 cpus and
|
||||
* above.
|
||||
*/
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
cmpl $CPUCLASS_386,_cpu_class
|
||||
je 1f
|
||||
movl %cr0,%eax /* get control word */
|
||||
orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
|
||||
movl %eax,%cr0 /* and do it */
|
||||
1:
|
||||
#endif
|
||||
/*
|
||||
* on return from main(), we are process 1
|
||||
* set up address space and stack so that we can 'return' to user mode
|
||||
*/
|
||||
movl __ucodesel,%eax
|
||||
movl __udatasel,%ecx
|
||||
|
||||
#if 0 /* ds/es/fs are in trap frame */
|
||||
mov %cx,%ds
|
||||
mov %cx,%es
|
||||
mov %cx,%fs
|
||||
#endif
|
||||
mov %cx,%gs /* and ds to gs */
|
||||
ret /* goto user! */
|
||||
|
||||
|
||||
/*
|
||||
* Signal trampoline, copied to top of user stack
|
||||
*/
|
||||
|
@ -240,6 +240,7 @@ vm_offset_t phys_avail[10];
|
||||
static vm_offset_t buffer_sva, buffer_eva;
|
||||
vm_offset_t clean_sva, clean_eva;
|
||||
static vm_offset_t pager_sva, pager_eva;
|
||||
static struct trapframe proc0_tf;
|
||||
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
@ -434,6 +435,7 @@ cpu_startup(dummy)
|
||||
mp_start(); /* fire up the APs and APICs */
|
||||
mp_announce();
|
||||
#endif /* SMP */
|
||||
cpu_setregs();
|
||||
}
|
||||
|
||||
int
|
||||
@ -1077,6 +1079,22 @@ setregs(p, entry, stack, ps_strings)
|
||||
p->p_retval[1] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_setregs(void)
|
||||
{
|
||||
unsigned int cr0;
|
||||
|
||||
cr0 = rcr0();
|
||||
cr0 |= CR0_NE; /* Done by npxinit() */
|
||||
cr0 |= CR0_MP | CR0_TS; /* Done at every execve() too. */
|
||||
#ifdef I386_CPU
|
||||
if (cpu_class != CPUCLASS_386)
|
||||
#endif
|
||||
cr0 |= CR0_WP | CR0_AM;
|
||||
load_cr0(cr0);
|
||||
load_gs(_udatasel);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
@ -1981,6 +1999,7 @@ init386(first)
|
||||
proc0.p_addr->u_pcb.pcb_mpnest = 1;
|
||||
#endif
|
||||
proc0.p_addr->u_pcb.pcb_ext = 0;
|
||||
proc0.p_md.md_regs = &proc0_tf;
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -92,6 +92,7 @@ static void cpu_reset_proxy __P((void));
|
||||
static u_int cpu_reset_proxyid;
|
||||
static volatile u_int cpu_reset_proxy_active;
|
||||
#endif
|
||||
extern int _ucodesel, _udatasel;
|
||||
|
||||
/*
|
||||
* quick version of vm_fault
|
||||
@ -156,18 +157,18 @@ cpu_fork(p1, p2, flags)
|
||||
*/
|
||||
p2->p_md.md_regs = (struct trapframe *)
|
||||
((int)p2->p_addr + UPAGES * PAGE_SIZE - 16) - 1;
|
||||
*p2->p_md.md_regs = *p1->p_md.md_regs;
|
||||
bcopy(p1->p_md.md_regs, p2->p_md.md_regs, sizeof(*p2->p_md.md_regs));
|
||||
|
||||
/*
|
||||
* Set registers for trampoline to user mode. Leave space for the
|
||||
* return address on stack. These are the kernel mode register values.
|
||||
*/
|
||||
pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pdir);
|
||||
pcb2->pcb_edi = p2->p_md.md_regs->tf_edi;
|
||||
pcb2->pcb_esi = (int)fork_return;
|
||||
pcb2->pcb_ebp = p2->p_md.md_regs->tf_ebp;
|
||||
pcb2->pcb_edi = 0;
|
||||
pcb2->pcb_esi = (int)fork_return; /* fork_trampoline argument */
|
||||
pcb2->pcb_ebp = 0;
|
||||
pcb2->pcb_esp = (int)p2->p_md.md_regs - sizeof(void *);
|
||||
pcb2->pcb_ebx = (int)p2;
|
||||
pcb2->pcb_ebx = (int)p2; /* fork_trampoline argument */
|
||||
pcb2->pcb_eip = (int)fork_trampoline;
|
||||
/*
|
||||
* pcb2->pcb_ldt: duplicated below, if necessary.
|
||||
@ -200,8 +201,8 @@ cpu_fork(p1, p2, flags)
|
||||
* Now, cpu_switch() can schedule the new process.
|
||||
* pcb_esp is loaded pointing to the cpu_switch() stack frame
|
||||
* containing the return address when exiting cpu_switch.
|
||||
* This will normally be to proc_trampoline(), which will have
|
||||
* %ebx loaded with the new proc's pointer. proc_trampoline()
|
||||
* This will normally be to fork_trampoline(), which will have
|
||||
* %ebx loaded with the new proc's pointer. fork_trampoline()
|
||||
* will set up a stack to call fork_return(p, frame); to complete
|
||||
* the return to user-mode.
|
||||
*/
|
||||
|
@ -56,7 +56,6 @@
|
||||
#define cpu_exec(p) /* nothing */
|
||||
#define cpu_swapin(p) /* nothing */
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs[SP] = (ap))
|
||||
#define cpu_set_init_frame(p, fp) ((p)->p_md.md_regs = (fp))
|
||||
|
||||
#define CLKF_USERMODE(framep) \
|
||||
((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM))
|
||||
|
@ -70,6 +70,7 @@ void bcopyb __P((const void *from, void *to, size_t len));
|
||||
void busdma_swi __P((void));
|
||||
void cpu_halt __P((void));
|
||||
void cpu_reset __P((void));
|
||||
void cpu_setregs __P((void));
|
||||
void cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs));
|
||||
void doreti_iret __P((void)) __asm(__STRING(doreti_iret));
|
||||
void doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault));
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -361,55 +361,10 @@ begin:
|
||||
call _init386 /* wire 386 chip for unix operation */
|
||||
popl %esi
|
||||
|
||||
.globl __ucodesel,__udatasel
|
||||
|
||||
pushl $0 /* unused */
|
||||
pushl __udatasel /* ss */
|
||||
pushl $0 /* esp - filled in by execve() */
|
||||
pushl $PSL_USER /* eflags (IOPL 0, int enab) */
|
||||
pushl __ucodesel /* cs */
|
||||
pushl $0 /* eip - filled in by execve() */
|
||||
subl $(13*4),%esp /* space for rest of registers */
|
||||
|
||||
pushl %esp /* call main with frame pointer */
|
||||
call _mi_startup /* autoconfiguration, mountroot etc */
|
||||
|
||||
hlt /* never returns to here */
|
||||
|
||||
/*
|
||||
* When starting init, call this to configure the process for user
|
||||
* mode. This will be inherited by other processes.
|
||||
*/
|
||||
NON_GPROF_ENTRY(prepare_usermode)
|
||||
/*
|
||||
* Now we've run main() and determined what cpu-type we are, we can
|
||||
* enable write protection and alignment checking on i486 cpus and
|
||||
* above.
|
||||
*/
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
cmpl $CPUCLASS_386,_cpu_class
|
||||
je 1f
|
||||
movl %cr0,%eax /* get control word */
|
||||
orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
|
||||
movl %eax,%cr0 /* and do it */
|
||||
1:
|
||||
#endif
|
||||
/*
|
||||
* on return from main(), we are process 1
|
||||
* set up address space and stack so that we can 'return' to user mode
|
||||
*/
|
||||
movl __ucodesel,%eax
|
||||
movl __udatasel,%ecx
|
||||
|
||||
#if 0 /* ds/es/fs are in trap frame */
|
||||
mov %cx,%ds
|
||||
mov %cx,%es
|
||||
mov %cx,%fs
|
||||
#endif
|
||||
mov %cx,%gs /* and ds to gs */
|
||||
ret /* goto user! */
|
||||
|
||||
|
||||
/*
|
||||
* Signal trampoline, copied to top of user stack
|
||||
*/
|
||||
|
@ -240,6 +240,7 @@ vm_offset_t phys_avail[10];
|
||||
static vm_offset_t buffer_sva, buffer_eva;
|
||||
vm_offset_t clean_sva, clean_eva;
|
||||
static vm_offset_t pager_sva, pager_eva;
|
||||
static struct trapframe proc0_tf;
|
||||
|
||||
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
|
||||
|
||||
@ -434,6 +435,7 @@ cpu_startup(dummy)
|
||||
mp_start(); /* fire up the APs and APICs */
|
||||
mp_announce();
|
||||
#endif /* SMP */
|
||||
cpu_setregs();
|
||||
}
|
||||
|
||||
int
|
||||
@ -1077,6 +1079,22 @@ setregs(p, entry, stack, ps_strings)
|
||||
p->p_retval[1] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_setregs(void)
|
||||
{
|
||||
unsigned int cr0;
|
||||
|
||||
cr0 = rcr0();
|
||||
cr0 |= CR0_NE; /* Done by npxinit() */
|
||||
cr0 |= CR0_MP | CR0_TS; /* Done at every execve() too. */
|
||||
#ifdef I386_CPU
|
||||
if (cpu_class != CPUCLASS_386)
|
||||
#endif
|
||||
cr0 |= CR0_WP | CR0_AM;
|
||||
load_cr0(cr0);
|
||||
load_gs(_udatasel);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
@ -1981,6 +1999,7 @@ init386(first)
|
||||
proc0.p_addr->u_pcb.pcb_mpnest = 1;
|
||||
#endif
|
||||
proc0.p_addr->u_pcb.pcb_ext = 0;
|
||||
proc0.p_md.md_regs = &proc0_tf;
|
||||
}
|
||||
|
||||
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -92,6 +92,7 @@ static void cpu_reset_proxy __P((void));
|
||||
static u_int cpu_reset_proxyid;
|
||||
static volatile u_int cpu_reset_proxy_active;
|
||||
#endif
|
||||
extern int _ucodesel, _udatasel;
|
||||
|
||||
/*
|
||||
* quick version of vm_fault
|
||||
@ -156,18 +157,18 @@ cpu_fork(p1, p2, flags)
|
||||
*/
|
||||
p2->p_md.md_regs = (struct trapframe *)
|
||||
((int)p2->p_addr + UPAGES * PAGE_SIZE - 16) - 1;
|
||||
*p2->p_md.md_regs = *p1->p_md.md_regs;
|
||||
bcopy(p1->p_md.md_regs, p2->p_md.md_regs, sizeof(*p2->p_md.md_regs));
|
||||
|
||||
/*
|
||||
* Set registers for trampoline to user mode. Leave space for the
|
||||
* return address on stack. These are the kernel mode register values.
|
||||
*/
|
||||
pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pdir);
|
||||
pcb2->pcb_edi = p2->p_md.md_regs->tf_edi;
|
||||
pcb2->pcb_esi = (int)fork_return;
|
||||
pcb2->pcb_ebp = p2->p_md.md_regs->tf_ebp;
|
||||
pcb2->pcb_edi = 0;
|
||||
pcb2->pcb_esi = (int)fork_return; /* fork_trampoline argument */
|
||||
pcb2->pcb_ebp = 0;
|
||||
pcb2->pcb_esp = (int)p2->p_md.md_regs - sizeof(void *);
|
||||
pcb2->pcb_ebx = (int)p2;
|
||||
pcb2->pcb_ebx = (int)p2; /* fork_trampoline argument */
|
||||
pcb2->pcb_eip = (int)fork_trampoline;
|
||||
/*
|
||||
* pcb2->pcb_ldt: duplicated below, if necessary.
|
||||
@ -200,8 +201,8 @@ cpu_fork(p1, p2, flags)
|
||||
* Now, cpu_switch() can schedule the new process.
|
||||
* pcb_esp is loaded pointing to the cpu_switch() stack frame
|
||||
* containing the return address when exiting cpu_switch.
|
||||
* This will normally be to proc_trampoline(), which will have
|
||||
* %ebx loaded with the new proc's pointer. proc_trampoline()
|
||||
* This will normally be to fork_trampoline(), which will have
|
||||
* %ebx loaded with the new proc's pointer. fork_trampoline()
|
||||
* will set up a stack to call fork_return(p, frame); to complete
|
||||
* the return to user-mode.
|
||||
*/
|
||||
|
@ -56,7 +56,6 @@
|
||||
#define cpu_exec(p) /* nothing */
|
||||
#define cpu_swapin(p) /* nothing */
|
||||
#define cpu_setstack(p, ap) ((p)->p_md.md_regs[SP] = (ap))
|
||||
#define cpu_set_init_frame(p, fp) ((p)->p_md.md_regs = (fp))
|
||||
|
||||
#define CLKF_USERMODE(framep) \
|
||||
((ISPL((framep)->cf_cs) == SEL_UPL) || (framep->cf_eflags & PSL_VM))
|
||||
|
@ -70,6 +70,7 @@ void bcopyb __P((const void *from, void *to, size_t len));
|
||||
void busdma_swi __P((void));
|
||||
void cpu_halt __P((void));
|
||||
void cpu_reset __P((void));
|
||||
void cpu_setregs __P((void));
|
||||
void cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs));
|
||||
void doreti_iret __P((void)) __asm(__STRING(doreti_iret));
|
||||
void doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault));
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
@ -74,7 +74,7 @@
|
||||
|
||||
extern struct linker_set sysinit_set; /* XXX */
|
||||
|
||||
extern void mi_startup __P((void *framep));
|
||||
void mi_startup(void); /* Should be elsewhere */
|
||||
|
||||
/* Components of the first process -- never freed. */
|
||||
static struct session session0;
|
||||
@ -94,20 +94,12 @@ struct vnode *rootvp;
|
||||
int boothowto = 0; /* initialized so that it can be patched */
|
||||
SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "");
|
||||
|
||||
/*
|
||||
* Promiscuous argument pass for start_init()
|
||||
*
|
||||
* This is a kludge because we use a return from mi_startup() rather than a call
|
||||
* to a new routine in locore.s to kick the kernel alive from locore.s.
|
||||
*/
|
||||
static void *init_framep;
|
||||
|
||||
/*
|
||||
* This ensures that there is at least one entry so that the sysinit_set
|
||||
* symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never
|
||||
* executed.
|
||||
*/
|
||||
SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL)
|
||||
SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
|
||||
|
||||
/*
|
||||
* The sysinit table itself. Items are checked off as the are run.
|
||||
@ -121,8 +113,7 @@ struct sysinit **newsysinit;
|
||||
* necessary. This can only be called after malloc is running.
|
||||
*/
|
||||
void
|
||||
sysinit_add(set)
|
||||
struct sysinit **set;
|
||||
sysinit_add(struct sysinit **set)
|
||||
{
|
||||
struct sysinit **newset;
|
||||
struct sysinit **sipp;
|
||||
@ -168,20 +159,13 @@ sysinit_add(set)
|
||||
* module. Finally, it allows for optional "kernel threads".
|
||||
*/
|
||||
void
|
||||
mi_startup(framep)
|
||||
void *framep;
|
||||
mi_startup(void)
|
||||
{
|
||||
|
||||
register struct sysinit **sipp; /* system initialization*/
|
||||
register struct sysinit **xipp; /* interior loop of sort*/
|
||||
register struct sysinit *save; /* bubble*/
|
||||
|
||||
/*
|
||||
* Copy the locore.s frame pointer for proc0, this is forked into
|
||||
* all other processes.
|
||||
*/
|
||||
init_framep = framep;
|
||||
|
||||
restart:
|
||||
/*
|
||||
* Perform a bubble sort of the system initialization objects by
|
||||
@ -243,10 +227,8 @@ mi_startup(framep)
|
||||
****
|
||||
***************************************************************************
|
||||
*/
|
||||
static void print_caddr_t __P((void *data));
|
||||
static void
|
||||
print_caddr_t(data)
|
||||
void *data;
|
||||
print_caddr_t(void *data __unused)
|
||||
{
|
||||
printf("%s", (char *)data);
|
||||
}
|
||||
@ -267,10 +249,8 @@ SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
|
||||
***************************************************************************
|
||||
*/
|
||||
/* ARGSUSED*/
|
||||
static void proc0_init __P((void *dummy));
|
||||
static void
|
||||
proc0_init(dummy)
|
||||
void *dummy;
|
||||
proc0_init(void *dummy __unused)
|
||||
{
|
||||
register struct proc *p;
|
||||
register struct filedesc0 *fdp;
|
||||
@ -314,9 +294,6 @@ proc0_init(dummy)
|
||||
p->p_rtprio.type = RTP_PRIO_NORMAL;
|
||||
p->p_rtprio.prio = 0;
|
||||
|
||||
/*
|
||||
* Link for kernel based threads
|
||||
*/
|
||||
p->p_peers = 0;
|
||||
p->p_leader = p;
|
||||
|
||||
@ -335,6 +312,9 @@ proc0_init(dummy)
|
||||
p->p_procsig = &procsig0;
|
||||
p->p_procsig->ps_refcnt = 1;
|
||||
|
||||
/* Initialize signal state for process 0. */
|
||||
siginit(&proc0);
|
||||
|
||||
/* Create the file descriptor table. */
|
||||
fdp = &filedesc0;
|
||||
p->p_fd = &fdp->fd_fd;
|
||||
@ -360,7 +340,6 @@ proc0_init(dummy)
|
||||
limit0.p_cpulimit = RLIM_INFINITY;
|
||||
limit0.p_refcnt = 1;
|
||||
|
||||
|
||||
/* Allocate a prototype map so we have something to fork. */
|
||||
pmap_pinit0(vmspace_pmap(&vmspace0));
|
||||
p->p_vmspace = &vmspace0;
|
||||
@ -370,13 +349,6 @@ proc0_init(dummy)
|
||||
vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0);
|
||||
p->p_addr = proc0paddr; /* XXX */
|
||||
|
||||
#ifdef cpu_set_init_frame
|
||||
/*
|
||||
* proc0 needs to have a coherent frame base in its stack.
|
||||
*/
|
||||
cpu_set_init_frame(p, init_framep); /* XXX! */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We continue to place resource usage info and signal
|
||||
* actions in the user struct so they're pageable.
|
||||
@ -399,19 +371,20 @@ proc0_init(dummy)
|
||||
SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
|
||||
|
||||
/* ARGSUSED*/
|
||||
static void proc0_post __P((void *dummy));
|
||||
static void
|
||||
proc0_post(dummy)
|
||||
void *dummy;
|
||||
proc0_post(void *dummy __unused)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct proc *p;
|
||||
|
||||
/*
|
||||
* Now we can look at the time, having had a chance to verify the
|
||||
* time from the file system. Pretend that proc0 started now.
|
||||
*/
|
||||
microtime(&proc0.p_stats->p_start);
|
||||
proc0.p_runtime = 0;
|
||||
LIST_FOREACH(p, &allproc, p_list) {
|
||||
microtime(&p->p_stats->p_start);
|
||||
p->p_runtime = 0;
|
||||
}
|
||||
microuptime(&switchtime);
|
||||
switchticks = ticks;
|
||||
|
||||
@ -420,15 +393,9 @@ proc0_post(dummy)
|
||||
*/
|
||||
nanotime(&ts);
|
||||
srandom(ts.tv_sec ^ ts.tv_nsec);
|
||||
|
||||
/* Initialize signal state for process 0. */
|
||||
siginit(&proc0);
|
||||
}
|
||||
SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
***************************************************************************
|
||||
****
|
||||
@ -438,58 +405,16 @@ SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
/* ARGSUSED*/
|
||||
static void xxx_vfs_root_fdtab __P((void *dummy));
|
||||
static void
|
||||
xxx_vfs_root_fdtab(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
register struct filedesc0 *fdp = &filedesc0;
|
||||
|
||||
/* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */
|
||||
if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
|
||||
panic("cannot find root vnode");
|
||||
fdp->fd_fd.fd_cdir = rootvnode;
|
||||
VREF(fdp->fd_fd.fd_cdir);
|
||||
VOP_UNLOCK(rootvnode, 0, &proc0);
|
||||
fdp->fd_fd.fd_rdir = rootvnode;
|
||||
}
|
||||
SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL)
|
||||
|
||||
|
||||
/*
|
||||
***************************************************************************
|
||||
****
|
||||
**** The following code probably belongs in another file, like
|
||||
**** kern/init_init.c. It is here for two reasons only:
|
||||
****
|
||||
**** 1) This code returns to startup the system; this is
|
||||
**** abnormal for a kernel thread.
|
||||
**** 2) This code promiscuously uses init_frame
|
||||
**** kern/init_init.c.
|
||||
****
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
extern void prepare_usermode __P((void));
|
||||
static void create_init __P((const void *dummy));
|
||||
static void start_init __P((void *dummy));
|
||||
SYSINIT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, create_init, NULL)
|
||||
|
||||
/*
|
||||
* Like kthread_create(), but runs in it's own address space.
|
||||
*/
|
||||
static void
|
||||
create_init(udata)
|
||||
const void *udata;
|
||||
{
|
||||
int error;
|
||||
|
||||
error = fork1(&proc0, RFFDG | RFPROC, &initproc);
|
||||
if (error)
|
||||
panic("cannot fork init: %d\n", error);
|
||||
initproc->p_flag |= P_INMEM | P_SYSTEM;
|
||||
cpu_set_fork_handler(initproc, start_init, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* List of paths to try when searching for "init".
|
||||
@ -507,8 +432,7 @@ SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0, "");
|
||||
* The program is invoked with one argument containing the boot flags.
|
||||
*/
|
||||
static void
|
||||
start_init(dummy)
|
||||
void *dummy;
|
||||
start_init(void *dummy)
|
||||
{
|
||||
vm_offset_t addr;
|
||||
struct execve_args args;
|
||||
@ -519,6 +443,14 @@ start_init(dummy)
|
||||
|
||||
p = curproc;
|
||||
|
||||
/* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */
|
||||
if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
|
||||
panic("cannot find root vnode");
|
||||
p->p_fd->fd_cdir = rootvnode;
|
||||
VREF(p->p_fd->fd_cdir);
|
||||
p->p_fd->fd_rdir = rootvnode;
|
||||
VOP_UNLOCK(rootvnode, 0, p);
|
||||
|
||||
/*
|
||||
* Need just enough stack to hold the faked-up "execve()" arguments.
|
||||
*/
|
||||
@ -598,13 +530,11 @@ start_init(dummy)
|
||||
* Now try to exec the program. If can't for any reason
|
||||
* other than it doesn't exist, complain.
|
||||
*
|
||||
* Otherwise, return via the fork trampoline all the way
|
||||
* Otherwise, return via fork_trampoline() all the way
|
||||
* to user mode as init!
|
||||
*/
|
||||
if ((error = execve(p, &args)) == 0) {
|
||||
prepare_usermode();
|
||||
if ((error = execve(p, &args)) == 0)
|
||||
return;
|
||||
}
|
||||
if (error != ENOENT)
|
||||
printf("exec %.*s: error %d\n", (int)(next - path),
|
||||
path, error);
|
||||
@ -612,3 +542,37 @@ start_init(dummy)
|
||||
printf("init: not found in path %s\n", init_path);
|
||||
panic("no init");
|
||||
}
|
||||
|
||||
/*
|
||||
* Like kthread_create(), but runs in it's own address space.
|
||||
* We do this early to reserve pid 1.
|
||||
*
|
||||
* Note special case - do not make it runnable yet. Other work
|
||||
* in progress will change this more.
|
||||
*/
|
||||
static void
|
||||
create_init(const void *udata __unused)
|
||||
{
|
||||
int error;
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
error = fork1(&proc0, RFFDG | RFPROC, &initproc);
|
||||
if (error)
|
||||
panic("cannot fork init: %d\n", error);
|
||||
initproc->p_flag |= P_INMEM | P_SYSTEM;
|
||||
cpu_set_fork_handler(initproc, start_init, NULL);
|
||||
remrunqueue(initproc);
|
||||
splx(s);
|
||||
}
|
||||
SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)
|
||||
|
||||
/*
|
||||
* Make it runnable now.
|
||||
*/
|
||||
static void
|
||||
kick_init(const void *udata __unused)
|
||||
{
|
||||
setrunqueue(initproc);
|
||||
}
|
||||
SYSINIT(kickinit,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL)
|
||||
|
@ -820,9 +820,11 @@ fdinit(p)
|
||||
M_FILEDESC, M_WAITOK);
|
||||
bzero(newfdp, sizeof(struct filedesc0));
|
||||
newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
|
||||
VREF(newfdp->fd_fd.fd_cdir);
|
||||
if (newfdp->fd_fd.fd_cdir)
|
||||
VREF(newfdp->fd_fd.fd_cdir);
|
||||
newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
|
||||
VREF(newfdp->fd_fd.fd_rdir);
|
||||
if (newfdp->fd_fd.fd_rdir)
|
||||
VREF(newfdp->fd_fd.fd_rdir);
|
||||
newfdp->fd_fd.fd_jdir = fdp->fd_jdir;
|
||||
if (newfdp->fd_fd.fd_jdir)
|
||||
VREF(newfdp->fd_fd.fd_jdir);
|
||||
@ -867,8 +869,10 @@ fdcopy(p)
|
||||
MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
|
||||
M_FILEDESC, M_WAITOK);
|
||||
bcopy(fdp, newfdp, sizeof(struct filedesc));
|
||||
VREF(newfdp->fd_cdir);
|
||||
VREF(newfdp->fd_rdir);
|
||||
if (newfdp->fd_cdir)
|
||||
VREF(newfdp->fd_cdir);
|
||||
if (newfdp->fd_rdir)
|
||||
VREF(newfdp->fd_rdir);
|
||||
if (newfdp->fd_jdir)
|
||||
VREF(newfdp->fd_jdir);
|
||||
newfdp->fd_refcnt = 1;
|
||||
@ -945,8 +949,10 @@ fdfree(p)
|
||||
(void) closef(*fpp, p);
|
||||
if (fdp->fd_nfiles > NDFILE)
|
||||
FREE(fdp->fd_ofiles, M_FILEDESC);
|
||||
vrele(fdp->fd_cdir);
|
||||
vrele(fdp->fd_rdir);
|
||||
if (fdp->fd_cdir)
|
||||
vrele(fdp->fd_cdir);
|
||||
if (fdp->fd_rdir)
|
||||
vrele(fdp->fd_rdir);
|
||||
if (fdp->fd_jdir)
|
||||
vrele(fdp->fd_jdir);
|
||||
if (fdp->fd_knlist)
|
||||
|
@ -69,10 +69,6 @@ kthread_create(void (*func)(void *), void *arg,
|
||||
va_list ap;
|
||||
struct proc *p2;
|
||||
|
||||
if (!proc0.p_stats || proc0.p_stats->p_start.tv_sec == 0) {
|
||||
panic("kthread_create called too soon");
|
||||
}
|
||||
|
||||
error = fork1(&proc0, RFMEM | RFFDG | RFPROC, &p2);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -487,8 +487,6 @@ init_secondary(void)
|
||||
common_tssd = *tss_gdt;
|
||||
ltr(gsel_tss);
|
||||
|
||||
load_cr0(0x8005003b); /* XXX! */
|
||||
|
||||
pmap_set_opt();
|
||||
}
|
||||
|
||||
@ -623,13 +621,6 @@ mp_enable(u_int boot_addr)
|
||||
|
||||
/* start each Application Processor */
|
||||
start_all_aps(boot_addr);
|
||||
|
||||
/*
|
||||
* The init process might be started on a different CPU now,
|
||||
* and the boot CPU might not call prepare_usermode to get
|
||||
* cr0 correctly configured. Thus we initialize cr0 here.
|
||||
*/
|
||||
load_cr0(rcr0() | CR0_WP | CR0_AM);
|
||||
}
|
||||
|
||||
|
||||
@ -2375,8 +2366,8 @@ ap_init()
|
||||
|
||||
printf("SMP: AP CPU #%d Launched!\n", cpuid);
|
||||
|
||||
/* XXX FIXME: i386 specific, and redundant: Setup the FPU. */
|
||||
load_cr0((rcr0() & ~CR0_EM) | CR0_MP | CR0_NE | CR0_TS);
|
||||
/* set up CPU registers and state */
|
||||
cpu_setregs();
|
||||
|
||||
/* set up FPU state on the AP */
|
||||
npxinit(__INITIAL_NPXCW__);
|
||||
|
Loading…
Reference in New Issue
Block a user