OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
8 #include <windows.h> | 8 #include <windows.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 #endif | 47 #endif |
48 | 48 |
49 #if defined(OS_LINUX) | 49 #if defined(OS_LINUX) |
50 #include "content/public/common/sandbox_init.h" | 50 #include "content/public/common/sandbox_init.h" |
51 #endif | 51 #endif |
52 | 52 |
53 const int kGpuTimeout = 10000; | 53 const int kGpuTimeout = 10000; |
54 | 54 |
55 namespace content { | 55 namespace content { |
56 namespace { | 56 namespace { |
57 void WarmUpSandbox(const GPUInfo&, bool); | 57 void WarmUpSandbox(); |
58 #if defined(OS_LINUX) | |
59 bool StartSandboxLinux(const GPUInfo&, GpuWatchdogThread*, bool); | |
60 #elif defined(OS_WIN) | |
61 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo*); | |
62 #endif | |
58 } | 63 } |
59 | 64 |
60 // Main function for starting the Gpu process. | 65 // Main function for starting the Gpu process. |
61 int GpuMain(const MainFunctionParams& parameters) { | 66 int GpuMain(const MainFunctionParams& parameters) { |
62 TRACE_EVENT0("gpu", "GpuMain"); | 67 TRACE_EVENT0("gpu", "GpuMain"); |
63 | 68 |
64 base::Time start_time = base::Time::Now(); | 69 base::Time start_time = base::Time::Now(); |
65 | 70 |
66 const CommandLine& command_line = parameters.command_line; | 71 const CommandLine& command_line = parameters.command_line; |
67 if (command_line.HasSwitch(switches::kGpuStartupDialog)) { | 72 if (command_line.HasSwitch(switches::kGpuStartupDialog)) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 success = base::HexStringToInt( | 168 success = base::HexStringToInt( |
164 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), | 169 command_line.GetSwitchValueASCII(switches::kGpuDeviceID), |
165 reinterpret_cast<int*>(&(gpu_info.gpu.device_id))); | 170 reinterpret_cast<int*>(&(gpu_info.gpu.device_id))); |
166 DCHECK(success); | 171 DCHECK(success); |
167 gpu_info.driver_vendor = | 172 gpu_info.driver_vendor = |
168 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); | 173 command_line.GetSwitchValueASCII(switches::kGpuDriverVendor); |
169 gpu_info.driver_version = | 174 gpu_info.driver_version = |
170 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); | 175 command_line.GetSwitchValueASCII(switches::kGpuDriverVersion); |
171 GetContentClient()->SetGpuInfo(gpu_info); | 176 GetContentClient()->SetGpuInfo(gpu_info); |
172 | 177 |
173 // We need to track that information for the WarmUpSandbox function. | 178 // Warm up resources that don't need access to GPUInfo. |
179 WarmUpSandbox(); | |
180 | |
181 #if defined(OS_LINUX) | |
182 bool initialized_sandbox = false; | |
174 bool initialized_gl_context = false; | 183 bool initialized_gl_context = false; |
184 bool should_initialize_gl_context = false; | |
185 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(NDEBUG) | |
piman
2013/04/17 17:45:41
I don't think we should make this depend on NDEBUG
Jorge Lucangeli Obes
2013/04/17 17:49:50
Done.
| |
186 // On Chrome OS ARM, GPU driver userspace creates threads when initializing | |
187 // a GL context, so start the sandbox early. | |
188 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(), | |
189 should_initialize_gl_context); | |
190 initialized_sandbox = true; | |
191 #endif | |
192 #endif // defined(OS_LINUX) | |
193 | |
175 // Load and initialize the GL implementation and locate the GL entry points. | 194 // Load and initialize the GL implementation and locate the GL entry points. |
176 if (gfx::GLSurface::InitializeOneOff()) { | 195 if (gfx::GLSurface::InitializeOneOff()) { |
177 // We need to collect GL strings (VENDOR, RENDERER) for blacklisting | 196 // We need to collect GL strings (VENDOR, RENDERER) for blacklisting |
178 // purpose. However, on Mac we don't actually use them. As documented in | 197 // purposes. However, on Mac we don't actually use them. As documented in |
179 // crbug.com/222934, due to some driver issues, glGetString could take | 198 // crbug.com/222934, due to some driver issues, glGetString could take |
180 // multiple seconds to finish, which in turn cause the GPU process to crash. | 199 // multiple seconds to finish, which in turn cause the GPU process to crash. |
181 // By skipping the following code on Mac, we don't really lose anything, | 200 // By skipping the following code on Mac, we don't really lose anything, |
182 // because the basic GPU information is passed down from browser process | 201 // because the basic GPU information is passed down from browser process |
183 // and we already registered them through SetGpuInfo() above. | 202 // and we already registered them through SetGpuInfo() above. |
184 #if !defined(OS_MACOSX) | 203 #if !defined(OS_MACOSX) |
185 if (!gpu_info_collector::CollectContextGraphicsInfo(&gpu_info)) | 204 if (!gpu_info_collector::CollectContextGraphicsInfo(&gpu_info)) |
186 VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed"; | 205 VLOG(1) << "gpu_info_collector::CollectGraphicsInfo failed"; |
187 GetContentClient()->SetGpuInfo(gpu_info); | 206 GetContentClient()->SetGpuInfo(gpu_info); |
188 | 207 |
189 // We know that CollectGraphicsInfo will initialize a GLContext. | 208 #if defined(OS_LINUX) |
190 initialized_gl_context = true; | 209 initialized_gl_context = true; |
191 | 210 #if !defined(OS_CHROMEOS) |
192 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
193 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA | 211 if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA |
194 gpu_info.driver_vendor == "NVIDIA") { | 212 gpu_info.driver_vendor == "NVIDIA") { |
195 base::ThreadRestrictions::AssertIOAllowed(); | 213 base::ThreadRestrictions::AssertIOAllowed(); |
196 if (access("/dev/nvidiactl", R_OK) != 0) { | 214 if (access("/dev/nvidiactl", R_OK) != 0) { |
197 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; | 215 VLOG(1) << "NVIDIA device file /dev/nvidiactl access denied"; |
198 gpu_info.gpu_accessible = false; | 216 gpu_info.gpu_accessible = false; |
199 dead_on_arrival = true; | 217 dead_on_arrival = true; |
200 } | 218 } |
201 } | 219 } |
202 #endif // OS_CHROMEOS | 220 #endif // !defined(OS_CHROMEOS) |
203 #endif // OS_MACOSX | 221 #endif // defined(OS_LINUX) |
222 #endif // !defined(OS_MACOSX) | |
204 } else { | 223 } else { |
205 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; | 224 VLOG(1) << "gfx::GLSurface::InitializeOneOff failed"; |
206 gpu_info.gpu_accessible = false; | 225 gpu_info.gpu_accessible = false; |
207 gpu_info.finalized = true; | 226 gpu_info.finalized = true; |
208 dead_on_arrival = true; | 227 dead_on_arrival = true; |
209 } | 228 } |
210 | 229 |
211 if (enable_watchdog && delayed_watchdog_enable) { | 230 if (enable_watchdog && delayed_watchdog_enable) { |
212 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); | 231 watchdog_thread = new GpuWatchdogThread(kGpuTimeout); |
213 watchdog_thread->Start(); | 232 watchdog_thread->Start(); |
214 } | 233 } |
215 | 234 |
216 // OSMesa is expected to run very slowly, so disable the watchdog in that | 235 // OSMesa is expected to run very slowly, so disable the watchdog in that |
217 // case. | 236 // case. |
218 if (enable_watchdog && | 237 if (enable_watchdog && |
219 gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) { | 238 gfx::GetGLImplementation() == gfx::kGLImplementationOSMesaGL) { |
220 watchdog_thread->Stop(); | 239 watchdog_thread->Stop(); |
221 | 240 |
222 watchdog_thread = NULL; | 241 watchdog_thread = NULL; |
223 } | 242 } |
224 | 243 |
225 { | 244 #if defined(OS_LINUX) |
226 const bool should_initialize_gl_context = !initialized_gl_context && | 245 should_initialize_gl_context = !initialized_gl_context && |
227 !dead_on_arrival; | 246 !dead_on_arrival; |
228 // Warm up the current process before enabling the sandbox. | |
229 WarmUpSandbox(gpu_info, should_initialize_gl_context); | |
230 } | |
231 | 247 |
232 #if defined(OS_LINUX) | 248 if (!initialized_sandbox) |
233 { | 249 gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(), |
234 TRACE_EVENT0("gpu", "Initialize sandbox"); | 250 should_initialize_gl_context); |
235 bool do_init_sandbox = true; | 251 #elif defined(OS_WIN) |
236 | 252 gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info); |
237 #if defined(OS_CHROMEOS) && defined(NDEBUG) | |
238 // On Chrome OS and when not on a debug build, initialize | |
239 // the GPU process' sandbox only for Intel GPUs. | |
240 do_init_sandbox = gpu_info.gpu.vendor_id == 0x8086; // Intel GPU. | |
241 #endif | |
242 | |
243 if (do_init_sandbox) { | |
244 if (watchdog_thread.get()) | |
245 watchdog_thread->Stop(); | |
246 gpu_info.sandboxed = LinuxSandbox::InitializeSandbox(); | |
247 if (watchdog_thread.get()) | |
248 watchdog_thread->Start(); | |
249 } | |
250 } | |
251 #endif | |
252 | |
253 #if defined(OS_WIN) | |
254 { | |
255 TRACE_EVENT0("gpu", "Lower token"); | |
256 // For windows, if the target_services interface is not zero, the process | |
257 // is sandboxed and we must call LowerToken() before rendering untrusted | |
258 // content. | |
259 sandbox::TargetServices* target_services = | |
260 parameters.sandbox_info->target_services; | |
261 if (target_services) { | |
262 target_services->LowerToken(); | |
263 gpu_info.sandboxed = true; | |
264 } | |
265 } | |
266 #endif | 253 #endif |
267 | 254 |
268 GpuProcess gpu_process; | 255 GpuProcess gpu_process; |
269 | 256 |
270 GpuChildThread* child_thread = new GpuChildThread(watchdog_thread.get(), | 257 GpuChildThread* child_thread = new GpuChildThread(watchdog_thread.get(), |
271 dead_on_arrival, gpu_info); | 258 dead_on_arrival, gpu_info); |
272 | 259 |
273 child_thread->Init(start_time); | 260 child_thread->Init(start_time); |
274 | 261 |
275 gpu_process.set_main_thread(child_thread); | 262 gpu_process.set_main_thread(child_thread); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
308 | 295 |
309 // Similarly, this is needed for /dev/nvidia0. | 296 // Similarly, this is needed for /dev/nvidia0. |
310 if (context->MakeCurrent(surface)) { | 297 if (context->MakeCurrent(surface)) { |
311 context->ReleaseCurrent(surface.get()); | 298 context->ReleaseCurrent(surface.get()); |
312 } else { | 299 } else { |
313 VLOG(1) << "gfx::GLContext::MakeCurrent failed"; | 300 VLOG(1) << "gfx::GLContext::MakeCurrent failed"; |
314 } | 301 } |
315 } | 302 } |
316 #endif | 303 #endif |
317 | 304 |
318 void WarmUpSandbox(const GPUInfo& gpu_info, | 305 void WarmUpSandbox() { |
319 bool should_initialize_gl_context) { | |
320 { | 306 { |
321 TRACE_EVENT0("gpu", "Warm up rand"); | 307 TRACE_EVENT0("gpu", "Warm up rand"); |
322 // Warm up the random subsystem, which needs to be done pre-sandbox on all | 308 // Warm up the random subsystem, which needs to be done pre-sandbox on all |
323 // platforms. | 309 // platforms. |
324 (void) base::RandUint64(); | 310 (void) base::RandUint64(); |
325 } | 311 } |
326 { | 312 { |
327 TRACE_EVENT0("gpu", "Warm up HMAC"); | 313 TRACE_EVENT0("gpu", "Warm up HMAC"); |
328 // Warm up the crypto subsystem, which needs to done pre-sandbox on all | 314 // Warm up the crypto subsystem, which needs to done pre-sandbox on all |
329 // platforms. | 315 // platforms. |
330 crypto::HMAC hmac(crypto::HMAC::SHA256); | 316 crypto::HMAC hmac(crypto::HMAC::SHA256); |
331 unsigned char key = '\0'; | 317 unsigned char key = '\0'; |
332 bool ret = hmac.Init(&key, sizeof(key)); | 318 bool ret = hmac.Init(&key, sizeof(key)); |
333 (void) ret; | 319 (void) ret; |
334 } | 320 } |
335 | 321 |
336 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) | 322 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11) |
337 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseExynosVda)) | 323 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseExynosVda)) |
338 ExynosVideoDecodeAccelerator::PreSandboxInitialization(); | 324 ExynosVideoDecodeAccelerator::PreSandboxInitialization(); |
339 else | 325 else |
340 OmxVideoDecodeAccelerator::PreSandboxInitialization(); | 326 OmxVideoDecodeAccelerator::PreSandboxInitialization(); |
341 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 327 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
342 VaapiVideoDecodeAccelerator::PreSandboxInitialization(); | 328 VaapiVideoDecodeAccelerator::PreSandboxInitialization(); |
343 #endif | 329 #endif |
344 | 330 |
345 #if defined(OS_LINUX) | |
346 // We special case Optimus since the vendor_id we see may not be Nvidia. | |
347 bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA. | |
348 gpu_info.driver_vendor == "NVIDIA") || | |
349 gpu_info.optimus; | |
350 if (uses_nvidia_driver && should_initialize_gl_context) { | |
351 // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. | |
352 CreateDummyGlContext(); | |
353 } | |
354 #endif | |
355 | |
356 #if defined(OS_WIN) | 331 #if defined(OS_WIN) |
357 { | 332 { |
358 TRACE_EVENT0("gpu", "Preload setupapi.dll"); | 333 TRACE_EVENT0("gpu", "Preload setupapi.dll"); |
359 // Preload this DLL because the sandbox prevents it from loading. | 334 // Preload this DLL because the sandbox prevents it from loading. |
360 LoadLibrary(L"setupapi.dll"); | 335 LoadLibrary(L"setupapi.dll"); |
361 } | 336 } |
362 | 337 |
363 { | 338 { |
364 TRACE_EVENT0("gpu", "Initialize DXVA"); | 339 TRACE_EVENT0("gpu", "Initialize DXVA"); |
365 // Initialize H/W video decoding stuff which fails in the sandbox. | 340 // Initialize H/W video decoding stuff which fails in the sandbox. |
366 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); | 341 DXVAVideoDecodeAccelerator::PreSandboxInitialization(); |
367 } | 342 } |
368 #endif | 343 #endif |
369 } | 344 } |
370 | 345 |
346 #if defined(OS_LINUX) | |
347 void WarmUpSandboxNvidia(const GPUInfo& gpu_info, | |
348 bool should_initialize_gl_context) { | |
349 // We special case Optimus since the vendor_id we see may not be Nvidia. | |
350 bool uses_nvidia_driver = (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA. | |
351 gpu_info.driver_vendor == "NVIDIA") || | |
352 gpu_info.optimus; | |
353 if (uses_nvidia_driver && should_initialize_gl_context) { | |
354 // We need this on Nvidia to pre-open /dev/nvidiactl and /dev/nvidia0. | |
355 CreateDummyGlContext(); | |
356 } | |
357 } | |
358 | |
359 bool StartSandboxLinux(const GPUInfo& gpu_info, | |
360 GpuWatchdogThread* watchdog_thread, | |
361 bool should_initialize_gl_context) { | |
362 TRACE_EVENT0("gpu", "Initialize sandbox"); | |
363 | |
364 bool res = false; | |
365 | |
366 WarmUpSandboxNvidia(gpu_info, should_initialize_gl_context); | |
367 | |
368 if (watchdog_thread) | |
369 watchdog_thread->Stop(); | |
370 // LinuxSandbox::InitializeSandbox() must always be called | |
371 // with only one thread. | |
372 res = LinuxSandbox::InitializeSandbox(); | |
373 if (watchdog_thread) | |
374 watchdog_thread->Start(); | |
375 | |
376 return res; | |
377 } | |
378 #endif // defined(OS_LINUX) | |
379 | |
380 #if defined(OS_WIN) | |
381 bool StartSandboxWindows(const sandbox::SandboxInterfaceInfo* sandbox_info) { | |
382 TRACE_EVENT0("gpu", "Lower token"); | |
383 | |
384 // For Windows, if the target_services interface is not zero, the process | |
385 // is sandboxed and we must call LowerToken() before rendering untrusted | |
386 // content. | |
387 sandbox::TargetServices* target_services = sandbox_info->target_services; | |
388 if (target_services) { | |
389 target_services->LowerToken(); | |
390 return true; | |
391 } | |
392 | |
393 return false; | |
394 } | |
395 #endif // defined(OS_WIN) | |
396 | |
371 } // namespace. | 397 } // namespace. |
372 | 398 |
373 } // namespace content | 399 } // namespace content |
OLD | NEW |