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