diff options
author | Keegan Saunders <keegan@undefinedbehaviour.org> | 2024-01-07 19:57:50 +0000 |
---|---|---|
committer | Keegan Saunders <keegan@undefinedbehaviour.org> | 2024-01-07 19:57:50 +0000 |
commit | 1fe150f1ed46a8c1a65187b3088274e067493639 (patch) | |
tree | 6e4879117e763e10f9c97b5f7d844ac7e4bb4639 | |
parent | 23f34184d60b393579a4de20f03da7befc6ceafc (diff) |
arm64/qemu: detect VM configuration
Now, *maxmem and *ncpu are not required to be provided.
They will be detected automatically from the QEMU device
tree. Further, >4GB memory configurations are also supported.
The maximum number of CPUs is 16 for now, and the maximum
supported memory is 16GB
-rw-r--r-- | sys/src/9/arm64/bootargs.c | 249 | ||||
-rw-r--r-- | sys/src/9/arm64/fns.h | 3 | ||||
-rw-r--r-- | sys/src/9/arm64/main.c | 114 | ||||
-rw-r--r-- | sys/src/9/arm64/mem.c | 11 | ||||
-rw-r--r-- | sys/src/9/arm64/mem.h | 8 | ||||
-rw-r--r-- | sys/src/9/arm64/mkfile | 1 |
6 files changed, 266 insertions, 120 deletions
diff --git a/sys/src/9/arm64/bootargs.c b/sys/src/9/arm64/bootargs.c new file mode 100644 index 000000000..d33df7162 --- /dev/null +++ b/sys/src/9/arm64/bootargs.c @@ -0,0 +1,249 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#define MAXCONF 64 +static char *confname[MAXCONF]; +static char *confval[MAXCONF]; +static int nconf; +static char maxmem[256]; +static int cpus; +static char ncpu[256]; + +static int +findconf(char *k) +{ + int i; + + for(i = 0; i < nconf; i++) + if(cistrcmp(confname[i], k) == 0) + return i; + return -1; +} + +static void +addconf(char *k, char *v) +{ + int i; + + i = findconf(k); + if(i < 0){ + if(nconf >= MAXCONF) + return; + i = nconf++; + confname[i] = k; + } + confval[i] = v; +} + +static void +plan9iniinit(char *s, int cmdline) +{ + char *toks[MAXCONF]; + int i, c, n; + char *v; + + if((c = *s) < ' ' || c >= 0x80) + return; + if(cmdline) + n = tokenize(s, toks, MAXCONF); + else + n = getfields(s, toks, MAXCONF, 1, "\n"); + for(i = 0; i < n; i++){ + if(toks[i][0] == '#') + continue; + v = strchr(toks[i], '='); + if(v == nil) + continue; + *v++ = '\0'; + addconf(toks[i], v); + } +} + +typedef struct Devtree Devtree; +struct Devtree +{ + uchar *base; + uchar *end; + char *stab; + char path[1024]; +}; + +enum { + DtHeader = 0xd00dfeed, + DtBeginNode = 1, + DtEndNode = 2, + DtProp = 3, + DtEnd = 9, +}; + +static u32int +beget4(uchar *p) +{ + return (u32int)p[0]<<24 | (u32int)p[1]<<16 | (u32int)p[2]<<8 | (u32int)p[3]; +} + +static void +devtreeprop(char *path, char *key, void *val, int len) +{ + uvlong addr; + uchar *p = val; + + if((strncmp(path, "/memory", 7) == 0 || strncmp(path, "/memory@0", 9) == 0) + && strcmp(key, "reg") == 0){ + if(findconf("*maxmem") < 0 && len == 16){ + p += 4; /* ignore */ + addr = (uvlong)beget4(p+4)<<32 | beget4(p); + addr += beget4(p+8); + snprint(maxmem, sizeof(maxmem), "%#llux", addr); + addconf("*maxmem", maxmem); + } + return; + } + if(strncmp(path, "/cpus/cpu", 9) == 0 && strcmp(key, "reg") == 0){ + cpus++; + return; + } + if(strncmp(path, "/chosen", 7) == 0 && strcmp(key, "bootargs") == 0){ + if(len > BOOTARGSLEN) + len = BOOTARGSLEN; + memmove(BOOTARGS, val, len); + plan9iniinit(BOOTARGS, 1); + return; + } +} + +static uchar* +devtreenode(Devtree *t, uchar *p, char *cp) +{ + uchar *e = (uchar*)t->stab; + char *s; + int n; + + if(p+4 > e || beget4(p) != DtBeginNode) + return nil; + p += 4; + if((s = memchr((char*)p, 0, e - p)) == nil) + return nil; + n = s - (char*)p; + cp += n; + if(cp >= &t->path[sizeof(t->path)]) + return nil; + memmove(cp - n, (char*)p, n); + *cp = 0; + p += (n + 4) & ~3; + while(p+12 <= e && beget4(p) == DtProp){ + n = beget4(p+4); + if(p + 12 + n > e) + return nil; + s = t->stab + beget4(p+8); + if(s < t->stab || s >= (char*)t->end + || memchr(s, 0, (char*)t->end - s) == nil) + return nil; + devtreeprop(t->path, s, p+12, n); + p += 12 + ((n + 3) & ~3); + } + while(p+4 <= e && beget4(p) == DtBeginNode){ + *cp = '/'; + p = devtreenode(t, p, cp+1); + if(p == nil) + return nil; + } + if(p+4 > e || beget4(p) != DtEndNode) + return nil; + return p+4; +} + +static int +parsedevtree(uchar *base, uintptr len) +{ + Devtree t[1]; + u32int total; + + if(len < 28 || beget4(base) != DtHeader) + return -1; + total = beget4(base+4); + if(total < 28 || total > len) + return -1; + t->base = base; + t->end = t->base + total; + t->stab = (char*)base + beget4(base+12); + if(t->stab >= (char*)t->end) + return -1; + devtreenode(t, base + beget4(base+8), t->path); + return 0; +} + +void +bootargsinit(void) +{ + void *va = KADDR(DTBADDR); + uintptr len = cankaddr(DTBADDR); + + plan9iniinit(BOOTARGS, 0); + if(parsedevtree(va, len) == 0){ + /* user can provide fewer ncpu */ + if(findconf("*ncpu") < 0){ + snprint(ncpu, sizeof(ncpu), "%d", cpus); + addconf("*ncpu", ncpu); + } + } +} + +char* +getconf(char *name) +{ + int i; + + if((i = findconf(name)) < 0) + return nil; + return confval[i]; +} + +void +setconfenv(void) +{ + int i; + + if(nconf < 0){ + /* use defaults when there was no configuration */ + ksetenv("console", "0", 1); + return; + } + + for(i = 0; i < nconf; i++){ + if(confname[i][0] != '*') + ksetenv(confname[i], confval[i], 0); + ksetenv(confname[i], confval[i], 1); + } +} + +void +writeconf(void) +{ + char *p, *q; + int n; + + p = getconfenv(); + if(waserror()) { + free(p); + nexterror(); + } + + /* convert to name=value\n format */ + for(q=p; *q; q++) { + q += strlen(q); + *q = '='; + q += strlen(q); + *q = '\n'; + } + n = q - p + 1; + if(n >= BOOTARGSLEN) + error("kernel configuration too large"); + memmove(BOOTARGS, p, n); + memset(BOOTARGS+n, 0, BOOTARGSLEN-n); + poperror(); + free(p); +} diff --git a/sys/src/9/arm64/fns.h b/sys/src/9/arm64/fns.h index 8ad535672..95d398767 100644 --- a/sys/src/9/arm64/fns.h +++ b/sys/src/9/arm64/fns.h @@ -168,3 +168,6 @@ extern int pcicfgrw16(int tbdf, int rno, int data, int read); extern int pcicfgrw32(int tbdf, int rno, int data, int read); extern void pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a); extern void pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a); + +/* bootargs */ +extern void bootargsinit(void); diff --git a/sys/src/9/arm64/main.c b/sys/src/9/arm64/main.c index 30397c935..092327860 100644 --- a/sys/src/9/arm64/main.c +++ b/sys/src/9/arm64/main.c @@ -14,120 +14,6 @@ Conf conf; -#define MAXCONF 64 -static char *confname[MAXCONF]; -static char *confval[MAXCONF]; -static int nconf = -1; - -void -bootargsinit(void) -{ - int i, j, n; - char *cp, *line[MAXCONF], *p, *q; - - /* - * parse configuration args from dos file plan9.ini - */ - cp = BOOTARGS; - cp[BOOTARGSLEN-1] = 0; - - /* - * Strip out '\r', change '\t' -> ' '. - */ - p = cp; - for(q = cp; *q; q++){ - if(*q == -1) - break; - if(*q == '\r') - continue; - if(*q == '\t') - *q = ' '; - *p++ = *q; - } - *p = 0; - - n = getfields(cp, line, MAXCONF, 1, "\n"); - if(n <= 0){ - /* empty plan9.ini, no configuration passed */ - return; - } - - nconf = 0; - for(i = 0; i < n; i++){ - if(*line[i] == '#') - continue; - cp = strchr(line[i], '='); - if(cp == nil) - continue; - *cp++ = '\0'; - for(j = 0; j < nconf; j++){ - if(cistrcmp(confname[j], line[i]) == 0) - break; - } - confname[j] = line[i]; - confval[j] = cp; - if(j == nconf) - nconf++; - } -} - -char* -getconf(char *name) -{ - int i; - - for(i = 0; i < nconf; i++) - if(cistrcmp(confname[i], name) == 0) - return confval[i]; - return nil; -} - -void -setconfenv(void) -{ - int i; - - if(nconf < 0){ - /* use defaults when there was no configuration */ - ksetenv("console", "0", 1); - return; - } - - for(i = 0; i < nconf; i++){ - if(confname[i][0] != '*') - ksetenv(confname[i], confval[i], 0); - ksetenv(confname[i], confval[i], 1); - } -} - -void -writeconf(void) -{ - char *p, *q; - int n; - - p = getconfenv(); - if(waserror()) { - free(p); - nexterror(); - } - - /* convert to name=value\n format */ - for(q=p; *q; q++) { - q += strlen(q); - *q = '='; - q += strlen(q); - *q = '\n'; - } - n = q - p + 1; - if(n >= BOOTARGSLEN) - error("kernel configuration too large"); - memmove(BOOTARGS, p, n); - memset(BOOTARGS+n, 0, BOOTARGSLEN-n); - poperror(); - free(p); -} - int isaconfig(char *, int, ISAConf *) { diff --git a/sys/src/9/arm64/mem.c b/sys/src/9/arm64/mem.c index 2af0fd743..b25160a8e 100644 --- a/sys/src/9/arm64/mem.c +++ b/sys/src/9/arm64/mem.c @@ -67,13 +67,16 @@ void meminit(void) { char *p; + uintptr l = GiB + 128 * MiB; - conf.mem[0].base = PGROUND((uintptr)end - KZERO); - conf.mem[0].limit = GiB + 128 * MiB; if(p = getconf("*maxmem")) - conf.mem[0].limit = strtoull(p, 0, 0); + l = strtoull(p, 0, 0); + conf.mem[0].base = PGROUND((uintptr)end - KZERO); + conf.mem[0].limit = l; - kmapram(conf.mem[0].base, conf.mem[0].limit); + if(l > KLIMIT) + l = KLIMIT; + kmapram(conf.mem[0].base, l); conf.mem[0].npage = (conf.mem[0].limit - conf.mem[0].base)/BY2PG; } diff --git a/sys/src/9/arm64/mem.h b/sys/src/9/arm64/mem.h index 627e3603a..827af4e91 100644 --- a/sys/src/9/arm64/mem.h +++ b/sys/src/9/arm64/mem.h @@ -18,7 +18,7 @@ #define PGROUND(s) ROUND(s, BY2PG) /* effective virtual address space */ -#define EVASHIFT 34 +#define EVASHIFT 36 #define EVAMASK ((1ULL<<EVASHIFT)-1) #define PTSHIFT (PGSHIFT-3) @@ -32,13 +32,15 @@ #define L1TABLE(v, l) (L1TABLES - ((PTLX(v, 2) % L1TABLES) >> (((l)-1)*PTSHIFT)) + (l)-1) #define L1TOPSIZE (1ULL << (EVASHIFT - PTLEVELS*PTSHIFT)) -#define MAXMACH 24 /* max # cpus system can run */ +#define MAXMACH 16 /* max # cpus system can run */ #define MACHSIZE (8*KiB) #define KSTACK (8*KiB) #define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ #define TRAPFRAMESIZE (38*8) +#define DTBADDR 0x40000000 + #define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */ #define KTZERO (VDRAM + 0x100000) /* 0x40100000 - kernel text start */ @@ -54,6 +56,8 @@ #define KMAPEND (0xFFFFFFFF00000000ULL) /* 0x140000000 */ #define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ +#define KLIMIT (VDRAM - KZERO + KMAPEND - KMAP) /* 0x140000000 */ + #define KSEG0 (0xFFFFFFFE00000000ULL) /* temporary identity map for TTBR0 (using only top-level) */ diff --git a/sys/src/9/arm64/mkfile b/sys/src/9/arm64/mkfile index cbe7a1473..7dbe84858 100644 --- a/sys/src/9/arm64/mkfile +++ b/sys/src/9/arm64/mkfile @@ -51,6 +51,7 @@ OBJ=\ sysreg.$O\ random.$O\ trap.$O\ + bootargs.$O\ $CONF.root.$O\ $CONF.rootc.$O\ $DEVS\ |