diff options
-rw-r--r-- | arch/x86/events/core.c | 34 | ||||
-rw-r--r-- | arch/x86/events/intel/core.c | 18 | ||||
-rw-r--r-- | arch/x86/events/intel/ds.c | 51 | ||||
-rw-r--r-- | arch/x86/events/intel/pt.c | 5 | ||||
-rw-r--r-- | arch/x86/events/perf_event.h | 17 | ||||
-rw-r--r-- | arch/x86/include/asm/intel_pt.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/msr-index.h | 4 |
7 files changed, 130 insertions, 1 deletions
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 325959d19d9a..15b90b1a8fb1 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c | |||
@@ -1005,6 +1005,27 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, | |||
1005 | 1005 | ||
1006 | /* current number of events already accepted */ | 1006 | /* current number of events already accepted */ |
1007 | n = cpuc->n_events; | 1007 | n = cpuc->n_events; |
1008 | if (!cpuc->n_events) | ||
1009 | cpuc->pebs_output = 0; | ||
1010 | |||
1011 | if (!cpuc->is_fake && leader->attr.precise_ip) { | ||
1012 | /* | ||
1013 | * For PEBS->PT, if !aux_event, the group leader (PT) went | ||
1014 | * away, the group was broken down and this singleton event | ||
1015 | * can't schedule any more. | ||
1016 | */ | ||
1017 | if (is_pebs_pt(leader) && !leader->aux_event) | ||
1018 | return -EINVAL; | ||
1019 | |||
1020 | /* | ||
1021 | * pebs_output: 0: no PEBS so far, 1: PT, 2: DS | ||
1022 | */ | ||
1023 | if (cpuc->pebs_output && | ||
1024 | cpuc->pebs_output != is_pebs_pt(leader) + 1) | ||
1025 | return -EINVAL; | ||
1026 | |||
1027 | cpuc->pebs_output = is_pebs_pt(leader) + 1; | ||
1028 | } | ||
1008 | 1029 | ||
1009 | if (is_x86_event(leader)) { | 1030 | if (is_x86_event(leader)) { |
1010 | if (n >= max_count) | 1031 | if (n >= max_count) |
@@ -2241,6 +2262,17 @@ static int x86_pmu_check_period(struct perf_event *event, u64 value) | |||
2241 | return 0; | 2262 | return 0; |
2242 | } | 2263 | } |
2243 | 2264 | ||
2265 | static int x86_pmu_aux_output_match(struct perf_event *event) | ||
2266 | { | ||
2267 | if (!(pmu.capabilities & PERF_PMU_CAP_AUX_OUTPUT)) | ||
2268 | return 0; | ||
2269 | |||
2270 | if (x86_pmu.aux_output_match) | ||
2271 | return x86_pmu.aux_output_match(event); | ||
2272 | |||
2273 | return 0; | ||
2274 | } | ||
2275 | |||
2244 | static struct pmu pmu = { | 2276 | static struct pmu pmu = { |
2245 | .pmu_enable = x86_pmu_enable, | 2277 | .pmu_enable = x86_pmu_enable, |
2246 | .pmu_disable = x86_pmu_disable, | 2278 | .pmu_disable = x86_pmu_disable, |
@@ -2266,6 +2298,8 @@ static struct pmu pmu = { | |||
2266 | .sched_task = x86_pmu_sched_task, | 2298 | .sched_task = x86_pmu_sched_task, |
2267 | .task_ctx_size = sizeof(struct x86_perf_task_context), | 2299 | .task_ctx_size = sizeof(struct x86_perf_task_context), |
2268 | .check_period = x86_pmu_check_period, | 2300 | .check_period = x86_pmu_check_period, |
2301 | |||
2302 | .aux_output_match = x86_pmu_aux_output_match, | ||
2269 | }; | 2303 | }; |
2270 | 2304 | ||
2271 | void arch_perf_update_userpage(struct perf_event *event, | 2305 | void arch_perf_update_userpage(struct perf_event *event, |
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 648260b5f367..28459f4b795a 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/cpufeature.h> | 18 | #include <asm/cpufeature.h> |
19 | #include <asm/hardirq.h> | 19 | #include <asm/hardirq.h> |
20 | #include <asm/intel-family.h> | 20 | #include <asm/intel-family.h> |
21 | #include <asm/intel_pt.h> | ||
21 | #include <asm/apic.h> | 22 | #include <asm/apic.h> |
22 | #include <asm/cpu_device_id.h> | 23 | #include <asm/cpu_device_id.h> |
23 | 24 | ||
@@ -3298,6 +3299,13 @@ static int intel_pmu_hw_config(struct perf_event *event) | |||
3298 | } | 3299 | } |
3299 | } | 3300 | } |
3300 | 3301 | ||
3302 | if (event->attr.aux_output) { | ||
3303 | if (!event->attr.precise_ip) | ||
3304 | return -EINVAL; | ||
3305 | |||
3306 | event->hw.flags |= PERF_X86_EVENT_PEBS_VIA_PT; | ||
3307 | } | ||
3308 | |||
3301 | if (event->attr.type != PERF_TYPE_RAW) | 3309 | if (event->attr.type != PERF_TYPE_RAW) |
3302 | return 0; | 3310 | return 0; |
3303 | 3311 | ||
@@ -3811,6 +3819,14 @@ static int intel_pmu_check_period(struct perf_event *event, u64 value) | |||
3811 | return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0; | 3819 | return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0; |
3812 | } | 3820 | } |
3813 | 3821 | ||
3822 | static int intel_pmu_aux_output_match(struct perf_event *event) | ||
3823 | { | ||
3824 | if (!x86_pmu.intel_cap.pebs_output_pt_available) | ||
3825 | return 0; | ||
3826 | |||
3827 | return is_intel_pt_event(event); | ||
3828 | } | ||
3829 | |||
3814 | PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); | 3830 | PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); |
3815 | 3831 | ||
3816 | PMU_FORMAT_ATTR(ldlat, "config1:0-15"); | 3832 | PMU_FORMAT_ATTR(ldlat, "config1:0-15"); |
@@ -3935,6 +3951,8 @@ static __initconst const struct x86_pmu intel_pmu = { | |||
3935 | .sched_task = intel_pmu_sched_task, | 3951 | .sched_task = intel_pmu_sched_task, |
3936 | 3952 | ||
3937 | .check_period = intel_pmu_check_period, | 3953 | .check_period = intel_pmu_check_period, |
3954 | |||
3955 | .aux_output_match = intel_pmu_aux_output_match, | ||
3938 | }; | 3956 | }; |
3939 | 3957 | ||
3940 | static __init void intel_clovertown_quirk(void) | 3958 | static __init void intel_clovertown_quirk(void) |
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index f1269e804e9b..ce83950036c5 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c | |||
@@ -902,6 +902,9 @@ struct event_constraint *intel_pebs_constraints(struct perf_event *event) | |||
902 | */ | 902 | */ |
903 | static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc) | 903 | static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc) |
904 | { | 904 | { |
905 | if (cpuc->n_pebs == cpuc->n_pebs_via_pt) | ||
906 | return false; | ||
907 | |||
905 | return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs); | 908 | return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs); |
906 | } | 909 | } |
907 | 910 | ||
@@ -919,6 +922,9 @@ static inline void pebs_update_threshold(struct cpu_hw_events *cpuc) | |||
919 | u64 threshold; | 922 | u64 threshold; |
920 | int reserved; | 923 | int reserved; |
921 | 924 | ||
925 | if (cpuc->n_pebs_via_pt) | ||
926 | return; | ||
927 | |||
922 | if (x86_pmu.flags & PMU_FL_PEBS_ALL) | 928 | if (x86_pmu.flags & PMU_FL_PEBS_ALL) |
923 | reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed; | 929 | reserved = x86_pmu.max_pebs_events + x86_pmu.num_counters_fixed; |
924 | else | 930 | else |
@@ -1059,10 +1065,40 @@ void intel_pmu_pebs_add(struct perf_event *event) | |||
1059 | cpuc->n_pebs++; | 1065 | cpuc->n_pebs++; |
1060 | if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) | 1066 | if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) |
1061 | cpuc->n_large_pebs++; | 1067 | cpuc->n_large_pebs++; |
1068 | if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT) | ||
1069 | cpuc->n_pebs_via_pt++; | ||
1062 | 1070 | ||
1063 | pebs_update_state(needed_cb, cpuc, event, true); | 1071 | pebs_update_state(needed_cb, cpuc, event, true); |
1064 | } | 1072 | } |
1065 | 1073 | ||
1074 | static void intel_pmu_pebs_via_pt_disable(struct perf_event *event) | ||
1075 | { | ||
1076 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); | ||
1077 | |||
1078 | if (!is_pebs_pt(event)) | ||
1079 | return; | ||
1080 | |||
1081 | if (!(cpuc->pebs_enabled & ~PEBS_VIA_PT_MASK)) | ||
1082 | cpuc->pebs_enabled &= ~PEBS_VIA_PT_MASK; | ||
1083 | } | ||
1084 | |||
1085 | static void intel_pmu_pebs_via_pt_enable(struct perf_event *event) | ||
1086 | { | ||
1087 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); | ||
1088 | struct hw_perf_event *hwc = &event->hw; | ||
1089 | struct debug_store *ds = cpuc->ds; | ||
1090 | |||
1091 | if (!is_pebs_pt(event)) | ||
1092 | return; | ||
1093 | |||
1094 | if (!(event->hw.flags & PERF_X86_EVENT_LARGE_PEBS)) | ||
1095 | cpuc->pebs_enabled |= PEBS_PMI_AFTER_EACH_RECORD; | ||
1096 | |||
1097 | cpuc->pebs_enabled |= PEBS_OUTPUT_PT; | ||
1098 | |||
1099 | wrmsrl(MSR_RELOAD_PMC0 + hwc->idx, ds->pebs_event_reset[hwc->idx]); | ||
1100 | } | ||
1101 | |||
1066 | void intel_pmu_pebs_enable(struct perf_event *event) | 1102 | void intel_pmu_pebs_enable(struct perf_event *event) |
1067 | { | 1103 | { |
1068 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); | 1104 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); |
@@ -1100,6 +1136,8 @@ void intel_pmu_pebs_enable(struct perf_event *event) | |||
1100 | } else { | 1136 | } else { |
1101 | ds->pebs_event_reset[hwc->idx] = 0; | 1137 | ds->pebs_event_reset[hwc->idx] = 0; |
1102 | } | 1138 | } |
1139 | |||
1140 | intel_pmu_pebs_via_pt_enable(event); | ||
1103 | } | 1141 | } |
1104 | 1142 | ||
1105 | void intel_pmu_pebs_del(struct perf_event *event) | 1143 | void intel_pmu_pebs_del(struct perf_event *event) |
@@ -1111,6 +1149,8 @@ void intel_pmu_pebs_del(struct perf_event *event) | |||
1111 | cpuc->n_pebs--; | 1149 | cpuc->n_pebs--; |
1112 | if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) | 1150 | if (hwc->flags & PERF_X86_EVENT_LARGE_PEBS) |
1113 | cpuc->n_large_pebs--; | 1151 | cpuc->n_large_pebs--; |
1152 | if (hwc->flags & PERF_X86_EVENT_PEBS_VIA_PT) | ||
1153 | cpuc->n_pebs_via_pt--; | ||
1114 | 1154 | ||
1115 | pebs_update_state(needed_cb, cpuc, event, false); | 1155 | pebs_update_state(needed_cb, cpuc, event, false); |
1116 | } | 1156 | } |
@@ -1120,7 +1160,8 @@ void intel_pmu_pebs_disable(struct perf_event *event) | |||
1120 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); | 1160 | struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); |
1121 | struct hw_perf_event *hwc = &event->hw; | 1161 | struct hw_perf_event *hwc = &event->hw; |
1122 | 1162 | ||
1123 | if (cpuc->n_pebs == cpuc->n_large_pebs) | 1163 | if (cpuc->n_pebs == cpuc->n_large_pebs && |
1164 | cpuc->n_pebs != cpuc->n_pebs_via_pt) | ||
1124 | intel_pmu_drain_pebs_buffer(); | 1165 | intel_pmu_drain_pebs_buffer(); |
1125 | 1166 | ||
1126 | cpuc->pebs_enabled &= ~(1ULL << hwc->idx); | 1167 | cpuc->pebs_enabled &= ~(1ULL << hwc->idx); |
@@ -1131,6 +1172,8 @@ void intel_pmu_pebs_disable(struct perf_event *event) | |||
1131 | else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) | 1172 | else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) |
1132 | cpuc->pebs_enabled &= ~(1ULL << 63); | 1173 | cpuc->pebs_enabled &= ~(1ULL << 63); |
1133 | 1174 | ||
1175 | intel_pmu_pebs_via_pt_disable(event); | ||
1176 | |||
1134 | if (cpuc->enabled) | 1177 | if (cpuc->enabled) |
1135 | wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); | 1178 | wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); |
1136 | 1179 | ||
@@ -2031,6 +2074,12 @@ void __init intel_ds_init(void) | |||
2031 | PERF_SAMPLE_REGS_INTR); | 2074 | PERF_SAMPLE_REGS_INTR); |
2032 | } | 2075 | } |
2033 | pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); | 2076 | pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); |
2077 | |||
2078 | if (x86_pmu.intel_cap.pebs_output_pt_available) { | ||
2079 | pr_cont("PEBS-via-PT, "); | ||
2080 | x86_get_pmu()->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; | ||
2081 | } | ||
2082 | |||
2034 | break; | 2083 | break; |
2035 | 2084 | ||
2036 | default: | 2085 | default: |
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index fa43d90799cc..b1bb4d28e0be 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c | |||
@@ -1564,6 +1564,11 @@ void cpu_emergency_stop_pt(void) | |||
1564 | pt_event_stop(pt->handle.event, PERF_EF_UPDATE); | 1564 | pt_event_stop(pt->handle.event, PERF_EF_UPDATE); |
1565 | } | 1565 | } |
1566 | 1566 | ||
1567 | int is_intel_pt_event(struct perf_event *event) | ||
1568 | { | ||
1569 | return event->pmu == &pt_pmu.pmu; | ||
1570 | } | ||
1571 | |||
1567 | static __init int pt_init(void) | 1572 | static __init int pt_init(void) |
1568 | { | 1573 | { |
1569 | int ret, cpu, prior_warn = 0; | 1574 | int ret, cpu, prior_warn = 0; |
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 8751008fc170..ecacfbf4ebc1 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h | |||
@@ -76,6 +76,7 @@ static inline bool constraint_match(struct event_constraint *c, u64 ecode) | |||
76 | #define PERF_X86_EVENT_EXCL_ACCT 0x0100 /* accounted EXCL event */ | 76 | #define PERF_X86_EVENT_EXCL_ACCT 0x0100 /* accounted EXCL event */ |
77 | #define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */ | 77 | #define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */ |
78 | #define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */ | 78 | #define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */ |
79 | #define PERF_X86_EVENT_PEBS_VIA_PT 0x0800 /* use PT buffer for PEBS */ | ||
79 | 80 | ||
80 | struct amd_nb { | 81 | struct amd_nb { |
81 | int nb_id; /* NorthBridge id */ | 82 | int nb_id; /* NorthBridge id */ |
@@ -85,6 +86,11 @@ struct amd_nb { | |||
85 | }; | 86 | }; |
86 | 87 | ||
87 | #define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1) | 88 | #define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1) |
89 | #define PEBS_PMI_AFTER_EACH_RECORD BIT_ULL(60) | ||
90 | #define PEBS_OUTPUT_OFFSET 61 | ||
91 | #define PEBS_OUTPUT_MASK (3ull << PEBS_OUTPUT_OFFSET) | ||
92 | #define PEBS_OUTPUT_PT (1ull << PEBS_OUTPUT_OFFSET) | ||
93 | #define PEBS_VIA_PT_MASK (PEBS_OUTPUT_PT | PEBS_PMI_AFTER_EACH_RECORD) | ||
88 | 94 | ||
89 | /* | 95 | /* |
90 | * Flags PEBS can handle without an PMI. | 96 | * Flags PEBS can handle without an PMI. |
@@ -211,6 +217,8 @@ struct cpu_hw_events { | |||
211 | u64 pebs_enabled; | 217 | u64 pebs_enabled; |
212 | int n_pebs; | 218 | int n_pebs; |
213 | int n_large_pebs; | 219 | int n_large_pebs; |
220 | int n_pebs_via_pt; | ||
221 | int pebs_output; | ||
214 | 222 | ||
215 | /* Current super set of events hardware configuration */ | 223 | /* Current super set of events hardware configuration */ |
216 | u64 pebs_data_cfg; | 224 | u64 pebs_data_cfg; |
@@ -510,6 +518,8 @@ union perf_capabilities { | |||
510 | */ | 518 | */ |
511 | u64 full_width_write:1; | 519 | u64 full_width_write:1; |
512 | u64 pebs_baseline:1; | 520 | u64 pebs_baseline:1; |
521 | u64 pebs_metrics_available:1; | ||
522 | u64 pebs_output_pt_available:1; | ||
513 | }; | 523 | }; |
514 | u64 capabilities; | 524 | u64 capabilities; |
515 | }; | 525 | }; |
@@ -692,6 +702,8 @@ struct x86_pmu { | |||
692 | * Check period value for PERF_EVENT_IOC_PERIOD ioctl. | 702 | * Check period value for PERF_EVENT_IOC_PERIOD ioctl. |
693 | */ | 703 | */ |
694 | int (*check_period) (struct perf_event *event, u64 period); | 704 | int (*check_period) (struct perf_event *event, u64 period); |
705 | |||
706 | int (*aux_output_match) (struct perf_event *event); | ||
695 | }; | 707 | }; |
696 | 708 | ||
697 | struct x86_perf_task_context { | 709 | struct x86_perf_task_context { |
@@ -901,6 +913,11 @@ static inline int amd_pmu_init(void) | |||
901 | 913 | ||
902 | #endif /* CONFIG_CPU_SUP_AMD */ | 914 | #endif /* CONFIG_CPU_SUP_AMD */ |
903 | 915 | ||
916 | static inline int is_pebs_pt(struct perf_event *event) | ||
917 | { | ||
918 | return !!(event->hw.flags & PERF_X86_EVENT_PEBS_VIA_PT); | ||
919 | } | ||
920 | |||
904 | #ifdef CONFIG_CPU_SUP_INTEL | 921 | #ifdef CONFIG_CPU_SUP_INTEL |
905 | 922 | ||
906 | static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period) | 923 | static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period) |
diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h index 634f99b1dc22..423b788f495e 100644 --- a/arch/x86/include/asm/intel_pt.h +++ b/arch/x86/include/asm/intel_pt.h | |||
@@ -28,10 +28,12 @@ enum pt_capabilities { | |||
28 | void cpu_emergency_stop_pt(void); | 28 | void cpu_emergency_stop_pt(void); |
29 | extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap); | 29 | extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap); |
30 | extern u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities cap); | 30 | extern u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities cap); |
31 | extern int is_intel_pt_event(struct perf_event *event); | ||
31 | #else | 32 | #else |
32 | static inline void cpu_emergency_stop_pt(void) {} | 33 | static inline void cpu_emergency_stop_pt(void) {} |
33 | static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; } | 34 | static inline u32 intel_pt_validate_hw_cap(enum pt_capabilities cap) { return 0; } |
34 | static inline u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities capability) { return 0; } | 35 | static inline u32 intel_pt_validate_cap(u32 *caps, enum pt_capabilities capability) { return 0; } |
36 | static inline int is_intel_pt_event(struct perf_event *event) { return 0; } | ||
35 | #endif | 37 | #endif |
36 | 38 | ||
37 | #endif /* _ASM_X86_INTEL_PT_H */ | 39 | #endif /* _ASM_X86_INTEL_PT_H */ |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 271d837d69a8..de753206b427 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -375,6 +375,10 @@ | |||
375 | /* Alternative perfctr range with full access. */ | 375 | /* Alternative perfctr range with full access. */ |
376 | #define MSR_IA32_PMC0 0x000004c1 | 376 | #define MSR_IA32_PMC0 0x000004c1 |
377 | 377 | ||
378 | /* Auto-reload via MSR instead of DS area */ | ||
379 | #define MSR_RELOAD_PMC0 0x000014c1 | ||
380 | #define MSR_RELOAD_FIXED_CTR0 0x00001309 | ||
381 | |||
378 | /* AMD64 MSRs. Not complete. See the architecture manual for a more | 382 | /* AMD64 MSRs. Not complete. See the architecture manual for a more |
379 | complete list. */ | 383 | complete list. */ |
380 | 384 | ||