diff options
Diffstat (limited to 'tools')
87 files changed, 2764 insertions, 387 deletions
diff --git a/tools/Makefile b/tools/Makefile index f10b64d8c674..daa8fb3e4363 100644 --- a/tools/Makefile +++ b/tools/Makefile | |||
@@ -85,7 +85,7 @@ tmon: FORCE | |||
85 | freefall: FORCE | 85 | freefall: FORCE |
86 | $(call descend,laptop/$@) | 86 | $(call descend,laptop/$@) |
87 | 87 | ||
88 | all: acpi cgroup cpupower hv firewire lguest \ | 88 | all: acpi cgroup cpupower gpio hv firewire lguest \ |
89 | perf selftests turbostat usb \ | 89 | perf selftests turbostat usb \ |
90 | virtio vm net x86_energy_perf_policy \ | 90 | virtio vm net x86_energy_perf_policy \ |
91 | tmon freefall objtool | 91 | tmon freefall objtool |
@@ -96,7 +96,7 @@ acpi_install: | |||
96 | cpupower_install: | 96 | cpupower_install: |
97 | $(call descend,power/$(@:_install=),install) | 97 | $(call descend,power/$(@:_install=),install) |
98 | 98 | ||
99 | cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: | 99 | cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: |
100 | $(call descend,$(@:_install=),install) | 100 | $(call descend,$(@:_install=),install) |
101 | 101 | ||
102 | selftests_install: | 102 | selftests_install: |
@@ -114,7 +114,8 @@ freefall_install: | |||
114 | kvm_stat_install: | 114 | kvm_stat_install: |
115 | $(call descend,kvm/$(@:_install=),install) | 115 | $(call descend,kvm/$(@:_install=),install) |
116 | 116 | ||
117 | install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ | 117 | install: acpi_install cgroup_install cpupower_install gpio_install \ |
118 | hv_install firewire_install lguest_install \ | ||
118 | perf_install selftests_install turbostat_install usb_install \ | 119 | perf_install selftests_install turbostat_install usb_install \ |
119 | virtio_install vm_install net_install x86_energy_perf_policy_install \ | 120 | virtio_install vm_install net_install x86_energy_perf_policy_install \ |
120 | tmon_install freefall_install objtool_install kvm_stat_install | 121 | tmon_install freefall_install objtool_install kvm_stat_install |
diff --git a/tools/gpio/Build b/tools/gpio/Build new file mode 100644 index 000000000000..620c1937d957 --- /dev/null +++ b/tools/gpio/Build | |||
@@ -0,0 +1,3 @@ | |||
1 | lsgpio-y += lsgpio.o gpio-utils.o | ||
2 | gpio-hammer-y += gpio-hammer.o gpio-utils.o | ||
3 | gpio-event-mon-y += gpio-event-mon.o gpio-utils.o | ||
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index c155d6bc47a7..250a891e6ef0 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile | |||
@@ -1,12 +1,75 @@ | |||
1 | include ../scripts/Makefile.include | ||
2 | |||
3 | bindir ?= /usr/bin | ||
4 | |||
5 | ifeq ($(srctree),) | ||
6 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | ||
7 | srctree := $(patsubst %/,%,$(dir $(srctree))) | ||
8 | endif | ||
9 | |||
10 | # Do not use make's built-in rules | ||
11 | # (this improves performance and avoids hard-to-debug behaviour); | ||
12 | MAKEFLAGS += -r | ||
13 | |||
1 | CC = $(CROSS_COMPILE)gcc | 14 | CC = $(CROSS_COMPILE)gcc |
2 | CFLAGS += -O2 -Wall -g -D_GNU_SOURCE | 15 | LD = $(CROSS_COMPILE)ld |
16 | CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include | ||
17 | |||
18 | ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon | ||
19 | ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) | ||
20 | |||
21 | all: $(ALL_PROGRAMS) | ||
3 | 22 | ||
4 | all: lsgpio | 23 | export srctree OUTPUT CC LD CFLAGS |
24 | include $(srctree)/tools/build/Makefile.include | ||
5 | 25 | ||
6 | lsgpio: lsgpio.o gpio-utils.o | 26 | # |
27 | # We need the following to be outside of kernel tree | ||
28 | # | ||
29 | $(OUTPUT)include/linux/gpio.h: ../../include/uapi/linux/gpio.h | ||
30 | mkdir -p $(OUTPUT)include/linux 2>&1 || true | ||
31 | ln -sf $(CURDIR)/../../include/uapi/linux/gpio.h $@ | ||
7 | 32 | ||
8 | %.o: %.c gpio-utils.h | 33 | prepare: $(OUTPUT)include/linux/gpio.h |
34 | |||
35 | # | ||
36 | # lsgpio | ||
37 | # | ||
38 | LSGPIO_IN := $(OUTPUT)lsgpio-in.o | ||
39 | $(LSGPIO_IN): prepare FORCE | ||
40 | $(Q)$(MAKE) $(build)=lsgpio | ||
41 | $(OUTPUT)lsgpio: $(LSGPIO_IN) | ||
42 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
43 | |||
44 | # | ||
45 | # gpio-hammer | ||
46 | # | ||
47 | GPIO_HAMMER_IN := $(OUTPUT)gpio-hammer-in.o | ||
48 | $(GPIO_HAMMER_IN): prepare FORCE | ||
49 | $(Q)$(MAKE) $(build)=gpio-hammer | ||
50 | $(OUTPUT)gpio-hammer: $(GPIO_HAMMER_IN) | ||
51 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
52 | |||
53 | # | ||
54 | # gpio-event-mon | ||
55 | # | ||
56 | GPIO_EVENT_MON_IN := $(OUTPUT)gpio-event-mon-in.o | ||
57 | $(GPIO_EVENT_MON_IN): prepare FORCE | ||
58 | $(Q)$(MAKE) $(build)=gpio-event-mon | ||
59 | $(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN) | ||
60 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ | ||
9 | 61 | ||
10 | .PHONY: clean | ||
11 | clean: | 62 | clean: |
12 | rm -f *.o lsgpio | 63 | rm -f $(ALL_PROGRAMS) |
64 | rm -f $(OUTPUT)include/linux/gpio.h | ||
65 | find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete | ||
66 | |||
67 | install: $(ALL_PROGRAMS) | ||
68 | install -d -m 755 $(DESTDIR)$(bindir); \ | ||
69 | for program in $(ALL_PROGRAMS); do \ | ||
70 | install $$program $(DESTDIR)$(bindir); \ | ||
71 | done | ||
72 | |||
73 | FORCE: | ||
74 | |||
75 | .PHONY: all install clean FORCE prepare | ||
diff --git a/tools/gpio/gpio-event-mon.c b/tools/gpio/gpio-event-mon.c new file mode 100644 index 000000000000..448ed96b3b4f --- /dev/null +++ b/tools/gpio/gpio-event-mon.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * gpio-hammer - example swiss army knife to shake GPIO lines on a system | ||
3 | * | ||
4 | * Copyright (C) 2016 Linus Walleij | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * Usage: | ||
11 | * gpio-event-mon -n <device-name> -o <offset> | ||
12 | */ | ||
13 | |||
14 | #include <unistd.h> | ||
15 | #include <stdlib.h> | ||
16 | #include <stdbool.h> | ||
17 | #include <stdio.h> | ||
18 | #include <dirent.h> | ||
19 | #include <errno.h> | ||
20 | #include <string.h> | ||
21 | #include <poll.h> | ||
22 | #include <fcntl.h> | ||
23 | #include <getopt.h> | ||
24 | #include <inttypes.h> | ||
25 | #include <sys/ioctl.h> | ||
26 | #include <linux/gpio.h> | ||
27 | |||
28 | int monitor_device(const char *device_name, | ||
29 | unsigned int line, | ||
30 | u_int32_t handleflags, | ||
31 | u_int32_t eventflags, | ||
32 | unsigned int loops) | ||
33 | { | ||
34 | struct gpioevent_request req; | ||
35 | struct gpiohandle_data data; | ||
36 | char *chrdev_name; | ||
37 | int fd; | ||
38 | int ret; | ||
39 | int i = 0; | ||
40 | |||
41 | ret = asprintf(&chrdev_name, "/dev/%s", device_name); | ||
42 | if (ret < 0) | ||
43 | return -ENOMEM; | ||
44 | |||
45 | fd = open(chrdev_name, 0); | ||
46 | if (fd == -1) { | ||
47 | ret = -errno; | ||
48 | fprintf(stderr, "Failed to open %s\n", chrdev_name); | ||
49 | goto exit_close_error; | ||
50 | } | ||
51 | |||
52 | req.lineoffset = line; | ||
53 | req.handleflags = handleflags; | ||
54 | req.eventflags = eventflags; | ||
55 | strcpy(req.consumer_label, "gpio-event-mon"); | ||
56 | |||
57 | ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req); | ||
58 | if (ret == -1) { | ||
59 | ret = -errno; | ||
60 | fprintf(stderr, "Failed to issue GET EVENT " | ||
61 | "IOCTL (%d)\n", | ||
62 | ret); | ||
63 | goto exit_close_error; | ||
64 | } | ||
65 | |||
66 | /* Read initial states */ | ||
67 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
68 | if (ret == -1) { | ||
69 | ret = -errno; | ||
70 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
71 | "VALUES IOCTL (%d)\n", | ||
72 | ret); | ||
73 | goto exit_close_error; | ||
74 | } | ||
75 | |||
76 | fprintf(stdout, "Monitoring line %d on %s\n", line, device_name); | ||
77 | fprintf(stdout, "Initial line value: %d\n", data.values[0]); | ||
78 | |||
79 | while (1) { | ||
80 | struct gpioevent_data event; | ||
81 | |||
82 | ret = read(req.fd, &event, sizeof(event)); | ||
83 | if (ret == -1) { | ||
84 | if (errno == -EAGAIN) { | ||
85 | fprintf(stderr, "nothing available\n"); | ||
86 | continue; | ||
87 | } else { | ||
88 | ret = -errno; | ||
89 | fprintf(stderr, "Failed to read event (%d)\n", | ||
90 | ret); | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | if (ret != sizeof(event)) { | ||
96 | fprintf(stderr, "Reading event failed\n"); | ||
97 | ret = -EIO; | ||
98 | break; | ||
99 | } | ||
100 | fprintf(stdout, "GPIO EVENT %" PRIu64 ": ", event.timestamp); | ||
101 | switch (event.id) { | ||
102 | case GPIOEVENT_EVENT_RISING_EDGE: | ||
103 | fprintf(stdout, "rising edge"); | ||
104 | break; | ||
105 | case GPIOEVENT_EVENT_FALLING_EDGE: | ||
106 | fprintf(stdout, "falling edge"); | ||
107 | break; | ||
108 | default: | ||
109 | fprintf(stdout, "unknown event"); | ||
110 | } | ||
111 | fprintf(stdout, "\n"); | ||
112 | |||
113 | i++; | ||
114 | if (i == loops) | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | exit_close_error: | ||
119 | if (close(fd) == -1) | ||
120 | perror("Failed to close GPIO character device file"); | ||
121 | free(chrdev_name); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | void print_usage(void) | ||
126 | { | ||
127 | fprintf(stderr, "Usage: gpio-event-mon [options]...\n" | ||
128 | "Listen to events on GPIO lines, 0->1 1->0\n" | ||
129 | " -n <name> Listen on GPIOs on a named device (must be stated)\n" | ||
130 | " -o <n> Offset to monitor\n" | ||
131 | " -d Set line as open drain\n" | ||
132 | " -s Set line as open source\n" | ||
133 | " -r Listen for rising edges\n" | ||
134 | " -f Listen for falling edges\n" | ||
135 | " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" | ||
136 | " -? This helptext\n" | ||
137 | "\n" | ||
138 | "Example:\n" | ||
139 | "gpio-event-mon -n gpiochip0 -o 4 -r -f\n" | ||
140 | ); | ||
141 | } | ||
142 | |||
143 | int main(int argc, char **argv) | ||
144 | { | ||
145 | const char *device_name = NULL; | ||
146 | unsigned int line = -1; | ||
147 | unsigned int loops = 0; | ||
148 | u_int32_t handleflags = GPIOHANDLE_REQUEST_INPUT; | ||
149 | u_int32_t eventflags = 0; | ||
150 | int c; | ||
151 | |||
152 | while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) { | ||
153 | switch (c) { | ||
154 | case 'c': | ||
155 | loops = strtoul(optarg, NULL, 10); | ||
156 | break; | ||
157 | case 'n': | ||
158 | device_name = optarg; | ||
159 | break; | ||
160 | case 'o': | ||
161 | line = strtoul(optarg, NULL, 10); | ||
162 | break; | ||
163 | case 'd': | ||
164 | handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN; | ||
165 | break; | ||
166 | case 's': | ||
167 | handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE; | ||
168 | break; | ||
169 | case 'r': | ||
170 | eventflags |= GPIOEVENT_REQUEST_RISING_EDGE; | ||
171 | break; | ||
172 | case 'f': | ||
173 | eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE; | ||
174 | break; | ||
175 | case '?': | ||
176 | print_usage(); | ||
177 | return -1; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | if (!device_name || line == -1) { | ||
182 | print_usage(); | ||
183 | return -1; | ||
184 | } | ||
185 | if (!eventflags) { | ||
186 | printf("No flags specified, listening on both rising and " | ||
187 | "falling edges\n"); | ||
188 | eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; | ||
189 | } | ||
190 | return monitor_device(device_name, line, handleflags, | ||
191 | eventflags, loops); | ||
192 | } | ||
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c new file mode 100644 index 000000000000..37b3f141053d --- /dev/null +++ b/tools/gpio/gpio-hammer.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * gpio-hammer - example swiss army knife to shake GPIO lines on a system | ||
3 | * | ||
4 | * Copyright (C) 2016 Linus Walleij | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * Usage: | ||
11 | * gpio-hammer -n <device-name> -o <offset1> -o <offset2> | ||
12 | */ | ||
13 | |||
14 | #include <unistd.h> | ||
15 | #include <stdlib.h> | ||
16 | #include <stdbool.h> | ||
17 | #include <stdio.h> | ||
18 | #include <dirent.h> | ||
19 | #include <errno.h> | ||
20 | #include <string.h> | ||
21 | #include <poll.h> | ||
22 | #include <fcntl.h> | ||
23 | #include <getopt.h> | ||
24 | #include <sys/ioctl.h> | ||
25 | #include <linux/gpio.h> | ||
26 | |||
27 | int hammer_device(const char *device_name, unsigned int *lines, int nlines, | ||
28 | unsigned int loops) | ||
29 | { | ||
30 | struct gpiohandle_request req; | ||
31 | struct gpiohandle_data data; | ||
32 | char *chrdev_name; | ||
33 | char swirr[] = "-\\|/"; | ||
34 | int fd; | ||
35 | int ret; | ||
36 | int i, j; | ||
37 | unsigned int iteration = 0; | ||
38 | |||
39 | ret = asprintf(&chrdev_name, "/dev/%s", device_name); | ||
40 | if (ret < 0) | ||
41 | return -ENOMEM; | ||
42 | |||
43 | fd = open(chrdev_name, 0); | ||
44 | if (fd == -1) { | ||
45 | ret = -errno; | ||
46 | fprintf(stderr, "Failed to open %s\n", chrdev_name); | ||
47 | goto exit_close_error; | ||
48 | } | ||
49 | |||
50 | /* Request lines as output */ | ||
51 | for (i = 0; i < nlines; i++) | ||
52 | req.lineoffsets[i] = lines[i]; | ||
53 | req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */ | ||
54 | strcpy(req.consumer_label, "gpio-hammer"); | ||
55 | req.lines = nlines; | ||
56 | ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); | ||
57 | if (ret == -1) { | ||
58 | ret = -errno; | ||
59 | fprintf(stderr, "Failed to issue GET LINEHANDLE " | ||
60 | "IOCTL (%d)\n", | ||
61 | ret); | ||
62 | goto exit_close_error; | ||
63 | } | ||
64 | |||
65 | /* Read initial states */ | ||
66 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
67 | if (ret == -1) { | ||
68 | ret = -errno; | ||
69 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
70 | "VALUES IOCTL (%d)\n", | ||
71 | ret); | ||
72 | goto exit_close_error; | ||
73 | } | ||
74 | fprintf(stdout, "Hammer lines ["); | ||
75 | for (i = 0; i < nlines; i++) { | ||
76 | fprintf(stdout, "%d", lines[i]); | ||
77 | if (i != (nlines - 1)) | ||
78 | fprintf(stdout, ", "); | ||
79 | } | ||
80 | fprintf(stdout, "] on %s, initial states: [", device_name); | ||
81 | for (i = 0; i < nlines; i++) { | ||
82 | fprintf(stdout, "%d", data.values[i]); | ||
83 | if (i != (nlines - 1)) | ||
84 | fprintf(stdout, ", "); | ||
85 | } | ||
86 | fprintf(stdout, "]\n"); | ||
87 | |||
88 | /* Hammertime! */ | ||
89 | j = 0; | ||
90 | while (1) { | ||
91 | /* Invert all lines so we blink */ | ||
92 | for (i = 0; i < nlines; i++) | ||
93 | data.values[i] = !data.values[i]; | ||
94 | |||
95 | ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data); | ||
96 | if (ret == -1) { | ||
97 | ret = -errno; | ||
98 | fprintf(stderr, "Failed to issue GPIOHANDLE SET LINE " | ||
99 | "VALUES IOCTL (%d)\n", | ||
100 | ret); | ||
101 | goto exit_close_error; | ||
102 | } | ||
103 | /* Re-read values to get status */ | ||
104 | ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); | ||
105 | if (ret == -1) { | ||
106 | ret = -errno; | ||
107 | fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE " | ||
108 | "VALUES IOCTL (%d)\n", | ||
109 | ret); | ||
110 | goto exit_close_error; | ||
111 | } | ||
112 | |||
113 | fprintf(stdout, "[%c] ", swirr[j]); | ||
114 | j++; | ||
115 | if (j == sizeof(swirr)-1) | ||
116 | j = 0; | ||
117 | |||
118 | fprintf(stdout, "["); | ||
119 | for (i = 0; i < nlines; i++) { | ||
120 | fprintf(stdout, "%d: %d", lines[i], data.values[i]); | ||
121 | if (i != (nlines - 1)) | ||
122 | fprintf(stdout, ", "); | ||
123 | } | ||
124 | fprintf(stdout, "]\r"); | ||
125 | fflush(stdout); | ||
126 | sleep(1); | ||
127 | iteration++; | ||
128 | if (loops && iteration == loops) | ||
129 | break; | ||
130 | } | ||
131 | fprintf(stdout, "\n"); | ||
132 | ret = 0; | ||
133 | |||
134 | exit_close_error: | ||
135 | if (close(fd) == -1) | ||
136 | perror("Failed to close GPIO character device file"); | ||
137 | free(chrdev_name); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | void print_usage(void) | ||
142 | { | ||
143 | fprintf(stderr, "Usage: gpio-hammer [options]...\n" | ||
144 | "Hammer GPIO lines, 0->1->0->1...\n" | ||
145 | " -n <name> Hammer GPIOs on a named device (must be stated)\n" | ||
146 | " -o <n> Offset[s] to hammer, at least one, several can be stated\n" | ||
147 | " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" | ||
148 | " -? This helptext\n" | ||
149 | "\n" | ||
150 | "Example:\n" | ||
151 | "gpio-hammer -n gpiochip0 -o 4\n" | ||
152 | ); | ||
153 | } | ||
154 | |||
155 | int main(int argc, char **argv) | ||
156 | { | ||
157 | const char *device_name = NULL; | ||
158 | unsigned int lines[GPIOHANDLES_MAX]; | ||
159 | unsigned int loops = 0; | ||
160 | int nlines; | ||
161 | int c; | ||
162 | int i; | ||
163 | |||
164 | i = 0; | ||
165 | while ((c = getopt(argc, argv, "c:n:o:?")) != -1) { | ||
166 | switch (c) { | ||
167 | case 'c': | ||
168 | loops = strtoul(optarg, NULL, 10); | ||
169 | break; | ||
170 | case 'n': | ||
171 | device_name = optarg; | ||
172 | break; | ||
173 | case 'o': | ||
174 | lines[i] = strtoul(optarg, NULL, 10); | ||
175 | i++; | ||
176 | break; | ||
177 | case '?': | ||
178 | print_usage(); | ||
179 | return -1; | ||
180 | } | ||
181 | } | ||
182 | nlines = i; | ||
183 | |||
184 | if (!device_name || !nlines) { | ||
185 | print_usage(); | ||
186 | return -1; | ||
187 | } | ||
188 | return hammer_device(device_name, lines, nlines, loops); | ||
189 | } | ||
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh new file mode 100755 index 000000000000..8e960234013d --- /dev/null +++ b/tools/hv/bondvf.sh | |||
@@ -0,0 +1,193 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # This example script creates bonding network devices based on synthetic NIC | ||
4 | # (the virtual network adapter usually provided by Hyper-V) and the matching | ||
5 | # VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can | ||
6 | # function as one network device, and fail over to the synthetic NIC if VF is | ||
7 | # down. | ||
8 | # | ||
9 | # Usage: | ||
10 | # - After configured vSwitch and vNIC with SRIOV, start Linux virtual | ||
11 | # machine (VM) | ||
12 | # - Run this scripts on the VM. It will create configuration files in | ||
13 | # distro specific directory. | ||
14 | # - Reboot the VM, so that the bonding config are enabled. | ||
15 | # | ||
16 | # The config files are DHCP by default. You may edit them if you need to change | ||
17 | # to Static IP or change other settings. | ||
18 | # | ||
19 | |||
20 | sysdir=/sys/class/net | ||
21 | netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e} | ||
22 | bondcnt=0 | ||
23 | |||
24 | # Detect Distro | ||
25 | if [ -f /etc/redhat-release ]; | ||
26 | then | ||
27 | cfgdir=/etc/sysconfig/network-scripts | ||
28 | distro=redhat | ||
29 | elif grep -q 'Ubuntu' /etc/issue | ||
30 | then | ||
31 | cfgdir=/etc/network | ||
32 | distro=ubuntu | ||
33 | elif grep -q 'SUSE' /etc/issue | ||
34 | then | ||
35 | cfgdir=/etc/sysconfig/network | ||
36 | distro=suse | ||
37 | else | ||
38 | echo "Unsupported Distro" | ||
39 | exit 1 | ||
40 | fi | ||
41 | |||
42 | echo Detected Distro: $distro, or compatible | ||
43 | |||
44 | # Get a list of ethernet names | ||
45 | list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`) | ||
46 | eth_cnt=${#list_eth[@]} | ||
47 | |||
48 | echo List of net devices: | ||
49 | |||
50 | # Get the MAC addresses | ||
51 | for (( i=0; i < $eth_cnt; i++ )) | ||
52 | do | ||
53 | list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address` | ||
54 | echo ${list_eth[$i]}, ${list_mac[$i]} | ||
55 | done | ||
56 | |||
57 | # Find NIC with matching MAC | ||
58 | for (( i=0; i < $eth_cnt-1; i++ )) | ||
59 | do | ||
60 | for (( j=i+1; j < $eth_cnt; j++ )) | ||
61 | do | ||
62 | if [ "${list_mac[$i]}" = "${list_mac[$j]}" ] | ||
63 | then | ||
64 | list_match[$i]=${list_eth[$j]} | ||
65 | break | ||
66 | fi | ||
67 | done | ||
68 | done | ||
69 | |||
70 | function create_eth_cfg_redhat { | ||
71 | local fn=$cfgdir/ifcfg-$1 | ||
72 | |||
73 | rm -f $fn | ||
74 | echo DEVICE=$1 >>$fn | ||
75 | echo TYPE=Ethernet >>$fn | ||
76 | echo BOOTPROTO=none >>$fn | ||
77 | echo ONBOOT=yes >>$fn | ||
78 | echo NM_CONTROLLED=no >>$fn | ||
79 | echo PEERDNS=yes >>$fn | ||
80 | echo IPV6INIT=yes >>$fn | ||
81 | echo MASTER=$2 >>$fn | ||
82 | echo SLAVE=yes >>$fn | ||
83 | } | ||
84 | |||
85 | function create_eth_cfg_pri_redhat { | ||
86 | create_eth_cfg_redhat $1 $2 | ||
87 | } | ||
88 | |||
89 | function create_bond_cfg_redhat { | ||
90 | local fn=$cfgdir/ifcfg-$1 | ||
91 | |||
92 | rm -f $fn | ||
93 | echo DEVICE=$1 >>$fn | ||
94 | echo TYPE=Bond >>$fn | ||
95 | echo BOOTPROTO=dhcp >>$fn | ||
96 | echo ONBOOT=yes >>$fn | ||
97 | echo NM_CONTROLLED=no >>$fn | ||
98 | echo PEERDNS=yes >>$fn | ||
99 | echo IPV6INIT=yes >>$fn | ||
100 | echo BONDING_MASTER=yes >>$fn | ||
101 | echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn | ||
102 | } | ||
103 | |||
104 | function create_eth_cfg_ubuntu { | ||
105 | local fn=$cfgdir/interfaces | ||
106 | |||
107 | echo $'\n'auto $1 >>$fn | ||
108 | echo iface $1 inet manual >>$fn | ||
109 | echo bond-master $2 >>$fn | ||
110 | } | ||
111 | |||
112 | function create_eth_cfg_pri_ubuntu { | ||
113 | local fn=$cfgdir/interfaces | ||
114 | |||
115 | create_eth_cfg_ubuntu $1 $2 | ||
116 | echo bond-primary $1 >>$fn | ||
117 | } | ||
118 | |||
119 | function create_bond_cfg_ubuntu { | ||
120 | local fn=$cfgdir/interfaces | ||
121 | |||
122 | echo $'\n'auto $1 >>$fn | ||
123 | echo iface $1 inet dhcp >>$fn | ||
124 | echo bond-mode active-backup >>$fn | ||
125 | echo bond-miimon 100 >>$fn | ||
126 | echo bond-slaves none >>$fn | ||
127 | } | ||
128 | |||
129 | function create_eth_cfg_suse { | ||
130 | local fn=$cfgdir/ifcfg-$1 | ||
131 | |||
132 | rm -f $fn | ||
133 | echo BOOTPROTO=none >>$fn | ||
134 | echo STARTMODE=auto >>$fn | ||
135 | } | ||
136 | |||
137 | function create_eth_cfg_pri_suse { | ||
138 | create_eth_cfg_suse $1 | ||
139 | } | ||
140 | |||
141 | function create_bond_cfg_suse { | ||
142 | local fn=$cfgdir/ifcfg-$1 | ||
143 | |||
144 | rm -f $fn | ||
145 | echo BOOTPROTO=dhcp >>$fn | ||
146 | echo STARTMODE=auto >>$fn | ||
147 | echo BONDING_MASTER=yes >>$fn | ||
148 | echo BONDING_SLAVE_0=$2 >>$fn | ||
149 | echo BONDING_SLAVE_1=$3 >>$fn | ||
150 | echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn | ||
151 | } | ||
152 | |||
153 | function create_bond { | ||
154 | local bondname=bond$bondcnt | ||
155 | local primary | ||
156 | local secondary | ||
157 | |||
158 | local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null` | ||
159 | local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null` | ||
160 | |||
161 | if [ "$class_id1" = "$netvsc_cls" ] | ||
162 | then | ||
163 | primary=$2 | ||
164 | secondary=$1 | ||
165 | elif [ "$class_id2" = "$netvsc_cls" ] | ||
166 | then | ||
167 | primary=$1 | ||
168 | secondary=$2 | ||
169 | else | ||
170 | return 0 | ||
171 | fi | ||
172 | |||
173 | echo $'\nBond name:' $bondname | ||
174 | |||
175 | echo configuring $primary | ||
176 | create_eth_cfg_pri_$distro $primary $bondname | ||
177 | |||
178 | echo configuring $secondary | ||
179 | create_eth_cfg_$distro $secondary $bondname | ||
180 | |||
181 | echo creating: $bondname with primary slave: $primary | ||
182 | create_bond_cfg_$distro $bondname $primary $secondary | ||
183 | |||
184 | let bondcnt=bondcnt+1 | ||
185 | } | ||
186 | |||
187 | for (( i=0; i < $eth_cnt-1; i++ )) | ||
188 | do | ||
189 | if [ -n "${list_match[$i]}" ] | ||
190 | then | ||
191 | create_bond ${list_eth[$i]} ${list_match[$i]} | ||
192 | fi | ||
193 | done | ||
diff --git a/tools/lib/api/Build b/tools/lib/api/Build index 954c644f7ad9..6e2373db5598 100644 --- a/tools/lib/api/Build +++ b/tools/lib/api/Build | |||
@@ -2,3 +2,8 @@ libapi-y += fd/ | |||
2 | libapi-y += fs/ | 2 | libapi-y += fs/ |
3 | libapi-y += cpu.o | 3 | libapi-y += cpu.o |
4 | libapi-y += debug.o | 4 | libapi-y += debug.o |
5 | libapi-y += str_error_r.o | ||
6 | |||
7 | $(OUTPUT)str_error_r.o: ../str_error_r.c FORCE | ||
8 | $(call rule_mkdir) | ||
9 | $(call if_changed_dep,cc_o_c) | ||
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 32e6b6bc6f7d..b699aea9a025 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -37,6 +37,10 @@ | |||
37 | #include "libbpf.h" | 37 | #include "libbpf.h" |
38 | #include "bpf.h" | 38 | #include "bpf.h" |
39 | 39 | ||
40 | #ifndef EM_BPF | ||
41 | #define EM_BPF 247 | ||
42 | #endif | ||
43 | |||
40 | #define __printf(a, b) __attribute__((format(printf, a, b))) | 44 | #define __printf(a, b) __attribute__((format(printf, a, b))) |
41 | 45 | ||
42 | __printf(1, 2) | 46 | __printf(1, 2) |
@@ -439,7 +443,8 @@ static int bpf_object__elf_init(struct bpf_object *obj) | |||
439 | } | 443 | } |
440 | ep = &obj->efile.ehdr; | 444 | ep = &obj->efile.ehdr; |
441 | 445 | ||
442 | if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) { | 446 | /* Old LLVM set e_machine to EM_NONE */ |
447 | if ((ep->e_type != ET_REL) || (ep->e_machine && (ep->e_machine != EM_BPF))) { | ||
443 | pr_warning("%s is not an eBPF object file\n", | 448 | pr_warning("%s is not an eBPF object file\n", |
444 | obj->path); | 449 | obj->path); |
445 | err = -LIBBPF_ERRNO__FORMAT; | 450 | err = -LIBBPF_ERRNO__FORMAT; |
diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore index a0b3128bb31f..d3102c865a95 100644 --- a/tools/objtool/.gitignore +++ b/tools/objtool/.gitignore | |||
@@ -1,2 +1,3 @@ | |||
1 | arch/x86/insn/inat-tables.c | 1 | arch/x86/insn/inat-tables.c |
2 | objtool | 2 | objtool |
3 | fixdep | ||
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 0b437700f688..041b493ad3ab 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile | |||
@@ -51,7 +51,7 @@ $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) | |||
51 | diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ | 51 | diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ |
52 | diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ | 52 | diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ |
53 | diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ | 53 | diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ |
54 | || echo "Warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true | 54 | || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true |
55 | $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ | 55 | $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ |
56 | 56 | ||
57 | 57 | ||
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk index 093a892026f9..a3d2c62fd805 100644 --- a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk +++ b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk | |||
@@ -72,12 +72,14 @@ BEGIN { | |||
72 | lprefix_expr = "\\((66|F2|F3)\\)" | 72 | lprefix_expr = "\\((66|F2|F3)\\)" |
73 | max_lprefix = 4 | 73 | max_lprefix = 4 |
74 | 74 | ||
75 | # All opcodes starting with lower-case 'v' or with (v1) superscript | 75 | # All opcodes starting with lower-case 'v', 'k' or with (v1) superscript |
76 | # accepts VEX prefix | 76 | # accepts VEX prefix |
77 | vexok_opcode_expr = "^v.*" | 77 | vexok_opcode_expr = "^[vk].*" |
78 | vexok_expr = "\\(v1\\)" | 78 | vexok_expr = "\\(v1\\)" |
79 | # All opcodes with (v) superscript supports *only* VEX prefix | 79 | # All opcodes with (v) superscript supports *only* VEX prefix |
80 | vexonly_expr = "\\(v\\)" | 80 | vexonly_expr = "\\(v\\)" |
81 | # All opcodes with (ev) superscript supports *only* EVEX prefix | ||
82 | evexonly_expr = "\\(ev\\)" | ||
81 | 83 | ||
82 | prefix_expr = "\\(Prefix\\)" | 84 | prefix_expr = "\\(Prefix\\)" |
83 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" | 85 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" |
@@ -95,6 +97,7 @@ BEGIN { | |||
95 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" | 97 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" |
96 | prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" | 98 | prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" |
97 | prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" | 99 | prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" |
100 | prefix_num["EVEX"] = "INAT_PFX_EVEX" | ||
98 | 101 | ||
99 | clear_vars() | 102 | clear_vars() |
100 | } | 103 | } |
@@ -319,7 +322,9 @@ function convert_operands(count,opnd, i,j,imm,mod) | |||
319 | flags = add_flags(flags, "INAT_MODRM") | 322 | flags = add_flags(flags, "INAT_MODRM") |
320 | 323 | ||
321 | # check VEX codes | 324 | # check VEX codes |
322 | if (match(ext, vexonly_expr)) | 325 | if (match(ext, evexonly_expr)) |
326 | flags = add_flags(flags, "INAT_VEXOK | INAT_EVEXONLY") | ||
327 | else if (match(ext, vexonly_expr)) | ||
323 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") | 328 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") |
324 | else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) | 329 | else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) |
325 | flags = add_flags(flags, "INAT_VEXOK") | 330 | flags = add_flags(flags, "INAT_VEXOK") |
diff --git a/tools/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/insn/inat.h index 611645e903a8..125ecd2a300d 100644 --- a/tools/objtool/arch/x86/insn/inat.h +++ b/tools/objtool/arch/x86/insn/inat.h | |||
@@ -48,6 +48,7 @@ | |||
48 | /* AVX VEX prefixes */ | 48 | /* AVX VEX prefixes */ |
49 | #define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ | 49 | #define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ |
50 | #define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ | 50 | #define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ |
51 | #define INAT_PFX_EVEX 15 /* EVEX prefix */ | ||
51 | 52 | ||
52 | #define INAT_LSTPFX_MAX 3 | 53 | #define INAT_LSTPFX_MAX 3 |
53 | #define INAT_LGCPFX_MAX 11 | 54 | #define INAT_LGCPFX_MAX 11 |
@@ -89,6 +90,7 @@ | |||
89 | #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) | 90 | #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) |
90 | #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) | 91 | #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) |
91 | #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) | 92 | #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) |
93 | #define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7)) | ||
92 | /* Attribute making macros for attribute tables */ | 94 | /* Attribute making macros for attribute tables */ |
93 | #define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) | 95 | #define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) |
94 | #define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) | 96 | #define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) |
@@ -141,7 +143,13 @@ static inline int inat_last_prefix_id(insn_attr_t attr) | |||
141 | static inline int inat_is_vex_prefix(insn_attr_t attr) | 143 | static inline int inat_is_vex_prefix(insn_attr_t attr) |
142 | { | 144 | { |
143 | attr &= INAT_PFX_MASK; | 145 | attr &= INAT_PFX_MASK; |
144 | return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3; | 146 | return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 || |
147 | attr == INAT_PFX_EVEX; | ||
148 | } | ||
149 | |||
150 | static inline int inat_is_evex_prefix(insn_attr_t attr) | ||
151 | { | ||
152 | return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX; | ||
145 | } | 153 | } |
146 | 154 | ||
147 | static inline int inat_is_vex3_prefix(insn_attr_t attr) | 155 | static inline int inat_is_vex3_prefix(insn_attr_t attr) |
@@ -216,6 +224,11 @@ static inline int inat_accept_vex(insn_attr_t attr) | |||
216 | 224 | ||
217 | static inline int inat_must_vex(insn_attr_t attr) | 225 | static inline int inat_must_vex(insn_attr_t attr) |
218 | { | 226 | { |
219 | return attr & INAT_VEXONLY; | 227 | return attr & (INAT_VEXONLY | INAT_EVEXONLY); |
228 | } | ||
229 | |||
230 | static inline int inat_must_evex(insn_attr_t attr) | ||
231 | { | ||
232 | return attr & INAT_EVEXONLY; | ||
220 | } | 233 | } |
221 | #endif | 234 | #endif |
diff --git a/tools/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/insn/insn.c index 9f26eae6c9f0..ca983e2bea8b 100644 --- a/tools/objtool/arch/x86/insn/insn.c +++ b/tools/objtool/arch/x86/insn/insn.c | |||
@@ -155,14 +155,24 @@ found: | |||
155 | /* | 155 | /* |
156 | * In 32-bits mode, if the [7:6] bits (mod bits of | 156 | * In 32-bits mode, if the [7:6] bits (mod bits of |
157 | * ModRM) on the second byte are not 11b, it is | 157 | * ModRM) on the second byte are not 11b, it is |
158 | * LDS or LES. | 158 | * LDS or LES or BOUND. |
159 | */ | 159 | */ |
160 | if (X86_MODRM_MOD(b2) != 3) | 160 | if (X86_MODRM_MOD(b2) != 3) |
161 | goto vex_end; | 161 | goto vex_end; |
162 | } | 162 | } |
163 | insn->vex_prefix.bytes[0] = b; | 163 | insn->vex_prefix.bytes[0] = b; |
164 | insn->vex_prefix.bytes[1] = b2; | 164 | insn->vex_prefix.bytes[1] = b2; |
165 | if (inat_is_vex3_prefix(attr)) { | 165 | if (inat_is_evex_prefix(attr)) { |
166 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); | ||
167 | insn->vex_prefix.bytes[2] = b2; | ||
168 | b2 = peek_nbyte_next(insn_byte_t, insn, 3); | ||
169 | insn->vex_prefix.bytes[3] = b2; | ||
170 | insn->vex_prefix.nbytes = 4; | ||
171 | insn->next_byte += 4; | ||
172 | if (insn->x86_64 && X86_VEX_W(b2)) | ||
173 | /* VEX.W overrides opnd_size */ | ||
174 | insn->opnd_bytes = 8; | ||
175 | } else if (inat_is_vex3_prefix(attr)) { | ||
166 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); | 176 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); |
167 | insn->vex_prefix.bytes[2] = b2; | 177 | insn->vex_prefix.bytes[2] = b2; |
168 | insn->vex_prefix.nbytes = 3; | 178 | insn->vex_prefix.nbytes = 3; |
@@ -221,7 +231,9 @@ void insn_get_opcode(struct insn *insn) | |||
221 | m = insn_vex_m_bits(insn); | 231 | m = insn_vex_m_bits(insn); |
222 | p = insn_vex_p_bits(insn); | 232 | p = insn_vex_p_bits(insn); |
223 | insn->attr = inat_get_avx_attribute(op, m, p); | 233 | insn->attr = inat_get_avx_attribute(op, m, p); |
224 | if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) | 234 | if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) || |
235 | (!inat_accept_vex(insn->attr) && | ||
236 | !inat_is_group(insn->attr))) | ||
225 | insn->attr = 0; /* This instruction is bad */ | 237 | insn->attr = 0; /* This instruction is bad */ |
226 | goto end; /* VEX has only 1 byte for opcode */ | 238 | goto end; /* VEX has only 1 byte for opcode */ |
227 | } | 239 | } |
diff --git a/tools/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/insn/insn.h index dd12da0f4593..e23578c7b1be 100644 --- a/tools/objtool/arch/x86/insn/insn.h +++ b/tools/objtool/arch/x86/insn/insn.h | |||
@@ -91,6 +91,7 @@ struct insn { | |||
91 | #define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ | 91 | #define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ |
92 | #define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ | 92 | #define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ |
93 | /* VEX bit fields */ | 93 | /* VEX bit fields */ |
94 | #define X86_EVEX_M(vex) ((vex) & 0x03) /* EVEX Byte1 */ | ||
94 | #define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ | 95 | #define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ |
95 | #define X86_VEX2_M 1 /* VEX2.M always 1 */ | 96 | #define X86_VEX2_M 1 /* VEX2.M always 1 */ |
96 | #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ | 97 | #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ |
@@ -133,6 +134,13 @@ static inline int insn_is_avx(struct insn *insn) | |||
133 | return (insn->vex_prefix.value != 0); | 134 | return (insn->vex_prefix.value != 0); |
134 | } | 135 | } |
135 | 136 | ||
137 | static inline int insn_is_evex(struct insn *insn) | ||
138 | { | ||
139 | if (!insn->prefixes.got) | ||
140 | insn_get_prefixes(insn); | ||
141 | return (insn->vex_prefix.nbytes == 4); | ||
142 | } | ||
143 | |||
136 | /* Ensure this instruction is decoded completely */ | 144 | /* Ensure this instruction is decoded completely */ |
137 | static inline int insn_complete(struct insn *insn) | 145 | static inline int insn_complete(struct insn *insn) |
138 | { | 146 | { |
@@ -144,8 +152,10 @@ static inline insn_byte_t insn_vex_m_bits(struct insn *insn) | |||
144 | { | 152 | { |
145 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ | 153 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ |
146 | return X86_VEX2_M; | 154 | return X86_VEX2_M; |
147 | else | 155 | else if (insn->vex_prefix.nbytes == 3) /* 3 bytes VEX */ |
148 | return X86_VEX3_M(insn->vex_prefix.bytes[1]); | 156 | return X86_VEX3_M(insn->vex_prefix.bytes[1]); |
157 | else /* EVEX */ | ||
158 | return X86_EVEX_M(insn->vex_prefix.bytes[1]); | ||
149 | } | 159 | } |
150 | 160 | ||
151 | static inline insn_byte_t insn_vex_p_bits(struct insn *insn) | 161 | static inline insn_byte_t insn_vex_p_bits(struct insn *insn) |
diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/insn/x86-opcode-map.txt index d388de72eaca..767be7c76034 100644 --- a/tools/objtool/arch/x86/insn/x86-opcode-map.txt +++ b/tools/objtool/arch/x86/insn/x86-opcode-map.txt | |||
@@ -13,12 +13,17 @@ | |||
13 | # opcode: escape # escaped-name | 13 | # opcode: escape # escaped-name |
14 | # EndTable | 14 | # EndTable |
15 | # | 15 | # |
16 | # mnemonics that begin with lowercase 'v' accept a VEX or EVEX prefix | ||
17 | # mnemonics that begin with lowercase 'k' accept a VEX prefix | ||
18 | # | ||
16 | #<group maps> | 19 | #<group maps> |
17 | # GrpTable: GrpXXX | 20 | # GrpTable: GrpXXX |
18 | # reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...] | 21 | # reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...] |
19 | # EndTable | 22 | # EndTable |
20 | # | 23 | # |
21 | # AVX Superscripts | 24 | # AVX Superscripts |
25 | # (ev): this opcode requires EVEX prefix. | ||
26 | # (evo): this opcode is changed by EVEX prefix (EVEX opcode) | ||
22 | # (v): this opcode requires VEX prefix. | 27 | # (v): this opcode requires VEX prefix. |
23 | # (v1): this opcode only supports 128bit VEX. | 28 | # (v1): this opcode only supports 128bit VEX. |
24 | # | 29 | # |
@@ -137,7 +142,7 @@ AVXcode: | |||
137 | # 0x60 - 0x6f | 142 | # 0x60 - 0x6f |
138 | 60: PUSHA/PUSHAD (i64) | 143 | 60: PUSHA/PUSHAD (i64) |
139 | 61: POPA/POPAD (i64) | 144 | 61: POPA/POPAD (i64) |
140 | 62: BOUND Gv,Ma (i64) | 145 | 62: BOUND Gv,Ma (i64) | EVEX (Prefix) |
141 | 63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) | 146 | 63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) |
142 | 64: SEG=FS (Prefix) | 147 | 64: SEG=FS (Prefix) |
143 | 65: SEG=GS (Prefix) | 148 | 65: SEG=GS (Prefix) |
@@ -399,17 +404,17 @@ AVXcode: 1 | |||
399 | 3f: | 404 | 3f: |
400 | # 0x0f 0x40-0x4f | 405 | # 0x0f 0x40-0x4f |
401 | 40: CMOVO Gv,Ev | 406 | 40: CMOVO Gv,Ev |
402 | 41: CMOVNO Gv,Ev | 407 | 41: CMOVNO Gv,Ev | kandw/q Vk,Hk,Uk | kandb/d Vk,Hk,Uk (66) |
403 | 42: CMOVB/C/NAE Gv,Ev | 408 | 42: CMOVB/C/NAE Gv,Ev | kandnw/q Vk,Hk,Uk | kandnb/d Vk,Hk,Uk (66) |
404 | 43: CMOVAE/NB/NC Gv,Ev | 409 | 43: CMOVAE/NB/NC Gv,Ev |
405 | 44: CMOVE/Z Gv,Ev | 410 | 44: CMOVE/Z Gv,Ev | knotw/q Vk,Uk | knotb/d Vk,Uk (66) |
406 | 45: CMOVNE/NZ Gv,Ev | 411 | 45: CMOVNE/NZ Gv,Ev | korw/q Vk,Hk,Uk | korb/d Vk,Hk,Uk (66) |
407 | 46: CMOVBE/NA Gv,Ev | 412 | 46: CMOVBE/NA Gv,Ev | kxnorw/q Vk,Hk,Uk | kxnorb/d Vk,Hk,Uk (66) |
408 | 47: CMOVA/NBE Gv,Ev | 413 | 47: CMOVA/NBE Gv,Ev | kxorw/q Vk,Hk,Uk | kxorb/d Vk,Hk,Uk (66) |
409 | 48: CMOVS Gv,Ev | 414 | 48: CMOVS Gv,Ev |
410 | 49: CMOVNS Gv,Ev | 415 | 49: CMOVNS Gv,Ev |
411 | 4a: CMOVP/PE Gv,Ev | 416 | 4a: CMOVP/PE Gv,Ev | kaddw/q Vk,Hk,Uk | kaddb/d Vk,Hk,Uk (66) |
412 | 4b: CMOVNP/PO Gv,Ev | 417 | 4b: CMOVNP/PO Gv,Ev | kunpckbw Vk,Hk,Uk (66) | kunpckwd/dq Vk,Hk,Uk |
413 | 4c: CMOVL/NGE Gv,Ev | 418 | 4c: CMOVL/NGE Gv,Ev |
414 | 4d: CMOVNL/GE Gv,Ev | 419 | 4d: CMOVNL/GE Gv,Ev |
415 | 4e: CMOVLE/NG Gv,Ev | 420 | 4e: CMOVLE/NG Gv,Ev |
@@ -426,7 +431,7 @@ AVXcode: 1 | |||
426 | 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) | 431 | 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) |
427 | 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) | 432 | 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) |
428 | 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) | 433 | 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) |
429 | 5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) | 434 | 5b: vcvtdq2ps Vps,Wdq | vcvtqq2ps Vps,Wqq (evo) | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) |
430 | 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) | 435 | 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) |
431 | 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) | 436 | 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) |
432 | 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) | 437 | 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) |
@@ -447,7 +452,7 @@ AVXcode: 1 | |||
447 | 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) | 452 | 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) |
448 | 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) | 453 | 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) |
449 | 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) | 454 | 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) |
450 | 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3) | 455 | 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqa32/64 Vx,Wx (66),(evo) | vmovdqu Vx,Wx (F3) | vmovdqu32/64 Vx,Wx (F3),(evo) | vmovdqu8/16 Vx,Wx (F2),(ev) |
451 | # 0x0f 0x70-0x7f | 456 | # 0x0f 0x70-0x7f |
452 | 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) | 457 | 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) |
453 | 71: Grp12 (1A) | 458 | 71: Grp12 (1A) |
@@ -458,14 +463,14 @@ AVXcode: 1 | |||
458 | 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) | 463 | 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) |
459 | # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. | 464 | # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. |
460 | 77: emms | vzeroupper | vzeroall | 465 | 77: emms | vzeroupper | vzeroall |
461 | 78: VMREAD Ey,Gy | 466 | 78: VMREAD Ey,Gy | vcvttps2udq/pd2udq Vx,Wpd (evo) | vcvttsd2usi Gv,Wx (F2),(ev) | vcvttss2usi Gv,Wx (F3),(ev) | vcvttps2uqq/pd2uqq Vx,Wx (66),(ev) |
462 | 79: VMWRITE Gy,Ey | 467 | 79: VMWRITE Gy,Ey | vcvtps2udq/pd2udq Vx,Wpd (evo) | vcvtsd2usi Gv,Wx (F2),(ev) | vcvtss2usi Gv,Wx (F3),(ev) | vcvtps2uqq/pd2uqq Vx,Wx (66),(ev) |
463 | 7a: | 468 | 7a: vcvtudq2pd/uqq2pd Vpd,Wx (F3),(ev) | vcvtudq2ps/uqq2ps Vpd,Wx (F2),(ev) | vcvttps2qq/pd2qq Vx,Wx (66),(ev) |
464 | 7b: | 469 | 7b: vcvtusi2sd Vpd,Hpd,Ev (F2),(ev) | vcvtusi2ss Vps,Hps,Ev (F3),(ev) | vcvtps2qq/pd2qq Vx,Wx (66),(ev) |
465 | 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) | 470 | 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) |
466 | 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) | 471 | 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) |
467 | 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) | 472 | 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) |
468 | 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3) | 473 | 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqa32/64 Wx,Vx (66),(evo) | vmovdqu Wx,Vx (F3) | vmovdqu32/64 Wx,Vx (F3),(evo) | vmovdqu8/16 Wx,Vx (F2),(ev) |
469 | # 0x0f 0x80-0x8f | 474 | # 0x0f 0x80-0x8f |
470 | # Note: "forced64" is Intel CPU behavior (see comment about CALL insn). | 475 | # Note: "forced64" is Intel CPU behavior (see comment about CALL insn). |
471 | 80: JO Jz (f64) | 476 | 80: JO Jz (f64) |
@@ -485,16 +490,16 @@ AVXcode: 1 | |||
485 | 8e: JLE/JNG Jz (f64) | 490 | 8e: JLE/JNG Jz (f64) |
486 | 8f: JNLE/JG Jz (f64) | 491 | 8f: JNLE/JG Jz (f64) |
487 | # 0x0f 0x90-0x9f | 492 | # 0x0f 0x90-0x9f |
488 | 90: SETO Eb | 493 | 90: SETO Eb | kmovw/q Vk,Wk | kmovb/d Vk,Wk (66) |
489 | 91: SETNO Eb | 494 | 91: SETNO Eb | kmovw/q Mv,Vk | kmovb/d Mv,Vk (66) |
490 | 92: SETB/C/NAE Eb | 495 | 92: SETB/C/NAE Eb | kmovw Vk,Rv | kmovb Vk,Rv (66) | kmovq/d Vk,Rv (F2) |
491 | 93: SETAE/NB/NC Eb | 496 | 93: SETAE/NB/NC Eb | kmovw Gv,Uk | kmovb Gv,Uk (66) | kmovq/d Gv,Uk (F2) |
492 | 94: SETE/Z Eb | 497 | 94: SETE/Z Eb |
493 | 95: SETNE/NZ Eb | 498 | 95: SETNE/NZ Eb |
494 | 96: SETBE/NA Eb | 499 | 96: SETBE/NA Eb |
495 | 97: SETA/NBE Eb | 500 | 97: SETA/NBE Eb |
496 | 98: SETS Eb | 501 | 98: SETS Eb | kortestw/q Vk,Uk | kortestb/d Vk,Uk (66) |
497 | 99: SETNS Eb | 502 | 99: SETNS Eb | ktestw/q Vk,Uk | ktestb/d Vk,Uk (66) |
498 | 9a: SETP/PE Eb | 503 | 9a: SETP/PE Eb |
499 | 9b: SETNP/PO Eb | 504 | 9b: SETNP/PO Eb |
500 | 9c: SETL/NGE Eb | 505 | 9c: SETL/NGE Eb |
@@ -564,11 +569,11 @@ d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1) | |||
564 | d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) | 569 | d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) |
565 | d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) | 570 | d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) |
566 | da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) | 571 | da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) |
567 | db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | 572 | db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | vpandd/q Vx,Hx,Wx (66),(evo) |
568 | dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) | 573 | dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) |
569 | dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) | 574 | dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) |
570 | de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) | 575 | de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) |
571 | df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | 576 | df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | vpandnd/q Vx,Hx,Wx (66),(evo) |
572 | # 0x0f 0xe0-0xef | 577 | # 0x0f 0xe0-0xef |
573 | e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) | 578 | e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) |
574 | e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) | 579 | e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) |
@@ -576,16 +581,16 @@ e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1) | |||
576 | e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) | 581 | e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) |
577 | e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) | 582 | e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) |
578 | e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) | 583 | e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) |
579 | e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2) | 584 | e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtdq2pd/qq2pd Vx,Wdq (F3),(evo) | vcvtpd2dq Vx,Wpd (F2) |
580 | e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) | 585 | e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) |
581 | e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) | 586 | e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) |
582 | e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) | 587 | e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) |
583 | ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) | 588 | ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) |
584 | eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | 589 | eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | vpord/q Vx,Hx,Wx (66),(evo) |
585 | ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) | 590 | ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) |
586 | ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) | 591 | ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) |
587 | ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) | 592 | ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) |
588 | ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | 593 | ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | vpxord/q Vx,Hx,Wx (66),(evo) |
589 | # 0x0f 0xf0-0xff | 594 | # 0x0f 0xf0-0xff |
590 | f0: vlddqu Vx,Mx (F2) | 595 | f0: vlddqu Vx,Mx (F2) |
591 | f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) | 596 | f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) |
@@ -626,81 +631,105 @@ AVXcode: 2 | |||
626 | 0e: vtestps Vx,Wx (66),(v) | 631 | 0e: vtestps Vx,Wx (66),(v) |
627 | 0f: vtestpd Vx,Wx (66),(v) | 632 | 0f: vtestpd Vx,Wx (66),(v) |
628 | # 0x0f 0x38 0x10-0x1f | 633 | # 0x0f 0x38 0x10-0x1f |
629 | 10: pblendvb Vdq,Wdq (66) | 634 | 10: pblendvb Vdq,Wdq (66) | vpsrlvw Vx,Hx,Wx (66),(evo) | vpmovuswb Wx,Vx (F3),(ev) |
630 | 11: | 635 | 11: vpmovusdb Wx,Vd (F3),(ev) | vpsravw Vx,Hx,Wx (66),(ev) |
631 | 12: | 636 | 12: vpmovusqb Wx,Vq (F3),(ev) | vpsllvw Vx,Hx,Wx (66),(ev) |
632 | 13: vcvtph2ps Vx,Wx,Ib (66),(v) | 637 | 13: vcvtph2ps Vx,Wx (66),(v) | vpmovusdw Wx,Vd (F3),(ev) |
633 | 14: blendvps Vdq,Wdq (66) | 638 | 14: blendvps Vdq,Wdq (66) | vpmovusqw Wx,Vq (F3),(ev) | vprorvd/q Vx,Hx,Wx (66),(evo) |
634 | 15: blendvpd Vdq,Wdq (66) | 639 | 15: blendvpd Vdq,Wdq (66) | vpmovusqd Wx,Vq (F3),(ev) | vprolvd/q Vx,Hx,Wx (66),(evo) |
635 | 16: vpermps Vqq,Hqq,Wqq (66),(v) | 640 | 16: vpermps Vqq,Hqq,Wqq (66),(v) | vpermps/d Vqq,Hqq,Wqq (66),(evo) |
636 | 17: vptest Vx,Wx (66) | 641 | 17: vptest Vx,Wx (66) |
637 | 18: vbroadcastss Vx,Wd (66),(v) | 642 | 18: vbroadcastss Vx,Wd (66),(v) |
638 | 19: vbroadcastsd Vqq,Wq (66),(v) | 643 | 19: vbroadcastsd Vqq,Wq (66),(v) | vbroadcastf32x2 Vqq,Wq (66),(evo) |
639 | 1a: vbroadcastf128 Vqq,Mdq (66),(v) | 644 | 1a: vbroadcastf128 Vqq,Mdq (66),(v) | vbroadcastf32x4/64x2 Vqq,Wq (66),(evo) |
640 | 1b: | 645 | 1b: vbroadcastf32x8/64x4 Vqq,Mdq (66),(ev) |
641 | 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) | 646 | 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) |
642 | 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) | 647 | 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) |
643 | 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) | 648 | 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) |
644 | 1f: | 649 | 1f: vpabsq Vx,Wx (66),(ev) |
645 | # 0x0f 0x38 0x20-0x2f | 650 | # 0x0f 0x38 0x20-0x2f |
646 | 20: vpmovsxbw Vx,Ux/Mq (66),(v1) | 651 | 20: vpmovsxbw Vx,Ux/Mq (66),(v1) | vpmovswb Wx,Vx (F3),(ev) |
647 | 21: vpmovsxbd Vx,Ux/Md (66),(v1) | 652 | 21: vpmovsxbd Vx,Ux/Md (66),(v1) | vpmovsdb Wx,Vd (F3),(ev) |
648 | 22: vpmovsxbq Vx,Ux/Mw (66),(v1) | 653 | 22: vpmovsxbq Vx,Ux/Mw (66),(v1) | vpmovsqb Wx,Vq (F3),(ev) |
649 | 23: vpmovsxwd Vx,Ux/Mq (66),(v1) | 654 | 23: vpmovsxwd Vx,Ux/Mq (66),(v1) | vpmovsdw Wx,Vd (F3),(ev) |
650 | 24: vpmovsxwq Vx,Ux/Md (66),(v1) | 655 | 24: vpmovsxwq Vx,Ux/Md (66),(v1) | vpmovsqw Wx,Vq (F3),(ev) |
651 | 25: vpmovsxdq Vx,Ux/Mq (66),(v1) | 656 | 25: vpmovsxdq Vx,Ux/Mq (66),(v1) | vpmovsqd Wx,Vq (F3),(ev) |
652 | 26: | 657 | 26: vptestmb/w Vk,Hx,Wx (66),(ev) | vptestnmb/w Vk,Hx,Wx (F3),(ev) |
653 | 27: | 658 | 27: vptestmd/q Vk,Hx,Wx (66),(ev) | vptestnmd/q Vk,Hx,Wx (F3),(ev) |
654 | 28: vpmuldq Vx,Hx,Wx (66),(v1) | 659 | 28: vpmuldq Vx,Hx,Wx (66),(v1) | vpmovm2b/w Vx,Uk (F3),(ev) |
655 | 29: vpcmpeqq Vx,Hx,Wx (66),(v1) | 660 | 29: vpcmpeqq Vx,Hx,Wx (66),(v1) | vpmovb2m/w2m Vk,Ux (F3),(ev) |
656 | 2a: vmovntdqa Vx,Mx (66),(v1) | 661 | 2a: vmovntdqa Vx,Mx (66),(v1) | vpbroadcastmb2q Vx,Uk (F3),(ev) |
657 | 2b: vpackusdw Vx,Hx,Wx (66),(v1) | 662 | 2b: vpackusdw Vx,Hx,Wx (66),(v1) |
658 | 2c: vmaskmovps Vx,Hx,Mx (66),(v) | 663 | 2c: vmaskmovps Vx,Hx,Mx (66),(v) | vscalefps/d Vx,Hx,Wx (66),(evo) |
659 | 2d: vmaskmovpd Vx,Hx,Mx (66),(v) | 664 | 2d: vmaskmovpd Vx,Hx,Mx (66),(v) | vscalefss/d Vx,Hx,Wx (66),(evo) |
660 | 2e: vmaskmovps Mx,Hx,Vx (66),(v) | 665 | 2e: vmaskmovps Mx,Hx,Vx (66),(v) |
661 | 2f: vmaskmovpd Mx,Hx,Vx (66),(v) | 666 | 2f: vmaskmovpd Mx,Hx,Vx (66),(v) |
662 | # 0x0f 0x38 0x30-0x3f | 667 | # 0x0f 0x38 0x30-0x3f |
663 | 30: vpmovzxbw Vx,Ux/Mq (66),(v1) | 668 | 30: vpmovzxbw Vx,Ux/Mq (66),(v1) | vpmovwb Wx,Vx (F3),(ev) |
664 | 31: vpmovzxbd Vx,Ux/Md (66),(v1) | 669 | 31: vpmovzxbd Vx,Ux/Md (66),(v1) | vpmovdb Wx,Vd (F3),(ev) |
665 | 32: vpmovzxbq Vx,Ux/Mw (66),(v1) | 670 | 32: vpmovzxbq Vx,Ux/Mw (66),(v1) | vpmovqb Wx,Vq (F3),(ev) |
666 | 33: vpmovzxwd Vx,Ux/Mq (66),(v1) | 671 | 33: vpmovzxwd Vx,Ux/Mq (66),(v1) | vpmovdw Wx,Vd (F3),(ev) |
667 | 34: vpmovzxwq Vx,Ux/Md (66),(v1) | 672 | 34: vpmovzxwq Vx,Ux/Md (66),(v1) | vpmovqw Wx,Vq (F3),(ev) |
668 | 35: vpmovzxdq Vx,Ux/Mq (66),(v1) | 673 | 35: vpmovzxdq Vx,Ux/Mq (66),(v1) | vpmovqd Wx,Vq (F3),(ev) |
669 | 36: vpermd Vqq,Hqq,Wqq (66),(v) | 674 | 36: vpermd Vqq,Hqq,Wqq (66),(v) | vpermd/q Vqq,Hqq,Wqq (66),(evo) |
670 | 37: vpcmpgtq Vx,Hx,Wx (66),(v1) | 675 | 37: vpcmpgtq Vx,Hx,Wx (66),(v1) |
671 | 38: vpminsb Vx,Hx,Wx (66),(v1) | 676 | 38: vpminsb Vx,Hx,Wx (66),(v1) | vpmovm2d/q Vx,Uk (F3),(ev) |
672 | 39: vpminsd Vx,Hx,Wx (66),(v1) | 677 | 39: vpminsd Vx,Hx,Wx (66),(v1) | vpminsd/q Vx,Hx,Wx (66),(evo) | vpmovd2m/q2m Vk,Ux (F3),(ev) |
673 | 3a: vpminuw Vx,Hx,Wx (66),(v1) | 678 | 3a: vpminuw Vx,Hx,Wx (66),(v1) | vpbroadcastmw2d Vx,Uk (F3),(ev) |
674 | 3b: vpminud Vx,Hx,Wx (66),(v1) | 679 | 3b: vpminud Vx,Hx,Wx (66),(v1) | vpminud/q Vx,Hx,Wx (66),(evo) |
675 | 3c: vpmaxsb Vx,Hx,Wx (66),(v1) | 680 | 3c: vpmaxsb Vx,Hx,Wx (66),(v1) |
676 | 3d: vpmaxsd Vx,Hx,Wx (66),(v1) | 681 | 3d: vpmaxsd Vx,Hx,Wx (66),(v1) | vpmaxsd/q Vx,Hx,Wx (66),(evo) |
677 | 3e: vpmaxuw Vx,Hx,Wx (66),(v1) | 682 | 3e: vpmaxuw Vx,Hx,Wx (66),(v1) |
678 | 3f: vpmaxud Vx,Hx,Wx (66),(v1) | 683 | 3f: vpmaxud Vx,Hx,Wx (66),(v1) | vpmaxud/q Vx,Hx,Wx (66),(evo) |
679 | # 0x0f 0x38 0x40-0x8f | 684 | # 0x0f 0x38 0x40-0x8f |
680 | 40: vpmulld Vx,Hx,Wx (66),(v1) | 685 | 40: vpmulld Vx,Hx,Wx (66),(v1) | vpmulld/q Vx,Hx,Wx (66),(evo) |
681 | 41: vphminposuw Vdq,Wdq (66),(v1) | 686 | 41: vphminposuw Vdq,Wdq (66),(v1) |
682 | 42: | 687 | 42: vgetexpps/d Vx,Wx (66),(ev) |
683 | 43: | 688 | 43: vgetexpss/d Vx,Hx,Wx (66),(ev) |
684 | 44: | 689 | 44: vplzcntd/q Vx,Wx (66),(ev) |
685 | 45: vpsrlvd/q Vx,Hx,Wx (66),(v) | 690 | 45: vpsrlvd/q Vx,Hx,Wx (66),(v) |
686 | 46: vpsravd Vx,Hx,Wx (66),(v) | 691 | 46: vpsravd Vx,Hx,Wx (66),(v) | vpsravd/q Vx,Hx,Wx (66),(evo) |
687 | 47: vpsllvd/q Vx,Hx,Wx (66),(v) | 692 | 47: vpsllvd/q Vx,Hx,Wx (66),(v) |
688 | # Skip 0x48-0x57 | 693 | # Skip 0x48-0x4b |
694 | 4c: vrcp14ps/d Vpd,Wpd (66),(ev) | ||
695 | 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev) | ||
696 | 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev) | ||
697 | 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev) | ||
698 | # Skip 0x50-0x57 | ||
689 | 58: vpbroadcastd Vx,Wx (66),(v) | 699 | 58: vpbroadcastd Vx,Wx (66),(v) |
690 | 59: vpbroadcastq Vx,Wx (66),(v) | 700 | 59: vpbroadcastq Vx,Wx (66),(v) | vbroadcasti32x2 Vx,Wx (66),(evo) |
691 | 5a: vbroadcasti128 Vqq,Mdq (66),(v) | 701 | 5a: vbroadcasti128 Vqq,Mdq (66),(v) | vbroadcasti32x4/64x2 Vx,Wx (66),(evo) |
692 | # Skip 0x5b-0x77 | 702 | 5b: vbroadcasti32x8/64x4 Vqq,Mdq (66),(ev) |
703 | # Skip 0x5c-0x63 | ||
704 | 64: vpblendmd/q Vx,Hx,Wx (66),(ev) | ||
705 | 65: vblendmps/d Vx,Hx,Wx (66),(ev) | ||
706 | 66: vpblendmb/w Vx,Hx,Wx (66),(ev) | ||
707 | # Skip 0x67-0x74 | ||
708 | 75: vpermi2b/w Vx,Hx,Wx (66),(ev) | ||
709 | 76: vpermi2d/q Vx,Hx,Wx (66),(ev) | ||
710 | 77: vpermi2ps/d Vx,Hx,Wx (66),(ev) | ||
693 | 78: vpbroadcastb Vx,Wx (66),(v) | 711 | 78: vpbroadcastb Vx,Wx (66),(v) |
694 | 79: vpbroadcastw Vx,Wx (66),(v) | 712 | 79: vpbroadcastw Vx,Wx (66),(v) |
695 | # Skip 0x7a-0x7f | 713 | 7a: vpbroadcastb Vx,Rv (66),(ev) |
714 | 7b: vpbroadcastw Vx,Rv (66),(ev) | ||
715 | 7c: vpbroadcastd/q Vx,Rv (66),(ev) | ||
716 | 7d: vpermt2b/w Vx,Hx,Wx (66),(ev) | ||
717 | 7e: vpermt2d/q Vx,Hx,Wx (66),(ev) | ||
718 | 7f: vpermt2ps/d Vx,Hx,Wx (66),(ev) | ||
696 | 80: INVEPT Gy,Mdq (66) | 719 | 80: INVEPT Gy,Mdq (66) |
697 | 81: INVPID Gy,Mdq (66) | 720 | 81: INVPID Gy,Mdq (66) |
698 | 82: INVPCID Gy,Mdq (66) | 721 | 82: INVPCID Gy,Mdq (66) |
722 | 83: vpmultishiftqb Vx,Hx,Wx (66),(ev) | ||
723 | 88: vexpandps/d Vpd,Wpd (66),(ev) | ||
724 | 89: vpexpandd/q Vx,Wx (66),(ev) | ||
725 | 8a: vcompressps/d Wx,Vx (66),(ev) | ||
726 | 8b: vpcompressd/q Wx,Vx (66),(ev) | ||
699 | 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) | 727 | 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) |
728 | 8d: vpermb/w Vx,Hx,Wx (66),(ev) | ||
700 | 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) | 729 | 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) |
701 | # 0x0f 0x38 0x90-0xbf (FMA) | 730 | # 0x0f 0x38 0x90-0xbf (FMA) |
702 | 90: vgatherdd/q Vx,Hx,Wx (66),(v) | 731 | 90: vgatherdd/q Vx,Hx,Wx (66),(v) | vpgatherdd/q Vx,Wx (66),(evo) |
703 | 91: vgatherqd/q Vx,Hx,Wx (66),(v) | 732 | 91: vgatherqd/q Vx,Hx,Wx (66),(v) | vpgatherqd/q Vx,Wx (66),(evo) |
704 | 92: vgatherdps/d Vx,Hx,Wx (66),(v) | 733 | 92: vgatherdps/d Vx,Hx,Wx (66),(v) |
705 | 93: vgatherqps/d Vx,Hx,Wx (66),(v) | 734 | 93: vgatherqps/d Vx,Hx,Wx (66),(v) |
706 | 94: | 735 | 94: |
@@ -715,6 +744,10 @@ AVXcode: 2 | |||
715 | 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) | 744 | 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) |
716 | 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) | 745 | 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) |
717 | 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) | 746 | 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) |
747 | a0: vpscatterdd/q Wx,Vx (66),(ev) | ||
748 | a1: vpscatterqd/q Wx,Vx (66),(ev) | ||
749 | a2: vscatterdps/d Wx,Vx (66),(ev) | ||
750 | a3: vscatterqps/d Wx,Vx (66),(ev) | ||
718 | a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) | 751 | a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) |
719 | a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) | 752 | a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) |
720 | a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) | 753 | a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) |
@@ -725,6 +758,8 @@ ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v) | |||
725 | ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) | 758 | ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) |
726 | ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) | 759 | ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) |
727 | af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) | 760 | af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) |
761 | b4: vpmadd52luq Vx,Hx,Wx (66),(ev) | ||
762 | b5: vpmadd52huq Vx,Hx,Wx (66),(ev) | ||
728 | b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) | 763 | b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) |
729 | b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) | 764 | b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) |
730 | b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) | 765 | b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) |
@@ -736,12 +771,15 @@ bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1) | |||
736 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) | 771 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) |
737 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) | 772 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) |
738 | # 0x0f 0x38 0xc0-0xff | 773 | # 0x0f 0x38 0xc0-0xff |
739 | c8: sha1nexte Vdq,Wdq | 774 | c4: vpconflictd/q Vx,Wx (66),(ev) |
775 | c6: Grp18 (1A) | ||
776 | c7: Grp19 (1A) | ||
777 | c8: sha1nexte Vdq,Wdq | vexp2ps/d Vx,Wx (66),(ev) | ||
740 | c9: sha1msg1 Vdq,Wdq | 778 | c9: sha1msg1 Vdq,Wdq |
741 | ca: sha1msg2 Vdq,Wdq | 779 | ca: sha1msg2 Vdq,Wdq | vrcp28ps/d Vx,Wx (66),(ev) |
742 | cb: sha256rnds2 Vdq,Wdq | 780 | cb: sha256rnds2 Vdq,Wdq | vrcp28ss/d Vx,Hx,Wx (66),(ev) |
743 | cc: sha256msg1 Vdq,Wdq | 781 | cc: sha256msg1 Vdq,Wdq | vrsqrt28ps/d Vx,Wx (66),(ev) |
744 | cd: sha256msg2 Vdq,Wdq | 782 | cd: sha256msg2 Vdq,Wdq | vrsqrt28ss/d Vx,Hx,Wx (66),(ev) |
745 | db: VAESIMC Vdq,Wdq (66),(v1) | 783 | db: VAESIMC Vdq,Wdq (66),(v1) |
746 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) | 784 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) |
747 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) | 785 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) |
@@ -763,15 +801,15 @@ AVXcode: 3 | |||
763 | 00: vpermq Vqq,Wqq,Ib (66),(v) | 801 | 00: vpermq Vqq,Wqq,Ib (66),(v) |
764 | 01: vpermpd Vqq,Wqq,Ib (66),(v) | 802 | 01: vpermpd Vqq,Wqq,Ib (66),(v) |
765 | 02: vpblendd Vx,Hx,Wx,Ib (66),(v) | 803 | 02: vpblendd Vx,Hx,Wx,Ib (66),(v) |
766 | 03: | 804 | 03: valignd/q Vx,Hx,Wx,Ib (66),(ev) |
767 | 04: vpermilps Vx,Wx,Ib (66),(v) | 805 | 04: vpermilps Vx,Wx,Ib (66),(v) |
768 | 05: vpermilpd Vx,Wx,Ib (66),(v) | 806 | 05: vpermilpd Vx,Wx,Ib (66),(v) |
769 | 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) | 807 | 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) |
770 | 07: | 808 | 07: |
771 | 08: vroundps Vx,Wx,Ib (66) | 809 | 08: vroundps Vx,Wx,Ib (66) | vrndscaleps Vx,Wx,Ib (66),(evo) |
772 | 09: vroundpd Vx,Wx,Ib (66) | 810 | 09: vroundpd Vx,Wx,Ib (66) | vrndscalepd Vx,Wx,Ib (66),(evo) |
773 | 0a: vroundss Vss,Wss,Ib (66),(v1) | 811 | 0a: vroundss Vss,Wss,Ib (66),(v1) | vrndscaless Vx,Hx,Wx,Ib (66),(evo) |
774 | 0b: vroundsd Vsd,Wsd,Ib (66),(v1) | 812 | 0b: vroundsd Vsd,Wsd,Ib (66),(v1) | vrndscalesd Vx,Hx,Wx,Ib (66),(evo) |
775 | 0c: vblendps Vx,Hx,Wx,Ib (66) | 813 | 0c: vblendps Vx,Hx,Wx,Ib (66) |
776 | 0d: vblendpd Vx,Hx,Wx,Ib (66) | 814 | 0d: vblendpd Vx,Hx,Wx,Ib (66) |
777 | 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) | 815 | 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) |
@@ -780,26 +818,51 @@ AVXcode: 3 | |||
780 | 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) | 818 | 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) |
781 | 16: vpextrd/q Ey,Vdq,Ib (66),(v1) | 819 | 16: vpextrd/q Ey,Vdq,Ib (66),(v1) |
782 | 17: vextractps Ed,Vdq,Ib (66),(v1) | 820 | 17: vextractps Ed,Vdq,Ib (66),(v1) |
783 | 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | 821 | 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | vinsertf32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo) |
784 | 19: vextractf128 Wdq,Vqq,Ib (66),(v) | 822 | 19: vextractf128 Wdq,Vqq,Ib (66),(v) | vextractf32x4/64x2 Wdq,Vqq,Ib (66),(evo) |
823 | 1a: vinsertf32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev) | ||
824 | 1b: vextractf32x8/64x4 Wdq,Vqq,Ib (66),(ev) | ||
785 | 1d: vcvtps2ph Wx,Vx,Ib (66),(v) | 825 | 1d: vcvtps2ph Wx,Vx,Ib (66),(v) |
826 | 1e: vpcmpud/q Vk,Hd,Wd,Ib (66),(ev) | ||
827 | 1f: vpcmpd/q Vk,Hd,Wd,Ib (66),(ev) | ||
786 | 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) | 828 | 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) |
787 | 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) | 829 | 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) |
788 | 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) | 830 | 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) |
789 | 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | 831 | 23: vshuff32x4/64x2 Vx,Hx,Wx,Ib (66),(ev) |
790 | 39: vextracti128 Wdq,Vqq,Ib (66),(v) | 832 | 25: vpternlogd/q Vx,Hx,Wx,Ib (66),(ev) |
833 | 26: vgetmantps/d Vx,Wx,Ib (66),(ev) | ||
834 | 27: vgetmantss/d Vx,Hx,Wx,Ib (66),(ev) | ||
835 | 30: kshiftrb/w Vk,Uk,Ib (66),(v) | ||
836 | 31: kshiftrd/q Vk,Uk,Ib (66),(v) | ||
837 | 32: kshiftlb/w Vk,Uk,Ib (66),(v) | ||
838 | 33: kshiftld/q Vk,Uk,Ib (66),(v) | ||
839 | 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | vinserti32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo) | ||
840 | 39: vextracti128 Wdq,Vqq,Ib (66),(v) | vextracti32x4/64x2 Wdq,Vqq,Ib (66),(evo) | ||
841 | 3a: vinserti32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev) | ||
842 | 3b: vextracti32x8/64x4 Wdq,Vqq,Ib (66),(ev) | ||
843 | 3e: vpcmpub/w Vk,Hk,Wx,Ib (66),(ev) | ||
844 | 3f: vpcmpb/w Vk,Hk,Wx,Ib (66),(ev) | ||
791 | 40: vdpps Vx,Hx,Wx,Ib (66) | 845 | 40: vdpps Vx,Hx,Wx,Ib (66) |
792 | 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) | 846 | 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) |
793 | 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | 847 | 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | vdbpsadbw Vx,Hx,Wx,Ib (66),(evo) |
848 | 43: vshufi32x4/64x2 Vx,Hx,Wx,Ib (66),(ev) | ||
794 | 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) | 849 | 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) |
795 | 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) | 850 | 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) |
796 | 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) | 851 | 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) |
797 | 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) | 852 | 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) |
798 | 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) | 853 | 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) |
854 | 50: vrangeps/d Vx,Hx,Wx,Ib (66),(ev) | ||
855 | 51: vrangess/d Vx,Hx,Wx,Ib (66),(ev) | ||
856 | 54: vfixupimmps/d Vx,Hx,Wx,Ib (66),(ev) | ||
857 | 55: vfixupimmss/d Vx,Hx,Wx,Ib (66),(ev) | ||
858 | 56: vreduceps/d Vx,Wx,Ib (66),(ev) | ||
859 | 57: vreducess/d Vx,Hx,Wx,Ib (66),(ev) | ||
799 | 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) | 860 | 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) |
800 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) | 861 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) |
801 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) | 862 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) |
802 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) | 863 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) |
864 | 66: vfpclassps/d Vk,Wx,Ib (66),(ev) | ||
865 | 67: vfpclassss/d Vk,Wx,Ib (66),(ev) | ||
803 | cc: sha1rnds4 Vdq,Wdq,Ib | 866 | cc: sha1rnds4 Vdq,Wdq,Ib |
804 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) | 867 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) |
805 | f0: RORX Gy,Ey,Ib (F2),(v) | 868 | f0: RORX Gy,Ey,Ib (F2),(v) |
@@ -927,8 +990,10 @@ GrpTable: Grp12 | |||
927 | EndTable | 990 | EndTable |
928 | 991 | ||
929 | GrpTable: Grp13 | 992 | GrpTable: Grp13 |
993 | 0: vprord/q Hx,Wx,Ib (66),(ev) | ||
994 | 1: vprold/q Hx,Wx,Ib (66),(ev) | ||
930 | 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) | 995 | 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) |
931 | 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | 996 | 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | vpsrad/q Hx,Ux,Ib (66),(evo) |
932 | 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) | 997 | 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) |
933 | EndTable | 998 | EndTable |
934 | 999 | ||
@@ -947,7 +1012,7 @@ GrpTable: Grp15 | |||
947 | 4: XSAVE | 1012 | 4: XSAVE |
948 | 5: XRSTOR | lfence (11B) | 1013 | 5: XRSTOR | lfence (11B) |
949 | 6: XSAVEOPT | clwb (66) | mfence (11B) | 1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) |
950 | 7: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B) | 1015 | 7: clflush | clflushopt (66) | sfence (11B) |
951 | EndTable | 1016 | EndTable |
952 | 1017 | ||
953 | GrpTable: Grp16 | 1018 | GrpTable: Grp16 |
@@ -963,6 +1028,20 @@ GrpTable: Grp17 | |||
963 | 3: BLSI By,Ey (v) | 1028 | 3: BLSI By,Ey (v) |
964 | EndTable | 1029 | EndTable |
965 | 1030 | ||
1031 | GrpTable: Grp18 | ||
1032 | 1: vgatherpf0dps/d Wx (66),(ev) | ||
1033 | 2: vgatherpf1dps/d Wx (66),(ev) | ||
1034 | 5: vscatterpf0dps/d Wx (66),(ev) | ||
1035 | 6: vscatterpf1dps/d Wx (66),(ev) | ||
1036 | EndTable | ||
1037 | |||
1038 | GrpTable: Grp19 | ||
1039 | 1: vgatherpf0qps/d Wx (66),(ev) | ||
1040 | 2: vgatherpf1qps/d Wx (66),(ev) | ||
1041 | 5: vscatterpf0qps/d Wx (66),(ev) | ||
1042 | 6: vscatterpf1qps/d Wx (66),(ev) | ||
1043 | EndTable | ||
1044 | |||
966 | # AMD's Prefetch Group | 1045 | # AMD's Prefetch Group |
967 | GrpTable: GrpP | 1046 | GrpTable: GrpP |
968 | 0: PREFETCH | 1047 | 0: PREFETCH |
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 17fa7fc34fdf..bd09d0effef8 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c | |||
@@ -107,6 +107,12 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file, | |||
107 | insn->offset < func->offset + func->len; \ | 107 | insn->offset < func->offset + func->len; \ |
108 | insn = list_next_entry(insn, list)) | 108 | insn = list_next_entry(insn, list)) |
109 | 109 | ||
110 | #define func_for_each_insn_continue_reverse(file, func, insn) \ | ||
111 | for (insn = list_prev_entry(insn, list); \ | ||
112 | &insn->list != &file->insn_list && \ | ||
113 | insn->sec == func->sec && insn->offset >= func->offset; \ | ||
114 | insn = list_prev_entry(insn, list)) | ||
115 | |||
110 | #define sec_for_each_insn_from(file, insn) \ | 116 | #define sec_for_each_insn_from(file, insn) \ |
111 | for (; insn; insn = next_insn_same_sec(file, insn)) | 117 | for (; insn; insn = next_insn_same_sec(file, insn)) |
112 | 118 | ||
@@ -664,65 +670,95 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func, | |||
664 | return 0; | 670 | return 0; |
665 | } | 671 | } |
666 | 672 | ||
667 | static int add_func_switch_tables(struct objtool_file *file, | 673 | /* |
668 | struct symbol *func) | 674 | * find_switch_table() - Given a dynamic jump, find the switch jump table in |
675 | * .rodata associated with it. | ||
676 | * | ||
677 | * There are 3 basic patterns: | ||
678 | * | ||
679 | * 1. jmpq *[rodata addr](,%reg,8) | ||
680 | * | ||
681 | * This is the most common case by far. It jumps to an address in a simple | ||
682 | * jump table which is stored in .rodata. | ||
683 | * | ||
684 | * 2. jmpq *[rodata addr](%rip) | ||
685 | * | ||
686 | * This is caused by a rare GCC quirk, currently only seen in three driver | ||
687 | * functions in the kernel, only with certain obscure non-distro configs. | ||
688 | * | ||
689 | * As part of an optimization, GCC makes a copy of an existing switch jump | ||
690 | * table, modifies it, and then hard-codes the jump (albeit with an indirect | ||
691 | * jump) to use a single entry in the table. The rest of the jump table and | ||
692 | * some of its jump targets remain as dead code. | ||
693 | * | ||
694 | * In such a case we can just crudely ignore all unreachable instruction | ||
695 | * warnings for the entire object file. Ideally we would just ignore them | ||
696 | * for the function, but that would require redesigning the code quite a | ||
697 | * bit. And honestly that's just not worth doing: unreachable instruction | ||
698 | * warnings are of questionable value anyway, and this is such a rare issue. | ||
699 | * | ||
700 | * 3. mov [rodata addr],%reg1 | ||
701 | * ... some instructions ... | ||
702 | * jmpq *(%reg1,%reg2,8) | ||
703 | * | ||
704 | * This is a fairly uncommon pattern which is new for GCC 6. As of this | ||
705 | * writing, there are 11 occurrences of it in the allmodconfig kernel. | ||
706 | * | ||
707 | * TODO: Once we have DWARF CFI and smarter instruction decoding logic, | ||
708 | * ensure the same register is used in the mov and jump instructions. | ||
709 | */ | ||
710 | static struct rela *find_switch_table(struct objtool_file *file, | ||
711 | struct symbol *func, | ||
712 | struct instruction *insn) | ||
669 | { | 713 | { |
670 | struct instruction *insn, *prev_jump; | 714 | struct rela *text_rela, *rodata_rela; |
671 | struct rela *text_rela, *rodata_rela, *prev_rela = NULL; | ||
672 | int ret; | ||
673 | 715 | ||
674 | prev_jump = NULL; | 716 | text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len); |
717 | if (text_rela && text_rela->sym == file->rodata->sym) { | ||
718 | /* case 1 */ | ||
719 | rodata_rela = find_rela_by_dest(file->rodata, | ||
720 | text_rela->addend); | ||
721 | if (rodata_rela) | ||
722 | return rodata_rela; | ||
675 | 723 | ||
676 | func_for_each_insn(file, func, insn) { | 724 | /* case 2 */ |
677 | if (insn->type != INSN_JUMP_DYNAMIC) | 725 | rodata_rela = find_rela_by_dest(file->rodata, |
678 | continue; | 726 | text_rela->addend + 4); |
727 | if (!rodata_rela) | ||
728 | return NULL; | ||
729 | file->ignore_unreachables = true; | ||
730 | return rodata_rela; | ||
731 | } | ||
732 | |||
733 | /* case 3 */ | ||
734 | func_for_each_insn_continue_reverse(file, func, insn) { | ||
735 | if (insn->type == INSN_JUMP_UNCONDITIONAL || | ||
736 | insn->type == INSN_JUMP_DYNAMIC) | ||
737 | break; | ||
679 | 738 | ||
680 | text_rela = find_rela_by_dest_range(insn->sec, insn->offset, | 739 | text_rela = find_rela_by_dest_range(insn->sec, insn->offset, |
681 | insn->len); | 740 | insn->len); |
682 | if (!text_rela || text_rela->sym != file->rodata->sym) | 741 | if (text_rela && text_rela->sym == file->rodata->sym) |
683 | continue; | 742 | return find_rela_by_dest(file->rodata, |
743 | text_rela->addend); | ||
744 | } | ||
684 | 745 | ||
685 | /* common case: jmpq *[addr](,%rax,8) */ | 746 | return NULL; |
686 | rodata_rela = find_rela_by_dest(file->rodata, | 747 | } |
687 | text_rela->addend); | ||
688 | 748 | ||
689 | /* | 749 | static int add_func_switch_tables(struct objtool_file *file, |
690 | * rare case: jmpq *[addr](%rip) | 750 | struct symbol *func) |
691 | * | 751 | { |
692 | * This check is for a rare gcc quirk, currently only seen in | 752 | struct instruction *insn, *prev_jump = NULL; |
693 | * three driver functions in the kernel, only with certain | 753 | struct rela *rela, *prev_rela = NULL; |
694 | * obscure non-distro configs. | 754 | int ret; |
695 | * | ||
696 | * As part of an optimization, gcc makes a copy of an existing | ||
697 | * switch jump table, modifies it, and then hard-codes the jump | ||
698 | * (albeit with an indirect jump) to use a single entry in the | ||
699 | * table. The rest of the jump table and some of its jump | ||
700 | * targets remain as dead code. | ||
701 | * | ||
702 | * In such a case we can just crudely ignore all unreachable | ||
703 | * instruction warnings for the entire object file. Ideally we | ||
704 | * would just ignore them for the function, but that would | ||
705 | * require redesigning the code quite a bit. And honestly | ||
706 | * that's just not worth doing: unreachable instruction | ||
707 | * warnings are of questionable value anyway, and this is such | ||
708 | * a rare issue. | ||
709 | * | ||
710 | * kbuild reports: | ||
711 | * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com | ||
712 | * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com | ||
713 | * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com | ||
714 | * | ||
715 | * gcc bug: | ||
716 | * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604 | ||
717 | */ | ||
718 | if (!rodata_rela) { | ||
719 | rodata_rela = find_rela_by_dest(file->rodata, | ||
720 | text_rela->addend + 4); | ||
721 | if (rodata_rela) | ||
722 | file->ignore_unreachables = true; | ||
723 | } | ||
724 | 755 | ||
725 | if (!rodata_rela) | 756 | func_for_each_insn(file, func, insn) { |
757 | if (insn->type != INSN_JUMP_DYNAMIC) | ||
758 | continue; | ||
759 | |||
760 | rela = find_switch_table(file, func, insn); | ||
761 | if (!rela) | ||
726 | continue; | 762 | continue; |
727 | 763 | ||
728 | /* | 764 | /* |
@@ -732,13 +768,13 @@ static int add_func_switch_tables(struct objtool_file *file, | |||
732 | */ | 768 | */ |
733 | if (prev_jump) { | 769 | if (prev_jump) { |
734 | ret = add_switch_table(file, func, prev_jump, prev_rela, | 770 | ret = add_switch_table(file, func, prev_jump, prev_rela, |
735 | rodata_rela); | 771 | rela); |
736 | if (ret) | 772 | if (ret) |
737 | return ret; | 773 | return ret; |
738 | } | 774 | } |
739 | 775 | ||
740 | prev_jump = insn; | 776 | prev_jump = insn; |
741 | prev_rela = rodata_rela; | 777 | prev_rela = rela; |
742 | } | 778 | } |
743 | 779 | ||
744 | if (prev_jump) { | 780 | if (prev_jump) { |
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build index 8a61372bb47a..5bd7b9260cc0 100644 --- a/tools/perf/arch/s390/util/Build +++ b/tools/perf/arch/s390/util/Build | |||
@@ -2,3 +2,5 @@ libperf-y += header.o | |||
2 | libperf-y += kvm-stat.o | 2 | libperf-y += kvm-stat.o |
3 | 3 | ||
4 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 4 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
5 | |||
6 | libperf-y += machine.o | ||
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c new file mode 100644 index 000000000000..b9a95a1a8e69 --- /dev/null +++ b/tools/perf/arch/s390/util/machine.c | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <unistd.h> | ||
2 | #include <stdio.h> | ||
3 | #include <string.h> | ||
4 | #include "util.h" | ||
5 | #include "machine.h" | ||
6 | #include "api/fs/fs.h" | ||
7 | |||
8 | int arch__fix_module_text_start(u64 *start, const char *name) | ||
9 | { | ||
10 | char path[PATH_MAX]; | ||
11 | |||
12 | snprintf(path, PATH_MAX, "module/%.*s/sections/.text", | ||
13 | (int)strlen(name) - 2, name + 1); | ||
14 | |||
15 | if (sysfs__read_ull(path, (unsigned long long *)start) < 0) | ||
16 | return -1; | ||
17 | |||
18 | return 0; | ||
19 | } | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c index 3918dd52e903..0f196eec9f48 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c | |||
@@ -1664,5 +1664,3 @@ | |||
1664 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, | 1664 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, |
1665 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1665 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", |
1666 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, | 1666 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, |
1667 | {{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "", | ||
1668 | "66 0f ae f8 \tpcommit ",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c index 9c8c61e06d5a..af25bc8240d0 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c | |||
@@ -1696,5 +1696,3 @@ | |||
1696 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, | 1696 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, |
1697 | {{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | 1697 | {{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", |
1698 | "41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, | 1698 | "41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, |
1699 | {{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "", | ||
1700 | "66 0f ae f8 \tpcommit ",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c index 76e0ec379c8b..979487dae8d4 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c | |||
@@ -2655,10 +2655,6 @@ int main(void) | |||
2655 | 2655 | ||
2656 | #endif /* #ifndef __x86_64__ */ | 2656 | #endif /* #ifndef __x86_64__ */ |
2657 | 2657 | ||
2658 | /* pcommit */ | ||
2659 | |||
2660 | asm volatile("pcommit"); | ||
2661 | |||
2662 | /* Following line is a marker for the awk script - do not change */ | 2658 | /* Following line is a marker for the awk script - do not change */ |
2663 | asm volatile("rdtsc"); /* Stop here */ | 2659 | asm volatile("rdtsc"); /* Stop here */ |
2664 | 2660 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index b1d491c2e704..fdde1bd3e306 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -608,6 +608,7 @@ static const struct { | |||
608 | const char *compact; | 608 | const char *compact; |
609 | } gfp_compact_table[] = { | 609 | } gfp_compact_table[] = { |
610 | { "GFP_TRANSHUGE", "THP" }, | 610 | { "GFP_TRANSHUGE", "THP" }, |
611 | { "GFP_TRANSHUGE_LIGHT", "THL" }, | ||
611 | { "GFP_HIGHUSER_MOVABLE", "HUM" }, | 612 | { "GFP_HIGHUSER_MOVABLE", "HUM" }, |
612 | { "GFP_HIGHUSER", "HU" }, | 613 | { "GFP_HIGHUSER", "HU" }, |
613 | { "GFP_USER", "U" }, | 614 | { "GFP_USER", "U" }, |
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py index 4d21ef2d601d..4c6f09ac7d12 100644 --- a/tools/perf/scripts/python/netdev-times.py +++ b/tools/perf/scripts/python/netdev-times.py | |||
@@ -252,9 +252,10 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i | |||
252 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) | 252 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) |
253 | all_event_list.append(event_info) | 253 | all_event_list.append(event_info) |
254 | 254 | ||
255 | def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): | 255 | def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, |
256 | dev_name, work=None, budget=None): | ||
256 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, | 257 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, |
257 | napi, dev_name) | 258 | napi, dev_name, work, budget) |
258 | all_event_list.append(event_info) | 259 | all_event_list.append(event_info) |
259 | 260 | ||
260 | def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, | 261 | def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, |
@@ -354,11 +355,13 @@ def handle_irq_softirq_exit(event_info): | |||
354 | receive_hunk_list.append(rec_data) | 355 | receive_hunk_list.append(rec_data) |
355 | 356 | ||
356 | def handle_napi_poll(event_info): | 357 | def handle_napi_poll(event_info): |
357 | (name, context, cpu, time, pid, comm, napi, dev_name) = event_info | 358 | (name, context, cpu, time, pid, comm, napi, dev_name, |
359 | work, budget) = event_info | ||
358 | if cpu in net_rx_dic.keys(): | 360 | if cpu in net_rx_dic.keys(): |
359 | event_list = net_rx_dic[cpu]['event_list'] | 361 | event_list = net_rx_dic[cpu]['event_list'] |
360 | rec_data = {'event_name':'napi_poll', | 362 | rec_data = {'event_name':'napi_poll', |
361 | 'dev':dev_name, 'event_t':time} | 363 | 'dev':dev_name, 'event_t':time, |
364 | 'work':work, 'budget':budget} | ||
362 | event_list.append(rec_data) | 365 | event_list.append(rec_data) |
363 | 366 | ||
364 | def handle_netif_rx(event_info): | 367 | def handle_netif_rx(event_info): |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 2fa7d8b69873..91c5f6e1af59 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -70,7 +70,6 @@ libperf-y += stat.o | |||
70 | libperf-y += stat-shadow.o | 70 | libperf-y += stat-shadow.o |
71 | libperf-y += record.o | 71 | libperf-y += record.o |
72 | libperf-y += srcline.o | 72 | libperf-y += srcline.o |
73 | libperf-y += str_error_r.o | ||
74 | libperf-y += data.o | 73 | libperf-y += data.o |
75 | libperf-y += tsc.o | 74 | libperf-y += tsc.o |
76 | libperf-y += cloexec.o | 75 | libperf-y += cloexec.o |
@@ -176,10 +175,6 @@ $(OUTPUT)util/libstring.o: ../lib/string.c FORCE | |||
176 | $(call rule_mkdir) | 175 | $(call rule_mkdir) |
177 | $(call if_changed_dep,cc_o_c) | 176 | $(call if_changed_dep,cc_o_c) |
178 | 177 | ||
179 | $(OUTPUT)util/str_error_r.o: ../lib/str_error_r.c FORCE | ||
180 | $(call rule_mkdir) | ||
181 | $(call if_changed_dep,cc_o_c) | ||
182 | |||
183 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE | 178 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE |
184 | $(call rule_mkdir) | 179 | $(call rule_mkdir) |
185 | $(call if_changed_dep,cc_o_c) | 180 | $(call if_changed_dep,cc_o_c) |
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt index ec378cd7b71e..767be7c76034 100644 --- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt +++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt | |||
@@ -1012,7 +1012,7 @@ GrpTable: Grp15 | |||
1012 | 4: XSAVE | 1012 | 4: XSAVE |
1013 | 5: XRSTOR | lfence (11B) | 1013 | 5: XRSTOR | lfence (11B) |
1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) | 1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) |
1015 | 7: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B) | 1015 | 7: clflush | clflushopt (66) | sfence (11B) |
1016 | EndTable | 1016 | EndTable |
1017 | 1017 | ||
1018 | GrpTable: Grp16 | 1018 | GrpTable: Grp16 |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index bc2cdbd09a25..cb6388dbdd98 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1093,12 +1093,20 @@ static int machine__set_modules_path(struct machine *machine) | |||
1093 | 1093 | ||
1094 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); | 1094 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); |
1095 | } | 1095 | } |
1096 | int __weak arch__fix_module_text_start(u64 *start __maybe_unused, | ||
1097 | const char *name __maybe_unused) | ||
1098 | { | ||
1099 | return 0; | ||
1100 | } | ||
1096 | 1101 | ||
1097 | static int machine__create_module(void *arg, const char *name, u64 start) | 1102 | static int machine__create_module(void *arg, const char *name, u64 start) |
1098 | { | 1103 | { |
1099 | struct machine *machine = arg; | 1104 | struct machine *machine = arg; |
1100 | struct map *map; | 1105 | struct map *map; |
1101 | 1106 | ||
1107 | if (arch__fix_module_text_start(&start, name) < 0) | ||
1108 | return -1; | ||
1109 | |||
1102 | map = machine__findnew_module_map(machine, start, name); | 1110 | map = machine__findnew_module_map(machine, start, name); |
1103 | if (map == NULL) | 1111 | if (map == NULL) |
1104 | return -1; | 1112 | return -1; |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 41ac9cfd416b..20739f746bc4 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -216,6 +216,7 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine, | |||
216 | 216 | ||
217 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, | 217 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, |
218 | const char *filename); | 218 | const char *filename); |
219 | int arch__fix_module_text_start(u64 *start, const char *name); | ||
219 | 220 | ||
220 | int __machine__load_kallsyms(struct machine *machine, const char *filename, | 221 | int __machine__load_kallsyms(struct machine *machine, const char *filename, |
221 | enum map_type type, bool no_kcore, symbol_filter_t filter); | 222 | enum map_type type, bool no_kcore, symbol_filter_t filter); |
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 5065ec98049c..b7d4f4aeee61 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
@@ -13,7 +13,6 @@ util/cpumap.c | |||
13 | ../lib/bitmap.c | 13 | ../lib/bitmap.c |
14 | ../lib/find_bit.c | 14 | ../lib/find_bit.c |
15 | ../lib/hweight.c | 15 | ../lib/hweight.c |
16 | ../lib/str_error_r.c | ||
17 | ../lib/vsprintf.c | 16 | ../lib/vsprintf.c |
18 | util/thread_map.c | 17 | util/thread_map.c |
19 | util/util.c | 18 | util/util.c |
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index 785985677159..ad6dd0543019 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild | |||
@@ -11,12 +11,14 @@ ldflags-y += --wrap=__devm_release_region | |||
11 | ldflags-y += --wrap=__request_region | 11 | ldflags-y += --wrap=__request_region |
12 | ldflags-y += --wrap=__release_region | 12 | ldflags-y += --wrap=__release_region |
13 | ldflags-y += --wrap=devm_memremap_pages | 13 | ldflags-y += --wrap=devm_memremap_pages |
14 | ldflags-y += --wrap=phys_to_pfn_t | 14 | ldflags-y += --wrap=insert_resource |
15 | ldflags-y += --wrap=remove_resource | ||
15 | 16 | ||
16 | DRIVERS := ../../../drivers | 17 | DRIVERS := ../../../drivers |
17 | NVDIMM_SRC := $(DRIVERS)/nvdimm | 18 | NVDIMM_SRC := $(DRIVERS)/nvdimm |
18 | ACPI_SRC := $(DRIVERS)/acpi | 19 | ACPI_SRC := $(DRIVERS)/acpi/nfit |
19 | DAX_SRC := $(DRIVERS)/dax | 20 | DAX_SRC := $(DRIVERS)/dax |
21 | ccflags-y := -I$(src)/$(NVDIMM_SRC)/ | ||
20 | 22 | ||
21 | obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o | 23 | obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o |
22 | obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o | 24 | obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o |
@@ -27,10 +29,12 @@ obj-$(CONFIG_ACPI_NFIT) += nfit.o | |||
27 | obj-$(CONFIG_DEV_DAX) += dax.o | 29 | obj-$(CONFIG_DEV_DAX) += dax.o |
28 | obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o | 30 | obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o |
29 | 31 | ||
30 | nfit-y := $(ACPI_SRC)/nfit.o | 32 | nfit-y := $(ACPI_SRC)/core.o |
33 | nfit-$(CONFIG_X86_MCE) += $(ACPI_SRC)/mce.o | ||
31 | nfit-y += config_check.o | 34 | nfit-y += config_check.o |
32 | 35 | ||
33 | nd_pmem-y := $(NVDIMM_SRC)/pmem.o | 36 | nd_pmem-y := $(NVDIMM_SRC)/pmem.o |
37 | nd_pmem-y += pmem-dax.o | ||
34 | nd_pmem-y += config_check.o | 38 | nd_pmem-y += config_check.o |
35 | 39 | ||
36 | nd_btt-y := $(NVDIMM_SRC)/btt.o | 40 | nd_btt-y := $(NVDIMM_SRC)/btt.o |
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c index adf18bfeca00..878daf3429e8 100644 --- a/tools/testing/nvdimm/config_check.c +++ b/tools/testing/nvdimm/config_check.c | |||
@@ -10,6 +10,7 @@ void check(void) | |||
10 | BUILD_BUG_ON(!IS_MODULE(CONFIG_LIBNVDIMM)); | 10 | BUILD_BUG_ON(!IS_MODULE(CONFIG_LIBNVDIMM)); |
11 | BUILD_BUG_ON(!IS_MODULE(CONFIG_BLK_DEV_PMEM)); | 11 | BUILD_BUG_ON(!IS_MODULE(CONFIG_BLK_DEV_PMEM)); |
12 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); | 12 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); |
13 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_PFN)); | ||
13 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); | 14 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); |
14 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); | 15 | BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); |
15 | BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX)); | 16 | BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX)); |
diff --git a/tools/testing/nvdimm/pmem-dax.c b/tools/testing/nvdimm/pmem-dax.c new file mode 100644 index 000000000000..c9b8c48f85fc --- /dev/null +++ b/tools/testing/nvdimm/pmem-dax.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014-2016, Intel Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | #include "test/nfit_test.h" | ||
14 | #include <linux/blkdev.h> | ||
15 | #include <pmem.h> | ||
16 | #include <nd.h> | ||
17 | |||
18 | long pmem_direct_access(struct block_device *bdev, sector_t sector, | ||
19 | void **kaddr, pfn_t *pfn, long size) | ||
20 | { | ||
21 | struct pmem_device *pmem = bdev->bd_queue->queuedata; | ||
22 | resource_size_t offset = sector * 512 + pmem->data_offset; | ||
23 | |||
24 | if (unlikely(is_bad_pmem(&pmem->bb, sector, size))) | ||
25 | return -EIO; | ||
26 | |||
27 | /* | ||
28 | * Limit dax to a single page at a time given vmalloc()-backed | ||
29 | * in the nfit_test case. | ||
30 | */ | ||
31 | if (get_nfit_res(pmem->phys_addr + offset)) { | ||
32 | struct page *page; | ||
33 | |||
34 | *kaddr = pmem->virt_addr + offset; | ||
35 | page = vmalloc_to_page(pmem->virt_addr + offset); | ||
36 | *pfn = page_to_pfn_t(page); | ||
37 | dev_dbg_ratelimited(disk_to_dev(bdev->bd_disk)->parent, | ||
38 | "%s: sector: %#llx pfn: %#lx\n", __func__, | ||
39 | (unsigned long long) sector, page_to_pfn(page)); | ||
40 | |||
41 | return PAGE_SIZE; | ||
42 | } | ||
43 | |||
44 | *kaddr = pmem->virt_addr + offset; | ||
45 | *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags); | ||
46 | |||
47 | /* | ||
48 | * If badblocks are present, limit known good range to the | ||
49 | * requested range. | ||
50 | */ | ||
51 | if (unlikely(pmem->bb.count)) | ||
52 | return size; | ||
53 | return pmem->size - pmem->pfn_pad - offset; | ||
54 | } | ||
diff --git a/tools/testing/nvdimm/test/Kbuild b/tools/testing/nvdimm/test/Kbuild index 9241064970fe..d32f25bba42a 100644 --- a/tools/testing/nvdimm/test/Kbuild +++ b/tools/testing/nvdimm/test/Kbuild | |||
@@ -1,5 +1,5 @@ | |||
1 | ccflags-y := -I$(src)/../../../../drivers/nvdimm/ | 1 | ccflags-y := -I$(src)/../../../../drivers/nvdimm/ |
2 | ccflags-y += -I$(src)/../../../../drivers/acpi/ | 2 | ccflags-y += -I$(src)/../../../../drivers/acpi/nfit/ |
3 | 3 | ||
4 | obj-m += nfit_test.o | 4 | obj-m += nfit_test.o |
5 | obj-m += nfit_test_iomap.o | 5 | obj-m += nfit_test_iomap.o |
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index c842095f2801..c29f8dca9e67 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c | |||
@@ -10,11 +10,13 @@ | |||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
11 | * General Public License for more details. | 11 | * General Public License for more details. |
12 | */ | 12 | */ |
13 | #include <linux/memremap.h> | ||
13 | #include <linux/rculist.h> | 14 | #include <linux/rculist.h> |
14 | #include <linux/export.h> | 15 | #include <linux/export.h> |
15 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/pfn_t.h> | ||
18 | #include <linux/io.h> | 20 | #include <linux/io.h> |
19 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
20 | #include "nfit_test.h" | 22 | #include "nfit_test.h" |
@@ -52,7 +54,7 @@ static struct nfit_test_resource *__get_nfit_res(resource_size_t resource) | |||
52 | return NULL; | 54 | return NULL; |
53 | } | 55 | } |
54 | 56 | ||
55 | static struct nfit_test_resource *get_nfit_res(resource_size_t resource) | 57 | struct nfit_test_resource *get_nfit_res(resource_size_t resource) |
56 | { | 58 | { |
57 | struct nfit_test_resource *res; | 59 | struct nfit_test_resource *res; |
58 | 60 | ||
@@ -62,6 +64,7 @@ static struct nfit_test_resource *get_nfit_res(resource_size_t resource) | |||
62 | 64 | ||
63 | return res; | 65 | return res; |
64 | } | 66 | } |
67 | EXPORT_SYMBOL(get_nfit_res); | ||
65 | 68 | ||
66 | void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, | 69 | void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, |
67 | void __iomem *(*fallback_fn)(resource_size_t, unsigned long)) | 70 | void __iomem *(*fallback_fn)(resource_size_t, unsigned long)) |
@@ -97,10 +100,6 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset, | |||
97 | } | 100 | } |
98 | EXPORT_SYMBOL(__wrap_devm_memremap); | 101 | EXPORT_SYMBOL(__wrap_devm_memremap); |
99 | 102 | ||
100 | #ifdef __HAVE_ARCH_PTE_DEVMAP | ||
101 | #include <linux/memremap.h> | ||
102 | #include <linux/pfn_t.h> | ||
103 | |||
104 | void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res, | 103 | void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res, |
105 | struct percpu_ref *ref, struct vmem_altmap *altmap) | 104 | struct percpu_ref *ref, struct vmem_altmap *altmap) |
106 | { | 105 | { |
@@ -122,19 +121,6 @@ pfn_t __wrap_phys_to_pfn_t(phys_addr_t addr, unsigned long flags) | |||
122 | return phys_to_pfn_t(addr, flags); | 121 | return phys_to_pfn_t(addr, flags); |
123 | } | 122 | } |
124 | EXPORT_SYMBOL(__wrap_phys_to_pfn_t); | 123 | EXPORT_SYMBOL(__wrap_phys_to_pfn_t); |
125 | #else | ||
126 | /* to be removed post 4.5-rc1 */ | ||
127 | void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res) | ||
128 | { | ||
129 | resource_size_t offset = res->start; | ||
130 | struct nfit_test_resource *nfit_res = get_nfit_res(offset); | ||
131 | |||
132 | if (nfit_res) | ||
133 | return nfit_res->buf + offset - nfit_res->res->start; | ||
134 | return devm_memremap_pages(dev, res); | ||
135 | } | ||
136 | EXPORT_SYMBOL(__wrap_devm_memremap_pages); | ||
137 | #endif | ||
138 | 124 | ||
139 | void *__wrap_memremap(resource_size_t offset, size_t size, | 125 | void *__wrap_memremap(resource_size_t offset, size_t size, |
140 | unsigned long flags) | 126 | unsigned long flags) |
@@ -229,6 +215,22 @@ struct resource *__wrap___request_region(struct resource *parent, | |||
229 | } | 215 | } |
230 | EXPORT_SYMBOL(__wrap___request_region); | 216 | EXPORT_SYMBOL(__wrap___request_region); |
231 | 217 | ||
218 | int __wrap_insert_resource(struct resource *parent, struct resource *res) | ||
219 | { | ||
220 | if (get_nfit_res(res->start)) | ||
221 | return 0; | ||
222 | return insert_resource(parent, res); | ||
223 | } | ||
224 | EXPORT_SYMBOL(__wrap_insert_resource); | ||
225 | |||
226 | int __wrap_remove_resource(struct resource *res) | ||
227 | { | ||
228 | if (get_nfit_res(res->start)) | ||
229 | return 0; | ||
230 | return remove_resource(res); | ||
231 | } | ||
232 | EXPORT_SYMBOL(__wrap_remove_resource); | ||
233 | |||
232 | struct resource *__wrap___devm_request_region(struct device *dev, | 234 | struct resource *__wrap___devm_request_region(struct device *dev, |
233 | struct resource *parent, resource_size_t start, | 235 | struct resource *parent, resource_size_t start, |
234 | resource_size_t n, const char *name) | 236 | resource_size_t n, const char *name) |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index c919866853a0..5404efa578a3 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -98,11 +98,13 @@ | |||
98 | enum { | 98 | enum { |
99 | NUM_PM = 3, | 99 | NUM_PM = 3, |
100 | NUM_DCR = 5, | 100 | NUM_DCR = 5, |
101 | NUM_HINTS = 8, | ||
101 | NUM_BDW = NUM_DCR, | 102 | NUM_BDW = NUM_DCR, |
102 | NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW, | 103 | NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW, |
103 | NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */, | 104 | NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */, |
104 | DIMM_SIZE = SZ_32M, | 105 | DIMM_SIZE = SZ_32M, |
105 | LABEL_SIZE = SZ_128K, | 106 | LABEL_SIZE = SZ_128K, |
107 | SPA_VCD_SIZE = SZ_4M, | ||
106 | SPA0_SIZE = DIMM_SIZE, | 108 | SPA0_SIZE = DIMM_SIZE, |
107 | SPA1_SIZE = DIMM_SIZE*2, | 109 | SPA1_SIZE = DIMM_SIZE*2, |
108 | SPA2_SIZE = DIMM_SIZE, | 110 | SPA2_SIZE = DIMM_SIZE, |
@@ -470,11 +472,7 @@ static void release_nfit_res(void *data) | |||
470 | list_del(&nfit_res->list); | 472 | list_del(&nfit_res->list); |
471 | spin_unlock(&nfit_test_lock); | 473 | spin_unlock(&nfit_test_lock); |
472 | 474 | ||
473 | if (is_vmalloc_addr(nfit_res->buf)) | 475 | vfree(nfit_res->buf); |
474 | vfree(nfit_res->buf); | ||
475 | else | ||
476 | dma_free_coherent(nfit_res->dev, resource_size(res), | ||
477 | nfit_res->buf, res->start); | ||
478 | kfree(res); | 476 | kfree(res); |
479 | kfree(nfit_res); | 477 | kfree(nfit_res); |
480 | } | 478 | } |
@@ -507,9 +505,7 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma, | |||
507 | 505 | ||
508 | return nfit_res->buf; | 506 | return nfit_res->buf; |
509 | err: | 507 | err: |
510 | if (buf && !is_vmalloc_addr(buf)) | 508 | if (buf) |
511 | dma_free_coherent(dev, size, buf, *dma); | ||
512 | else if (buf) | ||
513 | vfree(buf); | 509 | vfree(buf); |
514 | kfree(res); | 510 | kfree(res); |
515 | kfree(nfit_res); | 511 | kfree(nfit_res); |
@@ -524,15 +520,6 @@ static void *test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma) | |||
524 | return __test_alloc(t, size, dma, buf); | 520 | return __test_alloc(t, size, dma, buf); |
525 | } | 521 | } |
526 | 522 | ||
527 | static void *test_alloc_coherent(struct nfit_test *t, size_t size, | ||
528 | dma_addr_t *dma) | ||
529 | { | ||
530 | struct device *dev = &t->pdev.dev; | ||
531 | void *buf = dma_alloc_coherent(dev, size, dma, GFP_KERNEL); | ||
532 | |||
533 | return __test_alloc(t, size, dma, buf); | ||
534 | } | ||
535 | |||
536 | static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) | 523 | static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) |
537 | { | 524 | { |
538 | int i; | 525 | int i; |
@@ -584,7 +571,8 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
584 | + offsetof(struct acpi_nfit_control_region, | 571 | + offsetof(struct acpi_nfit_control_region, |
585 | window_size) * NUM_DCR | 572 | window_size) * NUM_DCR |
586 | + sizeof(struct acpi_nfit_data_region) * NUM_BDW | 573 | + sizeof(struct acpi_nfit_data_region) * NUM_BDW |
587 | + sizeof(struct acpi_nfit_flush_address) * NUM_DCR; | 574 | + (sizeof(struct acpi_nfit_flush_address) |
575 | + sizeof(u64) * NUM_HINTS) * NUM_DCR; | ||
588 | int i; | 576 | int i; |
589 | 577 | ||
590 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); | 578 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); |
@@ -592,15 +580,15 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
592 | return -ENOMEM; | 580 | return -ENOMEM; |
593 | t->nfit_size = nfit_size; | 581 | t->nfit_size = nfit_size; |
594 | 582 | ||
595 | t->spa_set[0] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[0]); | 583 | t->spa_set[0] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[0]); |
596 | if (!t->spa_set[0]) | 584 | if (!t->spa_set[0]) |
597 | return -ENOMEM; | 585 | return -ENOMEM; |
598 | 586 | ||
599 | t->spa_set[1] = test_alloc_coherent(t, SPA1_SIZE, &t->spa_set_dma[1]); | 587 | t->spa_set[1] = test_alloc(t, SPA1_SIZE, &t->spa_set_dma[1]); |
600 | if (!t->spa_set[1]) | 588 | if (!t->spa_set[1]) |
601 | return -ENOMEM; | 589 | return -ENOMEM; |
602 | 590 | ||
603 | t->spa_set[2] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[2]); | 591 | t->spa_set[2] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[2]); |
604 | if (!t->spa_set[2]) | 592 | if (!t->spa_set[2]) |
605 | return -ENOMEM; | 593 | return -ENOMEM; |
606 | 594 | ||
@@ -614,7 +602,8 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
614 | return -ENOMEM; | 602 | return -ENOMEM; |
615 | sprintf(t->label[i], "label%d", i); | 603 | sprintf(t->label[i], "label%d", i); |
616 | 604 | ||
617 | t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]); | 605 | t->flush[i] = test_alloc(t, sizeof(u64) * NUM_HINTS, |
606 | &t->flush_dma[i]); | ||
618 | if (!t->flush[i]) | 607 | if (!t->flush[i]) |
619 | return -ENOMEM; | 608 | return -ENOMEM; |
620 | } | 609 | } |
@@ -630,7 +619,7 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
630 | 619 | ||
631 | static int nfit_test1_alloc(struct nfit_test *t) | 620 | static int nfit_test1_alloc(struct nfit_test *t) |
632 | { | 621 | { |
633 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) | 622 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 |
634 | + sizeof(struct acpi_nfit_memory_map) | 623 | + sizeof(struct acpi_nfit_memory_map) |
635 | + offsetof(struct acpi_nfit_control_region, window_size); | 624 | + offsetof(struct acpi_nfit_control_region, window_size); |
636 | 625 | ||
@@ -639,15 +628,31 @@ static int nfit_test1_alloc(struct nfit_test *t) | |||
639 | return -ENOMEM; | 628 | return -ENOMEM; |
640 | t->nfit_size = nfit_size; | 629 | t->nfit_size = nfit_size; |
641 | 630 | ||
642 | t->spa_set[0] = test_alloc_coherent(t, SPA2_SIZE, &t->spa_set_dma[0]); | 631 | t->spa_set[0] = test_alloc(t, SPA2_SIZE, &t->spa_set_dma[0]); |
643 | if (!t->spa_set[0]) | 632 | if (!t->spa_set[0]) |
644 | return -ENOMEM; | 633 | return -ENOMEM; |
645 | 634 | ||
635 | t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); | ||
636 | if (!t->spa_set[1]) | ||
637 | return -ENOMEM; | ||
638 | |||
646 | return ars_state_init(&t->pdev.dev, &t->ars_state); | 639 | return ars_state_init(&t->pdev.dev, &t->ars_state); |
647 | } | 640 | } |
648 | 641 | ||
642 | static void dcr_common_init(struct acpi_nfit_control_region *dcr) | ||
643 | { | ||
644 | dcr->vendor_id = 0xabcd; | ||
645 | dcr->device_id = 0; | ||
646 | dcr->revision_id = 1; | ||
647 | dcr->valid_fields = 1; | ||
648 | dcr->manufacturing_location = 0xa; | ||
649 | dcr->manufacturing_date = cpu_to_be16(2016); | ||
650 | } | ||
651 | |||
649 | static void nfit_test0_setup(struct nfit_test *t) | 652 | static void nfit_test0_setup(struct nfit_test *t) |
650 | { | 653 | { |
654 | const int flush_hint_size = sizeof(struct acpi_nfit_flush_address) | ||
655 | + (sizeof(u64) * NUM_HINTS); | ||
651 | struct acpi_nfit_desc *acpi_desc; | 656 | struct acpi_nfit_desc *acpi_desc; |
652 | struct acpi_nfit_memory_map *memdev; | 657 | struct acpi_nfit_memory_map *memdev; |
653 | void *nfit_buf = t->nfit_buf; | 658 | void *nfit_buf = t->nfit_buf; |
@@ -655,7 +660,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
655 | struct acpi_nfit_control_region *dcr; | 660 | struct acpi_nfit_control_region *dcr; |
656 | struct acpi_nfit_data_region *bdw; | 661 | struct acpi_nfit_data_region *bdw; |
657 | struct acpi_nfit_flush_address *flush; | 662 | struct acpi_nfit_flush_address *flush; |
658 | unsigned int offset; | 663 | unsigned int offset, i; |
659 | 664 | ||
660 | /* | 665 | /* |
661 | * spa0 (interleave first half of dimm0 and dimm1, note storage | 666 | * spa0 (interleave first half of dimm0 and dimm1, note storage |
@@ -972,9 +977,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
972 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; | 977 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; |
973 | dcr->header.length = sizeof(struct acpi_nfit_control_region); | 978 | dcr->header.length = sizeof(struct acpi_nfit_control_region); |
974 | dcr->region_index = 0+1; | 979 | dcr->region_index = 0+1; |
975 | dcr->vendor_id = 0xabcd; | 980 | dcr_common_init(dcr); |
976 | dcr->device_id = 0; | ||
977 | dcr->revision_id = 1; | ||
978 | dcr->serial_number = ~handle[0]; | 981 | dcr->serial_number = ~handle[0]; |
979 | dcr->code = NFIT_FIC_BLK; | 982 | dcr->code = NFIT_FIC_BLK; |
980 | dcr->windows = 1; | 983 | dcr->windows = 1; |
@@ -989,9 +992,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
989 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; | 992 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; |
990 | dcr->header.length = sizeof(struct acpi_nfit_control_region); | 993 | dcr->header.length = sizeof(struct acpi_nfit_control_region); |
991 | dcr->region_index = 1+1; | 994 | dcr->region_index = 1+1; |
992 | dcr->vendor_id = 0xabcd; | 995 | dcr_common_init(dcr); |
993 | dcr->device_id = 0; | ||
994 | dcr->revision_id = 1; | ||
995 | dcr->serial_number = ~handle[1]; | 996 | dcr->serial_number = ~handle[1]; |
996 | dcr->code = NFIT_FIC_BLK; | 997 | dcr->code = NFIT_FIC_BLK; |
997 | dcr->windows = 1; | 998 | dcr->windows = 1; |
@@ -1006,9 +1007,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1006 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; | 1007 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; |
1007 | dcr->header.length = sizeof(struct acpi_nfit_control_region); | 1008 | dcr->header.length = sizeof(struct acpi_nfit_control_region); |
1008 | dcr->region_index = 2+1; | 1009 | dcr->region_index = 2+1; |
1009 | dcr->vendor_id = 0xabcd; | 1010 | dcr_common_init(dcr); |
1010 | dcr->device_id = 0; | ||
1011 | dcr->revision_id = 1; | ||
1012 | dcr->serial_number = ~handle[2]; | 1011 | dcr->serial_number = ~handle[2]; |
1013 | dcr->code = NFIT_FIC_BLK; | 1012 | dcr->code = NFIT_FIC_BLK; |
1014 | dcr->windows = 1; | 1013 | dcr->windows = 1; |
@@ -1023,9 +1022,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1023 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; | 1022 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; |
1024 | dcr->header.length = sizeof(struct acpi_nfit_control_region); | 1023 | dcr->header.length = sizeof(struct acpi_nfit_control_region); |
1025 | dcr->region_index = 3+1; | 1024 | dcr->region_index = 3+1; |
1026 | dcr->vendor_id = 0xabcd; | 1025 | dcr_common_init(dcr); |
1027 | dcr->device_id = 0; | ||
1028 | dcr->revision_id = 1; | ||
1029 | dcr->serial_number = ~handle[3]; | 1026 | dcr->serial_number = ~handle[3]; |
1030 | dcr->code = NFIT_FIC_BLK; | 1027 | dcr->code = NFIT_FIC_BLK; |
1031 | dcr->windows = 1; | 1028 | dcr->windows = 1; |
@@ -1042,9 +1039,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1042 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1039 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1043 | window_size); | 1040 | window_size); |
1044 | dcr->region_index = 4+1; | 1041 | dcr->region_index = 4+1; |
1045 | dcr->vendor_id = 0xabcd; | 1042 | dcr_common_init(dcr); |
1046 | dcr->device_id = 0; | ||
1047 | dcr->revision_id = 1; | ||
1048 | dcr->serial_number = ~handle[0]; | 1043 | dcr->serial_number = ~handle[0]; |
1049 | dcr->code = NFIT_FIC_BYTEN; | 1044 | dcr->code = NFIT_FIC_BYTEN; |
1050 | dcr->windows = 0; | 1045 | dcr->windows = 0; |
@@ -1056,9 +1051,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1056 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1051 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1057 | window_size); | 1052 | window_size); |
1058 | dcr->region_index = 5+1; | 1053 | dcr->region_index = 5+1; |
1059 | dcr->vendor_id = 0xabcd; | 1054 | dcr_common_init(dcr); |
1060 | dcr->device_id = 0; | ||
1061 | dcr->revision_id = 1; | ||
1062 | dcr->serial_number = ~handle[1]; | 1055 | dcr->serial_number = ~handle[1]; |
1063 | dcr->code = NFIT_FIC_BYTEN; | 1056 | dcr->code = NFIT_FIC_BYTEN; |
1064 | dcr->windows = 0; | 1057 | dcr->windows = 0; |
@@ -1070,9 +1063,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1070 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1063 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1071 | window_size); | 1064 | window_size); |
1072 | dcr->region_index = 6+1; | 1065 | dcr->region_index = 6+1; |
1073 | dcr->vendor_id = 0xabcd; | 1066 | dcr_common_init(dcr); |
1074 | dcr->device_id = 0; | ||
1075 | dcr->revision_id = 1; | ||
1076 | dcr->serial_number = ~handle[2]; | 1067 | dcr->serial_number = ~handle[2]; |
1077 | dcr->code = NFIT_FIC_BYTEN; | 1068 | dcr->code = NFIT_FIC_BYTEN; |
1078 | dcr->windows = 0; | 1069 | dcr->windows = 0; |
@@ -1084,9 +1075,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1084 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1075 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1085 | window_size); | 1076 | window_size); |
1086 | dcr->region_index = 7+1; | 1077 | dcr->region_index = 7+1; |
1087 | dcr->vendor_id = 0xabcd; | 1078 | dcr_common_init(dcr); |
1088 | dcr->device_id = 0; | ||
1089 | dcr->revision_id = 1; | ||
1090 | dcr->serial_number = ~handle[3]; | 1079 | dcr->serial_number = ~handle[3]; |
1091 | dcr->code = NFIT_FIC_BYTEN; | 1080 | dcr->code = NFIT_FIC_BYTEN; |
1092 | dcr->windows = 0; | 1081 | dcr->windows = 0; |
@@ -1141,45 +1130,47 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1141 | /* flush0 (dimm0) */ | 1130 | /* flush0 (dimm0) */ |
1142 | flush = nfit_buf + offset; | 1131 | flush = nfit_buf + offset; |
1143 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | 1132 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; |
1144 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | 1133 | flush->header.length = flush_hint_size; |
1145 | flush->device_handle = handle[0]; | 1134 | flush->device_handle = handle[0]; |
1146 | flush->hint_count = 1; | 1135 | flush->hint_count = NUM_HINTS; |
1147 | flush->hint_address[0] = t->flush_dma[0]; | 1136 | for (i = 0; i < NUM_HINTS; i++) |
1137 | flush->hint_address[i] = t->flush_dma[0] + i * sizeof(u64); | ||
1148 | 1138 | ||
1149 | /* flush1 (dimm1) */ | 1139 | /* flush1 (dimm1) */ |
1150 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1; | 1140 | flush = nfit_buf + offset + flush_hint_size * 1; |
1151 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | 1141 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; |
1152 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | 1142 | flush->header.length = flush_hint_size; |
1153 | flush->device_handle = handle[1]; | 1143 | flush->device_handle = handle[1]; |
1154 | flush->hint_count = 1; | 1144 | flush->hint_count = NUM_HINTS; |
1155 | flush->hint_address[0] = t->flush_dma[1]; | 1145 | for (i = 0; i < NUM_HINTS; i++) |
1146 | flush->hint_address[i] = t->flush_dma[1] + i * sizeof(u64); | ||
1156 | 1147 | ||
1157 | /* flush2 (dimm2) */ | 1148 | /* flush2 (dimm2) */ |
1158 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2; | 1149 | flush = nfit_buf + offset + flush_hint_size * 2; |
1159 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | 1150 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; |
1160 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | 1151 | flush->header.length = flush_hint_size; |
1161 | flush->device_handle = handle[2]; | 1152 | flush->device_handle = handle[2]; |
1162 | flush->hint_count = 1; | 1153 | flush->hint_count = NUM_HINTS; |
1163 | flush->hint_address[0] = t->flush_dma[2]; | 1154 | for (i = 0; i < NUM_HINTS; i++) |
1155 | flush->hint_address[i] = t->flush_dma[2] + i * sizeof(u64); | ||
1164 | 1156 | ||
1165 | /* flush3 (dimm3) */ | 1157 | /* flush3 (dimm3) */ |
1166 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3; | 1158 | flush = nfit_buf + offset + flush_hint_size * 3; |
1167 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | 1159 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; |
1168 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | 1160 | flush->header.length = flush_hint_size; |
1169 | flush->device_handle = handle[3]; | 1161 | flush->device_handle = handle[3]; |
1170 | flush->hint_count = 1; | 1162 | flush->hint_count = NUM_HINTS; |
1171 | flush->hint_address[0] = t->flush_dma[3]; | 1163 | for (i = 0; i < NUM_HINTS; i++) |
1164 | flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64); | ||
1172 | 1165 | ||
1173 | if (t->setup_hotplug) { | 1166 | if (t->setup_hotplug) { |
1174 | offset = offset + sizeof(struct acpi_nfit_flush_address) * 4; | 1167 | offset = offset + flush_hint_size * 4; |
1175 | /* dcr-descriptor4: blk */ | 1168 | /* dcr-descriptor4: blk */ |
1176 | dcr = nfit_buf + offset; | 1169 | dcr = nfit_buf + offset; |
1177 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; | 1170 | dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; |
1178 | dcr->header.length = sizeof(struct acpi_nfit_control_region); | 1171 | dcr->header.length = sizeof(struct acpi_nfit_control_region); |
1179 | dcr->region_index = 8+1; | 1172 | dcr->region_index = 8+1; |
1180 | dcr->vendor_id = 0xabcd; | 1173 | dcr_common_init(dcr); |
1181 | dcr->device_id = 0; | ||
1182 | dcr->revision_id = 1; | ||
1183 | dcr->serial_number = ~handle[4]; | 1174 | dcr->serial_number = ~handle[4]; |
1184 | dcr->code = NFIT_FIC_BLK; | 1175 | dcr->code = NFIT_FIC_BLK; |
1185 | dcr->windows = 1; | 1176 | dcr->windows = 1; |
@@ -1196,9 +1187,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1196 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1187 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1197 | window_size); | 1188 | window_size); |
1198 | dcr->region_index = 9+1; | 1189 | dcr->region_index = 9+1; |
1199 | dcr->vendor_id = 0xabcd; | 1190 | dcr_common_init(dcr); |
1200 | dcr->device_id = 0; | ||
1201 | dcr->revision_id = 1; | ||
1202 | dcr->serial_number = ~handle[4]; | 1191 | dcr->serial_number = ~handle[4]; |
1203 | dcr->code = NFIT_FIC_BYTEN; | 1192 | dcr->code = NFIT_FIC_BYTEN; |
1204 | dcr->windows = 0; | 1193 | dcr->windows = 0; |
@@ -1300,10 +1289,12 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
1300 | /* flush3 (dimm4) */ | 1289 | /* flush3 (dimm4) */ |
1301 | flush = nfit_buf + offset; | 1290 | flush = nfit_buf + offset; |
1302 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | 1291 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; |
1303 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | 1292 | flush->header.length = flush_hint_size; |
1304 | flush->device_handle = handle[4]; | 1293 | flush->device_handle = handle[4]; |
1305 | flush->hint_count = 1; | 1294 | flush->hint_count = NUM_HINTS; |
1306 | flush->hint_address[0] = t->flush_dma[4]; | 1295 | for (i = 0; i < NUM_HINTS; i++) |
1296 | flush->hint_address[i] = t->flush_dma[4] | ||
1297 | + i * sizeof(u64); | ||
1307 | } | 1298 | } |
1308 | 1299 | ||
1309 | post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); | 1300 | post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); |
@@ -1339,7 +1330,16 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
1339 | spa->address = t->spa_set_dma[0]; | 1330 | spa->address = t->spa_set_dma[0]; |
1340 | spa->length = SPA2_SIZE; | 1331 | spa->length = SPA2_SIZE; |
1341 | 1332 | ||
1342 | offset += sizeof(*spa); | 1333 | /* virtual cd region */ |
1334 | spa = nfit_buf + sizeof(*spa); | ||
1335 | spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS; | ||
1336 | spa->header.length = sizeof(*spa); | ||
1337 | memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16); | ||
1338 | spa->range_index = 0; | ||
1339 | spa->address = t->spa_set_dma[1]; | ||
1340 | spa->length = SPA_VCD_SIZE; | ||
1341 | |||
1342 | offset += sizeof(*spa) * 2; | ||
1343 | /* mem-region0 (spa0, dimm0) */ | 1343 | /* mem-region0 (spa0, dimm0) */ |
1344 | memdev = nfit_buf + offset; | 1344 | memdev = nfit_buf + offset; |
1345 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; | 1345 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; |
@@ -1365,9 +1365,7 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
1365 | dcr->header.length = offsetof(struct acpi_nfit_control_region, | 1365 | dcr->header.length = offsetof(struct acpi_nfit_control_region, |
1366 | window_size); | 1366 | window_size); |
1367 | dcr->region_index = 0+1; | 1367 | dcr->region_index = 0+1; |
1368 | dcr->vendor_id = 0xabcd; | 1368 | dcr_common_init(dcr); |
1369 | dcr->device_id = 0; | ||
1370 | dcr->revision_id = 1; | ||
1371 | dcr->serial_number = ~0; | 1369 | dcr->serial_number = ~0; |
1372 | dcr->code = NFIT_FIC_BYTE; | 1370 | dcr->code = NFIT_FIC_BYTE; |
1373 | dcr->windows = 0; | 1371 | dcr->windows = 0; |
@@ -1462,20 +1460,16 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
1462 | nfit_test->setup(nfit_test); | 1460 | nfit_test->setup(nfit_test); |
1463 | acpi_desc = &nfit_test->acpi_desc; | 1461 | acpi_desc = &nfit_test->acpi_desc; |
1464 | acpi_nfit_desc_init(acpi_desc, &pdev->dev); | 1462 | acpi_nfit_desc_init(acpi_desc, &pdev->dev); |
1465 | acpi_desc->nfit = nfit_test->nfit_buf; | ||
1466 | acpi_desc->blk_do_io = nfit_test_blk_do_io; | 1463 | acpi_desc->blk_do_io = nfit_test_blk_do_io; |
1467 | nd_desc = &acpi_desc->nd_desc; | 1464 | nd_desc = &acpi_desc->nd_desc; |
1468 | nd_desc->provider_name = NULL; | 1465 | nd_desc->provider_name = NULL; |
1466 | nd_desc->module = THIS_MODULE; | ||
1469 | nd_desc->ndctl = nfit_test_ctl; | 1467 | nd_desc->ndctl = nfit_test_ctl; |
1470 | acpi_desc->nvdimm_bus = nvdimm_bus_register(&pdev->dev, nd_desc); | ||
1471 | if (!acpi_desc->nvdimm_bus) | ||
1472 | return -ENXIO; | ||
1473 | 1468 | ||
1474 | rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); | 1469 | rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf, |
1475 | if (rc) { | 1470 | nfit_test->nfit_size); |
1476 | nvdimm_bus_unregister(acpi_desc->nvdimm_bus); | 1471 | if (rc) |
1477 | return rc; | 1472 | return rc; |
1478 | } | ||
1479 | 1473 | ||
1480 | if (nfit_test->setup != nfit_test0_setup) | 1474 | if (nfit_test->setup != nfit_test0_setup) |
1481 | return 0; | 1475 | return 0; |
@@ -1483,22 +1477,16 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
1483 | nfit_test->setup_hotplug = 1; | 1477 | nfit_test->setup_hotplug = 1; |
1484 | nfit_test->setup(nfit_test); | 1478 | nfit_test->setup(nfit_test); |
1485 | 1479 | ||
1486 | rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); | 1480 | rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf, |
1487 | if (rc) { | 1481 | nfit_test->nfit_size); |
1488 | nvdimm_bus_unregister(acpi_desc->nvdimm_bus); | 1482 | if (rc) |
1489 | return rc; | 1483 | return rc; |
1490 | } | ||
1491 | 1484 | ||
1492 | return 0; | 1485 | return 0; |
1493 | } | 1486 | } |
1494 | 1487 | ||
1495 | static int nfit_test_remove(struct platform_device *pdev) | 1488 | static int nfit_test_remove(struct platform_device *pdev) |
1496 | { | 1489 | { |
1497 | struct nfit_test *nfit_test = to_nfit_test(&pdev->dev); | ||
1498 | struct acpi_nfit_desc *acpi_desc = &nfit_test->acpi_desc; | ||
1499 | |||
1500 | nvdimm_bus_unregister(acpi_desc->nvdimm_bus); | ||
1501 | |||
1502 | return 0; | 1490 | return 0; |
1503 | } | 1491 | } |
1504 | 1492 | ||
@@ -1523,12 +1511,6 @@ static struct platform_driver nfit_test_driver = { | |||
1523 | .id_table = nfit_test_id, | 1511 | .id_table = nfit_test_id, |
1524 | }; | 1512 | }; |
1525 | 1513 | ||
1526 | #ifdef CONFIG_CMA_SIZE_MBYTES | ||
1527 | #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES | ||
1528 | #else | ||
1529 | #define CMA_SIZE_MBYTES 0 | ||
1530 | #endif | ||
1531 | |||
1532 | static __init int nfit_test_init(void) | 1514 | static __init int nfit_test_init(void) |
1533 | { | 1515 | { |
1534 | int rc, i; | 1516 | int rc, i; |
@@ -1538,7 +1520,6 @@ static __init int nfit_test_init(void) | |||
1538 | for (i = 0; i < NUM_NFITS; i++) { | 1520 | for (i = 0; i < NUM_NFITS; i++) { |
1539 | struct nfit_test *nfit_test; | 1521 | struct nfit_test *nfit_test; |
1540 | struct platform_device *pdev; | 1522 | struct platform_device *pdev; |
1541 | static int once; | ||
1542 | 1523 | ||
1543 | nfit_test = kzalloc(sizeof(*nfit_test), GFP_KERNEL); | 1524 | nfit_test = kzalloc(sizeof(*nfit_test), GFP_KERNEL); |
1544 | if (!nfit_test) { | 1525 | if (!nfit_test) { |
@@ -1577,20 +1558,6 @@ static __init int nfit_test_init(void) | |||
1577 | goto err_register; | 1558 | goto err_register; |
1578 | 1559 | ||
1579 | instances[i] = nfit_test; | 1560 | instances[i] = nfit_test; |
1580 | |||
1581 | if (!once++) { | ||
1582 | dma_addr_t dma; | ||
1583 | void *buf; | ||
1584 | |||
1585 | buf = dma_alloc_coherent(&pdev->dev, SZ_128M, &dma, | ||
1586 | GFP_KERNEL); | ||
1587 | if (!buf) { | ||
1588 | rc = -ENOMEM; | ||
1589 | dev_warn(&pdev->dev, "need 128M of free cma\n"); | ||
1590 | goto err_register; | ||
1591 | } | ||
1592 | dma_free_coherent(&pdev->dev, SZ_128M, buf, dma); | ||
1593 | } | ||
1594 | } | 1561 | } |
1595 | 1562 | ||
1596 | rc = platform_driver_register(&nfit_test_driver); | 1563 | rc = platform_driver_register(&nfit_test_driver); |
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h index 96c5e16d7db9..9f18e2a4a862 100644 --- a/tools/testing/nvdimm/test/nfit_test.h +++ b/tools/testing/nvdimm/test/nfit_test.h | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | #ifndef __NFIT_TEST_H__ | 13 | #ifndef __NFIT_TEST_H__ |
14 | #define __NFIT_TEST_H__ | 14 | #define __NFIT_TEST_H__ |
15 | #include <linux/list.h> | ||
15 | 16 | ||
16 | struct nfit_test_resource { | 17 | struct nfit_test_resource { |
17 | struct list_head list; | 18 | struct list_head list; |
@@ -26,4 +27,5 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, | |||
26 | void __wrap_iounmap(volatile void __iomem *addr); | 27 | void __wrap_iounmap(volatile void __iomem *addr); |
27 | void nfit_test_setup(nfit_test_lookup_fn lookup); | 28 | void nfit_test_setup(nfit_test_lookup_fn lookup); |
28 | void nfit_test_teardown(void); | 29 | void nfit_test_teardown(void); |
30 | struct nfit_test_resource *get_nfit_res(resource_size_t resource); | ||
29 | #endif | 31 | #endif |
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h index 0e37f7a760eb..5201b915f631 100644 --- a/tools/testing/radix-tree/linux/gfp.h +++ b/tools/testing/radix-tree/linux/gfp.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef _GFP_H | 1 | #ifndef _GFP_H |
2 | #define _GFP_H | 2 | #define _GFP_H |
3 | 3 | ||
4 | #define __GFP_BITS_SHIFT 22 | 4 | #define __GFP_BITS_SHIFT 26 |
5 | #define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) | 5 | #define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) |
6 | #define __GFP_WAIT 1 | 6 | #define __GFP_WAIT 1 |
7 | #define __GFP_ACCOUNT 0 | 7 | #define __GFP_ACCOUNT 0 |
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile index 4e400eb83657..d4300602bf37 100644 --- a/tools/testing/selftests/exec/Makefile +++ b/tools/testing/selftests/exec/Makefile | |||
@@ -18,7 +18,8 @@ execveat.denatured: execveat | |||
18 | $(CC) $(CFLAGS) -o $@ $^ | 18 | $(CC) $(CFLAGS) -o $@ $^ |
19 | 19 | ||
20 | TEST_PROGS := execveat | 20 | TEST_PROGS := execveat |
21 | TEST_FILES := $(DEPS) | 21 | # Makefile is a run-time dependency, since it's accessed by the execveat test |
22 | TEST_FILES := $(DEPS) Makefile | ||
22 | 23 | ||
23 | include ../lib.mk | 24 | include ../lib.mk |
24 | 25 | ||
diff --git a/tools/testing/selftests/lib/printf.sh b/tools/testing/selftests/lib/printf.sh index 4fdc70fe6980..4fdc70fe6980 100644..100755 --- a/tools/testing/selftests/lib/printf.sh +++ b/tools/testing/selftests/lib/printf.sh | |||
diff --git a/tools/testing/selftests/media_tests/.gitignore b/tools/testing/selftests/media_tests/.gitignore index 1c0711708b98..8745eba39012 100644 --- a/tools/testing/selftests/media_tests/.gitignore +++ b/tools/testing/selftests/media_tests/.gitignore | |||
@@ -1 +1,3 @@ | |||
1 | media_device_test | 1 | media_device_test |
2 | media_device_open | ||
3 | video_device_test | ||
diff --git a/tools/testing/selftests/media_tests/Makefile b/tools/testing/selftests/media_tests/Makefile index 7071bcc1d066..6b34a0199468 100644 --- a/tools/testing/selftests/media_tests/Makefile +++ b/tools/testing/selftests/media_tests/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | TEST_PROGS := media_device_test | 1 | TEST_PROGS := media_device_test media_device_open video_device_test |
2 | all: $(TEST_PROGS) | 2 | all: $(TEST_PROGS) |
3 | 3 | ||
4 | include ../lib.mk | 4 | include ../lib.mk |
5 | 5 | ||
6 | clean: | 6 | clean: |
7 | rm -fr media_device_test | 7 | rm -fr media_device_test media_device_open video_device_test |
diff --git a/tools/testing/selftests/media_tests/bind_unbind_sample.sh b/tools/testing/selftests/media_tests/bind_unbind_sample.sh new file mode 100755 index 000000000000..9f362f10631a --- /dev/null +++ b/tools/testing/selftests/media_tests/bind_unbind_sample.sh | |||
@@ -0,0 +1,12 @@ | |||
1 | #!/bin/bash | ||
2 | # Find device number in /sys/bus/usb/drivers/drivername | ||
3 | # Edit this file to update the driver numer and name | ||
4 | # Example test for uvcvideo driver | ||
5 | #i=0 | ||
6 | # while :; do | ||
7 | # i=$((i+1)) | ||
8 | # echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/unbind; | ||
9 | # echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/bind; | ||
10 | # clear | ||
11 | # echo $i | ||
12 | #done | ||
diff --git a/tools/testing/selftests/media_tests/media_device_open.c b/tools/testing/selftests/media_tests/media_device_open.c new file mode 100644 index 000000000000..44343c091a20 --- /dev/null +++ b/tools/testing/selftests/media_tests/media_device_open.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * media_device_open.c - Media Controller Device Open Test | ||
3 | * | ||
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | ||
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This file adds a test for Media Controller API. | ||
12 | * This test should be run as root and should not be | ||
13 | * included in the Kselftest run. This test should be | ||
14 | * run when hardware and driver that makes use Media | ||
15 | * Controller API are present in the system. | ||
16 | * | ||
17 | * This test opens user specified Media Device and calls | ||
18 | * MEDIA_IOC_DEVICE_INFO ioctl, closes the file, and exits. | ||
19 | * | ||
20 | * Usage: | ||
21 | * sudo ./media_device_open -d /dev/mediaX | ||
22 | * | ||
23 | * Run this test is a loop and run bind/unbind on the driver. | ||
24 | */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | #include <unistd.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <errno.h> | ||
30 | #include <string.h> | ||
31 | #include <fcntl.h> | ||
32 | #include <sys/ioctl.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <linux/media.h> | ||
35 | |||
36 | int main(int argc, char **argv) | ||
37 | { | ||
38 | int opt; | ||
39 | char media_device[256]; | ||
40 | int count = 0; | ||
41 | struct media_device_info mdi; | ||
42 | int ret; | ||
43 | int fd; | ||
44 | |||
45 | if (argc < 2) { | ||
46 | printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]); | ||
47 | exit(-1); | ||
48 | } | ||
49 | |||
50 | /* Process arguments */ | ||
51 | while ((opt = getopt(argc, argv, "d:")) != -1) { | ||
52 | switch (opt) { | ||
53 | case 'd': | ||
54 | strncpy(media_device, optarg, sizeof(media_device) - 1); | ||
55 | media_device[sizeof(media_device)-1] = '\0'; | ||
56 | break; | ||
57 | default: | ||
58 | printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]); | ||
59 | exit(-1); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | if (getuid() != 0) { | ||
64 | printf("Please run the test as root - Exiting.\n"); | ||
65 | exit(-1); | ||
66 | } | ||
67 | |||
68 | /* Open Media device and keep it open */ | ||
69 | fd = open(media_device, O_RDWR); | ||
70 | if (fd == -1) { | ||
71 | printf("Media Device open errno %s\n", strerror(errno)); | ||
72 | exit(-1); | ||
73 | } | ||
74 | |||
75 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); | ||
76 | if (ret < 0) | ||
77 | printf("Media Device Info errno %s\n", strerror(errno)); | ||
78 | else | ||
79 | printf("Media device model %s driver %s\n", | ||
80 | mdi.model, mdi.driver); | ||
81 | } | ||
diff --git a/tools/testing/selftests/media_tests/media_device_test.c b/tools/testing/selftests/media_tests/media_device_test.c index cbf53a032ab5..5d49943e77d0 100644 --- a/tools/testing/selftests/media_tests/media_device_test.c +++ b/tools/testing/selftests/media_tests/media_device_test.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * media_devkref_test.c - Media Controller Device Kref API Test | 2 | * media_device_test.c - Media Controller Device ioctl loop Test |
3 | * | 3 | * |
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | 4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> |
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. |
@@ -35,13 +35,14 @@ | |||
35 | #include <fcntl.h> | 35 | #include <fcntl.h> |
36 | #include <sys/ioctl.h> | 36 | #include <sys/ioctl.h> |
37 | #include <sys/stat.h> | 37 | #include <sys/stat.h> |
38 | #include <time.h> | ||
38 | #include <linux/media.h> | 39 | #include <linux/media.h> |
39 | 40 | ||
40 | int main(int argc, char **argv) | 41 | int main(int argc, char **argv) |
41 | { | 42 | { |
42 | int opt; | 43 | int opt; |
43 | char media_device[256]; | 44 | char media_device[256]; |
44 | int count = 0; | 45 | int count; |
45 | struct media_device_info mdi; | 46 | struct media_device_info mdi; |
46 | int ret; | 47 | int ret; |
47 | int fd; | 48 | int fd; |
@@ -69,6 +70,10 @@ int main(int argc, char **argv) | |||
69 | exit(-1); | 70 | exit(-1); |
70 | } | 71 | } |
71 | 72 | ||
73 | /* Generate random number of interations */ | ||
74 | srand((unsigned int) time(NULL)); | ||
75 | count = rand(); | ||
76 | |||
72 | /* Open Media device and keep it open */ | 77 | /* Open Media device and keep it open */ |
73 | fd = open(media_device, O_RDWR); | 78 | fd = open(media_device, O_RDWR); |
74 | if (fd == -1) { | 79 | if (fd == -1) { |
@@ -82,14 +87,16 @@ int main(int argc, char **argv) | |||
82 | "other Oops in the dmesg. Enable KaSan kernel\n" | 87 | "other Oops in the dmesg. Enable KaSan kernel\n" |
83 | "config option for use-after-free error detection.\n\n"); | 88 | "config option for use-after-free error detection.\n\n"); |
84 | 89 | ||
85 | while (count < 100) { | 90 | printf("Running test for %d iternations\n", count); |
91 | |||
92 | while (count > 0) { | ||
86 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); | 93 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); |
87 | if (ret < 0) | 94 | if (ret < 0) |
88 | printf("Media Device Info errno %s\n", strerror(errno)); | 95 | printf("Media Device Info errno %s\n", strerror(errno)); |
89 | else | 96 | else |
90 | printf("Media device model %s driver %s\n", | 97 | printf("Media device model %s driver %s - count %d\n", |
91 | mdi.model, mdi.driver); | 98 | mdi.model, mdi.driver, count); |
92 | sleep(10); | 99 | sleep(10); |
93 | count++; | 100 | count--; |
94 | } | 101 | } |
95 | } | 102 | } |
diff --git a/tools/testing/selftests/media_tests/open_loop_test.sh b/tools/testing/selftests/media_tests/open_loop_test.sh new file mode 100755 index 000000000000..dcd3c17efc17 --- /dev/null +++ b/tools/testing/selftests/media_tests/open_loop_test.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/bash | ||
2 | i=0 | ||
3 | file=/dev/media$1 | ||
4 | while :; do | ||
5 | echo $file | ||
6 | i=$((i+1)) | ||
7 | R=$(./media_device_open -d $file); | ||
8 | # clear | ||
9 | echo -e "Loop $i\n$R" | ||
10 | done | ||
diff --git a/tools/testing/selftests/media_tests/regression_test.txt b/tools/testing/selftests/media_tests/regression_test.txt new file mode 100644 index 000000000000..2627367681f7 --- /dev/null +++ b/tools/testing/selftests/media_tests/regression_test.txt | |||
@@ -0,0 +1,43 @@ | |||
1 | Testing for regressions in Media Controller API register, ioctl, syscall, | ||
2 | and unregister paths. There have a few problems that result in user-after | ||
3 | free on media_device, media_devnode, and cdev pointers when the driver is | ||
4 | unbound while ioctl is in progress. | ||
5 | |||
6 | Test Procedure: | ||
7 | |||
8 | Run bin/unbind loop while ioctls are in progress. | ||
9 | Run rmmod and modprobe. | ||
10 | Disconnect the device. | ||
11 | |||
12 | Setup: | ||
13 | |||
14 | Build media_device_test | ||
15 | cd tools/testing/selftests/media_tests | ||
16 | make | ||
17 | |||
18 | Regressions test for cdev user-after free error on /dev/mediaX when driver | ||
19 | is unbound: | ||
20 | |||
21 | Start media_device_test to regression test media devnode dynamic alloc | ||
22 | and cdev user-after-free fixes. This opens media dev files and sits in | ||
23 | a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10 | ||
24 | seconds. The idea is when device file goes away, media devnode and cdev | ||
25 | should stick around until this test exits. | ||
26 | |||
27 | The test for a random number of iterations or until user kills it with a | ||
28 | sleep 10 in between the ioctl calls. | ||
29 | |||
30 | sudo ./media_device_test -d /dev/mediaX | ||
31 | |||
32 | Regression test for media_devnode unregister race with ioctl_syscall: | ||
33 | |||
34 | Start 6 open_loop_test.sh tests with different /dev/mediaX files. When | ||
35 | device file goes away after unbind, device file name changes. Start the | ||
36 | test with possible device names. If we start with /dev/media0 for example, | ||
37 | after unbind, /dev/media1 or /dev/media2 could get created. The idea is | ||
38 | keep ioctls going while bind/unbind runs. | ||
39 | |||
40 | Copy bind_unbind_sample.txt and make changes to specify the driver name | ||
41 | and number to run bind and unbind. Start the bind_unbind.sh | ||
42 | |||
43 | Run dmesg looking for any user-after free errors or mutex lock errors. | ||
diff --git a/tools/testing/selftests/media_tests/video_device_test.c b/tools/testing/selftests/media_tests/video_device_test.c new file mode 100644 index 000000000000..66d419c28653 --- /dev/null +++ b/tools/testing/selftests/media_tests/video_device_test.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * video_device_test - Video Device Test | ||
3 | * | ||
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | ||
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This file adds a test for Video Device. This test should not be included | ||
12 | * in the Kselftest run. This test should be run when hardware and driver | ||
13 | * that makes use of V4L2 API is present. | ||
14 | * | ||
15 | * This test opens user specified Video Device and calls video ioctls in a | ||
16 | * loop once every 10 seconds. | ||
17 | * | ||
18 | * Usage: | ||
19 | * sudo ./video_device_test -d /dev/videoX | ||
20 | * | ||
21 | * While test is running, remove the device or unbind the driver and | ||
22 | * ensure there are no use after free errors and other Oops in the | ||
23 | * dmesg. | ||
24 | * When possible, enable KaSan kernel config option for use-after-free | ||
25 | * error detection. | ||
26 | */ | ||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <unistd.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <errno.h> | ||
32 | #include <string.h> | ||
33 | #include <fcntl.h> | ||
34 | #include <sys/ioctl.h> | ||
35 | #include <sys/stat.h> | ||
36 | #include <time.h> | ||
37 | #include <linux/videodev2.h> | ||
38 | |||
39 | int main(int argc, char **argv) | ||
40 | { | ||
41 | int opt; | ||
42 | char video_dev[256]; | ||
43 | int count; | ||
44 | struct v4l2_tuner vtuner; | ||
45 | struct v4l2_capability vcap; | ||
46 | int ret; | ||
47 | int fd; | ||
48 | |||
49 | if (argc < 2) { | ||
50 | printf("Usage: %s [-d </dev/videoX>]\n", argv[0]); | ||
51 | exit(-1); | ||
52 | } | ||
53 | |||
54 | /* Process arguments */ | ||
55 | while ((opt = getopt(argc, argv, "d:")) != -1) { | ||
56 | switch (opt) { | ||
57 | case 'd': | ||
58 | strncpy(video_dev, optarg, sizeof(video_dev) - 1); | ||
59 | video_dev[sizeof(video_dev)-1] = '\0'; | ||
60 | break; | ||
61 | default: | ||
62 | printf("Usage: %s [-d </dev/videoX>]\n", argv[0]); | ||
63 | exit(-1); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /* Generate random number of interations */ | ||
68 | srand((unsigned int) time(NULL)); | ||
69 | count = rand(); | ||
70 | |||
71 | /* Open Video device and keep it open */ | ||
72 | fd = open(video_dev, O_RDWR); | ||
73 | if (fd == -1) { | ||
74 | printf("Video Device open errno %s\n", strerror(errno)); | ||
75 | exit(-1); | ||
76 | } | ||
77 | |||
78 | printf("\nNote:\n" | ||
79 | "While test is running, remove the device or unbind\n" | ||
80 | "driver and ensure there are no use after free errors\n" | ||
81 | "and other Oops in the dmesg. When possible, enable KaSan\n" | ||
82 | "kernel config option for use-after-free error detection.\n\n"); | ||
83 | |||
84 | while (count > 0) { | ||
85 | ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap); | ||
86 | if (ret < 0) | ||
87 | printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno)); | ||
88 | else | ||
89 | printf("Video device driver %s\n", vcap.driver); | ||
90 | |||
91 | ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner); | ||
92 | if (ret < 0) | ||
93 | printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno)); | ||
94 | else | ||
95 | printf("type %d rangelow %d rangehigh %d\n", | ||
96 | vtuner.type, vtuner.rangelow, vtuner.rangehigh); | ||
97 | sleep(10); | ||
98 | count--; | ||
99 | } | ||
100 | } | ||
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 4ca83fe80654..3c40c9d0e6c7 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile | |||
@@ -12,7 +12,8 @@ CFLAGS := -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $ | |||
12 | 12 | ||
13 | export CFLAGS | 13 | export CFLAGS |
14 | 14 | ||
15 | SUB_DIRS = benchmarks \ | 15 | SUB_DIRS = alignment \ |
16 | benchmarks \ | ||
16 | copyloops \ | 17 | copyloops \ |
17 | context_switch \ | 18 | context_switch \ |
18 | dscr \ | 19 | dscr \ |
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore new file mode 100644 index 000000000000..1d980e3d7039 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/.gitignore | |||
@@ -0,0 +1,5 @@ | |||
1 | copy_unaligned | ||
2 | copy_first_unaligned | ||
3 | paste_unaligned | ||
4 | paste_last_unaligned | ||
5 | copy_paste_unaligned_common | ||
diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile new file mode 100644 index 000000000000..ad6a4e49da91 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | TEST_PROGS := copy_unaligned copy_first_unaligned paste_unaligned paste_last_unaligned | ||
2 | |||
3 | all: $(TEST_PROGS) | ||
4 | |||
5 | $(TEST_PROGS): ../harness.c ../utils.c copy_paste_unaligned_common.c | ||
6 | |||
7 | include ../../lib.mk | ||
8 | |||
9 | clean: | ||
10 | rm -f $(TEST_PROGS) | ||
diff --git a/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c new file mode 100644 index 000000000000..47b73b3a08bd --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Calls to copy_first which are not 128-byte aligned should be | ||
10 | * caught and sent a SIGBUS. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include "utils.h" | ||
17 | #include "instructions.h" | ||
18 | #include "copy_paste_unaligned_common.h" | ||
19 | |||
20 | unsigned int expected_instruction = PPC_INST_COPY_FIRST; | ||
21 | unsigned int instruction_mask = 0xfc2007fe; | ||
22 | |||
23 | int test_copy_first_unaligned(void) | ||
24 | { | ||
25 | /* Only run this test on a P9 or later */ | ||
26 | SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); | ||
27 | |||
28 | /* Register our signal handler with SIGBUS */ | ||
29 | setup_signal_handler(); | ||
30 | |||
31 | /* +1 makes buf unaligned */ | ||
32 | copy_first(cacheline_buf+1); | ||
33 | |||
34 | /* We should not get here */ | ||
35 | return 1; | ||
36 | } | ||
37 | |||
38 | int main(int argc, char *argv[]) | ||
39 | { | ||
40 | return test_harness(test_copy_first_unaligned, "test_copy_first_unaligned"); | ||
41 | } | ||
diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c new file mode 100644 index 000000000000..d35fa5f5d2d3 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Common code for copy, copy_first, paste and paste_last unaligned | ||
10 | * tests. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <signal.h> | ||
15 | #include <string.h> | ||
16 | #include <unistd.h> | ||
17 | #include "utils.h" | ||
18 | #include "instructions.h" | ||
19 | #include "copy_paste_unaligned_common.h" | ||
20 | |||
21 | unsigned int expected_instruction; | ||
22 | unsigned int instruction_mask; | ||
23 | |||
24 | char cacheline_buf[128] __cacheline_aligned; | ||
25 | |||
26 | void signal_action_handler(int signal_num, siginfo_t *info, void *ptr) | ||
27 | { | ||
28 | ucontext_t *ctx = ptr; | ||
29 | #if defined(__powerpc64__) | ||
30 | unsigned int *pc = (unsigned int *)ctx->uc_mcontext.gp_regs[PT_NIP]; | ||
31 | #else | ||
32 | unsigned int *pc = (unsigned int *)ctx->uc_mcontext.uc_regs->gregs[PT_NIP]; | ||
33 | #endif | ||
34 | |||
35 | /* | ||
36 | * Check that the signal was on the correct instruction, using a | ||
37 | * mask because the compiler assigns the register at RB. | ||
38 | */ | ||
39 | if ((*pc & instruction_mask) == expected_instruction) | ||
40 | _exit(0); /* We hit the right instruction */ | ||
41 | |||
42 | _exit(1); | ||
43 | } | ||
44 | |||
45 | void setup_signal_handler(void) | ||
46 | { | ||
47 | struct sigaction signal_action; | ||
48 | |||
49 | memset(&signal_action, 0, sizeof(signal_action)); | ||
50 | signal_action.sa_sigaction = signal_action_handler; | ||
51 | signal_action.sa_flags = SA_SIGINFO; | ||
52 | sigaction(SIGBUS, &signal_action, NULL); | ||
53 | } | ||
diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h new file mode 100644 index 000000000000..053899fe506e --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Declarations for common code for copy, copy_first, paste and | ||
10 | * paste_last unaligned tests. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _SELFTESTS_POWERPC_COPY_PASTE_H | ||
15 | #define _SELFTESTS_POWERPC_COPY_PASTE_H | ||
16 | |||
17 | #include <signal.h> | ||
18 | |||
19 | int main(int argc, char *argv[]); | ||
20 | void signal_action_handler(int signal_num, siginfo_t *info, void *ptr); | ||
21 | void setup_signal_handler(void); | ||
22 | extern char cacheline_buf[128] __cacheline_aligned; | ||
23 | extern unsigned int expected_instruction; | ||
24 | extern unsigned int instruction_mask; | ||
25 | |||
26 | #endif /* _SELFTESTS_POWERPC_COPY_PASTE_H */ | ||
diff --git a/tools/testing/selftests/powerpc/alignment/copy_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_unaligned.c new file mode 100644 index 000000000000..3a4e26461554 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/copy_unaligned.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Calls to copy which are not 128-byte aligned should be caught | ||
10 | * and sent a SIGBUS. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include "utils.h" | ||
17 | #include "instructions.h" | ||
18 | #include "copy_paste_unaligned_common.h" | ||
19 | |||
20 | unsigned int expected_instruction = PPC_INST_COPY; | ||
21 | unsigned int instruction_mask = 0xfc0007fe; | ||
22 | |||
23 | int test_copy_unaligned(void) | ||
24 | { | ||
25 | /* Only run this test on a P9 or later */ | ||
26 | SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); | ||
27 | |||
28 | /* Register our signal handler with SIGBUS */ | ||
29 | setup_signal_handler(); | ||
30 | |||
31 | /* +1 makes buf unaligned */ | ||
32 | copy(cacheline_buf+1); | ||
33 | |||
34 | /* We should not get here */ | ||
35 | return 1; | ||
36 | } | ||
37 | |||
38 | int main(int argc, char *argv[]) | ||
39 | { | ||
40 | return test_harness(test_copy_unaligned, "test_copy_unaligned"); | ||
41 | } | ||
diff --git a/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c new file mode 100644 index 000000000000..6e0ad045fcc3 --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Calls to paste_last which are not 128-byte aligned should be | ||
10 | * caught and sent a SIGBUS. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include "utils.h" | ||
17 | #include "instructions.h" | ||
18 | #include "copy_paste_unaligned_common.h" | ||
19 | |||
20 | unsigned int expected_instruction = PPC_INST_PASTE_LAST; | ||
21 | unsigned int instruction_mask = 0xfc2007ff; | ||
22 | |||
23 | int test_paste_last_unaligned(void) | ||
24 | { | ||
25 | /* Only run this test on a P9 or later */ | ||
26 | SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); | ||
27 | |||
28 | /* Register our signal handler with SIGBUS */ | ||
29 | setup_signal_handler(); | ||
30 | |||
31 | copy(cacheline_buf); | ||
32 | |||
33 | /* +1 makes buf unaligned */ | ||
34 | paste_last(cacheline_buf+1); | ||
35 | |||
36 | /* We should not get here */ | ||
37 | return 1; | ||
38 | } | ||
39 | |||
40 | int main(int argc, char *argv[]) | ||
41 | { | ||
42 | return test_harness(test_paste_last_unaligned, "test_paste_last_unaligned"); | ||
43 | } | ||
diff --git a/tools/testing/selftests/powerpc/alignment/paste_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_unaligned.c new file mode 100644 index 000000000000..6f982b45e4bd --- /dev/null +++ b/tools/testing/selftests/powerpc/alignment/paste_unaligned.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Chris Smart, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Calls to paste which are not 128-byte aligned should be caught | ||
10 | * and sent a SIGBUS. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <string.h> | ||
15 | #include <unistd.h> | ||
16 | #include "utils.h" | ||
17 | #include "instructions.h" | ||
18 | #include "copy_paste_unaligned_common.h" | ||
19 | |||
20 | unsigned int expected_instruction = PPC_INST_PASTE; | ||
21 | unsigned int instruction_mask = 0xfc0007fe; | ||
22 | |||
23 | int test_paste_unaligned(void) | ||
24 | { | ||
25 | /* Only run this test on a P9 or later */ | ||
26 | SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); | ||
27 | |||
28 | /* Register our signal handler with SIGBUS */ | ||
29 | setup_signal_handler(); | ||
30 | |||
31 | copy(cacheline_buf); | ||
32 | |||
33 | /* +1 makes buf unaligned */ | ||
34 | paste(cacheline_buf+1); | ||
35 | |||
36 | /* We should not get here */ | ||
37 | return 1; | ||
38 | } | ||
39 | |||
40 | int main(int argc, char *argv[]) | ||
41 | { | ||
42 | return test_harness(test_paste_unaligned, "test_paste_unaligned"); | ||
43 | } | ||
diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore index 6fa673316ac2..bce49ebd869e 100644 --- a/tools/testing/selftests/powerpc/benchmarks/.gitignore +++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore | |||
@@ -1,2 +1,4 @@ | |||
1 | gettimeofday | 1 | gettimeofday |
2 | context_switch | 2 | context_switch |
3 | mmap_bench | ||
4 | futex_bench \ No newline at end of file | ||
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile index 912445ff7ce7..a9adfb7de78f 100644 --- a/tools/testing/selftests/powerpc/benchmarks/Makefile +++ b/tools/testing/selftests/powerpc/benchmarks/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | TEST_PROGS := gettimeofday context_switch | 1 | TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench |
2 | 2 | ||
3 | CFLAGS += -O2 | 3 | CFLAGS += -O2 |
4 | 4 | ||
@@ -7,6 +7,7 @@ all: $(TEST_PROGS) | |||
7 | $(TEST_PROGS): ../harness.c | 7 | $(TEST_PROGS): ../harness.c |
8 | 8 | ||
9 | context_switch: ../utils.c | 9 | context_switch: ../utils.c |
10 | context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec | ||
10 | context_switch: LDLIBS += -lpthread | 11 | context_switch: LDLIBS += -lpthread |
11 | 12 | ||
12 | include ../../lib.mk | 13 | include ../../lib.mk |
diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c index 7b785941adec..a36883ad48a4 100644 --- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c +++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c | |||
@@ -25,7 +25,9 @@ | |||
25 | #include <sys/types.h> | 25 | #include <sys/types.h> |
26 | #include <sys/shm.h> | 26 | #include <sys/shm.h> |
27 | #include <linux/futex.h> | 27 | #include <linux/futex.h> |
28 | 28 | #ifdef __powerpc__ | |
29 | #include <altivec.h> | ||
30 | #endif | ||
29 | #include "../utils.h" | 31 | #include "../utils.h" |
30 | 32 | ||
31 | static unsigned int timeout = 30; | 33 | static unsigned int timeout = 30; |
@@ -37,12 +39,15 @@ static int touch_fp = 1; | |||
37 | double fp; | 39 | double fp; |
38 | 40 | ||
39 | static int touch_vector = 1; | 41 | static int touch_vector = 1; |
40 | typedef int v4si __attribute__ ((vector_size (16))); | 42 | vector int a, b, c; |
41 | v4si a, b, c; | ||
42 | 43 | ||
43 | #ifdef __powerpc__ | 44 | #ifdef __powerpc__ |
44 | static int touch_altivec = 1; | 45 | static int touch_altivec = 1; |
45 | 46 | ||
47 | /* | ||
48 | * Note: LTO (Link Time Optimisation) doesn't play well with this function | ||
49 | * attribute. Be very careful enabling LTO for this test. | ||
50 | */ | ||
46 | static void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void) | 51 | static void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void) |
47 | { | 52 | { |
48 | c = a + b; | 53 | c = a + b; |
@@ -369,11 +374,11 @@ static void usage(void) | |||
369 | fprintf(stderr, "\t\t--process\tUse processes (default threads)\n"); | 374 | fprintf(stderr, "\t\t--process\tUse processes (default threads)\n"); |
370 | fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n"); | 375 | fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n"); |
371 | fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n"); | 376 | fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n"); |
372 | fprintf(stderr, "\t\t--fp\t\ttouch FP\n"); | 377 | fprintf(stderr, "\t\t--no-fp\t\tDon't touch FP\n"); |
373 | #ifdef __powerpc__ | 378 | #ifdef __powerpc__ |
374 | fprintf(stderr, "\t\t--altivec\ttouch altivec\n"); | 379 | fprintf(stderr, "\t\t--no-altivec\tDon't touch altivec\n"); |
375 | #endif | 380 | #endif |
376 | fprintf(stderr, "\t\t--vector\ttouch vector\n"); | 381 | fprintf(stderr, "\t\t--no-vector\tDon't touch vector\n"); |
377 | } | 382 | } |
378 | 383 | ||
379 | int main(int argc, char *argv[]) | 384 | int main(int argc, char *argv[]) |
diff --git a/tools/testing/selftests/powerpc/benchmarks/futex_bench.c b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c new file mode 100644 index 000000000000..2fc711d9150d --- /dev/null +++ b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Anton Blanchard, Michael Ellerman, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #define _GNU_SOURCE | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <sys/syscall.h> | ||
10 | #include <time.h> | ||
11 | #include <unistd.h> | ||
12 | #include <linux/futex.h> | ||
13 | |||
14 | #include "utils.h" | ||
15 | |||
16 | #define ITERATIONS 100000000 | ||
17 | |||
18 | #define futex(A, B, C, D, E, F) syscall(__NR_futex, A, B, C, D, E, F) | ||
19 | |||
20 | int test_futex(void) | ||
21 | { | ||
22 | struct timespec ts_start, ts_end; | ||
23 | unsigned long i = ITERATIONS; | ||
24 | |||
25 | clock_gettime(CLOCK_MONOTONIC, &ts_start); | ||
26 | |||
27 | while (i--) { | ||
28 | unsigned int addr = 0; | ||
29 | futex(&addr, FUTEX_WAKE, 1, NULL, NULL, 0); | ||
30 | } | ||
31 | |||
32 | clock_gettime(CLOCK_MONOTONIC, &ts_end); | ||
33 | |||
34 | printf("time = %.6f\n", ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9); | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | int main(void) | ||
40 | { | ||
41 | return test_harness(test_futex, "futex_bench"); | ||
42 | } | ||
diff --git a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c new file mode 100644 index 000000000000..8d084a2d6e74 --- /dev/null +++ b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Anton Blanchard, Michael Ellerman, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <sys/mman.h> | ||
9 | #include <time.h> | ||
10 | |||
11 | #include "utils.h" | ||
12 | |||
13 | #define ITERATIONS 5000000 | ||
14 | |||
15 | #define MEMSIZE (128 * 1024 * 1024) | ||
16 | |||
17 | int test_mmap(void) | ||
18 | { | ||
19 | struct timespec ts_start, ts_end; | ||
20 | unsigned long i = ITERATIONS; | ||
21 | |||
22 | clock_gettime(CLOCK_MONOTONIC, &ts_start); | ||
23 | |||
24 | while (i--) { | ||
25 | char *c = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, | ||
26 | MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | ||
27 | FAIL_IF(c == MAP_FAILED); | ||
28 | munmap(c, MEMSIZE); | ||
29 | } | ||
30 | |||
31 | clock_gettime(CLOCK_MONOTONIC, &ts_end); | ||
32 | |||
33 | printf("time = %.6f\n", ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9); | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | int main(void) | ||
39 | { | ||
40 | return test_harness(test_mmap, "mmap_bench"); | ||
41 | } | ||
diff --git a/tools/testing/selftests/powerpc/instructions.h b/tools/testing/selftests/powerpc/instructions.h new file mode 100644 index 000000000000..0fb0bd3b28c9 --- /dev/null +++ b/tools/testing/selftests/powerpc/instructions.h | |||
@@ -0,0 +1,68 @@ | |||
1 | #ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H | ||
2 | #define _SELFTESTS_POWERPC_INSTRUCTIONS_H | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | |||
7 | /* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */ | ||
8 | #define __COPY(RA, RB, L) \ | ||
9 | (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10)) | ||
10 | #define COPY(RA, RB, L) \ | ||
11 | .long __COPY((RA), (RB), (L)) | ||
12 | |||
13 | static inline void copy(void *i) | ||
14 | { | ||
15 | asm volatile(str(COPY(0, %0, 0))";" | ||
16 | : | ||
17 | : "b" (i) | ||
18 | : "memory" | ||
19 | ); | ||
20 | } | ||
21 | |||
22 | static inline void copy_first(void *i) | ||
23 | { | ||
24 | asm volatile(str(COPY(0, %0, 1))";" | ||
25 | : | ||
26 | : "b" (i) | ||
27 | : "memory" | ||
28 | ); | ||
29 | } | ||
30 | |||
31 | /* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */ | ||
32 | #define __PASTE(RA, RB, L, RC) \ | ||
33 | (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31)) | ||
34 | #define PASTE(RA, RB, L, RC) \ | ||
35 | .long __PASTE((RA), (RB), (L), (RC)) | ||
36 | |||
37 | static inline int paste(void *i) | ||
38 | { | ||
39 | int cr; | ||
40 | |||
41 | asm volatile(str(PASTE(0, %1, 0, 0))";" | ||
42 | "mfcr %0;" | ||
43 | : "=r" (cr) | ||
44 | : "b" (i) | ||
45 | : "memory" | ||
46 | ); | ||
47 | return cr; | ||
48 | } | ||
49 | |||
50 | static inline int paste_last(void *i) | ||
51 | { | ||
52 | int cr; | ||
53 | |||
54 | asm volatile(str(PASTE(0, %1, 1, 1))";" | ||
55 | "mfcr %0;" | ||
56 | : "=r" (cr) | ||
57 | : "b" (i) | ||
58 | : "memory" | ||
59 | ); | ||
60 | return cr; | ||
61 | } | ||
62 | |||
63 | #define PPC_INST_COPY __COPY(0, 0, 0) | ||
64 | #define PPC_INST_COPY_FIRST __COPY(0, 0, 1) | ||
65 | #define PPC_INST_PASTE __PASTE(0, 0, 0, 0) | ||
66 | #define PPC_INST_PASTE_LAST __PASTE(0, 0, 1, 1) | ||
67 | |||
68 | #endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */ | ||
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore index b43ade0ec861..e715a3f2fbf4 100644 --- a/tools/testing/selftests/powerpc/mm/.gitignore +++ b/tools/testing/selftests/powerpc/mm/.gitignore | |||
@@ -1,3 +1,4 @@ | |||
1 | hugetlb_vs_thp_test | 1 | hugetlb_vs_thp_test |
2 | subpage_prot | 2 | subpage_prot |
3 | tempfile | 3 | tempfile |
4 | prot_sao \ No newline at end of file | ||
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile index ee179e22308c..3bdb96eae558 100644 --- a/tools/testing/selftests/powerpc/mm/Makefile +++ b/tools/testing/selftests/powerpc/mm/Makefile | |||
@@ -1,13 +1,15 @@ | |||
1 | noarg: | 1 | noarg: |
2 | $(MAKE) -C ../ | 2 | $(MAKE) -C ../ |
3 | 3 | ||
4 | TEST_PROGS := hugetlb_vs_thp_test subpage_prot | 4 | TEST_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao |
5 | TEST_FILES := tempfile | 5 | TEST_FILES := tempfile |
6 | 6 | ||
7 | all: $(TEST_PROGS) $(TEST_FILES) | 7 | all: $(TEST_PROGS) $(TEST_FILES) |
8 | 8 | ||
9 | $(TEST_PROGS): ../harness.c | 9 | $(TEST_PROGS): ../harness.c |
10 | 10 | ||
11 | prot_sao: ../utils.c | ||
12 | |||
11 | include ../../lib.mk | 13 | include ../../lib.mk |
12 | 14 | ||
13 | tempfile: | 15 | tempfile: |
diff --git a/tools/testing/selftests/powerpc/mm/prot_sao.c b/tools/testing/selftests/powerpc/mm/prot_sao.c new file mode 100644 index 000000000000..611530d43fa9 --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/prot_sao.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Michael Ellerman, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <string.h> | ||
9 | #include <sys/mman.h> | ||
10 | |||
11 | #include <asm/cputable.h> | ||
12 | |||
13 | #include "utils.h" | ||
14 | |||
15 | #define SIZE (64 * 1024) | ||
16 | |||
17 | int test_prot_sao(void) | ||
18 | { | ||
19 | char *p; | ||
20 | |||
21 | /* 2.06 or later should support SAO */ | ||
22 | SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); | ||
23 | |||
24 | /* | ||
25 | * Ensure we can ask for PROT_SAO. | ||
26 | * We can't really verify that it does the right thing, but at least we | ||
27 | * confirm the kernel will accept it. | ||
28 | */ | ||
29 | p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE | PROT_SAO, | ||
30 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); | ||
31 | FAIL_IF(p == MAP_FAILED); | ||
32 | |||
33 | /* Write to the mapping, to at least cause a fault */ | ||
34 | memset(p, 0xaa, SIZE); | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | int main(void) | ||
40 | { | ||
41 | return test_harness(test_prot_sao, "prot-sao"); | ||
42 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore index 42bddbed8b64..44b7df14a936 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore +++ b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore | |||
@@ -20,3 +20,5 @@ back_to_back_ebbs_test | |||
20 | lost_exception_test | 20 | lost_exception_test |
21 | no_handler_test | 21 | no_handler_test |
22 | cycles_with_mmcr2_test | 22 | cycles_with_mmcr2_test |
23 | ebb_lmr | ||
24 | ebb_lmr_regs \ No newline at end of file | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile index 8d2279c4bb4b..6b0453e60d53 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile +++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile | |||
@@ -14,7 +14,7 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_test \ | |||
14 | fork_cleanup_test ebb_on_child_test \ | 14 | fork_cleanup_test ebb_on_child_test \ |
15 | ebb_on_willing_child_test back_to_back_ebbs_test \ | 15 | ebb_on_willing_child_test back_to_back_ebbs_test \ |
16 | lost_exception_test no_handler_test \ | 16 | lost_exception_test no_handler_test \ |
17 | cycles_with_mmcr2_test | 17 | cycles_with_mmcr2_test ebb_lmr ebb_lmr_regs |
18 | 18 | ||
19 | all: $(TEST_PROGS) | 19 | all: $(TEST_PROGS) |
20 | 20 | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c new file mode 100644 index 000000000000..c47ebd55ba4d --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Jack Miller, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <stdio.h> | ||
8 | |||
9 | #include "ebb.h" | ||
10 | #include "ebb_lmr.h" | ||
11 | |||
12 | #define SIZE (32 * 1024 * 1024) /* 32M */ | ||
13 | #define LM_SIZE 0 /* Smallest encoding, 32M */ | ||
14 | |||
15 | #define SECTIONS 64 /* 1 per bit in LMSER */ | ||
16 | #define SECTION_SIZE (SIZE / SECTIONS) | ||
17 | #define SECTION_LONGS (SECTION_SIZE / sizeof(long)) | ||
18 | |||
19 | static unsigned long *test_mem; | ||
20 | |||
21 | static int lmr_count = 0; | ||
22 | |||
23 | void ebb_lmr_handler(void) | ||
24 | { | ||
25 | lmr_count++; | ||
26 | } | ||
27 | |||
28 | void ldmx_full_section(unsigned long *mem, int section) | ||
29 | { | ||
30 | unsigned long *ptr; | ||
31 | int i; | ||
32 | |||
33 | for (i = 0; i < SECTION_LONGS; i++) { | ||
34 | ptr = &mem[(SECTION_LONGS * section) + i]; | ||
35 | ldmx((unsigned long) &ptr); | ||
36 | ebb_lmr_reset(); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | unsigned long section_masks[] = { | ||
41 | 0x8000000000000000, | ||
42 | 0xFF00000000000000, | ||
43 | 0x0000000F70000000, | ||
44 | 0x8000000000000001, | ||
45 | 0xF0F0F0F0F0F0F0F0, | ||
46 | 0x0F0F0F0F0F0F0F0F, | ||
47 | 0x0 | ||
48 | }; | ||
49 | |||
50 | int ebb_lmr_section_test(unsigned long *mem) | ||
51 | { | ||
52 | unsigned long *mask = section_masks; | ||
53 | int i; | ||
54 | |||
55 | for (; *mask; mask++) { | ||
56 | mtspr(SPRN_LMSER, *mask); | ||
57 | printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER)); | ||
58 | |||
59 | for (i = 0; i < 64; i++) { | ||
60 | lmr_count = 0; | ||
61 | ldmx_full_section(mem, i); | ||
62 | if (*mask & (1UL << (63 - i))) | ||
63 | FAIL_IF(lmr_count != SECTION_LONGS); | ||
64 | else | ||
65 | FAIL_IF(lmr_count); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | int ebb_lmr(void) | ||
73 | { | ||
74 | int i; | ||
75 | |||
76 | SKIP_IF(!lmr_is_supported()); | ||
77 | |||
78 | setup_ebb_handler(ebb_lmr_handler); | ||
79 | |||
80 | ebb_global_enable(); | ||
81 | |||
82 | FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0); | ||
83 | |||
84 | mtspr(SPRN_LMSER, 0); | ||
85 | |||
86 | FAIL_IF(mfspr(SPRN_LMSER) != 0); | ||
87 | |||
88 | mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE)); | ||
89 | |||
90 | FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE)); | ||
91 | |||
92 | /* Read every single byte to ensure we get no false positives */ | ||
93 | for (i = 0; i < SECTIONS; i++) | ||
94 | ldmx_full_section(test_mem, i); | ||
95 | |||
96 | FAIL_IF(lmr_count != 0); | ||
97 | |||
98 | /* Turn on the first section */ | ||
99 | |||
100 | mtspr(SPRN_LMSER, (1UL << 63)); | ||
101 | FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63)); | ||
102 | |||
103 | /* Enable LM (BESCR) */ | ||
104 | |||
105 | mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME); | ||
106 | FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME)); | ||
107 | |||
108 | ldmx((unsigned long)&test_mem); | ||
109 | |||
110 | FAIL_IF(lmr_count != 1); // exactly one exception | ||
111 | FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled | ||
112 | FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set | ||
113 | |||
114 | printf("Simple LMR EBB OK\n"); | ||
115 | |||
116 | /* This shouldn't cause an EBB since it's been disabled */ | ||
117 | ldmx((unsigned long)&test_mem); | ||
118 | FAIL_IF(lmr_count != 1); | ||
119 | |||
120 | printf("LMR disable on EBB OK\n"); | ||
121 | |||
122 | ebb_lmr_reset(); | ||
123 | |||
124 | /* This should cause an EBB or reset is broken */ | ||
125 | ldmx((unsigned long)&test_mem); | ||
126 | FAIL_IF(lmr_count != 2); | ||
127 | |||
128 | printf("LMR reset EBB OK\n"); | ||
129 | |||
130 | ebb_lmr_reset(); | ||
131 | |||
132 | return ebb_lmr_section_test(test_mem); | ||
133 | } | ||
134 | |||
135 | int main(void) | ||
136 | { | ||
137 | int ret = test_harness(ebb_lmr, "ebb_lmr"); | ||
138 | |||
139 | if (test_mem) | ||
140 | free(test_mem); | ||
141 | |||
142 | return ret; | ||
143 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h new file mode 100644 index 000000000000..ef50abd557cd --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef _SELFTESTS_POWERPC_PMU_EBB_LMR_H | ||
2 | #define _SELFTESTS_POWERPC_PMU_EBB_LMR_H | ||
3 | |||
4 | #include "reg.h" | ||
5 | |||
6 | #ifndef PPC_FEATURE2_ARCH_3_00 | ||
7 | #define PPC_FEATURE2_ARCH_3_00 0x00800000 | ||
8 | #endif | ||
9 | |||
10 | #define lmr_is_supported() have_hwcap2(PPC_FEATURE2_ARCH_3_00) | ||
11 | |||
12 | static inline void ebb_lmr_reset(void) | ||
13 | { | ||
14 | unsigned long bescr = mfspr(SPRN_BESCR); | ||
15 | bescr &= ~(BESCR_LMEO); | ||
16 | bescr |= BESCR_LME; | ||
17 | mtspr(SPRN_BESCR, bescr); | ||
18 | } | ||
19 | |||
20 | #define LDMX(t, a, b)\ | ||
21 | (0x7c00026a | \ | ||
22 | (((t) & 0x1f) << 21) | \ | ||
23 | (((a) & 0x1f) << 16) | \ | ||
24 | (((b) & 0x1f) << 11)) | ||
25 | |||
26 | static inline unsigned long ldmx(unsigned long address) | ||
27 | { | ||
28 | unsigned long ret; | ||
29 | |||
30 | asm volatile ("mr 9, %1\r\n" | ||
31 | ".long " __stringify(LDMX(9, 0, 9)) "\r\n" | ||
32 | "mr %0, 9\r\n":"=r"(ret) | ||
33 | :"r"(address) | ||
34 | :"r9"); | ||
35 | |||
36 | return ret; | ||
37 | } | ||
38 | |||
39 | #endif | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c new file mode 100644 index 000000000000..aff4241fd88a --- /dev/null +++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Jack Miller, IBM Corp. | ||
3 | * Licensed under GPLv2. | ||
4 | */ | ||
5 | |||
6 | #include <stdlib.h> | ||
7 | #include <stdio.h> | ||
8 | #include <unistd.h> | ||
9 | |||
10 | #include "ebb.h" | ||
11 | #include "ebb_lmr.h" | ||
12 | |||
13 | #define CHECKS 10000 | ||
14 | |||
15 | int ebb_lmr_regs(void) | ||
16 | { | ||
17 | int i; | ||
18 | |||
19 | SKIP_IF(!lmr_is_supported()); | ||
20 | |||
21 | ebb_global_enable(); | ||
22 | |||
23 | for (i = 0; i < CHECKS; i++) { | ||
24 | mtspr(SPRN_LMRR, i << 25); // skip size and rsvd bits | ||
25 | mtspr(SPRN_LMSER, i); | ||
26 | |||
27 | FAIL_IF(mfspr(SPRN_LMRR) != (i << 25)); | ||
28 | FAIL_IF(mfspr(SPRN_LMSER) != i); | ||
29 | } | ||
30 | |||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | int main(void) | ||
35 | { | ||
36 | return test_harness(ebb_lmr_regs, "ebb_lmr_regs"); | ||
37 | } | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c index 5da355135df2..ae9a79086111 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c | |||
@@ -51,7 +51,7 @@ static int do_count_loop(struct event *event, uint64_t instructions, | |||
51 | printf("Looped for %lu instructions, overhead %lu\n", instructions, overhead); | 51 | printf("Looped for %lu instructions, overhead %lu\n", instructions, overhead); |
52 | printf("Expected %lu\n", expected); | 52 | printf("Expected %lu\n", expected); |
53 | printf("Actual %llu\n", event->result.value); | 53 | printf("Actual %llu\n", event->result.value); |
54 | printf("Error %ld, %f%%\n", difference, percentage); | 54 | printf("Delta %ld, %f%%\n", difference, percentage); |
55 | printf("Took %d EBBs\n", ebb_state.stats.ebb_count); | 55 | printf("Took %d EBBs\n", ebb_state.stats.ebb_count); |
56 | } | 56 | } |
57 | 57 | ||
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c index a361ad3334ce..8b992fa5b478 100644 --- a/tools/testing/selftests/powerpc/pmu/lib.c +++ b/tools/testing/selftests/powerpc/pmu/lib.c | |||
@@ -190,7 +190,7 @@ int parse_proc_maps(void) | |||
190 | 190 | ||
191 | bool require_paranoia_below(int level) | 191 | bool require_paranoia_below(int level) |
192 | { | 192 | { |
193 | unsigned long current; | 193 | long current; |
194 | char *end, buf[16]; | 194 | char *end, buf[16]; |
195 | FILE *f; | 195 | FILE *f; |
196 | int rc; | 196 | int rc; |
@@ -208,7 +208,7 @@ bool require_paranoia_below(int level) | |||
208 | goto out_close; | 208 | goto out_close; |
209 | } | 209 | } |
210 | 210 | ||
211 | current = strtoul(buf, &end, 10); | 211 | current = strtol(buf, &end, 10); |
212 | 212 | ||
213 | if (end == buf) { | 213 | if (end == buf) { |
214 | printf("Couldn't parse " PARANOID_PATH "?\n"); | 214 | printf("Couldn't parse " PARANOID_PATH "?\n"); |
@@ -216,7 +216,7 @@ bool require_paranoia_below(int level) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | if (current >= level) | 218 | if (current >= level) |
219 | goto out; | 219 | goto out_close; |
220 | 220 | ||
221 | rc = 0; | 221 | rc = 0; |
222 | out_close: | 222 | out_close: |
diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h index 65bfdeeebdee..fddf368ed82f 100644 --- a/tools/testing/selftests/powerpc/reg.h +++ b/tools/testing/selftests/powerpc/reg.h | |||
@@ -34,6 +34,11 @@ | |||
34 | 34 | ||
35 | #define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ | 35 | #define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ |
36 | #define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ | 36 | #define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ |
37 | #define BESCR_LME (0x1ul << 34) /* Load Monitor Enable */ | ||
38 | #define BESCR_LMEO (0x1ul << 2) /* Load Monitor Exception Occurred */ | ||
39 | |||
40 | #define SPRN_LMRR 813 /* Load Monitor Region Register */ | ||
41 | #define SPRN_LMSER 814 /* Load Monitor Section Enable Register */ | ||
37 | 42 | ||
38 | #define SPRN_PMC1 771 | 43 | #define SPRN_PMC1 771 |
39 | #define SPRN_PMC2 772 | 44 | #define SPRN_PMC2 772 |
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore index bb942db845bf..82c0a9ce6e74 100644 --- a/tools/testing/selftests/powerpc/tm/.gitignore +++ b/tools/testing/selftests/powerpc/tm/.gitignore | |||
@@ -6,3 +6,4 @@ tm-vmxcopy | |||
6 | tm-fork | 6 | tm-fork |
7 | tm-tar | 7 | tm-tar |
8 | tm-tmspr | 8 | tm-tmspr |
9 | tm-exec | ||
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile index d0505dbd22d5..9d301d785d9e 100644 --- a/tools/testing/selftests/powerpc/tm/Makefile +++ b/tools/testing/selftests/powerpc/tm/Makefile | |||
@@ -1,11 +1,14 @@ | |||
1 | TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy tm-fork tm-tar tm-tmspr | 1 | TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ |
2 | tm-vmxcopy tm-fork tm-tar tm-tmspr tm-exec tm-execed | ||
2 | 3 | ||
3 | all: $(TEST_PROGS) | 4 | all: $(TEST_PROGS) |
4 | 5 | ||
5 | $(TEST_PROGS): ../harness.c ../utils.c | 6 | $(TEST_PROGS): ../harness.c ../utils.c |
6 | 7 | ||
8 | CFLAGS += -mhtm | ||
9 | |||
7 | tm-syscall: tm-syscall-asm.S | 10 | tm-syscall: tm-syscall-asm.S |
8 | tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include | 11 | tm-syscall: CFLAGS += -I../../../../../usr/include |
9 | tm-tmspr: CFLAGS += -pthread | 12 | tm-tmspr: CFLAGS += -pthread |
10 | 13 | ||
11 | include ../../lib.mk | 14 | include ../../lib.mk |
diff --git a/tools/testing/selftests/powerpc/tm/tm-exec.c b/tools/testing/selftests/powerpc/tm/tm-exec.c new file mode 100644 index 000000000000..3d27fa0ece04 --- /dev/null +++ b/tools/testing/selftests/powerpc/tm/tm-exec.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright 2016, Cyril Bur, IBM Corp. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Syscalls can be performed provided the transactions are suspended. | ||
10 | * The exec() class of syscall is unique as a new process is loaded. | ||
11 | * | ||
12 | * It makes little sense for after an exec() call for the previously | ||
13 | * suspended transaction to still exist. | ||
14 | */ | ||
15 | |||
16 | #define _GNU_SOURCE | ||
17 | #include <errno.h> | ||
18 | #include <inttypes.h> | ||
19 | #include <libgen.h> | ||
20 | #include <pthread.h> | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <unistd.h> | ||
25 | |||
26 | #include "utils.h" | ||
27 | #include "tm.h" | ||
28 | |||
29 | static char *path; | ||
30 | |||
31 | static int test_exec(void) | ||
32 | { | ||
33 | SKIP_IF(!have_htm()); | ||
34 | |||
35 | asm __volatile__( | ||
36 | "tbegin.;" | ||
37 | "blt 1f; " | ||
38 | "tsuspend.;" | ||
39 | "1: ;" | ||
40 | : : : "memory"); | ||
41 | |||
42 | execl(path, "tm-exec", "--child", NULL); | ||
43 | |||
44 | /* Shouldn't get here */ | ||
45 | perror("execl() failed"); | ||
46 | return 1; | ||
47 | } | ||
48 | |||
49 | static int after_exec(void) | ||
50 | { | ||
51 | asm __volatile__( | ||
52 | "tbegin.;" | ||
53 | "blt 1f;" | ||
54 | "tsuspend.;" | ||
55 | "1: ;" | ||
56 | : : : "memory"); | ||
57 | |||
58 | FAIL_IF(failure_is_nesting()); | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | int main(int argc, char *argv[]) | ||
63 | { | ||
64 | path = argv[0]; | ||
65 | |||
66 | if (argc > 1 && strcmp(argv[1], "--child") == 0) | ||
67 | return after_exec(); | ||
68 | |||
69 | return test_harness(test_exec, "tm_exec"); | ||
70 | } | ||
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c index 60560cb20e38..454b965a2db3 100644 --- a/tools/testing/selftests/powerpc/tm/tm-syscall.c +++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c | |||
@@ -27,21 +27,6 @@ unsigned retries = 0; | |||
27 | #define TEST_DURATION 10 /* seconds */ | 27 | #define TEST_DURATION 10 /* seconds */ |
28 | #define TM_RETRIES 100 | 28 | #define TM_RETRIES 100 |
29 | 29 | ||
30 | long failure_code(void) | ||
31 | { | ||
32 | return __builtin_get_texasru() >> 24; | ||
33 | } | ||
34 | |||
35 | bool failure_is_persistent(void) | ||
36 | { | ||
37 | return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT; | ||
38 | } | ||
39 | |||
40 | bool failure_is_syscall(void) | ||
41 | { | ||
42 | return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL; | ||
43 | } | ||
44 | |||
45 | pid_t getppid_tm(bool suspend) | 30 | pid_t getppid_tm(bool suspend) |
46 | { | 31 | { |
47 | int i; | 32 | int i; |
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h index 24144b25772c..60318bad7d7a 100644 --- a/tools/testing/selftests/powerpc/tm/tm.h +++ b/tools/testing/selftests/powerpc/tm/tm.h | |||
@@ -6,8 +6,9 @@ | |||
6 | #ifndef _SELFTESTS_POWERPC_TM_TM_H | 6 | #ifndef _SELFTESTS_POWERPC_TM_TM_H |
7 | #define _SELFTESTS_POWERPC_TM_TM_H | 7 | #define _SELFTESTS_POWERPC_TM_TM_H |
8 | 8 | ||
9 | #include <stdbool.h> | 9 | #include <asm/tm.h> |
10 | #include <asm/cputable.h> | 10 | #include <asm/cputable.h> |
11 | #include <stdbool.h> | ||
11 | 12 | ||
12 | #include "../utils.h" | 13 | #include "../utils.h" |
13 | 14 | ||
@@ -31,4 +32,24 @@ static inline bool have_htm_nosc(void) | |||
31 | #endif | 32 | #endif |
32 | } | 33 | } |
33 | 34 | ||
35 | static inline long failure_code(void) | ||
36 | { | ||
37 | return __builtin_get_texasru() >> 24; | ||
38 | } | ||
39 | |||
40 | static inline bool failure_is_persistent(void) | ||
41 | { | ||
42 | return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT; | ||
43 | } | ||
44 | |||
45 | static inline bool failure_is_syscall(void) | ||
46 | { | ||
47 | return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL; | ||
48 | } | ||
49 | |||
50 | static inline bool failure_is_nesting(void) | ||
51 | { | ||
52 | return (__builtin_get_texasru() & 0x400000); | ||
53 | } | ||
54 | |||
34 | #endif /* _SELFTESTS_POWERPC_TM_TM_H */ | 55 | #endif /* _SELFTESTS_POWERPC_TM_TM_H */ |
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h index a985cfaa535e..fbd33e52ef8f 100644 --- a/tools/testing/selftests/powerpc/utils.h +++ b/tools/testing/selftests/powerpc/utils.h | |||
@@ -27,6 +27,11 @@ int test_harness(int (test_function)(void), char *name); | |||
27 | extern void *get_auxv_entry(int type); | 27 | extern void *get_auxv_entry(int type); |
28 | int pick_online_cpu(void); | 28 | int pick_online_cpu(void); |
29 | 29 | ||
30 | static inline bool have_hwcap(unsigned long ftr) | ||
31 | { | ||
32 | return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; | ||
33 | } | ||
34 | |||
30 | static inline bool have_hwcap2(unsigned long ftr2) | 35 | static inline bool have_hwcap2(unsigned long ftr2) |
31 | { | 36 | { |
32 | return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; | 37 | return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; |
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 2e58549b2f02..03f1fa495d74 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c | |||
@@ -1021,8 +1021,8 @@ void tracer_stop(int sig) | |||
1021 | typedef void tracer_func_t(struct __test_metadata *_metadata, | 1021 | typedef void tracer_func_t(struct __test_metadata *_metadata, |
1022 | pid_t tracee, int status, void *args); | 1022 | pid_t tracee, int status, void *args); |
1023 | 1023 | ||
1024 | void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, | 1024 | void start_tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, |
1025 | tracer_func_t tracer_func, void *args) | 1025 | tracer_func_t tracer_func, void *args, bool ptrace_syscall) |
1026 | { | 1026 | { |
1027 | int ret = -1; | 1027 | int ret = -1; |
1028 | struct sigaction action = { | 1028 | struct sigaction action = { |
@@ -1042,12 +1042,16 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, | |||
1042 | /* Wait for attach stop */ | 1042 | /* Wait for attach stop */ |
1043 | wait(NULL); | 1043 | wait(NULL); |
1044 | 1044 | ||
1045 | ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, PTRACE_O_TRACESECCOMP); | 1045 | ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, ptrace_syscall ? |
1046 | PTRACE_O_TRACESYSGOOD : | ||
1047 | PTRACE_O_TRACESECCOMP); | ||
1046 | ASSERT_EQ(0, ret) { | 1048 | ASSERT_EQ(0, ret) { |
1047 | TH_LOG("Failed to set PTRACE_O_TRACESECCOMP"); | 1049 | TH_LOG("Failed to set PTRACE_O_TRACESECCOMP"); |
1048 | kill(tracee, SIGKILL); | 1050 | kill(tracee, SIGKILL); |
1049 | } | 1051 | } |
1050 | ptrace(PTRACE_CONT, tracee, NULL, 0); | 1052 | ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT, |
1053 | tracee, NULL, 0); | ||
1054 | ASSERT_EQ(0, ret); | ||
1051 | 1055 | ||
1052 | /* Unblock the tracee */ | 1056 | /* Unblock the tracee */ |
1053 | ASSERT_EQ(1, write(fd, "A", 1)); | 1057 | ASSERT_EQ(1, write(fd, "A", 1)); |
@@ -1063,12 +1067,13 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, | |||
1063 | /* Child is dead. Time to go. */ | 1067 | /* Child is dead. Time to go. */ |
1064 | return; | 1068 | return; |
1065 | 1069 | ||
1066 | /* Make sure this is a seccomp event. */ | 1070 | /* Check if this is a seccomp event. */ |
1067 | ASSERT_EQ(true, IS_SECCOMP_EVENT(status)); | 1071 | ASSERT_EQ(!ptrace_syscall, IS_SECCOMP_EVENT(status)); |
1068 | 1072 | ||
1069 | tracer_func(_metadata, tracee, status, args); | 1073 | tracer_func(_metadata, tracee, status, args); |
1070 | 1074 | ||
1071 | ret = ptrace(PTRACE_CONT, tracee, NULL, NULL); | 1075 | ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT, |
1076 | tracee, NULL, 0); | ||
1072 | ASSERT_EQ(0, ret); | 1077 | ASSERT_EQ(0, ret); |
1073 | } | 1078 | } |
1074 | /* Directly report the status of our test harness results. */ | 1079 | /* Directly report the status of our test harness results. */ |
@@ -1079,7 +1084,7 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, | |||
1079 | void cont_handler(int num) | 1084 | void cont_handler(int num) |
1080 | { } | 1085 | { } |
1081 | pid_t setup_trace_fixture(struct __test_metadata *_metadata, | 1086 | pid_t setup_trace_fixture(struct __test_metadata *_metadata, |
1082 | tracer_func_t func, void *args) | 1087 | tracer_func_t func, void *args, bool ptrace_syscall) |
1083 | { | 1088 | { |
1084 | char sync; | 1089 | char sync; |
1085 | int pipefd[2]; | 1090 | int pipefd[2]; |
@@ -1095,7 +1100,8 @@ pid_t setup_trace_fixture(struct __test_metadata *_metadata, | |||
1095 | signal(SIGALRM, cont_handler); | 1100 | signal(SIGALRM, cont_handler); |
1096 | if (tracer_pid == 0) { | 1101 | if (tracer_pid == 0) { |
1097 | close(pipefd[0]); | 1102 | close(pipefd[0]); |
1098 | tracer(_metadata, pipefd[1], tracee, func, args); | 1103 | start_tracer(_metadata, pipefd[1], tracee, func, args, |
1104 | ptrace_syscall); | ||
1099 | syscall(__NR_exit, 0); | 1105 | syscall(__NR_exit, 0); |
1100 | } | 1106 | } |
1101 | close(pipefd[1]); | 1107 | close(pipefd[1]); |
@@ -1177,7 +1183,7 @@ FIXTURE_SETUP(TRACE_poke) | |||
1177 | 1183 | ||
1178 | /* Launch tracer. */ | 1184 | /* Launch tracer. */ |
1179 | self->tracer = setup_trace_fixture(_metadata, tracer_poke, | 1185 | self->tracer = setup_trace_fixture(_metadata, tracer_poke, |
1180 | &self->tracer_args); | 1186 | &self->tracer_args, false); |
1181 | } | 1187 | } |
1182 | 1188 | ||
1183 | FIXTURE_TEARDOWN(TRACE_poke) | 1189 | FIXTURE_TEARDOWN(TRACE_poke) |
@@ -1399,6 +1405,29 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee, | |||
1399 | 1405 | ||
1400 | } | 1406 | } |
1401 | 1407 | ||
1408 | void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee, | ||
1409 | int status, void *args) | ||
1410 | { | ||
1411 | int ret, nr; | ||
1412 | unsigned long msg; | ||
1413 | static bool entry; | ||
1414 | |||
1415 | /* Make sure we got an empty message. */ | ||
1416 | ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg); | ||
1417 | EXPECT_EQ(0, ret); | ||
1418 | EXPECT_EQ(0, msg); | ||
1419 | |||
1420 | /* The only way to tell PTRACE_SYSCALL entry/exit is by counting. */ | ||
1421 | entry = !entry; | ||
1422 | if (!entry) | ||
1423 | return; | ||
1424 | |||
1425 | nr = get_syscall(_metadata, tracee); | ||
1426 | |||
1427 | if (nr == __NR_getpid) | ||
1428 | change_syscall(_metadata, tracee, __NR_getppid); | ||
1429 | } | ||
1430 | |||
1402 | FIXTURE_DATA(TRACE_syscall) { | 1431 | FIXTURE_DATA(TRACE_syscall) { |
1403 | struct sock_fprog prog; | 1432 | struct sock_fprog prog; |
1404 | pid_t tracer, mytid, mypid, parent; | 1433 | pid_t tracer, mytid, mypid, parent; |
@@ -1440,7 +1469,8 @@ FIXTURE_SETUP(TRACE_syscall) | |||
1440 | ASSERT_NE(self->parent, self->mypid); | 1469 | ASSERT_NE(self->parent, self->mypid); |
1441 | 1470 | ||
1442 | /* Launch tracer. */ | 1471 | /* Launch tracer. */ |
1443 | self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL); | 1472 | self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL, |
1473 | false); | ||
1444 | } | 1474 | } |
1445 | 1475 | ||
1446 | FIXTURE_TEARDOWN(TRACE_syscall) | 1476 | FIXTURE_TEARDOWN(TRACE_syscall) |
@@ -1500,6 +1530,130 @@ TEST_F(TRACE_syscall, syscall_dropped) | |||
1500 | EXPECT_NE(self->mytid, syscall(__NR_gettid)); | 1530 | EXPECT_NE(self->mytid, syscall(__NR_gettid)); |
1501 | } | 1531 | } |
1502 | 1532 | ||
1533 | TEST_F(TRACE_syscall, skip_after_RET_TRACE) | ||
1534 | { | ||
1535 | struct sock_filter filter[] = { | ||
1536 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | ||
1537 | offsetof(struct seccomp_data, nr)), | ||
1538 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1), | ||
1539 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM), | ||
1540 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | ||
1541 | }; | ||
1542 | struct sock_fprog prog = { | ||
1543 | .len = (unsigned short)ARRAY_SIZE(filter), | ||
1544 | .filter = filter, | ||
1545 | }; | ||
1546 | long ret; | ||
1547 | |||
1548 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | ||
1549 | ASSERT_EQ(0, ret); | ||
1550 | |||
1551 | /* Install fixture filter. */ | ||
1552 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); | ||
1553 | ASSERT_EQ(0, ret); | ||
1554 | |||
1555 | /* Install "errno on getppid" filter. */ | ||
1556 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0); | ||
1557 | ASSERT_EQ(0, ret); | ||
1558 | |||
1559 | /* Tracer will redirect getpid to getppid, and we should see EPERM. */ | ||
1560 | EXPECT_EQ(-1, syscall(__NR_getpid)); | ||
1561 | EXPECT_EQ(EPERM, errno); | ||
1562 | } | ||
1563 | |||
1564 | TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS) | ||
1565 | { | ||
1566 | struct sock_filter filter[] = { | ||
1567 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | ||
1568 | offsetof(struct seccomp_data, nr)), | ||
1569 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1), | ||
1570 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL), | ||
1571 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | ||
1572 | }; | ||
1573 | struct sock_fprog prog = { | ||
1574 | .len = (unsigned short)ARRAY_SIZE(filter), | ||
1575 | .filter = filter, | ||
1576 | }; | ||
1577 | long ret; | ||
1578 | |||
1579 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | ||
1580 | ASSERT_EQ(0, ret); | ||
1581 | |||
1582 | /* Install fixture filter. */ | ||
1583 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); | ||
1584 | ASSERT_EQ(0, ret); | ||
1585 | |||
1586 | /* Install "death on getppid" filter. */ | ||
1587 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0); | ||
1588 | ASSERT_EQ(0, ret); | ||
1589 | |||
1590 | /* Tracer will redirect getpid to getppid, and we should die. */ | ||
1591 | EXPECT_NE(self->mypid, syscall(__NR_getpid)); | ||
1592 | } | ||
1593 | |||
1594 | TEST_F(TRACE_syscall, skip_after_ptrace) | ||
1595 | { | ||
1596 | struct sock_filter filter[] = { | ||
1597 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | ||
1598 | offsetof(struct seccomp_data, nr)), | ||
1599 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1), | ||
1600 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM), | ||
1601 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | ||
1602 | }; | ||
1603 | struct sock_fprog prog = { | ||
1604 | .len = (unsigned short)ARRAY_SIZE(filter), | ||
1605 | .filter = filter, | ||
1606 | }; | ||
1607 | long ret; | ||
1608 | |||
1609 | /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */ | ||
1610 | teardown_trace_fixture(_metadata, self->tracer); | ||
1611 | self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL, | ||
1612 | true); | ||
1613 | |||
1614 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | ||
1615 | ASSERT_EQ(0, ret); | ||
1616 | |||
1617 | /* Install "errno on getppid" filter. */ | ||
1618 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0); | ||
1619 | ASSERT_EQ(0, ret); | ||
1620 | |||
1621 | /* Tracer will redirect getpid to getppid, and we should see EPERM. */ | ||
1622 | EXPECT_EQ(-1, syscall(__NR_getpid)); | ||
1623 | EXPECT_EQ(EPERM, errno); | ||
1624 | } | ||
1625 | |||
1626 | TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS) | ||
1627 | { | ||
1628 | struct sock_filter filter[] = { | ||
1629 | BPF_STMT(BPF_LD|BPF_W|BPF_ABS, | ||
1630 | offsetof(struct seccomp_data, nr)), | ||
1631 | BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1), | ||
1632 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL), | ||
1633 | BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), | ||
1634 | }; | ||
1635 | struct sock_fprog prog = { | ||
1636 | .len = (unsigned short)ARRAY_SIZE(filter), | ||
1637 | .filter = filter, | ||
1638 | }; | ||
1639 | long ret; | ||
1640 | |||
1641 | /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */ | ||
1642 | teardown_trace_fixture(_metadata, self->tracer); | ||
1643 | self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL, | ||
1644 | true); | ||
1645 | |||
1646 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | ||
1647 | ASSERT_EQ(0, ret); | ||
1648 | |||
1649 | /* Install "death on getppid" filter. */ | ||
1650 | ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0); | ||
1651 | ASSERT_EQ(0, ret); | ||
1652 | |||
1653 | /* Tracer will redirect getpid to getppid, and we should die. */ | ||
1654 | EXPECT_NE(self->mypid, syscall(__NR_getpid)); | ||
1655 | } | ||
1656 | |||
1503 | #ifndef __NR_seccomp | 1657 | #ifndef __NR_seccomp |
1504 | # if defined(__i386__) | 1658 | # if defined(__i386__) |
1505 | # define __NR_seccomp 354 | 1659 | # define __NR_seccomp 354 |
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile index 4a1be1b75a7f..1d5556869137 100644 --- a/tools/testing/selftests/timers/Makefile +++ b/tools/testing/selftests/timers/Makefile | |||
@@ -10,7 +10,7 @@ TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \ | |||
10 | 10 | ||
11 | TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ | 11 | TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ |
12 | skew_consistency clocksource-switch leap-a-day \ | 12 | skew_consistency clocksource-switch leap-a-day \ |
13 | leapcrash set-tai set-2038 | 13 | leapcrash set-tai set-2038 set-tz |
14 | 14 | ||
15 | bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED) | 15 | bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED) |
16 | 16 | ||
@@ -30,6 +30,7 @@ run_destructive_tests: run_tests | |||
30 | ./clocksource-switch | 30 | ./clocksource-switch |
31 | ./leap-a-day -s -i 10 | 31 | ./leap-a-day -s -i 10 |
32 | ./leapcrash | 32 | ./leapcrash |
33 | ./set-tz | ||
33 | ./set-tai | 34 | ./set-tai |
34 | ./set-2038 | 35 | ./set-2038 |
35 | 36 | ||
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c index 624bce51b27d..4230d3052e5d 100644 --- a/tools/testing/selftests/timers/rtctest.c +++ b/tools/testing/selftests/timers/rtctest.c | |||
@@ -144,11 +144,12 @@ test_READ: | |||
144 | 144 | ||
145 | retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); | 145 | retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); |
146 | if (retval == -1) { | 146 | if (retval == -1) { |
147 | if (errno == ENOTTY) { | 147 | if (errno == EINVAL) { |
148 | fprintf(stderr, | 148 | fprintf(stderr, |
149 | "\n...Alarm IRQs not supported.\n"); | 149 | "\n...Alarm IRQs not supported.\n"); |
150 | goto test_PIE; | 150 | goto test_PIE; |
151 | } | 151 | } |
152 | |||
152 | perror("RTC_ALM_SET ioctl"); | 153 | perror("RTC_ALM_SET ioctl"); |
153 | exit(errno); | 154 | exit(errno); |
154 | } | 155 | } |
@@ -166,6 +167,12 @@ test_READ: | |||
166 | /* Enable alarm interrupts */ | 167 | /* Enable alarm interrupts */ |
167 | retval = ioctl(fd, RTC_AIE_ON, 0); | 168 | retval = ioctl(fd, RTC_AIE_ON, 0); |
168 | if (retval == -1) { | 169 | if (retval == -1) { |
170 | if (errno == EINVAL) { | ||
171 | fprintf(stderr, | ||
172 | "\n...Alarm IRQs not supported.\n"); | ||
173 | goto test_PIE; | ||
174 | } | ||
175 | |||
169 | perror("RTC_AIE_ON ioctl"); | 176 | perror("RTC_AIE_ON ioctl"); |
170 | exit(errno); | 177 | exit(errno); |
171 | } | 178 | } |
@@ -193,7 +200,7 @@ test_PIE: | |||
193 | retval = ioctl(fd, RTC_IRQP_READ, &tmp); | 200 | retval = ioctl(fd, RTC_IRQP_READ, &tmp); |
194 | if (retval == -1) { | 201 | if (retval == -1) { |
195 | /* not all RTCs support periodic IRQs */ | 202 | /* not all RTCs support periodic IRQs */ |
196 | if (errno == ENOTTY) { | 203 | if (errno == EINVAL) { |
197 | fprintf(stderr, "\nNo periodic IRQ support\n"); | 204 | fprintf(stderr, "\nNo periodic IRQ support\n"); |
198 | goto done; | 205 | goto done; |
199 | } | 206 | } |
@@ -211,7 +218,7 @@ test_PIE: | |||
211 | retval = ioctl(fd, RTC_IRQP_SET, tmp); | 218 | retval = ioctl(fd, RTC_IRQP_SET, tmp); |
212 | if (retval == -1) { | 219 | if (retval == -1) { |
213 | /* not all RTCs can change their periodic IRQ rate */ | 220 | /* not all RTCs can change their periodic IRQ rate */ |
214 | if (errno == ENOTTY) { | 221 | if (errno == EINVAL) { |
215 | fprintf(stderr, | 222 | fprintf(stderr, |
216 | "\n...Periodic IRQ rate is fixed\n"); | 223 | "\n...Periodic IRQ rate is fixed\n"); |
217 | goto done; | 224 | goto done; |
diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c new file mode 100644 index 000000000000..f4184928b16b --- /dev/null +++ b/tools/testing/selftests/timers/set-tz.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* Set tz value | ||
2 | * by: John Stultz <john.stultz@linaro.org> | ||
3 | * (C) Copyright Linaro 2016 | ||
4 | * Licensed under the GPLv2 | ||
5 | * | ||
6 | * This program is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | |||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <time.h> | ||
21 | #include <sys/time.h> | ||
22 | #include <sys/timex.h> | ||
23 | #include <string.h> | ||
24 | #include <signal.h> | ||
25 | #include <unistd.h> | ||
26 | #ifdef KTEST | ||
27 | #include "../kselftest.h" | ||
28 | #else | ||
29 | static inline int ksft_exit_pass(void) | ||
30 | { | ||
31 | exit(0); | ||
32 | } | ||
33 | static inline int ksft_exit_fail(void) | ||
34 | { | ||
35 | exit(1); | ||
36 | } | ||
37 | #endif | ||
38 | |||
39 | int set_tz(int min, int dst) | ||
40 | { | ||
41 | struct timezone tz; | ||
42 | |||
43 | tz.tz_minuteswest = min; | ||
44 | tz.tz_dsttime = dst; | ||
45 | |||
46 | return settimeofday(0, &tz); | ||
47 | } | ||
48 | |||
49 | int get_tz_min(void) | ||
50 | { | ||
51 | struct timezone tz; | ||
52 | struct timeval tv; | ||
53 | |||
54 | memset(&tz, 0, sizeof(tz)); | ||
55 | gettimeofday(&tv, &tz); | ||
56 | return tz.tz_minuteswest; | ||
57 | } | ||
58 | |||
59 | int get_tz_dst(void) | ||
60 | { | ||
61 | struct timezone tz; | ||
62 | struct timeval tv; | ||
63 | |||
64 | memset(&tz, 0, sizeof(tz)); | ||
65 | gettimeofday(&tv, &tz); | ||
66 | return tz.tz_dsttime; | ||
67 | } | ||
68 | |||
69 | int main(int argc, char **argv) | ||
70 | { | ||
71 | int i, ret; | ||
72 | int min, dst; | ||
73 | |||
74 | min = get_tz_min(); | ||
75 | dst = get_tz_dst(); | ||
76 | printf("tz_minuteswest started at %i, dst at %i\n", min, dst); | ||
77 | |||
78 | printf("Checking tz_minuteswest can be properly set: "); | ||
79 | for (i = -15*60; i < 15*60; i += 30) { | ||
80 | ret = set_tz(i, dst); | ||
81 | ret = get_tz_min(); | ||
82 | if (ret != i) { | ||
83 | printf("[FAILED] expected: %i got %i\n", i, ret); | ||
84 | goto err; | ||
85 | } | ||
86 | } | ||
87 | printf("[OK]\n"); | ||
88 | |||
89 | printf("Checking invalid tz_minuteswest values are caught: "); | ||
90 | |||
91 | if (!set_tz(-15*60-1, dst)) { | ||
92 | printf("[FAILED] %i didn't return failure!\n", -15*60-1); | ||
93 | goto err; | ||
94 | } | ||
95 | |||
96 | if (!set_tz(15*60+1, dst)) { | ||
97 | printf("[FAILED] %i didn't return failure!\n", 15*60+1); | ||
98 | goto err; | ||
99 | } | ||
100 | |||
101 | if (!set_tz(-24*60, dst)) { | ||
102 | printf("[FAILED] %i didn't return failure!\n", -24*60); | ||
103 | goto err; | ||
104 | } | ||
105 | |||
106 | if (!set_tz(24*60, dst)) { | ||
107 | printf("[FAILED] %i didn't return failure!\n", 24*60); | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | printf("[OK]\n"); | ||
112 | |||
113 | set_tz(min, dst); | ||
114 | return ksft_exit_pass(); | ||
115 | |||
116 | err: | ||
117 | set_tz(min, dst); | ||
118 | return ksft_exit_fail(); | ||
119 | } | ||
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c index 00c4f65d12da..6d1437f895b8 100644 --- a/tools/testing/selftests/vm/compaction_test.c +++ b/tools/testing/selftests/vm/compaction_test.c | |||
@@ -101,7 +101,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
101 | 101 | ||
102 | /* Start with the initial condition of 0 huge pages*/ | 102 | /* Start with the initial condition of 0 huge pages*/ |
103 | if (write(fd, "0", sizeof(char)) != sizeof(char)) { | 103 | if (write(fd, "0", sizeof(char)) != sizeof(char)) { |
104 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 104 | perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n"); |
105 | goto close_fd; | 105 | goto close_fd; |
106 | } | 106 | } |
107 | 107 | ||
@@ -110,14 +110,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
110 | /* Request a large number of huge pages. The Kernel will allocate | 110 | /* Request a large number of huge pages. The Kernel will allocate |
111 | as much as it can */ | 111 | as much as it can */ |
112 | if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { | 112 | if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { |
113 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 113 | perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n"); |
114 | goto close_fd; | 114 | goto close_fd; |
115 | } | 115 | } |
116 | 116 | ||
117 | lseek(fd, 0, SEEK_SET); | 117 | lseek(fd, 0, SEEK_SET); |
118 | 118 | ||
119 | if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { | 119 | if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { |
120 | perror("Failed to read from /proc/sys/vm/nr_hugepages\n"); | 120 | perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n"); |
121 | goto close_fd; | 121 | goto close_fd; |
122 | } | 122 | } |
123 | 123 | ||
@@ -138,7 +138,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
138 | 138 | ||
139 | if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) | 139 | if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) |
140 | != strlen(initial_nr_hugepages)) { | 140 | != strlen(initial_nr_hugepages)) { |
141 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 141 | perror("Failed to write value to /proc/sys/vm/nr_hugepages\n"); |
142 | goto close_fd; | 142 | goto close_fd; |
143 | } | 143 | } |
144 | 144 | ||
diff --git a/tools/testing/selftests/vm/on-fault-limit.c b/tools/testing/selftests/vm/on-fault-limit.c index 245acccce42d..0ae458f32fdb 100644 --- a/tools/testing/selftests/vm/on-fault-limit.c +++ b/tools/testing/selftests/vm/on-fault-limit.c | |||
@@ -20,7 +20,7 @@ static int test_limit(void) | |||
20 | return ret; | 20 | return ret; |
21 | } | 21 | } |
22 | 22 | ||
23 | if (mlockall(MCL_CURRENT | MCL_ONFAULT | MCL_FUTURE)) { | 23 | if (mlockall(MCL_ONFAULT | MCL_FUTURE)) { |
24 | perror("mlockall"); | 24 | perror("mlockall"); |
25 | return ret; | 25 | return ret; |
26 | } | 26 | } |
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile index 6173adae9f08..877a8a4721b6 100644 --- a/tools/virtio/ringtest/Makefile +++ b/tools/virtio/ringtest/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | all: | 1 | all: |
2 | 2 | ||
3 | all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder noring | 3 | all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring |
4 | 4 | ||
5 | CFLAGS += -Wall | 5 | CFLAGS += -Wall |
6 | CFLAGS += -pthread -O2 -ggdb | 6 | CFLAGS += -pthread -O2 -ggdb |
@@ -8,6 +8,7 @@ LDFLAGS += -pthread -O2 -ggdb | |||
8 | 8 | ||
9 | main.o: main.c main.h | 9 | main.o: main.c main.h |
10 | ring.o: ring.c main.h | 10 | ring.o: ring.c main.h |
11 | ptr_ring.o: ptr_ring.c main.h ../../../include/linux/ptr_ring.h | ||
11 | virtio_ring_0_9.o: virtio_ring_0_9.c main.h | 12 | virtio_ring_0_9.o: virtio_ring_0_9.c main.h |
12 | virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h | 13 | virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h |
13 | virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h | 14 | virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h |
@@ -15,6 +16,7 @@ ring: ring.o main.o | |||
15 | virtio_ring_0_9: virtio_ring_0_9.o main.o | 16 | virtio_ring_0_9: virtio_ring_0_9.o main.o |
16 | virtio_ring_poll: virtio_ring_poll.o main.o | 17 | virtio_ring_poll: virtio_ring_poll.o main.o |
17 | virtio_ring_inorder: virtio_ring_inorder.o main.o | 18 | virtio_ring_inorder: virtio_ring_inorder.o main.o |
19 | ptr_ring: ptr_ring.o main.o | ||
18 | noring: noring.o main.o | 20 | noring: noring.o main.o |
19 | clean: | 21 | clean: |
20 | -rm main.o | 22 | -rm main.o |
@@ -22,6 +24,7 @@ clean: | |||
22 | -rm virtio_ring_0_9.o virtio_ring_0_9 | 24 | -rm virtio_ring_0_9.o virtio_ring_0_9 |
23 | -rm virtio_ring_poll.o virtio_ring_poll | 25 | -rm virtio_ring_poll.o virtio_ring_poll |
24 | -rm virtio_ring_inorder.o virtio_ring_inorder | 26 | -rm virtio_ring_inorder.o virtio_ring_inorder |
27 | -rm ptr_ring.o ptr_ring | ||
25 | -rm noring.o noring | 28 | -rm noring.o noring |
26 | 29 | ||
27 | .PHONY: all clean | 30 | .PHONY: all clean |
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c new file mode 100644 index 000000000000..68e4f9f0da3a --- /dev/null +++ b/tools/virtio/ringtest/ptr_ring.c | |||
@@ -0,0 +1,197 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include "main.h" | ||
3 | #include <stdlib.h> | ||
4 | #include <stdio.h> | ||
5 | #include <string.h> | ||
6 | #include <pthread.h> | ||
7 | #include <malloc.h> | ||
8 | #include <assert.h> | ||
9 | #include <errno.h> | ||
10 | #include <limits.h> | ||
11 | |||
12 | #define SMP_CACHE_BYTES 64 | ||
13 | #define cache_line_size() SMP_CACHE_BYTES | ||
14 | #define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES))) | ||
15 | #define unlikely(x) (__builtin_expect(!!(x), 0)) | ||
16 | #define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a)) | ||
17 | typedef pthread_spinlock_t spinlock_t; | ||
18 | |||
19 | typedef int gfp_t; | ||
20 | static void *kmalloc(unsigned size, gfp_t gfp) | ||
21 | { | ||
22 | return memalign(64, size); | ||
23 | } | ||
24 | |||
25 | static void *kzalloc(unsigned size, gfp_t gfp) | ||
26 | { | ||
27 | void *p = memalign(64, size); | ||
28 | if (!p) | ||
29 | return p; | ||
30 | memset(p, 0, size); | ||
31 | |||
32 | return p; | ||
33 | } | ||
34 | |||
35 | static void kfree(void *p) | ||
36 | { | ||
37 | if (p) | ||
38 | free(p); | ||
39 | } | ||
40 | |||
41 | static void spin_lock_init(spinlock_t *lock) | ||
42 | { | ||
43 | int r = pthread_spin_init(lock, 0); | ||
44 | assert(!r); | ||
45 | } | ||
46 | |||
47 | static void spin_lock(spinlock_t *lock) | ||
48 | { | ||
49 | int ret = pthread_spin_lock(lock); | ||
50 | assert(!ret); | ||
51 | } | ||
52 | |||
53 | static void spin_unlock(spinlock_t *lock) | ||
54 | { | ||
55 | int ret = pthread_spin_unlock(lock); | ||
56 | assert(!ret); | ||
57 | } | ||
58 | |||
59 | static void spin_lock_bh(spinlock_t *lock) | ||
60 | { | ||
61 | spin_lock(lock); | ||
62 | } | ||
63 | |||
64 | static void spin_unlock_bh(spinlock_t *lock) | ||
65 | { | ||
66 | spin_unlock(lock); | ||
67 | } | ||
68 | |||
69 | static void spin_lock_irq(spinlock_t *lock) | ||
70 | { | ||
71 | spin_lock(lock); | ||
72 | } | ||
73 | |||
74 | static void spin_unlock_irq(spinlock_t *lock) | ||
75 | { | ||
76 | spin_unlock(lock); | ||
77 | } | ||
78 | |||
79 | static void spin_lock_irqsave(spinlock_t *lock, unsigned long f) | ||
80 | { | ||
81 | spin_lock(lock); | ||
82 | } | ||
83 | |||
84 | static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f) | ||
85 | { | ||
86 | spin_unlock(lock); | ||
87 | } | ||
88 | |||
89 | #include "../../../include/linux/ptr_ring.h" | ||
90 | |||
91 | static unsigned long long headcnt, tailcnt; | ||
92 | static struct ptr_ring array ____cacheline_aligned_in_smp; | ||
93 | |||
94 | /* implemented by ring */ | ||
95 | void alloc_ring(void) | ||
96 | { | ||
97 | int ret = ptr_ring_init(&array, ring_size, 0); | ||
98 | assert(!ret); | ||
99 | } | ||
100 | |||
101 | /* guest side */ | ||
102 | int add_inbuf(unsigned len, void *buf, void *datap) | ||
103 | { | ||
104 | int ret; | ||
105 | |||
106 | ret = __ptr_ring_produce(&array, buf); | ||
107 | if (ret >= 0) { | ||
108 | ret = 0; | ||
109 | headcnt++; | ||
110 | } | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* | ||
116 | * ptr_ring API provides no way for producer to find out whether a given | ||
117 | * buffer was consumed. Our tests merely require that a successful get_buf | ||
118 | * implies that add_inbuf succeed in the past, and that add_inbuf will succeed, | ||
119 | * fake it accordingly. | ||
120 | */ | ||
121 | void *get_buf(unsigned *lenp, void **bufp) | ||
122 | { | ||
123 | void *datap; | ||
124 | |||
125 | if (tailcnt == headcnt || __ptr_ring_full(&array)) | ||
126 | datap = NULL; | ||
127 | else { | ||
128 | datap = "Buffer\n"; | ||
129 | ++tailcnt; | ||
130 | } | ||
131 | |||
132 | return datap; | ||
133 | } | ||
134 | |||
135 | void poll_used(void) | ||
136 | { | ||
137 | void *b; | ||
138 | |||
139 | do { | ||
140 | if (tailcnt == headcnt || __ptr_ring_full(&array)) { | ||
141 | b = NULL; | ||
142 | barrier(); | ||
143 | } else { | ||
144 | b = "Buffer\n"; | ||
145 | } | ||
146 | } while (!b); | ||
147 | } | ||
148 | |||
149 | void disable_call() | ||
150 | { | ||
151 | assert(0); | ||
152 | } | ||
153 | |||
154 | bool enable_call() | ||
155 | { | ||
156 | assert(0); | ||
157 | } | ||
158 | |||
159 | void kick_available(void) | ||
160 | { | ||
161 | assert(0); | ||
162 | } | ||
163 | |||
164 | /* host side */ | ||
165 | void disable_kick() | ||
166 | { | ||
167 | assert(0); | ||
168 | } | ||
169 | |||
170 | bool enable_kick() | ||
171 | { | ||
172 | assert(0); | ||
173 | } | ||
174 | |||
175 | void poll_avail(void) | ||
176 | { | ||
177 | void *b; | ||
178 | |||
179 | do { | ||
180 | barrier(); | ||
181 | b = __ptr_ring_peek(&array); | ||
182 | } while (!b); | ||
183 | } | ||
184 | |||
185 | bool use_buf(unsigned *lenp, void **bufp) | ||
186 | { | ||
187 | void *ptr; | ||
188 | |||
189 | ptr = __ptr_ring_consume(&array); | ||
190 | |||
191 | return ptr; | ||
192 | } | ||
193 | |||
194 | void call_used(void) | ||
195 | { | ||
196 | assert(0); | ||
197 | } | ||
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c index 77147b42d598..f1c055f3c243 100644 --- a/tools/vm/page_owner_sort.c +++ b/tools/vm/page_owner_sort.c | |||
@@ -79,12 +79,12 @@ static void add_list(char *buf, int len) | |||
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | #define BUF_SIZE 1024 | 82 | #define BUF_SIZE (128 * 1024) |
83 | 83 | ||
84 | int main(int argc, char **argv) | 84 | int main(int argc, char **argv) |
85 | { | 85 | { |
86 | FILE *fin, *fout; | 86 | FILE *fin, *fout; |
87 | char buf[BUF_SIZE]; | 87 | char *buf; |
88 | int ret, i, count; | 88 | int ret, i, count; |
89 | struct block_list *list2; | 89 | struct block_list *list2; |
90 | struct stat st; | 90 | struct stat st; |
@@ -107,6 +107,11 @@ int main(int argc, char **argv) | |||
107 | max_size = st.st_size / 100; /* hack ... */ | 107 | max_size = st.st_size / 100; /* hack ... */ |
108 | 108 | ||
109 | list = malloc(max_size * sizeof(*list)); | 109 | list = malloc(max_size * sizeof(*list)); |
110 | buf = malloc(BUF_SIZE); | ||
111 | if (!list || !buf) { | ||
112 | printf("Out of memory\n"); | ||
113 | exit(1); | ||
114 | } | ||
110 | 115 | ||
111 | for ( ; ; ) { | 116 | for ( ; ; ) { |
112 | ret = read_block(buf, BUF_SIZE, fin); | 117 | ret = read_block(buf, BUF_SIZE, fin); |