0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <stdio.h>
0010 #include <stdlib.h>
0011 #include <string.h>
0012 #include <unistd.h>
0013 #include <stdint.h>
0014 #include <sys/types.h>
0015 #include <sys/stat.h>
0016 #include <sys/time.h>
0017 #include <sys/fcntl.h>
0018 #include <sys/mman.h>
0019 #include <endian.h>
0020 #include <bits/endian.h>
0021 #include <sys/ioctl.h>
0022 #include <assert.h>
0023 #include <errno.h>
0024 #include <signal.h>
0025 #include "vas-api.h"
0026 #include "nx.h"
0027 #include "copy-paste.h"
0028 #include "nxu.h"
0029 #include "nx_dbg.h"
0030 #include <sys/platform/ppc.h>
0031
0032 #define barrier()
0033 #define hwsync() ({ asm volatile("sync" ::: "memory"); })
0034
0035 #ifndef NX_NO_CPU_PRI
0036 #define cpu_pri_default() ({ asm volatile ("or 2, 2, 2"); })
0037 #define cpu_pri_low() ({ asm volatile ("or 31, 31, 31"); })
0038 #else
0039 #define cpu_pri_default()
0040 #define cpu_pri_low()
0041 #endif
0042
0043 void *nx_fault_storage_address;
0044
0045 struct nx_handle {
0046 int fd;
0047 int function;
0048 void *paste_addr;
0049 };
0050
0051 static int open_device_nodes(char *devname, int pri, struct nx_handle *handle)
0052 {
0053 int rc, fd;
0054 void *addr;
0055 struct vas_tx_win_open_attr txattr;
0056
0057 fd = open(devname, O_RDWR);
0058 if (fd < 0) {
0059 fprintf(stderr, " open device name %s\n", devname);
0060 return -errno;
0061 }
0062
0063 memset(&txattr, 0, sizeof(txattr));
0064 txattr.version = 1;
0065 txattr.vas_id = pri;
0066 rc = ioctl(fd, VAS_TX_WIN_OPEN, (unsigned long)&txattr);
0067 if (rc < 0) {
0068 fprintf(stderr, "ioctl() n %d, error %d\n", rc, errno);
0069 rc = -errno;
0070 goto out;
0071 }
0072
0073 addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0ULL);
0074 if (addr == MAP_FAILED) {
0075 fprintf(stderr, "mmap() failed, errno %d\n", errno);
0076 rc = -errno;
0077 goto out;
0078 }
0079 handle->fd = fd;
0080 handle->paste_addr = (void *)((char *)addr + 0x400);
0081
0082 rc = 0;
0083 out:
0084 close(fd);
0085 return rc;
0086 }
0087
0088 void *nx_function_begin(int function, int pri)
0089 {
0090 int rc;
0091 char *devname = "/dev/crypto/nx-gzip";
0092 struct nx_handle *nxhandle;
0093
0094 if (function != NX_FUNC_COMP_GZIP) {
0095 errno = EINVAL;
0096 fprintf(stderr, " NX_FUNC_COMP_GZIP not found\n");
0097 return NULL;
0098 }
0099
0100
0101 nxhandle = malloc(sizeof(*nxhandle));
0102 if (!nxhandle) {
0103 errno = ENOMEM;
0104 fprintf(stderr, " No memory\n");
0105 return NULL;
0106 }
0107
0108 nxhandle->function = function;
0109 rc = open_device_nodes(devname, pri, nxhandle);
0110 if (rc < 0) {
0111 errno = -rc;
0112 fprintf(stderr, " open_device_nodes failed\n");
0113 return NULL;
0114 }
0115
0116 return nxhandle;
0117 }
0118
0119 int nx_function_end(void *handle)
0120 {
0121 int rc = 0;
0122 struct nx_handle *nxhandle = handle;
0123
0124 rc = munmap(nxhandle->paste_addr - 0x400, 4096);
0125 if (rc < 0) {
0126 fprintf(stderr, "munmap() failed, errno %d\n", errno);
0127 return rc;
0128 }
0129 close(nxhandle->fd);
0130 free(nxhandle);
0131
0132 return rc;
0133 }
0134
0135 static int nx_wait_for_csb(struct nx_gzip_crb_cpb_t *cmdp)
0136 {
0137 long poll = 0;
0138 uint64_t t;
0139
0140
0141
0142
0143
0144
0145 cpu_pri_low();
0146
0147 #define CSB_MAX_POLL 200000000UL
0148 #define USLEEP_TH 300000UL
0149
0150 t = __ppc_get_timebase();
0151
0152 while (getnn(cmdp->crb.csb, csb_v) == 0) {
0153 ++poll;
0154 hwsync();
0155
0156 cpu_pri_low();
0157
0158
0159
0160
0161
0162 if ((__ppc_get_timebase() - t) > USLEEP_TH) {
0163 cpu_pri_default();
0164 usleep(1);
0165 }
0166
0167 if (poll > CSB_MAX_POLL)
0168 break;
0169
0170
0171 if (nx_fault_storage_address) {
0172 cpu_pri_default();
0173 return -EAGAIN;
0174 }
0175
0176 }
0177
0178 cpu_pri_default();
0179
0180
0181 hwsync();
0182
0183
0184 if (getnn(cmdp->crb.csb, csb_v) == 0) {
0185 fprintf(stderr, "CSB still not valid after %d polls.\n",
0186 (int) poll);
0187 prt_err("CSB still not valid after %d polls, giving up.\n",
0188 (int) poll);
0189 return -ETIMEDOUT;
0190 }
0191
0192 return 0;
0193 }
0194
0195 static int nxu_run_job(struct nx_gzip_crb_cpb_t *cmdp, void *handle)
0196 {
0197 int i, ret, retries;
0198 struct nx_handle *nxhandle = handle;
0199
0200 assert(handle != NULL);
0201 i = 0;
0202 retries = 5000;
0203 while (i++ < retries) {
0204 hwsync();
0205 vas_copy(&cmdp->crb, 0);
0206 ret = vas_paste(nxhandle->paste_addr, 0);
0207 hwsync();
0208
0209 NXPRT(fprintf(stderr, "Paste attempt %d/%d returns 0x%x\n",
0210 i, retries, ret));
0211
0212 if ((ret == 2) || (ret == 3)) {
0213
0214 ret = nx_wait_for_csb(cmdp);
0215 if (!ret) {
0216 goto out;
0217 } else if (ret == -EAGAIN) {
0218 long x;
0219
0220 prt_err("Touching address %p, 0x%lx\n",
0221 nx_fault_storage_address,
0222 *(long *) nx_fault_storage_address);
0223 x = *(long *) nx_fault_storage_address;
0224 *(long *) nx_fault_storage_address = x;
0225 nx_fault_storage_address = 0;
0226 continue;
0227 } else {
0228 prt_err("wait_for_csb() returns %d\n", ret);
0229 break;
0230 }
0231 } else {
0232 if (i < 10) {
0233
0234 #define SPIN_TH 500UL
0235 uint64_t fail_spin;
0236
0237 fail_spin = __ppc_get_timebase();
0238 while ((__ppc_get_timebase() - fail_spin) <
0239 SPIN_TH)
0240 ;
0241 } else {
0242
0243 unsigned int pr = 0;
0244
0245 if (pr++ % 100 == 0) {
0246 prt_err("Paste attempt %d/", i);
0247 prt_err("%d, failed pid= %d\n", retries,
0248 getpid());
0249 }
0250 usleep(1);
0251 }
0252 continue;
0253 }
0254 }
0255
0256 out:
0257 cpu_pri_default();
0258
0259 return ret;
0260 }
0261
0262 int nxu_submit_job(struct nx_gzip_crb_cpb_t *cmdp, void *handle)
0263 {
0264 int cc;
0265
0266 cc = nxu_run_job(cmdp, handle);
0267
0268 if (!cc)
0269 cc = getnn(cmdp->crb.csb, csb_cc);
0270
0271 return cc;
0272 }
0273
0274
0275 void nxu_sigsegv_handler(int sig, siginfo_t *info, void *ctx)
0276 {
0277 fprintf(stderr, "%d: Got signal %d si_code %d, si_addr %p\n", getpid(),
0278 sig, info->si_code, info->si_addr);
0279
0280 nx_fault_storage_address = info->si_addr;
0281 }
0282
0283
0284
0285
0286
0287
0288
0289 int nxu_touch_pages(void *buf, long buf_len, long page_len, int wr)
0290 {
0291 char *begin = buf;
0292 char *end = (char *) buf + buf_len - 1;
0293 volatile char t;
0294
0295 assert(buf_len >= 0 && !!buf);
0296
0297 NXPRT(fprintf(stderr, "touch %p %p len 0x%lx wr=%d\n", buf,
0298 (buf + buf_len), buf_len, wr));
0299
0300 if (buf_len <= 0 || buf == NULL)
0301 return -1;
0302
0303 do {
0304 t = *begin;
0305 if (wr)
0306 *begin = t;
0307 begin = begin + page_len;
0308 } while (begin < end);
0309
0310
0311 t = *end;
0312 if (wr)
0313 *end = t;
0314
0315 return 0;
0316 }