void ps3_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, struct mem_region *avail_regions, int *availsz) { uint64_t lpar_id, junk, ppe_id; /* Get real mode memory region */ avail_regions[0].mr_start = 0; lv1_get_logical_partition_id(&lpar_id); lv1_get_logical_ppe_id(&ppe_id); lv1_get_repository_node_value(lpar_id, lv1_repository_string("bi") >> 32, lv1_repository_string("pu"), ppe_id, lv1_repository_string("rm_size"), &avail_regions[0].mr_size, &junk); /* Now get extended memory region */ lv1_get_repository_node_value(lpar_id, lv1_repository_string("bi") >> 32, lv1_repository_string("rgntotal"), 0, 0, &avail_regions[1].mr_size, &junk); /* Convert to maximum amount we can allocate in 16 MB pages */ avail_regions[1].mr_size -= avail_regions[0].mr_size; avail_regions[1].mr_size -= avail_regions[1].mr_size % (16*1024*1024); *availsz = 2; if (phys != NULL) { memcpy(phys, avail_regions, sizeof(*phys)*2); *physsz = 2; } }
static int ps3_attach(platform_t plat) { uint64_t lpar_id, junk, ppe_id; /* Get real mode memory region */ avail_regions[0].mr_start = 0; lv1_get_logical_partition_id(&lpar_id); lv1_get_logical_ppe_id(&ppe_id); lv1_get_repository_node_value(lpar_id, lv1_repository_string("bi") >> 32, lv1_repository_string("pu"), ppe_id, lv1_repository_string("rm_size"), &avail_regions[0].mr_size, &junk); /* Now get extended memory region */ lv1_get_repository_node_value(lpar_id, lv1_repository_string("bi") >> 32, lv1_repository_string("rgntotal"), 0, 0, &avail_regions[1].mr_size, &junk); /* Convert to maximum amount we can allocate in 16 MB pages */ avail_regions[1].mr_size -= avail_regions[0].mr_size; avail_regions[1].mr_size -= avail_regions[1].mr_size % (16*1024*1024); lv1_allocate_memory(avail_regions[1].mr_size, 24 /* 16 MB pages */, 0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk); pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC); cpu_idle_hook = ps3_cpu_idle; /* Set a breakpoint to make NULL an invalid address */ lv1_set_dabr(0x7 /* read and write, MMU on */, 2 /* kernel accesses */); return (0); }
static unsigned long get_vas_id(void) { unsigned long id; lv1_get_logical_ppe_id(&id); lv1_get_virtual_address_space_id_of_ppe(id, &id); return id; }
static void ps3pic_eoi(device_t dev, u_int irq) { uint64_t ppe; int thread; lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); lv1_end_of_interrupt_ext(ppe, thread, irq); }
int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) { int result; u64 ppe_id; lv1_get_logical_ppe_id(&ppe_id); *rm_base = 0; result = ps3_repository_read_rm_size(ppe_id, rm_size); return result ? result : ps3_repository_read_region_total(region_total); }
static void ps3pic_unmask(device_t dev, u_int irq) { struct ps3pic_softc *sc; uint64_t ppe; sc = device_get_softc(dev); atomic_set_64(&sc->mask_thread0[0], 1UL << (63 - irq)); atomic_set_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); lv1_did_update_interrupt_mask(ppe, 1); }
static void ps3pic_mask(device_t dev, u_int irq) { struct ps3pic_softc *sc; uint64_t ppe; sc = device_get_softc(dev); /* Do not mask IPIs! */ if (irq == sc->sc_ipi_outlet[0]) return; atomic_clear_64(&sc->mask_thread0[0], 1UL << (63 - irq)); atomic_clear_64(&sc->mask_thread1[0], 1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); lv1_did_update_interrupt_mask(ppe, 1); }
static int ps3_repository_read_rm_size(u64 *rm_size) { s64 result; u64 lpar_id; u64 ppe_id; u64 v2; result = lv1_get_logical_partition_id(&lpar_id); if (result) return -1; result = lv1_get_logical_ppe_id(&ppe_id); if (result) return -1; /* * n1: 0000000062690000 : ....bi.. * n2: 7075000000000000 : pu...... * n3: 0000000000000001 : ........ * n4: 726d5f73697a6500 : rm_size. */ result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL, 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size, &v2); printf("%s:%d: ppe_id %lu \n", __func__, __LINE__, (unsigned long)ppe_id); printf("%s:%d: lpar_id %lu \n", __func__, __LINE__, (unsigned long)lpar_id); printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size); return result ? -1 : 0; }
static int ps3pic_attach(device_t dev) { struct ps3pic_softc *sc; uint64_t ppe; int thread; sc = device_get_softc(dev); sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC, M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */, PAGE_SIZE /* boundary */); sc->mask_thread0 = sc->bitmap_thread0 + 4; sc->bitmap_thread1 = sc->bitmap_thread0 + 8; sc->mask_thread1 = sc->bitmap_thread0 + 12; lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); lv1_configure_irq_state_bitmap(ppe, thread, vtophys(sc->bitmap_thread0)); #ifdef SMP lv1_configure_irq_state_bitmap(ppe, !thread, vtophys(sc->bitmap_thread1)); /* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */ lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]); lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_outlet[0], sc->sc_ipi_outlet[0], 0); lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]); lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_outlet[0], sc->sc_ipi_outlet[1], 0); #endif powerpc_register_pic(dev, 0, sc->sc_ipi_outlet[0], 1, FALSE); return (0); }
static void ps3bus_resources_init_by_type(struct rman *rm, int bus_index, int dev_index, uint64_t irq_type, uint64_t reg_type, struct ps3bus_devinfo *dinfo) { uint64_t _irq_type, irq, outlet; uint64_t _reg_type, paddr, len; uint64_t ppe, junk; int i, result; int thread; resource_list_init(&dinfo->resources); lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); /* Scan for interrupts */ for (i = 0; i < 10; i++) { result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("intr") | i, 0, &_irq_type, &irq); if (result != 0) break; if (_irq_type != irq_type) continue; lv1_construct_io_irq_outlet(irq, &outlet); lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 0); resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, outlet, outlet, 1); } /* Scan for registers */ for (i = 0; i < 10; i++) { result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("reg") | i, lv1_repository_string("type"), &_reg_type, &junk); if (result != 0) break; if (_reg_type != reg_type) continue; result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, (lv1_repository_string("bus") >> 32) | bus_index, lv1_repository_string("dev") | dev_index, lv1_repository_string("reg") | i, lv1_repository_string("data"), &paddr, &len); result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, paddr, len, 12 /* log_2(4 KB) */, &paddr); if (result != 0) { printf("Mapping registers failed for device " "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, dinfo->bustype, dinfo->devtype, result); break; } rman_manage_region(rm, paddr, paddr + len - 1); resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, paddr, paddr + len, len); } }