chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)

内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
This commit is contained in:
TermiNexus committed 2026-09-28 15:24:52 +08:00
1 parent 1c3fcd6e1e
commit dcb7c5c2c0
26 files changed
+1558 -1790

No files matched your search

+18 -21
View File
@@ -1,6 +1,3 @@
import t, c
MEMORY_TYPE_AVAILABLE: uint64 = 7
MEMORY_TYPE_RESERVED: uint64 = 0
MEMORY_TYPE_LOADER_CODE: uint64 = 1
@@ -13,24 +10,24 @@ MEMORY_TYPE_ACPI_RECLAIMABLE: uint64 = 9
MEMORY_TYPE_ACPI_NVS: uint64 = 10
MEMORY_TYPE_BAD_MEMORY: uint64 = 8
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class memory_map_entry:
type: t.CUnsignedInt
_pad: t.CUnsignedInt
physical_start: t.CUnsignedLong
virtual_start: t.CUnsignedLong
num_pages: t.CUnsignedLong
attribute: t.CUnsignedLong
type: uint
_pad: uint
physical_start: ulong
virtual_start: ulong
num_pages: ulong
attribute: ulong
class bootinfo:
MemmapAddr: t.CUnsignedLong
MemmapSize: t.CUnsignedLong
MemmapDescSize: t.CUnsignedLong
kernel_PhysAddr: t.CUnsignedLong
framebuffer_addr: t.CUnsignedLong
framebuffer_size: t.CUnsignedLong
framebuffer_width: t.CUnsignedLong
framebuffer_height: t.CUnsignedLong
framebuffer_pitch: t.CUnsignedLong
framebuffer_format: t.CUnsignedLong
system_table: t.CUnsignedLong
MemmapAddr: ulong
MemmapSize: ulong
MemmapDescSize: ulong
kernel_PhysAddr: ulong
framebuffer_addr: ulong
framebuffer_size: ulong
framebuffer_width: ulong
framebuffer_height: ulong
framebuffer_pitch: ulong
framebuffer_format: ulong
system_table: ulong
+7 -8
View File
@@ -6,7 +6,6 @@ import drivers.core.cpu.cpu as cpu
import mm.mm as mm
import platform.pch.timer as timer
import viperlib
import t, c
define IA32_APIC_BASE = 0x1B
@@ -66,7 +65,7 @@ def eoi():
def get_id() -> uint32:
return read(LAPIC_ID) >> 24
@c.Attribute(t.attr.noinline)
@__attribute__(noinline)
def init():
global _lapic_base, _bsp_lapic_id
msr_val: uint64 = cpu.msr_read(IA32_APIC_BASE)
@@ -83,7 +82,7 @@ def init():
write(LAPIC_LDR, 0x01000000)
eoi()
@c.Attribute(t.attr.noinline)
@__attribute__(noinline)
def detect_cpu_count() -> uint32:
res: cpu.cpuid_result
cpu.cpuid(0, &res)
@@ -119,8 +118,8 @@ def _send_ipi(apic_id: uint32, vector: uint32, delivery_mode: uint32):
def ap_entry():
global _ap_ready
my_id: uint32 = get_id()
buf: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(buf), 64, "[AP] core %u started (lapic=%u)\n", my_id, my_id)
buf: [64]char
viperlib.snprintf(&buf, 64, "[AP] core %u started (lapic=%u)\n", my_id, my_id)
serial.puts(buf)
_ap_ready = 1
while True:
@@ -214,13 +213,13 @@ def start_aps():
if _cpu_count <= 1: return
cr3_val: uint64 = 0
c.Asm(f"""mov rax, cr3
mov {c.AsmOut(cr3_val, t.ASM_DESCR.OUTPUT_REG)}, rax""", op = [t.ASM_DESCR.CLOBBER_RAX])
__asm__(f"""mov rax, cr3
mov {asmout(cr3_val, ASM_DESCR.OUTPUT_REG)}, rax""", op = [ASM_DESCR.CLOBBER_RAX])
stack_size: uint64 = 8192
for i in range(1, _cpu_count):
_ap_ready = 0
stack: t.CPtr = mm.malloc(stack_size)
stack: rawptr = mm.malloc(stack_size)
if stack is None: continue
stack_top: uint64 = uint64(stack) + stack_size
stack_top = stack_top & ~uint64(15)
+1 -1
View File
@@ -3,7 +3,7 @@ import string
import asm
define IA32_KERNEL_GS_BASE = 0xC0000102
defineKERN_STACK_SIZE = 8192
define KERN_STACK_SIZE = 8192
define CPU_FEATURE_FPU = (1 << 0)
+9 -9
View File
@@ -9,10 +9,10 @@ define MAX_DIRECTORIES = 16
define PATH_BUFFER_SIZE = 256
directories: [MAX_DIRECTORIES]devfs_directory = [0]
directory_count: static int = 0
static directory_count: int = 0
files: [MAX_DEVICE_FILES]devfs_file = [0]
file_count: static int = 0
static file_count: int = 0
class _fd_table:
@@ -88,7 +88,7 @@ virtual class devfs_file:
@staticmethod
def list_in_dir(dir_ptr: devfs_directory*, buffer: str, size: uint32, pos: int) -> int:
for f in range(file_count):
filep: devfs_file* = c.Addr(files[f])
filep: devfs_file* = &files[f]
if filep.parent_dir == dir_ptr:
name_len: int = string.strlen(filep.name)
if pos + name_len + 1 > size:
@@ -124,7 +124,7 @@ class _DevFSObject:
if directory_count >= MAX_DIRECTORIES: return None
if string.strlen(dir_name) >= 64: return None
new_dir: devfs_directory* = c.Addr(directories[directory_count])
new_dir: devfs_directory* = &directories[directory_count]
directory_count += 1
string.strcpy(new_dir.name, dir_name)
@@ -137,7 +137,7 @@ class _DevFSObject:
if not path or string.samestr(path, "/"): return None
if not self.root_directory:
self.root_directory = c.Addr(directories[directory_count])
self.root_directory = &directories[directory_count]
directory_count += 1
string.strcpy(self.root_directory.name, "")
self.root_directory.parent = None
@@ -204,7 +204,7 @@ class _DevFSObject:
file_ptr.parent_dir = dir_ptr
files[file_count] = file_ptr
else:
new_file: devfs_file* = c.Addr(files[file_count])
new_file: devfs_file* = &files[file_count]
string.strcpy(new_file.name, file_name)
new_file.private_data = private_data
new_file.parent_dir = dir_ptr
@@ -336,16 +336,16 @@ def serial0_read(self: rawptr, fd: int, buffer: rawptr, size: uint32) -> int:
def serial0_write(self: rawptr, fd: int, buffer: const rawptr, size: uint32) -> int:
serial.puts("[serial0] write\n")
serial.puts(str(buffer))
serial.puts(buffer)
serial.puts("\n")
return size
def devfs_register_serial0() -> int:
global serial0_file
serial0_file = devfs_file()
serial0_file.open = serial0_open
serial0_file.open = serial0_open
serial0_file.close = serial0_close
serial0_file.read = serial0_read
serial0_file.read = serial0_read
serial0_file.write = serial0_write
return devfs_create_file("/dev/serial0", serial0_file, None)
+105 -107
View File
@@ -1,4 +1,3 @@
import t, c
import mm.mm as mm
import string
import drivers.serial.uart.serial as serial
@@ -7,152 +6,153 @@ import drivers.usb.pci as pci
import platform.pch.timer as timer
import viperlib
USB_DESC_DEVICE: t.CDefine = 1
USB_DESC_CONFIG: t.CDefine = 2
USB_DESC_STRING: t.CDefine = 3
USB_DESC_INTERFACE: t.CDefine = 4
USB_DESC_ENDPOINT: t.CDefine = 5
USB_REQ_GET_STATUS: t.CDefine = 0
USB_REQ_CLEAR_FEATURE: t.CDefine = 1
USB_REQ_SET_FEATURE: t.CDefine = 3
USB_REQ_SET_ADDRESS: t.CDefine = 5
USB_REQ_GET_DESCRIPTOR: t.CDefine = 6
USB_REQ_SET_DESCRIPTOR: t.CDefine = 7
USB_REQ_GET_CONFIGURATION: t.CDefine = 8
USB_REQ_SET_CONFIGURATION: t.CDefine = 9
define USB_DESC_DEVICE = 1
define USB_DESC_CONFIG = 2
define USB_DESC_STRING = 3
define USB_DESC_INTERFACE = 4
define USB_DESC_ENDPOINT = 5
USB_REQ_SET_INTERFACE: t.CDefine = 11
define USB_REQ_GET_STATUS = 0
define USB_REQ_CLEAR_FEATURE = 1
define USB_REQ_SET_FEATURE = 3
define USB_REQ_SET_ADDRESS = 5
define USB_REQ_GET_DESCRIPTOR = 6
define USB_REQ_SET_DESCRIPTOR = 7
define USB_REQ_GET_CONFIGURATION = 8
define USB_REQ_SET_CONFIGURATION = 9
HID_CLASS: t.CDefine = 0x03
HID_SUBCLASS_BOOT: t.CDefine = 0x01
HID_PROTO_KEYBOARD: t.CDefine = 0x01
HID_PROTO_MOUSE: t.CDefine = 0x02
define USB_REQ_SET_INTERFACE = 11
HID_REQ_SET_PROTOCOL: t.CDefine = 0x0B
HID_REQ_SET_IDLE: t.CDefine = 0x0A
HID_REQ_GET_REPORT: t.CDefine = 0x01
define HID_CLASS = 0x03
define HID_SUBCLASS_BOOT = 0x01
define HID_PROTO_KEYBOARD = 0x01
define HID_PROTO_MOUSE = 0x02
USB_MAX_DEVICES: t.CDefine = 8
define HID_REQ_SET_PROTOCOL = 0x0B
define HID_REQ_SET_IDLE = 0x0A
define HID_REQ_GET_REPORT = 0x01
class usb_dev_desc(t.CStruct):
bLength: uint8
define USB_MAX_DEVICES = 8
class usb_dev_desc:
bLength: uint8
bDescriptorType: uint8
bcdUSB: uint16
bDeviceClass: uint8
bcdUSB: uint16
bDeviceClass: uint8
bDeviceSubClass: uint8
bDeviceProtocol: uint8
bMaxPacketSize0: uint8
idVendor: uint16
idProduct: uint16
bcdDevice: uint16
iManufacturer: uint8
iProduct: uint8
iSerialNumber: uint8
idVendor: uint16
idProduct: uint16
bcdDevice: uint16
iManufacturer: uint8
iProduct: uint8
iSerialNumber: uint8
bNumConfigurations: uint8
class usb_config_desc(t.CStruct):
bLength: uint8
class usb_config_desc:
bLength: uint8
bDescriptorType: uint8
wTotalLength: uint16
bNumInterfaces: uint8
wTotalLength: uint16
bNumInterfaces: uint8
bConfigurationValue: uint8
iConfiguration: uint8
bmAttributes: uint8
bMaxPower: uint8
iConfiguration: uint8
bmAttributes: uint8
bMaxPower: uint8
class usb_iface_desc(t.CStruct):
bLength: uint8
bDescriptorType: uint8
bInterfaceNumber: uint8
bAlternateSetting: uint8
bNumEndpoints: uint8
bInterfaceClass: uint8
class usb_iface_desc:
bLength: uint8
bDescriptorType: uint8
bInterfaceNumber: uint8
bAlternateSetting: uint8
bNumEndpoints: uint8
bInterfaceClass: uint8
bInterfaceSubClass: uint8
bInterfaceProtocol: uint8
iInterface: uint8
iInterface: uint8
class usb_ep_desc(t.CStruct):
bLength: uint8
bDescriptorType: uint8
class usb_ep_desc:
bLength: uint8
bDescriptorType: uint8
bEndpointAddress: uint8
bmAttributes: uint8
wMaxPacketSize: uint16
bInterval: uint8
bmAttributes: uint8
wMaxPacketSize: uint16
bInterval: uint8
class usb_setup_pkt(t.CStruct):
class usb_setup_pkt:
bmRequestType: uint8
bRequest: uint8
wValue: uint16
wIndex: uint16
wLength: uint16
bRequest: uint8
wValue: uint16
wIndex: uint16
wLength: uint16
class usb_device(t.CStruct):
addr: uint8
ls: int
max_pkt0: uint8
iface_class: uint8
class usb_device:
addr: uint8
ls: int
max_pkt0: uint8
iface_class: uint8
iface_subclass: uint8
iface_protocol: uint8
iface_num: uint8
ep_in: uint8
ep_in_max: uint16
iface_num: uint8
ep_in: uint8
ep_in_max: uint16
ep_in_interval: uint8
ep_in_toggle: uint8
configured: int
ep_in_toggle: uint8
configured: int
_devices: t.CArray[usb_device, USB_MAX_DEVICES]
_devices: [USB_MAX_DEVICES]usb_device
_device_count: int = 0
def _setup_packet(bmRequestType: uint8, bRequest: uint8, wValue: uint16, wIndex: uint16, wLength: uint16, buf: usb_setup_pkt | t.CPtr):
def _setup_packet(bmRequestType: uint8, bRequest: uint8, wValue: uint16, wIndex: uint16, wLength: uint16, buf: usb_setup_pkt*):
buf.bmRequestType = bmRequestType
buf.bRequest = bRequest
buf.wValue = wValue
buf.wIndex = wIndex
buf.wLength = wLength
def _send_control(dev_addr: uint8, ls: int, max_pkt: uint8, setup: usb_setup_pkt | t.CPtr, data_buf: t.CPtr, data_len: uint16, data_in: int) -> int:
return uhci.control_transfer(dev_addr, 0, ls, max_pkt, c.Addr(setup), data_buf, data_len, data_in)
def _send_control(dev_addr: uint8, ls: int, max_pkt: uint8, setup: usb_setup_pkt*, data_buf: rawptr, data_len: uint16, data_in: int) -> int:
return uhci.control_transfer(dev_addr, 0, ls, max_pkt, setup, data_buf, data_len, data_in)
def get_descriptor(dev_addr: uint8, ls: int, max_pkt: uint8, desc_type: uint8, desc_idx: uint8, buf: t.CPtr, length: uint16) -> int:
def get_descriptor(dev_addr: uint8, ls: int, max_pkt: uint8, desc_type: uint8, desc_idx: uint8, buf: rawptr, length: uint16) -> int:
setup: usb_setup_pkt
_setup_packet(0x80, USB_REQ_GET_DESCRIPTOR, (uint16(desc_type) << 8) | desc_idx, 0, length, c.Addr(setup))
return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), buf, length, 1)
_setup_packet(0x80, USB_REQ_GET_DESCRIPTOR, (uint16(desc_type) << 8) | desc_idx, 0, length, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, buf, length, 1)
def set_address(dev_addr: uint8, ls: int, max_pkt: uint8, new_addr: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x00, USB_REQ_SET_ADDRESS, new_addr, 0, 0, c.Addr(setup))
return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0)
_setup_packet(0x00, USB_REQ_SET_ADDRESS, new_addr, 0, 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def set_configuration(dev_addr: uint8, ls: int, max_pkt: uint8, config_val: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x00, USB_REQ_SET_CONFIGURATION, config_val, 0, 0, c.Addr(setup))
return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0)
_setup_packet(0x00, USB_REQ_SET_CONFIGURATION, config_val, 0, 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def hid_set_protocol(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, protocol: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x21, HID_REQ_SET_PROTOCOL, protocol, uint16(iface), 0, c.Addr(setup))
return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0)
_setup_packet(0x21, HID_REQ_SET_PROTOCOL, protocol, uint16(iface), 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def hid_set_idle(dev_addr: uint8, ls: int, max_pkt: uint8, iface: uint8, duration: uint8) -> int:
setup: usb_setup_pkt
_setup_packet(0x21, HID_REQ_SET_IDLE, uint16(duration) << 8, uint16(iface), 0, c.Addr(setup))
return _send_control(dev_addr, ls, max_pkt, c.Addr(setup), None, 0, 0)
_setup_packet(0x21, HID_REQ_SET_IDLE, uint16(duration) << 8, uint16(iface), 0, &setup)
return _send_control(dev_addr, ls, max_pkt, &setup, None, 0, 0)
def _parse_config(dev: usb_device | t.CPtr, config_buf: t.CPtr, total_len: uint16):
def _parse_config(dev: usb_device*, config_buf: rawptr, total_len: uint16):
offset: int = 0
found_hid: int = 0
while offset < int(total_len):
p: uint8 | t.CPtr = config_buf + uint64(offset)
desc_len: uint8 = c.Deref(p)
p2: uint8 | t.CPtr = config_buf + uint64(offset) + 1
desc_type: uint8 = c.Deref(p2)
p: uint8* = config_buf + uint64(offset)
desc_len: uint8 = *p
p2: uint8* = config_buf + uint64(offset) + 1
desc_type: uint8 = *p2
if desc_len == 0: break
# 边界:描述符整体须落在 config_buf(total_len 字节)内,且不得短于
# 所访问的结构体(interface=9 / endpoint=7),否则越界读。
if offset + int(desc_len) > int(total_len): break
if desc_type == USB_DESC_INTERFACE and int(desc_len) >= 9:
iface: usb_iface_desc | t.CPtr = config_buf + uint64(offset)
iface: usb_iface_desc* = usb_iface_desc*(config_buf + uint64(offset))
if iface.bInterfaceClass == HID_CLASS:
found_hid = 1
dev.iface_class = HID_CLASS
@@ -160,7 +160,7 @@ def _parse_config(dev: usb_device | t.CPtr, config_buf: t.CPtr, total_len: uint1
dev.iface_protocol = iface.bInterfaceProtocol
dev.iface_num = iface.bInterfaceNumber
if desc_type == USB_DESC_ENDPOINT and found_hid and int(desc_len) >= 7:
ep: usb_ep_desc | t.CPtr = config_buf + uint64(offset)
ep: usb_ep_desc* = usb_ep_desc*(config_buf + uint64(offset))
if (ep.bEndpointAddress & 0x80) != 0:
dev.ep_in = ep.bEndpointAddress & 0x0F
dev.ep_in_max = ep.wMaxPacketSize
@@ -175,7 +175,6 @@ def enumerate_port(port: int) -> int:
ls: int = uhci.port_is_low_speed(port)
reset_ok: int = -1
reset_retry: int
for reset_retry in range(3):
if uhci.port_reset(port) == 0:
reset_ok = 0
@@ -186,7 +185,7 @@ def enumerate_port(port: int) -> int:
timer.timer_msleep(10)
dev_buf: t.CPtr = mm.malloc(usb_dev_desc.__sizeof__())
dev_buf: rawptr = mm.malloc(usb_dev_desc.__sizeof__())
if dev_buf is None: return -3
string.memset(dev_buf, 0, usb_dev_desc.__sizeof__())
@@ -202,7 +201,7 @@ def enumerate_port(port: int) -> int:
mm.free(dev_buf)
return -4
desc: usb_dev_desc | t.CPtr = dev_buf
desc: usb_dev_desc* = dev_buf
max_pkt: uint8 = desc.bMaxPacketSize0
if max_pkt < 8: max_pkt = 8
@@ -218,7 +217,7 @@ def enumerate_port(port: int) -> int:
timer.timer_msleep(10)
dev: usb_device | t.CPtr = c.Addr(_devices[_device_count])
dev: usb_device* = &_devices[_device_count]
dev.addr = new_addr
dev.ls = ls
dev.max_pkt0 = max_pkt
@@ -231,7 +230,7 @@ def enumerate_port(port: int) -> int:
dev.ep_in_interval = 0
dev.ep_in_toggle = 0
config_buf: t.CPtr = mm.malloc(256)
config_buf: rawptr = mm.malloc(256)
if config_buf is None:
mm.free(dev_buf)
return -6
@@ -247,7 +246,7 @@ def enumerate_port(port: int) -> int:
mm.free(dev_buf)
return -7
cfg: usb_config_desc | t.CPtr = config_buf
cfg: usb_config_desc* = config_buf
total_len: uint16 = cfg.wTotalLength
if total_len > 256: total_len = 256
@@ -289,8 +288,8 @@ def init() -> int:
serial.puts("[usb] UHCI controller not found\n")
return -1
buf: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(buf), 64, "[usb] UHCI at I/O 0x%04X\n", uint32(io_base))
buf: [64]char
viperlib.snprintf(&buf, 64, "[usb] UHCI at I/O 0x%04X\n", uint32(io_base))
serial.puts(buf)
if uhci.init(io_base) != 0:
@@ -301,33 +300,32 @@ def init() -> int:
timer.timer_msleep(50)
port: int
for port in range(2):
if uhci.port_is_connected(port):
viperlib.snprintf(c.Addr(buf), 64, "[usb] port %d connected\n", uint32(port))
viperlib.snprintf(&buf, 64, "[usb] port %d connected\n", uint32(port))
serial.puts(buf)
dev_id: int = enumerate_port(port)
if dev_id > 0:
dev: usb_device | t.CPtr = c.Addr(_devices[dev_id - 1])
viperlib.snprintf(c.Addr(buf), 64, "[usb] device addr=%d class=%02X proto=%02X ep=%d\n",
dev: usb_device* = &_devices[dev_id - 1]
viperlib.snprintf(&buf, 64, "[usb] device addr=%d class=%02X proto=%02X ep=%d\n",
uint32(dev.addr), uint32(dev.iface_class),
uint32(dev.iface_protocol), uint32(dev.ep_in))
serial.puts(buf)
else:
viperlib.snprintf(c.Addr(buf), 64, "[usb] enumerate port %d failed: %d\n", uint32(port), int32(dev_id))
viperlib.snprintf(&buf, 64, "[usb] enumerate port %d failed: %d\n", uint32(port), int32(dev_id))
serial.puts(buf)
return _device_count
def find_hid_device(protocol: uint8) -> usb_device | t.CPtr:
def find_hid_device(protocol: uint8) -> usb_device*:
i: int
for i in range(_device_count):
dev: usb_device | t.CPtr = c.Addr(_devices[i])
dev: usb_device* = &_devices[i]
if dev.iface_class == HID_CLASS:
if dev.iface_protocol == protocol:
if dev.configured != 0:
return dev
return None
def read_interrupt(dev: usb_device | t.CPtr, buf: t.CPtr) -> int:
def read_interrupt(dev: usb_device*, buf: rawptr) -> int:
return 0
+13 -14
View File
@@ -1,14 +1,13 @@
from stdint import *
import drivers.video.vesafb.gfx as gfx
import t, c
MAX_SHEETS: t.CDefine = 64
MAX_UI_COMPONENTS: t.CDefine = 256
define MAX_SHEETS = 64
define MAX_UI_COMPONENTS = 256
_next_sheet_id: int = 0
_next_component_id: int = 0
@t.Object
class Sheet:
id: int
x: int
@@ -18,12 +17,12 @@ class Sheet:
visible: int
_surf_obj: gfx.Surface
_renderer_obj: gfx.Renderer
surf: gfx.Surface | t.CPtr
renderer: gfx.Renderer | t.CPtr
parent: 'Sheet | t.CPtr'
surf: gfx.Surface*
renderer: gfx.Renderer*
parent: Sheet*
bg_color: uint32
def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, x: int, y: int, w: int, h: int, parent: 'Sheet | t.CPtr' = None):
def __init__(self, fb: UINT32PTR, zb: float*, x: int, y: int, w: int, h: int, parent: Sheet* = None):
global _next_sheet_id
self.id = _next_sheet_id
_next_sheet_id += 1
@@ -33,12 +32,12 @@ class Sheet:
self.h = h
self.visible = 1
self._surf_obj = gfx.Surface(fb, zb, w, h)
self.surf = c.Addr(self._surf_obj)
self.surf = &self._surf_obj
# gfx.Renderer.__init__(fb, zb, w, h):此前只传 self.surf(Surface*)→
# fb 被 bitcast 错位、w/h 缺省为 0 → Renderer 的 _w/_h = 0 →
# Sheet.Clear/Fill/DrawRect(走 renderer)全部空操作。按 Surface 同参构造。
self._renderer_obj = gfx.Renderer(fb, zb, w, h)
self.renderer = c.Addr(self._renderer_obj)
self.renderer = &self._renderer_obj
self.parent = parent
self.bg_color = gfx.COLOR_RGB(20, 20, 30)
@@ -57,22 +56,22 @@ class Sheet:
self.visible = 0
def Clear(self):
r: gfx.Renderer = c.Deref(self.renderer)
r: gfx.Renderer = *self.renderer
r.Clear(self.bg_color)
def Fill(self, color: uint32):
r: gfx.Renderer = c.Deref(self.renderer)
r: gfx.Renderer = *self.renderer
r.Clear(color)
def DrawRect(self, rx: int, ry: int, rw: int, rh: int, color: uint32):
r: gfx.Renderer = c.Deref(self.renderer)
r: gfx.Renderer = *self.renderer
r.DrawLine2D(rx, ry, rx + rw - 1, ry, color)
r.DrawLine2D(rx + rw - 1, ry, rx + rw - 1, ry + rh - 1, color)
r.DrawLine2D(rx + rw - 1, ry + rh - 1, rx, ry + rh - 1, color)
r.DrawLine2D(rx, ry + rh - 1, rx, ry, color)
def DrawFilledRect(self, rx: int, ry: int, rw: int, rh: int, color: uint32):
surf: gfx.Surface = c.Deref(self.surf)
surf: gfx.Surface = *self.surf
fb: UINT32PTR = surf.fb
w: int = surf.w
h: int = surf.h
+26 -32
View File
@@ -2,14 +2,13 @@ from stdint import *
import drivers.video.vesafb.gfx as gfx
import drivers.video.ui.sheet as sheet
import string
import t, c
UI_LABEL: t.CDefine = 0
UI_BUTTON: t.CDefine = 1
UI_PANEL: t.CDefine = 2
UI_PROGRESS: t.CDefine = 3
@t.Object
define UI_LABEL = 0
define UI_BUTTON = 1
define UI_PANEL = 2
define UI_PROGRESS = 3
class UIComponent:
id: int
ctype: int
@@ -18,14 +17,14 @@ class UIComponent:
w: int
h: int
visible: int
sheet: sheet.Sheet | t.CPtr
sheet: sheet.Sheet*
fg_color: uint32
bg_color: uint32
text: t.CArray[t.CChar, 128]
text: [128]char
text_len: int
value: int
def __init__(self, ctype: int, sh: sheet.Sheet | t.CPtr, x: int, y: int, w: int, h: int):
def __init__(self, ctype: int, sh: sheet.Sheet*, x: int, y: int, w: int, h: int):
self.id = sheet._next_component_id
sheet._next_component_id += 1
self.ctype = ctype
@@ -37,7 +36,7 @@ class UIComponent:
self.sheet = sh
self.fg_color = gfx.COLOR_RGB(255, 255, 255)
self.bg_color = gfx.COLOR_RGB(40, 40, 60)
string.memset(c.Addr(self.text), 0, 128)
string.memset(&self.text, 0, 128)
self.text_len = 0
self.value = 0
@@ -55,16 +54,12 @@ class UIComponent:
def Render(self):
if self.visible == 0: return
sh: sheet.Sheet = c.Deref(self.sheet)
sh: sheet.Sheet = *self.sheet
match self.ctype:
case 0:
self._RenderLabel(sh)
case 1:
self._RenderButton(sh)
case 2:
self._RenderPanel(sh)
case 3:
self._RenderProgress(sh)
case 0: self._RenderLabel(sh)
case 1: self._RenderButton(sh)
case 2: self._RenderPanel(sh)
case 3: self._RenderProgress(sh)
def _RenderLabel(self, sh: sheet.Sheet):
sh.DrawFilledRect(self.x, self.y, self.w, self.h, 0)
@@ -90,11 +85,10 @@ class UIComponent:
return 0
@t.Object
class UIManager:
sheets: t.CArray[sheet.Sheet | t.CPtr, 64]
sheets: [64]sheet.Sheet*
sheet_count: int
components: t.CArray[UIComponent | t.CPtr, 256]
components: [256]UIComponent*
component_count: int
screen_w: int
screen_h: int
@@ -110,41 +104,41 @@ class UIManager:
for i in range(256):
self.components[i] = None
def AddSheet(self, sh: sheet.Sheet | t.CPtr) -> int:
def AddSheet(self, sh: sheet.Sheet*) -> int:
if self.sheet_count >= 64: return -1
self.sheets[self.sheet_count] = sh
self.sheet_count += 1
return 0
def AddComponent(self, comp: UIComponent | t.CPtr) -> int:
def AddComponent(self, comp: UIComponent*) -> int:
if self.component_count >= 256: return -1
self.components[self.component_count] = comp
self.component_count += 1
return 0
def FindComponent(self, cid: int) -> UIComponent | t.CPtr:
def FindComponent(self, cid: int) -> UIComponent*:
i: int
for i in range(self.component_count):
p: UIComponent | t.CPtr = self.components[i]
p: UIComponent* = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
comp: UIComponent = *p
if comp.id == cid: return p
return None
def RenderAll(self):
i: int
for i in range(self.component_count):
p: UIComponent | t.CPtr = self.components[i]
p: UIComponent* = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
comp: UIComponent = *p
comp.Render()
def HitTest(self, px: int, py: int) -> UIComponent | t.CPtr:
def HitTest(self, px: int, py: int) -> UIComponent*:
i: int = self.component_count - 1
while i >= 0:
p: UIComponent | t.CPtr = self.components[i]
p: UIComponent* = self.components[i]
if p is not None:
comp: UIComponent = c.Deref(p)
comp: UIComponent = *p
if comp.visible == 1 and comp.Contains(px, py) == 1:
return p
i -= 1
+12 -17
View File
@@ -1,10 +1,9 @@
from stdint import *
import math
import string
import t, c
PI: t.CDefine = float(3.14159265358979323846)
define PI: float = 3.14159265358979323846
SPHERE_SLICES: t.CDefine = (24 * 1)
SPHERE_STACKS: t.CDefine = (16 * 1)
@@ -13,7 +12,6 @@ SIN_WAVE_GRID: t.CDefine = (40 * 1)
def COLOR_RGB(r: int, g: int, b: int) -> t.CInline | int:
return (255 << 24) | (r << 16) | (g << 8) | (b)
@t.Object
class Vec3:
x: float
y: float
@@ -33,17 +31,17 @@ class Vec3:
return Vec3(self.x / l, self.y / l, self.z / l)
class Mat4:
m: t.CArray[t.CArray[float, 4], 4]
m: [4][4]float
def Mat4_Identity() -> Mat4:
m: Mat4 = Mat4()
string.memset(c.Addr(m), 0, Mat4.__sizeof__())
string.memset(&m, 0, Mat4.__sizeof__())
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:
res: Mat4 = Mat4()
string.memset(c.Addr(res), 0, Mat4.__sizeof__())
string.memset(&res, 0, Mat4.__sizeof__())
for i in range(4):
for j in range(4):
for k in range(4):
@@ -61,7 +59,7 @@ def Mat4_MulVec(m: Mat4, v: Vec3) -> Vec3:
def Mat4_Perspective(fov: float, aspect: float, zn: float, zf: float) -> Mat4:
m: Mat4 = Mat4()
string.memset(c.Addr(m), 0, Mat4.__sizeof__())
string.memset(&m, 0, Mat4.__sizeof__())
f: float = float(1.0) / math.tanf(fov / float(2.0))
m.m[0][0] = f / aspect; m.m[1][1] = f
m.m[2][2] = zf / (zn - zf); m.m[2][3] = (zf * zn) / (zn - zf); m.m[3][2] = -1
@@ -90,26 +88,24 @@ def Mat4_RotateY(a: float) -> Mat4:
return m
@t.Object
class Surface:
fb: UINT32PTR
zb: float | t.CPtr
zb: float*
w: int
h: int
def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int):
def __init__(self, fb: UINT32PTR, zb: float*, w: int, h: int):
self.fb = fb
self.zb = zb
self.w = w
self.h = h
@t.Object
class Renderer:
_fb: UINT32PTR
_zb: float | t.CPtr
_zb: float*
_w: int
_h: int
def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int):
def __init__(self, fb: UINT32PTR, zb: float*, w: int, h: int):
self._fb = fb
self._zb = zb
self._w = w
@@ -117,7 +113,7 @@ class Renderer:
def Clear(self, color: uint32):
fb: UINT32PTR = self._fb
zb: float | t.CPtr = self._zb
zb: float* = self._zb
size: int = self._w * self._h
for i in range(size):
fb[i] = color
@@ -143,7 +139,7 @@ class Renderer:
v2.x > float(10.0) or v2.x < float(-10.0) or v2.y > float(10.0) or v2.y < float(-10.0)): return
fb: UINT32PTR = self._fb
zb: float | t.CPtr = self._zb
zb: float* = self._zb
w: int = self._w
h: int = self._h
@@ -217,11 +213,10 @@ class Renderer:
255 if (nb > 255) else nb)
@t.Object
class Scene3D:
renderer: Renderer
def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: int, h: int):
def __init__(self, fb: UINT32PTR, zb: float*, w: int, h: int):
self.renderer = Renderer(fb, zb, w, h)
def Render(self, time: float):
+42 -50
View File
@@ -1,25 +1,18 @@
import string # std: standard
#import math # std: standard
import t, c
# 颜色格式枚举
class __ColorFormat(t.CEnum):
ColorFormat_BGRA: t.State # BGRA格式(蓝色、绿色、红色、Alpha)
ColorFormat_RGBA: t.State # RGBA格式(红色、绿色、蓝色、Alpha)
ColorFormat_BGR: t.State # BGR格式(蓝色、绿色、红色)
ColorFormat_RGB: t.State # RGB格式(红色、绿色、蓝色)
enum __ColorFormat:
ColorFormat_BGRA, ColorFormat_RGBA
ColorFormat_BGR, ColorFormat_RGB
# 常量定义 - 提升代码可读性和可维护性
VGA_WIDTH: t.CDefine = 80
VGA_HEIGHT: t.CDefine = 25
FONT_WIDTH: t.CDefine = 8
FONT_HEIGHT: t.CDefine = 16
DEFAULT_CHAR: t.CDefine = 0 # 非ASCII字符的默认替换字符
SERIAL_PORT: t.CDefine = 0x3F8 # 串口调试端口地址
# 常量定义
define VGA_WIDTH = 80
define VGA_HEIGHT = 25
define FONT_WIDTH = 8
define FONT_HEIGHT = 16
define DEFAULT_CHAR = 0 # 非ASCII字符的默认替换字符
define SERIAL_PORT = 0x3F8 # 串口调试端口地址
# 8x16字符点阵字库 (每个字符16字节,共256个字符)
font: t.CArray[t.CArray[uint8, 16], 256] = [
font: [256][16]uint8 = [
# 字符编号 0x00 - 0x0F
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, # 0x00
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, # 0x01
@@ -309,24 +302,23 @@ font: t.CArray[t.CArray[uint8, 16], 256] = [
{0x66, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x3E, 0x06, 0x06, 0x7E, 0x7C, 0x00}, # 0xFF
]
@t.Object
class _VGAScreenDriver:
# 帧缓冲区信息
fbv: t.CPtr # = None
fb: t.CUnsignedChar | t.CPtr # = None
fbv: rawptr # = None
fb: uchar* # = None
fw: int # = 800
fh: int # = 600
fp: int # = 800 * 4 # 3200 800*4
ColorFormat: __ColorFormat # = __ColorFormat.ColorFormat_BGRA # 默认使用BGRA格式
BgColor: t.CUnsignedInt = 0xFF000080 # RGBA: 不透明深蓝色
BgColor: uint = 0xFF000080 # RGBA: 不透明深蓝色
# 初始化VGA驱动
def __init__(self, fb: t.CPtr, width: int, height: int, pitch: int, format: int):
def __init__(self, fb: uchar*, width: int, height: int, pitch: int, format: int):
# 先做参数合法性检查
if fb is None or width <= 0 or height <= 0 or pitch <= 0: return
# 更新帧缓冲区参数
self.fbv = fb
self.fb = t.CUnsignedChar(fb, t.CPtr)
self.fb = fb
self.fw = width
self.fh = height
self.fp = pitch
@@ -345,24 +337,24 @@ class _VGAScreenDriver:
# 检测硬件颜色格式 - 优化测试逻辑,避免误判
def DetectColorFormat(self):
if self.fb is None: return
fb: t.CUnsignedChar | t.CPtr = t.CUnsignedChar(self.fb, t.CPtr)
testX: int = 0
testY: int = 0
fb: uchar* = self.fb
testX: int = 0
testY: int = 0
offset: int = testY * self.fp + testX * 4
# 保存测试位置原始像素值,避免污染屏幕
OriginalPixel: uint32 = c.Deref(uint32(fb + offset, t.CPtr))
OriginalPixel: uint32 = *(uint32*(fb + offset))
# 写入测试颜色:青色 (RGBA逻辑值: 0xFF00FFFF)
fb[offset + 0] = 0xFF # B
fb[offset + 1] = 0xFF # G
fb[offset + 2] = 0x00 # R
fb[offset + 3] = 0xFF # A
# 读取回测试像素
b: t.CUnsignedChar = fb[offset + 0]
g: t.CUnsignedChar = fb[offset + 1]
r: t.CUnsignedChar = fb[offset + 2]
b: uchar = fb[offset + 0]
g: uchar = fb[offset + 1]
r: uchar = fb[offset + 2]
# t\.CVoid(fb[offset + 3]) # 忽略Alpha
# 恢复原始像素
c.Set(c.Deref(uint32(fb + offset, t.CPtr)), OriginalPixel)
*(uint32*(fb + offset)) = OriginalPixel
# 判定颜色格式
if r == 0x00 and g == 0xFF and b == 0xFF: self.ColorFormat = __ColorFormat.ColorFormat_BGRA
elif r == 0xFF and g == 0xFF and b == 0x00: self.ColorFormat = __ColorFormat.ColorFormat_RGBA
@@ -371,15 +363,15 @@ class _VGAScreenDriver:
# 设置像素颜色 - 统一接口,输入为RGBA逻辑颜色
# color格式: 0xAARRGGBB (Alpha, Red, Green, Blue)
def SetPixel(self, x: int, y: int, color: uint32):
fb: t.CUnsignedChar | t.CPtr = self.fb
fb: uchar* = self.fb
if fb is None: return
if x < 0 or x >= self.fw or y < 0 or y >= self.fh: return
offset: int = y * self.fp + x * 4
# 解析RGBA分量
r: t.CUnsignedChar = (color >> 16) & 0xFF
g: t.CUnsignedChar = (color >> 8) & 0xFF
b: t.CUnsignedChar = color & 0xFF
a: t.CUnsignedChar = (color >> 24) & 0xFF
r: uchar = (color >> 16) & 0xFF
g: uchar = (color >> 8) & 0xFF
b: uchar = color & 0xFF
a: uchar = (color >> 24) & 0xFF
# 根据硬件格式写入像素
match self.ColorFormat:
case __ColorFormat.ColorFormat_BGRA:
@@ -409,19 +401,19 @@ class _VGAScreenDriver:
# 清除屏幕 - 优化循环效率,减少函数调用开销
def ClearScreen(self, color: uint32):
fb: t.CUnsignedChar | t.CPtr = self.fb
fb: uchar* = self.fb
fp: int = self.fp
if fb is None: return
PixelSize: int = 3 if self.ColorFormat == __ColorFormat.ColorFormat_BGR or self.ColorFormat == __ColorFormat.ColorFormat_RGB else 4
RowSize: int = self.fw * PixelSize
# 解析清除颜色的RGBA分量
r: t.CUnsignedChar = (color >> 16) & 0xFF
g: t.CUnsignedChar = (color >> 8 ) & 0xFF
b: t.CUnsignedChar = (color) & 0xFF
a: t.CUnsignedChar = (color >> 24) & 0xFF
r: uchar = (color >> 16) & 0xFF
g: uchar = (color >> 8 ) & 0xFF
b: uchar = (color) & 0xFF
a: uchar = (color >> 24) & 0xFF
# 逐行填充,比逐像素调用SetPixel快得多
for y in range(self.fh):
row_ptr: t.CUnsignedChar | t.CPtr = fb + y * fp
row_ptr: uchar* = fb + y * fp
for x in range(self.fw):
offset: int = x * PixelSize
match self.ColorFormat:
@@ -444,25 +436,25 @@ class _VGAScreenDriver:
row_ptr[offset + 1] = g
row_ptr[offset + 2] = b
def Print(self, x: int, y: int, s: str, fontcolor: t.CUnsignedInt = 0xFFFFFFFF, size: int = 16):
def Print(self, x: int, y: int, s: str, fontcolor: uint = 0xFFFFFFFF, size: int = 16):
self.PrintColor(x, y, s, fontcolor, 0x00000000, size)
def PutcharColor(self, x: int, y: int, cr: t.CChar, fontcolor: t.CUnsignedInt = 0xFFFFFFFF, bgcolor: t.CUnsignedInt = 0x00000000, size: int = 16):
def PutcharColor(self, x: int, y: int, cr: char, fontcolor: uint = 0xFFFFFFFF, bgcolor: uint = 0x00000000, size: int = 16):
fw: int = self.fw
fh: int = self.fh
fb: t.CUnsignedChar | t.CPtr = self.fb
fb: uchar* = self.fb
if fb is None: return
# 提前判断字符整体是否越界(8x16),避免内层循环冗余检查
if x < 0 or y < 0 or (x + FONT_WIDTH) > fw or (y + FONT_HEIGHT) > fh: return
# 处理字符范围,非ASCII字符替换为默认字符
ch: t.CUnsignedChar = t.CUnsignedChar(cr)
ch: uchar = uchar(cr)
if ch >= 128: ch = DEFAULT_CHAR
# 预解析背景色Alpha,避免内层循环重复计算
bg_alpha: uint8 = (bgcolor >> 24) & 0xFF
draw_bg: int = (bg_alpha != 0) # 背景是否需要绘制
# 渲染8x16点阵字符
for fy in range(FONT_HEIGHT):
row: t.CUnsignedChar = font[ch][fy]
row: uchar = font[ch][fy]
for fx in range(FONT_WIDTH):
px: int = x + fx
py: int = y + fy
@@ -475,10 +467,10 @@ class _VGAScreenDriver:
self.SetPixel(px, py, bgcolor)
# 在指定位置显示带颜色和字号的字符串
def PrintColor(self, x: int, y: int, s: str, fontcolor: t.CUnsignedInt = 0xFFFFFFFF, bgcolor: t.CUnsignedInt = 0x00000000, size: int = 16):
def PrintColor(self, x: int, y: int, s: str, fontcolor: uint = 0xFFFFFFFF, bgcolor: uint = 0x00000000, size: int = 16):
fw: int = self.fw
fh: int = self.fh
# fb: t.CUnsignedChar | t.CPtr = self.fb
# fb: uchar* = self.fb
currentX: int = x
currentY: int = y
if s is None: return
+194 -197
View File
@@ -7,53 +7,51 @@ import paging.paging as paging
import sched.process as proc
import sched.sched as sched
import intr.gdt as gdt
import t, c
import viperlib
import string
import asm
# Do NOT import KERN_STACK_SIZE/USER_STACK_SIZE from process - CDefine cross-module import is broken
# Redefine them here to ensure correct values
KERN_STACK_SIZE: t.CDefine = 8192
USER_STACK_SIZE: t.CDefine = 65536
import viperlib
import string
import asm
import t, c
define KERN_STACK_SIZE = 8192
define USER_STACK_SIZE = 65536
ELFMAG0: t.CDefine = 0x7F
ELFMAG1: t.CDefine = 0x45
ELFMAG2: t.CDefine = 0x4C
ELFMAG3: t.CDefine = 0x46
ELFCLASS64: t.CDefine = 2
ELFDATA2LSB: t.CDefine = 1
ET_EXEC: t.CDefine = 2
ET_DYN: t.CDefine = 3
EM_X86_64: t.CDefine = 62
PT_LOAD: t.CDefine = 1
PT_DYNAMIC: t.CDefine = 2
PF_X: t.CDefine = 1
PF_W: t.CDefine = 2
PF_R: t.CDefine = 4
DT_NULL: t.CDefine = 0
DT_HASH: t.CDefine = 4
DT_STRTAB: t.CDefine = 5
DT_SYMTAB: t.CDefine = 6
DT_STRSZ: t.CDefine = 10
DT_SYMENT: t.CDefine = 11
DT_RELA: t.CDefine = 7
DT_RELASZ: t.CDefine = 8
DT_RELAENT: t.CDefine = 9
DT_PLTRELSZ: t.CDefine = 2
DT_JMPREL: t.CDefine = 23
R_X86_64_64: t.CDefine = 1
R_X86_64_GLOB_DAT: t.CDefine = 6
R_X86_64_JUMP_SLOT: t.CDefine = 7
R_X86_64_RELATIVE: t.CDefine = 8
STB_GLOBAL: t.CDefine = 1
STB_WEAK: t.CDefine = 2
define ELFMAG0 = 0x7F
define ELFMAG1 = 0x45
define ELFMAG2 = 0x4C
define ELFMAG3 = 0x46
define ELFCLASS64 = 2
define ELFDATA2LSB = 1
define ET_EXEC = 2
define ET_DYN = 3
define EM_X86_64 = 62
define PT_LOAD = 1
define PT_DYNAMIC = 2
define PF_X = 1
define PF_W = 2
define PF_R = 4
define DT_NULL = 0
define DT_HASH = 4
define DT_STRTAB = 5
define DT_SYMTAB = 6
define DT_STRSZ = 10
define DT_SYMENT = 11
define DT_RELA = 7
define DT_RELASZ = 8
define DT_RELAENT = 9
define DT_PLTRELSZ = 2
define DT_JMPREL = 23
define R_X86_64_64 = 1
define R_X86_64_GLOB_DAT = 6
define R_X86_64_JUMP_SLOT = 7
define R_X86_64_RELATIVE = 8
define STB_GLOBAL = 1
define STB_WEAK = 2
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Ehdr:
e_ident: t.CArray[uint8, 16]
e_ident: [16]uint8
e_type: uint16
e_machine: uint16
e_version: uint32
@@ -68,7 +66,7 @@ class Elf64_Ehdr:
e_shnum: uint16
e_shstrndx: uint16
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Phdr:
p_type: uint32
p_flags: uint32
@@ -79,9 +77,9 @@ class Elf64_Phdr:
p_memsz: uint64
p_align: uint64
MAX_PHDRS: t.CDefine = 16
define MAX_PHDRS = 16
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Shdr:
sh_name: uint32
sh_type: uint32
@@ -94,7 +92,7 @@ class Elf64_Shdr:
sh_addralign: uint64
sh_entsize: uint64
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Sym:
st_name: uint32
st_info: uint8
@@ -103,64 +101,64 @@ class Elf64_Sym:
st_value: uint64
st_size: uint64
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Rela:
r_offset: uint64
r_info: uint64
r_addend: int64
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class Elf64_Dyn:
d_tag: int64
d_val: uint64
MAX_SHDRS: t.CDefine = 64
MAX_DYNS: t.CDefine = 64
MAX_RELAS: t.CDefine = 256
define MAX_SHDRS = 64
define MAX_DYNS = 64
define MAX_RELAS = 256
def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ)
def load_elf(path: const str, do_map: int = 1) -> rawptr:
fp: fat32_types.fileobj* = fat32.open(path, fat32_types.FA_READ)
if fp is None:
err: uint32 = fat32.last_error()
eb: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(eb), 64, "[elf] failed to open file err=%d\n", err)
eb: [64]char
viperlib.snprintf(&eb, 64, "[elf] failed to open file err=%d\n", err)
serial.puts(eb)
return None
ehdr_buf: t.CArray[uint8, 64]
string.memset(c.Addr(ehdr_buf), 0, 64)
read_len: uint32 = fat32.read(fp, c.Addr(ehdr_buf), 64)
ehdr_buf: [64]uint8
string.memset(&ehdr_buf, 0, 64)
read_len: uint32 = fat32.read(fp, &ehdr_buf, 64)
# [DIAG] read_len 实际值 + call 后 RAX 快照:区分"call 返回错"(rl=0 rax=0)
# vs "store 后 RAX 被覆盖"(rl=0 rax=64)
_rax_v2: uint64 = 0
# 读 RAX 未声明输入:至少须声明 CLOBBER_RAX,让编译器知道本块不保留
# RAX(此前只声明 ~{memory},编译器可假设 RAX 存活 → 读到的值不保证是
# 紧邻 call 的返回值)。N16。(本块为 [DIAG] 探针,问题定位后建议删除。)
c.Asm(f"""mov {c.AsmOut(_rax_v2, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
_dbrl: t.CArray[t.CChar, 96]
viperlib.snprintf(c.Addr(_dbrl), 96, "[elf] rl=%lu rax=0x%lx\n", read_len, _rax_v2)
serial.puts(c.Addr(_dbrl))
__asm__(f"""mov {asmout(_rax_v2, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
_dbrl: [96]char
viperlib.snprintf(&_dbrl, 96, "[elf] rl=%lu rax=0x%lx\n", read_len, _rax_v2)
serial.puts(&_dbrl)
if read_len < 64:
serial.puts("[elf] failed to read ehdr\n")
fat32.close(fp)
return None
ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf)
ehdr: Elf64_Ehdr* = &ehdr_buf
if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3:
serial.puts("[elf] bad magic\n")
# [DIAG] 一次性定位 bad magic:dump ehdr_buf 前 16 字节 + read_len,
# 区分全 0(read 未写)/ 目录数据(sector 错)/ 垃圾(seek 或缓冲错)。
_dbg_mg: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbg_mg), 120,
_dbg_mg: [120]char
viperlib.snprintf(&_dbg_mg, 120,
"[elf] mg=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu fp=%lu/%lu/%lu/%lu\n",
ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3],
ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7],
ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11],
ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15],
read_len, fp.first_cluster, fp.current_cluster, fp.file_pos, fp.file_size)
serial.puts(c.Addr(_dbg_mg))
serial.puts(&_dbg_mg)
fat32.close(fp)
return None
@@ -182,15 +180,15 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
if ehdr.e_machine != EM_X86_64:
serial.puts("[elf] not x86_64\n")
# [DIAG] e_machine 错:dump ehdr 前 24 字节(read_len=64 正确但内容错)
_dbg_em: t.CArray[t.CChar, 128]
viperlib.snprintf(c.Addr(_dbg_em), 128,
_dbg_em: [128]char
viperlib.snprintf(&_dbg_em, 128,
"[elf] ehdr=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x rl=%lu\n",
ehdr_buf[0], ehdr_buf[1], ehdr_buf[2], ehdr_buf[3],
ehdr_buf[4], ehdr_buf[5], ehdr_buf[6], ehdr_buf[7],
ehdr_buf[8], ehdr_buf[9], ehdr_buf[10], ehdr_buf[11],
ehdr_buf[12], ehdr_buf[13], ehdr_buf[14], ehdr_buf[15],
ehdr_buf[16], ehdr_buf[17], ehdr_buf[18], ehdr_buf[19], read_len)
serial.puts(c.Addr(_dbg_em))
serial.puts(&_dbg_em)
fat32.close(fp)
return None
@@ -204,17 +202,17 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
fat32.close(fp)
return None
cr: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(cr), 80, "[elf] entry=0x%lx phoff=%lu phentsize=%u phnum=%u\n", entry_point, phoff, phentsize, phnum)
cr: [80]char
viperlib.snprintf(&cr, 80, "[elf] entry=0x%lx phoff=%lu phentsize=%u phnum=%u\n", entry_point, phoff, phentsize, phnum)
serial.puts(cr)
phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS]
string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56)
phdr_bufs: [MAX_PHDRS]Elf64_Phdr
string.memset(&phdr_bufs, 0, MAX_PHDRS * 56)
for pi in range(phnum):
phdr_off: uint64 = phoff + uint64(pi) * uint64(phentsize)
fat32.seek(fp, uint32(phdr_off))
fat32.read(fp, c.Addr(phdr_bufs[pi]), 56)
fat32.read(fp, &phdr_bufs[pi], 56)
found_load: int = 0
lowest_vaddr: uint64 = 0
@@ -240,13 +238,13 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
total_memsz: uint64 = highest_vaddr_end - lowest_vaddr
total_pages: uint64 = (total_memsz + 0xFFF) // 0x1000
cr2: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(cr2), 80, "[elf] vaddr 0x%lx-0x%lx pages=%lu\n", lowest_vaddr, highest_vaddr_end, total_pages)
cr2: [80]char
viperlib.snprintf(&cr2, 80, "[elf] vaddr 0x%lx-0x%lx pages=%lu\n", lowest_vaddr, highest_vaddr_end, total_pages)
serial.puts(cr2)
raw_alloc: t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000)
_db_ra: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(_db_ra), 80, "[elf] malloc ret raw_alloc=0x%lx\n", uint64(raw_alloc))
raw_alloc: rawptr = mm.malloc(total_pages * 0x1000 + 0x1000)
_db_ra: [80]char
viperlib.snprintf(&_db_ra, 80, "[elf] malloc ret raw_alloc=0x%lx\n", uint64(raw_alloc))
serial.puts(_db_ra)
if not raw_alloc:
serial.puts("[elf] malloc failed\n")
@@ -254,7 +252,7 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
return None
phys_base_aligned: uint64 = (uint64(raw_alloc) + uint64(0xFFF)) & ~uint64(0xFFF)
phys_base: t.CPtr = t.CPtr(phys_base_aligned)
phys_base: rawptr = rawptr(phys_base_aligned)
string.memset(phys_base, 0, total_pages * 0x1000)
@@ -265,14 +263,14 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
filesz: uint64 = phdr_bufs[pi].p_filesz
memsz: uint64 = phdr_bufs[pi].p_memsz
dest_off: uint64 = vaddr - lowest_vaddr
dest: t.CPtr = t.CPtr(uint64(phys_base) + dest_off)
dest: rawptr = rawptr(uint64(phys_base) + dest_off)
if filesz > 0:
fat32.seek(fp, uint32(file_off))
fat32.read(fp, dest, uint32(filesz))
if memsz > filesz:
bss_start: t.CPtr = t.CPtr(uint64(dest) + filesz)
bss_start: rawptr = rawptr(uint64(dest) + filesz)
bss_len: uint64 = memsz - filesz
string.memset(bss_start, 0, bss_len)
@@ -296,32 +294,32 @@ def load_elf(path: t.CConst | str, do_map: int = 1) -> t.CPtr:
page_flags: uint64 = paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER
paging.MapPage(virt_addr, phys_addr, page_flags)
entry_addr: t.CPtr = t.CPtr(entry_point)
entry_addr: rawptr = rawptr(entry_point)
return entry_addr
def run_elf(path: t.CConst | str) -> int:
entry: t.CPtr = load_elf(path)
def run_elf(path: const str) -> int:
entry: rawptr = load_elf(path)
if entry is None:
serial.puts("[elf] load failed\n")
return -1
serial.puts("[elf] jumping to entry...\n")
# 被调方是任意 ELF 入口(外部代码):`call` 破坏全部 caller-saved 寄存器,
# 除 rax/rcx/rdx/r8~r11 外必须声明 rsi/rdi(N20)。
c.Asm(f"""call {c.AsmInp(entry, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(entry, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
serial.puts("[elf] returned from entry\n")
return 0
MAX_SPAWNED: t.CDefine = 8
_elf_entries: t.CArray[t.CPtr, MAX_SPAWNED]
define MAX_SPAWNED = 8
_elf_entries: [MAX_SPAWNED]rawptr
# User stack virtual address: top of 48-bit user space, 64KB below
USER_STACK_VTOP: t.CDefine = 0x7FFFFFE00000
define USER_STACK_VTOP = 0x7FFFFFE00000
# Globals for ELF mapping info (set by load_elf when do_map=0, used by spawn_elf
# to map ELF pages in the cloned PML4 instead of kernel PML4).
@@ -332,26 +330,26 @@ USER_STACK_VTOP: t.CDefine = 0x7FFFFFE00000
# in the cloned PML4 after clone_for_process.
_last_elf_phys_page_start: uint64 = 0
_last_elf_virt_page_start: uint64 = 0
_last_elf_num_map_pages: uint64 = 0
_last_elf_num_map_pages: uint64 = 0
def _elf_entry_wrapper(arg: t.CPtr) -> int:
def _elf_entry_wrapper(arg: rawptr) -> int:
pid: int = int(uint64(arg))
_db1: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(_db1), 64, "[elf] wrapper pid=%d\n", pid)
_db1: [64]char
viperlib.snprintf(&_db1, 64, "[elf] wrapper pid=%d\n", pid)
serial.puts(_db1)
# Disable interrupts around switch_pid + MapPage + TSS setup: @pml4 is a global
# that switch_pid modifies. A timer interrupt mid-section would make the scheduler
# call switch_pid for another thread, corrupting @pml4 for our MapPage calls.
asm.cli()
proc.switch_pid(pid)
cur_p: proc.Process | t.CPtr = proc.ProcessManager.current()
entry_fn: t.CPtr = cur_p.entry
cur_p: proc.Process* = proc.ProcessManager.current()
entry_fn: rawptr = cur_p.entry
# [DIAG] 定位用户进程首个指令 PF:打印 entry 实际值(PF cr2=ELF 物理区最后一页,
# 疑似 entry 被写成 phys 地址而非虚拟 0x400000)。
_dbw: t.CArray[t.CChar, 160]
viperlib.snprintf(c.Addr(_dbw), 160, "[wrap] pid=%d cur=0x%lx ent=0x%lx ebase=0x%lx ks=0x%lx us=0x%lx\n",
_dbw: [160]char
viperlib.snprintf(&_dbw, 160, "[wrap] pid=%d cur=0x%lx ent=0x%lx ebase=0x%lx ks=0x%lx us=0x%lx\n",
pid, uint64(cur_p), uint64(entry_fn), cur_p.elf_base, cur_p.kern_stack, cur_p.user_stack)
serial.puts(c.Addr(_dbw))
serial.puts(&_dbw)
if entry_fn is not None:
user_stack_vtop: uint64 = USER_STACK_VTOP
us_sz: uint64 = USER_STACK_SIZE
@@ -375,47 +373,46 @@ def _elf_entry_wrapper(arg: t.CPtr) -> int:
# This prevents timer interrupt preemption between TSS setup and iretq.
# Drop to Ring 3 user mode via iretq
proc.drop_to_user_mode(entry_fn, user_stack_vtop, cur_p.kern_stack)
cur: proc.Process | t.CPtr = proc.ProcessManager.current()
cur: proc.Process* = proc.ProcessManager.current()
cur.exit()
return 0
def spawn_elf(path: t.CConst | str) -> int:
def spawn_elf(path: const str) -> int:
fat32.lock()
name_start: int = 0
si: int = 0
while True:
ch: t.CChar = path[si]
if ch == 0: break
if ch == 47:
name_start = si + 1
ch: char = path[si]
if ch == 0: break
if ch == 47: name_start = si + 1
si += 1
lowest_vaddr: uint64 = 0
highest_vaddr_end: uint64 = 0
fp_scan: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ)
fp_scan: fat32_types.fileobj* = fat32.open(path, fat32_types.FA_READ)
if fp_scan is None:
serr: uint32 = fat32.last_error()
seb: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(seb), 64, "[elf] spawn scan open failed err=%d\n", serr)
serial.puts(seb)
seb: [64]char
viperlib.snprintf(&seb, 64, "[elf] spawn scan open failed err=%d\n", serr)
serial.puts(&seb)
fat32.unlock()
return -1
if fp_scan is not None:
ehdr_buf_s: t.CArray[uint8, 64]
string.memset(c.Addr(ehdr_buf_s), 0, 64)
fat32.read(fp_scan, c.Addr(ehdr_buf_s), 64)
ehdr_s: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf_s)
ehdr_buf_s: [64]uint8
string.memset(&ehdr_buf_s, 0, 64)
fat32.read(fp_scan, &ehdr_buf_s, 64)
ehdr_s: Elf64_Ehdr* = &ehdr_buf_s
if ehdr_s.e_type == ET_EXEC or ehdr_s.e_type == ET_DYN:
phoff_s: uint64 = ehdr_s.e_phoff
phentsize_s: uint16 = ehdr_s.e_phentsize
phnum_s: uint16 = ehdr_s.e_phnum
if phentsize_s > 0 and phnum_s > 0 and phnum_s <= MAX_PHDRS:
phdr_bufs_s: t.CArray[Elf64_Phdr, MAX_PHDRS]
string.memset(c.Addr(phdr_bufs_s), 0, MAX_PHDRS * 56)
phdr_bufs_s: [MAX_PHDRS]Elf64_Phdr
string.memset(&phdr_bufs_s, 0, MAX_PHDRS * 56)
found_load_s: int = 0
for pi_s in range(phnum_s):
fat32.seek(fp_scan, uint32(phoff_s + uint64(pi_s) * uint64(phentsize_s)))
fat32.read(fp_scan, c.Addr(phdr_bufs_s[pi_s]), 56)
fat32.read(fp_scan, &phdr_bufs_s[pi_s], 56)
if phdr_bufs_s[pi_s].p_type == PT_LOAD:
seg_end_s: uint64 = phdr_bufs_s[pi_s].p_vaddr + phdr_bufs_s[pi_s].p_memsz
if found_load_s == 0:
@@ -437,7 +434,7 @@ def spawn_elf(path: t.CConst | str) -> int:
# do_map=0: load_elf stores mapping info in globals for spawn_elf to use.
# ROOT CAUSE FIX: previously load_elf mapped ELF vaddr (e.g. 0x400000) into
# kernel PML4, overwriting identity mapping of buddy memory_block headers.
entry: t.CPtr = load_elf(path, 0)
entry: rawptr = load_elf(path, 0)
if entry is None:
serial.puts("[elf] spawn: load failed\n")
fat32.unlock()
@@ -445,9 +442,9 @@ def spawn_elf(path: t.CConst | str) -> int:
# Clone kernel PML4 (identity mapping intact, no ELF mapping yet)
proc_pml4: uint64 = paging.clone_for_process(isolate_va)
slog1: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(slog1), 80, "[elf] spawn: clone pml4=0x%lx va=0x%lx\n", proc_pml4, isolate_va)
serial.puts(slog1)
slog1: [80]char
viperlib.snprintf(&slog1, 80, "[elf] spawn: clone pml4=0x%lx va=0x%lx\n", proc_pml4, isolate_va)
serial.puts(&slog1)
if proc_pml4 == 0:
serial.puts("[elf] spawn: clone_for_process failed\n")
fat32.unlock()
@@ -460,22 +457,22 @@ def spawn_elf(path: t.CConst | str) -> int:
# interrupt mid-section would call switch_pid, corrupting @pml4.
asm.cli()
_kernel_cr3: uint64 = 0
c.Asm(f"""mov {c.AsmOut(_kernel_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3""", op=[t.ASM_DESCR.CLOBBER_MEMORY])
c.Asm(f"mov cr3, {c.AsmInp(proc_pml4, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"""mov {asmout(_kernel_cr3, ASM_DESCR.OUTPUT_REG)}, cr3""", op=[ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"mov cr3, {asminp(proc_pml4, ASM_DESCR.REG_ANY)}", op=[ASM_DESCR.CLOBBER_MEMORY])
paging.set_active_pml4(proc_pml4)
mi: uint64
for mi in range(_last_elf_num_map_pages):
_va: uint64 = _last_elf_virt_page_start + mi * 0x1000
_pa: uint64 = _last_elf_phys_page_start + mi * 0x1000
paging.MapPage(_va, _pa, paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER)
c.Asm(f"mov cr3, {c.AsmInp(_kernel_cr3, t.ASM_DESCR.REG_ANY)}", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"mov cr3, {asminp(_kernel_cr3, ASM_DESCR.REG_ANY)}", op=[ASM_DESCR.CLOBBER_MEMORY])
paging.set_active_pml4(_kernel_cr3)
asm.sti()
# path[name_start:] 切片表达式 translate_subscript 不支持 Slice(返回 None)→
# 作为实参丢 name、entry 错位成第一参数(TPV 已修,此处指针算术双保险)
nm_ptr: t.CConst | t.CChar | t.CPtr = t.CConst(uint64(path) + uint64(name_start), t.CPtr)
p: proc.Process | t.CPtr = proc.ProcessManager.create_process(nm_ptr, entry)
nm_ptr: const str = str(uint64(path) + uint64(name_start))
p: proc.Process* = proc.ProcessManager.create_process(nm_ptr, entry)
if p is None:
serial.puts("[elf] spawn: create_process failed\n")
fat32.unlock()
@@ -485,7 +482,7 @@ def spawn_elf(path: t.CConst | str) -> int:
if p.pid >= 0 and p.pid < MAX_SPAWNED:
_elf_entries[p.pid] = entry
th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(t.CPtr(_elf_entry_wrapper), t.CPtr(uint64(p.pid)), p.pid)
th: sched.Thread* = sched.Scheduler.create_thread(&_elf_entry_wrapper, rawptr(uint64(p.pid)), p.pid)
if th is None:
serial.puts("[elf] spawn: create_thread failed\n")
p.exit()
@@ -493,26 +490,26 @@ def spawn_elf(path: t.CConst | str) -> int:
return -3
tid: int = th.tid
p.addThread(tid)
slog: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(slog), 80, "[elf] spawn: pid=%d tid=%d entry=0x%lx pml4=0x%lx\n", p.pid, tid, uint64(entry), p.pml4_root)
serial.puts(slog)
slog: [80]char
viperlib.snprintf(&slog, 80, "[elf] spawn: pid=%d tid=%d entry=0x%lx pml4=0x%lx\n", p.pid, tid, uint64(entry), p.pml4_root)
serial.puts(&slog)
# [DIAG] 确认 return p.pid 的实际值(main 收到 pid=0 而此处打印 3)
_dbw2: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(_dbw2), 64, "[elf] spawn ret pid=%d\n", p.pid)
serial.puts(c.Addr(_dbw2))
_dbw2: [64]char
viperlib.snprintf(&_dbw2, 64, "[elf] spawn ret pid=%d\n", p.pid)
serial.puts(&_dbw2)
fat32.unlock()
return p.pid
def _resolve_symbol(name: t.CConst | t.CChar | t.CPtr) -> t.CPtr:
def _resolve_symbol(name: const str) -> rawptr:
nm: int = 0
while c.Deref(name + nm) != 0:
while name[nm] != 0:
nm += 1
cmp_name: t.CConst | t.CChar | t.CPtr = name
cmp_name: const str = name
cmp_len: int = nm
if nm > 9:
sha1_len2: int = 0
for si2 in range(nm):
ch2: t.CChar = c.Deref(name + si2)
ch2: char = name[si2]
if ch2 == 46:
if sha1_len2 >= 8:
cmp_name = str(uint64(name) + si2 + 1)
@@ -527,35 +524,35 @@ def _resolve_symbol(name: t.CConst | t.CChar | t.CPtr) -> t.CPtr:
if cmp_len == 11:
match: int = 1
for i in range(cmp_len):
if c.Deref(cmp_name + i) != c.Deref("serial_puts" + i):
if cmp_name[i] != "serial_puts"[i]:
match = 0
if match:
return c.Addr(serial.puts)
return &serial.puts
return None
_so_strtab: t.CPtr
_so_symtab: t.CPtr
_so_strtab: rawptr
_so_symtab: rawptr
_so_syment: uint64
_so_sym_count: int
def load_so(path: t.CConst | str) -> t.CPtr:
def load_so(path: const str) -> rawptr:
fat32.lock()
fp: fat32_types.fileobj | t.CPtr = fat32.open(path, fat32_types.FA_READ)
fp: fat32_types.fileobj* = fat32.open(path, fat32_types.FA_READ)
if fp is None:
serial.puts("[so] failed to open file\n")
fat32.unlock()
return None
ehdr_buf: t.CArray[uint8, 64]
string.memset(c.Addr(ehdr_buf), 0, 64)
read_len: uint32 = fat32.read(fp, c.Addr(ehdr_buf), 64)
ehdr_buf: [64]uint8
string.memset(&ehdr_buf, 0, 64)
read_len: uint32 = fat32.read(fp, &ehdr_buf, 64)
if read_len < 64:
serial.puts("[so] failed to read ehdr\n")
fat32.close(fp)
fat32.unlock()
return None
ehdr: Elf64_Ehdr | t.CPtr = c.Addr(ehdr_buf)
ehdr: Elf64_Ehdr* = &ehdr_buf
if ehdr.e_ident[0] != ELFMAG0 or ehdr.e_ident[1] != ELFMAG1 or ehdr.e_ident[2] != ELFMAG2 or ehdr.e_ident[3] != ELFMAG3:
serial.puts("[so] bad magic\n")
fat32.close(fp)
@@ -588,12 +585,12 @@ def load_so(path: t.CConst | str) -> t.CPtr:
fat32.unlock()
return None
phdr_bufs: t.CArray[Elf64_Phdr, MAX_PHDRS]
string.memset(c.Addr(phdr_bufs), 0, MAX_PHDRS * 56)
phdr_bufs: [MAX_PHDRS]Elf64_Phdr
string.memset(&phdr_bufs, 0, MAX_PHDRS * 56)
for pi in range(phnum):
phdr_off: uint64 = phoff + uint64(pi) * uint64(phentsize)
fat32.seek(fp, uint32(phdr_off))
fat32.read(fp, c.Addr(phdr_bufs[pi]), 56)
fat32.read(fp, &phdr_bufs[pi], 56)
found_load: int = 0
lowest_vaddr: uint64 = 0
@@ -621,7 +618,7 @@ def load_so(path: t.CConst | str) -> t.CPtr:
total_pages: uint64 = (total_memsz + 0xFFF) // 0x1000
so_load_addr: uint64 = 0x600000
raw_alloc: t.CPtr = mm.malloc(total_pages * 0x1000 + 0x1000)
raw_alloc: rawptr = mm.malloc(total_pages * 0x1000 + 0x1000)
if not raw_alloc:
serial.puts("[so] malloc failed\n")
fat32.close(fp)
@@ -629,7 +626,7 @@ def load_so(path: t.CConst | str) -> t.CPtr:
return None
phys_base_aligned: uint64 = (uint64(raw_alloc) + 0xFFF) & ~uint64(0xFFF)
phys_base: t.CPtr = t.CPtr(phys_base_aligned)
phys_base: rawptr = rawptr(phys_base_aligned)
string.memset(phys_base, 0, total_pages * 0x1000)
for pi in range(phnum):
@@ -639,12 +636,12 @@ def load_so(path: t.CConst | str) -> t.CPtr:
filesz: uint64 = phdr_bufs[pi].p_filesz
memsz: uint64 = phdr_bufs[pi].p_memsz
dest_off: uint64 = vaddr - lowest_vaddr
dest: t.CPtr = t.CPtr(uint64(phys_base) + dest_off)
dest: rawptr = rawptr(uint64(phys_base) + dest_off)
if filesz > 0:
fat32.seek(fp, uint32(file_off))
fat32.read(fp, dest, uint32(filesz))
if memsz > filesz:
bss_start: t.CPtr = t.CPtr(uint64(dest) + filesz)
bss_start: rawptr = rawptr(uint64(dest) + filesz)
bss_len: uint64 = memsz - filesz
string.memset(bss_start, 0, bss_len)
@@ -660,8 +657,8 @@ def load_so(path: t.CConst | str) -> t.CPtr:
base_vaddr: uint64 = so_load_addr + lowest_vaddr
dyn_buf: t.CArray[Elf64_Dyn, MAX_DYNS]
string.memset(c.Addr(dyn_buf), 0, MAX_DYNS * 16)
dyn_buf: [MAX_DYNS]Elf64_Dyn
string.memset(&dyn_buf, 0, MAX_DYNS * 16)
dyn_count: int = 0
for pi in range(phnum):
if phdr_bufs[pi].p_type == PT_DYNAMIC:
@@ -671,7 +668,7 @@ def load_so(path: t.CConst | str) -> t.CPtr:
max_dyn_bytes: uint32 = uint32(MAX_DYNS * 16)
if filesz_d > max_dyn_bytes:
filesz_d = max_dyn_bytes
dyn_read: uint32 = fat32.read(fp, c.Addr(dyn_buf), filesz_d)
dyn_read: uint32 = fat32.read(fp, &dyn_buf, filesz_d)
dyn_count = int(dyn_read) // 16
strtab_vaddr: uint64 = 0
@@ -693,51 +690,51 @@ def load_so(path: t.CConst | str) -> t.CPtr:
elif dyn_buf[di].d_tag == DT_JMPREL: jmprel_vaddr = dyn_buf[di].d_val
elif dyn_buf[di].d_tag == DT_PLTRELSZ: pltrelsz = dyn_buf[di].d_val
strtab_ptr: t.CPtr = t.CPtr(strtab_vaddr + so_load_addr)
symtab_ptr: t.CPtr = t.CPtr(symtab_vaddr + so_load_addr)
strtab_ptr: rawptr = rawptr(strtab_vaddr + so_load_addr)
symtab_ptr: rawptr = rawptr(symtab_vaddr + so_load_addr)
if rela_vaddr != 0 and relasz > 0:
rela_count: uint64 = relasz // 24
for ri in range(rela_count):
rela: Elf64_Rela | t.CPtr = t.CPtr(uint64(rela_vaddr) + so_load_addr + ri * 24)
rela: Elf64_Rela* = Elf64_Rela*(uint64(rela_vaddr) + so_load_addr + ri * 24)
r_type: uint32 = uint32(rela.r_info & 0xFFFFFFFF)
r_sym: uint32 = uint32(rela.r_info >> 32)
target_addr: t.CPtr = t.CPtr(rela.r_offset + so_load_addr)
target_addr: rawptr = rawptr(rela.r_offset + so_load_addr)
if r_type == R_X86_64_RELATIVE:
val: uint64 = uint64(rela.r_addend) + so_load_addr
string.memcpy(target_addr, c.Addr(val), 8)
string.memcpy(target_addr, &val, 8)
elif r_type == R_X86_64_64 or r_type == R_X86_64_GLOB_DAT or r_type == R_X86_64_JUMP_SLOT:
sym: Elf64_Sym | t.CPtr = t.CPtr(uint64(symtab_ptr) + uint64(r_sym) * syment)
sym_name: t.CConst | str = t.CPtr(uint64(strtab_ptr) + sym.st_name)
resolved: t.CPtr = _resolve_symbol(sym_name)
sym: Elf64_Sym* = Elf64_Sym*(uint64(symtab_ptr) + uint64(r_sym) * syment)
sym_name: const str = str(uint64(strtab_ptr) + sym.st_name)
resolved: rawptr = _resolve_symbol(sym_name)
if resolved is not None:
val2: uint64 = uint64(resolved) + uint64(rela.r_addend)
string.memcpy(target_addr, c.Addr(val2), 8)
string.memcpy(target_addr, &val2, 8)
elif sym.st_value != 0:
val3: uint64 = sym.st_value + so_load_addr + uint64(rela.r_addend)
string.memcpy(target_addr, c.Addr(val3), 8)
string.memcpy(target_addr, &val3, 8)
if jmprel_vaddr != 0 and pltrelsz > 0:
jmprel_count: uint64 = pltrelsz // 24
for ji in range(jmprel_count):
rela2: Elf64_Rela | t.CPtr = t.CPtr(jmprel_vaddr + so_load_addr + ji * 24)
rela2: Elf64_Rela* = Elf64_Rela*(jmprel_vaddr + so_load_addr + ji * 24)
r_type2: uint32 = uint32(rela2.r_info & 0xFFFFFFFF)
r_sym2: uint32 = uint32(rela2.r_info >> 32)
target2: t.CPtr = t.CPtr(rela2.r_offset + so_load_addr)
target2: rawptr = rawptr(rela2.r_offset + so_load_addr)
if r_type2 == R_X86_64_JUMP_SLOT or r_type2 == R_X86_64_GLOB_DAT:
sym2: Elf64_Sym | t.CPtr = t.CPtr(uint64(symtab_ptr) + uint64(r_sym2) * syment)
sym_name2: t.CConst | str = t.CPtr(uint64(strtab_ptr) + sym2.st_name)
resolved2: t.CPtr = _resolve_symbol(sym_name2)
sym2: Elf64_Sym* = Elf64_Sym*(uint64(symtab_ptr) + uint64(r_sym2) * syment)
sym_name2: const str = str(uint64(strtab_ptr) + sym2.st_name)
resolved2: rawptr = _resolve_symbol(sym_name2)
if resolved2 is not None:
val4: uint64 = uint64(resolved2) + uint64(rela2.r_addend)
string.memcpy(target2, c.Addr(val4), 8)
string.memcpy(target2, &val4, 8)
elif sym2.st_value != 0:
val5: uint64 = sym2.st_value + so_load_addr + uint64(rela2.r_addend)
string.memcpy(target2, c.Addr(val5), 8)
string.memcpy(target2, &val5, 8)
else:
cr3: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(cr3), 80, "[so] WARN: unresolved PLT sym offset=%lu\n", sym2.st_name)
serial.puts(cr3)
cr3: [80]char
viperlib.snprintf(&cr3, 80, "[so] WARN: unresolved PLT sym offset=%lu\n", sym2.st_name)
serial.puts(&cr3)
fat32.close(fp)
@@ -748,37 +745,37 @@ def load_so(path: t.CConst | str) -> t.CPtr:
_so_syment = syment
_so_sym_count = 0
if hash_vaddr != 0:
hash_ptr: t.CPtr = t.CPtr(hash_vaddr + so_load_addr)
# 宽度只由指针的元素类型决定:nchain 是 4 字节字段,必须给出 u32*
# (i8* 现在恒读 1 字节)。地址口径不变(hash_ptr + 4 字节)。
nchain: uint32 = c.Deref(uint32(uint64(hash_ptr) + 4, t.CPtr))
hash_ptr: rawptr = rawptr(hash_vaddr + so_load_addr)
# 宽度只由指针的元素类型决定:nchain 是 4 字节字段,必须给出 u32*
# (i8* 现在恒读 1 字节)。地址口径不变(hash_ptr + 4 字节)。
nchain: uint32 = *(uint32*(uint64(hash_ptr) + 4))
_so_sym_count = int(nchain)
elif syment > 0 and strtab_vaddr > symtab_vaddr and symtab_vaddr != 0:
sym_tab_size: uint64 = strtab_vaddr - symtab_vaddr
_so_sym_count = int(sym_tab_size // syment)
cr: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(cr), 80, "[so] loaded at 0x%lx\n", base_vaddr)
cr: [80]char
viperlib.snprintf(&cr, 80, "[so] loaded at 0x%lx\n", base_vaddr)
serial.puts(cr)
fat32.unlock()
return t.CPtr(base_vaddr)
return rawptr(base_vaddr)
def get_so_symbol(so_base: t.CPtr, name: t.CConst | str, so_path: t.CConst | t.CChar | t.CPtr) -> t.CPtr:
def get_so_symbol(so_base: rawptr, name: const str, so_path: const str) -> rawptr:
if _so_symtab is None or _so_strtab is None or _so_syment == 0:
return None
if name is None:
return None
for symi in range(_so_sym_count):
sb2: Elf64_Sym | t.CPtr = t.CPtr(uint64(_so_symtab) + uint64(symi) * _so_syment)
sb2: Elf64_Sym* = Elf64_Sym*(uint64(_so_symtab) + uint64(symi) * _so_syment)
if sb2.st_value != 0 and sb2.st_shndx != 0:
sym_name_off2: uint32 = sb2.st_name
cmp_off2: uint32 = sym_name_off2
match2: int = 0
ni2: int = 0
while True:
sc3: t.CChar = c.Deref(t.CPtr(uint64(_so_strtab) + cmp_off2 + ni2))
nc3: t.CChar = c.Deref(name + ni2)
sc3: char = *(char*(uint64(_so_strtab) + cmp_off2 + ni2))
nc3: char = *(name + ni2)
if sc3 != nc3:
break
if sc3 == 0:
@@ -790,7 +787,7 @@ def get_so_symbol(so_base: t.CPtr, name: t.CConst | str, so_path: t.CConst | t.C
is_sha1_2: int = 0
sha1_len_2: uint32 = 0
while True:
dc4: t.CChar = c.Deref(t.CPtr(uint64(_so_strtab) + dot_pos3))
dc4: char = *(char*(uint64(_so_strtab) + dot_pos3))
if dc4 == 46:
if sha1_len_2 >= 8:
is_sha1_2 = 1
@@ -807,8 +804,8 @@ def get_so_symbol(so_base: t.CPtr, name: t.CConst | str, so_path: t.CConst | t.C
match2 = 1
ni2 = 0
while True:
sc4: t.CChar = c.Deref(t.CPtr(uint64(_so_strtab) + cmp_off2 + ni2))
nc4: t.CChar = c.Deref(name + ni2)
sc4: char = *(char*(uint64(_so_strtab) + cmp_off2 + ni2))
nc4: char = *(name + ni2)
if sc4 != nc4:
match2 = 0
break
@@ -817,9 +814,9 @@ def get_so_symbol(so_base: t.CPtr, name: t.CConst | str, so_path: t.CConst | t.C
ni2 += 1
if match2:
result_addr: uint64 = uint64(so_base) + sb2.st_value
dbg2: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(dbg2), 80, "[so] found '%s' at 0x%lx\n", t.CPtr(uint64(_so_strtab) + sym_name_off2), result_addr)
serial.puts(dbg2)
return t.CPtr(result_addr)
dbg2: [80]char
viperlib.snprintf(&dbg2, 80, "[so] found '%s' at 0x%lx\n", rawptr(uint64(_so_strtab) + sym_name_off2), result_addr)
serial.puts(&dbg2)
return rawptr(result_addr)
serial.puts("[so] symbol not found\n")
return None
+20 -20
View File
@@ -1,7 +1,7 @@
import t, c
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class gdt_entry:
limit_low: uint16
base_low: uint16
@@ -10,7 +10,7 @@ class gdt_entry:
granularity: uint8
base_high: uint8
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class gdt_entry64:
limit_low: uint16
base_low: uint16
@@ -21,22 +21,22 @@ class gdt_entry64:
base_upper: uint32
reserved: uint32
@c.Attribute(t.attr.packed)
@__attribute__(packed)
class gdt_ptr:
limit: uint16
base: uint64
gdt: t.CArray[gdt_entry, 7] | t.CExport = []
gp: t.CArray[uint8, 10] | t.CExport
export gdt: [7]gdt_entry = []
export gp: [10]uint8 = []
# TSS buffer: 104 bytes, raw byte array to avoid packed struct issues
# x86_64 TSS layout: reserved0(4) rsp0(8) rsp1(8) rsp2(8) reserved1(8) ist1-ist7(56) reserved2(8) reserved3(2) iomap_base(2)
tss_buf: t.CArray[uint8, 104]
export tss_buf: [104]uint8
CODE_SEG: t.CDefine | uint16 = 0x08
DATA_SEG: t.CDefine | uint16 = 0x10
USER_CODE_SEG: t.CDefine | uint16 = 0x18
USER_DATA_SEG: t.CDefine | uint16 = 0x20
TSS_SEG: t.CDefine | uint16 = 0x28
define CODE_SEG: uint16 = 0x08
define DATA_SEG: uint16 = 0x10
define USER_CODE_SEG: uint16 = 0x18
define USER_DATA_SEG: uint16 = 0x20
define TSS_SEG: uint16 = 0x28
def init():
@@ -72,25 +72,25 @@ def init():
gdt[4].granularity = 0xCF
gdt[4].base_high = 0
# Set up TSS descriptor in GDT entries 5-6 (selector 0x28)
setTSS64(5, uint64(c.Addr(tss_buf)), 103)
c.Asm("""lea rax, [rip + gdt]
setTSS64(5, uint64(&tss_buf), 103)
__asm__("""lea rax, [rip + gdt]
lea rcx, [rip + gp]
mov word ptr [rcx], 0x37
mov qword ptr [rcx+2], rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX])
c.Asm("sfence; mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX])
__asm__("sfence; mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
flush()
# Initialize TSS: set iomap_base = 104 (0x68) at offset 102
tss_buf[102] = 0x68
tss_buf[103] = 0x00
# Load Task Register with TSS selector 0x28
c.Asm("""mov ax, 0x28
__asm__("""mov ax, 0x28
ltr ax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
op=[ASM_DESCR.CLOBBER_RAX])
@c.Attribute(t.attr.naked)
@__attribute__(naked)
def flush():
c.Asm("""lea rax, [rip + gp]
__asm__("""lea rax, [rip + gp]
lgdt [rax]
push 0x08
lea rax, [rip+2f]
@@ -103,7 +103,7 @@ def flush():
mov fs, eax
mov gs, eax
mov ss, eax
ret""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
ret""", op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
def set_tss_rsp0(rsp0: uint64):
global tss_buf
+193 -194
View File
@@ -5,11 +5,11 @@ import drivers.serial.uart.serial as serial
import drivers.core.cpu.apic as apic
import viperlib
import asm
import t, c
CODE_SEG: t.CDefine | uint16 = 0x08
@c.Attribute(t.attr.packed)
define CODE_SEG: uint16 = 0x08
@__attribute__(packed)
class idt_entry:
base_low: uint16
selector: uint16
@@ -18,62 +18,61 @@ class idt_entry:
base_middle: uint16
base_high: uint32
reserved1: uint32
idt: t.CArray[idt_entry, 256] | t.CExport = []
irq_handler_t: t.CTypedef = t.Callable[[], int]
export idt: [256]idt_entry = []
typedef irq_handler_t = callable[[], int]
def isr0() -> t.State: pass
def isr1() -> t.State: pass
def isr2() -> t.State: pass
def isr3() -> t.State: pass
def isr4() -> t.State: pass
def isr5() -> t.State: pass
def isr6() -> t.State: pass
def isr7() -> t.State: pass
def isr8() -> t.State: pass
def isr9() -> t.State: pass
def isr10() -> t.State: pass
def isr11() -> t.State: pass
def isr12() -> t.State: pass
def isr13() -> t.State: pass
def isr14() -> t.State: pass
def isr15() -> t.State: pass
def isr16() -> t.State: pass
def isr17() -> t.State: pass
def isr18() -> t.State: pass
def isr19() -> t.State: pass
def isr20() -> t.State: pass
def isr21() -> t.State: pass
def isr22() -> t.State: pass
def isr23() -> t.State: pass
def isr24() -> t.State: pass
def isr25() -> t.State: pass
def isr26() -> t.State: pass
def isr27() -> t.State: pass
def isr28() -> t.State: pass
def isr29() -> t.State: pass
def isr30() -> t.State: pass
def isr31() -> t.State: pass
def isr32() -> t.State: pass
def isr33() -> t.State: pass
def isr34() -> t.State: pass
def isr35() -> t.State: pass
def isr36() -> t.State: pass
def isr37() -> t.State: pass
def isr38() -> t.State: pass
def isr39() -> t.State: pass
def isr40() -> t.State: pass
def isr41() -> t.State: pass
def isr42() -> t.State: pass
def isr43() -> t.State: pass
def isr44() -> t.State: pass
def isr45() -> t.State: pass
def isr46() -> t.State: pass
def isr47() -> t.State: pass
extern def isr0()
extern def isr1()
extern def isr2()
extern def isr3()
extern def isr4()
extern def isr5()
extern def isr6()
extern def isr7()
extern def isr8()
extern def isr9()
extern def isr10()
extern def isr11()
extern def isr12()
extern def isr13()
extern def isr14()
extern def isr15()
extern def isr16()
extern def isr17()
extern def isr18()
extern def isr19()
extern def isr20()
extern def isr21()
extern def isr22()
extern def isr23()
extern def isr24()
extern def isr25()
extern def isr26()
extern def isr27()
extern def isr28()
extern def isr29()
extern def isr30()
extern def isr31()
extern def isr32()
extern def isr33()
extern def isr34()
extern def isr35()
extern def isr36()
extern def isr37()
extern def isr38()
extern def isr39()
extern def isr40()
extern def isr41()
extern def isr42()
extern def isr43()
extern def isr44()
extern def isr45()
extern def isr46()
extern def isr47()
def isr80() -> t.State: pass
def isr_default() -> t.State: pass
extern def isr80()
extern def isr_default()
def setGate(num: int, base: uint64, sel: uint16, flags: uint8):
global idt
@@ -86,10 +85,10 @@ def setGate(num: int, base: uint64, sel: uint16, flags: uint8):
idt[num].reserved1 = 0
def isrCommonhandler(interrupt: int):
c.Asm(f"""mov dx, 0x3F8
__asm__(f"""mov dx, 0x3F8
mov al, 91
out dx, al
mov ecx, {c.AsmInp(interrupt, t.ASM_DESCR.REG_ANY)}
mov ecx, {asminp(interrupt, ASM_DESCR.REG_ANY)}
mov rax, rcx
shr rax, 4
and al, 15
@@ -109,69 +108,69 @@ def isrCommonhandler(interrupt: int):
out dx, al
mov al, 93
out dx, al""",
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX])
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
# Print CR2 for page faults (ISR 14)
if interrupt == 14:
cr2: uint64 = 0
c.Asm(f"""mov {c.AsmOut(cr2, t.ASM_DESCR.OUTPUT_REG)}, cr2""",
op=[t.ASM_DESCR.CLOBBER_RAX])
__asm__(f"""mov {asmout(cr2, ASM_DESCR.OUTPUT_REG)}, cr2""",
op=[ASM_DESCR.CLOBBER_RAX])
fault_rip: uint64 = 0
fault_err: uint64 = 0
fault_rsp: uint64 = 0
c.Asm(f"""mov {c.AsmOut(fault_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {c.AsmOut(fault_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err]
mov {c.AsmOut(fault_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
op=[t.ASM_DESCR.CLOBBER_RAX])
buf: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(buf), 100, "[PF] cr2=0x%lx rip=0x%lx err=0x%lx rsp=0x%lx\n", cr2, fault_rip, fault_err, fault_rsp)
__asm__(f"""mov {asmout(fault_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {asmout(fault_err, ASM_DESCR.OUTPUT_REG)}, [_fault_err]
mov {asmout(fault_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
op=[ASM_DESCR.CLOBBER_RAX])
buf: [100]char
viperlib.snprintf(&buf, 100, "[PF] cr2=0x%lx rip=0x%lx err=0x%lx rsp=0x%lx\n", cr2, fault_rip, fault_err, fault_rsp)
serial.puts(buf)
# [CR3] 当前 pml4:定位栈区/对象写缺页是否因 pml4 被 switch_pid 切走
# (内核 pml4=0xf801000,用户 pml4=0x9781xxx —— 若显示用户 pml4 而 rsp
# 在 bootloader 栈区 0x60000-0x80000,则是进程切换后未切回内核页表)。
cur_cr3: uint64 = 0
c.Asm(f"mov {c.AsmOut(cur_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3",
op=[t.ASM_DESCR.CLOBBER_RAX])
cr3_buf: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(cr3_buf), 80, "[CR3] pml4=0x%lx\n", cur_cr3)
__asm__(f"mov {asmout(cur_cr3, ASM_DESCR.OUTPUT_REG)}, cr3",
op=[ASM_DESCR.CLOBBER_RAX])
cr3_buf: [80]char
viperlib.snprintf(&cr3_buf, 80, "[CR3] pml4=0x%lx\n", cur_cr3)
serial.puts(cr3_buf)
# [RAX] 崩溃时 rax(isr.s 保存):定位 cr2 与 rax 关系(rax-偏移=cr2)
f_rax: uint64 = 0
c.Asm(f"""mov {c.AsmOut(f_rax, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
op=[t.ASM_DESCR.CLOBBER_RAX])
rax_buf: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(rax_buf), 80, "[RAX] rax=0x%lx\n", f_rax)
__asm__(f"""mov {asmout(f_rax, ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
op=[ASM_DESCR.CLOBBER_RAX])
rax_buf: [80]char
viperlib.snprintf(&rax_buf, 80, "[RAX] rax=0x%lx\n", f_rax)
serial.puts(rax_buf)
# [STK] rbp 链回溯(定位栈损坏源:崩溃帧 + 4 级调用链的返回地址)
# 先读崩溃 rbp 判断(用户 rbp 不回溯,避免读用户地址嵌套 #PF)
fr0: uint64 = 0
c.Asm(f"""mov rax, [_fault_rbp]
mov {c.AsmOut(fr0, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
stk_buf: t.CArray[t.CChar, 160]
__asm__(f"""mov rax, [_fault_rbp]
mov {asmout(fr0, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_RAX])
stk_buf: [160]char
if fr0 >= 0x80000000:
# 用户态 rbp(如 0x7fffff...):回溯会读用户栈地址 → 嵌套 #PF 死循环
viperlib.snprintf(c.Addr(stk_buf), 160, "[STK] user rbp=0x%lx, chain skipped\n", fr0)
viperlib.snprintf(&stk_buf, 160, "[STK] user rbp=0x%lx, chain skipped\n", fr0)
serial.puts(stk_buf)
else:
fr1: uint64 = 0
fr2: uint64 = 0
fr3: uint64 = 0
fr4: uint64 = 0
c.Asm(f"""mov rax, [_fault_rbp]
__asm__(f"""mov rax, [_fault_rbp]
mov rax, [rax + 8]
mov {c.AsmOut(fr1, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr1, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [_fault_rbp]
mov rax, [rax]
mov {c.AsmOut(fr2, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr2, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [rax + 8]
mov {c.AsmOut(fr3, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr3, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [_fault_rbp]
mov rax, [rax]
mov rax, [rax]
mov rax, [rax + 8]
mov {c.AsmOut(fr4, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
viperlib.snprintf(c.Addr(stk_buf), 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
mov {asmout(fr4, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_RAX])
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
fr0, fr1, fr2, fr3, fr4)
serial.puts(stk_buf)
elif interrupt == 13:
@@ -180,34 +179,34 @@ def isrCommonhandler(interrupt: int):
gp_rsp: uint64 = 0
gp_cr4: uint64 = 0
gp_cr0: uint64 = 0
c.Asm(f"""mov {c.AsmOut(gp_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {c.AsmOut(gp_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err]
mov {c.AsmOut(gp_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]
__asm__(f"""mov {asmout(gp_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {asmout(gp_err, ASM_DESCR.OUTPUT_REG)}, [_fault_err]
mov {asmout(gp_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]
mov rax, cr4
mov {c.AsmOut(gp_cr4, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(gp_cr4, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, cr0
mov {c.AsmOut(gp_cr0, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
gp_buf: t.CArray[t.CChar, 140]
viperlib.snprintf(c.Addr(gp_buf), 140, "[GP] rip=0x%lx err=0x%lx rsp=0x%lx cr4=0x%lx cr0=0x%lx\n",
mov {asmout(gp_cr0, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_RAX])
gp_buf: [140]char
viperlib.snprintf(&gp_buf, 140, "[GP] rip=0x%lx err=0x%lx rsp=0x%lx cr4=0x%lx cr0=0x%lx\n",
gp_rip, gp_err, gp_rsp, gp_cr4, gp_cr0)
serial.puts(gp_buf)
else:
# 其他异常(#UD 等):打印 rip/rsp 定位执行位置(isr.s 已保存 _fault_rip)
ex_rip: uint64 = 0
ex_rsp: uint64 = 0
c.Asm(f"""mov {c.AsmOut(ex_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {c.AsmOut(ex_rsp, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
op=[t.ASM_DESCR.CLOBBER_RAX])
ex_buf: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(ex_buf), 100, "[EX] int=%d rip=0x%lx rsp=0x%lx\n", interrupt, ex_rip, ex_rsp)
__asm__(f"""mov {asmout(ex_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
mov {asmout(ex_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
op=[ASM_DESCR.CLOBBER_RAX])
ex_buf: [100]char
viperlib.snprintf(&ex_buf, 100, "[EX] int=%d rip=0x%lx rsp=0x%lx\n", interrupt, ex_rip, ex_rsp)
serial.puts(ex_buf)
# [RAX] 崩溃时 rax(isr.s 保存)
f_rax: uint64 = 0
c.Asm(f"""mov {c.AsmOut(f_rax, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
op=[t.ASM_DESCR.CLOBBER_RAX])
rax_buf: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(rax_buf), 80, "[RAX] rax=0x%lx\n", f_rax)
__asm__(f"""mov {asmout(f_rax, ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
op=[ASM_DESCR.CLOBBER_RAX])
rax_buf: [80]char
viperlib.snprintf(&rax_buf, 80, "[RAX] rax=0x%lx\n", f_rax)
serial.puts(rax_buf)
# [STK] rbp 链回溯(与 #PF 分支一致,定位栈损坏源)
fr0: uint64 = 0
@@ -215,30 +214,30 @@ def isrCommonhandler(interrupt: int):
fr2: uint64 = 0
fr3: uint64 = 0
fr4: uint64 = 0
c.Asm(f"""mov rax, [_fault_rbp]
mov {c.AsmOut(fr0, t.ASM_DESCR.OUTPUT_REG)}, rax
__asm__(f"""mov rax, [_fault_rbp]
mov {asmout(fr0, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [rax + 8]
mov {c.AsmOut(fr1, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr1, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [_fault_rbp]
mov rax, [rax]
mov {c.AsmOut(fr2, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr2, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [rax + 8]
mov {c.AsmOut(fr3, t.ASM_DESCR.OUTPUT_REG)}, rax
mov {asmout(fr3, ASM_DESCR.OUTPUT_REG)}, rax
mov rax, [_fault_rbp]
mov rax, [rax]
mov rax, [rax]
mov rax, [rax + 8]
mov {c.AsmOut(fr4, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
stk_buf: t.CArray[t.CChar, 160]
mov {asmout(fr4, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_RAX])
stk_buf: [160]char
if fr0 >= 0x80000000:
# 用户态 rbp(如 0x7fffff...):回溯会读用户栈地址 → 嵌套 #PF 死循环
viperlib.snprintf(c.Addr(stk_buf), 160, "[STK] user rbp=0x%lx, chain skipped\n", fr0)
viperlib.snprintf(&stk_buf, 160, "[STK] user rbp=0x%lx, chain skipped\n", fr0)
else:
viperlib.snprintf(c.Addr(stk_buf), 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
fr0, fr1, fr2, fr3, fr4)
serial.puts(stk_buf)
s: sched.Scheduler | t.CPtr = sched._sched_ptr
s: sched.Scheduler* = sched._sched_ptr
# 如果调度器未初始化,直接进入安全停机状态
if s == 0:
serial.puts(" KERNEL PANIC (sched not init)\n")
@@ -260,8 +259,8 @@ def isrCommonhandler(interrupt: int):
asm.sti()
asm.hlt()
pass
buf2: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(buf2), 64, " exc in tid=%d, terminating\n", tid)
buf2: [64]char
viperlib.snprintf(&buf2, 64, " exc in tid=%d, terminating\n", tid)
serial.puts(buf2)
s.threads[tid].state = 3
# Restore GS to kernel-normal state before _yield().
@@ -269,7 +268,7 @@ def isrCommonhandler(interrupt: int):
# Since _yield() switches to another thread and never returns via ISR exit,
# the swapgs at ISR exit is never executed. We must swap back here.
# Check IA32_GS_BASE (MSR 0xC0000101): if non-zero, swapgs was done at entry.
c.Asm(f"""mov ecx, 0xC0000101
__asm__(f"""mov ecx, 0xC0000101
rdmsr
shl rdx, 32
or rax, rdx
@@ -277,7 +276,7 @@ def isrCommonhandler(interrupt: int):
jz 1f
swapgs
1:""",
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX])
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
sched.Scheduler._yield()
while True:
asm.sti()
@@ -320,72 +319,72 @@ export def isr32_handler(): timer.timer_handler()
export def isr33_handler():
handler: irq_handler_t = irqGetHandler(1)
if handler:
c.Asm(f"""call {c.AsmInp(handler, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(1)
apic.eoi()
export def isr34_handler():
handler2: irq_handler_t = irqGetHandler(2)
if handler2:
c.Asm(f"""call {c.AsmInp(handler2, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler2, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(2)
apic.eoi()
export def isr35_handler():
handler3: irq_handler_t = irqGetHandler(3)
if handler3:
c.Asm(f"""call {c.AsmInp(handler3, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler3, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(3)
apic.eoi()
export def isr36_handler():
handler4: irq_handler_t = irqGetHandler(4)
if handler4:
c.Asm(f"""call {c.AsmInp(handler4, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler4, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(4)
apic.eoi()
export def isr37_handler():
handler5: irq_handler_t = irqGetHandler(5)
if handler5:
c.Asm(f"""call {c.AsmInp(handler5, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler5, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(5)
apic.eoi()
export def isr38_handler():
handler6: irq_handler_t = irqGetHandler(6)
if handler6:
c.Asm(f"""call {c.AsmInp(handler6, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler6, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(6)
apic.eoi()
@@ -394,72 +393,72 @@ export def isr39_handler():
return
handler7: irq_handler_t = irqGetHandler(7)
if handler7:
c.Asm(f"""call {c.AsmInp(handler7, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler7, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(7)
apic.eoi()
export def isr40_handler():
handler8: irq_handler_t = irqGetHandler(8)
if handler8:
c.Asm(f"""call {c.AsmInp(handler8, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler8, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(8)
apic.eoi()
export def isr41_handler():
handler9: irq_handler_t = irqGetHandler(9)
if handler9:
c.Asm(f"""call {c.AsmInp(handler9, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler9, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(9)
apic.eoi()
export def isr42_handler():
handler10: irq_handler_t = irqGetHandler(10)
if handler10:
c.Asm(f"""call {c.AsmInp(handler10, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler10, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(10)
apic.eoi()
export def isr43_handler():
handler11: irq_handler_t = irqGetHandler(11)
if handler11:
c.Asm(f"""call {c.AsmInp(handler11, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler11, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(11)
apic.eoi()
export def isr44_handler():
handler: irq_handler_t = irqGetHandler(12)
if handler:
c.Asm(f"""call {c.AsmInp(handler, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""call {asminp(handler, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
pic.eoi(12)
apic.eoi()
@@ -529,7 +528,7 @@ def init_irqs():
setGate(46, uint64(isr46), CODE_SEG, 0x8E)
setGate(47, uint64(isr47), CODE_SEG, 0x8E)
irq_handlers: t.CStatic | t.CArray[irq_handler_t, 16] = [None]
irq_handlers: static [16]irq_handler_t = [None]
def irqInstallHandler(irq: int, handler: irq_handler_t, name: str) -> int:
global irq_handlers
@@ -551,10 +550,10 @@ def init():
# Register ISR 0x80 for int 0x80 syscall interface (user-mode ELF apps)
setGate(0x80, uint64(isr80), CODE_SEG, 0xEE) # DPL=3 allows Ring 3 to call int 0x80
# Build idt_ptr on stack and load directly in one asm block
c.Asm("""lea rax, [rip + idt]
__asm__("""lea rax, [rip + idt]
sub rsp, 16
mov word ptr [rsp], 0x0fff
mov qword ptr [rsp+2], rax
lidt [rsp]
add rsp, 16""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
+128 -128
View File
@@ -9,101 +9,101 @@ import string
import mm.mm as mm
import paging.paging as paging
import execrunner.elf as elf
import t, c
CREATE_WINDOW: t.CDefine = 1
DRAW_TEXT: t.CDefine = 2
EXIT: t.CDefine = 3
OPEN: t.CDefine = 4
CLOSE: t.CDefine = 5
READ: t.CDefine = 6
WRITE: t.CDefine = 7
SEEK: t.CDefine = 8
TELL: t.CDefine = 9
SIZE: t.CDefine = 10
MKDIR: t.CDefine = 11
REMOVE: t.CDefine = 12
OPENDIR: t.CDefine = 13
READDIR: t.CDefine = 14
CLOSEDIR: t.CDefine = 15
STAT: t.CDefine = 16
WAIT_WINDOW: t.CDefine = 17
SERIAL_PUTS: t.CDefine = 18
LOAD_SO: t.CDefine = 19
SO_CALL1: t.CDefine = 20
GET_WINBUF: t.CDefine = 21
WIN_FLUSH: t.CDefine = 22
POLL_EVENT: t.CDefine = 23
SET_CURSOR: t.CDefine = 24
YIELD: t.CDefine = 25
SET_TITLE: t.CDefine = 26
SET_GEOMETRY: t.CDefine = 27
SPAWN: t.CDefine = 28
MMAP: t.CDefine = 29
MUNMAP: t.CDefine = 30
SET_RESIZABLE: t.CDefine = 31
GET_WIN_SIZE: t.CDefine = 32
THREAD_CREATE: t.CDefine = 33
IA32_EFER: t.CDefine = 0xC0000080
IA32_STAR: t.CDefine = 0xC0000081
IA32_LSTAR: t.CDefine = 0xC0000082
IA32_FMASK: t.CDefine = 0xC0000084
define CREATE_WINDOW = 1
define DRAW_TEXT = 2
define EXIT = 3
define OPEN = 4
define CLOSE = 5
define READ = 6
define WRITE = 7
define SEEK = 8
define TELL = 9
define SIZE = 10
define MKDIR = 11
define REMOVE = 12
define OPENDIR = 13
define READDIR = 14
define CLOSEDIR = 15
define STAT = 16
define WAIT_WINDOW = 17
define SERIAL_PUTS = 18
define LOAD_SO = 19
define SO_CALL1 = 20
define GET_WINBUF = 21
define WIN_FLUSH = 22
define POLL_EVENT = 23
define SET_CURSOR = 24
define YIELD = 25
define SET_TITLE = 26
define SET_GEOMETRY = 27
define SPAWN = 28
define MMAP = 29
define MUNMAP = 30
define SET_RESIZABLE = 31
define GET_WIN_SIZE = 32
define THREAD_CREATE = 33
define IA32_EFER = 0xC0000080
define IA32_STAR = 0xC0000081
define IA32_LSTAR = 0xC0000082
define IA32_FMASK = 0xC0000084
def wrmsr(msr: uint32, val: uint64):
lo: uint32 = uint32(val & 0xFFFFFFFF)
hi: uint32 = uint32(val >> 32)
c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(lo, t.ASM_DESCR.REG_ANY)}
mov edx, {c.AsmInp(hi, t.ASM_DESCR.REG_ANY)}
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
mov eax, {asminp(lo, ASM_DESCR.REG_ANY)}
mov edx, {asminp(hi, ASM_DESCR.REG_ANY)}
wrmsr""",
op=[t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX])
op=[ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
def rdmsr(msr: uint32) -> uint64:
lo: uint32
hi: uint32
# rdmsr 固定写 EDX:EAX;out 绑定 + CLOBBER_RAX/RDX 冲突会导致 lo/hi
# 分配到非 EAX/EDX 读到垃圾。显式 mov 到输出寄存器(与 asm.inb 修复同模式)。
c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)}
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
rdmsr
mov {c.AsmOut(lo, t.ASM_DESCR.OUTPUT_REG)}, eax
mov {c.AsmOut(hi, t.ASM_DESCR.OUTPUT_REG)}, edx""",
out=[c.AsmOut(lo, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(hi, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX])
mov {asmout(lo, ASM_DESCR.OUTPUT_REG)}, eax
mov {asmout(hi, ASM_DESCR.OUTPUT_REG)}, edx""",
out=[asmout(lo, ASM_DESCR.OUTPUT_REG), asmout(hi, ASM_DESCR.OUTPUT_REG)],
op=[ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
return uint64(lo) | (uint64(hi) << 32)
def _current_proc() -> process.Process | t.CPtr:
def _current_proc() -> process.Process*:
return process.ProcessManager.current()
def _fd_alloc(p: process.Process | t.CPtr) -> int:
def _fd_alloc(p: process.Process*) -> int:
for i in range(process.PROC_MAX_FDS):
if not p.fd_used[i]:
p.fd_used[i] = 1
return i
return -1
def _fd_free(p: process.Process | t.CPtr, fd: int):
def _fd_free(p: process.Process*, fd: int):
if fd >= 0 and fd < process.PROC_MAX_FDS:
p.fd_used[fd] = 0
p.fd_table[fd] = t.CPtr(0)
p.fd_used[fd] = None
p.fd_table[fd] = None
def _dir_alloc(p: process.Process | t.CPtr) -> int:
def _dir_alloc(p: process.Process*) -> int:
for i in range(process.PROC_MAX_DIRS):
if not p.dir_used[i]:
p.dir_used[i] = 1
return i
return -1
def _dir_free(p: process.Process | t.CPtr, dd: int):
def _dir_free(p: process.Process*, dd: int):
if dd >= 0 and dd < process.PROC_MAX_DIRS:
p.dir_used[dd] = 0
p.dir_table[dd] = t.CPtr(0)
p.dir_used[dd] = None
p.dir_table[dd] = None
def CREATE_WINDOW(x: int, y: int, w: int, h: int, title: t.CConst | t.CChar | t.CPtr, style: int) -> int:
def CREATE_WINDOW(x: int, y: int, w: int, h: int, title: const str, style: int) -> int:
desktop.set_app_pid(process.current())
return desktop.create(x, y, w, h, title, style)
def DRAW_TEXT(win_id: int, x: int, y: int, text: t.CConst | t.CChar | t.CPtr, color: uint32) -> int:
def DRAW_TEXT(win_id: int, x: int, y: int, text: const str, color: uint32) -> int:
return desktop.draw_text(win_id, x, y, text, color)
def EXIT(code: int) -> int:
@@ -117,49 +117,49 @@ def WAIT_WINDOW(win_id: int) -> int:
return 0
def SERIAL_PUTS(str_ptr: str) -> int:
s: t.CConst | str = str_ptr
s: const str = str_ptr
serial.puts(s)
return 0
_loaded_so_base: t.CPtr = None
_loaded_so_path: t.CArray[t.CChar, 64]
_loaded_so_base: rawptr = None
_loaded_so_path: [64]char
def LOAD_SO(path_ptr: str) -> uint64:
global _loaded_so_base
path: t.CConst | str = path_ptr
path: const str = path_ptr
serial.puts("[so] loading: ")
serial.puts(path)
serial.puts("\n")
base: t.CPtr = elf.load_so(path)
base: rawptr = elf.load_so(path)
if base is not None:
_loaded_so_base = base
for i in range(63):
ch: t.CChar = c.Deref(path + i)
ch: char = path[i]
_loaded_so_path[i] = ch
if ch == 0: break
_loaded_so_path[63] = 0
return uint64(base)
return 0
def SO_CALL1(sym_name_ptr: str, arg1: t.CPtr) -> int:
def SO_CALL1(sym_name_ptr: str, arg1: rawptr) -> int:
if _loaded_so_base is None: return -1
sym_name: t.CConst | str = t.CPtr(sym_name_ptr)
fn: t.CPtr = elf.get_so_symbol(_loaded_so_base, sym_name, c.Addr(_loaded_so_path[0]))
sym_name: const str = sym_name_ptr
fn: rawptr = elf.get_so_symbol(_loaded_so_base, sym_name, &_loaded_so_path[0])
if fn is None:
serial.puts("[so] symbol not found\n")
return -2
c.Asm(f"""mov rdi, {c.AsmInp(arg1, t.ASM_DESCR.REG_ANY)}
call {c.AsmInp(fn, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
__asm__(f"""mov rdi, {asminp(arg1, ASM_DESCR.REG_ANY)}
call {asminp(fn, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_RSI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
serial.puts("[so] call returned\n")
return 0
def GET_WINBUF(win_id: int) -> uint64:
buf: t.CPtr = desktop.get_fb(win_id)
buf: rawptr = desktop.get_fb(win_id)
if buf is None:
return 0
return uint64(buf)
@@ -173,10 +173,10 @@ def SET_CURSOR(win_id: int, cursor_t: int) -> int:
return 0
def OPEN(path_ptr: str, mode: uint32) -> int:
p: process.Process | t.CPtr = _current_proc()
path: t.CConst | str = path_ptr
p: process.Process* = _current_proc()
path: const str = path_ptr
fat32.lock()
fp: t.CPtr = fat32.open(path, uint8(mode))
fp: rawptr = fat32.open(path, uint8(mode))
if not fp:
fat32.unlock()
return -1
@@ -190,10 +190,10 @@ def OPEN(path_ptr: str, mode: uint32) -> int:
return fd
def CLOSE(fd: int) -> int:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fat32.lock()
@@ -202,11 +202,11 @@ def CLOSE(fd: int) -> int:
_fd_free(p, fd)
return res
def READ(fd: int, buf_ptr: t.CPtr, count: uint32) -> int:
p: process.Process | t.CPtr = _current_proc()
def READ(fd: int, buf_ptr: rawptr, count: uint32) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return -1
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return -1
fat32.lock()
@@ -214,11 +214,11 @@ def READ(fd: int, buf_ptr: t.CPtr, count: uint32) -> int:
fat32.unlock()
return int(br)
def WRITE(fd: int, buf_ptr: t.CPtr, count: uint32) -> int:
p: process.Process | t.CPtr = _current_proc()
def WRITE(fd: int, buf_ptr: rawptr, count: uint32) -> int:
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return -1
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return -1
fat32.lock()
@@ -227,10 +227,10 @@ def WRITE(fd: int, buf_ptr: t.CPtr, count: uint32) -> int:
return int(bw)
def SEEK(fd: int, offset: uint32) -> int:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fat32.lock()
@@ -239,10 +239,10 @@ def SEEK(fd: int, offset: uint32) -> int:
return r
def TELL(fd: int) -> uint32:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return 0
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return 0
fat32.lock()
@@ -251,10 +251,10 @@ def TELL(fd: int) -> uint32:
return pos
def fsize(fd: int) -> uint32:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if fd < 0 or fd >= process.PROC_MAX_FDS:
return 0
fp: t.CPtr = p.fd_table[fd]
fp: rawptr = p.fd_table[fd]
if not fp:
return 0
fat32.lock()
@@ -263,53 +263,53 @@ def fsize(fd: int) -> uint32:
return sz
def MKDIR(path_ptr: str) -> int:
path: t.CConst | str = path_ptr
path: const str = path_ptr
fat32.lock()
r: int = int(fat32.mkdir(path))
fat32.unlock()
return r
def REMOVE(path_ptr: str) -> int:
path: t.CConst | str = path_ptr
path: const str = path_ptr
fat32.lock()
r: int = int(fat32.remove(path))
fat32.unlock()
return r
def OPENdir(path_ptr: str) -> int:
p: process.Process | t.CPtr = _current_proc()
path: t.CConst | str = path_ptr
p: process.Process* = _current_proc()
path: const str = path_ptr
dd: int = _dir_alloc(p)
if dd < 0:
return -1
dp: fat32_types.dirobj | t.CPtr = c.Addr(p.dir_pool[dd])
dp: fat32_types.dirobj* = &p.dir_pool[dd]
fat32.lock()
res: int = int(fat32.opendir(path, dp))
fat32.unlock()
if res != 0:
_dir_free(p, dd)
return -1
p.dir_table[dd] = t.CPtr(uint64(dp))
p.dir_table[dd] = rawptr(uint64(dp))
return dd
def READdir(dd: int, info_ptr: t.CPtr) -> int:
p: process.Process | t.CPtr = _current_proc()
def READdir(dd: int, info_ptr: rawptr) -> int:
p: process.Process* = _current_proc()
if dd < 0 or dd >= process.PROC_MAX_DIRS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
dp: t.CPtr = p.dir_table[dd]
dp: rawptr = p.dir_table[dd]
if not dp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
info: fat32_types.fileinfo | t.CPtr = info_ptr
info: fat32_types.fileinfo* = info_ptr
fat32.lock()
r: int = int(fat32.readdir(dp, info))
fat32.unlock()
return r
def CLOSEdir(dd: int) -> int:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if dd < 0 or dd >= process.PROC_MAX_DIRS:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
dp: t.CPtr = p.dir_table[dd]
dp: rawptr = p.dir_table[dd]
if not dp:
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
fat32.lock()
@@ -318,30 +318,30 @@ def CLOSEdir(dd: int) -> int:
_dir_free(p, dd)
return 0
def STAT(path_ptr: str, info_ptr: t.CPtr) -> int:
path: t.CConst | str = path_ptr
info: fat32_types.fileinfo | t.CPtr = info_ptr
def STAT(path_ptr: str, info_ptr: rawptr) -> int:
path: const str = path_ptr
info: fat32_types.fileinfo* = info_ptr
fat32.lock()
r: int = int(fat32.stat(path, info))
fat32.unlock()
return r
def SPAWN(path_ptr: str, blocking: int) -> int:
path: t.CConst | str = path_ptr
path: const str = path_ptr
pid: int = elf.spawn_elf(path)
if pid < 0:
return pid
if blocking:
p: process.Process | t.CPtr = process.ProcessManager.get_process(pid)
p: process.Process* = process.ProcessManager.get_process(pid)
if p:
while p.state != process.PROC_DONE:
sched.Scheduler.try_reschedule()
return pid
USER_HEAP_BASE: t.CDefine = 0x20000000
define USER_HEAP_BASE = 0x20000000
def MMAP(size: uint64) -> uint64:
p: process.Process | t.CPtr = _current_proc()
p: process.Process* = _current_proc()
if size == 0: return 0
aligned_size: uint64 = (size + 4095) & ~uint64(4095)
if p.heap_start == 0:
@@ -349,7 +349,7 @@ def MMAP(size: uint64) -> uint64:
heap_end: uint64 = p.heap_start + p.heap_size
new_end: uint64 = heap_end + aligned_size
for va in range(heap_end, new_end, 4096):
phys_page: t.CPtr = mm.malloc(4096)
phys_page: rawptr = mm.malloc(4096)
if phys_page is None: return 0
paging.MapPage(va, uint64(phys_page), paging.PTE_PRESENT | paging.PTE_WRITABLE | paging.PTE_USER)
p.heap_size = p.heap_size + aligned_size
@@ -358,9 +358,9 @@ def MMAP(size: uint64) -> uint64:
def MUNMAP(ptr: uint64, size: uint64) -> int:
return 0
extern def syscall_entry(): pass
extern def syscall_entry()
def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4: uint64, arg5: uint64, arg6: uint64) -> t.CExport | uint64:
export def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4: uint64, arg5: uint64, arg6: uint64) -> uint64:
n: int = int(num)
if n == CREATE_WINDOW:
title_ptr: str = str(arg5)
@@ -376,10 +376,10 @@ def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4:
elif n == CLOSE:
return uint64(CLOSE(int(arg1)))
elif n == READ:
buf_ptr: t.CPtr = t.CPtr(arg2)
buf_ptr: rawptr = rawptr(arg2)
return uint64(READ(int(arg1), buf_ptr, uint32(arg3)))
elif n == WRITE:
buf_ptr: t.CPtr = t.CPtr(arg2)
buf_ptr: rawptr = rawptr(arg2)
return uint64(WRITE(int(arg1), buf_ptr, uint32(arg3)))
elif n == SEEK:
return uint64(SEEK(int(arg1), uint32(arg2)))
@@ -397,13 +397,13 @@ def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4:
path_ptr: str = str(arg1)
return uint64(OPENdir(path_ptr))
elif n == READDIR:
info_ptr: t.CPtr = t.CPtr(arg2)
info_ptr: rawptr = rawptr(arg2)
return uint64(READdir(int(arg1), info_ptr))
elif n == CLOSEDIR:
return uint64(CLOSEdir(int(arg1)))
elif n == STAT:
path_ptr: str = str(arg1)
info_ptr: t.CPtr = t.CPtr(arg2)
info_ptr: rawptr = rawptr(arg2)
return uint64(STAT(path_ptr, info_ptr))
elif n == WAIT_WINDOW:
if int(arg2) == 1:
@@ -416,17 +416,17 @@ def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4:
str_ptr_sp: str = str(arg1)
return uint64(SERIAL_PUTS(str_ptr_sp))
elif n == LOAD_SO:
path_ptr_so: t.CPtr = t.CPtr(arg1)
path_ptr_so: rawptr = rawptr(arg1)
return LOAD_SO(path_ptr_so)
elif n == SO_CALL1:
sym_ptr: t.CPtr = t.CPtr(arg1)
return uint64(SO_CALL1(sym_ptr, t.CPtr(arg2)))
sym_ptr: rawptr = rawptr(arg1)
return uint64(SO_CALL1(sym_ptr, rawptr(arg2)))
elif n == GET_WINBUF:
return GET_WINBUF(int(arg1))
elif n == WIN_FLUSH:
return uint64(WIN_FLUSH(int(arg1)))
elif n == POLL_EVENT:
buf_ptr_ev: t.CPtr = t.CPtr(arg1)
buf_ptr_ev: rawptr = rawptr(arg1)
caller_pid_ev: int = process.current()
return uint64(desktop.poll_event(buf_ptr_ev, caller_pid_ev))
elif n == SET_CURSOR:
@@ -436,7 +436,7 @@ def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4:
sched.Scheduler.try_reschedule()
return 0
elif n == SET_TITLE:
title_ptr_st: t.CPtr = t.CPtr(arg2)
title_ptr_st: rawptr = rawptr(arg2)
return uint64(desktop.set_title(int(arg1), title_ptr_st))
elif n == SET_GEOMETRY:
return uint64(desktop.set_geometry(int(arg1), int(arg2), int(arg3), int(arg4), int(arg5)))
@@ -445,19 +445,19 @@ def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64, arg4:
elif n == GET_WIN_SIZE:
return uint64(desktop.get_size(int(arg1)))
elif n == SPAWN:
path_ptr_sp: t.CPtr = t.CPtr(arg1)
path_ptr_sp: rawptr = rawptr(arg1)
return uint64(SPAWN(path_ptr_sp, int(arg2)))
elif n == MMAP:
return MMAP(arg1)
elif n == MUNMAP:
return uint64(MUNMAP(arg1, arg2))
elif n == THREAD_CREATE:
func_ptr: t.CPtr = t.CPtr(arg1)
arg_ptr: t.CPtr = t.CPtr(arg2)
func_ptr: rawptr = rawptr(arg1)
arg_ptr: rawptr = rawptr(arg2)
cur_pid: int = process.current()
th: sched.Thread | t.CPtr = sched.Scheduler.create_thread(func_ptr, arg_ptr, cur_pid)
th: sched.Thread* = sched.Scheduler.create_thread(func_ptr, arg_ptr, cur_pid)
if th is None: return uint64(0xFFFFFFFFFFFFFFFF)
p: process.Process | t.CPtr = process.ProcessManager.get_process(cur_pid)
p: process.Process* = process.ProcessManager.get_process(cur_pid)
if p:
p.addThread(th.tid)
return uint64(th.tid)
+8 -8
View File
@@ -101,7 +101,7 @@ class ViperKernel:
# [DBG] 软件触发 int 0x20:门 32 有效则分发到 isr32→timer_handler 打印 H 并返回;
# 门无效则 #GP(isrCommonhandler 打印 [GP] err=0x20),一次性区分分发路径(用后移除)
serial.puts("[DBG] before swint\n")
c.Asm("int 0x20", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("int 0x20", op=[ASM_DESCR.CLOBBER_MEMORY])
serial.puts("[DBG] after swint\n")
# [DBG] 读 PIC1 ISR:bit0 置位说明 PIT IRQ0 已到达 PIC 并被响应(用后移除)
@@ -124,7 +124,7 @@ class ViperKernel:
apic.start_aps()
serial.puts("[main] kernel init done\n")
fb: t.CPtr = t.CPtr(BootInfo.framebuffer_addr)
fb: rawptr = rawptr(BootInfo.framebuffer_addr)
width: uint64 = BootInfo.framebuffer_width
height: uint64 = BootInfo.framebuffer_height
pitch: uint64 = BootInfo.framebuffer_pitch
@@ -142,7 +142,7 @@ class ViperKernel:
if (_dbi % 16) == 0:
viperlib.snprintf(&_dbraw, 16, "\n[DB] %04x:", _dbi)
serial.puts(&_dbraw)
_dbv: uint8 = *(uint8(uint64(BootInfo) + uint64(_dbi)))
_dbv: uint8 = *(uint8*(uint64(BootInfo) + uint64(_dbi)))
viperlib.snprintf(&_dbraw, 16, " %02x", _dbv)
serial.puts(&_dbraw)
serial.puts("\n[DB] dump end\n")
@@ -156,12 +156,12 @@ class ViperKernel:
paging.MapPage(fva, fva, paging.PTE_WRITABLE | paging.PTE_PCD)
fpi += 1
mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size)
pt_pool_buf: t.CPtr = mm.malloc(uint64(513) * uint64(4096))
pt_pool_buf: rawptr = mm.malloc(uint64(513) * uint64(4096))
paging.init_pool(pt_pool_buf, uint64(513) * uint64(4096))
else:
paging.init(0, 0)
mm.init(0, 0, 0, 0, 0)
pt_pool_buf2: t.CPtr = mm.malloc(uint64(513) * uint64(4096))
pt_pool_buf2: rawptr = mm.malloc(uint64(513) * uint64(4096))
paging.init_pool(pt_pool_buf2, uint64(513) * uint64(4096))
serial.puts("[main] paging and mm init done\n")
# 把 .rodata(字符串常量/vtable)映射只读 + CR0.WP=1:
@@ -344,12 +344,12 @@ class ViperKernel:
VKP: ViperKernel*
# stackrealign:_start 由 bootloader jmp 进入(rsp≡0 mod 16),llc 按 call 约定
# 假设入口 rsp≡8 → 帧偏 8 → 变参函数 movaps #GP。动态重对齐栈修复。
@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16), t.attr.stackrealign)
@__attribute__(section(".text.startup"), aligned(16), stackrealign)
def _start() -> int:
global VKP, BootInfo
saved_rdi: ulong
c.Asm(f"mov {c.AsmOut(saved_rdi, t.ASM_DESCR.OUTPUT_REG)}, rdi",
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RDI])
__asm__(f"mov {asmout(saved_rdi, ASM_DESCR.OUTPUT_REG)}, rdi",
op = [ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RDI])
asm.BSSClean()
BootInfo = bootinfo*(saved_rdi) # 转为 bootinfo*
VKP = &ViperKernel()
+148 -262
View File
@@ -1,75 +1,73 @@
import bootinfo
import paging.paging as paging
import viperstring as string
import viperlib
import t, c
import string
# 伙伴系统常量定义
MIN_BLOCK_SIZE: t.CDefine = 4096 # 最小块大小(4KB)
MAX_BLOCK_SIZE: t.CDefine = 268435456 # 最大块大小(256MB)
MAX_ORDER: t.CDefine = 18 # 最大阶数(2^18 = 262144)
define MIN_BLOCK_SIZE = 4096 # 最小块大小(4KB)
define MAX_BLOCK_SIZE = 268435456 # 最大块大小(256MB)
define MAX_ORDER = 18 # 最大阶数(2^18 = 262144)
# 内存块状态
BLOCK_FREE: t.CDefine = 0 # 空闲
BLOCK_USED: t.CDefine = 1 # 已使用
define BLOCK_FREE = 0 # 空闲
define BLOCK_USED = 1 # 已使用
# 内存类型定义
MEMORY_TYPE_AVAILABLE: uint64 = 7
MEMORY_TYPE_RESERVED: uint64 = 0
MEMORY_TYPE_LOADER_CODE: uint64 = 1
MEMORY_TYPE_LOADER_DATA: uint64 = 2
MEMORY_TYPE_BOOT_SERVICES_CODE: uint64 = 3
MEMORY_TYPE_BOOT_SERVICES_DATA: uint64 = 4
MEMORY_TYPE_RUNTIME_SERVICES_CODE: uint64 = 5
MEMORY_TYPE_RUNTIME_SERVICES_DATA: uint64 = 6
MEMORY_TYPE_ACPI_RECLAIMABLE: uint64 = 9
MEMORY_TYPE_ACPI_NVS: uint64 = 10
MEMORY_TYPE_BAD_MEMORY: uint64 = 8
define MEMORY_TYPE_AVAILABLE: uint64 = 7
define MEMORY_TYPE_RESERVED: uint64 = 0
define MEMORY_TYPE_LOADER_CODE: uint64 = 1
define MEMORY_TYPE_LOADER_DATA: uint64 = 2
define MEMORY_TYPE_BOOT_SERVICES_CODE: uint64 = 3
define MEMORY_TYPE_BOOT_SERVICES_DATA: uint64 = 4
define MEMORY_TYPE_RUNTIME_SERVICES_CODE: uint64 = 5
define MEMORY_TYPE_RUNTIME_SERVICES_DATA: uint64 = 6
define MEMORY_TYPE_ACPI_RECLAIMABLE: uint64 = 9
define MEMORY_TYPE_ACPI_NVS: uint64 = 10
define MEMORY_TYPE_BAD_MEMORY: uint64 = 8
# 内存区域结构
class memory_region(t.CStruct):
class memory_region:
start: uint64
end: uint64
size: uint64
type: uint32
next: 'memory_region' | t.CPtr
next: memory_region*
# 全局内存区域链表
memory_regions: t.CStatic | memory_region | t.CPtr = None
static memory_regions: memory_region* = None
# 内存块结构
class memory_block(t.CStruct):
class memory_block:
size: uint64 # 块大小
state: uint8 # 块状态
order: uint8 # 块阶数
next: 'memory_block' | t.CPtr # 下一个块
prev: 'memory_block' | t.CPtr # 上一个块
next: memory_block* # 下一个块
prev: memory_block* # 上一个块
# 伙伴系统结构
class __buddy_system(t.CStruct):
free_lists: t.CArray[memory_block | t.CPtr, MAX_ORDER + 1]
class __buddy_system:
free_lists: [MAX_ORDER + 1]memory_block*
total_memory: uint64 # 总内存大小
used_memory: uint64 # 已使用内存大小
free_memory: uint64 # 空闲内存大小
start_addr: t.CPtr # 内存起始地址
end_addr: t.CPtr # 内存结束地址
start_addr: rawptr # 内存起始地址
end_addr: rawptr # 内存结束地址
SLAB_MAGIC: t.CDefine = 0x534C4142
SLAB_NUM_SIZES: t.CDefine = 6
SLAB_THRESHOLD: t.CDefine = 1024
define SLAB_MAGIC = 0x534C4142
define SLAB_NUM_SIZES = 6
define SLAB_THRESHOLD = 1024
class slab_page(t.CStruct):
magic: uint32
obj_size: uint16
free_count: uint16
class slab_page:
magic: uint32
obj_size: uint16
free_count: uint16
data_offset: uint16
total_objs: uint16
free_head: t.CPtr
block_ptr: memory_block | t.CPtr
next: 'slab_page' | t.CPtr
prev: 'slab_page' | t.CPtr
total_objs: uint16
free_head: rawptr
block_ptr: memory_block*
next: slab_page*
prev: slab_page*
# 4K对齐函数
@@ -77,7 +75,7 @@ def align_4k(addr: uint64) -> uint64:
return (addr + 0xFFF) & ~0xFFF
# 计算阶数
def get_order(size: uint64) -> t.CStatic | int:
static def get_order(size: uint64) -> int:
order: int = 0
while size > MIN_BLOCK_SIZE:
size >>= 1
@@ -85,31 +83,26 @@ def get_order(size: uint64) -> t.CStatic | int:
return order
# 计算块大小
def get_block_size(order: int) -> t.CStatic | uint64:
static def get_block_size(order: int) -> uint64:
# 4096 << 20 = 4GB 超出 i32 范围 → 0x0 → 伙伴初始化无限循环(bs=0x0)。
# 必须用 64 位移位(4096<<20 = 4294967296)。
return uint64(MIN_BLOCK_SIZE) << uint64(order)
@t.Object
class _BuddySystemObject:
# 全局伙伴系统实例
buddy: __buddy_system
# 初始化伙伴系统
def __init__(self, start_addr: t.CPtr, size: uint64):
def __init__(self, start_addr: rawptr, size: uint64):
for i in range(MAX_ORDER + 1):
self.buddy.free_lists[i] = None
self.buddy.total_memory = size
self.buddy.used_memory = 0
self.buddy.free_memory = size
self.buddy.start_addr = start_addr
self.buddy.end_addr = t.CPtr(uint64(start_addr) + size)
self.buddy.end_addr = rawptr(uint64(start_addr) + size)
remaining: uint64 = size
cur_addr: uint64 = uint64(start_addr)
# [DBG] buddy 初始化循环进度(用后移除)
import drivers.serial.uart.serial as _sdbg
_dbp: t.CArray[t.CChar, 80]
_itc: int = 0
while remaining >= MIN_BLOCK_SIZE:
order: int = 0
tmp: uint64 = remaining
@@ -121,12 +114,7 @@ class _BuddySystemObject:
order -= 1
block_size = get_block_size(order)
if block_size > remaining: break
_itc += 1
if _itc <= 6:
viperlib.snprintf(c.Addr(_dbp), 80, "[mm] it=%d order=%d bs=0x%lx addr=0x%lx rem=%lu\n",
_itc, order, block_size, cur_addr, remaining)
_sdbg.puts(c.Addr(_dbp))
block: memory_block | t.CPtr = t.CPtr(cur_addr)
block: memory_block* = memory_block*(cur_addr)
block.size = block_size
block.state = BLOCK_FREE
block.order = order
@@ -139,28 +127,16 @@ class _BuddySystemObject:
self.buddy.free_lists[order] = block
cur_addr += block_size
remaining -= block_size
_sdbg.puts("[mm] buddy loop done\n")
# DEBUG: print free_lists status after init
import drivers.serial.uart.serial as serial
_dmsg: t.CArray[t.CChar, 40]
serial.puts("[mm] buddy init:")
_di: int = 0
while _di <= MAX_ORDER:
if self.buddy.free_lists[_di]:
viperlib.snprintf(c.Addr(_dmsg), 40, " [%d]=0x%lx", _di, uint64(self.buddy.free_lists[_di]))
serial.puts(_dmsg)
_di += 1
serial.puts("\n")
# 分割内存块
def split_block(self, block: memory_block | t.CPtr, target_order: int) -> memory_block | t.CPtr:
def split_block(self, block: memory_block*, target_order: int) -> memory_block*:
current_order: int = block.order
# 从当前阶数向下分割,直到达到目标阶数
while current_order > target_order:
current_order -= 1
new_block_size: uint64 = get_block_size(current_order)
# 创建新块
new_block: memory_block | t.CPtr = t.CPtr(uint64(block) + new_block_size)
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
@@ -178,16 +154,16 @@ class _BuddySystemObject:
return block
# 合并内存块
def merge_blocks(self, block: memory_block | t.CPtr) -> t.CStatic | memory_block | t.CPtr:
static def merge_blocks(self, block: memory_block*) -> memory_block*:
order: int = block.order
while order < MAX_ORDER:
block_size: uint64 = get_block_size(order)
block_addr: uint64 = uint64(block) - uint64(self.buddy.start_addr)
buddy_addr: uint64 = block_addr ^ block_size
# 计算伙伴块地址
buddy: memory_block | t.CPtr = t.CPtr(uint64(self.buddy.start_addr) + buddy_addr)
buddy: memory_block* = memory_block*(uint64(self.buddy.start_addr) + buddy_addr)
# 检查伙伴块是否存在且空闲
if buddy >= t.CType(self.buddy.end_addr, memory_block, t.CPtr):
if buddy >= memory_block*(self.buddy.end_addr):
break # 伙伴块超出内存范围
if buddy.state != BLOCK_FREE or buddy.order != order:
break # 伙伴块不空闲或阶数不匹配
@@ -197,7 +173,7 @@ class _BuddySystemObject:
if buddy.next:
buddy.next.prev = buddy.prev
# 合并块
merged_block: memory_block | t.CPtr = block if block < buddy else buddy
merged_block: memory_block* = block if block < buddy else buddy
merged_block.size = get_block_size(order + 1)
merged_block.order = order + 1
block = merged_block
@@ -205,7 +181,7 @@ class _BuddySystemObject:
return block
# 分配内存块
def allocate_block(self, size: uint64) -> t.CStatic | memory_block | t.CPtr:
static def allocate_block(self, size: uint64) -> memory_block*:
# 计算所需阶数
order: int = get_order(size)
if order > MAX_ORDER: return None # 所需块大小超过最大限制
@@ -215,29 +191,9 @@ class _BuddySystemObject:
if self.buddy.free_lists[i]:
found_order = i
break
# DEBUG: trace allocate_block
import drivers.serial.uart.serial as serial
_dba: t.CArray[t.CChar, 120]
if found_order == -1:
viperlib.snprintf(c.Addr(_dba), 120, "[mm] alloc FAIL size=%lu order=%d\n", size, order)
serial.puts(_dba)
_dbf: t.CArray[t.CChar, 200]
_fi: int = 0
_fo: int = 0
while _fi <= MAX_ORDER:
if self.buddy.free_lists[_fi]:
_fs: int = viperlib.snprintf(c.Addr(_dbf) + _fo, 200 - _fo, "[%d]=0x%lx ", _fi, uint64(self.buddy.free_lists[_fi]))
_fo = _fo + _fs
_fi += 1
if _fo == 0:
serial.puts("[mm] all free_lists EMPTY\n")
else:
serial.puts(_dbf)
serial.puts("\n")
return None
if found_order == -1: return None # 没有合适的空闲块
if found_order == -1: return None
# 取出空闲块
block: memory_block | t.CPtr = self.buddy.free_lists[found_order]
block: memory_block* = self.buddy.free_lists[found_order]
# 从空闲链表中移除块
if block.next: block.next.prev = None
self.buddy.free_lists[found_order] = block.next
@@ -249,12 +205,10 @@ class _BuddySystemObject:
# 更新内存统计
self.buddy.used_memory += block.size
self.buddy.free_memory -= block.size
viperlib.snprintf(c.Addr(_dba), 120, "[mm] alloc OK size=%lu order=%d found=%d block=0x%lx\n", size, order, found_order, uint64(block))
serial.puts(_dba)
return block
# 释放内存块
def free_block(self, block: memory_block | t.CPtr):
def free_block(self, block: memory_block*):
# 标记块为空闲
block.state = BLOCK_FREE
# 更新内存统计
@@ -290,50 +244,50 @@ def _slab_size_class(size: uint64) -> int:
if size <= 1024: return 5
return -1
def _slab_read_ptr(addr: t.CPtr) -> t.CPtr:
result: t.CPtr
c.Asm(f"""mov rax, [{c.AsmInp(addr, t.ASM_DESCR.REG_ANY)}]
mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
def _slab_read_ptr(addr: rawptr) -> rawptr:
result: rawptr
__asm__(f"""mov rax, [{asminp(addr, ASM_DESCR.REG_ANY)}]
mov {asmout(result, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
return result
def _slab_write_ptr(addr: t.CPtr, val: t.CPtr):
c.Asm(f"""mov rax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)}
mov [{c.AsmInp(addr, t.ASM_DESCR.REG_ANY)}], rax""",
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_MEMORY])
def _slab_write_ptr(addr: rawptr, val: rawptr):
__asm__(f"""mov rax, {asminp(val, ASM_DESCR.REG_ANY)}
mov [{asminp(addr, ASM_DESCR.REG_ANY)}], rax""",
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_MEMORY])
def _slab_find_page(ptr: t.CPtr) -> slab_page | t.CPtr:
def _slab_find_page(ptr: rawptr) -> slab_page*:
if ptr is None: return None
hdr_off: uint64 = memory_block.__sizeof__()
page_addr: uint64 = uint64(ptr) & ~uint64(0xFFF)
page: slab_page | t.CPtr = t.CPtr(page_addr + hdr_off)
page: slab_page* = slab_page*(page_addr + hdr_off)
if page.magic == SLAB_MAGIC:
os: uint16 = page.obj_size
if os == 32 or os == 64 or os == 128 or os == 256 or os == 512 or os == 1024:
return page
page_addr2: uint64 = page_addr - 4096
page2: slab_page | t.CPtr = t.CPtr(page_addr2 + hdr_off)
page2: slab_page* = slab_page*(page_addr2 + hdr_off)
if page2.magic == SLAB_MAGIC:
os2: uint16 = page2.obj_size
if os2 == 32 or os2 == 64 or os2 == 128 or os2 == 256 or os2 == 512 or os2 == 1024:
return page2
return None
@t.Object
class _SlabAllocator:
caches: t.CArray[slab_page | t.CPtr, SLAB_NUM_SIZES]
caches: [SLAB_NUM_SIZES]slab_page*
def __init__(self):
for i in range(SLAB_NUM_SIZES):
self.caches[i] = None
def _create_page(self, size_class: int) -> slab_page | t.CPtr:
def _create_page(self, size_class: int) -> slab_page*:
obj_size: uint16 = _slab_obj_size(size_class)
aligned_size: uint16 = uint16((obj_size + 15) & ~15)
block: memory_block | t.CPtr = BuddySystemObject.allocate_block(4096 + memory_block.__sizeof__())
block: memory_block* = BuddySystemObject.allocate_block(4096 + memory_block.__sizeof__())
if not block: return None
hdr_off: uint64 = memory_block.__sizeof__()
page: slab_page | t.CPtr = t.CPtr(uint64(block) + hdr_off)
page: slab_page* = slab_page*(uint64(block) + hdr_off)
page.magic = SLAB_MAGIC
page.obj_size = aligned_size
d_off: uint16 = uint16((hdr_off + slab_page.__sizeof__() + 15) & ~15)
@@ -345,17 +299,17 @@ class _SlabAllocator:
page.next = None
page.prev = None
data_start: uint64 = uint64(block) + d_off
page.free_head = t.CPtr(data_start)
page.free_head = rawptr(data_start)
for i in range(1, total):
cur: t.CPtr = t.CPtr(data_start + uint64(i - 1) * aligned_size)
nxt: t.CPtr = t.CPtr(data_start + uint64(i) * aligned_size)
cur: rawptr = rawptr(data_start + uint64(i - 1) * aligned_size)
nxt: rawptr = rawptr(data_start + uint64(i) * aligned_size)
_slab_write_ptr(cur, nxt)
last: t.CPtr = t.CPtr(data_start + uint64(total - 1) * aligned_size)
_slab_write_ptr(last, t.CPtr(0))
last: rawptr = rawptr(data_start + uint64(total - 1) * aligned_size)
_slab_write_ptr(last, None)
return page
def alloc(self, size_class: int) -> t.CPtr:
page: slab_page | t.CPtr = self.caches[size_class]
def alloc(self, size_class: int) -> rawptr:
page: slab_page* = self.caches[size_class]
while page:
if page.free_count > 0: break
page = page.next
@@ -366,12 +320,12 @@ class _SlabAllocator:
if self.caches[size_class]:
self.caches[size_class].prev = page
self.caches[size_class] = page
obj: t.CPtr = page.free_head
obj: rawptr = page.free_head
page.free_head = _slab_read_ptr(obj)
page.free_count -= 1
return obj
def free_obj(self, ptr: t.CPtr, page: slab_page | t.CPtr):
def free_obj(self, ptr: rawptr, page: slab_page*):
_slab_write_ptr(ptr, page.free_head)
page.free_head = ptr
page.free_count += 1
@@ -391,12 +345,12 @@ SlabAllocator: _SlabAllocator
# 内存分配函数
def malloc(size: uint64) -> t.CPtr | t.CExport:
export def malloc(size: uint64) -> rawptr:
if size == 0: return None
if size <= SLAB_THRESHOLD:
sc: int = _slab_size_class(size)
if sc >= 0:
result: t.CPtr = SlabAllocator.alloc(sc)
result: rawptr = SlabAllocator.alloc(sc)
return result
hdr: uint64 = memory_block.__sizeof__()
if size >= 4096:
@@ -404,84 +358,78 @@ def malloc(size: uint64) -> t.CPtr | t.CExport:
total = align_4k(total)
order: int = get_order(total)
if order > MAX_ORDER: return None
block: memory_block | t.CPtr = BuddySystemObject.allocate_block(total)
import drivers.serial.uart.serial as serial
_dbm: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbm), 120, "[mm] malloc buddy size=%lu block=0x%lx\n", size, uint64(block))
serial.puts(_dbm)
block: memory_block* = BuddySystemObject.allocate_block(total)
if not block: return None
user_ptr: uint64 = (uint64(block) + hdr + 4095) & ~uint64(4095)
real_hdr: uint64 = user_ptr - 8
c.Asm(f"""mov rax, {c.AsmInp(block, t.ASM_DESCR.REG_ANY)}
mov [{c.AsmInp(t.CPtr(real_hdr), t.ASM_DESCR.REG_ANY)}], rax""",
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_MEMORY])
viperlib.snprintf(c.Addr(_dbm), 120, "[mm] malloc ret user_ptr=0x%lx\n", user_ptr)
serial.puts(_dbm)
return t.CPtr(user_ptr)
__asm__(f"""mov rax, {asminp(block, ASM_DESCR.REG_ANY)}
mov [{asminp(rawptr(real_hdr), ASM_DESCR.REG_ANY)}], rax""",
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_MEMORY])
return rawptr(user_ptr)
total2: uint64 = size + hdr
total2 = align_4k(total2)
order2: int = get_order(total2)
if order2 > MAX_ORDER: return None
block2: memory_block | t.CPtr = BuddySystemObject.allocate_block(total2)
block2: memory_block* = BuddySystemObject.allocate_block(total2)
if not block2: return None
return t.CPtr(uint64(block2) + hdr)
return rawptr(uint64(block2) + hdr)
def malloc_direct(size: uint64) -> t.CPtr | t.CExport:
export def malloc_direct(size: uint64) -> rawptr:
if size == 0: return None
hdr: uint64 = memory_block.__sizeof__()
total: uint64 = size + hdr
total = align_4k(total)
order: int = get_order(total)
if order > MAX_ORDER: return None
block: memory_block | t.CPtr = BuddySystemObject.allocate_block(total)
block: memory_block* = BuddySystemObject.allocate_block(total)
if not block: return None
return t.CPtr(uint64(block) + hdr)
return rawptr(uint64(block) + hdr)
def free(ptr: t.CPtr) -> t.CExport:
export def free(ptr: rawptr):
if ptr is None: return
sp: slab_page | t.CPtr = _slab_find_page(ptr)
sp: slab_page* = _slab_find_page(ptr)
if sp:
SlabAllocator.free_obj(ptr, sp)
return
if (uint64(ptr) & 0xFFF) == 0:
real_hdr: uint64 = uint64(ptr) - 8
block: memory_block | t.CPtr
c.Asm(f"""mov rax, [{c.AsmInp(t.CPtr(real_hdr), t.ASM_DESCR.REG_ANY)}]
mov {c.AsmOut(block, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
block: memory_block*
__asm__(f"""mov rax, [{asminp(rawptr(real_hdr), ASM_DESCR.REG_ANY)}]
mov {asmout(block, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
BuddySystemObject.free_block(block)
return
block2: memory_block | t.CPtr = t.CPtr(uint64(ptr) - memory_block.__sizeof__())
block2: memory_block* = rawptr(uint64(ptr) - memory_block.__sizeof__())
BuddySystemObject.free_block(block2)
def calloc(nmemb: uint64, size: uint64) -> t.CPtr | t.CExport:
export def calloc(nmemb: uint64, size: uint64) -> rawptr:
total_size: uint64 = nmemb * size
ptr: t.CPtr = malloc(total_size)
ptr: rawptr = malloc(total_size)
if ptr:
string.memset(ptr, 0, total_size)
return ptr
def realloc(ptr: t.CPtr, size: uint64) -> t.CPtr | t.CExport:
export def realloc(ptr: rawptr, size: uint64) -> rawptr:
if ptr is None: return malloc(size)
if size == 0:
free(ptr)
return None
new_ptr: t.CPtr = malloc(size)
new_ptr: rawptr = malloc(size)
if not new_ptr: return None
sp: slab_page | t.CPtr = _slab_find_page(ptr)
sp: slab_page* = _slab_find_page(ptr)
if sp:
old_size: uint64 = sp.obj_size
elif (uint64(ptr) & 0xFFF) == 0:
real_hdr_r: uint64 = uint64(ptr) - 8
block_r: memory_block | t.CPtr
c.Asm(f"""mov rax, [{c.AsmInp(t.CPtr(real_hdr_r), t.ASM_DESCR.REG_ANY)}]
mov {c.AsmOut(block_r, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
block_r: memory_block*
__asm__(f"""mov rax, [{asminp(rawptr(real_hdr_r), ASM_DESCR.REG_ANY)}]
mov {asmout(block_r, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
old_size = block_r.size - 4096
else:
block2: memory_block | t.CPtr = t.CPtr(uint64(ptr) - memory_block.__sizeof__())
block2: memory_block* = rawptr(uint64(ptr) - memory_block.__sizeof__())
old_size = block2.size - memory_block.__sizeof__()
copy_size: uint64 = old_size if old_size < size else size
string.memcpy(new_ptr, ptr, copy_size)
@@ -492,9 +440,9 @@ def realloc(ptr: t.CPtr, size: uint64) -> t.CPtr | t.CExport:
# 回收内存区域链表
def free_memory_regions():
global memory_regions
current: memory_region | t.CPtr = memory_regions
current: memory_region* = memory_regions
while current:
next_region: memory_region | t.CPtr = current.next
next_region: memory_region* = current.next
free(current)
current = next_region
memory_regions = None
@@ -502,23 +450,12 @@ def free_memory_regions():
# 初始化内存管理系统
def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0):
global BuddySystemObject
import drivers.serial.uart.serial as serial
# [DBG] 无条件打印 memmap 三参数,判定分支未走的根因(用后移除)
_dk0: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(_dk0), 100, "[mm] raw addr=0x%lx size=%lu desc=%lu\n",
MemmapAddr, MemmapSize, MemmapDescSize)
serial.puts(c.Addr(_dk0))
start_addr: t.CPtr = None
start_addr: rawptr = None
size: uint64 = 0
if MemmapAddr != 0:
if MemmapSize > 0:
if MemmapDescSize > 0:
num_entries: uint64 = MemmapSize / MemmapDescSize
# [DBG] 关键数值:memmap 缓冲/步长/条目数(用后移除)
_dk1: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(_dk1), 100, "[mm] addr=0x%lx size=%lu desc=%lu entries=%lu\n",
MemmapAddr, MemmapSize, MemmapDescSize, num_entries)
serial.puts(c.Addr(_dk1))
max_memory: uint64 = 0
best_start: uint64 = 0
best_avail_size: uint64 = 0
@@ -527,16 +464,8 @@ def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr:
best_bs_start: uint64 = 0
best_ld_size: uint64 = 0
best_ld_start: uint64 = 0
i: uint64
# [DBG] 转储全部 memmap 描述符,定位 4GB 伪可用区的来源(用后移除)
for i in range(num_entries):
entry: bootinfo.memory_map_entry | t.CPtr = t.CPtr(MemmapAddr + i * MemmapDescSize)
_dbgd: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(_dbgd), 100, "[mm] d[%lu] t=%lu start=0x%lx np=%lu\n",
i, uint64(entry.type), entry.physical_start, entry.num_pages)
serial.puts(c.Addr(_dbgd))
for i in range(num_entries):
entry: bootinfo.memory_map_entry | t.CPtr = t.CPtr(MemmapAddr + i * MemmapDescSize)
entry: bootinfo.memory_map_entry* = bootinfo.memory_map_entry*(MemmapAddr + i * MemmapDescSize)
etype: uint64 = entry.type
start: uint64 = align_4k(entry.physical_start)
np: uint64 = entry.num_pages
@@ -569,72 +498,54 @@ def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr:
elif best_ld_size >= min_blk:
best_start = best_ld_start
max_memory = best_ld_size
cr4: t.CArray[t.CChar, 128]
string.memset(c.Addr(cr4), 0, 128)
viperlib.snprintf(c.Addr(cr4), 128, "mm: best=0x%lx max=%lu entries=%lu avail=%lu bs=%lu ld=%lu\n",
best_start, max_memory, num_entries, best_avail_size, best_bs_size, best_ld_size)
serial.puts(cr4)
if best_start != 0:
if max_memory >= min_blk:
start_addr = t.CPtr(best_start)
start_addr = rawptr(best_start)
size = max_memory
if start_addr is None:
# [DBG] fallback:打印 detect_memory_size 与 CMOS 原始值(用后移除)
_dc0: t.CArray[t.CChar, 100]
viperlib.snprintf(c.Addr(_dc0), 100, "[mm] fallback cmos 0x%02x 0x%02x 0x%02x 0x%02x\n",
cmos_read(0x15), cmos_read(0x16), cmos_read(0x17), cmos_read(0x18))
serial.puts(c.Addr(_dc0))
_dsz: uint64 = detect_memory_size()
viperlib.snprintf(c.Addr(_dc0), 100, "[mm] fallback detect=%lu\n", _dsz)
serial.puts(c.Addr(_dc0))
size = detect_memory_size()
size = align_4k(size)
# 起始地址 4MB(内核之后),避免超出物理 RAM
# 旧值 0x10000000 在 256MB QEMU 中超出物理 RAM 边界
start_addr = t.CPtr(align_4k(0x400000))
start_addr = rawptr(align_4k(0x400000))
if size > 0x400000:
size = size - 0x400000
size = align_4k(size)
min_blk2: uint64 = MIN_BLOCK_SIZE
if size < min_blk2:
size = 33554432
cr2: t.CArray[t.CChar, 128]
string.memset(c.Addr(cr2), 0, 128)
viperlib.snprintf(c.Addr(cr2), 128, "mm.init: start=0x%lx size=%lu bytes\n",
uint64(start_addr), size)
serial.puts(cr2)
BuddySystemObject.__init__(start_addr, size)
SlabAllocator.__init__()
# 虚拟内存映射结构
class vm_area(t.CStruct):
class vm_area:
VirtAddr: uint64
PhysAddr: uint64
size: uint64
flags: uint32
next: 'vm_area' | t.CPtr
next: vm_area*
# 全局虚拟内存区域链表
vm_areas: vm_area | t.CPtr = None
vm_areas: vm_area* = None
# 博弈机制参数
ALLOCATION_RETRIES: t.CDefine = 5 # 分配重试次数
FRAGMENTATION_THRESHOLD: t.CDefine = 0.7 # 碎片率阈值
define ALLOCATION_RETRIES = 5 # 分配重试次数
define FRAGMENTATION_THRESHOLD = 0.7 # 碎片率阈值
# 获取内存使用统计
@c.CReturn(uint64, uint64, uint64)
def GetMemoryStats():
return (BuddySystemObject.buddy.total_memory, BuddySystemObject.buddy.used_memory, BuddySystemObject.buddy.free_memory)
def GetMemoryStats() -> tuple[uint64, uint64, uint64]:
return BuddySystemObject.buddy.total_memory, BuddySystemObject.buddy.used_memory, BuddySystemObject.buddy.free_memory
# 计算内存碎片率
def calculate_fragmentation() -> t.CDouble:
def calculate_fragmentation() -> double:
# 计算空闲块的数量和总大小
free_blocks: int = 0
free_size: uint64 = 0
for i in range(MAX_ORDER + 1):
block: memory_block | t.CPtr = BuddySystemObject.buddy.free_lists[i]
block: memory_block* = BuddySystemObject.buddy.free_lists[i]
while block:
free_blocks += 1
free_size += block.size
@@ -655,15 +566,15 @@ def calculate_fragmentation() -> t.CDouble:
if max_free_block == 0:
return 1.0
return 1.0 - (t.CDouble(max_free_block) / t.CDouble(free_size))
return 1.0 - (double(max_free_block) / double(free_size))
# 内存整理函数
def compact_memory() -> t.CStatic | int:
static def compact_memory() -> int:
freed_pages: int = 0
for sc in range(SLAB_NUM_SIZES):
page: slab_page | t.CPtr = SlabAllocator.caches[sc]
page: slab_page* = SlabAllocator.caches[sc]
while page:
next_page: slab_page | t.CPtr = page.next
next_page: slab_page* = page.next
if page.free_count == page.total_objs:
if page.prev:
page.prev.next = page.next
@@ -682,77 +593,59 @@ def vm_alloc(size: uint64, flags: uint32) -> uint64:
global vm_areas
# 4K对齐
size = align_4k(size)
# 尝试分配物理内存,使用博弈机制
PhysAddr: t.CPtr = None
retries: int = 0
while retries < ALLOCATION_RETRIES:
PhysAddr: rawptr = None
for retries in range(ALLOCATION_RETRIES):
PhysAddr = malloc(size)
if PhysAddr:
break
# 内存不足,尝试进行内存整理
if calculate_fragmentation() > FRAGMENTATION_THRESHOLD:
compact_memory()
retries += 1
if not PhysAddr:
return 0
if not PhysAddr: return 0
# 分配虚拟地址
# 简单的虚拟地址分配策略:从0x100000000开始
VirtAddr: uint64 = 0x100000000
current: vm_area | t.CPtr = vm_areas
current: vm_area* = vm_areas
# 寻找合适的虚拟地址空间
while current:
if VirtAddr + size <= current.VirtAddr:
break
if VirtAddr + size <= current.VirtAddr: break
VirtAddr = current.VirtAddr + current.size
current = current.next
# 创建虚拟内存区域
area: vm_area | t.CPtr = malloc(vm_area.__sizeof__())
area: vm_area* = malloc(vm_area.__sizeof__())
if area:
area.VirtAddr = VirtAddr
area.PhysAddr = uint64(PhysAddr)
area.size = size
area.size = size
area.flags = flags
area.next = vm_areas
vm_areas = area
area.next = vm_areas
vm_areas = area
# 映射虚拟地址到物理地址
# 计算需要映射的页数
pages: uint64 = size / 4096
i: uint64
for i in range(pages):
page_virt: uint64 = VirtAddr + (i * 4096)
page_phys: uint64 = uint64(PhysAddr) + (i * 4096)
# 调用paging模块的映射函数
paging.MapPage(page_virt, page_phys, flags)
return VirtAddr
# 虚拟内存释放函数
def vm_free(VirtAddr: uint64):
global vm_areas
# 查找虚拟内存区域
current: vm_area | t.CPtr = vm_areas
prev: vm_area | t.CPtr = None
current: vm_area* = vm_areas
prev: vm_area* = None
while current:
if current.VirtAddr == VirtAddr:
# 取消虚拟地址映射
pages: uint64 = current.size / 4096
i: uint64
for i in range(pages):
page_virt: uint64 = current.VirtAddr + (i * 4096)
paging.UnMapPage(page_virt)
# 释放物理内存
free(t.CPtr(current.PhysAddr))
free(rawptr(current.PhysAddr))
if prev:
prev.next = current.next
else:
@@ -766,15 +659,15 @@ def vm_free(VirtAddr: uint64):
def cmos_read(reg: uint8) -> uint8:
# in/out al 会改 EAX,必须 CLOBBER_RAX;显式 mov 到输出寄存器
#(与 asm.inb/inw 修复同模式,避免调用方 EAX 被静默破坏)。
c.Asm(f"""mov eax, {c.AsmInp(uint32(reg), t.ASM_DESCR.REG_ANY)}
__asm__(f"""mov eax, {asminp(uint32(reg), ASM_DESCR.REG_ANY)}
out 0x70, al""",
op=[t.ASM_DESCR.CLOBBER_RAX])
op=[ASM_DESCR.CLOBBER_RAX])
val32: uint32
c.Asm(f"""in al, 0x71
__asm__(f"""in al, 0x71
movzx eax, al
mov {c.AsmOut(val32, t.ASM_DESCR.OUTPUT_REG)}, eax""",
out=[c.AsmOut(val32, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_RAX])
mov {asmout(val32, ASM_DESCR.OUTPUT_REG)}, eax""",
out=[asmout(val32, ASM_DESCR.OUTPUT_REG)],
op=[ASM_DESCR.CLOBBER_RAX])
return uint8(val32)
# 内存大小测试函数
@@ -783,27 +676,20 @@ def detect_memory_size() -> uint64:
low: uint8 = cmos_read(0x15)
high: uint8 = cmos_read(0x16)
mem_kb: uint32 = (uint32(high) << 8) | low
# 读取 16MB 以上扩展内存(64KB 块为单位)
low2: uint8 = cmos_read(0x17)
high2: uint8 = cmos_read(0x18)
mem_above_16mb: uint32 = (uint32(high2) << 8) | low2
# 两个寄存器都为 0 时使用默认值
if mem_kb == 0 and mem_above_16mb == 0:
return 0x10000000 # 256MB
if mem_kb == 0 and mem_above_16mb == 0: return 0x10000000 # 256MB
# 计算总内存:1MB 基础 + 1MB-16MB + 16MB 以上
total_size: uint64 = 1048576 # 前 1MB
if mem_kb > 0:
total_size = total_size + uint64(mem_kb) * 1024
if mem_above_16mb > 0:
total_size = total_size + uint64(mem_above_16mb) * 65536
total_size = align_4k(total_size)
# 确保内存大小至少为32MB
if total_size < 33554432: # 32MB
total_size = 33554432
return total_size
+116 -125
View File
@@ -1,31 +1,30 @@
import drivers.serial.uart.serial as serial
import viperlib
import t, c
PTE_PRESENT: t.CDefine = (1 << 0)
PTE_WRITABLE: t.CDefine = (1 << 1)
PTE_USER: t.CDefine = (1 << 2)
PTE_PWT: t.CDefine = (1 << 3)
PTE_PCD: t.CDefine = (1 << 4)
PTE_ACCESSED: t.CDefine = (1 << 5)
PTE_DIRTY: t.CDefine = (1 << 6)
PTE_PS: t.CDefine = (1 << 7)
PTE_GLOBAL: t.CDefine = (1 << 8)
define PTE_PRESENT = (1 << 0)
define PTE_WRITABLE = (1 << 1)
define PTE_USER = (1 << 2)
define PTE_PWT = (1 << 3)
define PTE_PCD = (1 << 4)
define PTE_ACCESSED = (1 << 5)
define PTE_DIRTY = (1 << 6)
define PTE_PS = (1 << 7)
define PTE_GLOBAL = (1 << 8)
class _p:
entries: t.CArray[uint64, 512]
entries: [512]uint64
PT_POOL_PAGES: t.CDefine = 512
pt_pool_raw: t.CPtr = None
define PT_POOL_PAGES = 512
pt_pool_raw: rawptr = None
pt_pool_start: uint64 = 0
pt_pool_used: uint64 = 0
pt_pool_used: uint64 = 0
AllocatedPages: uint64 = 0
pml4: _p | t.CPtr = None
pdp: _p | t.CPtr
pd: _p | t.CPtr
pt: _p | t.CPtr
pml4: _p* = None
pdp: _p*
pd: _p*
pt: _p*
def init(MemmapAddr: uint64, MemmapSize: uint64):
global pml4
@@ -34,19 +33,19 @@ def init(MemmapAddr: uint64, MemmapSize: uint64):
# (pml4/pdp/pd/pt,0xf8xxxx)默认只读,而内核运行时 MapPage/clone 需
# 修改页表。顺序:先清 WP(允许写只读页表页)→ MakePTWritable 放开
# 全部页表页 → 再置 WP=1(此后写只读页即 #PF 暴露越界写源)。
c.Asm(f"""
__asm__(f"""
mov rax, cr0
and rax, ~0x10000
mov cr0, rax
""")
MakePTWritable()
c.Asm(f"""
__asm__(f"""
mov rax, cr0
or rax, 0x10000
mov cr0, rax
""")
def init_pool(buf: t.CPtr, buf_size: uint64):
def init_pool(buf: rawptr, buf_size: uint64):
global pt_pool_raw, pt_pool_start, pt_pool_used
pt_pool_raw = buf
if buf is None: return
@@ -54,29 +53,25 @@ def init_pool(buf: t.CPtr, buf_size: uint64):
aligned_addr: uint64 = (raw_addr + uint64(0xFFF)) & ~uint64(0xFFF)
pt_pool_start = aligned_addr
pt_pool_used = 0
# [DIAG] 定位 clone 时 pt_pool_raw=0x0(init 后被覆盖?还是 init 收到 0)
_dip: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(_dip), 80, "[paging] init_pool raw=0x%lx start=0x%lx\n", uint64(pt_pool_raw), pt_pool_start)
serial.puts(c.Addr(_dip))
def AllocPage() -> t.CPtr:
def AllocPage() -> rawptr:
global AllocatedPages, pt_pool_used, pml4, pdp, pd, pt
if pt_pool_raw is None: return None
if pt_pool_used >= uint64(PT_POOL_PAGES): return None
page: t.CPtr = t.CPtr(pt_pool_start + pt_pool_used * uint64(4096))
page: rawptr = rawptr(pt_pool_start + pt_pool_used * uint64(4096))
pt_pool_used = pt_pool_used + uint64(1)
# rep stosb 向 [rdi] 写 4096 字节:必须声明 CLOBBER_MEMORY,否则优化器
# 无法得知本块改写了内存,可能把其前后的内存读写重排/消除(N8)。
c.Asm(f"""mov al, 0
__asm__(f"""mov al, 0
mov ecx, 4096
mov rdi, {c.AsmInp(page, t.ASM_DESCR.REG_ANY)}
mov rdi, {asminp(page, ASM_DESCR.REG_ANY)}
rep stosb""",
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_AL,
t.ASM_DESCR.CLOBBER_ECX, t.ASM_DESCR.CLOBBER_RDI])
op = [ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_AL,
ASM_DESCR.CLOBBER_ECX, ASM_DESCR.CLOBBER_RDI])
AllocatedPages = AllocatedPages + uint64(1)
return page
def FreePage(page: t.CPtr):
def FreePage(page: rawptr):
global AllocatedPages, pml4, pdp, pd, pt
if page is None: return
if AllocatedPages > 0: AllocatedPages = AllocatedPages - uint64(1)
@@ -96,28 +91,28 @@ def MapPage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64):
if not pml4: return
if not (pml4.entries[Pml4Index] & PTE_PRESENT):
pdp: _p | t.CPtr = AllocPage()
pdp = AllocPage()
if not pdp: return
pml4.entries[Pml4Index] = (uint64(pdp) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER)
else:
if (flags & PTE_USER) and not (pml4.entries[Pml4Index] & PTE_USER):
pml4.entries[Pml4Index] = pml4.entries[Pml4Index] | PTE_USER
pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr)
pdp = _p*(pml4.entries[Pml4Index] & ~uint64(0xFFF))
if not (pdp.entries[PdpIndex] & PTE_PRESENT):
pd: _p | t.CPtr = AllocPage()
pd = AllocPage()
if not pd: return
pdp.entries[PdpIndex] = (uint64(pd) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER)
else:
if (flags & PTE_USER) and not (pdp.entries[PdpIndex] & PTE_USER):
pdp.entries[PdpIndex] = pdp.entries[PdpIndex] | PTE_USER
pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr)
pd = _p*(pdp.entries[PdpIndex] & ~uint64(0xFFF))
if pd.entries[PdIndex] & 1:
if pd.entries[PdIndex] & 0x80:
big_phys: uint64 = pd.entries[PdIndex] & ~uint64(0x1FFFFF)
inherit_flags: uint64 = pd.entries[PdIndex] & (PTE_PCD | PTE_PWT)
pt: _p | t.CPtr = AllocPage()
pt = AllocPage()
if not pt: return
split_i: int = 0
while split_i < 512:
@@ -131,13 +126,13 @@ def MapPage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64):
if (flags & PTE_USER) and not (pd.entries[PdIndex] & PTE_USER):
pd.entries[PdIndex] = pd.entries[PdIndex] | PTE_USER
else:
pt: _p | t.CPtr = AllocPage()
pt = AllocPage()
if not pt: return
pd.entries[PdIndex] = (uint64(pt) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (flags & PTE_USER)
pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~uint64(0xFFF), _p, t.CPtr)
pt = _p*(pd.entries[PdIndex] & ~uint64(0xFFF))
pt.entries[PtIndex] = PhysAddr | flags | PTE_PRESENT
c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(VirtAddr, ASM_DESCR.REG_ANY)}]")
def MapLargePage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64):
global pml4, pdp, pd, pt
@@ -152,19 +147,19 @@ def MapLargePage(VirtAddr: uint64, PhysAddr: uint64, flags: uint64):
if not pml4: return
if not pml4.entries[Pml4Index] & PTE_PRESENT:
pdp: _p | t.CPtr = AllocPage()
pdp = AllocPage()
if not pdp: return
pml4.entries[Pml4Index] = (uint64(pdp) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE
pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr)
pdp = _p*(pml4.entries[Pml4Index] & ~uint64(0xFFF))
if not (pdp.entries[PdpIndex] & PTE_PRESENT):
pd: _p | t.CPtr = AllocPage()
pd = AllocPage()
if not pd: return
pdp.entries[PdpIndex] = (uint64(pd) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE
pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr)
pd = _p*(pdp.entries[PdpIndex] & ~uint64(0xFFF))
pd.entries[PdIndex] = PhysAddr | flags | PTE_PRESENT | PTE_PS
c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(VirtAddr, ASM_DESCR.REG_ANY)}]")
def UnMapPage(VirtAddr: uint64):
global pml4, pdp, pd, pt
@@ -177,24 +172,24 @@ def UnMapPage(VirtAddr: uint64):
if not pml4.entries[Pml4Index] & PTE_PRESENT: return
pdp: _p | t.CPtr = t.CType(pml4.entries[Pml4Index] & ~uint64(0xFFF), _p, t.CPtr)
pdp = _p*(pml4.entries[Pml4Index] & ~uint64(0xFFF))
if not pdp.entries[PdpIndex] & PTE_PRESENT: return
pd: _p | t.CPtr = t.CType(pdp.entries[PdpIndex] & ~uint64(0xFFF), _p, t.CPtr)
pd = _p*(pdp.entries[PdpIndex] & ~uint64(0xFFF))
if not pd.entries[PdIndex] & PTE_PRESENT: return
if pd.entries[PdIndex] & PTE_PS:
pd.entries[PdIndex] = 0
else:
pt: _p | t.CPtr = t.CType(pd.entries[PdIndex] & ~uint64(0xFFF), _p, t.CPtr)
pt = _p*(pd.entries[PdIndex] & ~uint64(0xFFF))
pt.entries[PtIndex] = 0
c.Asm(f"invlpg [{c.AsmInp(VirtAddr, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(VirtAddr, ASM_DESCR.REG_ANY)}]")
def EnablePaging():
global pml4, pdp, pd, pt
c.Asm(f"mov cr3, {c.AsmInp(uint64(pml4), t.ASM_DESCR.REG_ANY)}")
__asm__(f"mov cr3, {asminp(uint64(pml4), ASM_DESCR.REG_ANY)}")
def _set_page_writable(phys_addr: uint64):
"""把物理页 phys_addr(identity 映射,虚拟=物理)的 PTE 置 W 位
@@ -209,21 +204,21 @@ def _set_page_writable(phys_addr: uint64):
va: uint64 = phys_addr & ~uint64(0xFFF)
pml4_idx: uint64 = (va >> 39) & 0x1FF
if not (pml4.entries[pml4_idx] & PTE_PRESENT): return
pdp_s: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr)
pdp_s: _p* = _p*(pml4.entries[pml4_idx] & ~uint64(0xFFF))
pdp_idx: uint64 = (va >> 30) & 0x1FF
if not (pdp_s.entries[pdp_idx] & PTE_PRESENT): return
pd_s: _p | t.CPtr = t.CType(pdp_s.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr)
pd_s: _p* = _p*(pdp_s.entries[pdp_idx] & ~uint64(0xFFF))
pd_idx: uint64 = (va >> 21) & 0x1FF
if not (pd_s.entries[pd_idx] & PTE_PRESENT): return
if pd_s.entries[pd_idx] & PTE_PS:
# 2MB 大页:W 位在 PD 条目自身(无下层 PT),直接置位
pd_s.entries[pd_idx] = pd_s.entries[pd_idx] | uint64(PTE_WRITABLE)
c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(va, ASM_DESCR.REG_ANY)}]")
return
pt_s: _p | t.CPtr = t.CType(pd_s.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
pt_s: _p* = _p*(pd_s.entries[pd_idx] & ~uint64(0xFFF))
pt_idx: uint64 = (va >> 12) & 0x1FF
pt_s.entries[pt_idx] = pt_s.entries[pt_idx] | uint64(PTE_WRITABLE)
c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(va, ASM_DESCR.REG_ANY)}]")
def MakePTWritable():
"""把当前页表层次所有页表页(pml4 自身 + pdp/pd/pt)设为可写
@@ -234,21 +229,20 @@ def MakePTWritable():
global pml4
if not pml4: return
_set_page_writable(uint64(pml4))
pi: uint64
for pi in range(512):
if not (pml4.entries[pi] & PTE_PRESENT): continue
pdp_m: _p | t.CPtr = t.CType(pml4.entries[pi] & ~uint64(0xFFF), _p, t.CPtr)
pdp_m: _p* = _p*(pml4.entries[pi] & ~uint64(0xFFF))
_set_page_writable(uint64(pdp_m))
pj: uint64
for pj in range(512):
if not (pdp_m.entries[pj] & PTE_PRESENT): continue
pd_m: _p | t.CPtr = t.CType(pdp_m.entries[pj] & ~uint64(0xFFF), _p, t.CPtr)
pd_m: _p* = _p*(pdp_m.entries[pj] & ~uint64(0xFFF))
_set_page_writable(uint64(pd_m))
pk: uint64
for pk in range(512):
if not (pd_m.entries[pk] & PTE_PRESENT): continue
if pd_m.entries[pk] & PTE_PS: continue
pt_m: _p | t.CPtr = t.CType(pd_m.entries[pk] & ~uint64(0xFFF), _p, t.CPtr)
pt_m: _p* = _p*(pd_m.entries[pk] & ~uint64(0xFFF))
_set_page_writable(uint64(pt_m))
def MakeRangeRO(vaddr_start: uint64, vaddr_end: uint64):
@@ -269,10 +263,10 @@ def MakeRangeRO(vaddr_start: uint64, vaddr_end: uint64):
while va < ro_end_align:
pml4_idx: uint64 = (va >> 39) & 0x1FF
if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue
pdp_r: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr)
pdp_r: _p* = _p*(pml4.entries[pml4_idx] & ~uint64(0xFFF))
pdp_idx: uint64 = (va >> 30) & 0x1FF
if not (pdp_r.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue
pd_r: _p | t.CPtr = t.CType(pdp_r.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr)
pd_r: _p* = _p*(pdp_r.entries[pdp_idx] & ~uint64(0xFFF))
pd_idx: uint64 = (va >> 21) & 0x1FF
if not (pd_r.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue
if pd_r.entries[pd_idx] & PTE_PS:
@@ -282,29 +276,27 @@ def MakeRangeRO(vaddr_start: uint64, vaddr_end: uint64):
# WP=1 后内核态写只读页即 #PF → isrCommonhandler 打印 cr2/rip 暴露写源。
big_phys: uint64 = pd_r.entries[pd_idx] & ~uint64(0x1FFFFF)
inherit_flags: uint64 = pd_r.entries[pd_idx] & (PTE_PCD | PTE_PWT | PTE_USER | uint64(0x8000000000000000))
pt_split: _p | t.CPtr = AllocPage()
pt_split: _p* = AllocPage()
if not pt_split:
va += 0x1000
continue
split_i: int = 0
while split_i < 512:
pt_split.entries[split_i] = (big_phys + uint64(split_i) * uint64(0x1000)) \
| PTE_PRESENT | PTE_WRITABLE | inherit_flags
pt_split.entries[split_i] = (big_phys + uint64(split_i) * uint64(0x1000)) | PTE_PRESENT | PTE_WRITABLE | inherit_flags
split_i += 1
pd_r.entries[pd_idx] = (uint64(pt_split) & ~uint64(0xFFF)) \
| PTE_PRESENT | PTE_WRITABLE | (pd_r.entries[pd_idx] & PTE_USER)
c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]")
pd_r.entries[pd_idx] = (uint64(pt_split) & ~uint64(0xFFF)) | PTE_PRESENT | PTE_WRITABLE | (pd_r.entries[pd_idx] & PTE_USER)
__asm__(f"invlpg [{asminp(va, ASM_DESCR.REG_ANY)}]")
# 分裂后落入下方 4KB 常规路径,继续清当前页 W 位
pt_r: _p | t.CPtr = t.CType(pd_r.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
pt_r: _p* = _p*(pd_r.entries[pd_idx] & ~uint64(0xFFF))
pt_idx: uint64 = (va >> 12) & 0x1FF
pt_r.entries[pt_idx] = pt_r.entries[pt_idx] & ~uint64(PTE_WRITABLE)
c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]")
__asm__(f"invlpg [{asminp(va, ASM_DESCR.REG_ANY)}]")
va += 0x1000
def ProtectKernelRO():
"""把内核镜像 .rodata 段(字符串常量/vtable 等)映射为只读
地址经 c.Asm 内联引用链接器符号 __rodata_start/__rodata_end
地址经 __asm__ 内联引用链接器符号 __rodata_start/__rodata_end
(linker.ld 定义,TPV 不声明 extern——避免生成定义与链接器符号冲突)。
"""
global pml4
@@ -313,17 +305,17 @@ def ProtectKernelRO():
# 此处只保护 .rodata 内容页(WP=1 后写只读页即 #PF 暴露写源)。
ro_start: uint64 = 0
ro_end: uint64 = 0
c.Asm(f"""lea rax, [rip + __rodata_start]
mov {c.AsmOut(ro_start, t.ASM_DESCR.OUTPUT_REG)}, rax
__asm__(f"""lea rax, [rip + __rodata_start]
mov {asmout(ro_start, ASM_DESCR.OUTPUT_REG)}, rax
lea rax, [rip + __rodata_end]
mov {c.AsmOut(ro_end, t.ASM_DESCR.OUTPUT_REG)}, rax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
mov {asmout(ro_end, ASM_DESCR.OUTPUT_REG)}, rax""",
op=[ASM_DESCR.CLOBBER_RAX])
MakeRangeRO(ro_start, ro_end)
# [PG] 打印 .rodata 起始页映射:确认只读真正生效。
# ps=1 说明仍在 2MB 大页(分裂失败)→ .rodata 保持可写 → 越界写继续被静默吞掉。
DumpMapping(ro_start, "ro_s")
def DumpMapping(va: uint64, tag: t.CConst | str):
def DumpMapping(va: uint64, tag: const str):
"""[PG] 打印指定 VA 的 pml4/pdp/pd/pt 条目,定位大页(PS)与权限位
内核区域若为 UEFI 2MB 大页,MakeRangeRO 无法只读 .rodata(越界写静默破坏
@@ -336,38 +328,38 @@ def DumpMapping(va: uint64, tag: t.CConst | str):
pd_i: uint64 = (va >> 21) & 0x1FF
pt_i: uint64 = (va >> 12) & 0x1FF
pml4_e: uint64 = pml4.entries[pml4_i]
pdp_e: uint64 = 0
pd_e: uint64 = 0
pt_e: uint64 = 0
pdp_e: uint64 = 0
pd_e: uint64 = 0
pt_e: uint64 = 0
if pml4_e & PTE_PRESENT:
pdp_r: _p | t.CPtr = t.CType(pml4_e & ~uint64(0xFFF), _p, t.CPtr)
pdp_r: _p* = _p*(pml4_e & ~uint64(0xFFF))
pdp_e = pdp_r.entries[pdp_i]
if pdp_e & PTE_PRESENT:
if pdp_e & PTE_PS:
pd_e = pdp_e
else:
pd_r: _p | t.CPtr = t.CType(pdp_e & ~uint64(0xFFF), _p, t.CPtr)
pd_r: _p* = _p*(pdp_e & ~uint64(0xFFF))
pd_e = pd_r.entries[pd_i]
if (pd_e & PTE_PRESENT) and not (pd_e & PTE_PS):
pt_r: _p | t.CPtr = t.CType(pd_e & ~uint64(0xFFF), _p, t.CPtr)
pt_r: _p* = _p*(pd_e & ~uint64(0xFFF))
pt_e = pt_r.entries[pt_i]
buf_d: t.CArray[t.CChar, 200]
viperlib.snprintf(c.Addr(buf_d), 200, "[PG] %s va=0x%lx pdpe=0x%lx pde=0x%lx pte=0x%lx (ps=%d W=%d)\n",
buf_d: [200]char
viperlib.snprintf(&buf_d, 200, "[PG] %s va=0x%lx pdpe=0x%lx pde=0x%lx pte=0x%lx (ps=%d W=%d)\n",
tag, va, pdp_e, pd_e, pt_e,
1 if (pd_e & PTE_PS) else 0,
1 if (pt_e & PTE_WRITABLE) or (pd_e & PTE_WRITABLE) or (pdp_e & PTE_WRITABLE) else 0)
serial.puts(c.Addr(buf_d))
serial.puts(&buf_d)
def GetCurrentPml4() -> _p | t.CPtr:
def GetCurrentPml4() -> _p*:
global pml4, pdp, pd, pt
cr3: uint64
c.Asm(f"mov {c.AsmOut(cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3")
return (_p | t.CPtr)(cr3 & ~uint64(0xFFF))
__asm__(f"mov {asmout(cr3, ASM_DESCR.OUTPUT_REG)}, cr3")
return _p*(cr3 & ~uint64(0xFFF))
def create_process_page_table() -> uint64:
global pml4
if not pml4: return 0
new_pml4: _p | t.CPtr = AllocPage()
new_pml4: _p* = AllocPage()
if not new_pml4: return 0
i: uint64
for i in range(512):
@@ -378,41 +370,41 @@ def create_process_page_table() -> uint64:
def clone_for_process(isolate_vaddr: uint64) -> uint64:
global pml4
_dbg: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbg), 120, "[clone] pml4=0x%lx pool_used=%lu iso_va=0x%lx\n", uint64(pml4), pt_pool_used, isolate_vaddr)
_dbg: [120]char
viperlib.snprintf(&_dbg, 120, "[clone] pml4=0x%lx pool_used=%lu iso_va=0x%lx\n", uint64(pml4), pt_pool_used, isolate_vaddr)
serial.puts(_dbg)
if not pml4: return 0
new_pml4_page: _p | t.CPtr = AllocPage()
new_pml4_page: _p* = AllocPage()
if not new_pml4_page:
# [DIAG] 定位 AllocPage 失败:pool_used 打印 0 但分配失败 → BSS 全局
# (pt_pool_raw/pt_pool_used)疑似被内存越界写覆盖。
_dbgf: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbgf), 120, "[clone] AllocPage FAIL raw=0x%lx used=%lu PP=%d\n",
_dbgf: [120]char
viperlib.snprintf(&_dbgf, 120, "[clone] AllocPage FAIL raw=0x%lx used=%lu PP=%d\n",
uint64(pt_pool_raw), pt_pool_used, PT_POOL_PAGES)
serial.puts(c.Addr(_dbgf))
serial.puts(&_dbgf)
serial.puts("[clone] AllocPage pml4 failed\n")
return 0
_dbg2: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbg2), 120, "[clone] new_pml4=0x%lx\n", uint64(new_pml4_page))
_dbg2: [120]char
viperlib.snprintf(&_dbg2, 120, "[clone] new_pml4=0x%lx\n", uint64(new_pml4_page))
serial.puts(_dbg2)
i: uint64
for i in range(512):
new_pml4_page.entries[i] = pml4.entries[i]
pml4_idx: uint64 = (isolate_vaddr >> 39) & 0x1FF
_dbg3: t.CArray[t.CChar, 120]
viperlib.snprintf(c.Addr(_dbg3), 120, "[clone] pml4_idx=%lu entry0=0x%lx\n", pml4_idx, pml4.entries[pml4_idx])
_dbg3: [120]char
viperlib.snprintf(&_dbg3, 120, "[clone] pml4_idx=%lu entry0=0x%lx\n", pml4_idx, pml4.entries[pml4_idx])
serial.puts(_dbg3)
if not (pml4.entries[pml4_idx] & PTE_PRESENT): return uint64(new_pml4_page)
kernel_pdp: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr)
new_pdp_page: _p | t.CPtr = AllocPage()
kernel_pdp: _p* = _p*(pml4.entries[pml4_idx] & ~uint64(0xFFF))
new_pdp_page: _p* = AllocPage()
if not new_pdp_page: return uint64(new_pml4_page)
for i in range(512):
new_pdp_page.entries[i] = kernel_pdp.entries[i]
new_pml4_page.entries[pml4_idx] = (uint64(new_pdp_page) & ~uint64(0xFFF)) | (pml4.entries[pml4_idx] & uint64(0xFFF))
pdp_idx: uint64 = (isolate_vaddr >> 30) & 0x1FF
if not (kernel_pdp.entries[pdp_idx] & PTE_PRESENT): return uint64(new_pml4_page)
kernel_pd: _p | t.CPtr = t.CType(kernel_pdp.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr)
new_pd_page: _p | t.CPtr = AllocPage()
kernel_pd: _p* = _p*(kernel_pdp.entries[pdp_idx] & ~uint64(0xFFF))
new_pd_page: _p* = AllocPage()
if not new_pd_page: return uint64(new_pml4_page)
for i in range(512):
new_pd_page.entries[i] = kernel_pd.entries[i]
@@ -420,70 +412,69 @@ def clone_for_process(isolate_vaddr: uint64) -> uint64:
pd_idx: uint64 = (isolate_vaddr >> 21) & 0x1FF
if not (kernel_pd.entries[pd_idx] & PTE_PRESENT): return uint64(new_pml4_page)
if kernel_pd.entries[pd_idx] & PTE_PS: return uint64(new_pml4_page)
kernel_pt: _p | t.CPtr = t.CType(kernel_pd.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
new_pt_page: _p | t.CPtr = AllocPage()
kernel_pt: _p* = _p*(kernel_pd.entries[pd_idx] & ~uint64(0xFFF))
new_pt_page: _p* = AllocPage()
if not new_pt_page: return uint64(new_pml4_page)
for i in range(512):
new_pt_page.entries[i] = kernel_pt.entries[i]
new_pd_page.entries[pd_idx] = (uint64(new_pt_page) & ~uint64(0xFFF)) | (kernel_pd.entries[pd_idx] & uint64(0xFFF))
return uint64(new_pml4_page)
def save_pt_range(vaddr_start: uint64, vaddr_end: uint64, save_buf: uint64 | t.CPtr, save_count: uint32 | t.CPtr) -> int:
def save_pt_range(vaddr_start: uint64, vaddr_end: uint64, save_buf: uint64*, save_count: uint32*) -> int:
global pml4
if not pml4: return -1
# c.Set(a,b)=a=b(改指针变量本身);写所指地址必须 c.Set(c.Deref(a),b)
c.Set(c.Deref(save_count), uint32(0))
*save_count = uint32(0)
va: uint64 = vaddr_start & ~uint64(0xFFF)
while va < vaddr_end:
pml4_idx: uint64 = (va >> 39) & 0x1FF
if not (pml4.entries[pml4_idx] & PTE_PRESENT): va += 0x1000; continue
pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr)
pdp_: _p* = _p*(pml4.entries[pml4_idx] & ~uint64(0xFFF))
pdp_idx: uint64 = (va >> 30) & 0x1FF
if not (pdp_.entries[pdp_idx] & PTE_PRESENT): va += 0x1000; continue
pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr)
pd_: _p* = _p*(pdp_.entries[pdp_idx] & ~uint64(0xFFF))
pd_idx: uint64 = (va >> 21) & 0x1FF
if not (pd_.entries[pd_idx] & PTE_PRESENT): va += 0x1000; continue
if pd_.entries[pd_idx] & PTE_PS: va += 0x200000; continue
pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
pt_: _p* = _p*(pd_.entries[pd_idx] & ~uint64(0xFFF))
pt_idx: uint64 = (va >> 12) & 0x1FF
saved: uint32 = c.DerefAs(save_count)
# [待复核·指针缩放] save_buf 是 `uint64 | t.CPtr`;若该联合解析为 Ptr(u64),则下面的
saved: uint32 = *save_count
# [待复核·指针缩放] save_buf 是 `uint64*`;若该联合解析为 Ptr(u64),则下面的
# `* 16` 与 `+ 8` 都会再乘 8(GEP 按元素缩放)⇒ 记录步长 128 字节、字段偏移 64 字节,
# 与本处"16 字节一条记录(va 在 +0、pte 在 +8)"的设计不符。若本意是字节偏移,
# 需改用整数加法推进地址(或显式 rawptr/字节指针)——迁移到 rawptr[T] 时一并复核,
# 见 Debugger/rawptr-migration-and-fastfail.md。结论待定(需一次 IR 取证 GEP 的元素类型)。
entry_ptr: uint64 | t.CPtr = save_buf + uint64(saved) * 16
c.DerefAs(entry_ptr, va)
c.DerefAs(entry_ptr + 8, pt_.entries[pt_idx])
c.Set(c.Deref(save_count), uint32(saved + 1))
entry_ptr: uint64* = save_buf + uint64(saved) * 16
*(entry_ptr + 0) = va
*(entry_ptr + 8) = pt_.entries[pt_idx]
*save_count = uint32(saved + 1)
va += 0x1000
return 0
def restore_pt_range(save_buf: uint64 | t.CPtr, save_count: uint32):
def restore_pt_range(save_buf: uint64*, save_count: uint32):
global pml4
if not pml4: return
i: uint32 = 0
while i < save_count:
# [待复核·指针缩放] 同 save_pt_range:`* 16` / `+ 8` 若按 Ptr(u64) 缩放会变成 128/64 字节
# (该函数必须与 save_pt_range 的写入布局严格一致,两者要一起复核/一起改)。
entry_ptr: uint64 | t.CPtr = save_buf + uint64(i) * 16
va: uint64 = c.DerefAs(entry_ptr)
orig_pte: uint64 = c.DerefAs(entry_ptr + 8)
entry_ptr: uint64* = save_buf + uint64(i) * 16
va: uint64 = *(entry_ptr + 0)
orig_pte: uint64 = *(entry_ptr + 8)
pml4_idx: uint64 = (va >> 39) & 0x1FF
if not (pml4.entries[pml4_idx] & PTE_PRESENT): i += 1; continue
pdp_: _p | t.CPtr = t.CType(pml4.entries[pml4_idx] & ~uint64(0xFFF), _p, t.CPtr)
pdp_: _p* = _p*(pml4.entries[pml4_idx] & ~uint64(0xFFF))
pdp_idx: uint64 = (va >> 30) & 0x1FF
if not (pdp_.entries[pdp_idx] & PTE_PRESENT): i += 1; continue
pd_: _p | t.CPtr = t.CType(pdp_.entries[pdp_idx] & ~uint64(0xFFF), _p, t.CPtr)
pd_: _p* = _p*(pdp_.entries[pdp_idx] & ~uint64(0xFFF))
pd_idx: uint64 = (va >> 21) & 0x1FF
if not (pd_.entries[pd_idx] & PTE_PRESENT): i += 1; continue
if pd_.entries[pd_idx] & PTE_PS: i += 1; continue
pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
pt_: _p* = _p*(pd_.entries[pd_idx] & ~uint64(0xFFF))
pt_idx: uint64 = (va >> 12) & 0x1FF
pt_.entries[pt_idx] = orig_pte
c.Asm(f"invlpg [{c.AsmInp(va, t.ASM_DESCR.REG_ANY)}]", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"invlpg [{asminp(va, ASM_DESCR.REG_ANY)}]", op=[ASM_DESCR.CLOBBER_MEMORY])
i += 1
def set_active_pml4(cr3_val: uint64):
global pml4
pml4 = (_p | t.CPtr)(cr3_val & ~uint64(0xFFF))
pml4 = _p*(cr3_val & ~uint64(0xFFF))
+16 -17
View File
@@ -1,32 +1,31 @@
import asm
import t, c
# PIC端口定义
PIC1_COMMAND: t.CDefine = 0x20
PIC1_DATA: t.CDefine = 0x21
PIC2_COMMAND: t.CDefine = 0xA0
PIC2_DATA: t.CDefine = 0xA1
define PIC1_COMMAND = 0x20
define PIC1_DATA = 0x21
define PIC2_COMMAND = 0xA0
define PIC2_DATA = 0xA1
# ICW1 - 初始化命令字1
ICW1_ICW4: t.CDefine = 0x01 # 需要ICW4
ICW1_SINGLE: t.CDefine = 0x02 # 单级模式
ICW1_INTERVAL4: t.CDefine = 0x04 # 间隔4字节
ICW1_LEVEL: t.CDefine = 0x08 # 电平触发模式
ICW1_INIT: t.CDefine = 0x10 # 初始化
define ICW1_ICW4 = 0x01 # 需要ICW4
define ICW1_SINGLE = 0x02 # 单级模式
define ICW1_INTERVAL4 = 0x04 # 间隔4字节
define ICW1_LEVEL = 0x08 # 电平触发模式
define ICW1_INIT = 0x10 # 初始化
# ICW4 - 初始化命令字4
ICW4_8086: t.CDefine = 0x01 # 8086/88模式
ICW4_AUTO: t.CDefine = 0x02 # 自动EOI
ICW4_BUF_SLAVE: t.CDefine = 0x08 # 缓冲模式(从片)
ICW4_BUF_MASTER: t.CDefine = 0x0C # 缓冲模式(主片)
ICW4_SFNM: t.CDefine = 0x10 # 特殊全嵌套模式
define ICW4_8086 = 0x01 # 8086/88模式
define ICW4_AUTO = 0x02 # 自动EOI
define ICW4_BUF_SLAVE = 0x08 # 缓冲模式(从片)
define ICW4_BUF_MASTER = 0x0C # 缓冲模式(主片)
define ICW4_SFNM = 0x10 # 特殊全嵌套模式
# OCW2 - 操作命令字2
OCW2_EOI: t.CDefine = 0x20 # 结束中断
define OCW2_EOI = 0x20 # 结束中断
# OCW3 - 操作命令字3
OCW3_READ_ISR: t.CDefine = 0x0B # 读取中断服务寄存器(ISR)
define OCW3_READ_ISR = 0x0B # 读取中断服务寄存器(ISR)
# 初始化PIC
def init():
+5 -5
View File
@@ -1,10 +1,10 @@
import asm
import t, c
PIT_CHANNEL0: t.CDefine = 0x40
PIT_CHANNEL1: t.CDefine = 0x41
PIT_CHANNEL2: t.CDefine = 0x42
PIT_COMMAND: t.CDefine = 0x43
define PIT_CHANNEL0 = 0x40
define PIT_CHANNEL1 = 0x41
define PIT_CHANNEL2 = 0x42
define PIT_COMMAND = 0x43
def pit_init(frequency: int):
# 参数验证:确保频率为正数
+31 -46
View File
@@ -1,28 +1,26 @@
from stdint import *
import t, c
import asm
RTC_CMOS_ADDR: uint16 = 0x70
RTC_CMOS_DATA: uint16 = 0x71
RTC_REG_SECONDS: t.CDefine = 0x00
RTC_REG_MINUTES: t.CDefine = 0x02
RTC_REG_HOURS: t.CDefine = 0x04
RTC_REG_DAY: t.CDefine = 0x07
RTC_REG_MONTH: t.CDefine = 0x08
RTC_REG_YEAR: t.CDefine = 0x09
RTC_REG_STATUS_A: t.CDefine = 0x0A
RTC_REG_STATUS_B: t.CDefine = 0x0B
define RTC_REG_SECONDS = 0x00
define RTC_REG_MINUTES = 0x02
define RTC_REG_HOURS = 0x04
define RTC_REG_DAY = 0x07
define RTC_REG_MONTH = 0x08
define RTC_REG_YEAR = 0x09
define RTC_REG_STATUS_A = 0x0A
define RTC_REG_STATUS_B = 0x0B
RTC_TZ_OFFSET: t.CDefine = 8
define RTC_TZ_OFFSET = 8
rtc_seconds: t.CStatic | t.CVolatile | uint8 = 0
rtc_minutes: t.CStatic | t.CVolatile | uint8 = 0
rtc_hours: t.CStatic | t.CVolatile | uint8 = 0
rtc_day: t.CStatic | t.CVolatile | uint8 = 0
rtc_month: t.CStatic | t.CVolatile | uint8 = 0
rtc_year: t.CStatic | t.CVolatile | uint16 = 0
static rtc_seconds: volatile uint8 = 0
static rtc_minutes: volatile uint8 = 0
static rtc_hours: volatile uint8 = 0
static rtc_day: volatile uint8 = 0
static rtc_month: volatile uint8 = 0
static rtc_year: volatile uint16 = 0
def cmos_read(reg: uint8) -> uint8:
asm.outb(RTC_CMOS_ADDR, reg)
@@ -33,19 +31,19 @@ def bcd_to_bin(bcd: uint8) -> uint8:
def rtc_read_time():
while cmos_read(RTC_REG_STATUS_A) & 0x80: pass
sec: uint8 = cmos_read(RTC_REG_SECONDS)
min_: uint8 = cmos_read(RTC_REG_MINUTES)
hour: uint8 = cmos_read(RTC_REG_HOURS)
day: uint8 = cmos_read(RTC_REG_DAY)
mon: uint8 = cmos_read(RTC_REG_MONTH)
year: uint8 = cmos_read(RTC_REG_YEAR)
sec: uint8 = cmos_read(RTC_REG_SECONDS)
min_: uint8 = cmos_read(RTC_REG_MINUTES)
hour: uint8 = cmos_read(RTC_REG_HOURS)
day: uint8 = cmos_read(RTC_REG_DAY)
mon: uint8 = cmos_read(RTC_REG_MONTH)
year: uint8 = cmos_read(RTC_REG_YEAR)
reg_b: uint8 = cmos_read(RTC_REG_STATUS_B)
if not (reg_b & 0x04):
sec = bcd_to_bin(sec)
sec = bcd_to_bin(sec)
min_ = bcd_to_bin(min_)
hour = bcd_to_bin(hour)
day = bcd_to_bin(day)
mon = bcd_to_bin(mon)
day = bcd_to_bin(day)
mon = bcd_to_bin(mon)
year = bcd_to_bin(year)
if not (reg_b & 0x02) and (hour & 0x80):
hour = ((hour & 0x7F) + 12) % 24
@@ -75,23 +73,10 @@ def rtc_read_time():
rtc_month = mon
rtc_year = uint16(year) + 2000
def rtc_init():
rtc_read_time()
def rtc_get_hours() -> uint8:
return rtc_hours
def rtc_get_minutes() -> uint8:
return rtc_minutes
def rtc_get_seconds() -> uint8:
return rtc_seconds
def rtc_get_day() -> uint8:
return rtc_day
def rtc_get_month() -> uint8:
return rtc_month
def rtc_get_year() -> uint16:
return rtc_year
def rtc_init(): rtc_read_time()
def rtc_get_hours() -> uint8: return rtc_hours
def rtc_get_minutes() -> uint8: return rtc_minutes
def rtc_get_seconds() -> uint8: return rtc_seconds
def rtc_get_day() -> uint8: return rtc_day
def rtc_get_month() -> uint8: return rtc_month
def rtc_get_year() -> uint16: return rtc_year
+32 -32
View File
@@ -5,35 +5,35 @@ import drivers.core.cpu.apic as apic
import drivers.serial.uart.serial as serial
import viperlib
import asm
import t, c
TIMER_FREQUENCY: t.CDefine = 1000
TICKS_PER_SECOND: t.CDefine = TIMER_FREQUENCY
MILLISECONDS_PER_TICK: t.CDefine = (1000 / TIMER_FREQUENCY)
ticks: t.CStatic | t.CVolatile | uint64 = 0
seconds: t.CStatic | t.CVolatile | uint32 = 0
milliseconds: t.CStatic | t.CVolatile | uint32 = 0
timer_running: t.CStatic | t.CVolatile | bool = False
define TIMER_FREQUENCY = 1000
define TICKS_PER_SECOND = TIMER_FREQUENCY
define MILLISECONDS_PER_TICK = (1000 / TIMER_FREQUENCY)
static ticks: volatile uint64 = 0
static seconds: volatile uint32 = 0
static milliseconds: volatile uint32 = 0
static timer_running: volatile bool = False
_dbg_once: int = 0
def timer_init():
global ticks, seconds, milliseconds, timer_running
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = 0
seconds = 0
milliseconds = 0
timer_running = True
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
pit.pit_init(TIMER_FREQUENCY)
# [DBG] 读 PIT 计数器验证是否在走(用后移除)
asm.outb(0x43, 0x00) # latch channel 0
_lo: uint8 = asm.inb(0x40)
_hi: uint8 = asm.inb(0x40)
_cnt: int = int(_lo) | (int(_hi) << 8)
_cb: t.CArray[t.CChar, 40]
viperlib.snprintf(c.Addr(_cb), 40, "[PIT] cnt=%d\n", _cnt)
serial.puts(c.Addr(_cb))
_cb: [40]char
viperlib.snprintf(&_cb, 40, "[PIT] cnt=%d\n", _cnt)
serial.puts(&_cb)
def timer_handler():
global ticks, seconds, milliseconds, timer_running, _dbg_once
@@ -45,13 +45,13 @@ def timer_handler():
pic.eoi(0)
apic.eoi()
return
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = ticks + 1
milliseconds = milliseconds + MILLISECONDS_PER_TICK
if milliseconds >= 1000:
seconds = seconds + 1
milliseconds = milliseconds - 1000
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
sched.Scheduler.sched_tick()
pic.eoi(0)
# LAPIC EOI:APIC 启用后中断经 LINT0(EXTINT) 送达会置 LAPIC ISR,
@@ -61,52 +61,52 @@ def timer_handler():
def timer_start():
global timer_running
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
timer_running = True
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_stop():
global timer_running
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
timer_running = False
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_reset():
global ticks, seconds, milliseconds
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
ticks = 0
seconds = 0
milliseconds = 0
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_get_ticks() -> uint64:
current_ticks: uint64
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_ticks = ticks
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_ticks
def timer_get_seconds() -> uint32:
current_seconds: uint32
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_seconds = seconds
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_seconds
def timer_get_milliseconds() -> uint32:
current_milliseconds: uint32
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
current_milliseconds = milliseconds
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
return current_milliseconds
def timer_get_time(out_seconds: uint32 | t.CPtr, out_milliseconds: uint32 | t.CPtr):
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
def timer_get_time(out_seconds: uint32*, out_milliseconds: uint32*):
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
if out_seconds:
c.Set(c.Deref(out_seconds), seconds)
*out_seconds = seconds
if out_milliseconds:
c.Set(c.Deref(out_milliseconds), milliseconds)
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
*out_milliseconds = milliseconds
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
def timer_msleep(ms: uint32):
target: uint64 = ticks + (ms + MILLISECONDS_PER_TICK - 1) / MILLISECONDS_PER_TICK
+54 -67
View File
@@ -1,23 +1,21 @@
import mm.mm as mm
import drivers.serial.uart.serial as serial
import asm
import t, c
CORO_READY: t.CDefine = 0
CORO_RUNNING: t.CDefine = 1
CORO_YIELDED: t.CDefine = 2
CORO_DONE: t.CDefine = 3
MAX_COROUTINES: t.CDefine = 32
CORO_STACK_SIZE: t.CDefine = 8192
@t.Object
define CORO_READY = 0
define CORO_RUNNING = 1
define CORO_YIELDED = 2
define CORO_DONE = 3
define MAX_COROUTINES = 32
define CORO_STACK_SIZE = 8192
class Coroutine:
rsp: uint64
stack: t.CPtr
stack: rawptr
stack_size: uint64
func: t.CPtr
arg: t.CPtr
func: rawptr
arg: rawptr
state: int
cid: int
caller_rsp: uint64
@@ -25,14 +23,14 @@ class Coroutine:
def resume(self) -> int:
global _coro_old_rsp, _coro_new_rsp
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
m: CoroutineManager* = _coro_mgr_ptr
if self.state == CORO_DONE: return self.ret_val
if self.state != CORO_READY and self.state != CORO_YIELDED: return -1
prev_cid: int = m.current_cid
m.current_cid = self.cid
self.state = CORO_RUNNING
_coro_old_rsp = c.Addr(m.coroutines[prev_cid].rsp)
_coro_new_rsp = c.Addr(self.rsp)
_coro_old_rsp = &m.coroutines[prev_cid].rsp
_coro_new_rsp = &self.rsp
self.caller_rsp = uint64(_coro_old_rsp)
_coro_switch()
if self.state == CORO_DONE:
@@ -42,49 +40,38 @@ class Coroutine:
@staticmethod
def _yield():
global _coro_old_rsp, _coro_new_rsp
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
m: CoroutineManager* = _coro_mgr_ptr
cid: int = m.current_cid
if cid < 0: return
m.coroutines[cid].state = CORO_YIELDED
prev_cid: int = -1
i: int
for i in range(m.count):
if m.coroutines[i].state == CORO_RUNNING and m.coroutines[i].caller_rsp != 0:
prev_cid = i
break
if prev_cid < 0: return
m.current_cid = prev_cid
_coro_old_rsp = c.Addr(m.coroutines[cid].rsp)
_coro_new_rsp = c.Addr(m.coroutines[prev_cid].rsp)
_coro_old_rsp = &m.coroutines[cid].rsp
_coro_new_rsp = &m.coroutines[prev_cid].rsp
_coro_switch()
@property
def is_done(self) -> int:
if self.state == CORO_DONE:
return 1
return 0
def is_done(self) -> bool: return self.state == CORO_DONE
@property
def is_yielded(self) -> int:
if self.state == CORO_YIELDED:
return 1
return 0
def is_yielded(self) -> bool: return self.state == CORO_YIELDED
@property
def retval(self) -> int:
return self.ret_val
def retval(self) -> int: return self.ret_val
@t.Object
class CoroutineManager:
coroutines: t.CArray[Coroutine, MAX_COROUTINES]
coroutines: [MAX_COROUTINES]Coroutine
current_cid: int
count: int
def __init__(self):
global _coro_mgr_ptr
_coro_mgr_ptr = c.Addr(_coro_mgr)
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
_coro_mgr_ptr = &_coro_mgr
m: CoroutineManager* = _coro_mgr_ptr
m.current_cid = 0
m.count = 1
m.coroutines[0].state = CORO_RUNNING
@@ -96,43 +83,43 @@ class CoroutineManager:
m.coroutines[0].stack_size = 0
m.coroutines[0].func = None
m.coroutines[0].arg = None
main_rsp_ptr: t.CPtr = c.Addr(m.coroutines[0].rsp)
c.Asm(f"""mov qword ptr [{c.AsmInp(main_rsp_ptr, t.ASM_DESCR.REG_ANY)}], rsp""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
main_rsp_ptr: rawptr = &m.coroutines[0].rsp
__asm__(f"""mov qword ptr [{asminp(main_rsp_ptr, ASM_DESCR.REG_ANY)}], rsp""",
op=[ASM_DESCR.CLOBBER_MEMORY])
@staticmethod
def current() -> Coroutine | t.CPtr:
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
return c.Addr(m.coroutines[m.current_cid])
def current() -> Coroutine*:
m: CoroutineManager* = _coro_mgr_ptr
return &m.coroutines[m.current_cid]
@staticmethod
def get_coroutine(cid: int) -> Coroutine | t.CPtr:
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
def get_coroutine(cid: int) -> Coroutine*:
m: CoroutineManager* = _coro_mgr_ptr
if cid < 0 or cid >= m.count: return None
return c.Addr(m.coroutines[cid])
return &m.coroutines[cid]
@staticmethod
def create(func: t.CPtr, arg: t.CPtr) -> Coroutine | t.CPtr:
m: CoroutineManager | t.CPtr = _coro_mgr_ptr
def create(func: rawptr, arg: rawptr) -> Coroutine*:
m: CoroutineManager* = _coro_mgr_ptr
if m.count >= MAX_COROUTINES: return None
cid: int = m.count
m.count += 1
co: Coroutine | t.CPtr = c.Addr(m.coroutines[cid])
co: Coroutine* = &m.coroutines[cid]
co.state = CORO_READY
co.cid = cid
co.func = func
co.arg = arg
co.caller_rsp = 0
co.ret_val = 0
stack_ptr: t.CPtr = mm.malloc(CORO_STACK_SIZE)
stack_ptr: rawptr = mm.malloc(CORO_STACK_SIZE)
if not stack_ptr: return None
co.stack = stack_ptr
co.stack_size = CORO_STACK_SIZE
stack_top: uint64 = uint64(stack_ptr) + CORO_STACK_SIZE - 16
stack_top = stack_top & ~uint64(0xF)
entry_addr: uint64 = uint64(c.Addr(_coro_entry))
sp: t.CPtr = t.CPtr(stack_top)
c.Asm(f"""mov rax, {c.AsmInp(sp, t.ASM_DESCR.REG_ANY)}
entry_addr: uint64 = uint64(&_coro_entry)
sp: rawptr = rawptr(stack_top)
__asm__(f"""mov rax, {asminp(sp, ASM_DESCR.REG_ANY)}
mov qword ptr [rax - 56], 0
mov qword ptr [rax - 48], 0
mov qword ptr [rax - 40], 0
@@ -140,21 +127,21 @@ class CoroutineManager:
mov qword ptr [rax - 24], 0
mov qword ptr [rax - 16], 0
mov qword ptr [rax - 8], 0
mov qword ptr [rax], {c.AsmInp(entry_addr, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
mov qword ptr [rax], {asminp(entry_addr, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
stack_top = stack_top - 56
co.rsp = stack_top
return co
_coro_mgr: CoroutineManager = CoroutineManager()
_coro_mgr_ptr: CoroutineManager | t.CPtr | t.CExport = c.Addr(_coro_mgr)
_coro_old_rsp: t.CPtr | t.CExport
_coro_new_rsp: t.CPtr | t.CExport
export _coro_mgr_ptr: CoroutineManager* = &_coro_mgr
export _coro_old_rsp: rawptr
export _coro_new_rsp: rawptr
@c.Attribute(t.attr.naked)
@__attribute__(naked)
def _coro_switch():
c.Asm(f"""push rax
__asm__(f"""push rax
push rbx
push rbp
push r12
@@ -173,16 +160,16 @@ def _coro_switch():
pop rbx
pop rax
ret""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
op=[ASM_DESCR.CLOBBER_MEMORY])
@c.Attribute(t.attr.naked)
@__attribute__(naked)
def _coro_entry():
# 结构体布局(以 stub.ll 为权威):
# Coroutine = {rsp@0, stack@8, stack_size@16, func@24, arg@32,
# state@40, cid@44, caller_rsp@48, ret_val@56}, sizeof=64
# CoroutineManager= {coroutines[32]@0 (32*64=2048), current_cid@2048, count@2052}
# 取 func/arg 入口,写 state=CORO_DONE(3)、ret_val。
c.Asm(f"""sub rsp, 8
__asm__(f"""sub rsp, 8
mov rax, qword ptr [rip + _coro_mgr_ptr]
mov ecx, dword ptr [rax + 2048]
movsxd rcx, ecx
@@ -200,11 +187,11 @@ def _coro_entry():
# `call rax` 破坏全部 caller-saved 寄存器(x64 SysV):除 RAX/RCX/RDX/
# R8-R11 外,RSI 与 RDI 也必须声明,否则编译器可能假设其值存活(N9)。
# RSP 由 `sub rsp,8` / `add rsp,8` 配对抵消,净变化为 0,无需声明。
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
Coroutine._yield()
while True:
asm.sti()
+73 -98
View File
@@ -5,39 +5,37 @@ import drivers.fs.fat32.fat32 as fat32
import drivers.fs.fat32.fat32_types as fat32_types
import drivers.core.cpu.cpu as cpu
import intr.gdt as gdt
import viperlib
import string
import t, c
PROC_READY: t.CDefine = 0
PROC_RUNNING: t.CDefine = 1
PROC_BLOCKED: t.CDefine = 2
PROC_DONE: t.CDefine = 3
MAX_PROCESSES: t.CDefine = 8
MAX_PROC_THREADS: t.CDefine = 8
PROC_MAX_FDS: t.CDefine = 16
PROC_MAX_DIRS: t.CDefine = 8
KERN_STACK_SIZE: t.CDefine = 8192
USER_STACK_SIZE: t.CDefine = 65536
@t.Object
define PROC_READY = 0
define PROC_RUNNING = 1
define PROC_BLOCKED = 2
define PROC_DONE = 3
define MAX_PROCESSES = 8
define MAX_PROC_THREADS = 8
define PROC_MAX_FDS = 16
define PROC_MAX_DIRS = 8
define KERN_STACK_SIZE = 8192
define USER_STACK_SIZE = 65536
class Process:
pid: int
pml4_root: uint64
threads: t.CArray[int, 8]
threads: [8]int
thread_count: int
state: int
entry: t.CPtr
entry: rawptr
elf_base: uint64
heap_start: uint64
heap_size: uint64
name: t.CArray[t.CChar, 32]
fd_table: t.CArray[t.CPtr, PROC_MAX_FDS]
fd_used: t.CArray[uint8, PROC_MAX_FDS]
dir_table: t.CArray[t.CPtr, PROC_MAX_DIRS]
dir_used: t.CArray[uint8, PROC_MAX_DIRS]
dir_pool: t.CArray[fat32_types.dirobj, PROC_MAX_DIRS]
name: [32]char
fd_table: [PROC_MAX_FDS]rawptr
fd_used: [PROC_MAX_FDS]uint8
dir_table: [PROC_MAX_DIRS]rawptr
dir_used: [PROC_MAX_DIRS]uint8
dir_pool: [PROC_MAX_DIRS]fat32_types.dirobj
kern_stack: uint64
user_stack: uint64
@@ -51,55 +49,47 @@ class Process:
self.state = PROC_DONE
for i in range(PROC_MAX_FDS):
if self.fd_used[i]:
fp: t.CPtr = self.fd_table[i]
fp: rawptr = self.fd_table[i]
if fp:
fat32.close(fp)
self.fd_used[i] = 0
self.fd_table[i] = None
for i in range(PROC_MAX_DIRS):
if self.dir_used[i]:
dp: t.CPtr = self.dir_table[i]
dp: rawptr = self.dir_table[i]
if dp:
fat32.closedir(dp)
self.dir_used[i] = 0
self.dir_table[i] = None
m: ProcessManager | t.CPtr = _proc_mgr_ptr
m: ProcessManager* = _proc_mgr_ptr
if m.current_pid == self.pid:
m.current_pid = 0
m.processes[0].state = PROC_RUNNING
if self.pml4_root != 0:
kernel_cr3: uint64 = m.processes[0].pml4_root
if kernel_cr3 != 0:
c.Asm(f"mov cr3, {c.AsmInp(kernel_cr3, t.ASM_DESCR.REG_ANY)}",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"mov cr3, {asminp(kernel_cr3, ASM_DESCR.REG_ANY)}",
op=[ASM_DESCR.CLOBBER_MEMORY])
paging.set_active_pml4(kernel_cr3)
@property
def is_running(self) -> int:
if self.state == PROC_RUNNING:
return 1
return 0
def is_running(self) -> bool: return self.state == PROC_RUNNING
@property
def is_done(self) -> int:
if self.state == PROC_DONE:
return 1
return 0
def is_done(self) -> bool: return self.state == PROC_DONE
@t.Object
class ProcessManager:
processes: t.CArray[Process, MAX_PROCESSES]
processes: [MAX_PROCESSES]Process
current_pid: int
count: int
def __init__(self):
global _proc_mgr_ptr
_proc_mgr_ptr = c.Addr(_proc_mgr)
m: ProcessManager | t.CPtr = _proc_mgr_ptr
_proc_mgr_ptr = &_proc_mgr
m: ProcessManager* = _proc_mgr_ptr
m.current_pid = 0
m.count = 1
p: Process | t.CPtr = c.Addr(m.processes[0])
p: Process* = &m.processes[0]
p.pid = 0
p.state = PROC_RUNNING
p.thread_count = 0
@@ -124,15 +114,15 @@ class ProcessManager:
for j in range(PROC_MAX_DIRS):
p.dir_used[j] = 0
p.dir_table[j] = None
c.Asm(f"""mov {c.AsmOut(p.pml4_root, t.ASM_DESCR.OUTPUT_REG)}, cr3""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"""mov {asmout(p.pml4_root, ASM_DESCR.OUTPUT_REG)}, cr3""",
op=[ASM_DESCR.CLOBBER_MEMORY])
@staticmethod
def _switch(pid: int) -> int:
global _saved_cr3
m: ProcessManager | t.CPtr = _proc_mgr_ptr
m: ProcessManager* = _proc_mgr_ptr
if pid < 0 or pid >= m.count: return -1
p: Process | t.CPtr = c.Addr(m.processes[pid])
p: Process* = &m.processes[pid]
if p.state == PROC_DONE: return -1
old_pid: int = m.current_pid
if old_pid == pid: return 0
@@ -140,33 +130,30 @@ class ProcessManager:
m.processes[old_pid].state = PROC_READY
p.state = PROC_RUNNING
m.current_pid = pid
c.Asm(f"""mov {c.AsmOut(_saved_cr3, t.ASM_DESCR.OUTPUT_REG)}, cr3
mov rax, {c.AsmInp(p.pml4_root, t.ASM_DESCR.REG_ANY)}
__asm__(f"""mov {asmout(_saved_cr3, ASM_DESCR.OUTPUT_REG)}, cr3
mov rax, {asminp(p.pml4_root, ASM_DESCR.REG_ANY)}
mov cr3, rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
return 0
@staticmethod
def current() -> Process | t.CPtr:
m: ProcessManager | t.CPtr = _proc_mgr_ptr
return c.Addr(m.processes[m.current_pid])
def current() -> Process*:
m: ProcessManager* = _proc_mgr_ptr
return &m.processes[m.current_pid]
@staticmethod
def get_process(pid: int) -> Process | t.CPtr:
m: ProcessManager | t.CPtr = _proc_mgr_ptr
def get_process(pid: int) -> Process*:
m: ProcessManager* = _proc_mgr_ptr
if pid < 0 or pid >= m.count: return None
return c.Addr(m.processes[pid])
return &m.processes[pid]
@staticmethod
def create_process(name: str, entry: t.CPtr) -> Process | t.CPtr:
m: ProcessManager | t.CPtr = _proc_mgr_ptr
_dbp: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(_dbp), 80, "[process] create_process count=%d MAX=%d\n", m.count, MAX_PROCESSES)
serial.puts(_dbp)
def create_process(name: str, entry: rawptr) -> Process*:
m: ProcessManager* = _proc_mgr_ptr
if m.count >= MAX_PROCESSES: return None
pid: int = m.count
m.count += 1
p: Process | t.CPtr = c.Addr(m.processes[pid])
p: Process* = &m.processes[pid]
p.pid = pid
p.state = PROC_READY
p.entry = entry
@@ -174,14 +161,13 @@ class ProcessManager:
p.thread_count = 0
p.heap_start = 0
p.heap_size = 0
string.memset(c.Addr(p.name), 0, 32)
string.memset(&p.name, 0, 32)
i: int = 0
for ch in name:
if i >= 31: break
p.name[i] = ch
i += 1
p.name[i] = 0
j: int
for j in range(MAX_PROC_THREADS):
p.threads[j] = -1
for j in range(PROC_MAX_FDS):
@@ -190,22 +176,13 @@ class ProcessManager:
for j in range(PROC_MAX_DIRS):
p.dir_used[j] = 0
p.dir_table[j] = None
ks: t.CPtr = mm.malloc(KERN_STACK_SIZE)
# [DIAG] 定位跨模块 malloc 返回值(mm 成功但调用方收到 None)
_dbg_ks: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(_dbg_ks), 64, "[proc] ks=0x%lx\n", uint64(ks))
serial.puts(c.Addr(_dbg_ks))
ks: rawptr = mm.malloc(KERN_STACK_SIZE)
if ks is None:
serial.puts("[process] kernel stack alloc failed\n")
m.count = m.count - 1
return None
ks_size: uint64 = KERN_STACK_SIZE
p.kern_stack = uint64(ks) + ks_size
us: t.CPtr = mm.malloc(USER_STACK_SIZE)
# [DIAG] 定位 user_stack 收到 None(mm 内部打印成功但此处收 0x0)
_dbg_us: t.CArray[t.CChar, 64]
viperlib.snprintf(c.Addr(_dbg_us), 64, "[proc] us=0x%lx\n", uint64(us))
serial.puts(c.Addr(_dbg_us))
us: rawptr = mm.malloc(USER_STACK_SIZE)
if us is None:
serial.puts("[process] user stack alloc failed\n")
mm.free(ks)
@@ -213,33 +190,33 @@ class ProcessManager:
return None
us_size: uint64 = USER_STACK_SIZE
p.user_stack = uint64(us) + us_size
c.Asm(f"""mov {c.AsmOut(p.pml4_root, t.ASM_DESCR.OUTPUT_REG)}, cr3""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
__asm__(f"""mov {asmout(p.pml4_root, ASM_DESCR.OUTPUT_REG)}, cr3""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
return p
_proc_mgr: ProcessManager = ProcessManager()
_proc_mgr_ptr: ProcessManager | t.CPtr = c.Addr(_proc_mgr)
_saved_cr3: uint64 | t.CExport
_proc_mgr_ptr: ProcessManager* = &_proc_mgr
export _saved_cr3: uint64
def current() -> int:
m: ProcessManager | t.CPtr = _proc_mgr_ptr
m: ProcessManager* = _proc_mgr_ptr
return m.current_pid
def switch_pid(new_pid: int):
m: ProcessManager | t.CPtr = _proc_mgr_ptr
m: ProcessManager* = _proc_mgr_ptr
if m.current_pid == new_pid: return
if m.current_pid >= 0 and m.current_pid < m.count:
old_p: Process | t.CPtr = c.Addr(m.processes[m.current_pid])
old_p: Process* = &m.processes[m.current_pid]
if old_p.state != PROC_DONE:
old_p.state = PROC_READY
if new_pid >= 0 and new_pid < m.count:
new_p: Process | t.CPtr = c.Addr(m.processes[new_pid])
new_p: Process* = &m.processes[new_pid]
new_p.state = PROC_RUNNING
new_cr3: uint64 = new_p.pml4_root
if new_cr3 != 0:
c.Asm(f"mov cr3, {c.AsmInp(new_cr3, t.ASM_DESCR.REG_ANY)}",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
__asm__(f"mov cr3, {asminp(new_cr3, ASM_DESCR.REG_ANY)}",
op=[ASM_DESCR.CLOBBER_MEMORY])
paging.set_active_pml4(new_cr3)
# Update TSS RSP0 and GS kernel_rsp0 for the new process
# This is needed so interrupts from Ring 3 use the correct kernel stack
@@ -249,26 +226,24 @@ def switch_pid(new_pid: int):
m.current_pid = new_pid
def get_pid(tid: int) -> int:
m: ProcessManager | t.CPtr = _proc_mgr_ptr
i: int
m: ProcessManager* = _proc_mgr_ptr
for i in range(m.count):
p: Process | t.CPtr = c.Addr(m.processes[i])
j: int
p: Process* = &m.processes[i]
for j in range(p.thread_count):
if p.threads[j] == tid:
return p.pid
return -1
def drop_to_user_mode(entry: t.CPtr, user_rsp: uint64, kern_rsp: uint64):
def drop_to_user_mode(entry: rawptr, user_rsp: uint64, kern_rsp: uint64):
# NOTE: Do NOT swapgs here. This OS uses reverse GS convention:
# GS_BASE = 0 (kernel & user), KERNEL_GS_BASE = &_per_cpu
# syscall/ISR entry does swapgs to get GS_BASE = &_per_cpu
# syscall/ISR return does swapgs to restore GS_BASE = 0
# GS state is restored in isrCommonhandler before _yield() if needed.
c.Asm(f"""cli
mov rsp, {c.AsmInp(kern_rsp, t.ASM_DESCR.REG_ANY)}
mov rdx, {c.AsmInp(user_rsp, t.ASM_DESCR.REG_ANY)}
mov rcx, {c.AsmInp(entry, t.ASM_DESCR.REG_ANY)}
__asm__(f"""cli
mov rsp, {asminp(kern_rsp, ASM_DESCR.REG_ANY)}
mov rdx, {asminp(user_rsp, ASM_DESCR.REG_ANY)}
mov rcx, {asminp(entry, ASM_DESCR.REG_ANY)}
mov r11, 0x202
push 0x23
push rdx
@@ -276,9 +251,9 @@ def drop_to_user_mode(entry: t.CPtr, user_rsp: uint64, kern_rsp: uint64):
push 0x1B
push rcx
iretq""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_R11, t.ASM_DESCR.CLOBBER_RSI,
t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_R8,
t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10,
t.ASM_DESCR.CLOBBER_RBP])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_R11, ASM_DESCR.CLOBBER_RSI,
ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_R8,
ASM_DESCR.CLOBBER_R9, ASM_DESCR.CLOBBER_R10,
ASM_DESCR.CLOBBER_RBP])
+67 -89
View File
@@ -1,30 +1,27 @@
import mm.mm as mm
import asm
import sched.process as proc
import drivers.serial.uart.serial as serial
import sched.process as proc
import mm.mm as mm
import viperlib
import t, c
import asm
THREAD_READY: t.CDefine = 0
THREAD_RUNNING: t.CDefine = 1
THREAD_BLOCKED: t.CDefine = 2
THREAD_DONE: t.CDefine = 3
MAX_THREADS: t.CDefine = 16
THREAD_STACK_SIZE: t.CDefine = 65536
SCHED_QUANTUM: t.CDefine = 10
define THREAD_READY = 0
define THREAD_RUNNING = 1
define THREAD_BLOCKED = 2
define THREAD_DONE = 3
define MAX_THREADS = 16
define THREAD_STACK_SIZE = 65536
define SCHED_QUANTUM = 10
_yield_cnt: uint32 = 0
_yield_lock: int = 0
@t.Object
class Thread:
rsp: uint64
stack: t.CPtr
stack: rawptr
stack_size: uint64
func: t.CPtr
arg: t.CPtr
func: rawptr
arg: rawptr
state: int
tid: int
pid: int
@@ -38,27 +35,15 @@ class Thread:
self.state = THREAD_READY
@property
def is_running(self) -> int:
if self.state == THREAD_RUNNING:
return 1
return 0
def is_running(self) -> bool: return self.state == THREAD_RUNNING
@property
def is_blocked(self) -> int:
if self.state == THREAD_BLOCKED:
return 1
return 0
def is_blocked(self) -> bool: return self.state == THREAD_BLOCKED
@property
def is_done(self) -> int:
if self.state == THREAD_DONE:
return 1
return 0
def is_done(self) -> bool: return self.state == THREAD_DONE
@t.Object
class Scheduler:
threads: t.CArray[Thread, MAX_THREADS]
threads: [MAX_THREADS]Thread
current_tid: int
thread_count: int
enabled: int
@@ -67,14 +52,13 @@ class Scheduler:
def __init__(self):
global _sched_ptr
_sched_ptr = c.Addr(_sched_storage)
s: Scheduler | t.CPtr = _sched_ptr
_sched_ptr = &_sched_storage
s: Scheduler* = _sched_ptr
s.current_tid = 0
s.thread_count = 1
s.enabled = 0
s.needs_reschedule = 0
s.tick_count = 0
i: int
for i in range(MAX_THREADS):
s.threads[i].rsp = 0
s.threads[i].stack = None
@@ -87,27 +71,27 @@ class Scheduler:
s.enabled = 1
s.threads[0].state = THREAD_RUNNING
s.threads[0].tid = 0
main_rsp_ptr: t.CPtr = c.Addr(s.threads[0].rsp)
c.Asm(f"""mov qword ptr [{c.AsmInp(main_rsp_ptr, t.ASM_DESCR.REG_ANY)}], rsp""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
main_rsp_ptr: rawptr = &s.threads[0].rsp
__asm__(f"""mov qword ptr [{asminp(main_rsp_ptr, ASM_DESCR.REG_ANY)}], rsp""",
op=[ASM_DESCR.CLOBBER_MEMORY])
@staticmethod
def _yield():
global _switch_old_rsp, _switch_new_rsp, _yield_cnt, _yield_lock
_if_saved: int = 0
c.Asm(f"""pushfq
__asm__(f"""pushfq
pop rax
shr rax, 9
and eax, 1
mov {c.AsmOut(_if_saved, t.ASM_DESCR.OUTPUT_REG)}, eax""",
op=[t.ASM_DESCR.CLOBBER_RAX])
mov {asmout(_if_saved, ASM_DESCR.OUTPUT_REG)}, eax""",
op=[ASM_DESCR.CLOBBER_RAX])
asm.cli()
if _yield_lock:
if _if_saved:
asm.sti()
return
_yield_lock = 1
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
s.needs_reschedule = 0
s.tick_count = 0
old_tid: int = s.current_tid
@@ -138,8 +122,8 @@ class Scheduler:
if s.threads[old_tid].state == THREAD_RUNNING:
s.threads[old_tid].state = THREAD_READY
s.threads[next_tid].state = THREAD_RUNNING
_switch_old_rsp = c.Addr(s.threads[old_tid].rsp)
_switch_new_rsp = c.Addr(s.threads[next_tid].rsp)
_switch_old_rsp = &s.threads[old_tid].rsp
_switch_new_rsp = &s.threads[next_tid].rsp
s.current_tid = next_tid
next_pid: int = s.threads[next_tid].pid
_yield_cnt += 1
@@ -151,7 +135,7 @@ class Scheduler:
@staticmethod
def sched_tick():
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
if not s.enabled: return
if s.thread_count <= 1: return
s.tick_count += 1
@@ -161,62 +145,56 @@ class Scheduler:
@staticmethod
def try_reschedule():
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
if s.needs_reschedule:
s.needs_reschedule = 0
Scheduler._yield()
@staticmethod
def disable():
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
s.enabled = 0
@staticmethod
def enable():
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
s.enabled = 1
@staticmethod
def current() -> Thread | t.CPtr:
s: Scheduler | t.CPtr = _sched_ptr
return c.Addr(s.threads[s.current_tid])
def current() -> Thread*:
s: Scheduler* = _sched_ptr
return &s.threads[s.current_tid]
@staticmethod
def get_thread(tid: int) -> Thread | t.CPtr:
s: Scheduler | t.CPtr = _sched_ptr
def get_thread(tid: int) -> Thread*:
s: Scheduler* = _sched_ptr
if tid < 0 or tid >= s.thread_count: return None
return c.Addr(s.threads[tid])
return &s.threads[tid]
@staticmethod
def create_thread(func: t.CPtr, arg: t.CPtr, thread_pid: int = 0) -> Thread | t.CPtr:
s: Scheduler | t.CPtr = _sched_ptr
def create_thread(func: rawptr, arg: rawptr, thread_pid: int = 0) -> Thread*:
s: Scheduler* = _sched_ptr
if s.thread_count >= MAX_THREADS: return None
tid: int = s.thread_count
s.thread_count += 1
th: Thread | t.CPtr = c.Addr(s.threads[tid])
th: Thread* = &s.threads[tid]
th.state = THREAD_READY
th.tid = tid
th.pid = thread_pid
th.func = func
th.arg = arg
stack_size: uint64 = THREAD_STACK_SIZE
stack_ptr: t.CPtr = mm.malloc(stack_size)
_dbg_ct: t.CArray[t.CChar, 96]
viperlib.snprintf(c.Addr(_dbg_ct), 96, "[sched] ct t%d func=0x%lx stack=0x%lx\n",
tid, uint64(th.func), uint64(stack_ptr))
serial.puts(c.Addr(_dbg_ct))
stack_ptr: rawptr = mm.malloc(stack_size)
if not stack_ptr:
# B4:栈分配失败回退槽位计数(对齐 process.vp create_process 失败路径),
# 否则 thread_count 漂移 → 调度器扫描未初始化槽位。
s.thread_count -= 1
return None
th.stack = stack_ptr
th.stack_size = stack_size
stack_top: uint64 = uint64(stack_ptr) + stack_size - 16
stack_top = stack_top & ~uint64(0xF)
entry_addr: uint64 = uint64(c.Addr(_thread_entry))
sp: t.CPtr = t.CPtr(stack_top)
c.Asm(f"""mov rax, {c.AsmInp(sp, t.ASM_DESCR.REG_ANY)}
entry_addr: uint64 = uint64(&_thread_entry)
sp: rawptr = rawptr(stack_top)
__asm__(f"""mov rax, {asminp(sp, ASM_DESCR.REG_ANY)}
mov qword ptr [rax - 64], 0x202
mov qword ptr [rax - 56], 0
mov qword ptr [rax - 48], 0
@@ -225,21 +203,21 @@ class Scheduler:
mov qword ptr [rax - 24], 0
mov qword ptr [rax - 16], 0
mov qword ptr [rax - 8], 0
mov qword ptr [rax], {c.AsmInp(entry_addr, t.ASM_DESCR.REG_ANY)}""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
mov qword ptr [rax], {asminp(entry_addr, ASM_DESCR.REG_ANY)}""",
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
stack_top = stack_top - 64
th.rsp = stack_top
return th
_sched_storage: Scheduler = Scheduler()
_sched_ptr: Scheduler | t.CPtr | t.CExport = c.Addr(_sched_storage)
_switch_old_rsp: t.CPtr | t.CExport
_switch_new_rsp: t.CPtr | t.CExport
export _sched_ptr: Scheduler* = &_sched_storage
export _switch_old_rsp: rawptr
export _switch_new_rsp: rawptr
@c.Attribute(t.attr.naked)
@__attribute__(naked)
def _do_switch():
c.Asm(f"""push rax
__asm__(f"""push rax
push rbx
push rbp
push r12
@@ -260,11 +238,11 @@ def _do_switch():
pop rbx
pop rax
ret""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
op=[ASM_DESCR.CLOBBER_MEMORY])
@c.Attribute(t.attr.naked)
@__attribute__(naked)
def _thread_entry():
c.Asm(f"""sub rsp, 8
__asm__(f"""sub rsp, 8
mov rax, qword ptr [rip + _sched_ptr]
mov ecx, dword ptr [rax + 896]
movsxd rcx, ecx
@@ -281,11 +259,11 @@ def _thread_entry():
# `call rax` 破坏全部 caller-saved 寄存器(x64 SysV):除 RAX/RCX/RDX/
# R8-R11 外,RSI 与 RDI 也必须声明,否则编译器可能假设其值存活(N9)。
# RSP 由 `sub rsp,8` / `add rsp,8` 配对抵消,净变化为 0,无需声明。
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
Scheduler._yield()
while True:
asm.sti()
@@ -293,19 +271,19 @@ def _thread_entry():
Scheduler._yield()
def thread_current() -> int:
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
return s.current_tid
def needs_reschedule() -> int:
s: Scheduler | t.CPtr = _sched_ptr
s: Scheduler* = _sched_ptr
return s.needs_reschedule
def sched_dump():
s: Scheduler | t.CPtr = _sched_ptr
dl: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(dl), 80, "[sched] dump: cur=%d cnt=%d yields=%u\n", s.current_tid, s.thread_count, _yield_cnt)
s: Scheduler* = _sched_ptr
dl: [80]char
viperlib.snprintf(&dl, 80, "[sched] dump: cur=%d cnt=%d yields=%u\n", s.current_tid, s.thread_count, _yield_cnt)
serial.puts(dl)
for i in range(s.thread_count):
sl: t.CArray[t.CChar, 80]
viperlib.snprintf(c.Addr(sl), 80, " t%d: st=%d pid=%d rsp=0x%lx\n", i, s.threads[i].state, s.threads[i].pid, s.threads[i].rsp)
sl: [80]char
viperlib.snprintf(&sl, 80, " t%d: st=%d pid=%d rsp=0x%lx\n", i, s.threads[i].state, s.threads[i].pid, s.threads[i].rsp)
serial.puts(sl)
File diff suppressed because it is too large. Load diff
+7 -8
View File
@@ -1,17 +1,16 @@
import t, c
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
SERVICE_KEYBOARD: t.CDefine = 1
@t.Object
define SERVICE_KEYBOARD = 1
class KeyboardService:
th: sched.Thread | t.CPtr
th: sched.Thread*
running: int
usb_kbd_th: sched.Thread | t.CPtr
usb_kbd_th: sched.Thread*
def __init__(self):
self.th = None
@@ -21,7 +20,7 @@ class KeyboardService:
kbd_svc: KeyboardService
def kbd_thread(arg: t.CPtr) -> int:
def kbd_thread(arg: rawptr) -> int:
serial.puts("[kbd_svc] started\n")
while True:
if keyboard.has_data():
@@ -30,12 +29,12 @@ def kbd_thread(arg: t.CPtr) -> int:
sched.Scheduler._yield()
return 0
def usb_kbd_thread(arg: t.CPtr) -> int:
def usb_kbd_thread(arg: rawptr) -> int:
serial.puts("[usb_kbd_svc] started\n")
evt: usb_kbd.usb_kbd_event
while True:
if usb_kbd.has_data():
usb_kbd.read_event(c.Addr(evt))
usb_kbd.read_event(&evt)
else:
sched.Scheduler._yield()
return 0
+1 -2
View File
@@ -1,10 +1,9 @@
import t, c
import drivers.input.mouse.mouse as mouse
import drivers.usb.hid.usb_mouse as usb_mouse
import drivers.serial.uart.serial as serial
import sched.sched as sched
SERVICE_MOUSE: t.CDefine = 2
define SERVICE_MOUSE = 2
def start() -> int:
serial.puts("[mse_svc] mouse initialized\n")