chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
This commit is contained in:
1 parent
1c3fcd6e1e
commit
dcb7c5c2c0
26 files changed
+1558
-1790
No files matched your search
+18
-21
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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))
|
||||
@@ -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():
|
||||
|
||||
@@ -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):
|
||||
# 参数验证:确保频率为正数
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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])
|
||||
@@ -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)
|
||||
+232
-233
File diff suppressed because it is too large.
Load diff
@@ -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,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")
|
||||
|
||||
Reference in new issue
Block a user