Changes in / [e2ea4ab1:4d1be48] in mainline
- Files:
-
- 1 added
- 2 deleted
- 52 edited
Legend:
- Unmodified
- Added
- Removed
-
HelenOS.config
re2ea4ab1 r4d1be48 359 359 ! CONFIG_LOG (n/y) 360 360 361 % Kernel function tracing362 ! CONFIG_TRACE (n/y)363 364 361 % Compile kernel tests 365 362 ! CONFIG_TEST (y/n) -
boot/arch/ia64/src/asm.S
re2ea4ab1 r4d1be48 113 113 jump_to_kernel: 114 114 alloc loc0 = ar.pfs, 1, 1, 0, 0 115 mov r 2= in0 ;; # Pass bootinfo address115 mov r1 = in0 ;; # Pass bootinfo address 116 116 movl r8 = KERNEL_ADDRESS;; 117 117 mov b1 = r8 ;; -
defaults/amd64/Makefile.config
re2ea4ab1 r4d1be48 32 32 CONFIG_LOG = n 33 33 34 # Kernel function tracing35 CONFIG_TRACE = n36 37 34 # Compile kernel tests 38 35 CONFIG_TEST = y -
defaults/arm32/Makefile.config
re2ea4ab1 r4d1be48 23 23 CONFIG_LOG = n 24 24 25 # Kernel function tracing26 CONFIG_TRACE = n27 28 25 # Compile kernel tests 29 26 CONFIG_TEST = y -
defaults/ia32/Makefile.config
re2ea4ab1 r4d1be48 38 38 CONFIG_LOG = n 39 39 40 # Kernel function tracing41 CONFIG_TRACE = n42 43 40 # Compile kernel tests 44 41 CONFIG_TEST = y -
defaults/ia64/Makefile.config
re2ea4ab1 r4d1be48 35 35 CONFIG_LOG = n 36 36 37 # Kernel function tracing38 CONFIG_TRACE = n39 40 37 # Compile kernel tests 41 38 CONFIG_TEST = y -
defaults/mips32/Makefile.config
re2ea4ab1 r4d1be48 29 29 CONFIG_LOG = n 30 30 31 # Kernel function tracing32 CONFIG_TRACE = n33 34 31 # Compile kernel tests 35 32 CONFIG_TEST = y -
defaults/ppc32/Makefile.config
re2ea4ab1 r4d1be48 23 23 CONFIG_LOG = n 24 24 25 # Kernel function tracing26 CONFIG_TRACE = n27 28 25 # Compile kernel tests 29 26 CONFIG_TEST = y -
defaults/sparc64/Makefile.config
re2ea4ab1 r4d1be48 38 38 CONFIG_LOG = n 39 39 40 # Kernel function tracing41 CONFIG_TRACE = n42 43 40 # Compile kernel tests 44 41 CONFIG_TEST = y -
defaults/special/Makefile.config
re2ea4ab1 r4d1be48 23 23 CONFIG_LOG = n 24 24 25 # Kernel function tracing26 CONFIG_TRACE = n27 28 25 # Compile kernel tests 29 26 CONFIG_TEST = y -
kernel/Makefile
re2ea4ab1 r4d1be48 160 160 CFLAGS = $(GCC_CFLAGS) 161 161 DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) 162 INSTRUMENTATION = -finstrument-functions163 162 endif 164 163 … … 166 165 CFLAGS = $(GCC_CFLAGS) 167 166 DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) 168 INSTRUMENTATION = -finstrument-functions169 167 endif 170 168 … … 172 170 CFLAGS = $(ICC_CFLAGS) 173 171 DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) 174 INSTRUMENTATION =175 172 endif 176 173 … … 179 176 DEFS += $(CONFIG_DEFS) 180 177 DEPEND_DEFS = $(DEFS) 181 INSTRUMENTATION =182 178 endif 183 179 … … 185 181 CFLAGS = $(CLANG_CFLAGS) 186 182 DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS) 187 INSTRUMENTATION =188 183 endif 189 184 … … 207 202 generic/src/debug/stacktrace.c \ 208 203 generic/src/debug/panic.c \ 209 generic/src/debug/debug.c \210 204 generic/src/interrupt/interrupt.c \ 211 205 generic/src/main/main.c \ … … 361 355 endif 362 356 363 ## Sources where instrumentation is enabled364 #365 366 ifeq ($(CONFIG_TRACE),y)367 INSTRUMENTED_SOURCES = \368 generic/src/cpu/cpu.c \369 generic/src/main/main.c \370 generic/src/main/kinit.c \371 generic/src/proc/the.c372 endif373 374 357 GENERIC_OBJECTS := $(addsuffix .o,$(basename $(GENERIC_SOURCES))) 375 358 ARCH_OBJECTS := $(addsuffix .o,$(basename $(ARCH_SOURCES))) … … 431 414 432 415 %.o: %.c $(DEPEND) 433 $(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) $(if $(findstring $<,$(INSTRUMENTED_SOURCES)),$(INSTRUMENTATION))-c -o $@ $<416 $(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -c -o $@ $< 434 417 ifeq ($(PRECHECK),y) 435 418 $(JOBFILE) $(JOB) $< $@ cc core $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -
kernel/arch/abs32le/include/interrupt.h
re2ea4ab1 r4d1be48 37 37 38 38 #include <typedefs.h> 39 #include <verify.h>40 39 41 40 #define IVT_ITEMS 0 -
kernel/arch/abs32le/src/abs32le.c
re2ea4ab1 r4d1be48 151 151 } 152 152 153 void early_putchar(wchar_t ch)154 {155 }156 157 153 /** @} 158 154 */ -
kernel/arch/amd64/Makefile.inc
re2ea4ab1 r4d1be48 71 71 arch/$(KARCH)/src/mm/page.c \ 72 72 arch/$(KARCH)/src/mm/tlb.c \ 73 arch/$(KARCH)/src/asm .S \73 arch/$(KARCH)/src/asm_utils.S \ 74 74 arch/$(KARCH)/src/cpu/cpu.c \ 75 75 arch/$(KARCH)/src/proc/scheduler.c \ -
kernel/arch/amd64/src/boot/boot.S
re2ea4ab1 r4d1be48 1 /* 2 *Copyright (c) 2005 Ondrej Palkovsky3 *Copyright (c) 2006 Martin Decky4 *Copyright (c) 2008 Jakub Jermar5 *All rights reserved.6 * 7 *Redistribution and use in source and binary forms, with or without8 *modification, are permitted provided that the following conditions9 *are met:10 * 11 *- Redistributions of source code must retain the above copyright12 *notice, this list of conditions and the following disclaimer.13 *- Redistributions in binary form must reproduce the above copyright14 *notice, this list of conditions and the following disclaimer in the15 *documentation and/or other materials provided with the distribution.16 *- The name of the author may not be used to endorse or promote products17 *derived from this software without specific prior written permission.18 * 19 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR20 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES21 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.22 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,23 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT24 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,25 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY26 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT27 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF28 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29 */ 1 # 2 # Copyright (c) 2005 Ondrej Palkovsky 3 # Copyright (c) 2006 Martin Decky 4 # Copyright (c) 2008 Jakub Jermar 5 # All rights reserved. 6 # 7 # Redistribution and use in source and binary forms, with or without 8 # modification, are permitted provided that the following conditions 9 # are met: 10 # 11 # - Redistributions of source code must retain the above copyright 12 # notice, this list of conditions and the following disclaimer. 13 # - Redistributions in binary form must reproduce the above copyright 14 # notice, this list of conditions and the following disclaimer in the 15 # documentation and/or other materials provided with the distribution. 16 # - The name of the author may not be used to endorse or promote products 17 # derived from this software without specific prior written permission. 18 # 19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 # 30 30 31 31 #include <arch/boot/boot.h> … … 37 37 #include <arch/cpuid.h> 38 38 39 #define START_STACK 39 #define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE) 40 40 41 41 .section K_TEXT_START, "ax" 42 42 43 43 .code32 44 45 .macro pm_error msg46 movl \msg, %esi47 jmp pm_error_halt48 .endm49 50 .macro pm_status msg51 #ifdef CONFIG_EGA52 pushl %esi53 movl \msg, %esi54 call pm_early_puts55 popl %esi56 #endif57 .endm58 59 .macro pm2_status msg60 #ifndef CONFIG_FB61 pm_status \msg62 #endif63 .endm64 65 44 .align 4 66 45 .global multiboot_image_start … … 68 47 .long MULTIBOOT_HEADER_MAGIC 69 48 .long MULTIBOOT_HEADER_FLAGS 70 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */49 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum 71 50 .long multiboot_header 72 51 .long unmapped_ktext_start … … 77 56 multiboot_image_start: 78 57 cld 79 80 /* Initialize stack pointer */ 81 movl $START_STACK, %esp 82 83 /* Initialize Global Descriptor Table register */ 84 lgdtl bootstrap_gdtr 85 86 /* Kernel data + stack */ 58 movl $START_STACK, %esp # initialize stack pointer 59 lgdtl bootstrap_gdtr # initialize Global Descriptor Table register 60 87 61 movw $gdtselector(KDATA_DES), %cx 88 62 movw %cx, %es 89 movw %cx, %ds 63 movw %cx, %ds # kernel data + stack 90 64 movw %cx, %ss 91 65 92 /* 93 * Simics seems to remove hidden part of GS on entering user mode 94 * when _visible_ part of GS does not point to user-mode segment. 95 */ 66 # 67 # Simics seems to remove hidden part of GS on entering user mode 68 # when _visible_ part of GS does not point to user-mode segment. 69 # 70 96 71 movw $gdtselector(UDATA_DES), %cx 97 72 movw %cx, %fs … … 101 76 multiboot_meeting_point: 102 77 103 /* Save GRUB arguments */ 104 movl %eax, grub_eax 78 movl %eax, grub_eax # save parameters from GRUB 105 79 movl %ebx, grub_ebx 106 80 107 pm_status $status_prot 81 # 82 # Protected 32-bit. We want to reuse the code-seg descriptor, 83 # the Default operand size must not be 1 when entering long mode. 84 # 108 85 109 86 movl $(INTEL_CPUID_EXTENDED), %eax … … 112 89 ja extended_cpuid_supported 113 90 114 pm_error $err_extended_cpuid 91 movl $extended_cpuid_msg, %esi 92 jmp error_halt 115 93 116 94 extended_cpuid_supported: … … 121 99 jc long_mode_supported 122 100 123 pm_error $err_long_mode 101 movl $long_mode_msg, %esi 102 jmp error_halt 124 103 125 104 long_mode_supported: … … 128 107 jc noexecute_supported 129 108 130 pm_error $err_noexecute 109 movl $noexecute_msg, %esi 110 jmp error_halt 131 111 132 112 noexecute_supported: … … 137 117 jc fx_supported 138 118 139 pm_error $err_fx 119 movl $fx_msg, %esi 120 jmp error_halt 140 121 141 122 fx_supported: … … 144 125 jc sse2_supported 145 126 146 pm_error $err_sse2 127 movl $sse2_msg, %esi 128 jmp error_halt 147 129 148 130 sse2_supported: 149 131 150 132 #include "vesa_prot.inc" 151 152 /* 153 * Protected 32-bit. We want to reuse the code-seg descriptor, 154 * the Default operand size must not be 1 when entering long mode. 155 */ 156 157 pm2_status $status_prot2 158 159 /* 160 * Enable 64-bit page translation entries - CR4.PAE = 1. 161 * Paging is not enabled until after long mode is enabled. 162 */ 133 134 # 135 # Enable 64-bit page translation entries - CR4.PAE = 1. 136 # Paging is not enabled until after long mode is enabled. 137 # 163 138 164 139 movl %cr4, %eax … … 166 141 movl %eax, %cr4 167 142 168 /* Set up paging tables */ 143 # set up paging tables 144 169 145 leal ptl_0, %eax 170 146 movl %eax, %cr3 171 147 172 /* Enable long mode */ 173 movl $EFER_MSR_NUM, %ecx 174 rdmsr /* read EFER */ 175 btsl $AMD_LME_FLAG, %eax /* set LME = 1 */ 176 wrmsr 177 178 /* Enable paging to activate long mode (set CR0.PG = 1) */ 148 # enable long mode 149 150 movl $EFER_MSR_NUM, %ecx # EFER MSR number 151 rdmsr # read EFER 152 btsl $AMD_LME_FLAG, %eax # set LME = 1 153 wrmsr # write EFER 154 155 # enable paging to activate long mode (set CR0.PG = 1) 156 179 157 movl %cr0, %eax 180 158 btsl $31, %eax 181 159 movl %eax, %cr0 182 160 183 /* At this point we are in compatibility mode */ 161 # at this point we are in compatibility mode 162 184 163 jmpl $gdtselector(KTEXT_DES), $start64 185 164 186 /** Print string to EGA display (in light red) and halt. 187 * 188 * Should be executed from 32 bit protected mode with paging 189 * turned off. Stack is not required. This routine is used even 190 * if CONFIG_EGA is not enabled. Since we are going to halt the 191 * CPU anyway, it is always better to at least try to print 192 * some hints. 193 * 194 * @param %esi Pointer to the NULL-terminated string 195 * to be print. 196 * 197 */ 198 pm_error_halt: 199 movl $0xb8000, %edi /* base of EGA text mode memory */ 165 .code64 166 start64: 167 movq $(PA2KA(START_STACK)), %rsp 168 169 # call arch_pre_main(grub_eax, grub_ebx) 170 xorq %rdi, %rdi 171 movl grub_eax, %edi 172 xorq %rsi, %rsi 173 movl grub_ebx, %esi 174 175 movabsq $arch_pre_main, %rax 176 callq *%rax 177 178 # create the first stack frame 179 pushq $0 180 movq %rsp, %rbp 181 182 movabsq $main_bsp, %rax 183 call *%rax 184 185 # not reached 186 187 cli 188 hlt0: 189 hlt 190 jmp hlt0 191 192 # Print string from %esi to EGA display (in red) and halt 193 error_halt: 194 movl $0xb8000, %edi # base of EGA text mode memory 200 195 xorl %eax, %eax 201 196 202 /* Read bits 8 - 15 of the cursor address */ 203 movw $0x3d4, %dx 197 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address 204 198 movb $0xe, %al 205 199 outb %al, %dx … … 209 203 shl $8, %ax 210 204 211 /* Read bits 0 - 7 of the cursor address */ 212 movw $0x3d4, %dx 205 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address 213 206 movb $0xf, %al 214 207 outb %al, %dx … … 217 210 inb %dx, %al 218 211 219 /* Sanity check for the cursor on screen */ 220 cmp $2000, %ax 221 jb err_cursor_ok 222 223 movw $1998, %ax 224 225 err_cursor_ok: 212 cmp $1920, %ax 213 jbe cursor_ok 214 215 movw $1920, %ax # sanity check for the cursor on the last line 216 217 cursor_ok: 226 218 227 219 movw %ax, %bx … … 229 221 addl %eax, %edi 230 222 231 err_ploop: 223 movw $0x0c00, %ax # black background, light red foreground 224 225 ploop: 232 226 lodsb 233 234 227 cmp $0, %al 235 je err_ploop_end 236 237 movb $0x0c, %ah /* black background, light red foreground */ 228 je ploop_end 238 229 stosw 239 240 /* Sanity check for the cursor on the last line */241 230 inc %bx 242 cmp $2000, %bx 243 jb err_ploop 244 245 /* Scroll the screen (24 rows) */ 246 movl %esi, %edx 247 movl $0xb80a0, %esi 248 movl $0xb8000, %edi 249 movl $1920, %ecx 250 rep movsw 251 252 /* Clear the 24th row */ 253 xorl %eax, %eax 254 movl $80, %ecx 255 rep stosw 256 257 /* Go to row 24 */ 258 movl %edx, %esi 259 movl $0xb8f00, %edi 260 movw $1920, %bx 261 262 jmp err_ploop 263 err_ploop_end: 264 265 /* Write bits 8 - 15 of the cursor address */ 266 movw $0x3d4, %dx 231 jmp ploop 232 ploop_end: 233 234 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address 267 235 movb $0xe, %al 268 236 outb %al, %dx … … 272 240 outb %al, %dx 273 241 274 /* Write bits 0 - 7 of the cursor address */ 275 movw $0x3d4, %dx 242 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address 276 243 movb $0xf, %al 277 244 outb %al, %dx … … 286 253 jmp hlt1 287 254 288 /** Print string to EGA display (in light green).289 *290 * Should be called from 32 bit protected mode with paging291 * turned off. A stack space of at least 24 bytes is required,292 * but the function does not establish a stack frame.293 *294 * Macros such as pm_status and pm2_status take care that295 * this function is used only when CONFIG_EGA is enabled296 * and CONFIG_FB is disabled.297 *298 * @param %esi Pointer to the NULL-terminated string299 * to be print.300 *301 */302 pm_early_puts:303 pushl %eax304 pushl %ebx305 pushl %ecx306 pushl %edx307 pushl %edi308 309 movl $0xb8000, %edi /* base of EGA text mode memory */310 xorl %eax, %eax311 312 /* Read bits 8 - 15 of the cursor address */313 movw $0x3d4, %dx314 movb $0xe, %al315 outb %al, %dx316 317 movw $0x3d5, %dx318 inb %dx, %al319 shl $8, %ax320 321 /* Read bits 0 - 7 of the cursor address */322 movw $0x3d4, %dx323 movb $0xf, %al324 outb %al, %dx325 326 movw $0x3d5, %dx327 inb %dx, %al328 329 /* Sanity check for the cursor on screen */330 cmp $2000, %ax331 jb pm_puts_cursor_ok332 333 movw $1998, %ax334 335 pm_puts_cursor_ok:336 337 movw %ax, %bx338 shl $1, %eax339 addl %eax, %edi340 341 pm_puts_ploop:342 lodsb343 344 cmp $0, %al345 je pm_puts_ploop_end346 347 movb $0x0a, %ah /* black background, light green foreground */348 stosw349 350 /* Sanity check for the cursor on the last line */351 inc %bx352 cmp $2000, %bx353 jb pm_puts_ploop354 355 /* Scroll the screen (24 rows) */356 movl %esi, %edx357 movl $0xb80a0, %esi358 movl $0xb8000, %edi359 movl $1920, %ecx360 rep movsw361 362 /* Clear the 24th row */363 xorl %eax, %eax364 movl $80, %ecx365 rep stosw366 367 /* Go to row 24 */368 movl %edx, %esi369 movl $0xb8f00, %edi370 movw $1920, %bx371 372 jmp pm_puts_ploop373 pm_puts_ploop_end:374 375 /* Write bits 8 - 15 of the cursor address */376 movw $0x3d4, %dx377 movb $0xe, %al378 outb %al, %dx379 380 movw $0x3d5, %dx381 movb %bh, %al382 outb %al, %dx383 384 /* Write bits 0 - 7 of the cursor address */385 movw $0x3d4, %dx386 movb $0xf, %al387 outb %al, %dx388 389 movw $0x3d5, %dx390 movb %bl, %al391 outb %al, %dx392 393 popl %edi394 popl %edx395 popl %ecx396 popl %ebx397 popl %eax398 399 ret400 401 .code64402 403 .macro long_status msg404 pushq %rdi405 movq \msg, %rdi406 call early_puts407 popq %rdi408 .endm409 410 start64:411 412 /*413 * Long mode.414 */415 416 movq $(PA2KA(START_STACK)), %rsp417 418 /* Create the first stack frame */419 pushq $0420 movq %rsp, %rbp421 422 long_status $status_long423 424 /* Call arch_pre_main(grub_eax, grub_ebx) */425 xorq %rdi, %rdi426 movl grub_eax, %edi427 xorq %rsi, %rsi428 movl grub_ebx, %esi429 430 movabsq $arch_pre_main, %rax431 callq *%rax432 433 long_status $status_main434 435 /* Call main_bsp() */436 movabsq $main_bsp, %rax437 call *%rax438 439 /* Not reached */440 cli441 hlt0:442 hlt443 jmp hlt0444 445 /** Print string to EGA display.446 *447 * Should be called from long mode (with paging enabled448 * and stack established). This function is ABI compliant449 * (without red-zone).450 *451 * If CONFIG_EGA is undefined or CONFIG_FB is defined452 * then this function does nothing.453 *454 * @param %rdi Pointer to the NULL-terminated string455 * to be printed.456 *457 */458 early_puts:459 460 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))461 462 /* Prologue, save preserved registers */463 pushq %rbp464 movq %rsp, %rbp465 pushq %rbx466 467 movq %rdi, %rsi468 movq $(PA2KA(0xb8000)), %rdi /* base of EGA text mode memory */469 xorq %rax, %rax470 471 /* Read bits 8 - 15 of the cursor address */472 movw $0x3d4, %dx473 movb $0xe, %al474 outb %al, %dx475 476 movw $0x3d5, %dx477 inb %dx, %al478 shl $8, %ax479 480 /* Read bits 0 - 7 of the cursor address */481 movw $0x3d4, %dx482 movb $0xf, %al483 outb %al, %dx484 485 movw $0x3d5, %dx486 inb %dx, %al487 488 /* Sanity check for the cursor on screen */489 cmp $2000, %ax490 jb early_puts_cursor_ok491 492 movw $1998, %ax493 494 early_puts_cursor_ok:495 496 movw %ax, %bx497 shl $1, %rax498 addq %rax, %rdi499 500 early_puts_ploop:501 lodsb502 503 cmp $0, %al504 je early_puts_ploop_end505 506 movb $0x0e, %ah /* black background, yellow foreground */507 stosw508 509 /* Sanity check for the cursor on the last line */510 inc %bx511 cmp $2000, %bx512 jb early_puts_ploop513 514 /* Scroll the screen (24 rows) */515 movq %rsi, %rdx516 movq $(PA2KA(0xb80a0)), %rsi517 movq $(PA2KA(0xb8000)), %rdi518 movq $1920, %rcx519 rep movsw520 521 /* Clear the 24th row */522 xorq %rax, %rax523 movq $80, %rcx524 rep stosw525 526 /* Go to row 24 */527 movq %rdx, %rsi528 movq $(PA2KA(0xb8f00)), %rdi529 movw $1920, %bx530 531 jmp early_puts_ploop532 early_puts_ploop_end:533 534 /* Write bits 8 - 15 of the cursor address */535 movw $0x3d4, %dx536 movb $0xe, %al537 outb %al, %dx538 539 movw $0x3d5, %dx540 movb %bh, %al541 outb %al, %dx542 543 /* Write bits 0 - 7 of the cursor address */544 movw $0x3d4, %dx545 movb $0xf, %al546 outb %al, %dx547 548 movw $0x3d5, %dx549 movb %bl, %al550 outb %al, %dx551 552 /* Epilogue, restore preserved registers */553 popq %rbx554 leave555 556 #endif557 558 ret559 560 255 #include "vesa_real.inc" 561 256 562 257 .section K_INI_PTLS, "aw", @progbits 563 258 564 /** Generate initial page table contents. 565 * 566 * @param cnt Number of entries to generate. Must be multiple of 8. 567 * @param g Number of GB that will be added to the mapping. 568 * 569 */ 259 # 260 # Macro for generating initial page table contents. 261 # @param cnt Number of entries to generate. Must be multiple of 8. 262 # @param g Number of GB that will be added to the mapping. 263 # 570 264 .macro ptl2gen cnt g 571 265 .if \cnt … … 582 276 .endm 583 277 584 /* Page table for pages in the 1st gigabyte. */ 278 # Page table for pages in the 1st gigabyte. 585 279 .align 4096 586 280 ptl_2_0g: 587 281 ptl2gen 512 0 588 282 589 /* Page table for pages in the 2nd gigabyte. */ 283 # Page table for pages in the 2nd gigabyte. 590 284 .align 4096 591 285 ptl_2_1g: 592 286 ptl2gen 512 1 593 287 594 /* Page table for pages in the 3rd gigabyte. */ 288 # Page table for pages in the 3rd gigabyte. 595 289 .align 4096 596 290 ptl_2_2g: 597 291 ptl2gen 512 2 598 292 599 /* Page table for pages in the 4th gigabyte. */ 293 # Page table for pages in the 4th gigabyte. 600 294 .align 4096 601 295 ptl_2_3g: 602 296 ptl2gen 512 3 603 297 604 /* Page table for pages in the 5th gigabyte. */ 298 # Page table for pages in the 5th gigabyte. 605 299 .align 4096 606 300 ptl_2_4g: 607 301 ptl2gen 512 3 608 302 609 /* Page table for pages in the 6th gigabyte. */ 303 # Page table for pages in the 6th gigabyte. 610 304 .align 4096 611 305 ptl_2_5g: 612 306 ptl2gen 512 3 613 307 614 /* Page table for pages in the 7th gigabyte. */ 308 # Page table for pages in the 7th gigabyte. 615 309 .align 4096 616 310 ptl_2_6g: 617 311 ptl2gen 512 3 618 312 619 /* Page table for pages in the 8th gigabyte. */ 313 # Page table for pages in the 8th gigabyte. 620 314 .align 4096 621 315 ptl_2_7g: … … 624 318 .align 4096 625 319 ptl_1: 626 /* Identity mapping for [0; 8G) */320 # Identity mapping for [0; 8G) 627 321 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT) 628 322 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT) … … 656 350 .long 0 657 351 658 e rr_extended_cpuid:352 extended_cpuid_msg: 659 353 .asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted." 660 err_long_mode:354 long_mode_msg: 661 355 .asciz "Error: 64-bit long mode not supported. System halted." 662 err_noexecute:356 noexecute_msg: 663 357 .asciz "Error: No-execute pages not supported. System halted." 664 err_fx:358 fx_msg: 665 359 .asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted." 666 err_sse2:360 sse2_msg: 667 361 .asciz "Error: SSE2 instructions not supported. System halted." 668 669 status_prot:670 .asciz "[prot] "671 status_vesa_copy:672 .asciz "[vesa_copy] "673 status_grub_cmdline:674 .asciz "[grub_cmdline] "675 status_vesa_real:676 .asciz "[vesa_real] "677 status_prot2:678 .asciz "[prot2] "679 status_long:680 .asciz "[long] "681 status_main:682 .asciz "[main] " -
kernel/arch/amd64/src/boot/vesa_ret.inc
re2ea4ab1 r4d1be48 1 1 .code32 2 2 vesa_init_protected: 3 cld4 5 /* Initialize stack pointer */6 movl $START_STACK, %esp7 8 /* Kernel data + stack */9 3 movw $gdtselector(KDATA_DES), %cx 10 4 movw %cx, %es 11 movw %cx, %ds 5 movw %cx, %ds # kernel data + stack 12 6 movw %cx, %ss 13 7 14 /*15 *Simics seems to remove hidden part of GS on entering user mode16 *when _visible_ part of GS does not point to user-mode segment.17 */8 # 9 # Simics seems to remove hidden part of GS on entering user mode 10 # when _visible_ part of GS does not point to user-mode segment. 11 # 18 12 19 13 movw $gdtselector(UDATA_DES), %cx … … 21 15 movw %cx, %gs 22 16 17 movl $START_STACK, %esp # initialize stack pointer 18 23 19 jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point -
kernel/arch/amd64/src/debugger.c
re2ea4ab1 r4d1be48 230 230 return; 231 231 232 printf("*** Found ZERO on address % " PRIp "(slot %d) ***\n",232 printf("*** Found ZERO on address %lx (slot %d) ***\n", 233 233 breakpoints[slot].address, slot); 234 234 } else { 235 printf("Data watchpoint - new data: % " PRIp "\n",235 printf("Data watchpoint - new data: %lx\n", 236 236 *((unative_t *) breakpoints[slot].address)); 237 237 } 238 238 } 239 239 240 printf("Reached breakpoint %d:% " PRIp "(%s)\n", slot, getip(istate),240 printf("Reached breakpoint %d:%lx (%s)\n", slot, getip(istate), 241 241 symtab_fmt_name_lookup(getip(istate))); 242 242 -
kernel/arch/arm32/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 *Copyright (c) 2007 Michal Kebrt3 *All rights reserved.4 * 5 *Redistribution and use in source and binary forms, with or without6 *modification, are permitted provided that the following conditions7 *are met:8 * 9 *- Redistributions of source code must retain the above copyright10 *notice, this list of conditions and the following disclaimer.11 *- Redistributions in binary form must reproduce the above copyright12 *notice, this list of conditions and the following disclaimer in the13 *documentation and/or other materials provided with the distribution.14 *- The name of the author may not be used to endorse or promote products15 *derived from this software without specific prior written permission.16 * 17 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27 */ 1 # 2 # Copyright (c) 2007 Michal Kebrt 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 28 29 29 30 .text 30 31 … … 36 37 .global memcpy_from_uspace_failover_address 37 38 .global memcpy_to_uspace_failover_address 38 .global early_putchar39 39 40 40 memsetb: … … 47 47 memcpy_from_uspace: 48 48 memcpy_to_uspace: 49 add r3, r1, #3 50 bic r3, r3, #3 51 cmp r1, r3 52 stmdb sp!, {r4, r5, lr} 53 mov r5, r0 /* save dst */ 54 beq 4f 55 56 1: 57 cmp r2, #0 58 movne ip, #0 59 beq 3f 60 61 2: 62 ldrb r3, [ip, r1] 63 strb r3, [ip, r0] 64 add ip, ip, #1 65 cmp ip, r2 66 bne 2b 67 68 3: 69 mov r0, r5 70 ldmia sp!, {r4, r5, pc} 71 72 4: 73 add r3, r0, #3 74 bic r3, r3, #3 75 cmp r0, r3 76 bne 1b 77 movs r4, r2, lsr #2 78 moveq lr, r4 79 beq 6f 80 mov lr, #0 81 mov ip, lr 82 83 5: 84 ldr r3, [ip, r1] 85 add lr, lr, #1 86 cmp lr, r4 87 str r3, [ip, r0] 88 add ip, ip, #4 89 bne 5b 90 91 6: 92 ands r4, r2, #3 93 beq 3b 94 mov r3, lr, lsl #2 95 add r0, r3, r0 96 add ip, r3, r1 97 mov r2, #0 98 99 7: 100 ldrb r3, [r2, ip] 101 strb r3, [r2, r0] 102 add r2, r2, #1 103 cmp r2, r4 104 bne 7b 105 b 3b 49 add r3, r1, #3 50 bic r3, r3, #3 51 cmp r1, r3 52 stmdb sp!, {r4, r5, lr} 53 mov r5, r0 /* save dst */ 54 beq 4f 55 1: 56 cmp r2, #0 57 movne ip, #0 58 beq 3f 59 2: 60 ldrb r3, [ip, r1] 61 strb r3, [ip, r0] 62 add ip, ip, #1 63 cmp ip, r2 64 bne 2b 65 3: 66 mov r0, r5 67 ldmia sp!, {r4, r5, pc} 68 4: 69 add r3, r0, #3 70 bic r3, r3, #3 71 cmp r0, r3 72 bne 1b 73 movs r4, r2, lsr #2 74 moveq lr, r4 75 beq 6f 76 mov lr, #0 77 mov ip, lr 78 5: 79 ldr r3, [ip, r1] 80 add lr, lr, #1 81 cmp lr, r4 82 str r3, [ip, r0] 83 add ip, ip, #4 84 bne 5b 85 6: 86 ands r4, r2, #3 87 beq 3b 88 mov r3, lr, lsl #2 89 add r0, r3, r0 90 add ip, r3, r1 91 mov r2, #0 92 7: 93 ldrb r3, [r2, ip] 94 strb r3, [r2, r0] 95 add r2, r2, #1 96 cmp r2, r4 97 bne 7b 98 b 3b 106 99 107 100 memcpy_from_uspace_failover_address: 108 101 memcpy_to_uspace_failover_address: 109 mov r0, #0 110 ldmia sp!, {r4, r5, pc} 111 112 early_putchar: 113 mov pc, lr 102 mov r0, #0 103 ldmia sp!, {r4, r5, pc} -
kernel/arch/ia32/include/smp/apic.h
re2ea4ab1 r4d1be48 347 347 348 348 extern uint32_t apic_id_mask; 349 extern uint8_t bsp_l_apic;350 349 351 350 extern void apic_init(void); … … 356 355 extern int l_apic_send_init_ipi(uint8_t); 357 356 extern void l_apic_debug(void); 357 extern uint8_t l_apic_id(void); 358 358 359 359 extern uint32_t io_apic_read(uint8_t); -
kernel/arch/ia32/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 * Copyright (c) 2001 Jakub Jermar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** Very low and hardware-level functions 30 * 31 */ 32 33 /** 34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 35 * has no error word and 1 means interrupt with error word 36 * 37 */ 38 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 39 40 #include <arch/pm.h> 41 #include <arch/mm/page.h> 1 # 2 # Copyright (c) 2001-2004 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 29 ## very low and hardware-level functions 30 31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error 32 # word and 1 means interrupt with error word 33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 42 34 43 35 .text 36 44 37 .global paging_on 45 38 .global enable_l_apic_in_msr … … 52 45 .global memcpy_to_uspace 53 46 .global memcpy_to_uspace_failover_address 54 .global early_putchar 55 56 /* Wrapper for generic memsetb */ 47 48 49 # Wrapper for generic memsetb 57 50 memsetb: 58 51 jmp _memsetb 59 52 60 /* Wrapper for generic memsetw */ 53 # Wrapper for generic memsetw 61 54 memsetw: 62 55 jmp _memsetw 63 56 64 #define MEMCPY_DST 4 65 #define MEMCPY_SRC 8 66 #define MEMCPY_SIZE 12 57 58 #define MEMCPY_DST 4 59 #define MEMCPY_SRC 8 60 #define MEMCPY_SIZE 12 67 61 68 62 /** Copy memory to/from userspace. … … 74 68 * or copy_to_uspace(). 75 69 * 76 * @param MEMCPY_DST(%esp) 77 * @param MEMCPY_SRC(%esp) 78 * @param MEMCPY_SIZE(%esp) 70 * @param MEMCPY_DST(%esp) Destination address. 71 * @param MEMCPY_SRC(%esp) Source address. 72 * @param MEMCPY_SIZE(%esp) Size. 79 73 * 80 74 * @return MEMCPY_DST(%esp) on success and 0 on failure. 81 *82 75 */ 83 76 memcpy: 84 77 memcpy_from_uspace: 85 78 memcpy_to_uspace: 86 movl %edi, %edx 87 movl %esi, %eax 79 movl %edi, %edx /* save %edi */ 80 movl %esi, %eax /* save %esi */ 88 81 89 82 movl MEMCPY_SIZE(%esp), %ecx 90 shrl $2, %ecx 83 shrl $2, %ecx /* size / 4 */ 91 84 92 85 movl MEMCPY_DST(%esp), %edi 93 86 movl MEMCPY_SRC(%esp), %esi 94 87 95 /* Copy whole words */ 96 rep movsl 97 88 rep movsl /* copy whole words */ 89 98 90 movl MEMCPY_SIZE(%esp), %ecx 99 andl $3, %ecx 91 andl $3, %ecx /* size % 4 */ 100 92 jz 0f 101 93 102 /* Copy the rest byte by byte */ 103 rep movsb 104 105 0: 106 107 movl %edx, %edi 108 movl %eax, %esi 109 110 /* MEMCPY_DST(%esp), success */ 111 movl MEMCPY_DST(%esp), %eax 112 ret 113 94 rep movsb /* copy the rest byte by byte */ 95 96 0: 97 movl %edx, %edi 98 movl %eax, %esi 99 movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ 100 ret 101 114 102 /* 115 103 * We got here from as_page_fault() after the memory operations … … 120 108 movl %edx, %edi 121 109 movl %eax, %esi 122 123 /* Return 0, failure */ 124 xorl %eax, %eax 110 xorl %eax, %eax /* return 0, failure */ 125 111 ret 126 112 127 /** Turn paging on 128 * 129 * Enable paging and write-back caching in CR0. 130 * 131 */ 113 ## Turn paging on 114 # 115 # Enable paging and write-back caching in CR0. 116 # 132 117 paging_on: 133 118 movl %cr0, %edx 134 orl $(1 << 31), %edx /* paging on */ 135 136 /* Clear Cache Disable and not Write Though */ 119 orl $(1 << 31), %edx # paging on 120 # clear Cache Disable and not Write Though 137 121 andl $~((1 << 30) | (1 << 29)), %edx 138 movl %edx, 122 movl %edx,%cr0 139 123 jmp 0f 140 141 0: 142 ret 143 144 /** Enable local APIC 145 * 146 * Enable local APIC in MSR. 147 * 148 */ 124 0: 125 ret 126 127 128 ## Enable local APIC 129 # 130 # Enable local APIC in MSR. 131 # 149 132 enable_l_apic_in_msr: 150 133 movl $0x1b, %ecx … … 155 138 ret 156 139 157 /** Clear nested flag 158 * 159 */ 140 # Clear nested flag 141 # overwrites %ecx 160 142 .macro CLEAR_NT_FLAG 161 143 pushfl 162 144 andl $0xffffbfff, (%esp) 163 145 popfl 164 .endm 146 .endm 165 147 166 148 /* … … 176 158 sysenter_handler: 177 159 sti 178 pushl %ebp /* remember user stack */179 pushl %edi /* remember return user address */180 181 xorl %ebp, %ebp /* stop stack traces here */182 183 pushl %gs /* remember TLS */184 185 pushl %eax /* syscall number */186 subl $8, %esp /* unused sixth and fifth argument */187 pushl %esi /* fourth argument */188 pushl %ebx /* third argument */189 pushl %ecx /* second argument */190 pushl %edx /* first argument */191 160 pushl %ebp # remember user stack 161 pushl %edi # remember return user address 162 163 xorl %ebp, %ebp # stop stack traces here 164 165 pushl %gs # remember TLS 166 167 pushl %eax # syscall number 168 subl $8, %esp # unused sixth and fifth argument 169 pushl %esi # fourth argument 170 pushl %ebx # third argument 171 pushl %ecx # second argument 172 pushl %edx # first argument 173 192 174 movw $16, %ax 193 175 movw %ax, %ds 194 176 movw %ax, %es 195 177 196 178 cld 197 179 call syscall_handler 198 addl $28, %esp /* remove arguments from stack */ 199 200 pop %gs /* restore TLS */ 201 202 pop %edx /* prepare return EIP for SYSEXIT */ 203 pop %ecx /* prepare userspace ESP for SYSEXIT */ 204 205 sysexit /* return to userspace */ 206 207 #define ISTATE_OFFSET_EAX 0 208 #define ISTATE_OFFSET_EBX 4 209 #define ISTATE_OFFSET_ECX 8 210 #define ISTATE_OFFSET_EDX 12 211 #define ISTATE_OFFSET_EDI 16 212 #define ISTATE_OFFSET_ESI 20 213 #define ISTATE_OFFSET_EBP 24 214 #define ISTATE_OFFSET_EBP_FRAME 28 215 #define ISTATE_OFFSET_EIP_FRAME 32 216 #define ISTATE_OFFSET_GS 36 217 #define ISTATE_OFFSET_FS 40 218 #define ISTATE_OFFSET_ES 44 219 #define ISTATE_OFFSET_DS 48 220 #define ISTATE_OFFSET_ERROR_WORD 52 221 #define ISTATE_OFFSET_EIP 56 222 #define ISTATE_OFFSET_CS 60 223 #define ISTATE_OFFSET_EFLAGS 64 224 #define ISTATE_OFFSET_ESP 68 225 #define ISTATE_OFFSET_SS 72 180 addl $28, %esp # remove arguments from stack 181 182 pop %gs # restore TLS 183 184 pop %edx # prepare return EIP for SYSEXIT 185 pop %ecx # prepare userspace ESP for SYSEXIT 186 187 sysexit # return to userspace 188 189 190 #define ISTATE_OFFSET_EAX 0 191 #define ISTATE_OFFSET_EBX 4 192 #define ISTATE_OFFSET_ECX 8 193 #define ISTATE_OFFSET_EDX 12 194 #define ISTATE_OFFSET_EDI 16 195 #define ISTATE_OFFSET_ESI 20 196 #define ISTATE_OFFSET_EBP 24 197 #define ISTATE_OFFSET_EBP_FRAME 28 198 #define ISTATE_OFFSET_EIP_FRAME 32 199 #define ISTATE_OFFSET_GS 36 200 #define ISTATE_OFFSET_FS 40 201 #define ISTATE_OFFSET_ES 44 202 #define ISTATE_OFFSET_DS 48 203 #define ISTATE_OFFSET_ERROR_WORD 52 204 #define ISTATE_OFFSET_EIP 56 205 #define ISTATE_OFFSET_CS 60 206 #define ISTATE_OFFSET_EFLAGS 64 207 #define ISTATE_OFFSET_ESP 68 208 #define ISTATE_OFFSET_SS 72 226 209 227 210 /* 228 * Size of the istate structure without the hardware-saved part 229 * and without theerror word.211 * Size of the istate structure without the hardware-saved part and without the 212 * error word. 230 213 */ 231 #define ISTATE_SOFT_SIZE 52 232 233 /** Declare interrupt handlers 234 * 235 * Declare interrupt handlers for n interrupt 236 * vectors starting at vector i. 237 * 238 * The handlers setup data segment registers 239 * and call exc_dispatch(). 240 * 241 */ 242 #define INTERRUPT_ALIGN 256 243 214 #define ISTATE_SOFT_SIZE 52 215 216 ## Declare interrupt handlers 217 # 218 # Declare interrupt handlers for n interrupt 219 # vectors starting at vector i. 220 # 221 # The handlers setup data segment registers 222 # and call exc_dispatch(). 223 # 224 #define INTERRUPT_ALIGN 256 244 225 .macro handler i n 245 .ifeq \i - 0x30 246 /* Syscall handler */ 247 pushl %ds 248 pushl %es 249 pushl %fs 250 pushl %gs 251 252 /* 253 * Push syscall arguments onto the stack 254 * 255 * NOTE: The idea behind the order of arguments passed 256 * in registers is to use all scratch registers 257 * first and preserved registers next. An optimized 258 * libc syscall wrapper can make use of this setup. 259 * 260 */ 261 pushl %eax 262 pushl %ebp 263 pushl %edi 264 pushl %esi 265 pushl %ebx 266 pushl %ecx 267 pushl %edx 268 269 /* We must fill the data segment registers */ 270 movw $16, %ax 271 movw %ax, %ds 272 movw %ax, %es 273 274 xorl %ebp, %ebp 275 276 cld 277 sti 278 279 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 280 call syscall_handler 281 cli 282 283 movl 20(%esp), %ebp /* restore EBP */ 284 addl $28, %esp /* clean-up of parameters */ 285 286 popl %gs 287 popl %fs 288 popl %es 289 popl %ds 290 291 CLEAR_NT_FLAG 292 iret 293 .else 294 /* 295 * This macro distinguishes between two versions of ia32 296 * exceptions. One version has error word and the other 297 * does not have it. The latter version fakes the error 298 * word on the stack so that the handlers and istate_t 299 * can be the same for both types. 300 */ 301 .iflt \i - 32 302 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 303 /* 304 * Exception with error word: do nothing 305 */ 306 .else 307 /* 308 * Exception without error word: fake up one 309 */ 310 pushl $0 311 .endif 312 .else 313 /* 314 * Interrupt: fake up one 315 */ 316 pushl $0 317 .endif 318 319 subl $ISTATE_SOFT_SIZE, %esp 320 321 /* 322 * Save the general purpose registers. 323 */ 324 movl %eax, ISTATE_OFFSET_EAX(%esp) 325 movl %ebx, ISTATE_OFFSET_EBX(%esp) 326 movl %ecx, ISTATE_OFFSET_ECX(%esp) 327 movl %edx, ISTATE_OFFSET_EDX(%esp) 328 movl %edi, ISTATE_OFFSET_EDI(%esp) 329 movl %esi, ISTATE_OFFSET_ESI(%esp) 330 movl %ebp, ISTATE_OFFSET_EBP(%esp) 331 332 /* 333 * Save the selector registers. 334 */ 335 movl %gs, %eax 336 movl %fs, %ebx 337 movl %es, %ecx 338 movl %ds, %edx 339 340 movl %eax, ISTATE_OFFSET_GS(%esp) 341 movl %ebx, ISTATE_OFFSET_FS(%esp) 342 movl %ecx, ISTATE_OFFSET_ES(%esp) 343 movl %edx, ISTATE_OFFSET_DS(%esp) 344 345 /* 346 * Switch to kernel selectors. 347 */ 348 movl $16, %eax 349 movl %eax, %ds 350 movl %eax, %es 351 352 /* 353 * Imitate a regular stack frame linkage. 354 * Stop stack traces here if we came from userspace. 355 */ 356 cmpl $8, ISTATE_OFFSET_CS(%esp) 357 jz 0f 358 xorl %ebp, %ebp 359 360 0: 361 362 movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 363 movl ISTATE_OFFSET_EIP(%esp), %eax 364 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 365 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 366 367 cld 368 369 pushl %esp /* pass istate address */ 370 pushl $(\i) /* pass intnum */ 371 372 /* Call exc_dispatch(intnum, istate) */ 373 call exc_dispatch 374 375 addl $8, %esp /* clear arguments from the stack */ 376 377 CLEAR_NT_FLAG 378 379 /* 380 * Restore the selector registers. 381 */ 382 movl ISTATE_OFFSET_GS(%esp), %eax 383 movl ISTATE_OFFSET_FS(%esp), %ebx 384 movl ISTATE_OFFSET_ES(%esp), %ecx 385 movl ISTATE_OFFSET_DS(%esp), %edx 386 387 movl %eax, %gs 388 movl %ebx, %fs 389 movl %ecx, %es 390 movl %edx, %ds 391 392 /* 393 * Restore the scratch registers and the preserved 394 * registers the handler cloberred itself 395 * (i.e. EBX and EBP). 396 */ 397 movl ISTATE_OFFSET_EAX(%esp), %eax 398 movl ISTATE_OFFSET_EBX(%esp), %ebx 399 movl ISTATE_OFFSET_ECX(%esp), %ecx 400 movl ISTATE_OFFSET_EDX(%esp), %edx 401 movl ISTATE_OFFSET_EBP(%esp), %ebp 402 403 addl $(ISTATE_SOFT_SIZE + 4), %esp 404 iret 405 406 .endif 407 408 .align INTERRUPT_ALIGN 409 .if (\n - \i) - 1 410 handler "(\i + 1)", \n 411 .endif 226 227 .ifeq \i - 0x30 # Syscall handler 228 pushl %ds 229 pushl %es 230 pushl %fs 231 pushl %gs 232 233 # 234 # Push syscall arguments onto the stack 235 # 236 # NOTE: The idea behind the order of arguments passed in registers is to 237 # use all scratch registers first and preserved registers next. 238 # An optimized libc syscall wrapper can make use of this setup. 239 # 240 pushl %eax 241 pushl %ebp 242 pushl %edi 243 pushl %esi 244 pushl %ebx 245 pushl %ecx 246 pushl %edx 247 248 # we must fill the data segment registers 249 movw $16, %ax 250 movw %ax, %ds 251 movw %ax, %es 252 253 xorl %ebp, %ebp 254 255 cld 256 sti 257 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) 258 call syscall_handler 259 cli 260 261 movl 20(%esp), %ebp # restore EBP 262 addl $28, %esp # clean-up of parameters 263 264 popl %gs 265 popl %fs 266 popl %es 267 popl %ds 268 269 CLEAR_NT_FLAG 270 iret 271 .else 272 /* 273 * This macro distinguishes between two versions of ia32 exceptions. 274 * One version has error word and the other does not have it. 275 * The latter version fakes the error word on the stack so that the 276 * handlers and istate_t can be the same for both types. 277 */ 278 .iflt \i - 32 279 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 280 # 281 # Exception with error word: do nothing 282 # 283 .else 284 # 285 # Exception without error word: fake up one 286 # 287 pushl $0 288 .endif 289 .else 290 # 291 # Interrupt: fake up one 292 # 293 pushl $0 294 .endif 295 296 subl $ISTATE_SOFT_SIZE, %esp 297 298 # 299 # Save the general purpose registers. 300 # 301 movl %eax, ISTATE_OFFSET_EAX(%esp) 302 movl %ebx, ISTATE_OFFSET_EBX(%esp) 303 movl %ecx, ISTATE_OFFSET_ECX(%esp) 304 movl %edx, ISTATE_OFFSET_EDX(%esp) 305 movl %edi, ISTATE_OFFSET_EDI(%esp) 306 movl %esi, ISTATE_OFFSET_ESI(%esp) 307 movl %ebp, ISTATE_OFFSET_EBP(%esp) 308 309 # 310 # Save the selector registers. 311 # 312 movl %gs, %eax 313 movl %fs, %ebx 314 movl %es, %ecx 315 movl %ds, %edx 316 317 movl %eax, ISTATE_OFFSET_GS(%esp) 318 movl %ebx, ISTATE_OFFSET_FS(%esp) 319 movl %ecx, ISTATE_OFFSET_ES(%esp) 320 movl %edx, ISTATE_OFFSET_DS(%esp) 321 322 # 323 # Switch to kernel selectors. 324 # 325 movl $16, %eax 326 movl %eax, %ds 327 movl %eax, %es 328 329 # 330 # Imitate a regular stack frame linkage. 331 # Stop stack traces here if we came from userspace. 332 # 333 cmpl $8, ISTATE_OFFSET_CS(%esp) 334 jz 0f 335 xorl %ebp, %ebp 336 0: movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 337 movl ISTATE_OFFSET_EIP(%esp), %eax 338 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 339 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 340 341 cld 342 343 pushl %esp # pass istate address 344 pushl $(\i) # pass intnum 345 call exc_dispatch # exc_dispatch(intnum, istate) 346 addl $8, %esp # Clear arguments from the stack 347 348 CLEAR_NT_FLAG 349 350 # 351 # Restore the selector registers. 352 # 353 movl ISTATE_OFFSET_GS(%esp), %eax 354 movl ISTATE_OFFSET_FS(%esp), %ebx 355 movl ISTATE_OFFSET_ES(%esp), %ecx 356 movl ISTATE_OFFSET_DS(%esp), %edx 357 358 movl %eax, %gs 359 movl %ebx, %fs 360 movl %ecx, %es 361 movl %edx, %ds 362 363 # 364 # Restore the scratch registers and the preserved registers the handler 365 # cloberred itself (i.e. EBX and EBP). 366 # 367 movl ISTATE_OFFSET_EAX(%esp), %eax 368 movl ISTATE_OFFSET_EBX(%esp), %ebx 369 movl ISTATE_OFFSET_ECX(%esp), %ecx 370 movl ISTATE_OFFSET_EDX(%esp), %edx 371 movl ISTATE_OFFSET_EBP(%esp), %ebp 372 373 addl $(ISTATE_SOFT_SIZE + 4), %esp 374 iret 375 .endif 376 377 .align INTERRUPT_ALIGN 378 .if (\n- \i) - 1 379 handler "(\i + 1)", \n 380 .endif 412 381 .endm 413 382 414 /* Keep in sync with pm.h! */ 415 #define IDT_ITEMS 64 416 383 # keep in sync with pm.h !!! 384 IDT_ITEMS = 64 417 385 .align INTERRUPT_ALIGN 418 386 interrupt_handlers: 419 h_start: 420 handler 0 IDT_ITEMS 421 h_end: 422 423 /** Print Unicode character to EGA display. 424 * 425 * If CONFIG_EGA is undefined or CONFIG_FB is defined 426 * then this function does nothing. 427 * 428 * Since the EGA can only display Extended ASCII (usually 429 * ISO Latin 1) characters, some of the Unicode characters 430 * can be displayed in a wrong way. Only the newline character 431 * is interpreted, all other characters (even unprintable) are 432 * printed verbatim. 433 * 434 * @param %ebp+0x08 Unicode character to be printed. 435 * 436 */ 437 early_putchar: 438 439 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB))) 440 441 /* Prologue, save preserved registers */ 442 pushl %ebp 443 movl %esp, %ebp 444 pushl %ebx 445 pushl %esi 446 pushl %edi 447 448 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */ 449 xorl %eax, %eax 450 451 /* Read bits 8 - 15 of the cursor address */ 452 movw $0x3d4, %dx 453 movb $0xe, %al 454 outb %al, %dx 455 456 movw $0x3d5, %dx 457 inb %dx, %al 458 shl $8, %ax 459 460 /* Read bits 0 - 7 of the cursor address */ 461 movw $0x3d4, %dx 462 movb $0xf, %al 463 outb %al, %dx 464 465 movw $0x3d5, %dx 466 inb %dx, %al 467 468 /* Sanity check for the cursor on screen */ 469 cmp $2000, %ax 470 jb early_putchar_cursor_ok 471 472 movw $1998, %ax 473 474 early_putchar_cursor_ok: 475 476 movw %ax, %bx 477 shl $1, %eax 478 addl %eax, %edi 479 480 movl 0x08(%ebp), %eax 481 482 cmp $0x0a, %al 483 jne early_putchar_print 484 485 /* Interpret newline */ 486 487 movw %bx, %ax /* %bx -> %dx:%ax */ 488 xorw %dx, %dx 489 490 movw $80, %cx 491 idivw %cx, %ax /* %dx = %bx % 80 */ 492 493 /* %bx <- %bx + 80 - (%bx % 80) */ 494 addw %cx, %bx 495 subw %dx, %bx 496 497 jmp early_putchar_newline 498 499 early_putchar_print: 500 501 /* Print character */ 502 503 movb $0x0e, %ah /* black background, yellow foreground */ 504 stosw 505 inc %bx 506 507 early_putchar_newline: 508 509 /* Sanity check for the cursor on the last line */ 510 cmp $2000, %bx 511 jb early_putchar_no_scroll 512 513 /* Scroll the screen (24 rows) */ 514 movl $(PA2KA(0xb80a0)), %esi 515 movl $(PA2KA(0xb8000)), %edi 516 movl $1920, %ecx 517 rep movsw 518 519 /* Clear the 24th row */ 520 xorl %eax, %eax 521 movl $80, %ecx 522 rep stosw 523 524 /* Go to row 24 */ 525 movw $1920, %bx 526 527 early_putchar_no_scroll: 528 529 /* Write bits 8 - 15 of the cursor address */ 530 movw $0x3d4, %dx 531 movb $0xe, %al 532 outb %al, %dx 533 534 movw $0x3d5, %dx 535 movb %bh, %al 536 outb %al, %dx 537 538 /* Write bits 0 - 7 of the cursor address */ 539 movw $0x3d4, %dx 540 movb $0xf, %al 541 outb %al, %dx 542 543 movw $0x3d5, %dx 544 movb %bl, %al 545 outb %al, %dx 546 547 /* Epilogue, restore preserved registers */ 548 popl %edi 549 popl %esi 550 popl %ebx 551 leave 552 553 #endif 554 555 ret 387 h_start: 388 handler 0 IDT_ITEMS 389 h_end: 556 390 557 391 .data -
kernel/arch/ia32/src/boot/boot.S
re2ea4ab1 r4d1be48 1 /* 2 * Copyright (c) 2001Jakub Jermar3 * Copyright (c) 2005Martin Decky4 *All rights reserved.5 * 6 *Redistribution and use in source and binary forms, with or without7 *modification, are permitted provided that the following conditions8 *are met:9 * 10 *- Redistributions of source code must retain the above copyright11 *notice, this list of conditions and the following disclaimer.12 *- Redistributions in binary form must reproduce the above copyright13 *notice, this list of conditions and the following disclaimer in the14 *documentation and/or other materials provided with the distribution.15 *- The name of the author may not be used to endorse or promote products16 *derived from this software without specific prior written permission.17 * 18 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR19 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES20 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.21 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,22 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT23 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF27 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28 */ 1 # 2 # Copyright (c) 2001-2004 Jakub Jermar 3 # Copyright (c) 2005-2006 Martin Decky 4 # All rights reserved. 5 # 6 # Redistribution and use in source and binary forms, with or without 7 # modification, are permitted provided that the following conditions 8 # are met: 9 # 10 # - Redistributions of source code must retain the above copyright 11 # notice, this list of conditions and the following disclaimer. 12 # - Redistributions in binary form must reproduce the above copyright 13 # notice, this list of conditions and the following disclaimer in the 14 # documentation and/or other materials provided with the distribution. 15 # - The name of the author may not be used to endorse or promote products 16 # derived from this software without specific prior written permission. 17 # 18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 # 29 29 30 30 #include <arch/boot/boot.h> … … 34 34 #include <arch/cpuid.h> 35 35 36 #define START_STACK 36 #define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE) 37 37 38 38 .section K_TEXT_START, "ax" 39 39 40 40 .code32 41 42 .macro pm_error msg43 movl \msg, %esi44 jmp pm_error_halt45 .endm46 47 .macro pm_status msg48 #ifdef CONFIG_EGA49 pushl %esi50 movl \msg, %esi51 call pm_early_puts52 popl %esi53 #endif54 .endm55 56 .macro pm2_status msg57 pushl \msg58 call early_puts59 .endm60 61 41 .align 4 62 42 .global multiboot_image_start … … 64 44 .long MULTIBOOT_HEADER_MAGIC 65 45 .long MULTIBOOT_HEADER_FLAGS 66 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */46 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum 67 47 .long multiboot_header 68 48 .long unmapped_ktext_start … … 73 53 multiboot_image_start: 74 54 cld 75 76 /* Initialize stack pointer */ 77 movl $START_STACK, %esp 78 79 /* Initialize Global Descriptor Table register */ 80 lgdtl KA2PA(bootstrap_gdtr) 81 82 /* Kernel data + stack */ 55 movl $START_STACK, %esp # initialize stack pointer 56 lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register 57 83 58 movw $gdtselector(KDATA_DES), %cx 84 59 movw %cx, %es 85 60 movw %cx, %fs 86 61 movw %cx, %gs 87 movw %cx, %ds 62 movw %cx, %ds # kernel data + stack 88 63 movw %cx, %ss 89 64 … … 91 66 multiboot_meeting_point: 92 67 93 /* Save GRUB arguments */ 94 movl %eax, grub_eax 68 movl %eax, grub_eax # save parameters from GRUB 95 69 movl %ebx, grub_ebx 96 97 pm_status $status_prot98 70 99 71 movl $(INTEL_CPUID_LEVEL), %eax 100 72 cpuid 101 cmp $0x0, %eax /* any function > 0? */73 cmp $0x0, %eax # any function > 0? 102 74 jbe pse_unsupported 103 75 … … 108 80 109 81 pse_unsupported: 110 111 pm_error $err_pse82 movl $pse_msg, %esi 83 jmp error_halt 112 84 113 85 pse_supported: 114 86 115 87 #include "vesa_prot.inc" 116 117 /* Map kernel and turn paging on */88 89 # map kernel and turn paging on 118 90 call map_kernel 119 91 120 /* Create the first stack frame */ 121 pushl $0 122 movl %esp, %ebp 123 124 pm2_status $status_prot2 125 126 /* Call arch_pre_main(grub_eax, grub_ebx) */ 92 # call arch_pre_main(grub_eax, grub_ebx) 127 93 pushl grub_ebx 128 94 pushl grub_eax 129 95 call arch_pre_main 130 131 pm2_status $status_main 132 133 /* Call main_bsp() */ 96 97 # Create the first stack frame 98 pushl $0 99 movl %esp, %ebp 100 134 101 call main_bsp 135 102 136 /* Not reached */103 # not reached 137 104 cli 138 105 hlt0: … … 140 107 jmp hlt0 141 108 142 /** Setup mapping for the kernel.143 *144 * Setup mapping for both the unmapped and mapped sections145 * of the kernel. For simplicity, we map the entire 4G space.146 *147 */148 109 .global map_kernel 149 110 map_kernel: 111 # 112 # Here we setup mapping for both the unmapped and mapped sections of the kernel. 113 # For simplicity, we map the entire 4G space. 114 # 150 115 movl %cr4, %ecx 151 orl $(1 << 4), %ecx /* PSE on */152 andl $(~(1 << 5)), %ecx /* PAE off */116 orl $(1 << 4), %ecx # turn PSE on 117 andl $(~(1 << 5)), %ecx # turn PAE off 153 118 movl %ecx, %cr4 154 119 … … 161 126 movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax 162 127 orl %ebx, %eax 163 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */ 164 movl %eax, (%esi, %ecx, 4) 165 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */ 166 movl %eax, (%edi, %ecx, 4) 128 movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M 129 movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M 167 130 addl $(4 * 1024 * 1024), %ebx 168 131 … … 174 137 175 138 movl %cr0, %ebx 176 orl $(1 << 31), %ebx /* paging on */139 orl $(1 << 31), %ebx # turn paging on 177 140 movl %ebx, %cr0 178 141 ret 179 142 180 /** Print string to EGA display (in light red) and halt. 181 * 182 * Should be executed from 32 bit protected mode with paging 183 * turned off. Stack is not required. This routine is used even 184 * if CONFIG_EGA is not enabled. Since we are going to halt the 185 * CPU anyway, it is always better to at least try to print 186 * some hints. 187 * 188 * @param %esi NULL-terminated string to print. 189 * 190 */ 191 pm_error_halt: 192 movl $0xb8000, %edi /* base of EGA text mode memory */ 143 # Print string from %esi to EGA display (in red) and halt 144 error_halt: 145 movl $0xb8000, %edi # base of EGA text mode memory 193 146 xorl %eax, %eax 194 147 195 /* Read bits 8 - 15 of the cursor address */ 196 movw $0x3d4, %dx 148 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address 197 149 movb $0xe, %al 198 150 outb %al, %dx … … 202 154 shl $8, %ax 203 155 204 /* Read bits 0 - 7 of the cursor address */ 205 movw $0x3d4, %dx 156 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address 206 157 movb $0xf, %al 207 158 outb %al, %dx … … 210 161 inb %dx, %al 211 162 212 /* Sanity check for the cursor on screen */ 213 cmp $2000, %ax 214 jb err_cursor_ok 215 216 movw $1998, %ax 217 218 err_cursor_ok: 163 cmp $1920, %ax 164 jbe cursor_ok 165 166 movw $1920, %ax # sanity check for the cursor on the last line 167 168 cursor_ok: 219 169 220 170 movw %ax, %bx … … 222 172 addl %eax, %edi 223 173 224 err_ploop: 174 movw $0x0c00, %ax # black background, light red foreground 175 176 ploop: 225 177 lodsb 226 227 178 cmp $0, %al 228 je err_ploop_end 229 230 movb $0x0c, %ah /* black background, light red foreground */ 179 je ploop_end 231 180 stosw 232 233 /* Sanity check for the cursor on the last line */234 181 inc %bx 235 cmp $2000, %bx 236 jb err_ploop 237 238 /* Scroll the screen (24 rows) */ 239 movl %esi, %edx 240 movl $0xb80a0, %esi 241 movl $0xb8000, %edi 242 movl $1920, %ecx 243 rep movsw 244 245 /* Clear the 24th row */ 246 xorl %eax, %eax 247 movl $80, %ecx 248 rep stosw 249 250 /* Go to row 24 */ 251 movl %edx, %esi 252 movl $0xb8f00, %edi 253 movw $1920, %bx 254 255 jmp err_ploop 256 err_ploop_end: 257 258 /* Write bits 8 - 15 of the cursor address */ 259 movw $0x3d4, %dx 182 jmp ploop 183 ploop_end: 184 185 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address 260 186 movb $0xe, %al 261 187 outb %al, %dx … … 265 191 outb %al, %dx 266 192 267 /* Write bits 0 - 7 of the cursor address */ 268 movw $0x3d4, %dx 193 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address 269 194 movb $0xf, %al 270 195 outb %al, %dx … … 279 204 jmp hlt1 280 205 281 /** Print string to EGA display (in light green).282 *283 * Should be called from 32 bit protected mode with paging284 * turned off. A stack space of at least 24 bytes is required,285 * but the function does not establish a stack frame.286 *287 * Macros such as pm_status take care that this function288 * is used only when CONFIG_EGA is enabled.289 *290 * @param %esi NULL-terminated string to print.291 *292 */293 pm_early_puts:294 pushl %eax295 pushl %ebx296 pushl %ecx297 pushl %edx298 pushl %edi299 300 movl $0xb8000, %edi /* base of EGA text mode memory */301 xorl %eax, %eax302 303 /* Read bits 8 - 15 of the cursor address */304 movw $0x3d4, %dx305 movb $0xe, %al306 outb %al, %dx307 308 movw $0x3d5, %dx309 inb %dx, %al310 shl $8, %ax311 312 /* Read bits 0 - 7 of the cursor address */313 movw $0x3d4, %dx314 movb $0xf, %al315 outb %al, %dx316 317 movw $0x3d5, %dx318 inb %dx, %al319 320 /* Sanity check for the cursor on screen */321 cmp $2000, %ax322 jb pm_puts_cursor_ok323 324 movw $1998, %ax325 326 pm_puts_cursor_ok:327 328 movw %ax, %bx329 shl $1, %eax330 addl %eax, %edi331 332 pm_puts_ploop:333 lodsb334 335 cmp $0, %al336 je pm_puts_ploop_end337 338 movb $0x0a, %ah /* black background, light green foreground */339 stosw340 341 /* Sanity check for the cursor on the last line */342 inc %bx343 cmp $2000, %bx344 jb pm_puts_ploop345 346 /* Scroll the screen (24 rows) */347 movl %esi, %edx348 movl $0xb80a0, %esi349 movl $0xb8000, %edi350 movl $1920, %ecx351 rep movsw352 353 /* Clear the 24th row */354 xorl %eax, %eax355 movl $80, %ecx356 rep stosw357 358 /* Go to row 24 */359 movl %edx, %esi360 movl $0xb8f00, %edi361 movw $1920, %bx362 363 jmp pm_puts_ploop364 pm_puts_ploop_end:365 366 /* Write bits 8 - 15 of the cursor address */367 movw $0x3d4, %dx368 movb $0xe, %al369 outb %al, %dx370 371 movw $0x3d5, %dx372 movb %bh, %al373 outb %al, %dx374 375 /* Write bits 0 - 7 of the cursor address */376 movw $0x3d4, %dx377 movb $0xf, %al378 outb %al, %dx379 380 movw $0x3d5, %dx381 movb %bl, %al382 outb %al, %dx383 384 popl %edi385 popl %edx386 popl %ecx387 popl %ebx388 popl %eax389 390 ret391 392 /** Print string to EGA display.393 *394 * Should be called from 32 bit protected mode (with paging395 * enabled and stack established). This function is ABI compliant.396 *397 * If CONFIG_EGA is undefined or CONFIG_FB is defined398 * then this function does nothing.399 *400 * @param %ebp+0x08 NULL-terminated string to print.401 *402 */403 early_puts:404 405 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))406 407 /* Prologue, save preserved registers */408 pushl %ebp409 movl %esp, %ebp410 pushl %ebx411 pushl %esi412 pushl %edi413 414 movl 0x08(%ebp), %esi415 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */416 xorl %eax, %eax417 418 /* Read bits 8 - 15 of the cursor address */419 movw $0x3d4, %dx420 movb $0xe, %al421 outb %al, %dx422 423 movw $0x3d5, %dx424 inb %dx, %al425 shl $8, %ax426 427 /* Read bits 0 - 7 of the cursor address */428 movw $0x3d4, %dx429 movb $0xf, %al430 outb %al, %dx431 432 movw $0x3d5, %dx433 inb %dx, %al434 435 /* Sanity check for the cursor on screen */436 cmp $2000, %ax437 jb early_puts_cursor_ok438 439 movw $1998, %ax440 441 early_puts_cursor_ok:442 443 movw %ax, %bx444 shl $1, %eax445 addl %eax, %edi446 447 early_puts_ploop:448 lodsb449 450 cmp $0, %al451 je early_puts_ploop_end452 453 movb $0x0e, %ah /* black background, yellow foreground */454 stosw455 456 /* Sanity check for the cursor on the last line */457 inc %bx458 cmp $2000, %bx459 jb early_puts_ploop460 461 /* Scroll the screen (24 rows) */462 movl %esi, %edx463 movl $(PA2KA(0xb80a0)), %esi464 movl $(PA2KA(0xb8000)), %edi465 movl $1920, %ecx466 rep movsw467 468 /* Clear the 24th row */469 xorl %eax, %eax470 movl $80, %ecx471 rep stosw472 473 /* Go to row 24 */474 movl %edx, %esi475 movl $(PA2KA(0xb8f00)), %edi476 movw $1920, %bx477 478 jmp early_puts_ploop479 early_puts_ploop_end:480 481 /* Write bits 8 - 15 of the cursor address */482 movw $0x3d4, %dx483 movb $0xe, %al484 outb %al, %dx485 486 movw $0x3d5, %dx487 movb %bh, %al488 outb %al, %dx489 490 /* Write bits 0 - 7 of the cursor address */491 movw $0x3d4, %dx492 movb $0xf, %al493 outb %al, %dx494 495 movw $0x3d5, %dx496 movb %bl, %al497 outb %al, %dx498 499 /* Epilogue, restore preserved registers */500 popl %edi501 popl %esi502 popl %ebx503 leave504 505 #endif506 507 ret508 509 206 #include "vesa_real.inc" 510 207 … … 521 218 .long 0 522 219 523 err_pse:220 pse_msg: 524 221 .asciz "Page Size Extension not supported. System halted." 525 222 526 status_prot:527 .asciz "[prot] "528 status_vesa_copy:529 .asciz "[vesa_copy] "530 status_grub_cmdline:531 .asciz "[grub_cmdline] "532 status_vesa_real:533 .asciz "[vesa_real] "534 status_prot2:535 .asciz "[prot2] "536 status_main:537 .asciz "[main] " -
kernel/arch/ia32/src/boot/vesa_prot.inc
re2ea4ab1 r4d1be48 5 5 #define MBINFO_OFFSET_CMDLINE 16 6 6 7 /* Copy real mode VESA initialization code */ 8 9 pm_status $status_vesa_copy 7 # copy real mode VESA initialization code 10 8 11 9 mov $vesa_init, %esi … … 14 12 rep movsb 15 13 16 /* Check for GRUB command line */ 17 18 pm_status $status_grub_cmdline 14 # check for GRUB command line 19 15 20 16 mov grub_eax, %eax … … 27 23 jnc no_cmdline 28 24 29 /* Skip the kernel path in command line */25 # skip the kernel path in command line 30 26 31 27 mov MBINFO_OFFSET_CMDLINE(%ebx), %esi … … 56 52 space_loop_done: 57 53 58 /* Copy at most 23 characters from command line */54 # copy at most 23 characters from command line 59 55 60 56 mov $VESA_INIT_SEGMENT << 4, %edi … … 72 68 cmd_loop_done: 73 69 74 /* Zero termination */70 # zero termination 75 71 76 72 xor %eax, %eax … … 79 75 no_cmdline: 80 76 81 /* Jump to the real mode */ 82 83 pm_status $status_vesa_real 77 # jump to the real mode 84 78 85 79 mov $VESA_INIT_SEGMENT << 4, %edi … … 87 81 88 82 vesa_meeting_point: 89 /* Returned back to protected mode */83 # returned back to protected mode 90 84 91 85 mov %ax, KA2PA(vesa_scanline) -
kernel/arch/ia32/src/boot/vesa_real.inc
re2ea4ab1 r4d1be48 31 31 vesa_init: 32 32 jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init 33 33 34 34 .code16 35 35 vesa_init_real: … … 55 55 pushl %eax 56 56 57 /* Parse default mode string */57 # parse default mode string 58 58 59 59 mov $default_mode - vesa_init, %di … … 65 65 mov (%di), %al 66 66 67 /* Check for digit */67 # check for digit 68 68 69 69 cmp $'0', %al … … 75 75 sub $'0', %al 76 76 77 /* Multiply default_width by 10 and add digit */77 # multiply default_width by 10 and add digit 78 78 79 79 mov default_width - vesa_init, %bx … … 96 96 mov (%di), %al 97 97 98 /* Check for digit */98 # check for digit 99 99 100 100 cmp $'0', %al … … 106 106 sub $'0', %al 107 107 108 /* Multiply default_height by 10 and add digit */108 # multiply default_height by 10 and add digit 109 109 110 110 mov default_height - vesa_init, %bx … … 127 127 mov (%di), %al 128 128 129 /* Check for digit */129 # check for digit 130 130 131 131 cmp $'0', %al … … 137 137 sub $'0', %al 138 138 139 /* Multiply default_bpp by 10 and add digit */139 # multiply default_bpp by 10 and add digit 140 140 141 141 mov default_bpp - vesa_init, %bx … … 167 167 168 168 next_mode: 169 /* Try next mode */ 170 169 # try next mode 171 170 mov %gs:(%si), %cx 172 171 cmp $VESA_END_OF_MODES, %cx … … 187 186 jne no_mode 188 187 189 /* 190 * Check for proper attributes (supported, 191 * color, graphics, linear framebuffer). 192 */ 188 # check for proper attributes (supported, color, graphics, linear framebuffer) 193 189 194 190 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax … … 197 193 jne next_mode 198 194 199 /* Check for proper resolution */195 # check for proper resolution 200 196 201 197 mov default_width - vesa_init, %ax … … 207 203 jne next_mode 208 204 209 /* Check for proper bpp */205 # check for proper bpp 210 206 211 207 mov default_bpp - vesa_init, %al … … 217 213 jne next_mode 218 214 219 /* For 24 bpp modes accept also 32 bit bpp */215 # for 24 bpp modes accept also 32 bit bpp 220 216 221 217 mov $32, %al … … 234 230 jnz no_mode 235 231 236 /* Set 3:2:3 VGA palette */232 # set 3:2:3 VGA palette 237 233 238 234 mov VESA_MODE_BPP_OFFSET(%di), %al … … 245 241 mov $0x100, %ecx 246 242 247 /* Test if VGA compatible registers are present */ 248 bt $5, %ax 243 bt $5, %ax # test if VGA compatible registers are present 249 244 jnc vga_compat 250 245 251 /* Use VESA routine to set the palette */ 252 246 # try VESA routine to set palette 253 247 mov $VESA_SET_PALETTE, %ax 254 248 xor %bl, %bl … … 260 254 261 255 vga_compat: 262 263 /* Use VGA registers to set the palette */ 264 265 movw $0x3c6, %dx /* set palette mask */ 256 # try VGA registers to set palette 257 movw $0x3c6, %dx # set palette mask 266 258 movb $0xff, %al 267 259 outb %al, %dx 268 260 269 movw $0x3c8, %dx /* first index to set */261 movw $0x3c8, %dx # first index to set 270 262 xor %al, %al 271 263 outb %al, %dx 272 264 273 movw $0x3c9, %dx /* data port */265 movw $0x3c9, %dx # data port 274 266 275 267 vga_loop: … … 292 284 vga_not_set: 293 285 294 /* 295 * Store mode parameters: 296 * eax = bpp[8] scanline[16] 297 * ebx = width[16] height[16] 298 * edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8] 299 * esi = blue_mask[8] blue_pos[8] 300 * edi = linear frame buffer 301 */ 286 # store mode parameters 287 # eax = bpp[8] scanline[16] 288 # ebx = width[16] height[16] 289 # edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8] 290 # esi = blue_mask[8] blue_pos[8] 291 # edi = linear frame buffer 302 292 303 293 mov VESA_MODE_BPP_OFFSET(%di), %al … … 338 328 339 329 no_mode: 340 341 /* No prefered mode found */ 342 330 # no prefered mode found 343 331 mov $0x111, %cx 344 332 push %di … … 351 339 cmp $VESA_OK, %al 352 340 jnz text_mode 353 jz set_mode /* force relative jump */341 jz set_mode # force relative jump 354 342 355 343 text_mode: 356 357 /* Reset to EGA text mode (because of problems with VESA) */ 358 344 # reset to EGA text mode (because of problems with VESA) 359 345 mov $0x0003, %ax 360 346 int $0x10 361 347 mov $0xffffffff, %edi 362 348 xor %ax, %ax 363 jz vesa_leave_real /* force relative jump */349 jz vesa_leave_real # force relative jump 364 350 365 351 vga323: -
kernel/arch/ia32/src/boot/vesa_ret.inc
re2ea4ab1 r4d1be48 1 1 .code32 2 2 vesa_init_protected: 3 cld4 5 /* Initialize stack pointer */6 movl $START_STACK, %esp7 8 /* Kernel data + stack */9 3 movw $gdtselector(KDATA_DES), %cx 10 4 movw %cx, %es 11 5 movw %cx, %fs 12 6 movw %cx, %gs 13 movw %cx, %ds 7 movw %cx, %ds # kernel data + stack 14 8 movw %cx, %ss 15 9 10 movl $START_STACK, %esp # initialize stack pointer 11 16 12 jmpl $gdtselector(KTEXT_DES), $vesa_meeting_point -
kernel/arch/ia32/src/smp/apic.c
re2ea4ab1 r4d1be48 76 76 77 77 uint32_t apic_id_mask = 0; 78 uint8_t bsp_l_apic = 0;79 80 78 static irq_t l_apic_timer_irq; 81 79 … … 156 154 } 157 155 158 /** Get Local APIC ID.159 *160 * @return Local APIC ID.161 *162 */163 static uint8_t l_apic_id(void)164 {165 l_apic_id_t idreg;166 167 idreg.value = l_apic[L_APIC_ID];168 return idreg.apic_id;169 }170 171 156 /** Initialize APIC on BSP. */ 172 157 void apic_init(void) … … 223 208 l_apic_init(); 224 209 l_apic_debug(); 225 226 bsp_l_apic = l_apic_id();227 210 } 228 211 … … 477 460 { 478 461 #ifdef LAPIC_VERBOSE 479 printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n", 480 CPU->id, l_apic_id()); 462 printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n", CPU->id, l_apic_id()); 481 463 482 464 lvt_tm_t tm; 483 465 tm.value = l_apic[LVT_Tm]; 484 printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n", 485 tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], 486 tm_mode_str[tm.mode]); 466 printf("LVT Tm: vector=%hhd, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]); 487 467 488 468 lvt_lint_t lint; 489 469 lint.value = l_apic[LVT_LINT0]; 490 printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 491 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 492 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 493 mask_str[lint.masked]); 494 495 lint.value = l_apic[LVT_LINT1]; 496 printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 497 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 498 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 499 mask_str[lint.masked]); 470 printf("LVT LINT0: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]); 471 lint.value = l_apic[LVT_LINT1]; 472 printf("LVT LINT1: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]); 500 473 501 474 lvt_error_t error; 502 475 error.value = l_apic[LVT_Err]; 503 printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector, 504 delivs_str[error.delivs], mask_str[error.masked]); 476 printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]); 505 477 #endif 478 } 479 480 /** Get Local APIC ID. 481 * 482 * @return Local APIC ID. 483 * 484 */ 485 uint8_t l_apic_id(void) 486 { 487 l_apic_id_t idreg; 488 489 idreg.value = l_apic[L_APIC_ID]; 490 return idreg.apic_id; 506 491 } 507 492 -
kernel/arch/ia32/src/smp/mps.c
re2ea4ab1 r4d1be48 72 72 static size_t l_intr_entry_cnt = 0; 73 73 74 static uint8_t mps_cpu_apic_id(size_t i)74 static uint8_t get_cpu_apic_id(size_t i) 75 75 { 76 76 ASSERT(i < processor_entry_cnt); … … 79 79 } 80 80 81 static bool mps_cpu_enabled(size_t i)81 static bool is_cpu_enabled(size_t i) 82 82 { 83 83 ASSERT(i < processor_entry_cnt); … … 85 85 /* 86 86 * FIXME: The current local APIC driver limits usable 87 * CPUIDs to 8.87 * APIC IDs to 8. 88 88 * 89 89 */ 90 if ( i> 7)90 if (get_cpu_apic_id(i) > 7) 91 91 return false; 92 92 … … 94 94 } 95 95 96 static bool mps_cpu_bootstrap(size_t i)96 static bool is_bsp(size_t i) 97 97 { 98 98 ASSERT(i < processor_entry_cnt); … … 118 118 */ 119 119 struct smp_config_operations mps_config_operations = { 120 .cpu_enabled = mps_cpu_enabled,121 .cpu_bootstrap = mps_cpu_bootstrap,122 .cpu_apic_id = mps_cpu_apic_id,120 .cpu_enabled = is_cpu_enabled, 121 .cpu_bootstrap = is_bsp, 122 .cpu_apic_id = get_cpu_apic_id, 123 123 .irq_to_pin = mps_irq_to_pin 124 124 }; -
kernel/arch/ia32/src/smp/smp.c
re2ea4ab1 r4d1be48 62 62 void smp_init(void) 63 63 { 64 uintptr_t l_apic_address; 65 uintptr_t io_apic_address; 66 64 67 if (acpi_madt) { 65 68 acpi_madt_parse(); … … 72 75 } 73 76 77 l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, 78 FRAME_ATOMIC | FRAME_KA); 79 if (!l_apic_address) 80 panic("Cannot allocate address for l_apic."); 81 82 io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, 83 FRAME_ATOMIC | FRAME_KA); 84 if (!io_apic_address) 85 panic("Cannot allocate address for io_apic."); 86 74 87 if (config.cpu_count > 1) { 75 l_apic = (uint32_t *) hw_map((uintptr_t) l_apic, PAGE_SIZE); 76 io_apic = (uint32_t *) hw_map((uintptr_t) io_apic, PAGE_SIZE); 88 page_table_lock(AS_KERNEL, true); 89 page_mapping_insert(AS_KERNEL, l_apic_address, 90 (uintptr_t) l_apic, PAGE_NOT_CACHEABLE | PAGE_WRITE); 91 page_mapping_insert(AS_KERNEL, io_apic_address, 92 (uintptr_t) io_apic, PAGE_NOT_CACHEABLE | PAGE_WRITE); 93 page_table_unlock(AS_KERNEL, true); 94 95 l_apic = (uint32_t *) l_apic_address; 96 io_apic = (uint32_t *) io_apic_address; 77 97 } 78 98 } … … 113 133 apic_init(); 114 134 135 uint8_t apic = l_apic_id(); 136 115 137 for (i = 0; i < config.cpu_count; i++) { 116 138 /* … … 126 148 continue; 127 149 128 if (ops->cpu_apic_id(i) == bsp_l_apic) {129 printf(" kmp: bad processor entry #%u, will not send IPI "130 "to myself\n", i);150 if (ops->cpu_apic_id(i) == apic) { 151 printf("%s: bad processor entry #%u, will not send IPI " 152 "to myself\n", __FUNCTION__, i); 131 153 continue; 132 154 } -
kernel/arch/ia64/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 *Copyright (c) 2005 Jakub Jermar3 *All rights reserved.4 * 5 *Redistribution and use in source and binary forms, with or without6 *modification, are permitted provided that the following conditions7 *are met:8 * 9 *- Redistributions of source code must retain the above copyright10 *notice, this list of conditions and the following disclaimer.11 *- Redistributions in binary form must reproduce the above copyright12 *notice, this list of conditions and the following disclaimer in the13 *documentation and/or other materials provided with the distribution.14 *- The name of the author may not be used to endorse or promote products15 *derived from this software without specific prior written permission.16 * 17 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27 */ 1 # 2 # Copyright (c) 2005 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 28 29 29 #include <arch/register.h> 30 30 31 31 .text 32 .global memcpy33 .global memcpy_from_uspace34 .global memcpy_to_uspace35 .global memcpy_from_uspace_failover_address36 .global memcpy_to_uspace_failover_address37 32 38 33 /** Copy memory from/to userspace. … … 44 39 * @param in1 Source address. 45 40 * @param in2 Number of byte to copy. 46 *47 41 */ 42 .global memcpy 43 .global memcpy_from_uspace 44 .global memcpy_to_uspace 45 .global memcpy_from_uspace_failover_address 46 .global memcpy_to_uspace_failover_address 48 47 memcpy: 49 48 memcpy_from_uspace: 50 49 memcpy_to_uspace: 51 50 alloc loc0 = ar.pfs, 3, 1, 0, 0 52 51 53 52 adds r14 = 7, in1 54 53 mov r2 = ar.lc … … 56 55 and r14 = -8, r14 ;; 57 56 cmp.ne p6, p7 = r14, in1 58 (p7) br.cond.dpnt 3f ;; 57 (p7) br.cond.dpnt 3f ;; 58 0: 59 cmp.ne p6, p7 = 0, in2 60 (p7) br.cond.dpnt 2f ;; 61 (p6) adds r14 = -1, in2 62 (p6) mov r16 = r0 63 (p6) mov r17 = r0 ;; 64 (p6) mov ar.lc = r14 65 1: 66 add r14 = r16, in1 67 add r15 = r16, in0 68 adds r17 = 1, r17 ;; 69 ld1 r14 = [r14] 70 mov r16 = r17 ;; 71 st1 [r15] = r14 72 br.cloop.sptk.few 1b ;; 73 2: 74 mov ar.lc = r2 75 mov ar.pfs = loc0 76 br.ret.sptk.many rp 77 3: 78 adds r14 = 7, in0 ;; 79 and r14 = -8, r14 ;; 80 cmp.eq p6, p7 = r14, in0 81 (p7) br.cond.dptk 0b 82 shr.u r18 = in2, 3 ;; 83 cmp.ne p6, p7 = 0, r18 84 (p7) br.cond.dpnt 5f ;; 85 (p6) adds r14 = -1, r18 86 (p6) mov r16 = r0 87 (p6) mov r17 = r0 ;; 88 (p6) mov ar.lc = r14 89 4: 90 shladd r14 = r16, 3, r0 91 adds r16 = 1, r17 ;; 92 add r15 = in1, r14 93 add r14 = in0, r14 94 mov r17 = r16 ;; 95 ld8 r15 = [r15] ;; 96 st8 [r14] = r15 97 br.cloop.sptk.few 4b 98 5: 99 and r15 = 7, in2 100 shladd r14 = r18, 3, r0 101 mov r16 = r0 102 mov r18 = r0 ;; 103 cmp.eq p6, p7 = 0, r15 104 add in0 = r14, in0 105 adds r15 = -1, r15 106 add r17 = r14, in1 107 (p6) br.cond.dpnt 2b ;; 108 mov ar.lc = r15 109 6: 110 add r14 = r16, r17 111 add r15 = r16, in0 112 adds r16 = 1, r18 ;; 113 ld1 r14 = [r14] 114 mov r18 = r16 ;; 115 st1 [r15] = r14 116 br.cloop.sptk.few 6b ;; 117 mov ar.lc = r2 118 mov ar.pfs = loc0 119 br.ret.sptk.many rp 59 120 60 0:61 62 cmp.ne p6, p7 = 0, in263 (p7) br.cond.dpnt 2f ;;64 (p6) adds r14 = -1, in265 (p6) mov r16 = r066 (p6) mov r17 = r0 ;;67 (p6) mov ar.lc = r1468 69 1:70 71 add r14 = r16, in172 add r15 = r16, in073 adds r17 = 1, r17 ;;74 ld1 r14 = [r14]75 mov r16 = r17 ;;76 st1 [r15] = r1477 br.cloop.sptk.few 1b ;;78 79 2:80 81 mov ar.lc = r282 mov ar.pfs = loc083 br.ret.sptk.many rp84 85 3:86 87 adds r14 = 7, in0 ;;88 and r14 = -8, r14 ;;89 cmp.eq p6, p7 = r14, in090 (p7) br.cond.dptk 0b91 shr.u r18 = in2, 3 ;;92 cmp.ne p6, p7 = 0, r1893 (p7) br.cond.dpnt 5f ;;94 (p6) adds r14 = -1, r1895 (p6) mov r16 = r096 (p6) mov r17 = r0 ;;97 (p6) mov ar.lc = r1498 99 4:100 101 shladd r14 = r16, 3, r0102 adds r16 = 1, r17 ;;103 add r15 = in1, r14104 add r14 = in0, r14105 mov r17 = r16 ;;106 ld8 r15 = [r15] ;;107 st8 [r14] = r15108 br.cloop.sptk.few 4b109 110 5:111 112 and r15 = 7, in2113 shladd r14 = r18, 3, r0114 mov r16 = r0115 mov r18 = r0 ;;116 cmp.eq p6, p7 = 0, r15117 add in0 = r14, in0118 adds r15 = -1, r15119 add r17 = r14, in1120 (p6) br.cond.dpnt 2b ;;121 mov ar.lc = r15122 123 6:124 125 add r14 = r16, r17126 add r15 = r16, in0127 adds r16 = 1, r18 ;;128 ld1 r14 = [r14]129 mov r18 = r16 ;;130 st1 [r15] = r14131 br.cloop.sptk.few 6b ;;132 mov ar.lc = r2133 mov ar.pfs = loc0134 br.ret.sptk.many rp135 136 121 memcpy_from_uspace_failover_address: 137 122 memcpy_to_uspace_failover_address: 138 /* Return 0 on failure */ 139 mov r8 = r0 123 mov r8 = r0 /* return 0 on failure */ 140 124 mov ar.pfs = loc0 141 125 br.ret.sptk.many rp … … 161 145 * @param in4 Value to be stored in IPSR. 162 146 * @param in5 Value to be stored in RSC. 163 *164 147 */ 165 148 .global switch_to_userspace 166 149 switch_to_userspace: 167 150 alloc loc0 = ar.pfs, 6, 3, 0, 0 168 169 /* Disable interruption collection and interrupts */ 170 rsm (PSR_IC_MASK | PSR_I_MASK) 151 rsm (PSR_IC_MASK | PSR_I_MASK) /* disable interruption collection and interrupts */ 171 152 srlz.d ;; 172 153 srlz.i ;; … … 175 156 mov cr.iip = in0 176 157 mov r12 = in1 177 158 178 159 xor r1 = r1, r1 179 160 … … 184 165 movl loc2 = PFM_MASK ;; 185 166 and loc1 = loc2, loc1 ;; 186 mov cr.ifs = loc1 ;; 187 167 mov cr.ifs = loc1 ;; /* prevent decrementing BSP by rfi */ 168 188 169 invala 189 170 190 171 mov loc1 = ar.rsc ;; 191 and loc1 = ~3, loc1 ;; 192 mov ar.rsc = loc1 ;; 193 172 and loc1 = ~3, loc1 ;; 173 mov ar.rsc = loc1 ;; /* put RSE into enforced lazy mode */ 174 194 175 flushrs ;; 195 176 … … 200 181 201 182 rfi ;; 202 203 .global early_putchar204 early_putchar:205 br.ret.sptk.many b0 -
kernel/arch/ia64/src/start.S
re2ea4ab1 r4d1be48 47 47 48 48 stack0: 49 50 #51 # Kernel entry point.52 #53 # This is where we are passed control from the boot code.54 # Register contents:55 #56 # r2 Address of the boot code's bootinfo structure.57 #58 49 kernel_image_start: 59 50 .auto … … 166 157 loadrs 167 158 168 # 169 # Initialize memory stack to some sane value and allocate a scratch are 170 # on it. 171 # 172 movl sp = stack0 ;; 173 add sp = -16, sp 159 # Initialize memory stack to some sane value 160 movl r12 = stack0 ;; 161 add r12 = -16, r12 /* allocate a scratch area on the stack */ 174 162 175 163 # Initialize gp (Global Pointer) register 176 movl gp = kernel_image_start 164 movl r20 = (VRN_KERNEL << VRN_SHIFT) ;; 165 or r20 = r20, r1 ;; 166 movl r1 = kernel_image_start 177 167 178 # 179 # Initialize bootinfo on BSP. 180 # 181 movl r20 = (VRN_KERNEL << VRN_SHIFT) ;; 182 or r20 = r20, r2 ;; 168 /* 169 * Initialize bootinfo on BSP. 170 */ 183 171 addl r21 = @gprel(bootinfo), gp ;; 184 172 st8 [r21] = r20 -
kernel/arch/mips32/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 * Copyright (c) 2003Jakub Jermar3 *All rights reserved.4 * 5 *Redistribution and use in source and binary forms, with or without6 *modification, are permitted provided that the following conditions7 *are met:8 * 9 *- Redistributions of source code must retain the above copyright10 *notice, this list of conditions and the following disclaimer.11 *- Redistributions in binary form must reproduce the above copyright12 *notice, this list of conditions and the following disclaimer in the13 *documentation and/or other materials provided with the distribution.14 *- The name of the author may not be used to endorse or promote products15 *derived from this software without specific prior written permission.16 * 17 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27 */ 1 # 2 # Copyright (c) 2003-2004 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 28 29 29 #include <arch/asm/regname.h> … … 57 57 nop 58 58 59 59 60 .global memsetb 60 61 memsetb: … … 62 63 nop 63 64 65 64 66 .global memsetw 65 67 memsetw: 66 68 j _memsetw 67 69 nop 70 68 71 69 72 .global memcpy … … 75 78 memcpy_from_uspace: 76 79 memcpy_to_uspace: 77 move $t2, $a0 /* save dst */80 move $t2, $a0 # save dst 78 81 79 82 addiu $v0, $a1, 3 80 li $v1, -4 /* 0xfffffffffffffffc */83 li $v1, -4 # 0xfffffffffffffffc 81 84 and $v0, $v0, $v1 82 85 beq $a1, $v0, 3f … … 146 149 move $v0, $zero 147 150 151 152 148 153 .macro fpu_gp_save reg ctx 149 154 mfc1 $t0, $\reg … … 159 164 cfc1 $t0, $1 160 165 sw $t0, (\reg + 32) * 4(\ctx) 161 .endm 166 .endm 162 167 163 168 .macro fpu_ct_restore reg ctx … … 165 170 ctc1 $t0, $\reg 166 171 .endm 172 167 173 168 174 .global fpu_context_save … … 307 313 j $ra 308 314 nop 309 310 .global early_putchar311 early_putchar:312 j $ra313 nop -
kernel/arch/ppc32/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 *Copyright (c) 2005 Martin Decky3 *All rights reserved.4 * 5 *Redistribution and use in source and binary forms, with or without6 *modification, are permitted provided that the following conditions7 *are met:8 * 9 *- Redistributions of source code must retain the above copyright10 *notice, this list of conditions and the following disclaimer.11 *- Redistributions in binary form must reproduce the above copyright12 *notice, this list of conditions and the following disclaimer in the13 *documentation and/or other materials provided with the distribution.14 *- The name of the author may not be used to endorse or promote products15 *derived from this software without specific prior written permission.16 * 17 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27 */ 1 # 2 # Copyright (c) 2005 Martin Decky 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 28 29 29 #include <arch/asm/regname.h> … … 42 42 .global memcpy_from_uspace_failover_address 43 43 .global memcpy_to_uspace_failover_address 44 .global early_putchar45 44 46 45 userspace_asm: 47 46 48 /* 49 * r3 = uspace_uarg 50 * r4 = stack 51 * r5 = entry 52 */ 53 54 /* Disable interrupts */ 47 # r3 = uspace_uarg 48 # r4 = stack 49 # r5 = entry 50 51 # disable interrupts 55 52 56 53 mfmsr r31 … … 58 55 mtmsr r31 59 56 60 /* Set entry point */57 # set entry point 61 58 62 59 mtsrr0 r5 63 60 64 /* Set problem state, enable interrupts */61 # set problem state, enable interrupts 65 62 66 63 ori r31, r31, MSR_PR … … 68 65 mtsrr1 r31 69 66 70 /* Set stack */67 # set stack 71 68 72 69 mr sp, r4 73 70 74 /* %r6 is defined to hold pcb_ptr - set it to 0 */71 # %r6 is defined to hold pcb_ptr - set it to 0 75 72 76 73 xor r6, r6, r6 77 74 78 /* Jump to userspace */75 # jump to userspace 79 76 80 77 rfi … … 82 79 iret: 83 80 84 /* Disable interrupts */81 # disable interrupts 85 82 86 83 mfmsr r31 … … 144 141 iret_syscall: 145 142 146 /* Reset decrementer */143 # reset decrementer 147 144 148 145 li r31, 1000 149 146 mtdec r31 150 147 151 /* Disable interrupts */148 # disable interrupts 152 149 153 150 mfmsr r31 … … 281 278 memcpy_from_uspace_failover_address: 282 279 memcpy_to_uspace_failover_address: 283 /* Return zero, failure */280 # return zero, failure 284 281 xor r3, r3, r3 285 282 blr 286 287 early_putchar:288 blr -
kernel/arch/sparc64/src/asm.S
re2ea4ab1 r4d1be48 1 /* 2 *Copyright (c) 2005 Jakub Jermar3 *All rights reserved.4 * 5 *Redistribution and use in source and binary forms, with or without6 *modification, are permitted provided that the following conditions7 *are met:8 * 9 *- Redistributions of source code must retain the above copyright10 *notice, this list of conditions and the following disclaimer.11 *- Redistributions in binary form must reproduce the above copyright12 *notice, this list of conditions and the following disclaimer in the13 *documentation and/or other materials provided with the distribution.14 *- The name of the author may not be used to endorse or promote products15 *derived from this software without specific prior written permission.16 * 17 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR18 *IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES19 *OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.20 *IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,21 *INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT22 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23 *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24 *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF26 *THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27 */ 1 # 2 # Copyright (c) 2005 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 28 29 29 #include <arch/arch.h> … … 32 32 .text 33 33 34 .register %g2, #scratch35 .register %g3, #scratch34 .register %g2, #scratch 35 .register %g3, #scratch 36 36 37 37 /* … … 40 40 .global memcpy 41 41 memcpy: 42 mov %o0, %o3 /* save dst */ 43 add %o1, 7, %g1 44 and %g1, -8, %g1 45 cmp %o1, %g1 46 be,pn %xcc, 3f 47 add %o0, 7, %g1 48 mov 0, %g3 49 50 0: 51 52 brz,pn %o2, 2f 53 mov 0, %g2 54 55 1: 56 57 ldub [%g3 + %o1], %g1 58 add %g2, 1, %g2 59 cmp %o2, %g2 60 stb %g1, [%g3 + %o0] 61 bne,pt %xcc, 1b 62 mov %g2, %g3 63 64 2: 65 66 jmp %o7 + 8 /* exit point */ 67 mov %o3, %o0 68 69 3: 70 71 and %g1, -8, %g1 72 cmp %o0, %g1 73 bne,pt %xcc, 0b 74 mov 0, %g3 75 srlx %o2, 3, %g4 76 brz,pn %g4, 5f 77 mov 0, %g5 78 79 4: 80 81 sllx %g3, 3, %g2 82 add %g5, 1, %g3 83 ldx [%o1 + %g2], %g1 84 mov %g3, %g5 85 cmp %g4, %g3 86 bne,pt %xcc, 4b 87 stx %g1, [%o0 + %g2] 88 89 5: 90 91 and %o2, 7, %o2 92 brz,pn %o2, 2b 93 sllx %g4, 3, %g1 94 mov 0, %g2 95 add %g1, %o0, %o0 96 add %g1, %o1, %g4 97 mov 0, %g3 98 99 6: 100 101 ldub [%g2 + %g4], %g1 102 stb %g1, [%g2 + %o0] 103 add %g3, 1, %g2 104 cmp %o2, %g2 105 bne,pt %xcc, 6b 106 mov %g2, %g3 107 108 jmp %o7 + 8 /* exit point */ 109 mov %o3, %o0 42 mov %o0, %o3 ! save dst 43 add %o1, 7, %g1 44 and %g1, -8, %g1 45 cmp %o1, %g1 46 be,pn %xcc, 3f 47 add %o0, 7, %g1 48 mov 0, %g3 49 0: 50 brz,pn %o2, 2f 51 mov 0, %g2 52 1: 53 ldub [%g3 + %o1], %g1 54 add %g2, 1, %g2 55 cmp %o2, %g2 56 stb %g1, [%g3 + %o0] 57 bne,pt %xcc, 1b 58 mov %g2, %g3 59 2: 60 jmp %o7 + 8 ! exit point 61 mov %o3, %o0 62 3: 63 and %g1, -8, %g1 64 cmp %o0, %g1 65 bne,pt %xcc, 0b 66 mov 0, %g3 67 srlx %o2, 3, %g4 68 brz,pn %g4, 5f 69 mov 0, %g5 70 4: 71 sllx %g3, 3, %g2 72 add %g5, 1, %g3 73 ldx [%o1 + %g2], %g1 74 mov %g3, %g5 75 cmp %g4, %g3 76 bne,pt %xcc, 4b 77 stx %g1, [%o0 + %g2] 78 5: 79 and %o2, 7, %o2 80 brz,pn %o2, 2b 81 sllx %g4, 3, %g1 82 mov 0, %g2 83 add %g1, %o0, %o0 84 add %g1, %o1, %g4 85 mov 0, %g3 86 6: 87 ldub [%g2 + %g4], %g1 88 stb %g1, [%g2 + %o0] 89 add %g3, 1, %g2 90 cmp %o2, %g2 91 bne,pt %xcc, 6b 92 mov %g2, %g3 93 94 jmp %o7 + 8 ! exit point 95 mov %o3, %o0 110 96 111 97 /* … … 114 100 .global memcpy_from_uspace 115 101 memcpy_from_uspace: 116 mov %o0, %o3 /* save dst */ 117 add %o1, 7, %g1 118 and %g1, -8, %g1 119 cmp %o1, %g1 120 be,pn %xcc, 3f 121 add %o0, 7, %g1 122 mov 0, %g3 123 124 0: 125 126 brz,pn %o2, 2f 127 mov 0, %g2 128 129 1: 130 131 lduba [%g3 + %o1] ASI_AIUS, %g1 132 add %g2, 1, %g2 133 cmp %o2, %g2 134 stb %g1, [%g3 + %o0] 135 bne,pt %xcc, 1b 136 mov %g2, %g3 137 138 2: 139 140 jmp %o7 + 8 /* exit point */ 141 mov %o3, %o0 142 143 3: 144 145 and %g1, -8, %g1 146 cmp %o0, %g1 147 bne,pt %xcc, 0b 148 mov 0, %g3 149 srlx %o2, 3, %g4 150 brz,pn %g4, 5f 151 mov 0, %g5 152 153 4: 154 155 sllx %g3, 3, %g2 156 add %g5, 1, %g3 157 ldxa [%o1 + %g2] ASI_AIUS, %g1 158 mov %g3, %g5 159 cmp %g4, %g3 160 bne,pt %xcc, 4b 161 stx %g1, [%o0 + %g2] 162 163 5: 164 165 and %o2, 7, %o2 166 brz,pn %o2, 2b 167 sllx %g4, 3, %g1 168 mov 0, %g2 169 add %g1, %o0, %o0 170 add %g1, %o1, %g4 171 mov 0, %g3 172 173 6: 174 175 lduba [%g2 + %g4] ASI_AIUS, %g1 176 stb %g1, [%g2 + %o0] 177 add %g3, 1, %g2 178 cmp %o2, %g2 179 bne,pt %xcc, 6b 180 mov %g2, %g3 181 182 jmp %o7 + 8 /* exit point */ 183 mov %o3, %o0 102 mov %o0, %o3 ! save dst 103 add %o1, 7, %g1 104 and %g1, -8, %g1 105 cmp %o1, %g1 106 be,pn %xcc, 3f 107 add %o0, 7, %g1 108 mov 0, %g3 109 0: 110 brz,pn %o2, 2f 111 mov 0, %g2 112 1: 113 lduba [%g3 + %o1] ASI_AIUS, %g1 114 add %g2, 1, %g2 115 cmp %o2, %g2 116 stb %g1, [%g3 + %o0] 117 bne,pt %xcc, 1b 118 mov %g2, %g3 119 2: 120 jmp %o7 + 8 ! exit point 121 mov %o3, %o0 122 3: 123 and %g1, -8, %g1 124 cmp %o0, %g1 125 bne,pt %xcc, 0b 126 mov 0, %g3 127 srlx %o2, 3, %g4 128 brz,pn %g4, 5f 129 mov 0, %g5 130 4: 131 sllx %g3, 3, %g2 132 add %g5, 1, %g3 133 ldxa [%o1 + %g2] ASI_AIUS, %g1 134 mov %g3, %g5 135 cmp %g4, %g3 136 bne,pt %xcc, 4b 137 stx %g1, [%o0 + %g2] 138 5: 139 and %o2, 7, %o2 140 brz,pn %o2, 2b 141 sllx %g4, 3, %g1 142 mov 0, %g2 143 add %g1, %o0, %o0 144 add %g1, %o1, %g4 145 mov 0, %g3 146 6: 147 lduba [%g2 + %g4] ASI_AIUS, %g1 148 stb %g1, [%g2 + %o0] 149 add %g3, 1, %g2 150 cmp %o2, %g2 151 bne,pt %xcc, 6b 152 mov %g2, %g3 153 154 jmp %o7 + 8 ! exit point 155 mov %o3, %o0 184 156 185 157 /* … … 188 160 .global memcpy_to_uspace 189 161 memcpy_to_uspace: 190 mov %o0, %o3 /* save dst */ 191 add %o1, 7, %g1 192 and %g1, -8, %g1 193 cmp %o1, %g1 194 be,pn %xcc, 3f 195 add %o0, 7, %g1 196 mov 0, %g3 197 198 0: 199 200 brz,pn %o2, 2f 201 mov 0, %g2 202 203 1: 204 205 ldub [%g3 + %o1], %g1 206 add %g2, 1, %g2 207 cmp %o2, %g2 208 stba %g1, [%g3 + %o0] ASI_AIUS 209 bne,pt %xcc, 1b 210 mov %g2, %g3 211 212 2: 213 214 jmp %o7 + 8 /* exit point */ 215 mov %o3, %o0 216 217 3: 218 219 and %g1, -8, %g1 220 cmp %o0, %g1 221 bne,pt %xcc, 0b 222 mov 0, %g3 223 srlx %o2, 3, %g4 224 brz,pn %g4, 5f 225 mov 0, %g5 226 227 4: 228 229 sllx %g3, 3, %g2 230 add %g5, 1, %g3 231 ldx [%o1 + %g2], %g1 232 mov %g3, %g5 233 cmp %g4, %g3 234 bne,pt %xcc, 4b 235 stxa %g1, [%o0 + %g2] ASI_AIUS 236 237 5: 238 239 and %o2, 7, %o2 240 brz,pn %o2, 2b 241 sllx %g4, 3, %g1 242 mov 0, %g2 243 add %g1, %o0, %o0 244 add %g1, %o1, %g4 245 mov 0, %g3 246 247 6: 248 249 ldub [%g2 + %g4], %g1 250 stba %g1, [%g2 + %o0] ASI_AIUS 251 add %g3, 1, %g2 252 cmp %o2, %g2 253 bne,pt %xcc, 6b 254 mov %g2, %g3 255 256 jmp %o7 + 8 /* exit point */ 257 mov %o3, %o0 162 mov %o0, %o3 ! save dst 163 add %o1, 7, %g1 164 and %g1, -8, %g1 165 cmp %o1, %g1 166 be,pn %xcc, 3f 167 add %o0, 7, %g1 168 mov 0, %g3 169 0: 170 brz,pn %o2, 2f 171 mov 0, %g2 172 1: 173 ldub [%g3 + %o1], %g1 174 add %g2, 1, %g2 175 cmp %o2, %g2 176 stba %g1, [%g3 + %o0] ASI_AIUS 177 bne,pt %xcc, 1b 178 mov %g2, %g3 179 2: 180 jmp %o7 + 8 ! exit point 181 mov %o3, %o0 182 3: 183 and %g1, -8, %g1 184 cmp %o0, %g1 185 bne,pt %xcc, 0b 186 mov 0, %g3 187 srlx %o2, 3, %g4 188 brz,pn %g4, 5f 189 mov 0, %g5 190 4: 191 sllx %g3, 3, %g2 192 add %g5, 1, %g3 193 ldx [%o1 + %g2], %g1 194 mov %g3, %g5 195 cmp %g4, %g3 196 bne,pt %xcc, 4b 197 stxa %g1, [%o0 + %g2] ASI_AIUS 198 5: 199 and %o2, 7, %o2 200 brz,pn %o2, 2b 201 sllx %g4, 3, %g1 202 mov 0, %g2 203 add %g1, %o0, %o0 204 add %g1, %o1, %g4 205 mov 0, %g3 206 6: 207 ldub [%g2 + %g4], %g1 208 stba %g1, [%g2 + %o0] ASI_AIUS 209 add %g3, 1, %g2 210 cmp %o2, %g2 211 bne,pt %xcc, 6b 212 mov %g2, %g3 213 214 jmp %o7 + 8 ! exit point 215 mov %o3, %o0 258 216 259 217 .global memcpy_from_uspace_failover_address … … 261 219 memcpy_from_uspace_failover_address: 262 220 memcpy_to_uspace_failover_address: 263 jmp %o7 + 8 /* exit point */264 mov %g0, %o0 /* return 0 on failure */221 jmp %o7 + 8 ! exit point 222 mov %g0, %o0 ! return 0 on failure 265 223 266 224 .global memsetb … … 274 232 nop 275 233 276 .global early_putchar277 early_putchar:278 retl279 nop -
kernel/arch/sparc64/src/trap/sun4v/interrupt.c
re2ea4ab1 r4d1be48 111 111 ((void (*)(void)) data1)(); 112 112 } else { 113 printf("Spurious interrupt on %d, data = % " PRIx64 ".\n",113 printf("Spurious interrupt on %d, data = %lx.\n", 114 114 CPU->arch.id, data1); 115 115 } -
kernel/genarch/src/acpi/madt.c
re2ea4ab1 r4d1be48 95 95 /* 96 96 * FIXME: The current local APIC driver limits usable 97 * CPUIDs to 8.97 * APIC IDs to 8. 98 98 * 99 99 */ 100 if ( i> 7)100 if (madt_cpu_apic_id(i) > 7) 101 101 return false; 102 102 … … 111 111 return ((struct madt_l_apic *) 112 112 madt_entries_index[madt_l_apic_entry_index + i])->apic_id == 113 bsp_l_apic;113 l_apic_id(); 114 114 } 115 115 … … 131 131 }; 132 132 133 static int madt_cmp(void *a, void *b , void *arg)134 { 135 uint8_t typea = ( *((struct madt_apic_header **) a))->type;136 uint8_t typeb = ( *((struct madt_apic_header **) b))->type;133 static int madt_cmp(void *a, void *b) 134 { 135 uint8_t typea = ((struct madt_apic_header *) a)->type; 136 uint8_t typeb = ((struct madt_apic_header *) b)->type; 137 137 138 138 if (typea > typeb) … … 147 147 static void madt_l_apic_entry(struct madt_l_apic *la, size_t i) 148 148 { 149 if ( madt_l_apic_entry_cnt == 0)149 if (!madt_l_apic_entry_cnt++) 150 150 madt_l_apic_entry_index = i; 151 152 madt_l_apic_entry_cnt++;153 151 154 152 if (!(la->flags & 0x1)) { … … 162 160 static void madt_io_apic_entry(struct madt_io_apic *ioa, size_t i) 163 161 { 164 if ( madt_io_apic_entry_cnt == 0) {162 if (!madt_io_apic_entry_cnt++) { 165 163 /* Remember index of the first io apic entry */ 166 164 madt_io_apic_entry_index = i; … … 169 167 /* Currently not supported */ 170 168 } 171 172 madt_io_apic_entry_cnt++;173 169 } 174 170 … … 194 190 /* Count MADT entries */ 195 191 unsigned int madt_entries_index_cnt = 0; 196 for (hdr = acpi_madt->apic_header; hdr < end;192 for (hdr = &acpi_madt->apic_header[0]; hdr < end; 197 193 hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) 198 194 madt_entries_index_cnt++; … … 200 196 /* Create MADT APIC entries index array */ 201 197 madt_entries_index = (struct madt_apic_header **) 202 malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header * ),198 malloc(madt_entries_index_cnt * sizeof(struct madt_apic_header **), 203 199 FRAME_ATOMIC); 204 200 if (!madt_entries_index) … … 207 203 size_t i = 0; 208 204 209 for (hdr = acpi_madt->apic_header; hdr < end; 210 hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) { 211 madt_entries_index[i] = hdr; 212 i++; 213 } 205 for (hdr = &acpi_madt->apic_header[0]; hdr < end; 206 hdr = (struct madt_apic_header *) (((uint8_t *) hdr) + hdr->length)) 207 madt_entries_index[i++] = hdr; 214 208 215 209 /* Sort MADT index structure */ 216 if (!gsort(madt_entries_index, madt_entries_index_cnt, 217 sizeof(struct madt_apic_header *), madt_cmp, NULL)) 218 panic("Sorting error."); 210 qsort(madt_entries_index, madt_entries_index_cnt, sizeof(uintptr_t), 211 &madt_cmp); 219 212 220 213 /* Parse MADT entries */ -
kernel/generic/include/console/console.h
re2ea4ab1 r4d1be48 56 56 extern outdev_t *stdout; 57 57 58 extern void early_putchar(wchar_t);59 60 58 extern indev_t *stdin_wire(void); 61 59 extern void stdout_wire(outdev_t *outdev); -
kernel/generic/include/context.h
re2ea4ab1 r4d1be48 87 87 * 88 88 * @param ctx Context structure. 89 *90 89 */ 91 static inline void __attribute__((no_instrument_function)) 92 context_restore(context_t *ctx) 90 static inline void context_restore(context_t *ctx) 93 91 { 94 92 context_restore_arch(ctx); -
kernel/generic/include/debug.h
re2ea4ab1 r4d1be48 93 93 #define LOG(format, ...) \ 94 94 do { \ 95 printf("%s() from %s at %s:%u: " format "\n", __func__, \ 96 symtab_fmt_name_lookup(CALLER), __FILE__, __LINE__, \ 97 ##__VA_ARGS__); \ 95 printf("%s->%s() at %s:%u: " format "\n", symtab_fmt_name_lookup(CALLER), \ 96 __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 97 } while (0) 98 99 /** Extensive logging execute macro 100 * 101 * If CONFIG_LOG is set, the LOG_EXEC() macro 102 * will print an information about calling a given 103 * function and call it. 104 * 105 */ 106 #define LOG_EXEC(fnc) \ 107 do { \ 108 printf("%s->%s() at %s:%u: " #fnc "\n", symtab_fmt_name_lookup(CALLER), \ 109 __func__, __FILE__, __LINE__); \ 110 fnc; \ 98 111 } while (0) 99 112 … … 101 114 102 115 #define LOG(format, ...) 116 #define LOG_EXEC(fnc) fnc 103 117 104 #endif /* CONFIG_LOG */ 105 106 #ifdef CONFIG_TRACE 107 108 extern void __cyg_profile_func_enter(void *, void *); 109 extern void __cyg_profile_func_exit(void *, void *); 110 111 #endif /* CONFIG_TRACE */ 118 #endif /* CONFOG_LOG */ 112 119 113 120 #endif -
kernel/generic/include/macros.h
re2ea4ab1 r4d1be48 47 47 * @param sz2 Size of the second interval. 48 48 */ 49 static inline int __attribute__((no_instrument_function)) 50 overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2) 49 static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2) 51 50 { 52 51 uintptr_t e1 = s1 + sz1; -
kernel/generic/include/sort.h
re2ea4ab1 r4d1be48 38 38 #include <typedefs.h> 39 39 40 typedef int (* sort_cmp_t)(void *, void *, void *); 40 /* 41 * sorting routines 42 */ 43 extern void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)); 44 extern void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)); 41 45 42 extern bool gsort(void *, size_t, size_t, sort_cmp_t, void *); 43 extern bool qsort(void *, size_t, size_t, sort_cmp_t, void *); 46 /* 47 * default sorting comparators 48 */ 49 extern int int_cmp(void * a, void * b); 50 extern int uint32_t_cmp(void * a, void * b); 51 extern int uint16_t_cmp(void * a, void * b); 52 extern int uint8_t_cmp(void * a, void * b); 44 53 45 54 #endif -
kernel/generic/src/adt/btree.c
re2ea4ab1 r4d1be48 33 33 /** 34 34 * @file 35 * @brief 35 * @brief B+tree implementation. 36 36 * 37 37 * This file implements B+tree type and operations. … … 54 54 #include <print.h> 55 55 56 static void btree_destroy_subtree(btree_node_t *root); 57 static void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node); 58 static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node); 59 static void node_initialize(btree_node_t *node); 60 static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree); 61 static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree); 62 static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key); 63 static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key); 64 static btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median); 65 static btree_node_t *node_combine(btree_node_t *node); 66 static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right); 67 static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx); 68 static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx); 69 static bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree); 70 static bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree); 71 static bool try_rotation_from_left(btree_node_t *rnode); 72 static bool try_rotation_from_right(btree_node_t *lnode); 73 74 #define ROOT_NODE(n) (!(n)->parent) 75 #define INDEX_NODE(n) ((n)->subtree[0] != NULL) 76 #define LEAF_NODE(n) ((n)->subtree[0] == NULL) 77 78 #define FILL_FACTOR ((BTREE_M-1)/2) 79 80 #define MEDIAN_LOW_INDEX(n) (((n)->keys-1)/2) 81 #define MEDIAN_HIGH_INDEX(n) ((n)->keys/2) 82 #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]); 83 #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]); 84 56 85 static slab_cache_t *btree_node_slab; 57 58 #define ROOT_NODE(n) (!(n)->parent)59 #define INDEX_NODE(n) ((n)->subtree[0] != NULL)60 #define LEAF_NODE(n) ((n)->subtree[0] == NULL)61 62 #define FILL_FACTOR ((BTREE_M - 1) / 2)63 64 #define MEDIAN_LOW_INDEX(n) (((n)->keys-1) / 2)65 #define MEDIAN_HIGH_INDEX(n) ((n)->keys / 2)66 #define MEDIAN_LOW(n) ((n)->key[MEDIAN_LOW_INDEX((n))]);67 #define MEDIAN_HIGH(n) ((n)->key[MEDIAN_HIGH_INDEX((n))]);68 86 69 87 /** Initialize B-trees. */ 70 88 void btree_init(void) 71 89 { 72 btree_node_slab = slab_cache_create("btree_node_slab", 73 sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED); 74 } 75 76 /** Initialize B-tree node. 77 * 78 * @param node B-tree node. 79 * 80 */ 81 static void node_initialize(btree_node_t *node) 82 { 83 unsigned int i; 84 85 node->keys = 0; 86 87 /* Clean also space for the extra key. */ 88 for (i = 0; i < BTREE_MAX_KEYS + 1; i++) { 89 node->key[i] = 0; 90 node->value[i] = NULL; 91 node->subtree[i] = NULL; 92 } 93 94 node->subtree[i] = NULL; 95 node->parent = NULL; 96 97 link_initialize(&node->leaf_link); 98 link_initialize(&node->bfs_link); 99 node->depth = 0; 90 btree_node_slab = slab_cache_create("btree_node_slab", sizeof(btree_node_t), 0, NULL, NULL, SLAB_CACHE_MAGDEFERRED); 100 91 } 101 92 … … 103 94 * 104 95 * @param t B-tree. 105 *106 96 */ 107 97 void btree_create(btree_t *t) … … 113 103 } 114 104 105 /** Destroy empty B-tree. */ 106 void btree_destroy(btree_t *t) 107 { 108 btree_destroy_subtree(t->root); 109 } 110 111 /** Insert key-value pair into B-tree. 112 * 113 * @param t B-tree. 114 * @param key Key to be inserted. 115 * @param value Value to be inserted. 116 * @param leaf_node Leaf node where the insertion should begin. 117 */ 118 void btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *leaf_node) 119 { 120 btree_node_t *lnode; 121 122 ASSERT(value); 123 124 lnode = leaf_node; 125 if (!lnode) { 126 if (btree_search(t, key, &lnode)) { 127 panic("B-tree %p already contains key %" PRIu64 ".", t, key); 128 } 129 } 130 131 _btree_insert(t, key, value, NULL, lnode); 132 } 133 115 134 /** Destroy subtree rooted in a node. 116 135 * 117 136 * @param root Root of the subtree. 118 * 119 */ 120 static void btree_destroy_subtree(btree_node_t *root) 137 */ 138 void btree_destroy_subtree(btree_node_t *root) 121 139 { 122 140 size_t i; 123 141 124 142 if (root->keys) { 125 143 for (i = 0; i < root->keys + 1; i++) { … … 128 146 } 129 147 } 130 131 148 slab_free(btree_node_slab, root); 132 149 } 133 150 134 /** Destroy empty B-tree. */135 void btree_destroy(btree_t *t)136 {137 btree_destroy_subtree(t->root);138 }139 140 /** Insert key-value-rsubtree triplet into B-tree node.141 *142 * It is actually possible to have more keys than BTREE_MAX_KEYS.143 * This feature is used during splitting the node when the144 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation145 * also makes use of this feature.146 *147 * @param node B-tree node into wich the new key is to be inserted.148 * @param key The key to be inserted.149 * @param value Pointer to value to be inserted.150 * @param rsubtree Pointer to the right subtree.151 *152 */153 static void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key,154 void *value, btree_node_t *rsubtree)155 {156 size_t i;157 158 for (i = 0; i < node->keys; i++) {159 if (key < node->key[i]) {160 size_t j;161 162 for (j = node->keys; j > i; j--) {163 node->key[j] = node->key[j - 1];164 node->value[j] = node->value[j - 1];165 node->subtree[j + 1] = node->subtree[j];166 }167 168 break;169 }170 }171 172 node->key[i] = key;173 node->value[i] = value;174 node->subtree[i + 1] = rsubtree;175 node->keys++;176 }177 178 /** Find key by its left or right subtree.179 *180 * @param node B-tree node.181 * @param subtree Left or right subtree of a key found in node.182 * @param right If true, subtree is a right subtree. If false,183 * subtree is a left subtree.184 *185 * @return Index of the key associated with the subtree.186 *187 */188 static size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree,189 bool right)190 {191 size_t i;192 193 for (i = 0; i < node->keys + 1; i++) {194 if (subtree == node->subtree[i])195 return i - (int) (right != false);196 }197 198 panic("Node %p does not contain subtree %p.", node, subtree);199 }200 201 /** Remove key and its left subtree pointer from B-tree node.202 *203 * Remove the key and eliminate gaps in node->key array.204 * Note that the value pointer and the left subtree pointer205 * is removed from the node as well.206 *207 * @param node B-tree node.208 * @param key Key to be removed.209 *210 */211 static void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key)212 {213 size_t i;214 size_t j;215 216 for (i = 0; i < node->keys; i++) {217 if (key == node->key[i]) {218 for (j = i + 1; j < node->keys; j++) {219 node->key[j - 1] = node->key[j];220 node->value[j - 1] = node->value[j];221 node->subtree[j - 1] = node->subtree[j];222 }223 224 node->subtree[j - 1] = node->subtree[j];225 node->keys--;226 227 return;228 }229 }230 231 panic("Node %p does not contain key %" PRIu64 ".", node, key);232 }233 234 /** Remove key and its right subtree pointer from B-tree node.235 *236 * Remove the key and eliminate gaps in node->key array.237 * Note that the value pointer and the right subtree pointer238 * is removed from the node as well.239 *240 * @param node B-tree node.241 * @param key Key to be removed.242 *243 */244 static void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key)245 {246 size_t i, j;247 248 for (i = 0; i < node->keys; i++) {249 if (key == node->key[i]) {250 for (j = i + 1; j < node->keys; j++) {251 node->key[j - 1] = node->key[j];252 node->value[j - 1] = node->value[j];253 node->subtree[j] = node->subtree[j + 1];254 }255 256 node->keys--;257 return;258 }259 }260 261 panic("Node %p does not contain key %" PRIu64 ".", node, key);262 }263 264 /** Insert key-value-lsubtree triplet into B-tree node.265 *266 * It is actually possible to have more keys than BTREE_MAX_KEYS.267 * This feature is used during insert by right rotation.268 *269 * @param node B-tree node into wich the new key is to be inserted.270 * @param key The key to be inserted.271 * @param value Pointer to value to be inserted.272 * @param lsubtree Pointer to the left subtree.273 *274 */275 static void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key,276 void *value, btree_node_t *lsubtree)277 {278 size_t i;279 280 for (i = 0; i < node->keys; i++) {281 if (key < node->key[i]) {282 size_t j;283 284 for (j = node->keys; j > i; j--) {285 node->key[j] = node->key[j - 1];286 node->value[j] = node->value[j - 1];287 node->subtree[j + 1] = node->subtree[j];288 }289 290 node->subtree[j + 1] = node->subtree[j];291 break;292 }293 }294 295 node->key[i] = key;296 node->value[i] = value;297 node->subtree[i] = lsubtree;298 299 node->keys++;300 }301 302 /** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling.303 *304 * The biggest key and its value and right subtree is rotated305 * from the left node to the right. If the node is an index node,306 * than the parent node key belonging to the left node takes part307 * in the rotation.308 *309 * @param lnode Left sibling.310 * @param rnode Right sibling.311 * @param idx Index of the parent node key that is taking part312 * in the rotation.313 *314 */315 static void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx)316 {317 btree_key_t key = lnode->key[lnode->keys - 1];318 319 if (LEAF_NODE(lnode)) {320 void *value = lnode->value[lnode->keys - 1];321 322 node_remove_key_and_rsubtree(lnode, key);323 node_insert_key_and_lsubtree(rnode, key, value, NULL);324 lnode->parent->key[idx] = key;325 } else {326 btree_node_t *rsubtree = lnode->subtree[lnode->keys];327 328 node_remove_key_and_rsubtree(lnode, key);329 node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree);330 lnode->parent->key[idx] = key;331 332 /* Fix parent link of the reconnected right subtree. */333 rsubtree->parent = rnode;334 }335 }336 337 /** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling.338 *339 * The smallest key and its value and left subtree is rotated340 * from the right node to the left. If the node is an index node,341 * than the parent node key belonging to the right node takes part342 * in the rotation.343 *344 * @param lnode Left sibling.345 * @param rnode Right sibling.346 * @param idx Index of the parent node key that is taking part347 * in the rotation.348 *349 */350 static void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx)351 {352 btree_key_t key = rnode->key[0];353 354 if (LEAF_NODE(rnode)) {355 void *value = rnode->value[0];356 357 node_remove_key_and_lsubtree(rnode, key);358 node_insert_key_and_rsubtree(lnode, key, value, NULL);359 rnode->parent->key[idx] = rnode->key[0];360 } else {361 btree_node_t *lsubtree = rnode->subtree[0];362 363 node_remove_key_and_lsubtree(rnode, key);364 node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree);365 rnode->parent->key[idx] = key;366 367 /* Fix parent link of the reconnected left subtree. */368 lsubtree->parent = lnode;369 }370 }371 372 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done.373 *374 * Left sibling of the node (if it exists) is checked for free space.375 * If there is free space, the key is inserted and the smallest key of376 * the node is moved there. The index node which is the parent of both377 * nodes is fixed.378 *379 * @param node B-tree node.380 * @param inskey Key to be inserted.381 * @param insvalue Value to be inserted.382 * @param rsubtree Right subtree of inskey.383 *384 * @return True if the rotation was performed, false otherwise.385 *386 */387 static bool try_insert_by_rotation_to_left(btree_node_t *node,388 btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)389 {390 size_t idx;391 btree_node_t *lnode;392 393 /*394 * If this is root node, the rotation can not be done.395 */396 if (ROOT_NODE(node))397 return false;398 399 idx = find_key_by_subtree(node->parent, node, true);400 if ((int) idx == -1) {401 /*402 * If this node is the leftmost subtree of its parent,403 * the rotation can not be done.404 */405 return false;406 }407 408 lnode = node->parent->subtree[idx];409 if (lnode->keys < BTREE_MAX_KEYS) {410 /*411 * The rotaion can be done. The left sibling has free space.412 */413 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);414 rotate_from_right(lnode, node, idx);415 return true;416 }417 418 return false;419 }420 421 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done.422 *423 * Right sibling of the node (if it exists) is checked for free space.424 * If there is free space, the key is inserted and the biggest key of425 * the node is moved there. The index node which is the parent of both426 * nodes is fixed.427 *428 * @param node B-tree node.429 * @param inskey Key to be inserted.430 * @param insvalue Value to be inserted.431 * @param rsubtree Right subtree of inskey.432 *433 * @return True if the rotation was performed, false otherwise.434 *435 */436 static bool try_insert_by_rotation_to_right(btree_node_t *node,437 btree_key_t inskey, void *insvalue, btree_node_t *rsubtree)438 {439 size_t idx;440 btree_node_t *rnode;441 442 /*443 * If this is root node, the rotation can not be done.444 */445 if (ROOT_NODE(node))446 return false;447 448 idx = find_key_by_subtree(node->parent, node, false);449 if (idx == node->parent->keys) {450 /*451 * If this node is the rightmost subtree of its parent,452 * the rotation can not be done.453 */454 return false;455 }456 457 rnode = node->parent->subtree[idx + 1];458 if (rnode->keys < BTREE_MAX_KEYS) {459 /*460 * The rotaion can be done. The right sibling has free space.461 */462 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree);463 rotate_from_left(node, rnode, idx);464 return true;465 }466 467 return false;468 }469 470 /** Split full B-tree node and insert new key-value-right-subtree triplet.471 *472 * This function will split a node and return a pointer to a newly created473 * node containing keys greater than or equal to the greater of medians474 * (or median) of the old keys and the newly added key. It will also write475 * the median key to a memory address supplied by the caller.476 *477 * If the node being split is an index node, the median will not be478 * included in the new node. If the node is a leaf node,479 * the median will be copied there.480 *481 * @param node B-tree node wich is going to be split.482 * @param key The key to be inserted.483 * @param value Pointer to the value to be inserted.484 * @param rsubtree Pointer to the right subtree of the key being added.485 * @param median Address in memory, where the median key will be stored.486 *487 * @return Newly created right sibling of node.488 *489 */490 static btree_node_t *node_split(btree_node_t *node, btree_key_t key,491 void *value, btree_node_t *rsubtree, btree_key_t *median)492 {493 btree_node_t *rnode;494 size_t i;495 size_t j;496 497 ASSERT(median);498 ASSERT(node->keys == BTREE_MAX_KEYS);499 500 /*501 * Use the extra space to store the extra node.502 */503 node_insert_key_and_rsubtree(node, key, value, rsubtree);504 505 /*506 * Compute median of keys.507 */508 *median = MEDIAN_HIGH(node);509 510 /*511 * Allocate and initialize new right sibling.512 */513 rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0);514 node_initialize(rnode);515 rnode->parent = node->parent;516 rnode->depth = node->depth;517 518 /*519 * Copy big keys, values and subtree pointers to the new right sibling.520 * If this is an index node, do not copy the median.521 */522 i = (size_t) INDEX_NODE(node);523 for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) {524 rnode->key[j] = node->key[i];525 rnode->value[j] = node->value[i];526 rnode->subtree[j] = node->subtree[i];527 528 /*529 * Fix parent links in subtrees.530 */531 if (rnode->subtree[j])532 rnode->subtree[j]->parent = rnode;533 }534 535 rnode->subtree[j] = node->subtree[i];536 if (rnode->subtree[j])537 rnode->subtree[j]->parent = rnode;538 539 rnode->keys = j; /* Set number of keys of the new node. */540 node->keys /= 2; /* Shrink the old node. */541 542 return rnode;543 }544 545 151 /** Recursively insert into B-tree. 546 152 * 547 * @param t 548 * @param key 549 * @param value 153 * @param t B-tree. 154 * @param key Key to be inserted. 155 * @param value Value to be inserted. 550 156 * @param rsubtree Right subtree of the inserted key. 551 * @param node Start inserting into this node. 552 * 553 */ 554 static void _btree_insert(btree_t *t, btree_key_t key, void *value, 555 btree_node_t *rsubtree, btree_node_t *node) 157 * @param node Start inserting into this node. 158 */ 159 void _btree_insert(btree_t *t, btree_key_t key, void *value, btree_node_t *rsubtree, btree_node_t *node) 556 160 { 557 161 if (node->keys < BTREE_MAX_KEYS) { … … 579 183 * bigger keys (i.e. the new node) into its parent. 580 184 */ 581 185 582 186 rnode = node_split(node, key, value, rsubtree, &median); 583 187 584 188 if (LEAF_NODE(node)) { 585 189 list_prepend(&rnode->leaf_link, &node->leaf_link); … … 598 202 * Left-hand side subtree will be the old root (i.e. node). 599 203 * Right-hand side subtree will be rnode. 600 */ 204 */ 601 205 t->root->subtree[0] = node; 602 206 603 207 t->root->depth = node->depth + 1; 604 208 } 605 209 _btree_insert(t, median, NULL, rnode, node->parent); 606 } 607 } 608 609 /** Insert key-value pair into B-tree. 610 * 611 * @param t B-tree. 612 * @param key Key to be inserted. 613 * @param value Value to be inserted. 614 * @param leaf_node Leaf node where the insertion should begin. 615 * 616 */ 617 void btree_insert(btree_t *t, btree_key_t key, void *value, 618 btree_node_t *leaf_node) 210 } 211 212 } 213 214 /** Remove B-tree node. 215 * 216 * @param t B-tree. 217 * @param key Key to be removed from the B-tree along with its associated value. 218 * @param leaf_node If not NULL, pointer to the leaf node where the key is found. 219 */ 220 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node) 619 221 { 620 222 btree_node_t *lnode; 621 622 ASSERT(value);623 223 624 224 lnode = leaf_node; 625 225 if (!lnode) { 626 if (btree_search(t, key, &lnode)) 627 panic("B-tree %p already contains key %" PRIu64 ".", t, key); 628 } 629 630 _btree_insert(t, key, value, NULL, lnode); 631 } 632 633 /** Rotate in a key from the left sibling or from the index node, if this operation can be done. 634 * 635 * @param rnode Node into which to add key from its left sibling 636 * or from the index node. 637 * 638 * @return True if the rotation was performed, false otherwise. 639 * 640 */ 641 static bool try_rotation_from_left(btree_node_t *rnode) 642 { 643 size_t idx; 644 btree_node_t *lnode; 645 646 /* 647 * If this is root node, the rotation can not be done. 648 */ 649 if (ROOT_NODE(rnode)) 650 return false; 651 652 idx = find_key_by_subtree(rnode->parent, rnode, true); 653 if ((int) idx == -1) { 654 /* 655 * If this node is the leftmost subtree of its parent, 656 * the rotation can not be done. 657 */ 658 return false; 659 } 660 661 lnode = rnode->parent->subtree[idx]; 662 if (lnode->keys > FILL_FACTOR) { 663 rotate_from_left(lnode, rnode, idx); 664 return true; 665 } 666 667 return false; 668 } 669 670 /** Rotate in a key from the right sibling or from the index node, if this operation can be done. 671 * 672 * @param lnode Node into which to add key from its right sibling 673 * or from the index node. 674 * 675 * @return True if the rotation was performed, false otherwise. 676 * 677 */ 678 static bool try_rotation_from_right(btree_node_t *lnode) 679 { 680 size_t idx; 681 btree_node_t *rnode; 682 683 /* 684 * If this is root node, the rotation can not be done. 685 */ 686 if (ROOT_NODE(lnode)) 687 return false; 688 689 idx = find_key_by_subtree(lnode->parent, lnode, false); 690 if (idx == lnode->parent->keys) { 691 /* 692 * If this node is the rightmost subtree of its parent, 693 * the rotation can not be done. 694 */ 695 return false; 696 } 697 698 rnode = lnode->parent->subtree[idx + 1]; 699 if (rnode->keys > FILL_FACTOR) { 700 rotate_from_right(lnode, rnode, idx); 701 return true; 702 } 703 704 return false; 705 } 706 707 /** Combine node with any of its siblings. 708 * 709 * The siblings are required to be below the fill factor. 710 * 711 * @param node Node to combine with one of its siblings. 712 * 713 * @return Pointer to the rightmost of the two nodes. 714 * 715 */ 716 static btree_node_t *node_combine(btree_node_t *node) 717 { 718 size_t idx; 719 btree_node_t *rnode; 720 size_t i; 721 722 ASSERT(!ROOT_NODE(node)); 723 724 idx = find_key_by_subtree(node->parent, node, false); 725 if (idx == node->parent->keys) { 726 /* 727 * Rightmost subtree of its parent, combine with the left sibling. 728 */ 729 idx--; 730 rnode = node; 731 node = node->parent->subtree[idx]; 732 } else 733 rnode = node->parent->subtree[idx + 1]; 734 735 /* Index nodes need to insert parent node key in between left and right node. */ 736 if (INDEX_NODE(node)) 737 node->key[node->keys++] = node->parent->key[idx]; 738 739 /* Copy the key-value-subtree triplets from the right node. */ 740 for (i = 0; i < rnode->keys; i++) { 741 node->key[node->keys + i] = rnode->key[i]; 742 node->value[node->keys + i] = rnode->value[i]; 743 744 if (INDEX_NODE(node)) { 745 node->subtree[node->keys + i] = rnode->subtree[i]; 746 rnode->subtree[i]->parent = node; 747 } 748 } 749 750 if (INDEX_NODE(node)) { 751 node->subtree[node->keys + i] = rnode->subtree[i]; 752 rnode->subtree[i]->parent = node; 753 } 754 755 node->keys += rnode->keys; 756 return rnode; 226 if (!btree_search(t, key, &lnode)) { 227 panic("B-tree %p does not contain key %" PRIu64 ".", t, key); 228 } 229 } 230 231 _btree_remove(t, key, lnode); 757 232 } 758 233 759 234 /** Recursively remove B-tree node. 760 235 * 761 * @param t 762 * @param key 236 * @param t B-tree. 237 * @param key Key to be removed from the B-tree along with its associated value. 763 238 * @param node Node where the key being removed resides. 764 * 765 */ 766 static void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node) 239 */ 240 void _btree_remove(btree_t *t, btree_key_t key, btree_node_t *node) 767 241 { 768 242 if (ROOT_NODE(node)) { 769 if ( (node->keys == 1) && (node->subtree[0])) {243 if (node->keys == 1 && node->subtree[0]) { 770 244 /* 771 245 * Free the current root and set new root. … … 783 257 node_remove_key_and_rsubtree(node, key); 784 258 } 785 786 259 return; 787 260 } … … 798 271 if (node->keys > FILL_FACTOR) { 799 272 size_t i; 800 273 801 274 /* 802 275 * The key can be immediatelly removed. … … 807 280 */ 808 281 node_remove_key_and_rsubtree(node, key); 809 810 282 for (i = 0; i < node->parent->keys; i++) { 811 283 if (node->parent->key[i] == key) 812 284 node->parent->key[i] = node->key[0]; 813 285 } 286 814 287 } else { 815 288 size_t idx; 816 btree_node_t *rnode; 817 btree_node_t *parent; 818 289 btree_node_t *rnode, *parent; 290 819 291 /* 820 292 * The node is below the fill factor as well as its left and right sibling. … … 826 298 node_remove_key_and_rsubtree(node, key); 827 299 rnode = node_combine(node); 828 829 300 if (LEAF_NODE(rnode)) 830 301 list_remove(&rnode->leaf_link); 831 832 302 idx = find_key_by_subtree(parent, rnode, true); 833 303 ASSERT((int) idx != -1); … … 837 307 } 838 308 839 /** Remove B-tree node.840 *841 * @param t B-tree.842 * @param key Key to be removed from the B-tree along843 * with its associated value.844 * @param leaf_node If not NULL, pointer to the leaf node where845 * the key is found.846 *847 */848 void btree_remove(btree_t *t, btree_key_t key, btree_node_t *leaf_node)849 {850 btree_node_t *lnode;851 852 lnode = leaf_node;853 if (!lnode) {854 if (!btree_search(t, key, &lnode))855 panic("B-tree %p does not contain key %" PRIu64 ".", t, key);856 }857 858 _btree_remove(t, key, lnode);859 }860 861 309 /** Search key in a B-tree. 862 310 * 863 * @param t 864 * @param key 311 * @param t B-tree. 312 * @param key Key to be searched. 865 313 * @param leaf_node Address where to put pointer to visited leaf node. 866 314 * 867 315 * @return Pointer to value or NULL if there is no such key. 868 *869 316 */ 870 317 void *btree_search(btree_t *t, btree_key_t key, btree_node_t **leaf_node) … … 876 323 */ 877 324 for (cur = t->root; cur; cur = next) { 878 /* 879 * Last iteration will set this with proper 880 * leaf node address. 881 */ 325 326 /* Last iteration will set this with proper leaf node address. */ 882 327 *leaf_node = cur; 883 328 … … 892 337 void *val; 893 338 size_t i; 894 339 895 340 /* 896 341 * Now if the key is smaller than cur->key[i] … … 902 347 next = cur->subtree[i]; 903 348 val = cur->value[i - 1]; 904 349 905 350 if (LEAF_NODE(cur)) 906 351 return key == cur->key[i - 1] ? val : NULL; 907 352 908 353 goto descend; 909 } 354 } 910 355 } 911 356 912 357 /* 913 * Last possibility is that the key is 914 * in the rightmost subtree. 358 * Last possibility is that the key is in the rightmost subtree. 915 359 */ 916 360 next = cur->subtree[i]; 917 361 val = cur->value[i - 1]; 918 919 362 if (LEAF_NODE(cur)) 920 363 return key == cur->key[i - 1] ? val : NULL; 921 364 } 922 365 descend: 923 ;924 } 925 366 ; 367 } 368 926 369 /* 927 * The key was not found in the *leaf_node and 928 * is smaller than any of its keys. 370 * The key was not found in the *leaf_node and is smaller than any of its keys. 929 371 */ 930 372 return NULL; … … 933 375 /** Return pointer to B-tree leaf node's left neighbour. 934 376 * 935 * @param t 377 * @param t B-tree. 936 378 * @param node Node whose left neighbour will be returned. 937 379 * 938 * @return Left neighbour of the node or NULL if the node 939 * does not have the left neighbour. 940 * 380 * @return Left neighbour of the node or NULL if the node does not have the left neighbour. 941 381 */ 942 382 btree_node_t *btree_leaf_node_left_neighbour(btree_t *t, btree_node_t *node) 943 383 { 944 384 ASSERT(LEAF_NODE(node)); 945 946 385 if (node->leaf_link.prev != &t->leaf_head) 947 386 return list_get_instance(node->leaf_link.prev, btree_node_t, leaf_link); … … 952 391 /** Return pointer to B-tree leaf node's right neighbour. 953 392 * 954 * @param t 393 * @param t B-tree. 955 394 * @param node Node whose right neighbour will be returned. 956 395 * 957 * @return Right neighbour of the node or NULL if the node 958 * does not have the right neighbour. 959 * 396 * @return Right neighbour of the node or NULL if the node does not have the right neighbour. 960 397 */ 961 398 btree_node_t *btree_leaf_node_right_neighbour(btree_t *t, btree_node_t *node) 962 399 { 963 400 ASSERT(LEAF_NODE(node)); 964 965 401 if (node->leaf_link.next != &t->leaf_head) 966 402 return list_get_instance(node->leaf_link.next, btree_node_t, leaf_link); … … 969 405 } 970 406 407 /** Initialize B-tree node. 408 * 409 * @param node B-tree node. 410 */ 411 void node_initialize(btree_node_t *node) 412 { 413 int i; 414 415 node->keys = 0; 416 417 /* Clean also space for the extra key. */ 418 for (i = 0; i < BTREE_MAX_KEYS + 1; i++) { 419 node->key[i] = 0; 420 node->value[i] = NULL; 421 node->subtree[i] = NULL; 422 } 423 node->subtree[i] = NULL; 424 425 node->parent = NULL; 426 427 link_initialize(&node->leaf_link); 428 429 link_initialize(&node->bfs_link); 430 node->depth = 0; 431 } 432 433 /** Insert key-value-lsubtree triplet into B-tree node. 434 * 435 * It is actually possible to have more keys than BTREE_MAX_KEYS. 436 * This feature is used during insert by right rotation. 437 * 438 * @param node B-tree node into wich the new key is to be inserted. 439 * @param key The key to be inserted. 440 * @param value Pointer to value to be inserted. 441 * @param lsubtree Pointer to the left subtree. 442 */ 443 void node_insert_key_and_lsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *lsubtree) 444 { 445 size_t i; 446 447 for (i = 0; i < node->keys; i++) { 448 if (key < node->key[i]) { 449 size_t j; 450 451 for (j = node->keys; j > i; j--) { 452 node->key[j] = node->key[j - 1]; 453 node->value[j] = node->value[j - 1]; 454 node->subtree[j + 1] = node->subtree[j]; 455 } 456 node->subtree[j + 1] = node->subtree[j]; 457 break; 458 } 459 } 460 node->key[i] = key; 461 node->value[i] = value; 462 node->subtree[i] = lsubtree; 463 464 node->keys++; 465 } 466 467 /** Insert key-value-rsubtree triplet into B-tree node. 468 * 469 * It is actually possible to have more keys than BTREE_MAX_KEYS. 470 * This feature is used during splitting the node when the 471 * number of keys is BTREE_MAX_KEYS + 1. Insert by left rotation 472 * also makes use of this feature. 473 * 474 * @param node B-tree node into wich the new key is to be inserted. 475 * @param key The key to be inserted. 476 * @param value Pointer to value to be inserted. 477 * @param rsubtree Pointer to the right subtree. 478 */ 479 void node_insert_key_and_rsubtree(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree) 480 { 481 size_t i; 482 483 for (i = 0; i < node->keys; i++) { 484 if (key < node->key[i]) { 485 size_t j; 486 487 for (j = node->keys; j > i; j--) { 488 node->key[j] = node->key[j - 1]; 489 node->value[j] = node->value[j - 1]; 490 node->subtree[j + 1] = node->subtree[j]; 491 } 492 break; 493 } 494 } 495 node->key[i] = key; 496 node->value[i] = value; 497 node->subtree[i + 1] = rsubtree; 498 499 node->keys++; 500 } 501 502 /** Remove key and its left subtree pointer from B-tree node. 503 * 504 * Remove the key and eliminate gaps in node->key array. 505 * Note that the value pointer and the left subtree pointer 506 * is removed from the node as well. 507 * 508 * @param node B-tree node. 509 * @param key Key to be removed. 510 */ 511 void node_remove_key_and_lsubtree(btree_node_t *node, btree_key_t key) 512 { 513 size_t i, j; 514 515 for (i = 0; i < node->keys; i++) { 516 if (key == node->key[i]) { 517 for (j = i + 1; j < node->keys; j++) { 518 node->key[j - 1] = node->key[j]; 519 node->value[j - 1] = node->value[j]; 520 node->subtree[j - 1] = node->subtree[j]; 521 } 522 node->subtree[j - 1] = node->subtree[j]; 523 node->keys--; 524 return; 525 } 526 } 527 panic("Node %p does not contain key %" PRIu64 ".", node, key); 528 } 529 530 /** Remove key and its right subtree pointer from B-tree node. 531 * 532 * Remove the key and eliminate gaps in node->key array. 533 * Note that the value pointer and the right subtree pointer 534 * is removed from the node as well. 535 * 536 * @param node B-tree node. 537 * @param key Key to be removed. 538 */ 539 void node_remove_key_and_rsubtree(btree_node_t *node, btree_key_t key) 540 { 541 size_t i, j; 542 543 for (i = 0; i < node->keys; i++) { 544 if (key == node->key[i]) { 545 for (j = i + 1; j < node->keys; j++) { 546 node->key[j - 1] = node->key[j]; 547 node->value[j - 1] = node->value[j]; 548 node->subtree[j] = node->subtree[j + 1]; 549 } 550 node->keys--; 551 return; 552 } 553 } 554 panic("Node %p does not contain key %" PRIu64 ".", node, key); 555 } 556 557 /** Split full B-tree node and insert new key-value-right-subtree triplet. 558 * 559 * This function will split a node and return a pointer to a newly created 560 * node containing keys greater than or equal to the greater of medians 561 * (or median) of the old keys and the newly added key. It will also write 562 * the median key to a memory address supplied by the caller. 563 * 564 * If the node being split is an index node, the median will not be 565 * included in the new node. If the node is a leaf node, 566 * the median will be copied there. 567 * 568 * @param node B-tree node wich is going to be split. 569 * @param key The key to be inserted. 570 * @param value Pointer to the value to be inserted. 571 * @param rsubtree Pointer to the right subtree of the key being added. 572 * @param median Address in memory, where the median key will be stored. 573 * 574 * @return Newly created right sibling of node. 575 */ 576 btree_node_t *node_split(btree_node_t *node, btree_key_t key, void *value, btree_node_t *rsubtree, btree_key_t *median) 577 { 578 btree_node_t *rnode; 579 size_t i, j; 580 581 ASSERT(median); 582 ASSERT(node->keys == BTREE_MAX_KEYS); 583 584 /* 585 * Use the extra space to store the extra node. 586 */ 587 node_insert_key_and_rsubtree(node, key, value, rsubtree); 588 589 /* 590 * Compute median of keys. 591 */ 592 *median = MEDIAN_HIGH(node); 593 594 /* 595 * Allocate and initialize new right sibling. 596 */ 597 rnode = (btree_node_t *) slab_alloc(btree_node_slab, 0); 598 node_initialize(rnode); 599 rnode->parent = node->parent; 600 rnode->depth = node->depth; 601 602 /* 603 * Copy big keys, values and subtree pointers to the new right sibling. 604 * If this is an index node, do not copy the median. 605 */ 606 i = (size_t) INDEX_NODE(node); 607 for (i += MEDIAN_HIGH_INDEX(node), j = 0; i < node->keys; i++, j++) { 608 rnode->key[j] = node->key[i]; 609 rnode->value[j] = node->value[i]; 610 rnode->subtree[j] = node->subtree[i]; 611 612 /* 613 * Fix parent links in subtrees. 614 */ 615 if (rnode->subtree[j]) 616 rnode->subtree[j]->parent = rnode; 617 618 } 619 rnode->subtree[j] = node->subtree[i]; 620 if (rnode->subtree[j]) 621 rnode->subtree[j]->parent = rnode; 622 623 rnode->keys = j; /* Set number of keys of the new node. */ 624 node->keys /= 2; /* Shrink the old node. */ 625 626 return rnode; 627 } 628 629 /** Combine node with any of its siblings. 630 * 631 * The siblings are required to be below the fill factor. 632 * 633 * @param node Node to combine with one of its siblings. 634 * 635 * @return Pointer to the rightmost of the two nodes. 636 */ 637 btree_node_t *node_combine(btree_node_t *node) 638 { 639 size_t idx; 640 btree_node_t *rnode; 641 size_t i; 642 643 ASSERT(!ROOT_NODE(node)); 644 645 idx = find_key_by_subtree(node->parent, node, false); 646 if (idx == node->parent->keys) { 647 /* 648 * Rightmost subtree of its parent, combine with the left sibling. 649 */ 650 idx--; 651 rnode = node; 652 node = node->parent->subtree[idx]; 653 } else { 654 rnode = node->parent->subtree[idx + 1]; 655 } 656 657 /* Index nodes need to insert parent node key in between left and right node. */ 658 if (INDEX_NODE(node)) 659 node->key[node->keys++] = node->parent->key[idx]; 660 661 /* Copy the key-value-subtree triplets from the right node. */ 662 for (i = 0; i < rnode->keys; i++) { 663 node->key[node->keys + i] = rnode->key[i]; 664 node->value[node->keys + i] = rnode->value[i]; 665 if (INDEX_NODE(node)) { 666 node->subtree[node->keys + i] = rnode->subtree[i]; 667 rnode->subtree[i]->parent = node; 668 } 669 } 670 if (INDEX_NODE(node)) { 671 node->subtree[node->keys + i] = rnode->subtree[i]; 672 rnode->subtree[i]->parent = node; 673 } 674 675 node->keys += rnode->keys; 676 677 return rnode; 678 } 679 680 /** Find key by its left or right subtree. 681 * 682 * @param node B-tree node. 683 * @param subtree Left or right subtree of a key found in node. 684 * @param right If true, subtree is a right subtree. If false, subtree is a left subtree. 685 * 686 * @return Index of the key associated with the subtree. 687 */ 688 size_t find_key_by_subtree(btree_node_t *node, btree_node_t *subtree, bool right) 689 { 690 size_t i; 691 692 for (i = 0; i < node->keys + 1; i++) { 693 if (subtree == node->subtree[i]) 694 return i - (int) (right != false); 695 } 696 panic("Node %p does not contain subtree %p.", node, subtree); 697 } 698 699 /** Rotate one key-value-rsubtree triplet from the left sibling to the right sibling. 700 * 701 * The biggest key and its value and right subtree is rotated from the left node 702 * to the right. If the node is an index node, than the parent node key belonging to 703 * the left node takes part in the rotation. 704 * 705 * @param lnode Left sibling. 706 * @param rnode Right sibling. 707 * @param idx Index of the parent node key that is taking part in the rotation. 708 */ 709 void rotate_from_left(btree_node_t *lnode, btree_node_t *rnode, size_t idx) 710 { 711 btree_key_t key; 712 713 key = lnode->key[lnode->keys - 1]; 714 715 if (LEAF_NODE(lnode)) { 716 void *value; 717 718 value = lnode->value[lnode->keys - 1]; 719 node_remove_key_and_rsubtree(lnode, key); 720 node_insert_key_and_lsubtree(rnode, key, value, NULL); 721 lnode->parent->key[idx] = key; 722 } else { 723 btree_node_t *rsubtree; 724 725 rsubtree = lnode->subtree[lnode->keys]; 726 node_remove_key_and_rsubtree(lnode, key); 727 node_insert_key_and_lsubtree(rnode, lnode->parent->key[idx], NULL, rsubtree); 728 lnode->parent->key[idx] = key; 729 730 /* Fix parent link of the reconnected right subtree. */ 731 rsubtree->parent = rnode; 732 } 733 734 } 735 736 /** Rotate one key-value-lsubtree triplet from the right sibling to the left sibling. 737 * 738 * The smallest key and its value and left subtree is rotated from the right node 739 * to the left. If the node is an index node, than the parent node key belonging to 740 * the right node takes part in the rotation. 741 * 742 * @param lnode Left sibling. 743 * @param rnode Right sibling. 744 * @param idx Index of the parent node key that is taking part in the rotation. 745 */ 746 void rotate_from_right(btree_node_t *lnode, btree_node_t *rnode, size_t idx) 747 { 748 btree_key_t key; 749 750 key = rnode->key[0]; 751 752 if (LEAF_NODE(rnode)) { 753 void *value; 754 755 value = rnode->value[0]; 756 node_remove_key_and_lsubtree(rnode, key); 757 node_insert_key_and_rsubtree(lnode, key, value, NULL); 758 rnode->parent->key[idx] = rnode->key[0]; 759 } else { 760 btree_node_t *lsubtree; 761 762 lsubtree = rnode->subtree[0]; 763 node_remove_key_and_lsubtree(rnode, key); 764 node_insert_key_and_rsubtree(lnode, rnode->parent->key[idx], NULL, lsubtree); 765 rnode->parent->key[idx] = key; 766 767 /* Fix parent link of the reconnected left subtree. */ 768 lsubtree->parent = lnode; 769 } 770 771 } 772 773 /** Insert key-value-rsubtree triplet and rotate the node to the left, if this operation can be done. 774 * 775 * Left sibling of the node (if it exists) is checked for free space. 776 * If there is free space, the key is inserted and the smallest key of 777 * the node is moved there. The index node which is the parent of both 778 * nodes is fixed. 779 * 780 * @param node B-tree node. 781 * @param inskey Key to be inserted. 782 * @param insvalue Value to be inserted. 783 * @param rsubtree Right subtree of inskey. 784 * 785 * @return True if the rotation was performed, false otherwise. 786 */ 787 bool try_insert_by_rotation_to_left(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree) 788 { 789 size_t idx; 790 btree_node_t *lnode; 791 792 /* 793 * If this is root node, the rotation can not be done. 794 */ 795 if (ROOT_NODE(node)) 796 return false; 797 798 idx = find_key_by_subtree(node->parent, node, true); 799 if ((int) idx == -1) { 800 /* 801 * If this node is the leftmost subtree of its parent, 802 * the rotation can not be done. 803 */ 804 return false; 805 } 806 807 lnode = node->parent->subtree[idx]; 808 if (lnode->keys < BTREE_MAX_KEYS) { 809 /* 810 * The rotaion can be done. The left sibling has free space. 811 */ 812 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree); 813 rotate_from_right(lnode, node, idx); 814 return true; 815 } 816 817 return false; 818 } 819 820 /** Insert key-value-rsubtree triplet and rotate the node to the right, if this operation can be done. 821 * 822 * Right sibling of the node (if it exists) is checked for free space. 823 * If there is free space, the key is inserted and the biggest key of 824 * the node is moved there. The index node which is the parent of both 825 * nodes is fixed. 826 * 827 * @param node B-tree node. 828 * @param inskey Key to be inserted. 829 * @param insvalue Value to be inserted. 830 * @param rsubtree Right subtree of inskey. 831 * 832 * @return True if the rotation was performed, false otherwise. 833 */ 834 bool try_insert_by_rotation_to_right(btree_node_t *node, btree_key_t inskey, void *insvalue, btree_node_t *rsubtree) 835 { 836 size_t idx; 837 btree_node_t *rnode; 838 839 /* 840 * If this is root node, the rotation can not be done. 841 */ 842 if (ROOT_NODE(node)) 843 return false; 844 845 idx = find_key_by_subtree(node->parent, node, false); 846 if (idx == node->parent->keys) { 847 /* 848 * If this node is the rightmost subtree of its parent, 849 * the rotation can not be done. 850 */ 851 return false; 852 } 853 854 rnode = node->parent->subtree[idx + 1]; 855 if (rnode->keys < BTREE_MAX_KEYS) { 856 /* 857 * The rotaion can be done. The right sibling has free space. 858 */ 859 node_insert_key_and_rsubtree(node, inskey, insvalue, rsubtree); 860 rotate_from_left(node, rnode, idx); 861 return true; 862 } 863 864 return false; 865 } 866 867 /** Rotate in a key from the left sibling or from the index node, if this operation can be done. 868 * 869 * @param rnode Node into which to add key from its left sibling or from the index node. 870 * 871 * @return True if the rotation was performed, false otherwise. 872 */ 873 bool try_rotation_from_left(btree_node_t *rnode) 874 { 875 size_t idx; 876 btree_node_t *lnode; 877 878 /* 879 * If this is root node, the rotation can not be done. 880 */ 881 if (ROOT_NODE(rnode)) 882 return false; 883 884 idx = find_key_by_subtree(rnode->parent, rnode, true); 885 if ((int) idx == -1) { 886 /* 887 * If this node is the leftmost subtree of its parent, 888 * the rotation can not be done. 889 */ 890 return false; 891 } 892 893 lnode = rnode->parent->subtree[idx]; 894 if (lnode->keys > FILL_FACTOR) { 895 rotate_from_left(lnode, rnode, idx); 896 return true; 897 } 898 899 return false; 900 } 901 902 /** Rotate in a key from the right sibling or from the index node, if this operation can be done. 903 * 904 * @param lnode Node into which to add key from its right sibling or from the index node. 905 * 906 * @return True if the rotation was performed, false otherwise. 907 */ 908 bool try_rotation_from_right(btree_node_t *lnode) 909 { 910 size_t idx; 911 btree_node_t *rnode; 912 913 /* 914 * If this is root node, the rotation can not be done. 915 */ 916 if (ROOT_NODE(lnode)) 917 return false; 918 919 idx = find_key_by_subtree(lnode->parent, lnode, false); 920 if (idx == lnode->parent->keys) { 921 /* 922 * If this node is the rightmost subtree of its parent, 923 * the rotation can not be done. 924 */ 925 return false; 926 } 927 928 rnode = lnode->parent->subtree[idx + 1]; 929 if (rnode->keys > FILL_FACTOR) { 930 rotate_from_right(lnode, rnode, idx); 931 return true; 932 } 933 934 return false; 935 } 936 971 937 /** Print B-tree. 972 938 * 973 939 * @param t Print out B-tree. 974 *975 940 */ 976 941 void btree_print(btree_t *t) … … 979 944 int depth = t->root->depth; 980 945 link_t head, *cur; 981 946 982 947 printf("Printing B-tree:\n"); 983 948 list_initialize(&head); 984 949 list_append(&t->root->bfs_link, &head); 985 950 986 951 /* 987 952 * Use BFS search to print out the tree. 988 953 * Levels are distinguished from one another by node->depth. 989 */ 954 */ 990 955 while (!list_empty(&head)) { 991 956 link_t *hlp; … … 1003 968 depth = node->depth; 1004 969 } 1005 970 1006 971 printf("("); 1007 1008 972 for (i = 0; i < node->keys; i++) { 1009 973 printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); … … 1012 976 } 1013 977 } 1014 1015 if (node->depth && node->subtree[i]) 978 if (node->depth && node->subtree[i]) { 1016 979 list_append(&node->subtree[i]->bfs_link, &head); 1017 980 } 1018 981 printf(")"); 1019 982 } 1020 1021 983 printf("\n"); 1022 984 … … 1028 990 1029 991 ASSERT(node); 1030 992 1031 993 printf("("); 1032 1033 994 for (i = 0; i < node->keys; i++) 1034 995 printf("%" PRIu64 "%s", node->key[i], i < node->keys - 1 ? "," : ""); 1035 1036 996 printf(")"); 1037 997 } 1038 1039 998 printf("\n"); 1040 999 } -
kernel/generic/src/console/console.c
re2ea4ab1 r4d1be48 294 294 stdout->op->write(stdout, ch, silent); 295 295 else { 296 /* 297 * No standard output routine defined yet. 298 * The character is still stored in the kernel log 299 * for possible future output. 300 * 301 * The early_putchar() function is used to output 302 * the character for low-level debugging purposes. 303 * Note that the early_putc() function might be 304 * a no-op on certain hardware configurations. 305 * 306 */ 307 early_putchar(ch); 308 296 /* The character is just in the kernel log */ 309 297 if (klog_stored < klog_len) 310 298 klog_stored++; -
kernel/generic/src/cpu/cpu.c
re2ea4ab1 r4d1be48 119 119 /** @} 120 120 */ 121 -
kernel/generic/src/debug/stacktrace.c
re2ea4ab1 r4d1be48 52 52 ops->symbol_resolve(pc, &symbol, &offset)) { 53 53 if (offset) 54 printf("%p: %s+% " PRIp "()\n", fp, symbol, offset);54 printf("%p: %s+%lx()\n", fp, symbol, offset); 55 55 else 56 56 printf("%p: %s()\n", fp, symbol); -
kernel/generic/src/lib/sort.c
re2ea4ab1 r4d1be48 27 27 */ 28 28 29 /** @addtogroup generic 29 /** @addtogroup generic 30 30 * @{ 31 31 */ … … 33 33 /** 34 34 * @file 35 * @brief 35 * @brief Sorting functions. 36 36 * 37 37 * This files contains functions implementing several sorting 38 * algorithms (e.g. quick sort and gnome sort). 39 * 40 */ 41 38 * algorithms (e.g. quick sort and bubble sort). 39 */ 40 42 41 #include <mm/slab.h> 43 42 #include <memstr.h> 44 43 #include <sort.h> 45 46 /** Immediate buffer size. 47 * 48 * For small buffer sizes avoid doing malloc() 49 * and use the stack. 50 * 51 */ 52 #define IBUF_SIZE 32 53 54 /** Array accessor. 55 * 56 */ 57 #define INDEX(buf, i, elem_size) ((buf) + (i) * (elem_size)) 58 59 /** Gnome sort 60 * 61 * Apply generic gnome sort algorithm on supplied data, 62 * using pre-allocated buffer. 63 * 64 * @param data Pointer to data to be sorted. 65 * @param cnt Number of elements to be sorted. 66 * @param elem_size Size of one element. 67 * @param cmp Comparator function. 68 * @param arg 3rd argument passed to cmp. 69 * @param slot Pointer to scratch memory buffer 70 * elem_size bytes long. 71 * 72 */ 73 static void _gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, 74 void *arg, void *slot) 75 { 76 size_t i = 0; 44 #include <panic.h> 45 46 #define EBUFSIZE 32 47 48 void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot); 49 void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot); 50 51 /** Quicksort wrapper 52 * 53 * This is only a wrapper that takes care of memory allocations for storing 54 * the pivot and temporary elements for generic quicksort algorithm. 55 * 56 * This function _can_ sleep 57 * 58 * @param data Pointer to data to be sorted. 59 * @param n Number of elements to be sorted. 60 * @param e_size Size of one element. 61 * @param cmp Comparator function. 62 * 63 */ 64 void qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)) 65 { 66 uint8_t buf_tmp[EBUFSIZE]; 67 uint8_t buf_pivot[EBUFSIZE]; 68 void * tmp = buf_tmp; 69 void * pivot = buf_pivot; 70 71 if (e_size > EBUFSIZE) { 72 pivot = (void *) malloc(e_size, 0); 73 tmp = (void *) malloc(e_size, 0); 74 } 75 76 _qsort(data, n, e_size, cmp, tmp, pivot); 77 77 78 while (i < cnt) { 79 if ((i > 0) && 80 (cmp(INDEX(data, i, elem_size), 81 INDEX(data, i - 1, elem_size), arg) == -1)) { 82 memcpy(slot, INDEX(data, i, elem_size), elem_size); 83 memcpy(INDEX(data, i, elem_size), INDEX(data, i - 1, elem_size), 84 elem_size); 85 memcpy(INDEX(data, i - 1, elem_size), slot, elem_size); 86 i--; 87 } else 88 i++; 78 if (e_size > EBUFSIZE) { 79 free(tmp); 80 free(pivot); 89 81 } 90 82 } … … 92 84 /** Quicksort 93 85 * 94 * Apply generic quicksort algorithm on supplied data, 95 * using pre-allocated buffers. 96 * 97 * @param data Pointer to data to be sorted. 98 * @param cnt Number of elements to be sorted. 99 * @param elem_size Size of one element. 100 * @param cmp Comparator function. 101 * @param arg 3rd argument passed to cmp. 102 * @param slot Pointer to scratch memory buffer 103 * elem_size bytes long. 104 * @param pivot Pointer to scratch memory buffer 105 * elem_size bytes long. 106 * 107 */ 108 static void _qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, 109 void *arg, void *slot, void *pivot) 110 { 111 if (cnt > 4) { 112 size_t i = 0; 113 size_t j = cnt - 1; 114 115 memcpy(pivot, data, elem_size); 116 117 while (true) { 118 while ((cmp(INDEX(data, i, elem_size), pivot, arg) < 0) && (i < cnt)) 86 * Apply generic quicksort algorithm on supplied data, using pre-allocated buffers. 87 * 88 * @param data Pointer to data to be sorted. 89 * @param n Number of elements to be sorted. 90 * @param e_size Size of one element. 91 * @param cmp Comparator function. 92 * @param tmp Pointer to scratch memory buffer e_size bytes long. 93 * @param pivot Pointer to scratch memory buffer e_size bytes long. 94 * 95 */ 96 void _qsort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *tmp, void *pivot) 97 { 98 if (n > 4) { 99 unsigned int i = 0, j = n - 1; 100 101 memcpy(pivot, data, e_size); 102 103 while (1) { 104 while ((cmp(data + i * e_size, pivot) < 0) && (i < n)) 119 105 i++; 120 121 while ((cmp(INDEX(data, j, elem_size), pivot, arg) >= 0) && (j > 0)) 106 while ((cmp(data + j * e_size, pivot) >= 0) && (j > 0)) 122 107 j--; 123 108 124 109 if (i < j) { 125 memcpy(slot, INDEX(data, i, elem_size), elem_size); 126 memcpy(INDEX(data, i, elem_size), INDEX(data, j, elem_size), 127 elem_size); 128 memcpy(INDEX(data, j, elem_size), slot, elem_size); 129 } else 110 memcpy(tmp, data + i * e_size, e_size); 111 memcpy(data + i * e_size, data + j * e_size, e_size); 112 memcpy(data + j * e_size, tmp, e_size); 113 } else { 130 114 break; 115 } 131 116 } 132 133 _qsort(data, j + 1, elem_size, cmp, arg, slot, pivot); 134 _qsort(INDEX(data, j + 1, elem_size), cnt - j - 1, elem_size, 135 cmp, arg, slot, pivot); 136 } else 137 _gsort(data, cnt, elem_size, cmp, arg, slot); 138 } 139 140 /** Gnome sort wrapper 141 * 142 * This is only a wrapper that takes care of memory 143 * allocations for storing the slot element for generic 144 * gnome sort algorithm. 145 * 146 * This function can sleep. 147 * 148 * @param data Pointer to data to be sorted. 149 * @param cnt Number of elements to be sorted. 150 * @param elem_size Size of one element. 151 * @param cmp Comparator function. 152 * @param arg 3rd argument passed to cmp. 153 * 154 * @return True if sorting succeeded. 155 * 156 */ 157 bool gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 158 { 159 uint8_t ibuf_slot[IBUF_SIZE]; 160 void *slot; 117 118 _qsort(data, j + 1, e_size, cmp, tmp, pivot); 119 _qsort(data + (j + 1) * e_size, n - j - 1, e_size, cmp, tmp, pivot); 120 } else { 121 _bubblesort(data, n, e_size, cmp, tmp); 122 } 123 } 124 125 /** Bubblesort wrapper 126 * 127 * This is only a wrapper that takes care of memory allocation for storing 128 * the slot element for generic bubblesort algorithm. 129 * 130 * @param data Pointer to data to be sorted. 131 * @param n Number of elements to be sorted. 132 * @param e_size Size of one element. 133 * @param cmp Comparator function. 134 * 135 */ 136 void bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b)) 137 { 138 uint8_t buf_slot[EBUFSIZE]; 139 void * slot = buf_slot; 161 140 162 if (elem_size > IBUF_SIZE) { 163 slot = (void *) malloc(elem_size, 0); 164 if (!slot) 165 return false; 166 } else 167 slot = (void *) ibuf_slot; 141 if (e_size > EBUFSIZE) { 142 slot = (void *) malloc(e_size, 0); 143 } 144 145 _bubblesort(data, n, e_size, cmp, slot); 168 146 169 _gsort(data, cnt, elem_size, cmp, arg, slot); 170 171 if (elem_size > IBUF_SIZE) 147 if (e_size > EBUFSIZE) { 172 148 free(slot); 173 174 return true; 175 } 176 177 /** Quicksort wrapper 178 * 179 * This is only a wrapper that takes care of memory 180 * allocations for storing the pivot and temporary elements 181 * for generic quicksort algorithm. 182 * 183 * This function can sleep. 184 * 185 * @param data Pointer to data to be sorted. 186 * @param cnt Number of elements to be sorted. 187 * @param elem_size Size of one element. 188 * @param cmp Comparator function. 189 * @param arg 3rd argument passed to cmp. 190 * 191 * @return True if sorting succeeded. 192 * 193 */ 194 bool qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 195 { 196 uint8_t ibuf_slot[IBUF_SIZE]; 197 uint8_t ibuf_pivot[IBUF_SIZE]; 198 void *slot; 199 void *pivot; 200 201 if (elem_size > IBUF_SIZE) { 202 slot = (void *) malloc(elem_size, 0); 203 if (!slot) 204 return false; 205 206 pivot = (void *) malloc(elem_size, 0); 207 if (!pivot) { 208 free(slot); 209 return false; 149 } 150 } 151 152 /** Bubblesort 153 * 154 * Apply generic bubblesort algorithm on supplied data, using pre-allocated buffer. 155 * 156 * @param data Pointer to data to be sorted. 157 * @param n Number of elements to be sorted. 158 * @param e_size Size of one element. 159 * @param cmp Comparator function. 160 * @param slot Pointer to scratch memory buffer e_size bytes long. 161 * 162 */ 163 void _bubblesort(void * data, size_t n, size_t e_size, int (* cmp) (void * a, void * b), void *slot) 164 { 165 bool done = false; 166 void * p; 167 168 while (!done) { 169 done = true; 170 for (p = data; p < data + e_size * (n - 1); p = p + e_size) { 171 if (cmp(p, p + e_size) == 1) { 172 memcpy(slot, p, e_size); 173 memcpy(p, p + e_size, e_size); 174 memcpy(p + e_size, slot, e_size); 175 done = false; 176 } 210 177 } 211 } else { 212 slot = (void *) ibuf_slot; 213 pivot = (void *) ibuf_pivot; 214 } 215 216 _qsort(data, cnt, elem_size, cmp, arg, slot, pivot); 217 218 if (elem_size > IBUF_SIZE) { 219 free(pivot); 220 free(slot); 221 } 222 223 return true; 178 } 179 180 } 181 182 /* 183 * Comparator returns 1 if a > b, 0 if a == b, -1 if a < b 184 */ 185 int int_cmp(void * a, void * b) 186 { 187 return (* (int *) a > * (int*)b) ? 1 : (*(int *)a < * (int *)b) ? -1 : 0; 188 } 189 190 int uint8_t_cmp(void * a, void * b) 191 { 192 return (* (uint8_t *) a > * (uint8_t *)b) ? 1 : (*(uint8_t *)a < * (uint8_t *)b) ? -1 : 0; 193 } 194 195 int uint16_t_cmp(void * a, void * b) 196 { 197 return (* (uint16_t *) a > * (uint16_t *)b) ? 1 : (*(uint16_t *)a < * (uint16_t *)b) ? -1 : 0; 198 } 199 200 int uint32_t_cmp(void * a, void * b) 201 { 202 return (* (uint32_t *) a > * (uint32_t *)b) ? 1 : (*(uint32_t *)a < * (uint32_t *)b) ? -1 : 0; 224 203 } 225 204 -
kernel/generic/src/main/main.c
re2ea4ab1 r4d1be48 104 104 105 105 /** Lowest safe stack virtual address. */ 106 uintptr_t stack_safe = 0; 106 uintptr_t stack_safe = 0; 107 107 108 108 /* … … 113 113 */ 114 114 static void main_bsp_separated_stack(void); 115 116 115 #ifdef CONFIG_SMP 117 116 static void main_ap_separated_stack(void); 118 117 #endif 119 118 120 #define CONFIG_STACK_SIZE 119 #define CONFIG_STACK_SIZE ((1 << STACK_FRAMES) * STACK_SIZE) 121 120 122 121 /** Main kernel routine for bootstrap CPU. … … 131 130 * 132 131 */ 133 void __attribute__((no_instrument_function))main_bsp(void)132 void main_bsp(void) 134 133 { 135 134 config.cpu_count = 1; … … 152 151 init.tasks[i].size, config.stack_size); 153 152 } 154 153 155 154 /* Avoid placing stack on top of boot allocations. */ 156 155 if (ballocs.size) { … … 171 170 } 172 171 172 173 173 /** Main kernel routine for bootstrap CPU using new stack. 174 174 * … … 176 176 * 177 177 */ 178 void main_bsp_separated_stack(void) 178 void main_bsp_separated_stack(void) 179 179 { 180 180 /* Keep this the first thing. */ … … 183 183 version_print(); 184 184 185 LOG("\nconfig.base=% pconfig.kernel_size=%" PRIs186 "\nconfig.stack_base=% pconfig.stack_size=%" PRIs,185 LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs 186 "\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs, 187 187 config.base, config.kernel_size, config.stack_base, 188 188 config.stack_size); … … 194 194 * commands. 195 195 */ 196 kconsole_init();196 LOG_EXEC(kconsole_init()); 197 197 #endif 198 198 … … 201 201 * starts adding its own handlers 202 202 */ 203 exc_init();203 LOG_EXEC(exc_init()); 204 204 205 205 /* 206 206 * Memory management subsystems initialization. 207 207 */ 208 arch_pre_mm_init();209 frame_init();208 LOG_EXEC(arch_pre_mm_init()); 209 LOG_EXEC(frame_init()); 210 210 211 211 /* Initialize at least 1 memory segment big enough for slab to work. */ 212 slab_cache_init();213 sysinfo_init();214 btree_init();215 as_init();216 page_init();217 tlb_init();218 ddi_init();219 tasklet_init();220 arch_post_mm_init();221 arch_pre_smp_init();222 smp_init();212 LOG_EXEC(slab_cache_init()); 213 LOG_EXEC(sysinfo_init()); 214 LOG_EXEC(btree_init()); 215 LOG_EXEC(as_init()); 216 LOG_EXEC(page_init()); 217 LOG_EXEC(tlb_init()); 218 LOG_EXEC(ddi_init()); 219 LOG_EXEC(tasklet_init()); 220 LOG_EXEC(arch_post_mm_init()); 221 LOG_EXEC(arch_pre_smp_init()); 222 LOG_EXEC(smp_init()); 223 223 224 224 /* Slab must be initialized after we know the number of processors. */ 225 slab_enable_cpucache();225 LOG_EXEC(slab_enable_cpucache()); 226 226 227 227 printf("Detected %" PRIs " CPU(s), %" PRIu64" MiB free memory\n", 228 228 config.cpu_count, SIZE2MB(zones_total_size())); 229 230 cpu_init();231 232 calibrate_delay_loop();233 clock_counter_init();234 timeout_init();235 scheduler_init();236 task_init();237 thread_init();238 futex_init();229 230 LOG_EXEC(cpu_init()); 231 232 LOG_EXEC(calibrate_delay_loop()); 233 LOG_EXEC(clock_counter_init()); 234 LOG_EXEC(timeout_init()); 235 LOG_EXEC(scheduler_init()); 236 LOG_EXEC(task_init()); 237 LOG_EXEC(thread_init()); 238 LOG_EXEC(futex_init()); 239 239 240 240 if (init.cnt > 0) { 241 241 size_t i; 242 242 for (i = 0; i < init.cnt; i++) 243 LOG("init[%" PRIs "].addr=% p, init[%" PRIs244 "].size=% " PRIs, i, init.tasks[i].addr, i,243 LOG("init[%" PRIs "].addr=%#" PRIp ", init[%" PRIs 244 "].size=%#" PRIs, i, init.tasks[i].addr, i, 245 245 init.tasks[i].size); 246 246 } else 247 247 printf("No init binaries found.\n"); 248 248 249 ipc_init();250 event_init();251 klog_init();252 stats_init();249 LOG_EXEC(ipc_init()); 250 LOG_EXEC(event_init()); 251 LOG_EXEC(klog_init()); 252 LOG_EXEC(stats_init()); 253 253 254 254 /* … … 266 266 if (!kinit_thread) 267 267 panic("Cannot create kinit thread."); 268 thread_ready(kinit_thread);268 LOG_EXEC(thread_ready(kinit_thread)); 269 269 270 270 /* … … 276 276 } 277 277 278 278 279 #ifdef CONFIG_SMP 279 280 280 /** Main kernel routine for application CPUs. 281 281 * … … 296 296 */ 297 297 config.cpu_active++; 298 298 299 299 /* 300 300 * The THE structure is well defined because ctx.sp is used as stack. … … 311 311 calibrate_delay_loop(); 312 312 arch_post_cpu_init(); 313 313 314 314 the_copy(THE, (the_t *) CPU->stack); 315 315 316 316 /* 317 317 * If we woke kmp up before we left the kernel stack, we could … … 326 326 } 327 327 328 328 329 /** Main kernel routine for application CPUs using new stack. 329 330 * … … 337 338 */ 338 339 timeout_init(); 339 340 340 341 waitq_wakeup(&ap_completion_wq, WAKEUP_FIRST); 341 342 scheduler(); 342 343 /* not reached */ 343 344 } 344 345 345 #endif /* CONFIG_SMP */ 346 346 -
kernel/generic/src/mm/as.c
re2ea4ab1 r4d1be48 116 116 as_t *AS_KERNEL = NULL; 117 117 118 static unsigned int area_flags_to_page_flags(unsigned int); 119 static as_area_t *find_area_and_lock(as_t *, uintptr_t); 120 static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *); 121 static void sh_info_remove_reference(share_info_t *); 122 118 123 static int as_constructor(void *obj, unsigned int flags) 119 124 { … … 291 296 if (atomic_predec(&as->refcount) == 0) 292 297 as_destroy(as); 293 }294 295 /** Check area conflicts with other areas.296 *297 * @param as Address space.298 * @param va Starting virtual address of the area being tested.299 * @param size Size of the area being tested.300 * @param avoid_area Do not touch this area.301 *302 * @return True if there is no conflict, false otherwise.303 *304 */305 static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size,306 as_area_t *avoid_area)307 {308 ASSERT(mutex_locked(&as->lock));309 310 /*311 * We don't want any area to have conflicts with NULL page.312 *313 */314 if (overlaps(va, size, NULL, PAGE_SIZE))315 return false;316 317 /*318 * The leaf node is found in O(log n), where n is proportional to319 * the number of address space areas belonging to as.320 * The check for conflicts is then attempted on the rightmost321 * record in the left neighbour, the leftmost record in the right322 * neighbour and all records in the leaf node itself.323 *324 */325 btree_node_t *leaf;326 as_area_t *area =327 (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);328 if (area) {329 if (area != avoid_area)330 return false;331 }332 333 /* First, check the two border cases. */334 btree_node_t *node =335 btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);336 if (node) {337 area = (as_area_t *) node->value[node->keys - 1];338 339 mutex_lock(&area->lock);340 341 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {342 mutex_unlock(&area->lock);343 return false;344 }345 346 mutex_unlock(&area->lock);347 }348 349 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);350 if (node) {351 area = (as_area_t *) node->value[0];352 353 mutex_lock(&area->lock);354 355 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {356 mutex_unlock(&area->lock);357 return false;358 }359 360 mutex_unlock(&area->lock);361 }362 363 /* Second, check the leaf node. */364 btree_key_t i;365 for (i = 0; i < leaf->keys; i++) {366 area = (as_area_t *) leaf->value[i];367 368 if (area == avoid_area)369 continue;370 371 mutex_lock(&area->lock);372 373 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) {374 mutex_unlock(&area->lock);375 return false;376 }377 378 mutex_unlock(&area->lock);379 }380 381 /*382 * So far, the area does not conflict with other areas.383 * Check if it doesn't conflict with kernel address space.384 *385 */386 if (!KERNEL_ADDRESS_SPACE_SHADOWED) {387 return !overlaps(va, size,388 KERNEL_ADDRESS_SPACE_START,389 KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START);390 }391 392 return true;393 298 } 394 299 … … 452 357 453 358 return area; 454 }455 456 /** Find address space area and lock it.457 *458 * @param as Address space.459 * @param va Virtual address.460 *461 * @return Locked address space area containing va on success or462 * NULL on failure.463 *464 */465 static as_area_t *find_area_and_lock(as_t *as, uintptr_t va)466 {467 ASSERT(mutex_locked(&as->lock));468 469 btree_node_t *leaf;470 as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf);471 if (area) {472 /* va is the base address of an address space area */473 mutex_lock(&area->lock);474 return area;475 }476 477 /*478 * Search the leaf node and the righmost record of its left neighbour479 * to find out whether this is a miss or va belongs to an address480 * space area found there.481 *482 */483 484 /* First, search the leaf node itself. */485 btree_key_t i;486 487 for (i = 0; i < leaf->keys; i++) {488 area = (as_area_t *) leaf->value[i];489 490 mutex_lock(&area->lock);491 492 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE))493 return area;494 495 mutex_unlock(&area->lock);496 }497 498 /*499 * Second, locate the left neighbour and test its last record.500 * Because of its position in the B+tree, it must have base < va.501 *502 */503 btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf);504 if (lnode) {505 area = (as_area_t *) lnode->value[lnode->keys - 1];506 507 mutex_lock(&area->lock);508 509 if (va < area->base + area->pages * PAGE_SIZE)510 return area;511 512 mutex_unlock(&area->lock);513 }514 515 return NULL;516 359 } 517 360 … … 710 553 } 711 554 712 /** Remove reference to address space area share info.713 *714 * If the reference count drops to 0, the sh_info is deallocated.715 *716 * @param sh_info Pointer to address space area share info.717 *718 */719 static void sh_info_remove_reference(share_info_t *sh_info)720 {721 bool dealloc = false;722 723 mutex_lock(&sh_info->lock);724 ASSERT(sh_info->refcount);725 726 if (--sh_info->refcount == 0) {727 dealloc = true;728 link_t *cur;729 730 /*731 * Now walk carefully the pagemap B+tree and free/remove732 * reference from all frames found there.733 */734 for (cur = sh_info->pagemap.leaf_head.next;735 cur != &sh_info->pagemap.leaf_head; cur = cur->next) {736 btree_node_t *node737 = list_get_instance(cur, btree_node_t, leaf_link);738 btree_key_t i;739 740 for (i = 0; i < node->keys; i++)741 frame_free((uintptr_t) node->value[i]);742 }743 744 }745 mutex_unlock(&sh_info->lock);746 747 if (dealloc) {748 btree_destroy(&sh_info->pagemap);749 free(sh_info);750 }751 }752 753 555 /** Destroy address space area. 754 556 * … … 1003 805 } 1004 806 1005 /** Convert address space area flags to page flags.1006 *1007 * @param aflags Flags of some address space area.1008 *1009 * @return Flags to be passed to page_mapping_insert().1010 *1011 */1012 static unsigned int area_flags_to_page_flags(unsigned int aflags)1013 {1014 unsigned int flags = PAGE_USER | PAGE_PRESENT;1015 1016 if (aflags & AS_AREA_READ)1017 flags |= PAGE_READ;1018 1019 if (aflags & AS_AREA_WRITE)1020 flags |= PAGE_WRITE;1021 1022 if (aflags & AS_AREA_EXEC)1023 flags |= PAGE_EXEC;1024 1025 if (aflags & AS_AREA_CACHEABLE)1026 flags |= PAGE_CACHEABLE;1027 1028 return flags;1029 }1030 1031 807 /** Change adress space area flags. 1032 808 * … … 1385 1161 } 1386 1162 1387 1163 /** Convert address space area flags to page flags. 1164 * 1165 * @param aflags Flags of some address space area. 1166 * 1167 * @return Flags to be passed to page_mapping_insert(). 1168 * 1169 */ 1170 unsigned int area_flags_to_page_flags(unsigned int aflags) 1171 { 1172 unsigned int flags = PAGE_USER | PAGE_PRESENT; 1173 1174 if (aflags & AS_AREA_READ) 1175 flags |= PAGE_READ; 1176 1177 if (aflags & AS_AREA_WRITE) 1178 flags |= PAGE_WRITE; 1179 1180 if (aflags & AS_AREA_EXEC) 1181 flags |= PAGE_EXEC; 1182 1183 if (aflags & AS_AREA_CACHEABLE) 1184 flags |= PAGE_CACHEABLE; 1185 1186 return flags; 1187 } 1388 1188 1389 1189 /** Compute flags for virtual address translation subsytem. … … 1472 1272 /** Test whether page tables are locked. 1473 1273 * 1474 * @param as 1475 * 1476 * @return 1477 * 1274 * @param as Address space where the page tables belong. 1275 * 1276 * @return True if the page tables belonging to the address soace 1277 * are locked, otherwise false. 1478 1278 */ 1479 1279 bool page_table_locked(as_t *as) … … 1483 1283 1484 1284 return as_operations->page_table_locked(as); 1285 } 1286 1287 1288 /** Find address space area and lock it. 1289 * 1290 * @param as Address space. 1291 * @param va Virtual address. 1292 * 1293 * @return Locked address space area containing va on success or 1294 * NULL on failure. 1295 * 1296 */ 1297 as_area_t *find_area_and_lock(as_t *as, uintptr_t va) 1298 { 1299 ASSERT(mutex_locked(&as->lock)); 1300 1301 btree_node_t *leaf; 1302 as_area_t *area = (as_area_t *) btree_search(&as->as_area_btree, va, &leaf); 1303 if (area) { 1304 /* va is the base address of an address space area */ 1305 mutex_lock(&area->lock); 1306 return area; 1307 } 1308 1309 /* 1310 * Search the leaf node and the righmost record of its left neighbour 1311 * to find out whether this is a miss or va belongs to an address 1312 * space area found there. 1313 * 1314 */ 1315 1316 /* First, search the leaf node itself. */ 1317 btree_key_t i; 1318 1319 for (i = 0; i < leaf->keys; i++) { 1320 area = (as_area_t *) leaf->value[i]; 1321 1322 mutex_lock(&area->lock); 1323 1324 if ((area->base <= va) && (va < area->base + area->pages * PAGE_SIZE)) 1325 return area; 1326 1327 mutex_unlock(&area->lock); 1328 } 1329 1330 /* 1331 * Second, locate the left neighbour and test its last record. 1332 * Because of its position in the B+tree, it must have base < va. 1333 * 1334 */ 1335 btree_node_t *lnode = btree_leaf_node_left_neighbour(&as->as_area_btree, leaf); 1336 if (lnode) { 1337 area = (as_area_t *) lnode->value[lnode->keys - 1]; 1338 1339 mutex_lock(&area->lock); 1340 1341 if (va < area->base + area->pages * PAGE_SIZE) 1342 return area; 1343 1344 mutex_unlock(&area->lock); 1345 } 1346 1347 return NULL; 1348 } 1349 1350 /** Check area conflicts with other areas. 1351 * 1352 * @param as Address space. 1353 * @param va Starting virtual address of the area being tested. 1354 * @param size Size of the area being tested. 1355 * @param avoid_area Do not touch this area. 1356 * 1357 * @return True if there is no conflict, false otherwise. 1358 * 1359 */ 1360 bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, 1361 as_area_t *avoid_area) 1362 { 1363 ASSERT(mutex_locked(&as->lock)); 1364 1365 /* 1366 * We don't want any area to have conflicts with NULL page. 1367 * 1368 */ 1369 if (overlaps(va, size, NULL, PAGE_SIZE)) 1370 return false; 1371 1372 /* 1373 * The leaf node is found in O(log n), where n is proportional to 1374 * the number of address space areas belonging to as. 1375 * The check for conflicts is then attempted on the rightmost 1376 * record in the left neighbour, the leftmost record in the right 1377 * neighbour and all records in the leaf node itself. 1378 * 1379 */ 1380 btree_node_t *leaf; 1381 as_area_t *area = 1382 (as_area_t *) btree_search(&as->as_area_btree, va, &leaf); 1383 if (area) { 1384 if (area != avoid_area) 1385 return false; 1386 } 1387 1388 /* First, check the two border cases. */ 1389 btree_node_t *node = 1390 btree_leaf_node_left_neighbour(&as->as_area_btree, leaf); 1391 if (node) { 1392 area = (as_area_t *) node->value[node->keys - 1]; 1393 1394 mutex_lock(&area->lock); 1395 1396 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) { 1397 mutex_unlock(&area->lock); 1398 return false; 1399 } 1400 1401 mutex_unlock(&area->lock); 1402 } 1403 1404 node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf); 1405 if (node) { 1406 area = (as_area_t *) node->value[0]; 1407 1408 mutex_lock(&area->lock); 1409 1410 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) { 1411 mutex_unlock(&area->lock); 1412 return false; 1413 } 1414 1415 mutex_unlock(&area->lock); 1416 } 1417 1418 /* Second, check the leaf node. */ 1419 btree_key_t i; 1420 for (i = 0; i < leaf->keys; i++) { 1421 area = (as_area_t *) leaf->value[i]; 1422 1423 if (area == avoid_area) 1424 continue; 1425 1426 mutex_lock(&area->lock); 1427 1428 if (overlaps(va, size, area->base, area->pages * PAGE_SIZE)) { 1429 mutex_unlock(&area->lock); 1430 return false; 1431 } 1432 1433 mutex_unlock(&area->lock); 1434 } 1435 1436 /* 1437 * So far, the area does not conflict with other areas. 1438 * Check if it doesn't conflict with kernel address space. 1439 * 1440 */ 1441 if (!KERNEL_ADDRESS_SPACE_SHADOWED) { 1442 return !overlaps(va, size, 1443 KERNEL_ADDRESS_SPACE_START, 1444 KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START); 1445 } 1446 1447 return true; 1485 1448 } 1486 1449 … … 1997 1960 } 1998 1961 1962 /** Remove reference to address space area share info. 1963 * 1964 * If the reference count drops to 0, the sh_info is deallocated. 1965 * 1966 * @param sh_info Pointer to address space area share info. 1967 * 1968 */ 1969 void sh_info_remove_reference(share_info_t *sh_info) 1970 { 1971 bool dealloc = false; 1972 1973 mutex_lock(&sh_info->lock); 1974 ASSERT(sh_info->refcount); 1975 1976 if (--sh_info->refcount == 0) { 1977 dealloc = true; 1978 link_t *cur; 1979 1980 /* 1981 * Now walk carefully the pagemap B+tree and free/remove 1982 * reference from all frames found there. 1983 */ 1984 for (cur = sh_info->pagemap.leaf_head.next; 1985 cur != &sh_info->pagemap.leaf_head; cur = cur->next) { 1986 btree_node_t *node 1987 = list_get_instance(cur, btree_node_t, leaf_link); 1988 btree_key_t i; 1989 1990 for (i = 0; i < node->keys; i++) 1991 frame_free((uintptr_t) node->value[i]); 1992 } 1993 1994 } 1995 mutex_unlock(&sh_info->lock); 1996 1997 if (dealloc) { 1998 btree_destroy(&sh_info->pagemap); 1999 free(sh_info); 2000 } 2001 } 2002 1999 2003 /* 2000 2004 * Address space related syscalls. -
kernel/generic/src/mm/page.c
re2ea4ab1 r4d1be48 38 38 * mappings between virtual addresses and physical addresses. 39 39 * Functions here are mere wrappers that call the real implementation. 40 * They however, define the single interface. 40 * They however, define the single interface. 41 41 * 42 42 */ -
kernel/generic/src/proc/the.c
re2ea4ab1 r4d1be48 33 33 /** 34 34 * @file 35 * @brief 35 * @brief THE structure functions. 36 36 * 37 37 * This file contains functions to manage the THE structure. … … 43 43 44 44 #include <arch.h> 45 45 46 46 47 /** Initialize THE structure -
uspace/lib/c/arch/ia64/src/entry.s
re2ea4ab1 r4d1be48 39 39 __entry: 40 40 alloc loc0 = ar.pfs, 0, 1, 2, 0 41 movl gp= _gp41 movl r1 = _gp 42 42 43 43 # Pass PCB pointer as the first argument to __main -
uspace/lib/c/arch/ia64/src/thread_entry.s
re2ea4ab1 r4d1be48 37 37 alloc loc0 = ar.pfs, 0, 1, 1, 0 38 38 39 movl gp= _gp39 movl r1 = _gp 40 40 41 41 # -
uspace/lib/c/generic/sort.c
re2ea4ab1 r4d1be48 36 36 * 37 37 * This files contains functions implementing several sorting 38 * algorithms (e.g. quick sort and gnome sort).38 * algorithms (e.g. quick sort and bubble sort). 39 39 * 40 40 */ … … 44 44 #include <malloc.h> 45 45 46 /** Immediate buffer size.46 /** Bubble sort 47 47 * 48 * For small buffer sizes avoid doing malloc() 49 * and use the stack. 50 * 51 */ 52 #define IBUF_SIZE 32 53 54 /** Array accessor. 55 * 56 */ 57 #define INDEX(buf, i, elem_size) ((buf) + (i) * (elem_size)) 58 59 /** Gnome sort 60 * 61 * Apply generic gnome sort algorithm on supplied data, 48 * Apply generic bubble sort algorithm on supplied data, 62 49 * using pre-allocated buffer. 63 50 * … … 71 58 * 72 59 */ 73 static void _ gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp,60 static void _bsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, 74 61 void *arg, void *slot) 75 62 { 76 size_t i = 0; 63 bool done = false; 64 void *tmp; 77 65 78 while (i < cnt) { 79 if ((i != 0) && 80 (cmp(INDEX(data, i, elem_size), 81 INDEX(data, i - 1, elem_size), arg) == -1)) { 82 memcpy(slot, INDEX(data, i, elem_size), elem_size); 83 memcpy(INDEX(data, i, elem_size), INDEX(data, i - 1, elem_size), 84 elem_size); 85 memcpy(INDEX(data, i - 1, elem_size), slot, elem_size); 86 i--; 87 } else 88 i++; 66 while (!done) { 67 done = true; 68 69 for (tmp = data; tmp < data + elem_size * (cnt - 1); 70 tmp = tmp + elem_size) { 71 if (cmp(tmp, tmp + elem_size, arg) == 1) { 72 memcpy(slot, tmp, elem_size); 73 memcpy(tmp, tmp + elem_size, elem_size); 74 memcpy(tmp + elem_size, slot, elem_size); 75 done = false; 76 } 77 } 89 78 } 90 79 } … … 100 89 * @param cmp Comparator function. 101 90 * @param arg 3rd argument passed to cmp. 102 * @param slotPointer to scratch memory buffer91 * @param tmp Pointer to scratch memory buffer 103 92 * elem_size bytes long. 104 93 * @param pivot Pointer to scratch memory buffer … … 107 96 */ 108 97 static void _qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, 109 void *arg, void * slot, void *pivot)98 void *arg, void *tmp, void *pivot) 110 99 { 111 100 if (cnt > 4) { … … 116 105 117 106 while (true) { 118 while ((cmp( INDEX(data, i, elem_size), pivot, arg) < 0) && (i < cnt))107 while ((cmp(data + i * elem_size, pivot, arg) < 0) && (i < cnt)) 119 108 i++; 120 109 121 while ((cmp( INDEX(data, j, elem_size), pivot, arg) >= 0) && (j > 0))110 while ((cmp(data + j * elem_size, pivot, arg) >= 0) && (j > 0)) 122 111 j--; 123 112 124 113 if (i < j) { 125 memcpy( slot, INDEX(data, i, elem_size), elem_size);126 memcpy( INDEX(data, i, elem_size), INDEX(data, j, elem_size),114 memcpy(tmp, data + i * elem_size, elem_size); 115 memcpy(data + i * elem_size, data + j * elem_size, 127 116 elem_size); 128 memcpy( INDEX(data, j, elem_size), slot, elem_size);117 memcpy(data + j * elem_size, tmp, elem_size); 129 118 } else 130 119 break; 131 120 } 132 121 133 _qsort(data, j + 1, elem_size, cmp, arg, slot, pivot);134 _qsort( INDEX(data, j + 1, elem_size), cnt - j - 1, elem_size,135 cmp, arg, slot, pivot);122 _qsort(data, j + 1, elem_size, cmp, arg, tmp, pivot); 123 _qsort(data + (j + 1) * elem_size, cnt - j - 1, elem_size, 124 cmp, arg, tmp, pivot); 136 125 } else 137 _ gsort(data, cnt, elem_size, cmp, arg, slot);126 _bsort(data, cnt, elem_size, cmp, arg, tmp); 138 127 } 139 128 140 /** Gnome sort wrapper129 /** Bubble sort wrapper 141 130 * 142 131 * This is only a wrapper that takes care of memory 143 132 * allocations for storing the slot element for generic 144 * gnome sort algorithm.133 * bubble sort algorithm. 145 134 * 146 135 * @param data Pointer to data to be sorted. … … 153 142 * 154 143 */ 155 bool gsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg)144 bool bsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 156 145 { 157 uint8_t ibuf_slot[IBUF_SIZE]; 158 void *slot; 146 void *slot = (void *) malloc(elem_size); 147 if (!slot) 148 return false; 159 149 160 if (elem_size > IBUF_SIZE) { 161 slot = (void *) malloc(elem_size); 162 if (!slot) 163 return false; 164 } else 165 slot = (void *) ibuf_slot; 150 _bsort(data, cnt, elem_size, cmp, arg, slot); 166 151 167 _gsort(data, cnt, elem_size, cmp, arg, slot); 168 169 if (elem_size > IBUF_SIZE) 170 free(slot); 152 free(slot); 171 153 172 154 return true; … … 190 172 bool qsort(void *data, size_t cnt, size_t elem_size, sort_cmp_t cmp, void *arg) 191 173 { 192 uint8_t ibuf_slot[IBUF_SIZE]; 193 uint8_t ibuf_pivot[IBUF_SIZE]; 194 void *slot; 195 void *pivot; 174 void *tmp = (void *) malloc(elem_size); 175 if (!tmp) 176 return false; 196 177 197 if (elem_size > IBUF_SIZE) { 198 slot = (void *) malloc(elem_size); 199 if (!slot) 200 return false; 201 202 pivot = (void *) malloc(elem_size); 203 if (!pivot) { 204 free(slot); 205 return false; 206 } 207 } else { 208 slot = (void *) ibuf_slot; 209 pivot = (void *) ibuf_pivot; 178 void *pivot = (void *) malloc(elem_size); 179 if (!pivot) { 180 free(tmp); 181 return false; 210 182 } 211 183 212 _qsort(data, cnt, elem_size, cmp, arg, slot, pivot);184 _qsort(data, cnt, elem_size, cmp, arg, tmp, pivot); 213 185 214 if (elem_size > IBUF_SIZE) { 215 free(pivot); 216 free(slot); 217 } 186 free(pivot); 187 free(tmp); 218 188 219 189 return true; -
uspace/lib/c/include/sort.h
re2ea4ab1 r4d1be48 41 41 typedef int (* sort_cmp_t)(void *, void *, void *); 42 42 43 extern bool gsort(void *, size_t, size_t, sort_cmp_t, void *);43 extern bool bsort(void *, size_t, size_t, sort_cmp_t, void *); 44 44 extern bool qsort(void *, size_t, size_t, sort_cmp_t, void *); 45 45
Note:
See TracChangeset
for help on using the changeset viewer.