Commit 5516d670f69dafc77c936a02ff9916a9fba9fcd0
1 parent
cc6f538b
make lsl, lar verr and verw exception safe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1369 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
45 additions
and
33 deletions
target-i386/helper.c
| @@ -2335,13 +2335,13 @@ void helper_rdmsr(void) | @@ -2335,13 +2335,13 @@ void helper_rdmsr(void) | ||
| 2335 | void helper_lsl(void) | 2335 | void helper_lsl(void) |
| 2336 | { | 2336 | { |
| 2337 | unsigned int selector, limit; | 2337 | unsigned int selector, limit; |
| 2338 | - uint32_t e1, e2; | 2338 | + uint32_t e1, e2, eflags; |
| 2339 | int rpl, dpl, cpl, type; | 2339 | int rpl, dpl, cpl, type; |
| 2340 | 2340 | ||
| 2341 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | 2341 | + eflags = cc_table[CC_OP].compute_all(); |
| 2342 | selector = T0 & 0xffff; | 2342 | selector = T0 & 0xffff; |
| 2343 | if (load_segment(&e1, &e2, selector) != 0) | 2343 | if (load_segment(&e1, &e2, selector) != 0) |
| 2344 | - return; | 2344 | + goto fail; |
| 2345 | rpl = selector & 3; | 2345 | rpl = selector & 3; |
| 2346 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 2346 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 2347 | cpl = env->hflags & HF_CPL_MASK; | 2347 | cpl = env->hflags & HF_CPL_MASK; |
| @@ -2350,7 +2350,7 @@ void helper_lsl(void) | @@ -2350,7 +2350,7 @@ void helper_lsl(void) | ||
| 2350 | /* conforming */ | 2350 | /* conforming */ |
| 2351 | } else { | 2351 | } else { |
| 2352 | if (dpl < cpl || dpl < rpl) | 2352 | if (dpl < cpl || dpl < rpl) |
| 2353 | - return; | 2353 | + goto fail; |
| 2354 | } | 2354 | } |
| 2355 | } else { | 2355 | } else { |
| 2356 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; | 2356 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
| @@ -2362,28 +2362,31 @@ void helper_lsl(void) | @@ -2362,28 +2362,31 @@ void helper_lsl(void) | ||
| 2362 | case 11: | 2362 | case 11: |
| 2363 | break; | 2363 | break; |
| 2364 | default: | 2364 | default: |
| 2365 | - return; | 2365 | + goto fail; |
| 2366 | } | 2366 | } |
| 2367 | - if (dpl < cpl || dpl < rpl) | 2367 | + if (dpl < cpl || dpl < rpl) { |
| 2368 | + fail: | ||
| 2369 | + CC_SRC = eflags & ~CC_Z; | ||
| 2368 | return; | 2370 | return; |
| 2371 | + } | ||
| 2369 | } | 2372 | } |
| 2370 | limit = get_seg_limit(e1, e2); | 2373 | limit = get_seg_limit(e1, e2); |
| 2371 | T1 = limit; | 2374 | T1 = limit; |
| 2372 | - CC_SRC |= CC_Z; | 2375 | + CC_SRC = eflags | CC_Z; |
| 2373 | } | 2376 | } |
| 2374 | 2377 | ||
| 2375 | void helper_lar(void) | 2378 | void helper_lar(void) |
| 2376 | { | 2379 | { |
| 2377 | unsigned int selector; | 2380 | unsigned int selector; |
| 2378 | - uint32_t e1, e2; | 2381 | + uint32_t e1, e2, eflags; |
| 2379 | int rpl, dpl, cpl, type; | 2382 | int rpl, dpl, cpl, type; |
| 2380 | 2383 | ||
| 2381 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | 2384 | + eflags = cc_table[CC_OP].compute_all(); |
| 2382 | selector = T0 & 0xffff; | 2385 | selector = T0 & 0xffff; |
| 2383 | if ((selector & 0xfffc) == 0) | 2386 | if ((selector & 0xfffc) == 0) |
| 2384 | - return; | 2387 | + goto fail; |
| 2385 | if (load_segment(&e1, &e2, selector) != 0) | 2388 | if (load_segment(&e1, &e2, selector) != 0) |
| 2386 | - return; | 2389 | + goto fail; |
| 2387 | rpl = selector & 3; | 2390 | rpl = selector & 3; |
| 2388 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 2391 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 2389 | cpl = env->hflags & HF_CPL_MASK; | 2392 | cpl = env->hflags & HF_CPL_MASK; |
| @@ -2392,7 +2395,7 @@ void helper_lar(void) | @@ -2392,7 +2395,7 @@ void helper_lar(void) | ||
| 2392 | /* conforming */ | 2395 | /* conforming */ |
| 2393 | } else { | 2396 | } else { |
| 2394 | if (dpl < cpl || dpl < rpl) | 2397 | if (dpl < cpl || dpl < rpl) |
| 2395 | - return; | 2398 | + goto fail; |
| 2396 | } | 2399 | } |
| 2397 | } else { | 2400 | } else { |
| 2398 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; | 2401 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
| @@ -2407,72 +2410,81 @@ void helper_lar(void) | @@ -2407,72 +2410,81 @@ void helper_lar(void) | ||
| 2407 | case 12: | 2410 | case 12: |
| 2408 | break; | 2411 | break; |
| 2409 | default: | 2412 | default: |
| 2410 | - return; | 2413 | + goto fail; |
| 2411 | } | 2414 | } |
| 2412 | - if (dpl < cpl || dpl < rpl) | 2415 | + if (dpl < cpl || dpl < rpl) { |
| 2416 | + fail: | ||
| 2417 | + CC_SRC = eflags & ~CC_Z; | ||
| 2413 | return; | 2418 | return; |
| 2419 | + } | ||
| 2414 | } | 2420 | } |
| 2415 | T1 = e2 & 0x00f0ff00; | 2421 | T1 = e2 & 0x00f0ff00; |
| 2416 | - CC_SRC |= CC_Z; | 2422 | + CC_SRC = eflags | CC_Z; |
| 2417 | } | 2423 | } |
| 2418 | 2424 | ||
| 2419 | void helper_verr(void) | 2425 | void helper_verr(void) |
| 2420 | { | 2426 | { |
| 2421 | unsigned int selector; | 2427 | unsigned int selector; |
| 2422 | - uint32_t e1, e2; | 2428 | + uint32_t e1, e2, eflags; |
| 2423 | int rpl, dpl, cpl; | 2429 | int rpl, dpl, cpl; |
| 2424 | 2430 | ||
| 2425 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | 2431 | + eflags = cc_table[CC_OP].compute_all(); |
| 2426 | selector = T0 & 0xffff; | 2432 | selector = T0 & 0xffff; |
| 2427 | if ((selector & 0xfffc) == 0) | 2433 | if ((selector & 0xfffc) == 0) |
| 2428 | - return; | 2434 | + goto fail; |
| 2429 | if (load_segment(&e1, &e2, selector) != 0) | 2435 | if (load_segment(&e1, &e2, selector) != 0) |
| 2430 | - return; | 2436 | + goto fail; |
| 2431 | if (!(e2 & DESC_S_MASK)) | 2437 | if (!(e2 & DESC_S_MASK)) |
| 2432 | - return; | 2438 | + goto fail; |
| 2433 | rpl = selector & 3; | 2439 | rpl = selector & 3; |
| 2434 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 2440 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 2435 | cpl = env->hflags & HF_CPL_MASK; | 2441 | cpl = env->hflags & HF_CPL_MASK; |
| 2436 | if (e2 & DESC_CS_MASK) { | 2442 | if (e2 & DESC_CS_MASK) { |
| 2437 | if (!(e2 & DESC_R_MASK)) | 2443 | if (!(e2 & DESC_R_MASK)) |
| 2438 | - return; | 2444 | + goto fail; |
| 2439 | if (!(e2 & DESC_C_MASK)) { | 2445 | if (!(e2 & DESC_C_MASK)) { |
| 2440 | if (dpl < cpl || dpl < rpl) | 2446 | if (dpl < cpl || dpl < rpl) |
| 2441 | - return; | 2447 | + goto fail; |
| 2442 | } | 2448 | } |
| 2443 | } else { | 2449 | } else { |
| 2444 | - if (dpl < cpl || dpl < rpl) | 2450 | + if (dpl < cpl || dpl < rpl) { |
| 2451 | + fail: | ||
| 2452 | + CC_SRC = eflags & ~CC_Z; | ||
| 2445 | return; | 2453 | return; |
| 2454 | + } | ||
| 2446 | } | 2455 | } |
| 2447 | - CC_SRC |= CC_Z; | 2456 | + CC_SRC = eflags | CC_Z; |
| 2448 | } | 2457 | } |
| 2449 | 2458 | ||
| 2450 | void helper_verw(void) | 2459 | void helper_verw(void) |
| 2451 | { | 2460 | { |
| 2452 | unsigned int selector; | 2461 | unsigned int selector; |
| 2453 | - uint32_t e1, e2; | 2462 | + uint32_t e1, e2, eflags; |
| 2454 | int rpl, dpl, cpl; | 2463 | int rpl, dpl, cpl; |
| 2455 | 2464 | ||
| 2456 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | 2465 | + eflags = cc_table[CC_OP].compute_all(); |
| 2457 | selector = T0 & 0xffff; | 2466 | selector = T0 & 0xffff; |
| 2458 | if ((selector & 0xfffc) == 0) | 2467 | if ((selector & 0xfffc) == 0) |
| 2459 | - return; | 2468 | + goto fail; |
| 2460 | if (load_segment(&e1, &e2, selector) != 0) | 2469 | if (load_segment(&e1, &e2, selector) != 0) |
| 2461 | - return; | 2470 | + goto fail; |
| 2462 | if (!(e2 & DESC_S_MASK)) | 2471 | if (!(e2 & DESC_S_MASK)) |
| 2463 | - return; | 2472 | + goto fail; |
| 2464 | rpl = selector & 3; | 2473 | rpl = selector & 3; |
| 2465 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; | 2474 | dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
| 2466 | cpl = env->hflags & HF_CPL_MASK; | 2475 | cpl = env->hflags & HF_CPL_MASK; |
| 2467 | if (e2 & DESC_CS_MASK) { | 2476 | if (e2 & DESC_CS_MASK) { |
| 2468 | - return; | 2477 | + goto fail; |
| 2469 | } else { | 2478 | } else { |
| 2470 | if (dpl < cpl || dpl < rpl) | 2479 | if (dpl < cpl || dpl < rpl) |
| 2480 | + goto fail; | ||
| 2481 | + if (!(e2 & DESC_W_MASK)) { | ||
| 2482 | + fail: | ||
| 2483 | + CC_SRC = eflags & ~CC_Z; | ||
| 2471 | return; | 2484 | return; |
| 2472 | - if (!(e2 & DESC_W_MASK)) | ||
| 2473 | - return; | 2485 | + } |
| 2474 | } | 2486 | } |
| 2475 | - CC_SRC |= CC_Z; | 2487 | + CC_SRC = eflags | CC_Z; |
| 2476 | } | 2488 | } |
| 2477 | 2489 | ||
| 2478 | /* FPU helpers */ | 2490 | /* FPU helpers */ |