Files
TermiNexus 172af1e172 fix(asm): io_wait 改为连续 4 次读备选状态寄存器 0x3F6,提供真实 400ns I/O 延时
原先写的是诊断端口 0x80:该端口背后没有设备,在 QEMU 上几乎不消耗时间,等于没有延时。于是 IDE 命令块寄存器 0x1F2..0x1F7 连写会丢写,LBA 寄存器残留上一次的值,导致读到别的扇区(现场:读根目录扇区 8192 却读回 ELF 文件头,目录项全是垃圾,五个 app 全部 spawn 失败;另有 waitDataReady 超时表现为 diskio.read 返回 FR_DISK_ERR)。0ee5ec5 曾为同一现场补过 io_wait 调用,但当时见效靠的是调用开销与代码节奏的余量;内核变大后被吃掉,故障必现。改为 4 次 in al, 0x3F6(真实设备端口,每次均为真实 I/O 往返),并补 CLOBBER_RAX(in al 会改写 RAX,原实现未声明该 clobber)。
2026-10-16 19:56:26 +08:00

156 lines
4.6 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
def cli(): __asm__("cli", [ASM_DESCR.CLOBBER_MEMORY])
def sti(): __asm__("sti", [ASM_DESCR.CLOBBER_MEMORY])
def hlt(): __asm__("hlt", [ASM_DESCR.CLOBBER_MEMORY])
def nop(): __asm__("nop", [ASM_DESCR.CLOBBER_MEMORY])
def pause(): __asm__("pause", op=[ASM_DESCR.CLOBBER_MEMORY])
def inb(port: uint16) -> uint8:
value: uint32
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
in al, dx
movzx $0, al""",
out = [asmout(value, ASM_DESCR.OUTPUT_REG)],
op =[ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
return uint8(value)
def outb(port: uint16, value: uint8):
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
mov eax, {asminp(uint32(value), ASM_DESCR.REG_ANY)}
out dx, al""",
op = [ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
def inw(port: uint16) -> uint16:
value: uint32
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
in ax, dx
movzx eax, ax
mov {asmout(value, ASM_DESCR.OUTPUT_REG)}, eax""",
out = [asmout(value, ASM_DESCR.OUTPUT_REG)],
op =[ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
return uint16(value)
def outw(port: uint16, value: uint16):
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
mov eax, {asminp(uint32(value), ASM_DESCR.REG_ANY)}
out dx, ax""",
op = [ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
def inl(port: uint16) -> uint32:
value: uint32
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
in eax, dx
mov {asmout(value, ASM_DESCR.OUTPUT_REG)}, eax""",
out = [asmout(value, ASM_DESCR.OUTPUT_REG)],
op =[ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
return value
def outl(port: uint16, value: uint32):
__asm__(f"""mov edx, {asminp(uint32(port), ASM_DESCR.REG_ANY)}
mov eax, {asminp(value, ASM_DESCR.REG_ANY)}
out dx, eax""",
op = [ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RAX])
def io_wait():
# ATA 规范的 I/O 延时:**连续 4 次读备选状态寄存器 0x3F6**。它是真实设备端口,每次 in
# 都是一次真实 I/O 往返,稳定给出 ≥400ns(规范要求命令块寄存器两次写之间至少 400ns)。
# 原先写的是诊断端口 0x80 —— 该端口背后没有设备,在 QEMU 上几乎不消耗时间,等于**没有
# 延时**:IDE 命令块寄存器(0x1F2..0x1F7)连写会丢写 ⇒ LBA 寄存器残留上一次的值 ⇒ 读到
# **别的扇区**的数据。现场(参见 0ee5ec5 与 serial.log):读根目录扇区 8192 却读回 ELF
# 文件头 ⇒ 目录项全是垃圾 ⇒ app spawn 失败;或 waitDataReady 超时 ⇒ diskio.read 报错。
__asm__(f"""mov dx, 0x3F6
in al, dx
in al, dx
in al, dx
in al, dx""",
op = [ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_DX, ASM_DESCR.CLOBBER_RAX])
inline def pushall():
__asm__(f"""
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15""",
[ASM_DESCR.CLOBBER_MEMORY]
)
inline def popall():
__asm__(f"""
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax""",
[ASM_DESCR.CLOBBER_MEMORY]
)
def cpu_switch_context(old_stack: uint64*, new_stack: uint64):
__asm__(f"""
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov [{asminp(old_stack, ASM_DESCR.REG_ANY)}], rsp
mov rsp, {asminp(new_stack, ASM_DESCR.REG_ANY)}
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax""",
op=[ASM_DESCR.CLOBBER_MEMORY])
def BSSClean():
__asm__(
"lea rdi, [rip + __bss_start]\n"
"lea rcx, [rip + __bss_end]\n"
"sub rcx, rdi\n"
"xor eax, eax\n"
"cld\n"
"rep stosb",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RAX]
)