mirror of
				https://gitlab.com/bztsrc/bootboot.git
				synced 2023-02-13 20:54:32 -05:00 
			
		
		
		
	ACPI, and SMP and more bullet-proof coding
This commit is contained in:
		
							parent
							
								
									bf6ab93f6f
								
							
						
					
					
						commit
						daf9fc50f3
					
				
					 19 changed files with 373 additions and 244 deletions
				
			
		| 
						 | 
				
			
			@ -280,6 +280,7 @@ void _start()
 | 
			
		|||
    /*** FIGYELEM: ez a kód párhuzamosan fut minden processzormagon ***/
 | 
			
		||||
    int x, y, s=bootboot.fb_scanline, w=bootboot.fb_width, h=bootboot.fb_height;
 | 
			
		||||
 | 
			
		||||
    if(s) {
 | 
			
		||||
        // célkereszt, hogy lássuk, a felbontás jó-e
 | 
			
		||||
        for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
 | 
			
		||||
        for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +292,7 @@ void _start()
 | 
			
		|||
 | 
			
		||||
        // köszönünk
 | 
			
		||||
        puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    // leállunk egyelőre
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -281,6 +281,7 @@ void _start()
 | 
			
		|||
    /*** NOTE: this code runs on all cores in parallel ***/
 | 
			
		||||
    int x, y, s=bootboot.fb_scanline, w=bootboot.fb_width, h=bootboot.fb_height;
 | 
			
		||||
 | 
			
		||||
    if(s) {
 | 
			
		||||
        // cross-hair to see screen dimension detected correctly
 | 
			
		||||
        for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
 | 
			
		||||
        for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +293,7 @@ void _start()
 | 
			
		|||
 | 
			
		||||
        // say hello
 | 
			
		||||
        puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    // hang for now
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1893,9 +1893,9 @@ void bootboot_startcore()
 | 
			
		|||
    asm volatile ("msr sctlr_el1, %0; isb" : : "r" (reg));
 | 
			
		||||
 | 
			
		||||
    // set stack and call _start() in sys/core
 | 
			
		||||
    asm volatile (  "mrs x2, mpidr_el1;"
 | 
			
		||||
                    "and x2, x2, #3;"
 | 
			
		||||
                    "mul x2, x2, %1;"
 | 
			
		||||
    asm volatile (  "mrs x0, mpidr_el1;"
 | 
			
		||||
                    "and x0, x0, #3;"
 | 
			
		||||
                    "mul x2, x0, %1;"
 | 
			
		||||
                    "sub x2, xzr, x2;" // sp = core_num * -initstack
 | 
			
		||||
                    "mov sp, x2; mov x30, %0; ret" : : "r" (entrypoint), "r" (initstack));
 | 
			
		||||
                    "mov sp, x2; mov x30, %0; ret" : : "r" (entrypoint), "r" (initstack) : "x0","x2");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								dist/bootboot.bin
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								dist/bootboot.bin
									
										
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								dist/bootboot.efi
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								dist/bootboot.efi
									
										
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								dist/bootboot.img
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								dist/bootboot.img
									
										
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								dist/bootboot.rom
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								dist/bootboot.rom
									
										
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 | 
			
		||||
extern unsigned char binary_boot_bin[512];
 | 
			
		||||
extern unsigned char binary_bootboot_bin[12288];
 | 
			
		||||
extern unsigned char binary_bootboot_efi[102002];
 | 
			
		||||
extern unsigned char binary_bootboot_efi[102543];
 | 
			
		||||
extern unsigned char binary_bootboot_img[35032];
 | 
			
		||||
extern unsigned char binary_bootboot_rv64[8192];
 | 
			
		||||
extern unsigned char binary_LICENCE_broadcom[1594];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,6 +81,7 @@ procedure Kernel is
 | 
			
		|||
begin
 | 
			
		||||
    ----- NOTE: this code runs on all cores in parallel -----
 | 
			
		||||
 | 
			
		||||
    if S > 0 then
 | 
			
		||||
        -- cross-hair to see screen dimension detected correctly
 | 
			
		||||
        for Y in Integer range 0 .. (H-1) loop
 | 
			
		||||
            bootboot.fb (S*Y + W/2) := bootboot.UInt32(16#00FFFFFF#);
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +109,7 @@ begin
 | 
			
		|||
 | 
			
		||||
        -- say hello
 | 
			
		||||
        puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
    end if;
 | 
			
		||||
    -- hang for now
 | 
			
		||||
    loop
 | 
			
		||||
        null;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,7 @@ void _start()
 | 
			
		|||
    /*** NOTE: this code runs on all cores in parallel ***/
 | 
			
		||||
    int x, y, s=bootboot.fb_scanline, w=bootboot.fb_width, h=bootboot.fb_height;
 | 
			
		||||
 | 
			
		||||
    if(s) {
 | 
			
		||||
        // cross-hair to see screen dimension detected correctly
 | 
			
		||||
        for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
 | 
			
		||||
        for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +65,7 @@ void _start()
 | 
			
		|||
 | 
			
		||||
        // say hello
 | 
			
		||||
        puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    // hang for now
 | 
			
		||||
    while(1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,7 @@ public:
 | 
			
		|||
        /*** NOTE: this code runs on all cores in parallel ***/
 | 
			
		||||
        int x, y, s=bootboot.fb_scanline, w=bootboot.fb_width, h=bootboot.fb_height;
 | 
			
		||||
 | 
			
		||||
        if(s) {
 | 
			
		||||
            // cross-hair to see screen dimension detected correctly
 | 
			
		||||
            for(y=0;y<h;y++) { *((uint32_t*)(&fb + s*y + (w*2)))=0x00FFFFFF; }
 | 
			
		||||
            for(x=0;x<w;x++) { *((uint32_t*)(&fb + s*(h/2)+x*4))=0x00FFFFFF; }
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +77,7 @@ public:
 | 
			
		|||
 | 
			
		||||
            // say hello
 | 
			
		||||
            MyKernel::puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        // hang for now
 | 
			
		||||
        while(1);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,10 +62,11 @@ const glyphs = "\x00\x00\xda\x02\x80\x82\x02\x80\x82\x02\x80\xb6\x00\x00\x00\x00
 | 
			
		|||
func init() {
 | 
			
		||||
    /*** NOTE: this code runs on all cores in parallel ***/
 | 
			
		||||
    var x, y int
 | 
			
		||||
    var w int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x34))))
 | 
			
		||||
    var h int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x38))))
 | 
			
		||||
    var s int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x3c))))
 | 
			
		||||
    var w int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x34))))    // bootboot.fb_width
 | 
			
		||||
    var h int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x38))))    // bootboot.fb_height
 | 
			
		||||
    var s int = (int)(*(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_INFO + 0x3c))))    // bootboot.fb_scanline
 | 
			
		||||
 | 
			
		||||
    if (s > 0) {
 | 
			
		||||
        // cross-hair to see screen dimension detected correctly
 | 
			
		||||
        for y = 0; y < h; y++ {
 | 
			
		||||
            *(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_FB) + uintptr(s*y + w*2))) = 0x00FFFFFF;
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +91,7 @@ func init() {
 | 
			
		|||
                *(*uint32)(unsafe.Pointer(uintptr(BOOTBOOT_FB) + uintptr(s*(y+20) + (x+80)*4))) = 0x000000FF;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    // say hello
 | 
			
		||||
    puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,8 @@ Begin
 | 
			
		|||
    W := Integer(bootboot.fb_width);
 | 
			
		||||
    H := Integer(bootboot.fb_height);
 | 
			
		||||
 | 
			
		||||
    If (S > 0) Then
 | 
			
		||||
    Begin
 | 
			
		||||
        { cross-hair to see screen dimension detected correctly }
 | 
			
		||||
        For Y := 0 to (H-1) Do
 | 
			
		||||
        Begin
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +103,7 @@ Begin
 | 
			
		|||
 | 
			
		||||
        { say hello }
 | 
			
		||||
        Puts('Hello from a simple BOOTBOOT kernel');
 | 
			
		||||
 | 
			
		||||
    End;
 | 
			
		||||
    { hang for now }
 | 
			
		||||
    While (True) Do;
 | 
			
		||||
End;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ extern crate rlibc;
 | 
			
		|||
#[no_mangle] // don't mangle the name of this function
 | 
			
		||||
fn _start() -> ! {
 | 
			
		||||
    /*** NOTE: this code runs on all cores in parallel ***/
 | 
			
		||||
    if bootboot::bootboot.fb_scanline > 0 {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            let fb = &bootboot::fb as *const u8 as u64;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +95,7 @@ fn _start() -> ! {
 | 
			
		|||
 | 
			
		||||
        // say hello
 | 
			
		||||
        puts("Hello from a simple BOOTBOOT kernel");
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    // hang for now
 | 
			
		||||
    loop {}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1968,7 +1968,7 @@ end if
 | 
			
		|||
            cmp         byte [ebx], 0       ; madt_entry.type: is it a Local APIC Processor?
 | 
			
		||||
            jne         @f
 | 
			
		||||
            xor         ax, ax
 | 
			
		||||
            mov         al, byte [ebx+2]    ; madt_entry.lapicproc.lapicid
 | 
			
		||||
            mov         al, byte [ebx+3]    ; madt_entry.lapicproc.lapicid
 | 
			
		||||
            stosw                           ; ACPI table holds 1 byte id, but internally we have 2 bytes
 | 
			
		||||
            inc         word [bootboot.numcores]
 | 
			
		||||
@@:         xor         eax, eax
 | 
			
		||||
| 
						 | 
				
			
			@ -2012,7 +2012,52 @@ end if
 | 
			
		|||
.dosmp:     cmp         word [bootboot.numcores], 2
 | 
			
		||||
            jb          .nosmp
 | 
			
		||||
 | 
			
		||||
            DBG32       dbg_smp
 | 
			
		||||
if BBDEBUG eq 1
 | 
			
		||||
            xor         eax, eax
 | 
			
		||||
            mov         dword [gpt_ptr], eax
 | 
			
		||||
            mov         dword [gpt_num], eax
 | 
			
		||||
            prot_realmode
 | 
			
		||||
            mov         si, dbg_smp
 | 
			
		||||
            mov         bx, word [bootboot.numcores]
 | 
			
		||||
            mov         di, gpt_ptr
 | 
			
		||||
 | 
			
		||||
            cmp         bx, 1000
 | 
			
		||||
            jl          @f
 | 
			
		||||
            mov         al, '1'
 | 
			
		||||
            stosb
 | 
			
		||||
            sub         bx, 1000
 | 
			
		||||
@@:         mov         cx, 100
 | 
			
		||||
            cmp         bx, cx
 | 
			
		||||
            jl          @f
 | 
			
		||||
            mov         ax, bx
 | 
			
		||||
            xor         dx, dx
 | 
			
		||||
            div         cx
 | 
			
		||||
            add         al, '0'
 | 
			
		||||
            stosb
 | 
			
		||||
            mov         bx, dx
 | 
			
		||||
@@:         mov         cx, 10
 | 
			
		||||
            cmp         bx, cx
 | 
			
		||||
            jl          @f
 | 
			
		||||
            mov         ax, bx
 | 
			
		||||
            xor         dx, dx
 | 
			
		||||
            div         cx
 | 
			
		||||
            add         al, '0'
 | 
			
		||||
            stosb
 | 
			
		||||
            mov         bx, dx
 | 
			
		||||
@@:         mov         al, bl
 | 
			
		||||
            add         al, '0'
 | 
			
		||||
            stosb
 | 
			
		||||
            xor         al, al
 | 
			
		||||
            stosb
 | 
			
		||||
 | 
			
		||||
            mov         si, dbg_smp
 | 
			
		||||
            call        real_printfunc
 | 
			
		||||
            mov         si, gpt_ptr
 | 
			
		||||
            call        real_printfunc
 | 
			
		||||
            mov         si, crlf
 | 
			
		||||
            call        real_printfunc
 | 
			
		||||
            real_protmode
 | 
			
		||||
end if
 | 
			
		||||
 | 
			
		||||
            ; relocate AP trampoline
 | 
			
		||||
            mov         esi, ap_trampoline
 | 
			
		||||
| 
						 | 
				
			
			@ -2324,11 +2369,10 @@ longmode_init:
 | 
			
		|||
            mov         eax, 0C0000011h ;clear EM, MP (enable SSE) and WP
 | 
			
		||||
            mov         cr0, eax        ;enable paging with cache disabled
 | 
			
		||||
            lgdt        [GDT_value]     ;read 80 bit address
 | 
			
		||||
            jmp         @f
 | 
			
		||||
            nop
 | 
			
		||||
@@:         jmp         8:@f
 | 
			
		||||
            jmp         8:.bootboot_startcore
 | 
			
		||||
            USE64
 | 
			
		||||
@@:         xor         eax, eax        ;load long mode segments
 | 
			
		||||
.bootboot_startcore:
 | 
			
		||||
            xor         rax, rax        ;load long mode segments
 | 
			
		||||
            mov         ax, 10h
 | 
			
		||||
            mov         ds, ax
 | 
			
		||||
            mov         es, ax
 | 
			
		||||
| 
						 | 
				
			
			@ -2336,10 +2380,13 @@ longmode_init:
 | 
			
		|||
            mov         fs, ax
 | 
			
		||||
            mov         gs, ax
 | 
			
		||||
            ; find out our lapic id
 | 
			
		||||
            mov         eax, 1
 | 
			
		||||
            cpuid
 | 
			
		||||
            shr         ebx, 24
 | 
			
		||||
            mov         edx, ebx
 | 
			
		||||
            mov         eax, dword [lapic_ptr]
 | 
			
		||||
            or          eax, eax
 | 
			
		||||
            jz          @f
 | 
			
		||||
            add         eax, 20h
 | 
			
		||||
            mov         eax, dword [rax]
 | 
			
		||||
            shr         eax, 24
 | 
			
		||||
@@:         mov         edx, eax
 | 
			
		||||
            ; get array index for it
 | 
			
		||||
            xor         rbx, rbx
 | 
			
		||||
            mov         rsi, lapic_ids
 | 
			
		||||
| 
						 | 
				
			
			@ -2351,7 +2398,8 @@ longmode_init:
 | 
			
		|||
            dec         cx
 | 
			
		||||
            jnz         @b
 | 
			
		||||
            xor         rbx, rbx
 | 
			
		||||
@@:         shl         rbx, 10         ; 1k stack for each core
 | 
			
		||||
@@:         mov         rdi, rbx
 | 
			
		||||
            shl         rbx, 10         ; 1k stack for each core
 | 
			
		||||
 | 
			
		||||
            ; set stack and call _start() in sys/core
 | 
			
		||||
            xor         rsp, rsp        ;sp = core_num * -1024
 | 
			
		||||
| 
						 | 
				
			
			@ -2732,7 +2780,7 @@ dbg_gzinitrd db         " * Gzip compressed initrd",10,13,0
 | 
			
		|||
dbg_scan    db          " * Autodetecting kernel",10,13,0
 | 
			
		||||
dbg_elf     db          " * Parsing ELF64",10,13,0
 | 
			
		||||
dbg_pe      db          " * Parsing PE32+",10,13,0
 | 
			
		||||
dbg_smp     db          " * SMP init",10,13,0
 | 
			
		||||
dbg_smp     db          " * SMP numcores ",0
 | 
			
		||||
dbg_vesa    db          " * Screen VESA VBE",10,13,0
 | 
			
		||||
end if
 | 
			
		||||
backup:     db          " * Backup initrd",10,13,0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,7 @@
 | 
			
		|||
 | 
			
		||||
extern void ap_trampoline();
 | 
			
		||||
#if __WORDSIZE == 64
 | 
			
		||||
extern void bsp64_init();
 | 
			
		||||
extern void bsp64_init(uint64_t apicid);
 | 
			
		||||
#else
 | 
			
		||||
extern void bsp_init();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -597,7 +597,7 @@ void GetLFB()
 | 
			
		|||
 */
 | 
			
		||||
void LoadCore()
 | 
			
		||||
{
 | 
			
		||||
    uint64_t bss = 0;
 | 
			
		||||
    uint64_t bss = 0, ptr;
 | 
			
		||||
    uint32_t r = 0;
 | 
			
		||||
 | 
			
		||||
    entrypoint=0;
 | 
			
		||||
| 
						 | 
				
			
			@ -716,8 +716,9 @@ void LoadCore()
 | 
			
		|||
    if(initstack < 1024) initstack = 1024;
 | 
			
		||||
    if(initstack > 16384) initstack = 16384;
 | 
			
		||||
    // create core segment
 | 
			
		||||
    memcpy((void*)((uint8_t*)(uintptr_t)bootboot->initrd_ptr+bootboot->initrd_size), core.ptr, core.size);
 | 
			
		||||
    core.ptr=(uint8_t*)(uintptr_t)bootboot->initrd_ptr+bootboot->initrd_size;
 | 
			
		||||
    ptr = ((bootboot->initrd_ptr+bootboot->initrd_size) + PAGESIZE - 1) & ~(PAGESIZE-1);
 | 
			
		||||
    memcpy((void*)(uintptr_t)ptr, core.ptr, core.size);
 | 
			
		||||
    core.ptr=(uint8_t*)(uintptr_t)ptr;
 | 
			
		||||
    if(bss>0)
 | 
			
		||||
        memset(core.ptr + core.size, 0, bss);
 | 
			
		||||
    core.size += bss;
 | 
			
		||||
| 
						 | 
				
			
			@ -1110,7 +1111,7 @@ gzerr:      panic("Unable to uncompress");
 | 
			
		|||
    LoadCore();
 | 
			
		||||
 | 
			
		||||
    /* Symmetric Multi Processing support */
 | 
			
		||||
    memset(lapic_ids, 0, sizeof(lapic_ids)); lapic_ids[0] = bootboot->bspid;
 | 
			
		||||
    memset(lapic_ids, 0xFF, sizeof(lapic_ids));
 | 
			
		||||
    ptr = (uint8_t*)(uintptr_t)bootboot->arch.x86_64.acpi_ptr;
 | 
			
		||||
    if(ptr && (ptr[0]=='X' || ptr[0]=='R') && ptr[1]=='S' && ptr[2]=='D' && ptr[3]=='T') {
 | 
			
		||||
        pe = ptr; ptr += 36;
 | 
			
		||||
| 
						 | 
				
			
			@ -1123,11 +1124,13 @@ gzerr:      panic("Unable to uncompress");
 | 
			
		|||
                for(r = *((uint32_t*)(data + 4)), ptr = data + 44, i = 0; ptr < data + r &&
 | 
			
		||||
                    i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); ptr += ptr[1]) {
 | 
			
		||||
                    switch(ptr[0]) {
 | 
			
		||||
                        case 0: lapic_ids[(int)ptr[2]] = i++; break;        // found Processor Local APIC
 | 
			
		||||
                        case 0:                                             // found Processor Local APIC
 | 
			
		||||
                            if((ptr[4] & 1) && lapic_ids[(int)ptr[3]] == 0xFFFF) { lapic_ids[(int)ptr[3]] = i++; }
 | 
			
		||||
                        break;
 | 
			
		||||
                        case 5: lapic_addr = *((uint64_t*)(ptr+4)); break;  // found 64 bit Local APIC Address
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if(i) bootboot->numcores = i;
 | 
			
		||||
                if(i && lapic_ids[bootboot->bspid] != 0xFFFF) bootboot->numcores = i;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1135,20 +1138,56 @@ gzerr:      panic("Unable to uncompress");
 | 
			
		|||
    if(!nosmp && bootboot->numcores > 1 && lapic_addr) {
 | 
			
		||||
        DBG(" * SMP numcores %d\n", bootboot->numcores);
 | 
			
		||||
        memcpy((uint8_t*)0x1000, &ap_trampoline, 128);
 | 
			
		||||
        // send Broadcast INIT IPI
 | 
			
		||||
        *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4500;
 | 
			
		||||
 | 
			
		||||
        // send INIT IPI (supports up to 256 cores, requires x2APIC to have more)
 | 
			
		||||
        for(i = 0; i < 256; i++) {
 | 
			
		||||
            if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0;                            // clear APIC errors
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & 0xfff00000) | 0x00C500;  // trigger INIT IPI
 | 
			
		||||
            do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                while(*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & (1 << 12));         // wait for delivery
 | 
			
		||||
            // deassert
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) & 0x00ffffff) | (i << 24);
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & 0xfff00000) | 0x008500;
 | 
			
		||||
            do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                while(*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & (1 << 12));
 | 
			
		||||
        }
 | 
			
		||||
        mdelay(10);
 | 
			
		||||
        // send Broadcast STARTUP IPI
 | 
			
		||||
        *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601; // start at 0100:0000h
 | 
			
		||||
        // send STARTUP IPI
 | 
			
		||||
        for(i = 0; i < 256; i++) {
 | 
			
		||||
            if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0;                            // clear APIC errors
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP
 | 
			
		||||
            // trigger IPI, start at 0100:0000h
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & 0xfff0f800) | 0x000601;
 | 
			
		||||
            udelay(200);
 | 
			
		||||
        // send second SIPI
 | 
			
		||||
        *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) = 0x0C4601;
 | 
			
		||||
    } else
 | 
			
		||||
            do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                while(*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & (1 << 12));         // wait for delivery
 | 
			
		||||
            // send second IPI
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x280)) = 0;
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x310)) & 0x00ffffff) | (i << 24);
 | 
			
		||||
            *((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) =
 | 
			
		||||
                (*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & 0xfff0f800) | 0x000601;
 | 
			
		||||
            do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                while(*((volatile uint32_t*)((uintptr_t)lapic_addr + 0x300)) & (1 << 12));
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        lapic_addr = 0;
 | 
			
		||||
        lapic_ids[bootboot->bspid] = 0;
 | 
			
		||||
        bootboot->numcores = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Create paging tables */
 | 
			
		||||
    DBG(" * Pagetables PML4 @%p\n",paging);
 | 
			
		||||
    memset(paging, 0, 37*PAGESIZE+bootboot->numcores*initstack);
 | 
			
		||||
    memset(paging, 0, (37+(bootboot->numcores*initstack+PAGESIZE-1)/PAGESIZE)*PAGESIZE);
 | 
			
		||||
    //PML4
 | 
			
		||||
    paging[0]=(uint64_t)((uintptr_t)paging+PAGESIZE)+3;  // pointer to 2M PDPE (16G RAM identity mapped)
 | 
			
		||||
    paging[511]=(uint64_t)((uintptr_t)paging+20*PAGESIZE)+3;   // pointer to 4k PDPE (core mapped at -2M)
 | 
			
		||||
| 
						 | 
				
			
			@ -1243,7 +1282,7 @@ gzerr:      panic("Unable to uncompress");
 | 
			
		|||
 | 
			
		||||
    /* continue in Assembly, enable long mode and jump to kernel's entry point */
 | 
			
		||||
#if __WORDSIZE == 64
 | 
			
		||||
    bsp64_init();
 | 
			
		||||
    bsp64_init(bootboot->bspid);
 | 
			
		||||
#else
 | 
			
		||||
    bsp_init();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@
 | 
			
		|||
.globl bsp_init
 | 
			
		||||
.globl bsp64_init
 | 
			
		||||
.extern lapic_ids
 | 
			
		||||
.extern lapic_addr
 | 
			
		||||
.extern initstack
 | 
			
		||||
 | 
			
		||||
    .text
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +77,7 @@ _L1060:
 | 
			
		|||
    cmpb    $0, 0x1010
 | 
			
		||||
    jz      1b
 | 
			
		||||
    // jump back to non-relocated code segment
 | 
			
		||||
    jmp     longmode_init
 | 
			
		||||
    ljmp    $8, $longmode_init
 | 
			
		||||
    .align 128
 | 
			
		||||
ap_trampoline_end:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +94,7 @@ GDT_value:
 | 
			
		|||
    .word 0
 | 
			
		||||
    .align 8
 | 
			
		||||
stack64:
 | 
			
		||||
    .long bit64
 | 
			
		||||
    .long bootboot_startcore
 | 
			
		||||
    .long 0
 | 
			
		||||
    .quad 8
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -117,6 +118,15 @@ bsp_init:
 | 
			
		|||
 * common code for all cores, enable long mode and start kernel              *
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
longmode_init:
 | 
			
		||||
    // find our lapic id
 | 
			
		||||
    movl    lapic_addr, %edi
 | 
			
		||||
    or      %edi, %edi
 | 
			
		||||
    jz      1f
 | 
			
		||||
    addl    $0x20, %edi
 | 
			
		||||
    movl    (%edi), %edi
 | 
			
		||||
    shrl    $24, %edi
 | 
			
		||||
1:  // do not clobber di
 | 
			
		||||
 | 
			
		||||
    movl    $0x368, %eax        // Set PAE, MCE, PGE; OSFXSR, OSXMMEXCPT (enable SSE)
 | 
			
		||||
    movl    %eax, %cr4
 | 
			
		||||
    movl    $0x4000, %eax
 | 
			
		||||
| 
						 | 
				
			
			@ -129,11 +139,12 @@ longmode_init:
 | 
			
		|||
    movl    $0x0C0000011, %eax  // clear EM, MP (enable SSE) and WP
 | 
			
		||||
    movl    %eax, %cr0
 | 
			
		||||
    lgdt    GDT_value
 | 
			
		||||
    ljmp    $8, $bit64
 | 
			
		||||
    ljmp    $8, $bootboot_startcore
 | 
			
		||||
 | 
			
		||||
    .code64
 | 
			
		||||
    /* similar code to above, but these are 64 bit encoded, only needed on BSP if coreboot is compiled for x86_64 */
 | 
			
		||||
bsp64_init:
 | 
			
		||||
    // do not clobber di
 | 
			
		||||
    cli
 | 
			
		||||
    cld
 | 
			
		||||
    movb    $0xFF, %al          // disable PIC
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +154,7 @@ bsp64_init:
 | 
			
		|||
    orb     $0x80, %al
 | 
			
		||||
    outb    %al, $0x70
 | 
			
		||||
    incb    0x1010              // release AP spin lock
 | 
			
		||||
 | 
			
		||||
    xorq    %rax, %rax
 | 
			
		||||
    movl    $0xC0000011, %eax   // enable SSE
 | 
			
		||||
    movq    %rax, %cr0
 | 
			
		||||
| 
						 | 
				
			
			@ -158,24 +170,22 @@ bsp64_init:
 | 
			
		|||
    movq    %rax, %rsp
 | 
			
		||||
    lretq
 | 
			
		||||
 | 
			
		||||
bit64:
 | 
			
		||||
    /* IN: di = apic id of current core */
 | 
			
		||||
bootboot_startcore:
 | 
			
		||||
    movl    $0x10, %eax         // load long mode segments
 | 
			
		||||
    movw    %ax, %ds
 | 
			
		||||
    movw    %ax, %es
 | 
			
		||||
    movw    %ax, %ss
 | 
			
		||||
    movw    %ax, %fs
 | 
			
		||||
    movw    %ax, %gs
 | 
			
		||||
    xorq    %rbx, %rbx
 | 
			
		||||
    // find our lapic id
 | 
			
		||||
    movl    $1, %eax
 | 
			
		||||
    cpuid
 | 
			
		||||
    shrl    $23, %ebx
 | 
			
		||||
    andb    $0xfe, %bl          // ebx = lapic id * 2
 | 
			
		||||
    movzwq  %di, %rbx
 | 
			
		||||
    shll    $1, %ebx            // ebx = lapic id * 2
 | 
			
		||||
    addl    $lapic_ids, %ebx
 | 
			
		||||
    xorq    %rax, %rax
 | 
			
		||||
    movw    (%rbx), %ax         // ax = word[lapic_ids + lapic id * 2]
 | 
			
		||||
1:  movl    $initstack, %ebx
 | 
			
		||||
    movl    $initstack, %ebx
 | 
			
		||||
    movl    (%rbx), %ebx
 | 
			
		||||
    movzwq  %ax, %rdi
 | 
			
		||||
    mulq    %rbx                // 1k stack for each core
 | 
			
		||||
 | 
			
		||||
    // set stack and call _start() in sys/core
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -223,6 +223,7 @@ struct _EFI_MP_SERVICES_PROTOCOL {
 | 
			
		|||
#else
 | 
			
		||||
extern void ap_trampoline();
 | 
			
		||||
UINT16 lapic_ids[1024];
 | 
			
		||||
UINT64 lapic_addr=0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef
 | 
			
		||||
| 
						 | 
				
			
			@ -1394,21 +1395,14 @@ VOID EFIAPI bootboot_startcore(IN VOID* buf)
 | 
			
		|||
{
 | 
			
		||||
#if USE_MP_SERVICES
 | 
			
		||||
    // we have a scalar number, not a pointer, so cast it
 | 
			
		||||
    UINTN core_num = (UINTN)buf;
 | 
			
		||||
    register UINTN core_num = (UINTN)buf;
 | 
			
		||||
#else
 | 
			
		||||
    (void)buf;
 | 
			
		||||
    UINT16 core_num;
 | 
			
		||||
    __asm__ __volatile__ (
 | 
			
		||||
        "movl $1, %%eax;"
 | 
			
		||||
        "cpuid;"
 | 
			
		||||
        "shrl $24, %%ebx;"
 | 
			
		||||
        "mov %%bx,%0"
 | 
			
		||||
        : "=b"(core_num) : : );
 | 
			
		||||
    core_num = lapic_ids[core_num];
 | 
			
		||||
    register UINT16 core_num = lapic_addr ? lapic_ids[*((volatile uint32_t*)(lapic_addr + 0x20)) >> 24] : 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // spinlock until BSP finishes
 | 
			
		||||
    do { __asm__ __volatile__ ("pause"); } while(!bsp_done);
 | 
			
		||||
    // spinlock until BSP finishes (or forever if we got an invalid lapicid, should never happen)
 | 
			
		||||
    do { __asm__ __volatile__ ("pause" : : : "memory"); } while(!bsp_done && core_num != 0xFFFF);
 | 
			
		||||
 | 
			
		||||
    // enable SSE
 | 
			
		||||
    __asm__ __volatile__ (
 | 
			
		||||
| 
						 | 
				
			
			@ -1432,8 +1426,9 @@ VOID EFIAPI bootboot_startcore(IN VOID* buf)
 | 
			
		|||
        "subq %0, %%rsp;"  // sp = core_num * -initstack
 | 
			
		||||
        // pass control over
 | 
			
		||||
        "pushq %1;"
 | 
			
		||||
        "movq %2, %%rdi;"
 | 
			
		||||
        "retq"
 | 
			
		||||
        : : "a"((UINTN)core_num*initstack), "b"(entrypoint) : "memory" );
 | 
			
		||||
        : : "a"((UINTN)core_num*initstack), "b"(entrypoint), "c"((UINTN)core_num) : "memory" );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1924,8 +1919,8 @@ gzerr:          return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
 | 
			
		|||
            bootboot->numcores = 1;
 | 
			
		||||
#else
 | 
			
		||||
        UINT8 *ptr = (UINT8*)bootboot->arch.x86_64.acpi_ptr, *pe, *data;
 | 
			
		||||
        UINT64 r, lapic_addr=0;
 | 
			
		||||
        ZeroMem(lapic_ids, sizeof(lapic_ids));
 | 
			
		||||
        UINT64 r;
 | 
			
		||||
        for(i = 0; i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); i++) lapic_ids[i] = 0xFFFF;
 | 
			
		||||
        if(!nosmp && ptr && (ptr[0]=='X' || ptr[0]=='R') && ptr[1]=='S' && ptr[2]=='D' && ptr[3]=='T') {
 | 
			
		||||
            pe = ptr; ptr += 36;
 | 
			
		||||
            // iterate on ACPI table pointers
 | 
			
		||||
| 
						 | 
				
			
			@ -1937,15 +1932,16 @@ gzerr:          return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
 | 
			
		|||
                    for(r = *((uint32_t*)(data + 4)), ptr = data + 44, i = 0; ptr < data + r &&
 | 
			
		||||
                        i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); ptr += ptr[1]) {
 | 
			
		||||
                        switch(ptr[0]) {
 | 
			
		||||
                            case 0:
 | 
			
		||||
                            DBG(L"ACPI table lapicid %02x is core %d\n",ptr[2],i);
 | 
			
		||||
                            lapic_ids[(INTN)ptr[2]] = i++; break;           // found Processor Local APIC
 | 
			
		||||
                            case 0:                                             // found Processor Local APIC
 | 
			
		||||
                                if((ptr[4] & 1) && lapic_ids[(INTN)ptr[3]] == 0xFFFF) { lapic_ids[(INTN)ptr[3]] = i++; }
 | 
			
		||||
                            break;
 | 
			
		||||
                            case 5: lapic_addr = *((uint64_t*)(ptr+4)); break;  // found 64 bit Local APIC Address
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    if(i) {
 | 
			
		||||
                        bootboot->numcores = i;
 | 
			
		||||
                        bsp_num = lapic_ids[bootboot->bspid];
 | 
			
		||||
                        if(bsp_num == 0xFFFF) bsp_num = 0;
 | 
			
		||||
                        else bootboot->numcores = i;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1953,13 +1949,6 @@ gzerr:          return report(EFI_COMPROMISED_DATA,L"Unable to uncompress");
 | 
			
		|||
        }
 | 
			
		||||
        if(!nosmp && bootboot->numcores > 1 && lapic_addr && ap_code) {
 | 
			
		||||
            DBG(L" * SMP numcores %d\n", bootboot->numcores);
 | 
			
		||||
#if BBDEBUG
 | 
			
		||||
            for(i = 0; i < (int)(sizeof(lapic_ids)/sizeof(lapic_ids[0])); i++) {
 | 
			
		||||
                if(!i || lapic_ids[i])
 | 
			
		||||
                    DBG(L" %02x:%d", i, lapic_ids[i]);
 | 
			
		||||
            }
 | 
			
		||||
            DBG(L"\n%s", L"");
 | 
			
		||||
#endif
 | 
			
		||||
            CopyMem((uint8_t*)0x8000, &ap_trampoline, 256);
 | 
			
		||||
            // save UEFI's 64 bit system registers for the trampoline code
 | 
			
		||||
            __asm__ __volatile__ (
 | 
			
		||||
| 
						 | 
				
			
			@ -2106,14 +2095,48 @@ get_memory_map:
 | 
			
		|||
 | 
			
		||||
        // start APs
 | 
			
		||||
        if(bootboot->numcores > 1) {
 | 
			
		||||
            // send Broadcast INIT IPI
 | 
			
		||||
            *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4500;
 | 
			
		||||
            // send INIT IPI (supports up to 256 cores, requires x2APIC to have more)
 | 
			
		||||
            for(i = 0; i < 256; i++) {
 | 
			
		||||
                if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x280)) = 0;                            // clear APIC errors
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x310)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x300)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x00C500;  // trigger INIT IPI
 | 
			
		||||
                do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                    while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12));         // wait for delivery
 | 
			
		||||
                // deassert
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x310)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24);
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x300)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff00000) | 0x008500;
 | 
			
		||||
                do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                    while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12));
 | 
			
		||||
            }
 | 
			
		||||
            // wait 10 msec
 | 
			
		||||
            sleep(50);
 | 
			
		||||
            // send Broadcast STARTUP IPI
 | 
			
		||||
            *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608; // start at 0800:0000h
 | 
			
		||||
            // send STARTUP IPI
 | 
			
		||||
            for(i = 0; i < 256; i++) {
 | 
			
		||||
                if(i == bootboot->bspid || lapic_ids[i] == 0xFFFF) continue;
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x280)) = 0;                            // clear APIC errors
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x310)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24); // select AP
 | 
			
		||||
                // trigger IPI, start at 0800:0000h
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x300)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff0f800) | 0x000608;
 | 
			
		||||
                // wait 200 usec
 | 
			
		||||
                sleep(1);
 | 
			
		||||
            // send second SIPI
 | 
			
		||||
            *((volatile uint32_t*)(lapic_addr + 0x300)) = 0x0C4608;
 | 
			
		||||
                do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                    while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12));         // wait for delivery
 | 
			
		||||
                // send second IPI
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x280)) = 0;
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x310)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x310)) & 0x00ffffff) | (i << 24);
 | 
			
		||||
                *((volatile uint32_t*)(lapic_addr + 0x300)) =
 | 
			
		||||
                    (*((volatile uint32_t*)(lapic_addr + 0x300)) & 0xfff0f800) | 0x000608;
 | 
			
		||||
                do { __asm__ __volatile__ ("pause" : : : "memory"); }
 | 
			
		||||
                    while(*((volatile uint32_t*)(lapic_addr + 0x300)) & (1 << 12));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue