Changeset View
Changeset View
Standalone View
Standalone View
head/stand/powerpc/ofw/cas.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:keywords | null | FreeBSD=%H \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/*- | |||||
* Copyright (c) 2019 Leandro Lupori | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <openfirm.h> | |||||
#include <stand.h> | |||||
/* PVR */ | |||||
#define PVR_VER_P8E 0x004b0000 | |||||
#define PVR_VER_P8NVL 0x004c0000 | |||||
#define PVR_VER_P8 0x004d0000 | |||||
#define PVR_VER_P9 0x004e0000 | |||||
#define PVR_VER_MASK 0xffff0000 | |||||
/* loader version of kernel's CPU_MAXSIZE */ | |||||
#define MAX_CPUS ((uint32_t)256u) | |||||
/* Option Vectors' settings */ | |||||
/* length of ignored OV */ | |||||
#define OV_IGN_LEN 0 | |||||
/* byte 1 (of any OV) */ | |||||
#define OV_IGN 0x80 | |||||
/* Option Vector 5 */ | |||||
/* byte 2 */ | |||||
#define OV5_LPAR 0x80 | |||||
#define OV5_SPLPAR 0x40 | |||||
#define OV5_DRMEM 0x20 | |||||
#define OV5_LP 0x10 | |||||
#define OV5_ALPHA_PART 0x08 | |||||
#define OV5_DMA_DELAY 0x04 | |||||
#define OV5_DONATE_CPU 0x02 | |||||
#define OV5_MSI 0x01 | |||||
/* 9-12: max cpus */ | |||||
#define OV5_MAX_CPUS(n) ((MAX_CPUS >> (3*8 - (n)*8)) & 0xff) | |||||
/* 13-14: LoPAPR Level */ | |||||
#define LOPAPR_LEVEL 0x0101 /* 1.1 */ | |||||
#define OV5_LOPAPR_LEVEL(n) ((LOPAPR_LEVEL >> (8 - (n)*8)) & 0xff) | |||||
/* byte 17: Platform Facilities */ | |||||
#define OV5_RNG 0x80 | |||||
#define OV5_COMP_ENG 0x40 | |||||
#define OV5_ENC_ENG 0x20 | |||||
/* byte 21: Sub-Processors */ | |||||
#define OV5_NO_SUBPROCS 0 | |||||
#define OV5_SUBPROCS 1 | |||||
/* byte 23: interrupt controller */ | |||||
#define OV5_INTC_XICS 0 | |||||
/* byte 24: MMU */ | |||||
#define OV5_MMU_HPT 0 | |||||
/* byte 25: HPT MMU Extensions */ | |||||
#define OV5_HPT_EXT_NONE 0 | |||||
/* byte 26: Radix MMU Extensions */ | |||||
#define OV5_RPT_EXT_NONE 0 | |||||
struct pvr { | |||||
uint32_t mask; | |||||
uint32_t val; | |||||
}; | |||||
struct opt_vec_ignore { | |||||
char data[2]; | |||||
} __packed; | |||||
struct opt_vec4 { | |||||
char data[3]; | |||||
} __packed; | |||||
struct opt_vec5 { | |||||
char data[27]; | |||||
} __packed; | |||||
static struct ibm_arch_vec { | |||||
struct pvr pvr_list[5]; | |||||
uint8_t num_opts; | |||||
struct opt_vec_ignore vec1; | |||||
struct opt_vec_ignore vec2; | |||||
struct opt_vec_ignore vec3; | |||||
struct opt_vec4 vec4; | |||||
struct opt_vec5 vec5; | |||||
} __packed ibm_arch_vec = { | |||||
/* pvr_list */ { | |||||
{ PVR_VER_MASK, PVR_VER_P8 }, /* POWER8 */ | |||||
{ PVR_VER_MASK, PVR_VER_P8E }, /* POWER8E */ | |||||
{ PVR_VER_MASK, PVR_VER_P8NVL }, /* POWER8NVL */ | |||||
{ PVR_VER_MASK, PVR_VER_P9 }, /* POWER9 */ | |||||
{ 0, 0xffffffffu } /* terminator */ | |||||
}, | |||||
4, /* num_opts (4 actually means 5 option vectors) */ | |||||
{ OV_IGN_LEN, OV_IGN }, /* OV1 */ | |||||
{ OV_IGN_LEN, OV_IGN }, /* OV2 */ | |||||
{ OV_IGN_LEN, OV_IGN }, /* OV3 */ | |||||
/* OV4 (can't be ignored) */ { | |||||
sizeof(struct opt_vec4) - 2, /* length (n-2) */ | |||||
0, | |||||
10 /* Minimum VP entitled capacity percentage * 100 | |||||
* (if absent assume 10%) */ | |||||
}, | |||||
/* OV5 */ { | |||||
sizeof(struct opt_vec5) - 2, /* length (n-2) */ | |||||
0, /* don't ignore */ | |||||
OV5_LPAR | OV5_SPLPAR | OV5_LP | OV5_MSI, | |||||
0, | |||||
0, /* Cooperative Memory Over-commitment */ | |||||
0, /* Associativity Information Option */ | |||||
0, /* Binary Option Controls */ | |||||
0, /* Reserved */ | |||||
0, /* Reserved */ | |||||
OV5_MAX_CPUS(0), | |||||
OV5_MAX_CPUS(1), /* 10 */ | |||||
OV5_MAX_CPUS(2), | |||||
OV5_MAX_CPUS(3), | |||||
OV5_LOPAPR_LEVEL(0), | |||||
OV5_LOPAPR_LEVEL(1), | |||||
0, /* Reserved */ | |||||
0, /* Reserved */ | |||||
0, /* Platform Facilities */ | |||||
0, /* Reserved */ | |||||
0, /* Reserved */ | |||||
0, /* Reserved */ /* 20 */ | |||||
OV5_NO_SUBPROCS, | |||||
0, /* DRMEM_V2 */ | |||||
OV5_INTC_XICS, | |||||
OV5_MMU_HPT, | |||||
OV5_HPT_EXT_NONE, | |||||
OV5_RPT_EXT_NONE | |||||
} | |||||
}; | |||||
static __inline register_t | |||||
mfpvr(void) | |||||
{ | |||||
register_t value; | |||||
__asm __volatile ("mfpvr %0" : "=r"(value)); | |||||
return (value); | |||||
} | |||||
static __inline int | |||||
ppc64_hv(void) | |||||
{ | |||||
int hv; | |||||
/* PSL_HV is bit 3 of 64-bit MSR */ | |||||
__asm __volatile ("mfmsr %0\n\t" | |||||
"rldicl %0,%0,4,63" : "=r"(hv)); | |||||
return (hv); | |||||
} | |||||
int | |||||
ppc64_cas(void) | |||||
{ | |||||
int rc; | |||||
ihandle_t ihandle; | |||||
cell_t err; | |||||
/* Skip CAS when running on PowerNV */ | |||||
if (!ppc64_hv()) | |||||
return (0); | |||||
/* Perform CAS only for POWER8 and later cores */ | |||||
switch (mfpvr() & PVR_VER_MASK) { | |||||
case PVR_VER_P8: | |||||
case PVR_VER_P8E: | |||||
case PVR_VER_P8NVL: | |||||
case PVR_VER_P9: | |||||
break; | |||||
default: | |||||
return (0); | |||||
} | |||||
ihandle = OF_open("/"); | |||||
if (ihandle == -1) { | |||||
printf("cas: failed to open / node\n"); | |||||
return (-1); | |||||
} | |||||
if (rc = OF_call_method("ibm,client-architecture-support", | |||||
ihandle, 1, 1, &ibm_arch_vec, &err)) | |||||
printf("cas: failed to call CAS method\n"); | |||||
else if (err) { | |||||
printf("cas: error: 0x%08lX\n", err); | |||||
rc = -1; | |||||
} | |||||
OF_close(ihandle); | |||||
return (rc); | |||||
} |