https://github.com/torvalds/linux
Revision 51a63e67da6056c13b5b597dcc9e1b3bd7ceaa55 authored by Joseph Cihula on 21 March 2011, 18:04:24 UTC, committed by David Woodhouse on 21 April 2011, 12:51:40 UTC
Intel VT-d Protected Memory Regions (PMRs) are supposed to be disabled, on each VT-d engine, after DMA remapping is enabled on the engines. This is because the behavior of having both enabled is not deterministic and because, if TXT has been used to launch the kernel, the PMRs may be programmed to cover memory regions that will be used for DMA. Under some circumstances (certain quirks detected, lack of multiple devices, etc.), the current code does not set up DMA remapping on some VT-d engines. In such cases it also skips disabling the PMRs. This causes failures when the kernel is launched with TXT (most often this occurs on the graphics engine and results in colored vertical bars on the display). This patch detects when the kernel has been launched with TXT and then disables the PMRs on all VT-d engines. In some cases where the reason that remapping is not being enabled is due to possible ACPI DMAR table errors, the VT-d engine addresses may not be correct and thus not able to be safely programmed even to disable PMRs. Because part of the TXT launch process is the verification of these addresses, it will always be safe to disable PMRs if the TXT launch has succeeded and hence only doing this in such cases. Signed-off-by: Joseph Cihula <joseph.cihula@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
1 parent 2fe9723
Tip revision: 51a63e67da6056c13b5b597dcc9e1b3bd7ceaa55 authored by Joseph Cihula on 21 March 2011, 18:04:24 UTC
intel_iommu: disable all VT-d PMRs when TXT launched
intel_iommu: disable all VT-d PMRs when TXT launched
Tip revision: 51a63e6
cleanpatch
#!/usr/bin/perl -w
#
# Clean a patch file -- or directory of patch files -- of stealth whitespace.
# WARNING: this can be a highly destructive operation. Use with caution.
#
use bytes;
use File::Basename;
# Default options
$max_width = 79;
# Clean up space-tab sequences, either by removing spaces or
# replacing them with tabs.
sub clean_space_tabs($)
{
no bytes; # Tab alignment depends on characters
my($li) = @_;
my($lo) = '';
my $pos = 0;
my $nsp = 0;
my($i, $c);
for ($i = 0; $i < length($li); $i++) {
$c = substr($li, $i, 1);
if ($c eq "\t") {
my $npos = ($pos+$nsp+8) & ~7;
my $ntab = ($npos >> 3) - ($pos >> 3);
$lo .= "\t" x $ntab;
$pos = $npos;
$nsp = 0;
} elsif ($c eq "\n" || $c eq "\r") {
$lo .= " " x $nsp;
$pos += $nsp;
$nsp = 0;
$lo .= $c;
$pos = 0;
} elsif ($c eq " ") {
$nsp++;
} else {
$lo .= " " x $nsp;
$pos += $nsp;
$nsp = 0;
$lo .= $c;
$pos++;
}
}
$lo .= " " x $nsp;
return $lo;
}
# Compute the visual width of a string
sub strwidth($) {
no bytes; # Tab alignment depends on characters
my($li) = @_;
my($c, $i);
my $pos = 0;
my $mlen = 0;
for ($i = 0; $i < length($li); $i++) {
$c = substr($li,$i,1);
if ($c eq "\t") {
$pos = ($pos+8) & ~7;
} elsif ($c eq "\n") {
$mlen = $pos if ($pos > $mlen);
$pos = 0;
} else {
$pos++;
}
}
$mlen = $pos if ($pos > $mlen);
return $mlen;
}
$name = basename($0);
@files = ();
while (defined($a = shift(@ARGV))) {
if ($a =~ /^-/) {
if ($a eq '-width' || $a eq '-w') {
$max_width = shift(@ARGV)+0;
} else {
print STDERR "Usage: $name [-width #] files...\n";
exit 1;
}
} else {
push(@files, $a);
}
}
foreach $f ( @files ) {
print STDERR "$name: $f\n";
if (! -f $f) {
print STDERR "$f: not a file\n";
next;
}
if (!open(FILE, '+<', $f)) {
print STDERR "$name: Cannot open file: $f: $!\n";
next;
}
binmode FILE;
# First, verify that it is not a binary file; consider any file
# with a zero byte to be a binary file. Is there any better, or
# additional, heuristic that should be applied?
$is_binary = 0;
while (read(FILE, $data, 65536) > 0) {
if ($data =~ /\0/) {
$is_binary = 1;
last;
}
}
if ($is_binary) {
print STDERR "$name: $f: binary file\n";
next;
}
seek(FILE, 0, 0);
$in_bytes = 0;
$out_bytes = 0;
$lineno = 0;
@lines = ();
$in_hunk = 0;
$err = 0;
while ( defined($line = <FILE>) ) {
$lineno++;
$in_bytes += length($line);
if (!$in_hunk) {
if ($line =~
/^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@/) {
$minus_lines = $2;
$plus_lines = $4;
if ($minus_lines || $plus_lines) {
$in_hunk = 1;
@hunk_lines = ($line);
}
} else {
push(@lines, $line);
$out_bytes += length($line);
}
} else {
# We're in a hunk
if ($line =~ /^\+/) {
$plus_lines--;
$text = substr($line, 1);
$text =~ s/[ \t\r]*$//; # Remove trailing spaces
$text = clean_space_tabs($text);
$l_width = strwidth($text);
if ($max_width && $l_width > $max_width) {
print STDERR
"$f:$lineno: adds line exceeds $max_width ",
"characters ($l_width)\n";
}
push(@hunk_lines, '+'.$text);
} elsif ($line =~ /^\-/) {
$minus_lines--;
push(@hunk_lines, $line);
} elsif ($line =~ /^ /) {
$plus_lines--;
$minus_lines--;
push(@hunk_lines, $line);
} else {
print STDERR "$name: $f: malformed patch\n";
$err = 1;
last;
}
if ($plus_lines < 0 || $minus_lines < 0) {
print STDERR "$name: $f: malformed patch\n";
$err = 1;
last;
} elsif ($plus_lines == 0 && $minus_lines == 0) {
# End of a hunk. Process this hunk.
my $i;
my $l;
my @h = ();
my $adj = 0;
my $done = 0;
for ($i = scalar(@hunk_lines)-1; $i > 0; $i--) {
$l = $hunk_lines[$i];
if (!$done && $l eq "+\n") {
$adj++; # Skip this line
} elsif ($l =~ /^[ +]/) {
$done = 1;
unshift(@h, $l);
} else {
unshift(@h, $l);
}
}
$l = $hunk_lines[0]; # Hunk header
undef @hunk_lines; # Free memory
if ($adj) {
die unless
($l =~ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@(.*)$/);
my $mstart = $1;
my $mlin = $2;
my $pstart = $3;
my $plin = $4;
my $tail = $5; # doesn't include the final newline
$l = sprintf("@@ -%d,%d +%d,%d @@%s\n",
$mstart, $mlin, $pstart, $plin-$adj,
$tail);
}
unshift(@h, $l);
# Transfer to the output array
foreach $l (@h) {
$out_bytes += length($l);
push(@lines, $l);
}
$in_hunk = 0;
}
}
}
if ($in_hunk) {
print STDERR "$name: $f: malformed patch\n";
$err = 1;
}
if (!$err) {
if ($in_bytes != $out_bytes) {
# Only write to the file if changed
seek(FILE, 0, 0);
print FILE @lines;
if ( !defined($where = tell(FILE)) ||
!truncate(FILE, $where) ) {
die "$name: Failed to truncate modified file: $f: $!\n";
}
}
}
close(FILE);
}
Computing file changes ...