Skip to content

Commit

Permalink
Pretender (#3)
Browse files Browse the repository at this point in the history
* ARM: added a configurable machine

* Small fixes

* Fixed compilation error

* Support for system-wide named semaphores

* Added support for message queues

* IPC: fixes permission on message queues and semaphores creation

* Message queues: non-blocking

Conflicts:
	include/qemu/thread-posix.h

* Avatar: Modifications to the IPC interface

Extracted from 6e31210a3c13f4b6db7d7db5262cc47278e1f693

* Started the memory forwarder device

* Configurable: entry address and endianness

* somewhat working remotememoryreadrequests

* RemoteMemory!

* Experimental removal of ram-resizable flag

* Small fixes on the configurable machine

* error handling in remote memory

* integrated change in qapi

* Hotfix: Don't bail out on failed rmr/rmw

* Fixed bug regarding entrypoint, removed load_kernel and set_endianness from configurable machine

* Cleaned up configurable machine and added MIPS-support

* Adjusted RMemory to hold pc

* bugfix in configurable machine

* Banked registers!

* move header files to include/hw/avatar

* Refactored avatar mqueueing

* starting on interrupt-injection

* Unclean hackish commit to be squashed later

* WIP: interrupt_exec and avatar_log

* added log_item for avatar

* minimal changes

* nvic-related changes (untested!)

* bugfixes

* Banked registers!

* nvic-write-forward update

* let\'s return xpsr and not cpsr

* Refactored avatar mqueueing

* new logging for interrupts

* move header files to include/hw/avatar

* minor fixes

* ignore/unignore irq returns

* not enabling - stuff should be fine

* additional interrupt notifications and acks

* bugfix

* Allow board init for more than armv7m

* format strings are hard

* Add set_nvic_base to qmp

* I meant vector table base, not nvic base

* fix compile on 18.04

* Update to comply with qemu-3.1

* cpu-model -> cpu-type

* make usage of the new ARM_CPU_TYPE_NAME macro

* temporary race condition hotfix: don't emit qapi_resume/stop
  • Loading branch information
mariusmue committed Jan 21, 2020
1 parent 59c36a3 commit 2de8b91
Show file tree
Hide file tree
Showing 15 changed files with 6,775 additions and 25 deletions.
8 changes: 4 additions & 4 deletions cpus.c
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,7 @@ int vm_stop(RunState state)
return 0;
}

return do_vm_stop(state, true);
return do_vm_stop(state, false);
}

/**
Expand All @@ -2194,13 +2194,13 @@ int vm_prepare_start(void)
* the STOP event.
*/
if (runstate_is_running()) {
qapi_event_send_stop();
qapi_event_send_resume();
//qapi_event_send_stop();
//qapi_event_send_resume();
return -1;
}

/* We are sending this now, but the CPUs will be resumed shortly later */
qapi_event_send_resume();
//qapi_event_send_resume();

cpu_enable_ticks();
runstate_set(RUN_STATE_RUNNING);
Expand Down
1 change: 1 addition & 0 deletions hw/avatar/Makefile.objs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
obj-$(TARGET_ARM) += avatar_posix.o configurable_machine.o remote_memory.o arm_helper.o
obj-$(TARGET_MIPS) += avatar_posix.o configurable_machine.o remote_memory.o
obj-$(CONFIG_SOFTMMU) += interrupts.o
20 changes: 10 additions & 10 deletions hw/avatar/configurable_machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#ifdef TARGET_ARM
#include "target/arm/cpu.h"
#include "hw/arm/arm.h"
#include "hw/arm/armv7m.h"
#include "hw/avatar/arm_helper.h"
#endif

Expand Down Expand Up @@ -66,6 +67,7 @@ static inline void set_feature(CPUARMState *env, int feature)

// For now, this function is unused so let's prevent the compiler from failing.
static inline void unset_feature(CPUARMState *env, int feature) __attribute__ ((unused));

static inline void unset_feature(CPUARMState *env, int feature)
{
env->features &= ~(1ULL << feature);
Expand Down Expand Up @@ -111,7 +113,6 @@ static QDict * load_configuration(const char * filename)
exit(1);
}


obj_dict = qobject_to(QDict, obj);
if (!obj_dict) {
qobject_unref(obj);
Expand Down Expand Up @@ -338,7 +339,7 @@ static void init_memory_area(QDict *mapping, const char *kernel_filename)

}

printf("Configurable: Inserting 0x%"
printf("Configurable: Inserting %"
PRIx64 " bytes of data in memory region %s\n", data_size, name);
//Size of data to put into a RAM region needs to fit in the RAM region
g_assert(data_size <= size);
Expand Down Expand Up @@ -439,7 +440,6 @@ static ARMCPU *create_cpu(MachineState * ms, QDict *conf)
DeviceState *dstate; //generic device if CPU can be initiliazed via qdev-API
int num_irq = 64;


if (qdict_haskey(conf, "cpu_model"))
{
cpu_model = qdict_get_str(conf, "cpu_model");
Expand Down Expand Up @@ -478,28 +478,28 @@ static ARMCPU *create_cpu(MachineState * ms, QDict *conf)
exit(1);
}

cpuobj = object_new(object_class_get_name(cpu_oc));
cpuobj = object_new(object_class_get_name(cpu_oc));

object_property_set_bool(cpuobj, true, "realized", &error_fatal);
cpuu = ARM_CPU(cpuobj);
object_property_set_bool(cpuobj, true, "realized", &error_fatal);
cpuu = ARM_CPU(cpuobj);
}

env = (CPUState *) &(cpuu->env);
if (!env)
{
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}

avatar_add_banked_registers(cpuu);
set_feature(&cpuu->env, ARM_FEATURE_CONFIGURABLE);
return cpuu;
}


#elif TARGET_MIPS
static MIPSCPU *create_cpu(MachineState * ms, QDict *conf)
{
const char *cpu_model = ms->cpu_type;
i
MIPSCPU *cpuu;
CPUState *cpu;

Expand Down
180 changes: 180 additions & 0 deletions hw/avatar/interrupts.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "qemu-common.h"
#include "qapi/qapi-commands-avatar.h"
#include "qapi/error.h"

#include "hw/sysbus.h"
#include "sysemu/sysemu.h"

#ifdef TARGET_ARM
#include "target/arm/cpu.h"
#elif TARGET_MIPS
#include "target/mips/cpu.h"
#endif

#include "hw/avatar/interrupts.h"
#include "hw/avatar/avatar_posix.h"
#include "hw/avatar/remote_memory.h"


static QemuAvatarMessageQueue *irq_rx_queue_ref = NULL;
static QemuAvatarMessageQueue *irq_tx_queue_ref = NULL;

extern QemuAvatarMessageQueue *rmem_rx_queue_ref;
extern QemuAvatarMessageQueue *rmem_tx_queue_ref;

static uint64_t req_id;

static bool armv7m_exception_handling_enabled = false;
static uint8_t ignore_irq_return_map[32] = {0};


void qmp_avatar_armv7m_set_vector_table_base(int64_t num_cpu, int64_t base, Error **errp)
{
#ifdef TARGET_ARM
qemu_log_mask(LOG_AVATAR, "Changing NVIC base to%lx\n", base & 0xffffff80);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(num_cpu));
/* MM: qemu now has multiple vecbases, we may need to fix this */
armcpu->env.v7m.vecbase[armcpu->env.v7m.secure] = base & 0xffffff80;
#endif
}


void avatar_armv7m_nvic_forward_write(uint32_t offset, uint32_t value, unsigned size){
int ret;
RemoteMemoryResp resp;

qemu_log_mask(LOG_AVATAR, "armv7m nvic write at offset 0x%x\n", offset);
qemu_log_flush();
if(!armv7m_exception_handling_enabled){
return;
}

memset(&resp, 0, sizeof(resp));

uint64_t pc = get_current_pc();

//for now, assusme nvic at the standard location at 0xE000E000
MemoryForwardReq request = {req_id++, pc, 0xe000e000+offset, value, size, AVATAR_WRITE};

qemu_avatar_mq_send(rmem_tx_queue_ref, &request, sizeof(request));
ret = qemu_avatar_mq_receive(rmem_rx_queue_ref, &resp, sizeof(resp));
if(!resp.success || (resp.id != request.id)){

error_report("RemoteMemoryWrite for NVIC failed (%d)!\n", ret);
exit(1);
}
}

void qmp_avatar_armv7m_enable_irq(const char *irq_rx_queue_name,
const char *irq_tx_queue_name,
const char *rmem_rx_queue_name,
const char *rmem_tx_queue_name, Error **errp)
{
if(irq_rx_queue_ref == NULL){
irq_rx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_read(irq_rx_queue_ref, irq_rx_queue_name,
sizeof(V7MInterruptResp));
}
if(irq_tx_queue_ref == NULL){
irq_tx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_write(irq_tx_queue_ref, irq_tx_queue_name,
sizeof(V7MInterruptReq));
}

if(rmem_rx_queue_ref == NULL){
rmem_rx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_read(rmem_rx_queue_ref, rmem_rx_queue_name, sizeof(RemoteMemoryResp));
}
if(rmem_tx_queue_ref == NULL){
rmem_tx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_write(rmem_tx_queue_ref, rmem_tx_queue_name, sizeof(MemoryForwardReq));
}

armv7m_exception_handling_enabled = true;
qemu_log_mask(LOG_AVATAR, "armv7m interrupt injection enabled\n");
qemu_log_flush();
}


void qmp_avatar_armv7m_disable_irq(Error **errp)
{
qemu_log_mask(LOG_AVATAR, "armv7m interrupt injection disabled\n");
armv7m_exception_handling_enabled = false;
qemu_log_flush();
}


void qmp_avatar_armv7m_ignore_irq_return(int64_t num_irq, Error **errp)
{
ignore_irq_return_map[num_irq/8] |= 1 << num_irq % 8;
}

void qmp_avatar_armv7m_unignore_irq_return(int64_t num_irq, Error **errp)
{
ignore_irq_return_map[num_irq/8] &= 0 << num_irq % 8;
}

void qmp_avatar_armv7m_inject_irq(int64_t num_cpu,int64_t num_irq, Error **errp)
{
#ifdef TARGET_ARM
qemu_log_mask(LOG_AVATAR, "Injecting exception 0x%lx\n", num_irq);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(num_cpu));
CPUARMState *env = &armcpu->env;
/* MM: for now, we can only inject non-secure irqs */
armv7m_nvic_set_pending(env->nvic, num_irq, false);
#endif
}


void avatar_armv7m_exception_exit(int irq, uint32_t type)
{
int ret;
V7MInterruptResp resp;
V7MInterruptReq request = {req_id++, irq, INTERRUPT_EXIT, type};

if( (ignore_irq_return_map[irq/8] & 1 << irq % 8) || !armv7m_exception_handling_enabled)
{
qemu_log_mask(LOG_AVATAR, "Returning form 0x%x - Ignored by avatar\n", irq);
}
else{
qemu_log_mask(LOG_AVATAR, "Returning form 0x%x\n", irq);
memset(&resp, 0, sizeof(resp));

qemu_avatar_mq_send(irq_tx_queue_ref, &request, sizeof(request));
ret = qemu_avatar_mq_receive(irq_rx_queue_ref, &resp, sizeof(resp));

if(!resp.success || (resp.id != request.id) || (resp.operation != INTERRUPT_EXIT) ){
error_report("ARMv7mInterruptRequest failed (%d)!\n", ret);
exit(1);
}
}
}

void avatar_armv7m_exception_enter(int irq)
{
int ret;
V7MInterruptResp resp;
V7MInterruptReq request = {req_id++, irq, INTERRUPT_ENTER, 0};

if( (ignore_irq_return_map[irq/8] & 1 << irq % 8) || !armv7m_exception_handling_enabled)
{
qemu_log_mask(LOG_AVATAR, "Entered IRQ 0x%x - Ignored by avatar\n", irq);
}
else{
qemu_log_mask(LOG_AVATAR, "Entering IRQ 0x%x\n", irq);
memset(&resp, 0, sizeof(resp));

qemu_avatar_mq_send(irq_tx_queue_ref, &request, sizeof(request));
ret = qemu_avatar_mq_receive(irq_rx_queue_ref, &resp, sizeof(resp));

if(!resp.success || (resp.id != request.id) || (resp.operation != INTERRUPT_ENTER)){
error_report("ARMv7mInterruptRequest failed (%d)!\n", ret);
exit(1);
}
}
}

22 changes: 12 additions & 10 deletions hw/avatar/remote_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "qemu/error-report.h"
#include "hw/sysbus.h"

#include "hw/avatar/remote_memory.h"
#include "hw/avatar/avatar_posix.h"
#include "hw/avatar/remote_memory.h"

Expand Down Expand Up @@ -102,11 +103,12 @@ static Property avatar_rmemory_properties[] = {

//}

QemuAvatarMessageQueue *rmem_rx_queue_ref = NULL;
QemuAvatarMessageQueue *rmem_tx_queue_ref = NULL;

static void avatar_rmemory_realize(DeviceState *dev, Error **errp)
{

static QemuAvatarMessageQueue *rx_queue_ref = NULL;
static QemuAvatarMessageQueue *tx_queue_ref = NULL;


AvatarRMemoryState *s = AVATAR_RMEMORY(dev);
Expand All @@ -115,17 +117,17 @@ static void avatar_rmemory_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);

if(rx_queue_ref == NULL){
rx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_read(rx_queue_ref, s->rx_queue_name, sizeof(RemoteMemoryResp));
if(rmem_rx_queue_ref == NULL){
rmem_rx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_read(rmem_rx_queue_ref, s->rx_queue_name, sizeof(RemoteMemoryResp));
}
if(tx_queue_ref == NULL){
tx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_write(tx_queue_ref, s->tx_queue_name, sizeof(MemoryForwardReq));
if(rmem_tx_queue_ref == NULL){
rmem_tx_queue_ref = malloc(sizeof(QemuAvatarMessageQueue));
qemu_avatar_mq_open_write(rmem_tx_queue_ref, s->tx_queue_name, sizeof(MemoryForwardReq));
}

s->rx_queue = rx_queue_ref;
s->tx_queue = tx_queue_ref;
s->rx_queue = rmem_rx_queue_ref;
s->tx_queue = rmem_tx_queue_ref;
s->request_id = 0;

}
Expand Down
4 changes: 4 additions & 0 deletions hw/intc/armv7m_nvic.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "trace.h"
#include "hw/avatar/interrupts.h"

/* IRQ number counting:
*
Expand Down Expand Up @@ -782,6 +783,7 @@ void armv7m_nvic_acknowledge_irq(void *opaque)
assert(s->vectpending_prio < running);

trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
avatar_armv7m_exception_enter(pending);

vec->active = 1;
vec->pending = 0;
Expand Down Expand Up @@ -1471,6 +1473,7 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
{
ARMCPU *cpu = s->cpu;


switch (offset) {
case 0xc: /* CPPWR */
if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
Expand Down Expand Up @@ -2229,6 +2232,7 @@ static MemTxResult nvic_sysreg_write(void *opaque, hwaddr addr,
unsigned i, startvec, end;
unsigned setval = 0;

avatar_armv7m_nvic_forward_write(offset, value, size);
trace_nvic_sysreg_write(addr, value, size);

if (attrs.user && !nvic_user_access_ok(s, addr, attrs)) {
Expand Down
26 changes: 26 additions & 0 deletions include/hw/avatar/interrupts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef HW_AVATAR_INTERRUPTS_H
#define HW_AVATAR_INTERRUPTS_H

enum RemoteInterruptOperation{
INTERRUPT_ENTER,
INTERRUPT_EXIT,
};

typedef struct V7MInterruptReq{
uint64_t id;
uint32_t num_irq;
uint32_t operation;
uint32_t type;
} V7MInterruptReq;

typedef struct V7MInterruptResp{
uint64_t id;
bool success;
uint32_t operation;
} V7MInterruptResp;

void avatar_armv7m_exception_exit(int irq, uint32_t type);
void avatar_armv7m_exception_enter(int irq);
void avatar_armv7m_nvic_forward_write(uint32_t offset, uint32_t value,unsigned size);

#endif

0 comments on commit 2de8b91

Please sign in to comment.