minix/kernel/start.c

166 lines
4.5 KiB
C
Raw Normal View History

Split of architecture-dependent and -independent functions for i386, mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
2006-12-22 16:22:27 +01:00
/* First C file used by the kernel. */
2005-04-21 16:53:53 +02:00
#include "kernel.h"
2005-04-29 17:36:43 +02:00
#include "proc.h"
2005-07-19 17:01:47 +02:00
#include <stdlib.h>
#include <string.h>
#include "proto.h"
Split of architecture-dependent and -independent functions for i386, mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
2006-12-22 16:22:27 +01:00
NMI watchdog is an awesome feature for debugging locked up kernels. There is not that much use for it on a single CPU, however, deadlock between kernel and system task can be delected. Or a runaway loop. If a kernel gets locked up the timer interrupts don't occure (as all interrupts are disabled in kernel mode). The only chance is to interrupt the kernel by a non-maskable interrupt. This patch generates NMIs using performance counters. It uses the most widely available performace counters. As the performance counters are highly model-specific this patch is not guaranteed to work on every machine. Unfortunately this is also true for KVM :-/ On the other hand adding this feature for other models is not extremely difficult and the framework makes it hopefully easy enough. Depending on the frequency of the CPU an NMI is generated at most about every 0.5s If the cpu's speed is less then 2Ghz it is generated at most every 1s. In general an NMI is generated much less often as the performance counter counts down only if the cpu is not idle. Therefore the overhead of this feature is fairly minimal even if the load is high. Uppon detecting that the kernel is locked up the kernel dumps the state of the kernel registers and panics. Local APIC must be enabled for the watchdog to work. The code is _always_ compiled in, however, it is only enabled if watchdog=<non-zero> is set in the boot monitor. One corner case is serial console debugging. As dumping a lot of stuff to the serial link may take a lot of time, the watchdog does not detect lockups during this time!!! as it would result in too many false positives. 10 nmi have to be handled before the lockup is detected. This means something between ~5s to 10s. Another corner case is that the watchdog is enabled only after the paging is enabled as it would be pure madness to try to get it right.
2010-01-16 21:53:55 +01:00
#ifdef CONFIG_WATCHDOG
#include "watchdog.h"
#endif
2005-09-11 18:44:06 +02:00
/*===========================================================================*
* cstart *
*===========================================================================*/
PUBLIC void cstart(
u16_t cs, /* kernel code segment */
u16_t ds, /* kernel data segment */
u16_t mds, /* monitor data segment */
u16_t parmoff, /* boot parameters offset */
u16_t parmsize /* boot parameters length */
)
2005-04-21 16:53:53 +02:00
{
/* Perform system initializations prior to calling main(). Most settings are
* determined with help of the environment strings passed by MINIX' loader.
*/
register char *value; /* value in key=value pair */
2005-04-29 17:36:43 +02:00
extern int etext, end;
int h;
2005-04-29 17:36:43 +02:00
2005-04-21 16:53:53 +02:00
/* Record where the kernel and the monitor are. */
2005-04-29 17:36:43 +02:00
kinfo.code_base = seg2phys(cs);
kinfo.code_size = (phys_bytes) &etext; /* size of code segment */
kinfo.data_base = seg2phys(ds);
kinfo.data_size = (phys_bytes) &end; /* size of data segment */
2005-04-21 16:53:53 +02:00
/* protection initialization */
prot_init();
2005-04-21 16:53:53 +02:00
/* Copy the boot parameters to the local buffer. */
arch_get_params(params_buffer, sizeof(params_buffer));
2005-04-21 16:53:53 +02:00
/* determine verbosity */
if ((value = env_get(VERBOSEBOOTVARNAME)))
verboseboot = atoi(value);
DEBUGEXTRA(("cstart\n"));
2005-04-29 17:36:43 +02:00
/* Record miscellaneous information for user-space servers. */
kinfo.nr_procs = NR_PROCS;
kinfo.nr_tasks = NR_TASKS;
strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
kinfo.release[sizeof(kinfo.release)-1] = '\0';
strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
kinfo.version[sizeof(kinfo.version)-1] = '\0';
2005-04-29 17:36:43 +02:00
kinfo.proc_addr = (vir_bytes) proc;
2005-04-21 16:53:53 +02:00
/* Load average data initialization. */
kloadinfo.proc_last_slot = 0;
for(h = 0; h < _LOAD_HISTORY; h++)
kloadinfo.proc_load_history[h] = 0;
Split of architecture-dependent and -independent functions for i386, mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
2006-12-22 16:22:27 +01:00
/* Processor? Decide if mode is protected for older machines. */
machine.processor=atoi(env_get("processor"));
2005-04-21 16:53:53 +02:00
/* XT, AT or MCA bus? */
value = env_get("bus");
if (value == NULL || strcmp(value, "at") == 0) {
2005-04-29 17:36:43 +02:00
machine.pc_at = TRUE; /* PC-AT compatible hardware */
} else if (strcmp(value, "mca") == 0) {
2005-04-29 17:36:43 +02:00
machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */
2005-04-21 16:53:53 +02:00
}
2005-04-29 17:36:43 +02:00
/* Type of VDU: */
value = env_get("video"); /* EGA or VGA video unit */
if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
2005-04-29 17:36:43 +02:00
/* Get clock tick frequency. */
value = env_get("hz");
if(value)
system_hz = atoi(value);
if(!value || system_hz < 2 || system_hz > 50000) /* sanity check */
system_hz = DEFAULT_HZ;
/* Intitialize serial debugging */
value = env_get(SERVARNAME);
if(value && atoi(value) == 0) {
do_serial_debug=1;
value = env_get(SERBAUDVARNAME);
if (value) serial_debug_baud = atoi(value);
}
#ifdef CONFIG_APIC
value = env_get("no_apic");
if(value)
config_no_apic = atoi(value);
else
config_no_apic = 1;
value = env_get("apic_timer_x");
if(value)
config_apic_timer_x = atoi(value);
else
config_apic_timer_x = 1;
#endif
NMI watchdog is an awesome feature for debugging locked up kernels. There is not that much use for it on a single CPU, however, deadlock between kernel and system task can be delected. Or a runaway loop. If a kernel gets locked up the timer interrupts don't occure (as all interrupts are disabled in kernel mode). The only chance is to interrupt the kernel by a non-maskable interrupt. This patch generates NMIs using performance counters. It uses the most widely available performace counters. As the performance counters are highly model-specific this patch is not guaranteed to work on every machine. Unfortunately this is also true for KVM :-/ On the other hand adding this feature for other models is not extremely difficult and the framework makes it hopefully easy enough. Depending on the frequency of the CPU an NMI is generated at most about every 0.5s If the cpu's speed is less then 2Ghz it is generated at most every 1s. In general an NMI is generated much less often as the performance counter counts down only if the cpu is not idle. Therefore the overhead of this feature is fairly minimal even if the load is high. Uppon detecting that the kernel is locked up the kernel dumps the state of the kernel registers and panics. Local APIC must be enabled for the watchdog to work. The code is _always_ compiled in, however, it is only enabled if watchdog=<non-zero> is set in the boot monitor. One corner case is serial console debugging. As dumping a lot of stuff to the serial link may take a lot of time, the watchdog does not detect lockups during this time!!! as it would result in too many false positives. 10 nmi have to be handled before the lockup is detected. This means something between ~5s to 10s. Another corner case is that the watchdog is enabled only after the paging is enabled as it would be pure madness to try to get it right.
2010-01-16 21:53:55 +01:00
#ifdef CONFIG_WATCHDOG
value = env_get("watchdog");
NMI watchdog is an awesome feature for debugging locked up kernels. There is not that much use for it on a single CPU, however, deadlock between kernel and system task can be delected. Or a runaway loop. If a kernel gets locked up the timer interrupts don't occure (as all interrupts are disabled in kernel mode). The only chance is to interrupt the kernel by a non-maskable interrupt. This patch generates NMIs using performance counters. It uses the most widely available performace counters. As the performance counters are highly model-specific this patch is not guaranteed to work on every machine. Unfortunately this is also true for KVM :-/ On the other hand adding this feature for other models is not extremely difficult and the framework makes it hopefully easy enough. Depending on the frequency of the CPU an NMI is generated at most about every 0.5s If the cpu's speed is less then 2Ghz it is generated at most every 1s. In general an NMI is generated much less often as the performance counter counts down only if the cpu is not idle. Therefore the overhead of this feature is fairly minimal even if the load is high. Uppon detecting that the kernel is locked up the kernel dumps the state of the kernel registers and panics. Local APIC must be enabled for the watchdog to work. The code is _always_ compiled in, however, it is only enabled if watchdog=<non-zero> is set in the boot monitor. One corner case is serial console debugging. As dumping a lot of stuff to the serial link may take a lot of time, the watchdog does not detect lockups during this time!!! as it would result in too many false positives. 10 nmi have to be handled before the lockup is detected. This means something between ~5s to 10s. Another corner case is that the watchdog is enabled only after the paging is enabled as it would be pure madness to try to get it right.
2010-01-16 21:53:55 +01:00
if (value)
watchdog_enabled = atoi(value);
#endif
#ifdef CONFIG_SMP
if (config_no_apic)
config_no_smp = 1;
value = env_get("no_smp");
if(value)
config_no_smp = atoi(value);
else
config_no_smp = 0;
#endif
2005-04-29 17:36:43 +02:00
/* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main().
*/
Split of architecture-dependent and -independent functions for i386, mainly in the kernel and headers. This split based on work by Ingmar Alting <iaalting@cs.vu.nl> done for his Minix PowerPC architecture port. . kernel does not program the interrupt controller directly, do any other architecture-dependent operations, or contain assembly any more, but uses architecture-dependent functions in arch/$(ARCH)/. . architecture-dependent constants and types defined in arch/$(ARCH)/include. . <ibm/portio.h> moved to <minix/portio.h>, as they have become, for now, architecture-independent functions. . int86, sdevio, readbios, and iopenable are now i386-specific kernel calls and live in arch/i386/do_* now. . i386 arch now supports even less 86 code; e.g. mpx86.s and klib86.s have gone, and 'machine.protected' is gone (and always taken to be 1 in i386). If 86 support is to return, it should be a new architecture. . prototypes for the architecture-dependent functions defined in kernel/arch/$(ARCH)/*.c but used in kernel/ are in kernel/proto.h . /etc/make.conf included in makefiles and shell scripts that need to know the building architecture; it defines ARCH=<arch>, currently only i386. . some basic per-architecture build support outside of the kernel (lib) . in clock.c, only dequeue a process if it was ready . fixes for new include files files deleted: . mpx/klib.s - only for choosing between mpx/klib86 and -386 . klib86.s - only for 86 i386-specific files files moved (or arch-dependent stuff moved) to arch/i386/: . mpx386.s (entry point) . klib386.s . sconst.h . exception.c . protect.c . protect.h . i8269.c
2006-12-22 16:22:27 +01:00
DEBUGEXTRA(("intr_init(%d, 0)\n", INTS_MINIX));
intr_init(INTS_MINIX, 0);
2005-04-29 17:36:43 +02:00
}
2005-09-11 18:44:06 +02:00
/*===========================================================================*
* get_value *
*===========================================================================*/
PUBLIC char *get_value(
const char *params, /* boot monitor parameters */
const char *name /* key to look up */
)
2005-04-21 16:53:53 +02:00
{
/* Get environment value - kernel version of getenv to avoid setting up the
* usual environment array.
*/
2010-03-27 15:31:00 +01:00
register const char *namep;
2005-04-21 16:53:53 +02:00
register char *envp;
for (envp = (char *) params; *envp != 0;) {
2005-04-21 16:53:53 +02:00
for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
;
if (*namep == '\0' && *envp == '=') return(envp + 1);
while (*envp++ != 0)
;
}
return(NULL);
2005-04-21 16:53:53 +02:00
}
/*===========================================================================*
* env_get *
*===========================================================================*/
PUBLIC char *env_get(const char *name)
{
return get_value(params_buffer, name);
}