1 /* system dependent functions for use inside the whole kernel. */
3 #include "../../kernel.h"
10 #include <minix/portio.h>
11 #include <minix/cpufeature.h>
13 #include <archconst.h>
16 #include "../../proc.h"
17 #include "../../debug.h"
23 /* set MP and NE flags to handle FPU exceptions in native mode. */
24 #define CR0_MP_NE 0x0022
25 /* set CR4.OSFXSR[bit 9] if FXSR is supported. */
26 #define CR4_OSFXSR (1L<<9)
27 /* set OSXMMEXCPT[bit 10] if we provide #XM handler. */
28 #define CR4_OSXMMEXCPT (1L<<10)
30 FORWARD
_PROTOTYPE( void ser_debug
, (int c
));
32 PUBLIC
void arch_monitor(void)
37 PUBLIC
int cpu_has_tsc
;
39 PUBLIC
void arch_shutdown(int how
)
41 /* Mask all interrupts, including the clock. */
42 outb( INT_CTLMASK
, ~0);
45 /* We're panicing? Then retrieve and decode currently
46 * loaded segment selectors.
48 printseg("cs: ", 1, proc_ptr
, read_cs());
49 printseg("ds: ", 0, proc_ptr
, read_ds());
50 if(read_ds() != read_ss()) {
51 printseg("ss: ", 0, NULL
, read_ss());
55 if(how
!= RBT_RESET
) {
56 /* return to boot monitor */
58 outb( INT_CTLMASK
, 0);
59 outb( INT2_CTLMASK
, 0);
61 /* Return to the boot monitor. Set
62 * the program if not already done.
64 if (how
!= RBT_MONITOR
)
65 arch_set_params("", 1);
68 static char mybuffer
[sizeof(params_buffer
)];
69 char *lead
= "echo \\n*** kernel messages:\\n";
70 int leadlen
= strlen(lead
);
71 strcpy(mybuffer
, lead
);
73 #define DECSOURCE source = (source - 1 + _KMESS_BUF_SIZE) % _KMESS_BUF_SIZE
75 dest
= sizeof(mybuffer
)-1;
76 mybuffer
[dest
--] = '\0';
78 source
= kmess
.km_next
;
81 while(dest
>= leadlen
) {
82 char c
= kmess
.km_buf
[source
];
84 mybuffer
[dest
--] = 'n';
85 mybuffer
[dest
] = '\\';
86 } else if(isprint(c
) &&
87 c
!= '\'' && c
!= '"' &&
88 c
!= '\\' && c
!= ';') {
90 } else mybuffer
[dest
] = ' ';
96 arch_set_params(mybuffer
, strlen(mybuffer
)+1);
100 /* Reset the system by forcing a processor shutdown. First stop
101 * the BIOS memory test by setting a soft reset flag.
103 u16_t magic
= STOP_MEM_CHECK
;
104 phys_copy(vir2phys(&magic
), SOFT_RESET_FLAG_ADDR
,
105 SOFT_RESET_FLAG_SIZE
);
110 /* address of a.out headers, set in mpx386.s */
113 PUBLIC
void arch_get_aout_headers(int i
, struct exec
*h
)
115 /* The bootstrap loader created an array of the a.out headers at
116 * absolute address 'aout'. Get one element to h.
118 phys_copy(aout
+ i
* A_MINHDR
, vir2phys(h
), (phys_bytes
) A_MINHDR
);
121 PRIVATE
void tss_init(struct tss_s
* tss
, void * kernel_stack
, unsigned cpu
)
124 * make space for process pointer and cpu id and point to the first
127 tss
->sp0
= ((unsigned) kernel_stack
) - 2 * sizeof(void *);
128 tss
->ss0
= DS_SELECTOR
;
131 * set the cpu id at the top of the stack so we know on which cpu is
132 * this stak in use when we trap to kernel
134 *((reg_t
*)(tss
->sp0
+ 1 * sizeof(reg_t
))) = cpu
;
137 PUBLIC
void arch_init(void)
139 unsigned short cw
, sw
;
145 if((sw
& 0xff) == 0 &&
146 (cw
& 0x103f) == 0x3f) {
147 /* We have some sort of FPU, but don't check exact model.
148 * Set CR0_NE and CR0_MP to handle fpu exceptions
150 write_cr0(read_cr0() | CR0_MP_NE
);
152 if(_cpufeature(_CPUF_I386_FXSR
)) {
153 register struct proc
*rp
;
154 phys_bytes aligned_fp_area
;
156 /* Enable FXSR feature usage. */
157 write_cr4(read_cr4() | CR4_OSFXSR
| CR4_OSXMMEXCPT
);
160 for (rp
= BEG_PROC_ADDR
; rp
< END_PROC_ADDR
; ++rp
) {
161 /* FXSR requires 16-byte alignment of memory
162 * image, but unfortunately some old tools
163 * (probably linker) ignores ".balign 16"
164 * applied to our memory image.
165 * Thus we have to do manual alignment.
168 (phys_bytes
) &rp
->p_fpu_state
.fpu_image
;
169 if(aligned_fp_area
% FPUALIGN
) {
170 aligned_fp_area
+= FPUALIGN
-
171 (aligned_fp_area
% FPUALIGN
);
173 rp
->p_fpu_state
.fpu_save_area_p
=
174 (void *) aligned_fp_area
;
180 /* No FPU presents. */
188 * this is setting kernel segments to cover most of the phys memory. The
189 * value is high enough to reach local APIC nad IOAPICs before paging is
192 prot_set_kern_seg_limit(0xfff00000);
198 tss_init(&tss
, &k_boot_stktop
, 0);
200 #if defined(CONFIG_APIC) && !defined(CONFIG_SMP)
201 if (config_no_apic
) {
202 BOOT_VERBOSE(kprintf("APIC disabled, using legacy PIC\n"));
204 else if (!apic_single_cpu_init()) {
205 BOOT_VERBOSE(kprintf("APIC not present, using legacy PIC\n"));
211 #define COM1_BASE 0x3F8
212 #define COM1_THR (COM1_BASE + 0)
213 #define COM1_RBR (COM1_BASE + 0)
214 #define COM1_LSR (COM1_BASE + 5)
216 #define LSR_THRE 0x20
218 PUBLIC
void ser_putc(char c
)
225 for (i
= 0; i
<100000; i
++)
227 if (inb( lsr
) & LSR_THRE
)
233 /*===========================================================================*
235 *===========================================================================*/
236 PUBLIC
void do_ser_debug()
247 PRIVATE
void ser_dump_queues(void)
250 for(q
= 0; q
< NR_SCHED_QUEUES
; q
++) {
254 for(p
= rdy_head
[q
]; p
; p
= p
->p_nextready
) {
255 printf("%s / %d ", p
->p_name
, p
->p_endpoint
);
262 PRIVATE
void ser_dump_segs(void)
265 for (pp
= BEG_PROC_ADDR
; pp
< END_PROC_ADDR
; pp
++)
269 kprintf("%d: %s ep %d\n", proc_nr(pp
), pp
->p_name
, pp
->p_endpoint
);
270 printseg("cs: ", 1, pp
, pp
->p_reg
.cs
);
271 printseg("ds: ", 0, pp
, pp
->p_reg
.ds
);
272 if(pp
->p_reg
.ss
!= pp
->p_reg
.ds
) {
273 printseg("ss: ", 0, pp
, pp
->p_reg
.ss
);
278 PRIVATE
void ser_debug(int c
)
282 serial_debug_active
= 1;
283 /* Disable interrupts so that we get a consistent state. */
284 if(!intr_disabled()) { lock
; u
= 1; };
289 minix_shutdown(NULL
);
301 #define TOGGLECASE(ch, flag) \
303 if(verboseflags & flag) { \
304 verboseflags &= ~flag; \
305 printf("%s disabled\n", #flag); \
307 verboseflags |= flag; \
308 printf("%s enabled\n", #flag); \
312 TOGGLECASE('8', VF_SCHEDULING
)
313 TOGGLECASE('9', VF_PICKPROC
)
316 serial_debug_active
= 0;
320 PRIVATE
void printslot(struct proc
*pp
, int level
)
322 struct proc
*depproc
= NULL
;
324 #define COL { int i; for(i = 0; i < level; i++) printf("> "); }
326 if(level
>= NR_PROCS
) {
333 kprintf("%d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s",
334 proc_nr(pp
), pp
->p_name
, pp
->p_endpoint
,
335 pp
->p_priority
, pp
->p_max_priority
, pp
->p_user_time
,
336 pp
->p_sys_time
, pp
->p_seg
.p_cr3
,
337 rtsflagstr(pp
->p_rts_flags
), miscflagstr(pp
->p_misc_flags
));
339 if(pp
->p_rts_flags
& RTS_SENDING
) {
340 dep
= pp
->p_sendto_e
;
342 } else if(pp
->p_rts_flags
& RTS_RECEIVING
) {
343 dep
= pp
->p_getfrom_e
;
352 if(!isokendpt(dep
, &procno
)) {
353 kprintf(" ??? %d\n", dep
);
355 depproc
= proc_addr(procno
);
356 if(isemptyp(depproc
)) {
357 kprintf(" empty slot %d???\n", procno
);
360 kprintf(" %s\n", depproc
->p_name
);
373 printslot(depproc
, level
+1);
377 PUBLIC
void ser_dump_proc()
381 for (pp
= BEG_PROC_ADDR
; pp
< END_PROC_ADDR
; pp
++)
391 PUBLIC
int arch_init_profile_clock(u32_t freq
)
394 /* Set CMOS timer frequency. */
395 outb(RTC_INDEX
, RTC_REG_A
);
396 outb(RTC_IO
, RTC_A_DV_OK
| freq
);
397 /* Enable CMOS timer interrupts. */
398 outb(RTC_INDEX
, RTC_REG_B
);
400 outb(RTC_INDEX
, RTC_REG_B
);
401 outb(RTC_IO
, r
| RTC_B_PIE
);
402 /* Mandatory read of CMOS register to enable timer interrupts. */
403 outb(RTC_INDEX
, RTC_REG_C
);
406 return CMOS_CLOCK_IRQ
;
409 PUBLIC
void arch_stop_profile_clock(void)
412 /* Disable CMOS timer interrupts. */
413 outb(RTC_INDEX
, RTC_REG_B
);
415 outb(RTC_INDEX
, RTC_REG_B
);
416 outb(RTC_IO
, r
& ~RTC_B_PIE
);
419 PUBLIC
void arch_ack_profile_clock(void)
421 /* Mandatory read of CMOS register to re-enable timer interrupts. */
422 outb(RTC_INDEX
, RTC_REG_C
);
428 #define COLOR_BASE 0xB8000L
430 PRIVATE
void cons_setc(int pos
, int c
)
435 phys_copy(vir2phys((vir_bytes
)&ch
), COLOR_BASE
+(20*80+pos
)*2, 1);
438 PRIVATE
void cons_seth(int pos
, int n
)
442 cons_setc(pos
, '0'+n
);
444 cons_setc(pos
, 'A'+(n
-10));
447 /* Saved by mpx386.s into these variables. */
448 u32_t params_size
, params_offset
, mon_ds
;
450 PUBLIC
int arch_get_params(char *params
, int maxsize
)
452 phys_copy(seg2phys(mon_ds
) + params_offset
, vir2phys(params
),
453 MIN(maxsize
, params_size
));
454 params
[maxsize
-1] = '\0';
458 PUBLIC
int arch_set_params(char *params
, int size
)
460 if(size
> params_size
)
462 phys_copy(vir2phys(params
), seg2phys(mon_ds
) + params_offset
, size
);
466 PUBLIC
void arch_do_syscall(struct proc
*proc
)
468 /* Perform a previously postponed system call.
470 int call_nr
, src_dst_e
;
474 /* Get the system call parameters from their respective registers. */
475 call_nr
= proc
->p_reg
.cx
;
476 src_dst_e
= proc
->p_reg
.retreg
;
477 m_ptr
= (message
*) proc
->p_reg
.bx
;
478 bit_map
= proc
->p_reg
.dx
;
480 /* sys_call() expects the given process's memory to be accessible. */
483 /* Make the system call, for real this time. */
484 proc
->p_reg
.retreg
= sys_call(call_nr
, src_dst_e
, m_ptr
, bit_map
);
487 PUBLIC
struct proc
* arch_finish_schedcheck(void)
490 stk
= (char *)tss
.sp0
;
491 /* set pointer to the process to run on the stack */
492 *((reg_t
*)stk
) = (reg_t
) proc_ptr
;