Add LoongArch support

This commit is contained in:
Keegan Saunders 2024-07-31 23:03:09 -04:00
parent 3be68d0502
commit d9a2fb95a9
30 changed files with 695 additions and 10 deletions

1
.gitignore vendored
View File

@ -56,6 +56,7 @@
/common-uefi-x86-64
/common-uefi-aarch64
/common-uefi-riscv64
/common-uefi-loongarch64
/decompressor-build
/stage1.stamp

View File

@ -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`.

View File

@ -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 \

View File

@ -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:

View File

@ -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

View File

@ -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 \

View File

@ -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,$@)')"

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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)
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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],

View File

@ -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'

View File

@ -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
View File

@ -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

View File

@ -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 \

View File

@ -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("");