1a4b84608SBin Meng /*
2a4b84608SBin Meng * QEMU SiFive Test Finisher
3a4b84608SBin Meng *
4a4b84608SBin Meng * Copyright (c) 2018 SiFive, Inc.
5a4b84608SBin Meng *
6a4b84608SBin Meng * Test finisher memory mapped device used to exit simulation
7a4b84608SBin Meng *
8a4b84608SBin Meng * This program is free software; you can redistribute it and/or modify it
9a4b84608SBin Meng * under the terms and conditions of the GNU General Public License,
10a4b84608SBin Meng * version 2 or later, as published by the Free Software Foundation.
11a4b84608SBin Meng *
12a4b84608SBin Meng * This program is distributed in the hope it will be useful, but WITHOUT
13a4b84608SBin Meng * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14a4b84608SBin Meng * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15a4b84608SBin Meng * more details.
16a4b84608SBin Meng *
17a4b84608SBin Meng * You should have received a copy of the GNU General Public License along with
18a4b84608SBin Meng * this program. If not, see <http://www.gnu.org/licenses/>.
19a4b84608SBin Meng */
20a4b84608SBin Meng
21a4b84608SBin Meng #include "qemu/osdep.h"
22a4b84608SBin Meng #include "hw/sysbus.h"
23a4b84608SBin Meng #include "qapi/error.h"
24a4b84608SBin Meng #include "qemu/log.h"
25a4b84608SBin Meng #include "qemu/module.h"
26a4b84608SBin Meng #include "sysemu/runstate.h"
27a4b84608SBin Meng #include "hw/misc/sifive_test.h"
28*215128e4SClément Chigot #include "sysemu/sysemu.h"
29a4b84608SBin Meng
sifive_test_read(void * opaque,hwaddr addr,unsigned int size)30a4b84608SBin Meng static uint64_t sifive_test_read(void *opaque, hwaddr addr, unsigned int size)
31a4b84608SBin Meng {
32a4b84608SBin Meng return 0;
33a4b84608SBin Meng }
34a4b84608SBin Meng
sifive_test_write(void * opaque,hwaddr addr,uint64_t val64,unsigned int size)35a4b84608SBin Meng static void sifive_test_write(void *opaque, hwaddr addr,
36a4b84608SBin Meng uint64_t val64, unsigned int size)
37a4b84608SBin Meng {
38a4b84608SBin Meng if (addr == 0) {
39a4b84608SBin Meng int status = val64 & 0xffff;
40a4b84608SBin Meng int code = (val64 >> 16) & 0xffff;
41a4b84608SBin Meng switch (status) {
42a4b84608SBin Meng case FINISHER_FAIL:
43*215128e4SClément Chigot qemu_system_shutdown_request_with_code(
44*215128e4SClément Chigot SHUTDOWN_CAUSE_GUEST_PANIC, code);
45*215128e4SClément Chigot return;
46a4b84608SBin Meng case FINISHER_PASS:
47*215128e4SClément Chigot qemu_system_shutdown_request_with_code(
48*215128e4SClément Chigot SHUTDOWN_CAUSE_GUEST_SHUTDOWN, code);
49*215128e4SClément Chigot return;
50a4b84608SBin Meng case FINISHER_RESET:
51a4b84608SBin Meng qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
52a4b84608SBin Meng return;
53a4b84608SBin Meng default:
54a4b84608SBin Meng break;
55a4b84608SBin Meng }
56a4b84608SBin Meng }
57a4b84608SBin Meng qemu_log_mask(LOG_GUEST_ERROR, "%s: write: addr=0x%x val=0x%016" PRIx64 "\n",
58a4b84608SBin Meng __func__, (int)addr, val64);
59a4b84608SBin Meng }
60a4b84608SBin Meng
61a4b84608SBin Meng static const MemoryRegionOps sifive_test_ops = {
62a4b84608SBin Meng .read = sifive_test_read,
63a4b84608SBin Meng .write = sifive_test_write,
64a4b84608SBin Meng .endianness = DEVICE_NATIVE_ENDIAN,
65a4b84608SBin Meng .valid = {
66a4b84608SBin Meng .min_access_size = 2,
67a4b84608SBin Meng .max_access_size = 4
68a4b84608SBin Meng }
69a4b84608SBin Meng };
70a4b84608SBin Meng
sifive_test_init(Object * obj)71a4b84608SBin Meng static void sifive_test_init(Object *obj)
72a4b84608SBin Meng {
73a4b84608SBin Meng SiFiveTestState *s = SIFIVE_TEST(obj);
74a4b84608SBin Meng
75a4b84608SBin Meng memory_region_init_io(&s->mmio, obj, &sifive_test_ops, s,
76a4b84608SBin Meng TYPE_SIFIVE_TEST, 0x1000);
77a4b84608SBin Meng sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
78a4b84608SBin Meng }
79a4b84608SBin Meng
80a4b84608SBin Meng static const TypeInfo sifive_test_info = {
81a4b84608SBin Meng .name = TYPE_SIFIVE_TEST,
82a4b84608SBin Meng .parent = TYPE_SYS_BUS_DEVICE,
83a4b84608SBin Meng .instance_size = sizeof(SiFiveTestState),
84a4b84608SBin Meng .instance_init = sifive_test_init,
85a4b84608SBin Meng };
86a4b84608SBin Meng
sifive_test_register_types(void)87a4b84608SBin Meng static void sifive_test_register_types(void)
88a4b84608SBin Meng {
89a4b84608SBin Meng type_register_static(&sifive_test_info);
90a4b84608SBin Meng }
91a4b84608SBin Meng
type_init(sifive_test_register_types)92a4b84608SBin Meng type_init(sifive_test_register_types)
93a4b84608SBin Meng
94a4b84608SBin Meng
95a4b84608SBin Meng /*
96a4b84608SBin Meng * Create Test device.
97a4b84608SBin Meng */
98a4b84608SBin Meng DeviceState *sifive_test_create(hwaddr addr)
99a4b84608SBin Meng {
100a4b84608SBin Meng DeviceState *dev = qdev_new(TYPE_SIFIVE_TEST);
101a4b84608SBin Meng sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
102a4b84608SBin Meng sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
103a4b84608SBin Meng return dev;
104a4b84608SBin Meng }
105