summaryrefslogtreecommitdiff
path: root/arch/powerpc/mm/vphn.c
diff options
context:
space:
mode:
authorGreg Kurz <gkurz@linux.vnet.ibm.com>2015-02-23 18:14:31 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2015-03-18 02:48:59 +0300
commit4b6cfb2a8cd7520e8a747718e5c1da047697ca31 (patch)
tree4c11bb5e691f12eec899ae7350a743920541e96b /arch/powerpc/mm/vphn.c
parentb1fc9484aa339c19bd57702dc88fb046702b6092 (diff)
downloadlinux-4b6cfb2a8cd7520e8a747718e5c1da047697ca31.tar.xz
powerpc/vphn: move VPHN parsing logic to a separate file
The goal behind this patch is to be able to write userland tests for the VPHN parsing code. Suggested-by: Michael Ellerman <mpe@ellerman.id.au> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm/vphn.c')
-rw-r--r--arch/powerpc/mm/vphn.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/powerpc/mm/vphn.c b/arch/powerpc/mm/vphn.c
new file mode 100644
index 000000000000..c49ed519c381
--- /dev/null
+++ b/arch/powerpc/mm/vphn.c
@@ -0,0 +1,50 @@
+#include <asm/byteorder.h>
+#include "vphn.h"
+
+/*
+ * Convert the associativity domain numbers returned from the hypervisor
+ * to the sequence they would appear in the ibm,associativity property.
+ */
+int vphn_unpack_associativity(const long *packed, __be32 *unpacked)
+{
+ __be64 be_packed[VPHN_REGISTER_COUNT];
+ int i, nr_assoc_doms = 0;
+ const __be16 *field = (const __be16 *) be_packed;
+
+#define VPHN_FIELD_UNUSED (0xffff)
+#define VPHN_FIELD_MSB (0x8000)
+#define VPHN_FIELD_MASK (~VPHN_FIELD_MSB)
+
+ /* Let's recreate the original stream. */
+ for (i = 0; i < VPHN_REGISTER_COUNT; i++)
+ be_packed[i] = cpu_to_be64(packed[i]);
+
+ for (i = 1; i < VPHN_ASSOC_BUFSIZE; i++) {
+ if (be16_to_cpup(field) == VPHN_FIELD_UNUSED) {
+ /* All significant fields processed, and remaining
+ * fields contain the reserved value of all 1's.
+ * Just store them.
+ */
+ unpacked[i] = *((__be32 *)field);
+ field += 2;
+ } else if (be16_to_cpup(field) & VPHN_FIELD_MSB) {
+ /* Data is in the lower 15 bits of this field */
+ unpacked[i] = cpu_to_be32(
+ be16_to_cpup(field) & VPHN_FIELD_MASK);
+ field++;
+ nr_assoc_doms++;
+ } else {
+ /* Data is in the lower 15 bits of this field
+ * concatenated with the next 16 bit field
+ */
+ unpacked[i] = *((__be32 *)field);
+ field += 2;
+ nr_assoc_doms++;
+ }
+ }
+
+ /* The first cell contains the length of the property */
+ unpacked[0] = cpu_to_be32(nr_assoc_doms);
+
+ return nr_assoc_doms;
+}