Damien Zammit, le ven. 02 janv. 2026 04:15:36 +0000, a ecrit:
> + /* Protected mode! */
> + movw $BOOT_DS, %ax
> + movw %ax, %ds
> + movw %ax, %es
> + movw %ax, %ss
> +
> + lgdtl apboot_gdt_descr - KERNELBASE
> + ljmpl $KERNEL_CS, $(1f + KERNELBASE32)
> +1:
Why not clearing segments here before reloading them? IIRC some
documentation said it is needed for some odd processors, so better be
safe, it's not performance-critical anyway.
> + movw $KERNEL_DS, %ax
> + movw %ax, %ds
> + movw %ax, %es
> + movw %ax, %fs
> + movw %ax, %gs
> + movw %ax, %ss
> +
> + /*
> + * Prepare minimal page mapping to jump to 64 bit and to C code.
> + * The first 4GB is identity mapped, and the first 2GB are re-mapped
> + * to high addresses at KERNEL_MAP_BASE
> + */
> +
> + movl $AP_p3table,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p4table)
> + /*
> + * Fill 4 entries in L3 table to cover the whole 32-bit 4GB address
> + * space. Part of it might be remapped later if the kernel is mapped
> + * below 4G.
> + */
> + movl $AP_p2table,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table)
> + movl $AP_p2table1,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table + 8)
> + movl $AP_p2table2,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table + 16)
> + movl $AP_p2table3,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table + 24)
> + /* point each page table level two entry to a page */
> + mov $0,%ecx
> +.map_p2_table:
> + mov $0x200000,%eax // 2MiB page, should be always available
> + mul %ecx
> + or $(PTE_V|PTE_W|PTE_S),%eax // enable 2MiB page instead of 4k
Instead of recomputing each time, you can just start with
movl $(PTE_V|PTE_W|PTE_S),%eax // enable 2MiB page instead of 4k
and on each loop iteration,
addl $0x200000,%eax
> + mov %eax,AP_p2table(,%ecx,8)
> + inc %ecx
> + cmp $2048,%ecx // 512 entries per table, map 4 L2 tables
> + jne .map_p2_table
> +
> + /*
> + * KERNEL_MAP_BASE must me aligned to 2GB.
> + * Depending on kernel starting address, we might need to add another
> + * entry in the L4 table (controlling 512 GB chunks). In any case, we
> + * add two entries in L3 table to make sure we map 2GB for the kernel.
> + * Note that this may override part of the mapping create above.
> + */
> +.kernel_map:
> +#if KERNEL_MAP_BASE >= (1U << 39)
> + movl $AP_p3ktable,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p4table + (8 * ((KERNEL_MAP_BASE >> 39) & 0x1FF))) //
> select 512G block
> + movl $AP_p2ktable1,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3ktable + (8 * ((KERNEL_MAP_BASE >> 30) & 0x1FF) ))
> // select first 1G block
> + movl $AP_p2ktable2,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3ktable + (8 * (((KERNEL_MAP_BASE >> 30) & 0x1FF) +
> 1) )) // select second 1G block
> +#else
> + movl $AP_p2ktable1,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table + (8 * ((KERNEL_MAP_BASE >> 30) & 0x1FF) ))
> // select first 1G block
> + movl $AP_p2ktable2,%eax
> + or $(PTE_V|PTE_W),%eax
> + movl %eax,(AP_p3table + (8 * (((KERNEL_MAP_BASE >> 30) & 0x1FF) + 1)
> )) // select second 1G block
> +#endif
> +
> + mov $0,%ecx
> +.map_p2k_table:
> + mov $0x200000,%eax // 2MiB page, should be always available
> + mul %ecx
> + or $(PTE_V|PTE_W|PTE_S),%eax // enable 2MiB page instead of 4K
Same here.
> + mov %eax,AP_p2ktable1(,%ecx,8)
> + inc %ecx
> + cmp $1024,%ecx // 512 entries per table, map 2 L2 tables
> + jne .map_p2k_table
> +
> +switch64:
> + /*
> + * Jump to 64 bit mode, we have to
> + * - enable PAE
> + * - enable long mode
> + * - enable paging and load the tables filled above in CR3
> + * - jump to a 64-bit code segment
> + */
> + mov %cr4,%eax
> + or $CR4_PAE,%eax
> + mov %eax,%cr4
> + mov $0xC0000080,%ecx // select EFER register
Use $MSR_REG_EFER
> + rdmsr
> + or $(1 << 8),%eax // long mode enable bit
> + wrmsr
> + mov $AP_p4table,%eax
> + mov %eax,%cr3
> + mov %cr0,%eax
> + or $CR0_PG,%eax
> + or $CR0_WP,%eax
> + mov %eax,%cr0
> +
> + lgdt apboot_gdt64_descr
> + movw $0,%ax
> + movw %ax,%fs
> + movw %ax,%gs
> + movw $16,%ax
Use $BOOT_DS.
> + movw %ax,%ds
> + movw %ax,%es
> + movw %ax,%ss
> + ljmp $8, $start64
Use $BOOT_CS.
> +
> + .code64
> +
> +start64:
> + /* Get CPU number into rbp */
> + movq $1, %rax
%eax is enough.
> + cpuid
> + shrq $24, %rbx
> + andq %cs:apic_id_mask, %rbx
> + movq %cs:CX(cpu_id_lut, %rbx), %rbp
> +
> + /* Copy first gdt64 descriptor and gdt64 to cpu-th area */
> + movq $(GDT_DESCR_M32 + GDT_TABLE_M32), %rcx
> + movq $apboot_gdt64_top, %rsi
> + movq %rsi, %rdi
> + movq $((GDT_DESCR_M32 + GDT_TABLE_M32) * 4), %rax
> + mul %rbp
> + addq %rax, %rdi
> + cld
> + rep movsq
> +
> + /* Access per_cpu area */
> + movq %rbp, %rax
> + movq $PC_SIZE,%rbx
> + mul %rbx
> + addq $percpu_array, %rax
> +
> + /* Record our cpu number */
> + movq %rbp, (PERCPU_CPU_ID)(%rax)
> +
> + /* Make rax hold offset to my cpus gdt64 */
> + movq %rax, %rbx
> + movq $((GDT_DESCR_M32 + GDT_TABLE_M32) * 4), %rax
> + mul %rbp
> +
> + /* Patch only our own copy of gdt descriptor */
> + addq %rax, apboot_gdt64_descr_addr(%rax)
> + movq %rax, %rsi
> +
> + /* Set GS base address */
> + movq CX(EXT(percpu_array), %rbp), %rdx
> + movl %edx, %eax
> + shrq $32, %rdx
> + movl $MSR_REG_GSBASE, %ecx
> + wrmsr
> +
> + /* Set KernelGS base address */
> + movq CX(EXT(percpu_array), %rbp), %rdx
> + movl %edx, %eax
> + shrq $32, %rdx
> + movl $MSR_REG_KGSBASE, %ecx
> + wrmsr
> +
> + /* Reload our copy of gdt with 2 args */
> + movq %rsi, %rax
> + movw apboot_gdt64_descr(%rax), %di
> + movq (apboot_gdt64_descr+2)(%rax), %rsi
> + lgdtq apboot_gdt64_descr(%rax)
> +
> + movw $PERCPU_DS,%ax
> + movw %ax,%gs
> +
> + /* set up mini stack to do far return */
> + movq CX(EXT(int_stack_top), %rbp), %rsp
> +
> + /* instead of ljmp */
You can ljmpq *reload with
reload:
.quad $reloaded_gdt64
.short $KERNEL_CS
(and it can easily be relocated)
> + pushq $KERNEL_CS
> + pushq $reloaded_gdt64
> + retfq
> +
> +/* We are back here still in long mode but with percpu GS */
> +reloaded_gdt64:
> + movw $PERCPU_DS, %ax
> + movw %ax, %gs
> +
> + /* Load null Interrupt descriptor table */
> + movq $apboot_idt_ptr, %rbx
> + lidt (%rbx)
> +
> + /* Enable local apic in xAPIC mode */
> + xorq %rax, %rax
> + xorq %rdx, %rdx
> + movq $APIC_MSR, %rcx
> + rdmsr
> + orq $APIC_MSR_ENABLE, %rax
> + andq $(~(APIC_MSR_BSP | APIC_MSR_X2APIC)), %rax
> + movq $APIC_MSR, %rcx
> + wrmsr
> +
> + /* Load int_stack_top[cpu] -> esp */
> + CPU_NUMBER(%edx)
> + movq CX(EXT(int_stack_top), %rdx), %rsp
> +
> + /* Ensure stack alignment */
> + andq $(~0xf), %rsp
> +
> + /* Reset EFLAGS to a known state */
> + pushq $0
> + popfq
> +
> + /* Finish the cpu configuration */
> + call EXT(cpu_ap_main)
> +
> +3:
> + /* NOT REACHED */
> + hlt
> + jmp 3b
> +
> +.align 16
> + .word 0
> +gdt_descr_tmp:
> + .short 3*8-1
> + .long RELOC(gdt_tmp)
> +.align 16
> +gdt_tmp:
> + /* 0 */
> + .quad 0
> + /* BOOT_CS */
> + .word 0xffff
> + .word 0x0000
> + .byte 0x00
> + .byte ACC_PL_K | ACC_CODE_R | ACC_P
> + .byte ((SZ_32 | SZ_G) << 4) | 0xf
> + .byte 0x00
> + /* BOOT_DS */
> + .word 0xffff
> + .word 0x0000
> + .byte 0x00
> + .byte ACC_PL_K | ACC_DATA_W | ACC_P
> + .byte ((SZ_32 | SZ_G) << 4) | 0xf
> + .byte 0x00
> +
> +apbootend:
> +
> +.section .apboot16.data,"ad",@progbits
> +.align 16
> +apboot_idt_ptr:
> + .long 0
> +.align 16
> +apboot_gdt_top:
> + .word 0
> +apboot_gdt_descr:
> + .word (GDT_TABLE_M32 * 4) - 1
> +apboot_gdt_descr_addr:
> + .long apboot_gdt - KERNELBASE
> +.align 16
> +apboot_gdt:
> + /* NULL segment = 0x0 */
> + .quad 0
> +
> + /* KERNEL_CS = 0x8 */
> + .word 0xffff /* Segment limit first 0-15 bits*/
> + .word (-KERNELBASE32) & 0xffff /*Base first 0-15 bits*/
> + .byte ((-KERNELBASE32) >> 16) & 0xff /*Base 16-23 bits */
> + .byte ACC_PL_K | ACC_CODE_R | ACC_P /*Access byte */
> + .byte ((SZ_32 | SZ_G) << 4) | 0xf /* High 4 bits */
> + .byte ((-KERNELBASE32) >> 24) & 0xff /*Base 24-31 bits */
> +
> + /* KERNEL_DS = 0x10 */
> + .word 0xffff /*Segment limit */
> + .word (-KERNELBASE32) & 0xffff /*Base first 0-15 bits*/
> + .byte ((-KERNELBASE32) >> 16) & 0xff
> + .byte ACC_PL_K | ACC_DATA_W | ACC_P /*Access byte*/
> + .byte ((SZ_32 | SZ_G) << 4) | 0xf /* High 4 bits */
> + .byte ((-KERNELBASE32) >> 24) & 0xff /*Base 24-31 bits */
> +
> + /* LDT = 0x18 */
> + .quad 0
> +
> + /* TSS = 0x20 */
> + .quad 0
> +
> + /* USER_LDT = 0x28 */
> + .quad 0
> +
> + /* USER_TSS = 0x30 */
> + .quad 0
> +
> + /* LINEAR = 0x38 */
> + .quad 0
> +
> + /* FPREGS = 0x40 */
> + .quad 0
> +
> + /* USER_GDT = 0x48 and 0x50 */
> + .quad 0
> + .quad 0
> +
> + /* USER_TSS64 = 0x58 */
> + .quad 0
> +
> + /* USER_TSS64 = 0x60 */
> + .quad 0
> +
> + /* boot GS = 0x68 */
> + .word 0xffff
> + .word 0
> + .byte 0
> + .byte ACC_PL_K | ACC_DATA_W | ACC_P
> + .byte ((SZ_32 | SZ_G) << 4) | 0xf
> + .byte 0
> +
> +.align 4096
> +AP_p4table: .space 4096
> +AP_p3table: .space 4096
> +AP_p2table: .space 4096
> +AP_p2table1: .space 4096
> +AP_p2table2: .space 4096
> +AP_p2table3: .space 4096
> +AP_p3ktable: .space 4096
> +AP_p2ktable1: .space 4096
> +AP_p2ktable2: .space 4096
> +
> +.code64
> +.align 4096
> +apboot_gdt64_top:
> + .word 0
> +apboot_gdt64_descr:
> + .word (GDT_TABLE_M32 * 4) - 1
> +apboot_gdt64_descr_addr:
> + .quad apboot_gdt64
> +.align 16
> +apboot_gdt64:
> + /* NULL segment */
> + .quad 0
> + /* BOOT_CS */
> + .word 0x0000
> + .word 0x0000
> + .byte 0x00
> + .byte ACC_PL_K | ACC_CODE_R | ACC_P
> + .byte (SZ_64 << 4) | 0xf
> + .byte 0x00
> + /* BOOT_DS */
> + .word 0x0000
> + .word 0x0000
> + .byte 0x00
> + .byte ACC_PL_K | ACC_DATA_W | ACC_P
> + .byte (SZ_64 << 4) | 0xf
> + .byte 0x00
> +
> + /* LDT = 0x18 */
> + .quad 0
> +
> + /* TSS = 0x20 */
> + .quad 0
> +
> + /* USER_LDT = 0x28 */
> + .quad 0
> +
> + /* USER_TSS = 0x30 */
> + .quad 0
> +
> + /* LINEAR = 0x38 */
> + .quad 0
> +
> + /* FPREGS = 0x40 */
> + .quad 0
> +
> + /* USER_GDT = 0x48 and 0x50 */
> + .quad 0
> + .quad 0
> +
> + /* USER_TSS64 = 0x58 */
> + .quad 0
> +
> + /* USER_TSS64 = 0x60 */
> + .quad 0
> +
> + /* boot GS = 0x68 */
> + .word 0x0000
> + .word 0
> + .byte 0
> + .byte ACC_PL_K | ACC_DATA_W | ACC_P
> + .byte (SZ_64 << 4) | 0xf
> + .byte 0
> +
> +/* Empty space for per-cpu gdt64 descriptor and gdt64 */
> +.space (NCPUS-1) * (GDT_DESCR_M32 + GDT_TABLE_M32) * 4, 0x0
> +
> +#endif
> --
> 2.45.2
>
>
>
--
Samuel
...
<rv_> et Ctrl alt F2 pour aller sous console
<rv_> mais c koi pour passer d'un bureau a un autre !
<rv_> au fait c koi le raccourci pour passer d'un bureau a un autre 'question
stupide"
<cycyx> ça dépend du window manager et de ta conf
<Firebird> ce qui fonctionne toujours c'est CTRL-ALT-BCKSP
-:- SignOff rv_: #linuxfr (Read error: EOF from client)
-:- rv_ [[email protected]] has joined #linuxfr
<rv_> Firebird: MEURT...