>  기사  >  운영 및 유지보수  >  실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

嵌入式Linux充电站
嵌入式Linux充电站앞으로
2023-08-01 15:37:591147검색

이전 기사에서는 RISC-V Linux 시작을 위한 페이지 테이블 생성을 분석했습니다. RISC-V Linux 항목 주소는 2M 정렬되어야 한다고 언급되었습니다. 오늘은 2M 정렬 문제를 해결하는 방법에 대해 이야기하겠습니다. 메모리의 일부를 최적화합니다.

참고: 이 기사는 linux5.10.111 커널을 기반으로 합니다.

메모리 사용량 분석

각 칩이 공장에서 출고될 때 해당 부트롬은 칩 내부에 굳어져 있다고 가정합니다. bootrom은 0x0, 즉 위와 같습니다. 전원을 켜면 프로그램은 주소 0x0에서 실행됩니다.

RISC-V Linux를 시작하기 전에 먼저 opensbi를 실행해야 하므로 opensbi는 0x0处,这样芯片上电后,就会从0x0地址处执行opensbi。在opensbi运行完后,会跳转到opensbi运行地址偏移2M的位置去执行下一级boot(这里下一级boot是kernel),即跳转到0x200000地址处运行kernel,因此应该把kernel放到内存的0x200000 주소에 배치되어야 합니다.

메모리 분포 다이어그램은 다음과 같습니다.

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

커널의 경우 시작 시 자체 커널에서 주소를 로드합니다(예: 0x200000) 페이지 테이블 매핑을 설정하기 시작합니다. 물리적 메모리에 대해 페이지 테이블 매핑이 설정되어야 나중에 해당 메모리에 액세스할 수 있습니다. 커널은 주소 앞에 2M 메모리를 로드합니다(예: 0x0 - 0x200000)은 커널에 의해 무시되며 이 2M 메모리에 대한 페이지 테이블이 설정되지 않습니다. 즉, 커널은 이 2M 메모리에 액세스할 수 없습니다. 0x200000)开始建立页表映射,只有对物理内存建立了页表映射,后面才能访问这些内存。而kernel加载地址前面的2M内存(即0x0 - 0x200000)将被kernel忽略,不会对这2M内存建立页表,即kernel无法访问这2M内存。

在QEMU上RISC-V Linux的启动信息:

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

但opensbi实际不需要使用2M这么大的范围,默认是512KB,opensbi的pmp会保护这512KB内存,不让其他程序访问。

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

因此在Kernel和opensbi之间会存在1.5M

QEMU에서 RISC-V Linux 시작 정보:

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화 하지만 opensbi는 실제로 2M만큼 큰 범위를 사용할 필요가 없습니다. 기본값은 512KB, opensbi의 pmp는 이것을 보호합니다512KB 메모리, 다른 프로그램에서 액세스할 수 없습니다. 실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

그래서 1.5M 메모리 간격 및 메모리 공백의 이 부분은 프로그램에서 사용되지 않으므로 메모리 낭비가 발생합니다. 그러면 커널이 메모리의 이전 부분을 사용하도록 하는 방법은 무엇입니까?

최적화 계획

이 2M 메모리를 최적화하기 위한 두 가지 계획이 있습니다: 🎜🎜🎜옵션 1🎜: opensbi를 메모리 끝에 넣고 커널 항목 주소는 여전히 2M 정렬을 유지합니다. 🎜🎜🎜옵션 2🎜: Opensbi는 여전히 메모리 시작 부분에 배치됩니다. 커널 소스 코드를 수정하고 2M 정렬 제한을 해제하면 커널 주소를 앞으로 이동할 수 있습니다. 🎜

Option 1

opensbi를 메모리 끝에 두었고 커널 항목 주소는 여전히 2M 정렬을 유지합니다.

즉, 커널은 메모리 앞쪽에 배치되고, opensbi는 뒤쪽에 배치됩니다.

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

예를 들어 커널은 메모리의 0x0地址处,opensbi放到内存的0x10000000地址处。这样kernel前面就不会有预留内存,只不过这样需要修改bootrom的地址,将地址从0x0修改为0x0x10000000。这种方案只适合芯片还没出厂前,因为用户无法修改bootrom的地址,芯片出厂后,bootrom地址是固定的,假设bootrom地址为0x0,那么芯片上电后,就会从0x0开始运行程序,所以opensbi必须放到0x0 주소에 배치되므로 커널은 2M만큼 오프셋됩니다.

옵션 2

또한 RISC-V Linux의 커널 소스 코드를 수정하여 2M 정렬 제한을 해제할 수도 있습니다. setup_vm () 함수를 사용하여 원래 두 번째 수준 페이지 테이블을 세 번째 수준 페이지 테이블로 변경하여 커널 항목 주소를 4K로만 정렬하면 커널이 앞으로 이동하여 전면 메모리를 사용합니다. setup_vm()函数中,将原来的二级页表改为三级页表,这样kernel入口地址只需要4K对齐,因此就能将kernel往前挪,从而利用前面的内存。

修改代码

路径:arch/riscv/mm/init.c

코드 수정

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화경로: 아치 / riscv/mm/init.c

원래 2M 정렬 검사에 주석을 추가하세요.

실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

두 번째 수준 페이지 테이블에서 세 번째 수준 페이지 테이블로 커널의 첫 번째 2M 페이지 테이블 매핑을 변경합니다.

//新增一个PTE
pte_t trampoline_pte[PTRS_PER_PTE] __page_aligned_bss;

create_pgd_mapping(trampoline_pg_dir,PAGE_OFFSET,
                   (uintptr_t)trampoline_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(trampoline_pmd,PAGE_OFFSET,
                   (uintptr_t)trampoline_pte,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + PMD_SIZE;
for (va = PAGE_OFFSET; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(trampoline_pte,PAGE_OFFSET,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

전체 커널의 페이지 테이블 매핑이 2단계 페이지 테이블에서 3단계 페이지 테이블로 변경됩니다.
실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화
커널 크기가 4M+
실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화
//定义三个PTE
pte_t load_sz_pte[PTRS_PER_PTE] __page_aligned_bss;
pte_t load_sz_pte1[PTRS_PER_PTE] __page_aligned_bss;
pte_t load_sz_pte2[PTRS_PER_PTE] __page_aligned_bss;

//=======0-2M======
create_pgd_mapping(early_pg_dir,PAGE_OFFSET,
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + PMD_SIZE;
for (va = PAGE_OFFSET; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte,PAGE_OFFSET,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

//=======2-4M==========
create_pgd_mapping(early_pg_dir,PAGE_OFFSET + PMD_SIZE,
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte1,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + (PMD_SIZE * 2);
for (va = PAGE_OFFSET + PMD_SIZE; va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte1,va,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

//=======4-6M==========
create_pgd_mapping(early_pg_dir,PAGE_OFFSET + (PMD_SIZE*2),
                   (uintptr_t)early_pmd,PGDIR_SIZE,PAGE_TABLE);
create_pmd_mapping(early_pmd,PAGE_OFFSET,
                   (uintptr_t)load_sz_pte2,PMD_SIZE,PAGE_TABLE);

end_va = PAGE_OFFSET + (PMD_SIZE * 3);
for (va = PAGE_OFFSET + (PMD_SIZE*2); va < end_va; va += PAGE_SIZE)
{
    create_pte_mapping(load_sz_pte2,va,
                   load_pa + (va - PAGE_OFFSET),
                       PAGE_SIZE,PAGE_KERNEL_EXEC);
}

🎜🎜🎜이라고 가정합니다. 🎜위 코드를 수정하면 커널 항목을 1.5M 앞으로 이동하고 opensbi용으로 512KB만 예약할 수 있습니다. 이런 식으로 RISC-V Linux가 시작된 후 사용 가능한 물리적 메모리가 늘어납니다. 🎜
실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화

Summary

RISC-V Linux 항목 주소 2M 정렬 작업은 아직 설명되지 않았지만 opensbi를 위해 2M을 예약해야 하므로 커널은 보조 페이지 테이블만 설정하므로 항목 주소는 2M로 정렬되어야 합니다. 아직까지 메모리의 이 부분에 대한 최적화 솔루션을 제시한 사람은 없습니다. 이 기사의 최적화 솔루션이 일부 사람들에게 도움이 되고 모든 사람에게 영감을 줄 수 있기를 바랍니다.

위 내용은 실용적인 전투 | RISC-V Linux 항목 주소 2M 예약 메모리 최적화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 嵌入式Linux充电站에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제