Statistics
| Branch: | Revision:

root / hw / spapr_rtas.c @ 39ac8455

History | View | Annotate | Download (4 kB)

1
/*
2
 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
3
 *
4
 * Hypercall based emulated RTAS
5
 *
6
 * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 *
26
 */
27
#include "cpu.h"
28
#include "sysemu.h"
29
#include "qemu-char.h"
30
#include "hw/qdev.h"
31
#include "device_tree.h"
32

    
33
#include "hw/spapr.h"
34
#include "hw/spapr_vio.h"
35

    
36
#include <libfdt.h>
37

    
38
#define TOKEN_BASE      0x2000
39
#define TOKEN_MAX       0x100
40

    
41
static struct rtas_call {
42
    const char *name;
43
    spapr_rtas_fn fn;
44
} rtas_table[TOKEN_MAX];
45

    
46
struct rtas_call *rtas_next = rtas_table;
47

    
48
target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
49
                             uint32_t token, uint32_t nargs, target_ulong args,
50
                             uint32_t nret, target_ulong rets)
51
{
52
    if ((token >= TOKEN_BASE)
53
        && ((token - TOKEN_BASE) < TOKEN_MAX)) {
54
        struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
55

    
56
        if (call->fn) {
57
            call->fn(spapr, token, nargs, args, nret, rets);
58
            return H_SUCCESS;
59
        }
60
    }
61

    
62
    hcall_dprintf("Unknown RTAS token 0x%x\n", token);
63
    rtas_st(rets, 0, -3);
64
    return H_PARAMETER;
65
}
66

    
67
void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
68
{
69
    assert(rtas_next < (rtas_table + TOKEN_MAX));
70

    
71
    rtas_next->name = name;
72
    rtas_next->fn = fn;
73

    
74
    rtas_next++;
75
}
76

    
77
int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
78
                                 target_phys_addr_t rtas_size)
79
{
80
    int ret;
81
    int i;
82

    
83
    ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
84
    if (ret < 0) {
85
        fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
86
                fdt_strerror(ret));
87
        return ret;
88
    }
89

    
90
    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-base",
91
                                    rtas_addr);
92
    if (ret < 0) {
93
        fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
94
                fdt_strerror(ret));
95
        return ret;
96
    }
97

    
98
    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
99
                                    rtas_addr);
100
    if (ret < 0) {
101
        fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
102
                fdt_strerror(ret));
103
        return ret;
104
    }
105

    
106
    ret = qemu_devtree_setprop_cell(fdt, "/rtas", "rtas-size",
107
                                    rtas_size);
108
    if (ret < 0) {
109
        fprintf(stderr, "Couldn't add rtas-size property: %s\n",
110
                fdt_strerror(ret));
111
        return ret;
112
    }
113

    
114
    for (i = 0; i < TOKEN_MAX; i++) {
115
        struct rtas_call *call = &rtas_table[i];
116

    
117
        if (!call->fn) {
118
            continue;
119
        }
120

    
121
        ret = qemu_devtree_setprop_cell(fdt, "/rtas", call->name,
122
                                        i + TOKEN_BASE);
123
        if (ret < 0) {
124
            fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
125
                    call->name, fdt_strerror(ret));
126
            return ret;
127
        }
128

    
129
    }
130
    return 0;
131
}