Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2016 Google, Inc.
  4 *
  5 * Original Code by Pavel Labath <labath@google.com>
  6 *
  7 * Code modified by Pratyush Anand <panand@redhat.com>
  8 * for testing different byte select for each access size.
  9 */
 10
 11#define _GNU_SOURCE
 12
 13#include <asm/ptrace.h>
 14#include <sys/types.h>
 15#include <sys/wait.h>
 16#include <sys/ptrace.h>
 17#include <sys/param.h>
 18#include <sys/uio.h>
 19#include <stdint.h>
 20#include <stdbool.h>
 21#include <stddef.h>
 22#include <string.h>
 23#include <stdio.h>
 24#include <unistd.h>
 25#include <elf.h>
 26#include <errno.h>
 27#include <signal.h>
 28
 29#include "../kselftest.h"
 30
 31static volatile uint8_t var[96] __attribute__((__aligned__(32)));
 32
 33static void child(int size, int wr)
 34{
 35	volatile uint8_t *addr = &var[32 + wr];
 36
 37	if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
 38		ksft_print_msg(
 39			"ptrace(PTRACE_TRACEME) failed: %s\n",
 40			strerror(errno));
 41		_exit(1);
 42	}
 43
 44	if (raise(SIGSTOP) != 0) {
 45		ksft_print_msg(
 46			"raise(SIGSTOP) failed: %s\n", strerror(errno));
 47		_exit(1);
 48	}
 49
 50	if ((uintptr_t) addr % size) {
 51		ksft_print_msg(
 52			 "Wrong address write for the given size: %s\n",
 53			 strerror(errno));
 54		_exit(1);
 55	}
 56
 57	switch (size) {
 58	case 1:
 59		*addr = 47;
 60		break;
 61	case 2:
 62		*(uint16_t *)addr = 47;
 63		break;
 64	case 4:
 65		*(uint32_t *)addr = 47;
 66		break;
 67	case 8:
 68		*(uint64_t *)addr = 47;
 69		break;
 70	case 16:
 71		__asm__ volatile ("stp x29, x30, %0" : "=m" (addr[0]));
 72		break;
 73	case 32:
 74		__asm__ volatile ("stp q29, q30, %0" : "=m" (addr[0]));
 75		break;
 76	}
 77
 78	_exit(0);
 79}
 80
 81static bool set_watchpoint(pid_t pid, int size, int wp)
 82{
 83	const volatile uint8_t *addr = &var[32 + wp];
 84	const int offset = (uintptr_t)addr % 8;
 85	const unsigned int byte_mask = ((1 << size) - 1) << offset;
 86	const unsigned int type = 2; /* Write */
 87	const unsigned int enable = 1;
 88	const unsigned int control = byte_mask << 5 | type << 3 | enable;
 89	struct user_hwdebug_state dreg_state;
 90	struct iovec iov;
 91
 92	memset(&dreg_state, 0, sizeof(dreg_state));
 93	dreg_state.dbg_regs[0].addr = (uintptr_t)(addr - offset);
 94	dreg_state.dbg_regs[0].ctrl = control;
 95	iov.iov_base = &dreg_state;
 96	iov.iov_len = offsetof(struct user_hwdebug_state, dbg_regs) +
 97				sizeof(dreg_state.dbg_regs[0]);
 98	if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0)
 99		return true;
100
101	if (errno == EIO)
102		ksft_print_msg(
103			"ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) not supported on this hardware: %s\n",
104			strerror(errno));
105
106	ksft_print_msg(
107		"ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed: %s\n",
108		strerror(errno));
109	return false;
110}
111
112static bool run_test(int wr_size, int wp_size, int wr, int wp)
113{
114	int status;
115	siginfo_t siginfo;
116	pid_t pid = fork();
117	pid_t wpid;
118
119	if (pid < 0) {
120		ksft_test_result_fail(
121			"fork() failed: %s\n", strerror(errno));
122		return false;
123	}
124	if (pid == 0)
125		child(wr_size, wr);
126
127	wpid = waitpid(pid, &status, __WALL);
128	if (wpid != pid) {
129		ksft_print_msg(
130			"waitpid() failed: %s\n", strerror(errno));
131		return false;
132	}
133	if (!WIFSTOPPED(status)) {
134		ksft_print_msg(
135			"child did not stop: %s\n", strerror(errno));
136		return false;
137	}
138	if (WSTOPSIG(status) != SIGSTOP) {
139		ksft_print_msg("child did not stop with SIGSTOP\n");
140		return false;
141	}
142
143	if (!set_watchpoint(pid, wp_size, wp))
144		return false;
145
146	if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
147		ksft_print_msg(
148			"ptrace(PTRACE_SINGLESTEP) failed: %s\n",
149			strerror(errno));
150		return false;
151	}
152
153	alarm(3);
154	wpid = waitpid(pid, &status, __WALL);
155	if (wpid != pid) {
156		ksft_print_msg(
157			"waitpid() failed: %s\n", strerror(errno));
158		return false;
159	}
160	alarm(0);
161	if (WIFEXITED(status)) {
162		ksft_print_msg("child did not single-step\n");
163		return false;
164	}
165	if (!WIFSTOPPED(status)) {
166		ksft_print_msg("child did not stop\n");
167		return false;
168	}
169	if (WSTOPSIG(status) != SIGTRAP) {
170		ksft_print_msg("child did not stop with SIGTRAP\n");
171		return false;
172	}
173	if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0) {
174		ksft_print_msg(
175			"ptrace(PTRACE_GETSIGINFO): %s\n",
176			strerror(errno));
177		return false;
178	}
179	if (siginfo.si_code != TRAP_HWBKPT) {
180		ksft_print_msg(
181			"Unexpected si_code %d\n", siginfo.si_code);
182		return false;
183	}
184
185	kill(pid, SIGKILL);
186	wpid = waitpid(pid, &status, 0);
187	if (wpid != pid) {
188		ksft_print_msg(
189			"waitpid() failed: %s\n", strerror(errno));
190		return false;
191	}
192	return true;
193}
194
195static void sigalrm(int sig)
196{
197}
198
199int main(int argc, char **argv)
200{
201	int opt;
202	bool succeeded = true;
203	struct sigaction act;
204	int wr, wp, size;
205	bool result;
206
207	ksft_print_header();
208	ksft_set_plan(213);
209
210	act.sa_handler = sigalrm;
211	sigemptyset(&act.sa_mask);
212	act.sa_flags = 0;
213	sigaction(SIGALRM, &act, NULL);
214	for (size = 1; size <= 32; size = size*2) {
215		for (wr = 0; wr <= 32; wr = wr + size) {
216			for (wp = wr - size; wp <= wr + size; wp = wp + size) {
217				result = run_test(size, MIN(size, 8), wr, wp);
218				if ((result && wr == wp) ||
219				    (!result && wr != wp))
220					ksft_test_result_pass(
221						"Test size = %d write offset = %d watchpoint offset = %d\n",
222						size, wr, wp);
223				else {
224					ksft_test_result_fail(
225						"Test size = %d write offset = %d watchpoint offset = %d\n",
226						size, wr, wp);
227					succeeded = false;
228				}
229			}
230		}
231	}
232
233	for (size = 1; size <= 32; size = size*2) {
234		if (run_test(size, 8, -size, -8))
235			ksft_test_result_pass(
236				"Test size = %d write offset = %d watchpoint offset = -8\n",
237				size, -size);
238		else {
239			ksft_test_result_fail(
240				"Test size = %d write offset = %d watchpoint offset = -8\n",
241				size, -size);
242			succeeded = false;
243		}
244	}
245
246	if (succeeded)
247		ksft_exit_pass();
248	else
249		ksft_exit_fail();
250}
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2016 Google, Inc.
  4 *
  5 * Original Code by Pavel Labath <labath@google.com>
  6 *
  7 * Code modified by Pratyush Anand <panand@redhat.com>
  8 * for testing different byte select for each access size.
  9 */
 10
 11#define _GNU_SOURCE
 12
 13#include <asm/ptrace.h>
 14#include <sys/types.h>
 15#include <sys/wait.h>
 16#include <sys/ptrace.h>
 17#include <sys/param.h>
 18#include <sys/uio.h>
 19#include <stdint.h>
 20#include <stdbool.h>
 21#include <stddef.h>
 22#include <string.h>
 23#include <stdio.h>
 24#include <unistd.h>
 25#include <elf.h>
 26#include <errno.h>
 27#include <signal.h>
 28
 29#include "../kselftest.h"
 30
 31static volatile uint8_t var[96] __attribute__((__aligned__(32)));
 32
 33static void child(int size, int wr)
 34{
 35	volatile uint8_t *addr = &var[32 + wr];
 36
 37	if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
 38		ksft_print_msg(
 39			"ptrace(PTRACE_TRACEME) failed: %s\n",
 40			strerror(errno));
 41		_exit(1);
 42	}
 43
 44	if (raise(SIGSTOP) != 0) {
 45		ksft_print_msg(
 46			"raise(SIGSTOP) failed: %s\n", strerror(errno));
 47		_exit(1);
 48	}
 49
 50	if ((uintptr_t) addr % size) {
 51		ksft_print_msg(
 52			 "Wrong address write for the given size: %s\n",
 53			 strerror(errno));
 54		_exit(1);
 55	}
 56
 57	switch (size) {
 58	case 1:
 59		*addr = 47;
 60		break;
 61	case 2:
 62		*(uint16_t *)addr = 47;
 63		break;
 64	case 4:
 65		*(uint32_t *)addr = 47;
 66		break;
 67	case 8:
 68		*(uint64_t *)addr = 47;
 69		break;
 70	case 16:
 71		__asm__ volatile ("stp x29, x30, %0" : "=m" (addr[0]));
 72		break;
 73	case 32:
 74		__asm__ volatile ("stp q29, q30, %0" : "=m" (addr[0]));
 75		break;
 76	}
 77
 78	_exit(0);
 79}
 80
 81static bool set_watchpoint(pid_t pid, int size, int wp)
 82{
 83	const volatile uint8_t *addr = &var[32 + wp];
 84	const int offset = (uintptr_t)addr % 8;
 85	const unsigned int byte_mask = ((1 << size) - 1) << offset;
 86	const unsigned int type = 2; /* Write */
 87	const unsigned int enable = 1;
 88	const unsigned int control = byte_mask << 5 | type << 3 | enable;
 89	struct user_hwdebug_state dreg_state;
 90	struct iovec iov;
 91
 92	memset(&dreg_state, 0, sizeof(dreg_state));
 93	dreg_state.dbg_regs[0].addr = (uintptr_t)(addr - offset);
 94	dreg_state.dbg_regs[0].ctrl = control;
 95	iov.iov_base = &dreg_state;
 96	iov.iov_len = offsetof(struct user_hwdebug_state, dbg_regs) +
 97				sizeof(dreg_state.dbg_regs[0]);
 98	if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0)
 99		return true;
100
101	if (errno == EIO)
102		ksft_print_msg(
103			"ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) not supported on this hardware: %s\n",
104			strerror(errno));
105
106	ksft_print_msg(
107		"ptrace(PTRACE_SETREGSET, NT_ARM_HW_WATCH) failed: %s\n",
108		strerror(errno));
109	return false;
110}
111
112static bool run_test(int wr_size, int wp_size, int wr, int wp)
113{
114	int status;
115	siginfo_t siginfo;
116	pid_t pid = fork();
117	pid_t wpid;
118
119	if (pid < 0) {
120		ksft_test_result_fail(
121			"fork() failed: %s\n", strerror(errno));
122		return false;
123	}
124	if (pid == 0)
125		child(wr_size, wr);
126
127	wpid = waitpid(pid, &status, __WALL);
128	if (wpid != pid) {
129		ksft_print_msg(
130			"waitpid() failed: %s\n", strerror(errno));
131		return false;
132	}
133	if (!WIFSTOPPED(status)) {
134		ksft_print_msg(
135			"child did not stop: %s\n", strerror(errno));
136		return false;
137	}
138	if (WSTOPSIG(status) != SIGSTOP) {
139		ksft_print_msg("child did not stop with SIGSTOP\n");
140		return false;
141	}
142
143	if (!set_watchpoint(pid, wp_size, wp))
144		return false;
145
146	if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
147		ksft_print_msg(
148			"ptrace(PTRACE_CONT) failed: %s\n",
149			strerror(errno));
150		return false;
151	}
152
153	alarm(3);
154	wpid = waitpid(pid, &status, __WALL);
155	if (wpid != pid) {
156		ksft_print_msg(
157			"waitpid() failed: %s\n", strerror(errno));
158		return false;
159	}
160	alarm(0);
161	if (WIFEXITED(status)) {
162		ksft_print_msg("child exited prematurely\n");
163		return false;
164	}
165	if (!WIFSTOPPED(status)) {
166		ksft_print_msg("child did not stop\n");
167		return false;
168	}
169	if (WSTOPSIG(status) != SIGTRAP) {
170		ksft_print_msg("child did not stop with SIGTRAP\n");
171		return false;
172	}
173	if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0) {
174		ksft_print_msg(
175			"ptrace(PTRACE_GETSIGINFO): %s\n",
176			strerror(errno));
177		return false;
178	}
179	if (siginfo.si_code != TRAP_HWBKPT) {
180		ksft_print_msg(
181			"Unexpected si_code %d\n", siginfo.si_code);
182		return false;
183	}
184
185	kill(pid, SIGKILL);
186	wpid = waitpid(pid, &status, 0);
187	if (wpid != pid) {
188		ksft_print_msg(
189			"waitpid() failed: %s\n", strerror(errno));
190		return false;
191	}
192	return true;
193}
194
195static void sigalrm(int sig)
196{
197}
198
199int main(int argc, char **argv)
200{
201	int opt;
202	bool succeeded = true;
203	struct sigaction act;
204	int wr, wp, size;
205	bool result;
206
207	ksft_print_header();
208	ksft_set_plan(213);
209
210	act.sa_handler = sigalrm;
211	sigemptyset(&act.sa_mask);
212	act.sa_flags = 0;
213	sigaction(SIGALRM, &act, NULL);
214	for (size = 1; size <= 32; size = size*2) {
215		for (wr = 0; wr <= 32; wr = wr + size) {
216			for (wp = wr - size; wp <= wr + size; wp = wp + size) {
217				result = run_test(size, MIN(size, 8), wr, wp);
218				if ((result && wr == wp) ||
219				    (!result && wr != wp))
220					ksft_test_result_pass(
221						"Test size = %d write offset = %d watchpoint offset = %d\n",
222						size, wr, wp);
223				else {
224					ksft_test_result_fail(
225						"Test size = %d write offset = %d watchpoint offset = %d\n",
226						size, wr, wp);
227					succeeded = false;
228				}
229			}
230		}
231	}
232
233	for (size = 1; size <= 32; size = size*2) {
234		if (run_test(size, 8, -size, -8))
235			ksft_test_result_pass(
236				"Test size = %d write offset = %d watchpoint offset = -8\n",
237				size, -size);
238		else {
239			ksft_test_result_fail(
240				"Test size = %d write offset = %d watchpoint offset = -8\n",
241				size, -size);
242			succeeded = false;
243		}
244	}
245
246	if (succeeded)
247		ksft_exit_pass();
248	else
249		ksft_exit_fail();
250}