diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d9b90a5..4002e2b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -109,3 +109,4 @@ CONFIG_IOH3420=y
 CONFIG_I82801B11=y
 CONFIG_ACPI=y
 CONFIG_SMBIOS=y
+CONFIG_SDM=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..ce2aa89 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -21,6 +21,10 @@ common-obj-$(CONFIG_MACIO) += macio/
 
 obj-$(CONFIG_IVSHMEM) += ivshmem.o
 
+obj-$(CONFIG_SDM) += sdm-device.o 
+obj-$(CONFIG_SDM) += sdm-communication.o
+obj-$(CONFIG_SDM) += sdm-signal.o
+
 obj-$(CONFIG_REALVIEW) += arm_sysctl.o
 obj-$(CONFIG_NSERIES) += cbus.o
 obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
diff --git a/hw/misc/sdm-communication.c b/hw/misc/sdm-communication.c
new file mode 100644
index 0000000..a85fe35
--- /dev/null
+++ b/hw/misc/sdm-communication.c
@@ -0,0 +1,68 @@
+/*
+ * SDM Communication
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *	   Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "hw/misc/sdm-communication.h"
+#include "qom/object_interfaces.h"
+
+int sdm_communication_signal(SDMCommunication *sdmc, SDMDevice *sdm,
+        SDMSignalData *signal)
+{
+    SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+    if (sdmck->signal) {
+        return sdmck->signal(sdmc, sdm, signal);
+    } else {
+        return -1;
+    }
+}
+
+int sdm_communication_connect(SDMCommunication *sdmc, SDMDevice *sdm)
+{
+    SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+    if (sdmck->connect) {
+        return sdmck->connect(sdmc, sdm);
+    } else {
+        return -1;
+    }
+}
+
+int sdm_communication_update_num_slaves(SDMCommunication *sdmc, SDMDevice *sdm,
+            uint16_t num_slaves)
+{
+    SDMCommunicationClass *sdmck = SDM_COMMUNICATION_GET_CLASS(sdmc);
+
+    if (sdmck->update_num_slaves) {
+        return sdmck->update_num_slaves(sdmc, sdm, num_slaves);
+    } else {
+        return -1;
+    }
+}
+
+static const TypeInfo sdm_communication_info = {
+    .name = TYPE_SDM_COMMUNICATION,
+    .parent = TYPE_OBJECT,
+    .abstract = true,
+    .class_size = sizeof(SDMCommunicationClass),
+    .instance_size = sizeof(SDMCommunication),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void register_types(void)
+{
+    type_register_static(&sdm_communication_info);
+}
+
+type_init(register_types);
diff --git a/hw/misc/sdm-device.c b/hw/misc/sdm-device.c
new file mode 100644
index 0000000..01e0cbc
--- /dev/null
+++ b/hw/misc/sdm-device.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ * 	   Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include "hw/misc/sdm-device.h"
+
+int sdm_device_notify(SDMDevice *sdm, SDMSignalData *signal)
+{
+    SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+    if (sdmc->notify) {
+        return sdmc->notify(sdm, signal);
+    } else {
+        return -1;
+    }
+}
+
+int sdm_device_accept(SDMDevice *sdm)
+{
+    SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+    if (sdmc->accept) {
+        return sdmc->accept(sdm);
+    } else {
+        return -1;
+    }
+}
+
+int sdm_device_get_num_slaves(SDMDevice *sdm)
+{
+    SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+    if (sdmc->get_num_slaves) {
+        return sdmc->get_num_slaves(sdm);
+    } else {
+        return 0;
+    }
+}
+
+int sdm_device_set_num_slaves(SDMDevice *sdm, uint16_t num_slaves)
+{
+    SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+    if (sdmc->set_num_slaves) {
+        return sdmc->set_num_slaves(sdm, num_slaves);
+    } else {
+        return 0;
+    }
+}
+
+bool sdm_device_is_master(SDMDevice *sdm)
+{
+    SDMDeviceClass *sdmc = SDM_DEVICE_GET_CLASS(sdm);
+
+    if (sdmc->is_master) {
+        return sdmc->is_master(sdm);
+    } else {
+        return false;
+    }
+}
+
+static void register_types(void)
+{
+    static const TypeInfo sdm_device_info = {
+        .name		= TYPE_SDM_DEVICE,
+        .parent		= TYPE_INTERFACE,
+        .class_size	= sizeof(SDMDeviceClass),
+    };
+
+    type_register_static(&sdm_device_info);
+}
+
+type_init(register_types)
diff --git a/hw/misc/sdm-signal.c b/hw/misc/sdm-signal.c
new file mode 100644
index 0000000..c4af0ac
--- /dev/null
+++ b/hw/misc/sdm-signal.c
@@ -0,0 +1,51 @@
+/*
+ * SDM Signal
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include "hw/misc/sdm-signal.h"
+#include "qom/object_interfaces.h"
+
+int sdm_signal_hw_ops(SDMSignal *signal, SDMSignalData *data) {
+    SDMSignalClass *signalc = SDM_SIGNAL_GET_CLASS(signal);
+
+    if (signalc->hw_ops) {
+        return signalc->hw_ops(signal, data);
+    } else {
+        return 0;
+    }
+}
+
+bool sdm_signal_hw_only(SDMSignal *signal)
+{
+    SDMSignalClass *signalc = SDM_SIGNAL_GET_CLASS(signal);
+
+    if (signalc->hw_only) {
+        return signalc->hw_only(signal);
+    } else {
+        return false;
+    }
+}
+
+static const TypeInfo sdm_signal_info = {
+    .name = TYPE_SDM_SIGNAL,
+    .parent = TYPE_OBJECT,
+    .class_size = sizeof(SDMSignalClass),
+    .instance_size = sizeof(SDMSignal),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void register_types(void)
+{
+    type_register_static(&sdm_signal_info);
+}
+
+type_init(register_types);
diff --git a/include/hw/misc/sdm-communication.h b/include/hw/misc/sdm-communication.h
new file mode 100644
index 0000000..e9b04a4
--- /dev/null
+++ b/include/hw/misc/sdm-communication.h
@@ -0,0 +1,60 @@
+/*
+ * SDM Communication
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *	   Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_COMM_H
+#define HW_SDM_COMM_H
+
+#include "hw/misc/sdm-device.h"
+
+#define TYPE_SDM_COMMUNICATION "sdm-communication"
+#define SDM_COMMUNICATION(obj) \
+    OBJECT_CHECK(SDMCommunication, (obj), TYPE_SDM_COMMUNICATION)
+#define SDM_COMMUNICATION_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SDMCommunicationClass, (obj), TYPE_SDM_COMMUNICATION)
+#define SDM_COMMUNICATION_CLASS(klass) \
+    OBJECT_CLASS_CHECK(SDMCommunicationClass, (klass), \
+            TYPE_SDM_COMMUNICATION);
+
+typedef struct SDMCommunication SDMCommunication;
+typedef struct SDMCommunicationClass SDMCommunicationClass;
+
+/**
+ * @SDMCommunicationClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMCommunicationClass {
+    ObjectClass parent_class;
+
+    int (*signal)(SDMCommunication *sdmc, SDMDevice *sdm,
+            SDMSignalData *signal);
+    int (*connect)(SDMCommunication *sdmc, SDMDevice *sdm);
+    int (*update_num_slaves)(SDMCommunication *sdmc, SDMDevice *sdm,
+                uint16_t num_slaves);
+};
+
+/**
+ * @SDMCommunication
+ *
+ * @parent: opaque parent object container
+ */
+struct SDMCommunication {
+    /* private */
+    Object parent;
+};
+
+int sdm_communication_signal(SDMCommunication *sdmc, SDMDevice *sdm,
+        SDMSignalData *signal);
+int sdm_communication_connect(SDMCommunication *sdmc, SDMDevice *sdm);
+int sdm_communication_update_num_slaves(SDMCommunication *sdmc,
+        SDMDevice *sdm, uint16_t num_slaves);
+
+#endif
diff --git a/include/hw/misc/sdm-device.h b/include/hw/misc/sdm-device.h
new file mode 100644
index 0000000..a0aca28
--- /dev/null
+++ b/include/hw/misc/sdm-device.h
@@ -0,0 +1,61 @@
+/*
+ * SDM Device
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *	   Christian Pinto <c.pinto@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_H
+#define HW_SDM_H
+
+#include "qemu-common.h"
+#include "qom/object.h"
+#include "hw/misc/sdm-signal.h"
+
+#define TYPE_SDM_DEVICE "sdm-device"
+#define SDM_DEVICE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(SDMDeviceClass, (klass), TYPE_SDM_DEVICE);
+#define SDM_DEVICE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SDMDeviceClass, (obj), TYPE_SDM_DEVICE)
+#define SDM_DEVICE(obj) \
+    INTERFACE_CHECK(SDMDevice, (obj), TYPE_SDM_DEVICE)
+
+typedef struct SDMDevice SDMDevice;
+typedef struct SDMDeviceClass SDMDeviceClass;
+
+/**
+ * SDMDeviceClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMDeviceClass {
+    InterfaceClass parent_class;
+
+    int (**signal_hw_ops)(SDMDevice *sdm, SDMSignalData *signal);
+
+    /* Notify the device about a new signal. If the signal cannot
+     * be handled by device (busy), returns -1. The communication
+     * channel should then try to deliver the signal again later.
+     */
+    int (*notify)(SDMDevice *sdm, SDMSignalData *signal);
+    int (*accept)(SDMDevice *sdm);
+    int (*get_num_slaves)(SDMDevice *sdm);
+    int (*set_num_slaves)(SDMDevice *sdm, uint16_t num_slaves);
+    bool (*is_master)(SDMDevice *sdm);
+};
+
+struct SDMDevice {
+    /* private */
+    Object parent;
+};
+
+int sdm_device_notify(SDMDevice *sdm, SDMSignalData *signal);
+int sdm_device_accept(SDMDevice *sdm);
+int sdm_device_get_num_slaves(SDMDevice *sdm);
+int sdm_device_set_num_slaves(SDMDevice *sdm, uint16_t num_slaves);
+bool sdm_device_is_master(SDMDevice *sdm);
+#endif
diff --git a/include/hw/misc/sdm-signal.h b/include/hw/misc/sdm-signal.h
new file mode 100644
index 0000000..f9b82eb
--- /dev/null
+++ b/include/hw/misc/sdm-signal.h
@@ -0,0 +1,60 @@
+/*
+ * SDM Signal
+ *
+ * Copyright (C) 2016 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef HW_SDM_SIGNAL_H
+#define HW_SDM_SIGNAL_H
+
+#include "qemu-common.h"
+#include "qom/object.h"
+
+#define TYPE_SDM_SIGNAL "sdm-signal"
+#define SDM_SIGNAL(obj) \
+    OBJECT_CHECK(SDMSignal, (obj), TYPE_SDM_SIGNAL)
+#define SDM_SIGNAL_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SDMSignalClass, (obj), TYPE_SDM_SIGNAL)
+#define SDM_SIGNAL_CLASS(klass) \
+    OBJECT_CLASS_CHECK(SDMSignalClass, (klass), \
+            TYPE_SDM_SIGNAL)
+
+typedef struct SDMSignalData SDMSignalData;
+typedef struct SDMSignal SDMSignal;
+typedef struct SDMSignalClass SDMSignalClass;
+
+struct SDMSignalData {
+    uint32_t type;
+    uint32_t slave;
+    uint32_t payload[2];
+};
+
+/**
+ * @SDMSignalClass
+ *
+ * @parent_class: opaque parent class container
+ */
+struct SDMSignalClass {
+    ObjectClass parent_class;
+
+    int (*hw_ops)(SDMSignal *signal, SDMSignalData *data);
+    bool (*hw_only)(SDMSignal *signal);
+};
+
+/**
+ * @SDMSignal
+ *
+ * @parent: opaque parent object container
+ */
+struct SDMSignal {
+    /* private */
+    Object parent;
+};
+
+int sdm_signal_hw_ops(SDMSignal *signal, SDMSignalData *data);
+bool sdm_signal_hw_only(SDMSignal *signal);
+#endif
