From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Jones Subject: [PATCH 6/9] Introduce a simple iomap structure Date: Wed, 4 Dec 2013 17:42:54 +0100 Message-ID: <1386175377-23086-7-git-send-email-drjones@redhat.com> References: <1386175377-23086-1-git-send-email-drjones@redhat.com> To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Return-path: Received: from mx1.redhat.com ([209.132.183.28]:47675 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932925Ab3LDQn3 (ORCPT ); Wed, 4 Dec 2013 11:43:29 -0500 In-Reply-To: <1386175377-23086-1-git-send-email-drjones@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: Add a simple structure and search function to the common code that can be used for looking up a set of addresses by type. The user must supply the iomaps[] table, e.g. struct iomap iomaps[] = { { .type = "virtio_mmio", .nr = 4, .addrs = { 0x2000000, 0x2000200, 0x2000400, 0x2000600, }, }, { .type = NULL, }, }; Also add a script scripts/gen-devtree-iomaps.pl that can generate the iomaps table from an fdt, e.g. fdtdump dtb | scripts/gen-devtree-iomaps.pl - virtio_mmio Signed-off-by: Andrew Jones --- v2: - switch to kernel coding style - rework fdt parsing to enable extraction of properties. Extract the 'compatible' property. - add iomaps_find_compatible() to allow searching for iomaps by its 'compatible' property. --- README | 1 + lib/iomaps.c | 31 +++++++++++++ lib/iomaps.h | 14 ++++++ scripts/gen-devtree-iomaps.pl | 105 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 lib/iomaps.c create mode 100644 lib/iomaps.h create mode 100755 scripts/gen-devtree-iomaps.pl diff --git a/README b/README index 0174679c05021..f834c61dc6112 100644 --- a/README +++ b/README @@ -20,6 +20,7 @@ Directory structure: .: Makefile and config files for the tests ./config: config files for the tests ./docs: documentation files +./scripts: misc helper scripts ./lib: general services for the tests ./lib/: architecture dependent services for the tests ./: the sources of the tests and the created objects/images diff --git a/lib/iomaps.c b/lib/iomaps.c new file mode 100644 index 0000000000000..f2263b79dce96 --- /dev/null +++ b/lib/iomaps.c @@ -0,0 +1,31 @@ +#include "libcflat.h" +#include "iomaps.h" + +extern const struct iomap iomaps[]; + +const struct iomap *iomaps_find_type(const char *type) +{ + const struct iomap *m = &iomaps[0]; + + while (m->type) { + if (strcmp(m->type, type) == 0) + return m; + ++m; + } + return NULL; +} + +const struct iomap *iomaps_find_compatible(const char *compat) +{ + const struct iomap *m = &iomaps[0]; + const char *c; + int i; + + while (m->type) { + for (i = 0, c = m->compats[0]; c != NULL; c = m->compats[++i]) + if (strcmp(c, compat) == 0) + return m; + ++m; + } + return NULL; +} diff --git a/lib/iomaps.h b/lib/iomaps.h new file mode 100644 index 0000000000000..76a1aa4720337 --- /dev/null +++ b/lib/iomaps.h @@ -0,0 +1,14 @@ +#ifndef _IOMAPS_H_ +#define _IOMAPS_H_ +#include "libcflat.h" + +struct iomap { + const char *type; + const char *compats[5]; + u32 nr; + u32 addrs[64]; +}; + +const struct iomap *iomaps_find_type(const char *type); +const struct iomap *iomaps_find_compatible(const char *compat); +#endif diff --git a/scripts/gen-devtree-iomaps.pl b/scripts/gen-devtree-iomaps.pl new file mode 100755 index 0000000000000..b48e85e48ab34 --- /dev/null +++ b/scripts/gen-devtree-iomaps.pl @@ -0,0 +1,105 @@ +#!/usr/bin/perl -w +use strict; +use File::Temp qw/:POSIX/; + +my $dts = shift @ARGV; +my @types = @ARGV; +my $max_nr_addrs = 64; +my $max_nr_compats = 4; + +if (!defined $dts || $#types < 0) { + print STDERR "Usage: gen-devtree-iomaps ". + " [addr-types...]\n"; + exit 1; +} + +my $dtb = tmpnam(); +system "dtc -I dts -O dtb $dts -o $dtb"; + +my $g = join '|', map { $_ . '@' } @types; +my @devs = grep { /$g/ } `fdtget -l $dtb / 2>/dev/null`; + +my %iomaps; +foreach my $dev (@devs) { + + chomp($dev); + my ($type, $addr) = split /@/, $dev; + + if (!exists $iomaps{$type}) { + + my $compatible = `fdtget $dtb /$dev compatible 2>/dev/null`; + chomp($compatible); + my @compats = split ' ', $compatible; + + $iomaps{$type}{compats} = \@compats; + $iomaps{$type}{addrs} = [$addr]; + } else { + push @{ $iomaps{$type}{addrs} }, $addr; + } +} +unlink $dtb; + +print < $max_nr_compats) { + print STDERR "$type has $nr_compats compats, but iomaps can ". + "only support up to $max_nr_compats.\n"; + splice @{ $compats }, $max_nr_compats; + } + + @{ $addrs } = sort @{ $addrs }; + + my $nr = $#{ $addrs } + 1; + if ($nr > $max_nr_addrs) { + print STDERR "$type has $nr addrs, but iomaps can ". + "only support up to $max_nr_addrs.\n"; + $nr = $max_nr_addrs; + splice @{ $addrs }, $nr; + } + + @{ $addrs } = map { $_ = sprintf '0x%.8x', hex($_) } @{ $addrs }; + + print "{\n"; + print "\t.type = \"$type\",\n"; + + print "\t.compats = {"; + foreach my $compat (@{ $compats }) { + print " \"$compat\","; + } + print " NULL, },\n"; + + print "\t.nr = $nr,\n"; + print "\t.addrs = {"; + if ($nr < 5) { + print ' '; + print join ', ', @{ $addrs }; + print ", },\n"; + } else { + print "\n"; + for (my $i = 0; $i < $nr; $i += 5) { + print "\t\t"; + my $j = $i; + while ($j < $i + 4 && $j < $nr - 1) { + print $addrs->[$j] . ", "; + ++$j; + } + print $addrs->[$j] . ",\n"; + } + print "\t},\n"; + } + print "},\n"; +} +print "{\n\t.type = NULL,\n},\n"; +print "};\n"; +exit 0; -- 1.8.1.4