Date: Mon, 5 Jul 2010 01:14:32 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r209708 - in user/nwhitehorn/ps3: conf powerpc/ps3 Message-ID: <201007050114.o651EWHp000326@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Mon Jul 5 01:14:32 2010 New Revision: 209708 URL: http://svn.freebsd.org/changeset/base/209708 Log: Add support for the LV1 hypervisor MMU routines. This gets the PS3 to boot to the point of complaining about the lack of a PIC driver (and to print cpu0: IBM Cell Broadband Engine revision 0.0 to the console on the way). Added: user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c Modified: user/nwhitehorn/ps3/conf/files.powerpc64 user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.S user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.h user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master Modified: user/nwhitehorn/ps3/conf/files.powerpc64 ============================================================================== --- user/nwhitehorn/ps3/conf/files.powerpc64 Mon Jul 5 01:12:41 2010 (r209707) +++ user/nwhitehorn/ps3/conf/files.powerpc64 Mon Jul 5 01:14:32 2010 (r209708) @@ -137,8 +137,9 @@ powerpc/powerpc/suswintr.c standard powerpc/powerpc/syncicache.c standard powerpc/powerpc/sys_machdep.c standard powerpc/powerpc/uio_machdep.c standard +powerpc/ps3/mmu_ps3.c optional ps3 powerpc/ps3/platform_ps3.c optional ps3 -powerpc/ps3/ps3_syscons.c optional ps3 +powerpc/ps3/ps3_syscons.c optional ps3 sc powerpc/ps3/ps3-hvcall.S optional ps3 compat/freebsd32/freebsd32_ioctl.c optional compat_freebsd32 Added: user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/nwhitehorn/ps3/powerpc/ps3/mmu_ps3.c Mon Jul 5 01:14:32 2010 (r209708) @@ -0,0 +1,333 @@ +/*- + * Copyright (C) 2010 Nathan Whitehorn + * All rights reserved. + * + * 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 AUTHOR ``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 TOOLS GMBH 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/param.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/msgbuf.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/vmmeter.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> +#include <vm/vm_pageout.h> +#include <vm/vm_pager.h> +#include <vm/uma.h> + +#include <powerpc/aim/mmu_oea64.h> + +#include "mmu_if.h" +#include "ps3-hvcall.h" + +#define VSID_HASH_MASK 0x0000007fffffffffULL + +extern int ps3fb_remap(void); + +static uint64_t mps3_vas_id; + +/* + * Kernel MMU interface + */ + +static void mps3_bootstrap(mmu_t mmup, vm_offset_t kernelstart, + vm_offset_t kernelend); +static void mps3_cpu_bootstrap(mmu_t mmup, int ap); +static void mps3_pte_synch(struct lpte *pt, struct lpte *pvo_pt); +static void mps3_pte_clear(struct lpte *pt, struct lpte *pvo_pt, + uint64_t vpn, u_int64_t ptebit); +static void mps3_pte_unset(struct lpte *pt, struct lpte *pvo_pt, + uint64_t vpn); +static void mps3_pte_change(struct lpte *pt, struct lpte *pvo_pt, + uint64_t vpn); +static int mps3_pte_insert(u_int ptegidx, struct lpte *pvo_pt); +static struct lpte *mps3_pvo_to_pte(const struct pvo_entry *pvo); + + +static mmu_method_t mps3_methods[] = { + MMUMETHOD(mmu_change_wiring, moea64_change_wiring), + MMUMETHOD(mmu_clear_modify, moea64_clear_modify), + MMUMETHOD(mmu_clear_reference, moea64_clear_reference), + MMUMETHOD(mmu_copy_page, moea64_copy_page), + MMUMETHOD(mmu_enter, moea64_enter), + MMUMETHOD(mmu_enter_object, moea64_enter_object), + MMUMETHOD(mmu_enter_quick, moea64_enter_quick), + MMUMETHOD(mmu_extract, moea64_extract), + MMUMETHOD(mmu_extract_and_hold, moea64_extract_and_hold), + MMUMETHOD(mmu_init, moea64_init), + MMUMETHOD(mmu_is_modified, moea64_is_modified), + MMUMETHOD(mmu_is_referenced, moea64_is_referenced), + MMUMETHOD(mmu_ts_referenced, moea64_ts_referenced), + MMUMETHOD(mmu_map, moea64_map), + MMUMETHOD(mmu_page_exists_quick,moea64_page_exists_quick), + MMUMETHOD(mmu_page_wired_mappings,moea64_page_wired_mappings), + MMUMETHOD(mmu_pinit, moea64_pinit), + MMUMETHOD(mmu_pinit0, moea64_pinit0), + MMUMETHOD(mmu_protect, moea64_protect), + MMUMETHOD(mmu_qenter, moea64_qenter), + MMUMETHOD(mmu_qremove, moea64_qremove), + MMUMETHOD(mmu_release, moea64_release), + MMUMETHOD(mmu_remove, moea64_remove), + MMUMETHOD(mmu_remove_all, moea64_remove_all), + MMUMETHOD(mmu_remove_write, moea64_remove_write), + MMUMETHOD(mmu_sync_icache, moea64_sync_icache), + MMUMETHOD(mmu_zero_page, moea64_zero_page), + MMUMETHOD(mmu_zero_page_area, moea64_zero_page_area), + MMUMETHOD(mmu_zero_page_idle, moea64_zero_page_idle), + MMUMETHOD(mmu_activate, moea64_activate), + MMUMETHOD(mmu_deactivate, moea64_deactivate), + + /* Internal interfaces */ + MMUMETHOD(mmu_bootstrap, mps3_bootstrap), + MMUMETHOD(mmu_cpu_bootstrap, mps3_cpu_bootstrap), + MMUMETHOD(mmu_mapdev, moea64_mapdev), + MMUMETHOD(mmu_unmapdev, moea64_unmapdev), + MMUMETHOD(mmu_kextract, moea64_kextract), + MMUMETHOD(mmu_kenter, moea64_kenter), + MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped), + + { 0, 0 } +}; + +static mmu_def_t ps3_mmu = { + "mmu_ps3", + mps3_methods, + 0 +}; +MMU_DEF(ps3_mmu); + +static void +mps3_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) +{ + uint64_t final_pteg_count; + + /* + * Set our page table override functions + */ + moea64_pte_synch_hook = mps3_pte_synch; + moea64_pte_clear_hook = mps3_pte_clear; + moea64_pte_unset_hook = mps3_pte_unset; + moea64_pte_change_hook = mps3_pte_change; + moea64_pte_insert_hook = mps3_pte_insert; + moea64_pvo_to_pte_hook = mps3_pvo_to_pte; + + moea64_early_bootstrap(mmup, kernelstart, kernelend); + + lv1_construct_virtual_address_space( + 20 /* log_2(moea64_pteg_count) */, 2 /* n page sizes */, + (24UL << 56) | (16UL << 48) /* page sizes 16 MB + 64 KB */, + &mps3_vas_id, &final_pteg_count + ); + + moea64_pteg_count = final_pteg_count / sizeof(struct lpteg); + + moea64_late_bootstrap(mmup, kernelstart, kernelend); +} + +static void +mps3_cpu_bootstrap(mmu_t mmup, int ap) +{ + struct slb *slb = PCPU_GET(slb); + register_t seg0; + int i; + + mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR); + + /* + * Destroy the loader's address space if we are coming up for + * the first time, and redo the FB mapping so we can continue + * having a console. + */ + + if (!ap) + lv1_destruct_virtual_address_space(0); + + lv1_select_virtual_address_space(mps3_vas_id); + mps3_vas_id = 0; /* Now this is the current mapping */ + + if (!ap) + ps3fb_remap(); + + /* + * Install kernel SLB entries + */ + + __asm __volatile ("slbia"); + __asm __volatile ("slbmfee %0,%1; slbie %0;" : "=r"(seg0) : "r"(0)); + for (i = 0; i < 64; i++) { + if (!(slb[i].slbe & SLBE_VALID)) + continue; + + __asm __volatile ("slbmte %0, %1" :: + "r"(slb[i].slbv), "r"(slb[i].slbe)); + } +} + +static void +mps3_pte_synch(struct lpte *pt, struct lpte *pvo_pt) +{ + uint64_t halfbucket[4], rcbits; + uint64_t slot = (uint64_t)(pt)-1; + + lv1_read_htab_entries(mps3_vas_id, slot & ~0x3UL, &halfbucket[0], + &halfbucket[1], &halfbucket[2], &halfbucket[3], &rcbits); + + pvo_pt->pte_lo |= ((rcbits >> (slot & 0x3)) & 0x3) << 7; +} + +static void +mps3_pte_clear(struct lpte *pt, struct lpte *pvo_pt, uint64_t vpn, + u_int64_t ptebit) +{ + uint64_t slot = (uint64_t)(pt)-1; + + lv1_write_htab_entry(mps3_vas_id, slot, pvo_pt->pte_hi, + pvo_pt->pte_lo & ~ptebit); +} + +static void +mps3_pte_unset(struct lpte *pt, struct lpte *pvo_pt, uint64_t vpn) +{ + uint64_t slot = (uint64_t)(pt)-1; + + pvo_pt->pte_hi &= ~LPTE_VALID; + lv1_write_htab_entry(mps3_vas_id, slot, 0, 0); + moea64_pte_valid--; +} + +static void +mps3_pte_change(struct lpte *pt, struct lpte *pvo_pt, uint64_t vpn) +{ + uint64_t slot = (uint64_t)(pt)-1; + + pvo_pt->pte_hi |= LPTE_VALID; + lv1_write_htab_entry(mps3_vas_id, slot & ~0x3UL, pvo_pt->pte_hi, + pvo_pt->pte_lo); +} + +static int +mps3_pte_insert(u_int ptegidx, struct lpte *pvo_pt) +{ + int result; + struct lpte evicted; + struct pvo_entry *pvo; + uint64_t index; + + pvo_pt->pte_hi |= LPTE_VALID; + pvo_pt->pte_hi &= ~LPTE_HID; + evicted.pte_hi = 0; + result = lv1_insert_htab_entry(mps3_vas_id, ptegidx << 3, + pvo_pt->pte_hi, pvo_pt->pte_lo, LPTE_LOCKED | LPTE_WIRED, 0, + &index, &evicted.pte_hi, &evicted.pte_lo); + + if (result != 0) { + /* No freeable slots in either PTEG? We're hosed. */ + mtmsr(mfmsr() | PSL_DR); panic("moea64_pte_insert: overflow"); + return (-1); + } + + /* + * See where we ended up. + */ + if (index >> 3 != ptegidx) + pvo_pt->pte_hi |= LPTE_HID; + + moea64_pte_valid++; + + if (!evicted.pte_hi) + return (index & 0x7); + + /* + * Synchronize the sacrifice PTE with its PVO, then mark both + * invalid. The PVO will be reused when/if the VM system comes + * here after a fault. + */ + + if (evicted.pte_hi & LPTE_HID) + ptegidx ^= moea64_pteg_mask; /* PTEs indexed by primary */ + + LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) { + if (pvo->pvo_pte.lpte.pte_hi == evicted.pte_hi) { + KASSERT(pvo->pvo_pte.lpte.pte_hi & LPTE_VALID, + ("Invalid PVO for valid PTE!")); + pvo->pvo_pte.lpte.pte_hi &= ~LPTE_VALID; + pvo->pvo_pte.lpte.pte_lo |= + evicted.pte_lo & (LPTE_REF | LPTE_CHG); + PVO_PTEGIDX_CLR(pvo); + moea64_pte_valid--; + moea64_pte_overflow++; + break; + } + } + + return (index & 0x7); +} + +static __inline u_int +va_to_pteg(uint64_t vsid, vm_offset_t addr, int large) +{ + uint64_t hash; + int shift; + + shift = large ? moea64_large_page_shift : ADDR_PIDX_SHFT; + hash = (vsid & VSID_HASH_MASK) ^ (((uint64_t)addr & ADDR_PIDX) >> + shift); + return (hash & moea64_pteg_mask); +} + +static struct lpte * +mps3_pvo_to_pte(const struct pvo_entry *pvo) +{ + uint64_t slot, vsid; + u_int ptegidx; + + /* If the PTEG index is not set, then there is no page table entry */ + if (!PVO_PTEGIDX_ISSET(pvo)) + return (NULL); + + vsid = PVO_VSID(pvo); + ptegidx = va_to_pteg(vsid, PVO_VADDR(pvo), pvo->pvo_vaddr & PVO_LARGE); + + /* + * We can find the actual pte entry without searching by grabbing + * the PTEG index from 3 unused bits in pvo_vaddr and by + * noticing the HID bit. + */ + if (pvo->pvo_pte.lpte.pte_hi & LPTE_HID) + ptegidx ^= moea64_pteg_mask; + + slot = (ptegidx << 3) | PVO_PTEGIDX_GET(pvo); + + return ((struct lpte *)(slot + 1)); +} + Modified: user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Mon Jul 5 01:12:41 2010 (r209707) +++ user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Mon Jul 5 01:14:32 2010 (r209708) @@ -36,12 +36,16 @@ __FBSDID("$FreeBSD: user/nwhitehorn/ps3/ #include <sys/reboot.h> #include <sys/smp.h> +#include <vm/vm.h> +#include <vm/pmap.h> + #include <machine/bootinfo.h> #include <machine/bus.h> #include <machine/cpu.h> #include <machine/hid.h> #include <machine/platform.h> #include <machine/platformvar.h> +#include <machine/pmap.h> #include <machine/smp.h> #include <machine/spr.h> #include <machine/vmparam.h> @@ -107,7 +111,8 @@ ps3_probe(platform_t plat) static int ps3_attach(platform_t plat) { - boothowto |= RB_VERBOSE; + + pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC); return (0); } Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.S ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.S Mon Jul 5 01:12:41 2010 (r209707) +++ user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.S Mon Jul 5 01:14:32 2010 (r209708) @@ -2,11 +2,6 @@ #define hc .long 0x44000022 -/* - * Playstation 3 LV1 hypercall interface - * - * $FreeBSD: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master 209631 2010-07-01 15:23:29Z nwhitehorn $ - */ ASENTRY(lv1_allocate_memory) mflr %r0 std %r0,16(%r1) @@ -321,15 +316,15 @@ ASENTRY(lv1_construct_logical_spe) std %r0,16(%r1) stdu %r1,-96(%r1) std %r10,48(%r1) - ld %r11,152(%r1) + ld %r11,208(%r1) std %r11,56(%r1) - ld %r11,160(%r1) + ld %r11,216(%r1) std %r11,64(%r1) - ld %r11,168(%r1) + ld %r11,224(%r1) std %r11,72(%r1) - ld %r11,176(%r1) + ld %r11,232(%r1) std %r11,80(%r1) - ld %r11,184(%r1) + ld %r11,240(%r1) std %r11,88(%r1) li %r11,57 hc @@ -477,6 +472,33 @@ ASENTRY(lv1_get_repository_node_value) mtlr %r0 blr +ASENTRY(lv1_read_htab_entries) + mflr %r0 + std %r0,16(%r1) + stdu %r1,-88(%r1) + std %r5,48(%r1) + std %r6,56(%r1) + std %r7,64(%r1) + std %r8,72(%r1) + std %r9,80(%r1) + li %r11,95 + hc + extsw %r3,%r3 + ld %r11,48(%r1) + std %r4,0(%r11) + ld %r11,56(%r1) + std %r5,0(%r11) + ld %r11,64(%r1) + std %r6,0(%r11) + ld %r11,72(%r1) + std %r7,0(%r11) + ld %r11,80(%r1) + std %r8,0(%r11) + ld %r1,0(%r1) + ld %r0,16(%r1) + mtlr %r0 + blr + ASENTRY(lv1_set_dabr) mflr %r0 std %r0,16(%r1) @@ -585,6 +607,28 @@ ASENTRY(lv1_get_version_info) mtlr %r0 blr +ASENTRY(lv1_insert_htab_entry) + mflr %r0 + std %r0,16(%r1) + stdu %r1,-72(%r1) + std %r9,48(%r1) + std %r10,56(%r1) + ld %r11,184(%r1) + std %r11,64(%r1) + li %r11,158 + hc + extsw %r3,%r3 + ld %r11,48(%r1) + std %r4,0(%r11) + ld %r11,56(%r1) + std %r5,0(%r11) + ld %r11,64(%r1) + std %r6,0(%r11) + ld %r1,0(%r1) + ld %r0,16(%r1) + mtlr %r0 + blr + ASENTRY(lv1_read_virtual_uart) mflr %r0 std %r0,16(%r1) Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.h ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.h Mon Jul 5 01:12:41 2010 (r209707) +++ user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.h Mon Jul 5 01:14:32 2010 (r209708) @@ -1,7 +1,7 @@ /* * Playstation 3 LV1 hypercall interface * - * $FreeBSD: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master 209631 2010-07-01 15:23:29Z nwhitehorn $ + * $FreeBSD: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master 209679 2010-07-04 02:40:31Z nwhitehorn $ */ #include <sys/types.h> @@ -52,6 +52,7 @@ int lv1_get_logical_partition_id(uint64_ int lv1_get_spe_irq_outlet(uint64_t spe_id, uint64_t class, uint64_t *outlet); int lv1_set_spe_privilege_state_area_1_register(uint64_t spe_id, uint64_t offset, uint64_t value); int lv1_get_repository_node_value(uint64_t lpar_id, uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4, uint64_t *v1, uint64_t *v2); +int lv1_read_htab_entries(uint64_t vas_id, uint64_t slot, uint64_t *hi1, uint64_t *hi2, uint64_t *hi3, uint64_t *hi4, uint64_t *rcbits); int lv1_set_dabr(uint64_t dabr, uint64_t flags); int lv1_allocate_io_segment(uint64_t ioas_id, uint64_t seg_size, uint64_t io_pagesize, uint64_t *ioif_addr); int lv1_release_io_segment(uint64_t ioas_id, uint64_t ioif_addr); @@ -60,6 +61,7 @@ int lv1_destruct_io_irq_outlet(uint64_t int lv1_map_htab(uint64_t lpar_id, uint64_t *htab_addr); int lv1_unmap_htab(uint64_t htab_addr); int lv1_get_version_info(uint64_t *firm_vers); +int lv1_insert_htab_entry(uint64_t vas_id, uint64_t pteg, uint64_t pte_hi, uint64_t pte_lo, uint64_t lockflags, uint64_t flags, uint64_t *index, uint64_t *evicted_hi, uint64_t *evicted_lo); int lv1_read_virtual_uart(uint64_t port, uint64_t buffer, uint64_t bytes, uint64_t *bytes_read); int lv1_write_virtual_uart(uint64_t port, uint64_t buffer, uint64_t bytes, uint64_t *bytes_written); int lv1_set_virtual_uart_param(uint64_t port, uint64_t param, uint64_t value); Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master Mon Jul 5 01:12:41 2010 (r209707) +++ user/nwhitehorn/ps3/powerpc/ps3/ps3-hvcall.master Mon Jul 5 01:14:32 2010 (r209708) @@ -53,6 +53,7 @@ HVCALL 74 lv1_get_logical_partition_id HVCALL 78 lv1_get_spe_irq_outlet spe_id,class outlet HVCALL 79 lv1_set_spe_privilege_state_area_1_register spe_id,offset,value HVCALL 91 lv1_get_repository_node_value lpar_id,n1,n2,n3,n4 v1,v2 +HVCALL 95 lv1_read_htab_entries vas_id,slot hi1,hi2,hi3,hi4,rcbits HVCALL 96 lv1_set_dabr dabr,flags HVCALL 116 lv1_allocate_io_segment ioas_id,seg_size,io_pagesize ioif_addr HVCALL 117 lv1_release_io_segment ioas_id,ioif_addr @@ -61,6 +62,7 @@ HVCALL 121 lv1_destruct_io_irq_outlet o HVCALL 122 lv1_map_htab lpar_id htab_addr HVCALL 123 lv1_unmap_htab htab_addr HVCALL 127 lv1_get_version_info UNUSED firm_vers +HVCALL 158 lv1_insert_htab_entry vas_id,pteg,pte_hi,pte_lo,lockflags,flags index,evicted_hi,evicted_lo HVCALL 162 lv1_read_virtual_uart port,buffer,bytes bytes_read HVCALL 163 lv1_write_virtual_uart port,buffer,bytes bytes_written HVCALL 164 lv1_set_virtual_uart_param port,param,value
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007050114.o651EWHp000326>