summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDrew Richardson2013-12-17 17:40:56 -0600
committerJon Medhurst2013-12-18 13:03:26 -0600
commit1de4a819a058e09019bffbd51b26dffc13d81ee1 (patch)
treef2894cb297e9bb8e4d1f65d8c061eafdf84624fd
parentc3fc2b13fd58f1f5db521a062f0bbf782874383c (diff)
downloadarm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.tar.gz
arm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.tar.xz
arm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.zip
gator-driver: Handle task struct correctly
Use put_task_struct/get_task_struct to ensure the task_struct pointer is still valid. Change translate_buffer to ensure that both arguments are written atomically. Drop additional requests if the translate_buffer is full. Signed-off-by: Drew Richardson <drew.richardson@arm.com> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
-rw-r--r--driver/gator_cookies.c74
-rw-r--r--driver/gator_iks.c2
2 files changed, 52 insertions, 24 deletions
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 91adfdd..eb9b946 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -15,13 +15,18 @@
15static uint32_t *gator_crc32_table; 15static uint32_t *gator_crc32_table;
16static unsigned int translate_buffer_mask; 16static unsigned int translate_buffer_mask;
17 17
18struct cookie_args {
19 struct task_struct *task;
20 const char *text;
21};
22
18static DEFINE_PER_CPU(char *, translate_text); 23static DEFINE_PER_CPU(char *, translate_text);
19static DEFINE_PER_CPU(uint32_t, cookie_next_key); 24static DEFINE_PER_CPU(uint32_t, cookie_next_key);
20static DEFINE_PER_CPU(uint64_t *, cookie_keys); 25static DEFINE_PER_CPU(uint64_t *, cookie_keys);
21static DEFINE_PER_CPU(uint32_t *, cookie_values); 26static DEFINE_PER_CPU(uint32_t *, cookie_values);
22static DEFINE_PER_CPU(int, translate_buffer_read); 27static DEFINE_PER_CPU(int, translate_buffer_read);
23static DEFINE_PER_CPU(int, translate_buffer_write); 28static DEFINE_PER_CPU(int, translate_buffer_write);
24static DEFINE_PER_CPU(void **, translate_buffer); 29static DEFINE_PER_CPU(struct cookie_args *, translate_buffer);
25 30
26static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); 31static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq);
27static void wq_cookie_handler(struct work_struct *unused); 32static void wq_cookie_handler(struct work_struct *unused);
@@ -109,36 +114,58 @@ static void cookiemap_add(uint64_t key, uint32_t value)
109} 114}
110 115
111#ifndef CONFIG_PREEMPT_RT_FULL 116#ifndef CONFIG_PREEMPT_RT_FULL
112static void translate_buffer_write_ptr(int cpu, void *x) 117static void translate_buffer_write_args(int cpu, struct task_struct *task, const char *text)
113{ 118{
114 per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; 119 unsigned long flags;
115 per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; 120 int write;
121 int next_write;
122 struct cookie_args *args;
123
124 local_irq_save(flags);
125
126 write = per_cpu(translate_buffer_write, cpu);
127 next_write = (write + 1) & translate_buffer_mask;
128
129 // At least one entry must always remain available as when read == write, the queue is empty not full
130 if (next_write != per_cpu(translate_buffer_read, cpu)) {
131 args = &per_cpu(translate_buffer, cpu)[write];
132 args->task = task;
133 args->text = text;
134 get_task_struct(task);
135 per_cpu(translate_buffer_write, cpu) = next_write;
136 }
137
138 local_irq_restore(flags);
116} 139}
117#endif 140#endif
118 141
119static void *translate_buffer_read_ptr(int cpu) 142static void translate_buffer_read_args(int cpu, struct cookie_args *args)
120{ 143{
121 void *value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; 144 unsigned long flags;
122 per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; 145 int read;
123 return value; 146
147 local_irq_save(flags);
148
149 read = per_cpu(translate_buffer_read, cpu);
150 *args = per_cpu(translate_buffer, cpu)[read];
151 per_cpu(translate_buffer_read, cpu) = (read + 1) & translate_buffer_mask;
152
153 local_irq_restore(flags);
124} 154}
125 155
126static void wq_cookie_handler(struct work_struct *unused) 156static void wq_cookie_handler(struct work_struct *unused)
127{ 157{
128 struct task_struct *task; 158 struct cookie_args args;
129 char *text;
130 int cpu = get_physical_cpu(), cookie; 159 int cpu = get_physical_cpu(), cookie;
131 unsigned int commit;
132 160
133 mutex_lock(&start_mutex); 161 mutex_lock(&start_mutex);
134 162
135 if (gator_started != 0) { 163 if (gator_started != 0) {
136 commit = per_cpu(translate_buffer_write, cpu); 164 while (per_cpu(translate_buffer_read, cpu) != per_cpu(translate_buffer_write, cpu)) {
137 while (per_cpu(translate_buffer_read, cpu) != commit) { 165 translate_buffer_read_args(cpu, &args);
138 task = (struct task_struct *)translate_buffer_read_ptr(cpu); 166 cookie = get_cookie(cpu, args.task, args.text, true);
139 text = (char *)translate_buffer_read_ptr(cpu); 167 marshal_link(cookie, args.task->tgid, args.task->pid);
140 cookie = get_cookie(cpu, task, text, true); 168 put_task_struct(args.task);
141 marshal_link(cookie, task->tgid, task->pid);
142 } 169 }
143 } 170 }
144 171
@@ -169,15 +196,14 @@ static int translate_app_process(const char **text, int cpu, struct task_struct
169 // inconsistent during a context switch between android/linux versions 196 // inconsistent during a context switch between android/linux versions
170 if (!from_wq) { 197 if (!from_wq) {
171 // Check if already in buffer 198 // Check if already in buffer
172 int ptr = per_cpu(translate_buffer_read, cpu); 199 int pos = per_cpu(translate_buffer_read, cpu);
173 while (ptr != per_cpu(translate_buffer_write, cpu)) { 200 while (pos != per_cpu(translate_buffer_write, cpu)) {
174 if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task) 201 if (per_cpu(translate_buffer, cpu)[pos].task == task)
175 goto out; 202 goto out;
176 ptr = (ptr + 2) & translate_buffer_mask; 203 pos = (pos + 1) & translate_buffer_mask;
177 } 204 }
178 205
179 translate_buffer_write_ptr(cpu, (void *)task); 206 translate_buffer_write_args(cpu, task, *text);
180 translate_buffer_write_ptr(cpu, (void *)*text);
181 207
182 // Not safe to call in RT-Preempt full in schedule switch context 208 // Not safe to call in RT-Preempt full in schedule switch context
183 mod_timer(&app_process_wake_up_timer, jiffies + 1); 209 mod_timer(&app_process_wake_up_timer, jiffies + 1);
@@ -340,7 +366,7 @@ static int cookies_initialize(void)
340 } 366 }
341 memset(per_cpu(cookie_values, cpu), 0, size); 367 memset(per_cpu(cookie_values, cpu), 0, size);
342 368
343 per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); 369 per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL);
344 if (!per_cpu(translate_buffer, cpu)) { 370 if (!per_cpu(translate_buffer, cpu)) {
345 err = -ENOMEM; 371 err = -ENOMEM;
346 goto cookie_setup_error; 372 goto cookie_setup_error;
diff --git a/driver/gator_iks.c b/driver/gator_iks.c
index 24233d7..0a90bdd 100644
--- a/driver/gator_iks.c
+++ b/driver/gator_iks.c
@@ -147,11 +147,13 @@ static void gator_send_iks_core_names(void)
147{ 147{
148 int cpu; 148 int cpu;
149 // Send the cpu names 149 // Send the cpu names
150 preempt_disable();
150 for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { 151 for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
151 if (mpidr_cpus[cpu] != NULL) { 152 if (mpidr_cpus[cpu] != NULL) {
152 gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); 153 gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]);
153 } 154 }
154 } 155 }
156 preempt_enable();
155} 157}
156 158
157static int gator_migrate_start(void) 159static int gator_migrate_start(void)