0001
0002 #include <asm/byteorder.h>
0003 #include <asm/lppaca.h>
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 static int vphn_unpack_associativity(const long *packed, __be32 *unpacked)
0026 {
0027 __be64 be_packed[VPHN_REGISTER_COUNT];
0028 int i, nr_assoc_doms = 0;
0029 const __be16 *field = (const __be16 *) be_packed;
0030 u16 last = 0;
0031 bool is_32bit = false;
0032
0033 #define VPHN_FIELD_UNUSED (0xffff)
0034 #define VPHN_FIELD_MSB (0x8000)
0035 #define VPHN_FIELD_MASK (~VPHN_FIELD_MSB)
0036
0037
0038 for (i = 0; i < VPHN_REGISTER_COUNT; i++)
0039 be_packed[i] = cpu_to_be64(packed[i]);
0040
0041 for (i = 1; i < VPHN_ASSOC_BUFSIZE; i++) {
0042 u16 new = be16_to_cpup(field++);
0043
0044 if (is_32bit) {
0045
0046
0047
0048
0049 unpacked[++nr_assoc_doms] =
0050 cpu_to_be32(last << 16 | new);
0051 is_32bit = false;
0052 } else if (new == VPHN_FIELD_UNUSED)
0053
0054 break;
0055 else if (new & VPHN_FIELD_MSB) {
0056
0057 unpacked[++nr_assoc_doms] =
0058 cpu_to_be32(new & VPHN_FIELD_MASK);
0059 } else {
0060
0061
0062
0063
0064 last = new;
0065 is_32bit = true;
0066 }
0067 }
0068
0069
0070 unpacked[0] = cpu_to_be32(nr_assoc_doms);
0071
0072 return nr_assoc_doms;
0073 }
0074
0075
0076 #ifdef __KERNEL__
0077 #include <asm/hvcall.h>
0078
0079 long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity)
0080 {
0081 long rc;
0082 long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
0083
0084 rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, cpu);
0085 if (rc == H_SUCCESS)
0086 vphn_unpack_associativity(retbuf, associativity);
0087
0088 return rc;
0089 }
0090 #endif