Deleted Added
full compact
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 ---