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