From e09b41010ba33a20a87472ee821fa407a5b8da36 Mon Sep 17 00:00:00 2001 From: José Pekkarinen Date: Mon, 11 Apr 2016 10:41:07 +0300 Subject: These changes are the raw update to linux-4.4.6-rt14. Kernel sources are taken from kernel.org, and rt patch from the rt wiki download page. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen --- kernel/drivers/staging/unisys/visorutil/Kconfig | 9 - kernel/drivers/staging/unisys/visorutil/Makefile | 9 - .../drivers/staging/unisys/visorutil/charqueue.c | 127 ------------- .../drivers/staging/unisys/visorutil/charqueue.h | 37 ---- .../drivers/staging/unisys/visorutil/memregion.h | 43 ----- .../staging/unisys/visorutil/memregion_direct.c | 207 --------------------- .../staging/unisys/visorutil/periodic_work.c | 204 -------------------- .../staging/unisys/visorutil/visorkmodutils.c | 71 ------- 8 files changed, 707 deletions(-) delete mode 100644 kernel/drivers/staging/unisys/visorutil/Kconfig delete mode 100644 kernel/drivers/staging/unisys/visorutil/Makefile delete mode 100644 kernel/drivers/staging/unisys/visorutil/charqueue.c delete mode 100644 kernel/drivers/staging/unisys/visorutil/charqueue.h delete mode 100644 kernel/drivers/staging/unisys/visorutil/memregion.h delete mode 100644 kernel/drivers/staging/unisys/visorutil/memregion_direct.c delete mode 100644 kernel/drivers/staging/unisys/visorutil/periodic_work.c delete mode 100644 kernel/drivers/staging/unisys/visorutil/visorkmodutils.c (limited to 'kernel/drivers/staging/unisys/visorutil') diff --git a/kernel/drivers/staging/unisys/visorutil/Kconfig b/kernel/drivers/staging/unisys/visorutil/Kconfig deleted file mode 100644 index be9c2cf89..000000000 --- a/kernel/drivers/staging/unisys/visorutil/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -# -# Unisys timskmod configuration -# - -config UNISYS_VISORUTIL - tristate "Unisys visorutil driver" - ---help--- - If you say Y here, you will enable the Unisys visorutil driver. - diff --git a/kernel/drivers/staging/unisys/visorutil/Makefile b/kernel/drivers/staging/unisys/visorutil/Makefile deleted file mode 100644 index d9ab5a36e..000000000 --- a/kernel/drivers/staging/unisys/visorutil/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# Makefile for Unisys timskmod -# - -obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil.o - -visorutil-y := charqueue.o periodic_work.o memregion_direct.o visorkmodutils.o - -ccflags-y += -Idrivers/staging/unisys/include diff --git a/kernel/drivers/staging/unisys/visorutil/charqueue.c b/kernel/drivers/staging/unisys/visorutil/charqueue.c deleted file mode 100644 index c91752a2d..000000000 --- a/kernel/drivers/staging/unisys/visorutil/charqueue.c +++ /dev/null @@ -1,127 +0,0 @@ -/* charqueue.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Simple character queue implementation for Linux kernel mode. - */ - -#include "charqueue.h" - -#define MYDRVNAME "charqueue" - -#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail) - -struct charqueue { - int alloc_size; - int nslots; - spinlock_t lock; /* read/write lock for this structure */ - int head, tail; - unsigned char buf[0]; -}; - -struct charqueue *visor_charqueue_create(ulong nslots) -{ - int alloc_size = sizeof(struct charqueue) + nslots + 1; - struct charqueue *cq; - - cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY); - if (cq == NULL) - return NULL; - cq->alloc_size = alloc_size; - cq->nslots = nslots; - cq->head = 0; - cq->tail = 0; - spin_lock_init(&cq->lock); - return cq; -} -EXPORT_SYMBOL_GPL(visor_charqueue_create); - -void visor_charqueue_enqueue(struct charqueue *charqueue, unsigned char c) -{ - int alloc_slots = charqueue->nslots+1; /* 1 slot is always empty */ - - spin_lock(&charqueue->lock); - charqueue->head = (charqueue->head+1) % alloc_slots; - if (charqueue->head == charqueue->tail) - /* overflow; overwrite the oldest entry */ - charqueue->tail = (charqueue->tail+1) % alloc_slots; - charqueue->buf[charqueue->head] = c; - spin_unlock(&charqueue->lock); -} -EXPORT_SYMBOL_GPL(visor_charqueue_enqueue); - -BOOL visor_charqueue_is_empty(struct charqueue *charqueue) -{ - BOOL b; - - spin_lock(&charqueue->lock); - b = IS_EMPTY(charqueue); - spin_unlock(&charqueue->lock); - return b; -} -EXPORT_SYMBOL_GPL(visor_charqueue_is_empty); - -static int charqueue_dequeue_1(struct charqueue *charqueue) -{ - int alloc_slots = charqueue->nslots + 1; /* 1 slot is always empty */ - - if (IS_EMPTY(charqueue)) - return -1; - charqueue->tail = (charqueue->tail+1) % alloc_slots; - return charqueue->buf[charqueue->tail]; -} - -int charqueue_dequeue(struct charqueue *charqueue) -{ - int rc; - - spin_lock(&charqueue->lock); - rc = charqueue_dequeue_1(charqueue); - spin_unlock(&charqueue->lock); - return rc; -} - -int visor_charqueue_dequeue_n(struct charqueue *charqueue, unsigned char *buf, - int n) -{ - int rc, counter = 0, c; - - spin_lock(&charqueue->lock); - for (;;) { - if (n <= 0) - break; /* no more buffer space */ - c = charqueue_dequeue_1(charqueue); - if (c < 0) - break; /* no more input */ - *buf = (unsigned char)(c); - buf++; - n--; - counter++; - } - rc = counter; - spin_unlock(&charqueue->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_charqueue_dequeue_n); - -void visor_charqueue_destroy(struct charqueue *charqueue) -{ - if (charqueue == NULL) - return; - kfree(charqueue); -} -EXPORT_SYMBOL_GPL(visor_charqueue_destroy); diff --git a/kernel/drivers/staging/unisys/visorutil/charqueue.h b/kernel/drivers/staging/unisys/visorutil/charqueue.h deleted file mode 100644 index f46a776b9..000000000 --- a/kernel/drivers/staging/unisys/visorutil/charqueue.h +++ /dev/null @@ -1,37 +0,0 @@ -/* charqueue.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CHARQUEUE_H__ -#define __CHARQUEUE_H__ - -#include "timskmod.h" - -/* struct charqueue is an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -struct charqueue; - -struct charqueue *visor_charqueue_create(ulong nslots); -void visor_charqueue_enqueue(struct charqueue *charqueue, unsigned char c); -int charqueue_dequeue(struct charqueue *charqueue); -int visor_charqueue_dequeue_n(struct charqueue *charqueue, unsigned char *buf, - int n); -BOOL visor_charqueue_is_empty(struct charqueue *charqueue); -void visor_charqueue_destroy(struct charqueue *charqueue); - -#endif - diff --git a/kernel/drivers/staging/unisys/visorutil/memregion.h b/kernel/drivers/staging/unisys/visorutil/memregion.h deleted file mode 100644 index 0c3eebcf6..000000000 --- a/kernel/drivers/staging/unisys/visorutil/memregion.h +++ /dev/null @@ -1,43 +0,0 @@ -/* memregion.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __MEMREGION_H__ -#define __MEMREGION_H__ - -#include "timskmod.h" - -/* struct memregion is an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -struct memregion; - -struct memregion *visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes); -struct memregion *visor_memregion_create_overlapped(struct memregion *parent, - ulong offset, ulong nbytes); -int visor_memregion_resize(struct memregion *memregion, ulong newsize); -int visor_memregion_read(struct memregion *memregion, - ulong offset, void *dest, ulong nbytes); -int visor_memregion_write(struct memregion *memregion, - ulong offset, void *src, ulong nbytes); -void visor_memregion_destroy(struct memregion *memregion); -HOSTADDRESS visor_memregion_get_physaddr(struct memregion *memregion); -ulong visor_memregion_get_nbytes(struct memregion *memregion); -void memregion_dump(struct memregion *memregion, char *s, - ulong off, ulong len, struct seq_file *seq); -void __iomem *visor_memregion_get_pointer(struct memregion *memregion); - -#endif diff --git a/kernel/drivers/staging/unisys/visorutil/memregion_direct.c b/kernel/drivers/staging/unisys/visorutil/memregion_direct.c deleted file mode 100644 index eb7422fbe..000000000 --- a/kernel/drivers/staging/unisys/visorutil/memregion_direct.c +++ /dev/null @@ -1,207 +0,0 @@ -/* memregion_direct.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * This is an implementation of memory regions that can be used to read/write - * channel memory (in main memory of the host system) from code running in - * a virtual partition. - */ -#include "timskmod.h" -#include "memregion.h" - -#define MYDRVNAME "memregion" - -struct memregion { - HOSTADDRESS physaddr; - ulong nbytes; - void __iomem *mapped; - BOOL requested; - BOOL overlapped; -}; - -static BOOL mapit(struct memregion *memregion); -static void unmapit(struct memregion *memregion); - -struct memregion * -visor_memregion_create(HOSTADDRESS physaddr, ulong nbytes) -{ - struct memregion *rc = NULL; - struct memregion *memregion; - - memregion = kzalloc(sizeof(*memregion), GFP_KERNEL | __GFP_NORETRY); - if (memregion == NULL) - return NULL; - - memregion->physaddr = physaddr; - memregion->nbytes = nbytes; - memregion->overlapped = FALSE; - if (!mapit(memregion)) { - rc = NULL; - goto cleanup; - } - rc = memregion; -cleanup: - if (rc == NULL) { - visor_memregion_destroy(memregion); - memregion = NULL; - } - return rc; -} -EXPORT_SYMBOL_GPL(visor_memregion_create); - -struct memregion * -visor_memregion_create_overlapped(struct memregion *parent, ulong offset, - ulong nbytes) -{ - struct memregion *memregion = NULL; - - if (parent == NULL) - return NULL; - - if (parent->mapped == NULL) - return NULL; - - if ((offset >= parent->nbytes) || - ((offset + nbytes) >= parent->nbytes)) - return NULL; - - memregion = kzalloc(sizeof(*memregion), GFP_KERNEL|__GFP_NORETRY); - if (memregion == NULL) - return NULL; - - memregion->physaddr = parent->physaddr + offset; - memregion->nbytes = nbytes; - memregion->mapped = ((u8 __iomem *)(parent->mapped)) + offset; - memregion->requested = FALSE; - memregion->overlapped = TRUE; - return memregion; -} -EXPORT_SYMBOL_GPL(visor_memregion_create_overlapped); - -static BOOL -mapit(struct memregion *memregion) -{ - ulong physaddr = (ulong)(memregion->physaddr); - ulong nbytes = memregion->nbytes; - - memregion->requested = FALSE; - if (request_mem_region(physaddr, nbytes, MYDRVNAME)) - memregion->requested = TRUE; - memregion->mapped = ioremap_cache(physaddr, nbytes); - if (!memregion->mapped) - return FALSE; - return TRUE; -} - -static void -unmapit(struct memregion *memregion) -{ - if (memregion->mapped != NULL) { - iounmap(memregion->mapped); - memregion->mapped = NULL; - } - if (memregion->requested) { - release_mem_region((ulong)(memregion->physaddr), - memregion->nbytes); - memregion->requested = FALSE; - } -} - -HOSTADDRESS -visor_memregion_get_physaddr(struct memregion *memregion) -{ - return memregion->physaddr; -} -EXPORT_SYMBOL_GPL(visor_memregion_get_physaddr); - -ulong -visor_memregion_get_nbytes(struct memregion *memregion) -{ - return memregion->nbytes; -} -EXPORT_SYMBOL_GPL(visor_memregion_get_nbytes); - -void __iomem * -visor_memregion_get_pointer(struct memregion *memregion) -{ - return memregion->mapped; -} -EXPORT_SYMBOL_GPL(visor_memregion_get_pointer); - -int -visor_memregion_resize(struct memregion *memregion, ulong newsize) -{ - if (newsize == memregion->nbytes) - return 0; - if (memregion->overlapped) - /* no error check here - we no longer know the - * parent's range! - */ - memregion->nbytes = newsize; - else { - unmapit(memregion); - memregion->nbytes = newsize; - if (!mapit(memregion)) - return -1; - } - return 0; -} -EXPORT_SYMBOL_GPL(visor_memregion_resize); - -static int -memregion_readwrite(BOOL is_write, - struct memregion *memregion, ulong offset, - void *local, ulong nbytes) -{ - if (offset + nbytes > memregion->nbytes) - return -EIO; - - if (is_write) - memcpy_toio(memregion->mapped + offset, local, nbytes); - else - memcpy_fromio(local, memregion->mapped + offset, nbytes); - - return 0; -} - -int -visor_memregion_read(struct memregion *memregion, ulong offset, void *dest, - ulong nbytes) -{ - return memregion_readwrite(FALSE, memregion, offset, dest, nbytes); -} -EXPORT_SYMBOL_GPL(visor_memregion_read); - -int -visor_memregion_write(struct memregion *memregion, ulong offset, void *src, - ulong nbytes) -{ - return memregion_readwrite(TRUE, memregion, offset, src, nbytes); -} -EXPORT_SYMBOL_GPL(visor_memregion_write); - -void -visor_memregion_destroy(struct memregion *memregion) -{ - if (memregion == NULL) - return; - if (!memregion->overlapped) - unmapit(memregion); - kfree(memregion); -} -EXPORT_SYMBOL_GPL(visor_memregion_destroy); - diff --git a/kernel/drivers/staging/unisys/visorutil/periodic_work.c b/kernel/drivers/staging/unisys/visorutil/periodic_work.c deleted file mode 100644 index abbfb4889..000000000 --- a/kernel/drivers/staging/unisys/visorutil/periodic_work.c +++ /dev/null @@ -1,204 +0,0 @@ -/* periodic_work.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -/* - * Helper functions to schedule periodic work in Linux kernel mode. - */ - -#include "timskmod.h" -#include "periodic_work.h" - -#define MYDRVNAME "periodic_work" - -struct periodic_work { - rwlock_t lock; - struct delayed_work work; - void (*workfunc)(void *); - void *workfuncarg; - BOOL is_scheduled; - BOOL want_to_stop; - ulong jiffy_interval; - struct workqueue_struct *workqueue; - const char *devnam; -}; - -static void periodic_work_func(struct work_struct *work) -{ - struct periodic_work *pw; - - pw = container_of(work, struct periodic_work, work.work); - (*pw->workfunc)(pw->workfuncarg); -} - -struct periodic_work *visor_periodic_work_create(ulong jiffy_interval, - struct workqueue_struct *workqueue, - void (*workfunc)(void *), - void *workfuncarg, - const char *devnam) -{ - struct periodic_work *pw; - - pw = kzalloc(sizeof(*pw), GFP_KERNEL | __GFP_NORETRY); - if (!pw) - return NULL; - - rwlock_init(&pw->lock); - pw->jiffy_interval = jiffy_interval; - pw->workqueue = workqueue; - pw->workfunc = workfunc; - pw->workfuncarg = workfuncarg; - pw->devnam = devnam; - return pw; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_create); - -void visor_periodic_work_destroy(struct periodic_work *pw) -{ - kfree(pw); -} -EXPORT_SYMBOL_GPL(visor_periodic_work_destroy); - -/** Call this from your periodic work worker function to schedule the next - * call. - * If this function returns FALSE, there was a failure and the - * periodic work is no longer scheduled - */ -BOOL visor_periodic_work_nextperiod(struct periodic_work *pw) -{ - BOOL rc = FALSE; - - write_lock(&pw->lock); - if (pw->want_to_stop) { - pw->is_scheduled = FALSE; - pw->want_to_stop = FALSE; - rc = TRUE; /* yes, TRUE; see visor_periodic_work_stop() */ - goto unlock; - } else if (queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval) < 0) { - pw->is_scheduled = FALSE; - rc = FALSE; - goto unlock; - } - rc = TRUE; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_nextperiod); - -/** This function returns TRUE iff new periodic work was actually started. - * If this function returns FALSE, then no work was started - * (either because it was already started, or because of a failure). - */ -BOOL visor_periodic_work_start(struct periodic_work *pw) -{ - BOOL rc = FALSE; - - write_lock(&pw->lock); - if (pw->is_scheduled) { - rc = FALSE; - goto unlock; - } - if (pw->want_to_stop) { - rc = FALSE; - goto unlock; - } - INIT_DELAYED_WORK(&pw->work, &periodic_work_func); - if (queue_delayed_work(pw->workqueue, &pw->work, - pw->jiffy_interval) < 0) { - rc = FALSE; - goto unlock; - } - pw->is_scheduled = TRUE; - rc = TRUE; -unlock: - write_unlock(&pw->lock); - return rc; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_start); - -/** This function returns TRUE iff your call actually stopped the periodic - * work. - * - * -- PAY ATTENTION... this is important -- - * - * NO NO #1 - * - * Do NOT call this function from some function that is running on the - * same workqueue as the work you are trying to stop might be running - * on! If you violate this rule, visor_periodic_work_stop() MIGHT work, - * but it also MIGHT get hung up in an infinite loop saying - * "waiting for delayed work...". This will happen if the delayed work - * you are trying to cancel has been put in the workqueue list, but can't - * run yet because we are running that same workqueue thread right now. - * - * Bottom line: If you need to call visor_periodic_work_stop() from a - * workitem, be sure the workitem is on a DIFFERENT workqueue than the - * workitem that you are trying to cancel. - * - * If I could figure out some way to check for this "no no" condition in - * the code, I would. It would have saved me the trouble of writing this - * long comment. And also, don't think this is some "theoretical" race - * condition. It is REAL, as I have spent the day chasing it. - * - * NO NO #2 - * - * Take close note of the locks that you own when you call this function. - * You must NOT own any locks that are needed by the periodic work - * function that is currently installed. If you DO, a deadlock may result, - * because stopping the periodic work often involves waiting for the last - * iteration of the periodic work function to complete. Again, if you hit - * this deadlock, you will get hung up in an infinite loop saying - * "waiting for delayed work...". - */ -BOOL visor_periodic_work_stop(struct periodic_work *pw) -{ - BOOL stopped_something = FALSE; - - write_lock(&pw->lock); - stopped_something = pw->is_scheduled && (!pw->want_to_stop); - while (pw->is_scheduled) { - pw->want_to_stop = TRUE; - if (cancel_delayed_work(&pw->work)) { - /* We get here if the delayed work was pending as - * delayed work, but was NOT run. - */ - WARN_ON(!pw->is_scheduled); - pw->is_scheduled = FALSE; - } else { - /* If we get here, either the delayed work: - * - was run, OR, - * - is running RIGHT NOW on another processor, OR, - * - wasn't even scheduled (there is a miniscule - * timing window where this could be the case) - * flush_workqueue() would make sure it is finished - * executing, but that still isn't very useful, which - * explains the loop... - */ - } - if (pw->is_scheduled) { - write_unlock(&pw->lock); - SLEEPJIFFIES(10); - write_lock(&pw->lock); - } else { - pw->want_to_stop = FALSE; - } - } - write_unlock(&pw->lock); - return stopped_something; -} -EXPORT_SYMBOL_GPL(visor_periodic_work_stop); diff --git a/kernel/drivers/staging/unisys/visorutil/visorkmodutils.c b/kernel/drivers/staging/unisys/visorutil/visorkmodutils.c deleted file mode 100644 index 62f0f7046..000000000 --- a/kernel/drivers/staging/unisys/visorutil/visorkmodutils.c +++ /dev/null @@ -1,71 +0,0 @@ -/* timskmodutils.c - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include "timskmod.h" - -#define MYDRVNAME "timskmodutils" - -/* s-Par uses the Intel processor's VT-X features to separate groups of - * processors into partitions. The firmware sets the hypervisor bit and - * reports an ID in the HV capabilities leaf so that the partition's OS - * knows s-Par is present and managing the processors. - */ - -#define UNISYS_SPAR_LEAF_ID 0x40000000 - -/* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */ -#define UNISYS_SPAR_ID_EBX 0x73696e55 -#define UNISYS_SPAR_ID_ECX 0x70537379 -#define UNISYS_SPAR_ID_EDX 0x34367261 - -int unisys_spar_platform; -EXPORT_SYMBOL_GPL(unisys_spar_platform); - -static __init uint32_t visorutil_spar_detect(void) -{ - unsigned int eax, ebx, ecx, edx; - - if (cpu_has_hypervisor) { - /* check the ID */ - cpuid(UNISYS_SPAR_LEAF_ID, &eax, &ebx, &ecx, &edx); - return (ebx == UNISYS_SPAR_ID_EBX) && - (ecx == UNISYS_SPAR_ID_ECX) && - (edx == UNISYS_SPAR_ID_EDX); - } else { - return 0; - } -} - -static __init int visorutil_mod_init(void) -{ - if (visorutil_spar_detect()) { - unisys_spar_platform = TRUE; - return 0; - } else { - return -ENODEV; - } -} - -static __exit void -visorutil_mod_exit(void) -{ -} - -module_init(visorutil_mod_init); -module_exit(visorutil_mod_exit); - -MODULE_LICENSE("GPL"); -- cgit 1.2.3-korg