Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Add loongarch64 support #225

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

yfblock
Copy link
Contributor

@yfblock yfblock commented Feb 17, 2025

@yfblock
Copy link
Contributor Author

yfblock commented Feb 17, 2025

@yfblock
Copy link
Contributor Author

yfblock commented Feb 17, 2025

运行 Starry-next:

image

@Azure-stars
Copy link
Contributor

Please fix the error from la64 ci-test.

@yfblock
Copy link
Contributor Author

yfblock commented Feb 19, 2025

Please fix the error from la64 ci-test.

Need new version of arceos-apps, but haven't merged。

@Azure-stars
Copy link
Contributor

Please fix the error from la64 ci-test.

Need new version of arceos-apps, but haven't merged it yet!

You can modify https://github.com/arceos-org/arceos/blob/main/.github/workflows/test.yml#L8 to choose a suitable commit of arceos-apps, not need to care whether the PR in arceoes-apps has been merged.

@yfblock yfblock force-pushed the main branch 2 times, most recently from 71c524a to ae31649 Compare February 19, 2025 10:46
@yfblock
Copy link
Contributor Author

yfblock commented Feb 19, 2025

Please fix the error from la64 ci-test.

Need new version of arceos-apps, but haven't merged it yet!

You can modify https://github.com/arceos-org/arceos/blob/main/.github/workflows/test.yml#L8 to choose a suitable commit of arceos-apps, not need to care whether the PR in arceoes-apps has been merged.

Unfortunately, that doesn't solve the problem.

@yfblock
Copy link
Contributor Author

yfblock commented Feb 19, 2025

I migrated arceos-apps and arceos to oscomp and then changed the dependency

DownStream CI: https://github.com/oscomp/arceos/actions/runs/13418318407

run: |
TOOLCHAIN_REPO=https://github.com/LoongsonLab/oscomp-toolchains-for-oskernel
wget ${TOOLCHAIN_REPO}/releases/download/gcc-13.2.0-loongarch64/gcc-13.2.0-loongarch64-linux-gnu.tgz
wget ${TOOLCHAIN_REPO}/raw/refs/heads/main/musl-loongarch64-1.2.2.tgz
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to download both gnu and musl toolchain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This musl is just a warpper

#!/bin/sh

MUSL_DIR=$(cd $(dirname $0)/..; pwd)

exec "${REALGCC:-loongarch64-linux-gnu-gcc}" "$@" -specs "${MUSL_DIR}/lib/musl-gcc.specs"

}
let stack_top_virt_addr = phys_to_virt(stack_top).as_usize();
unsafe {
SMP_BOOT_STACK_TOP = stack_top_virt_addr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloud this global variable access be avoided? Could the stack pointer be passed through the mailbox argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -68,7 +68,7 @@ SECTIONS
. = ALIGN(4K);
_edata = .;

.bss : ALIGN(4K) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference is the lma in the .bss section.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Sections:
Idx Name              Size     VMA              LMA              Type
  0                   00000000 0000000000000000 0000000000000000 
  1 .text             0000f000 ffff000080000000 ffff000080000000 TEXT
  2 .rodata           00003c80 ffff00008000f000 ffff00008000f000 DATA
  3 .init_array       00000000 ffff000080012c80 ffff000080012c80 
  4 .data             00002018 ffff000080013000 ffff000080013000 DATA
  5 .tdata            00000000 ffff000080015020 ffff000080015020 DATA
  6 .tbss             00000000 ffff000080015020 ffff000080015020 DATA
  7 linkme_IRQ        00000000 ffff000080015020 ffff000080015020 DATA
  8 linkm2_IRQ        00000008 ffff000080015020 ffff000080015020 DATA
  9 linkme_PAGE_FAULT 00000000 ffff000080015028 ffff000080015028 DATA
 10 linkm2_PAGE_FAULT 00000008 ffff000080015028 ffff000080015028 DATA
 11 .percpu           00000040 0000000000000000 ffff000080016000 DATA
 12 .bss              00044000 ffff000080017000 ffff000080017000 BSS
 13 .symtab           000011d0 0000000000000000 0000000000000000 
 14 .shstrtab         0000008f 0000000000000000 0000000000000000 
 15 .strtab           0000273a 0000000000000000 0000000000000000 

Not Added

Sections:
Idx Name              Size     VMA              LMA              Type
  0                   00000000 0000000000000000 0000000000000000 
  1 .text             0000f000 ffff000080000000 ffff000080000000 TEXT
  2 .rodata           00003c78 ffff00008000f000 ffff00008000f000 DATA
  3 .init_array       00000000 ffff000080012c80 ffff000080012c80 
  4 .data             00002018 ffff000080013000 ffff000080013000 DATA
  5 .tdata            00000000 ffff000080015020 ffff000080015020 DATA
  6 .tbss             00000000 ffff000080015020 ffff000080015020 DATA
  7 linkme_IRQ        00000000 ffff000080015020 ffff000080015020 DATA
  8 linkm2_IRQ        00000008 ffff000080015020 ffff000080015020 DATA
  9 linkme_PAGE_FAULT 00000000 ffff000080015028 ffff000080015028 DATA
 10 linkm2_PAGE_FAULT 00000008 ffff000080015028 ffff000080015028 DATA
 11 .percpu           00000040 0000000000000000 ffff000080016000 DATA
 12 .bss              00044000 ffff000080017000 fffe00010002d000 BSS
 13 .symtab           000011d0 0000000000000000 0000000000000000 
 14 .shstrtab         0000008f 0000000000000000 0000000000000000 
 15 .strtab           0000273a 0000000000000000 0000000000000000  

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not added will display:

qemu-system-loongarch64: could not load kernel 'examples/helloworld/helloworld_loongarch64-qemu-virt.elf': The image segments are too big to load

@@ -0,0 +1,286 @@
use core::arch::naked_asm;
use memory_addr::VirtAddr;
/// Saved registers when a trap (interrupt or exception) occurs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add blank line

#[derive(Debug, Default, Clone, Copy)]
pub struct TrapFrame {
/// All general registers.
pub regs: [usize; 32],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend listing all register names like a0, s0 (same as riscv), which avoids magic register offset such as regs[4].


ld.d $sp, $sp, 3*8 // user sp
ertn
",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having the inline asm code end with a single " line, we can move the " to the end of the last line.

Same for many places.

tlbrehi::set_ps(PS_4K);

// Set Page table entry width
pwcl::set_pte_width(8);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use LA64MetaData::PWCL_VALUE

/// Initializes CPU states on the current CPU.
pub fn cpu_init() {
// Enable floating point
euen::set_fpe(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enable FP conditionally with the fp_simd feature.

.endm

.macro RESTORE_REGS
csrrd $t0, 0x1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use .equ PRMD, 0x1

ld.d $s7, $sp, 30*8
ld.d $s8, $sp, 31*8
.endm

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove blank line

@@ -21,6 +21,9 @@ else ifeq ($(ARCH), aarch64)
else
machine := virt
endif
else ifeq ($(ARCH), loongarch64)
machine := virt
override MEM := 1G
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it requires 1G memory?

/// Exception Return Address
pub era: usize,
/// Access Memory Address When Exception
pub badv: usize,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

badv and crmd don't need to be saved in TrapFrame, do they? We can use csrrd to get them when we need them.

unsafe {
core::arch::asm!(
r"
.equ KSAVE_KSP, 0x30
Copy link
Member

@equation314 equation314 Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the common .equ definition and the ld.d sequence into a macro, like include_asm_macros in riscv.


super::disable_irqs();
prmd::set_pplv(CpuMode::Ring3);
prmd::set_pie(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not write self.prmd to the actual CSR.PRMD?


impl TaskContext {
/// Creates a new default context for a new task.
pub const fn new() -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TaskContext::new does not require const, use safe code instead.

pub s: [usize; 10], // loongArch need to save 10 static registers from $r22 to $r31
pub tp: usize,
#[cfg(feature = "uspace")]
pub pgdl: usize,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments to indicate it's the user page table root.

self.tp = tls_area.as_usize();
}

/// Changes the page table root (`pgdl` register for loongarch64).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments not matched


// restore new context
ld.d $ra, $a1, 0
ld.d $s0, $a1, 2 * 8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjust the restore order: fp, s8, ..., s0, sp, ra

@@ -0,0 +1,62 @@
use loongArch64::time::Time;

const NANOS_PER_TICK: u64 = crate::time::NANOS_PER_SEC / axconfig::devices::TIMER_FREQUENCY as u64;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get timer frequency by loongArch64::time::get_timer_freq?

let init_value = ticks_deadline - ticks_now;

// This initial value must be an integer multiple of 4.
tcfg::set_init_val(((init_value + 3) & !3) as _);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alignment of init_value is unnecessary, its lowest two bits are simply ignored.


// This initial value must be an integer multiple of 4.
tcfg::set_init_val(((init_value + 3) & !3) as _);
tcfg::set_periodic(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting periodic and en again is also unnecessary.

/// The timer IRQ number.
pub const TIMER_IRQ_NUM: usize = 11;

static TIMER_HANDLER: LazyInit<IrqHandler> = LazyInit::new();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardware interrupts and timer interrupts are numbered together in la64, so we can manage them uniformly with axhal::irq::IRQ_HANDLER_TABLE. The separate TIMER_HANDLER is unnecessary.

pub const EXT_IRQ_NUM: usize = 2;

/// The timer IRQ number.
pub const TIMER_IRQ_NUM: usize = 11;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get it from estat::Interrupt::Timer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants