cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mk-ccs-regs (10817B)


      1#!/usr/bin/perl -w
      2# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
      3# Copyright (C) 2019--2020 Intel Corporation
      4
      5use Getopt::Long qw(:config no_ignore_case);
      6use File::Basename;
      7
      8my $ccsregs = "ccs-regs.asc";
      9my $header;
     10my $regarray;
     11my $limitc;
     12my $limith;
     13my $kernel;
     14my $help;
     15
     16GetOptions("ccsregs|c=s" => \$ccsregs,
     17	   "header|e=s" => \$header,
     18	   "regarray|r=s" => \$regarray,
     19	   "limitc|l=s" => \$limitc,
     20	   "limith|L=s" => \$limith,
     21	   "kernel|k" => \$kernel,
     22	   "help|h" => \$help) or die "can't parse options";
     23
     24$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
     25
     26if (defined $help) {
     27	print <<EOH
     28$0 - Create CCS register definitions for C
     29
     30usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
     31
     32	-c ccs register file
     33	-e header file name
     34	-r register description array file name
     35	-l limit and capability array file name
     36	-L limit and capability header file name
     37	-k generate files for kernel space consumption
     38EOH
     39	  ;
     40	exit 0;
     41}
     42
     43my $lh_hdr = ! defined $kernel
     44	? '#include "ccs-os.h"' . "\n"
     45	: "#include <linux/bits.h>\n#include <linux/types.h>\n";
     46my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32';
     47my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16';
     48
     49open(my $R, "< $ccsregs") or die "can't open $ccsregs";
     50
     51open(my $H, "> $header") or die "can't open $header";
     52my $A;
     53if (defined $regarray) {
     54	open($A, "> $regarray") or die "can't open $regarray";
     55}
     56open(my $LC, "> $limitc") or die "can't open $limitc";
     57open(my $LH, "> $limith") or die "can't open $limith";
     58
     59my %this;
     60
     61sub is_limit_reg($) {
     62	my $addr = hex $_[0];
     63
     64	return 0 if $addr < 0x40; # weed out status registers
     65	return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
     66
     67	return 1;
     68}
     69
     70my $uc_header = basename uc $header;
     71$uc_header =~ s/[^A-Z0-9]/_/g;
     72
     73my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
     74my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";
     75my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";
     76
     77for my $fh ($A, $LC) {
     78	print $fh "// $license\n$copyright$note\n" if defined $fh;
     79}
     80
     81for my $fh ($H, $LH) {
     82	print $fh "/* $license */\n$copyright$note\n";
     83}
     84
     85sub bit_def($) {
     86	my $bit = shift @_;
     87
     88	return "BIT($bit)" if defined $kernel;
     89	return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/;
     90	return "(1U << ($bit))";
     91}
     92
     93print $H <<EOF
     94#ifndef __${uc_header}__
     95#define __${uc_header}__
     96
     97EOF
     98  ;
     99
    100print $H "#include <linux/bits.h>\n\n" if defined $kernel;
    101
    102print $H <<EOF
    103#define CCS_FL_BASE		16
    104EOF
    105  ;
    106
    107print $H "#define CCS_FL_16BIT		" . bit_def("CCS_FL_BASE") . "\n";
    108print $H "#define CCS_FL_32BIT		" . bit_def("CCS_FL_BASE + 1") . "\n";
    109print $H "#define CCS_FL_FLOAT_IREAL	" . bit_def("CCS_FL_BASE + 2") . "\n";
    110print $H "#define CCS_FL_IREAL		" . bit_def("CCS_FL_BASE + 3") . "\n";
    111
    112print $H <<EOF
    113#define CCS_R_ADDR(r)		((r) & 0xffff)
    114
    115EOF
    116  ;
    117
    118print $A <<EOF
    119#include <stdint.h>
    120#include <stdio.h>
    121#include "ccs-extra.h"
    122#include "ccs-regs.h"
    123
    124EOF
    125	if defined $A;
    126
    127my $uc_limith = basename uc $limith;
    128$uc_limith =~ s/[^A-Z0-9]/_/g;
    129
    130print $LH <<EOF
    131#ifndef __${uc_limith}__
    132#define __${uc_limith}__
    133
    134$lh_hdr
    135struct ccs_limit {
    136	$uint32_t reg;
    137	$uint16_t size;
    138	$uint16_t flags;
    139	const char *name;
    140};
    141
    142EOF
    143  ;
    144print $LH "#define CCS_L_FL_SAME_REG	" . bit_def(0) . "\n\n";
    145
    146print $LH <<EOF
    147extern const struct ccs_limit ccs_limits[];
    148
    149EOF
    150  ;
    151
    152print $LC <<EOF
    153#include "ccs-limits.h"
    154#include "ccs-regs.h"
    155
    156const struct ccs_limit ccs_limits[] = {
    157EOF
    158  ;
    159
    160my $limitcount = 0;
    161my $argdescs;
    162my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
    163
    164sub name_split($$) {
    165	my ($name, $addr) = @_;
    166	my $args;
    167
    168	$name =~ /([^\(]+?)(\(.*)/;
    169	($name, $args) = ($1, $2);
    170	$args = [split /,\s*/, $args];
    171	foreach my $t (@$args) {
    172		$t =~ s/[\(\)]//g;
    173		$t =~ s/\//\\\//g;
    174	}
    175
    176	return ($name, $addr, $args);
    177}
    178
    179sub tabconv($) {
    180	$_ = shift;
    181
    182	my @l = split "\n", $_;
    183
    184	map {
    185		s/ {8,8}/\t/g;
    186		s/\t\K +//;
    187	} @l;
    188
    189	return (join "\n", @l) . "\n";
    190}
    191
    192sub elem_size(@) {
    193	my @flags = @_;
    194
    195	return 2 if grep /^16$/, @flags;
    196	return 4 if grep /^32$/, @flags;
    197	return 1;
    198}
    199
    200sub arr_size($) {
    201	my $this = $_[0];
    202	my $size = $this->{elsize};
    203	my $h = $this->{argparams};
    204
    205	foreach my $arg (@{$this->{args}}) {
    206		my $apref = $h->{$arg};
    207
    208		$size *= $apref->{max} - $apref->{min} + 1;
    209	}
    210
    211	return $size;
    212}
    213
    214sub print_args($$$) {
    215	my ($this, $postfix, $is_same_reg) = @_;
    216	my ($args, $argparams, $name) =
    217	  ($this->{args}, $this->{argparams}, $this->{name});
    218	my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
    219	my @mins;
    220	my @sorted_args = @{$this->{sorted_args}};
    221	my $lim_arg;
    222	my $size = arr_size($this);
    223
    224	$argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
    225
    226	foreach my $sorted_arg (@sorted_args) {
    227		push @mins, $argparams->{$sorted_arg}->{min};
    228	}
    229
    230	foreach my $sorted_arg (@sorted_args) {
    231		my $h = $argparams->{$sorted_arg};
    232
    233		$argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
    234
    235		$lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";
    236	}
    237
    238	$argdescs .= "};\n\n";
    239
    240	$reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
    241	  "), $size, sizeof($varname) / sizeof(*$varname)," .
    242	    " \"" . (lc $name) . "\", $varname },\n";
    243
    244	print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
    245	  $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .
    246	    ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"
    247	      if is_limit_reg $this->{base_addr};
    248}
    249
    250my $hdr_data;
    251
    252while (<$R>) {
    253	chop;
    254	s/^\s*//;
    255	next if /^[#;]/ || /^$/;
    256	if (s/^-\s*//) {
    257		if (s/^b\s*//) {
    258			my ($bit, $addr) = split /\t+/;
    259			$bit = uc $bit;
    260			$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";
    261		} elsif (s/^f\s*//) {
    262			s/[,\.-]/_/g;
    263			my @a = split /\s+/;
    264			my ($msb, $lsb, $this_field) = reverse @a;
    265		        @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },
    266			       { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );
    267			$this{"field"} = $this_field;
    268			foreach my $ar (@a) {
    269				#print $ar->{fmt}."\n";
    270				$hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";
    271			}
    272		} elsif (s/^e\s*//) {
    273			s/[,\.-]/_/g;
    274			my ($enum, $addr) = split /\s+/;
    275			$enum = uc $enum;
    276			$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";
    277		} elsif (s/^l\s*//) {
    278			my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
    279			my $size;
    280
    281			foreach my $num ($min, $max) {
    282				$num = hex $num if $num =~ /0x/i;
    283			}
    284
    285			$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";
    286			$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";
    287
    288			my $h = $this{argparams};
    289
    290			$h->{$arg} = { "min" => $min,
    291				       "max" => $max,
    292				       "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,
    293				       "discontig" => \@discontig };
    294
    295			$this{discontig} = $arg if @discontig;
    296
    297			next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
    298
    299			my $reg_formula = "($this{addr}";
    300			my $lim_formula;
    301
    302			foreach my $arg (@{$this{args}}) {
    303				my $d = $h->{$arg}->{discontig};
    304				my $times = $h->{$arg}->{elsize} != 1 ?
    305				  " * " . $h->{$arg}->{elsize} : "";
    306
    307				if (@$d) {
    308					my ($lim, $offset) = split /,/, $d->[0];
    309
    310					$reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
    311				} else {
    312					$reg_formula .= " + ($arg)$times";
    313				}
    314
    315				$lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";
    316			}
    317
    318			$reg_formula .= ")\n";
    319			$lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
    320
    321			print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .
    322			  $this{arglist}, $reg_formula);
    323
    324			print $H tabconv $hdr_data;
    325			undef $hdr_data;
    326
    327			# Sort arguments in descending order by size
    328			@{$this{sorted_args}} = sort {
    329				$h->{$a}->{elsize} <= $h->{$b}->{elsize}
    330			} @{$this{args}};
    331
    332			if (defined $this{discontig}) {
    333				my $da = $this{argparams}->{$this{discontig}};
    334				my ($first_discontig) = split /,/, $da->{discontig}->[0];
    335				my $max = $da->{max};
    336
    337				$da->{max} = $first_discontig - 1;
    338				print_args(\%this, "", 0);
    339
    340				$da->{min} = $da->{max} + 1;
    341				$da->{max} = $max;
    342				print_args(\%this, $first_discontig, 1);
    343			} else {
    344				print_args(\%this, "", 0);
    345			}
    346
    347			next unless is_limit_reg $this{base_addr};
    348
    349			print $LH tabconv sprintf "#define %-63s%s\n",
    350			  "CCS_L_" . (uc $this{name}) . "_OFFSET(" .
    351			    (join ", ", @{$this{args}}) . ")", "($lim_formula)";
    352		}
    353
    354		if (! @{$this{args}}) {
    355			print $H tabconv($hdr_data);
    356			undef $hdr_data;
    357		}
    358
    359		next;
    360	}
    361
    362	my ($name, $addr, @flags) = split /\t+/, $_;
    363	my $args = [];
    364
    365	my $sp;
    366
    367	($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
    368
    369	$name =~ s/[,\.-]/_/g;
    370
    371	my $flagstring = "";
    372	my $size = elem_size(@flags);
    373	$flagstring .= "| CCS_FL_16BIT " if $size eq "2";
    374	$flagstring .= "| CCS_FL_32BIT " if $size eq "4";
    375	$flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
    376	$flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
    377	$flagstring =~ s/^\| //;
    378	$flagstring =~ s/ $//;
    379	$flagstring = "($flagstring)" if $flagstring =~ /\|/;
    380	my $base_addr = $addr;
    381	$addr = "($addr | $flagstring)" if $flagstring ne "";
    382
    383	my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";
    384	$hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
    385	  if !@$args;
    386
    387	$name =~ s/\(.*//;
    388
    389	%this = ( name => $name,
    390		  addr => $addr,
    391		  base_addr => $base_addr,
    392		  argparams => {},
    393		  args => $args,
    394		  arglist => $arglist,
    395		  elsize => $size,
    396		);
    397
    398	if (!@$args) {
    399		$reglist .= "\t{ CCS_R_" . (uc $name) . ", 1,  0, \"" . (lc $name) . "\", NULL },\n";
    400		print $H tabconv $hdr_data;
    401		undef $hdr_data;
    402
    403		print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
    404		  $this{elsize} . ", 0, \"$name\" },\n"
    405		    if is_limit_reg $this{base_addr};
    406	}
    407
    408	print $LH tabconv sprintf "#define %-63s%s\n",
    409	  "CCS_L_" . (uc $this{name}), $limitcount++
    410	    if is_limit_reg $this{base_addr};
    411}
    412
    413if (defined $A) {
    414	print $A $argdescs, $reglist;
    415
    416	print $A "\t{ 0 }\n";
    417
    418	print $A "};\n";
    419}
    420
    421print $H "\n#endif /* __${uc_header}__ */\n";
    422
    423print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
    424
    425print $LH "\n#endif /* __${uc_limith}__ */\n";
    426
    427print $LC "\t{ 0 } /* Guardian */\n";
    428print $LC "};\n";
    429
    430close($R);
    431close($H);
    432close($A) if defined $A;
    433close($LC);
    434close($LH);