Changeset View
Changeset View
Standalone View
Standalone View
stand/kboot/main.c
Show All 29 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/boot.h> | #include <sys/boot.h> | ||||
#include <fdt_platform.h> | #include <fdt_platform.h> | ||||
#include <machine/cpufunc.h> | #include <machine/cpufunc.h> | ||||
#include <bootstrap.h> | #include <bootstrap.h> | ||||
#include "host_syscall.h" | #include "host_syscall.h" | ||||
#include "kboot.h" | #include "kboot.h" | ||||
#include "stand.h" | |||||
struct arch_switch archsw; | struct arch_switch archsw; | ||||
extern void *_end; | extern void *_end; | ||||
int kboot_getdev(void **vdev, const char *devspec, const char **path); | int kboot_getdev(void **vdev, const char *devspec, const char **path); | ||||
ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); | ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); | ||||
ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); | ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); | ||||
ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); | ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); | ||||
int kboot_autoload(void); | int kboot_autoload(void); | ||||
static void kboot_kseg_get(int *nseg, void **ptr); | static void kboot_kseg_get(int *nseg, void **ptr); | ||||
static void kboot_zfs_probe(void); | static void kboot_zfs_probe(void); | ||||
extern int command_fdt_internal(int argc, char *argv[]); | extern int command_fdt_internal(int argc, char *argv[]); | ||||
#define PA_INVAL (vm_offset_t)-1 | |||||
static vm_offset_t pa_start = PA_INVAL; | |||||
static vm_offset_t padding; | |||||
static vm_offset_t offset; | |||||
static uint64_t commit_limit; | static uint64_t commit_limit; | ||||
static uint64_t committed_as; | static uint64_t committed_as; | ||||
static uint64_t mem_avail; | static uint64_t mem_avail; | ||||
static void | static void | ||||
memory_limits(void) | memory_limits(void) | ||||
{ | { | ||||
int fd; | int fd; | ||||
Show All 30 Lines | |||||
/* | /* | ||||
* NB: getdev should likely be identical to this most places, except maybe | * NB: getdev should likely be identical to this most places, except maybe | ||||
* we should move to storing the length of the platform devdesc. | * we should move to storing the length of the platform devdesc. | ||||
*/ | */ | ||||
int | int | ||||
kboot_getdev(void **vdev, const char *devspec, const char **path) | kboot_getdev(void **vdev, const char *devspec, const char **path) | ||||
{ | { | ||||
int rv; | |||||
struct devdesc **dev = (struct devdesc **)vdev; | struct devdesc **dev = (struct devdesc **)vdev; | ||||
int rv; | |||||
/* | /* | ||||
* If it looks like this is just a path and no device, go with the | * If it looks like this is just a path and no device, go with the | ||||
* current device. | * current device. | ||||
*/ | */ | ||||
if (devspec == NULL || strchr(devspec, ':') == NULL) { | if (devspec == NULL || strchr(devspec, ':') == NULL) { | ||||
if (((rv = devparse(dev, getenv("currdev"), NULL)) == 0) && | if (((rv = devparse(dev, getenv("currdev"), NULL)) == 0) && | ||||
(path != NULL)) | (path != NULL)) | ||||
▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | if (tloc != NULL) | ||||
*tloc = rv; | *tloc = rv; | ||||
return (rv); | return (rv); | ||||
} | } | ||||
struct host_kexec_segment loaded_segments[HOST_KEXEC_SEGMENT_MAX]; | struct host_kexec_segment loaded_segments[HOST_KEXEC_SEGMENT_MAX]; | ||||
int nkexec_segments = 0; | int nkexec_segments = 0; | ||||
#define SEGALIGN (1ul<<20) | |||||
static ssize_t | static ssize_t | ||||
get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) | get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) | ||||
{ | { | ||||
int i = 0; | int i = 0; | ||||
const size_t segsize = 8*1024*1024; | const size_t segsize = 64*1024*1024; | ||||
if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX) | if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX) | ||||
panic("Tried to load too many kexec segments"); | panic("Tried to load too many kexec segments"); | ||||
for (i = 0; i < nkexec_segments; i++) { | for (i = 0; i < nkexec_segments; i++) { | ||||
if (dest >= (vm_offset_t)loaded_segments[i].mem && | if (dest >= (vm_offset_t)loaded_segments[i].mem && | ||||
dest < (vm_offset_t)loaded_segments[i].mem + | dest < (vm_offset_t)loaded_segments[i].mem + | ||||
loaded_segments[i].memsz) | loaded_segments[i].memsz) | ||||
goto out; | goto out; | ||||
} | } | ||||
loaded_segments[nkexec_segments].buf = host_getmem(segsize); | loaded_segments[nkexec_segments].buf = host_getmem(segsize); | ||||
andrew: Why not put them in `#ifdef DEBUG` or similar? | |||||
loaded_segments[nkexec_segments].bufsz = segsize; | loaded_segments[nkexec_segments].bufsz = segsize; | ||||
loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,segsize); | loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,SEGALIGN); | ||||
loaded_segments[nkexec_segments].memsz = segsize; | loaded_segments[nkexec_segments].memsz = segsize; | ||||
i = nkexec_segments; | i = nkexec_segments; | ||||
nkexec_segments++; | nkexec_segments++; | ||||
out: | out: | ||||
*buf = loaded_segments[i].buf + (dest - | *buf = loaded_segments[i].buf + (dest - | ||||
(vm_offset_t)loaded_segments[i].mem); | (vm_offset_t)loaded_segments[i].mem); | ||||
return (min(len,loaded_segments[i].bufsz - (dest - | return (min(len,loaded_segments[i].bufsz - (dest - | ||||
(vm_offset_t)loaded_segments[i].mem))); | (vm_offset_t)loaded_segments[i].mem))); | ||||
} | } | ||||
ssize_t | ssize_t | ||||
kboot_copyin(const void *src, vm_offset_t dest, const size_t len) | kboot_copyin(const void *src, vm_offset_t dest, const size_t len) | ||||
{ | { | ||||
ssize_t segsize, remainder; | ssize_t segsize, remainder; | ||||
void *destbuf; | void *destbuf; | ||||
if (pa_start == PA_INVAL) { | |||||
pa_start = kboot_get_phys_load_segment(); | |||||
// padding = 2 << 20; /* XXX amd64: revisit this when we make it work */ | |||||
padding = 0; | |||||
offset = dest; | |||||
get_phys_buffer(pa_start, len, &destbuf); | |||||
} | |||||
remainder = len; | remainder = len; | ||||
do { | do { | ||||
segsize = get_phys_buffer(dest, remainder, &destbuf); | segsize = get_phys_buffer(dest + pa_start + padding - offset, remainder, &destbuf); | ||||
bcopy(src, destbuf, segsize); | bcopy(src, destbuf, segsize); | ||||
remainder -= segsize; | remainder -= segsize; | ||||
src += segsize; | src += segsize; | ||||
dest += segsize; | dest += segsize; | ||||
} while (remainder > 0); | } while (remainder > 0); | ||||
return (len); | return (len); | ||||
} | } | ||||
ssize_t | ssize_t | ||||
kboot_copyout(vm_offset_t src, void *dest, const size_t len) | kboot_copyout(vm_offset_t src, void *dest, const size_t len) | ||||
{ | { | ||||
ssize_t segsize, remainder; | ssize_t segsize, remainder; | ||||
void *srcbuf; | void *srcbuf; | ||||
remainder = len; | remainder = len; | ||||
do { | do { | ||||
segsize = get_phys_buffer(src, remainder, &srcbuf); | segsize = get_phys_buffer(src + pa_start + padding - offset, remainder, &srcbuf); | ||||
bcopy(srcbuf, dest, segsize); | bcopy(srcbuf, dest, segsize); | ||||
remainder -= segsize; | remainder -= segsize; | ||||
src += segsize; | src += segsize; | ||||
dest += segsize; | dest += segsize; | ||||
} while (remainder > 0); | } while (remainder > 0); | ||||
return (len); | return (len); | ||||
} | } | ||||
Show All 36 Lines | |||||
{ | { | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
kboot_kseg_get(int *nseg, void **ptr) | kboot_kseg_get(int *nseg, void **ptr) | ||||
{ | { | ||||
#if 0 | |||||
int a; | int a; | ||||
printf("kseg_get: %d segments\n", nkexec_segments); | |||||
printf("VA SZ PA MEMSZ\n"); | |||||
printf("---------------- -------- ---------------- -----\n"); | |||||
for (a = 0; a < nkexec_segments; a++) { | for (a = 0; a < nkexec_segments; a++) { | ||||
printf("kseg_get: %jx %jx %jx %jx\n", | printf("%016jx %08jx %016jx %08jx\n", | ||||
(uintmax_t)loaded_segments[a].buf, | (uintmax_t)loaded_segments[a].buf, | ||||
(uintmax_t)loaded_segments[a].bufsz, | (uintmax_t)loaded_segments[a].bufsz, | ||||
(uintmax_t)loaded_segments[a].mem, | (uintmax_t)loaded_segments[a].mem, | ||||
(uintmax_t)loaded_segments[a].memsz); | (uintmax_t)loaded_segments[a].memsz); | ||||
} | } | ||||
#endif | |||||
*nseg = nkexec_segments; | *nseg = nkexec_segments; | ||||
*ptr = &loaded_segments[0]; | *ptr = &loaded_segments[0]; | ||||
} | } | ||||
static void | static void | ||||
kboot_zfs_probe(void) | kboot_zfs_probe(void) | ||||
{ | { | ||||
Show All 23 Lines |
Why not put them in #ifdef DEBUG or similar?