fix(vkernel): 预留内核 .bss 与栈区,修堆 arena 覆盖未预留内核内存

根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss
尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是
EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、
堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时
#GP(rip=0x130d45, err=0x0)。

- linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖
  .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss)
- mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr,
  __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃)
- main.vp: 取 __bss_end 并传入 mm.init
- boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData)
  占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用

另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为
kbd_svc.__init__() 等。
This commit is contained in:
TermiNexus committed 2026-10-14 12:54:43 +08:00
1 parent 52728bc8da
commit 0919a058a8
17 files changed
+148 -105

No files matched your search

+2 -2
View File
@@ -215,7 +215,7 @@ class _CPUObject:
string.memset(&self.tss, 0, self.tss.__sizeof__())
self.tss.io_map_base = self.tss.__sizeof__()
string.memset(&_per_cpu, 0, per_cpu_data.__sizeof__())
gdt.setTSS64(5, uint64(&self.tss), self.tss.__sizeof__() - 1)
gdt.setTSS64(5, uint64(&self.tss), int(self.tss.__sizeof__() - 1))
gdt.flush()
# IA32_KERNEL_GS_BASE holds the per_cpu address for swapgs.
# When entering from Ring 3, swapgs swaps IA32_GS_BASE (0) with
@@ -245,7 +245,7 @@ class _CPUObject:
# 下标按字节偏移且被截断为 i8(只写低字节、偏移不乘 4)。
brand_addr: uint64 = uint64(uint32*(info.brand_string))
for i in range(3):
cpuid(0x80000002 + i, &res)
cpuid(int(0x80000002 + i), &res)
off_b: uint64 = uint64(i) * 16
*(uint32*(brand_addr + off_b + 0)) = res.eax
*(uint32*(brand_addr + off_b + 4)) = res.ebx
+15 -17
View File
@@ -62,7 +62,7 @@ class devfs_directory:
for d in range(directory_count):
dirp: devfs_directory = &directories[d]
if dirp.parent == dir_ptr:
name_len: int = string.strlen(dirp.name)
name_len: int = int(string.strlen(dirp.name))
if pos + name_len + 1 > size:
break
string.strcpy(buffer + pos, dirp.name)
@@ -90,7 +90,7 @@ virtual class devfs_file:
for f in range(file_count):
filep: devfs_file* = &files[f]
if filep.parent_dir == dir_ptr:
name_len: int = string.strlen(filep.name)
name_len: int = int(string.strlen(filep.name))
if pos + name_len + 1 > size:
break
string.strcpy(buffer + pos, filep.name)
@@ -115,8 +115,8 @@ class _DevFSObject:
directory_count = 0
file_count = 0
string.memset(&directories, 0, devfs_directory.__sizeof__() * MAX_DIRECTORIES)
string.memset(&files, 0, devfs_file.__sizeof__() * MAX_DEVICE_FILES)
string.memset(&fd_table, 0, _fd_table.__sizeof__() * MAX_FILE_DESCRIPTORS)
string.memset(&files, 0, devfs_file.__sizeof__() * MAX_DEVICE_FILES)
string.memset(&fd_table, 0, _fd_table.__sizeof__() * MAX_FILE_DESCRIPTORS)
def create_single_dir(self, parent: devfs_directory*, dir_name: const str) -> devfs_directory*:
global directory_count
@@ -283,14 +283,12 @@ class _DevFSObject:
return pos
DevFSObject: _DevFSObject*
_DevFSObject_instance: _DevFSObject
DevFSObject: _DevFSObject* = _DevFSObject()
def devfs_init() -> int:
global DevFSObject, _DevFSObject_instance
DevFSObject = &_DevFSObject_instance
_DevFSObject_instance = _DevFSObject()
global DevFSObject
DevFSObject.__init__()
DevFSObject.init()
return 0
@@ -318,7 +316,7 @@ def devfs_ioctl(fd: int, cmd: uint32, arg: rawptr) -> int:
def devfs_list_directory(path: const str, buffer: str, size: uint32) -> int:
return DevFSObject.list_directory(path, buffer, size)
serial0_file: devfs_file
serial0_file: devfs_file* = devfs_file()
def serial0_open(self: rawptr, path: const str, flags: int) -> int:
serial.puts("[serial0] open: ")
@@ -342,7 +340,7 @@ def serial0_write(self: rawptr, fd: int, buffer: const rawptr, size: uint32) ->
def devfs_register_serial0() -> int:
global serial0_file
serial0_file = devfs_file()
serial0_file.__init__()
serial0_file.open = serial0_open
serial0_file.close = serial0_close
serial0_file.read = serial0_read
@@ -371,11 +369,11 @@ virtual class serial1_device(devfs_file):
serial.puts("\n")
return size
serial1_file: serial1_device
serial1_file: serial1_device* = serial1_device()
def devfs_register_serial1() -> int:
global serial1_file
serial1_file = serial1_device()
serial1_file.__init__()
return devfs_create_file("/dev/serial1", serial1_file, None)
import drivers.input.keyboard.keyboard as keyboard
@@ -405,11 +403,11 @@ virtual class keyboard_device(devfs_file):
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
return 0
kbd_file: keyboard_device
kbd_file: keyboard_device* = keyboard_device()
def devfs_register_keyboard() -> int:
global kbd_file
kbd_file = keyboard_device()
kbd_file.__init__()
keyboard.init()
return devfs_create_file("/dev/input/keyboard", kbd_file, None)
@@ -441,10 +439,10 @@ virtual class mouse_device(devfs_file):
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
return 0
mse_file: mouse_device
mse_file: mouse_device* = mouse_device()
def devfs_register_mouse() -> int:
global mse_file
mse_file = mouse_device()
mse_file.__init__()
mouse.init()
return devfs_create_file("/dev/input/mouse", mse_file, None)
@@ -10,7 +10,7 @@ def cmos_read(reg: uint8) -> uint8:
return asm.inb(rtc_cmos_data)
def bcd_to_bin(bcd: uint8) -> uint8:
return (bcd >> 4) * 10 + (bcd & 0x0F)
return uint8((bcd >> 4) * 10 + (bcd & 0x0F))
def get_rtc_time() -> uint32:
while cmos_read(0x0A) & 0x80: pass
@@ -28,17 +28,17 @@ def get_rtc_time() -> uint32:
day = bcd_to_bin(day)
mon = bcd_to_bin(mon)
year = bcd_to_bin(year)
fat_year: uint16 = uint16(year) + 2000 - 1980
fat_year: uint16 = uint16(uint16(year) + 2000 - 1980)
if fat_year > 127: fat_year = 127
fat_date: uint16 = (fat_year << 9) | (uint16(mon) << 5) | uint16(day)
fat_time: uint16 = (uint16(hour) << 11) | (uint16(min_) << 5) | (uint16(sec) / 2)
fat_date: uint16 = uint16((fat_year << 9) | (uint16(mon) << 5) | uint16(day))
fat_time: uint16 = uint16((uint16(hour) << 11) | (uint16(min_) << 5) | (uint16(sec) / 2))
return (uint32(fat_date) << 16) | uint32(fat_time)
def get_fattime() -> uint32:
return get_rtc_time()
def to_year(ft: uint32) -> uint16:
return uint16((ft >> 25) & 0x7F) + 1980
return uint16(uint16((ft >> 25) & 0x7F) + 1980)
def to_month(ft: uint32) -> uint8:
return uint8((ft >> 21) & 0x0F)
@@ -56,8 +56,8 @@ def to_second(ft: uint32) -> uint8:
return uint8((ft & 0x1F) * 2)
def make(year: uint16, month: uint8, day: uint8, hour: uint8, minute: uint8, second: uint8) -> uint32:
fat_year: uint16 = year - 1980
fat_year: uint16 = uint16(year - 1980)
if fat_year > 127: fat_year = 127
fat_date: uint16 = (fat_year << 9) | (uint16(month) << 5) | uint16(day)
fat_time: uint16 = (uint16(hour) << 11) | (uint16(minute) << 5) | (uint16(second) / 2)
fat_date: uint16 = uint16((fat_year << 9) | (uint16(month) << 5) | uint16(day))
fat_time: uint16 = uint16((uint16(hour) << 11) | (uint16(minute) << 5) | (uint16(second) / 2))
return (uint32(fat_date) << 16) | uint32(fat_time)
@@ -168,7 +168,7 @@ class lfn_entry:
def sfn_checksum(name: const str) -> uint8:
sum: uint8 = 0
for i in range(11):
sum = ((sum & 1) << 7) + (sum >> 1) + name[i]
sum = uint8(((sum & 1) << 7) + (sum >> 1) + name[i])
return sum
def uni2oem_placeholder(uni: uint16, cp: uint16) -> uint16:
@@ -233,7 +233,7 @@ def sfn_from_lfn(lfn: const str, sfn: str):
if ch == '.':
dot_pos = si; si += 1; ext_i = 0; continue
uc: char
if ch >= 'a' and ch <= 'z': uc = ch - 32
if ch >= 'a' and ch <= 'z': uc = char(ch - 32)
elif ch == ' ': uc = '_'
elif ch == '+' or ch == ',' or ch == ';' or ch == '=' or ch == '[' or ch == ']': uc = '_'
else: uc = ch
@@ -722,8 +722,8 @@ class volinfo:
for i in range(11):
a: char = self.win[entry_offset_in_sector + i]
b: char = sfn[i]
if a >= 'a' and a <= 'z': a = a - 32
if b >= 'a' and b <= 'z': b = b - 32
if a >= 'a' and a <= 'z': a = char(a - 32)
if b >= 'a' and b <= 'z': b = char(b - 32)
if a != b:
match_found = 0
break
@@ -732,11 +732,11 @@ class volinfo:
lfn_matched: int = 1
li: int = 0
for name_ch in name:
lfn_ch: uint16 = *(uint16*(uint64(lfn_buf) + li * 2))
lfn_low: uint16 = lfn_ch
if lfn_low >= 65 and lfn_low <= 90: lfn_low = lfn_low + 32
lfn_ch: uint16 = *(uint16*(uint64(lfn_buf) + li * 2))
lfn_low: uint16 = uint16(lfn_ch)
if lfn_low >= 65 and lfn_low <= 90: lfn_low = uint16(lfn_low + 32)
n_low: uint16 = uint16(name_ch)
if n_low >= 65 and n_low <= 90: n_low = n_low + 32
if n_low >= 65 and n_low <= 90: n_low = uint16(n_low + 32)
if lfn_low != n_low:
lfn_matched = 0
break
@@ -88,7 +88,7 @@ def read_scancode() -> uint8:
return code
def scancode_to_ascii(scancode: uint8) -> char:
code: uint8 = scancode & ~uint8(KEY_RELEASED)
code: uint8 = uint8(scancode & ~uint8(KEY_RELEASED))
if code >= 128: return '\0'
shifted: bool = (shift_l or shift_r) != 0
if caps_lock and code >= 0x10 and code <= 0x32:
+6 -11
View File
@@ -64,7 +64,7 @@ def init() -> int:
_ide_initialized = 1
return IDError.IDE_ERR_NONE
def readSector(lba: uint32, buffer: t.CPtr) -> int:
def readSector(lba: uint32, buffer: rawptr) -> int:
if buffer is None: return IDError.IDE_ERR_BUFFER_NULL
err: IDError = waitReady(IDE_baseport_PRIMARY)
if err != IDError.IDE_ERR_NONE:
@@ -84,8 +84,8 @@ def readSector(lba: uint32, buffer: t.CPtr) -> int:
buf: uint16* = uint16*(buffer)
for j in range(256):
*buf = asm.inw(0x1F0)
# buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节
buf = buf + 2
# buf 是 i16*(uint16*):+1 表示前进 1 个元素 = 2 字节,256 次恰好填满 512B
buf = buf + 1
first_byte: uint8 = *(uint8*(buffer))
# viperlib.snprintf(c.Addr(dbg), 120, "[readSector] lba=%lu status=0x%02x first=%02x\n", lba, uint32(st2), uint32(first_byte))
# serial.puts(dbg)
@@ -108,14 +108,9 @@ def writeSector(lba: uint32, buffer: const rawptr) -> int:
for j in range(256):
val: uint16 = *buf
asm.outw(0x1F0, val)
# [待复核·指针缩放] 下面这行注释声称 "uint16|t.CPtr → i8*(字节指针),每次前进 2 字节",
# 但 `X | t.CPtr` 的联合类型当前解析为 Ptr(X)(见联合类型解析与 includes/memhub.vp 中
# `t.CUInt64T(x, t.CPtr)` 的既有用法)——若 `buf` 实际是 u16*,则 `buf + 2` 前进的是
# 4 字节(GEP 按元素缩放),本循环 256 次会读满 1KB 而不是 512B,且越界读到缓冲区之后。
# 结论待定(需一次 IR 取证:看 `buf + 2` 生成的是 getelementptr i16 还是 i8)。
# 与按整数加法推进地址、不依赖指针元素类型的写法(同仓另有此类)对齐后再改;
# `| t.CPtr` → `rawptr[T]` 迁移时一并复核,见 Debugger/rawptr-migration-and-fastfail.md。
buf = buf + 2
# buf 是 i16*(uint16*):+1 表示前进 1 个元素 = 2 字节,256 次恰好读完 512B
# (IR 取证:`buf + 2` 生成 getelementptr ..., i16,按元素缩放 → +4 字节,越界)
buf = buf + 1
asm.outb(0x1F7, 0xE7)
waitReady(IDE_baseport_PRIMARY)
return IDError.IDE_ERR_NONE
+10 -10
View File
@@ -20,13 +20,13 @@ class Vec3:
self.x = x
self.y = y
self.z = z
def Sub(self, b: Vec3) -> Vec3*:
def Sub(self, b: Vec3) -> Vec3:
return Vec3(self.x - b.x, self.y - b.y, self.z - b.z)
def Cross(self, b: Vec3) -> Vec3*:
def Cross(self, b: Vec3) -> Vec3:
return Vec3(self.y * b.z - self.z * b.y, self.z * b.x - self.x * b.z, self.x * b.y - self.y * b.x)
def Dot(self, b: Vec3) -> float:
return self.x * b.x + self.y * b.y + self.z * b.z
def Norm(self) -> Vec3*:
def Norm(self) -> Vec3:
l = math.sqrtf(self.Dot(self))
return Vec3(self.x / l, self.y / l, self.z / l)
@@ -39,7 +39,7 @@ def Mat4_Identity() -> Mat4*:
m.m[0][0] = 1; m.m[1][1] = 1; m.m[2][2] = 1; m.m[3][3] = 1
return m
def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4*:
def Mat4_Mul(a: Mat4*, b: Mat4*) -> Mat4*:
res: Mat4 = Mat4()
string.memset(&res, 0, Mat4.__sizeof__())
for i in range(4):
@@ -48,7 +48,7 @@ def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4*:
res.m[i][j] += a.m[i][k] * b.m[k][j]
return res
def Mat4_MulVec(m: Mat4, v: Vec3) -> Vec3*:
def Mat4_MulVec(m: Mat4*, v: Vec3*) -> Vec3:
x: float = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]
y: float = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]
z: float = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]
@@ -65,7 +65,7 @@ def Mat4_Perspective(fov: float, aspect: float, zn: float, zf: float) -> Mat4*:
m.m[2][2] = zf / (zn - zf); m.m[2][3] = (zf * zn) / (zn - zf); m.m[3][2] = -1
return m
def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4*:
def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4:
zaxis: Vec3 = eye.Sub(target).Norm()
xaxis: Vec3 = up.Cross(zaxis).Norm()
yaxis: Vec3 = zaxis.Cross(xaxis)
@@ -76,7 +76,7 @@ def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4*:
m.m[3][3] = 1
return m
def Mat4_Translate(x: float, y: float, z: float) -> Mat4*:
def Mat4_Translate(x: float, y: float, z: float) -> Mat4:
m: Mat4 = Mat4_Identity()
m.m[0][3] = x; m.m[1][3] = y; m.m[2][3] = z
return m
@@ -132,7 +132,7 @@ class Renderer:
if e2 > -dy: err -= dy; x0 += sx
if e2 < dx: err += dx; y0 += sy
def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: uint32):
def DrawTriangle(self, v0: Vec3*, v1: Vec3*, v2: Vec3*, col: uint32):
if v0.z < float(0.0) or v1.z < float(0.0) or v2.z < float(0.0): return
if (v0.x > float(10.0) or v0.x < float(-10.0) or v0.y > float(10.0) or v0.y < float(-10.0) or
v1.x > float(10.0) or v1.x < float(-10.0) or v1.y > float(10.0) or v1.y < float(-10.0) or
@@ -259,7 +259,7 @@ class Scene3D:
Vec3(-1, -1, -1), Vec3(-1, -1, 1), Vec3(-1, 1, -1), Vec3(-1, 1, 1),
Vec3( 1, -1, -1), Vec3( 1, -1, 1), Vec3( 1, 1, -1), Vec3( 1, 1, 1)
]
for i in range(8): v[i] = *Mat4_MulVec(mvp, &v[i])
for i in range(8): v[i] = Mat4_MulVec(mvp, &v[i])
faces: t.CArray[t.CArray[int, 3], 12] = [
[0, 2, 1], [1, 2, 3], [4, 1, 5], [4, 0, 1], [6, 3, 2], [6, 7, 3],
[4, 6, 0], [0, 6, 2], [5, 7, 4], [4, 7, 6], [1, 3, 5], [5, 3, 7]
@@ -277,7 +277,7 @@ class Scene3D:
v[1] = Vec3(center.x+radius*math.sinf(theta1)*math.cosf(phi2), center.y+radius*math.cosf(theta1), center.z+radius*math.sinf(theta1)*math.sinf(phi2))
v[2] = Vec3(center.x+radius*math.sinf(theta2)*math.cosf(phi1), center.y+radius*math.cosf(theta2), center.z+radius*math.sinf(theta2)*math.sinf(phi1))
v[3] = Vec3(center.x+radius*math.sinf(theta2)*math.cosf(phi2), center.y+radius*math.cosf(theta2), center.z+radius*math.sinf(theta2)*math.sinf(phi2))
for k in range(4): v[k] = *Mat4_MulVec(mvp, &v[k])
for k in range(4): v[k] = Mat4_MulVec(mvp, &v[k])
self.renderer.DrawTriangle(&v[0], &v[1], &v[2], col)
self.renderer.DrawTriangle(&v[1], &v[3], &v[2], col)
+11 -11
View File
@@ -368,12 +368,12 @@ class _VGAScreenDriver:
if x < 0 or x >= self.fw or y < 0 or y >= self.fh: return
offset: int = y * self.fp + x * 4
# 解析RGBA分量
r: uchar = (color >> 16) & 0xFF
g: uchar = (color >> 8) & 0xFF
b: uchar = color & 0xFF
a: uchar = (color >> 24) & 0xFF
r: uchar = uchar((color >> 16) & 0xFF)
g: uchar = uchar((color >> 8) & 0xFF)
b: uchar = uchar((color >> 0) & 0xFF)
a: uchar = uchar((color >> 24) & 0xFF)
# 根据硬件格式写入像素
match self.ColorFormat:
switch self.ColorFormat:
case __ColorFormat.ColorFormat_BGRA:
self.fb[offset + 0] = b
fb[offset + 1] = g
@@ -392,7 +392,7 @@ class _VGAScreenDriver:
fb[offset + 0] = r
fb[offset + 1] = g
fb[offset + 2] = b
case _:
default:
# 降级到BGRA
fb[offset + 0] = b
fb[offset + 1] = g
@@ -407,10 +407,10 @@ class _VGAScreenDriver:
PixelSize: int = 3 if self.ColorFormat == __ColorFormat.ColorFormat_BGR or self.ColorFormat == __ColorFormat.ColorFormat_RGB else 4
RowSize: int = self.fw * PixelSize
# 解析清除颜色的RGBA分量
r: uchar = (color >> 16) & 0xFF
g: uchar = (color >> 8 ) & 0xFF
b: uchar = (color) & 0xFF
a: uchar = (color >> 24) & 0xFF
r: uchar = uchar((color >> 16) & 0xFF)
g: uchar = uchar((color >> 8) & 0xFF)
b: uchar = uchar((color >> 0) & 0xFF)
a: uchar = uchar((color >> 24) & 0xFF)
# 逐行填充,比逐像素调用SetPixel快得多
for y in range(self.fh):
row_ptr: uchar* = fb + y * fp
@@ -450,7 +450,7 @@ class _VGAScreenDriver:
ch: uchar = uchar(cr)
if ch >= 128: ch = DEFAULT_CHAR
# 预解析背景色Alpha,避免内层循环重复计算
bg_alpha: uint8 = (bgcolor >> 24) & 0xFF
bg_alpha: uint8 = uint8((bgcolor >> 24) & 0xFF)
draw_bg: int = (bg_alpha != 0) # 背景是否需要绘制
# 渲染8x16点阵字符
for fy in range(FONT_HEIGHT):
+11 -11
View File
@@ -119,23 +119,23 @@ def set_tss_rsp0(rsp0: uint64):
def setGate(num: int, base: uint64, limit: uint32, access: uint8, gran: uint8):
global gdt
gdt[num].limit_low = (limit & 0xFFFF)
gdt[num].base_low = (base & 0xFFFF)
gdt[num].base_middle = (base >> 16) & 0xFF
gdt[num].base_high = (base >> 24) & 0xFF
gdt[num].granularity = ((limit >> 16) & 0x0F) | (gran & 0xF0)
gdt[num].access = access
gdt[num].limit_low = uint16(limit & 0xFFFF)
gdt[num].base_low = uint16(base & 0xFFFF)
gdt[num].base_middle = uint8((base >> 16) & 0xFF)
gdt[num].base_high = uint8((base >> 24) & 0xFF)
gdt[num].granularity = uint8((limit >> 16) & 0x0F) | (gran & 0xF0)
gdt[num].access = uint8(access)
def setTSS64(num: int, base: uint64, limit: uint32):
global gdt
# 64 位 TSS 描述符占 16 字节(GDT 两项),复用同一地址按 gdt_entry64 整体写入:
# 前 8 字节为常规描述符字段,后 8 字节为 base[63:32] + 保留 0
e: gdt_entry64* = gdt_entry64*(&gdt[num])
e.limit_low = limit & 0xFFFF
e.base_low = base & 0xFFFF
e.base_middle = (base >> 16) & 0xFF
e.limit_low = uint16(limit & 0xFFFF)
e.base_low = uint16(base & 0xFFFF)
e.base_middle = uint8((base >> 16) & 0xFF)
e.access = 0x89
e.granularity = (limit >> 16) & 0x0F
e.base_high = (base >> 24) & 0xFF
e.granularity = uint8((limit >> 16) & 0x0F)
e.base_high = uint8((base >> 24) & 0xFF)
e.base_upper = uint32(base >> 32)
e.reserved = 0
+5 -5
View File
@@ -76,12 +76,12 @@ extern def isr_default()
def setGate(num: int, base: uint64, sel: uint16, flags: uint8):
global idt
idt[num].base_low = (base & 0xFFFF)
idt[num].base_middle = (base >> 16) & 0xFFFF
idt[num].base_high = (base >> 32) & 0xFFFFFFFF
idt[num].selector = sel
idt[num].base_low = uint16(base & 0xFFFF)
idt[num].base_middle = uint16((base >> 16) & 0xFFFF)
idt[num].base_high = uint32((base >> 32) & 0xFFFFFFFF)
idt[num].selector = uint16(sel)
idt[num].ist_attr = 0
idt[num].type_attr = flags
idt[num].type_attr = uint8(flags)
idt[num].reserved1 = 0
def isrCommonhandler(interrupt: int):
+12 -8
View File
@@ -28,7 +28,6 @@ import services.mouse as mse_svc
import services.desktop as desktop
import intr.syscall as syscall
import execrunner.elf as elf
import t, c
import asm
@@ -125,11 +124,11 @@ class ViperKernel:
serial.puts("[main] kernel init done\n")
fb: rawptr = rawptr(BootInfo.framebuffer_addr)
width: uint64 = BootInfo.framebuffer_width
height: uint64 = BootInfo.framebuffer_height
pitch: uint64 = BootInfo.framebuffer_pitch
fb_format: uint64 = BootInfo.framebuffer_format
fb_size: uint64 = BootInfo.framebuffer_size
width: int = int(BootInfo.framebuffer_width)
height: int = int(BootInfo.framebuffer_height)
pitch: int = int(BootInfo.framebuffer_pitch)
fb_format: int = int(BootInfo.framebuffer_format)
fb_size: uint64 = BootInfo.framebuffer_size
# [DBG] 打印 BootInfo 指针与 memmap 原始字段,定位全 0 根因(用后移除)
_dbbuf: [140]char
viperlib.snprintf(&_dbbuf, 140, "[main] BootInfo=0x%lx mmap=0x%lx mmsz=%lu mmd=%lu fb=0x%lx\n",
@@ -147,13 +146,19 @@ class ViperKernel:
serial.puts(&_dbraw)
serial.puts("\n[DB] dump end\n")
# 内核镜像末端(含 .bss;__bss_end 见 VKernel/linker.ld):传给 mm.init 使其在挑选
# 堆 arena 时排除整块内核镜像 —— .bss 不占文件大小,bootloader 只按文件大小预留页,
# 否则 .bss 尾部(ticks/_perf_* 等全局量)会落在 memmap 空闲区里被堆占用。
_kern_end: uint64 = 0
__asm__(f"lea {asmout(_kern_end, ASM_DESCR.OUTPUT_REG)}, [rip + __bss_end]",
op=[ASM_DESCR.CLOBBER_MEMORY])
if BootInfo is not None:
paging.init(BootInfo.MemmapAddr, BootInfo.MemmapSize)
fb_pages: uint64 = (fb_size + uint64(0xFFF)) >> uint64(12)
for fpi in range(fb_pages):
fva: uint64 = uint64(fb) + fpi * uint64(0x1000)
paging.MapPage(fva, fva, paging.PTE_WRITABLE | paging.PTE_PCD)
mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size)
mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size, BootInfo.kernel_PhysAddr, _kern_end)
pt_pool_buf: rawptr = mm.malloc(uint64(513) * uint64(4096))
paging.init_pool(pt_pool_buf, uint64(513) * uint64(4096))
else:
@@ -354,4 +359,3 @@ def _start() -> int:
asm.hlt()
sched.Scheduler._yield()
return 0
+19 -5
View File
@@ -117,7 +117,7 @@ class _BuddySystemObject:
block: memory_block* = memory_block*(cur_addr)
block.size = block_size
block.state = BLOCK_FREE
block.order = order
block.order = uint8(order)
block.next = None
block.prev = None
if order <= MAX_ORDER:
@@ -139,12 +139,12 @@ class _BuddySystemObject:
new_block: memory_block* = memory_block*(uint64(block) + new_block_size)
new_block.size = new_block_size
new_block.state = BLOCK_FREE
new_block.order = current_order
new_block.order = uint8(current_order)
new_block.next = None
new_block.prev = None
# 更新原块大小和阶数
block.size = new_block_size
block.order = current_order
block.order = uint8(current_order)
# 将新块添加到对应阶数的空闲链表
if current_order <= MAX_ORDER:
new_block.next = self.buddy.free_lists[current_order]
@@ -175,7 +175,7 @@ class _BuddySystemObject:
# 合并块
merged_block: memory_block* = block if block < buddy else buddy
merged_block.size = get_block_size(order + 1)
merged_block.order = order + 1
merged_block.order = uint8(order + 1)
block = merged_block
order += 1
return block
@@ -448,7 +448,7 @@ def free_memory_regions():
memory_regions = None
# 初始化内存管理系统
def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0):
def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0, KernelAddr: uint64 = 0, KernelEnd: uint64 = 0):
global BuddySystemObject
start_addr: rawptr = None
size: uint64 = 0
@@ -476,6 +476,20 @@ def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr:
fb_end: uint64 = FbAddr + FbSize
if start < fb_end and end > FbAddr:
continue
# 排除内核镜像区([KernelAddr, KernelEnd),含 .bss):bootloader 只按
# 文件大小预留页,.bss 不占文件 → 其尾部留在 memmap 的 EfiConventionalMemory
# 里。若不排除,堆 arena 会用这段内存写 memory_block 头/用户数据,与内核
# 全局量(ticks/_perf_* 等)互相破坏,并进一步搞乱堆元数据。
# 内核镜像位于常规内存低端,故把与该区间重叠的 region 起点抬到镜像末端,
# 而不是整段丢弃(整段丢弃会连带弃掉镜像之上的一大片可用内存)。
if KernelEnd > KernelAddr:
if end <= KernelEnd:
continue
if start < KernelEnd:
start = KernelEnd
region_size = end - start
if end <= start:
continue
if etype == MEMORY_TYPE_AVAILABLE:
if region_size > best_avail_size:
best_avail_size = region_size
+2 -2
View File
@@ -99,7 +99,7 @@ def setMask(irq: uint8):
else:
port = PIC2_DATA
irq -= 8
value = asm.inb(port) | (1 << irq)
value = uint8(asm.inb(port) | (1 << irq))
asm.outb(port, value)
asm.io_wait() # 确保命令生效
@@ -114,6 +114,6 @@ def clearMask(irq: uint8):
else:
port = PIC2_DATA
irq -= 8
value = asm.inb(port) & ~(1 << irq)
value = uint8(asm.inb(port) & ~(1 << irq))
asm.outb(port, value)
asm.io_wait() # 确保命令生效
+2 -2
View File
@@ -18,9 +18,9 @@ def pit_init(frequency: int):
asm.io_wait()
# 写入低字节
asm.outb(PIT_CHANNEL0, divisor & 0xFF)
asm.outb(PIT_CHANNEL0, uint8(divisor & 0xFF))
asm.io_wait()
# 写入高字节
asm.outb(PIT_CHANNEL0, (divisor >> 8) & 0xFF)
asm.outb(PIT_CHANNEL0, uint8((divisor >> 8) & 0xFF))
asm.io_wait()
+4 -4
View File
@@ -2,7 +2,6 @@ import drivers.input.keyboard.keyboard as keyboard
import drivers.usb.hid.usb_kbd as usb_kbd
import drivers.serial.uart.serial as serial
import sched.sched as sched
import viperlib
define SERVICE_KEYBOARD = 1
@@ -17,8 +16,6 @@ class KeyboardService:
self.running = 0
self.usb_kbd_th = None
kbd_svc: KeyboardService
def kbd_thread(arg: rawptr) -> int:
serial.puts("[kbd_svc] started\n")
@@ -39,9 +36,12 @@ def usb_kbd_thread(arg: rawptr) -> int:
sched.Scheduler._yield()
return 0
kbd_svc: KeyboardService = KeyboardService()
def start() -> int:
global kbd_svc
kbd_svc = KeyboardService()
kbd_svc.__init__()
keyboard.init()
serial.puts("[kbd_svc] PS/2 keyboard initialized, IRQ1 installed\n")
usb_kbd.init()
+7
View File
@@ -26,6 +26,13 @@ SECTIONS {
*(.bss)
*(.bss.*)
*(COMMON)
/* 强制本输出段为 PROGBITS 并占用文件空间:.bss 默认是 NOBITS(不占文件),
于是 kernel.bin 的 FileSize 不包含 .bss。bootloader 只按文件大小预留物理页
(PagesNeeded = KernelSize/4096),.bss 尾部(ticks/_perf_* 等全局量)便留在
未预留的 EfiConventionalMemory 里,被 mm 的堆 arena 覆盖 → 破坏内核全局量、
并反过来破坏堆元数据。加一条数据语句(LONG)即让整段 .bss 写入 kernel.bin。 */
. = ALIGN(16);
LONG(0);
__bss_end = .;
}
+25
View File
@@ -464,6 +464,31 @@ EFI_STATUS ExitBootServicesAndJumpToKernel(
Print(L"Final FB: 0x%lx | %lux%lu | pitch %lu | format %lu\r\n",
framebuffer_addr, framebuffer_width, framebuffer_height, framebuffer_pitch, framebuffer_format);
// ==========================
// 预留内核栈区(BOOTLOADER_STACK_BOTTOM ~ BOOTLOADER_STACK_TOP)
// ==========================
// 跳转内核后此区是主线程栈,但它在 memmap 里默认仍是 EfiConventionalMemory。
// 若不占位,内核 mm 堆可能把这段内存当空闲区分配 → 主线程栈被堆数据覆盖。
// 必须在 GetMemoryMap 之前用 AllocatePages 显式占位(AllocateAddress +
// EfiLoaderData),使其在捕获的 memmap 中标记为已用。
{
EFI_PHYSICAL_ADDRESS StackAddr = BOOTLOADER_STACK_BOTTOM;
UINTN StackPages = (UINTN)((BOOTLOADER_STACK_TOP - BOOTLOADER_STACK_BOTTOM) / 0x1000ULL);
EFI_STATUS StackStatus = SystemTable->BootServices->AllocatePages(
AllocateAddress,
EfiLoaderData,
StackPages,
&StackAddr
);
if (EFI_ERROR(StackStatus)) {
Print(L"Warning: Reserve boot stack region (0x%lx-0x%lx) failed - %r\r\n",
BOOTLOADER_STACK_BOTTOM, BOOTLOADER_STACK_TOP, StackStatus);
} else {
Print(L"Boot stack region reserved: 0x%lx-0x%lx (%lu pages)\r\n",
BOOTLOADER_STACK_BOTTOM, BOOTLOADER_STACK_TOP, StackPages);
}
}
// ==========================
// ExitBootServices 流程
// ==========================