Commit f11df496 authored by imirkin's avatar imirkin Committed by nouveau

update instructions to be simpler, remove the long python versions

parent 8baeffa1
......@@ -2,93 +2,39 @@
<div id="google_translate_element"></div>
<script type="text/javascript" src="/wiki/translate.js"></script>
# Firmware
# Context Switching Firmware
## Status
You basically never need to do the mmiotrace, unless you're a nouveau developer. There is a script that will extract all the known (useful) firmware from the blob directly. See the [[VideoAcceleration]] page for instructions. [[A list of which cards do and don't need to load blob firmware at this point.|InstallDRM]]
You basically never need to do the mmiotrace, unless you're a nouveau developer. There is a script that will extract all the known (useful) firmware from the blob directly. See the [[VideoAcceleration]] page for instructions. If you have a Maxwell card, or want to attempt using firmware from blob versions not supported by the script, the instructions are below.
## Instructions
Do an [[MmioTrace]] of the blob
1. Do an [[MmioTrace]] of the blob. You just need to trace X starting (or a CUDA app). See [[these instructions|https://wiki.ubuntu.com/X/MMIOTracing]] for more details.
* Ensure that your kernel has MMIO tracing enabled
2. Extract the firmware into separate files. The below perl script will do so with the help of demmio, available as part of [EnvyTools](https://github.com/envytools/envytools).
Kernel Hacking -> Tracers -> Memory mapped IO tracing
demmio -f mmiotrace.log.xz | perl -e '
open($fh409c, ">fuc409c"); open($fh409d, ">fuc409d"); open($fh41ac, ">fuc41ac"); open($fh41ad, ">fuc41ad");
%m = ("0x409184" => $fh409c, "0x4091c4" => $fh409d, "0x41a184" => $fh41ac, "0x41a1c4" => $fh41ad);
while (<>) { exit if (/0x409840/); next if (!/W (0x4(?:09|1a)1[c8]4) .* <= (.*)/); print { $m{$1} } pack "I", hex($2);}'
* Boot up the system, without loading the blob or nouveau
* Mount debugfs and start the tracer
3. Rename the files to have a `nvXX_` prefix. For example if you have a NVE6 (as determined by 'Chipset' in dmesg), the files would be `nve6_fuc409c`, `nve6_fuc409d`, `nve6_fuc41ac`, and `nve6_fuc41ad`. (c = code, d = data)
mount -t debugfs debugfs /sys/kernel/debug
echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
* Load the blob kernel module (insmod nvidia)
* run X or a CUDA application
* Stop the tracer
echo nop > /sys/kernel/debug/tracing/current_tracer
Extract register writes from the trace and put them in binary files:
* 41a1c4 -> nvXX_fuc41ad
* 4091c4 -> nvXX_fuc409d
* 41a184 -> nvXX_fuc41ac
* 409184 -> nvXX_fuc409c
The important lines in the trace will look like this:
W 4 433.851950 1 0xXX41a1c4 0x2072614d 0x0 0
where `0xXX41a1c4` is the register and `0x2072614d` the value written
and put them in binary files in `/lib/firmware/nouveau/`
#!/usr/bin/python
import struct, sys, re
# substitute the correct value for XX
registers = {
'XX41a1c4': 'fuc41ad',
'XX4091c4': 'fuc409d',
'XX41a184': 'fuc41ac',
'XX409184': 'fuc409c',
}
firmwares = dict((register, open(registers[register], 'wb')) for register in registers)
for line in open(sys.argv[1]):
line = line.split()
if len(line) < 5:
continue
for register in registers:
if not re.match(r'0x%s' % register, line[4]):
continue
if not line[5].startswith('0x'):
break
firmwares[register].write(struct.pack('@I', int(line[5][2:], 16)))
Alternatively you can use this perl snippet in combination with demmio:
demmio -f mmiotrace.log.xz | perl -e '
open($fh409c, ">fuc409c"); open($fh409d, ">fuc409d"); open($fh41ac, ">fuc41ac"); open($fh41ad, ">fuc41ad");
%m = ("0x409184" => $fh409c, "0x4091c4" => $fh409d, "0x41a184" => $fh41ac, "0x41a1c4" => $fh41ad);
while (<>) { exit if (/0x409840/); next if (!/W (0x4(?:09|1a)1[c8]4) .* <= (.*)/); print { $m{$1} } pack "I", hex($2);}'
Note: These instructions were tested with 340.32. Other versions should work fine too, but if the firmware upload mechanism is too different, it will fail.
---
# Video firmware
Unlike the firmware you need above, there is no requirement on version. Up to nvidia 310.* will likely work. Newer versions are untested, but should still work. Note that there is a script which performs the extraction from the blob directly, see [[VideoAcceleration|VideoAcceleration#firmware]].
Note that there is a script which performs the extraction from the blob directly, see [[VideoAcceleration|VideoAcceleration#firmware]]. To extract from a blob version that is not supported by the script, you can try the below:
## Extracting kernel video firmware on fermi and kepler.
## Extracting kernel video firmware on VP3/4/5:
There are 2 sets of firmware for video decoding, one for kernel and one for userspace. Only nvc0 series need the userspace firmware. Kepler, and also nvd9 do **NOT** have userspace firmware.
There are 2 sets of firmware for video decoding, one for kernel and one for userspace. Only VP3/4 series have the userspace firmware. VP5 does not have userspace firmware. (So, pre-GF117 has userspace firmware, post GF117 and later does not.)
The kernel parts can be obtained by doing a mmiotrace of a program using vdpau for video decoding, for example mplayer -vc ffmpeg12vdpau,ffh264vdpau,ffwmv3vdpau,ffvc1vdpau,ffodivxvdpau, somefile.mkv
......@@ -100,29 +46,20 @@ After you obtained the mmiotrace, look for the base offsets used by the firmware
[0] 445.938745 MMIO32 W 0x086110 0x004dd800 PPPP.XFER_EXT_BASE <= 0x4dd80000
$ demmio -f vdpau-mmiotrace | less
/RAMIN32.*4de40000
/RAMIN32.*4de40000 (i.e. search for the PBSP offset)
would get you to the start of the mmiotrace, from my log I could see the RAMIN32 writes end at 4de50918, so I need to grab 4de[45].* for BSP firmware:
$ demmio -f vdpau-mmiotrace 2>&1 | grep 'RAMIN32 .* 4de[45].* <=' | awk '{ print $7 }' | python -c \
"
import struct; import sys; fd = open(\"fuc084\", \"wb\");
for line in sys.stdin:
fd.write(struct.pack(\"@I\", int(line.rstrip(), 16)))
"
Alternatively, you can use perl to execute for the last command. It is also more convenient as the same script can be used for all firmwares:
$ demmio -f vdpau-mmiotrace | grep 'RAMIN32 .* 4de[45].* <=' | awk '{ print $7 }' | perl -ne 'print pack "I", hex($_)' > nvXX_fuc084
This was just for PBSP, but the same applies to PVP with fuc085, and PPPP with fuc086. Put the resulting files in /lib/firmware/nouveau/
Offsets may differ, and it is recommended to check you don't end up with too big or too small a file. It *looks* like mine are multiples of 1000 bytes, on the nvidia 310 drivers.
Offsets may differ, and it is recommended to check you don't end up with too big or too small a file. Sometimes the addresses in memory will not lend themselves nicely to regular expressions. In that case, you can just manually extract the portion of the mmiotrace that you would like to end up in the fuc file and adjust the command above accordingly (i.e. start at `awk`).
---
## Extracting userspace video firmware on nvc0 series (fermi) (NOT NVD9!!)
## Extracting userspace video firmware (pre-GF117)
Requirements:
......@@ -130,6 +67,7 @@ Requirements:
* [[Valgrind-mmt]]
* build a recent envytools.git, and go to envytools.git/vdpow directory
* with nvidia drivers enabled and X server running, do:
* `/usr/local/bin/valgrind --tool=mmt --mmt-trace-file=/dev/nvidia0 --mmt-trace-file=/dev/dri/card0 --mmt-trace-nvidia-ioctls --mmt-trace-nouveau-ioctls ./mmt_ufw 2>&1 | ./dumpstruct -m 10`
* `/usr/local/bin/valgrind --tool=mmt --mmt-trace-file=/dev/nvidia0 --mmt-trace-nvidia-ioctls ./mmt_ufw 2>&1 | ./dumpstruct -m 10`
* Note: dumpstruct is not designed to work with the new binary logging format of mmt. But this firmware hasn't changed in a long time, just use the one output by the firmware extraction script.
Copy the resulting `vuc-*` files to `/lib/firmware/nouveau/`
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment