[PATCH v2] kvm: ppc: bookehv: Save restore SPRN_SPRG9 on guest entry exit
SPRN_SPRG is used by debug interrupt handler, so this is required for debug support. Signed-off-by: Bharat Bhushan --- v1->v2 - sprng9 is 64bit, not 32bit arch/powerpc/include/asm/kvm_host.h | 1 + arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kvm/bookehv_interrupts.S | 4 3 files changed, 6 insertions(+) diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 372b977..b3e370c 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -588,6 +588,7 @@ struct kvm_vcpu_arch { u32 mmucfg; u32 eptcfg; u32 epr; + u64 sprg9; u32 pwrmgtcr0; u32 crit_save; /* guest debug registers*/ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 17ffcb4..ab9ae04 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -668,6 +668,7 @@ int main(void) DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); + DEFINE(VCPU_SPRG9, offsetof(struct kvm_vcpu, arch.sprg9)); DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S index a1712b8..f45da85 100644 --- a/arch/powerpc/kvm/bookehv_interrupts.S +++ b/arch/powerpc/kvm/bookehv_interrupts.S @@ -441,6 +441,7 @@ _GLOBAL(kvmppc_resume_host) #ifdef CONFIG_64BIT PPC_LL r3, PACA_SPRG_VDSO(r13) #endif + mfspr r5, SPRN_SPRG9 PPC_STD(r6, VCPU_SHARED_SPRG4, r11) mfspr r8, SPRN_SPRG6 PPC_STD(r7, VCPU_SHARED_SPRG5, r11) @@ -448,6 +449,7 @@ _GLOBAL(kvmppc_resume_host) #ifdef CONFIG_64BIT mtspr SPRN_SPRG_VDSO_WRITE, r3 #endif + PPC_STD(r5, VCPU_SPRG9, r4) PPC_STD(r8, VCPU_SHARED_SPRG6, r11) mfxer r3 PPC_STD(r9, VCPU_SHARED_SPRG7, r11) @@ -682,7 +684,9 @@ lightweight_exit: mtspr SPRN_SPRG5W, r6 PPC_LD(r8, VCPU_SHARED_SPRG7, r11) mtspr SPRN_SPRG6W, r7 + PPC_LD(r5, VCPU_SPRG9, r4) mtspr SPRN_SPRG7W, r8 + mtspr SPRN_SPRG9, r5 /* Load some guest volatiles. */ PPC_LL r3, VCPU_LR(r4) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] docs: update ivshmem device spec
Add some notes on the parts needed to use ivshmem devices: more specifically, explain the purpose of an ivshmem server and the basic concept to use the ivshmem devices in guests. Move some parts of the documentation and re-organise it. Signed-off-by: David Marchand --- docs/specs/ivshmem_device_spec.txt | 124 +++- 1 file changed, 93 insertions(+), 31 deletions(-) diff --git a/docs/specs/ivshmem_device_spec.txt b/docs/specs/ivshmem_device_spec.txt index 667a862..f5f2b95 100644 --- a/docs/specs/ivshmem_device_spec.txt +++ b/docs/specs/ivshmem_device_spec.txt @@ -2,30 +2,103 @@ Device Specification for Inter-VM shared memory device -- -The Inter-VM shared memory device is designed to share a region of memory to -userspace in multiple virtual guests. The memory region does not belong to any -guest, but is a POSIX memory object on the host. Optionally, the device may -support sending interrupts to other guests sharing the same memory region. +The Inter-VM shared memory device is designed to share a memory region (created +on the host via the POSIX shared memory API) between multiple QEMU processes +running different guests. In order for all guests to be able to pick up the +shared memory area, it is modeled by QEMU as a PCI device exposing said memory +to the guest as a PCI BAR. +The memory region does not belong to any guest, but is a POSIX memory object on +the host. The host can access this shared memory if needed. + +The device also provides an optional communication mechanism between guests +sharing the same memory object. More details about that in the section 'Guest to +guest communication' section. The Inter-VM PCI device --- -*BARs* +From the VM point of view, the ivshmem PCI device supports three BARs. + +- BAR0 is a 1 Kbyte MMIO region to support registers and interrupts when MSI is + not used. +- BAR1 is used for MSI-X when it is enabled in the device. +- BAR2 is used to access the shared memory object. + +It is your choice how to use the device but you must choose between two +behaviors : + +- basically, if you only need the shared memory part, you will map BAR2. + This way, you have access to the shared memory in guest and can use it as you + see fit (memnic, for example, uses it in userland + http://dpdk.org/browse/memnic). + +- BAR0 and BAR1 are used to implement an optional communication mechanism + through interrupts in the guests. If you need an event mechanism between the + guests accessing the shared memory, you will most likely want to write a + kernel driver that will handle interrupts. See details in the section 'Guest + to guest communication' section. + +The behavior is chosen when starting your QEMU processes: +- no communication mechanism needed, the first QEMU to start creates the shared + memory on the host, subsequent QEMU processes will use it. + +- communication mechanism needed, an ivshmem server must be started before any + QEMU processes, then each QEMU process connects to the server unix socket. + +For more details on the QEMU ivshmem parameters, see qemu-doc documentation. + + +Guest to guest communication + + +This section details the communication mechanism between the guests accessing +the ivhsmem shared memory. -The device supports three BARs. BAR0 is a 1 Kbyte MMIO region to support -registers. BAR1 is used for MSI-X when it is enabled in the device. BAR2 is -used to map the shared memory object from the host. The size of BAR2 is -specified when the guest is started and must be a power of 2 in size. +*ivshmem server* -*Registers* +This server code is available in qemu.git/contrib/ivshmem-server. -The device currently supports 4 registers of 32-bits each. Registers -are used for synchronization between guests sharing the same memory object when -interrupts are supported (this requires using the shared memory server). +The server must be started on the host before any guest. +It creates a shared memory object then waits for clients to connect on an unix +socket. -The server assigns each VM an ID number and sends this ID number to the QEMU -process when the guest starts. +For each client (QEMU processes) that connects to the server: +- the server assigns an ID for this client and sends this ID to him as the first + message, +- the server sends a fd to the shared memory object to this client, +- the server creates a new set of host eventfds associated to the new client and + sends this set to all already connected clients, +- finally, the server sends all the eventfds sets for all clients to the new + client. + +The server signals all clients when one of them disconnects. + +The client IDs are limited to 16 bits because of the current implementation (see +Doorbell register in 'PCI device registers' subsection). Hence on 65536 clients +are supported. + +All the file descriptors (fd to the share
[PATCH v2 1/2] contrib: add ivshmem client and server
When using ivshmem devices, notifications between guests can be sent as interrupts using a ivshmem-server (typical use described in documentation). The client is provided as a debug tool. Signed-off-by: Olivier Matz Signed-off-by: David Marchand --- contrib/ivshmem-client/Makefile | 26 ++ contrib/ivshmem-client/ivshmem-client.c | 418 ++ contrib/ivshmem-client/ivshmem-client.h | 238 ++ contrib/ivshmem-client/main.c | 246 ++ contrib/ivshmem-server/Makefile | 26 ++ contrib/ivshmem-server/ivshmem-server.c | 420 +++ contrib/ivshmem-server/ivshmem-server.h | 185 ++ contrib/ivshmem-server/main.c | 296 ++ qemu-doc.texi | 10 +- 9 files changed, 1862 insertions(+), 3 deletions(-) create mode 100644 contrib/ivshmem-client/Makefile create mode 100644 contrib/ivshmem-client/ivshmem-client.c create mode 100644 contrib/ivshmem-client/ivshmem-client.h create mode 100644 contrib/ivshmem-client/main.c create mode 100644 contrib/ivshmem-server/Makefile create mode 100644 contrib/ivshmem-server/ivshmem-server.c create mode 100644 contrib/ivshmem-server/ivshmem-server.h create mode 100644 contrib/ivshmem-server/main.c diff --git a/contrib/ivshmem-client/Makefile b/contrib/ivshmem-client/Makefile new file mode 100644 index 000..9e32409 --- /dev/null +++ b/contrib/ivshmem-client/Makefile @@ -0,0 +1,26 @@ +# Copyright 2014 6WIND S.A. +# All rights reserved + +S ?= $(CURDIR) +O ?= $(CURDIR) + +CFLAGS += -Wall -Wextra -Werror -g +LDFLAGS += +LDLIBS += -lrt + +VPATH = $(S) +PROG = ivshmem-client +OBJS := $(O)/ivshmem-client.o +OBJS += $(O)/main.o + +$(O)/%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +$(O)/$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +.PHONY: all +all: $(O)/$(PROG) + +clean: + rm -f $(OBJS) $(O)/$(PROG) diff --git a/contrib/ivshmem-client/ivshmem-client.c b/contrib/ivshmem-client/ivshmem-client.c new file mode 100644 index 000..32ef3ef --- /dev/null +++ b/contrib/ivshmem-client/ivshmem-client.c @@ -0,0 +1,418 @@ +/* + * Copyright(c) 2014 6WIND S.A. + * All rights reserved. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ivshmem-client.h" + +/* log a message on stdout if verbose=1 */ +#define debug_log(client, fmt, ...) do { \ +if ((client)->verbose) { \ +printf(fmt, ## __VA_ARGS__); \ +}\ +} while (0) + +/* read message from the unix socket */ +static int +read_one_msg(struct ivshmem_client *client, long *index, int *fd) +{ +int ret; +struct msghdr msg; +struct iovec iov[1]; +union { +struct cmsghdr cmsg; +char control[CMSG_SPACE(sizeof(int))]; +} msg_control; +struct cmsghdr *cmsg; + +iov[0].iov_base = index; +iov[0].iov_len = sizeof(*index); + +memset(&msg, 0, sizeof(msg)); +msg.msg_iov = iov; +msg.msg_iovlen = 1; +msg.msg_control = &msg_control; +msg.msg_controllen = sizeof(msg_control); + +ret = recvmsg(client->sock_fd, &msg, 0); +if (ret < 0) { +debug_log(client, "cannot read message: %s\n", strerror(errno)); +return -1; +} +if (ret == 0) { +debug_log(client, "lost connection to server\n"); +return -1; +} + +*fd = -1; + +for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + +if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || +cmsg->cmsg_level != SOL_SOCKET || +cmsg->cmsg_type != SCM_RIGHTS) { +continue; +} + +memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd)); +} + +return 0; +} + +/* free a peer when the server advertise a disconnection or when the + * client is freed */ +static void +free_peer(struct ivshmem_client *client, struct ivshmem_client_peer *peer) +{ +unsigned vector; + +TAILQ_REMOVE(&client->peer_list, peer, next); +for (vector = 0; vector < peer->vectors_count; vector++) { +close(peer->vectors[vector]); +} + +free(peer); +} + +/* handle message coming from server (new peer, new vectors) */ +static int +handle_server_msg(struct ivshmem_client *client) +{ +struct ivshmem_client_peer *peer; +long peer_id; +int ret, fd; + +ret = read_one_msg(client, &peer_id, &fd); +if (ret < 0) { +return -1; +} + +/* can return a peer or the local client */ +peer = ivshmem_client_search_peer(client, peer_id); + +/* delete peer */ +if (fd == -1) { + +if (peer == NULL || peer == &client->local) { +debug_log(client, "receive delete for invalid peer %ld", peer_id); +return
[PATCH v2 0/2] ivshmem: update documentation, add client/server tools
Here is a patchset containing an update on ivshmem specs documentation and importing ivshmem server and client tools. These tools have been written from scratch and are not related to what is available in nahanni repository. I put them in contrib/ directory as the qemu-doc.texi was already telling the server was supposed to be there. Changes since v1: - moved client/server import patch before doc update, - tried to re-organise the ivshmem_device_spec.txt file based on Claudio comments (still not sure if the result is that great, comments welcome), - incorporated comments from Claudio, Eric and Cam, - added more details on the server <-> client messages exchange (but sorry, no ASCII art here). By the way, there are still some functionnalities that need description (use of ioeventfd, the lack of irqfd support) and some parts of the ivshmem code clearly need cleanup. I will try to address this in future patches when these first patches are ok. -- David Marchand David Marchand (2): contrib: add ivshmem client and server docs: update ivshmem device spec contrib/ivshmem-client/Makefile | 26 ++ contrib/ivshmem-client/ivshmem-client.c | 418 ++ contrib/ivshmem-client/ivshmem-client.h | 238 ++ contrib/ivshmem-client/main.c | 246 ++ contrib/ivshmem-server/Makefile | 26 ++ contrib/ivshmem-server/ivshmem-server.c | 420 +++ contrib/ivshmem-server/ivshmem-server.h | 185 ++ contrib/ivshmem-server/main.c | 296 ++ docs/specs/ivshmem_device_spec.txt | 124 ++--- qemu-doc.texi | 10 +- 10 files changed, 1955 insertions(+), 34 deletions(-) create mode 100644 contrib/ivshmem-client/Makefile create mode 100644 contrib/ivshmem-client/ivshmem-client.c create mode 100644 contrib/ivshmem-client/ivshmem-client.h create mode 100644 contrib/ivshmem-client/main.c create mode 100644 contrib/ivshmem-server/Makefile create mode 100644 contrib/ivshmem-server/ivshmem-server.c create mode 100644 contrib/ivshmem-server/ivshmem-server.h create mode 100644 contrib/ivshmem-server/main.c -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] kvm-all: Use 'tmpcpu' instead of 'cpu' in sub-looping to avoid 'cpu' be NULL
On 07/20/2014 03:29 PM, Jan Kiszka wrote: > On 2014-07-19 03:21, Chen Gang wrote: >> If kvm_arch_remove_sw_breakpoint() in CPU_FOREACH() always be fail, it >> will let 'cpu' NULL. And the next kvm_arch_remove_sw_breakpoint() in >> QTAILQ_FOREACH_SAFE() will get NULL parameter for 'cpu'. >> >> And kvm_arch_remove_sw_breakpoint() can assumes 'cpu' must never be NULL, >> so need define additional temporary variable for 'cpu' to avoid the case. >> >> >> Signed-off-by: Chen Gang >> --- >> kvm-all.c | 5 +++-- >> 1 file changed, 3 insertions(+), 2 deletions(-) >> >> diff --git a/kvm-all.c b/kvm-all.c >> index 3ae30ee..1402f4f 100644 >> --- a/kvm-all.c >> +++ b/kvm-all.c >> @@ -2077,12 +2077,13 @@ void kvm_remove_all_breakpoints(CPUState *cpu) >> { >> struct kvm_sw_breakpoint *bp, *next; >> KVMState *s = cpu->kvm_state; >> +CPUState *tmpcpu; >> >> QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { >> if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) { >> /* Try harder to find a CPU that currently sees the breakpoint. >> */ >> -CPU_FOREACH(cpu) { >> -if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) { >> +CPU_FOREACH(tmpcpu) { >> +if (kvm_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) { >> break; >> } >> } >> > > Good catch. To make it clear in the changelog: The actual issue is that > we misuse "cpu" as an iteration variable while its original value is > still in use. That cpu can eventually become NULL this way is one result. > OK, thanks. If necessary, I shall send patch v2 for additional comments. (if really necessary to send, please let me know) Thanks. -- Chen Gang Open share and attitude like air water and life which God blessed -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] kvm-all: Use 'tmpcpu' instead of 'cpu' in sub-looping to avoid 'cpu' be NULL
On 2014-07-19 03:21, Chen Gang wrote: > If kvm_arch_remove_sw_breakpoint() in CPU_FOREACH() always be fail, it > will let 'cpu' NULL. And the next kvm_arch_remove_sw_breakpoint() in > QTAILQ_FOREACH_SAFE() will get NULL parameter for 'cpu'. > > And kvm_arch_remove_sw_breakpoint() can assumes 'cpu' must never be NULL, > so need define additional temporary variable for 'cpu' to avoid the case. > > > Signed-off-by: Chen Gang > --- > kvm-all.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/kvm-all.c b/kvm-all.c > index 3ae30ee..1402f4f 100644 > --- a/kvm-all.c > +++ b/kvm-all.c > @@ -2077,12 +2077,13 @@ void kvm_remove_all_breakpoints(CPUState *cpu) > { > struct kvm_sw_breakpoint *bp, *next; > KVMState *s = cpu->kvm_state; > +CPUState *tmpcpu; > > QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { > if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) { > /* Try harder to find a CPU that currently sees the breakpoint. > */ > -CPU_FOREACH(cpu) { > -if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) { > +CPU_FOREACH(tmpcpu) { > +if (kvm_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) { > break; > } > } > Good catch. To make it clear in the changelog: The actual issue is that we misuse "cpu" as an iteration variable while its original value is still in use. That cpu can eventually become NULL this way is one result. Jan signature.asc Description: OpenPGP digital signature