-
Notifications
You must be signed in to change notification settings - Fork 308
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
base: main
Are you sure you want to change the base?
Conversation
Please fix the error from la64 ci-test. |
Need new version of arceos-apps, but haven't merged。 |
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. |
71c524a
to
ae31649
Compare
Unfortunately, that doesn't solve the problem. |
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why need this change?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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], |
There was a problem hiding this comment.
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 | ||
", |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 | ||
|
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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). |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 _); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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
Related PR: