Skip to content

Commit

Permalink
Blackfin: add softmmu support
Browse files Browse the repository at this point in the history
Semi-functional -- it can run Das U-Boot!

Signed-off-by: Mike Frysinger <[email protected]>
  • Loading branch information
vapier committed Dec 1, 2023
1 parent db1326d commit 40844d6
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 4 deletions.
12 changes: 12 additions & 0 deletions configs/devices/bfin-softmmu/default.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Default configuration for arm-softmmu

CONFIG_NAND=y
CONFIG_ECC=y
CONFIG_SERIAL=y
CONFIG_SD=y
CONFIG_SSI_SD=y
CONFIG_SMC91C111=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
CONFIG_SSI=y
CONFIG_SSI_M25P80=y
2 changes: 2 additions & 0 deletions configs/targets/bfin-softmmu.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TARGET_ARCH=bfin
TARGET_ALIGNED_ONLY=y
1 change: 1 addition & 0 deletions include/sysemu/arch_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ enum {
QEMU_ARCH_AVR = (1 << 21),
QEMU_ARCH_HEXAGON = (1 << 22),
QEMU_ARCH_LOONGARCH = (1 << 23),
QEMU_ARCH_BFIN = (1 << 24),
};

extern const uint32_t arch_type;
Expand Down
42 changes: 42 additions & 0 deletions target/bfin/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ static ObjectClass *bfin_cpu_class_by_name(const char *cpu_model)
return oc;
}

#ifndef CONFIG_USER_ONLY
#include "hw/core/sysemu-cpu-ops.h"

static const struct SysemuCPUOps bfin_sysemu_ops = {
.get_phys_page_debug = bfin_cpu_get_phys_page_debug,
};
#endif

#ifdef CONFIG_TCG
static const struct TCGCPUOps bfin_tcg_ops = {
.initialize = bfin_translate_init,
Expand Down Expand Up @@ -132,6 +140,10 @@ static void bfin_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_write_register = bfin_cpu_gdb_write_register;
cc->dump_state = bfin_cpu_dump_state;
cc->disas_set_info = bfin_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
dc->vmsd = &vmstate_bfin_cpu;
cc->sysemu_ops = &bfin_sysemu_ops;
#endif

#ifdef CONFIG_TCG
cc->tcg_ops = &bfin_tcg_ops;
Expand Down Expand Up @@ -161,7 +173,37 @@ static const TypeInfo bfin_cpu_type_infos[] = {
.class_size = sizeof(BlackfinCPUClass),
.class_init = bfin_cpu_class_init,
},
DEFINE_BLACKFIN_CPU_TYPE("bf504"),
DEFINE_BLACKFIN_CPU_TYPE("bf506"),
DEFINE_BLACKFIN_CPU_TYPE("bf512"),
DEFINE_BLACKFIN_CPU_TYPE("bf514"),
DEFINE_BLACKFIN_CPU_TYPE("bf516"),
DEFINE_BLACKFIN_CPU_TYPE("bf518"),
DEFINE_BLACKFIN_CPU_TYPE("bf522"),
DEFINE_BLACKFIN_CPU_TYPE("bf523"),
DEFINE_BLACKFIN_CPU_TYPE("bf524"),
DEFINE_BLACKFIN_CPU_TYPE("bf525"),
DEFINE_BLACKFIN_CPU_TYPE("bf526"),
DEFINE_BLACKFIN_CPU_TYPE("bf527"),
DEFINE_BLACKFIN_CPU_TYPE("bf531"),
DEFINE_BLACKFIN_CPU_TYPE("bf532"),
DEFINE_BLACKFIN_CPU_TYPE("bf533"),
DEFINE_BLACKFIN_CPU_TYPE("bf534"),
/*DEFINE_BLACKFIN_CPU_TYPE("bf535"),*/
DEFINE_BLACKFIN_CPU_TYPE("bf536"),
DEFINE_BLACKFIN_CPU_TYPE("bf537"),
DEFINE_BLACKFIN_CPU_TYPE("bf538"),
DEFINE_BLACKFIN_CPU_TYPE("bf539"),
DEFINE_BLACKFIN_CPU_TYPE("bf542"),
DEFINE_BLACKFIN_CPU_TYPE("bf544"),
DEFINE_BLACKFIN_CPU_TYPE("bf547"),
DEFINE_BLACKFIN_CPU_TYPE("bf548"),
DEFINE_BLACKFIN_CPU_TYPE("bf549"),
DEFINE_BLACKFIN_CPU_TYPE("bf561"),
DEFINE_BLACKFIN_CPU_TYPE("bf592"),
#ifdef CONFIG_USER_ONLY
DEFINE_BLACKFIN_CPU_TYPE("any"),
#endif
};

DEFINE_TYPES(bfin_cpu_type_infos);
19 changes: 17 additions & 2 deletions target/bfin/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,21 @@ static inline BlackfinCPU *bfin_env_get_cpu(CPUArchState *env)

#define ENV_OFFSET offsetof(BlackfinCPU, env)

#ifndef CONFIG_USER_ONLY
extern const struct VMStateDescription vmstate_bfin_cpu;
#endif

#define BLACKFIN_CPU_TYPE_SUFFIX "-" TYPE_BLACKFIN_CPU
#define BLACKFIN_CPU_TYPE_NAME(model) (model BLACKFIN_CPU_TYPE_SUFFIX)
#define CPU_RESOLVING_TYPE TYPE_BLACKFIN_CPU

#define cpu_list cpu_bfin_list
#define cpu_signal_handler cpu_bfin_signal_handler

void bfin_cpu_do_interrupt(CPUState *cpu);

void bfin_cpu_dump_state(CPUState *cs, FILE *f, int flags);
hwaddr bfin_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int bfin_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int bfin_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);

Expand Down Expand Up @@ -210,6 +216,7 @@ enum astat_ops {
ASTAT_OP_VECTOR_SUB_ADD, /* -|+ */
};

void cpu_list(void);
bool bfin_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx, bool probe,
uintptr_t retaddr);
Expand All @@ -219,8 +226,16 @@ void bfin_translate_init(void);
extern const char * const greg_names[];
extern const char *get_allreg_name(int grp, int reg);

#define MMU_KERNEL_IDX 0
#define MMU_USER_IDX 1
#include "dv-bfin_cec.h"

/* */
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _user
#define MMU_USER_IDX 1
static inline int cpu_mmu_index(CPUArchState *env, bool ifetch)
{
return !cec_is_supervisor_mode(env);
}

int cpu_bfin_handle_mmu_fault(CPUState *cs, target_ulong address,
MMUAccessType access_type, int mmu_idx);
Expand Down
5 changes: 5 additions & 0 deletions target/bfin/dv-bfin_cec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdbool.h>
static inline bool cec_is_supervisor_mode(CPUBfinState *env)
{
return true;
}
97 changes: 97 additions & 0 deletions target/bfin/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
*/

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "qemu/qemu-print.h"

#if defined(CONFIG_USER_ONLY)

void bfin_cpu_do_interrupt(CPUState *cs)
{
Expand All @@ -25,6 +29,43 @@ int cpu_handle_mmu_fault(CPUState *cs, target_ulong address,
return 1;
}

#else

void bfin_cpu_do_interrupt(CPUState *cs)
{
BlackfinCPU *cpu = BFIN_CPU(cs);
CPUBfinState *env = &cpu->env;

qemu_log_mask(CPU_LOG_INT,
"exception at pc=%x type=%x\n", env->pc, cs->exception_index);

switch (cs->exception_index) {
default:
cpu_abort(cs, "unhandled exception type=%d\n",
cs->exception_index);
break;
}
}

hwaddr bfin_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
{
return addr & TARGET_PAGE_MASK;
}

int cpu_handle_mmu_fault(CPUState *cs, target_ulong address,
MMUAccessType access_type, int mmu_idx)
{
int prot;

address &= TARGET_PAGE_MASK;
prot = PAGE_BITS;
tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);

return 0;
}

#endif

/* Try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
Expand All @@ -33,7 +74,63 @@ bool bfin_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx, bool probe,
uintptr_t retaddr)
{
#ifdef CONFIG_USER_ONLY
// TODO: This should depend on access_type.
cs->exception_index = EXCP_DCPLB_VIOLATE;
cpu_loop_exit_restore(cs, retaddr);
#else
int ret;

ret = cpu_bfin_handle_mmu_fault(cs, address, access_type, mmu_idx);
if (likely(!ret)) {
return true;
} else if (probe) {
return false;
} else {
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr);
cpu_loop_exit(cs);
}
#endif
}

/* Sort alphabetically by type name, except for "any". */
static gint cpu_list_compare(gconstpointer a, gconstpointer b)
{
ObjectClass *class_a = (ObjectClass *)a;
ObjectClass *class_b = (ObjectClass *)b;
const char *name_a, *name_b;

name_a = object_class_get_name(class_a);
name_b = object_class_get_name(class_b);
if (strcmp(name_a, BLACKFIN_CPU_TYPE_NAME("any")) == 0) {
return 1;
} else if (strcmp(name_b, BLACKFIN_CPU_TYPE_NAME("any")) == 0) {
return -1;
} else {
return strcmp(name_a, name_b);
}
}

static void cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
const char *typename;
char *name;

typename = object_class_get_name(oc);
name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_BLACKFIN_CPU));
qemu_printf(" %s\n", name);
g_free(name);
}

void cpu_bfin_list(void)
{
GSList *list;

list = object_class_get_list(TYPE_BLACKFIN_CPU, false);
list = g_slist_sort(list, cpu_list_compare);
qemu_printf("Available CPUs:\n");
g_slist_foreach(list, cpu_list_entry, NULL);
g_slist_free(list);
}
1 change: 1 addition & 0 deletions target/bfin/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

DEF_HELPER_FLAGS_3(raise_exception, TCG_CALL_NO_WG, void, env, i32, i32)
DEF_HELPER_FLAGS_5(memalign, TCG_CALL_NO_WG, void, env, i32, i32, i32, i32)
DEF_HELPER_FLAGS_2(require_supervisor, TCG_CALL_NO_WG, void, env, i32)

DEF_HELPER_FLAGS_4(dbga_l, TCG_CALL_NO_WG, void, env, i32, i32, i32)
DEF_HELPER_FLAGS_4(dbga_h, TCG_CALL_NO_WG, void, env, i32, i32, i32)
Expand Down
53 changes: 53 additions & 0 deletions target/bfin/machine.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Blackfin cpu save/load logic
*
* Copyright 2007-2023 Mike Frysinger
* Copyright 2007-2011 Analog Devices, Inc.
*
* Licensed under the Lesser GPL 2 or later.
*/

#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/boards.h"
#include "migration/cpu.h"

#define VMSTATE_AUTO32_ARRAY(member) \
VMSTATE_UINT32_ARRAY(member, CPUArchState, ARRAY_SIZE(((CPUArchState *)NULL)->member))
#define VMSTATE_AUTO64_ARRAY(member) \
VMSTATE_UINT64_ARRAY(member, CPUArchState, ARRAY_SIZE(((CPUArchState *)NULL)->member))
#define _VMSTATE_UINT32(member) \
VMSTATE_UINT32(member, CPUArchState)
const VMStateDescription vmstate_bfin_cpu = {
.name = "cpu",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_AUTO32_ARRAY(dreg),
VMSTATE_AUTO32_ARRAY(preg),
VMSTATE_AUTO32_ARRAY(ireg),
VMSTATE_AUTO32_ARRAY(mreg),
VMSTATE_AUTO32_ARRAY(breg),
VMSTATE_AUTO32_ARRAY(lreg),
VMSTATE_AUTO64_ARRAY(areg),
_VMSTATE_UINT32(rets),
VMSTATE_AUTO32_ARRAY(lcreg),
VMSTATE_AUTO32_ARRAY(ltreg),
VMSTATE_AUTO32_ARRAY(lbreg),
VMSTATE_AUTO32_ARRAY(cycles),
_VMSTATE_UINT32(uspreg),
_VMSTATE_UINT32(seqstat),
_VMSTATE_UINT32(syscfg),
_VMSTATE_UINT32(reti),
_VMSTATE_UINT32(retx),
_VMSTATE_UINT32(retn),
_VMSTATE_UINT32(rete),
_VMSTATE_UINT32(emudat),
_VMSTATE_UINT32(pc),
VMSTATE_AUTO32_ARRAY(astat),
_VMSTATE_UINT32(astat_op),
VMSTATE_AUTO32_ARRAY(astat_arg),
VMSTATE_END_OF_LIST()
}
};
7 changes: 7 additions & 0 deletions target/bfin/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ bfin_ss.add(files(
'translate.c',
))

bfin_system_ss = ss.source_set()
bfin_system_ss.add(files(
'machine.c',
'monitor.c',
))

target_arch += {'bfin': bfin_ss}
target_system_arch += {'bfin': bfin_system_ss}
Loading

0 comments on commit 40844d6

Please sign in to comment.