diff options
author | Alex Bennée <alex.bennee@linaro.org> | 2018-04-05 15:03:22 +0100 |
---|---|---|
committer | Alex Bennée <alex.bennee@linaro.org> | 2018-06-20 20:22:34 +0100 |
commit | dd28bebd024b4c7cfb6352126cd010d389a8d374 (patch) | |
tree | e6396a4e43bf7f44eefeae6b35faf134e326ce58 /tests/tcg/multiarch | |
parent | e27cae268fc18a22b7842fae1fe8257df704741a (diff) | |
download | qemu-dd28bebd024b4c7cfb6352126cd010d389a8d374.zip qemu-dd28bebd024b4c7cfb6352126cd010d389a8d374.tar.gz qemu-dd28bebd024b4c7cfb6352126cd010d389a8d374.tar.bz2 |
tests/tcg: move architecture independent tests into subdir
We will want to build these for all supported guest architectures so
lets move them all into one place. We also drop test_path at this
point because it needs qemu utils and glib bits which is hard to
support for cross compiling.
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tests/tcg/multiarch')
-rw-r--r-- | tests/tcg/multiarch/Makefile.target | 36 | ||||
-rw-r--r-- | tests/tcg/multiarch/README | 1 | ||||
-rw-r--r-- | tests/tcg/multiarch/linux-test.c | 539 | ||||
-rw-r--r-- | tests/tcg/multiarch/sha1.c | 240 | ||||
-rw-r--r-- | tests/tcg/multiarch/test-mmap.c | 484 | ||||
-rw-r--r-- | tests/tcg/multiarch/testthread.c | 57 |
6 files changed, 1357 insertions, 0 deletions
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target new file mode 100644 index 0000000..90e45a8 --- /dev/null +++ b/tests/tcg/multiarch/Makefile.target @@ -0,0 +1,36 @@ +# -*- Mode: makefile -*- +# +# Multiarch Tests - included from tests/tcg/Makefile.target +# +# These tests are plain C and built without any architecture specific code. +# + +MULTIARCH_SRC=$(SRC_PATH)/tests/tcg/multiarch + +# Set search path for all sources +VPATH += $(MULTIARCH_SRC) +MULTIARCH_SRCS =$(notdir $(wildcard $(MULTIARCH_SRC)/*.c)) +MULTIARCH_TESTS =$(MULTIARCH_SRCS:.c=) + +# Update TESTS +TESTS +=$(MULTIARCH_TESTS) + +# +# The following are any additional rules needed to build things +# + +testthread: LDFLAGS+=-lpthread + +# We define the runner for test-mmap after the individual +# architectures have defined their supported pages sizes. If no +# additional page sizes are defined we only run the default test. + +# default case (host page size) +run-test-mmap: test-mmap + $(call quiet-command, $(QEMU) $< > test-mmap.out, "TEST", \ + "$< (default) on $(TARGET_NAME)") + +# additional page sizes (defined by each architecture adding to EXTRA_RUNS) +run-test-mmap-%: test-mmap + $(call quiet-command, $(QEMU) -p $* $< > test-mmap-$*.out, "TEST", \ + "$< ($* byte pages) on $(TARGET_NAME)") diff --git a/tests/tcg/multiarch/README b/tests/tcg/multiarch/README new file mode 100644 index 0000000..522c9d2 --- /dev/null +++ b/tests/tcg/multiarch/README @@ -0,0 +1 @@ +Multi-architecture linux-user tests diff --git a/tests/tcg/multiarch/linux-test.c b/tests/tcg/multiarch/linux-test.c new file mode 100644 index 0000000..5070d31 --- /dev/null +++ b/tests/tcg/multiarch/linux-test.c @@ -0,0 +1,539 @@ +/* + * linux and CPU test + * + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#define _GNU_SOURCE +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <inttypes.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <errno.h> +#include <utime.h> +#include <time.h> +#include <sys/time.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sched.h> +#include <dirent.h> +#include <setjmp.h> +#include <sys/shm.h> +#include "qemu/cutils.h" + +#define TESTPATH "/tmp/linux-test.tmp" +#define TESTPORT 7654 +#define STACK_SIZE 16384 + +void error1(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d: ", filename, line); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +int __chk_error(const char *filename, int line, int ret) +{ + if (ret < 0) { + error1(filename, line, "%m (ret=%d, errno=%d)", + ret, errno); + } + return ret; +} + +#define error(fmt, ...) error1(__FILE__, __LINE__, fmt, ## __VA_ARGS__) + +#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) + +/*******************************************************/ + +#define FILE_BUF_SIZE 300 + +void test_file(void) +{ + int fd, i, len, ret; + uint8_t buf[FILE_BUF_SIZE]; + uint8_t buf2[FILE_BUF_SIZE]; + uint8_t buf3[FILE_BUF_SIZE]; + char cur_dir[1024]; + struct stat st; + struct utimbuf tbuf; + struct iovec vecs[2]; + DIR *dir; + struct dirent *de; + + /* clean up, just in case */ + unlink(TESTPATH "/file1"); + unlink(TESTPATH "/file2"); + unlink(TESTPATH "/file3"); + rmdir(TESTPATH); + + if (getcwd(cur_dir, sizeof(cur_dir)) == NULL) + error("getcwd"); + + chk_error(mkdir(TESTPATH, 0755)); + + chk_error(chdir(TESTPATH)); + + /* open/read/write/close/readv/writev/lseek */ + + fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644)); + for(i=0;i < FILE_BUF_SIZE; i++) + buf[i] = i; + len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2)); + if (len != (FILE_BUF_SIZE / 2)) + error("write"); + vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2); + vecs[0].iov_len = 16; + vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16; + vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16; + len = chk_error(writev(fd, vecs, 2)); + if (len != (FILE_BUF_SIZE / 2)) + error("writev"); + chk_error(close(fd)); + + chk_error(rename("file1", "file2")); + + fd = chk_error(open("file2", O_RDONLY)); + + len = chk_error(read(fd, buf2, FILE_BUF_SIZE)); + if (len != FILE_BUF_SIZE) + error("read"); + if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0) + error("memcmp"); + +#define FOFFSET 16 + ret = chk_error(lseek(fd, FOFFSET, SEEK_SET)); + if (ret != 16) + error("lseek"); + vecs[0].iov_base = buf3; + vecs[0].iov_len = 32; + vecs[1].iov_base = buf3 + 32; + vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32; + len = chk_error(readv(fd, vecs, 2)); + if (len != FILE_BUF_SIZE - FOFFSET) + error("readv"); + if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0) + error("memcmp"); + + chk_error(close(fd)); + + /* access */ + chk_error(access("file2", R_OK)); + + /* stat/chmod/utime/truncate */ + + chk_error(chmod("file2", 0600)); + tbuf.actime = 1001; + tbuf.modtime = 1000; + chk_error(truncate("file2", 100)); + chk_error(utime("file2", &tbuf)); + chk_error(stat("file2", &st)); + if (st.st_size != 100) + error("stat size"); + if (!S_ISREG(st.st_mode)) + error("stat mode"); + if ((st.st_mode & 0777) != 0600) + error("stat mode2"); + if (st.st_atime != 1001 || + st.st_mtime != 1000) + error("stat time"); + + chk_error(stat(TESTPATH, &st)); + if (!S_ISDIR(st.st_mode)) + error("stat mode"); + + /* fstat */ + fd = chk_error(open("file2", O_RDWR)); + chk_error(ftruncate(fd, 50)); + chk_error(fstat(fd, &st)); + chk_error(close(fd)); + + if (st.st_size != 50) + error("stat size"); + if (!S_ISREG(st.st_mode)) + error("stat mode"); + + /* symlink/lstat */ + chk_error(symlink("file2", "file3")); + chk_error(lstat("file3", &st)); + if (!S_ISLNK(st.st_mode)) + error("stat mode"); + + /* getdents */ + dir = opendir(TESTPATH); + if (!dir) + error("opendir"); + len = 0; + for(;;) { + de = readdir(dir); + if (!de) + break; + if (strcmp(de->d_name, ".") != 0 && + strcmp(de->d_name, "..") != 0 && + strcmp(de->d_name, "file2") != 0 && + strcmp(de->d_name, "file3") != 0) + error("readdir"); + len++; + } + closedir(dir); + if (len != 4) + error("readdir"); + + chk_error(unlink("file3")); + chk_error(unlink("file2")); + chk_error(chdir(cur_dir)); + chk_error(rmdir(TESTPATH)); +} + +void test_fork(void) +{ + int pid, status; + + pid = chk_error(fork()); + if (pid == 0) { + /* child */ + exit(2); + } + chk_error(waitpid(pid, &status, 0)); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 2) + error("waitpid status=0x%x", status); +} + +void test_time(void) +{ + struct timeval tv, tv2; + struct timespec ts, rem; + struct rusage rusg1, rusg2; + int ti, i; + + chk_error(gettimeofday(&tv, NULL)); + rem.tv_sec = 1; + ts.tv_sec = 0; + ts.tv_nsec = 20 * 1000000; + chk_error(nanosleep(&ts, &rem)); + if (rem.tv_sec != 1) + error("nanosleep"); + chk_error(gettimeofday(&tv2, NULL)); + ti = tv2.tv_sec - tv.tv_sec; + if (ti >= 2) + error("gettimeofday"); + + chk_error(getrusage(RUSAGE_SELF, &rusg1)); + for(i = 0;i < 10000; i++); + chk_error(getrusage(RUSAGE_SELF, &rusg2)); + if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 || + (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0) + error("getrusage"); +} + +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +char *pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +int server_socket(void) +{ + int val, fd; + struct sockaddr_in sockaddr; + + /* server socket */ + fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); + + val = 1; + chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(TESTPORT); + sockaddr.sin_addr.s_addr = 0; + chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); + chk_error(listen(fd, 0)); + return fd; + +} + +int client_socket(void) +{ + int fd; + struct sockaddr_in sockaddr; + + /* server socket */ + fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(TESTPORT); + inet_aton("127.0.0.1", &sockaddr.sin_addr); + chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); + return fd; +} + +const char socket_msg[] = "hello socket\n"; + +void test_socket(void) +{ + int server_fd, client_fd, fd, pid, ret, val; + struct sockaddr_in sockaddr; + socklen_t len; + char buf[512]; + + server_fd = server_socket(); + + /* test a few socket options */ + len = sizeof(val); + chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len)); + if (val != SOCK_STREAM) + error("getsockopt"); + + pid = chk_error(fork()); + if (pid == 0) { + client_fd = client_socket(); + send(client_fd, socket_msg, sizeof(socket_msg), 0); + close(client_fd); + exit(0); + } + len = sizeof(sockaddr); + fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len)); + + ret = chk_error(recv(fd, buf, sizeof(buf), 0)); + if (ret != sizeof(socket_msg)) + error("recv"); + if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0) + error("socket_msg"); + chk_error(close(fd)); + chk_error(close(server_fd)); +} + +#define WCOUNT_MAX 512 + +void test_pipe(void) +{ + fd_set rfds, wfds; + int fds[2], fd_max, ret; + uint8_t ch; + int wcount, rcount; + + chk_error(pipe(fds)); + chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK)); + chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK)); + wcount = 0; + rcount = 0; + for(;;) { + FD_ZERO(&rfds); + fd_max = fds[0]; + FD_SET(fds[0], &rfds); + + FD_ZERO(&wfds); + FD_SET(fds[1], &wfds); + if (fds[1] > fd_max) + fd_max = fds[1]; + + ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL)); + if (ret > 0) { + if (FD_ISSET(fds[0], &rfds)) { + chk_error(read(fds[0], &ch, 1)); + rcount++; + if (rcount >= WCOUNT_MAX) + break; + } + if (FD_ISSET(fds[1], &wfds)) { + ch = 'a'; + chk_error(write(fds[0], &ch, 1)); + wcount++; + } + } + } + chk_error(close(fds[0])); + chk_error(close(fds[1])); +} + +int thread1_res; +int thread2_res; + +int thread1_func(void *arg) +{ + int i; + for(i=0;i<5;i++) { + thread1_res++; + usleep(10 * 1000); + } + return 0; +} + +int thread2_func(void *arg) +{ + int i; + for(i=0;i<6;i++) { + thread2_res++; + usleep(10 * 1000); + } + return 0; +} + +void test_clone(void) +{ + uint8_t *stack1, *stack2; + int pid1, pid2, status1, status2; + + stack1 = malloc(STACK_SIZE); + pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1")); + + stack2 = malloc(STACK_SIZE); + pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2")); + + while (waitpid(pid1, &status1, 0) != pid1); + free(stack1); + while (waitpid(pid2, &status2, 0) != pid2); + free(stack2); + if (thread1_res != 5 || + thread2_res != 6) + error("clone"); +} + +/***********************************/ + +volatile int alarm_count; +jmp_buf jmp_env; + +void sig_alarm(int sig) +{ + if (sig != SIGALRM) + error("signal"); + alarm_count++; +} + +void sig_segv(int sig, siginfo_t *info, void *puc) +{ + if (sig != SIGSEGV) + error("signal"); + longjmp(jmp_env, 1); +} + +void test_signal(void) +{ + struct sigaction act; + struct itimerval it, oit; + + /* timer test */ + + alarm_count = 0; + + act.sa_handler = sig_alarm; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + chk_error(sigaction(SIGALRM, &act, NULL)); + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 10 * 1000; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 10 * 1000; + chk_error(setitimer(ITIMER_REAL, &it, NULL)); + chk_error(getitimer(ITIMER_REAL, &oit)); + if (oit.it_value.tv_sec != it.it_value.tv_sec || + oit.it_value.tv_usec != it.it_value.tv_usec) + error("itimer"); + + while (alarm_count < 5) { + usleep(10 * 1000); + } + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; + memset(&oit, 0xff, sizeof(oit)); + chk_error(setitimer(ITIMER_REAL, &it, &oit)); + if (oit.it_value.tv_sec != 0 || + oit.it_value.tv_usec != 10 * 1000) + error("setitimer"); + + /* SIGSEGV test */ + act.sa_sigaction = sig_segv; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + chk_error(sigaction(SIGSEGV, &act, NULL)); + if (setjmp(jmp_env) == 0) { + *(uint8_t *)0 = 0; + } + + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + chk_error(sigaction(SIGSEGV, &act, NULL)); +} + +#define SHM_SIZE 32768 + +void test_shm(void) +{ + void *ptr; + int shmid; + + shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777)); + ptr = shmat(shmid, NULL, 0); + if (!ptr) + error("shmat"); + + memset(ptr, 0, SHM_SIZE); + + chk_error(shmctl(shmid, IPC_RMID, 0)); + chk_error(shmdt(ptr)); +} + +int main(int argc, char **argv) +{ + test_file(); + test_fork(); + test_time(); + test_socket(); + // test_clone(); + test_signal(); + test_shm(); + return 0; +} diff --git a/tests/tcg/multiarch/sha1.c b/tests/tcg/multiarch/sha1.c new file mode 100644 index 0000000..93b7c8e --- /dev/null +++ b/tests/tcg/multiarch/sha1.c @@ -0,0 +1,240 @@ + +/* from valgrind tests */ + +/* ================ sha1.c ================ */ +/* +SHA-1 in C +By Steve Reid <steve@edmweb.com> +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +/* ================ sha1.h ================ */ +/* +SHA-1 in C +By Steve Reid <steve@edmweb.com> +100% Public Domain +*/ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); +/* ================ end of sha1.h ================ */ +#include <endian.h> + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], const unsigned char buffer[64]) +{ +uint32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + uint32_t l[16]; +} CHAR64LONG16; +#ifdef SHA1HANDSOFF +CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ +CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len) +{ +uint32_t i; +uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len>>29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned i; +unsigned char finalcount[8]; +unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t; + } +#else + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} +/* ================ end of sha1.c ================ */ + +#define BUFSIZE 4096 + +int +main(int argc, char **argv) +{ + SHA1_CTX ctx; + unsigned char hash[20], buf[BUFSIZE]; + int i; + + for(i=0;i<BUFSIZE;i++) + buf[i] = i; + + SHA1Init(&ctx); + for(i=0;i<1000;i++) + SHA1Update(&ctx, buf, BUFSIZE); + SHA1Final(hash, &ctx); + + printf("SHA1="); + for(i=0;i<20;i++) + printf("%02x", hash[i]); + printf("\n"); + return 0; +} diff --git a/tests/tcg/multiarch/test-mmap.c b/tests/tcg/multiarch/test-mmap.c new file mode 100644 index 0000000..cdefadf --- /dev/null +++ b/tests/tcg/multiarch/test-mmap.c @@ -0,0 +1,484 @@ +/* + * Small test program to verify simulated mmap behaviour. + * + * When running qemu-linux-user with the -p flag, you may need to tell + * this test program about the pagesize because getpagesize() will not reflect + * the -p choice. Simply pass one argument being the pagesize. + * + * Copyright (c) 2007 AXIS Communications AB + * Written by Edgar E. Iglesias. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#include <sys/mman.h> + +#define D(x) + +#define fail_unless(x) \ +do \ +{ \ + if (!(x)) { \ + fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \ + exit (EXIT_FAILURE); \ + } \ +} while (0) + +unsigned char *dummybuf; +static unsigned int pagesize; +static unsigned int pagemask; +int test_fd; +size_t test_fsize; + +void check_aligned_anonymous_unfixed_mmaps(void) +{ + void *p1; + void *p2; + void *p3; + void *p4; + void *p5; + uintptr_t p; + int i; + + fprintf (stderr, "%s", __func__); + for (i = 0; i < 0x1fff; i++) + { + size_t len; + + len = pagesize + (pagesize * i & 7); + p1 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p2 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p3 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p4 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + p5 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + fail_unless (p1 != MAP_FAILED); + fail_unless (p2 != MAP_FAILED); + fail_unless (p3 != MAP_FAILED); + fail_unless (p4 != MAP_FAILED); + fail_unless (p5 != MAP_FAILED); + p = (uintptr_t) p1; + D(printf ("p=%x\n", p)); + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p2; + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p3; + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p4; + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p5; + fail_unless ((p & pagemask) == 0); + + /* Make sure we can read from the entire area. */ + memcpy (dummybuf, p1, pagesize); + memcpy (dummybuf, p2, pagesize); + memcpy (dummybuf, p3, pagesize); + memcpy (dummybuf, p4, pagesize); + memcpy (dummybuf, p5, pagesize); + + munmap (p1, len); + munmap (p2, len); + munmap (p3, len); + munmap (p4, len); + munmap (p5, len); + } + fprintf (stderr, " passed\n"); +} + +void check_large_anonymous_unfixed_mmap(void) +{ + void *p1; + uintptr_t p; + size_t len; + + fprintf (stderr, "%s", __func__); + + len = 0x02000000; + p1 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + fail_unless (p1 != MAP_FAILED); + p = (uintptr_t) p1; + fail_unless ((p & pagemask) == 0); + + /* Make sure we can read from the entire area. */ + memcpy (dummybuf, p1, pagesize); + munmap (p1, len); + fprintf (stderr, " passed\n"); +} + +void check_aligned_anonymous_unfixed_colliding_mmaps(void) +{ + char *p1; + char *p2; + char *p3; + uintptr_t p; + int i; + + fprintf (stderr, "%s", __func__); + for (i = 0; i < 0x2fff; i++) + { + int nlen; + p1 = mmap(NULL, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless (p1 != MAP_FAILED); + p = (uintptr_t) p1; + fail_unless ((p & pagemask) == 0); + memcpy (dummybuf, p1, pagesize); + + p2 = mmap(NULL, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless (p2 != MAP_FAILED); + p = (uintptr_t) p2; + fail_unless ((p & pagemask) == 0); + memcpy (dummybuf, p2, pagesize); + + + munmap (p1, pagesize); + nlen = pagesize * 8; + p3 = mmap(NULL, nlen, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fail_unless (p3 != MAP_FAILED); + + /* Check if the mmaped areas collide. */ + if (p3 < p2 + && (p3 + nlen) > p2) + fail_unless (0); + + memcpy (dummybuf, p3, pagesize); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + p = (uintptr_t) p3; + fail_unless ((p & pagemask) == 0); + munmap (p2, pagesize); + munmap (p3, nlen); + } + fprintf (stderr, " passed\n"); +} + +void check_aligned_anonymous_fixed_mmaps(void) +{ + char *addr; + void *p1; + uintptr_t p; + int i; + + /* Find a suitable address to start with. */ + addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + fprintf (stderr, "%s addr=%p", __func__, addr); + fail_unless (addr != MAP_FAILED); + + for (i = 0; i < 40; i++) + { + /* Create submaps within our unfixed map. */ + p1 = mmap(addr, pagesize, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + p = (uintptr_t) p1; + fail_unless (p1 == addr); + fail_unless ((p & pagemask) == 0); + memcpy (dummybuf, p1, pagesize); + munmap (p1, pagesize); + addr += pagesize; + } + fprintf (stderr, " passed\n"); +} + +void check_aligned_anonymous_fixed_mmaps_collide_with_host(void) +{ + char *addr; + void *p1; + uintptr_t p; + int i; + + /* Find a suitable address to start with. Right were the x86 hosts + stack is. */ + addr = ((void *)0x80000000); + fprintf (stderr, "%s addr=%p", __func__, addr); + fprintf (stderr, "FIXME: QEMU fails to track pages used by the host."); + + for (i = 0; i < 20; i++) + { + /* Create submaps within our unfixed map. */ + p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + p = (uintptr_t) p1; + fail_unless (p1 == addr); + fail_unless ((p & pagemask) == 0); + memcpy (p1, dummybuf, pagesize); + munmap (p1, pagesize); + addr += pagesize; + } + fprintf (stderr, " passed\n"); +} + +void check_file_unfixed_mmaps(void) +{ + unsigned int *p1, *p2, *p3; + uintptr_t p; + int i; + + fprintf (stderr, "%s", __func__); + for (i = 0; i < 0x10; i++) + { + size_t len; + + len = pagesize; + p1 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE, + test_fd, 0); + p2 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE, + test_fd, pagesize); + p3 = mmap(NULL, len, PROT_READ, + MAP_PRIVATE, + test_fd, pagesize * 2); + + fail_unless (p1 != MAP_FAILED); + fail_unless (p2 != MAP_FAILED); + fail_unless (p3 != MAP_FAILED); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + p = (uintptr_t) p1; + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p2; + fail_unless ((p & pagemask) == 0); + p = (uintptr_t) p3; + fail_unless ((p & pagemask) == 0); + + /* Verify that the file maps was made correctly. */ + D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3)); + fail_unless (*p1 == 0); + fail_unless (*p2 == (pagesize / sizeof *p2)); + fail_unless (*p3 == ((pagesize * 2) / sizeof *p3)); + + memcpy (dummybuf, p1, pagesize); + memcpy (dummybuf, p2, pagesize); + memcpy (dummybuf, p3, pagesize); + munmap (p1, len); + munmap (p2, len); + munmap (p3, len); + } + fprintf (stderr, " passed\n"); +} + +void check_file_unfixed_eof_mmaps(void) +{ + char *cp; + unsigned int *p1; + uintptr_t p; + int i; + + fprintf (stderr, "%s", __func__); + for (i = 0; i < 0x10; i++) + { + p1 = mmap(NULL, pagesize, PROT_READ, + MAP_PRIVATE, + test_fd, + (test_fsize - sizeof *p1) & ~pagemask); + + fail_unless (p1 != MAP_FAILED); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + p = (uintptr_t) p1; + fail_unless ((p & pagemask) == 0); + /* Verify that the file maps was made correctly. */ + fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1] + == ((test_fsize - sizeof *p1) / sizeof *p1)); + + /* Verify that the end of page is accessible and zeroed. */ + cp = (void *) p1; + fail_unless (cp[pagesize - 4] == 0); + munmap (p1, pagesize); + } + fprintf (stderr, " passed\n"); +} + +void check_file_fixed_eof_mmaps(void) +{ + char *addr; + char *cp; + unsigned int *p1; + uintptr_t p; + int i; + + /* Find a suitable address to start with. */ + addr = mmap(NULL, pagesize * 44, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + + fprintf (stderr, "%s addr=%p", __func__, (void *)addr); + fail_unless (addr != MAP_FAILED); + + for (i = 0; i < 0x10; i++) + { + /* Create submaps within our unfixed map. */ + p1 = mmap(addr, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, + (test_fsize - sizeof *p1) & ~pagemask); + + fail_unless (p1 != MAP_FAILED); + + /* Make sure we get pages aligned with the pagesize. The + target expects this. */ + p = (uintptr_t) p1; + fail_unless ((p & pagemask) == 0); + + /* Verify that the file maps was made correctly. */ + fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1] + == ((test_fsize - sizeof *p1) / sizeof *p1)); + + /* Verify that the end of page is accessible and zeroed. */ + cp = (void *)p1; + fail_unless (cp[pagesize - 4] == 0); + munmap (p1, pagesize); + addr += pagesize; + } + fprintf (stderr, " passed\n"); +} + +void check_file_fixed_mmaps(void) +{ + unsigned char *addr; + unsigned int *p1, *p2, *p3, *p4; + int i; + + /* Find a suitable address to start with. */ + addr = mmap(NULL, pagesize * 40 * 4, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + fprintf (stderr, "%s addr=%p", __func__, (void *)addr); + fail_unless (addr != MAP_FAILED); + + for (i = 0; i < 40; i++) + { + p1 = mmap(addr, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, 0); + p2 = mmap(addr + pagesize, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, pagesize); + p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, pagesize * 2); + p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ, + MAP_PRIVATE | MAP_FIXED, + test_fd, pagesize * 3); + + /* Make sure we get pages aligned with the pagesize. + The target expects this. */ + fail_unless (p1 == (void *)addr); + fail_unless (p2 == (void *)addr + pagesize); + fail_unless (p3 == (void *)addr + pagesize * 2); + fail_unless (p4 == (void *)addr + pagesize * 3); + + /* Verify that the file maps was made correctly. */ + fail_unless (*p1 == 0); + fail_unless (*p2 == (pagesize / sizeof *p2)); + fail_unless (*p3 == ((pagesize * 2) / sizeof *p3)); + fail_unless (*p4 == ((pagesize * 3) / sizeof *p4)); + + memcpy (dummybuf, p1, pagesize); + memcpy (dummybuf, p2, pagesize); + memcpy (dummybuf, p3, pagesize); + memcpy (dummybuf, p4, pagesize); + + munmap (p1, pagesize); + munmap (p2, pagesize); + munmap (p3, pagesize); + munmap (p4, pagesize); + addr += pagesize * 4; + } + fprintf (stderr, " passed\n"); +} + +void checked_write(int fd, const void *buf, size_t count) +{ + ssize_t rc = write(fd, buf, count); + fail_unless(rc == count); +} + +int main(int argc, char **argv) +{ + char tempname[] = "/tmp/.cmmapXXXXXX"; + unsigned int i; + + /* Trust the first argument, otherwise probe the system for our + pagesize. */ + if (argc > 1) + pagesize = strtoul(argv[1], NULL, 0); + else + pagesize = sysconf(_SC_PAGESIZE); + + /* Assume pagesize is a power of two. */ + pagemask = pagesize - 1; + dummybuf = malloc (pagesize); + printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask); + + test_fd = mkstemp(tempname); + unlink(tempname); + + /* Fill the file with int's counting from zero and up. */ + for (i = 0; i < (pagesize * 4) / sizeof i; i++) { + checked_write(test_fd, &i, sizeof i); + } + + /* Append a few extra writes to make the file end at non + page boundary. */ + checked_write(test_fd, &i, sizeof i); i++; + checked_write(test_fd, &i, sizeof i); i++; + checked_write(test_fd, &i, sizeof i); i++; + + test_fsize = lseek(test_fd, 0, SEEK_CUR); + + /* Run the tests. */ + check_aligned_anonymous_unfixed_mmaps(); + check_aligned_anonymous_unfixed_colliding_mmaps(); + check_aligned_anonymous_fixed_mmaps(); + check_file_unfixed_mmaps(); + check_file_fixed_mmaps(); + check_file_fixed_eof_mmaps(); + check_file_unfixed_eof_mmaps(); + + /* Fails at the moment. */ + /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */ + + return EXIT_SUCCESS; +} diff --git a/tests/tcg/multiarch/testthread.c b/tests/tcg/multiarch/testthread.c new file mode 100644 index 0000000..810ba5d --- /dev/null +++ b/tests/tcg/multiarch/testthread.c @@ -0,0 +1,57 @@ +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <inttypes.h> +#include <pthread.h> +#include <sys/wait.h> +#include <sched.h> + +void checked_write(int fd, const void *buf, size_t count) +{ + ssize_t rc = write(fd, buf, count); + assert(rc == count); +} + +void *thread1_func(void *arg) +{ + int i; + char buf[512]; + + for(i=0;i<10;i++) { + snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg); + checked_write(1, buf, strlen(buf)); + usleep(100 * 1000); + } + return NULL; +} + +void *thread2_func(void *arg) +{ + int i; + char buf[512]; + for(i=0;i<20;i++) { + snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg); + checked_write(1, buf, strlen(buf)); + usleep(150 * 1000); + } + return NULL; +} + +void test_pthread(void) +{ + pthread_t tid1, tid2; + + pthread_create(&tid1, NULL, thread1_func, "hello1"); + pthread_create(&tid2, NULL, thread2_func, "hello2"); + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("End of pthread test.\n"); +} + +int main(int argc, char **argv) +{ + test_pthread(); + return 0; +} |