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 |
} |