Skip to content
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d179509
initfs ok
bullhh Jun 2, 2026
bc3ef62
add debug
bullhh Jun 2, 2026
2cc7b08
opt qemu env
bullhh Jun 2, 2026
42468d0
rootfs
bullhh Jun 3, 2026
76d9f2b
opt
bullhh Jun 3, 2026
60d342d
optimize quick start
bullhh Jun 4, 2026
fcf5d0e
fix(axvisor): restore loongarch rootfs boot after dev rebase
bullhh Jun 4, 2026
e4f3226
opt
bullhh Jun 4, 2026
47999e1
fix: wait time etc
bullhh Jun 4, 2026
ad345c0
fix(axvisor): support LoongArch Linux rootfs boot with standard images
bullhh Jun 9, 2026
225f587
use init
bullhh Jun 9, 2026
03a7120
rebase
bullhh Jun 10, 2026
4e6e94a
add loongarch CI
bullhh Jun 10, 2026
64c2cbd
fix loongarch arcoes CI
bullhh Jun 10, 2026
c78efb5
fix(ci): raise Starry LoongArch QEMU memory
bullhh Jun 10, 2026
9736255
fix loongarch CI
bullhh Jun 10, 2026
ef4802a
docs(axvisor): clean LoongArch debug notes
bullhh Jun 11, 2026
12ee1b7
feat(axvisor): dyn to shell
bullhh Jun 12, 2026
9c9bda8
loongarch uefi ok
bullhh Jun 15, 2026
a2bfbb8
opt log
bullhh Jun 15, 2026
eaf4fba
refactor(axvisor): drop legacy LoongArch ELF and zboot loaders
bullhh Jun 15, 2026
70bf693
opt log
bullhh Jun 15, 2026
84aeaf7
optimize
bullhh Jun 15, 2026
2435122
chore(config): omit default dynamic platform flag
bullhh Jun 15, 2026
4907242
fix(starryos): restore LoongArch qemu memory size
bullhh Jun 16, 2026
5b18718
use dyn addr
bullhh Jun 18, 2026
7fd667d
feat(axvisor): refine LoongArch UEFI guest platform
bullhh Jun 18, 2026
554c4c4
feat(axvisor): support LoongArch UEFI Linux guests
bullhh Jun 22, 2026
cf50929
fix(axvisor): clean up LoongArch UEFI guest support
bullhh Jun 22, 2026
7adba68
fix(axvisor): restore LoongArch dynamic guest boot
bullhh Jun 22, 2026
404f862
fix(axvisor): remove unused LoongArch PCH PIC debug helper
bullhh Jun 22, 2026
e65d01b
fix(axbuild): expose musl bindgen helper to build tests
bullhh Jun 22, 2026
257210b
fix(axbuild): tolerate slow host HTTP receivers
bullhh Jun 22, 2026
9192595
fix(starry-kernel): synchronize ptrace text patches
bullhh Jun 22, 2026
711077a
fix(starry): stabilize LoongArch qemu system tests
bullhh Jun 22, 2026
0707a16
fix(starry): reduce curl fixture size for CI
bullhh Jun 22, 2026
6092416
fix(axvisor): align LoongArch qemu smoke boot config
bullhh Jun 22, 2026
b0c32bf
Revert "fix(starry): reduce curl fixture size for CI"
bullhh Jun 23, 2026
bbc2a29
fix(loongarch): route eiointc through registered driver
bullhh Jun 24, 2026
820fdad
fix(axvisor): harden LoongArch guest IRQ lifecycle
bullhh Jun 25, 2026
5f948aa
fix(loongarch-vcpu): move IOCSR state into VM lifecycle
bullhh Jun 25, 2026
ce3b4a6
fix(someboot): make LoongArch PE image base configurable
bullhh Jun 25, 2026
bc29586
fix(someboot): restore LoongArch default load address
bullhh Jun 25, 2026
2bf87be
fix(someboot): scope LoongArch fixed load address to AxVisor
bullhh Jun 26, 2026
6f34512
fix(axvisor): restore LoongArch guest boot after rebase
bullhh Jun 26, 2026
dcb9feb
fix(someboot): use hv for LoongArch load address
bullhh Jun 26, 2026
4c1ec3b
refactor(axvm): move LoongArch HV IRQ routing into runtime
bullhh Jun 26, 2026
b354b66
opt fdt
bullhh Jun 26, 2026
c6bc62f
refactor(axvisor): trim LoongArch guest boot changes
bullhh Jun 26, 2026
6b6db6c
refactor(axvisor): minimize LoongArch guest boot changes
bullhh Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/arch-platform-porting/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Use this skill when adding or fixing an architecture, switching QEMU cases to dy

For detailed pitfalls and debugging notes from the LoongArch dynamic UEFI/SMP bring-up, read `references/boot-debugging.md` when the task touches early boot, trap vectors, MMU, SMP, UEFI exit, or Axvisor LVZ QEMU.

Current Axvisor LoongArch QEMU tests intentionally use the static `ax-hal/loongarch64-qemu-virt` platform, non-UEFI QEMU boot, and an ELF kernel image without BIN conversion. Treat Axvisor LoongArch dynamic UEFI bring-up as a separate task unless the user explicitly asks to change that platform mode.
Current Axvisor LoongArch QEMU bring-up uses the dynamic UEFI platform path. The host AxVisor boots through LoongArch OVMF, and Linux guests boot through guest UEFI with the kernel/rootfs read from the AxVisor runtime rootfs and the local OVMF firmware captured at build time.

## First Pass

Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 24 additions & 2 deletions components/axcpu/src/loongarch64/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
use core::arch::asm;

use ax_memory_addr::{PhysAddr, VirtAddr};
use loongArch64::register::{crmd, ecfg, eentry, pgdh, pgdl};
use loongArch64::register::{
crmd,
ecfg::{self, LineBasedInterrupt},
eentry, pgdh, pgdl,
};

/// Allows the current CPU to respond to interrupts.
#[inline]
Expand All @@ -23,12 +27,30 @@ pub fn irqs_enabled() -> bool {
crmd::read().ie()
}

/// Enables or disables the local timer interrupt line.
#[inline]
pub fn set_timer_irq_enabled(enabled: bool) {
set_local_irq_line_enabled(LineBasedInterrupt::TIMER, enabled)
}

/// Enables or disables a local interrupt line.
#[inline]
fn set_local_irq_line_enabled(line: LineBasedInterrupt, enabled: bool) {
let current = ecfg::read().lie();
let new_value = if enabled {
current | line
} else {
current & !line
};
ecfg::set_lie(new_value);
}

/// Relaxes the current CPU and waits for interrupts.
///
/// It must be called with interrupts enabled, otherwise it will never return.
#[inline]
pub fn wait_for_irqs() {
unsafe { loongArch64::asm::idle() }
unsafe { asm!("idle 0", options(nomem, nostack)) }
}

/// Halt the current CPU.
Expand Down
9 changes: 9 additions & 0 deletions components/someboot/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ fn main() {
out_dir,
kernel_vaddr: 0x200000,
kernel_paddr: 0x200000,
efi_image_base: 0,
uspace,
hv,
page_size: 4096,
Expand Down Expand Up @@ -74,6 +75,7 @@ struct Build {
out_dir: PathBuf,
kernel_vaddr: u64,
kernel_paddr: u64,
efi_image_base: u64,
uspace: bool,
hv: bool,
page_size: usize,
Expand Down Expand Up @@ -115,6 +117,10 @@ impl Build {
}

fn prepare_loongarch64(&mut self) {
if self.hv {
self.kernel_paddr = 0x8000_0000;
self.efi_image_base = self.kernel_paddr;
}
self.kernel_vaddr = 0xffff_ffff_8000_0000;

println!("cargo:rustc-cfg=efi");
Expand Down Expand Up @@ -156,11 +162,14 @@ impl Build {
fn gen_defines(&self) {
let kernel_load_vaddr = self.kernel_vaddr as usize;
let kernel_load_paddr = self.kernel_paddr as usize;
let efi_image_base = self.efi_image_base as usize;
let defines = quote::quote! {
#[allow(dead_code)]
pub const VM_LOAD_ADDRESS: usize = #kernel_load_vaddr;
#[allow(dead_code)]
pub const KERNEL_LOAD_ADDRESS: usize = #kernel_load_paddr;
#[allow(dead_code)]
pub const EFI_IMAGE_BASE: usize = #efi_image_base;
};
let syntax_tree = syn::parse2(defines).unwrap();
let formatted = prettyplease::unparse(&syntax_tree);
Expand Down
10 changes: 7 additions & 3 deletions components/someboot/src/acpi/earlycon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ use crate::{
mem::_fixmap_io,
};

pub(crate) fn acpi_setup_earlycon() -> Result<(), AcpiError> {
pub(crate) fn acpi_setup_earlycon() -> Result<bool, AcpiError> {
setup_earlycon_from_spcr()
}

pub(crate) fn setup_earlycon_from_spcr() -> Result<bool, AcpiError> {
let tb = crate::acpi::tables()?;

for spsr in tb.find_tables::<Spcr>() {
if deal_with_spsr(&spsr).is_some() {
println!("Early console setup complete.");
break;
return Ok(true);
}
}

Ok(())
Ok(false)
}

fn deal_with_spsr(spsr: &PhysicalMapping<impl Handler, Spcr>) -> Option<()> {
Expand Down
5 changes: 3 additions & 2 deletions components/someboot/src/arch/loongarch64/head.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::arch::naked_asm;

// use super::entry::kernel_entry;
use crate::{
arch::addrspace::KERNEL_LOAD_ADDRESS,
arch::addrspace::{EFI_IMAGE_BASE, KERNEL_LOAD_ADDRESS},
efi_stub::{efi_pe_entry, pe::*},
};

Expand Down Expand Up @@ -48,7 +48,7 @@ pub unsafe extern "C" fn _head() {
".long _stext - _head", // BaseOfCode

// Extra header fields
".quad 0", // ImageBase
".quad {efi_image_base}", // ImageBase
".long PAGE_SIZE", // SectionAlignment (PECOFF_SEGMENT_ALIGN)
".long PECOFF_FILE_ALIGN", // FileAlignment (PECOFF_FILE_ALIGN)
".short 0", // MajorOperatingSystemVersion
Expand Down Expand Up @@ -110,6 +110,7 @@ pub unsafe extern "C" fn _head() {
dos_signature = const IMAGE_DOS_SIGNATURE,
linux_pe_magic = const LINUX_PE_MAGIC,
phys_link_kaddr = const KERNEL_LOAD_ADDRESS,
efi_image_base = const EFI_IMAGE_BASE,
efi_pe_entry = sym efi_pe_entry,
image_nt_signature = const IMAGE_NT_SIGNATURE,
file_machine = const IMAGE_FILE_MACHINE_LOONGARCH64,
Expand Down
5 changes: 5 additions & 0 deletions components/someboot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ pub fn post_allocator() {
arch::Arch::post_allocator();
}

/// Returns boot arguments captured from FDT, UEFI load options, or built into the image.
pub fn bootargs() -> Option<&'static str> {
cmdline::cmdline()
}

/// Get the current kernel page table physical address and ASID
pub fn kernel_page_table_paddr() -> usize {
arch::Arch::kernel_page_table().addr
Expand Down
83 changes: 83 additions & 0 deletions drivers/rdrive/src/probe/acpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,16 @@ pub struct AcpiResourceRange {
pub size: u64,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AcpiResourceDevice {
pub path: String,
pub hid: Option<String>,
pub cids: Vec<String>,
pub memory_ranges: Vec<AcpiResourceRange>,
pub io_ranges: Vec<AcpiResourceRange>,
pub irq_routes: Vec<AcpiGsiRoute>,
}

#[derive(Debug, Clone)]
struct AcpiDeviceInfo {
path: String,
Expand Down Expand Up @@ -832,6 +842,19 @@ impl AcpiInfo<'_> {
}
}

impl From<AcpiDeviceInfo> for AcpiResourceDevice {
fn from(value: AcpiDeviceInfo) -> Self {
Self {
path: value.path,
hid: value.hid,
cids: value.cids,
memory_ranges: value.memory_ranges,
io_ranges: value.io_ranges,
irq_routes: value.irq_routes,
}
}
}

pub struct ProbeAcpi<'a> {
info: AcpiInfo<'a>,
platform: PlatformDevice,
Expand Down Expand Up @@ -1194,6 +1217,29 @@ impl System {
})
}

pub fn resource_devices(&self) -> Result<Vec<AcpiResourceDevice>, ProbeError> {
self.device_infos().map(|devices| {
devices
.into_iter()
.map(AcpiResourceDevice::from)
.collect::<Vec<_>>()
})
}

pub fn serial_console_memory_range(&self) -> Option<AcpiResourceRange> {
let tables = self.handler.root.tables().ok()?;
let spcr = tables.find_table::<acpi::sdt::spcr::Spcr>()?;
let address = spcr.base_address()?.ok()?;
if address.address_space != acpi::address::AddressSpace::SystemMemory {
return None;
}

Some(AcpiResourceRange {
base: address.address,
size: spcr_uart_register_size(address.access_size),
})
}

pub fn pci_irq_for_endpoint(
&self,
info: PciInfo,
Expand Down Expand Up @@ -1336,6 +1382,32 @@ impl System {
Ok(devices)
}

fn device_infos(&self) -> Result<Vec<AcpiDeviceInfo>, ProbeError> {
let mut devices = Vec::new();
let mut namespace = self.interpreter.namespace.lock().clone();
namespace
.traverse(|path, level| {
if level.kind != NamespaceLevelKind::Device {
return Ok(true);
}
let Some((hid, cids)) = acpi_device_ids(&self.interpreter, path)? else {
return Ok(true);
};
let resources = read_device_resources(&self.interpreter, path, &self.routing)?;
devices.push(AcpiDeviceInfo {
path: path.as_string(),
hid: Some(hid),
cids,
memory_ranges: resources.memory_ranges,
io_ranges: resources.io_ranges,
irq_routes: resources.irq_routes,
});
Ok(true)
})
.map_err(|err| ProbeError::OnProbe(OnProbeError::other(format!("{err:?}"))))?;
Ok(devices)
}

fn probe_register(
&self,
register: &DriverRegister,
Expand Down Expand Up @@ -1556,6 +1628,17 @@ fn read_loongarch_bio_pic_entry(
});
}

fn spcr_uart_register_size(access_size: u8) -> u64 {
let access_bytes = match access_size {
1 => 1,
2 => 2,
3 => 4,
4 => 8,
_ => 1,
};
access_bytes * 8
}

#[derive(Default)]
struct AcpiDeviceResources {
memory_ranges: Vec<AcpiResourceRange>,
Expand Down
29 changes: 19 additions & 10 deletions os/StarryOS/kernel/src/syscall/task/ptrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,7 @@ fn ptrace_write_word(tracee: &ProcessData, addr: usize, data: usize) -> AxResult
let mut aspace = aspace.lock();
ptrace_populate_remote_range(&mut aspace, addr, size_of::<usize>(), MappingFlags::WRITE)?;
aspace.write(VirtAddr::from_usize(addr), &data.to_ne_bytes())?;
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(addr, size_of::<usize>());
Ok(())
}

Expand Down Expand Up @@ -1121,7 +1121,7 @@ fn remote_write(tracee: &ProcessData, addr: usize, data: &[u8]) -> AxResult {
let mut aspace = aspace.lock();
ptrace_populate_remote_range(&mut aspace, addr, data.len(), MappingFlags::WRITE)?;
aspace.write(VirtAddr::from_usize(addr), data)?;
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(addr, data.len());
Ok(())
}

Expand Down Expand Up @@ -1217,7 +1217,7 @@ pub fn ptrace_setup_singlestep(
};
if orig_insn == EBREAK_INSN {
tracee.set_ptrace_ss_saved_insn_for(tid, None);
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u16>());
return;
}

Expand All @@ -1226,7 +1226,7 @@ pub fn ptrace_setup_singlestep(
return;
}
tracee.set_ptrace_ss_saved_insn_for(tid, Some((next_insn_addr, orig_insn as usize)));
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u16>());
}

#[cfg(target_arch = "aarch64")]
Expand Down Expand Up @@ -1261,7 +1261,7 @@ pub fn ptrace_setup_singlestep(
};
if orig_insn == AARCH64_BRK_INSN {
tracee.set_ptrace_ss_saved_insn_for(tid, None);
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u32>());
return;
}

Expand All @@ -1270,7 +1270,7 @@ pub fn ptrace_setup_singlestep(
return;
}
tracee.set_ptrace_ss_saved_insn_for(tid, Some((next_insn_addr, orig_insn as usize)));
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u32>());
}

#[cfg(target_arch = "loongarch64")]
Expand Down Expand Up @@ -1305,7 +1305,7 @@ pub fn ptrace_setup_singlestep(
};
if orig_insn == LOONGARCH_BREAK_INSN {
tracee.set_ptrace_ss_saved_insn_for(tid, None);
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u32>());
return;
}

Expand All @@ -1314,7 +1314,7 @@ pub fn ptrace_setup_singlestep(
return;
}
tracee.set_ptrace_ss_saved_insn_for(tid, Some((next_insn_addr, orig_insn as usize)));
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(next_insn_addr, size_of::<u32>());
}

#[cfg(target_arch = "riscv64")]
Expand All @@ -1327,7 +1327,7 @@ pub fn ptrace_restore_singlestep_insn(
let aspace = tracee.aspace();
let mut aspace = aspace.lock();
let restored = ptrace_write_u16_unlocked(&mut aspace, addr, insn as u16).is_ok();
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(addr, size_of::<u16>());
if !restored {
tracee.set_ptrace_ss_saved_insn_for(tid, Some((addr, insn)));
}
Expand All @@ -1344,7 +1344,7 @@ pub fn ptrace_restore_singlestep_insn(
let aspace = tracee.aspace();
let mut aspace = aspace.lock();
let restored = ptrace_write_u32_unlocked(&mut aspace, addr, insn as u32).is_ok();
ax_runtime::hal::cpu::asm::flush_icache_all();
sync_user_text_patch(addr, size_of::<u32>());
if !restored {
tracee.set_ptrace_ss_saved_insn_for(tid, Some((addr, insn)));
}
Expand Down Expand Up @@ -1770,6 +1770,15 @@ fn ptrace_write_u32_unlocked(aspace: &mut AddrSpace, addr: usize, data: u32) ->
Ok(())
}

fn sync_user_text_patch(addr: usize, len: usize) {
#[cfg(target_arch = "aarch64")]
ax_runtime::hal::cpu::asm::clean_dcache_range_to_pou(VirtAddr::from_usize(addr), len);
#[cfg(not(target_arch = "aarch64"))]
let _ = (addr, len);

ax_runtime::hal::cpu::asm::flush_icache_all();
}

pub fn ptrace_notify_clone(parent_pid: Pid, parent_tid: Pid, child_pid: Pid, event: u32) -> bool {
let Ok(parent) = get_process_data(parent_pid) else {
return false;
Expand Down
Loading
Loading