root/arch/powerpc/platforms/ps3/spu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _dump_areas
  2. ps3_get_spe_id
  3. get_vas_id
  4. construct_spu
  5. spu_unmap
  6. setup_areas
  7. setup_interrupts
  8. enable_spu
  9. ps3_destroy_spu
  10. ps3_create_spu
  11. ps3_enumerate_spus
  12. ps3_init_affinity
  13. ps3_enable_spu
  14. ps3_disable_spu
  15. int_mask_and
  16. int_mask_or
  17. int_mask_set
  18. int_mask_get
  19. int_stat_clear
  20. int_stat_get
  21. cpu_affinity_set
  22. mfc_dar_get
  23. mfc_dsisr_set
  24. mfc_dsisr_get
  25. mfc_sdr_setup
  26. mfc_sr1_set
  27. mfc_sr1_get
  28. mfc_tclass_id_set
  29. mfc_tclass_id_get
  30. tlb_invalidate
  31. resource_allocation_groupID_set
  32. resource_allocation_groupID_get
  33. resource_allocation_enable_set
  34. resource_allocation_enable_get
  35. ps3_spu_set_platform

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  PS3 Platform spu routines.
   4  *
   5  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
   6  *  Copyright 2006 Sony Corp.
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/init.h>
  11 #include <linux/slab.h>
  12 #include <linux/mmzone.h>
  13 #include <linux/export.h>
  14 #include <linux/io.h>
  15 #include <linux/mm.h>
  16 
  17 #include <asm/spu.h>
  18 #include <asm/spu_priv1.h>
  19 #include <asm/lv1call.h>
  20 #include <asm/ps3.h>
  21 
  22 #include "../cell/spufs/spufs.h"
  23 #include "platform.h"
  24 
  25 /* spu_management_ops */
  26 
  27 /**
  28  * enum spe_type - Type of spe to create.
  29  * @spe_type_logical: Standard logical spe.
  30  *
  31  * For use with lv1_construct_logical_spe().  The current HV does not support
  32  * any types other than those listed.
  33  */
  34 
  35 enum spe_type {
  36         SPE_TYPE_LOGICAL = 0,
  37 };
  38 
  39 /**
  40  * struct spe_shadow - logical spe shadow register area.
  41  *
  42  * Read-only shadow of spe registers.
  43  */
  44 
  45 struct spe_shadow {
  46         u8 padding_0140[0x0140];
  47         u64 int_status_class0_RW;       /* 0x0140 */
  48         u64 int_status_class1_RW;       /* 0x0148 */
  49         u64 int_status_class2_RW;       /* 0x0150 */
  50         u8 padding_0158[0x0610-0x0158];
  51         u64 mfc_dsisr_RW;               /* 0x0610 */
  52         u8 padding_0618[0x0620-0x0618];
  53         u64 mfc_dar_RW;                 /* 0x0620 */
  54         u8 padding_0628[0x0800-0x0628];
  55         u64 mfc_dsipr_R;                /* 0x0800 */
  56         u8 padding_0808[0x0810-0x0808];
  57         u64 mfc_lscrr_R;                /* 0x0810 */
  58         u8 padding_0818[0x0c00-0x0818];
  59         u64 mfc_cer_R;                  /* 0x0c00 */
  60         u8 padding_0c08[0x0f00-0x0c08];
  61         u64 spe_execution_status;       /* 0x0f00 */
  62         u8 padding_0f08[0x1000-0x0f08];
  63 };
  64 
  65 /**
  66  * enum spe_ex_state - Logical spe execution state.
  67  * @spe_ex_state_unexecutable: Uninitialized.
  68  * @spe_ex_state_executable: Enabled, not ready.
  69  * @spe_ex_state_executed: Ready for use.
  70  *
  71  * The execution state (status) of the logical spe as reported in
  72  * struct spe_shadow:spe_execution_status.
  73  */
  74 
  75 enum spe_ex_state {
  76         SPE_EX_STATE_UNEXECUTABLE = 0,
  77         SPE_EX_STATE_EXECUTABLE = 2,
  78         SPE_EX_STATE_EXECUTED = 3,
  79 };
  80 
  81 /**
  82  * struct priv1_cache - Cached values of priv1 registers.
  83  * @masks[]: Array of cached spe interrupt masks, indexed by class.
  84  * @sr1: Cached mfc_sr1 register.
  85  * @tclass_id: Cached mfc_tclass_id register.
  86  */
  87 
  88 struct priv1_cache {
  89         u64 masks[3];
  90         u64 sr1;
  91         u64 tclass_id;
  92 };
  93 
  94 /**
  95  * struct spu_pdata - Platform state variables.
  96  * @spe_id: HV spe id returned by lv1_construct_logical_spe().
  97  * @resource_id: HV spe resource id returned by
  98  *      ps3_repository_read_spe_resource_id().
  99  * @priv2_addr: lpar address of spe priv2 area returned by
 100  *      lv1_construct_logical_spe().
 101  * @shadow_addr: lpar address of spe register shadow area returned by
 102  *      lv1_construct_logical_spe().
 103  * @shadow: Virtual (ioremap) address of spe register shadow area.
 104  * @cache: Cached values of priv1 registers.
 105  */
 106 
 107 struct spu_pdata {
 108         u64 spe_id;
 109         u64 resource_id;
 110         u64 priv2_addr;
 111         u64 shadow_addr;
 112         struct spe_shadow __iomem *shadow;
 113         struct priv1_cache cache;
 114 };
 115 
 116 static struct spu_pdata *spu_pdata(struct spu *spu)
 117 {
 118         return spu->pdata;
 119 }
 120 
 121 #define dump_areas(_a, _b, _c, _d, _e) \
 122         _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__)
 123 static void _dump_areas(unsigned int spe_id, unsigned long priv2,
 124         unsigned long problem, unsigned long ls, unsigned long shadow,
 125         const char* func, int line)
 126 {
 127         pr_debug("%s:%d: spe_id:  %xh (%u)\n", func, line, spe_id, spe_id);
 128         pr_debug("%s:%d: priv2:   %lxh\n", func, line, priv2);
 129         pr_debug("%s:%d: problem: %lxh\n", func, line, problem);
 130         pr_debug("%s:%d: ls:      %lxh\n", func, line, ls);
 131         pr_debug("%s:%d: shadow:  %lxh\n", func, line, shadow);
 132 }
 133 
 134 u64 ps3_get_spe_id(void *arg)
 135 {
 136         return spu_pdata(arg)->spe_id;
 137 }
 138 EXPORT_SYMBOL_GPL(ps3_get_spe_id);
 139 
 140 static unsigned long get_vas_id(void)
 141 {
 142         u64 id;
 143 
 144         lv1_get_logical_ppe_id(&id);
 145         lv1_get_virtual_address_space_id_of_ppe(&id);
 146 
 147         return id;
 148 }
 149 
 150 static int __init construct_spu(struct spu *spu)
 151 {
 152         int result;
 153         u64 unused;
 154         u64 problem_phys;
 155         u64 local_store_phys;
 156 
 157         result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT,
 158                 PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL,
 159                 &spu_pdata(spu)->priv2_addr, &problem_phys,
 160                 &local_store_phys, &unused,
 161                 &spu_pdata(spu)->shadow_addr,
 162                 &spu_pdata(spu)->spe_id);
 163         spu->problem_phys = problem_phys;
 164         spu->local_store_phys = local_store_phys;
 165 
 166         if (result) {
 167                 pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n",
 168                         __func__, __LINE__, ps3_result(result));
 169                 return result;
 170         }
 171 
 172         return result;
 173 }
 174 
 175 static void spu_unmap(struct spu *spu)
 176 {
 177         iounmap(spu->priv2);
 178         iounmap(spu->problem);
 179         iounmap((__force u8 __iomem *)spu->local_store);
 180         iounmap(spu_pdata(spu)->shadow);
 181 }
 182 
 183 /**
 184  * setup_areas - Map the spu regions into the address space.
 185  *
 186  * The current HV requires the spu shadow regs to be mapped with the
 187  * PTE page protection bits set as read-only.
 188  */
 189 
 190 static int __init setup_areas(struct spu *spu)
 191 {
 192         struct table {char* name; unsigned long addr; unsigned long size;};
 193         unsigned long shadow_flags = pgprot_val(pgprot_noncached_wc(PAGE_KERNEL_RO));
 194 
 195         spu_pdata(spu)->shadow = ioremap_prot(spu_pdata(spu)->shadow_addr,
 196                                               sizeof(struct spe_shadow), shadow_flags);
 197         if (!spu_pdata(spu)->shadow) {
 198                 pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
 199                 goto fail_ioremap;
 200         }
 201 
 202         spu->local_store = (__force void *)ioremap_wc(spu->local_store_phys, LS_SIZE);
 203 
 204         if (!spu->local_store) {
 205                 pr_debug("%s:%d: ioremap local_store failed\n",
 206                         __func__, __LINE__);
 207                 goto fail_ioremap;
 208         }
 209 
 210         spu->problem = ioremap(spu->problem_phys,
 211                 sizeof(struct spu_problem));
 212 
 213         if (!spu->problem) {
 214                 pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
 215                 goto fail_ioremap;
 216         }
 217 
 218         spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
 219                 sizeof(struct spu_priv2));
 220 
 221         if (!spu->priv2) {
 222                 pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
 223                 goto fail_ioremap;
 224         }
 225 
 226         dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr,
 227                 spu->problem_phys, spu->local_store_phys,
 228                 spu_pdata(spu)->shadow_addr);
 229         dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2,
 230                 (unsigned long)spu->problem, (unsigned long)spu->local_store,
 231                 (unsigned long)spu_pdata(spu)->shadow);
 232 
 233         return 0;
 234 
 235 fail_ioremap:
 236         spu_unmap(spu);
 237 
 238         return -ENOMEM;
 239 }
 240 
 241 static int __init setup_interrupts(struct spu *spu)
 242 {
 243         int result;
 244 
 245         result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
 246                 0, &spu->irqs[0]);
 247 
 248         if (result)
 249                 goto fail_alloc_0;
 250 
 251         result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
 252                 1, &spu->irqs[1]);
 253 
 254         if (result)
 255                 goto fail_alloc_1;
 256 
 257         result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
 258                 2, &spu->irqs[2]);
 259 
 260         if (result)
 261                 goto fail_alloc_2;
 262 
 263         return result;
 264 
 265 fail_alloc_2:
 266         ps3_spe_irq_destroy(spu->irqs[1]);
 267 fail_alloc_1:
 268         ps3_spe_irq_destroy(spu->irqs[0]);
 269 fail_alloc_0:
 270         spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = 0;
 271         return result;
 272 }
 273 
 274 static int __init enable_spu(struct spu *spu)
 275 {
 276         int result;
 277 
 278         result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id,
 279                 spu_pdata(spu)->resource_id);
 280 
 281         if (result) {
 282                 pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n",
 283                         __func__, __LINE__, ps3_result(result));
 284                 goto fail_enable;
 285         }
 286 
 287         result = setup_areas(spu);
 288 
 289         if (result)
 290                 goto fail_areas;
 291 
 292         result = setup_interrupts(spu);
 293 
 294         if (result)
 295                 goto fail_interrupts;
 296 
 297         return 0;
 298 
 299 fail_interrupts:
 300         spu_unmap(spu);
 301 fail_areas:
 302         lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
 303 fail_enable:
 304         return result;
 305 }
 306 
 307 static int ps3_destroy_spu(struct spu *spu)
 308 {
 309         int result;
 310 
 311         pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
 312 
 313         result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
 314         BUG_ON(result);
 315 
 316         ps3_spe_irq_destroy(spu->irqs[2]);
 317         ps3_spe_irq_destroy(spu->irqs[1]);
 318         ps3_spe_irq_destroy(spu->irqs[0]);
 319 
 320         spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = 0;
 321 
 322         spu_unmap(spu);
 323 
 324         result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id);
 325         BUG_ON(result);
 326 
 327         kfree(spu->pdata);
 328         spu->pdata = NULL;
 329 
 330         return 0;
 331 }
 332 
 333 static int __init ps3_create_spu(struct spu *spu, void *data)
 334 {
 335         int result;
 336 
 337         pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
 338 
 339         spu->pdata = kzalloc(sizeof(struct spu_pdata),
 340                 GFP_KERNEL);
 341 
 342         if (!spu->pdata) {
 343                 result = -ENOMEM;
 344                 goto fail_malloc;
 345         }
 346 
 347         spu_pdata(spu)->resource_id = (unsigned long)data;
 348 
 349         /* Init cached reg values to HV defaults. */
 350 
 351         spu_pdata(spu)->cache.sr1 = 0x33;
 352 
 353         result = construct_spu(spu);
 354 
 355         if (result)
 356                 goto fail_construct;
 357 
 358         /* For now, just go ahead and enable it. */
 359 
 360         result = enable_spu(spu);
 361 
 362         if (result)
 363                 goto fail_enable;
 364 
 365         /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */
 366 
 367         /* need something better here!!! */
 368         while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status)
 369                 != SPE_EX_STATE_EXECUTED)
 370                 (void)0;
 371 
 372         return result;
 373 
 374 fail_enable:
 375 fail_construct:
 376         ps3_destroy_spu(spu);
 377 fail_malloc:
 378         return result;
 379 }
 380 
 381 static int __init ps3_enumerate_spus(int (*fn)(void *data))
 382 {
 383         int result;
 384         unsigned int num_resource_id;
 385         unsigned int i;
 386 
 387         result = ps3_repository_read_num_spu_resource_id(&num_resource_id);
 388 
 389         pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__,
 390                 num_resource_id);
 391 
 392         /*
 393          * For now, just create logical spus equal to the number
 394          * of physical spus reserved for the partition.
 395          */
 396 
 397         for (i = 0; i < num_resource_id; i++) {
 398                 enum ps3_spu_resource_type resource_type;
 399                 unsigned int resource_id;
 400 
 401                 result = ps3_repository_read_spu_resource_id(i,
 402                         &resource_type, &resource_id);
 403 
 404                 if (result)
 405                         break;
 406 
 407                 if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) {
 408                         result = fn((void*)(unsigned long)resource_id);
 409 
 410                         if (result)
 411                                 break;
 412                 }
 413         }
 414 
 415         if (result) {
 416                 printk(KERN_WARNING "%s:%d: Error initializing spus\n",
 417                         __func__, __LINE__);
 418                 return result;
 419         }
 420 
 421         return num_resource_id;
 422 }
 423 
 424 static int ps3_init_affinity(void)
 425 {
 426         return 0;
 427 }
 428 
 429 /**
 430  * ps3_enable_spu - Enable SPU run control.
 431  *
 432  * An outstanding enhancement for the PS3 would be to add a guard to check
 433  * for incorrect access to the spu problem state when the spu context is
 434  * disabled.  This check could be implemented with a flag added to the spu
 435  * context that would inhibit mapping problem state pages, and a routine
 436  * to unmap spu problem state pages.  When the spu is enabled with
 437  * ps3_enable_spu() the flag would be set allowing pages to be mapped,
 438  * and when the spu is disabled with ps3_disable_spu() the flag would be
 439  * cleared and the mapped problem state pages would be unmapped.
 440  */
 441 
 442 static void ps3_enable_spu(struct spu_context *ctx)
 443 {
 444 }
 445 
 446 static void ps3_disable_spu(struct spu_context *ctx)
 447 {
 448         ctx->ops->runcntl_stop(ctx);
 449 }
 450 
 451 const struct spu_management_ops spu_management_ps3_ops = {
 452         .enumerate_spus = ps3_enumerate_spus,
 453         .create_spu = ps3_create_spu,
 454         .destroy_spu = ps3_destroy_spu,
 455         .enable_spu = ps3_enable_spu,
 456         .disable_spu = ps3_disable_spu,
 457         .init_affinity = ps3_init_affinity,
 458 };
 459 
 460 /* spu_priv1_ops */
 461 
 462 static void int_mask_and(struct spu *spu, int class, u64 mask)
 463 {
 464         u64 old_mask;
 465 
 466         /* are these serialized by caller??? */
 467         old_mask = spu_int_mask_get(spu, class);
 468         spu_int_mask_set(spu, class, old_mask & mask);
 469 }
 470 
 471 static void int_mask_or(struct spu *spu, int class, u64 mask)
 472 {
 473         u64 old_mask;
 474 
 475         old_mask = spu_int_mask_get(spu, class);
 476         spu_int_mask_set(spu, class, old_mask | mask);
 477 }
 478 
 479 static void int_mask_set(struct spu *spu, int class, u64 mask)
 480 {
 481         spu_pdata(spu)->cache.masks[class] = mask;
 482         lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class,
 483                 spu_pdata(spu)->cache.masks[class]);
 484 }
 485 
 486 static u64 int_mask_get(struct spu *spu, int class)
 487 {
 488         return spu_pdata(spu)->cache.masks[class];
 489 }
 490 
 491 static void int_stat_clear(struct spu *spu, int class, u64 stat)
 492 {
 493         /* Note that MFC_DSISR will be cleared when class1[MF] is set. */
 494 
 495         lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class,
 496                 stat, 0);
 497 }
 498 
 499 static u64 int_stat_get(struct spu *spu, int class)
 500 {
 501         u64 stat;
 502 
 503         lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat);
 504         return stat;
 505 }
 506 
 507 static void cpu_affinity_set(struct spu *spu, int cpu)
 508 {
 509         /* No support. */
 510 }
 511 
 512 static u64 mfc_dar_get(struct spu *spu)
 513 {
 514         return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW);
 515 }
 516 
 517 static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
 518 {
 519         /* Nothing to do, cleared in int_stat_clear(). */
 520 }
 521 
 522 static u64 mfc_dsisr_get(struct spu *spu)
 523 {
 524         return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW);
 525 }
 526 
 527 static void mfc_sdr_setup(struct spu *spu)
 528 {
 529         /* Nothing to do. */
 530 }
 531 
 532 static void mfc_sr1_set(struct spu *spu, u64 sr1)
 533 {
 534         /* Check bits allowed by HV. */
 535 
 536         static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
 537                 | MFC_STATE1_PROBLEM_STATE_MASK);
 538 
 539         BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
 540 
 541         spu_pdata(spu)->cache.sr1 = sr1;
 542         lv1_set_spe_privilege_state_area_1_register(
 543                 spu_pdata(spu)->spe_id,
 544                 offsetof(struct spu_priv1, mfc_sr1_RW),
 545                 spu_pdata(spu)->cache.sr1);
 546 }
 547 
 548 static u64 mfc_sr1_get(struct spu *spu)
 549 {
 550         return spu_pdata(spu)->cache.sr1;
 551 }
 552 
 553 static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
 554 {
 555         spu_pdata(spu)->cache.tclass_id = tclass_id;
 556         lv1_set_spe_privilege_state_area_1_register(
 557                 spu_pdata(spu)->spe_id,
 558                 offsetof(struct spu_priv1, mfc_tclass_id_RW),
 559                 spu_pdata(spu)->cache.tclass_id);
 560 }
 561 
 562 static u64 mfc_tclass_id_get(struct spu *spu)
 563 {
 564         return spu_pdata(spu)->cache.tclass_id;
 565 }
 566 
 567 static void tlb_invalidate(struct spu *spu)
 568 {
 569         /* Nothing to do. */
 570 }
 571 
 572 static void resource_allocation_groupID_set(struct spu *spu, u64 id)
 573 {
 574         /* No support. */
 575 }
 576 
 577 static u64 resource_allocation_groupID_get(struct spu *spu)
 578 {
 579         return 0; /* No support. */
 580 }
 581 
 582 static void resource_allocation_enable_set(struct spu *spu, u64 enable)
 583 {
 584         /* No support. */
 585 }
 586 
 587 static u64 resource_allocation_enable_get(struct spu *spu)
 588 {
 589         return 0; /* No support. */
 590 }
 591 
 592 const struct spu_priv1_ops spu_priv1_ps3_ops = {
 593         .int_mask_and = int_mask_and,
 594         .int_mask_or = int_mask_or,
 595         .int_mask_set = int_mask_set,
 596         .int_mask_get = int_mask_get,
 597         .int_stat_clear = int_stat_clear,
 598         .int_stat_get = int_stat_get,
 599         .cpu_affinity_set = cpu_affinity_set,
 600         .mfc_dar_get = mfc_dar_get,
 601         .mfc_dsisr_set = mfc_dsisr_set,
 602         .mfc_dsisr_get = mfc_dsisr_get,
 603         .mfc_sdr_setup = mfc_sdr_setup,
 604         .mfc_sr1_set = mfc_sr1_set,
 605         .mfc_sr1_get = mfc_sr1_get,
 606         .mfc_tclass_id_set = mfc_tclass_id_set,
 607         .mfc_tclass_id_get = mfc_tclass_id_get,
 608         .tlb_invalidate = tlb_invalidate,
 609         .resource_allocation_groupID_set = resource_allocation_groupID_set,
 610         .resource_allocation_groupID_get = resource_allocation_groupID_get,
 611         .resource_allocation_enable_set = resource_allocation_enable_set,
 612         .resource_allocation_enable_get = resource_allocation_enable_get,
 613 };
 614 
 615 void ps3_spu_set_platform(void)
 616 {
 617         spu_priv1_ops = &spu_priv1_ps3_ops;
 618         spu_management_ops = &spu_management_ps3_ops;
 619 }

/* [<][>][^][v][top][bottom][index][help] */