WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

Re: [XenPPC] [Patch] Find serial device and platform type

To: xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
Subject: Re: [XenPPC] [Patch] Find serial device and platform type
From: Maria Butrico <butrico@xxxxxxxxxxxxx>
Date: Mon, 24 Apr 2006 16:22:15 -0400
Delivery-date: Mon, 24 Apr 2006 13:22:39 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <E1FWwwp-0001Vm-Ud@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-ppc-devel-request@lists.xensource.com?subject=help>
List-id: Xen PPC development <xen-ppc-devel.lists.xensource.com>
List-post: <mailto:xen-ppc-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ppc-devel>, <mailto:xen-ppc-devel-request@lists.xensource.com?subject=unsubscribe>
References: <E1FWwwp-0001Vm-Ud@xxxxxxxxxxxxxxxxxxxxx>
Reply-to: butrico@xxxxxxxxxxxxxx
Sender: xen-ppc-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 1.5 (Windows/20051201)
This patch is intended as a preliminary request for comment, status update and a good place to keep it, in case I destroy my tree. It's work in progress.

(I don't get my email to echo back to me for quite a few hours, btw, so commnts like this one might not be too timely.)

Maria Butrico wrote:
diff -r 56e1802303e5 xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c    Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/boot_of.c    Fri Apr 21 10:41:42 2006 -0400
@@ -24,6 +24,36 @@
 #include <xen/compile.h>
 #include <public/of-devtree.h>
 #include <asm/page.h>
+#include <xen/string.h>
+
+struct global_hardware_stuff {
+    int platform_type;
+    #define UNKNOWN_PLATFORM        1
+    #define PMAC_HARDWARE           2
+    #define MAPLE_SIM               3
+    #define MAPLE_HARDWARE          4
+    #define JS2X_HARDWARE           5
+
+    /* these are not definite platform but we start to isolate the type */
+    #define MAPLE_GENERIC           10  /* could be simulator(MAPLE_SIM) or
+                                           hardware(MAPLE_HARDWARE) or JX20 */
+
+    int hv_supported;
+
+    struct {
+        int type;
+        #define UART_UNKNOWN    0
+        #define UART_ZILOG      2
+        #define UART_NS16550    3
+
+        u64 uart_io_base;
+        u64 isa_io_base;
+        u32 clock;
+        // function serial port initialization routine
+    } serial_port;
+};
+static struct global_hardware_stuff global_hs;
+extern int opt_nohv;
static ulong of_vec;
 static ulong of_msr;
@@ -152,6 +182,7 @@ static int __init of_getprop(int ph, con
if (rets[0] == OF_FAILURE) {
         DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
+        if (buflen > 0) memset(buf, 0, 1);
         return OF_FAILURE;
     }
@@ -301,6 +332,7 @@ static int __init of_instance_to_package return rets[0];
 }
+#endif
static int __init of_getparent(int ph)
 {
@@ -311,8 +343,6 @@ static int __init of_getparent(int ph)
     DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
     return rets[0];
 }
-
-#endif
extern char _start[];
 extern char _end[];
@@ -331,7 +361,6 @@ static void boot_of_probemem(multiboot_i
     root = of_finddevice("/");
     p = of_getchild(root);
- /* code is writen to assume sizes of 1 */
     of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
     of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
     DBG("%s: address_cells=%d  size_cells=%d\n",
@@ -786,10 +815,282 @@ static void boot_of_module(ulong r3, ulo
 }
-int __init boot_of_serial(void)
-{
-    /* right now we are punting and using mambo writes which is the
-     * hardcoded setup */
+static void search_by_property_value(int p, const char *prop_name,
+                const char *prop_value)
+{
+    int pnext;          /* of handdle */
+
+    do {
+ // does this package have the property 'prop_name' with + // value "prop_value"?
+        char of_property[256];
+        of_property[0] = '\0';
+        of_getprop(p, prop_name, of_property, sizeof (of_property));
+        if (strncmp(of_property, prop_value, sizeof (prop_value)) == 0) {
+            char path[256];
+            int sz = of_package_to_path(p, path, sizeof(path));
+            of_printf("\npackage with property '%s' with value '%s' found. "
+                            "path is %s (size %d)\n", prop_name, prop_value,
+                            path, sz);
+#ifdef OF_DEBUG
+            // Print all its properties
+            char name[128];
+            int result = of_nextprop(p, 0, name);       /* first prop. */
+            while (result > 0) {
+                int sz;
+                u64 obj[1024];
+                sz = of_getproplen(p, name);
+                if (sz > 0) {
+                    int actual = of_getprop(p, name, obj, sz);
+                    of_printf("device property *%s* size %d value %s  ",
+                                        name, actual, (char*)obj);
+                    int i;
+                    for (i=0; i<=(actual/sizeof(obj[0])); i++)
+                                of_printf("0x%016lx ", obj[i]);
+                    of_printf("\n");
+                } else if (0 == sz) {
+                        of_printf("device property *%s* size 0\n",
+                                        name);
+                }
+
+                result = of_nextprop(p, name, name);
+            }
+#endif
+        }
+
+        /* do children first */
+        pnext = of_getchild(p);
+        if (pnext != 0) {
+            search_by_property_value(pnext, prop_name, prop_value);
+        }
+
+        p = of_getpeer(p);
+    } while (p != OF_FAILURE && p != 0);
+}
+
+
+/*
+ * Returns the value of the property '/#size-cells'
+ */
+int __init boot_of_get_sizecells_prop()
+{
+    int of_root;
+    u32 cell = 1;
+ + of_root = of_finddevice("/");
+    if (OF_FAILURE != of_root)
+        of_getprop(of_root, "#size-cells", &cell, sizeof(cell));
+    return cell;
+}
+
+int __init boot_of_serial()
+{
+    int p, ofout;      /* of handle */
+    int rc;
+    char of_property[256];
+    char ofout_path[256] = {0,};
+    const char serial[] = "serial";
+    const char macio[] = "mac-io";
+    const char escc[] = "escc";
+
+    #ifdef OF_DEBUG
+    {
+    p = of_finddevice("/");
+    const char device_type[] = "device_type";
+    search_by_property_value(p, device_type, serial);
+    }
+    #endif
+
+    global_hs.serial_port.type = UART_UNKNOWN;
+
+    /* copied and adapted from rhype */
+    ofout = OF_FAILURE;
+
+    /* probe /options tree */
+    rc = p = of_finddevice("/options");
+    if (p != OF_FAILURE) {
+        rc = of_getprop(p, "output-device", ofout_path, sizeof(ofout_path));
+ } + if (OF_FAILURE == rc) {
+        strncpy(ofout_path, serial, sizeof(serial));
+    }
+
+    /*
+     * if the options are not a path (they do not start with '/')
+     * then they are aliases and we must look them up.  we look it
+     * up in aliases because it is possible that the OF does not
+     * support finddevice() of an alias.
+     */
+    if (ofout_path[0] != '/') {
+        p = of_finddevice("/aliases");
+        if (p != OF_FAILURE) {
+            char alias[256];
+            memcpy(alias, ofout_path, sizeof(alias));
+            rc = of_getprop(p, alias, ofout_path, sizeof (ofout_path));
+        }
+    }
+
+    if (OF_FAILURE != rc) {
+        ofout = of_finddevice(ofout_path);
+    } else {
+        s32 iout;       /* ihandle ?? */
+        /*
+         * Our last chance is to figure out the package for
+         * the current console and hopefully discover it to be
+         * a serial device.
+         */
+        p = of_finddevice("/chosen");
+        if (p != OF_FAILURE) {
+            rc = of_getprop(p, "stdout", &iout, sizeof(iout));
+        }
+        if (rc != OF_FAILURE) {
+            rc = of_instance_to_path(iout, ofout_path, sizeof(ofout_path));
+ if (rc != OF_FAILURE) + ofout = of_finddevice(ofout_path);
+        }
+    }
+
+    DBG("serial port OF handle=0x%x\n", ofout);
+
+    if (OF_FAILURE == ofout) {
+        /* can try the rtas device.  Code not written yet */
+        of_printf("Could not find any serial device\n");
+        return OF_FAILURE;
+    }
+
+
+    /* Now we have the OF handle of the serial device.  Let's find out
+     * what it is and its address.
+     *
+     * The device must have of type 'serial'
+     *
+     * If the grandparent directory has the name 'mac-io', then this must
+     * be a power mac.  The serial device is a zilog.
+     *
+     * Otherwise (we are assuming that) the grandparent has the name
+     * 'pci' and the parent 'isa'.  The serial device is a NS16550.
+     *
+     * And what about the ns16750?
+ * + */
+    rc = of_getprop(ofout, "device_type", of_property, sizeof(of_property));
+    of_printf("serial device type %s\n", of_property);
+
+    union of_pci_hi {
+       u32 word;
+       struct {
+           u32  opa_n: 1; /* relocatable */
+           u32  opa_p: 1; /* prefetchable */
+           u32  opa_t: 1; /* aliased */
+           u32  _opa_res: 3;
+           u32  opa_s: 2; /* space code */
+           u32  opa_b: 8; /* bus number */
+           u32  opa_d: 5; /* device number */
+           u32  opa_f: 3; /* function number */
+           u32  opa_r: 8; /* register number */
+       } bits;
+    };
+    struct of_pci_addr_s {
+        union of_pci_hi opa_hi;
+        u32 opa_mid;
+        u32 opa_lo;
+    };
+
+    if (strncmp(of_property, serial, sizeof(serial))) {
+        of_printf("Serial device is not serial\n");
+        return OF_FAILURE;
+    }
+
+    int parent, grandparent;        /* of handles */
+    parent = of_getparent(ofout);
+    if (OF_FAILURE == parent) return OF_FAILURE;
+    grandparent = of_getparent(parent);
+    if (OF_FAILURE == grandparent) return OF_FAILURE;
+
+    of_getprop(grandparent, "name", of_property, sizeof(of_property));
+    if (0 == strncmp(of_property, macio, sizeof(macio))) {
+        struct reg_property32 {
+            u32 address;
+            u32 size;
+        } reg;
+        struct of_pci_range32_s {
+            struct of_pci_addr_s opr_addr;
+            u32 opr_phys;
+            u32 opr_size;
+        } r32;
+
+        of_getprop(parent, "device_type", of_property, sizeof(of_property));
+        if (strncmp(of_property, escc, sizeof(escc))) {
+            of_printf("Serial device parent's type is not escc\n");
+            return OF_FAILURE;
+        }
+
+        if (global_hs.platform_type != PMAC_HARDWARE) {
+           of_printf("WARNING: serial device found in path mac-io"
+                     "but we don't think this is a power mac\n");
+           return OF_FAILURE;
+        }
+
+        global_hs.serial_port.type = UART_ZILOG;
+        of_getprop(grandparent , "ranges", &r32, sizeof(r32));
+        of_getprop(ofout, "reg", &reg, sizeof(reg));
+
+        of_printf("reg property address=0x%08x  size=0x%08x\n",
+                        reg.address, reg.size);
+        of_printf("ranges property %x:%x:%x %x %x\n",
+                            r32.opr_addr.opa_hi.word,
+                            r32.opr_addr.opa_mid,
+                            r32.opr_addr.opa_lo,
+                            r32.opr_phys, r32.opr_size);
+
+        global_hs.serial_port.uart_io_base = reg.address;
+        global_hs.serial_port.isa_io_base = r32.opr_phys;
+        /* io_addr = isa_io_base + uart_io_base; */
+    } else {
+        /* grandparent directory is not 'mac-io'.  We are assuming 'pci/isa' */
+        struct isa_reg_property {
+            u32 space;
+            u32 address;
+            u32 size;
+        } isa_reg;
+        struct of_pci_range64_s {
+            struct of_pci_addr_s opr_addr;
+            u32 opr_phys_hi;
+            u32 opr_phys_lo;
+            u32 opr_size_hi;
+            u32 opr_size_lo;
+        } r64;
+        u32 clock;
+
+        global_hs.serial_port.type = UART_NS16550;
+        of_getprop(grandparent , "ranges", &r64, sizeof(r64));
+        of_getprop(ofout, "clock-frequency", &clock, sizeof (clock));
+        of_getprop(ofout, "reg", &isa_reg, sizeof(isa_reg));
+
+        of_printf("reg property address=0x%08x  size=0x%08x\n",
+                        isa_reg.address, isa_reg.size);
+        of_printf("ranges property %x:%x:%x %x:%x %x:%x\n",
+                     r64.opr_addr.opa_hi.word,
+                     r64.opr_addr.opa_mid,
+                     r64.opr_addr.opa_lo,
+                     r64.opr_phys_hi,
+                     r64.opr_phys_lo,
+                     r64.opr_size_hi, r64.opr_size_lo);
+
+        global_hs.serial_port.uart_io_base = isa_reg.address;
+ global_hs.serial_port.isa_io_base = + (((u64)r64.opr_phys_hi) << 32) | r64.opr_phys_lo;
+        global_hs.serial_port.clock = clock;
+        /* io_addr = isa_io_base + uart_io_base; */
+    }
+
+    of_printf("%s: serial type=%d  io base=0x%016lx  isa io@=0x%016lx  "
+              "clock=%d\n",
+              __func__, global_hs.serial_port.type,
+              global_hs.serial_port.uart_io_base,
+              global_hs.serial_port.isa_io_base,
+              global_hs.serial_port.clock
+              );
return 1;
 }
@@ -825,6 +1126,119 @@ int __init boot_of_rtas(void)
     return 1;
 }
+/*
+ * Returns the length of the OF compatible property; OF_FAILURE on error
+ * The value of the property itself is returned in the first parameter.
+ */
+int __init boot_of_get_compatible_prop(char *cstring, int cstring_size)
+{
+    int of_root;
+    int comp_length;
+ + of_root = of_finddevice("/");
+    if (OF_FAILURE == of_root) return OF_FAILURE;
+
+    comp_length = of_getprop(of_root, "compatible", cstring, cstring_size);
+    #if 0
+    if (comp_length != OF_FAILURE) {
+        // null separated string yuck
+        int used_length;
+        of_printf("%s :\n", __func__);
+        for (used_length = 0; used_length < comp_length; used_length++) {
+            if (cstring[used_length] == '\0' ) {
+                of_printf("   NULL\n");
+            } else {
+                of_printf("%c", cstring[used_length]);
+            }
+        }
+ } + #endif
+
+    return comp_length;
+}
+
+/*
+ * Does the compatible of property indicate that the platform is a Power
+ * Macintosh, or a maple (hardware or simulated), or ..
+ * return 0 if not an known value;
+ */
+int __init boot_of_platform(char * compatible_p, int c_length)
+{
+    static const char pmac_string[] = "Power Macintosh";
+    static const char maple_string[] = "Momentum,Maple";
+    static const char JS_20[] = "junk";
+
+    char *cmpstr;
+    int used_length;
+
+    // loop over each null terminated piece of the compatible property
+    for (cmpstr = compatible_p, used_length = 0; used_length < c_length;
+         cmpstr = &compatible_p[used_length]) {
+        if (strstr(cmpstr, pmac_string)) return PMAC_HARDWARE;
+        if (strstr(cmpstr, maple_string)) return MAPLE_GENERIC;
+        if (strstr(cmpstr, JS_20)) return JS2X_HARDWARE;
+        used_length += strlen(cmpstr) + 1;
+    }
+
+    return 0;
+}
+
+void __init boot_of_hardware_specific() +{
+    int rc;
+    char compatible_string[256];
+    int compatible_length;
+    int cell;
+
+    memset(&global_hs, 0, sizeof(global_hs));
+    global_hs.platform_type = UNKNOWN_PLATFORM;
+
+    compatible_length = boot_of_get_compatible_prop(compatible_string,
+                                               sizeof(compatible_string));
+
+    if (compatible_length != OF_FAILURE) {
+        rc = boot_of_platform(compatible_string, compatible_length);
+        cell = boot_of_get_sizecells_prop();
+        switch (rc) {
+        default:
+            of_printf("Warning: %s is not aware of this machine type %d\n",
+                            __func__, rc);
+            break;
+ + case 0:
+            // did not learn anything
+            break;
+
+        case PMAC_HARDWARE:
+            global_hs.platform_type = rc;
+            if (cell != 1) of_panic("powermac with cell %d\n", cell);
+
+            /*
+             * Power Macintosh' do not distinguish between supervisor and
+             * hypervisor mode.  Hence, we run, if at all, with in a special
+             * mode called non-hypervisor hypervisor. (nohv)
+             */
+            of_printf("Non hypervisor hardware found.\n");
+            global_hs.hv_supported = 0;
+            opt_nohv = 1;
+            break;
+
+        case MAPLE_GENERIC:
+            global_hs.platform_type = rc;
+            if (cell != 2) of_panic("maple like thing with cell %d\n", cell);
+            global_hs.hv_supported = 1;
+            break;
+        }
+    }
+
+    of_printf("%s: type=%d  hv=%d\n", __func__, global_hs.platform_type,
+                    global_hs.hv_supported);
+
+    boot_of_serial();
+    boot_of_rtas();
+}
+
+
 multiboot_info_t __init *boot_of_init(
         ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
 {
@@ -858,9 +1272,16 @@ multiboot_info_t __init *boot_of_init(
     boot_of_probemem(&mbi);
     boot_of_bootargs(&mbi);
     boot_of_module(r3, r4, &mbi);
-    boot_of_serial();
     boot_of_cpus();
-    boot_of_rtas();
+
+    /* Note: serial and rtas were before cpus, but should really happen after 
hardware
+     * specific, since we want to use the machine type as a hint of where/what
+     * the serial device might be
+     *
+     * If serial initalization needs to be before cpus, then we need to move up
+     * hardware specific as well.
+     */
+    boot_of_hardware_specific();
/* end of OF */
     of_printf("closing OF stdout...\n");
diff -r 56e1802303e5 xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c      Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/setup.c      Fri Apr 21 10:41:42 2006 -0400
@@ -43,6 +43,12 @@ int opt_noht = 0;
 int opt_noht = 0;
 boolean_param("noht", opt_noht);
+/* opt_nohv: If true, hardware has no hypervisor (HV) mode or nohv boot + * parameter was specified. + */
+int opt_nohv = 0;
+boolean_param("nohv", opt_nohv);
+
 int opt_earlygdb = 0;
 boolean_param("earlygdb", opt_earlygdb);
@@ -282,6 +288,8 @@ static void __init __start_xen(multiboot
     if (dom0 == NULL)
         panic("Error creating domain 0\n");
     set_bit(_DOMF_privileged, &dom0->domain_flags);
+    if (opt_nohv)
+       set_bit(_DOMF_prob, &dom0->domain_flags);
/* Grab the DOM0 command line. Skip past the image name. */
     cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
diff -r 56e1802303e5 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/include/xen/sched.h   Fri Apr 21 10:41:42 2006 -0400
@@ -392,6 +392,10 @@ extern struct domain *domain_list;
  /* Domain is being debugged by controller software. */
 #define _DOMF_debugging        4
 #define DOMF_debugging         (1UL<<_DOMF_debugging)
+ /* run domain in prob mode */
+#define _DOMF_prob      7
+#define DOMF_prob       (1UL<<_DOMF_prob)
+
static inline int vcpu_runnable(struct vcpu *v)
 {

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel



_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel