Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F96258591
D38308.id116348.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D38308.id116348.diff
View Options
diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile
--- a/stand/kboot/Makefile
+++ b/stand/kboot/Makefile
@@ -30,6 +30,7 @@
init.c \
kbootfdt.c \
main.c \
+ seg.c \
termios.c \
util.c \
vers.c
diff --git a/stand/kboot/kboot.h b/stand/kboot/kboot.h
--- a/stand/kboot/kboot.h
+++ b/stand/kboot/kboot.h
@@ -34,6 +34,14 @@
void hostdisk_zfs_probe(void);
bool hostdisk_zfs_find_default(void);
+/* seg.c */
+void init_avail(void);
+void need_avail(int n);
+void add_avail(uint64_t start, uint64_t end, uint64_t type);
+void remove_avail(uint64_t start, uint64_t end, uint64_t type);
+uint64_t first_avail(uint64_t align, uint64_t min_size, uint64_t type);
+void print_avail(void);
+
/* util.c */
bool file2str(const char *fn, char *buffer, size_t buflen);
bool file2u64(const char *fn, uint64_t *val);
diff --git a/stand/kboot/seg.c b/stand/kboot/seg.c
new file mode 100644
--- /dev/null
+++ b/stand/kboot/seg.c
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2023, Netflix, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "stand.h"
+#include "kboot.h"
+
+#include <sys/param.h>
+
+static struct memory_segments *segs;
+static int nr_seg = 0;
+static int segalloc = 0;
+
+void
+init_avail(void)
+{
+ if (segs)
+ free(segs);
+ nr_seg = 0;
+ segalloc = 16;
+ segs = malloc(sizeof(*segs) * segalloc);
+ if (segs == NULL)
+ panic("not enough memory to get memory map\n");
+}
+
+/*
+ * Make sure at least n items can be accessed in the segs array. Note the
+ * realloc here will invalidate cached pointers (potentially), so addresses
+ * into the segs array must be recomputed after this call.
+ */
+void
+need_avail(int n)
+{
+ if (n <= segalloc)
+ return;
+
+ while (n > segalloc)
+ segalloc *= 2;
+ segs = realloc(segs, segalloc * sizeof(*segs));
+ if (segs == NULL)
+ panic("not enough memory to get memory map\n");
+}
+
+/*
+ * Always called for a new range, so always just append a range,
+ * unless it's continuous with the prior range.
+ */
+void
+add_avail(uint64_t start, uint64_t end, uint64_t type)
+{
+ /*
+ * This range is contiguous with the previous range, and is
+ * the same type: we can collapse the two.
+ */
+ if (nr_seg >= 1 &&
+ segs[nr_seg - 1].end + 1 == start &&
+ segs[nr_seg - 1].type == type) {
+ segs[nr_seg - 1].end = end;
+ return;
+ }
+
+ /*
+ * Otherwise we need to add a new range at the end, but don't need to
+ * adjust the current end.
+ */
+ need_avail(nr_seg + 1);
+ segs[nr_seg].start = start;
+ segs[nr_seg].end = end;
+ segs[nr_seg].type = type;
+ nr_seg++;
+}
+
+/*
+ * All or part of a prior entry needs to be modified. Given the structure of the
+ * code, we know that it will always be modifying the last time and/or extending
+ * the one before it if its contiguous.
+ */
+void
+remove_avail(uint64_t start, uint64_t end, uint64_t type)
+{
+ struct memory_segments *s;
+
+ /*
+ * simple case: we are extending a previously removed item.
+ */
+ if (nr_seg >= 2) {
+ s = &segs[nr_seg - 2];
+ if (s->end + 1 == start &&
+ s->type == type) {
+ s->end = end;
+ /* Now adjust the ending element */
+ s++;
+ if (s->end == end) {
+ /* we've used up the 'free' space */
+ nr_seg--;
+ return;
+ }
+ /* Otherwise adjust the 'free' space */
+ s->start = end + 1;
+ return;
+ }
+ }
+
+ /*
+ * OK, we have four cases:
+ * (1) The new chunk is at the start of the free space, but didn't catch the above
+ * folding for whatever reason (different type, start of space). In this case,
+ * we allocate 1 additional item. The current end is copied to the new end. The
+ * current end is set to <start, end, type> and the new end's start is set to end + 1.
+ * (2) The new chunk is in the middle of the free space. In this case we allocate 2
+ * additional items. We copy the current end to the new end, set the new end's start
+ * to end + 1, the old end's end to start - 1 and the new item is <start, end, type>
+ * (3) The new chunk is at the end of the current end. In this case we allocate 1 more
+ * and adjust the current end's end to start - 1 and set the new end to <start, end, type>.
+ * (4) The new chunk is exactly the current end, except for type. In this case, we just adjust
+ * the type.
+ * We can assume we always have at least one chunk since that's created with new_avail() above
+ * necessarily before we are called to subset it.
+ */
+ s = &segs[nr_seg - 1];
+ if (s->start == start) {
+ if (s->end == end) { /* (4) */
+ s->type = type;
+ return;
+ }
+ /* chunk at start of old chunk -> (1) */
+ need_avail(nr_seg + 1);
+ s = &segs[nr_seg - 1]; /* Realloc may change pointers */
+ s[1] = s[0];
+ s->start = start;
+ s->end = end;
+ s->type = type;
+ s[1].start = end + 1;
+ nr_seg++;
+ return;
+ }
+ if (s->end == end) { /* At end of old chunk (3) */
+ need_avail(nr_seg + 1);
+ s = &segs[nr_seg - 1]; /* Realloc may change pointers */
+ s[1] = s[0];
+ s->end = start - 1;
+ s[1].start = start;
+ s[1].type = type;
+ nr_seg++;
+ return;
+ }
+ /* In the middle, need to split things up (2) */
+ need_avail(nr_seg + 2);
+ s = &segs[nr_seg - 1]; /* Realloc may change pointers */
+ s[2] = s[1] = s[0];
+ s->end = start - 1;
+ s[1].start = start;
+ s[1].end = end;
+ s[1].type = type;
+ s[2].start = end + 1;
+ nr_seg += 2;
+}
+
+void
+print_avail(void)
+{
+ printf("Found %d RAM segments:\n", nr_seg);
+
+ for (int i = 0; i < nr_seg; i++) {
+ printf("%#jx-%#jx type %lu\n",
+ (uintmax_t)segs[i].start,
+ (uintmax_t)segs[i].end,
+ (u_long)segs[i].type);
+ }
+}
+
+uint64_t
+first_avail(uint64_t align, uint64_t min_size, uint64_t memtype)
+{
+ uint64_t s, len;
+
+ for (int i = 0; i < nr_seg; i++) {
+ if (segs[i].type != memtype) /* Not candidate */
+ continue;
+ s = roundup(segs[i].start, align);
+ if (s >= segs[i].end) /* roundup past end */
+ continue;
+ len = segs[i].end - s + 1;
+ if (len >= min_size) {
+ printf("Found a big enough hole at in seg %d at %#jx (%#jx-%#jx)\n",
+ i,
+ (uintmax_t)s,
+ (uintmax_t)segs[i].start,
+ (uintmax_t)segs[i].end);
+ return (s);
+ }
+ }
+
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Sep 25, 6:01 AM (5 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
12738613
Default Alt Text
D38308.id116348.diff (6 KB)
Attached To
Mode
D38308: kboot: Create segment handling code at main level
Attached
Detach File
Event Timeline
Log In to Comment