]>
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, | |
d377ba48 | 28 | plugin, plugin_log, console_pattern, args=None): |
4c134d07 AB |
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): | |
11959996 AB |
57 | kernel_url = ('https://storage.tuxboot.com/20230331/arm64/Image') |
58 | kernel_sha256 = 'ce95a7101a5fecebe0fe630deee6bd97b32ba41bc8754090e9ad8961ea8674c7' | |
59 | kernel_path = self.fetch_asset(kernel_url, | |
60 | asset_hash=kernel_sha256, | |
61 | algorithm = "sha256") | |
4c134d07 AB |
62 | return kernel_path |
63 | ||
64 | def test_aarch64_virt_insn(self): | |
65 | """ | |
66 | :avocado: tags=accel:tcg | |
67 | :avocado: tags=arch:aarch64 | |
68 | :avocado: tags=machine:virt | |
8a7c1fde | 69 | :avocado: tags=cpu:cortex-a53 |
4c134d07 AB |
70 | """ |
71 | kernel_path = self._grab_aarch64_kernel() | |
72 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
73 | 'console=ttyAMA0') | |
74 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
75 | ||
76 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
77 | suffix=".log") | |
78 | ||
79 | self.run_vm(kernel_path, kernel_command_line, | |
80 | "tests/plugin/libinsn.so", plugin_log.name, | |
d377ba48 | 81 | console_pattern) |
4c134d07 AB |
82 | |
83 | with plugin_log as lf, \ | |
84 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
85 | ||
86 | m = re.search(br"insns: (?P<count>\d+)", s) | |
87 | if "count" not in m.groupdict(): | |
88 | self.fail("Failed to find instruction count") | |
11959996 AB |
89 | else: |
90 | count = int(m.group("count")) | |
91 | self.log.info(f"Counted: {count} instructions") | |
92 | ||
36fc4a2f AB |
93 | |
94 | def test_aarch64_virt_insn_icount(self): | |
95 | """ | |
96 | :avocado: tags=accel:tcg | |
97 | :avocado: tags=arch:aarch64 | |
98 | :avocado: tags=machine:virt | |
8a7c1fde | 99 | :avocado: tags=cpu:cortex-a53 |
36fc4a2f AB |
100 | """ |
101 | kernel_path = self._grab_aarch64_kernel() | |
102 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
103 | 'console=ttyAMA0') | |
104 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
105 | ||
106 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
107 | suffix=".log") | |
108 | ||
109 | self.run_vm(kernel_path, kernel_command_line, | |
110 | "tests/plugin/libinsn.so", plugin_log.name, | |
111 | console_pattern, | |
d377ba48 | 112 | args=('-icount', 'shift=1')) |
36fc4a2f AB |
113 | |
114 | with plugin_log as lf, \ | |
115 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
11959996 AB |
116 | |
117 | m = re.search(br"insns: (?P<count>\d+)", s) | |
118 | if "count" not in m.groupdict(): | |
119 | self.fail("Failed to find instruction count") | |
120 | else: | |
121 | count = int(m.group("count")) | |
122 | self.log.info(f"Counted: {count} instructions") | |
df55e2a7 AB |
123 | |
124 | def test_aarch64_virt_mem_icount(self): | |
125 | """ | |
126 | :avocado: tags=accel:tcg | |
127 | :avocado: tags=arch:aarch64 | |
128 | :avocado: tags=machine:virt | |
8a7c1fde | 129 | :avocado: tags=cpu:cortex-a53 |
df55e2a7 AB |
130 | """ |
131 | kernel_path = self._grab_aarch64_kernel() | |
132 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
133 | 'console=ttyAMA0') | |
134 | console_pattern = 'Kernel panic - not syncing: VFS:' | |
135 | ||
136 | plugin_log = tempfile.NamedTemporaryFile(mode="r+t", prefix="plugin", | |
137 | suffix=".log") | |
138 | ||
139 | self.run_vm(kernel_path, kernel_command_line, | |
a7c6e562 | 140 | "tests/plugin/libmem.so,inline=true,callback=true", plugin_log.name, |
df55e2a7 | 141 | console_pattern, |
d377ba48 | 142 | args=('-icount', 'shift=1')) |
df55e2a7 AB |
143 | |
144 | with plugin_log as lf, \ | |
145 | mmap.mmap(lf.fileno(), 0, access=mmap.ACCESS_READ) as s: | |
146 | m = re.findall(br"mem accesses: (?P<count>\d+)", s) | |
147 | if m is None or len(m) != 2: | |
148 | self.fail("no memory access counts found") | |
149 | else: | |
150 | inline = int(m[0]) | |
151 | callback = int(m[1]) | |
152 | if inline != callback: | |
153 | self.fail("mismatched access counts") | |
11959996 AB |
154 | else: |
155 | self.log.info(f"Counted {inline} memory accesses") |