xref: /openbmc/qemu/hw/riscv/riscv_hart.c (revision a68694cd)
14b50b8d9SMichael Clark /*
24b50b8d9SMichael Clark  * QEMU RISCV Hart Array
34b50b8d9SMichael Clark  *
44b50b8d9SMichael Clark  * Copyright (c) 2017 SiFive, Inc.
54b50b8d9SMichael Clark  *
691c98585SBin Meng  * Holds the state of a homogeneous array of RISC-V harts
74b50b8d9SMichael Clark  *
84b50b8d9SMichael Clark  * This program is free software; you can redistribute it and/or modify it
94b50b8d9SMichael Clark  * under the terms and conditions of the GNU General Public License,
104b50b8d9SMichael Clark  * version 2 or later, as published by the Free Software Foundation.
114b50b8d9SMichael Clark  *
124b50b8d9SMichael Clark  * This program is distributed in the hope it will be useful, but WITHOUT
134b50b8d9SMichael Clark  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
144b50b8d9SMichael Clark  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
154b50b8d9SMichael Clark  * more details.
164b50b8d9SMichael Clark  *
174b50b8d9SMichael Clark  * You should have received a copy of the GNU General Public License along with
184b50b8d9SMichael Clark  * this program.  If not, see <http://www.gnu.org/licenses/>.
194b50b8d9SMichael Clark  */
204b50b8d9SMichael Clark 
214b50b8d9SMichael Clark #include "qemu/osdep.h"
224b50b8d9SMichael Clark #include "qapi/error.h"
230b8fa32fSMarkus Armbruster #include "qemu/module.h"
2471e8a915SMarkus Armbruster #include "sysemu/reset.h"
254b50b8d9SMichael Clark #include "hw/sysbus.h"
264b50b8d9SMichael Clark #include "target/riscv/cpu.h"
27a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
284b50b8d9SMichael Clark #include "hw/riscv/riscv_hart.h"
294b50b8d9SMichael Clark 
304b50b8d9SMichael Clark static Property riscv_harts_props[] = {
314b50b8d9SMichael Clark     DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
32e8c56787SBin Meng     DEFINE_PROP_UINT32("hartid-base", RISCVHartArrayState, hartid_base, 0),
334b50b8d9SMichael Clark     DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
34*4100d5e6SBin Meng     DEFINE_PROP_UINT64("resetvec", RISCVHartArrayState, resetvec,
35*4100d5e6SBin Meng                        DEFAULT_RSTVEC),
364b50b8d9SMichael Clark     DEFINE_PROP_END_OF_LIST(),
374b50b8d9SMichael Clark };
384b50b8d9SMichael Clark 
riscv_harts_cpu_reset(void * opaque)394b50b8d9SMichael Clark static void riscv_harts_cpu_reset(void *opaque)
404b50b8d9SMichael Clark {
414b50b8d9SMichael Clark     RISCVCPU *cpu = opaque;
424b50b8d9SMichael Clark     cpu_reset(CPU(cpu));
434b50b8d9SMichael Clark }
444b50b8d9SMichael Clark 
riscv_hart_realize(RISCVHartArrayState * s,int idx,char * cpu_type,Error ** errp)453e9a88c3SMarkus Armbruster static bool riscv_hart_realize(RISCVHartArrayState *s, int idx,
4691c98585SBin Meng                                char *cpu_type, Error **errp)
474b50b8d9SMichael Clark {
489fc7fc4dSMarkus Armbruster     object_initialize_child(OBJECT(s), "harts[*]", &s->harts[idx], cpu_type);
49*4100d5e6SBin Meng     qdev_prop_set_uint64(DEVICE(&s->harts[idx]), "resetvec", s->resetvec);
50e8c56787SBin Meng     s->harts[idx].env.mhartid = s->hartid_base + idx;
5191c98585SBin Meng     qemu_register_reset(riscv_harts_cpu_reset, &s->harts[idx]);
523e9a88c3SMarkus Armbruster     return qdev_realize(DEVICE(&s->harts[idx]), NULL, errp);
534b50b8d9SMichael Clark }
5491c98585SBin Meng 
riscv_harts_realize(DeviceState * dev,Error ** errp)5591c98585SBin Meng static void riscv_harts_realize(DeviceState *dev, Error **errp)
5691c98585SBin Meng {
5791c98585SBin Meng     RISCVHartArrayState *s = RISCV_HART_ARRAY(dev);
5891c98585SBin Meng     int n;
5991c98585SBin Meng 
6091c98585SBin Meng     s->harts = g_new0(RISCVCPU, s->num_harts);
6191c98585SBin Meng 
6291c98585SBin Meng     for (n = 0; n < s->num_harts; n++) {
633e9a88c3SMarkus Armbruster         if (!riscv_hart_realize(s, n, s->cpu_type, errp)) {
643e9a88c3SMarkus Armbruster             return;
653e9a88c3SMarkus Armbruster         }
6691c98585SBin Meng     }
674b50b8d9SMichael Clark }
684b50b8d9SMichael Clark 
riscv_harts_class_init(ObjectClass * klass,void * data)694b50b8d9SMichael Clark static void riscv_harts_class_init(ObjectClass *klass, void *data)
704b50b8d9SMichael Clark {
714b50b8d9SMichael Clark     DeviceClass *dc = DEVICE_CLASS(klass);
724b50b8d9SMichael Clark 
734f67d30bSMarc-André Lureau     device_class_set_props(dc, riscv_harts_props);
744b50b8d9SMichael Clark     dc->realize = riscv_harts_realize;
754b50b8d9SMichael Clark }
764b50b8d9SMichael Clark 
774b50b8d9SMichael Clark static const TypeInfo riscv_harts_info = {
784b50b8d9SMichael Clark     .name          = TYPE_RISCV_HART_ARRAY,
794b50b8d9SMichael Clark     .parent        = TYPE_SYS_BUS_DEVICE,
804b50b8d9SMichael Clark     .instance_size = sizeof(RISCVHartArrayState),
814b50b8d9SMichael Clark     .class_init    = riscv_harts_class_init,
824b50b8d9SMichael Clark };
834b50b8d9SMichael Clark 
riscv_harts_register_types(void)844b50b8d9SMichael Clark static void riscv_harts_register_types(void)
854b50b8d9SMichael Clark {
864b50b8d9SMichael Clark     type_register_static(&riscv_harts_info);
874b50b8d9SMichael Clark }
884b50b8d9SMichael Clark 
894b50b8d9SMichael Clark type_init(riscv_harts_register_types)
90