[Skiboot] [PATCH v2 2/6] VAS: Initialize the basic VAS internal registers

Oliver O'Halloran oohall at gmail.com
Wed Nov 23 16:28:43 AEDT 2016


On Wed, Nov 23, 2016 at 1:00 PM, Sukadev Bhattiprolu
<sukadev at linux.vnet.ibm.com> wrote:
> Initialize the basic VAS internal registers that are needed for a
> functioning VAS. Initializing VAS involves writing either pre-defined
> values or allocated addresses to appropriate SCOM addresses.
>
> Signed-off-by: Sukadev Bhattiprolu <sukadev at linux.vnet.ibm.com>
> ---
>  core/vas.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 245 insertions(+), 1 deletion(-)
>
> diff --git a/core/vas.c b/core/vas.c
> index eefb40d..47556a0 100644
> --- a/core/vas.c
> +++ b/core/vas.c
> @@ -13,8 +13,252 @@
>   * See the License for the specific language governing permissions and
>   * limitations under the License.
>   */
> +#include <skiboot.h>
> +#include <chip.h>
> +#include <xscom.h>
>  #include <vas.h>
>
> -__attrconst void init_vas(void)
> +/*
> + * TODO: Set to 64K after initial development.
> + */
> +static int max_win_per_chip = 16;
> +static int vas_initialized;
> +
> +static uint64_t get_hvwc_mmio_bar(const int chipid)
> +{
> +       return VAS_HVWC_MMIO_BAR_BASE + chipid * VAS_HVWC_MMIO_BAR_SIZE;
> +}
> +
> +static uint64_t get_uwc_mmio_bar(int chipid)
> +{
> +       return VAS_UWC_MMIO_BAR_BASE + chipid * VAS_UWC_MMIO_BAR_SIZE;
> +}
> +
> +static inline uint64_t compute_vas_scom_addr(uint64_t ring_sat_offset)
> +{
> +       return VAS_SCOM_BASE_ADDR + ring_sat_offset;
> +}
> +
> +static int vas_scom_write(struct proc_chip *chip, uint64_t reg, uint64_t val)
> +{
> +       return xscom_write(chip->id, compute_vas_scom_addr(reg), val);
> +}
> +
> +static inline int vas_scom_read(struct proc_chip *chip, uint64_t reg,
> +                       uint64_t *val)
> +{
> +       return xscom_read(chip->id, compute_vas_scom_addr(reg), val);
> +}
> +
> +static int init_north_ctl(struct proc_chip *chip)
> +{
> +       uint64_t val = 0ULL;
> +
> +       val = SETFIELD(VAS_64K_MODE_MASK, val, VAS_64K_MODE);
> +       val = SETFIELD(VAS_ACCEPT_PASTE_MASK, val, VAS_ACCEPT_PASTE);
> +
> +       return vas_scom_write(chip, VAS_MISC_N_CTL, val);
> +}
> +
> +static int reset_north_ctl(struct proc_chip *chip)
> +{
> +       return vas_scom_write(chip, VAS_MISC_N_CTL, 0ULL);
> +}
> +
> +static void reset_fir(struct proc_chip *chip)
> +{
> +       uint64_t val;
> +
> +       val = 0x0ULL;
> +       vas_scom_write(chip, VAS_FIR0, val);
> +       vas_scom_write(chip, VAS_FIR1, val);
> +       vas_scom_write(chip, VAS_FIR2, val);
> +       vas_scom_write(chip, VAS_FIR3, val);
> +       vas_scom_write(chip, VAS_FIR4, val);
> +       vas_scom_write(chip, VAS_FIR5, val);
> +       vas_scom_write(chip, VAS_FIR6, val);
> +       vas_scom_write(chip, VAS_FIR7, val);
> +}
> +
> +/*
> + * Initialize RMA BAR and RMA Base Address Mask Register (BAMR) to their
> + * default values. This will cause VAS to accept paste commands to all
> + * chips in the system.
> + */
> +static int init_rma(struct proc_chip *chip)
> +{
> +       int rc;
> +       uint64_t val;
> +
> +       val = 0ULL;
> +       val = SETFIELD(VAS_RMA_BAR_ADDR_MASK, val, 0x08000000000ULL);
> +
> +       rc = vas_scom_write(chip, VAS_RMA_BAR, val);
> +       if (rc)
> +               return rc;
> +
> +       val = 0ULL;
> +       val = SETFIELD(VAS_RMA_BAMR_ADDR_MASK, val, 0xFFFC0000000ULL);
> +
> +       rc = vas_scom_write(chip, VAS_RMA_BAMR, val);
> +
> +       return rc;
> +}
> +
> +/*
> + * Window Context MMIO (WCM) Region for each chip is assigned in the P9
> + * MMIO MAP spreadsheet. Write this value to the SCOM address associated
> + * with WCM_BAR.
> + */
> +static int init_wcm(struct proc_chip *chip)
> +{
> +       uint64_t wcmbar;
> +
> +       wcmbar = get_hvwc_mmio_bar(chip->id);
> +
> +       /*
> +        * Write the entire WCMBAR address to the SCOM address. VAS will
> +        * extract bits that it thinks are relevant i.e bits 8..38
> +        */
> +       return vas_scom_write(chip, VAS_WCM_BAR, wcmbar);
> +}
> +
> +/*
> + * OS/User Window Context MMIO (UWCM) Region for each is assigned in the
> + * P9 MMIO MAP spreadsheet. Write this value to the SCOM address associated
> + * with UWCM_BAR.
> + */
> +static int init_uwcm(struct proc_chip *chip)
> +{
> +       uint64_t uwcmbar;
> +
> +       uwcmbar = get_uwc_mmio_bar(chip->id);
> +
> +       /*
> +        * Write the entire UWCMBAR address to the SCOM address. VAS will
> +        * extract bits that it thinks are relevant i.e bits 8..35.
> +        */
> +       return vas_scom_write(chip, VAS_UWCM_BAR, uwcmbar);
> +}
> +
> +/*
> + * VAS needs a backing store for the 64K window contexts on a chip.
> + * (64K times 512 = 8MB). This region needs to be contiguous, so
> + * allocate during early boot. Then write the allocated address to
> + * the SCOM address for the Backing store BAR.
> + */
> +static int init_wcbs(struct proc_chip *chip)
> +{
> +       uint64_t wcbs;
> +       size_t size;
> +
> +       /* align to the backing store size */
> +       size = (size_t)VAS_WCBS_SIZE;
> +       wcbs = (uint64_t)local_alloc(chip->id, size, size);
> +       if (!wcbs)
> +               return -ENOMEM;
> +
> +       /*
> +        * Write entire WCBS_BAR address to the SCOM address. VAS will extract
> +        * relevant bits.
> +        */
> +       return vas_scom_write(chip, VAS_WCBS_BAR, wcbs);
> +}
> +
> +/*
> + * A VAS Window context is a 512-byte area made up of a set of 64-bit
> + * registers. But not all registers (eg: 0, 1, 7 etc) are valid and
> + * hence should not be written to.
> + *
> + * Use the following bitmask to identify valid offsets in the window
> + * context. Refer to Table 3.2 in the VAS workbook for list of valid
> + * offsets.
> + */
> +uint64_t valid_wcm_mask = 0x00D71FFF13F7D77CULL;
> +
> +/*
> + * Init all registers in one window context
> + */
> +static int init_one_window(struct proc_chip *chip, int idx)
>  {
> +       uint64_t wcmbar;
> +       uint64_t *window_start;
> +       int reg, nregs;
> +
> +       if (idx >= max_win_per_chip)
> +               return -1;
> +
> +       wcmbar = get_hvwc_mmio_bar(chip->id);
> +       window_start = (uint64_t *)wcmbar + idx * VAS_WC_SIZE;
> +       nregs = VAS_WC_SIZE / sizeof(uint64_t);
> +
> +       for (reg = 0; reg < nregs; reg++) {
> +               if (!((valid_wcm_mask >> reg) & 0x1))
> +                       continue;
> +
> +               *(window_start + reg) = 0x0ULL;

Is it safe to access these MMIO registers with cached loads/stores?

> +       }
> +
> +       return 0;
> +}
> +
> +static int init_windows(struct proc_chip *chip)
> +{
> +       int i, rc;
> +
> +       for (i = 0; i < max_win_per_chip; i++) {
> +               rc = init_one_window(chip, i);
> +               if (rc)
> +                       return rc;
> +       }
> +
> +       return 0;
> +}
> +
> +static int init_one_chip(struct proc_chip *chip)
> +{
> +       if (init_wcbs(chip) || init_wcm(chip) || init_uwcm(chip))
> +               return -1;
> +
> +       reset_fir(chip);
> +
> +       if (init_north_ctl(chip))
> +               return -1;
> +
> +       if (init_rma(chip) || init_windows(chip))
> +               goto out;
> +
> +       printf("VAS: Initialized chip %d\n", chip->id);

In general we prefer using prlog() with an appropriate log level over
raw printf(),

> +       return 0;
> +
> +out:
> +       reset_north_ctl(chip);
> +       return -1;
> +}
> +
> +void init_vas()
> +{
> +       int ct;
> +       struct proc_chip *chip;
> +
> +       chip = next_chip(NULL);
> +       ct = chip->type;
> +
> +       if (ct != PROC_CHIP_P9_CUMULUS && ct != PROC_CHIP_P9_NIMBUS)
> +               return;

Can this be replaced with a proc_gen >= proc_gen_p9 check?

> +
> +       for_each_chip(chip) {
> +               if (init_one_chip(chip))
> +                       goto cleanup;

Can you report an error if we fail to initialise VAS on a given chip.
Also, if we succeed in initialising some chips how what happens to the
memory that's allocated with local_alloc(). It looks like it will be
leaked here.

> +       }
> +
> +       vas_initialized = 1;
> +       printf("VAS: Intialized\n");
> +       return;
> +
> +cleanup:
> +       /* ensure none of the chips accept paste instructions */
> +       for_each_chip(chip)
> +               reset_north_ctl(chip);
> +       return;
>  }
> --
> 2.7.4
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot


More information about the Skiboot mailing list