Rev 3153 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3153 | Rev 3674 | ||
|---|---|---|---|
| Line 38... | Line 38... | ||
| 38 | #include <string.h> |
38 | #include <string.h> |
| 39 | #include <register.h> |
39 | #include <register.h> |
| 40 | #include "main.h" |
40 | #include "main.h" |
| 41 | #include "asm.h" |
41 | #include "asm.h" |
| 42 | 42 | ||
| - | 43 | /* these tho variables will be set by the detect_subarchitecture function */ |
|
| - | 44 | extern uint8_t subarchitecture; |
|
| - | 45 | extern uint16_t mid_mask; |
|
| - | 46 | ||
| 43 | void write(const char *str, const int len) |
47 | void write(const char *str, const int len) |
| 44 | { |
48 | { |
| 45 | int i; |
49 | int i; |
| 46 | 50 | ||
| 47 | for (i = 0; i < len; i++) { |
51 | for (i = 0; i < len; i++) { |
| Line 54... | Line 58... | ||
| 54 | int ofw_translate_failed(ofw_arg_t flag) |
58 | int ofw_translate_failed(ofw_arg_t flag) |
| 55 | { |
59 | { |
| 56 | return flag != -1; |
60 | return flag != -1; |
| 57 | } |
61 | } |
| 58 | 62 | ||
| - | 63 | /** |
|
| - | 64 | * Starts all CPUs represented by following siblings of the given node, |
|
| - | 65 | * except for the current CPU. |
|
| - | 66 | * |
|
| - | 67 | * @param child The first child of the OFW tree node whose children |
|
| - | 68 | * represent CPUs to be woken up. |
|
| - | 69 | * @param current_mid MID of the current CPU, the current CPU will |
|
| - | 70 | * (of course) not be woken up. |
|
| - | 71 | * @return Number of CPUs which have the same parent node as |
|
| 59 | int ofw_cpu(void) |
72 | * "child". |
| - | 73 | */ |
|
| - | 74 | static int wake_cpus_in_node(phandle child, uint64_t current_mid) |
|
| 60 | { |
75 | { |
| 61 | char type_name[BUF_SIZE]; |
- | |
| 62 | - | ||
| 63 | phandle node; |
- | |
| 64 | node = ofw_get_child_node(ofw_root); |
- | |
| 65 | if (node == 0 || node == -1) { |
- | |
| 66 | printf("Could not find any child nodes of the root node.\n"); |
- | |
| 67 | return 0; |
- | |
| 68 | } |
- | |
| 69 | - | ||
| 70 | uint64_t current_mid; |
- | |
| 71 | - | ||
| 72 | asm volatile ("ldxa [%1] %2, %0\n" |
- | |
| 73 | : "=r" (current_mid) |
- | |
| 74 | : "r" (0), "i" (ASI_UPA_CONFIG)); |
- | |
| 75 | current_mid >>= UPA_CONFIG_MID_SHIFT; |
- | |
| 76 | current_mid &= UPA_CONFIG_MID_MASK; |
- | |
| 77 | - | ||
| 78 | int cpus; |
76 | int cpus; |
| - | 77 | char type_name[BUF_SIZE]; |
|
| 79 | 78 | ||
| 80 | for (cpus = 0; node != 0 && node != -1; node = ofw_get_peer_node(node), |
79 | for (cpus = 0; child != 0 && child != -1; |
| 81 | cpus++) { |
80 | child = ofw_get_peer_node(child), cpus++) { |
| 82 | if (ofw_get_property(node, "device_type", type_name, |
81 | if (ofw_get_property(child, "device_type", type_name, |
| 83 | sizeof(type_name)) > 0) { |
82 | sizeof(type_name)) > 0) { |
| 84 | if (strcmp(type_name, "cpu") == 0) { |
83 | if (strcmp(type_name, "cpu") == 0) { |
| 85 | uint32_t mid; |
84 | uint32_t mid; |
| 86 | 85 | ||
| - | 86 | /* |
|
| - | 87 | * "upa-portid" for US, "portid" for US-III, |
|
| - | 88 | * "cpuid" for US-IV |
|
| - | 89 | */ |
|
| - | 90 | if (ofw_get_property( |
|
| - | 91 | child, "upa-portid", |
|
| - | 92 | &mid, sizeof(mid)) <= 0 |
|
| 87 | if (ofw_get_property(node, "upa-portid", &mid, |
93 | && ofw_get_property(child, "portid", |
| - | 94 | &mid, sizeof(mid)) <= 0 |
|
| - | 95 | && ofw_get_property(child, "cpuid", |
|
| 88 | sizeof(mid)) <= 0) |
96 | &mid, sizeof(mid)) <= 0) |
| 89 | continue; |
97 | continue; |
| 90 | 98 | ||
| 91 | if (current_mid != mid) { |
99 | if (current_mid != mid) { |
| 92 | /* |
100 | /* |
| 93 | * Start secondary processor. |
101 | * Start secondary processor. |
| 94 | */ |
102 | */ |
| 95 | (void) ofw_call("SUNW,start-cpu", 3, 1, |
103 | (void) ofw_call("SUNW,start-cpu", 3, 1, |
| 96 | NULL, node, KERNEL_VIRTUAL_ADDRESS, |
104 | NULL, child, KERNEL_VIRTUAL_ADDRESS, |
| 97 | bootinfo.physmem_start | |
105 | bootinfo.physmem_start | |
| 98 | AP_PROCESSOR); |
106 | AP_PROCESSOR); |
| 99 | } |
107 | } |
| 100 | } |
108 | } |
| 101 | } |
109 | } |
| 102 | } |
110 | } |
| 103 | 111 | ||
| 104 | return cpus; |
112 | return cpus; |
| 105 | } |
113 | } |
| 106 | 114 | ||
| - | 115 | /** |
|
| - | 116 | * Finds out the current CPU's MID and wakes up all AP processors. |
|
| - | 117 | */ |
|
| - | 118 | int ofw_cpu(void) |
|
| - | 119 | { |
|
| - | 120 | int cpus; |
|
| - | 121 | phandle node; |
|
| - | 122 | phandle subnode; |
|
| - | 123 | phandle cpus_parent; |
|
| - | 124 | phandle cmp; |
|
| - | 125 | char name[BUF_SIZE]; |
|
| - | 126 | ||
| - | 127 | /* get the current CPU MID */ |
|
| - | 128 | uint64_t current_mid; |
|
| - | 129 | ||
| - | 130 | asm volatile ("ldxa [%1] %2, %0\n" |
|
| - | 131 | : "=r" (current_mid) |
|
| - | 132 | : "r" (0), "i" (ASI_ICBUS_CONFIG)); |
|
| - | 133 | current_mid >>= ICBUS_CONFIG_MID_SHIFT; |
|
| - | 134 | ||
| - | 135 | current_mid &= mid_mask; |
|
| - | 136 | ||
| - | 137 | /* wake up CPUs */ |
|
| - | 138 | ||
| - | 139 | cpus_parent = ofw_find_device("/ssm@0,0"); |
|
| - | 140 | if (cpus_parent == 0 || cpus_parent == -1) { |
|
| - | 141 | cpus_parent = ofw_find_device("/"); |
|
| - | 142 | } |
|
| - | 143 | ||
| - | 144 | node = ofw_get_child_node(cpus_parent); |
|
| - | 145 | cpus = wake_cpus_in_node(node, current_mid); |
|
| - | 146 | while (node != 0 && node != -1) { |
|
| - | 147 | if (ofw_get_property(node, "name", name, |
|
| - | 148 | sizeof(name)) > 0) { |
|
| - | 149 | if (strcmp(name, "cmp") == 0) { |
|
| - | 150 | subnode = ofw_get_child_node(node); |
|
| - | 151 | cpus += wake_cpus_in_node(subnode, |
|
| - | 152 | current_mid); |
|
| - | 153 | } |
|
| - | 154 | } |
|
| - | 155 | node = ofw_get_peer_node(node); |
|
| - | 156 | } |
|
| - | 157 | ||
| - | 158 | return cpus; |
|
| - | 159 | ||
| - | 160 | } |
|
| - | 161 | ||
| 107 | /** Get physical memory starting address. |
162 | /** Get physical memory starting address. |
| 108 | * |
163 | * |
| 109 | * @param start Pointer to variable where the physical memory starting |
164 | * @param start Pointer to variable where the physical memory starting |
| 110 | * address will be stored. |
165 | * address will be stored. |
| 111 | * |
166 | * |
| 112 | * @return Non-zero on succes, zero on failure. |
167 | * @return Non-zero on succes, zero on failure. |
| 113 | */ |
168 | */ |
| 114 | int ofw_get_physmem_start(uintptr_t *start) |
169 | int ofw_get_physmem_start(uintptr_t *start) |
| 115 | { |
170 | { |
| 116 | uint32_t memreg[4]; |
171 | uint32_t memreg[4]; |
| 117 | 172 | ||