>From c0bd363ee0b744c750ddb609a796c9abb8206e66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reinier=20Millo=20S=C3=A1nchez?= <rmillo>
Date: Thu, 7 May 2015 01:41:24 -0400
Subject: [PATCH] Monitor para tracear el driver USB en base_hw para la
 RaspberryPI.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Reinier Millo S����nchez <rmillo@...210...>
---
 repos/base-hw/include/irq_session/client.h         |   27 ++-
 repos/base-hw/include/irq_session/irq_session.h    |   13 +-
 .../src/core/include/irq_session_component.h       |    2 +-
 repos/base-hw/src/core/irq_session_component.cc    |    2 +-
 repos/dde_linux/run/usb_hid2.run                   |  136 ++++++++++++++
 repos/dde_linux/src/trace/usb_drv/main.cc          |  191 ++++++++++++++++++++
 repos/dde_linux/src/trace/usb_drv/target.mk        |    3 +
 7 files changed, 369 insertions(+), 5 deletions(-)
 create mode 100644 repos/dde_linux/run/usb_hid2.run
 create mode 100644 repos/dde_linux/src/trace/usb_drv/main.cc
 create mode 100644 repos/dde_linux/src/trace/usb_drv/target.mk

diff --git a/repos/base-hw/include/irq_session/client.h b/repos/base-hw/include/irq_session/client.h
index 8a417d9..fcb388b 100644
--- a/repos/base-hw/include/irq_session/client.h
+++ b/repos/base-hw/include/irq_session/client.h
@@ -17,6 +17,28 @@
 /* Genode includes */
 #include <irq_session/capability.h>
 #include <base/rpc_client.h>
+#include <util/mmio.h>
+#include <trace/timestamp.h>
+
+struct Dwc_otg : Genode::Mmio
+{
+	struct Core_interrupt : Register<0x14, 32> { };
+
+	enum { DWC_BASE = 0x20980000 };
+
+	Dwc_otg() : Genode::Mmio(DWC_BASE) { }
+
+	void dump()
+	{
+		PINF("Core_interrupt=0x%08x", read<Core_interrupt>());
+	}
+};
+
+static Dwc_otg *dwc_otg()
+{
+	static Dwc_otg inst;
+	return &inst;
+}
 
 namespace Genode
 {
@@ -48,13 +70,16 @@ namespace Genode
 
 		Irq_signal signal() { return call<Rpc_signal>(); }
 
-		void wait_for_irq()
+		Irq_info wait_for_irq()
 		{
 			while (Kernel::await_signal(irq_signal.receiver_id,
 			                            irq_signal.context_id))
 			{
 				PERR("failed to receive interrupt");
 			}
+
+			return Irq_session::Irq_info(Trace::timestamp(),
+	                             dwc_otg()->read<Dwc_otg::Core_interrupt>());
 		}
 	};
 }
diff --git a/repos/base-hw/include/irq_session/irq_session.h b/repos/base-hw/include/irq_session/irq_session.h
index 9060257..93ae6c7 100644
--- a/repos/base-hw/include/irq_session/irq_session.h
+++ b/repos/base-hw/include/irq_session/irq_session.h
@@ -17,6 +17,7 @@
 /* Genode includes */
 #include <base/capability.h>
 #include <session/session.h>
+#include <trace/timestamp.h>
 
 namespace Genode
 {
@@ -52,7 +53,15 @@ namespace Genode
 		/**
 		 * Await the next occurence of the interrupt of this session
 		 */
-		virtual void wait_for_irq() = 0;
+		struct Irq_info
+		{
+			Trace::Timestamp timestamp;
+			unsigned long status;
+			Irq_info() : timestamp(0), status(0) { }
+			Irq_info(Trace::Timestamp timestamp, unsigned long status)
+				: timestamp(timestamp),status(status) { }
+		};
+		virtual Irq_info wait_for_irq() = 0;
 
 		/**
 		 * Get information for direct interrupt handling
@@ -73,7 +82,7 @@ namespace Genode
 		 ** RPC declaration **
 		 *********************/
 
-		GENODE_RPC(Rpc_wait_for_irq, void, wait_for_irq);
+		GENODE_RPC(Rpc_wait_for_irq, Irq_info, wait_for_irq);
 		GENODE_RPC(Rpc_signal, Irq_signal, signal);
 		GENODE_RPC_INTERFACE(Rpc_wait_for_irq, Rpc_signal);
 	};
diff --git a/repos/base-hw/src/core/include/irq_session_component.h b/repos/base-hw/src/core/include/irq_session_component.h
index 204a71d..36ef0a5 100644
--- a/repos/base-hw/src/core/include/irq_session_component.h
+++ b/repos/base-hw/src/core/include/irq_session_component.h
@@ -66,7 +66,7 @@ namespace Genode
 			 ** Irq_session **
 			 *****************/
 
-			void wait_for_irq();
+			Irq_info wait_for_irq();
 
 			Irq_signal signal();
 	};
diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc
index 529a4ac..c72f76d 100644
--- a/repos/base-hw/src/core/irq_session_component.cc
+++ b/repos/base-hw/src/core/irq_session_component.cc
@@ -36,7 +36,7 @@ static Rpc_entrypoint * irq_session_ep()
 	return &_ep;
 }
 
-void Irq_session_component::wait_for_irq() { PERR("not implemented"); }
+Irq_session::Irq_info Irq_session_component::wait_for_irq() { PERR("not implemented"); }
 
 Irq_signal Irq_session_component::signal() { return _signal; }
 
diff --git a/repos/dde_linux/run/usb_hid2.run b/repos/dde_linux/run/usb_hid2.run
new file mode 100644
index 0000000..b4ab65d
--- /dev/null
+++ b/repos/dde_linux/run/usb_hid2.run
@@ -0,0 +1,136 @@
+#
+# Build
+#
+
+set build_components {
+	core init
+	drivers/timer
+	drivers/usb
+	test/input
+	trace/usb_drv
+	lib/trace/policy/null
+	test/affinity
+}
+
+lappend_if [have_spec acpi]             build_components drivers/acpi
+lappend_if [have_spec pci]              build_components drivers/pci
+lappend_if [have_spec pci]              build_components drivers/pci/device_pd
+lappend_if [have_spec platform_arndale] build_components drivers/platform
+lappend_if [have_spec platform_rpi] build_components drivers/platform
+lappend_if [have_spec gpio]             build_components drivers/gpio
+
+build $build_components
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+append config {
+<config>
+	<parent-provides>
+		<service name="ROM"/>
+		<service name="RAM"/>
+		<service name="IRQ"/>
+		<service name="IO_MEM"/>
+		<service name="IO_PORT"/>
+		<service name="CAP"/>
+		<service name="PD"/>
+		<service name="RM"/>
+		<service name="CPU"/>
+		<service name="LOG"/>
+		<service name="SIGNAL" />
+		<service name="TRACE"/>
+	</parent-provides>
+	<default-route>
+		<any-service> <parent/> <any-child/> </any-service>
+	</default-route>}
+
+append_if [have_spec platform_arndale] config {
+		<start name="platform_drv">
+			<resource name="RAM" quantum="1M"/>
+			<provides><service name="Regulator"/></provides>
+		</start>}
+
+append_if [have_spec platform_rpi] config {
+	<start name="platform_drv">
+		<resource name="RAM" quantum="1M"/>
+		<provides><service name="Platform"/></provides>
+		<config/>
+	</start>}
+
+append_if [have_spec gpio] config {
+	<start name="gpio_drv">
+		<resource name="RAM" quantum="4M"/>
+		<provides><service name="Gpio"/></provides>
+		<config/>
+	</start>}
+
+append_if [have_spec acpi] config {
+	<start name="acpi">
+		<resource name="RAM" quantum="8M" constrain_phys="yes"/>
+		<binary name="acpi_drv"/>
+		<provides>
+			<service name="PCI"/>
+			<service name="IRQ" />
+		</provides>
+		<route>
+			<service name="PCI"> <any-child /> </service>
+			<any-service> <parent/> <any-child /> </any-service>
+		</route>
+	</start>}
+
+append_if [expr ![have_spec acpi] && [have_spec pci]] config {
+	<start name="pci_drv">
+		<resource name="RAM" quantum="5M" constrain_phys="yes"/>
+		<provides><service name="PCI"/></provides>
+	</start>}
+
+append config {
+	<start name="timer">
+		<resource name="RAM" quantum="1M"/>
+		<provides><service name="Timer"/></provides>
+	</start>
+	<start name="usb_drv">
+		<resource name="RAM" quantum="7M"/>
+		<provides><service name="Input"/></provides>
+		<config uhci="yes" ehci="yes" xhci="yes">
+			<hid/>
+		</config>
+	</start>
+	<start name="test-input">
+		<resource name="RAM" quantum="1M"/>
+	</start>
+	<start name="trace-usb_drv">
+		<resource name="RAM" quantum="35M"/>
+		<config>
+			<trace_policy label="init -> usb_drv" module="null" />
+		</config>
+	</start>
+</config>}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+	core init timer usb_drv test-input trace-usb_drv null test-affinity
+}
+
+lappend_if [have_spec acpi]             boot_modules acpi_drv
+lappend_if [have_spec pci]              boot_modules pci_drv
+lappend_if [have_spec nova]             boot_modules pci_device_pd
+lappend_if [have_spec platform_arndale] boot_modules platform_drv
+lappend_if [have_spec platform_rpi] boot_modules platform_drv
+lappend_if [have_spec gpio]             boot_modules gpio_drv
+
+build_boot_image $boot_modules
+
+append qemu_args " -m 256 -usb  -usbdevice mouse -usbdevice keyboard"
+
+
+run_genode_until forever
diff --git a/repos/dde_linux/src/trace/usb_drv/main.cc b/repos/dde_linux/src/trace/usb_drv/main.cc
new file mode 100644
index 0000000..6c0048b
--- /dev/null
+++ b/repos/dde_linux/src/trace/usb_drv/main.cc
@@ -0,0 +1,191 @@
+/*
+ * \brief  Trace monitor for tracing the USB driver
+ * \author Norman Feske
+ * \date   2013-09-12
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* Genode includes */
+#include <trace/timestamp.h>
+#include <trace_session/connection.h>
+#include <base/printf.h>
+#include <timer_session/connection.h>
+#include <os/attached_rom_dataspace.h>
+#include <os/config.h>
+
+using namespace Genode;
+
+
+class Trace_buffer_monitor
+{
+	private:
+
+		enum { MAX_ENTRY_BUF = 256, MAX_EVENTS_TO_DUMP = 250 };
+		char                  _buf[MAX_ENTRY_BUF];
+
+		Trace::Subject_id     _id;
+		Trace::Buffer        *_buffer;
+		Trace::Buffer::Entry _curr_entry;
+
+		const char *_terminate_entry(Trace::Buffer::Entry const &entry)
+		{
+			size_t len = min(entry.length() + 1, MAX_ENTRY_BUF);
+			memcpy(_buf, entry.data(), len);
+			_buf[len-1] = '\0';
+
+			return _buf;
+		}
+
+	public:
+
+		Trace_buffer_monitor(Trace::Subject_id id, Dataspace_capability ds_cap)
+		:
+			_id(id),
+			_buffer(env()->rm_session()->attach(ds_cap)),
+			_curr_entry(_buffer->first())
+		{
+			PLOG("monitor subject:%d buffer:0x%lx", _id.id, (addr_t)_buffer);
+		}
+
+		~Trace_buffer_monitor()
+		{
+			if (_buffer)
+				env()->rm_session()->detach(_buffer);
+		}
+
+		Trace::Subject_id id() { return _id; };
+
+		void dump()
+		{
+			PLOG("overflows: %u", _buffer->wrapped());
+
+			PLOG("read all remaining events");
+			unsigned cnt=0;
+			for (; !_curr_entry.is_last(); _curr_entry = _buffer->next(_curr_entry)) {
+
+				/* omit empty entries */
+				if (_curr_entry.length() == 0)
+					continue;
+
+				cnt++;
+				const char *data = _terminate_entry(_curr_entry);
+				if (data)
+					PLOG("%s", data);
+			}
+			PLOG("entries: %u", cnt);
+
+			/* reset after we read all available entries */
+			_curr_entry = _buffer->first();
+		}
+};
+
+
+int main(int argc, char **argv)
+{
+	using namespace Genode;
+	using namespace Trace;
+
+	printf("--- trace-usb_drv started ---\n");
+
+	static Genode::Trace::Connection trace(32*1024*1024, 64*1024, 0);
+	static Timer::Connection timer;
+
+	timer.msleep(3000);
+
+	static Trace_buffer_monitor *test_monitor = 0;
+
+	Genode::Trace::Policy_id policy_id;
+
+	char                     policy_label[64];
+	char                     policy_module[64];
+	Rom_dataspace_capability policy_module_rom_ds;
+
+	try {
+		Xml_node policy = config()->xml_node().sub_node("trace_policy");
+		for (;; policy = policy.next("trace_policy")) {
+			try {
+				policy.attribute("label").value(policy_label, sizeof (policy_label));
+				policy.attribute("module").value(policy_module, sizeof (policy_module));
+
+				static Rom_connection policy_rom(policy_module);
+				policy_module_rom_ds = policy_rom.dataspace();
+
+				size_t rom_size = Dataspace_client(policy_module_rom_ds).size();
+
+				policy_id = trace.alloc_policy(rom_size);
+				Dataspace_capability ds_cap = trace.policy(policy_id);
+
+				if (ds_cap.valid()) {
+					void *ram = env()->rm_session()->attach(ds_cap);
+					void *rom = env()->rm_session()->attach(policy_module_rom_ds);
+					memcpy(ram, rom, rom_size);
+
+					env()->rm_session()->detach(ram);
+					env()->rm_session()->detach(rom);
+				}
+			} catch (...) {
+				PERR("could not load module '%s' for label '%s'", policy_module, policy_label);
+			}
+
+			PINF("load module: '%s' for label: '%s'", policy_module, policy_label);
+
+			if (policy.is_last("trace_policy")) break;
+		}
+
+	} catch (...) { }
+
+	enum { MAX_SUBJECTS = 64 };
+	static Trace::Subject_id subjects[MAX_SUBJECTS];
+	size_t num_subjects = trace.subjects(subjects, 32);
+
+	printf("%zd tracing subjects present\n", num_subjects);
+
+	for (size_t i = 0; i < num_subjects; i++) {
+		Trace::Subject_info info = trace.subject_info(subjects[i]);
+
+		if (strcmp(info.session_label().string(), "init -> usb_drv") != 0)
+			continue;
+
+		printf("install policy to thread: %s\n", info.thread_name().string());
+
+		/* enable tracing */
+		trace.trace(subjects[i], policy_id, 6*1024*1024);
+	}
+
+	timer.msleep(3000);
+
+	/* pause all tracing */
+	for (unsigned i = 0; i < num_subjects; i++)
+		trace.pause(subjects[i]);
+
+	for (unsigned i = 0; i < num_subjects; i++) {
+
+		Trace::Subject_info info = trace.subject_info(subjects[i]);
+
+		if (strcmp(info.session_label().string(), "init -> usb_drv") != 0)
+			continue;
+
+		try{
+			Dataspace_capability ds_cap = trace.buffer(subjects[i].id);
+			printf("-- buffer of %s --\n", info.thread_name().string());
+			test_monitor = new (env()->heap()) Trace_buffer_monitor(subjects[i].id, ds_cap);
+		} catch (Trace::Source_is_dead) { PERR("source is dead"); }
+
+		if (test_monitor) {
+			if (subjects[i].id == test_monitor->id().id)
+				test_monitor->dump();
+		}
+	}
+
+	if (test_monitor)
+		destroy(env()->heap(), test_monitor);
+
+	printf("--- trace-usb_drv finished ---\n");
+	return 0;
+}
diff --git a/repos/dde_linux/src/trace/usb_drv/target.mk b/repos/dde_linux/src/trace/usb_drv/target.mk
new file mode 100644
index 0000000..4c8f757
--- /dev/null
+++ b/repos/dde_linux/src/trace/usb_drv/target.mk
@@ -0,0 +1,3 @@
+TARGET = trace-usb_drv
+SRC_CC = main.cc
+LIBS  += base config
-- 
1.7.10.4

