Skip to content

Commit

Permalink
try to add loongarch64 support
Browse files Browse the repository at this point in the history
  • Loading branch information
yfblock committed Mar 21, 2024
1 parent f7b688a commit 173911b
Show file tree
Hide file tree
Showing 21 changed files with 363 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ rustflags = [
'-Cforce-frame-pointers=yes',
'-Clink-arg=-no-pie',
'--cfg=board="qemu"',
'--cfg=driver="kvirtio,kgoldfish-rtc,ns16550a"',
'--cfg=driver="kgoldfish-rtc,ns16550a,kramdisk"',
# '-Zunstable-options',
# '--check-cfg=values(board, "qemu","k210","cv1811h", "knvme", "")',
# '--cfg=kernel_base="0xffffffc080200000"', # riscv64imac-unknown-none-elf
Expand Down
13 changes: 13 additions & 0 deletions Cargo.lock

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

8 changes: 1 addition & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,7 @@ members = [
"modules/signal",

#drivers
"drivers/kgoldfish-rtc",
"drivers/knvme",
"drivers/kvirtio",
"drivers/kcvitek-sd",
"drivers/k210-sdcard",
"drivers/general-plic",
"drivers/ns16550a",
"drivers/*",

# kernel
"kernel"
Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ else ifeq ($(ARCH), aarch64)
-kernel $(KERNEL_BIN)
else ifeq ($(ARCH), loongarch64)
TARGET := loongarch64-unknown-none
QEMU_EXEC += qemu-system-$(ARCH) -bios tools/qemu_8.2_uefi_bios.bin -kernel $(KERNEL_ELF)
QEMU_EXEC += qemu-system-$(ARCH) -kernel $(KERNEL_ELF)
BUS := pci
else
$(error "ARCH" must be one of "x86_64", "riscv64", "aarch64" or "loongarch64")
Expand All @@ -48,7 +48,7 @@ K210-BURNER = tools/k210/kflash.py
QEMU_EXEC += -m 1G\
-nographic \
-smp 1 \
-D qemu.log -d in_asm,int,mmu,pcall,cpu_reset,guest_errors
-D qemu.log -d in_asm,mmu,pcall,cpu_reset,guest_errors

BUILD_ARGS :=
ifeq ($(RELEASE), release)
Expand Down Expand Up @@ -84,7 +84,7 @@ offline:

fs-img:
rm -f $(FS_IMG)
dd if=/dev/zero of=$(FS_IMG) bs=1M count=2000
dd if=/dev/zero of=$(FS_IMG) bs=1M count=64
mkfs.vfat -F 32 $(FS_IMG)
mkdir mount/ -p
sudo mount $(FS_IMG) mount/ -o uid=1000,gid=1000
Expand Down Expand Up @@ -126,7 +126,7 @@ flash: k210-build
python3 -m serial.tools.miniterm --eol LF --dtr 0 --rts 0 --filter direct $(K210-SERIALPORT) 115200

debug: fs-img build
@tmux new-session -d \tools/qemu_8.2_uefi_bios.bin
@tmux new-session -d \
"$(QEMU_EXEC) -s -S && echo '按任意键继续' && read -n 1" && \
tmux split-window -h "$(GDB) $(KERNEL_ELF) -ex 'target remote localhost:1234' -ex 'disp /16i $pc' " && \
tmux -2 attach-session -d
Expand Down
1 change: 1 addition & 0 deletions arch/src/aarch64/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tock_registers::interfaces::{Readable, Writeable};
pub fn get_time() -> usize {
CNTPCT_EL0.get() as _
}

#[inline]
pub fn time_to_usec(ts: usize) -> usize {
ts * 1000_000 / CNTFRQ_EL0.get() as usize
Expand Down
4 changes: 4 additions & 0 deletions arch/src/loongarch64/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ impl Context {
#[inline]
pub fn new() -> Self {
Self {
// bit 1:0 PLV
// bit 2 PIE
// bit 3 PWE
prmd: (0b1111),
..Default::default()
}
}
Expand Down
12 changes: 4 additions & 8 deletions arch/src/loongarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use console::{console_getchar, console_putchar};
pub use consts::*;
pub use context::Context;
pub use page_table::*;
pub use timer::get_time;
pub use timer::{get_time, time_to_usec};
pub use trap::{enable_external_irq, enable_irq, init_interrupt, run_user_task};

use crate::{clear_bss, ArchInterface};
Expand All @@ -26,16 +26,12 @@ pub fn rust_tmp_main(hart_id: usize) {
VIRT_ADDR_START | (0x9000_0000 + 0x2000_0000),
);
info!("hart_id: {}", hart_id);
unsafe {
core::arch::asm!("break 2");
}

ArchInterface::prepare_drivers();

shutdown();
}
ArchInterface::main(0);

pub fn time_to_usec(_t: usize) -> usize {
todo!("time to usec")
shutdown();
}

pub fn switch_to_kernel_page_table() {
Expand Down
113 changes: 40 additions & 73 deletions arch/src/loongarch64/page_table.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloc::sync::Arc;
use loongarch64::register::pgdl;

use crate::{
ArchInterface, MappingFlags, PhysAddr, PhysPage, VirtAddr, VirtPage, PAGE_ITEM_COUNT, PAGE_SIZE,
Expand All @@ -14,23 +15,13 @@ impl PTE {
}

#[inline]
pub const fn from_ppn(ppn: usize, flags: PTEFlags) -> Self {
PTE((ppn << 12) | flags.bits())
pub const fn from_addr(ppn: PhysAddr, flags: PTEFlags) -> Self {
PTE(ppn.0 | flags.bits())
}

#[inline]
pub const fn from_addr(addr: usize, flags: PTEFlags) -> Self {
Self::from_ppn(addr >> 12, flags)
}

#[inline]
pub const fn to_ppn(&self) -> PhysPage {
PhysPage((self.0 & 0xffff_ffff_ffff_f000) >> 12)
}

#[inline]
pub fn set(&mut self, ppn: usize, flags: PTEFlags) {
self.0 = (ppn << 10) | flags.bits() as usize;
pub const fn addr(&self) -> PhysAddr {
PhysAddr(self.0 & 0xffff_ffff_ffff_f000)
}

#[inline]
Expand All @@ -40,12 +31,7 @@ impl PTE {

#[inline]
pub const fn is_valid(&self) -> bool {
self.flags().contains(PTEFlags::VALID)
}

#[inline]
pub fn is_block(&self) -> bool {
self.flags().contains(PTEFlags::NON_BLOCK)
self.0 != 0
}

#[inline]
Expand All @@ -56,17 +42,17 @@ impl PTE {

impl From<MappingFlags> for PTEFlags {
fn from(value: MappingFlags) -> Self {
let mut flags = PTEFlags::VALID | PTEFlags::NON_BLOCK | PTEFlags::AF | PTEFlags::NG;
let mut flags = PTEFlags::V | PTEFlags::D;
if !value.contains(MappingFlags::W) {
flags |= PTEFlags::AP_RO;
flags |= PTEFlags::W;
}

if !value.contains(MappingFlags::X) {
flags |= PTEFlags::UXN | PTEFlags::PXN;
flags |= PTEFlags::NX;
}

if value.contains(MappingFlags::U) {
flags |= PTEFlags::AP_EL0;
flags |= PTEFlags::PLV_USER;
}
flags
}
Expand All @@ -75,50 +61,31 @@ impl From<MappingFlags> for PTEFlags {
bitflags::bitflags! {
/// Possible flags for a page table entry.
pub struct PTEFlags: usize {
// Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors:
/// Whether the descriptor is valid.
const VALID = 1 << 0;
/// The descriptor gives the address of the next level of translation table or 4KB page.
/// (not a 2M, 1G block)
const NON_BLOCK = 1 << 1;
/// Memory attributes index field.
const ATTR_INDX = 0b111 << 2;
const NORMAL_NONCACHE = 0b010 << 2;
/// Non-secure bit. For memory accesses from Secure state, specifies whether the output
/// address is in Secure or Non-secure memory.
const NS = 1 << 5;
/// Access permission: accessable at EL0.
const AP_EL0 = 1 << 6;
/// Access permission: read-only.
const AP_RO = 1 << 7;
/// Shareability: Inner Shareable (otherwise Outer Shareable).
const INNER = 1 << 8;
/// Shareability: Inner or Outer Shareable (otherwise Non-shareable).
const SHAREABLE = 1 << 9;
/// The Access flag.
const AF = 1 << 10;
/// The not global bit.
const NG = 1 << 11;
/// Indicates that 16 adjacent translation table entries point to contiguous memory regions.
const CONTIGUOUS = 1 << 52;
/// The Privileged execute-never field.
const PXN = 1 << 53;
/// The Execute-never or Unprivileged execute-never field.
const UXN = 1 << 54;

// Next-level attributes in stage 1 VMSAv8-64 Table descriptors:

/// PXN limit for subsequent levels of lookup.
const PXN_TABLE = 1 << 59;
/// XN limit for subsequent levels of lookup.
const XN_TABLE = 1 << 60;
/// Access permissions limit for subsequent levels of lookup: access at EL0 not permitted.
const AP_NO_EL0_TABLE = 1 << 61;
/// Access permissions limit for subsequent levels of lookup: write access not permitted.
const AP_NO_WRITE_TABLE = 1 << 62;
/// For memory accesses from Secure state, specifies the Security state for subsequent
/// levels of lookup.
const NS_TABLE = 1 << 63;
/// Page Valid
const V = 1 << 0;
/// Dirty, The page has been writed.
const D = 1 << 1;

const PLV_USER = 0b11 << 2;

const MAT_NOCACHE = 0b01 << 4;

/// Designates a global mapping OR Whether the page is huge page.
const GH = 1 << 6;

/// Page is existing.
const P = 1 << 7;
/// Page is writeable.
const W = 1 << 8;
/// Is a Global Page if using huge page(GH bit).
const G = 1 << 10;
/// Page is not readable.
const NR = 1 << 11;
/// Page is not executable.
const NX = 1 << 12;
/// Whether the privilege Level is restricted. When RPLV is 0, the PTE
/// can be accessed by any program with privilege Level highter than PLV.
const RPLV = 1 << 63;
}
}

Expand All @@ -145,7 +112,7 @@ impl PageTable {

#[inline]
pub fn change(&self) {
todo!("change pagetable")
pgdl::set_base(self.0.addr());
}

#[inline]
Expand All @@ -156,19 +123,19 @@ impl PageTable {
// l2 pte
let l2_pte = &mut l1_list[l1_index];
if !l2_pte.is_valid() {
*l2_pte = PTE(ArchInterface::frame_alloc_persist().to_addr() | 0b11);
*l2_pte = PTE(ArchInterface::frame_alloc_persist().to_addr());
}
let l2_list = l2_pte.get_next_ptr().slice_mut_with_len::<PTE>(512);
let l2_index = (vpn.0 >> 9) & 0x1ff;

// l3 pte
let l3_pte = &mut l2_list[l2_index];
if !l3_pte.is_valid() {
*l3_pte = PTE(ArchInterface::frame_alloc_persist().to_addr() | 0b11);
*l3_pte = PTE(ArchInterface::frame_alloc_persist().to_addr());
}
let l3_list = l3_pte.get_next_ptr().slice_mut_with_len::<PTE>(512);
let l3_index = vpn.0 & 0x1ff;
l3_list[l3_index] = PTE::from_ppn(ppn.0, flags.into());
l3_list[l3_index] = PTE::from_addr(ppn.into(), flags.into());
}

#[inline]
Expand All @@ -187,7 +154,7 @@ impl PageTable {
if !pte.is_valid() {
return None;
}
paddr = pte.to_ppn().into()
paddr = pte.addr()
}
Some(PhysAddr(paddr.0 | vaddr.0 % PAGE_SIZE))
}
Expand Down
14 changes: 13 additions & 1 deletion arch/src/loongarch64/timer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
/// Returns the current clock time in hardware ticks.
use loongarch64::time::{get_timer_freq, Time};
use spin::Lazy;

// static mut FREQ: usize = 0;
static FREQ: Lazy<usize> = Lazy::new(|| get_timer_freq());

/// Returns the current clock time in hardware ticks.
#[inline]
pub fn get_time() -> usize {
todo!("get_time")
Time::read()
}

#[inline]
pub fn time_to_usec(ts: usize) -> usize {
ts * 1000_000 / *FREQ
}
Loading

0 comments on commit 173911b

Please sign in to comment.