From 4b9bf071e53a284a15512b6621ce336ae2fc6ae6 Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Thu, 9 Nov 2017 17:53:28 +0000 Subject: [PATCH] Update hyperkit vendoring This includes using ftruncate for speedier disk creation Signed-off-by: Rolf Neugebauer --- src/cmd/linuxkit/vendor.conf | 2 +- .../github.com/moby/hyperkit/go/hyperkit.go | 6 +- .../src/include/xhyve/firmware/bootrom.h | 1 + .../moby/hyperkit/src/include/xhyve/fwctl.h | 54 ++ .../moby/hyperkit/src/lib/block_if.c | 100 +++- .../github.com/moby/hyperkit/src/lib/fwctl.c | 560 ++++++++++++++++++ .../moby/hyperkit/src/lib/pci_ahci.c | 13 +- 7 files changed, 715 insertions(+), 21 deletions(-) create mode 100644 src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/fwctl.h create mode 100644 src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/fwctl.c diff --git a/src/cmd/linuxkit/vendor.conf b/src/cmd/linuxkit/vendor.conf index 50791623b..6e3480bfc 100644 --- a/src/cmd/linuxkit/vendor.conf +++ b/src/cmd/linuxkit/vendor.conf @@ -15,7 +15,7 @@ github.com/gophercloud/gophercloud 2804b72cf099b41d2e25c8afcca786f9f962ddee github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d github.com/mitchellh/go-ps 4fdf99ab29366514c69ccccddab5dc58b8d84062 github.com/moby/datakit 97b3d230535397a813323902c23751e176481a86 -github.com/moby/hyperkit 3e31617ae866c93925e2b3bc5d8006b60985e920 +github.com/moby/hyperkit a12cd7250bcd8d689078e3e42ae4a7cf6a0cbaf3 github.com/moby/vpnkit 0e4293bb1058598c4b0a406ed171f52573ef414c github.com/packethost/packngo 131798f2804a1b3e895ca98047d56f0d7e094e2a github.com/pmezard/go-difflib v1.0.0 diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go index db0a9b5aa..9cb38b1a2 100644 --- a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/go/hyperkit.go @@ -395,11 +395,7 @@ func CreateDiskImage(location string, sizeMB int) error { } defer f.Close() - buf := make([]byte, 1048676) - for i := 0; i < sizeMB; i++ { - f.Write(buf) - } - return nil + return f.Truncate(int64(sizeMB) * int64(1024) * int64(1024)) } func intArrayToString(i []int, sep string) string { diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/firmware/bootrom.h b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/firmware/bootrom.h index 7c4c82261..170c78d06 100644 --- a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/firmware/bootrom.h +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/firmware/bootrom.h @@ -4,5 +4,6 @@ #include int bootrom_init(const char *bootrom_path); +const char *bootrom(void); uint64_t bootrom_load(void); bool bootrom_contains_gpa(uint64_t gpa); diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/fwctl.h b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/fwctl.h new file mode 100644 index 000000000..b45a4dbe4 --- /dev/null +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/include/xhyve/fwctl.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2015 Peter Grehan + * 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. + * + * 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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _FWCTL_H_ +#define _FWCTL_H_ + +#include + +/* + * Linker set api for export of information to guest firmware via + * a sysctl-like OID interface + */ +struct ctl { + const char *c_oid; + const void *c_data; + const int c_len; +}; + +#define CTL_NODE(oid, data, len) \ + static struct ctl __CONCAT(__ctl, __LINE__) = { \ + oid, \ + (data), \ + (len), \ + }; \ + DATA_SET(ctl_set, __CONCAT(__ctl, __LINE__)) + +void fwctl_init(void); + +#endif /* _FWCTL_H_ */ diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c index 07a3e6efc..cce6ef185 100644 --- a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/block_if.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,14 @@ #define BLOCKIF_SIG 0xb109b109 +#ifndef ALIGNUP +#define ALIGNUP(x, a) (((x - 1) & ~(a - 1)) + a) +#endif + +#ifndef ALIGNDOWN +#define ALIGNDOWN(x, a) (-(a) & (x)) +#endif + /* xhyve: FIXME * * // #define BLOCKIF_NUMTHR 8 @@ -101,6 +110,8 @@ struct blockif_ctxt { off_t bc_size; int bc_sectsz; int bc_psectsz; + size_t bc_delete_alignment; /* f_bsize always a power of 2 */ + void* bc_delete_zero_buf; int bc_psectoff; int bc_closing; pthread_t bc_btid[BLOCKIF_NUMTHR]; @@ -211,6 +222,7 @@ static int block_delete(struct blockif_ctxt *bc, off_t offset, off_t len) { int ret = -1; + #ifdef __FreeBSD__ off_t arg[2] = { offset, len }; #endif @@ -221,22 +233,52 @@ block_delete(struct blockif_ctxt *bc, off_t offset, off_t len) errno = EOPNOTSUPP; else if (bc->bc_rdonly) errno = EROFS; - if (bc->bc_fd >= 0) { - if (bc->bc_ischr) { -#ifdef __FreeBSD__ - ret = ioctl(bc->bc_fd, DIOCGDELETE, arg); -#else - errno = EOPNOTSUPP; -#endif - } else - errno = EOPNOTSUPP; #ifdef HAVE_OCAML_QCOW - } else if (bc->bc_mbh >= 0) { + if (bc->bc_mbh >= 0) { ret = mirage_block_delete(bc->bc_mbh, offset, len); + goto out; + } #endif - } else - abort(); +#ifdef __FreeBSD__ + if ((bc->bc_fd >= 0) && (bc->bc_ischr)) { + ret = ioctl(bc->bc_fd, DIOCGDELETE, arg); + errno = EOPNOTSUPP; + goto out; + } +#elif __APPLE__ + if (bc->bc_fd >= 0) { + /* PUNCHHOLE lengths and offsets have to be aligned so explicitly write zeroes + into the unaligned parts at the beginning and the end. This wouldn't be necessary + if the host and guest had the same sector size */ + assert (offset >= 0); + assert (len >= 0); + size_t fp_offset = (size_t) offset; + size_t fp_length = (size_t) len; + size_t aligned_offset = ALIGNUP(fp_offset, bc->bc_delete_alignment); + if (aligned_offset != fp_offset) { + size_t len_to_zero = aligned_offset - fp_offset; + assert(len_to_zero <= bc->bc_delete_alignment); + ssize_t written = pwrite(bc->bc_fd, bc->bc_delete_zero_buf, len_to_zero, (off_t) fp_offset); + if (written == -1) goto out; + fp_offset += len_to_zero; + fp_length -= len_to_zero; + } + size_t aligned_length = ALIGNDOWN(fp_length, bc->bc_delete_alignment); + if (aligned_length != fp_length) { + size_t len_to_zero = fp_length - aligned_length; + assert(len_to_zero <= bc->bc_delete_alignment); + fp_length -= len_to_zero; + ssize_t written = pwrite(bc->bc_fd, bc->bc_delete_zero_buf, len_to_zero, (off_t) (fp_offset + fp_length)); + if (written == -1) goto out; + } + struct fpunchhole arg = { .fp_flags = 0, .reserved = 0, .fp_offset = (off_t) fp_offset, .fp_length = (off_t) fp_length }; + ret = fcntl(bc->bc_fd, F_PUNCHHOLE, &arg); + goto out; + } +#endif + errno = EOPNOTSUPP; +out: HYPERKIT_BLOCK_DELETE_DONE(offset, ret); return ret; } @@ -554,9 +596,12 @@ blockif_open(const char *optstr, const char *ident) char *nopt, *xopts, *cp; struct blockif_ctxt *bc; struct stat sbuf; + struct statfs fsbuf; // struct diocgattr_arg arg; off_t size, psectsz, psectoff, blocks; int extra, fd, i, sectsz; + size_t delete_alignment; + void *delete_zero_buf; int nocache, sync, ro, candelete, geom, ssopt, pssopt; mirage_block_handle mbh; int use_mirage = 0; @@ -621,6 +666,8 @@ blockif_open(const char *optstr, const char *ident) extra |= O_SYNC; candelete = 0; + sectsz = DEV_BSIZE; + delete_alignment = DEV_BSIZE; if (use_mirage) { #ifdef HAVE_OCAML_QCOW @@ -655,7 +702,33 @@ blockif_open(const char *optstr, const char *ident) perror("Could not stat backing file"); goto err; } + if (fstatfs(fd, &fsbuf) < 0) { + perror("Could not stat backfile file filesystem"); + goto err; + } + delete_alignment = (size_t)fsbuf.f_bsize; +#ifdef __APPLE__ + { + /* Check to see whether we can use F_PUNCHHOLE on this file */ + struct fpunchhole arg = { .fp_flags = 0, .reserved = 0, .fp_offset = 0, .fp_length = 0 }; + if (fcntl(fd, F_PUNCHHOLE, &arg) == 0) { + /* Sparse files are supported: enable TRIM */ + candelete = 1; + } else { + perror("fcntl(F_PUNCHHOLE) failed: host filesystem does not support sparse files"); + candelete = 0; + } + } +#endif } + /* delete_alignment is a power of 2 allowing us to use ALIGNDOWN for rounding */ + assert((delete_alignment & (delete_alignment - 1)) == 0); + + if ((delete_zero_buf = malloc(delete_alignment)) == NULL){ + perror("Failed to allocate zeroed buffer for unaligned deletes"); + goto err; + } + bzero(delete_zero_buf, delete_alignment); /* One and only one handle */ assert(mbh >= 0 || fd >= 0); @@ -664,7 +737,6 @@ blockif_open(const char *optstr, const char *ident) * Deal with raw devices */ size = sbuf.st_size; - sectsz = DEV_BSIZE; psectsz = psectoff = 0; geom = 0; if (S_ISCHR(sbuf.st_mode)) { @@ -749,6 +821,8 @@ blockif_open(const char *optstr, const char *ident) bc->bc_sectsz = sectsz; bc->bc_psectsz = (int)psectsz; bc->bc_psectoff = (int)psectoff; + bc->bc_delete_alignment = delete_alignment; + bc->bc_delete_zero_buf = delete_zero_buf; pthread_mutex_init(&bc->bc_mtx, NULL); pthread_cond_init(&bc->bc_cond, NULL); TAILQ_INIT(&bc->bc_freeq); diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/fwctl.c b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/fwctl.c new file mode 100644 index 000000000..0dfd77154 --- /dev/null +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/fwctl.c @@ -0,0 +1,560 @@ +/*- + * Copyright (c) 2015 Peter Grehan + * 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. + * + * 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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +/* + * Guest firmware interface. Uses i/o ports x510/x511 as Qemu does, + * but with a request/response messaging protocol. + */ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "xhyve/inout.h" +#include "xhyve/xhyve.h" +#include "xhyve/support/misc.h" +#include "xhyve/fwctl.h" + +/* + * Messaging protocol base operations + */ +#define OP_NULL 1 +#define OP_ECHO 2 +#define OP_GET 3 +#define OP_GET_LEN 4 +#define OP_SET 5 +#define OP_MAX OP_SET + +/* I/O ports */ +#define FWCTL_OUT 0x510 +#define FWCTL_IN 0x511 + +/* + * Back-end state-machine + */ +static enum state { + DORMANT, + IDENT_WAIT, + IDENT_SEND, + REQ, + RESP +} be_state = DORMANT; + +static uint8_t sig[] = { 'B', 'H', 'Y', 'V' }; +static u_int ident_idx; + +struct op_info { + int op; + int (*op_start)(size_t len); + void (*op_data)(uint32_t data, size_t len); + int (*op_result)(struct iovec **data); + void (*op_done)(struct iovec *data); +}; +static struct op_info *ops[OP_MAX+1]; + +/* Return 0-padded uint32_t */ +static uint32_t +fwctl_send_rest(uint8_t *data, size_t len) +{ + union { + uint8_t c[4]; + uint32_t w; + } u; + size_t i; + + u.w = 0; + + for (i = 0, u.w = 0; i < len; i++) + u.c[i] = *data++; + + return (u.w); +} + +/* + * error op dummy proto - drop all data sent and return an error +*/ +static int errop_code; + +static void +errop_set(int err) +{ + + errop_code = err; +} + +static int +errop_start(UNUSED size_t len) +{ + errop_code = ENOENT; + + /* accept any length */ + return (errop_code); +} + +static void +errop_data(UNUSED uint32_t data, UNUSED size_t len) +{ + + /* ignore */ +} + +static int +errop_result(struct iovec **data) +{ + + /* no data to send back; always successful */ + *data = NULL; + return (errop_code); +} + +static void +errop_done(UNUSED struct iovec *data) +{ + + /* assert data is NULL */ +} + +static struct op_info errop_info = { + .op_start = errop_start, + .op_data = errop_data, + .op_result = errop_result, + .op_done = errop_done +}; + +/* OID search */ +SET_DECLARE(ctl_set, struct ctl); + +CTL_NODE("hw.ncpu", &guest_ncpus, sizeof(guest_ncpus)); + +static struct ctl * +ctl_locate(const char *str, size_t maxlen) +{ + struct ctl *cp, **cpp; + + SET_FOREACH(cpp, ctl_set) { + cp = *cpp; + if (!strncmp(str, cp->c_oid, maxlen)) + return (cp); + } + + return (NULL); +} + +/* uefi-sysctl get-len */ +#define FGET_STRSZ 80 +static struct iovec fget_biov[2]; +static char fget_str[FGET_STRSZ]; +static struct { + size_t f_sz; + uint32_t f_data[1024]; +} fget_buf; +static size_t fget_cnt; +static size_t fget_size; + +static int +fget_start(size_t len) +{ + + if (len > FGET_STRSZ) + return(E2BIG); + + fget_cnt = 0; + + return (0); +} + +static void +fget_data(uint32_t data, UNUSED size_t len) +{ + memcpy(&fget_str[fget_cnt], &data, sizeof(data)); + fget_cnt += sizeof(uint32_t); +} + +static int +fget_result(struct iovec **data, int val) +{ + struct ctl *cp; + int err; + + err = 0; + + /* Locate the OID */ + cp = ctl_locate(fget_str, fget_cnt); + if (cp == NULL) { + *data = NULL; + err = ENOENT; + } else { + if (val) { + /* For now, copy the len/data into a buffer */ + memset(&fget_buf, 0, sizeof(fget_buf)); + fget_buf.f_sz = (size_t)cp->c_len; + memcpy(fget_buf.f_data, cp->c_data, cp->c_len); + fget_biov[0].iov_base = (char *)&fget_buf; + fget_biov[0].iov_len = sizeof(fget_buf.f_sz) + + (size_t)cp->c_len; + } else { + fget_size = (size_t)cp->c_len; + fget_biov[0].iov_base = (char *)&fget_size; + fget_biov[0].iov_len = sizeof(fget_size); + } + + fget_biov[1].iov_base = NULL; + fget_biov[1].iov_len = 0; + *data = fget_biov; + } + + return (err); +} + +static void +fget_done(UNUSED struct iovec *data) +{ + + /* nothing needs to be freed */ +} + +static int +fget_len_result(struct iovec **data) +{ + return (fget_result(data, 0)); +} + +static int +fget_val_result(struct iovec **data) +{ + return (fget_result(data, 1)); +} + +static struct op_info fgetlen_info = { + .op_start = fget_start, + .op_data = fget_data, + .op_result = fget_len_result, + .op_done = fget_done +}; + +static struct op_info fgetval_info = { + .op_start = fget_start, + .op_data = fget_data, + .op_result = fget_val_result, + .op_done = fget_done +}; + +static struct req_info { + int req_error; + u_int req_count; + uint32_t req_size; + uint32_t req_type; + uint32_t req_txid; + struct op_info *req_op; + int resp_error; + int resp_count; + int resp_size; + int resp_off; + struct iovec *resp_biov; +} rinfo; + +static void +fwctl_response_done(void) +{ + + (*rinfo.req_op->op_done)(rinfo.resp_biov); + + /* reinit the req data struct */ + memset(&rinfo, 0, sizeof(rinfo)); +} + +static void +fwctl_request_done(void) +{ + + rinfo.resp_error = (*rinfo.req_op->op_result)(&rinfo.resp_biov); + + /* XXX only a single vector supported at the moment */ + rinfo.resp_off = 0; + if (rinfo.resp_biov == NULL) { + rinfo.resp_size = 0; + } else { + assert(rinfo.resp_biov[0].iov_len < INT_MAX); + rinfo.resp_size = (int)rinfo.resp_biov[0].iov_len; + } +} + +static int +fwctl_request_start(void) +{ + int err; + + /* Data size doesn't include header */ + rinfo.req_size -= 12; + + rinfo.req_op = &errop_info; + if (rinfo.req_type <= OP_MAX && ops[rinfo.req_type] != NULL) + rinfo.req_op = ops[rinfo.req_type]; + + err = (*rinfo.req_op->op_start)(rinfo.req_size); + + if (err) { + errop_set(err); + rinfo.req_op = &errop_info; + } + + /* Catch case of zero-length message here */ + if (rinfo.req_size == 0) { + fwctl_request_done(); + return (1); + } + + return (0); +} + +static int +fwctl_request_data(uint32_t value) +{ + size_t remlen; + + /* Make sure remaining size is >= 0 */ + rinfo.req_size -= sizeof(uint32_t); + remlen = MAX(rinfo.req_size, 0); + + (*rinfo.req_op->op_data)(value, remlen); + + if (rinfo.req_size < sizeof(uint32_t)) { + fwctl_request_done(); + return (1); + } + + return (0); +} + +static int +fwctl_request(uint32_t value) +{ + + int ret; + + ret = 0; + + switch (rinfo.req_count) { + case 0: + /* Verify size */ + if (value < 12) { + printf("msg size error"); + exit(1); + } + rinfo.req_size = value; + rinfo.req_count = 1; + break; + case 1: + rinfo.req_type = value; + rinfo.req_count++; + break; + case 2: + rinfo.req_txid = value; + rinfo.req_count++; + ret = fwctl_request_start(); + break; + default: + ret = fwctl_request_data(value); + break; + } + + return (ret); +} + +static int +fwctl_response(uint32_t *retval) +{ + uint8_t *dp; + size_t remlen; + + switch(rinfo.resp_count) { + case 0: + /* 4 x u32 header len + data */ + *retval = 4*sizeof(uint32_t) + + roundup((uint32_t)rinfo.resp_size, sizeof(uint32_t)); + rinfo.resp_count++; + break; + case 1: + *retval = rinfo.req_type; + rinfo.resp_count++; + break; + case 2: + *retval = rinfo.req_txid; + rinfo.resp_count++; + break; + case 3: + *retval = (uint32_t)rinfo.resp_error; + rinfo.resp_count++; + break; + default: + remlen = (size_t)rinfo.resp_size - (size_t)rinfo.resp_off; + dp = ((uint8_t *)rinfo.resp_biov->iov_base + rinfo.resp_off); + if (remlen >= sizeof(uint32_t)) { + memcpy(retval, dp, sizeof(*retval)); + } else if (remlen > 0) { + *retval = fwctl_send_rest(dp, remlen); + } + rinfo.resp_off += sizeof(uint32_t); + break; + } + + if (rinfo.resp_count > 3 && + rinfo.resp_size - rinfo.resp_off <= 0) { + fwctl_response_done(); + return (1); + } + + return (0); +} + + +/* + * i/o port handling. + */ +static uint8_t +fwctl_inb(void) +{ + uint8_t retval; + + retval = 0xff; + + switch (be_state) { + case DORMANT: + case IDENT_WAIT: + break; + case IDENT_SEND: + retval = sig[ident_idx++]; + if (ident_idx >= sizeof(sig)) + be_state = REQ; + break; + case REQ: + case RESP: + break; + } + + return (retval); +} + +static void +fwctl_outw(uint16_t val) +{ + switch (be_state) { + case DORMANT: + break; + case IDENT_WAIT: + if (val == 0) { + be_state = IDENT_SEND; + ident_idx = 0; + } + break; + case IDENT_SEND: + case REQ: + case RESP: + break; + } +} + +static uint32_t +fwctl_inl(void) +{ + uint32_t retval; + + switch (be_state) { + case DORMANT: + case IDENT_WAIT: + case IDENT_SEND: + case REQ: + retval = 0xffffffff; + break; + case RESP: + if (fwctl_response(&retval)) + be_state = REQ; + break; + } + + return (retval); +} + +static void +fwctl_outl(uint32_t val) +{ + + switch (be_state) { + case DORMANT: + case IDENT_WAIT: + case IDENT_SEND: + break; + case REQ: + if (fwctl_request(val)) + be_state = RESP; + case RESP: + break; + } + +} + +static int +fwctl_handler(UNUSED int vcpu, int in, UNUSED int port, int bytes, + uint32_t *eax, UNUSED void *arg) +{ + + if (in) { + if (bytes == 1) + *eax = fwctl_inb(); + else if (bytes == 4) + *eax = fwctl_inl(); + else + *eax = 0xffff; + } else { + if (bytes == 2) + fwctl_outw((uint16_t)*eax); + else if (bytes == 4) + fwctl_outl(*eax); + } + + return (0); +} +INOUT_PORT(fwctl_wreg, FWCTL_OUT, IOPORT_F_INOUT, fwctl_handler); +INOUT_PORT(fwctl_rreg, FWCTL_IN, IOPORT_F_IN, fwctl_handler); + +void +fwctl_init(void) +{ + + ops[OP_GET_LEN] = &fgetlen_info; + ops[OP_GET] = &fgetval_info; + + be_state = IDENT_WAIT; +} diff --git a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_ahci.c b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_ahci.c index 32b4c8d8e..064c44931 100644 --- a/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_ahci.c +++ b/src/cmd/linuxkit/vendor/github.com/moby/hyperkit/src/lib/pci_ahci.c @@ -797,7 +797,15 @@ next: done += 8; if (elen == 0) { if (done >= len) { - ahci_write_fis_d2h(p, slot, cfis, ATA_S_READY | ATA_S_DSC); + if (ncq) { + if (first) + ahci_write_fis_d2h_ncq(p, slot); + ahci_write_fis_sdb(p, slot, cfis, + ATA_S_READY | ATA_S_DSC); + } else { + ahci_write_fis_d2h(p, slot, cfis, + ATA_S_READY | ATA_S_DSC); + } p->pending &= ~(1 << slot); ahci_check_stopped(p); if (!first) @@ -977,6 +985,7 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis) buf[88] = 0x7f; if (p->xfermode & ATA_UDMA0) buf[88] |= (1 << ((p->xfermode & 7) + 8)); + buf[93] = (1 | 1 <<14); buf[100] = (uint16_t) sectors; buf[101] = (uint16_t) (sectors >> 16); buf[102] = (uint16_t) (sectors >> 32); @@ -1725,7 +1734,7 @@ ahci_handle_cmd(struct ahci_port *p, int slot, uint8_t *cfis) case ATA_SEND_FPDMA_QUEUED: if ((cfis[13] & 0x1f) == ATA_SFPDMA_DSM && cfis[17] == 0 && cfis[16] == ATA_DSM_TRIM && - cfis[11] == 0 && cfis[13] == 1) { + cfis[11] == 0 && cfis[3] == 1) { ahci_handle_dsm_trim(p, slot, cfis, 0); break; }