Add LoongArch support
This commit is contained in:
parent
3be68d0502
commit
d9a2fb95a9
|
@ -56,6 +56,7 @@
|
|||
/common-uefi-x86-64
|
||||
/common-uefi-aarch64
|
||||
/common-uefi-riscv64
|
||||
/common-uefi-loongarch64
|
||||
/decompressor-build
|
||||
/stage1.stamp
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ Editor control options:
|
|||
* `MAX_PAGING_MODE`, `MIN_PAGING_MODE` - Limit the maximum and minimum paging modes to one of the following:
|
||||
- x86-64 and aarch64: `4level`, `5level`.
|
||||
- riscv64: `sv39`, `sv48`, `sv57`.
|
||||
- loongarch64: `4level`.
|
||||
* `PAGING_MODE` - Equivalent to setting both `MAX_PAGING_MODE` and `MIN_PAGING_MODE` to the same value.
|
||||
|
||||
* multiboot1 and multiboot2 protocols:
|
||||
|
@ -194,4 +195,4 @@ Macros must always be placed inside `${...}` where `...` is the arbitrary macro
|
|||
|
||||
Limine automatically defines these macros:
|
||||
|
||||
* `ARCH` - This built-in macro expands to the architecture of the machine. Possible values are: `x86-64`, `ia-32`, `aarch64`, `riscv64`. In the case of IA-32, BIOS or UEFI, the macro will always expand to `x86-64` if the 64-bit extensions are available, else `ia-32`.
|
||||
* `ARCH` - This built-in macro expands to the architecture of the machine. Possible values are: `x86-64`, `ia-32`, `aarch64`, `riscv64`, `loongarch64`. In the case of IA-32, BIOS or UEFI, the macro will always expand to `x86-64` if the 64-bit extensions are available, else `ia-32`.
|
||||
|
|
|
@ -54,6 +54,7 @@ override BUILD_UEFI_X86_64 := @BUILD_UEFI_X86_64@
|
|||
override BUILD_UEFI_IA32 := @BUILD_UEFI_IA32@
|
||||
override BUILD_UEFI_AARCH64 := @BUILD_UEFI_AARCH64@
|
||||
override BUILD_UEFI_RISCV64 := @BUILD_UEFI_RISCV64@
|
||||
override BUILD_UEFI_LOONGARCH64 := @BUILD_UEFI_LOONGARCH64@
|
||||
override BUILD_UEFI_CD := @BUILD_UEFI_CD@
|
||||
override BUILD_BIOS_PXE := @BUILD_BIOS_PXE@
|
||||
override BUILD_BIOS_CD := @BUILD_BIOS_CD@
|
||||
|
@ -124,7 +125,7 @@ all: $(call MKESCAPE,$(BINDIR))/Makefile
|
|||
$(MAKE) all1
|
||||
|
||||
.PHONY: all1
|
||||
all1: $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_UEFI_RISCV64) $(BUILD_BIOS)
|
||||
all1: $(BUILD_UEFI_X86_64) $(BUILD_UEFI_IA32) $(BUILD_UEFI_AARCH64) $(BUILD_UEFI_RISCV64) $(BUILD_UEFI_LOONGARCH64) $(BUILD_BIOS)
|
||||
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine'
|
||||
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
|
||||
|
||||
|
@ -151,7 +152,7 @@ limine:
|
|||
$(MAKE) '$(call SHESCAPE,$(BINDIR))/limine'
|
||||
|
||||
.PHONY: clean
|
||||
clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean limine-uefi-riscv64-clean
|
||||
clean: limine-bios-clean limine-uefi-ia32-clean limine-uefi-x86-64-clean limine-uefi-aarch64-clean limine-uefi-riscv64-clean limine-uefi-loongarch64-clean
|
||||
rm -rf '$(call SHESCAPE,$(BINDIR))' '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
|
||||
|
||||
.PHONY: install
|
||||
|
@ -184,6 +185,9 @@ endif
|
|||
ifeq ($(BUILD_UEFI_RISCV64),limine-uefi-riscv64)
|
||||
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTRISCV64.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
|
||||
endif
|
||||
ifeq ($(BUILD_UEFI_LOONGARCH64),limine-uefi-loongarch64)
|
||||
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTLOONGARCH64.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
|
||||
endif
|
||||
ifeq ($(BUILD_UEFI_X86_64),limine-uefi-x86-64)
|
||||
$(INSTALL_DATA) '$(call SHESCAPE,$(BINDIR))/BOOTX64.EFI' '$(call SHESCAPE,$(DESTDIR)$(datarootdir))/limine/'
|
||||
endif
|
||||
|
@ -227,7 +231,7 @@ endif
|
|||
limine-bios: common-bios decompressor
|
||||
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/stage1.stamp'
|
||||
|
||||
$(call MKESCAPE,$(BINDIR))/limine-uefi-cd.bin: $(if $(BUILD_UEFI_IA32),$(call MKESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI) $(if $(BUILD_UEFI_X86_64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI) $(if $(BUILD_UEFI_AARCH64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI) $(if $(BUILD_UEFI_RISCV64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI)
|
||||
$(call MKESCAPE,$(BINDIR))/limine-uefi-cd.bin: $(if $(BUILD_UEFI_IA32),$(call MKESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI) $(if $(BUILD_UEFI_X86_64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI) $(if $(BUILD_UEFI_AARCH64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI) $(if $(BUILD_UEFI_RISCV64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI) $(if $(BUILD_UEFI_LOONGARCH64),$(call MKESCAPE,$(BUILDDIR))/common-uefi-loongarch64/BOOTLOONGARCH64.EFI)
|
||||
ifneq ($(BUILD_UEFI_CD),no)
|
||||
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
|
||||
rm -f '$(call SHESCAPE,$(BINDIR))/limine-uefi-cd.bin'
|
||||
|
@ -237,6 +241,7 @@ ifneq ($(BUILD_UEFI_CD),no)
|
|||
mkdir -p "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT; \
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-aarch64/BOOTAA64.EFI' "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT/ 2>/dev/null; \
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64/BOOTRISCV64.EFI' "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT/ 2>/dev/null; \
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-loongarch64/BOOTLOONGARCH64.EFI' "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT/ 2>/dev/null; \
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-x86-64/BOOTX64.EFI' "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT/ 2>/dev/null; \
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-ia32/BOOTIA32.EFI' "$$LIMINE_UEFI_CD_TMP"/EFI/BOOT/ 2>/dev/null; \
|
||||
find "$$LIMINE_UEFI_CD_TMP" -exec touch -t $(SOURCE_DATE_EPOCH_TOUCH) '{}' + && \
|
||||
|
@ -284,6 +289,15 @@ limine-uefi-riscv64:
|
|||
$(MAKE) common-uefi-riscv64
|
||||
$(MAKE) '$(call SHESCAPE,$(BINDIR))/BOOTRISCV64.EFI'
|
||||
|
||||
$(call MKESCAPE,$(BINDIR))/BOOTLOONGARCH64.EFI: $(call MKESCAPE,$(BUILDDIR))/common-uefi-loongarch64/BOOTLOONGARCH64.EFI
|
||||
$(MKDIR_P) '$(call SHESCAPE,$(BINDIR))'
|
||||
cp '$(call SHESCAPE,$(BUILDDIR))/common-uefi-loongarch64/BOOTLOONGARCH64.EFI' '$(call SHESCAPE,$(BINDIR))/'
|
||||
|
||||
.PHONY: limine-uefi-loongarch64
|
||||
limine-uefi-loongarch64:
|
||||
$(MAKE) common-uefi-loongarch64
|
||||
$(MAKE) '$(call SHESCAPE,$(BINDIR))/BOOTLOONGARCH64.EFI'
|
||||
|
||||
.PHONY: limine-bios-clean
|
||||
limine-bios-clean: common-bios-clean decompressor-clean
|
||||
|
||||
|
@ -299,6 +313,9 @@ limine-uefi-aarch64-clean: common-uefi-aarch64-clean
|
|||
.PHONY: limine-uefi-riscv64-clean
|
||||
limine-uefi-riscv64-clean: common-uefi-riscv64-clean
|
||||
|
||||
.PHONY: limine-uefi-loongarch64-clean
|
||||
limine-uefi-loongarch64-clean: common-uefi-loongarch64-clean
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))'/"limine-$(LIMINE_VERSION)"
|
||||
|
@ -377,6 +394,17 @@ common-uefi-riscv64:
|
|||
common-uefi-riscv64-clean:
|
||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))/common-uefi-riscv64'
|
||||
|
||||
.PHONY: common-uefi-loongarch64
|
||||
common-uefi-loongarch64:
|
||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
|
||||
TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-loongarch64-toolchain.mk' \
|
||||
TARGET=uefi-loongarch64 \
|
||||
BUILDDIR='$(call SHESCAPE,$(BUILDDIR))/common-uefi-loongarch64'
|
||||
|
||||
.PHONY: common-uefi-loongarch64-clean
|
||||
common-uefi-loongarch64-clean:
|
||||
rm -rf '$(call SHESCAPE,$(BUILDDIR))/common-uefi-loongarch64'
|
||||
|
||||
.PHONY: common-uefi-ia32
|
||||
common-uefi-ia32:
|
||||
$(MAKE) -C '$(call SHESCAPE,$(SRCDIR))/common' all \
|
||||
|
|
44
PROTOCOL.md
44
PROTOCOL.md
|
@ -247,6 +247,15 @@ with the default `PBMT=PMA`.
|
|||
If the `Svpbmt` extension is not available, no PMAs can be overridden (effectively,
|
||||
everything is mapped with `PBMT=PMA`).
|
||||
|
||||
### loongarch64
|
||||
|
||||
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
|
||||
segments mapped using the Coherent Cached (CC) memory access type (MAT).
|
||||
|
||||
All HHDM and identity map memory regions are mapped using the Coherent Cached (CC)
|
||||
MAT, except for the framebuffer regions, which are mapped in using the
|
||||
Weakly-ordered UnCached (WUC) MAT.
|
||||
|
||||
## Machine state at entry
|
||||
|
||||
### x86-64
|
||||
|
@ -368,6 +377,30 @@ Paging is enabled with the paging mode specified by the Paging Mode feature (see
|
|||
|
||||
The (A)PLIC, if present, is in an undefined state.
|
||||
|
||||
### loongarch64
|
||||
|
||||
At entry the machine is executing in PLV0.
|
||||
|
||||
`$pc` will be the entry point as defined as part of the executable file format,
|
||||
unless the Entry Point feature is requested (see below), in which case, the
|
||||
value of `$pc` is going to be taken from there.
|
||||
|
||||
`$r1`(`$ra`) is set to 0, the kernel must not return from the entry point.
|
||||
|
||||
`$r3`(`$sp`) is set to point to a stack, in bootloader-reclaimable memory, which is
|
||||
at least 64KiB (65536 bytes) in size, or the size specified in the Stack
|
||||
Size Request (see below).
|
||||
|
||||
All other general purpose registers, with the exception of `$r12`(`$t0`), are set to 0.
|
||||
|
||||
If booted by EFI/UEFI, boot services are exited.
|
||||
|
||||
`CSR.EENTRY`, `CSR.MERRENTRY` and `CSR.DWM0-3` are in an undefined state.
|
||||
|
||||
`PG` in `CSR.CRMD` is 1, `DA` is 0, `IE` is 0 and `PLV` is 0 but is otherwise unspecified.
|
||||
|
||||
`CSR.TLBRENTRY` is filled with a provided TLB refill handler.
|
||||
|
||||
## Feature List
|
||||
|
||||
Request IDs are composed of 4 64-bit unsigned integers, but the first 2 are
|
||||
|
@ -664,6 +697,17 @@ Values for `mode`, `max_mode`, and `min_mode`:
|
|||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57
|
||||
```
|
||||
|
||||
### loongarch64
|
||||
|
||||
Values for `mode`, `max_mode`, and `min_mode`:
|
||||
```c
|
||||
#define LIMINE_PAGING_MODE_LOONGARCH64_4LVL 0
|
||||
|
||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
```
|
||||
|
||||
### SMP (multiprocessor) Feature
|
||||
|
||||
ID:
|
||||
|
|
|
@ -28,6 +28,7 @@ Donations welcome, but absolutely not mandatory!
|
|||
* x86-64
|
||||
* aarch64 (arm64)
|
||||
* riscv64
|
||||
* loongarch64
|
||||
|
||||
### Supported boot protocols
|
||||
* Linux
|
||||
|
@ -53,7 +54,7 @@ opening issues or pull requests related to this.
|
|||
For 32-bit x86 systems, support is only ensured starting with those with
|
||||
Pentium Pro (i686) class CPUs.
|
||||
|
||||
All x86-64, aarch64, and riscv64 (UEFI) systems are supported.
|
||||
All x86-64, aarch64, riscv64 and loongarch64 (UEFI) systems are supported.
|
||||
|
||||
## Packaging status
|
||||
|
||||
|
|
|
@ -76,15 +76,15 @@ if ! test -f version; then
|
|||
done
|
||||
|
||||
download_by_hash \
|
||||
https://github.com/osdev0/freestanding-toolchain/raw/18a5e52483344e117d45738c9afb2b34792cbced/freestanding-toolchain \
|
||||
https://github.com/osdev0/freestanding-toolchain/raw/a8b871c2a952f7efe89bd38658f8356bc00d4d29/freestanding-toolchain \
|
||||
build-aux/freestanding-toolchain \
|
||||
b5b66c4e94d463116e549b10e78fb96cdb97530cc165f9b5babe31a97a78e90c
|
||||
6e167855d2ea68ebaf1e3d7450f3297bec2ab3f425e56ed11ed7c72396f6b540
|
||||
chmod +x build-aux/freestanding-toolchain
|
||||
|
||||
clone_repo_commit \
|
||||
https://github.com/limine-bootloader/limine-efi.git \
|
||||
limine-efi \
|
||||
d8257094947b0edefe9fa4dcb15255235e3c5193
|
||||
f31f942b6f1390777102af28ad0aabde7695a466
|
||||
|
||||
clone_repo_commit \
|
||||
https://github.com/jibsen/tinf.git \
|
||||
|
|
|
@ -157,6 +157,21 @@ ifeq ($(TARGET),uefi-riscv64)
|
|||
-D__riscv64
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
override CFLAGS_FOR_TARGET += \
|
||||
-fPIE \
|
||||
-fshort-wchar \
|
||||
-march=loongarch64 \
|
||||
-mabi=lp64s
|
||||
|
||||
override CPPFLAGS_FOR_TARGET := \
|
||||
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc' \
|
||||
-I'$(call SHESCAPE,$(BUILDDIR))/limine-efi/inc/loongarch64' \
|
||||
$(CPPFLAGS_FOR_TARGET) \
|
||||
-DUEFI \
|
||||
-D__loongarch64
|
||||
endif
|
||||
|
||||
override LDFLAGS_FOR_TARGET += \
|
||||
-nostdlib \
|
||||
-z max-page-size=0x1000 \
|
||||
|
@ -202,6 +217,14 @@ ifeq ($(TARGET),uefi-riscv64)
|
|||
-z text
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
override LDFLAGS_FOR_TARGET += \
|
||||
-m elf64loongarch \
|
||||
--no-relax \
|
||||
-pie \
|
||||
-z text
|
||||
endif
|
||||
|
||||
override C_FILES := $(shell find . -type f -name '*.c' | LC_ALL=C sort)
|
||||
ifeq ($(TARGET),bios)
|
||||
override ASMX86_FILES := $(shell find . -type f -name '*.asm_x86' | LC_ALL=C sort)
|
||||
|
@ -237,6 +260,12 @@ ifeq ($(TARGET),uefi-riscv64)
|
|||
|
||||
override OBJ := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.o) $(ASM64_FILES:.asm_riscv64=.o) $(ASM64U_FILES:.asm_uefi_riscv64=.o))
|
||||
endif
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
override ASM64_FILES := $(shell find . -type f -name '*.asm_loongarch64' | LC_ALL=C sort)
|
||||
override ASM64U_FILES := $(shell find . -type f -name '*.asm_uefi_loongarch64' | LC_ALL=C sort)
|
||||
|
||||
override OBJ := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.o) $(ASM64_FILES:.asm_loongarch64=.o) $(ASM64U_FILES:.asm_uefi_loongarch64=.o))
|
||||
endif
|
||||
|
||||
override HEADER_DEPS := $(addprefix $(call MKESCAPE,$(BUILDDIR))/, $(C_FILES:.c=.d))
|
||||
|
||||
|
@ -252,6 +281,8 @@ else ifeq ($(TARGET),uefi-aarch64)
|
|||
all: $(call MKESCAPE,$(BUILDDIR))/BOOTAA64.EFI
|
||||
else ifeq ($(TARGET),uefi-riscv64)
|
||||
all: $(call MKESCAPE,$(BUILDDIR))/BOOTRISCV64.EFI
|
||||
else ifeq ($(TARGET),uefi-loongarch64)
|
||||
all: $(call MKESCAPE,$(BUILDDIR))/BOOTLOONGARCH64.EFI
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),bios)
|
||||
|
@ -490,6 +521,52 @@ $(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi
|
|||
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
|
||||
cd '$(call SHESCAPE,$(BUILDDIR))' && \
|
||||
'$(call SHESCAPE,$(SRCDIR))/gensyms.sh' '$(call SHESCAPE,$<)' full 64 '\.text'
|
||||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$(BUILDDIR))/full.map.S' -o '$(call SHESCAPE,$@)'
|
||||
rm -f '$(call SHESCAPE,$(BUILDDIR))/full.map.S' '$(call SHESCAPE,$(BUILDDIR))/full.map.d'
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/BOOTLOONGARCH64.EFI: $(call MKESCAPE,$(BUILDDIR))/limine.elf
|
||||
$(OBJCOPY_FOR_TARGET) -O binary '$(call SHESCAPE,$<)' '$(call SHESCAPE,$@)'
|
||||
chmod -x '$(call SHESCAPE,$@)'
|
||||
dd if=/dev/zero of='$(call SHESCAPE,$@)' bs=4096 count=0 seek=$$(( ($$(wc -c < '$(call SHESCAPE,$@)') + 4095) / 4096 ))
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-loongarch64.S.o: limine-efi
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_loongarch64.c.o: limine-efi
|
||||
|
||||
.PHONY: limine-efi
|
||||
limine-efi: $(call MKESCAPE,$(BUILDDIR))/limine-efi
|
||||
$(MAKE) -C '$(call SHESCAPE,$(BUILDDIR))/limine-efi/gnuefi' \
|
||||
CC="$(CC_FOR_TARGET)" \
|
||||
CFLAGS="$(BASE_CFLAGS)" \
|
||||
CPPFLAGS='-nostdinc -isystem $(call SHESCAPE,$(SRCDIR))/../freestanding-headers' \
|
||||
ARCH=loongarch64
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/linker_nomap.ld: linker_uefi_loongarch64.ld.in
|
||||
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
|
||||
$(CC_FOR_TARGET) -x c -E -P -undef -DLINKER_NOMAP linker_uefi_loongarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-loongarch64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_loongarch64.c.o $(OBJ)
|
||||
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld'
|
||||
$(LD_FOR_TARGET) \
|
||||
-T'$(call SHESCAPE,$(BUILDDIR))/linker_nomap.ld' \
|
||||
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/linker.ld: linker_uefi_loongarch64.ld.in
|
||||
$(MKDIR_P) '$(call SHESCAPE,$(BUILDDIR))'
|
||||
$(CC_FOR_TARGET) -x c -E -P -undef linker_uefi_loongarch64.ld.in -o '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/limine.elf: $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/crt0-efi-loongarch64.S.o $(call MKESCAPE,$(BUILDDIR))/limine-efi/gnuefi/reloc_loongarch64.c.o $(OBJ) $(call MKESCAPE,$(BUILDDIR))/full.map.o
|
||||
$(MAKE) '$(call SHESCAPE,$(BUILDDIR))/linker.ld'
|
||||
$(LD_FOR_TARGET) \
|
||||
-T'$(call SHESCAPE,$(BUILDDIR))/linker.ld' \
|
||||
'$(call OBJESCAPE,$^)' $(LDFLAGS_FOR_TARGET) -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-ia32)
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/full.map.o: $(call MKESCAPE,$(BUILDDIR))/limine_nomap.elf
|
||||
|
@ -557,6 +634,12 @@ $(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
|
|||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
|
||||
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
|
||||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-ia32)
|
||||
$(call MKESCAPE,$(BUILDDIR))/%.o: %.c $(call MKESCAPE,$(BUILDDIR))/limine-efi
|
||||
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
|
||||
|
@ -627,6 +710,16 @@ $(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_uefi_riscv64
|
|||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-loongarch64)
|
||||
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_loongarch64
|
||||
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
|
||||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
|
||||
|
||||
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_uefi_loongarch64
|
||||
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
|
||||
$(CC_FOR_TARGET) $(CFLAGS_FOR_TARGET) $(CPPFLAGS_FOR_TARGET) -x assembler-with-cpp -c '$(call SHESCAPE,$<)' -o '$(call SHESCAPE,$@)'
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET),uefi-ia32)
|
||||
$(call MKESCAPE,$(BUILDDIR))/%.o: %.asm_ia32
|
||||
$(MKDIR_P) "$$(dirname '$(call SHESCAPE,$@)')"
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.section .text
|
||||
|
||||
.global efi_main
|
||||
.extern uefi_entry
|
||||
efi_main:
|
||||
move $fp, $r0
|
||||
move $ra, $r0
|
||||
b uefi_entry
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
|
@ -208,6 +208,8 @@ skip_loop:
|
|||
strcpy(arch_macro->value, "aarch64");
|
||||
#elif defined (__riscv64)
|
||||
strcpy(arch_macro->value, "riscv64");
|
||||
#elif defined (__loongarch64)
|
||||
strcpy(arch_macro->value, "loongarch64");
|
||||
#else
|
||||
#error "Unspecified architecture"
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#define ARCH_X86_32 0x03
|
||||
#define ARCH_AARCH64 0xb7
|
||||
#define ARCH_RISCV 0xf3
|
||||
#define ARCH_LOONGARCH 0x102
|
||||
#define BITS_LE 0x01
|
||||
#define ELFCLASS64 0x02
|
||||
#define SHT_RELA 0x00000004
|
||||
|
@ -50,16 +51,20 @@
|
|||
#define R_X86_64_NONE 0x00000000
|
||||
#define R_AARCH64_NONE 0x00000000
|
||||
#define R_RISCV_NONE 0x00000000
|
||||
#define R_LARCH_NONE 0x00000000
|
||||
#define R_X86_64_RELATIVE 0x00000008
|
||||
#define R_AARCH64_RELATIVE 0x00000403
|
||||
#define R_RISCV_RELATIVE 0x00000003
|
||||
#define R_LARCH_RELATIVE 0x00000003
|
||||
#define R_X86_64_GLOB_DAT 0x00000006
|
||||
#define R_AARCH64_GLOB_DAT 0x00000401
|
||||
#define R_X86_64_JUMP_SLOT 0x00000007
|
||||
#define R_AARCH64_JUMP_SLOT 0x00000402
|
||||
#define R_RISCV_JUMP_SLOT 0x00000005
|
||||
#define R_LARCH_JUMP_SLOT 0x00000005
|
||||
#define R_X86_64_64 0x00000001
|
||||
#define R_RISCV_64 0x00000002
|
||||
#define R_LARCH_64 0x00000002
|
||||
#define R_AARCH64_ABS64 0x00000101
|
||||
|
||||
#define R_INTERNAL_RELR 0xfffffff0
|
||||
|
@ -163,6 +168,10 @@ static bool elf64_validate(struct elf64_hdr *hdr) {
|
|||
if (hdr->machine != ARCH_RISCV && hdr->ident[EI_CLASS] == ELFCLASS64) {
|
||||
panic(true, "elf: Not a riscv64 ELF file.");
|
||||
}
|
||||
#elif defined (__loongarch64)
|
||||
if (hdr->machine != ARCH_LOONGARCH && hdr->ident[EI_CLASS] == ELFCLASS64) {
|
||||
panic(true, "elf: Not a loongarch64 ELF file.");
|
||||
}
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -183,6 +192,7 @@ int elf_bits(uint8_t *elf) {
|
|||
case ARCH_AARCH64:
|
||||
return 64;
|
||||
case ARCH_RISCV:
|
||||
case ARCH_LOONGARCH:
|
||||
return (hdr->ident[EI_CLASS] == ELFCLASS64) ? 64 : 32;
|
||||
case ARCH_X86_32:
|
||||
return 32;
|
||||
|
@ -465,6 +475,8 @@ end_of_pt_segment:
|
|||
case R_AARCH64_NONE:
|
||||
#elif defined (__riscv64)
|
||||
case R_RISCV_NONE:
|
||||
#elif defined (__loongarch64)
|
||||
case R_LARCH_NONE:
|
||||
#endif
|
||||
{
|
||||
break;
|
||||
|
@ -475,6 +487,8 @@ end_of_pt_segment:
|
|||
case R_AARCH64_RELATIVE:
|
||||
#elif defined (__riscv64)
|
||||
case R_RISCV_RELATIVE:
|
||||
#elif defined (__loongarch64)
|
||||
case R_LARCH_RELATIVE:
|
||||
#endif
|
||||
{
|
||||
*ptr = slide + relocation->r_addend;
|
||||
|
@ -493,6 +507,8 @@ end_of_pt_segment:
|
|||
case R_AARCH64_JUMP_SLOT:
|
||||
#elif defined (__riscv64)
|
||||
case R_RISCV_JUMP_SLOT:
|
||||
#elif defined (__loongarch64)
|
||||
case R_LARCH_JUMP_SLOT:
|
||||
#endif
|
||||
{
|
||||
struct elf64_sym *s = (void *)elf + symtab_offset + symtab_ent * relocation->r_symbol;
|
||||
|
@ -516,6 +532,8 @@ end_of_pt_segment:
|
|||
case R_AARCH64_ABS64:
|
||||
#elif defined (__riscv64)
|
||||
case R_RISCV_64:
|
||||
#elif defined (__loongarch64)
|
||||
case R_LARCH_64:
|
||||
#endif
|
||||
{
|
||||
struct elf64_sym *s = (void *)elf + symtab_offset + symtab_ent * relocation->r_symbol;
|
||||
|
|
|
@ -253,6 +253,8 @@ retry:
|
|||
asm volatile ("msr daifset, #15" ::: "memory");
|
||||
#elif defined (__riscv64)
|
||||
asm volatile ("csrci sstatus, 0x2" ::: "memory");
|
||||
#elif defined (__loongarch64)
|
||||
asm volatile ("csrxchg $r0, %0, 0x0" :: "r" (0x4) : "memory");
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -95,6 +95,9 @@ noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp, uint64_t
|
|||
#if defined (UEFI)
|
||||
RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void);
|
||||
#endif
|
||||
#elif defined (__loongarch64)
|
||||
noreturn void loongarch_spinup(uint64_t entry, uint64_t sp, uint64_t pgdl,
|
||||
uint64_t pgdh, uint64_t direct_map_offset);
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -78,6 +78,8 @@ noreturn void panic(bool allow_menu, const char *fmt, ...) {
|
|||
asm ("hlt");
|
||||
#elif defined (__aarch64__) || defined (__riscv64)
|
||||
asm ("wfi");
|
||||
#elif defined (__loongarch64)
|
||||
asm ("idle 0");
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
.section .text
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
#define PT_SHIFT (PAGE_SHIFT - 3)
|
||||
#define PT_BASE(level) (PAGE_SHIFT + PT_SHIFT * (level))
|
||||
|
||||
#define MAKE_PWCL(Dir2_width, Dir2_base, Dirl_width, Dirl_base, PTwidth, PTbase) \
|
||||
((Dir2_width) << 25) | ((Dir2_base) << 20) | ((Dirl_width) << 15) | \
|
||||
((Dirl_base) << 10) | ((PTwidth) << 5) | ((PTbase) << 0)
|
||||
|
||||
#define MAKE_PWCH(Dir4_width, Dir4_base, Dir3_width, Dir3_base) \
|
||||
((Dir4_width) << 18) | ((Dir4_base) << 12) | ((Dir3_width) << 6) | \
|
||||
((Dir3_base) << 0)
|
||||
|
||||
#define CSR_CRMD 0x00
|
||||
#define CSR_EENTRY 0xc
|
||||
#define CSR_PGDL 0x19
|
||||
#define CSR_PGDH 0x1a
|
||||
#define CSR_PGD 0x1b
|
||||
#define CSR_PWCL 0x1c
|
||||
#define CSR_PWCH 0x1d
|
||||
#define CSR_STLBPS 0x1e
|
||||
#define CSR_TLBRENTRY 0x88
|
||||
#define CSR_TLBRSAVE 0x8b
|
||||
#define CSR_TLBREHI 0x8e
|
||||
#define CSR_MERRENTRY 0x93
|
||||
#define CSR_DMW0 0x180
|
||||
#define CSR_DMW1 0x181
|
||||
#define CSR_DMW2 0x182
|
||||
#define CSR_DMW3 0x183
|
||||
|
||||
.global loongarch_spinup
|
||||
loongarch_spinup:
|
||||
li.d $t0, 0b010001 // MAT=01, PLV1..3=0, PLV0=1
|
||||
csrwr $t0, CSR_DMW0
|
||||
csrwr $zero, CSR_DMW1
|
||||
csrwr $zero, CSR_DMW2
|
||||
csrwr $zero, CSR_DMW3
|
||||
|
||||
li.d $t0, 0b010110000 // DATF=01, DATM=01, PG=1, DA=0, IE=0, PLV=00
|
||||
csrwr $t0, CSR_CRMD
|
||||
|
||||
invtlb 0, $zero, $zero
|
||||
li.d $t0, PAGE_SHIFT
|
||||
csrwr $t0, CSR_STLBPS
|
||||
csrwr $t0, CSR_TLBREHI
|
||||
|
||||
csrwr $a2, CSR_PGDL
|
||||
csrwr $a3, CSR_PGDH
|
||||
|
||||
li.d $t0, MAKE_PWCL(PT_SHIFT, PT_BASE(2), PT_SHIFT, PT_BASE(1), PT_SHIFT, PT_BASE(0))
|
||||
csrwr $t0, CSR_PWCL
|
||||
li.d $t0, MAKE_PWCH(0, 0, PT_SHIFT, PT_BASE(3))
|
||||
csrwr $t0, CSR_PWCH
|
||||
|
||||
la $t0, loongarch_handle_refill
|
||||
csrwr $t0, CSR_TLBRENTRY
|
||||
|
||||
csrwr $zero, CSR_EENTRY
|
||||
csrwr $zero, CSR_MERRENTRY
|
||||
|
||||
move $t0, $a0
|
||||
move $sp, $a1
|
||||
|
||||
move $ra, $zero
|
||||
move $tp, $zero
|
||||
move $a0, $zero
|
||||
move $a1, $zero
|
||||
move $a2, $zero
|
||||
move $a3, $zero
|
||||
move $a4, $zero
|
||||
move $a5, $zero
|
||||
move $a6, $zero
|
||||
move $a7, $zero
|
||||
move $t1, $zero
|
||||
move $t2, $zero
|
||||
move $t3, $zero
|
||||
move $t4, $zero
|
||||
move $t5, $zero
|
||||
move $t6, $zero
|
||||
move $t7, $zero
|
||||
move $t8, $zero
|
||||
move $fp, $zero
|
||||
move $s0, $zero
|
||||
move $s1, $zero
|
||||
move $s2, $zero
|
||||
move $s3, $zero
|
||||
move $s4, $zero
|
||||
move $s5, $zero
|
||||
move $s6, $zero
|
||||
move $s7, $zero
|
||||
move $s8, $zero
|
||||
|
||||
jirl $zero, $t0, 0
|
||||
|
||||
.global loongarch_handle_refill
|
||||
.align 4
|
||||
loongarch_handle_refill:
|
||||
csrwr $t0, CSR_TLBRSAVE
|
||||
csrrd $t0, CSR_PGD
|
||||
lddir $t0, $t0, 3
|
||||
lddir $t0, $t0, 2
|
||||
lddir $t0, $t0, 1
|
||||
ldpte $t0, 0
|
||||
ldpte $t0, 1
|
||||
tlbfill
|
||||
csrrd $t0, CSR_TLBRSAVE
|
||||
ertn
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
|
@ -56,6 +56,8 @@ void print_stacktrace(size_t *base_ptr) {
|
|||
"mov %0, x29"
|
||||
#elif defined (__riscv64)
|
||||
"mv %0, fp; addi %0, %0, -16"
|
||||
#elif defined (__loongarch64)
|
||||
"move %0, $fp; addi.d %0, %0, -16"
|
||||
#endif
|
||||
: "=r"(base_ptr)
|
||||
:: "memory"
|
||||
|
@ -75,7 +77,7 @@ void print_stacktrace(size_t *base_ptr) {
|
|||
print(" [%p]\n", ret_addr);
|
||||
if (!old_bp)
|
||||
break;
|
||||
#if defined (__riscv)
|
||||
#if defined (__riscv) || defined (__loongarch64)
|
||||
base_ptr = (void *)(old_bp - 16);
|
||||
#else
|
||||
base_ptr = (void*)old_bp;
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
OUTPUT_FORMAT("elf64-loongarch", "elf64-loongarch", "elf64-loongarch")
|
||||
OUTPUT_ARCH(loongarch)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(0x05);
|
||||
rodata PT_LOAD FLAGS(0x04);
|
||||
data PT_LOAD FLAGS(0x06);
|
||||
dynamic PT_DYNAMIC FLAGS(0x06);
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
__slide = .;
|
||||
__image_base = ABSOLUTE(.);
|
||||
__image_size = ABSOLUTE(__image_end - __image_base);
|
||||
|
||||
.text : {
|
||||
KEEP(*(.pe_header))
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
__text_start = ABSOLUTE(.);
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
__text_end = ABSOLUTE(.);
|
||||
__text_size = ABSOLUTE(__text_end - __text_start);
|
||||
|
||||
.rodata : {
|
||||
__reloc_start = ABSOLUTE(.);
|
||||
*(.dummy_reloc)
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
__reloc_end = ABSOLUTE(.);
|
||||
__reloc_size = ABSOLUTE(__reloc_end - __reloc_start);
|
||||
|
||||
__data_start = ABSOLUTE(.);
|
||||
*(.rodata .rodata.*)
|
||||
|
||||
#ifdef LINKER_NOMAP
|
||||
full_map = .;
|
||||
#else
|
||||
*(.full_map)
|
||||
#endif
|
||||
} :rodata
|
||||
|
||||
.data : {
|
||||
data_begin = .;
|
||||
*(.data .data.*)
|
||||
*(.sdata .sdata.*)
|
||||
*(.sbss .sbss.*)
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
data_end = .;
|
||||
|
||||
*(.no_unwind)
|
||||
} :data
|
||||
|
||||
.dynamic : {
|
||||
*(.dynamic)
|
||||
} :data :dynamic
|
||||
|
||||
__data_end = ABSOLUTE(ALIGN(0x1000));
|
||||
__data_size = ABSOLUTE(__data_end - __data_start);
|
||||
|
||||
__image_end = ABSOLUTE(ALIGN(0x1000));
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
*(.interp)
|
||||
}
|
||||
}
|
|
@ -794,6 +794,8 @@ noreturn void _menu(bool first_run) {
|
|||
"riscv64"
|
||||
#elif defined (__aarch64__)
|
||||
"aarch64"
|
||||
#elif defined (__loongarch64)
|
||||
"loongarch64"
|
||||
#endif
|
||||
", UEFI)";
|
||||
#endif
|
||||
|
@ -1132,7 +1134,12 @@ noreturn void boot(char *config) {
|
|||
if (!strcmp(proto, "limine")) {
|
||||
limine_load(config, cmdline);
|
||||
} else if (!strcmp(proto, "linux")) {
|
||||
#if defined (__loongarch64)
|
||||
quiet = false;
|
||||
print("TODO: Linux is not available on LoongArch64.\n\n");
|
||||
#else
|
||||
linux_load(config, cmdline);
|
||||
#endif
|
||||
} else if (!strcmp(proto, "multiboot1") || !strcmp(proto, "multiboot")) {
|
||||
#if defined (__x86_64__) || defined (__i386__)
|
||||
multiboot1_load(config, cmdline);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.section .data
|
||||
|
||||
.align 3
|
||||
stack_at_first_entry:
|
||||
.quad 0
|
||||
|
||||
.section .text
|
||||
|
||||
.global menu
|
||||
.extern _menu
|
||||
|
||||
menu:
|
||||
la $t0, stack_at_first_entry
|
||||
ld.d $t1, $t0, 0
|
||||
beqz $t1, 1f
|
||||
move $sp, $t1
|
||||
b 2f
|
||||
1:
|
||||
st.d $sp, $t0, 0
|
||||
2:
|
||||
move $fp, $r0
|
||||
move $ra, $r0
|
||||
b _menu
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
|
@ -389,6 +389,98 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined (__loongarch64)
|
||||
|
||||
#define INVALID_PAGE 0
|
||||
|
||||
#define PT_FLAG_VALID ((uint64_t)1 << 0)
|
||||
#define PT_FLAG_DIRTY ((uint64_t)1 << 1)
|
||||
#define PT_FLAG_MAT_CC ((uint64_t)1 << 4)
|
||||
#define PT_FLAG_MAT_WUC ((uint64_t)1 << 5)
|
||||
#define PT_FLAG_GLOBAL ((uint64_t)1 << 6)
|
||||
#define PT_FLAG_HUGE ((uint64_t)1 << 6)
|
||||
#define PT_FLAG_WRITE ((uint64_t)1 << 8)
|
||||
#define PT_FLAG_HGLOBAL ((uint64_t)1 << 12)
|
||||
#define PT_FLAG_NX ((uint64_t)1 << 62)
|
||||
#define PT_PADDR_MASK ((uint64_t)0x0000FFFFFFFFF000)
|
||||
#define PT_PADDR_HMASK ((uint64_t)0x0000FFFFFF000000)
|
||||
|
||||
#define PT_TABLE_FLAGS 0
|
||||
#define PT_IS_TABLE(x) ((level_idx > 0) && (((x) & PT_FLAG_VALID) == 0) && ((x) != INVALID_PAGE))
|
||||
#define PT_IS_LARGE(x) (((x) & (PT_FLAG_HGLOBAL | PT_FLAG_HUGE)) == (PT_FLAG_HGLOBAL | PT_FLAG_HUGE))
|
||||
#define PT_TO_VMM_FLAGS(x) (pt_to_vmm_flags_internal(x))
|
||||
|
||||
#define pte_new(addr, flags) (pt_entry_t)((addr) | (flags))
|
||||
|
||||
static inline uint64_t pte_addr(uint64_t pte) {
|
||||
if (PT_IS_LARGE(pte)) {
|
||||
return pte & PT_PADDR_HMASK;
|
||||
}
|
||||
return pte & PT_PADDR_MASK;
|
||||
}
|
||||
|
||||
static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
|
||||
uint64_t flags = 0;
|
||||
|
||||
if (entry & PT_FLAG_WRITE)
|
||||
flags |= VMM_FLAG_WRITE;
|
||||
if (entry & PT_FLAG_NX)
|
||||
flags |= VMM_FLAG_NOEXEC;
|
||||
if (entry & PT_FLAG_MAT_WUC)
|
||||
flags |= VMM_FLAG_FB;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
pagemap_t new_pagemap(int paging_mode) {
|
||||
(void)paging_mode;
|
||||
pagemap_t pagemap;
|
||||
pagemap.pgd[0] = ext_mem_alloc(PT_SIZE);
|
||||
pagemap.pgd[1] = ext_mem_alloc(PT_SIZE);
|
||||
return pagemap;
|
||||
}
|
||||
|
||||
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size pg_size) {
|
||||
size_t pml4_entry = (virt_addr & ((uint64_t)0x1ff << 39)) >> 39;
|
||||
size_t pml3_entry = (virt_addr & ((uint64_t)0x1ff << 30)) >> 30;
|
||||
size_t pml2_entry = (virt_addr & ((uint64_t)0x1ff << 21)) >> 21;
|
||||
size_t pml1_entry = (virt_addr & ((uint64_t)0x1ff << 12)) >> 12;
|
||||
|
||||
pt_entry_t *pml4, *pml3, *pml2, *pml1;
|
||||
|
||||
bool is_higher_half = virt_addr & ((uint64_t)1 << 63);
|
||||
|
||||
uint64_t real_flags = PT_FLAG_VALID | PT_FLAG_GLOBAL;
|
||||
if (flags & VMM_FLAG_WRITE)
|
||||
real_flags |= PT_FLAG_DIRTY | PT_FLAG_WRITE;
|
||||
if (flags & VMM_FLAG_NOEXEC)
|
||||
real_flags |= PT_FLAG_NX;
|
||||
if (flags & VMM_FLAG_FB)
|
||||
real_flags |= PT_FLAG_MAT_WUC;
|
||||
else
|
||||
real_flags |= PT_FLAG_MAT_CC;
|
||||
|
||||
pml4 = pagemap.pgd[is_higher_half];
|
||||
|
||||
pml3 = get_next_level(pagemap, pml4, virt_addr, pg_size, 3, pml4_entry);
|
||||
|
||||
if (pg_size == Size1GiB) {
|
||||
pml3[pml3_entry] = pte_new(phys_addr, real_flags | PT_FLAG_HGLOBAL | PT_FLAG_HUGE);
|
||||
return;
|
||||
}
|
||||
|
||||
pml2 = get_next_level(pagemap, pml3, virt_addr, pg_size, 2, pml3_entry);
|
||||
|
||||
if (pg_size == Size2MiB) {
|
||||
pml2[pml2_entry] = pte_new(phys_addr, real_flags | PT_FLAG_HGLOBAL | PT_FLAG_HUGE);
|
||||
return;
|
||||
}
|
||||
|
||||
pml1 = get_next_level(pagemap, pml2, virt_addr, pg_size, 1, pml2_entry);
|
||||
|
||||
pml1[pml1_entry] = pte_new(phys_addr, real_flags);
|
||||
}
|
||||
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -121,6 +121,41 @@ int vmm_max_paging_mode(void);
|
|||
pagemap_t new_pagemap(int paging_mode);
|
||||
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size);
|
||||
|
||||
#elif defined (__loongarch64)
|
||||
|
||||
#define paging_mode_va_bits(mode) 48
|
||||
|
||||
static inline uint64_t paging_mode_higher_half(int paging_mode) {
|
||||
(void)paging_mode;
|
||||
return 0xffff000000000000;
|
||||
}
|
||||
|
||||
// We use fake flags here because these don't properly map onto the
|
||||
// LoongArch flags.
|
||||
#define VMM_FLAG_WRITE ((uint64_t)1 << 0)
|
||||
#define VMM_FLAG_NOEXEC ((uint64_t)1 << 1)
|
||||
#define VMM_FLAG_FB ((uint64_t)1 << 2)
|
||||
|
||||
#define VMM_MAX_LEVEL 3
|
||||
|
||||
#define PAGING_MODE_LOONGARCH64_4LVL 0
|
||||
|
||||
#define PAGING_MODE_MIN PAGING_MODE_LOONGARCH64_4LVL
|
||||
#define PAGING_MODE_MAX PAGING_MODE_LOONGARCH64_4LVL
|
||||
|
||||
enum page_size {
|
||||
Size4KiB,
|
||||
Size2MiB,
|
||||
Size1GiB
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *pgd[2];
|
||||
} pagemap_t;
|
||||
|
||||
pagemap_t new_pagemap(int paging_mode);
|
||||
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags, enum page_size page_size);
|
||||
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -288,7 +288,9 @@ extern symbol limine_spinup_32;
|
|||
| ((uint64_t)1 << 8) /* TTBR0 Inner WB RW-Allocate */ \
|
||||
| ((uint64_t)(tsz) << 0)) /* Address bits in TTBR0 */
|
||||
|
||||
#elif !defined (__riscv64)
|
||||
#elif defined (__riscv64)
|
||||
#elif defined (__loongarch64)
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
||||
|
@ -612,6 +614,12 @@ noreturn void limine_load(char *config, char *cmdline) {
|
|||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - 2) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
#elif defined (__loongarch64)
|
||||
max_supported_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
|
||||
min_supported_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
|
||||
if (hhdm_span_top >= ((uint64_t)1 << paging_mode_va_bits(min_supported_paging_mode)) - 2) {
|
||||
goto hhdm_fail;
|
||||
}
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -652,6 +660,10 @@ hhdm_fail:
|
|||
} else if (strcasecmp(user_max_paging_mode_s, "sv57") == 0) {
|
||||
user_max_paging_mode = PAGING_MODE_RISCV_SV57;
|
||||
}
|
||||
#elif defined (__loongarch64)
|
||||
if (strcasecmp(user_max_paging_mode_s, "4level") == 0) {
|
||||
user_max_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
panic(true, "limine: Invalid MAX_PAGING_MODE: `%s`", user_max_paging_mode_s);
|
||||
|
@ -687,6 +699,10 @@ hhdm_fail:
|
|||
} else if (strcasecmp(user_min_paging_mode_s, "sv57") == 0) {
|
||||
user_min_paging_mode = PAGING_MODE_RISCV_SV57;
|
||||
}
|
||||
#elif defined (__loongarch64)
|
||||
if (strcasecmp(user_min_paging_mode_s, "4level") == 0) {
|
||||
user_min_paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
panic(true, "limine: Invalid MIN_PAGING_MODE: `%s`", user_min_paging_mode_s);
|
||||
|
@ -716,6 +732,8 @@ hhdm_fail:
|
|||
paging_mode = max_supported_paging_mode >= PAGING_MODE_RISCV_SV48 ? PAGING_MODE_RISCV_SV48 : PAGING_MODE_RISCV_SV39;
|
||||
#elif defined (__aarch64__)
|
||||
paging_mode = PAGING_MODE_AARCH64_4LVL;
|
||||
#elif defined (__loongarch64)
|
||||
paging_mode = PAGING_MODE_LOONGARCH64_4LVL;
|
||||
#endif
|
||||
|
||||
#if defined (__riscv64)
|
||||
|
@ -1327,6 +1345,9 @@ FEAT_START
|
|||
direct_map_offset);
|
||||
#elif defined (__riscv64)
|
||||
smp_info = init_smp(&cpu_count, pagemap, direct_map_offset);
|
||||
#elif defined (__loongarch64)
|
||||
cpu_count = 0;
|
||||
smp_info = NULL; // TODO: LoongArch SMP
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -1348,6 +1369,7 @@ FEAT_START
|
|||
if (smp_info[i].hartid == bsp_hartid) {
|
||||
continue;
|
||||
}
|
||||
#elif defined (__loongarch64)
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -1366,6 +1388,7 @@ FEAT_START
|
|||
smp_response->bsp_mpidr = bsp_mpidr;
|
||||
#elif defined (__riscv64)
|
||||
smp_response->bsp_hartid = bsp_hartid;
|
||||
#elif defined (__loongarch64)
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -1498,6 +1521,11 @@ FEAT_END
|
|||
uint64_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
|
||||
|
||||
riscv_spinup(entry_point, reported_stack, satp, direct_map_offset);
|
||||
#elif defined (__loongarch64)
|
||||
uint64_t reported_stack = reported_addr(stack);
|
||||
|
||||
loongarch_spinup(entry_point, reported_stack, (uint64_t)pagemap.pgd[0], (uint64_t)pagemap.pgd[1],
|
||||
direct_map_offset);
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -344,6 +344,16 @@ static inline bool riscv_check_isa_extension(const char *ext, size_t *maj, size_
|
|||
|
||||
void init_riscv(void);
|
||||
|
||||
#elif defined (__loongarch64)
|
||||
|
||||
#define LOONGARCH_CSR_TVAL 0x42
|
||||
|
||||
static inline uint64_t rdtsc(void) {
|
||||
uint64_t v;
|
||||
asm volatile ("csrrd %0, %1" : "=r" (v) : "i" (LOONGARCH_CSR_TVAL));
|
||||
return v;
|
||||
}
|
||||
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -799,6 +799,7 @@ struct limine_smp_info *init_smp(size_t *cpu_count, pagemap_t pagemap, uint64_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
#elif defined (__loongarch64)
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
|
|||
pagemap_t pagemap,
|
||||
uint64_t hhdm_offset);
|
||||
|
||||
#elif defined (__loongarch64)
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -296,6 +296,34 @@ fi
|
|||
|
||||
AC_SUBST([BUILD_UEFI_RISCV64])
|
||||
|
||||
BUILD_UEFI_LOONGARCH64="$BUILD_ALL"
|
||||
|
||||
AC_ARG_ENABLE([uefi-loongarch64],
|
||||
[AS_HELP_STRING([--enable-uefi-loongarch64], [enable building the loongarch64 UEFI port])],
|
||||
[BUILD_UEFI_LOONGARCH64="$enableval"])
|
||||
|
||||
if test "x$BUILD_UEFI_LOONGARCH64" = "xno"; then
|
||||
BUILD_UEFI_LOONGARCH64=""
|
||||
else
|
||||
mkdir -p toolchain-files
|
||||
CC="$CC" \
|
||||
ARCHITECTURE=loongarch64 \
|
||||
FREESTANDING_TOOLCHAIN_SUFFIX="_FOR_TARGET" \
|
||||
FREESTANDING_TOOLCHAIN="$TOOLCHAIN_FOR_TARGET" \
|
||||
WANT_FREESTANDING_CC=yes \
|
||||
FREESTANDING_CC="$CC_FOR_TARGET" \
|
||||
WANT_FREESTANDING_LD=yes \
|
||||
FREESTANDING_LD="$LD_FOR_TARGET" \
|
||||
WANT_FREESTANDING_OBJCOPY=yes \
|
||||
FREESTANDING_OBJCOPY="$OBJCOPY_FOR_TARGET" \
|
||||
WANT_FREESTANDING_OBJDUMP=yes \
|
||||
FREESTANDING_OBJDUMP="$OBJDUMP_FOR_TARGET" \
|
||||
"$SRCDIR/build-aux/freestanding-toolchain" 2>"toolchain-files/uefi-loongarch64-toolchain.mk" || exit 1
|
||||
BUILD_UEFI_LOONGARCH64="limine-uefi-loongarch64"
|
||||
fi
|
||||
|
||||
AC_SUBST([BUILD_UEFI_LOONGARCH64])
|
||||
|
||||
BUILD_UEFI_CD="$BUILD_ALL"
|
||||
|
||||
AC_ARG_ENABLE([uefi-cd],
|
||||
|
|
|
@ -21,6 +21,7 @@ install: all
|
|||
$(INSTALL) -m 644 BOOTIA32.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
|
||||
$(INSTALL) -m 644 BOOTAA64.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
|
||||
$(INSTALL) -m 644 BOOTRISCV64.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
|
||||
$(INSTALL) -m 644 BOOTLOONGARCH64.EFI '$(DESTDIR)$(PREFIX)/share/limine/'
|
||||
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/include'
|
||||
$(INSTALL) -m 644 limine.h '$(DESTDIR)$(PREFIX)/include/'
|
||||
$(INSTALL) -d '$(DESTDIR)$(PREFIX)/bin'
|
||||
|
|
16
limine.h
16
limine.h
|
@ -288,6 +288,11 @@ LIMINE_DEPRECATED_IGNORE_END
|
|||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_RISCV_SV39
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
|
||||
#elif defined (__loongarch__) && (__loongarch_grlen == 64)
|
||||
#define LIMINE_PAGING_MODE_LOONGARCH64_4LVL 0
|
||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_LOONGARCH64_4LVL
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
@ -389,6 +394,17 @@ struct limine_smp_response {
|
|||
LIMINE_PTR(struct limine_smp_info **) cpus;
|
||||
};
|
||||
|
||||
#elif defined (__loongarch__) && (__loongarch_grlen == 64)
|
||||
|
||||
struct limine_smp_info {
|
||||
uint64_t reserved;
|
||||
};
|
||||
|
||||
struct limine_smp_response {
|
||||
uint64_t cpu_count;
|
||||
LIMINE_PTR(struct limine_smp_info **) cpus;
|
||||
};
|
||||
|
||||
#else
|
||||
#error Unknown architecture
|
||||
#endif
|
||||
|
|
28
test.mk
28
test.mk
|
@ -19,6 +19,10 @@ ovmf-ia32:
|
|||
$(MKDIR_P) ovmf-ia32
|
||||
cd ovmf-ia32 && curl -o OVMF.fd https://retrage.github.io/edk2-nightly/bin/RELEASEIa32_OVMF.fd
|
||||
|
||||
ovmf-loongarch64:
|
||||
$(MKDIR_P) ovmf-loongarch64
|
||||
cd ovmf-loongarch64 && curl -o OVMF.fd https://raw.githubusercontent.com/limine-bootloader/firmware/trunk/loongarch64/QEMU_EFI.fd
|
||||
|
||||
.PHONY: test.hdd
|
||||
test.hdd:
|
||||
rm -f test.hdd
|
||||
|
@ -264,6 +268,30 @@ uefi-rv64-test:
|
|||
rm -rf test_image loopback_dev
|
||||
qemu-system-riscv64 -m 512M -M virt -cpu rv64 -drive if=pflash,unit=0,format=raw,file=ovmf-rv64/OVMF.fd -net none -smp 4 -device ramfb -device qemu-xhci -device usb-kbd -device virtio-blk-device,drive=hd0 -drive id=hd0,format=raw,file=test.hdd -serial stdio
|
||||
|
||||
.PHONY: uefi-loongarch64-test
|
||||
uefi-loongarch64-test:
|
||||
$(MAKE) ovmf-loongarch64
|
||||
$(MAKE) test-clean
|
||||
$(MAKE) test.hdd
|
||||
$(MAKE) limine-uefi-loongarch64
|
||||
$(MAKE) -C test TOOLCHAIN_FILE='$(call SHESCAPE,$(BUILDDIR))/toolchain-files/uefi-loongarch64-toolchain.mk'
|
||||
rm -rf test_image/
|
||||
mkdir test_image
|
||||
sudo losetup -Pf --show test.hdd > loopback_dev
|
||||
sudo partprobe `cat loopback_dev`
|
||||
sudo mkfs.fat -F 32 `cat loopback_dev`p1
|
||||
sudo mount `cat loopback_dev`p1 test_image
|
||||
sudo mkdir test_image/boot
|
||||
sudo cp -rv $(BINDIR)/* test_image/boot/
|
||||
sudo cp -rv test/* test_image/boot/
|
||||
sudo $(MKDIR_P) test_image/EFI/BOOT
|
||||
sudo cp $(BINDIR)/BOOTLOONGARCH64.EFI test_image/EFI/BOOT/
|
||||
sync
|
||||
sudo umount test_image/
|
||||
sudo losetup -d `cat loopback_dev`
|
||||
rm -rf test_image loopback_dev
|
||||
qemu-system-loongarch64 -m 1G -net none -M virt -cpu la464 -device ramfb -device qemu-xhci -device usb-kbd -bios ovmf-loongarch64/OVMF.fd -hda test.hdd -serial stdio
|
||||
|
||||
.PHONY: uefi-ia32-test
|
||||
uefi-ia32-test:
|
||||
$(MAKE) ovmf-ia32
|
||||
|
|
|
@ -24,6 +24,10 @@ ifneq ($(findstring riscv64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
|
|||
override LDFLAGS += \
|
||||
-m elf64lriscv
|
||||
endif
|
||||
ifneq ($(findstring loongarch64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
|
||||
override LDFLAGS += \
|
||||
-m elf64loongarch
|
||||
endif
|
||||
|
||||
override LDFLAGS += \
|
||||
-Tlinker.ld \
|
||||
|
@ -80,6 +84,14 @@ override LDFLAGS += \
|
|||
--no-relax
|
||||
endif
|
||||
|
||||
ifneq ($(findstring loongarch64,$(shell $(CC_FOR_TARGET) -dumpmachine)),)
|
||||
override CFLAGS += \
|
||||
-march=loongarch64 \
|
||||
-mabi=lp64s
|
||||
override LDFLAGS += \
|
||||
--no-relax
|
||||
endif
|
||||
|
||||
override CFLAGS_MB := \
|
||||
-std=c11 \
|
||||
-nostdinc \
|
||||
|
|
|
@ -124,11 +124,13 @@ static volatile struct limine_kernel_address_request kernel_address_request = {
|
|||
.revision = 0, .response = NULL
|
||||
};
|
||||
|
||||
#ifndef __loongarch__
|
||||
__attribute__((section(".limine_requests")))
|
||||
static volatile struct limine_smp_request _smp_request = {
|
||||
.id = LIMINE_SMP_REQUEST,
|
||||
.revision = 0, .response = NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
__attribute__((section(".limine_requests")))
|
||||
static volatile struct limine_dtb_request _dtb_request = {
|
||||
|
@ -231,6 +233,8 @@ void ap_entry(struct limine_smp_info *info) {
|
|||
e9_printf("My MPIDR: %x", info->mpidr);
|
||||
#elif defined (__riscv)
|
||||
e9_printf("My Hart ID: %x", info->hartid);
|
||||
#elif defined (__loongarch__)
|
||||
(void)info;
|
||||
#endif
|
||||
|
||||
__atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST);
|
||||
|
@ -455,6 +459,8 @@ FEAT_START
|
|||
e9_printf("Boot time: %d", boot_time_response->boot_time);
|
||||
FEAT_END
|
||||
|
||||
// TODO: LoongArch SMP
|
||||
#ifndef __loongarch__
|
||||
FEAT_START
|
||||
e9_printf("");
|
||||
if (_smp_request.response == NULL) {
|
||||
|
@ -500,6 +506,7 @@ FEAT_START
|
|||
}
|
||||
}
|
||||
FEAT_END
|
||||
#endif
|
||||
|
||||
FEAT_START
|
||||
e9_printf("");
|
||||
|
|
Loading…
Reference in New Issue