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 */ |