static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info) { ofdn_t n; static const char path[] = "/xen"; static const char console[] = "/xen/console"; n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); if (n > 0) { char xen[256]; int xl; u64 val[2]; s32 dom_id; dom_id = d->domain_id; ofd_prop_add(m, n, "reg", &dom_id, sizeof (dom_id)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); xl = snprintf(xen, sizeof (xen), "Xen-%d.%d%s", xen_major_version(), xen_minor_version(), xen_extra_version()); ASSERT(xl < sizeof (xen)); ofd_prop_add(m, n, "version", xen, xl + 1); /* convert xen pointer to guest physical */ val[0] = shared_info; val[1] = PAGE_SIZE; ofd_prop_add(m, n, "shared-info", val, sizeof (val)); /* reserve PAGE_SIZE @ addr shared info */ ofd_prop_add(m, n, "reserved", val, sizeof (val)); /* flags |= SIF_PROVILEDGED; */ ofd_prop_add(m, n, "privileged", NULL, 0); /* flags |= SIF_INITDOMAIN; */ ofd_prop_add(m, n, "initdomain", NULL, 0); /* tell dom0 that Xen depends on it to have power control */ if (!rtas_entry) ofd_prop_add(m, n, "power-control", NULL, 0); /* tell dom0 where granted pages go in the linear map */ val[0] = cpu_foreign_map_order(); val[1] = d->arch.foreign_mfn_count; ofd_prop_add(m, n, "foreign-map", val, sizeof (val)); n = ofd_node_add(m, n, console, sizeof (console)); if (n > 0) { val[0] = 0; ofd_prop_add(m, n, "interrupts", &val[0], sizeof (val[0])); } } return n; }
static ofdn_t ofd_vdevice_vty(void *m, ofdn_t p, struct domain *d) { ofdn_t n; static const char pathfmt[] = "/vdevice/vty@%x"; static const char name[] = "vty"; static const char compatible[] = "hvterm1"; static const char device_type[] = "serial"; char path[sizeof (pathfmt) + 8 - 2]; int client = 0; snprintf(path, sizeof (path), pathfmt, client); n = ofd_node_add(m, p, path, sizeof (path)); if (n > 0) { u32 val32; val32 = client; ofd_prop_add(m, n, "name", name, sizeof (name)); ofd_prop_add(m, n, "reg", &val32, sizeof (val32)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", device_type, sizeof (device_type)); } return n; }
static ofdn_t ofd_vdevice(void *m, struct domain *d) { ofdn_t n; static const char path[] = "/vdevice"; static const char name[] = "vdevice"; static const char compatible[] = "IBM,vdevice"; u32 val; n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); if (n > 0) { ofd_prop_add(m, n, "name", name, sizeof (name)); val = 1; ofd_prop_add(m, n, "#address-cells", &val, sizeof (val)); val = 0; ofd_prop_add(m, n, "#size-cells", &val, sizeof (val)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", name, sizeof (name)); ofd_prop_add(m, n, "interupt-controller", NULL, 0); #ifdef PAPR_VDEVICE ofdn_t r; /* add vty */ r = ofd_vdevice_vty(m, n, d); printk("vdevice r: %x\n", r); n = r; #endif } return n; }
static ofdn_t ofd_vdevice_vty(void *m, ofdn_t p, struct partition_status *ps) { ofdn_t n; static const char pathfmt[] = "/vdevice/vty@%lx"; static const char name[] = "vty"; static const char compatible[] = "hvterm1"; static const char device_type[] = "serial"; char path[sizeof (pathfmt) + 8 - 2]; uval server; uval client; vterm_create(ps, &server, &client); snprintf(path, sizeof (path), pathfmt, client); n = ofd_node_add(m, p, path, sizeof (path)); if (n > 0) { uval32 val32; val32 = client; ofd_prop_add(m, n, "name", name, sizeof (name)); ofd_prop_add(m, n, "reg", &val32, sizeof (val32)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", device_type, sizeof (device_type)); } if (server == 0 && ps->lpid == iohost_lpid) { ofd_vdevice_vty_server(m, p, 64); } return n; }
static ofdn_t ofd_vdevice_llan(void *m, ofdn_t p, uval lpid) { ofdn_t n; static const char pathfmt[] = "/vdevice/l-lan@%lx"; static const char name[] = "l-lan"; static const char compatible[] = "IBM,l-lan"; static const char device_type[] = "network"; char path[sizeof (pathfmt) + 8 - 2]; uval32 val; uval64 mac = 0x02ULL << 40; /* local address tag */ uval32 intr[2] = { /* source */ 0x0, /* +edge */ 0x0 }; uval32 dma_sz = 8 * 1024 * 1024; /* (((0x80<< 12) >> 3) << 12) */ uval32 dma[5] = { /* liobn */ 0x0, /* phys */ 0x0, 0x0, /* size */ 0x0, 0x0 }; uval liobn; dma_sz = llan_create(dma_sz, lpid, &liobn); dma[0] = liobn; dma[4] = dma_sz; intr[0] = liobn; mac |= liobn; snprintf(path, sizeof (path), pathfmt, liobn); n = ofd_node_add(m, p, path, sizeof (path)); if (n > 0) { ofd_prop_add(m, n, "name", name, sizeof (name)); val = liobn; ofd_prop_add(m, n, "reg", &val, sizeof (val)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", device_type, sizeof (device_type)); val = 2; ofd_prop_add(m, n, "ibm,#dma-address-cells", &val, sizeof (val)); ofd_prop_add(m, n, "ibm,#dma-size-cells", &val, sizeof (val)); val = 255; ofd_prop_add(m, n, "ibm,mac-address-filters", &val, sizeof (val)); ofd_prop_add(m, n, "ibm,vserver", NULL, 0); ofd_prop_add(m, n, "local-mac-address", &mac, sizeof (mac)); ofd_prop_add(m, n, "mac-address", &mac, sizeof (mac)); ofd_prop_add(m, n, "ibm,my-dma-window", dma, sizeof (dma)); ofd_prop_add(m, n, "interrupts", intr, sizeof (intr)); } return n; }
static ofdn_t ofd_cpus_props(void *m, struct domain *d) { static const char path[] = "/cpus"; static const char cpu[] = "cpu"; u32 val = 1; ofdn_t n; ofdn_t c; static u32 ibm_pft_size[] = { 0x0, 0x0 }; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "#address-cells", &val, sizeof(val)); ofd_prop_add(m, n, "#size-cells", &val, sizeof(val)); ofd_prop_add(m, n, "smp-enabled", NULL, 0); #ifdef HV_EXPOSE_PERFORMANCE_MONITOR ofd_prop_add(m, n, "performance-monitor", NULL, 0); #endif c = ofd_node_find_by_prop(m, n, "device_type", cpu, sizeof (cpu)); if (ofd_boot_cpu == -1) ofd_boot_cpu = c; while (c > 0) { /* We do not use the OF tree to identify secondary processors * so we must prune them from the tree */ if (c == ofd_boot_cpu) { ofdn_t p; ibm_pft_size[1] = d->arch.htab.log_num_ptes + LOG_PTE_SIZE; ofd_prop_add(m, c, "ibm,pft-size", ibm_pft_size, sizeof (ibm_pft_size)); /* get rid of non-standard properties */ p = ofd_prop_find(m, c, "cpu#"); if (p > 0) { ofd_prop_remove(m, c, p); } /* FIXME: Check the the "l2-cache" property who's * contents is an orphaned phandle? */ } else ofd_node_prune(m, c); c = ofd_node_find_next(m, c); } return n; }
static ofdn_t ofd_aliases_props(void *m) { static const char path[] = "/aliases"; static const char screen[] = "/vdevice/vty@0"; ofdn_t n; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "screen", screen, sizeof(screen)); return n; }
static ofdn_t ofd_options_props(void *m) { static const char path[] = "/options"; static const char boot[] = "true"; ofdn_t n; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "auto-boot?", boot, sizeof(boot)); return n; }
static ofdn_t ofd_chosen_props(void *m) { ofdn_t n; ofdn_t p; static const char path[] = "/chosen"; static const char console[] = " console=hvc0 nosmp"; char b[257]; uval sz = 0; // " root=/dev/hda " // " rootfstype=ramfs " // "init=/bin/sh " // "root=/dev/nfsroot " // "nfsroot=9.2.208.21:/,rsize=1024,wsize=1024 " // "ether=0,0,eth0 " //nfsaddrs=<wst-IP> :<srv-IP> :<gw-IP> :<netm-IP> :<hostname> //"nfsaddrs=9.2.208.161:9.2.208.21:9.2.208.2:255.255.248.0:freakazoid " //"nfsaddrs=9.2.208.161:9.2.208.21:9.2.208.2:255.255.248.0:freakazoid:eth0 " n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } sz = strlen(default_bootargs); memcpy(b, default_bootargs, sz); assert(sz + sizeof(console) <= 256, "boot args not big enough\n"); memcpy(b + sz, console, sizeof (console)); sz += sizeof (console); ofd_prop_add(m, n, "bootargs", b, sz); ofd_prop_add(m, n, "bootpath", NULL, 0); hputs("Remove /chosen/mmu, stub will replace\n"); p = ofd_prop_find(m, n, "mmu"); if (p > 0) { ofd_prop_remove(m, n, p); } return n; }
ofdn_t ofd_xics_props(void *m) { ofdn_t n; static const char path[] = "/interrupt-controller"; static const char compat[] = "IBM,ppc-xicp"; static const char model[] = "IBM, BoaC, PowerPC-PIC, 00"; static const char dtype[] = "PowerPC-External-Interrupt-Presentation"; /* * I don't think these are used for anything but linux wants * it. I seems to describe some per processor location for * IPIs but that is a complete guess. */ static const uval32 reg[] = { 0x000003e0, 0x0f000000, 0x00000000, 0x00001000, 0x000003e0, 0x0f001000, 0x00000000, 0x00001000, 0x000003e0, 0x0f002000, 0x00000000, 0x00001000, 0x000003e0, 0x0f003000, 0x00000000, 0x00001000, 0x000003e0, 0x0f004000, 0x00000000, 0x00001000, 0x000003e0, 0x0f005000, 0x00000000, 0x00001000, 0x000003e0, 0x0f006000, 0x00000000, 0x00001000, 0x000003e0, 0x0f007000, 0x00000000, 0x00001000, 0x000003e0, 0x0f008000, 0x00000000, 0x00001000, 0x000003e0, 0x0f009000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00a000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00b000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00c000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00d000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00e000, 0x00000000, 0x00001000, 0x000003e0, 0x0f00f000, 0x00000000, 0x00001000, }; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "built-in", NULL, 0); ofd_prop_add(m, n, "compatible", compat, sizeof(compat)); ofd_prop_add(m, n, "device_type", dtype, sizeof(dtype)); ofd_prop_add(m, n, "model", model, sizeof(model)); ofd_prop_add(m, n, "reg", reg, sizeof(reg)); return n; }
static ofdn_t ofd_chosen_props(void *m, const char *cmdline) { ofdn_t n; ofdn_t p; static const char path[] = "/chosen"; char bootargs[256] = { 0, }; int bsz; int sz; int rm; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } if (cmdline) strlcpy(bootargs, cmdline, sizeof(bootargs)); bsz = strlen(bootargs) + 1; rm = sizeof (bootargs) - bsz; if (default_bootargs != NULL) { sz = strlen(default_bootargs); if (sz > rm) { panic("default_bootargs is too big: 0x%x > 0x%x\n", sz, rm); } else if (sz > 0) { memcpy(&bootargs[bsz - 1], default_bootargs, sz + 1); bsz += sz; rm -= sz; } } printk("DOM0 bootargs: %s\n", bootargs); ofd_prop_add(m, n, "bootargs", bootargs, bsz); ofd_prop_add(m, n, "bootpath", NULL, 0); printk("Remove /chosen/mmu, stub will replace\n"); p = ofd_prop_find(m, n, "mmu"); if (p > 0) { ofd_prop_remove(m, n, p); } return n; }
static ofdn_t ofd_vdevice_vty_server(void *m, ofdn_t p, uval num) { ofdn_t n = 0; static const char pathfmt[] = "/vdevice/vty-server@%x"; static const char name[] = "vty-server"; static const char compatible[] = "hvterm2"; static const char device_type[] = "serial-server"; char path[sizeof (pathfmt) + 8 - 1]; uval i; uval server; for (i = 0; i < num; i++) { server = vterm_create_server(); assert(server > 0, "failed to create server\n"); if (server > 0) { uval32 val; val = server; snprintf(path, sizeof (path), pathfmt, val); n = ofd_node_add(m, p, path, sizeof (path)); assert(n > 0, "failed to create node\n"); if (n > 0) { uval32 intr[2] = { /* source */ 0x0, /* +edge */ 0x0 }; ofd_prop_add(m, n, "ibm,vserver", NULL, 0); ofd_prop_add(m, n, "name", name, sizeof (name)); ofd_prop_add(m, n, "reg", &val, sizeof (val)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", device_type, sizeof (device_type)); intr[0] = server; ofd_prop_add(m, n, "interrupts", intr, sizeof (intr)); } } } return n; }
static ofdn_t ofd_aliases_props(void *m) { static const char path[] = "/aliases"; static const char vty[] = "/vdevice/vty@0"; static const char net[] = "/vdevice/l-lan@1"; ofdn_t n; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "screen", vty, sizeof(vty)); ofd_prop_add(m, n, "net", net, sizeof(net)); ofd_prop_add(m, n, "network", net, sizeof(net)); return n; }
static ofdn_t ofd_openprom_props(void *m) { static const char path[] = "/openprom"; static const char vernum[] = "IBM,XenOF0.1"; ofdn_t n; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } /* I want to override */ ofd_prop_add(m, n, "model", vernum, sizeof(vernum)); ofd_prop_add(m, n, "ibm,fw-vernum_encoded", vernum, sizeof(vernum)); ofd_prop_add(m, n, "relative-addressing", NULL, 0); return n; }
static ofdn_t ofd_vdevice(void *m, struct partition_status *ps) { ofdn_t n; static const char path[] = "/vdevice"; static const char name[] = "vdevice"; static const char compatible[] = "IBM,vdevice"; uval32 val; n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); if (n > 0) { ofdn_t r; ofd_prop_add(m, n, "name", name, sizeof (name)); val = 1; ofd_prop_add(m, n, "#address-cells", &val, sizeof (val)); val = 0; ofd_prop_add(m, n, "#size-cells", &val, sizeof (val)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "device_type", name, sizeof (name)); ofd_prop_add(m, n, "interupt-controller", NULL, 0); /* add vty */ r = ofd_vdevice_vty(m, n, ps); hprintf("vdevice r: %x\n",r ); if (r > 0) { r = ofd_vdevice_llan(m, n, ps->lpid); } if (r > 0) { hprintf("VSCSI: lpid: 0x%lx iohost: 0x%lx\n", ps->lpid, iohost_lpid); if (ps->lpid == iohost_lpid) { r = ofd_vdevice_vscsi_server(m, n, ps->lpid, 10); } } n = r; } return n; }
static ofdn_t ofd_memory_props(void *m, uval mem_size) { ofdn_t n = 0; char fmt[] = "/memory@%lx"; char name[] = "memory"; uval32 v; uval start = 0; ofdn_t old; /* Remove all old memory props */ do { old = ofd_node_find_by_prop(m, OFD_ROOT, "device_type", name, sizeof(name)); if (old <= 0) break; ofd_node_prune(m, old); } while (1); while (start < mem_size) { /* FIXME: these two properties need to be set during parition * contruction */ struct reg { uval64 addr; uval64 sz; }; char path[64]; uval l = snprintf(path, 64, fmt, start); n = ofd_node_add(m, OFD_ROOT, path, l+1); ofd_prop_add(m, n, "name", name, sizeof (name)); v = 1; ofd_prop_add(m, n, "#address-cells", &v, sizeof (v)); v = 0; ofd_prop_add(m, n, "#size-cells", &v, sizeof (v)); ofd_prop_add(m, n, "device_type", name, sizeof (name)); /* physical addresses usable without regard to OF */ struct reg reg; reg.addr = start; reg.sz = mem_size - start; if (reg.sz > CHUNK_SIZE) { reg.sz = CHUNK_SIZE; } /* free list of physical addresses available after OF and * client program have been accounted for */ /* FIXME: obviously making this up */ if (start == 0) { struct reg avail = { .addr = 0, .sz = CHUNK_SIZE - (1024 * 1024), }; ofd_prop_add(m, n, "available", &avail, sizeof (avail)); } ofd_prop_add(m, n, "reg", ®, sizeof (reg)); start += reg.sz; } return n; } static ofdn_t ofd_prune(void *m, const char *devspec) { ofdn_t n; int rc = -1; while ((n = ofd_node_find(m, devspec)) > 0) { rc = ofd_node_prune(m, n); } return rc; }
static ofdn_t ofd_vdevice_vscsi_server(void *m, ofdn_t p, uval lpid, uval num) { ofdn_t n = 0; static const char pathfmt[] = "/vdevice/v-scsi-host@%x"; static const char name[] = "v-scsi-host"; static const char compatible[] = "IBM,v-scsi-host"; static const char device_type[] = "v-scsi-host"; char path[sizeof (pathfmt) + 8 - 1]; uval32 intr[2] = { /* source */ 0x0, /* +edge */ 0x0 }; uval32 dma_sz = 8 * 1024 * 1024; /* (((0x80<< 12) >> 3) << 12) */ uval32 dma[] = { /* server */ /* liobn */ 0x0, /* phys */ 0x0, 0x0, /* size */ 0x0, 0x0, /* client */ /* liobn */ 0x0, /* phys */ 0x0, 0x0, /* size */ 0x0, 0x0 }; uval i; struct crq_maintenance *cm; for (i = 0; i < num; i++) { uval server; uval32 val; cm = crq_create(lpid, ROLE_SERVER, dma_sz); if (cm != NULL) { server = cm->cm_liobn_server; dma[0] = server; dma[4] = cm->cm_dma_sz; dma[5] = cm->cm_liobn_client; dma[9] = cm->cm_dma_sz; intr[0] = server; val = server; snprintf(path, sizeof (path), pathfmt, val); n = ofd_node_add(m, p, path, sizeof (path)); assert(n > 0, "failed to create node\n"); if (n > 0) { ofd_prop_add(m, n, "name", name, sizeof (name)); ofd_prop_add(m, n, "device_type", device_type, sizeof (device_type)); ofd_prop_add(m, n, "compatible", compatible, sizeof (compatible)); ofd_prop_add(m, n, "reg", &val, sizeof (val)); ofd_prop_add(m, n, "ibm,my-dma-window", dma, sizeof (dma)); ofd_prop_add(m, n, "interrupts", intr, sizeof (intr)); ofd_prop_add(m, n, "ibm,vserver", NULL, 0); val = 2; ofd_prop_add(m, n, "ibm,#dma-address-cells", &val, sizeof (val)); ofd_prop_add(m, n, "ibm,#dma-size-cells", &val, sizeof (val)); } } } return n; }
static ofdn_t ofd_cpus_props(void *m, struct partition_status *ps) { static const char path[] = "/cpus"; static const char cpu[] = "cpu"; uval32 val = 1; ofdn_t n; ofdn_t c; static uval32 ibm_pft_size[] = { 0x0, 0x0 }; n = ofd_node_find(m, path); if (n == 0) { n = ofd_node_add(m, OFD_ROOT, path, sizeof (path)); ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1); } ofd_prop_add(m, n, "#address-cells", &val, sizeof(val)); ofd_prop_add(m, n, "#size-cells", &val, sizeof(val)); ofd_prop_add(m, n, "smp-enabled", NULL, 0); #ifdef HV_EXPOSE_PERFORMANCE_MONITOR ofd_prop_add(m, n, "performance-monitor", NULL, 0); #endif c = ofd_node_find_by_prop(m, n, "device_type", cpu, sizeof (cpu)); //assert(c > 0, "can't get first processor\n"); while (c > 0) { ibm_pft_size[1] = ps->log_htab_bytes; ofd_prop_add(m, c, "ibm,pft-size", ibm_pft_size, sizeof (ibm_pft_size)); /* FIXME: we don't sleep to good yet so if on simulator lie * about the clock speed */ if (onsim()) { val = 100000000; ofd_prop_add(m, c, "clock-frequency", &val, sizeof(val)); ofd_prop_add(m, c, "timebase-frequency", &val, sizeof(val)); } /* FIXME: Check the the "l2-cache" property who's * contents is an orphaned phandle? */ ofd_per_proc_props(m, c, ps->lpid); c = ofd_node_find_next(m, c); /* Since we are not MP yet we can prune the rest of the CPUs */ while (c > 0) { ofdn_t nc; nc = ofd_node_find_next(m, c); ofd_node_prune(m, c); c = nc; } } ofd_proc_props(m, ps->lpid); return n; }