Skip to content

Commit

Permalink
feat: handle data length exceeding PAGE_SIZE_4K
Browse files Browse the repository at this point in the history
  • Loading branch information
Azure-stars committed Aug 6, 2024
1 parent ff0e30e commit c29aee2
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 25 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/actions/setup-musl/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Download musl toolchain

inputs:
arch:
description: 'Architecture'
required: true
type: string

runs:
using: "composite"
steps:
- name: Cache musl
id: cache-musl
uses: actions/cache/restore@v3
with:
path: ${{ inputs.arch }}-linux-musl-cross
key: ${{ inputs.arch }}-linux-musl-cross
- name: Download musl toolchain
if: steps.cache-musl.outputs.cache-hit != 'true'
shell: bash
run: |
MUSL_PATH=${{ inputs.arch }}-linux-musl-cross
wget https://musl.cc/${MUSL_PATH}.tgz
tar -xf ${MUSL_PATH}.tgz
- uses: actions/cache/save@v3
if: steps.cache-musl.outputs.cache-hit != 'true'
with:
path: ${{ inputs.arch }}-linux-musl-cross
key: ${{ inputs.arch }}-linux-musl-cross

- name: Add to PATH environment variable
shell: bash
run: |
echo "$PWD/${{ inputs.arch }}-linux-musl-cross/bin" >> $GITHUB_PATH
- name: Verify installation
shell: bash
run: |
${{ inputs.arch }}-linux-musl-gcc --version
46 changes: 46 additions & 0 deletions .github/workflows/actions/setup-qemu/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Download and build QEMU

inputs:
qemu-version:
description: 'QEMU version'
required: true
type: string

runs:
using: "composite"
steps:
- name: Cache QEMU
id: cache-qemu
uses: actions/cache/restore@v3
with:
path: qemu_build
key: qemu-${{ inputs.qemu-version }}-slirp-1
- name: Download and build QEMU
if: steps.cache-qemu.outputs.cache-hit != 'true'
env:
QEMU_PATH: qemu-${{ inputs.qemu-version }}
PREFIX: ${{ github.workspace }}/qemu_build
shell: bash
run: |
sudo apt-get update && sudo apt-get install -y ninja-build libslirp-dev
wget https://download.qemu.org/$QEMU_PATH.tar.xz && tar -xJf $QEMU_PATH.tar.xz
cd $QEMU_PATH \
&& ./configure --prefix=$PREFIX --target-list=x86_64-softmmu,riscv64-softmmu,aarch64-softmmu --enable-slirp \
&& make -j > /dev/null 2>&1 \
&& make install
- uses: actions/cache/save@v3
if: steps.cache-qemu.outputs.cache-hit != 'true'
with:
path: qemu_build
key: qemu-${{ inputs.qemu-version }}-slirp-1

- name: Install QEMU
shell: bash
run: |
echo "$PWD/qemu_build/bin" >> $GITHUB_PATH
- name: Verify installation
shell: bash
run: |
qemu-system-x86_64 --version
qemu-system-aarch64 --version
qemu-system-riscv64 --version
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ jobs:
- uses: Swatinem/rust-cache@v2
- run: cargo install cargo-binutils
- run: ./scripts/get_deps.sh
- uses: ./.arceos/.github/workflows/actions/setup-musl
- uses: ./.github/workflows/actions/setup-musl
with:
arch: ${{ matrix.arch }}
- uses: ./.arceos/.github/workflows/actions/setup-qemu
- uses: ./.github/workflows/actions/setup-qemu
with:
qemu-version: ${{ env.qemu-version }}
- name: Run tests
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ user_apps:
test:
@./scripts/app_test.sh

build run justrun debug disasm clean: ax_root
build run justrun debug disasm: ax_root
@make -C $(AX_ROOT) A=$(PWD) $@

clean: ax_root
@make -C $(AX_ROOT) A=$(PWD) clean
@cargo clean

.PHONY: all ax_root build run justrun debug disasm clean
2 changes: 1 addition & 1 deletion apps/nimbos/test_cmd
Original file line number Diff line number Diff line change
@@ -1 +1 @@
test_one "LOG=error" "expect_off.out"
test_one "LOG=off" "expect_off.out"
2 changes: 1 addition & 1 deletion src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub(crate) fn load_user_app(name: &str) -> ELFInfo {
size: ed_vaddr_align.as_usize() - st_vaddr_align.as_usize(),
flags: into_mapflag(ph.flags()),
data,
offset: st_vaddr.as_usize() - st_vaddr_align.as_usize(),
offset: st_vaddr.align_offset_4k(),
});
});
ELFInfo {
Expand Down
7 changes: 3 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod loader;
mod mm;
mod syscall;
mod task;
use alloc::{sync::Arc, vec::Vec};
use alloc::sync::Arc;

use axhal::arch::UspaceContext;
use axsync::Mutex;
Expand All @@ -21,11 +21,10 @@ const KERNEL_STACK_SIZE: usize = 0x40000; // 256 KiB
#[no_mangle]
fn main() {
loader::list_apps();
let testcases: Vec<&'static str> = option_env!("AX_TESTCASES_LIST")
let testcases = option_env!("AX_TESTCASES_LIST")
.unwrap_or_else(|| "Please specify the testcases list by making user_apps")
.split(',')
.filter(|&x| !x.is_empty())
.collect();
.filter(|&x| !x.is_empty());
for testcase in testcases {
let (entry_vaddr, ustack_top, uspace) = mm::load_user_app(testcase).unwrap();
let user_task = task::spawn_user_task(
Expand Down
66 changes: 50 additions & 16 deletions src/mm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,70 @@ pub fn load_user_app(app_name: &str) -> AxResult<(VirtAddr, VirtAddr, AddrSpace)
let mut uspace = axmm::new_user_aspace()?;
for segement in elf_info.segments {
debug!(
"Mapping ELF segment: {:#x?} -> {:#x?} flags: {:#x?}",
"Mapping ELF segment: [{:#x?}, {:#x?}) flags: {:#x?}",
segement.start_vaddr,
segement.start_vaddr + segement.size,
segement.flags
);
uspace.map_alloc(segement.start_vaddr, segement.size, segement.flags, true)?;

let (segement_start_paddr, _, _) = uspace
.page_table()
.query(segement.start_vaddr)
.unwrap_or_else(|_| panic!("Mapping failed for segment: {:#x?}", segement.start_vaddr));
if segement.data.is_empty() {
continue;
}

let segement_page_iter = memory_addr::PageIter4K::new(
segement.start_vaddr,
segement.start_vaddr + segement.size,
)
.expect("Failed to create page iterator");

let mut segement_data_offset = 0;

// Copy data of the segment to the physical memory
let segement_start_vaddr = phys_to_virt(segement_start_paddr).as_mut_ptr();
let segement_data_ptr = segement.data.as_ptr();
unsafe {
// Copy and align the data to the start of the page
// FIXME: Handle data length exceeding the page size
core::ptr::copy_nonoverlapping(
segement_data_ptr,
segement_start_vaddr.add(segement.offset),
segement.data.len(),
for (idx, vaddr) in segement_page_iter.enumerate() {
let (paddr, _, _) = uspace
.page_table()
.query(vaddr)
.unwrap_or_else(|_| panic!("Mapping failed for segment: {:#x?}", vaddr));

let (start_paddr, copied_size) = if idx == 0 {
// Align the start of the segment to the start of the page
(
paddr + segement.offset,
memory_addr::PAGE_SIZE_4K - segement.offset,
)
} else {
(paddr, memory_addr::PAGE_SIZE_4K)
};

debug!(
"Copying segment data: {:#x?} -> {:#x?} size: {:#x?}",
segement.start_vaddr + segement_data_offset + segement.offset,
start_paddr,
copied_size
);

unsafe {
core::ptr::copy_nonoverlapping(
segement.data.as_ptr().add(segement_data_offset),
phys_to_virt(start_paddr).as_mut_ptr(),
copied_size,
);
}

segement_data_offset += copied_size;
if segement_data_offset >= segement.data.len() {
break;
}
}
// TDOO: flush the I-cache
}

let ustack_top = uspace.end();
let ustack_vaddr = ustack_top - crate::USER_STACK_SIZE;

debug!(
"Mapping user stack: {:#x?} -> {:#x?}",
ustack_vaddr, ustack_top
);
uspace.map_alloc(
ustack_vaddr,
crate::USER_STACK_SIZE,
Expand Down

0 comments on commit c29aee2

Please sign in to comment.