tlb.cc (5647:b06b49498c79) | tlb.cc (5648:e8abda6e0980) |
---|---|
1/* 2 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company 3 * All rights reserved. 4 * 5 * Redistribution and use of this software in source and binary forms, 6 * with or without modification, are permitted provided that the 7 * following conditions are met: 8 * --- 624 unchanged lines hidden (view full) --- 633 // Real mode 634 DPRINTF(TLB, "In real mode.\n"); 635 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 636 req->setPaddr(vaddr); 637 } 638 // Check for an access to the local APIC 639#if FULL_SYSTEM 640 LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE); | 1/* 2 * Copyright (c) 2007-2008 The Hewlett-Packard Development Company 3 * All rights reserved. 4 * 5 * Redistribution and use of this software in source and binary forms, 6 * with or without modification, are permitted provided that the 7 * following conditions are met: 8 * --- 624 unchanged lines hidden (view full) --- 633 // Real mode 634 DPRINTF(TLB, "In real mode.\n"); 635 DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, vaddr); 636 req->setPaddr(vaddr); 637 } 638 // Check for an access to the local APIC 639#if FULL_SYSTEM 640 LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE); |
641 Addr baseAddr = localApicBase.base << 12; | 641 Addr baseAddr = localApicBase.base * PageBytes; |
642 Addr paddr = req->getPaddr(); | 642 Addr paddr = req->getPaddr(); |
643 if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) { 644 req->setMmapedIpr(true); | 643 if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { |
645 // The Intel developer's manuals say the below restrictions apply, 646 // but the linux kernel, because of a compiler optimization, breaks 647 // them. 648 /* 649 // Check alignment 650 if (paddr & ((32/8) - 1)) 651 return new GeneralProtection(0); 652 // Check access size 653 if (req->getSize() != (32/8)) 654 return new GeneralProtection(0); 655 */ | 644 // The Intel developer's manuals say the below restrictions apply, 645 // but the linux kernel, because of a compiler optimization, breaks 646 // them. 647 /* 648 // Check alignment 649 if (paddr & ((32/8) - 1)) 650 return new GeneralProtection(0); 651 // Check access size 652 if (req->getSize() != (32/8)) 653 return new GeneralProtection(0); 654 */ |
656 657 //Make sure we're at least only accessing one register. 658 if ((paddr & ~mask(3)) != ((paddr + req->getSize()) & ~mask(3))) 659 panic("Accessed more than one register at a time in the APIC!\n"); 660 MiscReg regNum; 661 Addr offset = paddr & mask(3); 662 paddr &= ~mask(3); 663 switch (paddr - baseAddr) 664 { 665 case 0x20: 666 regNum = APIC_ID; 667 break; 668 case 0x30: 669 regNum = APIC_VERSION; 670 break; 671 case 0x80: 672 regNum = APIC_TASK_PRIORITY; 673 break; 674 case 0x90: 675 regNum = APIC_ARBITRATION_PRIORITY; 676 break; 677 case 0xA0: 678 regNum = APIC_PROCESSOR_PRIORITY; 679 break; 680 case 0xB0: 681 regNum = APIC_EOI; 682 break; 683 case 0xD0: 684 regNum = APIC_LOGICAL_DESTINATION; 685 break; 686 case 0xE0: 687 regNum = APIC_DESTINATION_FORMAT; 688 break; 689 case 0xF0: 690 regNum = APIC_SPURIOUS_INTERRUPT_VECTOR; 691 break; 692 case 0x100: 693 case 0x108: 694 case 0x110: 695 case 0x118: 696 case 0x120: 697 case 0x128: 698 case 0x130: 699 case 0x138: 700 case 0x140: 701 case 0x148: 702 case 0x150: 703 case 0x158: 704 case 0x160: 705 case 0x168: 706 case 0x170: 707 case 0x178: 708 regNum = APIC_IN_SERVICE((paddr - baseAddr - 0x100) / 0x8); 709 break; 710 case 0x180: 711 case 0x188: 712 case 0x190: 713 case 0x198: 714 case 0x1A0: 715 case 0x1A8: 716 case 0x1B0: 717 case 0x1B8: 718 case 0x1C0: 719 case 0x1C8: 720 case 0x1D0: 721 case 0x1D8: 722 case 0x1E0: 723 case 0x1E8: 724 case 0x1F0: 725 case 0x1F8: 726 regNum = APIC_TRIGGER_MODE((paddr - baseAddr - 0x180) / 0x8); 727 break; 728 case 0x200: 729 case 0x208: 730 case 0x210: 731 case 0x218: 732 case 0x220: 733 case 0x228: 734 case 0x230: 735 case 0x238: 736 case 0x240: 737 case 0x248: 738 case 0x250: 739 case 0x258: 740 case 0x260: 741 case 0x268: 742 case 0x270: 743 case 0x278: 744 regNum = APIC_INTERRUPT_REQUEST((paddr - baseAddr - 0x200) / 0x8); 745 break; 746 case 0x280: 747 regNum = APIC_ERROR_STATUS; 748 break; 749 case 0x300: 750 regNum = APIC_INTERRUPT_COMMAND_LOW; 751 break; 752 case 0x310: 753 regNum = APIC_INTERRUPT_COMMAND_HIGH; 754 break; 755 case 0x320: 756 regNum = APIC_LVT_TIMER; 757 break; 758 case 0x330: 759 regNum = APIC_LVT_THERMAL_SENSOR; 760 break; 761 case 0x340: 762 regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS; 763 break; 764 case 0x350: 765 regNum = APIC_LVT_LINT0; 766 break; 767 case 0x360: 768 regNum = APIC_LVT_LINT1; 769 break; 770 case 0x370: 771 regNum = APIC_LVT_ERROR; 772 break; 773 case 0x380: 774 regNum = APIC_INITIAL_COUNT; 775 break; 776 case 0x390: 777 regNum = APIC_CURRENT_COUNT; 778 break; 779 case 0x3E0: 780 regNum = APIC_DIVIDE_CONFIGURATION; 781 break; 782 default: 783 // A reserved register field. 784 return new GeneralProtection(0); 785 break; 786 } 787 regNum += MISCREG_APIC_START; 788 req->setPaddr(regNum * sizeof(MiscReg) + offset); | 655 // Force the access to be uncacheable. 656 req->setFlags(req->getFlags() | UNCACHEABLE); 657 req->setPaddr(x86LocalAPICAddress(tc->readCpuId(), paddr - baseAddr)); |
789 } 790#endif 791 return NoFault; 792}; 793 794Fault 795DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 796{ --- 60 unchanged lines hidden --- | 658 } 659#endif 660 return NoFault; 661}; 662 663Fault 664DTB::translate(RequestPtr &req, ThreadContext *tc, bool write) 665{ --- 60 unchanged lines hidden --- |