[arch][riscv] read the riscv feature string out of device tree
Also added initial implementation of a way to query run time features of the cpu.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include <platform.h>
|
||||
#include <arch.h>
|
||||
|
||||
#include "arch/riscv/feature.h"
|
||||
#include "riscv_priv.h"
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
@@ -71,6 +72,8 @@ void riscv_early_init_percpu(void) {
|
||||
void arch_early_init(void) {
|
||||
riscv_early_init_percpu();
|
||||
|
||||
riscv_feature_early_init();
|
||||
|
||||
#if RISCV_S_MODE
|
||||
sbi_early_init();
|
||||
#endif
|
||||
@@ -110,6 +113,8 @@ void arch_init(void) {
|
||||
riscv_get_mvendorid(), riscv_get_marchid(),
|
||||
riscv_get_mimpid(), riscv_current_hart());
|
||||
|
||||
riscv_feature_init();
|
||||
|
||||
#if RISCV_M_MODE
|
||||
dprintf(INFO, "RISCV: misa %#lx\n", riscv_csr_read(RISCV_CSR_MISA));
|
||||
#elif RISCV_S_MODE
|
||||
|
||||
214
arch/riscv/feature.c
Normal file
214
arch/riscv/feature.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Travis Geiselbrecht
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#include "arch/riscv/feature.h"
|
||||
|
||||
#include <lk/trace.h>
|
||||
#include <lk/debug.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
// Make feature bitmap
|
||||
uint32_t riscv_feature_bitmap[ROUNDUP(RISCV_FEAT_COUNT, 32) / 32];
|
||||
|
||||
static void set_feature(enum riscv_feature feature) {
|
||||
riscv_feature_bitmap[feature / 32] |= (1U << feature % 32);
|
||||
}
|
||||
|
||||
// match a one word feature from a known list
|
||||
static void match_feature(const char *str, size_t start, size_t end) {
|
||||
const struct {
|
||||
const char *str;
|
||||
enum riscv_feature feat;
|
||||
} oneword[] = {
|
||||
{ "zba", RISCV_FEAT_ZBA },
|
||||
{ "zbb", RISCV_FEAT_ZBB },
|
||||
{ "zbc", RISCV_FEAT_ZBC },
|
||||
{ "zbs", RISCV_FEAT_ZBS },
|
||||
{ "sstc", RISCV_FEAT_SSTC },
|
||||
{ "zicsr", RISCV_FEAT_ZICSR },
|
||||
{ "zfencei", RISCV_FEAT_ZIFENCEI },
|
||||
};
|
||||
|
||||
if (LOCAL_TRACE) {
|
||||
char feat[128];
|
||||
strlcpy(feat, &str[start], end - start + 1);
|
||||
printf("feature '%s'\n", feat);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < countof(oneword); i++) {
|
||||
if (strlen(oneword[i].str) != end - start)
|
||||
continue;
|
||||
|
||||
if (strncasecmp(oneword[i].str, &str[start], end - start) == 0) {
|
||||
dprintf(INFO, "riscv: found feature '%s'\n", oneword[i].str);
|
||||
set_feature(oneword[i].feat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void riscv_set_isa_string(const char *str) {
|
||||
LTRACEF("%s\n", str);
|
||||
|
||||
const size_t slen = strlen(str);
|
||||
|
||||
// Handle simple features first.
|
||||
// Feature string must start with either 'rv64' or 'rv32' followed by
|
||||
// one or more one character features until _ or null.
|
||||
if (slen < 4 || str[0] != 'r' || str[1] != 'v') {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're going to continue, so wipe out the existing default feature list
|
||||
memset(riscv_feature_bitmap, 0, 4 * countof(riscv_feature_bitmap));
|
||||
|
||||
size_t pos = 4;
|
||||
while (str[pos] != 0 && str[pos] != '_') {
|
||||
bool found = true;
|
||||
switch (tolower(str[pos])) {
|
||||
// TODO: make sure this is the complete list
|
||||
case 'i': set_feature(RISCV_FEAT_I); break;
|
||||
case 'm': set_feature(RISCV_FEAT_M); break;
|
||||
case 'a': set_feature(RISCV_FEAT_A); break;
|
||||
case 'q': set_feature(RISCV_FEAT_Q);
|
||||
// fallthrough
|
||||
case 'd':
|
||||
feat_d:
|
||||
set_feature(RISCV_FEAT_D);
|
||||
// fallthrough
|
||||
case 'f': set_feature(RISCV_FEAT_F); break;
|
||||
case 'c': set_feature(RISCV_FEAT_C); break;
|
||||
case 'b': set_feature(RISCV_FEAT_B); break;
|
||||
case 'p': set_feature(RISCV_FEAT_P); break;
|
||||
case 'h': set_feature(RISCV_FEAT_H); break;
|
||||
case 'v':
|
||||
set_feature(RISCV_FEAT_V);
|
||||
goto feat_d;
|
||||
case 'g':
|
||||
// 'g' is a special case that implies IMAFDZisr_Zifenci
|
||||
set_feature(RISCV_FEAT_I);
|
||||
set_feature(RISCV_FEAT_M);
|
||||
set_feature(RISCV_FEAT_A);
|
||||
set_feature(RISCV_FEAT_ZICSR);
|
||||
set_feature(RISCV_FEAT_ZIFENCEI);
|
||||
goto feat_d;
|
||||
default:
|
||||
found = false;
|
||||
}
|
||||
if (found) {
|
||||
dprintf(INFO, "riscv: found feature '%c'\n", tolower(str[pos]));
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
// walk the one-word features
|
||||
bool in_word = false;
|
||||
size_t start;
|
||||
for (; pos <= slen; pos++) {
|
||||
if (!in_word) {
|
||||
if (str[pos] == '_') {
|
||||
continue;
|
||||
} else if (str[pos] == 0) {
|
||||
break;
|
||||
}
|
||||
start = pos;
|
||||
in_word = true;
|
||||
} else {
|
||||
// we're in a word
|
||||
if (str[pos] == '_' || str[pos] == 0) {
|
||||
// end of word
|
||||
in_word = false;
|
||||
|
||||
// process the feature word, between str[start...pos]
|
||||
match_feature(str, start, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void riscv_feature_early_init(void) {
|
||||
// set the default features based on the compiler switches
|
||||
#if __riscv_i
|
||||
set_feature(RISCV_FEAT_I);
|
||||
#endif
|
||||
#if __riscv_m
|
||||
set_feature(RISCV_FEAT_M);
|
||||
#endif
|
||||
#if __riscv_a
|
||||
set_feature(RISCV_FEAT_A);
|
||||
#endif
|
||||
#if __riscv_f
|
||||
set_feature(RISCV_FEAT_F);
|
||||
#endif
|
||||
#if __riscv_d
|
||||
set_feature(RISCV_FEAT_D);
|
||||
#endif
|
||||
#if __riscv_q
|
||||
set_feature(RISCV_FEAT_Q);
|
||||
#endif
|
||||
#if __riscv_c
|
||||
set_feature(RISCV_FEAT_C);
|
||||
#endif
|
||||
#if __riscv_zba
|
||||
set_feature(RISCV_FEAT_ZBA);
|
||||
#endif
|
||||
#if __riscv_zbb
|
||||
set_feature(RISCV_FEAT_ZBB);
|
||||
#endif
|
||||
#if __riscv_zba
|
||||
set_feature(RISCV_FEAT_ZBA);
|
||||
#endif
|
||||
#if __riscv_zbc
|
||||
set_feature(RISCV_FEAT_ZBC);
|
||||
#endif
|
||||
#if __riscv_zbs
|
||||
set_feature(RISCV_FEAT_ZBS);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *riscv_feature_to_string(enum riscv_feature feature) {
|
||||
switch (feature) {
|
||||
case RISCV_FEAT_I: return "i";
|
||||
case RISCV_FEAT_M: return "m";
|
||||
case RISCV_FEAT_A: return "a";
|
||||
case RISCV_FEAT_F: return "f";
|
||||
case RISCV_FEAT_D: return "d";
|
||||
case RISCV_FEAT_Q: return "q";
|
||||
case RISCV_FEAT_C: return "c";
|
||||
case RISCV_FEAT_B: return "b";
|
||||
case RISCV_FEAT_P: return "p";
|
||||
case RISCV_FEAT_V: return "v";
|
||||
case RISCV_FEAT_H: return "h";
|
||||
case RISCV_FEAT_ZBA: return "zba";
|
||||
case RISCV_FEAT_ZBB: return "zbb";
|
||||
case RISCV_FEAT_ZBC: return "zbc";
|
||||
case RISCV_FEAT_ZBS: return "zbs";
|
||||
case RISCV_FEAT_ZICSR: return "zicsr";
|
||||
case RISCV_FEAT_ZIFENCEI: return "zifencei";
|
||||
case RISCV_FEAT_SSTC: return "sstc";
|
||||
|
||||
// keep this in so the compiler warns if something is missing
|
||||
case RISCV_FEAT_COUNT: return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void riscv_feature_init(void) {
|
||||
dprintf(INFO, "RISCV: detected features");
|
||||
for (size_t i = 0; i < countof(riscv_feature_bitmap); i++) {
|
||||
for (size_t j = 0; j < sizeof(riscv_feature_bitmap[i]) * 8; j++) {
|
||||
if (riscv_feature_bitmap[i] & (1U << j)) {
|
||||
dprintf(INFO, " %s", riscv_feature_to_string(i * 32 + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
dprintf(INFO, "\n");
|
||||
}
|
||||
58
arch/riscv/include/arch/riscv/feature.h
Normal file
58
arch/riscv/include/arch/riscv/feature.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Travis Geiselbrecht
|
||||
*
|
||||
* Use of this source code is governed by a MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <lk/compiler.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
// Given a list of features in foo_bar_baz form, break out known features.
|
||||
// Does not keep a pointer to the string.
|
||||
void riscv_set_isa_string(const char *string);
|
||||
|
||||
enum riscv_feature {
|
||||
// Basic one character features
|
||||
RISCV_FEAT_I,
|
||||
RISCV_FEAT_M,
|
||||
RISCV_FEAT_A,
|
||||
RISCV_FEAT_F,
|
||||
RISCV_FEAT_D,
|
||||
RISCV_FEAT_Q,
|
||||
RISCV_FEAT_C,
|
||||
RISCV_FEAT_B,
|
||||
RISCV_FEAT_P,
|
||||
RISCV_FEAT_V,
|
||||
RISCV_FEAT_H,
|
||||
|
||||
// multichar features
|
||||
RISCV_FEAT_ZBA,
|
||||
RISCV_FEAT_ZBB,
|
||||
RISCV_FEAT_ZBC,
|
||||
RISCV_FEAT_ZBS,
|
||||
RISCV_FEAT_ZICSR,
|
||||
RISCV_FEAT_ZIFENCEI,
|
||||
RISCV_FEAT_SSTC,
|
||||
|
||||
RISCV_FEAT_COUNT
|
||||
};
|
||||
|
||||
extern uint32_t riscv_feature_bitmap[];
|
||||
|
||||
// Test if a particular feature is present
|
||||
static inline bool riscv_feature_test(enum riscv_feature feature) {
|
||||
return riscv_feature_bitmap[feature / 32] & (1U << feature % 32);
|
||||
}
|
||||
|
||||
const char *riscv_feature_to_string(enum riscv_feature feature);
|
||||
|
||||
void riscv_feature_early_init(void);
|
||||
void riscv_feature_init(void);
|
||||
|
||||
__END_CDECLS
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
#include <kernel/vm.h>
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
#error "32 bit mmu not supported yet"
|
||||
#endif
|
||||
@@ -640,7 +638,7 @@ void riscv_early_mmu_init() {
|
||||
// called a bit later once on the boot cpu
|
||||
extern "C"
|
||||
void riscv_mmu_init() {
|
||||
printf("RISCV: MMU ASID mask %#lx\n", riscv_asid_mask);
|
||||
dprintf(INFO, "RISCV: MMU ASID mask %#lx\n", riscv_asid_mask);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,15 +3,17 @@ LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
MODULE_SRCS += $(LOCAL_DIR)/start.S
|
||||
|
||||
MODULE_SRCS += $(LOCAL_DIR)/arch.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/asm.S
|
||||
MODULE_SRCS += $(LOCAL_DIR)/exceptions.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/feature.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/fpu_asm.S
|
||||
MODULE_SRCS += $(LOCAL_DIR)/thread.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/mmu.cpp
|
||||
MODULE_SRCS += $(LOCAL_DIR)/mp.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/sbi.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/spinlock.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/thread.c
|
||||
MODULE_SRCS += $(LOCAL_DIR)/time.c
|
||||
|
||||
MODULE_DEPS += lib/libcpp
|
||||
|
||||
@@ -84,18 +84,35 @@ status_t read_base_len_pair(const uint8_t *prop_ptr, size_t prop_len,
|
||||
// returns true or false if a particular property is a particular value
|
||||
bool check_prop_is_val_string(const void *fdt, int offset, const char *prop, const char *val) {
|
||||
int lenp;
|
||||
const uint8_t *prop_ptr = (const uint8_t *)fdt_getprop(fdt, offset, prop, &lenp);
|
||||
const uint8_t *prop_ptr = static_cast<const uint8_t *>(fdt_getprop(fdt, offset, prop, &lenp));
|
||||
if (!prop_ptr || lenp <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strncmp(val, (const char *)prop_ptr, strlen(val)) == 0) {
|
||||
if (strncmp(val, reinterpret_cast<const char *>(prop_ptr), strlen(val)) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *get_prop_string(const void *fdt, int offset, const char *prop) {
|
||||
int lenp;
|
||||
const uint8_t *prop_ptr = static_cast<const uint8_t *>(fdt_getprop(fdt, offset, prop, &lenp));
|
||||
if (!prop_ptr || lenp <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check to see that it appears to be null terminated
|
||||
auto str = reinterpret_cast<const char *>(prop_ptr);
|
||||
if (str[lenp-1] != '\0') {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// seems safe
|
||||
return str;
|
||||
}
|
||||
|
||||
struct fdt_walk_state {
|
||||
const void *fdt;
|
||||
int offset;
|
||||
@@ -210,6 +227,18 @@ status_t fdt_walk_find_cpus(const void *fdt, struct fdt_walk_cpu_info *cpu, size
|
||||
cpu[*cpu_count].id = id;
|
||||
(*cpu_count)++;
|
||||
}
|
||||
#if ARCH_RISCV
|
||||
// look for riscv,isa and riscv,isa-extensions
|
||||
auto isa_string = get_prop_string(state.fdt, state.offset, "riscv,isa");
|
||||
if (isa_string) {
|
||||
cpu->isa_string = isa_string;
|
||||
}
|
||||
|
||||
auto isa_extensions_string = get_prop_string(state.fdt, state.offset, "riscv,isa-extensions");
|
||||
if (isa_extensions_string) {
|
||||
cpu->isa_extensions_string = isa_extensions_string;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#endif
|
||||
#if ARCH_RISCV
|
||||
#include <arch/riscv.h>
|
||||
#include <arch/riscv/feature.h>
|
||||
#endif
|
||||
#if ARCH_ARM || ARCH_ARM64
|
||||
#include <dev/power/psci.h>
|
||||
@@ -42,13 +43,13 @@ status_t fdtwalk_reserve_fdt_memory(const void *fdt, paddr_t fdt_phys) {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
unsigned long length = fdt_totalsize(fdt);
|
||||
uint32_t length = fdt_totalsize(fdt);
|
||||
|
||||
paddr_t base = fdt_phys;
|
||||
base = PAGE_ALIGN(base);
|
||||
length = ROUNDUP(length, PAGE_SIZE);
|
||||
|
||||
printf("FDT: reserving physical range for FDT: [%#lx, %#lx]\n", base, base + length - 1);
|
||||
dprintf(INFO, "FDT: reserving physical range for FDT: [%#lx, %#lx]\n", base, base + length - 1);
|
||||
|
||||
#if WITH_KERNEL_VM
|
||||
struct list_node list = LIST_INITIAL_VALUE(list);
|
||||
@@ -74,7 +75,7 @@ status_t fdtwalk_setup_memory(const void *fdt, paddr_t fdt_phys, paddr_t default
|
||||
status_t err = fdt_walk_find_memory(fdt, mem, &mem_count, reserved_mem, &reserved_mem_count);
|
||||
if (err < NO_ERROR || mem_count == 0) {
|
||||
/* add a default memory region if we didn't find it in the FDT */
|
||||
printf("FDT: could not find memory, using default base %#lx size %#zx\n", default_mem_base, default_mem_size);
|
||||
dprintf(INFO, "FDT: could not find memory, using default base %#lx size %#zx\n", default_mem_base, default_mem_size);
|
||||
#if WITH_KERNEL_VM
|
||||
mem[0].base = default_mem_base;
|
||||
mem[0].len = default_mem_size;
|
||||
@@ -84,20 +85,20 @@ status_t fdtwalk_setup_memory(const void *fdt, paddr_t fdt_phys, paddr_t default
|
||||
|
||||
for (size_t i = 0; i < mem_count; i++) {
|
||||
LTRACEF("base %#llx len %#llx\n", mem[i].base, mem[i].len);
|
||||
printf("FDT: found memory bank range [%#llx, %#llx] (length %#llx)\n", mem[i].base, mem[i].base + mem[i].len - 1, mem[i].len);
|
||||
dprintf(INFO, "FDT: found memory bank range [%#llx, %#llx] (length %#llx)\n", mem[i].base, mem[i].base + mem[i].len - 1, mem[i].len);
|
||||
|
||||
/* trim size on certain platforms */
|
||||
#if ARCH_ARM || (ARCH_RISCV && __riscv_xlen == 32)
|
||||
/* only use the first 1GB on ARM32 */
|
||||
const auto GB = 1024*1024*1024UL;
|
||||
if (mem[i].base - MEMBASE > GB) {
|
||||
printf("trimming memory to 1GB\n");
|
||||
dprintf(INFO, "trimming memory to 1GB\n");
|
||||
continue;
|
||||
}
|
||||
if (mem[i].base - MEMBASE + mem[i].len > GB) {
|
||||
printf("trimming memory to 1GB\n");
|
||||
dprintf(INFO, "trimming memory to 1GB\n");
|
||||
mem[i].len = MEMBASE + GB - mem[i].base;
|
||||
printf("range is now [%#llx, %#llx]\n", mem[i].base, mem[i].base + mem[i].len - 1);
|
||||
dprintf(INFO, "range is now [%#llx, %#llx]\n", mem[i].base, mem[i].base + mem[i].len - 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -120,7 +121,7 @@ status_t fdtwalk_setup_memory(const void *fdt, paddr_t fdt_phys, paddr_t default
|
||||
|
||||
/* reserve memory described by the FDT */
|
||||
for (size_t i = 0; i < reserved_mem_count; i++) {
|
||||
printf("FDT: reserving memory range [%#llx, %#llx]\n",
|
||||
dprintf(INFO, "FDT: reserving memory range [%#llx, %#llx]\n",
|
||||
reserved_mem[i].base, reserved_mem[i].base + reserved_mem[i].len - 1);
|
||||
|
||||
#if WITH_KERNEL_VM
|
||||
@@ -150,9 +151,10 @@ status_t fdtwalk_setup_cpus_riscv(const void *fdt) {
|
||||
|
||||
status_t err = fdt_walk_find_cpus(fdt, cpus, &cpu_count);
|
||||
if (err >= NO_ERROR) {
|
||||
const char *isa_string = {};
|
||||
|
||||
if (cpu_count > 0) {
|
||||
printf("FDT: found %zu cpu%c\n", cpu_count, cpu_count == 1 ? ' ' : 's');
|
||||
dprintf(INFO, "FDT: found %zu cpu%c\n", cpu_count, cpu_count == 1 ? ' ' : 's');
|
||||
uint harts[SMP_MAX_CPUS - 1];
|
||||
|
||||
// copy from the detected cpu list to an array of harts, excluding the boot hart
|
||||
@@ -166,12 +168,29 @@ status_t fdtwalk_setup_cpus_riscv(const void *fdt) {
|
||||
if (hart_index >= SMP_MAX_CPUS - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cpus[i].isa_string) {
|
||||
if (!isa_string) {
|
||||
// save the first isa string we found
|
||||
isa_string = cpus[i].isa_string;
|
||||
} else {
|
||||
if (!strcmp(cpus[i].isa_string, isa_string)) {
|
||||
printf("FDT Warning: isa_strings do not match between cpus, using first found\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tell the riscv layer how many cores we have to start
|
||||
if (hart_index > 0) {
|
||||
riscv_set_secondary_harts_to_start(harts, hart_index);
|
||||
}
|
||||
|
||||
if (isa_string) {
|
||||
dprintf(INFO, "FDT: isa string '%s'\n", isa_string);
|
||||
riscv_set_isa_string(isa_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -189,11 +208,11 @@ status_t fdtwalk_setup_cpus_arm(const void *fdt) {
|
||||
status_t err = fdt_walk_find_cpus(fdt, cpus, &cpu_count);
|
||||
if (err >= NO_ERROR) {
|
||||
if (cpu_count > 0) {
|
||||
printf("FDT: found %zu cpu%c\n", cpu_count, cpu_count == 1 ? ' ' : 's');
|
||||
dprintf(INFO, "FDT: found %zu cpu%c\n", cpu_count, cpu_count == 1 ? ' ' : 's');
|
||||
|
||||
if (cpu_count > SMP_MAX_CPUS) {
|
||||
cpu_count = MIN(cpu_count, SMP_MAX_CPUS);
|
||||
printf("FDT: clamping max cpus to %zu\n", cpu_count);
|
||||
dprintf(INFO, "FDT: clamping max cpus to %zu\n", cpu_count);
|
||||
}
|
||||
|
||||
LTRACEF("booting %zu cpus\n", cpu_count);
|
||||
@@ -201,7 +220,7 @@ status_t fdtwalk_setup_cpus_arm(const void *fdt) {
|
||||
/* boot the secondary cpus using the Power State Coordintion Interface */
|
||||
for (size_t i = 1; i < cpu_count; i++) {
|
||||
/* note: assumes cpuids are numbered like MPIDR 0:0:0:N */
|
||||
printf("ARM: starting cpu %#x\n", cpus[i].id);
|
||||
dprintf(INFO, "ARM: starting cpu %#x\n", cpus[i].id);
|
||||
int ret = psci_cpu_on(cpus[i].id, MEMBASE + KERNEL_LOAD_OFFSET);
|
||||
if (ret != 0) {
|
||||
printf("ERROR: psci CPU_ON returns %d\n", ret);
|
||||
@@ -235,7 +254,7 @@ status_t fdtwalk_setup_pci(const void *fdt) {
|
||||
}
|
||||
|
||||
if (pcie_info[i].ecam_len > 0) {
|
||||
printf("PCIE: initializing pcie with ecam at %#" PRIx64 " found in FDT\n", pcie_info[i].ecam_base);
|
||||
dprintf(INFO, "PCIE: initializing pcie with ecam at %#" PRIx64 " found in FDT\n", pcie_info[i].ecam_base);
|
||||
err = pci_init_ecam(pcie_info[i].ecam_base, pcie_info[i].ecam_len, pcie_info[i].bus_start, pcie_info[i].bus_end);
|
||||
if (err == NO_ERROR) {
|
||||
// add some additional resources to the pci bus manager in case it needs to configure
|
||||
|
||||
@@ -41,6 +41,10 @@ struct fdt_walk_memory_region {
|
||||
|
||||
struct fdt_walk_cpu_info {
|
||||
uint32_t id;
|
||||
#if ARCH_RISCV
|
||||
const char *isa_string; // pointer to riscv,isa inside device tree
|
||||
const char *isa_extensions_string; // pointer to riscv,isa-etensions inside device tree
|
||||
#endif
|
||||
};
|
||||
|
||||
status_t fdt_walk_dump(const void *fdt);
|
||||
|
||||
Reference in New Issue
Block a user