main.c (200946) | main.c (203829) |
---|---|
1/*- 2 * Initial implementation: 3 * Copyright (c) 2001 Robert Drehmel 4 * All rights reserved. 5 * 6 * As long as the above copyright statement and this notice remain 7 * unchanged, you can do what ever you want with this file. 8 */ --- 19 unchanged lines hidden (view full) --- 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> | 1/*- 2 * Initial implementation: 3 * Copyright (c) 2001 Robert Drehmel 4 * All rights reserved. 5 * 6 * As long as the above copyright statement and this notice remain 7 * unchanged, you can do what ever you want with this file. 8 */ --- 19 unchanged lines hidden (view full) --- 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sys/boot/sparc64/loader/main.c 200946 2009-12-24 15:23:51Z marius $"); | 36__FBSDID("$FreeBSD: head/sys/boot/sparc64/loader/main.c 203829 2010-02-13 14:13:39Z marius $"); |
37 38/* 39 * FreeBSD/sparc64 kernel loader - machine dependent part 40 * 41 * - implements copyin and readin functions that map kernel 42 * pages on demand. The machine independent code does not 43 * know the size of the kernel early enough to pre-enter 44 * TTEs and install just one 4MB mapping seemed to limiting 45 * to me. 46 */ 47 48#include <stand.h> | 37 38/* 39 * FreeBSD/sparc64 kernel loader - machine dependent part 40 * 41 * - implements copyin and readin functions that map kernel 42 * pages on demand. The machine independent code does not 43 * know the size of the kernel early enough to pre-enter 44 * TTEs and install just one 4MB mapping seemed to limiting 45 * to me. 46 */ 47 48#include <stand.h> |
49#include <sys/exec.h> | |
50#include <sys/param.h> | 49#include <sys/param.h> |
51#include <sys/queue.h> | 50#include <sys/exec.h> |
52#include <sys/linker.h> | 51#include <sys/linker.h> |
52#include <sys/queue.h> |
|
53#include <sys/types.h> 54 55#include <vm/vm.h> 56#include <machine/asi.h> | 53#include <sys/types.h> 54 55#include <vm/vm.h> 56#include <machine/asi.h> |
57#include <machine/cmt.h> |
|
57#include <machine/cpufunc.h> 58#include <machine/elf.h> | 58#include <machine/cpufunc.h> 59#include <machine/elf.h> |
60#include <machine/fireplane.h> 61#include <machine/jbus.h> |
|
59#include <machine/lsu.h> 60#include <machine/metadata.h> 61#include <machine/tte.h> 62#include <machine/tlb.h> 63#include <machine/upa.h> 64#include <machine/ver.h> 65#include <machine/vmparam.h> 66 67#include "bootstrap.h" 68#include "libofw.h" 69#include "dev_net.h" 70 | 62#include <machine/lsu.h> 63#include <machine/metadata.h> 64#include <machine/tte.h> 65#include <machine/tlb.h> 66#include <machine/upa.h> 67#include <machine/ver.h> 68#include <machine/vmparam.h> 69 70#include "bootstrap.h" 71#include "libofw.h" 72#include "dev_net.h" 73 |
74#ifndef CTASSERT 75#define CTASSERT(x) _CTASSERT(x, __LINE__) 76#define _CTASSERT(x, y) __CTASSERT(x, y) 77#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] 78#endif 79 |
|
71extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 72 73enum { 74 HEAPVA = 0x800000, 75 HEAPSZ = 0x1000000, 76 LOADSZ = 0x1000000 /* for kernel and modules */ 77}; 78 | 80extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 81 82enum { 83 HEAPVA = 0x800000, 84 HEAPSZ = 0x1000000, 85 LOADSZ = 0x1000000 /* for kernel and modules */ 86}; 87 |
88/* At least Sun Fire V1280 require page sized allocations to be claimed. */ 89CTASSERT(HEAPSZ % PAGE_SIZE == 0); 90 |
|
79static struct mmu_ops { 80 void (*tlb_init)(void); 81 int (*mmu_mapin)(vm_offset_t va, vm_size_t len); 82} *mmu_ops; 83 84typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, 85 void *openfirmware); 86 | 91static struct mmu_ops { 92 void (*tlb_init)(void); 93 int (*mmu_mapin)(vm_offset_t va, vm_size_t len); 94} *mmu_ops; 95 96typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, 97 void *openfirmware); 98 |
87static inline u_long dtlb_get_data_sun4u(int slot); 88static void dtlb_enter_sun4u(u_long vpn, u_long data); | 99static inline u_long dtlb_get_data_sun4u(u_int); 100static void dtlb_enter_sun4u(u_long, u_long); |
89static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t); | 101static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t); |
90static inline u_long itlb_get_data_sun4u(int slot); 91static void itlb_enter_sun4u(u_long vpn, u_long data); | 102static inline u_long itlb_get_data_sun4u(u_int); 103static void itlb_enter_sun4u(u_long, u_long); |
92static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); 93static void itlb_relocate_locked0_sun4u(void); 94extern vm_offset_t md_load(char *, vm_offset_t *); 95static int sparc64_autoload(void); 96static ssize_t sparc64_readin(const int, vm_offset_t, const size_t); 97static ssize_t sparc64_copyin(const void *, vm_offset_t, size_t); 98static void sparc64_maphint(vm_offset_t, size_t); 99static vm_offset_t claim_virt(vm_offset_t, size_t, int); 100static vm_offset_t alloc_phys(size_t, int); 101static int map_phys(int, size_t, vm_offset_t, vm_offset_t); 102static void release_phys(vm_offset_t, u_int); 103static int __elfN(exec)(struct preloaded_file *); 104static int mmu_mapin_sun4u(vm_offset_t, vm_size_t); 105static int mmu_mapin_sun4v(vm_offset_t, vm_size_t); 106static vm_offset_t init_heap(void); | 104static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); 105static void itlb_relocate_locked0_sun4u(void); 106extern vm_offset_t md_load(char *, vm_offset_t *); 107static int sparc64_autoload(void); 108static ssize_t sparc64_readin(const int, vm_offset_t, const size_t); 109static ssize_t sparc64_copyin(const void *, vm_offset_t, size_t); 110static void sparc64_maphint(vm_offset_t, size_t); 111static vm_offset_t claim_virt(vm_offset_t, size_t, int); 112static vm_offset_t alloc_phys(size_t, int); 113static int map_phys(int, size_t, vm_offset_t, vm_offset_t); 114static void release_phys(vm_offset_t, u_int); 115static int __elfN(exec)(struct preloaded_file *); 116static int mmu_mapin_sun4u(vm_offset_t, vm_size_t); 117static int mmu_mapin_sun4v(vm_offset_t, vm_size_t); 118static vm_offset_t init_heap(void); |
119static phandle_t find_bsp_sun4u(phandle_t, uint32_t); 120const char *cpu_cpuid_prop_sun4u(void); 121uint32_t cpu_get_mid_sun4u(void); |
|
107static void tlb_init_sun4u(void); 108static void tlb_init_sun4v(void); 109 110#ifdef LOADER_DEBUG 111typedef u_int64_t tte_t; 112 113static void pmap_print_tlb_sun4u(void); 114static void pmap_print_tte_sun4u(tte_t, tte_t); 115#endif 116 117static struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u }; 118static struct mmu_ops mmu_ops_sun4v = { tlb_init_sun4v, mmu_mapin_sun4v }; 119 120/* sun4u */ 121struct tlb_entry *dtlb_store; 122struct tlb_entry *itlb_store; | 122static void tlb_init_sun4u(void); 123static void tlb_init_sun4v(void); 124 125#ifdef LOADER_DEBUG 126typedef u_int64_t tte_t; 127 128static void pmap_print_tlb_sun4u(void); 129static void pmap_print_tte_sun4u(tte_t, tte_t); 130#endif 131 132static struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u }; 133static struct mmu_ops mmu_ops_sun4v = { tlb_init_sun4v, mmu_mapin_sun4v }; 134 135/* sun4u */ 136struct tlb_entry *dtlb_store; 137struct tlb_entry *itlb_store; |
123int dtlb_slot; 124int itlb_slot; | 138u_int dtlb_slot; 139u_int itlb_slot; |
125int cpu_impl; | 140int cpu_impl; |
126static int dtlb_slot_max; 127static int itlb_slot_max; | 141static u_int dtlb_slot_max; 142static u_int itlb_slot_max; |
128 129/* sun4v */ 130static struct tlb_entry *tlb_store; 131static int is_sun4v = 0; 132/* 133 * no direct TLB access on sun4v 134 * we somewhat arbitrarily declare enough 135 * slots to cover a 4GB AS with 4MB pages --- 257 unchanged lines hidden (view full) --- 393 OF_release((void *)heapva, HEAPSZ); 394 395 ((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware); 396 397 panic("%s: exec returned", __func__); 398} 399 400static inline u_long | 143 144/* sun4v */ 145static struct tlb_entry *tlb_store; 146static int is_sun4v = 0; 147/* 148 * no direct TLB access on sun4v 149 * we somewhat arbitrarily declare enough 150 * slots to cover a 4GB AS with 4MB pages --- 257 unchanged lines hidden (view full) --- 408 OF_release((void *)heapva, HEAPSZ); 409 410 ((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware); 411 412 panic("%s: exec returned", __func__); 413} 414 415static inline u_long |
401dtlb_get_data_sun4u(int slot) | 416dtlb_get_data_sun4u(u_int slot) |
402{ 403 404 /* 405 * We read ASI_DTLB_DATA_ACCESS_REG twice in order to work 406 * around errata of USIII and beyond. 407 */ 408 (void)ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG); 409 return (ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG)); 410} 411 412static inline u_long | 417{ 418 419 /* 420 * We read ASI_DTLB_DATA_ACCESS_REG twice in order to work 421 * around errata of USIII and beyond. 422 */ 423 (void)ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG); 424 return (ldxa(TLB_DAR_SLOT(slot), ASI_DTLB_DATA_ACCESS_REG)); 425} 426 427static inline u_long |
413itlb_get_data_sun4u(int slot) | 428itlb_get_data_sun4u(u_int slot) |
414{ 415 416 /* 417 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work 418 * around errata of USIII and beyond. 419 */ 420 (void)ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG); 421 return (ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG)); --- 241 unchanged lines hidden (view full) --- 663init_heap(void) 664{ 665 666 /* There is no need for continuous physical heap memory. */ 667 heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); 668 return (heapva); 669} 670 | 429{ 430 431 /* 432 * We read ASI_ITLB_DATA_ACCESS_REG twice in order to work 433 * around errata of USIII and beyond. 434 */ 435 (void)ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG); 436 return (ldxa(TLB_DAR_SLOT(slot), ASI_ITLB_DATA_ACCESS_REG)); --- 241 unchanged lines hidden (view full) --- 678init_heap(void) 679{ 680 681 /* There is no need for continuous physical heap memory. */ 682 heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); 683 return (heapva); 684} 685 |
686static phandle_t 687find_bsp_sun4u(phandle_t node, uint32_t bspid) 688{ 689 char type[sizeof("cpu")]; 690 phandle_t child; 691 uint32_t cpuid; 692 693 for (; node > 0; node = OF_peer(node)) { 694 child = OF_child(node); 695 if (child > 0) { 696 child = find_bsp_sun4u(child, bspid); 697 if (child > 0) 698 return (child); 699 } else { 700 if (OF_getprop(node, "device_type", type, 701 sizeof(type)) <= 0) 702 continue; 703 if (strcmp(type, "cpu") != 0) 704 continue; 705 if (OF_getprop(node, cpu_cpuid_prop_sun4u(), &cpuid, 706 sizeof(cpuid)) <= 0) 707 continue; 708 if (cpuid == bspid) 709 return (node); 710 } 711 } 712 return (0); 713} 714 715const char * 716cpu_cpuid_prop_sun4u(void) 717{ 718 719 switch (cpu_impl) { 720 case CPU_IMPL_SPARC64: 721 case CPU_IMPL_ULTRASPARCI: 722 case CPU_IMPL_ULTRASPARCII: 723 case CPU_IMPL_ULTRASPARCIIi: 724 case CPU_IMPL_ULTRASPARCIIe: 725 return ("upa-portid"); 726 case CPU_IMPL_ULTRASPARCIII: 727 case CPU_IMPL_ULTRASPARCIIIp: 728 case CPU_IMPL_ULTRASPARCIIIi: 729 case CPU_IMPL_ULTRASPARCIIIip: 730 return ("portid"); 731 case CPU_IMPL_ULTRASPARCIV: 732 case CPU_IMPL_ULTRASPARCIVp: 733 return ("cpuid"); 734 default: 735 return (""); 736 } 737} 738 739uint32_t 740cpu_get_mid_sun4u(void) 741{ 742 743 switch (cpu_impl) { 744 case CPU_IMPL_SPARC64: 745 case CPU_IMPL_ULTRASPARCI: 746 case CPU_IMPL_ULTRASPARCII: 747 case CPU_IMPL_ULTRASPARCIIi: 748 case CPU_IMPL_ULTRASPARCIIe: 749 return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); 750 case CPU_IMPL_ULTRASPARCIII: 751 case CPU_IMPL_ULTRASPARCIIIp: 752 return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, 753 ASI_FIREPLANE_CONFIG_REG))); 754 case CPU_IMPL_ULTRASPARCIIIi: 755 case CPU_IMPL_ULTRASPARCIIIip: 756 return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); 757 case CPU_IMPL_ULTRASPARCIV: 758 case CPU_IMPL_ULTRASPARCIVp: 759 return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); 760 default: 761 return (0); 762 } 763} 764 |
|
671static void 672tlb_init_sun4u(void) 673{ | 765static void 766tlb_init_sun4u(void) 767{ |
674 phandle_t child; 675 char buf[128]; 676 u_int bootcpu; 677 u_int cpu; | 768 phandle_t bsp; |
678 679 cpu_impl = VER_IMPL(rdpr(ver)); | 769 770 cpu_impl = VER_IMPL(rdpr(ver)); |
680 bootcpu = UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG)); 681 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 682 if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0) 683 continue; 684 if (strcmp(buf, "cpu") != 0) 685 continue; 686 if (OF_getprop(child, cpu_impl < CPU_IMPL_ULTRASPARCIII ? 687 "upa-portid" : "portid", &cpu, sizeof(cpu)) <= 0) 688 continue; 689 if (cpu == bootcpu) 690 break; 691 } 692 if (cpu != bootcpu) | 771 bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u()); 772 if (bsp == 0) |
693 panic("%s: no node for bootcpu?!?!", __func__); 694 | 773 panic("%s: no node for bootcpu?!?!", __func__); 774 |
695 if (OF_getprop(child, "#dtlb-entries", &dtlb_slot_max, | 775 if (OF_getprop(bsp, "#dtlb-entries", &dtlb_slot_max, |
696 sizeof(dtlb_slot_max)) == -1 || | 776 sizeof(dtlb_slot_max)) == -1 || |
697 OF_getprop(child, "#itlb-entries", &itlb_slot_max, | 777 OF_getprop(bsp, "#itlb-entries", &itlb_slot_max, |
698 sizeof(itlb_slot_max)) == -1) 699 panic("%s: can't get TLB slot max.", __func__); 700 701 if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) { 702#ifdef LOADER_DEBUG 703 printf("pre fixup:\n"); 704 pmap_print_tlb_sun4u(); 705#endif --- 38 unchanged lines hidden (view full) --- 744 745 archsw.arch_getdev = ofw_getdev; 746 archsw.arch_copyin = sparc64_copyin; 747 archsw.arch_copyout = ofw_copyout; 748 archsw.arch_readin = sparc64_readin; 749 archsw.arch_autoload = sparc64_autoload; 750 archsw.arch_maphint = sparc64_maphint; 751 | 778 sizeof(itlb_slot_max)) == -1) 779 panic("%s: can't get TLB slot max.", __func__); 780 781 if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) { 782#ifdef LOADER_DEBUG 783 printf("pre fixup:\n"); 784 pmap_print_tlb_sun4u(); 785#endif --- 38 unchanged lines hidden (view full) --- 824 825 archsw.arch_getdev = ofw_getdev; 826 archsw.arch_copyin = sparc64_copyin; 827 archsw.arch_copyout = ofw_copyout; 828 archsw.arch_readin = sparc64_readin; 829 archsw.arch_autoload = sparc64_autoload; 830 archsw.arch_maphint = sparc64_maphint; 831 |
752 init_heap(); 753 setheap((void *)heapva, (void *)(heapva + HEAPSZ)); 754 | |
755 /* 756 * Probe for a console. 757 */ 758 cons_probe(); 759 | 832 /* 833 * Probe for a console. 834 */ 835 cons_probe(); 836 |
837 if (init_heap() == (vm_offset_t)-1) 838 panic("%s: can't claim heap", __func__); 839 setheap((void *)heapva, (void *)(heapva + HEAPSZ)); 840 |
|
760 if ((root = OF_peer(0)) == -1) 761 panic("%s: can't get root phandle", __func__); 762 OF_getprop(root, "compatible", compatible, sizeof(compatible)); 763 if (!strcmp(compatible, "sun4v")) { 764 printf("\nBooting with sun4v support.\n"); 765 mmu_ops = &mmu_ops_sun4v; 766 is_sun4v = 1; 767 } else { --- 128 unchanged lines hidden --- | 841 if ((root = OF_peer(0)) == -1) 842 panic("%s: can't get root phandle", __func__); 843 OF_getprop(root, "compatible", compatible, sizeof(compatible)); 844 if (!strcmp(compatible, "sun4v")) { 845 printf("\nBooting with sun4v support.\n"); 846 mmu_ops = &mmu_ops_sun4v; 847 is_sun4v = 1; 848 } else { --- 128 unchanged lines hidden --- |