| /* |
| * Check decoding of s390_pci_mmio_read and s390_pci_mmio_write syscalls. |
| * |
| * Copyright (c) 2018 The strace developers. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "tests.h" |
| #include <asm/unistd.h> |
| |
| #if defined __NR_s390_pci_mmio_read && defined __NR_s390_pci_mmio_write |
| |
| # include <errno.h> |
| # include <stdint.h> |
| # include <stdio.h> |
| # include <unistd.h> |
| |
| static void |
| do_call(bool wr, kernel_ulong_t mmio_addr, kernel_ulong_t buf, |
| kernel_ulong_t len, bool buf_valid, const char *buf_str) |
| { |
| long saved_errno = 0; |
| long rc = 0; |
| |
| printf("s390_pci_mmio_%s(%#llx, ", wr ? "write" : "read", |
| (unsigned long long) mmio_addr); |
| |
| if (!wr) { |
| rc = syscall(__NR_s390_pci_mmio_read, mmio_addr, buf, len); |
| saved_errno = errno; |
| } |
| |
| if (buf_valid && !rc) { |
| char *buf_ptr = (char *) (uintptr_t) buf; |
| |
| print_quoted_hex(buf_ptr, |
| len > DEFAULT_STRLEN ? DEFAULT_STRLEN : len); |
| |
| if (len > DEFAULT_STRLEN) |
| printf("..."); |
| } else { |
| if (buf_str) |
| printf("%s", buf_str); |
| else |
| printf("%#llx", (unsigned long long) buf); |
| } |
| |
| printf(", %llu) = ", (unsigned long long) len); |
| |
| if (wr) |
| rc = syscall(__NR_s390_pci_mmio_write, mmio_addr, buf, len); |
| else |
| errno = saved_errno; |
| |
| puts(sprintrc(rc)); |
| } |
| |
| int |
| main(void) |
| { |
| static const size_t buf_size = DEFAULT_STRLEN + 10; |
| |
| char *buf = tail_alloc(buf_size); |
| |
| bool bools[] = { true, false }; |
| |
| kernel_ulong_t addrs[] = { |
| 0, |
| (kernel_ulong_t) 0xdeafbeefdeadc0deULL, |
| }; |
| |
| struct { |
| kernel_ulong_t buf; |
| const char *str; |
| size_t size; |
| } bufs[] = { |
| { (kernel_ulong_t) ARG_STR(NULL), 0 }, |
| { (kernel_ulong_t) (buf + buf_size), NULL, 0 }, |
| { (kernel_ulong_t) (buf), NULL, buf_size }, |
| { (kernel_ulong_t) (buf + 9), NULL, buf_size - 9 }, |
| { (kernel_ulong_t) (buf + 10), NULL, buf_size - 10 }, |
| { (kernel_ulong_t) (buf + 16), NULL, buf_size - 16 }, |
| { (kernel_ulong_t) (buf + 26), NULL, buf_size - 26 }, |
| { (kernel_ulong_t) (buf + 28), NULL, buf_size - 28 }, |
| }; |
| |
| kernel_ulong_t sizes[] = { |
| 0, |
| DEFAULT_STRLEN / 2, |
| DEFAULT_STRLEN - 10, |
| DEFAULT_STRLEN, |
| DEFAULT_STRLEN + 1, |
| buf_size, |
| buf_size + 10, |
| (kernel_ulong_t) 0xfacefeedac0ffeedULL, |
| }; |
| |
| unsigned int i, j, k, l; |
| unsigned int ctr = 0; |
| |
| for (i = 0; i < ARRAY_SIZE(addrs); i++) { |
| for (j = 0; j < ARRAY_SIZE(bufs); j++) { |
| for (k = 0; k < ARRAY_SIZE(sizes); k++) { |
| for (l = 0; l < ARRAY_SIZE(bools); l++) { |
| bool valid = bufs[j].buf && |
| bufs[j].size >= |
| MIN(sizes[k], |
| DEFAULT_STRLEN + 1); |
| |
| if (bufs[j].size && bools[l]) |
| fill_memory_ex((char *) buf, |
| bufs[j].size, |
| 0xC0 + ctr, 255); |
| |
| do_call(bools[l], addrs[i], bufs[j].buf, |
| sizes[k], valid, bufs[j].str); |
| |
| ctr++; |
| } |
| } |
| } |
| } |
| |
| puts("+++ exited with 0 +++"); |
| return 0; |
| } |
| |
| #else |
| |
| SKIP_MAIN_UNDEFINED("__NR_s390_pci_mmio_read && __NR_s390_pci_mmio_write"); |
| |
| #endif |