Revision 39ac8455

b/Makefile
213 213
pxe-rtl8139.bin pxe-virtio.bin \
214 214
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
215 215
multiboot.bin linuxboot.bin \
216
s390-zipl.rom
216
s390-zipl.rom \
217
spapr-rtas.bin
217 218
else
218 219
BLOBS=
219 220
endif
b/Makefile.target
233 233
obj-ppc-y += ppc_newworld.o
234 234
# IBM pSeries (sPAPR)
235 235
ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
236
obj-ppc-y += spapr.o spapr_hcall.o spapr_vio.o
236
obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
237 237
obj-ppc-y += spapr_vty.o
238 238
endif
239 239
# PowerPC 4xx boards
b/configure
2461 2461
        "$softmmu" = yes ; then
2462 2462
  roms="optionrom"
2463 2463
fi
2464

  
2464
if test "$cpu" = "ppc64" ; then
2465
  roms="$roms spapr-rtas"
2466
fi
2465 2467

  
2466 2468
echo "Install prefix    $prefix"
2467 2469
echo "BIOS directory    `eval echo $datadir`"
b/hw/spapr.c
40 40
#define KERNEL_LOAD_ADDR        0x00000000
41 41
#define INITRD_LOAD_ADDR        0x02800000
42 42
#define FDT_MAX_SIZE            0x10000
43
#define RTAS_MAX_SIZE           0x10000
43 44

  
44 45
#define TIMEBASE_FREQ           512000000ULL
45 46

  
......
53 54
                              target_phys_addr_t initrd_base,
54 55
                              target_phys_addr_t initrd_size,
55 56
                              const char *kernel_cmdline,
57
                              target_phys_addr_t rtas_addr,
58
                              target_phys_addr_t rtas_size,
56 59
                              long hash_shift)
57 60
{
58 61
    void *fdt;
......
195 198
        exit(1);
196 199
    }
197 200

  
201
    /* RTAS */
202
    ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
203
    if (ret < 0) {
204
        fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
205
    }
206

  
198 207
    _FDT((fdt_pack(fdt)));
199 208

  
200 209
    *fdt_size = fdt_totalsize(fdt);
......
224 233
    void *fdt, *htab;
225 234
    int i;
226 235
    ram_addr_t ram_offset;
227
    target_phys_addr_t fdt_addr;
236
    target_phys_addr_t fdt_addr, rtas_addr;
228 237
    uint32_t kernel_base, initrd_base;
229
    long kernel_size, initrd_size, htab_size;
238
    long kernel_size, initrd_size, htab_size, rtas_size;
230 239
    long pteg_shift = 17;
231 240
    int fdt_size;
241
    char *filename;
232 242

  
233 243
    spapr = qemu_malloc(sizeof(*spapr));
234 244
    cpu_ppc_hypercall = emulate_spapr_hypercall;
......
237 247
     * 2GB, so that it can be processed with 32-bit code if
238 248
     * necessary */
239 249
    fdt_addr = MIN(ram_size, 0x80000000) - FDT_MAX_SIZE;
250
    /* RTAS goes just below that */
251
    rtas_addr = fdt_addr - RTAS_MAX_SIZE;
240 252

  
241 253
    /* init CPUs */
242 254
    if (cpu_model == NULL) {
......
276 288
        envs[i]->htab_mask = htab_size - 1;
277 289
    }
278 290

  
291
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
292
    rtas_size = load_image_targphys(filename, rtas_addr, ram_size - rtas_addr);
293
    if (rtas_size < 0) {
294
        hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
295
        exit(1);
296
    }
297
    qemu_free(filename);
298

  
279 299
    spapr->vio_bus = spapr_vio_bus_init();
280 300

  
281 301
    for (i = 0; i < MAX_SERIAL_PORTS; i++) {
......
323 343
    /* Prepare the device tree */
324 344
    fdt = spapr_create_fdt(&fdt_size, ram_size, cpu_model, envs, spapr,
325 345
                           initrd_base, initrd_size, kernel_cmdline,
326
                           pteg_shift + 7);
346
                           rtas_addr, rtas_size, pteg_shift + 7);
327 347
    assert(fdt != NULL);
328 348

  
329 349
    cpu_physical_memory_write(fdt_addr, fdt, fdt_size);
b/hw/spapr.h
237 237
#define H_GET_MPP               0x2D4
238 238
#define MAX_HCALL_OPCODE        H_GET_MPP
239 239

  
240
/* The hcalls above are standardized in PAPR and implemented by pHyp
241
 * as well.
242
 *
243
 * We also need some hcalls which are specific to qemu / KVM-on-POWER.
244
 * So far we just need one for H_RTAS, but in future we'll need more
245
 * for extensions like virtio.  We put those into the 0xf000-0xfffc
246
 * range which is reserved by PAPR for "platform-specific" hcalls.
247
 */
248
#define KVMPPC_HCALL_BASE       0xf000
249
#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
250
#define KVMPPC_HCALL_MAX        KVMPPC_H_RTAS
251

  
240 252
extern sPAPREnvironment *spapr;
241 253

  
242 254
/*#define DEBUG_SPAPR_HCALLS*/
......
257 269
target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
258 270
                             target_ulong *args);
259 271

  
272
static inline uint32_t rtas_ld(target_ulong phys, int n)
273
{
274
    return ldl_phys(phys + 4*n);
275
}
276

  
277
static inline void rtas_st(target_ulong phys, int n, uint32_t val)
278
{
279
    stl_phys(phys + 4*n, val);
280
}
281

  
282
typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,
283
                              uint32_t nargs, target_ulong args,
284
                              uint32_t nret, target_ulong rets);
285
void spapr_rtas_register(const char *name, spapr_rtas_fn fn);
286
target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
287
                             uint32_t token, uint32_t nargs, target_ulong args,
288
                             uint32_t nret, target_ulong rets);
289
int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
290
                                 target_phys_addr_t rtas_size);
291

  
260 292
#endif /* !defined (__HW_SPAPR_H__) */
b/hw/spapr_hcall.c
248 248
    return H_SUCCESS;
249 249
}
250 250

  
251
spapr_hcall_fn hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
251
static target_ulong h_rtas(CPUState *env, sPAPREnvironment *spapr,
252
                           target_ulong opcode, target_ulong *args)
253
{
254
    target_ulong rtas_r3 = args[0];
255
    uint32_t token = ldl_phys(rtas_r3);
256
    uint32_t nargs = ldl_phys(rtas_r3 + 4);
257
    uint32_t nret = ldl_phys(rtas_r3 + 8);
258

  
259
    return spapr_rtas_call(spapr, token, nargs, rtas_r3 + 12,
260
                           nret, rtas_r3 + 12 + 4*nargs);
261
}
262

  
263
spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1];
264
spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE];
252 265

  
253 266
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
254 267
{
255
    spapr_hcall_fn old_fn;
268
    spapr_hcall_fn *slot;
269

  
270
    if (opcode <= MAX_HCALL_OPCODE) {
271
        assert((opcode & 0x3) == 0);
256 272

  
257
    assert(opcode <= MAX_HCALL_OPCODE);
258
    assert((opcode & 0x3) == 0);
273
        slot = &papr_hypercall_table[opcode / 4];
274
    } else {
275
        assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
259 276

  
260
    old_fn = hypercall_table[opcode / 4];
261 277

  
262
    assert(!old_fn || (fn == old_fn));
278
        slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
279
    }
263 280

  
264
    hypercall_table[opcode / 4] = fn;
281
    assert(!(*slot) || (fn == *slot));
282
    *slot = fn;
265 283
}
266 284

  
267 285
target_ulong spapr_hypercall(CPUState *env, target_ulong opcode,
......
274 292

  
275 293
    if ((opcode <= MAX_HCALL_OPCODE)
276 294
        && ((opcode & 0x3) == 0)) {
277
        spapr_hcall_fn fn = hypercall_table[opcode / 4];
295
        spapr_hcall_fn fn = papr_hypercall_table[opcode / 4];
296

  
297
        if (fn) {
298
            return fn(env, spapr, opcode, args);
299
        }
300
    } else if ((opcode >= KVMPPC_HCALL_BASE) &&
301
               (opcode <= KVMPPC_HCALL_MAX)) {
302
        spapr_hcall_fn fn = kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
278 303

  
279 304
        if (fn) {
280 305
            return fn(env, spapr, opcode, args);
......
291 316
    spapr_register_hypercall(H_ENTER, h_enter);
292 317
    spapr_register_hypercall(H_REMOVE, h_remove);
293 318
    spapr_register_hypercall(H_PROTECT, h_protect);
319

  
320
    /* qemu/KVM-PPC specific hcalls */
321
    spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
294 322
}
295 323
device_init(hypercall_init);
b/hw/spapr_rtas.c
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
}
b/pc-bios/spapr-rtas/Makefile
1
all: build-all
2
# Dummy command so that make thinks it has done something
3
	@true
4

  
5
include ../../config-host.mak
6
include $(SRC_PATH)/rules.mak
7

  
8
$(call set-vpath, $(SRC_PATH)/pc-bios/spapr-rtas)
9

  
10
.PHONY : all clean build-all
11

  
12
#CFLAGS += -I$(SRC_PATH)
13
#QEMU_CFLAGS = $(CFLAGS)
14

  
15
build-all: spapr-rtas.bin
16

  
17
%.img: %.o
18
	$(call quiet-command,$(CC) -nostdlib -o $@ $<,"  Building $(TARGET_DIR)$@")
19

  
20
%.bin: %.img
21
	$(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"  Building $(TARGET_DIR)$@")
22

  
23
clean:
24
	rm -f *.o *.d *.img *.bin *~
b/pc-bios/spapr-rtas/spapr-rtas.S
1
/*
2
 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
3
 *
4
 * Trivial in-partition RTAS implementation, based on a hypercall
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

  
28
#define KVMPPC_HCALL_BASE       0xf000
29
#define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
30

  
31
.globl	_start
32
_start:
33
	mr	4,3
34
	lis	3,KVMPPC_H_RTAS@h
35
	ori	3,3,KVMPPC_H_RTAS@l
36
	sc	1
37
	blr

Also available in: Unified diff