2020-02-28 16:04:28 +00:00
|
|
|
/*
|
|
|
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
2021-10-10 19:52:50 +00:00
|
|
|
Copyright (C) 2018-21 divingkatae and maximum
|
2020-02-28 16:04:28 +00:00
|
|
|
(theweirdo) spatium
|
|
|
|
|
|
|
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2021-08-19 11:31:13 +00:00
|
|
|
/** @file PowerPC Memory Management Unit definitions. */
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2021-08-19 11:31:13 +00:00
|
|
|
#ifndef PPCMMU_H
|
|
|
|
#define PPCMMU_H
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2021-10-23 18:17:47 +00:00
|
|
|
#include <devices/memctrl/memctrlbase.h>
|
|
|
|
|
2020-01-27 00:36:22 +00:00
|
|
|
#include <cinttypes>
|
2021-09-27 10:37:35 +00:00
|
|
|
#include <functional>
|
2023-11-03 07:21:33 +00:00
|
|
|
|
|
|
|
class MMIODevice;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-03 19:28:37 +00:00
|
|
|
/* Uncomment this to exhaustive MMU integrity checks. */
|
|
|
|
//#define MMU_INTEGRITY_CHECKS
|
|
|
|
|
2019-08-02 00:02:01 +00:00
|
|
|
/** generic PowerPC BAT descriptor (MMU internal state) */
|
|
|
|
typedef struct PPC_BAT_entry {
|
2021-09-27 10:37:35 +00:00
|
|
|
bool valid; /* BAT entry valid for MPC601 */
|
|
|
|
uint8_t access; /* copy of Vs | Vp bits */
|
|
|
|
uint8_t prot; /* copy of PP bits */
|
|
|
|
uint32_t phys_hi; /* high-order bits for physical address generation */
|
|
|
|
uint32_t hi_mask; /* mask for high-order logical address bits */
|
|
|
|
uint32_t bepi; /* copy of Block effective page index */
|
2019-08-02 00:02:01 +00:00
|
|
|
} PPC_BAT_entry;
|
|
|
|
|
2021-05-15 22:53:15 +00:00
|
|
|
/** Block address translation types. */
|
|
|
|
enum BATType : int {
|
2021-09-25 08:16:48 +00:00
|
|
|
IBAT,
|
|
|
|
DBAT
|
|
|
|
};
|
|
|
|
|
|
|
|
/** TLB types. */
|
|
|
|
enum TLBType : int {
|
|
|
|
ITLB,
|
|
|
|
DTLB
|
2021-05-15 22:53:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Result of the block address translation. */
|
|
|
|
typedef struct BATResult {
|
|
|
|
bool hit;
|
|
|
|
uint8_t prot;
|
|
|
|
uint32_t phys;
|
|
|
|
} BATResult;
|
|
|
|
|
2021-08-03 14:01:32 +00:00
|
|
|
/** Result of the page address translation. */
|
|
|
|
typedef struct PATResult {
|
|
|
|
uint32_t phys;
|
|
|
|
uint8_t prot;
|
|
|
|
uint8_t pte_c_status; // status of the C bit of the PTE
|
|
|
|
} PATResult;
|
|
|
|
|
2023-10-02 00:20:42 +00:00
|
|
|
/** DMA memory mapping result. */
|
|
|
|
typedef struct MapDmaResult {
|
|
|
|
uint32_t type;
|
|
|
|
bool is_writable;
|
|
|
|
// for memory regions
|
|
|
|
uint8_t* host_va;
|
|
|
|
// for MMIO regions
|
|
|
|
MMIODevice* dev_obj;
|
|
|
|
uint32_t dev_base;
|
|
|
|
} MapDmaResult;
|
|
|
|
|
2024-03-26 02:45:06 +00:00
|
|
|
constexpr uint32_t PPC_PAGE_SIZE_BITS = 12;
|
|
|
|
constexpr uint32_t PPC_PAGE_SIZE = (1 << PPC_PAGE_SIZE_BITS);
|
|
|
|
constexpr uint32_t PPC_PAGE_MASK = ~(PPC_PAGE_SIZE - 1);
|
|
|
|
constexpr uint32_t TLB_SIZE = 4096;
|
|
|
|
constexpr uint32_t TLB2_WAYS = 4;
|
|
|
|
constexpr uint32_t TLB_INVALID_TAG = 0xFFFFFFFF;
|
2021-08-03 14:01:32 +00:00
|
|
|
|
|
|
|
typedef struct TLBEntry {
|
|
|
|
uint32_t tag;
|
|
|
|
uint16_t flags;
|
|
|
|
uint16_t lru_bits;
|
|
|
|
union {
|
2023-08-07 11:45:26 +00:00
|
|
|
struct { // for memory pages
|
|
|
|
int64_t host_va_offs_r;
|
|
|
|
int64_t host_va_offs_w;
|
2023-07-23 10:42:40 +00:00
|
|
|
};
|
2023-08-07 11:45:26 +00:00
|
|
|
struct { // for MMIO pages
|
2023-08-07 11:56:49 +00:00
|
|
|
AddressMapEntry* rgn_desc;
|
2023-08-07 11:45:26 +00:00
|
|
|
int64_t dev_base_va;
|
2023-07-23 10:42:40 +00:00
|
|
|
};
|
2021-08-03 14:01:32 +00:00
|
|
|
};
|
2023-08-09 05:01:48 +00:00
|
|
|
uint32_t phys_tag;
|
|
|
|
uint32_t reserved;
|
2021-08-03 14:01:32 +00:00
|
|
|
} TLBEntry;
|
|
|
|
|
|
|
|
enum TLBFlags : uint16_t {
|
|
|
|
PAGE_MEM = 1 << 0, // memory page backed by host memory
|
|
|
|
PAGE_IO = 1 << 1, // memory mapped I/O page
|
2021-09-27 10:37:35 +00:00
|
|
|
PAGE_NOPHYS = 1 << 2, // no physical storage for this page (unmapped)
|
|
|
|
TLBE_FROM_BAT = 1 << 3, // TLB entry has been translated with BAT
|
|
|
|
TLBE_FROM_PAT = 1 << 4, // TLB entry has been translated with PAT
|
|
|
|
PAGE_WRITABLE = 1 << 5, // page is writable
|
|
|
|
PTE_SET_C = 1 << 6, // tells if C bit of the PTE needs to be updated
|
2021-08-03 14:01:32 +00:00
|
|
|
};
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2021-09-27 10:37:35 +00:00
|
|
|
extern std::function<void(uint32_t bat_reg)> ibat_update;
|
|
|
|
extern std::function<void(uint32_t bat_reg)> dbat_update;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2023-10-02 00:20:42 +00:00
|
|
|
extern MapDmaResult mmu_map_dma_mem(uint32_t addr, uint32_t size, bool allow_mmio);
|
2020-03-19 01:00:18 +00:00
|
|
|
|
2021-05-15 22:53:15 +00:00
|
|
|
extern void mmu_change_mode(void);
|
2021-08-03 14:01:32 +00:00
|
|
|
extern void mmu_pat_ctx_changed();
|
|
|
|
extern void tlb_flush_entry(uint32_t ea);
|
2021-05-15 22:53:15 +00:00
|
|
|
|
2021-09-25 13:57:35 +00:00
|
|
|
extern uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size);
|
2023-08-09 05:05:21 +00:00
|
|
|
uint8_t *mmu_translate_imem(uint32_t vaddr, uint32_t *paddr = nullptr);
|
2023-08-09 05:09:46 +00:00
|
|
|
bool mmu_translate_dbg(uint32_t guest_va, uint32_t &guest_pa);
|
2021-09-25 13:57:35 +00:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
extern T mmu_read_vmem(uint32_t guest_va);
|
|
|
|
template <class T>
|
|
|
|
extern void mmu_write_vmem(uint32_t guest_va, T value);
|
|
|
|
|
|
|
|
//====================== Deprecated calls =========================
|
|
|
|
#if 0
|
2020-01-27 00:36:22 +00:00
|
|
|
extern void mem_write_byte(uint32_t addr, uint8_t value);
|
|
|
|
extern void mem_write_word(uint32_t addr, uint16_t value);
|
|
|
|
extern void mem_write_dword(uint32_t addr, uint32_t value);
|
|
|
|
extern void mem_write_qword(uint32_t addr, uint64_t value);
|
2020-05-12 18:55:45 +00:00
|
|
|
extern uint8_t mem_grab_byte(uint32_t addr);
|
2020-01-27 00:36:22 +00:00
|
|
|
extern uint16_t mem_grab_word(uint32_t addr);
|
|
|
|
extern uint32_t mem_grab_dword(uint32_t addr);
|
|
|
|
extern uint64_t mem_grab_qword(uint32_t addr);
|
2020-01-26 02:30:55 +00:00
|
|
|
extern uint8_t* quickinstruction_translate(uint32_t address_grab);
|
2021-09-25 13:57:35 +00:00
|
|
|
#endif
|
2021-06-20 20:33:03 +00:00
|
|
|
|
2021-08-19 11:31:13 +00:00
|
|
|
#endif // PPCMMU_H
|