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 Aug 28, 2016
1 parent 192f313 commit b1f388c
Show file tree
Hide file tree
Showing 13 changed files with 324 additions and 4 deletions.
2 changes: 2 additions & 0 deletions arch_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ int graphic_depth = 32;
#define QEMU_ARCH QEMU_ARCH_ALPHA
#elif defined(TARGET_ARM)
#define QEMU_ARCH QEMU_ARCH_ARM
#elif defined(TARGET_BFIN)
#define QEMU_ARCH QEMU_ARCH_BFIN
#elif defined(TARGET_CRIS)
#define QEMU_ARCH QEMU_ARCH_CRIS
#elif defined(TARGET_I386)
Expand Down
12 changes: 12 additions & 0 deletions default-configs/bfin-softmmu.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
1 change: 1 addition & 0 deletions include/sysemu/arch_init.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum {
QEMU_ARCH_UNICORE32 = (1 << 14),
QEMU_ARCH_MOXIE = (1 << 15),
QEMU_ARCH_TRICORE = (1 << 16),
QEMU_ARCH_BFIN = (1 << 17),
};

extern const uint32_t arch_type;
Expand Down
1 change: 1 addition & 0 deletions target-bfin/Makefile.objs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
obj-y += translate.o op_helper.o helper.o cpu.o gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o monitor.o
34 changes: 34 additions & 0 deletions target-bfin/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,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
cc->get_phys_page_debug = bfin_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_bfin_cpu;
#endif
}

static const TypeInfo bfin_cpu_type_info = {
Expand All @@ -129,7 +133,37 @@ typedef struct BlackfinCPUInfo {
} BlackfinCPUInfo;

static const BlackfinCPUInfo bfin_cpus[] = {
{ .name = "bf504", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf506", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf512", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf514", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf516", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf518", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf522", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf523", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf524", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf525", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf526", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf527", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf531", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf532", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf533", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf534", .initfn = bf5xx_cpu_initfn, },
/*{ .name = "bf535", .initfn = bf5xx_cpu_initfn, },*/
{ .name = "bf536", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf537", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf538", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf539", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf542", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf544", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf547", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf548", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf549", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf561", .initfn = bf5xx_cpu_initfn, },
{ .name = "bf592", .initfn = bf5xx_cpu_initfn, },
#ifdef CONFIG_USER_ONLY
{ .name = "any", .initfn = bf5xx_cpu_initfn, },
#endif
};

static void bfin_cpu_register(const BlackfinCPUInfo *info)
Expand Down
19 changes: 17 additions & 2 deletions target-bfin/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,25 @@ 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

static inline BlackfinCPU *cpu_bfin_init(const char *cpu_model)
{
return BFIN_CPU(cpu_generic_init(TYPE_BLACKFIN_CPU, cpu_model));
}

#define cpu_init(cpu_model) CPU(cpu_bfin_init(cpu_model))

#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, fprintf_function cpu_fprintf,
int flags);
hwaddr bfin_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
int bfin_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
int bfin_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);

Expand Down Expand Up @@ -225,14 +231,23 @@ enum astat_ops {
ASTAT_OP_VECTOR_SUB_ADD, /* -|+ */
};

void cpu_list(FILE *f, fprintf_function cpu_fprintf);
int cpu_bfin_signal_handler(int host_signum, void *pinfo, void *puc);
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;
}
77 changes: 77 additions & 0 deletions target-bfin/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,81 @@ 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

/* 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, "any") == 0) {
return 1;
} else if (strcmp(name_b, "any") == 0) {
return -1;
} else {
return strcmp(name_a, name_b);
}
}

static void cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
CPUListState *s = user_data;

(*s->cpu_fprintf)(s->file, " %s\n",
object_class_get_name(oc));
}

void cpu_bfin_list(FILE *f, fprintf_function cpu_fprintf)
{
CPUListState s = {
.file = f,
.cpu_fprintf = cpu_fprintf,
};
GSList *list;

list = object_class_get_list(TYPE_BLACKFIN_CPU, false);
list = g_slist_sort(list, cpu_list_compare);
(*cpu_fprintf)(f, "Available CPUs:\n");
g_slist_foreach(list, cpu_list_entry, &s);
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-2016 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"

#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,
.minimum_version_id_old = 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()
}
};
80 changes: 80 additions & 0 deletions target-bfin/monitor.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* QEMU Blackfin CPU
*
* Copyright 2007-2016 Mike Frysinger
* Copyright 2007-2011 Analog Devices, Inc.
*
* Licensed under the Lesser GPL 2 or later.
*/

#include "qemu/osdep.h"
#include "cpu.h"
#include "monitor/monitor.h"
#include "monitor/hmp-target.h"
#include "hmp.h"

const MonitorDef monitor_defs[] = {
#define _REG(name, var) { name, offsetof(CPUArchState, var) }
#define REG(name) _REG(#name, name)
#define _REG_ARR(name, idx, arr) _REG(#name #idx, arr[idx])
#define REG_ARR(name, idx) _REG_ARR(name, idx, name##reg)
_REG_ARR(r, 0, dreg),
_REG_ARR(r, 1, dreg),
_REG_ARR(r, 2, dreg),
_REG_ARR(r, 3, dreg),
_REG_ARR(r, 4, dreg),
_REG_ARR(r, 5, dreg),
_REG_ARR(r, 6, dreg),
_REG_ARR(r, 7, dreg),
REG_ARR(p, 0),
REG_ARR(p, 1),
REG_ARR(p, 2),
REG_ARR(p, 3),
REG_ARR(p, 4),
REG_ARR(p, 5),
REG_ARR(i, 0),
REG_ARR(i, 1),
REG_ARR(i, 2),
REG_ARR(i, 3),
REG_ARR(m, 0),
REG_ARR(m, 1),
REG_ARR(m, 2),
REG_ARR(m, 3),
REG_ARR(b, 0),
REG_ARR(b, 1),
REG_ARR(b, 2),
REG_ARR(b, 3),
REG_ARR(l, 0),
REG_ARR(l, 1),
REG_ARR(l, 2),
REG_ARR(l, 3),
REG(rets),
REG_ARR(lc, 0),
REG_ARR(lc, 1),
REG_ARR(lt, 0),
REG_ARR(lt, 1),
REG_ARR(lb, 0),
REG_ARR(lb, 1),
_REG_ARR(cycles, 0, cycles),
_REG_ARR(cycles, 1, cycles),
_REG("usp", uspreg),
_REG("fp", fpreg),
_REG("sp", spreg),
REG(seqstat),
REG(syscfg),
REG(reti),
REG(retx),
REG(retn),
REG(rete),
REG(emudat),
REG(pc),
#undef REG_ARR
#undef _REG_ARR
#undef REG
#undef _REG
};

const MonitorDef *target_monitor_defs(void)
{
return monitor_defs;
}
Loading

0 comments on commit b1f388c

Please sign in to comment.