Revision 3b21e03e target-i386/helper.c

b/target-i386/helper.c
1215 1215
    raise_interrupt(exception_index, 0, 0, 0);
1216 1216
}
1217 1217

  
1218
/* SMM support */
1219

  
1220
#ifdef TARGET_X86_64
1221
#define SMM_REVISION_ID 0x00020064
1222
#else
1223
#define SMM_REVISION_ID 0x00020000
1224
#endif
1225

  
1226
void do_smm_enter(void)
1227
{
1228
    target_ulong sm_state;
1229
    SegmentCache *dt;
1230
    int i, offset;
1231

  
1232
    if (loglevel & CPU_LOG_INT) {
1233
        fprintf(logfile, "SMM: enter\n");
1234
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1235
    }
1236

  
1237
    env->hflags |= HF_SMM_MASK;
1238
    cpu_smm_update(env);
1239

  
1240
    sm_state = env->smbase + 0x8000;
1241
    
1242
#ifdef TARGET_X86_64
1243
    for(i = 0; i < 6; i++) {
1244
        dt = &env->segs[i];
1245
        offset = 0x7e00 + i * 16;
1246
        stw_phys(sm_state + offset, dt->selector);
1247
        stw_phys(sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff);
1248
        stl_phys(sm_state + offset + 4, dt->limit);
1249
        stq_phys(sm_state + offset + 8, dt->base);
1250
    }
1251

  
1252
    stq_phys(sm_state + 0x7e68, env->gdt.base);
1253
    stl_phys(sm_state + 0x7e64, env->gdt.limit);
1254

  
1255
    stw_phys(sm_state + 0x7e70, env->ldt.selector);
1256
    stq_phys(sm_state + 0x7e78, env->ldt.base);
1257
    stl_phys(sm_state + 0x7e74, env->ldt.limit);
1258
    stw_phys(sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff);
1259
    
1260
    stq_phys(sm_state + 0x7e88, env->idt.base);
1261
    stl_phys(sm_state + 0x7e84, env->idt.limit);
1262

  
1263
    stw_phys(sm_state + 0x7e90, env->tr.selector);
1264
    stq_phys(sm_state + 0x7e98, env->tr.base);
1265
    stl_phys(sm_state + 0x7e94, env->tr.limit);
1266
    stw_phys(sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff);
1267
    
1268
    stq_phys(sm_state + 0x7ed0, env->efer);
1269

  
1270
    stq_phys(sm_state + 0x7ff8, EAX);
1271
    stq_phys(sm_state + 0x7ff0, ECX);
1272
    stq_phys(sm_state + 0x7fe8, EDX);
1273
    stq_phys(sm_state + 0x7fe0, EBX);
1274
    stq_phys(sm_state + 0x7fd8, ESP);
1275
    stq_phys(sm_state + 0x7fd0, EBP);
1276
    stq_phys(sm_state + 0x7fc8, ESI);
1277
    stq_phys(sm_state + 0x7fc0, EDI);
1278
    for(i = 8; i < 16; i++) 
1279
        stq_phys(sm_state + 0x7ff8 - i * 8, env->regs[i]);
1280
    stq_phys(sm_state + 0x7f78, env->eip);
1281
    stl_phys(sm_state + 0x7f70, compute_eflags());
1282
    stl_phys(sm_state + 0x7f68, env->dr[6]);
1283
    stl_phys(sm_state + 0x7f60, env->dr[7]);
1284

  
1285
    stl_phys(sm_state + 0x7f48, env->cr[4]);
1286
    stl_phys(sm_state + 0x7f50, env->cr[3]);
1287
    stl_phys(sm_state + 0x7f58, env->cr[0]);
1288

  
1289
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1290
    stl_phys(sm_state + 0x7f00, env->smbase);
1291
#else
1292
    stl_phys(sm_state + 0x7ffc, env->cr[0]);
1293
    stl_phys(sm_state + 0x7ff8, env->cr[3]);
1294
    stl_phys(sm_state + 0x7ff4, compute_eflags());
1295
    stl_phys(sm_state + 0x7ff0, env->eip);
1296
    stl_phys(sm_state + 0x7fec, EDI);
1297
    stl_phys(sm_state + 0x7fe8, ESI);
1298
    stl_phys(sm_state + 0x7fe4, EBP);
1299
    stl_phys(sm_state + 0x7fe0, ESP);
1300
    stl_phys(sm_state + 0x7fdc, EBX);
1301
    stl_phys(sm_state + 0x7fd8, EDX);
1302
    stl_phys(sm_state + 0x7fd4, ECX);
1303
    stl_phys(sm_state + 0x7fd0, EAX);
1304
    stl_phys(sm_state + 0x7fcc, env->dr[6]);
1305
    stl_phys(sm_state + 0x7fc8, env->dr[7]);
1306
    
1307
    stl_phys(sm_state + 0x7fc4, env->tr.selector);
1308
    stl_phys(sm_state + 0x7f64, env->tr.base);
1309
    stl_phys(sm_state + 0x7f60, env->tr.limit);
1310
    stl_phys(sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff);
1311
    
1312
    stl_phys(sm_state + 0x7fc0, env->ldt.selector);
1313
    stl_phys(sm_state + 0x7f80, env->ldt.base);
1314
    stl_phys(sm_state + 0x7f7c, env->ldt.limit);
1315
    stl_phys(sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff);
1316
    
1317
    stl_phys(sm_state + 0x7f74, env->gdt.base);
1318
    stl_phys(sm_state + 0x7f70, env->gdt.limit);
1319

  
1320
    stl_phys(sm_state + 0x7f58, env->idt.base);
1321
    stl_phys(sm_state + 0x7f54, env->idt.limit);
1322

  
1323
    for(i = 0; i < 6; i++) {
1324
        dt = &env->segs[i];
1325
        if (i < 3)
1326
            offset = 0x7f84 + i * 12;
1327
        else
1328
            offset = 0x7f2c + (i - 3) * 12;
1329
        stl_phys(sm_state + 0x7fa8 + i * 4, dt->selector);
1330
        stl_phys(sm_state + offset + 8, dt->base);
1331
        stl_phys(sm_state + offset + 4, dt->limit);
1332
        stl_phys(sm_state + offset, (dt->flags >> 8) & 0xf0ff);
1333
    }
1334
    stl_phys(sm_state + 0x7f14, env->cr[4]);
1335

  
1336
    stl_phys(sm_state + 0x7efc, SMM_REVISION_ID);
1337
    stl_phys(sm_state + 0x7ef8, env->smbase);
1338
#endif
1339
    /* init SMM cpu state */
1340

  
1341
    load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1342
    env->eip = 0x00008000;
1343
    cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase,
1344
                           0xffffffff, 0);
1345
    cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, 0);
1346
    cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, 0);
1347
    cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, 0);
1348
    cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, 0);
1349
    cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, 0);
1350
    
1351
    cpu_x86_update_cr0(env, 
1352
                       env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK));
1353
    cpu_x86_update_cr4(env, 0);
1354
    env->dr[7] = 0x00000400;
1355
#ifdef TARGET_X86_64
1356
    env->efer = 0;
1357
#endif
1358
    CC_OP = CC_OP_EFLAGS;
1359
}
1360

  
1361
void helper_rsm(void)
1362
{
1363
    target_ulong sm_state;
1364
    int i, offset;
1365
    uint32_t val;
1366

  
1367
    sm_state = env->smbase + 0x8000;
1368
#ifdef TARGET_X86_64
1369
    for(i = 0; i < 6; i++) {
1370
        offset = 0x7e00 + i * 16;
1371
        cpu_x86_load_seg_cache(env, i, 
1372
                               lduw_phys(sm_state + offset),
1373
                               ldq_phys(sm_state + offset + 8),
1374
                               ldl_phys(sm_state + offset + 4),
1375
                               (lduw_phys(sm_state + offset + 2) & 0xf0ff) << 8);
1376
    }
1377

  
1378
    env->gdt.base = ldq_phys(sm_state + 0x7e68);
1379
    env->gdt.limit = ldl_phys(sm_state + 0x7e64);
1380

  
1381
    env->ldt.selector = lduw_phys(sm_state + 0x7e70);
1382
    env->ldt.base = ldq_phys(sm_state + 0x7e78);
1383
    env->ldt.limit = ldl_phys(sm_state + 0x7e74);
1384
    env->ldt.flags = (lduw_phys(sm_state + 0x7e72) & 0xf0ff) << 8;
1385
    
1386
    env->idt.base = ldq_phys(sm_state + 0x7e88);
1387
    env->idt.limit = ldl_phys(sm_state + 0x7e84);
1388

  
1389
    env->tr.selector = lduw_phys(sm_state + 0x7e90);
1390
    env->tr.base = ldq_phys(sm_state + 0x7e98);
1391
    env->tr.limit = ldl_phys(sm_state + 0x7e94);
1392
    env->tr.flags = (lduw_phys(sm_state + 0x7e92) & 0xf0ff) << 8;
1393
    
1394
    env->efer = ldq_phys(sm_state + 0x7ed0);
1395

  
1396
    EAX = ldq_phys(sm_state + 0x7ff8);
1397
    ECX = ldq_phys(sm_state + 0x7ff0);
1398
    EDX = ldq_phys(sm_state + 0x7fe8);
1399
    EBX = ldq_phys(sm_state + 0x7fe0);
1400
    ESP = ldq_phys(sm_state + 0x7fd8);
1401
    EBP = ldq_phys(sm_state + 0x7fd0);
1402
    ESI = ldq_phys(sm_state + 0x7fc8);
1403
    EDI = ldq_phys(sm_state + 0x7fc0);
1404
    for(i = 8; i < 16; i++) 
1405
        env->regs[i] = ldq_phys(sm_state + 0x7ff8 - i * 8);
1406
    env->eip = ldq_phys(sm_state + 0x7f78);
1407
    load_eflags(ldl_phys(sm_state + 0x7f70), 
1408
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1409
    env->dr[6] = ldl_phys(sm_state + 0x7f68);
1410
    env->dr[7] = ldl_phys(sm_state + 0x7f60);
1411

  
1412
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f48));
1413
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7f50));
1414
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7f58));
1415

  
1416
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1417
    if (val & 0x20000) {
1418
        env->smbase = ldl_phys(sm_state + 0x7f00) & ~0x7fff;
1419
    }
1420
#else
1421
    cpu_x86_update_cr0(env, ldl_phys(sm_state + 0x7ffc));
1422
    cpu_x86_update_cr3(env, ldl_phys(sm_state + 0x7ff8));
1423
    load_eflags(ldl_phys(sm_state + 0x7ff4), 
1424
                ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
1425
    env->eip = ldl_phys(sm_state + 0x7ff0);
1426
    EDI = ldl_phys(sm_state + 0x7fec);
1427
    ESI = ldl_phys(sm_state + 0x7fe8);
1428
    EBP = ldl_phys(sm_state + 0x7fe4);
1429
    ESP = ldl_phys(sm_state + 0x7fe0);
1430
    EBX = ldl_phys(sm_state + 0x7fdc);
1431
    EDX = ldl_phys(sm_state + 0x7fd8);
1432
    ECX = ldl_phys(sm_state + 0x7fd4);
1433
    EAX = ldl_phys(sm_state + 0x7fd0);
1434
    env->dr[6] = ldl_phys(sm_state + 0x7fcc);
1435
    env->dr[7] = ldl_phys(sm_state + 0x7fc8);
1436
    
1437
    env->tr.selector = ldl_phys(sm_state + 0x7fc4) & 0xffff;
1438
    env->tr.base = ldl_phys(sm_state + 0x7f64);
1439
    env->tr.limit = ldl_phys(sm_state + 0x7f60);
1440
    env->tr.flags = (ldl_phys(sm_state + 0x7f5c) & 0xf0ff) << 8;
1441
    
1442
    env->ldt.selector = ldl_phys(sm_state + 0x7fc0) & 0xffff;
1443
    env->ldt.base = ldl_phys(sm_state + 0x7f80);
1444
    env->ldt.limit = ldl_phys(sm_state + 0x7f7c);
1445
    env->ldt.flags = (ldl_phys(sm_state + 0x7f78) & 0xf0ff) << 8;
1446
    
1447
    env->gdt.base = ldl_phys(sm_state + 0x7f74);
1448
    env->gdt.limit = ldl_phys(sm_state + 0x7f70);
1449

  
1450
    env->idt.base = ldl_phys(sm_state + 0x7f58);
1451
    env->idt.limit = ldl_phys(sm_state + 0x7f54);
1452

  
1453
    for(i = 0; i < 6; i++) {
1454
        if (i < 3)
1455
            offset = 0x7f84 + i * 12;
1456
        else
1457
            offset = 0x7f2c + (i - 3) * 12;
1458
        cpu_x86_load_seg_cache(env, i, 
1459
                               ldl_phys(sm_state + 0x7fa8 + i * 4) & 0xffff,
1460
                               ldl_phys(sm_state + offset + 8),
1461
                               ldl_phys(sm_state + offset + 4),
1462
                               (ldl_phys(sm_state + offset) & 0xf0ff) << 8);
1463
    }
1464
    cpu_x86_update_cr4(env, ldl_phys(sm_state + 0x7f14));
1465

  
1466
    val = ldl_phys(sm_state + 0x7efc); /* revision ID */
1467
    if (val & 0x20000) {
1468
        env->smbase = ldl_phys(sm_state + 0x7ef8) & ~0x7fff;
1469
    }
1470
#endif
1471
    CC_OP = CC_OP_EFLAGS;
1472
    env->hflags &= ~HF_SMM_MASK;
1473
    cpu_smm_update(env);
1474

  
1475
    if (loglevel & CPU_LOG_INT) {
1476
        fprintf(logfile, "SMM: after RSM\n");
1477
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1478
    }
1479
}
1480

  
1218 1481
#ifdef BUGGY_GCC_DIV64
1219 1482
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1220 1483
   call it from another function */

Also available in: Unified diff