标签: osdev

x86-64 处理器的 NUMA 文档?

我已经查找过 X86-64 处理器的 NUMA 文档,不幸的是我只找到了 NUMA 的优化文档。

我想要的是:如何在系统中初始化 NUMA(这包括获取系统的内存拓扑和处理器拓扑)。有谁知道有关 X86-64 AMD 和 Intel 处理器的 NUMA 的好文档吗?

x86-64 intel osdev numa amd-processor

3
推荐指数
1
解决办法
2669
查看次数

NASM 调用外部 C++ 函数

我正在尝试从 NASM 调用外部 C++ 函数。当我在谷歌上搜索时,我没有找到任何相关的解决方案。
C++

void kernel_main()
{
    char* vidmem = (char*)0xb8000;
    /* And so on... */
}
Run Code Online (Sandbox Code Playgroud)

国家安全管理协会

;Some calls before
section     .text
    ;nothing special here

global start
extern kernel_main ;our problem
Run Code Online (Sandbox Code Playgroud)

运行编译这两个文件后,我收到此错误:kernel.asm(.text+0xe): undefined reference to kernel_main' 这里有什么问题?谢谢。

c++ compilation g++ nasm osdev

3
推荐指数
1
解决办法
1515
查看次数

如何用汇编语言修复“os.asm:113:错误:TIMES值-138为负数”

我正在用汇编语言开发一个操作系统。\n在某个时间我从 NASM 收到此错误:

\n\n
\n

os.asm:113: 错误: TIMES 值 -138 为负数

\n
\n\n

我想把这个项目进行到底。只有这样的错误才让我绝望!

\n\n

这是代码:

\n\n
BITS 16\n\nstart:\n    mov ax, 07C0h       ; Set up 4K stack space after this bootloader\n    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph\n    mov ss, ax\n    mov sp, 4096\n    mov ax, 07C0h       ; Set data segment to where we're loaded\n    mov ds, ax\n    call cls\n    MOV AH, 06h    ; Scroll up function\n    XOR AL, AL     ; Clear entire screen\n    XOR …
Run Code Online (Sandbox Code Playgroud)

assembly nasm osdev bootloader x86-16

3
推荐指数
1
解决办法
2027
查看次数

使用或不使用 IO 位图创建正确的任务状态段 (TSS) 结构?

阅读 Intel 和 AMD 之间的文档并查看代码有时会让人很难理解如何创建没有 IO 端口位图 (IOPB) 的正确任务状态段 (TSS)。使用 IOPB 创建 TSS 似乎也存在混淆,因为 IO 位图 (IOPB) 是否需要尾随字节似乎不明确0xff

我知道 TSS 和 TSS 描述符(在 GDT 中)之间存在依赖关系。TSS 描述符控制 TSS 的基地址以及限制。描述符中的限制比结构的实际大小小一(本质上类似于 GDT 和 IDT 记录中指定的大小)。TSS 限制用于确定 IOPB 大小。

我知道:

  • TSS描述符限制比整个TSS结构的大小小1
  • 16位TSS没有IOPB并且结构是固定大小的
  • 基本的32位和64位TSS结构大小相似(数据含义不同)
  • 32 位 TSS 可以通过向基本结构添加额外的 DWORD 来支持控制流强制。
  • TSS 中的 IOPB 偏移量(字)指向相对于任务段开头的偏移量。
  • IOPB 偏移量指向 IOPB 结构的开头,并且在启用虚拟模式增强 (VME)的情况下,IOPB 之前的 32 个字节是中断重定向表。
  • 如果未启用 VME,内核可以在基本 TSS 结构的末尾和 IOPB 偏移之间放置额外的每个任务实例数据
  • 如果启用了 VME,内核可以在基本 TSS 结构的末尾和 IOPB 以下 32 字节的偏移量之间放置额外的每个任务实例数据。
  • 如果存在 IOPB,则每个 0 位表示端口访问权限,1 位表示拒绝权限。 …

x86 x86-64 intel osdev amd-processor

3
推荐指数
1
解决办法
2284
查看次数

设置GDT时Qemu无限重启

我主要用 C++ 制作操作系统,但对于引导加载程序,我使用的是 FASM。当我尝试设置 GDT 时,Qemu 会清除屏幕并在顶部重新打印“SeaBIOS”。它会一直循环下去,直到我关闭它。这是它的gif:

我尝试使用 -nographic 运行它,但它在 Windows 控制台中执行相同的操作。

哦,是的,操作系统/版本信息。
Windows:20H2
FASM:1.73.25
Qemu:5.1.0

这是我的代码:

gdt_start:
    dd 0x00
    dd 0x00

gdt_code:
    dw 0xffff
    dw 0x0
    db 0x0
    db 10011010b
    db 11001111b
    db 0x0

gdt_data:
     dw   0xffff
     dw   0x0
     db   0x0
     db   10010010b
     db   11001111b
     db   0x0

gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

switch_to_pm:
    cli
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, …
Run Code Online (Sandbox Code Playgroud)

x86 assembly osdev fasm gdt

3
推荐指数
1
解决办法
158
查看次数

如何正确链接 16 位和 32 位 .o 文件?

我最近更换了我的计算机,从那时起,我的 makefile 链会输出一个 512 字节的二进制文件,其中只有 0x00s 或引导加载程序,但没有其他任何内容。我将以下内容创建为 MRE:

引导.asm:

BITS 16
SECTION boot
GLOBAL _entry
EXTERN _start

_entry:
mov [disk],dl
mov ah, 0x2 ; read sectors
mov al, 6   ; amount = 6
mov ch, 0   ; zylinder = 0
mov cl, 2   ; first sector to read = 2
mov dh, 0   ; head = 0 (up)
mov dl, [disk]  ; disk
mov bx, _start  ; segment:offset address
int 0x13

cli
lgdt [GDT_POINTER]

mov eax, cr0
or al, 1 …
Run Code Online (Sandbox Code Playgroud)

c x86 makefile ld osdev

3
推荐指数
1
解决办法
126
查看次数

当 CPL=3 时发生硬件中断时,导致仅设置写入位的 x86-64 页面错误的原因

我正在使用 Rust 编写自己的内核(大致基于 phil-opp 的博客,https://os.phil-opp.com/),到目前为止,我已经成功复制了 4 级页表,为用户模式应用程序代码和数据,将裸函数映射到虚拟地址0x40000000000,设置堆栈并跳转到代码。我还有一个使用 syscall/sysret 工作的系统调用处理程序,它在遇到系统调用时简单地打印一条消息。我注意到,每当 PIC 定时器中断发生时,它总是在 CPL=0 时发生,因为系统调用处理程序的代码比用户模式应用程序长很多倍,后者只是在无限循环中执行系统调用。如果我禁用打印(这需要大多数指令),则在循环数百次迭代之后,当 CPL=3 时会发生计时器中断。然而,CPU 没有调用中断处理程序,而是抛出一个页面错误,错误代码为 2(仅对应于写入位设置)。在我看来,这没有任何意义,问题可能出在哪里?

总表:

static ref GDT: (gdt::GlobalDescriptorTable, Selectors) = {
    let mut gdt = gdt::GlobalDescriptorTable::new();
    let kernel_code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment());
    let kernel_data_selector = gdt.add_entry(gdt::Descriptor::kernel_data_segment());
    let tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&TSS));
    let user_data_selector = gdt.add_entry(gdt::Descriptor::user_data_segment());
    let user_code_selector = gdt.add_entry(gdt::Descriptor::user_code_segment());
    (gdt, Selectors { kernel_code_selector, kernel_data_selector, tss_selector, user_code_selector, user_data_selector })
    };
Run Code Online (Sandbox Code Playgroud)

离散时间:

const DOUBLE_FAULT_IST_INDEX: u16 = 0;
let mut IDT: idt::InterruptDescriptorTable = idt::InterruptDescriptorTable::new();
IDT.breakpoint.set_handler_fn(interrupts::breakpoint::breakpoint_handler);
IDT.double_fault.set_handler_fn(interrupts::double_fault::double_fault_handler).set_stack_index(DOUBLE_FAULT_IST_INDEX);
IDT.page_fault.set_handler_fn(interrupts::page_fault::page_fault_handler);
IDT.general_protection_fault.set_handler_fn(interrupts::general_protection_fault::general_protection_fault_handler);
IDT.stack_segment_fault.set_handler_fn(interrupts::stack_segment_fault::stack_segment_fault_handler);
IDT.segment_not_present.set_handler_fn(interrupts::segment_not_present::segment_not_present_handler); …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly osdev rust

3
推荐指数
1
解决办法
440
查看次数

在真实硬件上启动时,引导加载程序会收到磁盘读取错误,但在 vmware、qemu 和 bochs 上则不会

我编写 x86 引导加载程序已经有一段时间了,并且已经验证我的引导加载程序可以在 bochs 和 qemu 以及 vmware 上运行。但是,我在真实硬件 (Thinkpad T400) 上遇到磁盘读取错误,错误代码为 0x0880,但在 qemu 上却没有。

[bits 16]
[extern kernel]
[global isr_stub_table]
[global IDT_load]

[extern FortressLoader_IdtInit]
[extern FortressLoader_ChecmMemMap]

[extern X86TTY_Init]
[extern X86TTY_Clear]
[extern printf]

[global FortressLoader_HeapStart]
[global FortressLoader_HeapEnd]

[global startKernel]

section .boot
global boot

KERNEL_SIZE_SECTORS equ 128

jmp boot
TIMES 3-($-$$) DB 0x90

OEMname:           db    "mkfs.fat"
bytesPerSector:    dw    512
sectPerCluster:    db    1
reservedSectors:   dw    1
numFAT:            db    2
numRootDirEntries: dw    224
numSectors:        dw    2880
mediaType:         db    0xf0
numFATsectors:     dw    9
sectorsPerTrack: …
Run Code Online (Sandbox Code Playgroud)

x86 assembly nasm osdev bootloader

3
推荐指数
1
解决办法
100
查看次数

在编译/链接时如何使用地址进行计算?

我编写了一些初始化IDT的代码,该IDT将32位地址存储在两个不相邻的16位半部分中。IDT可以存储在任何地方,您可以通过运行LIDT指令告诉CPU在哪里。

这是初始化表的代码:

void idt_init(void) {
    /* Unfortunately, we can't write this as loops. The first option,
     * initializing the IDT with the addresses, here looping over it, and
     * reinitializing the descriptors didn't work because assigning a
     * a uintptr_t (from (uintptr_t) handler_func) to a descr (a.k.a.
     * uint64_t), according to the compiler, "isn't computable at load
     * time."
     * The second option, storing the addresses as a local array, simply is
     * inefficient …
Run Code Online (Sandbox Code Playgroud)

c x86 linker interrupt osdev

2
推荐指数
1
解决办法
391
查看次数

使用int13h从软盘加载段

我目前正在尝试编写16位实模式启动代码,该代码打印一个字母,然后从软盘加载第二个段并跳转到该段,然后再打印一个字母。

但是,我对“从云端硬盘读取扇区”呼叫的工作方式有些困惑。到目前为止,这是我的代码:

[BITS 16]
org 0x7B00

start:
        mov ax, 0xB800 ; Video buffer
        mov es, ax     ; Copy address of video buffer to extra segment

        mov byte [es:0], 'A'    ; Move character A to first address
        mov byte [es:1], 0x17   ; Format for blue background, white foreground

        mov ah, 0x02 ; Read sectors from drive
        mov al, 1    ; Read 1 sector
        mov ch, 0    ; Cylinder 0
        mov cl, 0    ; Sector 0
        mov dh, 0    ; Head 0 …
Run Code Online (Sandbox Code Playgroud)

assembly nasm osdev bootloader x86-16

2
推荐指数
1
解决办法
913
查看次数

标签 统计

osdev ×10

x86 ×6

assembly ×5

nasm ×4

bootloader ×3

c ×3

amd-processor ×2

intel ×2

x86-16 ×2

x86-64 ×2

c++ ×1

compilation ×1

fasm ×1

g++ ×1

gdt ×1

interrupt ×1

ld ×1

linker ×1

makefile ×1

numa ×1

rust ×1