aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mvp/mvpkm/qp_host_kernel.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mvp/mvpkm/qp_host_kernel.c')
-rw-r--r--arch/arm/mvp/mvpkm/qp_host_kernel.c574
1 files changed, 0 insertions, 574 deletions
diff --git a/arch/arm/mvp/mvpkm/qp_host_kernel.c b/arch/arm/mvp/mvpkm/qp_host_kernel.c
deleted file mode 100644
index c53f315..0000000
--- a/arch/arm/mvp/mvpkm/qp_host_kernel.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * Linux 2.6.32 and later Kernel module for VMware MVP Hypervisor Support
- *
- * Copyright (C) 2010-2012 VMware, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#line 5
-
-/**
- * @file
- *
- * @brief MVP host kernel implementation of the queue pairs API
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/highmem.h>
-#include <linux/slab.h>
-
-#include "mvp.h"
-#include "mvpkm_kernel.h"
-#include "qp.h"
-#include "qp_host_kernel.h"
-
-static QPHandle queuePairs[QP_MAX_QUEUE_PAIRS];
-static QPListener listeners[QP_MAX_LISTENERS];
-
-/*
- * Protect listeners and queuePairs.
- */
-static DEFINE_MUTEX(qpLock);
-
-#define QPLock() mutex_lock(&qpLock)
-#define QPUnlock() mutex_unlock(&qpLock)
-
-/**
- * @brief Map a vector of pages into virtually contiguous kernel space
- * @param vm this vm's vm struct
- * @param base base machine page number that lists pages to map
- * @param nrPages number of pages to map
- * @param[out] qp handle to qp to set up
- * @param[out] hkva virtual address mapping
- * @return QP_SUCCESS on success, error code otherwise. Mapped address
- * is returned in hkva
- */
-
-static int32
-MapPages(MvpkmVM *vm,
- MPN base,
- uint32 nrPages,
- QPHandle *qp,
- HKVA *hkva)
-{
- HKVA *va;
- uint32 i;
- uint32 rc;
- struct page *basepfn = pfn_to_page(base);
- struct page **pages;
-
- BUG_ON(!vm); // this would be very bad.
-
- if (!hkva) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- pages = kmalloc(nrPages * sizeof (MPN), GFP_KERNEL);
- if (!pages) {
- return QP_ERROR_NO_MEM;
- }
-
- /*
- * Map in the first page, read out the MPN vector
- */
- down_write(&vm->lockedSem);
- va = kmap(basepfn);
- if (!va) {
- rc = QP_ERROR_INVALID_ARGS;
- kfree(pages);
- qp->pages = NULL;
- goto out;
- }
-
- /*
- * Grab references and translate MPNs->PFNs
- */
- for (i = 0; i < nrPages; i++) {
- pages[i] = pfn_to_page(((MPN*)va)[i]);
- get_page(pages[i]);
- }
-
- /*
- * Clean up the first mapping and remap the entire vector
- */
- kunmap(basepfn);
- va = vmap(pages, nrPages, VM_MAP, PAGE_KERNEL);
- if (!va) {
- rc = QP_ERROR_NO_MEM;
- for (i = 0; i < nrPages; i++) {
- put_page(pages[i]);
- }
- kfree(pages);
- qp->pages = NULL;
- goto out;
- } else {
- *hkva = (HKVA)va;
- qp->pages = pages;
- }
-
- /*
- * Let's not leak mpns..
- */
- memset(va, 0x0, nrPages * PAGE_SIZE);
-
- rc = QP_SUCCESS;
-
-out:
- up_write(&vm->lockedSem);
- return rc;
-}
-
-/**
- * @brief Initialize all free queue pair entries and listeners
- */
-
-void
-QP_HostInit(void)
-{
- uint32 i;
-
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- QP_MakeInvalidQPHandle(&queuePairs[i]);
- }
-
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- listeners[i] = NULL;
- }
-}
-
-
-/**
- * @brief Detaches a guest from a queue pair and notifies
- * any registered listeners through the detach callback
- * @param id id that guest requested a detach from, detaches all
- * queue pairs associated with a VM if the resource id == QP_INVALID_ID
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_GuestDetachRequest(QPId id)
-{
- QPHandle *qp;
- uint32 i;
-
- if (id.resource >= QP_MAX_ID && id.resource != QP_INVALID_ID) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QPLock();
-
- /*
- * Invalidate all queue pairs associated with this VM if
- * resource == QP_INVALID_ID
- */
- if (id.resource == QP_INVALID_ID) {
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- qp = &queuePairs[i];
- if (qp->id.context == id.context && qp->peerDetachCB) {
- qp->peerDetachCB(qp->detachData);
- }
- }
- } else {
- qp = &queuePairs[id.resource];
- if (qp->peerDetachCB) {
- qp->peerDetachCB(qp->detachData);
- }
- }
-
- QPUnlock();
-
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Attaches a guest to shared memory region
- * @param vm guest to attach
- * @param args queue pair args structure:
- * - args->id: id of the region to attach to, if id.resource == QP_INVALID_ID, then
- * an id is assigned
- * - args->capacity: total size of the region in bytes
- * - args->type: type of queue pair (e.g PVTCP)
- * @param base base machine page number that lists pages to map
- * @param nrPages number of pages to map
- * @return QP_SUCCESS on success, appropriate error code otherwise.
- */
-
-int32
-QP_GuestAttachRequest(MvpkmVM *vm,
- QPInitArgs *args,
- MPN base,
- uint32 nrPages)
-{
- int32 rc;
- HKVA hkva = 0;
- QPHandle *qp;
- uint32 i;
-
- if ((!QP_CheckArgs(args)) ||
- (vm->wsp->guestId != (Mksck_VmId)args->id.context) ||
- (args->capacity != (nrPages * PAGE_SIZE))) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QP_DBG("%s: Guest requested attach to [%u:%u] capacity: %u type: %x base: %x nrPages: %u\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity,
- args->type,
- base,
- nrPages);
-
- QPLock();
-
- /*
- * Assign a resource id if id == QP_INVALID_ID
- */
- if (args->id.resource == QP_INVALID_ID) {
- for (i = 0; i < QP_MAX_QUEUE_PAIRS; i++) {
- if (queuePairs[i].state == QP_STATE_FREE) {
- args->id.resource = i;
- QP_DBG("%s: Guest requested anonymous region, assigning resource id %u\n",
- __FUNCTION__, args->id.resource);
- goto found;
- }
- }
-
- rc = QP_ERROR_NO_MEM;
- goto out;
- }
-
-found:
- qp = queuePairs + args->id.resource;
-
- if (qp->state != QP_STATE_FREE) {
- rc = QP_ERROR_ALREADY_ATTACHED;
- goto out;
- }
-
- /*
- * Brand new queue pair, allocate some memory to back it and
- * initialize the entry
- */
- rc = MapPages(vm, base, nrPages, qp, &hkva);
- if (rc != QP_SUCCESS) {
- goto out;
- }
-
- /* NB: reversed from the guest */
- qp->id = args->id;
- qp->capacity = args->capacity;
- qp->produceQ = (QHandle*)hkva;
- qp->consumeQ = (QHandle*)(hkva + args->capacity/2);
- qp->queueSize = args->capacity/2 - sizeof(QHandle);
- qp->type = args->type;
- qp->state = QP_STATE_GUEST_ATTACHED;
-
- /*
- * The qp is now assumed to be well-formed
- */
- QP_DBG("%s: Guest attached to region [%u:%u] capacity: %u HKVA: %x\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity,
- (uint32)hkva);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- if (rc != QP_SUCCESS) {
- QP_DBG("%s: Failed to attach: %u\n", __FUNCTION__, rc);
- }
- return rc;
-}
-
-
-/**
- * @brief Attaches the host to the shared memory region. The guest
- * MUST have allocated the shmem region already or else this will fail.
- * @param args structure with the shared memory region id to attach to,
- * total size of the region in bytes, and type of queue pair (e.g PVTCP)
- * @param[in, out] qp handle to the queue pair to return
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_Attach(QPInitArgs *args,
- QPHandle** qp)
-{
- uint32 rc;
-
- if (!qp || !QP_CheckArgs(args)) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- QP_DBG("%s: Attaching to id: [%u:%u] capacity: %u\n",
- __FUNCTION__,
- args->id.context,
- args->id.resource,
- args->capacity);
-
- QPLock();
- *qp = queuePairs + args->id.resource;
-
- if (!QP_CheckHandle(*qp)) {
- *qp = NULL;
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- if ((*qp)->state == QP_STATE_CONNECTED) {
- rc = QP_ERROR_ALREADY_ATTACHED;
- goto out;
- }
-
- if ((*qp)->state != QP_STATE_GUEST_ATTACHED) {
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- (*qp)->state = QP_STATE_CONNECTED;
-
- QP_DBG("%s: Attached!\n", __FUNCTION__);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- return rc;
-}
-
-/**
- * @brief Detaches the host to the shared memory region.
- * @param[in, out] qp handle to the queue pair
- * @return QP_SUCCESS on success, appropriate error code otherwise
- * @sideeffects Frees memory
- */
-
-int32
-QP_Detach(QPHandle* qp)
-{
- uint32 rc;
- uint32 i;
-
- QPLock();
- if (!QP_CheckHandle(qp)) {
- rc = QP_ERROR_INVALID_HANDLE;
- goto out;
- }
-
- QP_DBG("%s: Freeing queue pair [%u:%u]\n",
- __FUNCTION__,
- qp->id.context,
- qp->id.resource);
-
- BUG_ON(!qp->produceQ);
- BUG_ON(!qp->pages);
- BUG_ON((qp->state != QP_STATE_CONNECTED) &&
- (qp->state != QP_STATE_GUEST_ATTACHED));
-
- vunmap(qp->produceQ);
-
- for (i = 0; i < qp->capacity/PAGE_SIZE; i++) {
- put_page(qp->pages[i]);
- }
- kfree(qp->pages);
-
- QP_DBG("%s: Host detached from [%u:%u]\n",
- __FUNCTION__,
- qp->id.context,
- qp->id.resource);
-
- QP_MakeInvalidQPHandle(qp);
- rc = QP_SUCCESS;
-
-out:
- QPUnlock();
- return rc;
-}
-
-
-/**
- * @brief Detaches and destroys all queue pairs associated with a given guest
- * @param vmID which VM to clean up
- * @sideeffects Destroys all queue pairs for guest vmID
- */
-
-void QP_DetachAll(Mksck_VmId vmID) {
- QPId id = {
- .context = (uint32)vmID,
- .resource = QP_INVALID_ID
- };
-
- QP_DBG("%s: Detaching all queue pairs from vmId context %u\n", __FUNCTION__, vmID);
- QP_GuestDetachRequest(id);
-}
-
-/**
- * @brief Registers a listener into the queue pair system. Callbacks are
- * called with interrupts disabled and must not sleep.
- * @param listener listener to be called
- * @return QP_SUCCESS on success, QP_ERROR_NO_MEM if no more
- * listeners can be registered
- */
-
-int32
-QP_RegisterListener(const QPListener listener)
-{
- uint32 i;
- int32 rc = QP_ERROR_NO_MEM;
-
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (!listeners[i]) {
- listeners[i] = listener;
- QP_DBG("%s: Registered listener\n", __FUNCTION__);
- rc = QP_SUCCESS;
- break;
- }
- }
- QPUnlock();
-
- return rc;
-}
-
-
-/**
- * @brief Unregister a listener service from the queue pair system.
- * @param listener listener to unregister
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_UnregisterListener(const QPListener listener)
-{
- uint32 i;
- int32 rc = QP_ERROR_INVALID_HANDLE;
-
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (listeners[i] == listener) {
- listeners[i] = NULL;
- QP_DBG("%s: Unregistered listener\n", __FUNCTION__);
- rc = QP_SUCCESS;
- break;
- }
- }
- QPUnlock();
-
- return rc;
-}
-
-
-/**
- * @brief Registers a callback to be called when the guest detaches
- * from a queue pair. Callbacks are called with interrupts and
- * must not sleep.
- * @param qp handle to the queue pair
- * @param callback callback to be called
- * @param data data to deliver to the callback
- * @return QP_SUCCESS on success, appropriate error code otherwise
- */
-
-int32
-QP_RegisterDetachCB(QPHandle *qp,
- void (*callback)(void*),
- void *data)
-{
- if (!QP_CheckHandle(qp)) {
- return QP_ERROR_INVALID_HANDLE;
- }
-
- if (!callback) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- qp->peerDetachCB = callback;
- qp->detachData = data;
- QP_DBG("%s: Registered detach callback\n", __FUNCTION__);
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Noop on the host, only guests can initiate a notify
- * @param args noop
- * @return QP_SUCCESS
- */
-
-
-int32 QP_Notify(QPInitArgs *args) {
- return QP_SUCCESS;
-}
-
-
-/**
- * @brief Notify any registered listeners for the given queue pair
- * @param args initialization arguments used by the guest
- * @return QP_SUCCESS on success, error otherwise
- */
-
-int32 QP_NotifyListener(QPInitArgs *args) {
- int32 i;
- QPHandle *qp = NULL;
-
- if (!QP_CheckArgs(args)) {
- return QP_ERROR_INVALID_ARGS;
- }
-
- /*
- * Iterate over listeners until one of them reports they handled it
- */
- QPLock();
- for (i = 0; i < QP_MAX_LISTENERS; i++) {
- if (listeners[i]) {
- QP_DBG("Delivering attach event to listener...\n");
- if (listeners[i](args) == QP_SUCCESS) {
- break;
- }
- }
- }
-
- if (i == QP_MAX_LISTENERS) {
- /*
- * No listener successfully probed this QP.
- * The guest DETACH HVC isn't implemented; we need compensate for it
- * by deallocating the QP here.
- * This is a workaround which assumes, more-or-less correctly, that
- * unsuccessful QP probes never lead to subsequent host-attaching.
- */
-
- qp = &queuePairs[args->id.resource];
- }
-
- QPUnlock();
-
- if (qp) {
- QP_Detach(qp);
- }
- return QP_SUCCESS;
-}
-
-
-EXPORT_SYMBOL(QP_Attach);
-EXPORT_SYMBOL(QP_Detach);
-EXPORT_SYMBOL(QP_RegisterListener);
-EXPORT_SYMBOL(QP_UnregisterListener);
-EXPORT_SYMBOL(QP_RegisterDetachCB);
-EXPORT_SYMBOL(QP_Notify);