Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  PS3 Platform spu routines.
0004  *
0005  *  Copyright (C) 2006 Sony Computer Entertainment Inc.
0006  *  Copyright 2006 Sony Corp.
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/slab.h>
0012 #include <linux/mmzone.h>
0013 #include <linux/export.h>
0014 #include <linux/io.h>
0015 #include <linux/mm.h>
0016 
0017 #include <asm/spu.h>
0018 #include <asm/spu_priv1.h>
0019 #include <asm/lv1call.h>
0020 #include <asm/ps3.h>
0021 
0022 #include "../cell/spufs/spufs.h"
0023 #include "platform.h"
0024 
0025 /* spu_management_ops */
0026 
0027 /**
0028  * enum spe_type - Type of spe to create.
0029  * @spe_type_logical: Standard logical spe.
0030  *
0031  * For use with lv1_construct_logical_spe().  The current HV does not support
0032  * any types other than those listed.
0033  */
0034 
0035 enum spe_type {
0036     SPE_TYPE_LOGICAL = 0,
0037 };
0038 
0039 /**
0040  * struct spe_shadow - logical spe shadow register area.
0041  *
0042  * Read-only shadow of spe registers.
0043  */
0044 
0045 struct spe_shadow {
0046     u8 padding_0140[0x0140];
0047     u64 int_status_class0_RW;       /* 0x0140 */
0048     u64 int_status_class1_RW;       /* 0x0148 */
0049     u64 int_status_class2_RW;       /* 0x0150 */
0050     u8 padding_0158[0x0610-0x0158];
0051     u64 mfc_dsisr_RW;               /* 0x0610 */
0052     u8 padding_0618[0x0620-0x0618];
0053     u64 mfc_dar_RW;                 /* 0x0620 */
0054     u8 padding_0628[0x0800-0x0628];
0055     u64 mfc_dsipr_R;                /* 0x0800 */
0056     u8 padding_0808[0x0810-0x0808];
0057     u64 mfc_lscrr_R;                /* 0x0810 */
0058     u8 padding_0818[0x0c00-0x0818];
0059     u64 mfc_cer_R;                  /* 0x0c00 */
0060     u8 padding_0c08[0x0f00-0x0c08];
0061     u64 spe_execution_status;       /* 0x0f00 */
0062     u8 padding_0f08[0x1000-0x0f08];
0063 };
0064 
0065 /**
0066  * enum spe_ex_state - Logical spe execution state.
0067  * @spe_ex_state_unexecutable: Uninitialized.
0068  * @spe_ex_state_executable: Enabled, not ready.
0069  * @spe_ex_state_executed: Ready for use.
0070  *
0071  * The execution state (status) of the logical spe as reported in
0072  * struct spe_shadow:spe_execution_status.
0073  */
0074 
0075 enum spe_ex_state {
0076     SPE_EX_STATE_UNEXECUTABLE = 0,
0077     SPE_EX_STATE_EXECUTABLE = 2,
0078     SPE_EX_STATE_EXECUTED = 3,
0079 };
0080 
0081 /**
0082  * struct priv1_cache - Cached values of priv1 registers.
0083  * @masks[]: Array of cached spe interrupt masks, indexed by class.
0084  * @sr1: Cached mfc_sr1 register.
0085  * @tclass_id: Cached mfc_tclass_id register.
0086  */
0087 
0088 struct priv1_cache {
0089     u64 masks[3];
0090     u64 sr1;
0091     u64 tclass_id;
0092 };
0093 
0094 /**
0095  * struct spu_pdata - Platform state variables.
0096  * @spe_id: HV spe id returned by lv1_construct_logical_spe().
0097  * @resource_id: HV spe resource id returned by
0098  *  ps3_repository_read_spe_resource_id().
0099  * @priv2_addr: lpar address of spe priv2 area returned by
0100  *  lv1_construct_logical_spe().
0101  * @shadow_addr: lpar address of spe register shadow area returned by
0102  *  lv1_construct_logical_spe().
0103  * @shadow: Virtual (ioremap) address of spe register shadow area.
0104  * @cache: Cached values of priv1 registers.
0105  */
0106 
0107 struct spu_pdata {
0108     u64 spe_id;
0109     u64 resource_id;
0110     u64 priv2_addr;
0111     u64 shadow_addr;
0112     struct spe_shadow __iomem *shadow;
0113     struct priv1_cache cache;
0114 };
0115 
0116 static struct spu_pdata *spu_pdata(struct spu *spu)
0117 {
0118     return spu->pdata;
0119 }
0120 
0121 #define dump_areas(_a, _b, _c, _d, _e) \
0122     _dump_areas(_a, _b, _c, _d, _e, __func__, __LINE__)
0123 static void _dump_areas(unsigned int spe_id, unsigned long priv2,
0124     unsigned long problem, unsigned long ls, unsigned long shadow,
0125     const char* func, int line)
0126 {
0127     pr_debug("%s:%d: spe_id:  %xh (%u)\n", func, line, spe_id, spe_id);
0128     pr_debug("%s:%d: priv2:   %lxh\n", func, line, priv2);
0129     pr_debug("%s:%d: problem: %lxh\n", func, line, problem);
0130     pr_debug("%s:%d: ls:      %lxh\n", func, line, ls);
0131     pr_debug("%s:%d: shadow:  %lxh\n", func, line, shadow);
0132 }
0133 
0134 u64 ps3_get_spe_id(void *arg)
0135 {
0136     return spu_pdata(arg)->spe_id;
0137 }
0138 EXPORT_SYMBOL_GPL(ps3_get_spe_id);
0139 
0140 static unsigned long __init get_vas_id(void)
0141 {
0142     u64 id;
0143 
0144     lv1_get_logical_ppe_id(&id);
0145     lv1_get_virtual_address_space_id_of_ppe(&id);
0146 
0147     return id;
0148 }
0149 
0150 static int __init construct_spu(struct spu *spu)
0151 {
0152     int result;
0153     u64 unused;
0154     u64 problem_phys;
0155     u64 local_store_phys;
0156 
0157     result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT,
0158         PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL,
0159         &spu_pdata(spu)->priv2_addr, &problem_phys,
0160         &local_store_phys, &unused,
0161         &spu_pdata(spu)->shadow_addr,
0162         &spu_pdata(spu)->spe_id);
0163     spu->problem_phys = problem_phys;
0164     spu->local_store_phys = local_store_phys;
0165 
0166     if (result) {
0167         pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n",
0168             __func__, __LINE__, ps3_result(result));
0169         return result;
0170     }
0171 
0172     return result;
0173 }
0174 
0175 static void spu_unmap(struct spu *spu)
0176 {
0177     iounmap(spu->priv2);
0178     iounmap(spu->problem);
0179     iounmap((__force u8 __iomem *)spu->local_store);
0180     iounmap(spu_pdata(spu)->shadow);
0181 }
0182 
0183 /**
0184  * setup_areas - Map the spu regions into the address space.
0185  *
0186  * The current HV requires the spu shadow regs to be mapped with the
0187  * PTE page protection bits set as read-only.
0188  */
0189 
0190 static int __init setup_areas(struct spu *spu)
0191 {
0192     struct table {char* name; unsigned long addr; unsigned long size;};
0193     unsigned long shadow_flags = pgprot_val(pgprot_noncached_wc(PAGE_KERNEL_RO));
0194 
0195     spu_pdata(spu)->shadow = ioremap_prot(spu_pdata(spu)->shadow_addr,
0196                           sizeof(struct spe_shadow), shadow_flags);
0197     if (!spu_pdata(spu)->shadow) {
0198         pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__);
0199         goto fail_ioremap;
0200     }
0201 
0202     spu->local_store = (__force void *)ioremap_wc(spu->local_store_phys, LS_SIZE);
0203 
0204     if (!spu->local_store) {
0205         pr_debug("%s:%d: ioremap local_store failed\n",
0206             __func__, __LINE__);
0207         goto fail_ioremap;
0208     }
0209 
0210     spu->problem = ioremap(spu->problem_phys,
0211         sizeof(struct spu_problem));
0212 
0213     if (!spu->problem) {
0214         pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__);
0215         goto fail_ioremap;
0216     }
0217 
0218     spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr,
0219         sizeof(struct spu_priv2));
0220 
0221     if (!spu->priv2) {
0222         pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__);
0223         goto fail_ioremap;
0224     }
0225 
0226     dump_areas(spu_pdata(spu)->spe_id, spu_pdata(spu)->priv2_addr,
0227         spu->problem_phys, spu->local_store_phys,
0228         spu_pdata(spu)->shadow_addr);
0229     dump_areas(spu_pdata(spu)->spe_id, (unsigned long)spu->priv2,
0230         (unsigned long)spu->problem, (unsigned long)spu->local_store,
0231         (unsigned long)spu_pdata(spu)->shadow);
0232 
0233     return 0;
0234 
0235 fail_ioremap:
0236     spu_unmap(spu);
0237 
0238     return -ENOMEM;
0239 }
0240 
0241 static int __init setup_interrupts(struct spu *spu)
0242 {
0243     int result;
0244 
0245     result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
0246         0, &spu->irqs[0]);
0247 
0248     if (result)
0249         goto fail_alloc_0;
0250 
0251     result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
0252         1, &spu->irqs[1]);
0253 
0254     if (result)
0255         goto fail_alloc_1;
0256 
0257     result = ps3_spe_irq_setup(PS3_BINDING_CPU_ANY, spu_pdata(spu)->spe_id,
0258         2, &spu->irqs[2]);
0259 
0260     if (result)
0261         goto fail_alloc_2;
0262 
0263     return result;
0264 
0265 fail_alloc_2:
0266     ps3_spe_irq_destroy(spu->irqs[1]);
0267 fail_alloc_1:
0268     ps3_spe_irq_destroy(spu->irqs[0]);
0269 fail_alloc_0:
0270     spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = 0;
0271     return result;
0272 }
0273 
0274 static int __init enable_spu(struct spu *spu)
0275 {
0276     int result;
0277 
0278     result = lv1_enable_logical_spe(spu_pdata(spu)->spe_id,
0279         spu_pdata(spu)->resource_id);
0280 
0281     if (result) {
0282         pr_debug("%s:%d: lv1_enable_logical_spe failed: %s\n",
0283             __func__, __LINE__, ps3_result(result));
0284         goto fail_enable;
0285     }
0286 
0287     result = setup_areas(spu);
0288 
0289     if (result)
0290         goto fail_areas;
0291 
0292     result = setup_interrupts(spu);
0293 
0294     if (result)
0295         goto fail_interrupts;
0296 
0297     return 0;
0298 
0299 fail_interrupts:
0300     spu_unmap(spu);
0301 fail_areas:
0302     lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
0303 fail_enable:
0304     return result;
0305 }
0306 
0307 static int ps3_destroy_spu(struct spu *spu)
0308 {
0309     int result;
0310 
0311     pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
0312 
0313     result = lv1_disable_logical_spe(spu_pdata(spu)->spe_id, 0);
0314     BUG_ON(result);
0315 
0316     ps3_spe_irq_destroy(spu->irqs[2]);
0317     ps3_spe_irq_destroy(spu->irqs[1]);
0318     ps3_spe_irq_destroy(spu->irqs[0]);
0319 
0320     spu->irqs[0] = spu->irqs[1] = spu->irqs[2] = 0;
0321 
0322     spu_unmap(spu);
0323 
0324     result = lv1_destruct_logical_spe(spu_pdata(spu)->spe_id);
0325     BUG_ON(result);
0326 
0327     kfree(spu->pdata);
0328     spu->pdata = NULL;
0329 
0330     return 0;
0331 }
0332 
0333 static int __init ps3_create_spu(struct spu *spu, void *data)
0334 {
0335     int result;
0336 
0337     pr_debug("%s:%d spu_%d\n", __func__, __LINE__, spu->number);
0338 
0339     spu->pdata = kzalloc(sizeof(struct spu_pdata),
0340         GFP_KERNEL);
0341 
0342     if (!spu->pdata) {
0343         result = -ENOMEM;
0344         goto fail_malloc;
0345     }
0346 
0347     spu_pdata(spu)->resource_id = (unsigned long)data;
0348 
0349     /* Init cached reg values to HV defaults. */
0350 
0351     spu_pdata(spu)->cache.sr1 = 0x33;
0352 
0353     result = construct_spu(spu);
0354 
0355     if (result)
0356         goto fail_construct;
0357 
0358     /* For now, just go ahead and enable it. */
0359 
0360     result = enable_spu(spu);
0361 
0362     if (result)
0363         goto fail_enable;
0364 
0365     /* Make sure the spu is in SPE_EX_STATE_EXECUTED. */
0366 
0367     /* need something better here!!! */
0368     while (in_be64(&spu_pdata(spu)->shadow->spe_execution_status)
0369         != SPE_EX_STATE_EXECUTED)
0370         (void)0;
0371 
0372     return result;
0373 
0374 fail_enable:
0375 fail_construct:
0376     ps3_destroy_spu(spu);
0377 fail_malloc:
0378     return result;
0379 }
0380 
0381 static int __init ps3_enumerate_spus(int (*fn)(void *data))
0382 {
0383     int result;
0384     unsigned int num_resource_id;
0385     unsigned int i;
0386 
0387     result = ps3_repository_read_num_spu_resource_id(&num_resource_id);
0388 
0389     pr_debug("%s:%d: num_resource_id %u\n", __func__, __LINE__,
0390         num_resource_id);
0391 
0392     /*
0393      * For now, just create logical spus equal to the number
0394      * of physical spus reserved for the partition.
0395      */
0396 
0397     for (i = 0; i < num_resource_id; i++) {
0398         enum ps3_spu_resource_type resource_type;
0399         unsigned int resource_id;
0400 
0401         result = ps3_repository_read_spu_resource_id(i,
0402             &resource_type, &resource_id);
0403 
0404         if (result)
0405             break;
0406 
0407         if (resource_type == PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) {
0408             result = fn((void*)(unsigned long)resource_id);
0409 
0410             if (result)
0411                 break;
0412         }
0413     }
0414 
0415     if (result) {
0416         printk(KERN_WARNING "%s:%d: Error initializing spus\n",
0417             __func__, __LINE__);
0418         return result;
0419     }
0420 
0421     return num_resource_id;
0422 }
0423 
0424 static int ps3_init_affinity(void)
0425 {
0426     return 0;
0427 }
0428 
0429 /**
0430  * ps3_enable_spu - Enable SPU run control.
0431  *
0432  * An outstanding enhancement for the PS3 would be to add a guard to check
0433  * for incorrect access to the spu problem state when the spu context is
0434  * disabled.  This check could be implemented with a flag added to the spu
0435  * context that would inhibit mapping problem state pages, and a routine
0436  * to unmap spu problem state pages.  When the spu is enabled with
0437  * ps3_enable_spu() the flag would be set allowing pages to be mapped,
0438  * and when the spu is disabled with ps3_disable_spu() the flag would be
0439  * cleared and the mapped problem state pages would be unmapped.
0440  */
0441 
0442 static void ps3_enable_spu(struct spu_context *ctx)
0443 {
0444 }
0445 
0446 static void ps3_disable_spu(struct spu_context *ctx)
0447 {
0448     ctx->ops->runcntl_stop(ctx);
0449 }
0450 
0451 static const struct spu_management_ops spu_management_ps3_ops = {
0452     .enumerate_spus = ps3_enumerate_spus,
0453     .create_spu = ps3_create_spu,
0454     .destroy_spu = ps3_destroy_spu,
0455     .enable_spu = ps3_enable_spu,
0456     .disable_spu = ps3_disable_spu,
0457     .init_affinity = ps3_init_affinity,
0458 };
0459 
0460 /* spu_priv1_ops */
0461 
0462 static void int_mask_and(struct spu *spu, int class, u64 mask)
0463 {
0464     u64 old_mask;
0465 
0466     /* are these serialized by caller??? */
0467     old_mask = spu_int_mask_get(spu, class);
0468     spu_int_mask_set(spu, class, old_mask & mask);
0469 }
0470 
0471 static void int_mask_or(struct spu *spu, int class, u64 mask)
0472 {
0473     u64 old_mask;
0474 
0475     old_mask = spu_int_mask_get(spu, class);
0476     spu_int_mask_set(spu, class, old_mask | mask);
0477 }
0478 
0479 static void int_mask_set(struct spu *spu, int class, u64 mask)
0480 {
0481     spu_pdata(spu)->cache.masks[class] = mask;
0482     lv1_set_spe_interrupt_mask(spu_pdata(spu)->spe_id, class,
0483         spu_pdata(spu)->cache.masks[class]);
0484 }
0485 
0486 static u64 int_mask_get(struct spu *spu, int class)
0487 {
0488     return spu_pdata(spu)->cache.masks[class];
0489 }
0490 
0491 static void int_stat_clear(struct spu *spu, int class, u64 stat)
0492 {
0493     /* Note that MFC_DSISR will be cleared when class1[MF] is set. */
0494 
0495     lv1_clear_spe_interrupt_status(spu_pdata(spu)->spe_id, class,
0496         stat, 0);
0497 }
0498 
0499 static u64 int_stat_get(struct spu *spu, int class)
0500 {
0501     u64 stat;
0502 
0503     lv1_get_spe_interrupt_status(spu_pdata(spu)->spe_id, class, &stat);
0504     return stat;
0505 }
0506 
0507 static void cpu_affinity_set(struct spu *spu, int cpu)
0508 {
0509     /* No support. */
0510 }
0511 
0512 static u64 mfc_dar_get(struct spu *spu)
0513 {
0514     return in_be64(&spu_pdata(spu)->shadow->mfc_dar_RW);
0515 }
0516 
0517 static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
0518 {
0519     /* Nothing to do, cleared in int_stat_clear(). */
0520 }
0521 
0522 static u64 mfc_dsisr_get(struct spu *spu)
0523 {
0524     return in_be64(&spu_pdata(spu)->shadow->mfc_dsisr_RW);
0525 }
0526 
0527 static void mfc_sdr_setup(struct spu *spu)
0528 {
0529     /* Nothing to do. */
0530 }
0531 
0532 static void mfc_sr1_set(struct spu *spu, u64 sr1)
0533 {
0534     /* Check bits allowed by HV. */
0535 
0536     static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
0537         | MFC_STATE1_PROBLEM_STATE_MASK);
0538 
0539     BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
0540 
0541     spu_pdata(spu)->cache.sr1 = sr1;
0542     lv1_set_spe_privilege_state_area_1_register(
0543         spu_pdata(spu)->spe_id,
0544         offsetof(struct spu_priv1, mfc_sr1_RW),
0545         spu_pdata(spu)->cache.sr1);
0546 }
0547 
0548 static u64 mfc_sr1_get(struct spu *spu)
0549 {
0550     return spu_pdata(spu)->cache.sr1;
0551 }
0552 
0553 static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
0554 {
0555     spu_pdata(spu)->cache.tclass_id = tclass_id;
0556     lv1_set_spe_privilege_state_area_1_register(
0557         spu_pdata(spu)->spe_id,
0558         offsetof(struct spu_priv1, mfc_tclass_id_RW),
0559         spu_pdata(spu)->cache.tclass_id);
0560 }
0561 
0562 static u64 mfc_tclass_id_get(struct spu *spu)
0563 {
0564     return spu_pdata(spu)->cache.tclass_id;
0565 }
0566 
0567 static void tlb_invalidate(struct spu *spu)
0568 {
0569     /* Nothing to do. */
0570 }
0571 
0572 static void resource_allocation_groupID_set(struct spu *spu, u64 id)
0573 {
0574     /* No support. */
0575 }
0576 
0577 static u64 resource_allocation_groupID_get(struct spu *spu)
0578 {
0579     return 0; /* No support. */
0580 }
0581 
0582 static void resource_allocation_enable_set(struct spu *spu, u64 enable)
0583 {
0584     /* No support. */
0585 }
0586 
0587 static u64 resource_allocation_enable_get(struct spu *spu)
0588 {
0589     return 0; /* No support. */
0590 }
0591 
0592 static const struct spu_priv1_ops spu_priv1_ps3_ops = {
0593     .int_mask_and = int_mask_and,
0594     .int_mask_or = int_mask_or,
0595     .int_mask_set = int_mask_set,
0596     .int_mask_get = int_mask_get,
0597     .int_stat_clear = int_stat_clear,
0598     .int_stat_get = int_stat_get,
0599     .cpu_affinity_set = cpu_affinity_set,
0600     .mfc_dar_get = mfc_dar_get,
0601     .mfc_dsisr_set = mfc_dsisr_set,
0602     .mfc_dsisr_get = mfc_dsisr_get,
0603     .mfc_sdr_setup = mfc_sdr_setup,
0604     .mfc_sr1_set = mfc_sr1_set,
0605     .mfc_sr1_get = mfc_sr1_get,
0606     .mfc_tclass_id_set = mfc_tclass_id_set,
0607     .mfc_tclass_id_get = mfc_tclass_id_get,
0608     .tlb_invalidate = tlb_invalidate,
0609     .resource_allocation_groupID_set = resource_allocation_groupID_set,
0610     .resource_allocation_groupID_get = resource_allocation_groupID_get,
0611     .resource_allocation_enable_set = resource_allocation_enable_set,
0612     .resource_allocation_enable_get = resource_allocation_enable_get,
0613 };
0614 
0615 void ps3_spu_set_platform(void)
0616 {
0617     spu_priv1_ops = &spu_priv1_ps3_ops;
0618     spu_management_ops = &spu_management_ps3_ops;
0619 }