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?