diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h
index da1af48ea6..82a127d757 100644
--- a/repos/base-nova/include/nova/syscall-generic.h
+++ b/repos/base-nova/include/nova/syscall-generic.h
@@ -135,6 +135,13 @@ namespace Nova {
uint8_t thread;
uint8_t core;
uint8_t package;
+ uint8_t acpi_id;
+ uint8_t family;
+ uint8_t model;
+ uint8_t stepping:4;
+ uint8_t platform:3;
+ uint8_t reserved:1;
+ uint32_t patch;
} __attribute__((packed));
unsigned cpu_max() const {
diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash
index 8c72367107..ef975a03db 100644
--- a/repos/base-nova/ports/nova.hash
+++ b/repos/base-nova/ports/nova.hash
@@ -1 +1 @@
-79dfa0facd434fa14cc92d48d0474118e718139b
+96a3ed33cf48798847b43f6023ae92a002224875
diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port
index fbc7227964..9008ad4924 100644
--- a/repos/base-nova/ports/nova.port
+++ b/repos/base-nova/ports/nova.port
@@ -2,9 +2,9 @@ LICENSE := GPLv2
VERSION := git
DOWNLOADS := nova.git
-# r9 branch - use r9_debug for more verbose kernel messages
+# r10 branch
URL(nova) := https://github.com/alex-ab/NOVA.git
-REV(nova) := 720fd5033a830d9425dbb33d8ced86d01353881b
+REV(nova) := b44329a8601ff3936aa77336752d85cff95f1a94
DIR(nova) := src/kernel/nova
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))
diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc
index 1eed812805..40083c2173 100644
--- a/repos/base-nova/src/core/platform.cc
+++ b/repos/base-nova/src/core/platform.cc
@@ -283,7 +283,7 @@ Platform::Platform() :
{
Hip *hip = (Hip *)__initial_sp;
/* check for right API version */
- if (hip->api_version != 7)
+ if (hip->api_version != 8)
nova_die();
/*
@@ -700,6 +700,23 @@ Platform::Platform() :
xml.attribute("invariant", cpuid_invariant_tsc());
xml.attribute("freq_khz" , hip->tsc_freq);
});
+ xml.node("cpus", [&] () {
+ unsigned const cpus = hip->cpus();
+ for (unsigned i = 0; i < cpus; i++) {
+ xml.node("cpu", [&] () {
+ unsigned const kernel_cpu_id = Platform::kernel_cpu_id(i);
+ xml.attribute("id", i);
+ xml.attribute("package", hip->cpu_desc_of_cpu(kernel_cpu_id)->package);
+ xml.attribute("core", hip->cpu_desc_of_cpu(kernel_cpu_id)->core);
+ xml.attribute("thread", hip->cpu_desc_of_cpu(kernel_cpu_id)->thread);
+ xml.attribute("family", String<5>(Hex(hip->cpu_desc_of_cpu(kernel_cpu_id)->family)));
+ xml.attribute("model", String<5>(Hex(hip->cpu_desc_of_cpu(kernel_cpu_id)->model)));
+ xml.attribute("stepping", String<5>(Hex(hip->cpu_desc_of_cpu(kernel_cpu_id)->stepping)));
+ xml.attribute("platform", String<5>(Hex(hip->cpu_desc_of_cpu(kernel_cpu_id)->platform)));
+ xml.attribute("patch", String<12>(Hex(hip->cpu_desc_of_cpu(kernel_cpu_id)->patch)));
+ });
+ }
+ });
});
});
diff --git a/repos/ports/run/microcode.run b/repos/ports/run/microcode.run
new file mode 100644
index 0000000000..13c3b850a3
--- /dev/null
+++ b/repos/ports/run/microcode.run
@@ -0,0 +1,76 @@
+assert_spec x86
+
+if { [get_cmd_switch --autopilot] } {
+
+ if {[have_include "power_on/qemu"]} {
+ puts "\nRun script does not support Qemu.\n"
+ exit 0
+ }
+
+ # platform_info data about CPUs on other kernels missing
+ assert_spec nova
+}
+
+build "core init test/microcode"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+set ::env(MAKEFLAGS) s
+set path_microcode [exec [genode_dir]/tool/ports/current microcode_intel]
+set microcode_files [glob -dir $path_microcode/src/app/intel *-*-*]
+
+file copy -force {*}$microcode_files bin/
+
+
+set boot_modules { core ld.lib.so init test-microcode }
+
+
+set microcode_files [glob -tails -dir bin {[0-9,a-f][0-9,a-f]-[0-9,a-f][0-9,a-f]-[0-9,a-f][0-9,a-f]}]
+append boot_modules $microcode_files
+
+
+build_boot_image $boot_modules
+
+
+append qemu_args "-nographic "
+append qemu_args "-smp 4 "
+
+run_genode_until "microcode check done" 30
+
+# cleanup
+if { [get_cmd_switch --autopilot] } {
+ foreach file $microcode_files {
+ file delete bin/$file
+ }
+}
+
+# check results
+grep_output {\[init -\> test-microcode}
+
+# no errors please
+set filtered_output $output
+grep_output {Error: }
+compare_output_to {}
+
+# no warnings please
+set output $filtered_output
+grep_output {Warning: }
+compare_output_to {}
diff --git a/repos/ports/src/test/microcode/main.cc b/repos/ports/src/test/microcode/main.cc
new file mode 100644
index 0000000000..0a872f8bed
--- /dev/null
+++ b/repos/ports/src/test/microcode/main.cc
@@ -0,0 +1,165 @@
+/*
+ * \brief Testing microcode status
+ * \author Alexander Boetcher
+ * \date 2018-08-01
+ *
+ */
+
+/*
+ * Copyright (C) 2018 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#include
+#include
+#include
+
+#include
+
+using Genode::uint8_t;
+
+struct Microcode : Genode::Mmio
+{
+ struct Version : Register< 0, 32> { };
+ struct Revision : Register< 4, 32> { };
+ struct Date : Register< 8, 32> {
+ struct Year : Bitfield< 0, 16> { };
+ struct Day : Bitfield<16, 8> { };
+ struct Month : Bitfield<24, 8> { };
+ };
+ struct Cpuid : Register<12, 32> {
+ struct Stepping : Bitfield< 0, 4> { };
+ struct Model : Bitfield< 4, 4> { };
+ struct Family : Bitfield< 8, 4> { };
+ struct Type : Bitfield< 12, 2> { };
+ struct Model_ext : Bitfield< 16, 4> { };
+ struct Family_ext : Bitfield< 20, 8> { };
+ };
+ struct Processor_flags : Register<24, 32> {
+ struct Flags : Bitfield< 0, 8> { };
+ };
+ struct Datasize : Register<28, 32> { };
+ struct Totalsize : Register<32, 32> { };
+
+ Microcode(Genode::addr_t const addr) : Mmio(addr) { }
+};
+
+static void read_micro_code_rom(Genode::Env &env, Genode::String<9> &rom_name,
+ unsigned const id, uint8_t const family,
+ uint8_t const model, uint8_t const stepping,
+ uint8_t const platform, unsigned const patch)
+{
+ using namespace Genode;
+
+ try {
+ Attached_rom_dataspace mc_rom(env, rom_name.string());
+ Microcode mc_bits(reinterpret_cast(mc_rom.local_addr()));
+
+ unsigned total_size = mc_bits.read();
+ unsigned data_size = mc_bits.read();
+
+ /* see Intel - 9.11 MICROCODE UPDATE FACILITIES */
+ if (data_size == 0) data_size = 2000;
+ if (total_size == 0) total_size = data_size + 48;
+
+ if (total_size < data_size || total_size <= 48) {
+ error(id, " ", rom_name, " - microcode sizes are bogus ", total_size, " ", data_size);
+ return;
+ }
+ unsigned const extension_size = total_size - data_size - 48;
+ if (extension_size)
+ warning("microcode patch contains extension we don't support yet!");
+
+ if (mc_bits.read() != 1) {
+ error(id, " ", rom_name, " - unsupported microcode version");
+ return;
+ }
+
+ uint8_t mc_family = (mc_bits.read() << 4)
+ | mc_bits.read();
+ uint8_t mc_model = (mc_bits.read() << 4)
+ | mc_bits.read();
+ uint8_t mc_stepping = mc_bits.read();
+ unsigned mc_patch = mc_bits.read();
+ uint8_t mc_flags = mc_bits.read();
+
+ bool const platform_match = (1U << platform) & mc_flags;
+ bool const match = (mc_family == family) && (mc_model == model) &&
+ (mc_stepping == stepping) && platform_match;
+
+ log(id,
+ " ", Hex(family, Hex::OMIT_PREFIX, Hex::PAD),
+ ":", Hex(model, Hex::OMIT_PREFIX, Hex::PAD),
+ ":", Hex(stepping, Hex::OMIT_PREFIX, Hex::PAD),
+ " [", Hex(patch, Hex::OMIT_PREFIX), "]",
+ " - microcode: "
+ " ", Hex(mc_family, Hex::OMIT_PREFIX, Hex::PAD),
+ ":", Hex(mc_model, Hex::OMIT_PREFIX, Hex::PAD),
+ ":", Hex(mc_stepping, Hex::OMIT_PREFIX, Hex::PAD),
+ " [", Hex(mc_patch, Hex::OMIT_PREFIX), "] from ",
+ Hex(mc_bits.read(), Hex::OMIT_PREFIX), "/",
+ Hex(mc_bits.read() , Hex::OMIT_PREFIX), "/",
+ Hex(mc_bits.read() , Hex::OMIT_PREFIX),
+ match ? " matches" : " mismatches",
+ platform_match ? "" : ", platform mismatch");
+
+ if (!match)
+ warning(id, " - microcode not applicable to CPU");
+ else
+ if (mc_patch > patch)
+ warning(id, " - microcode of CPU is not on last patch level!");
+ } catch (...) {
+ warning(id, " ", rom_name, " - no microcode available");
+ }
+}
+
+static void inline cpuid(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
+{
+ asm volatile ("cpuid" : "+a" (*eax), "+d" (*edx), "+b" (*ebx), "+c"(*ecx) :: "memory");
+}
+
+void Component::construct(Genode::Env &env)
+{
+ using namespace Genode;
+
+ /* we support currently solely Intel CPUs */
+ uint32_t eax = 0x0, ebx = 0, edx = 0, ecx = 0;
+ cpuid(&eax, &ebx, &ecx, &edx);
+ const char * intel = "GenuineIntel";
+
+ if (memcmp(intel, &ebx, 4) || memcmp(intel + 4, &edx, 4) || memcmp(intel + 8, &ecx, 4)) {
+ error("no Intel CPU detected");
+ return;
+ }
+
+ Attached_rom_dataspace const platform_info { env, "platform_info" };
+
+ log("CPU family:model:stepping [patch]");
+
+ try {
+ Xml_node const cpus = platform_info.xml().sub_node("hardware").sub_node("cpus");
+ cpus.for_each_sub_node("cpu", [&] (Xml_node cpu) {
+ uint8_t family = 0, model = 0, stepping = 0, platform = 0;
+ unsigned id = 0, patch = 0;
+
+ cpu.attribute("id").value(&id);
+ cpu.attribute("family").value(&family);
+ cpu.attribute("model").value(&model);
+ cpu.attribute("stepping").value(&stepping);
+ cpu.attribute("platform").value(&platform);
+ cpu.attribute("patch").value(&patch);
+
+ String<9> name(Hex(family, Hex::OMIT_PREFIX, Hex::PAD), "-",
+ Hex(model, Hex::OMIT_PREFIX, Hex::PAD), "-",
+ Hex(stepping, Hex::OMIT_PREFIX, Hex::PAD));
+
+ read_micro_code_rom(env, name, id, family, model, stepping,
+ platform, patch);
+ });
+ } catch (...) {
+ error("could not parse CPU data from platform_info");
+ }
+ log("microcode check done");
+}
diff --git a/repos/ports/src/test/microcode/target.mk b/repos/ports/src/test/microcode/target.mk
new file mode 100644
index 0000000000..13437bcdf1
--- /dev/null
+++ b/repos/ports/src/test/microcode/target.mk
@@ -0,0 +1,5 @@
+TARGET = test-microcode
+SRC_CC = main.cc
+LIBS = base
+
+REQUIRES = nova