* NBD fixes from Alex and Eric
* Debug code bitrot from Emilio * HPET fix from Bill * ps2kbd fix from Hervé * PKU fix from myself * Coverity fixes from Gonglei * More memory.txt update from Jiangang * .gitignore maintenance from Changlong -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJXBtpMAAoJEL/70l94x66Dz18H/im1nR9+DII3V4Ch2DOA/xaL gCDHOr+KOXnzLcKQytfBCRjVsXZKnd2kayxtDrFc6ebCh7+Uar5+Z21P0wzCry5a Z/LohJXg7rdHCNaF+9yW7uVbvDjuaepnS1fO9PaMnLviLjqxbIhZixYvuYRPwXD7 oFp88+cbgONIFTe7riXaVGBjjjsyTV8DyXyyS7zlBsuaTihfSYDuYy8upgrCk3Af k9P/VqHxoNpnR1dMPVJdjyN6UQwWYB6i1g4GOEFessRu3H7wz0zCtzUuFL8dGIEs 3VZ7pQ/1QCPr5zaMn7EXofusxeZhU+gZwDnp/bsgGSI73MnMZkTB4Ws8CPf6AXA= =1rhX -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * NBD fixes from Alex and Eric * Debug code bitrot from Emilio * HPET fix from Bill * ps2kbd fix from Hervé * PKU fix from myself * Coverity fixes from Gonglei * More memory.txt update from Jiangang * .gitignore maintenance from Changlong # gpg: Signature made Thu 07 Apr 2016 23:08:12 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" * remotes/bonzini/tags/for-upstream: target-i386: check for PKU even for non-writable pages tests: ignore test-logging translate-all: add missing fold of tb_ctx into tcg_ctx hostmem-file: fix memory leak spapr: fix possible Negative array index read nbd: do not hang nbd_wr_syncv if outside a coroutine and no available data nbd: Don't kill server when client requests unknown option nbd: Fix NBD unsupported options qemu-nbd: Document -x option nbd: Improve debug traces on little-endian nbd: Avoid bitrot in TRACE() usage nbd: Return correct error for write to read-only export docs: fix typo in memory.txt hw/timer: Revert "hpet: inverse polarity when pin above ISA_NUM_IRQS" ps2kbd: default to scancode_set 2, as with KBD_CMD_RESET Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
28ee01269e
@ -52,11 +52,14 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
error_setg(errp, "-mem-path not supported on this host");
|
||||
#else
|
||||
if (!memory_region_size(&backend->mr)) {
|
||||
gchar *path;
|
||||
backend->force_prealloc = mem_prealloc;
|
||||
path = object_get_canonical_path(OBJECT(backend));
|
||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
|
||||
object_get_canonical_path(OBJECT(backend)),
|
||||
path,
|
||||
backend->size, fb->share,
|
||||
fb->mem_path, errp);
|
||||
g_free(path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -185,9 +185,9 @@ an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two
|
||||
of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at
|
||||
offset 0x2000. As a diagram:
|
||||
|
||||
0 1000 2000 3000 4000 5000 6000 7000 8000
|
||||
|------|------|------|------|------|------|------|-------|
|
||||
A: [ ]
|
||||
0 1000 2000 3000 4000 5000 6000 7000 8000
|
||||
|------|------|------|------|------|------|------|------|
|
||||
A: [ ]
|
||||
C: [CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]
|
||||
B: [ ]
|
||||
D: [DDDDD]
|
||||
@ -247,7 +247,7 @@ system_memory: container@0-2^48-1
|
||||
|
|
||||
+---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
|
||||
|
|
||||
+---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
|
||||
+---- vga-window: alias@0xa0000-0xbffff ---> #pci (0xa0000-0xbffff)
|
||||
| (prio 1)
|
||||
|
|
||||
+---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
|
||||
|
@ -628,7 +628,7 @@ static void ps2_kbd_reset(void *opaque)
|
||||
ps2_common_reset(&s->common);
|
||||
s->scan_enabled = 0;
|
||||
s->translate = 0;
|
||||
s->scancode_set = 0;
|
||||
s->scancode_set = 2;
|
||||
}
|
||||
|
||||
static void ps2_mouse_reset(void *opaque)
|
||||
|
@ -2208,6 +2208,10 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
if (node < 0 || node >= MAX_NODES) {
|
||||
error_setg(errp, "Invaild node %d", node);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently PowerPC kernel doesn't allow hot-adding memory to
|
||||
|
@ -201,12 +201,7 @@ static void update_irq(struct HPETTimer *timer, int set)
|
||||
if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
|
||||
s->isr &= ~mask;
|
||||
if (!timer_fsb_route(timer)) {
|
||||
/* fold the ICH PIRQ# pin's internal inversion logic into hpet */
|
||||
if (route >= ISA_NUM_IRQS) {
|
||||
qemu_irq_raise(s->irqs[route]);
|
||||
} else {
|
||||
qemu_irq_lower(s->irqs[route]);
|
||||
}
|
||||
qemu_irq_lower(s->irqs[route]);
|
||||
}
|
||||
} else if (timer_fsb_route(timer)) {
|
||||
address_space_stl_le(&address_space_memory, timer->fsb >> 32,
|
||||
@ -214,12 +209,7 @@ static void update_irq(struct HPETTimer *timer, int set)
|
||||
NULL);
|
||||
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
|
||||
s->isr |= mask;
|
||||
/* fold the ICH PIRQ# pin's internal inversion logic into hpet */
|
||||
if (route >= ISA_NUM_IRQS) {
|
||||
qemu_irq_lower(s->irqs[route]);
|
||||
} else {
|
||||
qemu_irq_raise(s->irqs[route]);
|
||||
}
|
||||
qemu_irq_raise(s->irqs[route]);
|
||||
} else {
|
||||
s->isr &= ~mask;
|
||||
qemu_irq_pulse(s->irqs[route]);
|
||||
|
63
nbd/client.c
63
nbd/client.c
@ -73,16 +73,46 @@ static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports);
|
||||
*/
|
||||
|
||||
|
||||
static int nbd_handle_reply_err(uint32_t opt, uint32_t type, Error **errp)
|
||||
/* If type represents success, return 1 without further action.
|
||||
* If type represents an error reply, consume the rest of the packet on ioc.
|
||||
* Then return 0 for unsupported (so the client can fall back to
|
||||
* other approaches), or -1 with errp set for other errors.
|
||||
*/
|
||||
static int nbd_handle_reply_err(QIOChannel *ioc, uint32_t opt, uint32_t type,
|
||||
Error **errp)
|
||||
{
|
||||
uint32_t len;
|
||||
char *msg = NULL;
|
||||
int result = -1;
|
||||
|
||||
if (!(type & (1 << 31))) {
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (read_sync(ioc, &len, sizeof(len)) != sizeof(len)) {
|
||||
error_setg(errp, "failed to read option length");
|
||||
return -1;
|
||||
}
|
||||
len = be32_to_cpu(len);
|
||||
if (len) {
|
||||
if (len > NBD_MAX_BUFFER_SIZE) {
|
||||
error_setg(errp, "server's error message is too long");
|
||||
goto cleanup;
|
||||
}
|
||||
msg = g_malloc(len + 1);
|
||||
if (read_sync(ioc, msg, len) != len) {
|
||||
error_setg(errp, "failed to read option error message");
|
||||
goto cleanup;
|
||||
}
|
||||
msg[len] = '\0';
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NBD_REP_ERR_UNSUP:
|
||||
error_setg(errp, "Unsupported option type %x", opt);
|
||||
break;
|
||||
TRACE("server doesn't understand request %d, attempting fallback",
|
||||
opt);
|
||||
result = 0;
|
||||
goto cleanup;
|
||||
|
||||
case NBD_REP_ERR_POLICY:
|
||||
error_setg(errp, "Denied by server for option %x", opt);
|
||||
@ -101,7 +131,13 @@ static int nbd_handle_reply_err(uint32_t opt, uint32_t type, Error **errp)
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (msg) {
|
||||
error_append_hint(errp, "%s\n", msg);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_free(msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp)
|
||||
@ -111,6 +147,7 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp)
|
||||
uint32_t type;
|
||||
uint32_t len;
|
||||
uint32_t namelen;
|
||||
int error;
|
||||
|
||||
*name = NULL;
|
||||
if (read_sync(ioc, &magic, sizeof(magic)) != sizeof(magic)) {
|
||||
@ -138,11 +175,9 @@ static int nbd_receive_list(QIOChannel *ioc, char **name, Error **errp)
|
||||
return -1;
|
||||
}
|
||||
type = be32_to_cpu(type);
|
||||
if (type == NBD_REP_ERR_UNSUP) {
|
||||
return 0;
|
||||
}
|
||||
if (nbd_handle_reply_err(opt, type, errp) < 0) {
|
||||
return -1;
|
||||
error = nbd_handle_reply_err(ioc, opt, type, errp);
|
||||
if (error <= 0) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (read_sync(ioc, &len, sizeof(len)) != sizeof(len)) {
|
||||
@ -628,16 +663,16 @@ ssize_t nbd_send_request(QIOChannel *ioc, struct nbd_request *request)
|
||||
uint8_t buf[NBD_REQUEST_SIZE];
|
||||
ssize_t ret;
|
||||
|
||||
TRACE("Sending request to server: "
|
||||
"{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
|
||||
request->from, request->len, request->handle, request->type);
|
||||
|
||||
cpu_to_be32w((uint32_t*)buf, NBD_REQUEST_MAGIC);
|
||||
cpu_to_be32w((uint32_t*)(buf + 4), request->type);
|
||||
cpu_to_be64w((uint64_t*)(buf + 8), request->handle);
|
||||
cpu_to_be64w((uint64_t*)(buf + 16), request->from);
|
||||
cpu_to_be32w((uint32_t*)(buf + 24), request->len);
|
||||
|
||||
TRACE("Sending request to server: "
|
||||
"{ .from = %" PRIu64", .len = %u, .handle = %" PRIu64", .type=%i}",
|
||||
request->from, request->len, request->handle, request->type);
|
||||
|
||||
ret = write_sync(ioc, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -50,9 +50,12 @@ ssize_t nbd_wr_syncv(QIOChannel *ioc,
|
||||
* qio_channel_yield() that works with AIO contexts
|
||||
* and consider using that in this branch */
|
||||
qemu_coroutine_yield();
|
||||
} else {
|
||||
} else if (done) {
|
||||
/* XXX this is needed by nbd_reply_ready. */
|
||||
qio_channel_wait(ioc,
|
||||
do_read ? G_IO_IN : G_IO_OUT);
|
||||
} else {
|
||||
return -EAGAIN;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -33,18 +33,21 @@
|
||||
/* #define DEBUG_NBD */
|
||||
|
||||
#ifdef DEBUG_NBD
|
||||
#define TRACE(msg, ...) do { \
|
||||
LOG(msg, ## __VA_ARGS__); \
|
||||
} while(0)
|
||||
#define DEBUG_NBD_PRINT 1
|
||||
#else
|
||||
#define TRACE(msg, ...) \
|
||||
do { } while (0)
|
||||
#define DEBUG_NBD_PRINT 0
|
||||
#endif
|
||||
|
||||
#define TRACE(msg, ...) do { \
|
||||
if (DEBUG_NBD_PRINT) { \
|
||||
LOG(msg, ## __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LOG(msg, ...) do { \
|
||||
fprintf(stderr, "%s:%s():L%d: " msg "\n", \
|
||||
__FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
/* This is all part of the "official" NBD API.
|
||||
*
|
||||
|
11
nbd/server.c
11
nbd/server.c
@ -26,6 +26,7 @@ static int system_errno_to_nbd_errno(int err)
|
||||
case 0:
|
||||
return NBD_SUCCESS;
|
||||
case EPERM:
|
||||
case EROFS:
|
||||
return NBD_EPERM;
|
||||
case EIO:
|
||||
return NBD_EIO;
|
||||
@ -482,9 +483,12 @@ static int nbd_negotiate_options(NBDClient *client)
|
||||
return -EINVAL;
|
||||
default:
|
||||
TRACE("Unsupported option 0x%x", clientflags);
|
||||
if (nbd_negotiate_drop_sync(client->ioc, length) != length) {
|
||||
return -EIO;
|
||||
}
|
||||
nbd_negotiate_send_rep(client->ioc, NBD_REP_ERR_UNSUP,
|
||||
clientflags);
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@ -655,6 +659,9 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, struct nbd_reply *reply)
|
||||
|
||||
reply->error = system_errno_to_nbd_errno(reply->error);
|
||||
|
||||
TRACE("Sending response to client: { .error = %d, handle = %" PRIu64 " }",
|
||||
reply->error, reply->handle);
|
||||
|
||||
/* Reply
|
||||
[ 0 .. 3] magic (NBD_REPLY_MAGIC)
|
||||
[ 4 .. 7] error (0 == no error)
|
||||
@ -664,8 +671,6 @@ static ssize_t nbd_send_reply(QIOChannel *ioc, struct nbd_reply *reply)
|
||||
stl_be_p(buf + 4, reply->error);
|
||||
stq_be_p(buf + 8, reply->handle);
|
||||
|
||||
TRACE("Sending response to client");
|
||||
|
||||
ret = write_sync(ioc, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -75,6 +75,7 @@ static void usage(const char *name)
|
||||
" -e, --shared=NUM device can be shared by NUM clients (default '1')\n"
|
||||
" -t, --persistent don't exit on the last connection\n"
|
||||
" -v, --verbose display extra debugging information\n"
|
||||
" -x, --export-name=NAME expose export by name\n"
|
||||
"\n"
|
||||
"Exposing part of the image:\n"
|
||||
" -o, --offset=OFFSET offset into the image\n"
|
||||
|
@ -919,29 +919,31 @@ do_check_protect_pse36:
|
||||
!((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
|
||||
prot |= PAGE_EXEC;
|
||||
}
|
||||
|
||||
if ((prot & (1 << is_write1)) == 0) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
|
||||
if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
|
||||
(ptep & PG_USER_MASK) && env->pkru) {
|
||||
uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
|
||||
uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
|
||||
uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
|
||||
uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
|
||||
if (pkru_ad) {
|
||||
prot &= ~(PAGE_READ | PAGE_WRITE);
|
||||
pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
|
||||
} else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
|
||||
prot &= ~PAGE_WRITE;
|
||||
pkru_prot &= ~PAGE_WRITE;
|
||||
}
|
||||
if ((prot & (1 << is_write1)) == 0) {
|
||||
|
||||
prot &= pkru_prot;
|
||||
if ((pkru_prot & (1 << is_write1)) == 0) {
|
||||
assert(is_write1 != 2);
|
||||
error_code |= PG_ERROR_PK_MASK;
|
||||
goto do_fault_protect;
|
||||
}
|
||||
}
|
||||
|
||||
if ((prot & (1 << is_write1)) == 0) {
|
||||
goto do_fault_protect;
|
||||
}
|
||||
|
||||
/* yes, it can! */
|
||||
is_dirty = is_write && !(pte & PG_DIRTY_MASK);
|
||||
if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
|
||||
|
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -39,6 +39,7 @@ test-io-channel-file.txt
|
||||
test-io-channel-socket
|
||||
test-io-channel-tls
|
||||
test-io-task
|
||||
test-logging
|
||||
test-mul64
|
||||
test-opts-visitor
|
||||
test-qapi-event.[ch]
|
||||
|
@ -861,7 +861,8 @@ static void tb_invalidate_check(target_ulong address)
|
||||
|
||||
address &= TARGET_PAGE_MASK;
|
||||
for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
|
||||
for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
|
||||
for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL;
|
||||
tb = tb->phys_hash_next) {
|
||||
if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
|
||||
address >= tb->pc + tb->size)) {
|
||||
printf("ERROR invalidate: address=" TARGET_FMT_lx
|
||||
|
Loading…
Reference in New Issue
Block a user