]>
Commit | Line | Data |
---|---|---|
4c134d07 AB |
1 | # TCG Plugins tests |
2 | # | |
3 | # These are a little more involved than the basic tests run by check-tcg. | |
4 | # | |
5 | # Copyright (c) 2021 Linaro | |
6 | # | |
7 | # Author: | |
8 | # Alex Bennée <alex.bennee@linaro.org> | |
9 | # | |
10 | # SPDX-License-Identifier: GPL-2.0-or-later | |
11 | ||
12 | import tempfile | |
13 | import mmap | |
14 | import re | |
15 | ||
16 | from boot_linux_console import LinuxKernelTest | |
17 | ||
18 | ||
19 | class PluginKernelBase(LinuxKernelTest): | |
20 | """ | |
21 | Boots a Linux kernel with a TCG plugin enabled. | |
22 | """ | |
23 | ||
24 | timeout = 120 | |
25 | KERNEL_COMMON_COMMAND_LINE = 'printk.time=1 panic=-1 ' | |
26 | ||
27 | def run_vm(self, kernel_path, kernel_command_line, | |
28 | plugin, plugin_log, console_pattern, args): | |
29 | ||
30 | vm = self.get_vm() | |
31 | vm.set_console() | |
32 | vm.add_args('-kernel', kernel_path, | |
33 | '-append', kernel_command_line, | |
34 | '-plugin', plugin, | |
35 | '-d', 'plugin', | |
36 | '-D', plugin_log, | |
37 | '-net', 'none', | |
38 | '-no-reboot') | |
39 | if args: | |
40 | vm.add_args(*args) | |
41 | ||
42 | try: | |
43 | vm.launch() | |
44 | except: | |
45 | # TODO: probably fails because plugins not enabled but we | |
46 | # can't currently probe for the feature. | |
47 | self.cancel("TCG Plugins not enabled?") | |
48 | ||
49 | self.wait_for_console_pattern(console_pattern, vm) | |
50 | # ensure logs are flushed | |
51 | vm.shutdown() | |
52 | ||
53 | ||
54 | class PluginKernelNormal(PluginKernelBase): | |
55 | ||
56 | def _grab_aarch64_kernel(self): | |
57 | kernel_url = ('http://security.debian.org/' | |
58 | 'debian-security/pool/updates/main/l/linux-signed-arm64/' | |
59 | 'linux-image-4.19.0-12-arm64_4.19.152-1_arm64.deb') | |
60 | kernel_sha1 = '2036c2792f80ac9c4ccaae742b2e0a28385b6010' | |
61 | kernel_deb = self.fetch_asset(kernel_url, asset_hash=kernel_sha1) | |
62 | kernel_path = self.extract_from_deb(kernel_deb, | |
63 | "/boot/vmlinuz-4.19.0-12-arm64") | |
64 | return kernel_path | |
65 | ||
66 | def test_aarch64_virt_insn(self): | |
67 | """ | |
68 | :avocado: tags=accel:tcg | |
69 | :avocado: tags=arch:aarch64 | |
70 | :avocado: tags=machine:virt | |
8a7c1fde | 71 | :avocado: tags=cpu:cortex-a53 |
4c134d07 AB |
72 | """ |
73 | kernel_path = self._grab_aarch64_kernel() | |
74 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
75 | 'console=ttyAMA0') | |
76 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
77 | ||
78 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
79 | suffix=".log") | |
80 | ||
81 | self.run_vm(kernel_path, kernel_command_line, | |
82 | "tests/plugin/libinsn.so", plugin_log.name, | |
83 | console_pattern, | |
84 | args=('-cpu', 'cortex-a53')) | |
85 | ||
86 | with plugin_log as lf, \ | |
87 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
88 | ||
89 | m = re.search(br"insns: (?P<count>\d+)", s) | |
90 | if "count" not in m.groupdict(): | |
91 | self.fail("Failed to find instruction count") | |
36fc4a2f AB |
92 | |
93 | def test_aarch64_virt_insn_icount(self): | |
94 | """ | |
95 | :avocado: tags=accel:tcg | |
96 | :avocado: tags=arch:aarch64 | |
97 | :avocado: tags=machine:virt | |
8a7c1fde | 98 | :avocado: tags=cpu:cortex-a53 |
36fc4a2f AB |
99 | """ |
100 | kernel_path = self._grab_aarch64_kernel() | |
101 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
102 | 'console=ttyAMA0') | |
103 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
104 | ||
105 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
106 | suffix=".log") | |
107 | ||
108 | self.run_vm(kernel_path, kernel_command_line, | |
109 | "tests/plugin/libinsn.so", plugin_log.name, | |
110 | console_pattern, | |
111 | args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) | |
112 | ||
113 | with plugin_log as lf, \ | |
114 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
115 | m = re.search(br"detected repeat execution @ (?P<addr>0x[0-9A-Fa-f]+)", s) | |
116 | if m is not None and "addr" in m.groupdict(): | |
117 | self.fail("detected repeated instructions") | |
df55e2a7 AB |
118 | |
119 | def test_aarch64_virt_mem_icount(self): | |
120 | """ | |
121 | :avocado: tags=accel:tcg | |
122 | :avocado: tags=arch:aarch64 | |
123 | :avocado: tags=machine:virt | |
8a7c1fde | 124 | :avocado: tags=cpu:cortex-a53 |
df55e2a7 AB |
125 | """ |
126 | kernel_path = self._grab_aarch64_kernel() | |
127 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
128 | 'console=ttyAMA0') | |
129 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
130 | ||
131 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
132 | suffix=".log") | |
133 | ||
134 | self.run_vm(kernel_path, kernel_command_line, | |
135 | "tests/plugin/libmem.so,arg=both", plugin_log.name, | |
136 | console_pattern, | |
137 | args=('-cpu', 'cortex-a53', '-icount', 'shift=1')) | |
138 | ||
139 | with plugin_log as lf, \ | |
140 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
141 | m = re.findall(br"mem accesses: (?P<count>\d+)", s) | |
142 | if m is None or len(m) != 2: | |
143 | self.fail("no memory access counts found") | |
144 | else: | |
145 | inline = int(m[0]) | |
146 | callback = int(m[1]) | |
147 | if inline != callback: | |
148 | self.fail("mismatched access counts") |