source: trunk/packages/xen-common/xen-common/xen/arch/powerpc/ofd_fixup.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 12.6 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005, 2006
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
20
21#include <xen/config.h>
22#include <xen/lib.h>
23#include <xen/sched.h>
24#include <xen/version.h>
25#include <public/xen.h>
26#include "of-devtree.h"
27#include "oftree.h"
28#include "rtas.h"
29
30#undef RTAS
31
32ofdn_t ofd_boot_cpu;
33
34#ifdef PAPR_VTERM
35static ofdn_t ofd_vdevice_vty(void *m, ofdn_t p, struct domain *d)
36{
37    ofdn_t n;
38    static const char pathfmt[] = "/vdevice/vty@%x";
39    static const char name[] = "vty";
40    static const char compatible[] = "hvterm1";
41    static const char device_type[] = "serial";
42    char path[sizeof (pathfmt) + 8 - 2];
43    int client = 0;
44
45    snprintf(path, sizeof (path), pathfmt, client);
46    n = ofd_node_add(m, p, path, sizeof (path));
47
48    if (n > 0) {
49        u32 val32;
50
51        val32 = client;
52        ofd_prop_add(m, n, "name", name, sizeof (name));
53        ofd_prop_add(m, n, "reg", &val32, sizeof (val32));
54        ofd_prop_add(m, n, "compatible",
55                     compatible, sizeof (compatible));
56        ofd_prop_add(m, n, "device_type",
57                     device_type, sizeof (device_type));
58    }
59
60    return n;
61}
62#endif
63
64#ifdef PAPR_VDEVICE
65static ofdn_t ofd_vdevice(void *m, struct domain *d)
66{
67    ofdn_t n;
68    static const char path[] = "/vdevice";
69    static const char name[] = "vdevice";
70    static const char compatible[] = "IBM,vdevice";
71    u32 val;
72
73    n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
74
75    if (n > 0) {
76
77        ofd_prop_add(m, n, "name", name, sizeof (name));
78        val = 1;
79        ofd_prop_add(m, n, "#address-cells", &val, sizeof (val));
80        val = 0;
81        ofd_prop_add(m, n, "#size-cells", &val, sizeof (val));
82        ofd_prop_add(m, n, "compatible",
83                     compatible, sizeof (compatible));
84        ofd_prop_add(m, n, "device_type", name, sizeof (name));
85        ofd_prop_add(m, n, "interupt-controller", NULL, 0);
86
87#ifdef PAPR_VDEVICE
88        ofdn_t r;
89
90        /* add vty */
91        r = ofd_vdevice_vty(m, n, d);
92        printk("vdevice r: %x\n", r);
93        n = r;
94#endif
95    }
96    return n;
97}
98#endif
99
100static ofdn_t ofd_openprom_props(void *m)
101{
102    static const char path[] = "/openprom";
103    static const char vernum[] = "IBM,XenOF0.1";
104    ofdn_t n;
105
106    n = ofd_node_find(m, path);
107    if (n == 0) {
108        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
109        ofd_prop_add(m, n, "name",
110                     &path[1], sizeof (path) - 1);
111    }
112    /* I want to override */
113    ofd_prop_add(m, n, "model", vernum, sizeof(vernum));
114    ofd_prop_add(m, n, "ibm,fw-vernum_encoded", vernum, sizeof(vernum));
115    ofd_prop_add(m, n, "relative-addressing", NULL, 0);
116    return n;
117
118}
119
120#ifdef PAPR_VTERM
121static ofdn_t ofd_aliases_props(void *m)
122{
123    static const char path[] = "/aliases";
124    static const char screen[] = "/vdevice/vty@0";
125    ofdn_t n;
126
127    n = ofd_node_find(m, path);
128    if (n == 0) {
129        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
130        ofd_prop_add(m, n, "name",
131                     &path[1], sizeof (path) - 1);
132    }
133    ofd_prop_add(m, n, "screen", screen, sizeof(screen));
134    return n;
135}
136#endif
137
138static ofdn_t ofd_options_props(void *m)
139{
140    static const char path[] = "/options";
141    static const char boot[] = "true";
142    ofdn_t n;
143
144    n = ofd_node_find(m, path);
145    if (n == 0) {
146        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
147        ofd_prop_add(m, n, "name",
148                     &path[1], sizeof (path) - 1);
149    }
150    ofd_prop_add(m, n, "auto-boot?", boot, sizeof(boot));
151    return n;
152}
153
154static ofdn_t ofd_cpus_props(void *m, struct domain *d)
155{
156    static const char path[] = "/cpus";
157    static const char cpu[] = "cpu";
158    u32 val = 1;
159    ofdn_t n;
160    ofdn_t c;
161    static u32 ibm_pft_size[] = { 0x0, 0x0 };
162
163    n = ofd_node_find(m, path);
164    if (n == 0) {
165        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
166        ofd_prop_add(m, n, "name",
167                     &path[1], sizeof (path) - 1);
168    }
169    ofd_prop_add(m, n, "#address-cells", &val, sizeof(val));
170    ofd_prop_add(m, n, "#size-cells", &val, sizeof(val));
171    ofd_prop_add(m, n, "smp-enabled", NULL, 0);
172
173#ifdef HV_EXPOSE_PERFORMANCE_MONITOR
174    ofd_prop_add(m, n, "performance-monitor", NULL, 0);
175#endif
176
177    c = ofd_node_find_by_prop(m, n, "device_type", cpu, sizeof (cpu));
178    if (ofd_boot_cpu == -1)
179        ofd_boot_cpu = c;
180    while (c > 0) {
181        /* We do not use the OF tree to identify secondary processors
182         * so we must prune them from the tree */
183        if (c == ofd_boot_cpu) {
184            ofdn_t p;
185
186            ibm_pft_size[1] = d->arch.htab.log_num_ptes + LOG_PTE_SIZE;
187            ofd_prop_add(m, c, "ibm,pft-size",
188                         ibm_pft_size, sizeof (ibm_pft_size));
189
190            /* get rid of non-standard properties */
191            p = ofd_prop_find(m, c, "cpu#");
192            if (p > 0) {
193                ofd_prop_remove(m, c, p);
194            }
195
196            /* FIXME: Check the the "l2-cache" property who's
197             * contents is an orphaned phandle? */
198        } else
199            ofd_node_prune(m, c);
200
201        c = ofd_node_find_next(m, c);
202    }
203
204    return n;
205}
206
207#ifdef ADD_XICS
208static ofdn_t ofd_xics_props(void *m)
209{
210    ofdn_t n;
211    static const char path[] = "/interrupt-controller";
212    static const char compat[] = "IBM,ppc-xicp";
213    static const char model[] = "IBM, BoaC, PowerPC-PIC, 00";
214    static const char dtype[] =
215        "PowerPC-External-Interrupt-Presentation";
216    /*
217     * I don't think these are used for anything but linux wants
218     * it.  I seems to describe some per processor location for
219     * IPIs but that is a complete guess.
220     */
221    static const u32 reg[] = {
222        0x000003e0, 0x0f000000, 0x00000000, 0x00001000,
223        0x000003e0, 0x0f001000, 0x00000000, 0x00001000,
224        0x000003e0, 0x0f002000, 0x00000000, 0x00001000,
225        0x000003e0, 0x0f003000, 0x00000000, 0x00001000,
226        0x000003e0, 0x0f004000, 0x00000000, 0x00001000,
227        0x000003e0, 0x0f005000, 0x00000000, 0x00001000,
228        0x000003e0, 0x0f006000, 0x00000000, 0x00001000,
229        0x000003e0, 0x0f007000, 0x00000000, 0x00001000,
230        0x000003e0, 0x0f008000, 0x00000000, 0x00001000,
231        0x000003e0, 0x0f009000, 0x00000000, 0x00001000,
232        0x000003e0, 0x0f00a000, 0x00000000, 0x00001000,
233        0x000003e0, 0x0f00b000, 0x00000000, 0x00001000,
234        0x000003e0, 0x0f00c000, 0x00000000, 0x00001000,
235        0x000003e0, 0x0f00d000, 0x00000000, 0x00001000,
236        0x000003e0, 0x0f00e000, 0x00000000, 0x00001000,
237        0x000003e0, 0x0f00f000, 0x00000000, 0x00001000,
238    };
239
240    n = ofd_node_find(m, path);
241    if (n == 0) {
242        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
243        ofd_prop_add(m, n, "name",
244                     &path[1], sizeof (path) - 1);
245    }
246    ofd_prop_add(m, n, "built-in", NULL, 0);
247    ofd_prop_add(m, n, "compatible", compat, sizeof(compat));
248    ofd_prop_add(m, n, "device_type", dtype, sizeof(dtype));
249    ofd_prop_add(m, n, "model", model, sizeof(model));
250    ofd_prop_add(m, n, "reg", reg, sizeof(reg));
251
252    return n;
253}
254#endif
255
256/*
257 * Good things you can stick here:
258 *   init=/bin/bash ip=dhcp root=/dev/hda2 ide=nodma
259 */
260static char default_bootargs[] = ""; 
261
262static ofdn_t ofd_chosen_props(void *m, const char *cmdline)
263{
264    ofdn_t n;
265    ofdn_t p;
266    static const char path[] = "/chosen";
267    char bootargs[256] = { 0, };
268    int bsz;
269    int sz;
270    int rm;
271
272    n = ofd_node_find(m, path);
273    if (n == 0) {
274        n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
275        ofd_prop_add(m, n, "name",
276                     &path[1], sizeof (path) - 1);
277    }
278
279    if (cmdline)
280        strlcpy(bootargs, cmdline, sizeof(bootargs));
281    bsz = strlen(bootargs) + 1;
282    rm = sizeof (bootargs) - bsz;
283
284    if (default_bootargs != NULL) {
285        sz = strlen(default_bootargs);
286        if (sz > rm) {
287            panic("default_bootargs is too big: 0x%x > 0x%x\n",
288                  sz, rm);
289        } else if (sz > 0) {
290            memcpy(&bootargs[bsz - 1], default_bootargs, sz + 1);
291            bsz += sz;
292            rm -= sz;
293        }
294    }
295
296    printk("DOM0 bootargs: %s\n", bootargs);
297    ofd_prop_add(m, n, "bootargs", bootargs, bsz);
298
299    ofd_prop_add(m, n, "bootpath", NULL, 0);
300
301    printk("Remove /chosen/mmu, stub will replace\n");
302    p = ofd_prop_find(m, n, "mmu");
303    if (p > 0) {
304        ofd_prop_remove(m, n, p);
305    }
306
307    return n;
308}
309
310#ifdef RTAS
311static ofdn_t ofd_rtas_props(void *m)
312{
313    static const char path[] = "/rtas";
314    static const char hypertas[] = "dummy";
315    ofdn_t p;
316    ofdn_t n;
317
318    /* just enough to make linux think its on LPAR */
319
320    p = ofd_node_find(m, "/");
321
322    n = ofd_node_add(m, p, path, sizeof(path));
323    ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
324    ofd_prop_add(m, n, "ibm,hypertas-functions", hypertas, sizeof (hypertas));
325
326    return n;
327}
328#endif
329
330static ofdn_t ofd_xen_props(void *m, struct domain *d, ulong shared_info)
331{
332    ofdn_t n;
333    static const char path[] = "/xen";
334    static const char console[] = "/xen/console";
335
336    n = ofd_node_add(m, OFD_ROOT, path, sizeof (path));
337    if (n > 0) {
338        char xen[256];
339        int xl;
340        u64 val[2];
341        s32 dom_id;
342
343        dom_id = d->domain_id;
344
345        ofd_prop_add(m, n, "reg", &dom_id, sizeof (dom_id));
346        ofd_prop_add(m, n, "name", &path[1], sizeof (path) - 1);
347
348        xl = snprintf(xen, sizeof (xen), "Xen-%d.%d%s",
349                xen_major_version(), xen_minor_version(), xen_extra_version());
350        ASSERT(xl < sizeof (xen));
351        ofd_prop_add(m, n, "version", xen, xl + 1);
352
353        /* convert xen pointer to guest physical */
354        val[0] = shared_info;
355        val[1] = PAGE_SIZE;
356        ofd_prop_add(m, n, "shared-info", val, sizeof (val));
357
358        /* reserve PAGE_SIZE @ addr shared info */
359        ofd_prop_add(m, n, "reserved", val, sizeof (val));
360
361        /* flags |= SIF_PROVILEDGED; */
362        ofd_prop_add(m, n, "privileged", NULL, 0);
363
364        /* flags |= SIF_INITDOMAIN; */
365        ofd_prop_add(m, n, "initdomain", NULL, 0);
366
367        /* tell dom0 that Xen depends on it to have power control */
368        if (!rtas_entry)
369            ofd_prop_add(m, n, "power-control", NULL, 0);
370
371        /* tell dom0 where granted pages go in the linear map */
372        val[0] = cpu_foreign_map_order();
373        val[1] = d->arch.foreign_mfn_count;
374        ofd_prop_add(m, n, "foreign-map", val, sizeof (val));
375
376        n = ofd_node_add(m, n, console, sizeof (console));
377        if (n > 0) {
378            val[0] = 0;
379            ofd_prop_add(m, n, "interrupts", &val[0], sizeof (val[0]));
380        }
381    }
382    return n;
383}
384
385int ofd_dom0_fixup(struct domain *d, ulong mem, const char *cmdline,
386                   ulong shared_info)
387{
388    void *m;
389    const ofdn_t n = OFD_ROOT;
390    ofdn_t r;
391
392    m = (void *)mem;
393
394#ifdef PAPR_VDEVICE
395    printk("Add /vdevice\n");
396    ofd_vdevice(m, d);
397
398    printk("Add /aliases props\n");
399    ofd_aliases_props(m);
400#endif
401
402    printk("Add /openprom props\n");
403    ofd_openprom_props(m);
404
405    printk("Add /options props\n");
406    ofd_options_props(m);
407
408    printk("Add /cpus props\n");
409    ofd_cpus_props(m, d);
410
411    printk("Add /chosen props\n");
412    ofd_chosen_props(m, cmdline);
413
414    printk("fix /memory props\n");
415    ofd_memory_props(m, d);
416
417    printk("fix /xen props\n");
418    ofd_xen_props(m, d, shared_info);
419
420    printk("Remove original /dart\n");
421    ofd_prune_path(m, "/dart");
422
423    printk("Remove original /rtas\n");
424    ofd_prune_path(m, "/rtas");
425
426#ifdef RTAS
427    printk("Create a new RTAS with just enough stuff to convince "
428           "Linux that its on LPAR\n");
429    ofd_rtas_props(m);
430#endif
431#ifdef FIX_COMPAT
432    const char compat[] = "Hypervisor,Maple";
433    r = ofd_prop_add(m, n, "compatible", compat, sizeof (compat));
434    ASSERT( r > 0 );
435#endif
436
437    u32 did = d->domain_id;
438    r = ofd_prop_add(m, n, "ibm,partition-no", &did, sizeof(did));
439    ASSERT( r > 0 );
440
441    const char d0[] = "dom0";
442    r = ofd_prop_add(m, n, "ibm,partition-name", d0, sizeof (d0));
443    ASSERT( r > 0 );
444
445
446#ifdef DEBUG
447    ofd_walk(m, __func__, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
448#endif
449    return 1;
450}
Note: See TracBrowser for help on using the repository browser.