version 1.58, 2019/01/31 13:26:21 |
version 1.72, 2020/05/15 06:01:26 |
Line 64 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 64 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/disk.h> |
#include <sys/disk.h> |
#include <sys/md5.h> |
#include <sys/md5.h> |
#include <sys/pserialize.h> |
#include <sys/pserialize.h> |
|
#include <sys/rnd.h> |
|
#include <sys/rndsource.h> |
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
Line 88 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 90 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <evbarm/fdt/fdt_memory.h> |
#include <evbarm/fdt/fdt_memory.h> |
|
|
#include <arm/fdt/arm_fdtvar.h> |
#include <arm/fdt/arm_fdtvar.h> |
|
#include <dev/fdt/fdt_private.h> |
|
|
#ifdef EFI_RUNTIME |
#ifdef EFI_RUNTIME |
#include <arm/arm/efi_runtime.h> |
#include <arm/arm/efi_runtime.h> |
Line 117 u_long uboot_args[4] __attribute__((__se |
|
Line 120 u_long uboot_args[4] __attribute__((__se |
|
const uint8_t *fdt_addr_r __attribute__((__section__(".data"))); |
const uint8_t *fdt_addr_r __attribute__((__section__(".data"))); |
|
|
static uint64_t initrd_start, initrd_end; |
static uint64_t initrd_start, initrd_end; |
|
static uint64_t rndseed_start, rndseed_end; /* our on-disk seed */ |
|
static uint64_t efirng_start, efirng_end; /* firmware's EFI RNG output */ |
|
|
#include <libfdt.h> |
#include <libfdt.h> |
#include <dev/fdt/fdtvar.h> |
#include <dev/fdt/fdtvar.h> |
Line 158 static struct consdev earlycons = { |
|
Line 163 static struct consdev earlycons = { |
|
#endif |
#endif |
|
|
/* |
/* |
* ARM: Get the first physically contiguous region of memory. |
* Get all of physical memory, including holes. |
* ARM64: Get all of physical memory, including holes. |
|
*/ |
*/ |
static void |
static void |
fdt_get_memory(uint64_t *pstart, uint64_t *pend) |
fdt_get_memory(uint64_t *pstart, uint64_t *pend) |
Line 184 fdt_get_memory(uint64_t *pstart, uint64_ |
|
Line 188 fdt_get_memory(uint64_t *pstart, uint64_ |
|
VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n", |
VPRINTF("FDT /memory [%d] @ 0x%" PRIx64 " size 0x%" PRIx64 "\n", |
index, cur_addr, cur_size); |
index, cur_addr, cur_size); |
|
|
#ifdef __aarch64__ |
|
if (cur_addr + cur_size > *pend) |
if (cur_addr + cur_size > *pend) |
*pend = cur_addr + cur_size; |
*pend = cur_addr + cur_size; |
#else |
|
/* If subsequent entries follow the previous, append them. */ |
|
if (*pend == cur_addr) |
|
*pend = cur_addr + cur_size; |
|
#endif |
|
} |
} |
} |
} |
|
|
Line 258 static struct boot_physmem fdt_physmem[M |
|
Line 256 static struct boot_physmem fdt_physmem[M |
|
static void |
static void |
fdt_add_boot_physmem(const struct fdt_memory *m, void *arg) |
fdt_add_boot_physmem(const struct fdt_memory *m, void *arg) |
{ |
{ |
struct boot_physmem *bp = &fdt_physmem[nfdt_physmem++]; |
const paddr_t saddr = round_page(m->start); |
|
const paddr_t eaddr = trunc_page(m->end); |
|
|
VPRINTF(" %" PRIx64 " - %" PRIx64 "\n", m->start, m->end - 1); |
VPRINTF(" %" PRIx64 " - %" PRIx64, m->start, m->end - 1); |
|
if (saddr >= eaddr) { |
|
VPRINTF(" skipped\n"); |
|
return; |
|
} |
|
VPRINTF("\n"); |
|
|
|
struct boot_physmem *bp = &fdt_physmem[nfdt_physmem++]; |
|
|
KASSERT(nfdt_physmem <= MAX_PHYSMEM); |
KASSERT(nfdt_physmem <= MAX_PHYSMEM); |
|
|
bp->bp_start = atop(round_page(m->start)); |
bp->bp_start = atop(saddr); |
bp->bp_pages = atop(trunc_page(m->end)) - bp->bp_start; |
bp->bp_pages = atop(eaddr) - bp->bp_start; |
bp->bp_freelist = VM_FREELIST_DEFAULT; |
bp->bp_freelist = VM_FREELIST_DEFAULT; |
|
|
#ifdef _LP64 |
|
if (m->end > 0x100000000) |
|
bp->bp_freelist = VM_FREELIST_HIGHMEM; |
|
#endif |
|
|
|
#ifdef PMAP_NEED_ALLOC_POOLPAGE |
#ifdef PMAP_NEED_ALLOC_POOLPAGE |
const uint64_t memory_size = *(uint64_t *)arg; |
const uint64_t memory_size = *(uint64_t *)arg; |
if (atop(memory_size) > bp->bp_pages) { |
if (atop(memory_size) > bp->bp_pages) { |
Line 310 fdt_build_bootconfig(uint64_t mem_start, |
|
Line 311 fdt_build_bootconfig(uint64_t mem_start, |
|
if (initrd_size > 0) |
if (initrd_size > 0) |
fdt_memory_remove_range(initrd_start, initrd_size); |
fdt_memory_remove_range(initrd_start, initrd_size); |
|
|
|
const uint64_t rndseed_size = rndseed_end - rndseed_start; |
|
if (rndseed_size > 0) |
|
fdt_memory_remove_range(rndseed_start, rndseed_size); |
|
|
|
const uint64_t efirng_size = efirng_end - efirng_start; |
|
if (efirng_size > 0) |
|
fdt_memory_remove_range(efirng_start, efirng_size); |
|
|
const int framebuffer = OF_finddevice("/chosen/framebuffer"); |
const int framebuffer = OF_finddevice("/chosen/framebuffer"); |
if (framebuffer >= 0) { |
if (framebuffer >= 0) { |
for (index = 0; |
for (index = 0; |
Line 325 fdt_build_bootconfig(uint64_t mem_start, |
|
Line 334 fdt_build_bootconfig(uint64_t mem_start, |
|
} |
} |
|
|
static void |
static void |
fdt_probe_initrd(uint64_t *pstart, uint64_t *pend) |
fdt_probe_range(const char *startname, const char *endname, |
|
uint64_t *pstart, uint64_t *pend) |
{ |
{ |
|
int chosen, len; |
|
const void *start_data, *end_data; |
|
|
*pstart = *pend = 0; |
*pstart = *pend = 0; |
|
|
#ifdef MEMORY_DISK_DYNAMIC |
chosen = OF_finddevice("/chosen"); |
const int chosen = OF_finddevice("/chosen"); |
|
if (chosen < 0) |
if (chosen < 0) |
return; |
return; |
|
|
int len; |
start_data = fdtbus_get_prop(chosen, startname, &len); |
const void *start_data = fdtbus_get_prop(chosen, |
end_data = fdtbus_get_prop(chosen, endname, NULL); |
"linux,initrd-start", &len); |
|
const void *end_data = fdtbus_get_prop(chosen, |
|
"linux,initrd-end", NULL); |
|
if (start_data == NULL || end_data == NULL) |
if (start_data == NULL || end_data == NULL) |
return; |
return; |
|
|
Line 352 fdt_probe_initrd(uint64_t *pstart, uint6 |
|
Line 361 fdt_probe_initrd(uint64_t *pstart, uint6 |
|
*pend = be64dec(end_data); |
*pend = be64dec(end_data); |
break; |
break; |
default: |
default: |
printf("Unsupported len %d for /chosen/initrd-start\n", len); |
printf("Unsupported len %d for /chosen `%s'\n", |
|
len, startname); |
return; |
return; |
} |
} |
#endif |
|
} |
} |
|
|
static void |
static void * |
fdt_setup_initrd(void) |
fdt_map_range(uint64_t start, uint64_t end, uint64_t *psize, |
|
const char *purpose) |
{ |
{ |
#ifdef MEMORY_DISK_DYNAMIC |
const paddr_t startpa = trunc_page(start); |
const uint64_t initrd_size = initrd_end - initrd_start; |
const paddr_t endpa = round_page(end); |
paddr_t startpa = trunc_page(initrd_start); |
|
paddr_t endpa = round_page(initrd_end); |
|
paddr_t pa; |
paddr_t pa; |
vaddr_t va; |
vaddr_t va; |
void *md_start; |
void *ptr; |
|
|
if (initrd_size == 0) |
*psize = end - start; |
return; |
if (*psize == 0) |
|
return NULL; |
|
|
|
const vaddr_t voff = start & PAGE_MASK; |
|
|
va = uvm_km_alloc(kernel_map, initrd_size, 0, |
va = uvm_km_alloc(kernel_map, *psize, 0, UVM_KMF_VAONLY|UVM_KMF_NOWAIT); |
UVM_KMF_VAONLY | UVM_KMF_NOWAIT); |
|
if (va == 0) { |
if (va == 0) { |
printf("Failed to allocate VA for initrd\n"); |
printf("Failed to allocate VA for %s\n", purpose); |
return; |
return NULL; |
} |
} |
|
ptr = (void *)(va + voff); |
md_start = (void *)va; |
|
|
|
for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) |
for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) |
pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0); |
pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0); |
pmap_update(pmap_kernel()); |
pmap_update(pmap_kernel()); |
|
|
|
return ptr; |
|
} |
|
|
|
static void |
|
fdt_unmap_range(void *ptr, uint64_t size) |
|
{ |
|
const char *start = ptr, *end = start + size; |
|
const vaddr_t startva = trunc_page((vaddr_t)(uintptr_t)start); |
|
const vaddr_t endva = round_page((vaddr_t)(uintptr_t)end); |
|
|
|
pmap_kremove(startva, endva - startva); |
|
pmap_update(pmap_kernel()); |
|
} |
|
|
|
static void |
|
fdt_probe_initrd(uint64_t *pstart, uint64_t *pend) |
|
{ |
|
*pstart = *pend = 0; |
|
|
|
#ifdef MEMORY_DISK_DYNAMIC |
|
fdt_probe_range("linux,initrd-start", "linux,initrd-end", pstart, pend); |
|
#endif |
|
} |
|
|
|
static void |
|
fdt_setup_initrd(void) |
|
{ |
|
#ifdef MEMORY_DISK_DYNAMIC |
|
void *md_start; |
|
uint64_t initrd_size; |
|
|
|
md_start = fdt_map_range(initrd_start, initrd_end, &initrd_size, |
|
"initrd"); |
|
if (md_start == NULL) |
|
return; |
md_root_setconf(md_start, initrd_size); |
md_root_setconf(md_start, initrd_size); |
#endif |
#endif |
} |
} |
|
|
|
static void |
|
fdt_probe_rndseed(uint64_t *pstart, uint64_t *pend) |
|
{ |
|
|
|
fdt_probe_range("netbsd,rndseed-start", "netbsd,rndseed-end", |
|
pstart, pend); |
|
} |
|
|
|
static void |
|
fdt_setup_rndseed(void) |
|
{ |
|
uint64_t rndseed_size; |
|
void *rndseed; |
|
|
|
rndseed = fdt_map_range(rndseed_start, rndseed_end, &rndseed_size, |
|
"rndseed"); |
|
if (rndseed == NULL) |
|
return; |
|
rnd_seed(rndseed, rndseed_size); |
|
fdt_unmap_range(rndseed, rndseed_size); |
|
} |
|
|
|
static void |
|
fdt_probe_efirng(uint64_t *pstart, uint64_t *pend) |
|
{ |
|
|
|
fdt_probe_range("netbsd,efirng-start", "netbsd,efirng-end", |
|
pstart, pend); |
|
} |
|
|
|
static struct krndsource efirng_source; |
|
|
|
static void |
|
fdt_setup_efirng(void) |
|
{ |
|
uint64_t efirng_size; |
|
void *efirng; |
|
|
|
efirng = fdt_map_range(efirng_start, efirng_end, &efirng_size, |
|
"efirng"); |
|
if (efirng == NULL) |
|
return; |
|
|
|
rnd_attach_source(&efirng_source, "efirng", RND_TYPE_RNG, |
|
RND_FLAG_DEFAULT); |
|
rnd_add_data(&efirng_source, efirng, efirng_size, 0); |
|
explicit_memset(efirng, 0, efirng_size); |
|
fdt_unmap_range(efirng, efirng_size); |
|
} |
|
|
#ifdef EFI_RUNTIME |
#ifdef EFI_RUNTIME |
static void |
static void |
fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type) |
fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type) |
Line 415 fdt_map_efi_runtime(const char *prop, en |
|
Line 509 fdt_map_efi_runtime(const char *prop, en |
|
} |
} |
#endif |
#endif |
|
|
u_int initarm(void *arg); |
vaddr_t |
|
|
u_int |
|
initarm(void *arg) |
initarm(void *arg) |
{ |
{ |
const struct arm_platform *plat; |
const struct arm_platform *plat; |
Line 435 initarm(void *arg) |
|
Line 527 initarm(void *arg) |
|
error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data)); |
error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data)); |
if (error != 0) |
if (error != 0) |
panic("fdt_move failed: %s", fdt_strerror(error)); |
panic("fdt_move failed: %s", fdt_strerror(error)); |
fdtbus_set_data(fdt_data); |
fdtbus_init(fdt_data); |
} else { |
} else { |
panic("fdt_check_header failed: %s", fdt_strerror(error)); |
panic("fdt_check_header failed: %s", fdt_strerror(error)); |
} |
} |
Line 519 initarm(void *arg) |
|
Line 611 initarm(void *arg) |
|
/* Parse ramdisk info */ |
/* Parse ramdisk info */ |
fdt_probe_initrd(&initrd_start, &initrd_end); |
fdt_probe_initrd(&initrd_start, &initrd_end); |
|
|
|
/* Parse our on-disk rndseed and the firmware's RNG from EFI */ |
|
fdt_probe_rndseed(&rndseed_start, &rndseed_end); |
|
fdt_probe_efirng(&efirng_start, &efirng_end); |
|
|
/* |
/* |
* Populate bootconfig structure for the benefit of |
* Populate bootconfig structure for the benefit of |
* dodumpsys |
* dodumpsys |
Line 542 initarm(void *arg) |
|
Line 638 initarm(void *arg) |
|
VPRINTF("Memory regions:\n"); |
VPRINTF("Memory regions:\n"); |
fdt_memory_foreach(fdt_add_boot_physmem, &memory_size); |
fdt_memory_foreach(fdt_add_boot_physmem, &memory_size); |
|
|
u_int sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, fdt_physmem, |
vaddr_t sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, fdt_physmem, |
nfdt_physmem); |
nfdt_physmem); |
|
|
|
/* |
|
* initarm_common flushes cache if required before AP start |
|
*/ |
error = 0; |
error = 0; |
if ((boothowto & RB_MD1) == 0) { |
if ((boothowto & RB_MD1) == 0) { |
VPRINTF("mpstart\n"); |
VPRINTF("mpstart\n"); |
Line 567 initarm(void *arg) |
|
Line 666 initarm(void *arg) |
|
const paddr_t spg = atop(spa); |
const paddr_t spg = atop(spa); |
const paddr_t epg = atop(epa); |
const paddr_t epg = atop(epa); |
|
|
|
VPRINTF(" start %08lx end %08lx... " |
|
"loading in freelist %d\n", spa, epa, VM_FREELIST_DEFAULT); |
|
|
uvm_page_physload(spg, epg, spg, epg, VM_FREELIST_DEFAULT); |
uvm_page_physload(spg, epg, spg, epg, VM_FREELIST_DEFAULT); |
|
|
VPRINTF(" start %08lx end %08lx", ptoa(spa), ptoa(epa)); |
|
} |
} |
|
|
return sp; |
return sp; |
|
|
} |
} |
|
|
void |
void |
|
cpu_startup_hook(void) |
|
{ |
|
|
|
fdtbus_intr_init(); |
|
|
|
fdt_setup_rndseed(); |
|
fdt_setup_efirng(); |
|
} |
|
|
|
void |
delay(u_int us) |
delay(u_int us) |
{ |
{ |
const struct arm_platform *plat = arm_fdt_platform(); |
const struct arm_platform *plat = arm_fdt_platform(); |