1
- #if defined(__riscv ) || defined(__aarch64__ )
1
+ #if defined(__riscv ) || defined(__aarch64__ ) || defined( __loongarch__ )
2
2
3
3
#include <stdint.h>
4
4
#include <stddef.h>
22
22
// kernel headers released under GPL-2.0 WITH Linux-syscall-note
23
23
// allowing their inclusion in non GPL compliant code.
24
24
25
+ #if defined(__riscv ) || defined(__aarch64__ )
25
26
struct linux_header {
26
27
uint32_t code0 ;
27
28
uint32_t code1 ;
@@ -35,6 +36,22 @@ struct linux_header {
35
36
uint32_t magic2 ;
36
37
uint32_t res4 ;
37
38
} __attribute__((packed ));
39
+ #elif defined(__loongarch__ )
40
+ struct linux_header {
41
+ uint32_t mz ;
42
+ uint32_t res0 ;
43
+ uint64_t kernel_entry ;
44
+ uint64_t image_size ;
45
+ uint64_t load_offset ;
46
+ uint64_t res1 ;
47
+ uint64_t res2 ;
48
+ uint64_t res3 ;
49
+ uint32_t magic2 ; // LINUX_PE_MAGIC
50
+ uint32_t pe_offset ;
51
+ } __attribute__((packed ));
52
+ #else
53
+ #error "Unknown architecture"
54
+ #endif
38
55
39
56
struct linux_efi_memreserve {
40
57
int size ;
@@ -74,6 +91,8 @@ struct boot_param {
74
91
#define LINUX_HEADER_MINOR_VER (ver ) (((ver) >> 0) & 0xffff)
75
92
#elif defined(__aarch64__ )
76
93
#define LINUX_HEADER_MAGIC2 0x644d5241
94
+ #elif defined(__loongarch__ )
95
+ #define LINUX_HEADER_MAGIC2 0x818223cd
77
96
#endif
78
97
79
98
const char * verify_kernel (struct boot_param * p ) {
@@ -335,7 +354,13 @@ void prepare_mmap(struct boot_param *p) {
335
354
EFI_MEMORY_DESCRIPTOR * entry = (void * )efi_mmap + i * efi_desc_size ;
336
355
337
356
if (entry -> Attribute & EFI_MEMORY_RUNTIME ) {
338
- entry -> VirtualStart = entry -> PhysicalStart ;
357
+ // LoongArch kernel requires the virtual address stays in the
358
+ // privileged, direct-mapped window
359
+ #if defined(__loongarch__ )
360
+ entry -> VirtualStart = entry -> PhysicalStart | (0x8ULL << 60 );
361
+ #else
362
+ entry -> VirtualStart = entry -> PhysicalStart ;
363
+ #endif
339
364
}
340
365
}
341
366
@@ -361,6 +386,34 @@ noreturn void jump_to_kernel(struct boot_param *p) {
361
386
void (* kernel_entry )(uint64_t dtb , uint64_t res0 , uint64_t res1 , uint64_t res2 ) = p -> kernel_base ;
362
387
asm ("msr daifset, 0xF" );
363
388
kernel_entry ((uint64_t )p -> dtb , 0 , 0 , 0 );
389
+ #elif defined(__loongarch__ )
390
+ // LoongArch kernel used to store virtual address in header.kernel_entry
391
+ // clearing the high 16bits ensures compatibility
392
+ #define TO_PHYS (addr ) ((addr) & ((1ULL << 48) - 1))
393
+ #define CSR_DMW_PLV0 1ULL
394
+ #define CSR_DMW0_VSEG 0x8000ULL
395
+ #define CSR_DMW0_BASE (CSR_DMW0_VSEG << 48)
396
+ #define CSR_DMW0_INIT (CSR_DMW0_BASE | CSR_DMW_PLV0)
397
+ #define CSR_DMW1_MAT (1 << 4)
398
+ #define CSR_DMW1_VSEG 0x9000ULL
399
+ #define CSR_DMW1_BASE (CSR_DMW1_VSEG << 48)
400
+ #define CSR_DMW1_INIT (CSR_DMW1_BASE | CSR_DMW1_MAT | CSR_DMW_PLV0)
401
+ #define CSR_DMW2_VSEG 0xa000ULL
402
+ #define CSR_DMW2_MAT (2 << 4)
403
+ #define CSR_DMW2_BASE (CSR_DMW2_VSEG << 48)
404
+ #define CSR_DMW2_INIT (CSR_DMW2_BASE | CSR_DMW2_MAT | CSR_DMW_PLV0)
405
+ #define CSR_DMW3_INIT 0
406
+
407
+ struct linux_header * header = p -> kernel_base ;
408
+ void (* kernel_entry )(uint64_t efi_boot , uint64_t cmdline , uint64_t st );
409
+ kernel_entry = p -> kernel_base + (TO_PHYS (header -> kernel_entry ) - header -> load_offset );
410
+
411
+ asm volatile ("csrxchg $r0, %0, 0x0" :: "r" (0x4 ) : "memory" );
412
+ asm volatile ("csrwr %0, 0x180" :: "r" (CSR_DMW0_INIT ) : "memory" );
413
+ asm volatile ("csrwr %0, 0x181" :: "r" (CSR_DMW1_INIT ) : "memory" );
414
+ asm volatile ("csrwr %0, 0x182" :: "r" (CSR_DMW2_INIT ) : "memory" );
415
+ asm volatile ("csrwr %0, 0x183" :: "r" (CSR_DMW3_INIT ) : "memory" );
416
+ kernel_entry (1 , (uint64_t )p -> cmdline , (uint64_t )gST );
364
417
#endif
365
418
__builtin_unreachable ();
366
419
}
0 commit comments